From 328d0010475330b92a961a23d489c89f8f71b514 Mon Sep 17 00:00:00 2001 From: Time-Green <7501474+Time-Green@users.noreply.github.com> Date: Fri, 31 May 2024 19:08:15 +0200 Subject: [PATCH] STATION TRAIT GAMEMODE: Station-Wide Background Checks (#83307) ## About The Pull Request Adds a new station trait: Station-Wide Background Checks! It does two things: 1. Blocks most crew-side antagonists. No traitors, changelings, spies, heretics, etc. You won't be able to fully trust your crew though, as Space changelings, Paradox Clones, Obsesseds and Blob Infected are excempted crew-antags since a background check doesn't really help here. Other antagonists still spawn: pirates, revenants, blobs, aliens, nukies, wizards etc. Expect a LOT more of these, as Dynamic is gonna put threat somewhere... 2. Reduces dynamics threat slightly, configurable per server, but defaults to 15. It is essentially the first "dynamic gamemode". ## Why It's Good For The Game Blocking crew antagonists changes the shifts dynamic, similair to old warops. Security can "trust" crew to not be antagonists, and instead can focus more on petty crimes and hunting down external threats. Due to the increased chance of external threats and reduced chance of internal threats, the crew can focus its defenses outwards. Don't worry about your coworker killing you (intentionally/probably), but do worry a lot more about the pirates trying to break through your hull, or alien nests growing in virology. I've also reduced total threat count slightly because the idea of 90 threat being dumped into ghost spawns kinda terrifies me and I do want people to be able to let their guard down a slight bit. It can be reduced/disabled for servers that already tend to lower threats. I think it's a lot of fun to change the paranoia dynamic, and a fun deviation from a normal round of spaceman13. ## Changelog :cl: add: Station-Wide Background Checks (station trait, rare): Disables crew antagonists, but get a lot more non-crew antagonists /:cl: I want to do more like these (this was just an example I threw into discord to annoy @Mothblocks but I realized I kinda liked), and this is a good opportunity to gather community feedback and see how it plays! --------- Co-authored-by: carlarctg <53100513+carlarctg@users.noreply.github.com> --- code/__DEFINES/dynamic.dm | 6 ++++++ code/controllers/subsystem/dynamic/dynamic.dm | 6 +++++- .../subsystem/dynamic/dynamic_rulesets.dm | 2 ++ .../dynamic/dynamic_rulesets_midround.dm | 17 ++++++++++++++++- .../dynamic/dynamic_rulesets_roundstart.dm | 3 +++ code/datums/station_traits/_station_trait.dm | 4 ++++ code/datums/station_traits/neutral_traits.dm | 12 ++++++++++++ code/datums/station_traits/positive_traits.dm | 7 +++---- config/dynamic.json | 2 ++ 9 files changed, 53 insertions(+), 6 deletions(-) diff --git a/code/__DEFINES/dynamic.dm b/code/__DEFINES/dynamic.dm index 07c833cdc4947..0162ef755e315 100644 --- a/code/__DEFINES/dynamic.dm +++ b/code/__DEFINES/dynamic.dm @@ -38,3 +38,9 @@ #define RULESET_FORCE_ENABLED "force enabled" /// Ruleset should not run regardless of population and threat available #define RULESET_FORCE_DISABLED "force disabled" + +// Flavor ruletypes, used by station traits +/// Rulesets selected by dynamic at default +#define RULESET_CATEGORY_DEFAULT (1 << 0) +/// Rulesets not including crew antagonists, non-witting referring to antags like obsessed which aren't really enemies of the station +#define RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS (1 << 1) diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index 3fb1ce8af9cec..3824cc0b0048f 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -19,6 +19,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) GLOBAL_LIST_EMPTY(dynamic_station_traits) /// Rulesets which have been forcibly enabled or disabled GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) +/// Bitflags used during init by Dynamic to determine which rulesets we're allowed to use, used by station traits for gamemode-esque experiences +GLOBAL_VAR_INIT(dynamic_ruleset_categories, RULESET_CATEGORY_DEFAULT) SUBSYSTEM_DEF(dynamic) name = "Dynamic" @@ -643,7 +645,6 @@ SUBSYSTEM_DEF(dynamic) log_admin(concatenated_message) to_chat(GLOB.admins, concatenated_message) - /// Initializes the internal ruleset variables /datum/controller/subsystem/dynamic/proc/setup_rulesets() midround_rules = init_rulesets(/datum/dynamic_ruleset/midround) @@ -661,6 +662,9 @@ SUBSYSTEM_DEF(dynamic) if (initial(ruleset_type.weight) == 0) continue + if(!(initial(ruleset_type.ruleset_category) & GLOB.dynamic_ruleset_categories)) + continue + var/ruleset = new ruleset_type configure_ruleset(ruleset) rulesets += ruleset diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets.dm index 28789d938d381..c77cce50d0157 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets.dm @@ -83,6 +83,8 @@ /// A list, or null, of templates that the ruleset depends on to function correctly var/list/ruleset_lazy_templates + /// In what categories is this ruleset allowed to run? Used by station traits + var/ruleset_category = RULESET_CATEGORY_DEFAULT /datum/dynamic_ruleset/New() // Rulesets can be instantiated more than once, such as when an admin clicks diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm index 8ac5f27c4c9b9..857a1babd3249 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm @@ -341,6 +341,7 @@ antag_datum = /datum/antagonist/wizard antag_flag = ROLE_WIZARD_MIDROUND antag_flag_override = ROLE_WIZARD + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 weight = 1 @@ -369,6 +370,7 @@ antag_flag = ROLE_OPERATIVE_MIDROUND antag_flag_override = ROLE_OPERATIVE antag_datum = /datum/antagonist/nukeop + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS enemy_roles = list( JOB_AI, JOB_CYBORG, @@ -423,6 +425,7 @@ midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/blob antag_flag = ROLE_BLOB + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 minimum_round_time = 35 MINUTES @@ -442,6 +445,7 @@ antag_datum = /datum/antagonist/blob/infection antag_flag = ROLE_BLOB_INFECTION antag_flag_override = ROLE_BLOB + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS protected_roles = list( JOB_CAPTAIN, JOB_DETECTIVE, @@ -494,6 +498,7 @@ midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/xeno antag_flag = ROLE_ALIEN + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 minimum_round_time = 40 MINUTES @@ -542,6 +547,7 @@ antag_datum = /datum/antagonist/nightmare antag_flag = ROLE_NIGHTMARE antag_flag_override = ROLE_ALIEN + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 weight = 3 @@ -577,7 +583,7 @@ midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/space_dragon antag_flag = ROLE_SPACE_DRAGON - antag_flag_override = ROLE_SPACE_DRAGON + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 weight = 4 @@ -617,6 +623,7 @@ midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT antag_datum = /datum/antagonist/abductor antag_flag = ROLE_ABDUCTOR + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 2 required_applicants = 2 @@ -654,6 +661,7 @@ midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/ninja antag_flag = ROLE_NINJA + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 weight = 4 @@ -693,6 +701,7 @@ name = "Spiders" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_flag = ROLE_SPIDER + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_type = /mob/dead/observer required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 0 @@ -710,6 +719,7 @@ /datum/dynamic_ruleset/midround/from_ghosts/revenant name = "Revenant" midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS antag_datum = /datum/antagonist/revenant antag_flag = ROLE_REVENANT required_enemies = list(2,2,1,1,1,1,1,0,0,0) @@ -760,6 +770,7 @@ /datum/dynamic_ruleset/midround/pirates name = "Space Pirates" midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS antag_flag = "Space Pirates" required_type = /mob/dead/observer required_enemies = list(2,2,1,1,1,1,1,0,0,0) @@ -782,6 +793,7 @@ /datum/dynamic_ruleset/midround/dangerous_pirates name = "Dangerous Space Pirates" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS antag_flag = "Space Pirates" required_type = /mob/dead/observer required_enemies = list(2,2,1,1,1,1,1,0,0,0) @@ -806,6 +818,7 @@ midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT antag_datum = /datum/antagonist/obsessed antag_flag = ROLE_OBSESSED + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS restricted_roles = list( JOB_AI, JOB_CYBORG, @@ -849,6 +862,7 @@ antag_datum = /datum/antagonist/changeling/space antag_flag = ROLE_CHANGELING_MIDROUND antag_flag_override = ROLE_CHANGELING + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS required_type = /mob/dead/observer required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 @@ -869,6 +883,7 @@ midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT antag_datum = /datum/antagonist/paradox_clone antag_flag = ROLE_PARADOX_CLONE + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS enemy_roles = list( JOB_CAPTAIN, JOB_DETECTIVE, diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm index 12ec28c707212..72554a108e328 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm @@ -254,6 +254,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) name = "Wizard" antag_flag = ROLE_WIZARD antag_datum = /datum/antagonist/wizard + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS flags = HIGH_IMPACT_RULESET minimum_required_age = 14 restricted_roles = list( @@ -395,6 +396,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) /datum/dynamic_ruleset/roundstart/nuclear name = "Nuclear Emergency" antag_flag = ROLE_OPERATIVE + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS antag_datum = /datum/antagonist/nukeop var/datum/antagonist/antag_leader_datum = /datum/antagonist/nukeop/leader minimum_required_age = 14 @@ -618,6 +620,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) antag_datum = /datum/antagonist/nukeop/clownop antag_flag = ROLE_CLOWN_OPERATIVE antag_flag_override = ROLE_OPERATIVE + ruleset_category = parent_type::ruleset_category | RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS antag_leader_datum = /datum/antagonist/nukeop/leader/clownop requirements = list(101,101,101,101,101,101,101,101,101,101) required_role = ROLE_CLOWN_OPERATIVE diff --git a/code/datums/station_traits/_station_trait.dm b/code/datums/station_traits/_station_trait.dm index 28836b2b4fa5f..7d71c52012e22 100644 --- a/code/datums/station_traits/_station_trait.dm +++ b/code/datums/station_traits/_station_trait.dm @@ -35,6 +35,8 @@ GLOBAL_LIST_EMPTY(lobby_station_traits) var/dynamic_threat_id /// If ran during dynamic, do we reduce the total threat? Will be overriden by config if set var/threat_reduction = 0 + /// Which ruleset flags to allow dynamic to use. null to disregard + var/dynamic_category = null /// Trait should not be instantiated in a round if its type matches this type var/abstract_type = /datum/station_trait @@ -45,6 +47,8 @@ GLOBAL_LIST_EMPTY(lobby_station_traits) if(threat_reduction) GLOB.dynamic_station_traits[src] = threat_reduction + if(dynamic_category) + GLOB.dynamic_ruleset_categories = dynamic_category if(sign_up_button) GLOB.lobby_station_traits += src if(trait_processes) diff --git a/code/datums/station_traits/neutral_traits.dm b/code/datums/station_traits/neutral_traits.dm index 7545b2fb39582..f174f5f8d8bb0 100644 --- a/code/datums/station_traits/neutral_traits.dm +++ b/code/datums/station_traits/neutral_traits.dm @@ -561,3 +561,15 @@ #undef SKUB_IDFC #undef RANDOM_SKUB +/// Crew don't ever spawn as enemies of the station. Obsesseds, blob infection, space changelings etc can still happen though +/datum/station_trait/background_checks + name = "Station-Wide Background Checks" + report_message = "We replaced the intern doing your crew's background checks with a trained screener for this shift! That said, our enemies may just find another way to infiltrate the station, so be careful." + trait_type = STATION_TRAIT_NEUTRAL + weight = 1 + show_in_report = TRUE + can_revert = FALSE + + dynamic_category = RULESET_CATEGORY_NO_WITTING_CREW_ANTAGONISTS + threat_reduction = 15 + dynamic_threat_id = "Background Checks" diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index 8398e02139d74..185628a118738 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -1,7 +1,6 @@ #define PARTY_COOLDOWN_LENGTH_MIN (6 MINUTES) #define PARTY_COOLDOWN_LENGTH_MAX (12 MINUTES) - /datum/station_trait/lucky_winner name = "Lucky winner" trait_type = STATION_TRAIT_POSITIVE @@ -31,6 +30,9 @@ new /obj/item/reagent_containers/cup/glass/bottle/beer(toLaunch) new /obj/effect/pod_landingzone(T, toLaunch) +#undef PARTY_COOLDOWN_LENGTH_MIN +#undef PARTY_COOLDOWN_LENGTH_MAX + /datum/station_trait/galactic_grant name = "Galactic grant" trait_type = STATION_TRAIT_POSITIVE @@ -358,6 +360,3 @@ trait_to_give = STATION_TRAIT_ASSISTANT_GIMMICKS show_in_report = TRUE blacklist = list(/datum/station_trait/colored_assistants) - -#undef PARTY_COOLDOWN_LENGTH_MIN -#undef PARTY_COOLDOWN_LENGTH_MAX diff --git a/config/dynamic.json b/config/dynamic.json index 5761dbabc324e..569f015d7313c 100644 --- a/config/dynamic.json +++ b/config/dynamic.json @@ -154,6 +154,8 @@ "Station": { "Radioactive Nebula": { + }, + "Background Checks": { } } }