Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

round traits framework + a few placeholders #2876

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a43f297
adds bare bones and a dummy example
harryob Feb 9, 2023
8ab2edc
more work on the tgui to be done
harryob Feb 10, 2023
a022bc8
adds some more dummy round traits
harryob Feb 15, 2023
3fa6f75
Merge remote-tracking branch 'upstream/master' into round-traits
harryob Feb 26, 2023
e5dde65
todo: debug
harryob Feb 26, 2023
dd5db9b
new traits + better handling
harryob Feb 27, 2023
753ac07
Merge branch 'round-traits' of https://github.com/harryob/cmss13 into…
harryob Feb 27, 2023
7e08c9b
removes one that was never gonna work without really annoying people …
harryob Mar 18, 2023
955f60f
xenos can view xeno round traits
harryob Mar 18, 2023
eb24fb7
Merge remote-tracking branch 'upstream/master' into round-traits
harryob Mar 18, 2023
5f87b83
final touches
harryob Mar 18, 2023
791d698
changes interface size
harryob Mar 18, 2023
d8144ef
i've got to go
harryob Mar 18, 2023
1b7e7f1
the public announcement waits a bit
harryob Mar 18, 2023
387ebf1
for economic slump too
harryob Mar 18, 2023
8aad807
Update code/datums/round_traits/neutral.dm
harryob Mar 18, 2023
132cb8a
Merge branch 'master' into round-traits
harryob Mar 19, 2023
4b4e7b9
adjust weighting + removed force trait
harryob Mar 19, 2023
9933d6b
Merge remote-tracking branch 'upstream/master' into round-traits
harryob Mar 19, 2023
c75ee0b
Merge branch 'master' into round-traits
harryob Mar 22, 2023
9a60869
Merge branch 'master' into round-traits
harryob Apr 3, 2023
c33e5d7
Merge remote-tracking branch 'upstream/master' into round-traits
harryob Aug 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions code/__DEFINES/round.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#define ROUND_TRAIT_HUMAN_POSITIVE "human_positive"
#define ROUND_TRAIT_HUMAN_NEGATIVE "human_negative"

#define ROUND_TRAIT_XENO_POSITIVE "xeno_positive"
#define ROUND_TRAIT_XENO_NEGATIVE "xeno_negative"

#define ROUND_TRAIT_NEUTRAL "neutral"


#define ROUND_TRAIT_ABSTRACT (1<<0)

/// The data file that future station traits are stored in
#define FUTURE_ROUND_TRAITS_FILE "data/future_round_traits.json"
1 change: 1 addition & 0 deletions code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
#define SS_INIT_INFLUXDRIVER 28
#define SS_INIT_SUPPLY_SHUTTLE 25
#define SS_INIT_GARBAGE 24
#define SS_INIT_ROUND 23.6
#define SS_INIT_EVENTS 23.5
#define SS_INIT_JOB 23
#define SS_INIT_REDIS 22.5
Expand Down
12 changes: 12 additions & 0 deletions code/__DEFINES/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,16 @@
//This item will force clickdrag to work even if the preference to disable is enabled. (Full-auto items)
#define TRAIT_OVERRIDE_CLICKDRAG "t_override_clickdrag"


// Round Traits
#define TRAIT_ROUND_CRYOSLEEP_SICKNESS "t_cryosleep_sickness"
#define TRAIT_ROUND_FLU_SEASON "t_flu_season"
#define TRAIT_ROUND_FAULTY_PIPING "t_faulty_piping"
#define TRAIT_ROUND_ECONOMIC_BOOM "t_economic_boom"
#define TRAIT_ROUND_ECONOMIC_SLUMP "t_economic_slump"
#define TRAIT_ROUND_STANDARD_ISSUE "t_standard_issue"
#define TRAIT_ROUND_WRONG_TUBES "t_wrongtubes"

