Adds supermatter events (#21406)

* Class D and C SM events

* see above

* B-Class events

* A-class events

* S-class events (ebents done)

* Start of console

* datumization p1

* supermatter_event

* beginning of tgui

* adds new circuitboard for anomaly monitoring

* more supermatter event code

* forgot to change last_events

* tgui progression

* fix the freakin errors

* forgot to move this to on_start()

* some small fixes - tgui stuff to change

* bug fixes

* TGUI take two - in progress

* TGUI and circuit board removal for anom console

* Fixes world time spamming events

* S class event fix

* Fixes D class events

* Fixes worldtime based event calling

* Apply suggestions from code review

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>

* ACTUAL logging

* I blame copypaste

* Goddamit

---------

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>
Co-authored-by: Burzah <mbsx@proton.me>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
This commit is contained in:
Silverplate
2023-08-22 16:48:13 -04:00
committed by GitHub
parent c203fe01b9
commit 8d6cfbd418
7 changed files with 299 additions and 18 deletions
+1 -11
View File
@@ -59,17 +59,7 @@
continue
// if we are going to break this one
if(prob(APC_BREAK_PROBABILITY))
// if it has internal wires, cut the power wires
if(A.wires)
if(!A.wires.is_cut(WIRE_MAIN_POWER1))
A.wires.cut(WIRE_MAIN_POWER1)
if(!A.wires.is_cut(WIRE_MAIN_POWER2))
A.wires.cut(WIRE_MAIN_POWER2)
// if it was operating, toggle off the breaker
if(A.operating)
A.toggle_breaker()
// no matter what, ensure the area knows something happened to the power
current_area.powernet.power_change()
A.apc_short()
affected_apc_count++
log_and_message_admins("APC Short Out event has shorted out [affected_apc_count] APCs.")
+13
View File
@@ -1012,6 +1012,19 @@
to_chat(user, "You emag the APC interface.")
update_icon()
/obj/machinery/power/apc/proc/apc_short()
// if it has internal wires, cut the power wires
if(wires)
if(!wires.is_cut(WIRE_MAIN_POWER1))
wires.cut(WIRE_MAIN_POWER1)
if(!wires.is_cut(WIRE_MAIN_POWER2))
wires.cut(WIRE_MAIN_POWER2)
// if it was operating, toggle off the breaker
if(operating)
toggle_breaker()
// no matter what, ensure the area knows something happened to the power
apc_area.powernet.power_change()
/// *************
/// APC subtypes
/// *************
@@ -155,6 +155,8 @@
var/dynamic_heat_resistance = 1
///Uses powerloss_dynamic_scaling and combined_gas to lessen the effects of our powerloss functions
var/powerloss_inhibitor = 1
///value plus T0C = temp at which the SM starts to take damage. Variable for event usage
var/heat_penalty_threshold = HEAT_PENALTY_THRESHOLD
///Based on co2 percentage, slowly moves between 0 and 1. We use it to calc the powerloss_inhibitor
var/powerloss_dynamic_scaling= 0
///Affects the amount of radiation the sm makes. We multiply this with power to find the rads.
@@ -206,6 +208,23 @@
///Disables the sm's proccessing totally.
var/processes = TRUE
//vars used for supermatter events (Anomalous crystal activityw)
/// Do we have an active event?
var/datum/supermatter_event/event_active
///flat multiplies the amount of gas released by the SM.
var/gas_multiplier = 1
///flat multiplies the heat released by the SM
var/heat_multiplier = 1
///amount of EER to ADD
var/power_additive = 0
/// A list of all previous events
var/list/last_events
/// Time of next event
var/next_event_time
/// Run S-Class event? So we can only run one S-class event per round per crystal
var/has_run_sclass = FALSE
/obj/machinery/atmospherics/supermatter_crystal/Initialize(mapload)
. = ..()
supermatter_id = global_supermatter_id++
@@ -220,6 +239,7 @@
if(is_main_engine)
GLOB.main_supermatter_engine = src
soundloop = new(list(src), TRUE)
make_next_event_time()
/obj/machinery/atmospherics/supermatter_crystal/Destroy()
if(warp)
@@ -399,6 +419,8 @@
visible_message("<span class='warning'>[src] melts through [T]!</span>")
return
try_events()
//We vary volume by power, and handle OH FUCK FUSION IN COOLING LOOP noises.
if(power)
soundloop.volume = clamp((50 + (power / 50)), 50, 100)
@@ -439,7 +461,7 @@
//((((some value between 0.5 and 1 * temp - ((273.15 + 40) * some values between 1 and 10)) * some number between 0.25 and knock your socks off / 150) * 0.25
//Heat and mols account for each other, a lot of hot mols are more damaging then a few
//Mols start to have a positive effect on damage after 350
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.temperature - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.temperature - ((T0C + heat_penalty_threshold)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Power only starts affecting damage when it is above 5000
damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Molar count only starts affecting damage when it is above 1800
@@ -449,7 +471,7 @@
//healing damage
if(combined_gas < MOLE_PENALTY_THRESHOLD)
//Only has a net positive effect when the temp is below 313.15, heals up to 2 damage. Psycologists increase this temp min by up to 45
damage = max(damage + (min(removed.temperature - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150 ), 0)
damage = max(damage + (min(removed.temperature - (T0C + heat_penalty_threshold), 0) / 150 ), 0)
//Check for holes in the SM inner chamber
for(var/t in RANGE_TURFS(1, loc))
@@ -538,15 +560,15 @@
//Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock
//is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall.
//Power * 0.55 * (some value between 1.5 and 23) / 5
removed.temperature += ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER)
removed.temperature += (((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER) * heat_multiplier)
//We can only emit so much heat, that being 57500
removed.temperature = max(0, min(removed.temperature, 2500 * dynamic_heat_modifier))
//Calculate how much gas to release
//Varies based on power and gas content
removed.toxins += max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)
removed.toxins += max(((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER) * gas_multiplier, 0)
//Varies based on power, gas content, and heat
removed.oxygen += max(((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)
removed.oxygen += max((((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER) * gas_multiplier, 0)
if(produces_gas)
env.merge(removed)
@@ -649,7 +671,7 @@
//Boom (Mind blown)
if(damage > explosion_point)
countdown()
power += power_additive
return 1
/obj/machinery/atmospherics/supermatter_crystal/bullet_act(obj/item/projectile/Proj)
@@ -1152,6 +1174,47 @@
power += amount
message_admins("[src] has been activated and given an increase EER of [amount] at [ADMIN_JMP(src)]")
/obj/machinery/atmospherics/supermatter_crystal/proc/make_next_event_time()
// Some completely random bullshit to make a "bell curve"
var/fake_time = rand(5 MINUTES, 25 MINUTES)
if(fake_time < 15 MINUTES && prob(30))
fake_time += rand(2 MINUTES, 10 MINUTES)
else if(fake_time > 15 MINUTES && prob(30))
fake_time -= rand(2 MINUTES, 10 MINUTES)
next_event_time += fake_time
/obj/machinery/atmospherics/supermatter_crystal/proc/try_events()
if(has_been_powered == FALSE)
return
if(!next_event_time) // for when the SM starts
make_next_event_time()
return
if(world.time < next_event_time)
return
if(event_active)
return
var/static/list/events = list(/datum/supermatter_event/delta_tier = 40,
/datum/supermatter_event/charlie_tier = 40,
/datum/supermatter_event/bravo_tier = 15,
/datum/supermatter_event/alpha_tier = 5,
/datum/supermatter_event/sierra_tier = 1)
var/datum/supermatter_event/event = pick(subtypesof(pickweight(events)))
if(istype(event, /datum/supermatter_event/sierra_tier) && has_run_sclass)
make_next_event_time()
return // We're only gonna have one s-class per round, take a break engineers
run_event(event)
make_next_event_time()
/obj/machinery/atmospherics/supermatter_crystal/proc/run_event(datum/supermatter_event/event) // mostly admin testing and stuff
if(ispath(event))
event = new event(src)
if(!istype(event))
log_debug("Attempted supermatter event aborted due to incorrect path. Incorrect path type: [event.type].")
return
event.start_event()
#undef HALLUCINATION_RANGE
#undef GRAVITATIONAL_ANOMALY
#undef FLUX_ANOMALY
@@ -0,0 +1,209 @@
/datum/supermatter_event
var/name = "Unknown X-K (Report this to coders)"
var/obj/machinery/atmospherics/supermatter_crystal/supermatter
var/datum/gas_mixture/environment
/// Probability of the event not running, higher tiers being rarer
var/threat_level
var/duration
/datum/supermatter_event/New(obj/machinery/atmospherics/supermatter_crystal/_supermatter)
. = ..()
supermatter = _supermatter
if(!supermatter)
stack_trace("a /datum/supermatter_event was called without an involved supermatter.")
return
if(!istype(supermatter))
stack_trace("a /datum/supermatter_event was called with (name: [supermatter], type: [supermatter.type]) instead of a supermatter!")
return
var/turf/T = get_turf(supermatter)
environment = T.return_air()
/datum/supermatter_event/proc/start_event()
supermatter.event_active = src
on_start()
alert_engi()
if(duration)
addtimer(CALLBACK(src, PROC_REF(on_end)), duration)
/datum/supermatter_event/proc/on_start()
return
/datum/supermatter_event/proc/alert_engi()
return
/datum/supermatter_event/proc/on_end()
sm_radio_say("Anomalous crystal activity has ended.")
supermatter.heat_penalty_threshold = HEAT_PENALTY_THRESHOLD
supermatter.gas_multiplier = 1
supermatter.power_additive = 0
supermatter.heat_multiplier = 1
supermatter.event_active = null
supermatter.last_events += src
/datum/supermatter_event/proc/sm_radio_say(text)
if(!text)
return
supermatter.radio.autosay(text, supermatter, "Engineering", list(supermatter.z))
/datum/supermatter_event/proc/general_radio_say(text)
if(!text)
return
supermatter.radio.autosay(text, supermatter, null, list(supermatter.z))
// Below this are procs used for the SM events, in order of severity
//D class events
/datum/supermatter_event/delta_tier
threat_level = SM_EVENT_THREAT_D
duration = 10 SECONDS
/datum/supermatter_event/delta_tier/alert_engi()
sm_radio_say("Abnormal crystal activity detected! Activity class: [name].")
// sleeping gas
/datum/supermatter_event/delta_tier/sleeping_gas
name = "D-1"
/datum/supermatter_event/delta_tier/sleeping_gas/on_start()
environment.sleeping_agent += 200
// nitrogen
/datum/supermatter_event/delta_tier/nitrogen
name = "D-2"
/datum/supermatter_event/delta_tier/nitrogen/on_start()
environment.nitrogen += 200
// carbon dioxide
/datum/supermatter_event/delta_tier/carbon_dioxide
name = "D-3"
/datum/supermatter_event/delta_tier/carbon_dioxide/on_start()
environment.carbon_dioxide += 250
// C class events
/datum/supermatter_event/charlie_tier
threat_level = SM_EVENT_THREAT_C
duration = 15 SECONDS
/datum/supermatter_event/charlie_tier/alert_engi()
sm_radio_say("Anomalous crystal activity detected. Activity class: [name]. Operator intervention may be required.")
// oxygen
/datum/supermatter_event/charlie_tier/oxygen
name = "C-1"
/datum/supermatter_event/charlie_tier/oxygen/on_start()
environment.oxygen += 250
// plasma
/datum/supermatter_event/charlie_tier/plasma
name = "C-2"
/datum/supermatter_event/charlie_tier/plasma/on_start()
environment.toxins += 200
// lowers the temp required for the SM to take damage.
/datum/supermatter_event/charlie_tier/heat_penalty_threshold
name = "C-3"
duration = 5 MINUTES
/datum/supermatter_event/charlie_tier/heat_penalty_threshold/on_start()
supermatter.heat_penalty_threshold -= -73
//Class B events
/datum/supermatter_event/bravo_tier
threat_level = SM_EVENT_THREAT_B
duration = 1 MINUTES
/datum/supermatter_event/bravo_tier/alert_engi()
sm_radio_say("Anomalous crystal activity detected! Activity class: [name]. Operator intervention is required!")
// more gas
/datum/supermatter_event/bravo_tier/gas_multiply
name = "B-1"
/datum/supermatter_event/bravo_tier/gas_multiply/on_start()
supermatter.gas_multiplier = 1.5
/datum/supermatter_event/bravo_tier/heat_multiplier
name = "B-2"
/datum/supermatter_event/bravo_tier/heat_multiplier/on_start()
supermatter.heat_multiplier = 1.25
/datum/supermatter_event/bravo_tier/power_additive
name = "B-3"
/datum/supermatter_event/bravo_tier/power_additive/on_start()
supermatter.power_additive = 2000
//A class events
/datum/supermatter_event/alpha_tier
threat_level = SM_EVENT_THREAT_A
duration = 10 SECONDS
/datum/supermatter_event/alpha_tier/alert_engi()
sm_radio_say("ALERT: Critical anomalous crystal activity detected! Activity class: [name]. IMMEDIATE Operator intervention is REQUIRED!")
/datum/supermatter_event/alpha_tier/apc_short
name = "A-1"
/datum/supermatter_event/alpha_tier/apc_short/on_start()
var/area/current_area = get_area(src)
var/obj/machinery/power/apc/A = current_area.get_apc()
A.apc_short()
/datum/supermatter_event/alpha_tier/air_siphon
name = "A-2"
/datum/supermatter_event/alpha_tier/air_siphon/on_start()
var/area/current_area = get_area(src)
var/obj/machinery/alarm/engine/A = current_area.master_air_alarm
A.apply_mode(AALARM_MODE_SCRUBBING)
/datum/supermatter_event/alpha_tier/gas_multiplier
name = "A-3"
duration = 2 MINUTES
/datum/supermatter_event/alpha_tier/gas_multiplier/on_start()
supermatter.gas_multiplier = 4
// S-tier events are special. They are very dangerous, but give a 5 minute warning to the engis.
/datum/supermatter_event/sierra_tier
threat_level = SM_EVENT_THREAT_S
duration = 7 MINUTES // 2 MINUTES of s-tier anomaly
/datum/supermatter_event/sierra_tier/alert_engi()
general_radio_say("ALERT: Anomalous supermatter state expected in: 5 minutes.")
sm_radio_say("EMERGENCY ALERT: 5 MINUTES UNTIL [supermatter] EXHIBITS [name] CLASS ANOMALOUS ACTIVITY!")
/datum/supermatter_event/sierra_tier/on_start()
addtimer(CALLBACK(src, PROC_REF(start_sierra_event)), 5 MINUTES)
supermatter.has_run_sclass = TRUE
/datum/supermatter_event/sierra_tier/proc/start_sierra_event()
general_radio_say("ALERT: ANOMALOUS SUPERMATTER STATE DETECTED!")
sm_radio_say("EMERGENCY ALERT: Class [name] anomalous behavior in progress!")
//S class events
//Arc-type
/datum/supermatter_event/sierra_tier/arc
name = "S-ARC"
/datum/supermatter_event/sierra_tier/arc/start_sierra_event()
..()
supermatter.power_additive = 6000
// Laminate type
/datum/supermatter_event/sierra_tier/laminate
name = "S-LAMINATE REJECTION"
/datum/supermatter_event/sierra_tier/laminate/start_sierra_event()
..()
supermatter.heat_multiplier = 10