diff --git a/config/skyrat/skyrat_config.txt b/config/skyrat/skyrat_config.txt index 018fe459940..1043a128d9e 100644 --- a/config/skyrat/skyrat_config.txt +++ b/config/skyrat/skyrat_config.txt @@ -149,5 +149,16 @@ VETERAN_LEGACY_SYSTEM ## How much time arrivals shuttle should stay at station after its engines recharged before returning to interlink. In deciseconds. 150 - 15 seconds. 0 - disables autoreturn. ARRIVALS_WAIT 150 +## LOWPOP MEASURES + +## Enables or disables the lowpop system entirely. +# LOWPOP_MEASURES_ENABLED + +## The threshold for enabling/disabling the lowpop system LIVE. It's updated every so often(see below). +LOWPOP_THRESHOLD 10 + +## The lowpop subsystem fire rate. It does actions each time it fires.(default is 10 minutes) +LOWPOP_SUBSYSTEM_FIRE 6000 + ## Uncomment to make veteran quirks and jobs available to everybody #BYPASS_VETERAN_SYSTEM diff --git a/modular_skyrat/modules/lowpop/code/config.dm b/modular_skyrat/modules/lowpop/code/config.dm new file mode 100644 index 00000000000..d8f03f3d7f9 --- /dev/null +++ b/modular_skyrat/modules/lowpop/code/config.dm @@ -0,0 +1,11 @@ +// When enabled, turns the lowpop system on +/datum/config_entry/flag/lowpop_measures_enabled + default = FALSE + +// The threshold for lowpop systems to be enabled. +/datum/config_entry/number/lowpop_threshold + default = 10 + +// How often the subsystem should fire. +/datum/config_entry/number/lowpop_subsystem_fire + default = 10 MINUTES diff --git a/modular_skyrat/modules/lowpop/code/lowpop_subsystem.dm b/modular_skyrat/modules/lowpop/code/lowpop_subsystem.dm new file mode 100644 index 00000000000..25d0662d3bb --- /dev/null +++ b/modular_skyrat/modules/lowpop/code/lowpop_subsystem.dm @@ -0,0 +1,110 @@ +#define LOWPOP_ON_MESSAGE "Due to staffing issues, we have enacted the 'critically low staff' protocol. We will periodically use our high-intensity electron beam to recharge your SMES arrays." +#define LOWPOP_OFF_MESSAGE "As the staffing issues have been resolved, we have resumed normal staffing protocol. Automatic SMES recharging will no longer occur." +#define SMES_CRITICALLY_LOW_PERCENTAGE 5 +#define RECHARGE_THRESHOLD 70 + +// A subsystem for handling lowpop affairs. +SUBSYSTEM_DEF(lowpop) + name = "Lowpop Control Measures" + wait = 10 MINUTES + runlevels = RUNLEVEL_GAME + /// Since the last fire, were the measures on or off? + var/lowpop_active = FALSE + /// List of atmos machinery we set no power to + var/static/list/atmos_machinery_no_power = list( + /obj/machinery/atmospherics/components/trinary, + /obj/machinery/atmospherics/components/binary, + ) + +/datum/controller/subsystem/lowpop/Initialize() + if(!CONFIG_GET(flag/lowpop_measures_enabled)) + can_fire = FALSE + return SS_INIT_NO_NEED + wait = CONFIG_GET(number/lowpop_subsystem_fire) + if(LAZYLEN(GLOB.player_list) > CONFIG_GET(number/lowpop_threshold)) // Don't announce it if we're not within the threshold. We use player list as people haven't spawned in yet. + return SS_INIT_SUCCESS + RegisterSignal(SSticker, COMSIG_TICKER_ROUND_STARTING, PROC_REF(roundstart_check)) + return SS_INIT_SUCCESS + +/** + * Roundstart check + * + * We check at roundstart if we should activate the measures. + */ +/datum/controller/subsystem/lowpop/proc/roundstart_check() + if(get_active_player_count(TRUE, FALSE, FALSE) > CONFIG_GET(number/lowpop_threshold)) + disable_lowpop_measures() + return // If we go above it don't do it! + enable_lowpop_measures() + addtimer(CALLBACK(src, PROC_REF(send_announcement), LOWPOP_ON_MESSAGE), rand(10 SECONDS, 30 SECONDS)) + +/datum/controller/subsystem/lowpop/proc/send_announcement(message) + priority_announce(message, "Staffing Bureau") + + +/datum/controller/subsystem/lowpop/fire(resumed) + var/fire_population_count = get_active_player_count(TRUE, FALSE, FALSE) + if(fire_population_count <= CONFIG_GET(number/lowpop_threshold)) // Oh no, we went below the threshold. + enable_lowpop_measures() + if(!lowpop_active) + return + // First, check if we need to turn these measures off. + if(fire_population_count > CONFIG_GET(number/lowpop_threshold)) + // Okay, we're high enough again, lets turn it off, and let everyone know! + disable_lowpop_measures() + addtimer(CALLBACK(src, PROC_REF(send_announcement), LOWPOP_OFF_MESSAGE), rand(10 SECONDS, 30 SECONDS)) + return + + power_restore() + +/datum/controller/subsystem/lowpop/proc/enable_lowpop_measures() + lowpop_active = TRUE + update_power_changes() + + +/datum/controller/subsystem/lowpop/proc/disable_lowpop_measures() + lowpop_active = FALSE + update_power_changes() + +/** + * Changes the power requirements of some things. + */ +/datum/controller/subsystem/lowpop/proc/update_power_changes() + if(lowpop_active) + for(var/obj/machinery/atmospherics/atmos_device as anything in GLOB.atmos_components) + if(is_type_in_list(atmos_device, atmos_machinery_no_power)) + atmos_device.update_use_power(NO_POWER_USE) + else + for(var/obj/machinery/atmospherics/atmos_device as anything in GLOB.atmos_components) + if(is_type_in_list(atmos_device, atmos_machinery_no_power)) + atmos_device.update_use_power(initial(atmos_device.use_power)) +/** + * Here we check a few things, namely, if the SMES on station are more than percent critically low, we recharge! + */ +/datum/controller/subsystem/lowpop/proc/power_restore() + var/list/all_smes = SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/smes) + var/list/critically_low_smes = list() + var/list/valid_smes = list() + + for(var/obj/machinery/power/smes/smes as anything in all_smes) + // check if its the right z level + if(!is_station_level(smes.z)) + continue + LAZYADD(valid_smes, smes) + // check if it's actually low on power + if((smes.charge / smes.capacity * 100) < SMES_CRITICALLY_LOW_PERCENTAGE) + LAZYADD(critically_low_smes, smes) + + // check if enough of them are out of power + if((LAZYLEN(critically_low_smes) / LAZYLEN(valid_smes) * 100) < RECHARGE_THRESHOLD) + return + + // recharge all those smes if we're out of power! + for(var/obj/machinery/power/smes/smes as anything in valid_smes) + smes.charge = smes.capacity + smes.output_level = smes.output_level_max + smes.output_attempt = TRUE + smes.update_appearance() + smes.power_change() + + minor_announce("All SMESs on [station_name()] have been recharged via electron beam.", "Power Systems Recharged") diff --git a/tgstation.dme b/tgstation.dme index bf6283a3428..6e2d1f7211f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7358,6 +7358,8 @@ #include "modular_skyrat\modules\lorecaster\code\config.dm" #include "modular_skyrat\modules\lorecaster\code\story_manager.dm" #include "modular_skyrat\modules\lorecaster\code\subsystem.dm" +#include "modular_skyrat\modules\lowpop\code\config.dm" +#include "modular_skyrat\modules\lowpop\code\lowpop_subsystem.dm" #include "modular_skyrat\modules\manufacturer_examine\code\gun_company_additions.dm" #include "modular_skyrat\modules\manufacturer_examine\code\manufacturer_element.dm" #include "modular_skyrat\modules\mapping\code\airless.dm"