//This item will use special rename component behaviors.
//ie. naming a regulation tape "example" will become regulation tape (example)
#define TRAIT_ITEM_RENAME_SPECIAL "t_item_rename_special"
Expand Down Expand Up @@ -345,6 +355,8 @@ GLOBAL_LIST(trait_name_map)
#define TRAIT_SOURCE_ABILITY(ability) "t_s_ability_[ability]"
///Status trait forced by the xeno action charge
#define TRAIT_SOURCE_XENO_ACTION_CHARGE "t_s_xeno_action_charge"
/// status trait given by a round trait
#define TRAIT_SOURCE_ROUND "t_s_round_trait"
//-- structure traits --
///Status trait coming from being flipped or unflipped.
#define TRAIT_SOURCE_FLIP_TABLE "t_s_flip_table"
Expand Down
2 changes: 2 additions & 0 deletions code/_globalvars/global_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ GLOBAL_LIST_INIT_TYPED(hive_datum, /datum/hive_status, list(
XENO_HIVE_RENEGADE = new /datum/hive_status/corrupted/renegade(),
))

GLOBAL_DATUM_INIT(xeno_round_traits, /datum/xeno_round_traits, new())

GLOBAL_LIST_INIT(xeno_evolve_times, setup_xeno_evolve_times())

/proc/setup_xeno_evolve_times()
Expand Down
6 changes: 6 additions & 0 deletions code/_globalvars/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ GLOBAL_VAR_INIT(minimum_exterior_lighting_alpha, 255)

GLOBAL_DATUM_INIT(item_to_box_mapping, /datum/item_to_box_mapping, init_item_to_box_mapping())


GLOBAL_VAR(temperature_change)

GLOBAL_VAR(squad_mappings)

/// Offset for the Operation time
GLOBAL_VAR_INIT(time_offset, setup_offset())

/// Sets the offset 2 lines above.
/proc/setup_offset()
return rand(10 MINUTES, 24 HOURS)

2 changes: 2 additions & 0 deletions code/controllers/configuration/entries/general.dm
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,8 @@ This maintains a list of ip addresses that are able to bypass topic filtering.
/// logs all timers in buckets on automatic bucket reset (Useful for timer debugging)
/datum/config_entry/flag/log_timers_on_bucket_reset

/datum/config_entry/flag/forbid_round_traits

/datum/config_entry/number/hard_deletes_overrun_threshold
integer = FALSE
min_val = 0
Expand Down
102 changes: 102 additions & 0 deletions code/controllers/subsystem/processing/round.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
PROCESSING_SUBSYSTEM_DEF(round)
name = "Round"
init_order = SS_INIT_ROUND
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME
wait = 5 SECONDS

///A list of currently active round traits
var/list/round_traits = list()
///Assoc list of trait type || assoc list of traits with weighted value. Used for picking traits from a specific category.
var/list/selectable_traits_by_types = list(
ROUND_TRAIT_HUMAN_POSITIVE = list(),
ROUND_TRAIT_HUMAN_NEGATIVE = list(),
ROUND_TRAIT_XENO_POSITIVE = list(),
ROUND_TRAIT_XENO_NEGATIVE = list(),
ROUND_TRAIT_NEUTRAL = list(),
)

/datum/controller/subsystem/processing/round/Initialize()

//If doing unit tests we don't do none of that trait shit ya know?
// Autowiki also wants consistent outputs, for example making sure the vending machine page always reports the normal products
#if !defined(UNIT_TESTS) && !defined(AUTOWIKI)
SetupTraits()
#endif

return SS_INIT_SUCCESS

///Rolls for the amount of traits and adds them to the traits list
/datum/controller/subsystem/processing/round/proc/SetupTraits()
if (CONFIG_GET(flag/forbid_round_traits))
return

if (fexists(FUTURE_ROUND_TRAITS_FILE))
var/forced_traits_contents = file2text(FUTURE_ROUND_TRAITS_FILE)
fdel(FUTURE_ROUND_TRAITS_FILE)

var/list/forced_traits_text_paths = json_decode(forced_traits_contents)
forced_traits_text_paths = SANITIZE_LIST(forced_traits_text_paths)

for (var/trait_text_path in forced_traits_text_paths)
var/round_trait_path = text2path(trait_text_path)
if (!ispath(round_trait_path, /datum/round_trait) || round_trait_path == /datum/round_trait)
var/message = "Invalid round trait path [round_trait_path] was requested in the future round traits!"
log_game(message)
message_admins(message)
continue

setup_trait(round_trait_path)

return

for(var/datum/round_trait/trait_typepath as anything in subtypesof(/datum/round_trait))

// If forced, (probably debugging), just set it up now, keep it out of the pool.
if(initial(trait_typepath.force))
setup_trait(trait_typepath)
continue

