Mirror 72339 & 71284 (#18645)

* Renews a bunch of old roundend new reports that got lost. Plus, some roundend report QoL for cult and revs. (#71284)

A few roundend reports got lost from moving to dynamic and other prs.
This PRs re-allows them to occur. Namely: "Wizard Killed" (lost in
dynamic), "Blob nuked" (lost in dynamic), "Cult escaped" (lost in cult
rework), and "Nuke Ops Victory" (station destroyed via nuke) (lost from,
what I can see, an oversight / accidental swap of report values).

Additionally, small roundend report QOL for cult: Removes antag datums
from spirit realm ghosts after being dusted, so they do not show up on
the report. And in reverse, heads of staff who were dusted / destroyed
in revolution rounds are now also shown in roundend reports.

Some of these reports are dead, which is is a shame because I think
they're cool and fun.

🆑 Melbert
qol: Successfully fending off a blob now has a cross station news report
again. More pressing reports will take priority over it, though.
qol: Successfully killing a wizard (and all of their apprentices) now
has a cross station news report again.
qol: If more than half of a cultist team manages to escape on the
shuttle (rather than summoning Nar'sie), they will send a unique cross
station news report. This is still a loss, by the way. Summon Nar'sie!
qol: Nuclear Operatives successfully nuking the station now has its
unique cross station news report again, and no longer uses the generic
"The station was nuked" report.
qol: Nuking the station to stop a blob infection now has a unique cross
station news report again. Good luck convincing admins to allow this.
qol: Cult ghosts from "Spirit Realm" no longer persist on the cult's
team after being desummoned, meaning they will not show up on roundend
report.
qol: Heads of staff will now always show up on revolution roundend
report - even if their body was fully destroyed.
/🆑

* Adds support for Rulesets having intrinsic template requirements (#72339)

Title

Ensures that we load templates for a ruleset before we attempt to place
or cache characters for that ruleset
Also makes wizard and abductor async load their template to improve
(apparent) loading times for them

This is the only thing left that I can think of that would cause antags
like nukies and abductors to spawn in wrong

This should not be player facing

Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
This commit is contained in:
Zonespace
2023-01-11 22:18:18 -08:00
committed by GitHub
parent 8c0555856d
commit aa441a9633
25 changed files with 228 additions and 87 deletions
-2
View File
@@ -11,8 +11,6 @@
#define STATION_EVACUATED 5
/// The blob has reached critical mass and overtaken the station
#define BLOB_WIN 8
/// The station's nuke was detonated destroying the blob
#define BLOB_NUKE 9
/// The blob was destroyed by the crew
#define BLOB_DESTROYED 10
/// The cult managed to escape alive on the shuttle
+22 -25
View File
@@ -958,42 +958,39 @@ SUBSYSTEM_DEF(job)
living_mob.forceMove(toLaunch)
new /obj/effect/pod_landingzone(spawn_turf, toLaunch)
///////////////////////////////////
//Keeps track of all living heads//
///////////////////////////////////
/// Returns a list of minds of all heads of staff who are alive
/datum/controller/subsystem/job/proc/get_living_heads()
. = list()
for(var/mob/living/carbon/human/player as anything in GLOB.human_list)
if(player.stat != DEAD && (player.mind?.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND))
. += player.mind
for(var/datum/mind/head as anything in get_crewmember_minds())
if(!(head.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND))
continue
if(isnull(head.current) || head.current.stat == DEAD)
continue
. += head
////////////////////////////
//Keeps track of all heads//
////////////////////////////
/// Returns a list of minds of all heads of staff
/datum/controller/subsystem/job/proc/get_all_heads()
. = list()
for(var/mob/living/carbon/human/player as anything in GLOB.human_list)
if(player.mind?.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)
. += player.mind
for(var/datum/mind/head as anything in get_crewmember_minds())
if(head.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)
. += head
//////////////////////////////////////////////
//Keeps track of all living security members//
//////////////////////////////////////////////
/// Returns a list of minds of all security members who are alive
/datum/controller/subsystem/job/proc/get_living_sec()
. = list()
for(var/mob/living/carbon/human/player as anything in GLOB.human_list)
if(player.stat != DEAD && (player.mind?.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_SECURITY))
. += player.mind
for(var/datum/mind/sec as anything in get_crewmember_minds())
if(!(sec.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_SECURITY))
continue
if(isnull(sec.current) || sec.current.stat == DEAD)
continue
. += sec
////////////////////////////////////////
//Keeps track of all security members//
////////////////////////////////////////
/// Returns a list of minds of all security members
/datum/controller/subsystem/job/proc/get_all_sec()
. = list()
for(var/mob/living/carbon/human/player as anything in GLOB.human_list)
if(player.mind?.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_SECURITY)
. += player.mind
for(var/datum/mind/sec as anything in get_crewmember_minds())
if(sec.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_SECURITY)
. += sec
/datum/controller/subsystem/job/proc/JobDebug(message)
log_job_debug(message)
+11 -1
View File
@@ -861,6 +861,17 @@ GLOBAL_LIST_EMPTY(the_station_areas)
/datum/controller/subsystem/mapping/proc/lazy_load_template(template_key, force = FALSE)
RETURN_TYPE(/datum/turf_reservation)
var/static/lazy_loading = FALSE
UNTIL(!lazy_loading)
lazy_loading = TRUE
. = _lazy_load_template(template_key, force)
lazy_loading = FALSE
return .
/datum/controller/subsystem/mapping/proc/_lazy_load_template(template_key, force = FALSE)
PRIVATE_PROC(TRUE)
if(LAZYACCESS(loaded_lazy_templates, template_key) && !force)
var/datum/lazy_template/template = GLOB.lazy_templates[template_key]
return template.reservations[1]
@@ -869,7 +880,6 @@ GLOBAL_LIST_EMPTY(the_station_areas)
var/datum/lazy_template/target = GLOB.lazy_templates[template_key]
if(!target)
CRASH("Attempted to lazy load a template key that does not exist: '[template_key]'")
return target.lazy_load()
/proc/generate_lighting_appearance_by_z(z_level)
+70 -20
View File
@@ -48,6 +48,7 @@ SUBSYSTEM_DEF(ticker)
var/queue_delay = 0
var/list/queued_players = list() //used for join queues when the server exceeds the hard population cap
/// What is going to be reported to other stations at end of round?
var/news_report
@@ -582,47 +583,96 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/send_news_report()
var/news_message
var/news_source = "Nanotrasen News Network"
var/decoded_station_name = html_decode("[CONFIG_GET(string/cross_comms_name)]([station_name()])") //decode station_name to avoid minor_announce double encode //SKYRAT EDIT CHANGE
var/decoded_station_name = html_decode(CONFIG_GET(string/cross_comms_name)) //decode station_name to avoid minor_announce double encode // SKYRAT EDIT: CROSS COMMS CONFIG
switch(news_report)
// The nuke was detonated on the syndicate recon outpost
if(NUKE_SYNDICATE_BASE)
news_message = "In a daring raid, the heroic crew of [decoded_station_name] detonated a nuclear device in the heart of a terrorist base."
news_message = "In a daring raid, the heroic crew of [decoded_station_name] \
detonated a nuclear device in the heart of a terrorist base."
// The station was destroyed by nuke ops
if(STATION_DESTROYED_NUKE)
news_message = "We would like to reassure all employees that the reports of a Syndicate backed nuclear attack on [decoded_station_name] are, in fact, a hoax. Have a secure day!"
news_message = "We would like to reassure all employees that the reports of a Syndicate \
backed nuclear attack on [decoded_station_name] are, in fact, a hoax. Have a secure day!"
// The station was evacuated (normal result)
if(STATION_EVACUATED)
// Had an emergency reason supplied to pass along
if(emergency_reason)
news_message = "[decoded_station_name] has been evacuated after transmitting the following distress beacon:\n\n[html_decode(emergency_reason)]"
news_message = "[decoded_station_name] has been evacuated after transmitting \
the following distress beacon:\n\n[html_decode(emergency_reason)]"
else
news_message = "The crew of [decoded_station_name] has been evacuated amid unconfirmed reports of enemy activity."
news_message = "The crew of [decoded_station_name] has been \
evacuated amid unconfirmed reports of enemy activity."
// A blob won
if(BLOB_WIN)
news_message = "[decoded_station_name] was overcome by an unknown biological outbreak, killing all crew on board. Don't let it happen to you! Remember, a clean work station is a safe work station."
if(BLOB_NUKE)
news_message = "[decoded_station_name] is currently undergoing decontanimation after a controlled burst of radiation was used to remove a biological ooze. All employees were safely evacuated prior, and are enjoying a relaxing vacation."
news_message = "[decoded_station_name] was overcome by an unknown biological outbreak, killing \
all crew on board. Don't let it happen to you! Remember, a clean work station is a safe work station."
// A blob was destroyed
if(BLOB_DESTROYED)
news_message = "[decoded_station_name] is currently undergoing decontamination procedures after the destruction of a biological hazard. As a reminder, any crew members experiencing cramps or bloating should report immediately to security for incineration."
news_message = "[decoded_station_name] is currently undergoing decontamination procedures \
after the destruction of a biological hazard. As a reminder, any crew members experiencing \
cramps or bloating should report immediately to security for incineration."
// A certain percentage of all cultists managed to escape at the end of round
if(CULT_ESCAPE)
news_message = "Security Alert: A group of religious fanatics have escaped from [decoded_station_name]."
// Cult was completely or almost completely wiped out
if(CULT_FAILURE)
news_message = "Following the dismantling of a restricted cult aboard [decoded_station_name], we would like to remind all employees that worship outside of the Chapel is strictly prohibited, and cause for termination."
news_message = "Following the dismantling of a restricted cult aboard [decoded_station_name], \
we would like to remind all employees that worship outside of the Chapel is strictly prohibited, \
and cause for termination."
// Cult summoned Nar'sie
if(CULT_SUMMON)
news_message = "Company officials would like to clarify that [decoded_station_name] was scheduled to be decommissioned following meteor damage earlier this year. Earlier reports of an unknowable eldritch horror were made in error."
news_message = "Company officials would like to clarify that [decoded_station_name] was scheduled \
to be decommissioned following meteor damage earlier this year. Earlier reports of an \
unknowable eldritch horror were made in error."
// Nuke detonated, but missed the station entirely
if(NUKE_MISS)
news_message = "The Syndicate have bungled a terrorist attack [decoded_station_name], detonating a nuclear weapon in empty space nearby."
news_message = "The Syndicate have bungled a terrorist attack [decoded_station_name], \
detonating a nuclear weapon in empty space nearby."
// All nuke ops got killed
if(OPERATIVES_KILLED)
news_message = "Repairs to [decoded_station_name] are underway after an elite Syndicate death squad was wiped out by the crew."
news_message = "Repairs to [decoded_station_name] are underway after an elite \
Syndicate death squad was wiped out by the crew."
// Nuke ops results inconclusive - Crew escaped without the disk, or nukies were left alive, or something
if(OPERATIVE_SKIRMISH)
news_message = "A skirmish between security forces and Syndicate agents aboard [decoded_station_name] ended with both sides bloodied but intact."
news_message = "A skirmish between security forces and Syndicate agents aboard [decoded_station_name] \
ended with both sides bloodied but intact."
// Revolution victory
if(REVS_WIN)
news_message = "Company officials have reassured investors that despite a union led revolt aboard [decoded_station_name] there will be no wage increases for workers."
news_message = "Company officials have reassured investors that despite a union led revolt \
aboard [decoded_station_name] there will be no wage increases for workers."
// Revolution defeat
if(REVS_LOSE)
news_message = "[decoded_station_name] quickly put down a misguided attempt at mutiny. Remember, unionizing is illegal!"
news_message = "[decoded_station_name] quickly put down a misguided attempt at mutiny. \
Remember, unionizing is illegal!"
// All wizards (plus apprentices) have been killed
if(WIZARD_KILLED)
news_message = "Tensions have flared with the Space Wizard Federation following the death of one of their members aboard [decoded_station_name]."
news_message = "Tensions have flared with the Space Wizard Federation following the death \
of one of their members aboard [decoded_station_name]."
// The station was nuked generically
if(STATION_NUKED)
news_message = "[decoded_station_name] activated its self-destruct device for unknown reasons. Attempts to clone the Captain for arrest and execution are underway."
// There was a blob on board, guess it was nuked to stop it
if(length(GLOB.overminds))
for(var/mob/camera/blob/overmind as anything in GLOB.overminds)
if(overmind.max_count < overmind.announcement_size)
continue
news_message = "[decoded_station_name] is currently undergoing decontanimation after a controlled \
burst of radiation was used to remove a biological ooze. All employees were safely evacuated prior, \
and are enjoying a relaxing vacation."
break
// A self destruct or something else
else
news_message = "[decoded_station_name] activated its self-destruct device for unknown reasons. \
Attempts to clone the Captain for arrest and execution are underway."
// The emergency escape shuttle was hijacked
if(SHUTTLE_HIJACK)
news_message = "During routine evacuation procedures, the emergency shuttle of [decoded_station_name] had its navigation protocols corrupted and went off course, but was recovered shortly after."
news_message = "During routine evacuation procedures, the emergency shuttle of [decoded_station_name] \
had its navigation protocols corrupted and went off course, but was recovered shortly after."
// A supermatter cascade triggered
if(SUPERMATTER_CASCADE)
news_message = "Officials are advising nearby colonies about a newly declared exclusion zone in the sector surrounding [decoded_station_name]."
news_message = "Officials are advising nearby colonies about a newly declared exclusion zone in \
the sector surrounding [decoded_station_name]."
//SKYRAT EDIT - START
if(SSblackbox.first_death)
+2 -1
View File
@@ -73,7 +73,8 @@
var/has_ever_been_ai = FALSE
var/last_death = 0
/// Set by Into The Sunset command of the shuttle manipulator
/// Set by Into The Sunset command of the shuttle manipulator.
/// If TRUE, the mob will always be considered "escaped" if they are alive and not exiled.
var/force_escaped = FALSE
var/list/learned_recipes //List of learned recipe TYPES.
+10 -1
View File
@@ -290,7 +290,11 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
// If it got to this part, just pick one high impact ruleset if it exists
for(var/datum/dynamic_ruleset/rule in executed_rules)
if(rule.flags & HIGH_IMPACT_RULESET)
return rule.round_result()
rule.round_result()
// One was set, so we're done here
if(SSticker.news_report)
return
return ..()
/datum/game_mode/dynamic/proc/send_intercept()
@@ -503,6 +507,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
rule.acceptable(roundstart_pop_ready, threat_level) // Assigns some vars in the modes, running it here for consistency
rule.candidates = candidates.Copy()
rule.trim_candidates()
rule.load_templates()
if (rule.ready(roundstart_pop_ready, TRUE))
var/cost = rule.cost
var/scaled_times = 0
@@ -523,6 +528,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (rule.acceptable(roundstart_pop_ready, threat_level) && round_start_budget >= rule.cost) // If we got the population and threat required
rule.candidates = candidates.Copy()
rule.trim_candidates()
rule.load_templates()
if (rule.ready(roundstart_pop_ready) && rule.candidates.len > 0)
drafted_rules[rule] = rule.weight
@@ -630,6 +636,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
var/population = GLOB.alive_player_list.len
if((new_rule.acceptable(population, threat_level) && (ignore_cost || new_rule.cost <= mid_round_budget)) || forced)
new_rule.trim_candidates()
new_rule.load_templates()
if (new_rule.ready(forced))
if (!ignore_cost)
spend_midround_budget(new_rule.cost, threat_log, "[worldtime2text()]: Forced rule [new_rule.name]")
@@ -682,6 +689,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (forced_latejoin_rule)
forced_latejoin_rule.candidates = list(newPlayer)
forced_latejoin_rule.trim_candidates()
forced_latejoin_rule.load_templates()
log_dynamic("Forcing ruleset [forced_latejoin_rule]")
if (forced_latejoin_rule.ready(TRUE))
if (!forced_latejoin_rule.repeatable)
@@ -704,6 +712,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
rule.candidates = list(newPlayer)
rule.trim_candidates()
rule.load_templates()
if (rule.ready())
drafted_rules[rule] = rule.get_weight()
@@ -62,6 +62,7 @@
continue
ruleset.trim_candidates()
ruleset.load_templates()
if (!ruleset.ready())
log_game("DYNAMIC: FAIL: [ruleset] is not ready()")
continue
@@ -85,6 +85,9 @@
/// If written as a linear equation, will be in the form of `list("denominator" = denominator, "offset" = offset).
var/antag_cap = 0
/// A list, or null, of templates that the ruleset depends on to function correctly
var/list/ruleset_lazy_templates
/datum/dynamic_ruleset/New()
// Rulesets can be instantiated more than once, such as when an admin clicks
// "Execute Midround Ruleset". Thus, it would be wrong to perform any
@@ -173,6 +176,11 @@
/datum/dynamic_ruleset/proc/ready(forced = 0)
return check_candidates()
/// This should always be called before ready is, to ensure that the ruleset can locate map/template based landmarks as needed
/datum/dynamic_ruleset/proc/load_templates()
for(var/template in ruleset_lazy_templates)
SSmapping.lazy_load_template(template)
/// Runs from gamemode process() if ruleset fails to start, like delayed rulesets not getting valid candidates.
/// This one only handles refunding the threat, override in ruleset to clean up the rest.
/datum/dynamic_ruleset/proc/clean_up()
@@ -347,12 +347,12 @@
cost = 10
requirements = REQUIREMENTS_VERY_HIGH_THREAT_NEEDED
flags = HIGH_IMPACT_RULESET
ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_WIZARDDEN)
/datum/dynamic_ruleset/midround/from_ghosts/wizard/ready(forced = FALSE)
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN)
if (!check_candidates())
if(!check_candidates())
return FALSE
if(GLOB.wizardstart.len == 0)
if(!length(GLOB.wizardstart))
log_admin("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.")
message_admins("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.")
return FALSE
@@ -273,16 +273,30 @@
weight = 2
cost = 20
requirements = list(90,90,90,80,60,40,30,20,10,10)
var/list/roundstart_wizards = list()
ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_WIZARDDEN)
/datum/dynamic_ruleset/roundstart/wizard/acceptable(population=0, threat=0)
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN)
if(GLOB.wizardstart.len == 0)
/datum/dynamic_ruleset/roundstart/wizard/ready(forced = FALSE)
if(!check_candidates())
return FALSE
if(!length(GLOB.wizardstart))
log_admin("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.")
message_admins("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.")
return FALSE
return ..()
/datum/dynamic_ruleset/roundstart/wizard/round_result()
for(var/datum/antagonist/wizard/wiz in GLOB.antagonists)
var/mob/living/real_wiz = wiz.owner?.current
if(isnull(real_wiz))
continue
var/turf/wiz_location = get_turf(real_wiz)
// If this wiz is alive AND not in an away level, then we know not all wizards are dead and can leave entirely
if(considered_alive(wiz.owner) && wiz_location && !is_away_level(wiz_location.z))
return
SSticker.news_report = WIZARD_KILLED
/datum/dynamic_ruleset/roundstart/wizard/pre_execute()
. = ..()
if(GLOB.wizardstart.len == 0)
@@ -361,13 +375,25 @@
return TRUE
/datum/dynamic_ruleset/roundstart/bloodcult/round_result()
..()
if(main_cult.check_cult_victory())
SSticker.mode_result = "win - cult win"
SSticker.news_report = CULT_SUMMON
else
SSticker.mode_result = "loss - staff stopped the cult"
SSticker.news_report = CULT_FAILURE
return
SSticker.mode_result = "loss - staff stopped the cult"
if(main_cult.size_at_maximum == 0)
CRASH("Cult team existed with a size_at_maximum of 0 at round end!")
// If more than a certain ratio of our cultists have escaped, give the "cult escape" resport.
// Otherwise, give the "cult failure" report.
var/ratio_to_be_considered_escaped = 0.5
var/escaped_cultists = 0
for(var/datum/mind/escapee as anything in main_cult.members)
if(considered_escaped(escapee))
escaped_cultists++
SSticker.news_report = (escaped_cultists / main_cult.size_at_maximum) >= ratio_to_be_considered_escaped ? CULT_ESCAPE : CULT_FAILURE
//////////////////////////////////////////////
// //
@@ -391,6 +417,7 @@
requirements = list(90,90,90,80,60,40,30,20,10,10)
flags = HIGH_IMPACT_RULESET
antag_cap = list("denominator" = 18, "offset" = 1)
ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_NUKIEBASE)
var/required_role = ROLE_NUCLEAR_OPERATIVE
var/datum/team/nuclear/nuke_team
@@ -432,10 +459,10 @@
SSticker.news_report = NUKE_SYNDICATE_BASE
if(NUKE_RESULT_NUKE_WIN)
SSticker.mode_result = "win - syndicate nuke"
SSticker.news_report = STATION_NUKED
SSticker.news_report = STATION_DESTROYED_NUKE
if(NUKE_RESULT_NOSURVIVORS)
SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time"
SSticker.news_report = STATION_NUKED
SSticker.news_report = STATION_DESTROYED_NUKE
if(NUKE_RESULT_WRONG_STATION)
SSticker.mode_result = "halfwin - blew wrong station"
SSticker.news_report = NUKE_MISS
@@ -38,6 +38,7 @@
ruleset.trim_candidates()
ruleset.load_templates()
if (!ruleset.ready())
continue
+5 -5
View File
@@ -212,14 +212,14 @@
//Set result and news report here
/datum/game_mode/proc/set_round_result()
SSticker.mode_result = "undefined"
// Something nuked the station - it wasn't nuke ops (they set their own via their rulset)
if(GLOB.station_was_nuked)
SSticker.news_report = STATION_DESTROYED_NUKE
if(EMERGENCY_ESCAPED_OR_ENDGAMED)
SSticker.news_report = STATION_EVACUATED
if(SSshuttle.emergency.is_hijacked())
SSticker.news_report = SHUTTLE_HIJACK
SSticker.news_report = STATION_NUKED
if(SSsupermatter_cascade.cascade_initiated)
SSticker.news_report = SUPERMATTER_CASCADE
// Only show this one if we have nothing better to show
if(EMERGENCY_ESCAPED_OR_ENDGAMED && !SSticker.news_report)
SSticker.news_report = SSshuttle.emergency?.is_hijacked() ? SHUTTLE_HIJACK : STATION_EVACUATED
/// Mode specific admin panel.
/datum/game_mode/proc/admin_panel()
+13 -6
View File
@@ -61,21 +61,28 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION
update_explanation_text()
/datum/objective/proc/considered_escaped(datum/mind/M)
if(!considered_alive(M))
/**
* Checks if the passed mind is considered "escaped".
*
* Escaped mobs are used to check certain antag objectives / results.
*
* Escaped includes minds with alive, non-exiled mobs generally.
*/
/proc/considered_escaped(datum/mind/escapee)
if(!considered_alive(escapee))
return FALSE
if(considered_exiled(M))
if(considered_exiled(escapee))
return FALSE
if(M.force_escaped)
if(escapee.force_escaped)
return TRUE
if(SSticker.force_ending || GLOB.station_was_nuked) // Just let them win.
return TRUE
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
return FALSE
var/area/current_area = get_area(M.current)
var/area/current_area = get_area(escapee.current)
if(!current_area || istype(current_area, /area/shuttle/escape/brig)) // Fails if they are in the shuttle brig
return FALSE
var/turf/current_turf = get_turf(M.current)
var/turf/current_turf = get_turf(escapee.current)
return current_turf.onCentCom() || current_turf.onSyndieBase()
/datum/objective/proc/check_completion()
@@ -115,4 +115,3 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
///Custom names for individuals in a team
/datum/team/proc/antag_listing_name()
return name
@@ -17,6 +17,11 @@
/// Type path for the associated job datum.
var/role_job = /datum/job/abductor_agent
/datum/antagonist/abductor/New()
// lets get the loading started now, but don't block waiting for it
INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_ABDUCTOR_SHIPS)
return ..()
/datum/antagonist/abductor/get_preview_icon()
var/mob/living/carbon/human/dummy/consistent/scientist = new
var/mob/living/carbon/human/dummy/consistent/agent = new
@@ -99,6 +104,8 @@
H.real_name = "[team.name] [sub_role]"
H.equipOutfit(outfit)
// We require that the template be loaded here, so call it in a blocking manner, if its already done loading, this won't block
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_ABDUCTOR_SHIPS)
//Teleport to ship
for(var/obj/effect/landmark/abductor/LM in GLOB.landmarks_list)
if(istype(LM, landmark_type) && LM.team_number == team.team_number)
@@ -116,7 +123,6 @@
. = ..()
/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_ABDUCTOR_SHIPS)
var/list/current_teams = list()
for(var/datum/team/abductor_team/T in GLOB.antagonist_teams)
current_teams[T.name] = T
@@ -135,6 +135,8 @@ GLOBAL_LIST_EMPTY(blob_nodes)
if(autoplace_max_time && world.time >= autoplace_max_time)
place_blob_core(BLOB_RANDOM_PLACEMENT)
else
// If we get here, it means yes: the blob is kill
SSticker.news_report = BLOB_DESTROYED
qdel(src)
else if(!victory_in_progress && (blobs_legit.len >= blobwincount))
victory_in_progress = TRUE
+9
View File
@@ -271,6 +271,8 @@
///Has narsie been summoned yet?
var/narsie_summoned = FALSE
///How large were we at max size.
var/size_at_maximum = 0
/datum/team/cult/proc/check_size()
if(cult_ascendent)
@@ -305,6 +307,13 @@
cult_ascendent = TRUE
log_game("The blood cult has ascended with [cultplayers] players.")
/datum/team/cult/add_member(datum/mind/new_member)
. = ..()
// A little hacky, but this checks that cult ghosts don't contribute to the size at maximum value.
if(is_unassigned_job(new_member.assigned_role))
return
size_at_maximum++
/datum/team/cult/proc/make_image(datum/objective/sacrifice/sac_objective)
var/datum/job/job_of_sacrifice = sac_objective.target.assigned_role
var/datum/preferences/prefs_of_sacrifice = sac_objective.target.current.client.prefs
+4 -1
View File
@@ -869,7 +869,8 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(user, span_cultitalic("Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely..."))
var/obj/structure/emergency_shield/cult/weak/N = new(T)
new_human.key = ghost_to_spawn.key
new_human.mind?.add_antag_datum(/datum/antagonist/cult)
var/datum/antagonist/cult/created_cultist = new_human.mind?.add_antag_datum(/datum/antagonist/cult)
created_cultist?.silent = TRUE
to_chat(new_human, span_cultitalic("<b>You are a servant of the Geometer. You have been made semi-corporeal by the cult of Nar'Sie, and you are to serve them at all costs.</b>"))
while(!QDELETED(src) && !QDELETED(user) && !QDELETED(new_human) && (user in T))
@@ -885,7 +886,9 @@ structure_check() searches for nearby cultist structures required for the invoca
span_cultlarge("Your link to the world fades. Your form breaks apart."))
for(var/obj/I in new_human)
new_human.dropItemToGround(I, TRUE)
new_human.mind?.remove_antag_datum(/datum/antagonist/cult)
new_human.dust()
else if(choice == "Ascend as a Dark Spirit")
affecting = user
affecting.add_atom_colour(RUNE_COLOR_DARKRED, ADMIN_COLOUR_PRIORITY)
+8 -1
View File
@@ -25,6 +25,11 @@
/// The amount of limited discounts that the team get
var/discount_limited_amount = 10
/datum/antagonist/nukeop/New()
if(send_to_spawnpoint) // lets get the loading started now, but don't block waiting for it
INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_NUKIEBASE)
return ..()
/datum/antagonist/nukeop/proc/equip_op()
if(!ishuman(owner.current))
return
@@ -118,6 +123,9 @@
objectives |= nuke_team.objectives
/datum/antagonist/nukeop/proc/move_to_spawnpoint()
// Ensure that the nukiebase is loaded, and wait for it if required
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE)
var/team_number = 1
if(nuke_team)
team_number = nuke_team.members.Find(owner)
@@ -127,7 +135,6 @@
owner.current.forceMove(pick(GLOB.nukeop_leader_start))
/datum/antagonist/nukeop/create_team(datum/team/nuclear/new_team)
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE)
if(!new_team)
if(!always_new_team)
for(var/datum/antagonist/nukeop/N in GLOB.antagonists)
+3 -1
View File
@@ -28,7 +28,9 @@
/datum/outfit/syndicate/post_equip(mob/living/carbon/human/nukie, visualsOnly = FALSE)
if(visualsOnly)
return
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE)
// We don't require the nukiebase be loaded to function, but lets go ahead and kick off loading just in case
INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_NUKIEBASE)
var/obj/item/radio/radio = nukie.ears
radio.set_frequency(FREQ_SYNDICATE)
radio.freqlock = RADIO_FREQENCY_LOCKED
@@ -626,7 +626,7 @@
var/heads_report = "<b>Heads of Staff</b><br>"
heads_report += "<table cellspacing=5>"
for(var/datum/mind/N in SSjob.get_living_heads())
for(var/datum/mind/N as anything in SSjob.get_living_heads())
var/mob/M = N.current
if(M)
heads_report += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=[REF(M)]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
@@ -21,6 +21,11 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */
show_to_ghosts = TRUE
/datum/antagonist/wizard/New()
if(move_to_lair) // kick off loading of your lair, if you want to be moved to it
INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_WIZARDDEN)
return ..()
/datum/antagonist/wizard_minion
name = "Wizard Minion"
antagpanel_category = "Wizard"
@@ -92,7 +97,9 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
wiz_team.master_wizard = src
/datum/antagonist/wizard/proc/send_to_lair()
// And now we ensure that its loaded
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN)
if(!owner)
CRASH("Antag datum with no owner.")
if(!owner.current)
@@ -1,11 +1,8 @@
/datum/job/nuclear_operative
title = ROLE_NUCLEAR_OPERATIVE
/datum/job/nuclear_operative/get_roundstart_spawn_point()
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE)
return pick(GLOB.nukeop_start)
/datum/job/nuclear_operative/get_latejoin_spawn_point()
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE)
return pick(GLOB.nukeop_start)
@@ -3,9 +3,7 @@
faction = ROLE_WIZARD
/datum/job/space_wizard/get_roundstart_spawn_point()
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN)
return pick(GLOB.wizardstart)
/datum/job/space_wizard/get_latejoin_spawn_point()
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN)
return pick(GLOB.wizardstart)
+4 -2
View File
@@ -181,8 +181,9 @@
/obj/machinery/computer/emergency_shuttle/proc/increase_hijack_stage()
var/obj/docking_port/mobile/emergency/shuttle = SSshuttle.emergency
// Begin loading this early, otherwise we get an awkward 30 second delay on the
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE)
// Begin loading this early, prevents a delay when the shuttle goes to land
INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_NUKIEBASE)
shuttle.hijack_status++
if(hijack_announce)
announce_hijack_stage()
@@ -542,6 +543,7 @@
// unless the shuttle is "hijacked"
var/destination_dock = "emergency_away"
if(is_hijacked() || elimination_hijack())
// just double check
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE)
destination_dock = "emergency_syndicate"
minor_announce("Corruption detected in \