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

Title

## About The Pull Request

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
## Why It's Good For The Game

This is the only thing left that I can think of that would cause antags
like nukies and abductors to spawn in wrong
## Changelog
This should not be player facing

Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
This commit is contained in:
Zephyr
2022-12-29 22:02:29 -08:00
committed by GitHub
co-authored by Mothblocks
parent 581828c421
commit 8a8b4a37c4
14 changed files with 65 additions and 17 deletions
+11 -1
View File
@@ -853,6 +853,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]
@@ -861,7 +872,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)
+5
View File
@@ -502,6 +502,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
@@ -522,6 +523,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
@@ -629,6 +631,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]")
@@ -681,6 +684,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)
@@ -703,6 +707,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_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()
@@ -336,12 +336,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,10 +273,12 @@
weight = 2
cost = 20
requirements = list(90,90,90,80,60,40,30,20,10,10)
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
@@ -415,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
@@ -38,6 +38,7 @@
ruleset.trim_candidates()
ruleset.load_templates()
if (!ruleset.ready())
continue
@@ -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
+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
@@ -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)
+5 -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()
@@ -547,6 +548,8 @@
// 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 \
shuttle navigation protocols. Please contact your \