diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 55f540c4f796c..3421757c9291b 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -77,82 +77,6 @@ /datum/dynamic_ruleset/roundstart/hivemind ) -////////////////////////////////////////////// -// // -// REVOLUTIONARY PROVOCATEUR // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/latejoin/provocateur - name = "Provocateur" - persistent = TRUE - antag_datum = /datum/antagonist/rev/head - role_preference = /datum/role_preference/antagonist/revolutionary - restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_CHIEFENGINEER, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_RESEARCHDIRECTOR) - enemy_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER,JOB_NAME_DETECTIVE,JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_WARDEN) - required_enemies = list(2,2,1,1,1,1,1,0,0,0) - required_candidates = 1 - weight = 2 - delay = 1 MINUTES // Prevents rule start while head is offstation. - cost = 13 - requirements = list(101,101,70,40,30,20,20,20,20,20) - flags = HIGH_IMPACT_RULESET|INTACT_STATION_RULESET - blocking_rules = list(/datum/dynamic_ruleset/roundstart/revs) - var/required_heads_of_staff = 3 - var/finished = FALSE - /// How much threat should be injected when the revolution wins? - var/revs_win_threat_injection = 20 - var/datum/team/revolution/revolution - -/datum/dynamic_ruleset/latejoin/provocateur/ready(forced=FALSE) - if (forced) - required_heads_of_staff = 1 - if(!..()) - return FALSE - var/head_check = 0 - for(var/mob/player in mode.current_players[CURRENT_LIVING_PLAYERS]) - if (player.mind.assigned_role in GLOB.command_positions) - head_check++ - return (head_check >= required_heads_of_staff) - -/datum/dynamic_ruleset/latejoin/provocateur/execute(forced = FALSE) - var/mob/M = pick(candidates) // This should contain a single player, but in case. - if(check_eligible(M.mind)) // Didnt die/run off z-level/get implanted since leaving shuttle. - assigned += M.mind - M.mind.special_role = ROLE_REV_HEAD - revolution = new() - var/datum/antagonist/rev/head/new_head = new() - new_head.give_flash = TRUE - new_head.give_hud = TRUE - new_head.remove_clumsy = TRUE - new_head = M.mind.add_antag_datum(new_head, revolution) - revolution.update_objectives() - revolution.update_heads() - SSshuttle.registerHostileEnvironment(revolution) - return DYNAMIC_EXECUTE_SUCCESS - else - log_game("DYNAMIC: [ruletype] [name] discarded [M.name] from head revolutionary due to ineligibility.") - log_game("DYNAMIC: [ruletype] [name] failed to get any eligible headrevs. Refunding [cost] threat.") - return DYNAMIC_EXECUTE_NOT_ENOUGH_PLAYERS - -/datum/dynamic_ruleset/latejoin/provocateur/rule_process() - var/winner = revolution.process_victory(revs_win_threat_injection) - if (isnull(winner)) - return - - finished = winner - return RULESET_STOP_PROCESSING - -/// Checks for revhead loss conditions and other antag datums. -/datum/dynamic_ruleset/latejoin/provocateur/proc/check_eligible(var/datum/mind/M) - var/turf/T = get_turf(M.current) - if(!considered_afk(M) && considered_alive(M) && is_station_level(T.z) && !M.antag_datums?.len && !HAS_TRAIT(M, TRAIT_MINDSHIELD)) - return TRUE - return FALSE - -/datum/dynamic_ruleset/latejoin/provocateur/round_result() - revolution.round_result(finished) - ////////////////////////////////////////////// // // // HERETIC SMUGGLER // diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 8f05f9ad86340..89b51d29d3a5b 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -358,7 +358,6 @@ requirements = list(101,101,70,40,30,20,10,10,10,10) antag_cap = 3 flags = HIGH_IMPACT_RULESET | NO_OTHER_ROUNDSTARTS_RULESET | PERSISTENT_RULESET - blocking_rules = list(/datum/dynamic_ruleset/latejoin/provocateur) // I give up, just there should be enough heads with 35 players... minimum_players = 35 /// How much threat should be injected when the revolution wins? @@ -395,7 +394,6 @@ if(revolution.members.len) revolution.update_objectives() revolution.update_heads() - SSshuttle.registerHostileEnvironment(revolution) return DYNAMIC_EXECUTE_SUCCESS log_game("DYNAMIC: [ruletype] [name] failed to get any eligible headrevs. Refunding [cost] threat.") return DYNAMIC_EXECUTE_NOT_ENOUGH_PLAYERS diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 23e96e0fc4e83..301b7ddd293e1 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -15,7 +15,7 @@ antag_datum = /datum/antagonist/rev/head false_report_weight = 10 restricted_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_AI, JOB_NAME_CYBORG,JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_HEADOFSECURITY, JOB_NAME_CHIEFENGINEER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CHIEFMEDICALOFFICER) - required_jobs = list(list(JOB_NAME_CAPTAIN=1),list(JOB_NAME_HEADOFPERSONNEL=1),list(JOB_NAME_HEADOFSECURITY=1),list(JOB_NAME_CHIEFENGINEER=1),list(JOB_NAME_RESEARCHDIRECTOR=1),list(JOB_NAME_CHIEFMEDICALOFFICER=1)) //Any head present + required_jobs = list(list(JOB_NAME_CAPTAIN=1, JOB_NAME_LAWYER=1),list(JOB_NAME_HEADOFPERSONNEL=1),list(JOB_NAME_HEADOFSECURITY=1, JOB_NAME_LAWYER=1),list(JOB_NAME_CHIEFENGINEER=1, JOB_NAME_LAWYER=1),list(JOB_NAME_RESEARCHDIRECTOR=1, JOB_NAME_LAWYER=1),list(JOB_NAME_CHIEFMEDICALOFFICER=1, JOB_NAME_LAWYER=1)) //Any head present and a deconverter present required_players = 30 required_enemies = 2 recommended_enemies = 3 @@ -159,9 +159,11 @@ //Checks for rev victory// ////////////////////////// /datum/game_mode/revolution/proc/check_rev_victory() - for(var/datum/objective/mutiny/objective in revolution.objectives) - if(!(objective.check_completion())) - return FALSE + for(var/datum/mind/staff_mind in SSjob.get_all_heads()) + var/turf/location = get_turf(staff_mind.current) + if(!considered_afk(staff_mind) && considered_alive(staff_mind) && is_station_level(location.z)) + if(ishuman(staff_mind.current)) + return FALSE return TRUE ///////////////////////////// diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm index 5e22307559d44..85ff07f047e85 100644 --- a/code/game/objects/items/manuals.dm +++ b/code/game/objects/items/manuals.dm @@ -299,6 +299,53 @@ user.visible_message("[user] pretends to read \the [src] intently... then promptly dies of laughter!") return OXYLOSS +/obj/item/book/manual/wiki/security_space_law/afterattack(atom/target, mob/living/user, proximity_flag, click_parameters) + . = ..() + if (target != user && isliving(target) && (user.mind.assigned_role == JOB_NAME_LAWYER || user.mind.assigned_role == JOB_NAME_HEADOFPERSONNEL)) + INVOKE_ASYNC(src, PROC_REF(deconvert_target), user, target) + +/obj/item/book/manual/wiki/security_space_law/proc/deconvert_target(mob/living/user, mob/living/target) + if (user.do_afters) + return + for (var/i in 1 to 4) + if (user.do_afters) + return + if (!do_after(user, 2 SECONDS, target)) + return + if (user.mind?.has_antag_datum(/datum/antagonist/rev)) + switch (i) + if (1) + user.say("Number One: In 1945, corporations paid 50% of federal taxes; now they pay about 5%.", forced="space law") + if (2) + user.say("Number Two: In 1900, 90% of people were self employed; now it's about 2%... It's called consolidation; strengthen governments and corporations, weaken individuals. With taxes, this can be done imperceptibly over time.", forced="space law") + if (3) + user.say("Number Three: In the 2030s, there were strict regulations to prevent monopolies; now those regulations have been dismantled, allowing a few companies to control entire industries. This concentration of power stifles competition and innovation.") + if (4) + user.say("Number Four: In the past, media outlets were independent; now a handful of conglomerates control the majority of information. Control the narrative, control the minds of the masses.") + else + var/datum/crime/chosen = pick(subtypesof(/datum/crime) - /datum/crime/minor - /datum/crime/capital - /datum/crime/major - /datum/crime/misdemeanour) + user.say("[initial(chosen.tooltip)]", forced = "space law") + if (user.do_afters) + return + if (!do_after(user, 2 SECONDS, target)) + return + if (user.mind?.has_antag_datum(/datum/antagonist/rev)) + var/datum/antagonist/rev/rev = user.mind.has_antag_datum(/datum/antagonist/rev) + user.say("Isn't it obvious, Nanotrasen, the governments; everyone around us has been tricking us, playing us like we are pawns...", forced = "space law") + if (rev.add_revolutionary(target.mind, FALSE)) + target.visible_message("[target] nods in approval, taking in the information!", "That all makes perfect sense, the truth washes over you!") + else + target.visible_message("[target] spits on the floor, disrespecting [user]'s authority!", "You finish listening to [user]'s waffling. What a knobhead, you think to yourself...") + else + user.say("These shall all be considered acts which are in violation of your contract of employment, and you are contractually obliged to not commit them.", forced = "space law") + if(target.mind?.has_antag_datum(/datum/antagonist/rev/head) || target.mind?.unconvertable) + target.visible_message("[target] spits on the floor, disrespecting [user]'s authority!", "You finish listening to [user]'s waffling. What a knobhead, you think to yourself...") + return + var/datum/antagonist/rev/rev = target.mind?.has_antag_datum(/datum/antagonist/rev) + if(rev) + rev.remove_revolutionary(FALSE, user) + target.visible_message("[target] nods in approval, taking in the information!", "That all makes perfect sense, you feel a sense of pride to be working for Nanotrasen!") + /obj/item/book/manual/wiki/infections name = "Infections - Making your own pandemic!" icon_state = "bookInfections" diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index e4689ce8acebe..afaa77f842353 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -12,9 +12,6 @@ var/hud_type = "rev" var/datum/team/revolution/rev_team - /// 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) . = ..() if(.) @@ -49,10 +46,10 @@ . = ..() /datum/antagonist/rev/greet() - to_chat(owner, "You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!") + to_chat(owner, "You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Establish a new command structure for the station that will bring fairness to all.") owner.announce_objectives() owner.current.client?.tgui_panel?.give_antagonist_popup("Revolution", - "Eliminate the heads of staff. Viva la revolution!") + "Establish a new command structure to live a better life. Viva la revolution!") /datum/antagonist/rev/create_team(datum/team/revolution/new_team) if(!new_team) @@ -212,38 +209,19 @@ 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]") - /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...the only thing you remember is the name of the one who brainwashed you...") else if(issilicon(owner.current)) - owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.", null, null, null, owner.current) to_chat(owner, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.") /datum/antagonist/rev/head/farewell() - if (announce_victorious()) - 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) 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.") //blunt trauma deconversions call this through species.dm spec_attacked_by() @@ -287,22 +265,6 @@ 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 - banning_key = UNBANNABLE_ANTAGONIST - -/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 @@ -310,15 +272,8 @@ var/list/ex_revs = list() /datum/team/revolution/proc/update_objectives(initial = FALSE) - var/untracked_heads = SSjob.get_all_heads() - for(var/datum/objective/mutiny/O in objectives) - untracked_heads -= O.target - for(var/datum/mind/M in untracked_heads) - var/datum/objective/mutiny/new_target = new() - new_target.team = src - new_target.set_target(M) - new_target.update_explanation_text() - objectives += new_target + if (!objectives) + objectives += new /datum/objective/revolution() for(var/datum/mind/M in members) var/datum/antagonist/rev/R = M.has_antag_datum(/datum/antagonist/rev) R.objectives |= objectives @@ -359,15 +314,13 @@ addtimer(CALLBACK(src,PROC_REF(update_heads)),HEAD_UPDATE_PERIOD,TIMER_UNIQUE) -/datum/team/revolution/proc/save_members() - 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 + for(var/datum/mind/staff_mind in SSjob.get_all_heads()) + var/turf/location = get_turf(staff_mind.current) + if(!considered_afk(staff_mind) && considered_alive(staff_mind) && is_station_level(location.z)) + if(ishuman(staff_mind.current)) + return FALSE return TRUE /// Checks if heads have won @@ -384,69 +337,9 @@ /// 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 + return 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, SSstation.announcer.get_rand_report_sound(), 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.unfavorable_situation() - - 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, SSstation.announcer.get_rand_report_sound(), null, "Central Command Loyalty Monitoring Division") - addtimer(CALLBACK(SSshuttle.emergency, TYPE_PROC_REF(/obj/docking_port/mobile/emergency, request), null, 1), 50) + return STATION_VICTORY /// Mutates the ticker to report that the revs have won /datum/team/revolution/proc/round_result(finished) @@ -456,6 +349,9 @@ else if (finished == STATION_VICTORY) SSticker.mode_result = "loss - rev heads killed" SSticker.news_report = REVS_LOSE + else + SSticker.mode_result = "minor win - station forced to be abandoned" + SSticker.news_report = STATION_EVACUATED /datum/team/revolution/roundend_report() if(!members.len && !ex_headrevs.len) @@ -552,5 +448,12 @@ /datum/team/revolution/is_gamemode_hero() return SSticker.mode.name == "revolution" +/datum/objective/revolution + name = "revolution" + explanation_text = "Establish a new chain of command by throwing out the old heads of staff and promoting new ones." + +/datum/objective/revolution/get_completion_message() + return "[explanation_text]" + #undef DECONVERTER_STATION_WIN #undef DECONVERTER_REVS_WIN