if(initial(trait_typepath.trait_flags) & ROUND_TRAIT_ABSTRACT)
continue //Dont add abstract ones to it
selectable_traits_by_types[initial(trait_typepath.trait_type)][trait_typepath] = initial(trait_typepath.weight)

var/human_positive_trait_count = pick(50;0, 5;1, 1;2)
var/human_negative_trait_count = pick(50;0, 5;1, 1;2)

var/xeno_positive_trait_count = pick(50;0, 5;1, 1;2)
var/xeno_negative_trait_count = pick(50;0, 5;1, 1;2)

var/neutral_trait_count = pick(50;0, 5;1, 1;2)

pick_traits(ROUND_TRAIT_HUMAN_POSITIVE, human_positive_trait_count)
pick_traits(ROUND_TRAIT_HUMAN_NEGATIVE, human_negative_trait_count)

pick_traits(ROUND_TRAIT_XENO_POSITIVE, xeno_positive_trait_count)
pick_traits(ROUND_TRAIT_XENO_NEGATIVE, xeno_negative_trait_count)

pick_traits(ROUND_TRAIT_NEUTRAL, neutral_trait_count)

///Picks traits of a specific category (e.g. bad or good) and a specified amount, then initializes them, adds them to the list of traits,
///then removes them from possible traits as to not roll twice.
/datum/controller/subsystem/processing/round/proc/pick_traits(trait_sign, amount)
if(!amount)
return
for(var/iterator in 1 to amount)
var/datum/round_trait/trait_type = pick_weight(selectable_traits_by_types[trait_sign]) //Rolls from the table for the specific trait type
selectable_traits_by_types[trait_sign] -= trait_type
setup_trait(trait_type)

///Creates a given trait of a specific type, while also removing any blacklisted ones from the future pool.
/datum/controller/subsystem/processing/round/proc/setup_trait(datum/round_trait/trait_type)
if(!trait_type)
return

var/datum/round_trait/trait_instance = new trait_type()
round_traits += trait_instance
log_game("round trait: [trait_instance.name] chosen for this round.")
if(!trait_instance.blacklist)
return
for(var/i in trait_instance.blacklist)
var/datum/round_trait/trait_to_remove = i
selectable_traits_by_types[initial(trait_to_remove.trait_type)] -= trait_to_remove
4 changes: 4 additions & 0 deletions code/datums/diseases/flu.dm
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,7 @@
affected_mob.apply_damage(1, TOX)
affected_mob.updatehealth()
return


/datum/disease/flu/cryo_flu
spread_type = NON_CONTAGIOUS
60 changes: 60 additions & 0 deletions code/datums/round_traits/_round_traits.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
///Base class of round traits. These are used to influence rounds in one way or the other by influencing the levers of the round.

/datum/round_trait
///Name of the trait
var/name = "unnamed round trait"
///The type of this trait. Used to classify how this trait influences the round
var/trait_type = ROUND_TRAIT_NEUTRAL
///Whether or not this trait uses process()
var/trait_processes = FALSE
///Whether this trait is always enabled; generally used for debugging
var/force = FALSE
///Chance relative to other traits of its type to be picked
var/weight = 10
///Does this trait show in the human report?
var/show_in_human_report = FALSE
///Does this trait show in the xeno report?
var/show_in_xeno_report = FALSE
///What message to show in the human report?
var/human_report_message
///What message to show in the xeno report?
var/xeno_report_message
///What trait does this round trait give? gives none if null
var/trait_to_give
///What traits are incompatible with this one?
var/blacklist
///Extra flags for round traits such as it being abstract
var/trait_flags
/// Whether or not this trait can be reverted by an admin
var/can_revert = TRUE


/datum/round_trait/New()
. = ..()
SSticker.OnRoundstart(CALLBACK(src, PROC_REF(on_round_start)))
if(trait_processes)
START_PROCESSING(SSround, src)
if(trait_to_give)
ADD_TRAIT(SSround, trait_to_give, TRAIT_SOURCE_ROUND)

/datum/round_trait/Destroy()
SSround.round_traits -= src
return ..()

///Proc ran when round starts. Use this for roundstart effects.
/datum/round_trait/proc/on_round_start()
return

///type of info the human report has on this trait, if any.
/datum/round_trait/proc/get_report()
return "[name] - [human_report_message]"

