Replace adding threat (the traitor objective, post-revs victory) with unfavorable situations (#67538)

Hacking the command console and winning revs no longer adds midround threat. Instead, it'll force a heavy ruleset to spawn, and barring that, will spawn a dangerous random event.

Not really tested, you know how it is with stuff like this.

This change will slightly decrease the total number of midrounds in the round.
Why It's Good For The Game

Before D2022P1, midround threat effectively did not work. Adding midround threat did not guarantee anything would actually happen, whether that be the "obsessed spawn and doesn't do anything" kind of nothing happens, or the "absolutely no ruleset spawns" literally kind of nothing happens.

Sometimes, though, it might have! This PR makes that a guarantee.

After D2022P1, midround threat works and is also extremely dangerous in the quantities that are being added. 15 threat means 2-3 extra midround antagonists are spawned, and this late into the round are often going to force heavy rulesets anyway, but at a disproportionate cost.

Furthermore, adding midround threat decreases the time it takes for the next midround, as midround rolls are rolled equidistantly from one another. It is possible, for instance, for a midround ruleset to run, and then another to run seconds later as the distance changes.

This keeps things direct--the crew gets a disadvantage, but is not completely overwhelmed by several antagonists disproportionately.
This commit is contained in:
Mothblocks
2022-06-19 01:40:36 -07:00
committed by GitHub
parent 8fbd58734c
commit 97c040cee2
5 changed files with 70 additions and 22 deletions
+4 -3
View File
@@ -592,7 +592,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
return FALSE
/// An experimental proc to allow admins to call rules on the fly or have rules call other rules.
/datum/game_mode/dynamic/proc/picking_specific_rule(ruletype, forced = FALSE)
/datum/game_mode/dynamic/proc/picking_specific_rule(ruletype, forced = FALSE, ignore_cost = FALSE)
var/datum/dynamic_ruleset/midround/new_rule
if(ispath(ruletype))
new_rule = new ruletype() // You should only use it to call midround rules though.
@@ -618,10 +618,11 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
return FALSE
var/population = GLOB.alive_player_list.len
if((new_rule.acceptable(population, threat_level) && new_rule.cost <= mid_round_budget) || forced)
if((new_rule.acceptable(population, threat_level) && (ignore_cost || new_rule.cost <= mid_round_budget)) || forced)
new_rule.trim_candidates()
if (new_rule.ready(forced))
spend_midround_budget(new_rule.cost, threat_log, "[worldtime2text()]: Forced rule [new_rule.name]")
if (!ignore_cost)
spend_midround_budget(new_rule.cost, threat_log, "[worldtime2text()]: Forced rule [new_rule.name]")
new_rule.pre_execute(population)
if (new_rule.execute()) // This should never fail since ready() returned 1
if(new_rule.flags & HIGH_IMPACT_RULESET)
@@ -0,0 +1,52 @@
/// An easy interface to make...*waves hands* bad things happen.
/// This is used for impactful events like traitors hacking and creating more threat, or a revolutions victory.
/// It tries to spawn a heavy midround if possible, otherwise it will trigger a "bad" random event after a short period.
/// Calling this function will not use up any threat.
/datum/game_mode/dynamic/proc/unfavorable_situation()
var/static/list/unfavorable_random_events = list(
/datum/round_event_control/immovable_rod,
/datum/round_event_control/meteor_wave,
/datum/round_event_control/portal_storm_syndicate,
)
var/list/possible_heavies = list()
// Ignored factors: threat cost, minimum round time
for (var/datum/dynamic_ruleset/midround/ruleset as anything in midround_rules)
if (ruleset.midround_ruleset_style != MIDROUND_RULESET_STYLE_HEAVY)
continue
if (ruleset.weight == 0)
continue
if (ruleset.cost > max_threat_level)
continue
if (!ruleset.acceptable(GLOB.alive_player_list.len, threat_level))
continue
if (ruleset.minimum_round_time > world.time - SSticker.round_start_time)
continue
if(istype(ruleset, /datum/dynamic_ruleset/midround/from_ghosts) && !(GLOB.ghost_role_flags & GHOSTROLE_MIDROUND_EVENT))
continue
ruleset.trim_candidates()
if (!ruleset.ready())
continue
possible_heavies[ruleset] = ruleset.get_weight()
if (possible_heavies.len == 0)
var/datum/round_event_control/round_event_control_type = pick(unfavorable_random_events)
var/delay = rand(20 SECONDS, 1 MINUTES)
dynamic_log("An unfavorable situation was requested, but no heavy rulesets could be drafted. Spawning [initial(round_event_control_type.name)] in [DisplayTimeText(delay)] instead.")
var/datum/round_event_control/round_event_control = new round_event_control_type
addtimer(CALLBACK(round_event_control, /datum/round_event_control.proc/runEvent), delay)
else
var/datum/dynamic_ruleset/midround/heavy_ruleset = pick_weight(possible_heavies)
dynamic_log("An unfavorable situation was requested, spawning [initial(heavy_ruleset.name)]")
picking_specific_rule(heavy_ruleset, forced = TRUE, ignore_cost = TRUE)
+12 -18
View File
@@ -776,8 +776,6 @@
#define MIN_GHOSTS_FOR_FUGITIVES 6
/// The maximum percentage of the population to be ghosts before we no longer have the chance of spawning Sleeper Agents.
#define MAX_PERCENT_GHOSTS_FOR_SLEEPER 0.2
/// The amount of threat injected by a hack, if chosen.
#define HACK_THREAT_INJECTION_AMOUNT 15
/*
* The communications console hack,
@@ -811,8 +809,8 @@
if(HACK_PIRATE) // Triggers pirates, which the crew may be able to pay off to prevent
priority_announce(
"Attention crew, it appears that someone on your station has made unexpected communication with a Syndicate ship in nearby space.",
"[command_name()] High-Priority Update"
)
"[command_name()] High-Priority Update",
)
var/datum/round_event_control/pirates/pirate_event = locate() in SSevents.control
if(!pirate_event)
@@ -822,19 +820,19 @@
if(HACK_FUGITIVES) // Triggers fugitives, which can cause confusion / chaos as the crew decides which side help
priority_announce(
"Attention crew, it appears that someone on your station has made unexpected communication with an unmarked ship in nearby space.",
"[command_name()] High-Priority Update"
)
"[command_name()] High-Priority Update",
)
var/datum/round_event_control/fugitives/fugitive_event = locate() in SSevents.control
if(!fugitive_event)
CRASH("hack_console() attempted to run fugitives, but could not find an event controller!")
addtimer(CALLBACK(fugitive_event, /datum/round_event_control.proc/runEvent), rand(20 SECONDS, 1 MINUTES))
if(HACK_THREAT) // Adds a flat amount of threat to buy a (probably) more dangerous antag later
if(HACK_THREAT) // Force an unfavorable situation on the crew
priority_announce(
SSmapping.config.orbit_shift_replacement,
"[command_name()] High-Priority Update"
)
"[command_name()] High-Priority Update",
)
for(var/mob/crew_member as anything in GLOB.player_list)
if(!is_station_level(crew_member.z))
@@ -842,7 +840,7 @@
shake_camera(crew_member, 15, 1)
var/datum/game_mode/dynamic/dynamic = SSticker.mode
dynamic.create_threat(HACK_THREAT_INJECTION_AMOUNT, list(dynamic.threat_log, dynamic.roundend_threat_log), "[worldtime2text()]: Communications console hacked by [hacker]")
dynamic.unfavorable_situation()
if(HACK_SLEEPER) // Trigger one or multiple sleeper agents with the crew (or for latejoining crew)
var/datum/dynamic_ruleset/midround/sleeper_agent_type = /datum/dynamic_ruleset/midround/autotraitor
@@ -850,23 +848,20 @@
var/max_number_of_sleepers = clamp(round(length(GLOB.alive_player_list) / 20), 1, 3)
var/num_agents_created = 0
for(var/num_agents in 1 to rand(1, max_number_of_sleepers))
// Offset the threat cost of the sleeper agent(s) we're about to run...
dynamic.create_threat(initial(sleeper_agent_type.cost))
// ...Then try to actually trigger a sleeper agent.
if(!dynamic.picking_specific_rule(sleeper_agent_type, TRUE))
if(!dynamic.picking_specific_rule(sleeper_agent_type, forced = TRUE, ignore_cost = TRUE))
break
num_agents_created++
if(num_agents_created <= 0)
// We failed to run any midround sleeper agents, so let's be patient and run latejoin traitor
dynamic.picking_specific_rule(/datum/dynamic_ruleset/latejoin/infiltrator, TRUE)
dynamic.picking_specific_rule(/datum/dynamic_ruleset/latejoin/infiltrator, forced = TRUE, ignore_cost = TRUE)
else
// We spawned some sleeper agents, nice - give them a report to kickstart the paranoia
priority_announce(
"Attention crew, it appears that someone on your station has hijacked your telecommunications, broadcasting a Syndicate radio signal to your fellow employees.",
"[command_name()] High-Priority Update"
)
"[command_name()] High-Priority Update",
)
#undef HACK_PIRATE
#undef HACK_FUGITIVES
@@ -876,7 +871,6 @@
#undef MIN_GHOSTS_FOR_PIRATES
#undef MIN_GHOSTS_FOR_FUGITIVES
#undef MAX_PERCENT_GHOSTS_FOR_SLEEPER
#undef HACK_THREAT_INJECTION_AMOUNT
/datum/comm_message
var/title
@@ -486,7 +486,7 @@
if (revs_win_injection_amount)
var/datum/game_mode/dynamic/dynamic = SSticker.mode
dynamic.create_threat(revs_win_injection_amount, list(dynamic.threat_log, dynamic.roundend_threat_log), "[worldtime2text()]: Revolution victory")
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. \
+1
View File
@@ -1250,6 +1250,7 @@
#include "code\game\gamemodes\dynamic\dynamic_rulesets_midround.dm"
#include "code\game\gamemodes\dynamic\dynamic_rulesets_roundstart.dm"
#include "code\game\gamemodes\dynamic\dynamic_simulations.dm"
#include "code\game\gamemodes\dynamic\dynamic_unfavorable_situation.dm"
#include "code\game\gamemodes\dynamic\ruleset_picking.dm"
#include "code\game\machinery\_machinery.dm"
#include "code\game\machinery\ai_slipper.dm"