From 792dc073b3ceb411d936d16e9449244047d17c98 Mon Sep 17 00:00:00 2001 From: keronshb Date: Thu, 16 Sep 2021 13:28:34 -0400 Subject: [PATCH] Final fixes? --- code/__DEFINES/role_preferences.dm | 1 + code/__HELPERS/config.dm | 2 + .../configuration/configuration.dm | 8 +- .../configuration/entries/general.dm | 2 + code/controllers/subsystem/job.dm | 2 + code/datums/mind.dm | 2 + .../dynamic/dynamic_rulesets_midround.dm | 1 - code/modules/admin/antag_panel.dm | 2 +- .../antagonists/revolution/revolution.dm | 175 ++++++++++++++++-- code/modules/jobs/job_types/_job.dm | 3 + code/modules/jobs/job_types/ai.dm | 1 + config/entries/general.txt | 3 + tgstation.dme | 1 + 13 files changed, 178 insertions(+), 25 deletions(-) create mode 100644 code/__HELPERS/config.dm diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index d47740f370..43c74b8b08 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -14,6 +14,7 @@ #define ROLE_MALF "malf AI" #define ROLE_REV "revolutionary" #define ROLE_REV_HEAD "Head Revolutionary" +#define ROLE_REV_SUCCESSFUL "Victorious Revolutionary" #define ROLE_ALIEN "xenomorph" #define ROLE_PAI "pAI" #define ROLE_CULTIST "cultist" diff --git a/code/__HELPERS/config.dm b/code/__HELPERS/config.dm new file mode 100644 index 0000000000..1320851ef8 --- /dev/null +++ b/code/__HELPERS/config.dm @@ -0,0 +1,2 @@ +/proc/get_policy(keyword) + return global.config.policy[keyword] diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index ed3959c0cc..73f7904d7d 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -20,7 +20,7 @@ var/list/mode_false_report_weight var/motd - // var/policy + var/policy var/static/regex/ic_filter_regex @@ -51,7 +51,7 @@ break loadmaplist(CONFIG_MAPS_FILE) LoadMOTD() - // LoadPolicy() + LoadPolicy() LoadChatFilter() if (Master) @@ -291,7 +291,7 @@ Example config: } */ -/* + /datum/controller/configuration/proc/LoadPolicy() policy = list() var/rawpolicy = file2text("[directory]/policy.json") @@ -302,7 +302,7 @@ Example config: DelayedMessageAdmins("JSON parsing failure for policy.json") else policy = parsed -*/ + /datum/controller/configuration/proc/loadmaplist(filename) log_config("Loading config file [filename]...") filename = "[directory]/[filename]" diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index d828457fa7..57f7c535b7 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -342,3 +342,5 @@ /datum/config_entry/number/hard_deletes_overrun_limit default = 0 min_val = 0 + +/datum/config_entry/flag/dynamic_config_enabled diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 7e7efe398f..46bf45bdce 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -30,11 +30,13 @@ SUBSYSTEM_DEF(job) var/datum/job/new_overflow = GetJob(new_overflow_role) var/cap = CONFIG_GET(number/overflow_cap) + new_overflow.allow_bureaucratic_error = FALSE new_overflow.spawn_positions = cap new_overflow.total_positions = cap if(new_overflow_role != overflow_role) var/datum/job/old_overflow = GetJob(overflow_role) + old_overflow.allow_bureaucratic_error = initial(old_overflow.allow_bureaucratic_error) old_overflow.spawn_positions = initial(old_overflow.spawn_positions) old_overflow.total_positions = initial(old_overflow.total_positions) overflow_role = new_overflow_role diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 897e2e7d71..fdd576067b 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -71,6 +71,8 @@ ///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not var/mob/original_character + /// A lazy list of statuses to add next to this mind in the traitor panel + var/list/special_statuses /datum/mind/New(var/key) skill_holder = new(src) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 02d93e9222..18a83d1364 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -601,7 +601,6 @@ /datum/dynamic_ruleset/midround/swarmers name = "Swarmers" - antag_datum = /datum/antagonist/swarmer antag_flag = "Swarmer" antag_flag_override = ROLE_ALIEN required_type = /mob/dead/observer diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm index 2d1aa63a91..180735d746 100644 --- a/code/modules/admin/antag_panel.dm +++ b/code/modules/admin/antag_panel.dm @@ -77,7 +77,7 @@ GLOBAL_VAR(antag_prototypes) return common_commands /datum/mind/proc/get_special_statuses() - var/list/result = list() + var/list/result = LAZYCOPY(special_statuses) if(!current) result += "No body!" if(current && HAS_TRAIT(current, TRAIT_MINDSHIELD)) diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index c23523cc6b..d27a7c6c1e 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -1,3 +1,5 @@ +#define DECONVERTER_STATION_WIN "gamemode_station_win" +#define DECONVERTER_REVS_WIN "gamemode_revs_win" //How often to check for promotion possibility #define HEAD_UPDATE_PERIOD 300 @@ -10,6 +12,11 @@ threat = 2 var/hud_type = "rev" var/datum/team/revolution/rev_team + ///when this antagonist is being de-antagged, this is why + var/deconversion_reason + + /// What message should the player receive when they are being demoted, and the revolution has won? + var/victory_message = "The revolution has overpowered the command staff! Viva la revolution! Execute any head of staff and security should you find them alive." /datum/antagonist/rev/can_be_owned(datum/mind/new_owner) . = ..() @@ -201,7 +208,22 @@ new_rev.silent = FALSE to_chat(old_owner, "Revolution has been disappointed of your leader traits! You are a regular revolutionary now!") +/// Checks if the revolution succeeded, and lets them know. +/datum/antagonist/rev/proc/announce_victorious() + . = rev_team.check_rev_victory() + + if (!.) + return + + to_chat(owner, "[victory_message]") + var/policy = get_policy(ROLE_REV_SUCCESSFUL) + if (policy) + to_chat(owner, policy) + /datum/antagonist/rev/farewell() + if (announce_victorious()) + return + if(ishuman(owner.current)) owner.current.visible_message("[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!", null, null, null, owner.current) to_chat(owner, "You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel... You don't seem to be able to recall the names of your comrades, not even your leaders...") @@ -210,15 +232,17 @@ to_chat(owner, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing of your time spent reprogrammed, you can't even remember the names or identities of anyone involved...") /datum/antagonist/rev/head/farewell() - if((ishuman(owner.current) || ismonkey(owner.current))) + if (announce_victorious() || deconversion_reason == DECONVERTER_STATION_WIN) + return + if((ishuman(owner.current))) if(owner.current.stat != DEAD) - owner.current.visible_message("[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!", null, null, null, owner.current) + owner.current.visible_message(span_deconversion_message("[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!"), null, null, null, owner.current) to_chat(owner, "You have given up your cause of overthrowing the command staff. You are no longer a Head Revolutionary.") else to_chat(owner, "The sweet release of death. You are no longer a Head Revolutionary.") else if(issilicon(owner.current)) - owner.current.visible_message("The frame beeps contentedly, suppressing the disloyal personality traits from the MMI before initalizing it.", null, null, null, owner.current) - to_chat(owner, "The frame's firmware detects and suppresses your unwanted personality traits! You feel more content with the leadership around these parts.") + owner.current.visible_message(span_deconversion_message("The frame beeps contentedly, suppressing the disloyal personality traits from the MMI before initalizing it."), null, null, null, owner.current) + to_chat(owner, span_userdanger("The frame's firmware detects and suppresses your unwanted personality traits! You feel more content with the leadership around these parts.")) //blunt trauma deconversions call this through species.dm spec_attacked_by() /datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter) @@ -226,13 +250,14 @@ if(borged) message_admins("[ADMIN_LOOKUPFLW(owner.current)] has been borged while being a [name]") owner.special_role = null - if(iscarbon(owner.current)) + if(iscarbon(owner.current) && deconverter != DECONVERTER_REVS_WIN) var/mob/living/carbon/C = owner.current C.Unconscious(100) + deconversion_reason = deconverter owner.remove_antag_datum(type) /datum/antagonist/rev/head/remove_revolutionary(borged,deconverter) - if(borged || deconverter == "gamemode") + if(borged || deconverter == DECONVERTER_STATION_WIN || deconverter == DECONVERTER_REVS_WIN) . = ..() /datum/antagonist/rev/head/equip_rev() @@ -262,6 +287,21 @@ S.Insert(H, special = FALSE, drop_if_replaced = FALSE) to_chat(H, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.") +/// "Enemy of the Revolutionary", given to heads and security when the revolution wins +/datum/antagonist/revolution_enemy + name = "Enemy of the Revolution" + show_in_antagpanel = FALSE + +/datum/antagonist/revolution_enemy/on_gain() + owner.special_role = "revolution enemy" + + var/datum/objective/survive/survive = new /datum/objective/survive + survive.owner = owner + survive.explanation_text = "The station has been overrun by revolutionaries, stay alive until the end." + objectives += survive + + return ..() + /datum/team/revolution name = "Revolution" var/max_headrevs = 3 @@ -314,6 +354,100 @@ ex_headrevs = get_antag_minds(/datum/antagonist/rev/head, TRUE) ex_revs = get_antag_minds(/datum/antagonist/rev, TRUE) +/// Checks if revs have won +/datum/team/revolution/proc/check_rev_victory() + for(var/datum/objective/mutiny/objective in objectives) + if(!(objective.check_completion())) + return FALSE + return TRUE + +/// Checks if heads have won +/datum/team/revolution/proc/check_heads_victory() + for(var/datum/mind/rev_mind in head_revolutionaries()) + var/turf/rev_turf = get_turf(rev_mind.current) + if(!considered_afk(rev_mind) && considered_alive(rev_mind) && is_station_level(rev_turf.z)) + if(ishuman(rev_mind.current)) + return FALSE + return TRUE + +/// Updates the state of the world depending on if revs won or loss. +/// Returns who won, at which case this method should no longer be called. +/// If revs_win_injection_amount is passed, then that amount of threat will be added if the revs win. +/datum/team/revolution/proc/process_victory(revs_win_injection_amount) + if (check_rev_victory()) + . = REVOLUTION_VICTORY + else if (check_heads_victory()) + . = STATION_VICTORY + else + return + + SSshuttle.clearHostileEnvironment(src) + save_members() + + // Remove everyone as a revolutionary + for (var/_rev_mind in members) + var/datum/mind/rev_mind = _rev_mind + if (rev_mind.has_antag_datum(/datum/antagonist/rev)) + var/datum/antagonist/rev/rev_antag = rev_mind.has_antag_datum(/datum/antagonist/rev) + rev_antag.remove_revolutionary(FALSE, . == STATION_VICTORY ? DECONVERTER_STATION_WIN : DECONVERTER_REVS_WIN) + LAZYADD(rev_mind.special_statuses, "Former [(rev_mind in ex_headrevs) ? "head revolutionary" : "revolutionary"]") + + if (. == STATION_VICTORY) + // If the revolution was quelled, make rev heads unable to be revived through pods + for (var/_rev_head_mind in ex_revs) + var/datum/mind/rev_head_mind = _rev_head_mind + var/mob/living/carbon/rev_head_body = rev_head_mind.current + if(istype(rev_head_body) && rev_head_body.stat == DEAD) + rev_head_body.makeUncloneable() + + priority_announce("It appears the mutiny has been quelled. Please return yourself and your incapacitated colleagues to work. \ + We have remotely blacklisted the head revolutionaries in your medical records to prevent accidental revival.", null, 'sound/announcer/classic/attention.ogg', null, "Central Command Loyalty Monitoring Division") + else + for (var/_player in GLOB.player_list) + var/mob/player = _player + var/datum/mind/mind = player.mind + + if (isnull(mind)) + continue + + if (!(mind.assigned_role in GLOB.command_positions + GLOB.security_positions)) + continue + + var/mob/living/carbon/target_body = mind.current + + mind.add_antag_datum(/datum/antagonist/revolution_enemy) + + if (!istype(target_body)) + continue + + if (target_body.stat == DEAD) + target_body.makeUncloneable() + else + mind.announce_objectives() + + for (var/job_name in GLOB.command_positions + GLOB.security_positions) + var/datum/job/job = SSjob.GetJob(job_name) + job.allow_bureaucratic_error = FALSE + job.total_positions = 0 + + if (revs_win_injection_amount) + var/datum/game_mode/dynamic/dynamic = SSticker.mode + dynamic.create_threat(revs_win_injection_amount) + dynamic.threat_log += "[worldtime2text()]: Revolution victory. Added [revs_win_injection_amount] threat." + + priority_announce("A recent assessment of your station has marked your station as a severe risk area for high ranking Nanotrasen officials. \ + For the safety of our staff, we have blacklisted your station for new employment of security and command. \ + [pick(world.file2list("strings/anti_union_propaganda.txt"))]", null, 'sound/announcer/classic/attention.ogg', null, "Central Command Loyalty Monitoring Division") + +/// Mutates the ticker to report that the revs have won +/datum/team/revolution/proc/round_result(finished) + if (finished == REVOLUTION_VICTORY) + SSticker.mode_result = "win - heads killed" + SSticker.news_report = REVS_WIN + else if (finished == STATION_VICTORY) + SSticker.mode_result = "loss - rev heads killed" + SSticker.news_report = REVS_LOSE + /datum/team/revolution/roundend_report() if(!members.len && !ex_headrevs.len) return @@ -322,18 +456,6 @@ result += "
" - var/num_revs = 0 - var/num_survivors = 0 - for(var/mob/living/carbon/survivor in GLOB.alive_mob_list) - if(survivor.ckey) - num_survivors++ - if(survivor.mind) - if(is_revolutionary(survivor)) - num_revs++ - if(num_survivors) - result += "Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%
" - - var/list/targets = list() var/list/datum/mind/headrevs var/list/datum/mind/revs @@ -346,10 +468,22 @@ revs = ex_revs else revs = get_antag_minds(/datum/antagonist/rev, TRUE) + + var/num_revs = 0 + var/num_survivors = 0 + for(var/mob/living/carbon/survivor in GLOB.alive_mob_list) + if(survivor.ckey) + num_survivors += 1 + if ((survivor.mind in revs) || (survivor.mind in headrevs)) + num_revs += 1 + + if(num_survivors) + result += "Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%
" + if(headrevs.len) var/list/headrev_part = list() headrev_part += "The head revolutionaries were:" - headrev_part += printplayerlist(headrevs,TRUE) + headrev_part += printplayerlist(headrevs, !check_rev_victory()) result += headrev_part.Join("
") if(revs.len) @@ -408,3 +542,6 @@ /datum/team/revolution/is_gamemode_hero() return SSticker.mode.name == "revolution" + +#undef DECONVERTER_STATION_WIN +#undef DECONVERTER_REVS_WIN \ No newline at end of file diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 855e2ccbd7..1f5becace8 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -63,6 +63,9 @@ var/list/mind_traits // Traits added to the mind of the mob assigned this job var/list/blacklisted_quirks //list of quirk typepaths blacklisted. +/// Should this job be allowed to be picked for the bureaucratic error event? + var/allow_bureaucratic_error = TRUE + var/display_order = JOB_DISPLAY_ORDER_DEFAULT //If a job complies with dresscodes, loadout items will not be equipped instead of the job's outfit, instead placing the items into the player's backpack. diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm index d0eb690e94..38625cfd9c 100644 --- a/code/modules/jobs/job_types/ai.dm +++ b/code/modules/jobs/job_types/ai.dm @@ -14,6 +14,7 @@ exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_SILICON display_order = JOB_DISPLAY_ORDER_AI + allow_bureaucratic_error = FALSE var/do_special_check = TRUE threat = 5 considered_combat_role = TRUE diff --git a/config/entries/general.txt b/config/entries/general.txt index b3130565e4..f96815503b 100644 --- a/config/entries/general.txt +++ b/config/entries/general.txt @@ -465,6 +465,9 @@ ECONOMY #Replaces standard extended/secret dichotomy with extended and calm/chaotic votes for dynamic. #DYNAMIC_VOTING +## Uncomment to enable dynamic ruleset config file. +DYNAMIC_CONFIG_ENABLED + ## Choose which Engine to start the round with. Weight is after the comma. Setting the weight to 0 removes the engine from rotation. BOX_RANDOM_ENGINE Box SM,3 BOX_RANDOM_ENGINE Box Tesla,3 diff --git a/tgstation.dme b/tgstation.dme index 0f53705172..83c6477050 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -166,6 +166,7 @@ #include "code\__HELPERS\AStar.dm" #include "code\__HELPERS\chat.dm" #include "code\__HELPERS\cmp.dm" +#include "code\__HELPERS\config.dm" #include "code\__HELPERS\custom_holoforms.dm" #include "code\__HELPERS\dates.dm" #include "code\__HELPERS\dna.dm"