/// Will attempt to revert the round trait, used by admins.
/datum/round_trait/proc/revert()
if(!can_revert)
CRASH("revert() was called on [type], which can't be reverted!")

if(trait_to_give)
REMOVE_TRAIT(SSround, trait_to_give, TRAIT_SOURCE_ROUND)

qdel(src)
133 changes: 133 additions & 0 deletions code/datums/round_traits/admin_panel.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/// Opens the station traits admin panel
/datum/admins/proc/round_traits_panel()
set name = "Modify Round Traits"
set category = "Admin.Events"

var/static/datum/round_traits_panel/round_traits_panel = new
round_traits_panel.tgui_interact(usr)

/datum/round_traits_panel
var/static/list/future_traits

/datum/round_traits_panel/ui_data(mob/user)
var/list/data = list()

data["too_late_to_revert"] = too_late_to_revert()

var/list/current_round_traits = list()
for (var/datum/round_trait/round_trait as anything in SSround.round_traits)
current_round_traits += list(list(
"name" = round_trait.name,
"can_revert" = round_trait.can_revert,
"ref" = REF(round_trait),
))

data["current_traits"] = current_round_traits
data["future_round_traits"] = future_traits

return data

/datum/round_traits_panel/ui_static_data(mob/user)
var/list/data = list()

var/list/valid_round_traits = list()

for (var/datum/round_trait/round_trait_path as anything in subtypesof(/datum/round_trait))
valid_round_traits += list(list(
"name" = initial(round_trait_path.name),
"path" = round_trait_path,
))

data["valid_round_traits"] = valid_round_traits

return data

/datum/round_traits_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if (.)
return

switch (action)
if ("revert")
var/ref = params["ref"]
if (!ref)
return TRUE

var/datum/round_trait/round_trait = locate(ref)

if (!istype(round_trait))
return TRUE

if (too_late_to_revert())
to_chat(usr, SPAN_WARNING("It's too late to revert station traits, the round has already started!"))
return TRUE

if (!round_trait.can_revert)
stack_trace("[round_trait.type] can't be reverted, but was requested anyway.")
return TRUE

var/message = "[key_name(usr)] reverted the station trait [round_trait.name] ([round_trait.type])"
log_admin(message)
message_admins(message)

round_trait.revert()

return TRUE
if ("setup_future_traits")
if (too_late_for_future_traits())
to_chat(usr, SPAN_WARNING("It's too late to add future station traits, the round is already over!"))
return TRUE

var/list/new_future_traits = list()
var/list/round_trait_names = list()

for (var/round_trait_text in params["round_traits"])
var/datum/round_trait/round_trait_path = text2path(round_trait_text)
if (!ispath(round_trait_path, /datum/round_trait) || round_trait_path == /datum/round_trait)
log_admin("[key_name(usr)] tried to set an invalid future station trait: [round_trait_text]")
to_chat(usr, SPAN_WARNING("Invalid future station trait: [round_trait_text]"))
return TRUE

round_trait_names += initial(round_trait_path.name)

new_future_traits += list(list(
"name" = initial(round_trait_path.name),
"path" = round_trait_path,
))

var/message = "[key_name(usr)] has prepared the following station traits for next round: [round_trait_names.Join(", ") || "None"]"
log_admin(message)
message_admins(message)

future_traits = new_future_traits
rustg_file_write(json_encode(params["round_traits"]), FUTURE_ROUND_TRAITS_FILE)

return TRUE
if ("clear_future_traits")
if (!future_traits)
to_chat(usr, SPAN_WARNING("There are no future station traits."))
return TRUE

var/message = "[key_name(usr)] has cleared the station traits for next round."
log_admin(message)
message_admins(message)

fdel(FUTURE_ROUND_TRAITS_FILE)
future_traits = null

return TRUE

/datum/round_traits_panel/proc/too_late_for_future_traits()
return SSticker.current_state >= GAME_STATE_FINISHED

/datum/round_traits_panel/proc/too_late_to_revert()
return SSticker.current_state >= GAME_STATE_PLAYING

/datum/round_traits_panel/ui_status(mob/user, datum/ui_state/state)
return check_rights_for(user.client, R_EVENT) ? UI_INTERACTIVE : UI_CLOSE

/datum/round_traits_panel/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "RoundTraitsPanel")
ui.open()
Loading
Loading