mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 14:08:31 +01:00
[MIRROR] Refactors SM Delaminations to be strategies [MDB IGNORE] (#15370)
* Refactors SM Delaminations to be strategies * wew Co-authored-by: vincentiusvin <54709710+vincentiusvin@users.noreply.github.com> Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
This commit is contained in:
co-authored by
vincentiusvin
Gandalf
parent
6823589e7a
commit
c0d6df89e4
@@ -110,16 +110,6 @@
|
||||
#define DETOMATIX_RESIST_MINOR 1
|
||||
#define DETOMATIX_RESIST_MAJOR 2
|
||||
|
||||
// These are used by supermatter and supermatter monitor program, mostly for UI updating purposes. Higher should always be worse!
|
||||
#define SUPERMATTER_ERROR -1 // Unknown status, shouldn't happen but just in case.
|
||||
#define SUPERMATTER_INACTIVE 0 // No or minimal energy
|
||||
#define SUPERMATTER_NORMAL 1 // Normal operation
|
||||
#define SUPERMATTER_NOTIFY 2 // Ambient temp > 80% of CRITICAL_TEMPERATURE
|
||||
#define SUPERMATTER_WARNING 3 // Ambient temp > CRITICAL_TEMPERATURE OR integrity damaged
|
||||
#define SUPERMATTER_DANGER 4 // Integrity < 50%
|
||||
#define SUPERMATTER_EMERGENCY 5 // Integrity < 25%
|
||||
#define SUPERMATTER_DELAMINATING 6 // Pretty obvious.
|
||||
|
||||
#define HYPERTORUS_INACTIVE 0 // No or minimal energy
|
||||
#define HYPERTORUS_NOMINAL 1 // Normal operation
|
||||
#define HYPERTORUS_WARNING 2 // Integrity damaged
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
/// All humans within this range will be irradiated
|
||||
#define DETONATION_RADIATION_RANGE 20
|
||||
|
||||
#define WARNING_DELAY 60
|
||||
#define SUPERMATTER_WARNING_DELAY 60 SECONDS
|
||||
|
||||
#define HALLUCINATION_RANGE(P) (min(7, round(P ** 0.25)))
|
||||
|
||||
@@ -102,13 +102,6 @@
|
||||
#define HALLUCINATION_ANOMALY "hallucination_anomaly"
|
||||
#define VORTEX_ANOMALY "vortex_anomaly"
|
||||
|
||||
//If integrity percent remaining is less than these values, the monitor sets off the relevant alarm.
|
||||
#define SUPERMATTER_DELAM_PERCENT 5
|
||||
#define SUPERMATTER_EMERGENCY_PERCENT 25
|
||||
#define SUPERMATTER_DANGER_PERCENT 50
|
||||
#define SUPERMATTER_WARNING_PERCENT 100
|
||||
#define CRITICAL_TEMPERATURE 10000
|
||||
|
||||
#define SUPERMATTER_COUNTDOWN_TIME 30 SECONDS
|
||||
|
||||
///to prevent accent sounds from layering
|
||||
@@ -128,3 +121,32 @@
|
||||
#define POWERLOSS_LINEAR_RATE 0.83
|
||||
/// How much a psychologist can reduce power loss.
|
||||
#define PSYCHOLOGIST_POWERLOSS_REDUCTION 0.2
|
||||
|
||||
/// Means it's not forced, sm decides itself by checking the [/datum/sm_delam/proc/can_select]
|
||||
#define SM_DELAM_PRIO_NONE 0
|
||||
/// In-game factors like the destabilizing crystal [/obj/item/destabilizing_crystal].
|
||||
/// Purged when SM heals to 100
|
||||
#define SM_DELAM_PRIO_IN_GAME 1
|
||||
|
||||
/// Purge the current forced delam and make it zero again (back to normal).
|
||||
/// Needs to be higher priority than current forced_delam though.
|
||||
#define SM_DELAM_STRATEGY_PURGE null
|
||||
|
||||
// These are used by supermatter and supermatter monitor program, mostly for UI updating purposes. Higher should always be worse!
|
||||
// [/obj/machinery/power/supermatter_crystal/proc/get_status]
|
||||
/// Unknown status, shouldn't happen but just in case.
|
||||
#define SUPERMATTER_ERROR -1
|
||||
/// No or minimal energy
|
||||
#define SUPERMATTER_INACTIVE 0
|
||||
/// Normal operation
|
||||
#define SUPERMATTER_NORMAL 1
|
||||
/// Ambient temp 80% of the default temp for SM to take damage.
|
||||
#define SUPERMATTER_NOTIFY 2
|
||||
/// Integrity below [/obj/machinery/power/supermatter_crystal/var/warning_point]. Start complaining on comms.
|
||||
#define SUPERMATTER_WARNING 3
|
||||
/// Integrity below [/obj/machinery/power/supermatter_crystal/var/danger_point]. Start spawning anomalies.
|
||||
#define SUPERMATTER_DANGER 4
|
||||
/// Integrity below [/obj/machinery/power/supermatter_crystal/var/emergency_point]. Start complaining to more people.
|
||||
#define SUPERMATTER_EMERGENCY 5
|
||||
/// Currently counting down to delamination. True [/obj/machinery/power/supermatter_crystal/var/final_countdown]
|
||||
#define SUPERMATTER_DELAMINATING 6
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
desc = "Your benefactors conveinently neglected to mention it's already assembled."
|
||||
anchored = TRUE
|
||||
radio_key = /obj/item/encryptionkey/syndicate
|
||||
engineering_channel = "Syndicate"
|
||||
common_channel = "Syndicate"
|
||||
emergency_channel = "Syndicate"
|
||||
warning_channel = "Syndicate"
|
||||
include_in_cims = FALSE
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/shard/syndicate/attackby(obj/item/item, mob/living/user, params)
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
#define OBJECT (LOWEST + 1)
|
||||
#define LOWEST (1)
|
||||
|
||||
#define CASCADING_ADMIN "Admin"
|
||||
#define CASCADING_CRITICAL_GAS "Critical gas point"
|
||||
#define CASCADING_DESTAB_CRYSTAL "Destabilizing crystal"
|
||||
|
||||
GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
|
||||
/obj/machinery/power/supermatter_crystal
|
||||
@@ -38,30 +34,27 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
var/static/gl_uid = 1
|
||||
///Tracks the bolt color we are using
|
||||
var/zap_icon = DEFAULT_ZAP_ICON_STATE
|
||||
///The portion of the gasmix we're on that we should remove
|
||||
var/gasefficency = 0.15
|
||||
|
||||
///Are we exploding?
|
||||
var/final_countdown = FALSE
|
||||
|
||||
///The amount of damage we have currently
|
||||
var/damage = 0
|
||||
///The damage we had before this cycle. Used to limit the damage we can take each cycle, and for safe_alert
|
||||
/// The damage we had before this cycle.
|
||||
/// Used to limit the damage we can take each cycle, and to check if we are currently taking damage or healing.
|
||||
var/damage_archived = 0
|
||||
///Our "Shit is no longer fucked" message. We send it when damage is less then damage_archived
|
||||
var/safe_alert = "Crystalline hyperstructure returning to safe operating parameters."
|
||||
///The point at which we should start sending messeges about the damage to the engi channels.
|
||||
|
||||
///The point at which we consider the supermatter to be [SUPERMATTER_STATUS_WARNING]
|
||||
var/warning_point = 50
|
||||
///The alert we send when we've reached warning_point
|
||||
var/warning_alert = "Danger! Crystal hyperstructure integrity faltering!"
|
||||
///The point at which we start sending messages to the common channel
|
||||
var/emergency_point = 700
|
||||
///The alert we send when we've reached emergency_point
|
||||
var/emergency_alert = "CRYSTAL DELAMINATION IMMINENT."
|
||||
///The point at which we delam
|
||||
var/warning_channel = RADIO_CHANNEL_ENGINEERING
|
||||
///The point at which we consider the supermatter to be [SUPERMATTER_STATUS_DANGER]
|
||||
///Spawns anomalies when more damaged than this too.
|
||||
var/danger_point = 550
|
||||
///The point at which we consider the supermatter to be [SUPERMATTER_STATUS_EMERGENCY]
|
||||
var/emergency_point = 675
|
||||
var/emergency_channel = null // Need null to actually broadcast, lol.
|
||||
///The point at which we delam [SUPERMATTER_STATUS_DELAMINATING]
|
||||
var/explosion_point = 900
|
||||
///When we pass this amount of damage we start shooting bolts
|
||||
var/damage_penalty_point = 550
|
||||
|
||||
///A scaling value that affects the severity of explosions.
|
||||
var/explosion_power = 35
|
||||
@@ -220,20 +213,14 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
var/obj/item/radio/radio
|
||||
///The key our internal radio uses
|
||||
var/radio_key = /obj/item/encryptionkey/headset_eng
|
||||
///The engineering channel
|
||||
var/engineering_channel = "Engineering"
|
||||
///The common channel
|
||||
var/common_channel = null
|
||||
|
||||
///Boolean used for logging if we've been powered
|
||||
var/has_been_powered = FALSE
|
||||
///Boolean used for logging if we've passed the emergency point
|
||||
var/has_reached_emergency = FALSE
|
||||
|
||||
///An effect we show to admins and ghosts the percentage of delam we're at
|
||||
var/obj/effect/countdown/supermatter/countdown
|
||||
|
||||
///Used along with a global var to track if we can give out the sm sliver stealing objective
|
||||
///Only main engines can have their sliver stolen, can trigger cascades, and can spawn stationwide anomalies.
|
||||
var/is_main_engine = FALSE
|
||||
///Our soundloop
|
||||
var/datum/looping_sound/supermatter/soundloop
|
||||
@@ -264,16 +251,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
var/include_in_cims = TRUE
|
||||
|
||||
var/freonbonus = 0
|
||||
///Can the crystal trigger the station wide anomaly spawn?
|
||||
var/anomaly_event = TRUE
|
||||
///Hue shift of the zaps color based on the power of the crystal
|
||||
var/hue_angle_shift = 0
|
||||
///If an admin wants a sure cascade with the delamination just set this to true (don't be a badmin)
|
||||
var/admin_cascade = FALSE
|
||||
///Do we have a destabilizing crystal attached?
|
||||
var/has_destabilizing_crystal = FALSE
|
||||
///Has the cascade been triggered?
|
||||
var/cascade_initiated = FALSE
|
||||
///Reference to the warp effect
|
||||
var/atom/movable/supermatter_warp_effect/warp
|
||||
///The power threshold required to transform the powerloss function into a linear function from a cubic function.
|
||||
@@ -281,9 +260,21 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
///The offset of the linear powerloss function set so the transition is differentiable.
|
||||
var/powerloss_linear_offset = 0
|
||||
|
||||
///The portion of the gasmix we're on that we should remove
|
||||
var/absorption_ratio = 0.15
|
||||
/// The gasmix we just recently absorbed. Tile's air multiplied by absorption_ratio
|
||||
var/datum/gas_mixture/absorbed_gasmix
|
||||
|
||||
/// How we are delaminating.
|
||||
var/datum/sm_delam/delamination_strategy
|
||||
/// Whether the sm is forced in a specific delamination_strategy or not. All truthy values means it's forced.
|
||||
/// Only values greater or equal to the current one can change the strat.
|
||||
var/delam_priority = SM_DELAM_PRIO_NONE
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/Initialize(mapload)
|
||||
. = ..()
|
||||
uid = gl_uid++
|
||||
set_delam(SM_DELAM_PRIO_NONE, /datum/sm_delam/explosive)
|
||||
SSair.start_processing_machine(src)
|
||||
countdown = new(src)
|
||||
countdown.start()
|
||||
@@ -297,7 +288,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
GLOB.main_supermatter_engine = src
|
||||
|
||||
AddElement(/datum/element/bsa_blocker)
|
||||
RegisterSignal(src, COMSIG_ATOM_BSA_BEAM, .proc/call_delamination_event)
|
||||
RegisterSignal(src, COMSIG_ATOM_BSA_BEAM, .proc/force_delam)
|
||||
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_TURF_INDUSTRIAL_LIFT_ENTER = .proc/tram_contents_consume,
|
||||
@@ -344,8 +335,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
var/immune = HAS_TRAIT(user, TRAIT_MADNESS_IMMUNE) || (user.mind && HAS_TRAIT(user.mind, TRAIT_MADNESS_IMMUNE))
|
||||
if(isliving(user) && !immune && (get_dist(user, src) < HALLUCINATION_RANGE(power)))
|
||||
. += span_danger("You get headaches just from looking at it.")
|
||||
if(cascade_initiated)
|
||||
. += span_bolddanger("The crystal is vibrating at immense speeds, warping space around it!")
|
||||
. += delamination_strategy.examine(src)
|
||||
return .
|
||||
|
||||
// SupermatterMonitor UI for ghosts only. Inherited attack_ghost will call this.
|
||||
/obj/machinery/power/supermatter_crystal/ui_interact(mob/user, datum/tgui/ui)
|
||||
@@ -371,7 +362,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
data["SM_power"] = power
|
||||
data["SM_ambienttemp"] = air.temperature
|
||||
data["SM_ambientpressure"] = air.return_pressure()
|
||||
data["SM_bad_moles_amount"] = MOLE_PENALTY_THRESHOLD / gasefficency
|
||||
data["SM_bad_moles_amount"] = MOLE_PENALTY_THRESHOLD / absorption_ratio
|
||||
data["SM_moles"] = 0
|
||||
data["SM_uid"] = uid
|
||||
var/area/active_supermatter_area = get_area(src)
|
||||
@@ -396,6 +387,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
|
||||
return data
|
||||
|
||||
/// Encodes the current state of the supermatter.
|
||||
/obj/machinery/power/supermatter_crystal/proc/get_status()
|
||||
var/turf/local_turf = get_turf(src)
|
||||
if(!local_turf)
|
||||
@@ -403,46 +395,20 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
var/datum/gas_mixture/air = local_turf.return_air()
|
||||
if(!air)
|
||||
return SUPERMATTER_ERROR
|
||||
|
||||
var/integrity = get_integrity_percent()
|
||||
if(integrity < SUPERMATTER_DELAM_PERCENT)
|
||||
if(final_countdown)
|
||||
return SUPERMATTER_DELAMINATING
|
||||
|
||||
if(integrity < SUPERMATTER_EMERGENCY_PERCENT)
|
||||
if(damage >= emergency_point)
|
||||
return SUPERMATTER_EMERGENCY
|
||||
|
||||
if(integrity < SUPERMATTER_DANGER_PERCENT)
|
||||
if(damage >= danger_point)
|
||||
return SUPERMATTER_DANGER
|
||||
|
||||
if((integrity < SUPERMATTER_WARNING_PERCENT) || (air.temperature > CRITICAL_TEMPERATURE))
|
||||
if(damage >= warning_point)
|
||||
return SUPERMATTER_WARNING
|
||||
|
||||
if(air.temperature > (CRITICAL_TEMPERATURE * 0.8))
|
||||
if(absorbed_gasmix.temperature > (T0C + HEAT_PENALTY_THRESHOLD) * 0.8)
|
||||
return SUPERMATTER_NOTIFY
|
||||
|
||||
if(power > 5)
|
||||
if(power)
|
||||
return SUPERMATTER_NORMAL
|
||||
return SUPERMATTER_INACTIVE
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/alarm()
|
||||
switch(get_status())
|
||||
if(SUPERMATTER_DELAMINATING)
|
||||
playsound(src, 'sound/misc/bloblarm.ogg', 100, FALSE, 40, 30, falloff_distance = 10)
|
||||
// SKYRAT EDIT ADDITION
|
||||
alert_sound_to_playing('modular_skyrat/master_files/sound/effects/reactor/meltdown.ogg', override_volume = TRUE)
|
||||
alert_sound_to_playing('modular_skyrat/modules/alerts/sound/alerts/alert1.ogg', override_volume = TRUE)
|
||||
// SKYRAT EDIT END
|
||||
if(SUPERMATTER_EMERGENCY)
|
||||
// SKYRAT EDIT ADDITION
|
||||
alert_sound_to_playing('modular_skyrat/master_files/sound/effects/reactor/core_overheating.ogg', override_volume = TRUE)
|
||||
alert_sound_to_playing('modular_skyrat/modules/alerts/sound/alerts/alert1.ogg', override_volume = TRUE)
|
||||
// SKYRAT EDIT END
|
||||
playsound(src, 'sound/machines/engine_alert1.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
|
||||
if(SUPERMATTER_DANGER)
|
||||
playsound(src, 'sound/machines/engine_alert2.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
|
||||
if(SUPERMATTER_WARNING)
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 75)
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/get_integrity_percent()
|
||||
var/integrity = damage / explosion_point
|
||||
integrity = round(100 - integrity * 100, 0.01)
|
||||
@@ -451,93 +417,13 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/update_overlays()
|
||||
. = ..()
|
||||
if(final_countdown && !cascade_initiated)
|
||||
. += "casuality_field"
|
||||
. += delamination_strategy.overlays(src)
|
||||
return .
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/countdown()
|
||||
set waitfor = FALSE
|
||||
|
||||
if(final_countdown) // We're already doing it go away
|
||||
return
|
||||
final_countdown = TRUE
|
||||
update_appearance()
|
||||
|
||||
var/cascading = cascade_initiated
|
||||
|
||||
var/speaking = "[emergency_alert] The supermatter has reached critical integrity failure."
|
||||
|
||||
if(cascading)
|
||||
speaking += " Harmonic frequency limits exceeded. Causality destabilization field could not be engaged."
|
||||
else
|
||||
speaking += " Emergency causality destabilization field has been activated."
|
||||
|
||||
radio.talk_into(src, speaking, common_channel, language = get_selected_language())
|
||||
for(var/i in SUPERMATTER_COUNTDOWN_TIME to 0 step -10)
|
||||
if(damage < explosion_point) // Cutting it a bit close there engineers
|
||||
if(cascading)
|
||||
radio.talk_into(src, "[safe_alert] Harmonic frequency restored within emergency bounds. Anti-resonance filter initiated.", common_channel)
|
||||
else
|
||||
radio.talk_into(src, "[safe_alert] Failsafe has been disengaged.", common_channel)
|
||||
final_countdown = FALSE
|
||||
update_appearance()
|
||||
return
|
||||
else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individualy
|
||||
sleep(10)
|
||||
continue
|
||||
else if(i > 50)
|
||||
if(cascading)
|
||||
speaking = "[DisplayTimeText(i, TRUE)] remain before resonance-induced stabilization."
|
||||
else
|
||||
speaking = "[DisplayTimeText(i, TRUE)] remain before causality stabilization."
|
||||
else
|
||||
speaking = "[i*0.1]..."
|
||||
radio.talk_into(src, speaking, common_channel)
|
||||
sleep(1 SECONDS)
|
||||
|
||||
delamination_event()
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/delamination_event()
|
||||
var/can_spawn_anomalies = is_station_level(loc.z) && is_main_engine && anomaly_event
|
||||
|
||||
var/is_cascading = cascade_initiated
|
||||
|
||||
new /datum/supermatter_delamination(power, combined_gas, get_turf(src), explosion_power, gasmix_power_ratio, can_spawn_anomalies, is_cascading)
|
||||
qdel(src)
|
||||
|
||||
//this is here to eat arguments
|
||||
/obj/machinery/power/supermatter_crystal/proc/call_delamination_event()
|
||||
/obj/machinery/power/supermatter_crystal/proc/force_delam()
|
||||
SIGNAL_HANDLER
|
||||
delamination_event()
|
||||
|
||||
/**
|
||||
* Checks if and why the supermatter is in a state where it can cascade
|
||||
*
|
||||
* Returns: cause of the cascade, for logging
|
||||
*/
|
||||
/obj/machinery/power/supermatter_crystal/proc/check_cascade_requirements()
|
||||
if(admin_cascade)
|
||||
return CASCADING_ADMIN
|
||||
|
||||
if(!anomaly_event)
|
||||
return FALSE
|
||||
|
||||
if(has_destabilizing_crystal)
|
||||
return CASCADING_DESTAB_CRYSTAL
|
||||
|
||||
var/critical_gas_exceeded = TRUE
|
||||
var/list/required_gases = list(/datum/gas/hypernoblium, /datum/gas/antinoblium)
|
||||
if(environment_total_moles < MOLE_PENALTY_THRESHOLD)
|
||||
critical_gas_exceeded = FALSE
|
||||
else
|
||||
for(var/gas_path in required_gases)
|
||||
if(gas_comp[gas_path] < 0.4)
|
||||
critical_gas_exceeded = FALSE
|
||||
break
|
||||
|
||||
if(critical_gas_exceeded)
|
||||
return CASCADING_CRITICAL_GAS
|
||||
|
||||
return FALSE
|
||||
investigate_log("was forcefully delaminated", INVESTIGATE_ENGINE)
|
||||
INVOKE_ASYNC(delamination_strategy, /datum/sm_delam/proc/delaminate, src)
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/supermatter_pull(turf/center, pull_range = 3)
|
||||
playsound(center, 'sound/weapons/marauder.ogg', 100, TRUE, extrarange = pull_range - world.view)
|
||||
@@ -553,6 +439,61 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
continue //You can't pull someone nailed to the deck
|
||||
step_towards(movable_atom,center)
|
||||
|
||||
/**
|
||||
* Count down, spout some messages, and then execute the delam itself.
|
||||
* We guard for last second delam strat changes here, mostly because some have diff messages.
|
||||
*
|
||||
* By last second changes, we mean that it's possible for say, a tesla delam to
|
||||
* just explode normally if at the absolute last second it loses power and switches to default one.
|
||||
* Even after countdown is already in progress.
|
||||
*/
|
||||
/obj/machinery/power/supermatter_crystal/proc/count_down()
|
||||
set waitfor = FALSE
|
||||
|
||||
if(final_countdown) // We're already doing it go away
|
||||
stack_trace("[src] told to delaminate again while it's already delaminating.")
|
||||
return
|
||||
|
||||
final_countdown = TRUE
|
||||
update_appearance()
|
||||
|
||||
var/datum/sm_delam/last_delamination_strategy = delamination_strategy
|
||||
var/list/count_down_messages = delamination_strategy.count_down_messages()
|
||||
|
||||
radio.talk_into(
|
||||
src,
|
||||
count_down_messages[1],
|
||||
emergency_channel
|
||||
)
|
||||
|
||||
for(var/i in SUPERMATTER_COUNTDOWN_TIME to 0 step -10)
|
||||
if(last_delamination_strategy != delamination_strategy)
|
||||
count_down_messages = delamination_strategy.count_down_messages()
|
||||
|
||||
var/message
|
||||
var/healed = FALSE
|
||||
|
||||
if(damage < explosion_point) // Cutting it a bit close there engineers
|
||||
message = count_down_messages[2]
|
||||
healed = TRUE
|
||||
else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individualy
|
||||
sleep(1 SECONDS)
|
||||
continue
|
||||
else if(i > 50)
|
||||
message = "[DisplayTimeText(i, TRUE)] [count_down_messages[3]]"
|
||||
else
|
||||
message = "[i*0.1]..."
|
||||
|
||||
radio.talk_into(src, message, emergency_channel)
|
||||
|
||||
if(healed)
|
||||
final_countdown = FALSE
|
||||
update_appearance()
|
||||
return // delam averted
|
||||
sleep(1 SECONDS)
|
||||
|
||||
delamination_strategy.delaminate(src)
|
||||
|
||||
/proc/supermatter_anomaly_gen(turf/anomalycenter, type = FLUX_ANOMALY, anomalyrange = 5, has_changed_lifespan = TRUE)
|
||||
var/turf/local_turf = pick(orange(anomalyrange, anomalycenter))
|
||||
if(!local_turf)
|
||||
@@ -721,13 +662,12 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
base_icon_state = "darkmatter_shard"
|
||||
icon_state = "darkmatter_shard"
|
||||
anchored = FALSE
|
||||
gasefficency = 0.125
|
||||
absorption_ratio = 0.125
|
||||
explosion_power = 12
|
||||
layer = ABOVE_MOB_LAYER
|
||||
plane = GAME_PLANE_UPPER
|
||||
moveable = TRUE
|
||||
psyOverlay = /obj/overlay/psy/shard
|
||||
anomaly_event = FALSE
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/shard/engine
|
||||
name = "anchored supermatter shard"
|
||||
@@ -767,10 +707,6 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
pixel_x = -176
|
||||
pixel_y = -176
|
||||
|
||||
#undef CASCADING_ADMIN
|
||||
#undef CASCADING_CRITICAL_GAS
|
||||
#undef CASCADING_DESTAB_CRYSTAL
|
||||
|
||||
#undef BIKE
|
||||
#undef COIL
|
||||
#undef ROD
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
///Minimum distance that a crystal mass must have from the rift
|
||||
#define MIN_RIFT_SAFE_DIST 30
|
||||
|
||||
/datum/supermatter_delamination
|
||||
///Power amount of the SM at the moment of death
|
||||
var/supermatter_power = 0
|
||||
///Amount of total gases interacting with the SM
|
||||
var/supermatter_gas_amount = 0
|
||||
///Base number of anomalies to spawn (can go up or down with a random small amount)
|
||||
var/anomalies_to_spawn = 10
|
||||
///Can we spawn anomalies after dealing with the delamination type?
|
||||
var/should_spawn_anomalies = TRUE
|
||||
///Reference to the supermatter turf
|
||||
var/turf/supermatter_turf
|
||||
///Baseline strenght of the explosion caused by the SM
|
||||
var/supermatter_explosion_power = 0
|
||||
///Amount the gasmix will affect the explosion size
|
||||
var/supermatter_gasmix_power_ratio = 0
|
||||
///Are we triggering a supermatter cascade?
|
||||
var/supermatter_cascade = FALSE
|
||||
///The rift in space that will be created by the cascade
|
||||
var/obj/cascade_portal/cascade_rift
|
||||
|
||||
/datum/supermatter_delamination/New(supermatter_power, supermatter_gas_amount, turf/supermatter_turf, supermatter_explosion_power, supermatter_gasmix_power_ratio, can_spawn_anomalies, supermatter_cascade)
|
||||
. = ..()
|
||||
|
||||
src.supermatter_power = supermatter_power
|
||||
src.supermatter_gas_amount = supermatter_gas_amount
|
||||
src.supermatter_turf = supermatter_turf
|
||||
src.supermatter_explosion_power = supermatter_explosion_power
|
||||
src.supermatter_gasmix_power_ratio = supermatter_gasmix_power_ratio
|
||||
|
||||
if(supermatter_cascade)
|
||||
start_supermatter_cascade()
|
||||
return
|
||||
|
||||
setup_mob_interaction()
|
||||
setup_delamination_type()
|
||||
|
||||
if(!should_spawn_anomalies || !can_spawn_anomalies)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
setup_anomalies()
|
||||
|
||||
/**
|
||||
* What the mobs should deal with when a delamination happens
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/setup_mob_interaction()
|
||||
for(var/mob/living/victim as anything in GLOB.alive_mob_list)
|
||||
if(!istype(victim) || victim.z != supermatter_turf.z)
|
||||
continue
|
||||
|
||||
if(ishuman(victim))
|
||||
//Hilariously enough, running into a closet should make you get hit the hardest.
|
||||
var/mob/living/carbon/human/human = victim
|
||||
human.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(victim, src) + 1)) ) )
|
||||
|
||||
if (get_dist(victim, src) <= DETONATION_RADIATION_RANGE)
|
||||
SSradiation.irradiate(victim)
|
||||
|
||||
for(var/mob/victim as anything in GLOB.player_list)
|
||||
var/turf/mob_turf = get_turf(victim)
|
||||
if(supermatter_turf.z != mob_turf.z)
|
||||
continue
|
||||
|
||||
SEND_SOUND(victim, 'sound/magic/charge.ogg')
|
||||
|
||||
if (victim.z != supermatter_turf.z)
|
||||
to_chat(victim, span_boldannounce("You hold onto \the [victim.loc] as hard as you can, as reality distorts around you. You feel safe."))
|
||||
continue
|
||||
|
||||
to_chat(victim, span_boldannounce("You feel reality distort for a moment..."))
|
||||
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "delam", /datum/mood_event/delam)
|
||||
|
||||
/**
|
||||
* Setup for the types of possible delaminations and their effects (singulo, tesla or normal)
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/setup_delamination_type()
|
||||
if(supermatter_gas_amount > MOLE_PENALTY_THRESHOLD)
|
||||
call_singulo()
|
||||
return
|
||||
if(supermatter_power > POWER_PENALTY_THRESHOLD)
|
||||
call_tesla()
|
||||
return
|
||||
|
||||
call_explosion()
|
||||
|
||||
/**
|
||||
* Spawns the singularity
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/call_singulo()
|
||||
if(!supermatter_turf) //If something fucks up we blow anyhow. This fix is 4 years old and none ever said why it's here. help.
|
||||
call_explosion()
|
||||
return
|
||||
var/obj/singularity/created_singularity = new(supermatter_turf)
|
||||
created_singularity.energy = 800
|
||||
created_singularity.consume(src)
|
||||
should_spawn_anomalies = FALSE
|
||||
|
||||
/**
|
||||
* Spawns the tesla
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/call_tesla()
|
||||
if(supermatter_turf)
|
||||
var/obj/energy_ball/created_tesla = new(supermatter_turf)
|
||||
created_tesla.energy = 200 //Gets us about 9 balls
|
||||
call_explosion()
|
||||
should_spawn_anomalies = FALSE
|
||||
|
||||
/**
|
||||
* Spawns the explosion
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/call_explosion()
|
||||
//Dear mappers, balance the sm max explosion radius to 17.5, 37, 39, 41
|
||||
explosion(origin = supermatter_turf,
|
||||
devastation_range = supermatter_explosion_power * max(supermatter_gasmix_power_ratio, 0.205) * 0.5,
|
||||
heavy_impact_range = supermatter_explosion_power * max(supermatter_gasmix_power_ratio, 0.205) + 2,
|
||||
light_impact_range = supermatter_explosion_power * max(supermatter_gasmix_power_ratio, 0.205) + 4,
|
||||
flash_range = supermatter_explosion_power * max(supermatter_gasmix_power_ratio, 0.205) + 6,
|
||||
adminlog = TRUE,
|
||||
ignorecap = TRUE
|
||||
)
|
||||
|
||||
/**
|
||||
* Setups how many anomalies to spawn
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/setup_anomalies()
|
||||
anomalies_to_spawn = max(round(0.004 * supermatter_power, 1) + rand(-2, 2), 1)
|
||||
spawn_anomalies()
|
||||
|
||||
/**
|
||||
* Spawns the first half anomalies instantly and calls the second half
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/spawn_anomalies()
|
||||
var/list/anomaly_types = list(GRAVITATIONAL_ANOMALY = 55, HALLUCINATION_ANOMALY = 45, BIOSCRAMBLER_ANOMALY = 35, FLUX_ANOMALY = 25, PYRO_ANOMALY = 5, VORTEX_ANOMALY = 1)
|
||||
var/list/anomaly_places = GLOB.generic_event_spawns
|
||||
var/currently_spawning_anomalies = round(anomalies_to_spawn * 0.5, 1)
|
||||
anomalies_to_spawn -= currently_spawning_anomalies
|
||||
for(var/i in 1 to currently_spawning_anomalies)
|
||||
var/anomaly_to_spawn = pick_weight(anomaly_types)
|
||||
var/anomaly_location = pick_n_take(anomaly_places)
|
||||
supermatter_anomaly_gen(anomaly_location, anomaly_to_spawn, has_changed_lifespan = FALSE)
|
||||
|
||||
spawn_overtime()
|
||||
|
||||
/**
|
||||
* Spawns the second half anomalies after a delay
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/spawn_overtime()
|
||||
|
||||
var/list/anomaly_types = list(GRAVITATIONAL_ANOMALY = 55, HALLUCINATION_ANOMALY = 45, BIOSCRAMBLER_ANOMALY = 35, FLUX_ANOMALY = 25, PYRO_ANOMALY = 5, VORTEX_ANOMALY = 1)
|
||||
var/list/anomaly_places = GLOB.generic_event_spawns
|
||||
|
||||
var/current_spawn = rand(5 SECONDS, 10 SECONDS)
|
||||
for(var/i in 1 to anomalies_to_spawn)
|
||||
var/anomaly_to_spawn = pick_weight(anomaly_types)
|
||||
var/anomaly_location = pick_n_take(anomaly_places)
|
||||
var/next_spawn = rand(5 SECONDS, 10 SECONDS)
|
||||
var/extended_spawn = 0
|
||||
if(DT_PROB(1, next_spawn))
|
||||
extended_spawn = rand(5 MINUTES, 15 MINUTES)
|
||||
addtimer(CALLBACK(src, .proc/spawn_anomaly, anomaly_location, anomaly_to_spawn), current_spawn + extended_spawn)
|
||||
current_spawn += next_spawn
|
||||
|
||||
/**
|
||||
* Callback for the anomalies to spawn after some time
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/spawn_anomaly(location, type)
|
||||
supermatter_anomaly_gen(location, type, has_changed_lifespan = FALSE)
|
||||
|
||||
/**
|
||||
* Setup for the cascade delamination
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/start_supermatter_cascade()
|
||||
// buncha shuttle manipulation incoming
|
||||
|
||||
// set timer to infinity, so shuttle never arrives
|
||||
SSshuttle.emergency.setTimer(INFINITY)
|
||||
// disallow shuttle recalls, so people cannot cheese the timer
|
||||
SSshuttle.emergency_no_recall = TRUE
|
||||
// set supermatter cascade to true, to prevent auto evacuation due to no way of calling the shuttle
|
||||
SSshuttle.supermatter_cascade = TRUE
|
||||
// This logic is to keep uncalled shuttles uncalled
|
||||
// In SSshuttle, there is not much of a way to prevent shuttle calls, unless we mess with admin panel vars
|
||||
// SHUTTLE_STRANDED is different here, because it *can* block the shuttle from being called, however if we don't register a hostile
|
||||
// environment, it gets unset immediately. Internally, it checks if the count of HEs is zero
|
||||
// and that the shuttle is in stranded mode, then frees it with an announcement.
|
||||
// This is a botched solution to a problem that could be solved with a small change in shuttle code, however-
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_IDLE)
|
||||
SSshuttle.emergency.mode = SHUTTLE_STRANDED
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
// set hijack completion timer to infinity, so that you cant prematurely end the round with a hijack
|
||||
for(var/obj/machinery/computer/emergency_shuttle/console in GLOB.machines)
|
||||
console.hijack_completion_flight_time_set = INFINITY
|
||||
|
||||
for(var/mob/player as anything in GLOB.player_list)
|
||||
if(!isdead(player))
|
||||
to_chat(player, span_boldannounce("Everything around you is resonating with a powerful energy. This can't be good."))
|
||||
SEND_SIGNAL(player, COMSIG_ADD_MOOD_EVENT, "cascade", /datum/mood_event/cascade)
|
||||
SEND_SOUND(player, 'sound/magic/charge.ogg')
|
||||
|
||||
call_explosion()
|
||||
create_cascade_ambience()
|
||||
warn_crew()
|
||||
|
||||
var/rift_loc = pick_rift_location()
|
||||
new /obj/crystal_mass(supermatter_turf)
|
||||
|
||||
var/list/mass_loc_candidates = GLOB.generic_event_spawns.Copy()
|
||||
mass_loc_candidates.Remove(rift_loc) // this should now actually get rid of stalemates
|
||||
for(var/i in 1 to rand(4,6))
|
||||
var/list/loc_list = mass_loc_candidates.Copy()
|
||||
var/mass_loc
|
||||
do
|
||||
mass_loc = pick_n_take(loc_list)
|
||||
while(get_dist(mass_loc, rift_loc) < MIN_RIFT_SAFE_DIST)
|
||||
new /obj/crystal_mass(get_turf(mass_loc))
|
||||
|
||||
SSsupermatter_cascade.cascade_initiated = TRUE
|
||||
|
||||
/**
|
||||
* Adds a bit of spiciness to the cascade by breaking lights and turning emergency maint access on
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/create_cascade_ambience()
|
||||
if(SSsecurity_level.get_current_level_as_number() != SEC_LEVEL_DELTA)
|
||||
SSsecurity_level.set_level(SEC_LEVEL_DELTA) // skip the announcement and shuttle timer adjustment in set_security_level()
|
||||
make_maint_all_access()
|
||||
break_lights_on_station()
|
||||
|
||||
/**
|
||||
* Picks a random location for the rift
|
||||
* Returns: ref to rift location
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/pick_rift_location()
|
||||
var/rift_spawn = pick(GLOB.generic_event_spawns)
|
||||
var/turf/rift_turf = get_turf(rift_spawn)
|
||||
cascade_rift = new /obj/cascade_portal(rift_turf)
|
||||
message_admins("Exit rift created at [get_area_name(rift_turf)]. [ADMIN_JMP(cascade_rift)]")
|
||||
log_game("Bluespace Exit Rift was created at [get_area_name(rift_turf)].")
|
||||
cascade_rift.investigate_log("created at [get_area_name(rift_turf)].", INVESTIGATE_ENGINE)
|
||||
RegisterSignal(cascade_rift, COMSIG_PARENT_QDELETING, .proc/deleted_portal)
|
||||
return rift_spawn
|
||||
|
||||
/**
|
||||
* Warns the crew about the cascade start and the rift location
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/warn_crew()
|
||||
priority_announce("A Type-C resonance shift event has occurred in your sector. Scans indicate local oscillation flux affecting spatial and gravitational substructure. \
|
||||
Multiple resonance hotspots have formed. Please standby.", "Nanotrasen Star Observation Association", ANNOUNCER_SPANOMALIES)
|
||||
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_STRANDED)
|
||||
addtimer(CALLBACK(src, .proc/announce_shuttle_gone), 2 SECONDS)
|
||||
|
||||
addtimer(CALLBACK(src, .proc/announce_beginning), 5 SECONDS)
|
||||
|
||||
/**
|
||||
* Logs the deletion of the bluespace rift, and starts countdown to the end of the round.
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/deleted_portal()
|
||||
SIGNAL_HANDLER
|
||||
message_admins("[cascade_rift] deleted at [get_area_name(cascade_rift.loc)]. [ADMIN_JMP(cascade_rift.loc)]")
|
||||
log_game("[cascade_rift] was deleted.")
|
||||
cascade_rift.investigate_log("was deleted.", INVESTIGATE_ENGINE)
|
||||
|
||||
priority_announce("[Gibberish("The rift has been destroyed, we can no longer help you.", FALSE, 5)]")
|
||||
|
||||
addtimer(CALLBACK(src, .proc/announce_gravitation_shift), 25 SECONDS)
|
||||
addtimer(CALLBACK(src, .proc/last_message), 50 SECONDS)
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_ESCAPE) // if the shuttle is enroute to centcom, we let the shuttle end the round
|
||||
addtimer(CALLBACK(src, .proc/the_end), 1 MINUTES)
|
||||
|
||||
/**
|
||||
* Announces the halfway point to the end.
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/announce_gravitation_shift()
|
||||
priority_announce("Reports indicate formation of crystalline seeds following resonance shift event. \
|
||||
Rapid expansion of crystal mass proportional to rising gravitational force. \
|
||||
Matter collapse due to gravitational pull foreseeable.",
|
||||
"Nanotrasen Star Observation Association")
|
||||
|
||||
/**
|
||||
* This proc manipulates the shuttle if it's enroute to centcom, to remain in hyperspace. Otherwise, it just plays an announcement if
|
||||
* the shuttle was in any other state except stranded (idle)
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/announce_shuttle_gone()
|
||||
// say goodbye to that shuttle of yours
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_ESCAPE)
|
||||
priority_announce("Fatal error occurred in emergency shuttle uplink during transit. Unable to reestablish connection.",
|
||||
"Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
|
||||
else
|
||||
// except if you are on it already, then you are safe c:
|
||||
minor_announce("ERROR: Corruption detected in navigation protocols. Connection with Transponder #XCC-P5831-ES13 lost. \
|
||||
Backup exit route protocol decrypted. Calibrating route...",
|
||||
"Emergency Shuttle", TRUE) // wait out until the rift on the station gets destroyed and the final message plays
|
||||
var/list/mobs = mobs_in_area_type(list(/area/shuttle/escape))
|
||||
for(var/mob/living/mob as anything in mobs) // emulate mob/living/lateShuttleMove() behaviour
|
||||
if(mob.buckled)
|
||||
continue
|
||||
if(mob.client)
|
||||
shake_camera(mob, 3 SECONDS * 0.25, 1)
|
||||
mob.Paralyze(3 SECONDS, TRUE)
|
||||
|
||||
/**
|
||||
* Announces the last message to the station, frees the shuttle from purgatory if applicable
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/last_message()
|
||||
priority_announce("[Gibberish("All attempts at evacuation have now ceased, and all assets have been retrieved from your sector.\n \
|
||||
To the remaining survivors of [station_name()], farewell.", FALSE, 5)]")
|
||||
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
|
||||
// special message for hijacks
|
||||
var/shuttle_msg = "Navigation protocol set to [SSshuttle.emergency.is_hijacked() ? "\[ERROR\]" : "backup route"]. \
|
||||
Reorienting bluespace vessel to exit vector. ETA 15 seconds."
|
||||
// garble the special message
|
||||
if(SSshuttle.emergency.is_hijacked())
|
||||
shuttle_msg = Gibberish(shuttle_msg, TRUE, 15)
|
||||
minor_announce(shuttle_msg, "Emergency Shuttle", TRUE)
|
||||
SSshuttle.emergency.setTimer(15 SECONDS)
|
||||
|
||||
/**
|
||||
* Announce detail about the event, as well as rift location
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/announce_beginning()
|
||||
priority_announce("We have been hit by a sector-wide electromagnetic pulse. All of our systems are heavily damaged, including those \
|
||||
required for shuttle navigation. We can only reasonably conclude that a supermatter cascade is occurring on or near your station.\n\n\
|
||||
Evacuation is no longer possible by conventional means; however, we managed to open a rift near the [get_area_name(cascade_rift)]. \
|
||||
All personnel are hereby required to enter the rift by any means available.\n\n\
|
||||
[Gibberish("Retrieval of survivors will be conducted upon recovery of necessary facilities.", FALSE, 5)] \
|
||||
[Gibberish("Good luck--", FALSE, 25)]")
|
||||
|
||||
/**
|
||||
* Ends the round
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/the_end()
|
||||
SSticker.news_report = SUPERMATTER_CASCADE
|
||||
SSticker.force_ending = TRUE
|
||||
|
||||
/**
|
||||
* Break the lights on the station, have 35% of them be set to emergency
|
||||
*/
|
||||
/datum/supermatter_delamination/proc/break_lights_on_station()
|
||||
for(var/obj/machinery/light/light_to_break in GLOB.machines)
|
||||
if(prob(35))
|
||||
light_to_break.set_major_emergency_light()
|
||||
continue
|
||||
light_to_break.break_light_tube()
|
||||
|
||||
#undef MIN_RIFT_SAFE_DIST
|
||||
@@ -0,0 +1,106 @@
|
||||
/// Priority is top to bottom.
|
||||
GLOBAL_LIST_INIT(sm_delam_list, list(
|
||||
/datum/sm_delam/cascade = new /datum/sm_delam/cascade,
|
||||
/datum/sm_delam/singularity = new /datum/sm_delam/singularity,
|
||||
/datum/sm_delam/tesla = new /datum/sm_delam/tesla,
|
||||
/datum/sm_delam/explosive = new /datum/sm_delam/explosive,
|
||||
))
|
||||
|
||||
/// Logic holder for supermatter delaminations, goes off the strategy design pattern.
|
||||
/// Selected by [/obj/machinery/power/supermatter_crystal/proc/set_delam]
|
||||
/datum/sm_delam
|
||||
|
||||
/// Whether we are eligible for this delamination or not. TRUE if valid, FALSE if not.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/set_delam]
|
||||
/datum/sm_delam/proc/can_select(obj/machinery/power/supermatter_crystal/sm)
|
||||
return FALSE
|
||||
|
||||
/// Called when the count down has been finished, do the nasty work.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/count_down]
|
||||
/datum/sm_delam/proc/delaminate(obj/machinery/power/supermatter_crystal/sm)
|
||||
qdel(sm)
|
||||
|
||||
/// Whatever we're supposed to do when a delam is currently in progress.
|
||||
/// Mostly just to tell people how useless engi is, and play some alarm sounds.
|
||||
/// Returns TRUE if we just told people a delam is going on. FALSE if its healing or we didnt say anything.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/process_atmos]
|
||||
/datum/sm_delam/proc/delam_progress(obj/machinery/power/supermatter_crystal/sm)
|
||||
if(sm.damage <= sm.warning_point) // Damage is too low, lets not
|
||||
return FALSE
|
||||
|
||||
if (sm.damage >= sm.emergency_point && sm.damage_archived < sm.emergency_point)
|
||||
sm.investigate_log("has entered the emergency point.", INVESTIGATE_ENGINE)
|
||||
message_admins("[sm] has entered the emergency point [ADMIN_VERBOSEJMP(sm)].")
|
||||
|
||||
if((REALTIMEOFDAY - sm.lastwarning) < SUPERMATTER_WARNING_DELAY)
|
||||
return FALSE
|
||||
sm.lastwarning = REALTIMEOFDAY
|
||||
|
||||
switch(sm.get_status())
|
||||
if(SUPERMATTER_DELAMINATING)
|
||||
// SKYRAT EDIT ADDITION
|
||||
alert_sound_to_playing('modular_skyrat/master_files/sound/effects/reactor/meltdown.ogg', override_volume = TRUE)
|
||||
alert_sound_to_playing('modular_skyrat/modules/alerts/sound/alerts/alert1.ogg', override_volume = TRUE)
|
||||
// SKYRAT EDIT END
|
||||
playsound(sm, 'sound/misc/bloblarm.ogg', 100, FALSE, 40, 30, falloff_distance = 10)
|
||||
if(SUPERMATTER_EMERGENCY)
|
||||
// SKYRAT EDIT ADDITION
|
||||
alert_sound_to_playing('modular_skyrat/master_files/sound/effects/reactor/core_overheating.ogg', override_volume = TRUE)
|
||||
alert_sound_to_playing('modular_skyrat/modules/alerts/sound/alerts/alert1.ogg', override_volume = TRUE)
|
||||
// SKYRAT EDIT END
|
||||
playsound(sm, 'sound/machines/engine_alert1.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
|
||||
if(SUPERMATTER_DANGER)
|
||||
playsound(sm, 'sound/machines/engine_alert2.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
|
||||
if(SUPERMATTER_WARNING)
|
||||
playsound(sm, 'sound/machines/terminal_alert.ogg', 75)
|
||||
|
||||
if(sm.damage < sm.damage_archived) // Healing
|
||||
sm.radio.talk_into(sm,"Crystalline hyperstructure returning to safe operating parameters. Integrity: [sm.get_integrity_percent()]%", sm.damage_archived >= sm.emergency_point ? sm.emergency_channel : sm.warning_channel)
|
||||
return FALSE
|
||||
|
||||
if(sm.damage >= sm.emergency_point) // Taking damage, in emergency
|
||||
sm.radio.talk_into(sm, "CRYSTAL DELAMINATION IMMINENT Integrity: [sm.get_integrity_percent()]%", sm.emergency_channel)
|
||||
sm.lastwarning = REALTIMEOFDAY - (SUPERMATTER_WARNING_DELAY / 2) // Cut the time to next announcement in half.
|
||||
else // Taking damage, in warning
|
||||
sm.radio.talk_into(sm, "Danger! Crystal hyperstructure integrity faltering! Integrity: [sm.get_integrity_percent()]%", sm.warning_channel)
|
||||
if(sm.damage_archived < sm.warning_point)
|
||||
SEND_SIGNAL(sm, COMSIG_SUPERMATTER_DELAM_START_ALARM)
|
||||
|
||||
SEND_SIGNAL(sm, COMSIG_SUPERMATTER_DELAM_ALARM)
|
||||
return TRUE
|
||||
|
||||
/// Called when a supermatter switches it's strategy from another one to us.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/set_delam]
|
||||
/datum/sm_delam/proc/on_select(obj/machinery/power/supermatter_crystal/sm)
|
||||
return
|
||||
|
||||
/// Called when a supermatter switches it's strategy from us to something else.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/set_delam]
|
||||
/datum/sm_delam/proc/on_deselect(obj/machinery/power/supermatter_crystal/sm)
|
||||
return
|
||||
|
||||
/// Added to an examine return value.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/examine]
|
||||
/datum/sm_delam/proc/examine(obj/machinery/power/supermatter_crystal/sm)
|
||||
return list()
|
||||
|
||||
/// Add whatever overlay to the sm.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/overlays]
|
||||
/datum/sm_delam/proc/overlays(obj/machinery/power/supermatter_crystal/sm)
|
||||
if(sm.final_countdown)
|
||||
return list(mutable_appearance(sm.icon, "causality_field"))
|
||||
return list()
|
||||
|
||||
/// Modifies the damage dealt to the sm.
|
||||
/// [/obj/machinery/power/supermatter_crystal/proc/deal_damage]
|
||||
/datum/sm_delam/proc/damage_multiplier(obj/machinery/power/supermatter_crystal/sm)
|
||||
return 1
|
||||
|
||||
/// Returns a set of messages to be spouted during delams
|
||||
/// First message is start of count down, second message is quitting of count down (if sm healed), third is 5 second intervals
|
||||
/datum/sm_delam/proc/count_down_messages(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/list/messages = list()
|
||||
messages += "CRYSTAL DELAMINATION IMMINENT. The supermatter has reached critical integrity failure. Emergency causality destabilization field has been activated."
|
||||
messages += "Crystalline hyperstructure returning to safe operating parameters. Failsafe has been disengaged."
|
||||
messages += "remain before causality stabilization."
|
||||
return messages
|
||||
@@ -0,0 +1,97 @@
|
||||
/datum/sm_delam/cascade
|
||||
|
||||
/datum/sm_delam/cascade/can_select(obj/machinery/power/supermatter_crystal/sm)
|
||||
if(!sm.is_main_engine)
|
||||
return FALSE
|
||||
var/total_moles = sm.absorbed_gasmix.total_moles()
|
||||
if(total_moles < MOLE_PENALTY_THRESHOLD * sm.absorption_ratio)
|
||||
return FALSE
|
||||
for (var/gas_path in list(/datum/gas/antinoblium, /datum/gas/hypernoblium))
|
||||
var/percent = sm.absorbed_gasmix.gases[gas_path]?[MOLES] / total_moles
|
||||
if(!percent || percent < 0.4)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/sm_delam/cascade/delam_progress(obj/machinery/power/supermatter_crystal/sm)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
sm.radio.talk_into(
|
||||
sm,
|
||||
"DANGER: HYPERSTRUCTURE OSCILLATION FREQUENCY OUT OF BOUNDS.",
|
||||
sm.damage >= sm.emergency_point ? sm.emergency_channel : sm.warning_channel
|
||||
)
|
||||
var/list/messages = list(
|
||||
"Space seems to be shifting around you...",
|
||||
"You hear a high-pitched ringing sound.",
|
||||
"You feel tingling going down your back.",
|
||||
"Something feels very off.",
|
||||
"A drowning sense of dread washes over you.",
|
||||
)
|
||||
for(var/mob/victim as anything in GLOB.player_list)
|
||||
to_chat(victim, span_danger(pick(messages)))
|
||||
|
||||
/datum/sm_delam/cascade/on_select(obj/machinery/power/supermatter_crystal/sm)
|
||||
message_admins("[sm] is heading towards a cascade. [ADMIN_VERBOSEJMP(sm)]")
|
||||
sm.investigate_log("is heading towards a cascade.", INVESTIGATE_ENGINE)
|
||||
|
||||
sm.warp = new(sm)
|
||||
sm.vis_contents += sm.warp
|
||||
animate(sm.warp, time = 1, transform = matrix().Scale(0.5,0.5))
|
||||
animate(time = 9, transform = matrix())
|
||||
|
||||
addtimer(CALLBACK(src, .proc/announce_cascade, sm), 2 MINUTES)
|
||||
|
||||
/datum/sm_delam/cascade/on_deselect(obj/machinery/power/supermatter_crystal/sm)
|
||||
message_admins("[sm] will no longer cascade. [ADMIN_VERBOSEJMP(sm)]")
|
||||
sm.investigate_log("will no longer cascade.", INVESTIGATE_ENGINE)
|
||||
|
||||
sm.vis_contents -= sm.warp
|
||||
QDEL_NULL(sm.warp)
|
||||
|
||||
/datum/sm_delam/cascade/delaminate(obj/machinery/power/supermatter_crystal/sm)
|
||||
message_admins("Supermatter [sm] at [ADMIN_VERBOSEJMP(sm)] triggered a cascade delam.")
|
||||
sm.investigate_log("triggered a cascade delam.", INVESTIGATE_ENGINE)
|
||||
|
||||
effect_explosion(sm)
|
||||
effect_emergency_state()
|
||||
effect_cascade_demoralize()
|
||||
priority_announce("A Type-C resonance shift event has occurred in your sector. Scans indicate local oscillation flux affecting spatial and gravitational substructure. \
|
||||
Multiple resonance hotspots have formed. Please standby.", "Nanotrasen Star Observation Association", ANNOUNCER_SPANOMALIES)
|
||||
sleep(2 SECONDS)
|
||||
effect_strand_shuttle()
|
||||
sleep(5 SECONDS)
|
||||
var/obj/cascade_portal/rift = effect_evac_rift_start()
|
||||
RegisterSignal(rift, COMSIG_PARENT_QDELETING, .proc/end_round_holder)
|
||||
effect_crystal_mass(sm, rift)
|
||||
SSsupermatter_cascade.cascade_initiated = TRUE
|
||||
qdel(sm)
|
||||
|
||||
/datum/sm_delam/cascade/examine(obj/machinery/power/supermatter_crystal/sm)
|
||||
return list(span_bolddanger("The crystal is vibrating at immense speeds, warping space around it!"))
|
||||
|
||||
/datum/sm_delam/cascade/overlays(obj/machinery/power/supermatter_crystal/sm)
|
||||
return list()
|
||||
|
||||
/datum/sm_delam/cascade/damage_multiplier(obj/machinery/power/supermatter_crystal/sm)
|
||||
return 0.25
|
||||
|
||||
/datum/sm_delam/cascade/count_down_messages(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/list/messages = list()
|
||||
messages += "CRYSTAL DELAMINATION IMMINENT. The supermatter has reached critical integrity failure. Harmonic frequency limits exceeded. Causality destabilization field could not be engaged."
|
||||
messages += "Crystalline hyperstructure returning to safe operating parameters. Harmonic frequency restored within emergency bounds. Anti-resonance filter initiated."
|
||||
messages += "remain before resonance-induced stabilization."
|
||||
return messages
|
||||
|
||||
/datum/sm_delam/cascade/proc/announce_cascade(obj/machinery/power/supermatter_crystal/sm)
|
||||
if(!can_select(sm))
|
||||
return FALSE
|
||||
priority_announce("Attention: Long range anomaly scans indicate abnormal quantities of harmonic flux originating from \
|
||||
a subject within [station_name()], a resonance collapse may occur.",
|
||||
"Nanotrasen Star Observation Association")
|
||||
return TRUE
|
||||
|
||||
/// Signal calls cant sleep, we gotta do this.
|
||||
/datum/sm_delam/cascade/proc/end_round_holder()
|
||||
SIGNAL_HANDLER
|
||||
INVOKE_ASYNC(src, .proc/effect_evac_rift_end)
|
||||
+18
-1
@@ -110,6 +110,22 @@
|
||||
pixel_y = -96
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
|
||||
|
||||
/obj/cascade_portal/Initialize(mapload)
|
||||
. = ..()
|
||||
var/turf/location = get_turf(src)
|
||||
var/area_name = get_area_name(src)
|
||||
message_admins("Exit rift created at [area_name]. [ADMIN_VERBOSEJMP(location)]")
|
||||
log_game("Bluespace Exit Rift was created at [area_name].")
|
||||
investigate_log("created at [area_name].", INVESTIGATE_ENGINE)
|
||||
|
||||
/obj/cascade_portal/Destroy(force)
|
||||
var/turf/location = get_turf(src)
|
||||
var/area_name = get_area_name(src)
|
||||
message_admins("Exit rift at [area_name] deleted. [ADMIN_VERBOSEJMP(location)]")
|
||||
log_game("Bluespace Exit Rift at [area_name] was deleted.")
|
||||
investigate_log("was deleted.", INVESTIGATE_ENGINE)
|
||||
return ..()
|
||||
|
||||
/obj/cascade_portal/Bumped(atom/movable/hit_object)
|
||||
consume(hit_object)
|
||||
new /obj/effect/particle_effect/sparks(loc)
|
||||
@@ -135,7 +151,7 @@
|
||||
while(!is_safe_turf(arrival_turf))
|
||||
|
||||
var/mob/living/consumed_mob = consumed_object
|
||||
message_admins("[key_name_admin(consumed_mob)] has entered [src] [ADMIN_JMP(src)].")
|
||||
message_admins("[key_name_admin(consumed_mob)] has entered [src] [ADMIN_VERBOSEJMP(src)].")
|
||||
investigate_log("was entered by [key_name(consumed_mob)].", INVESTIGATE_ENGINE)
|
||||
consumed_mob.forceMove(arrival_turf)
|
||||
consumed_mob.Paralyze(100)
|
||||
@@ -149,3 +165,4 @@
|
||||
span_hear("You hear a loud crack as a small distortion passes through you."))
|
||||
|
||||
qdel(consumed_object)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Singulo, tesla, and explosive delam
|
||||
|
||||
/// When we have too much gas.
|
||||
/datum/sm_delam/singularity
|
||||
|
||||
/datum/sm_delam/singularity/can_select(obj/machinery/power/supermatter_crystal/sm)
|
||||
return (sm.absorbed_gasmix.total_moles() >= MOLE_PENALTY_THRESHOLD)
|
||||
|
||||
/datum/sm_delam/singularity/delam_progress(obj/machinery/power/supermatter_crystal/sm)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
sm.radio.talk_into(
|
||||
sm,
|
||||
"Warning: Critical coolant mass reached.",
|
||||
sm.damage > sm.emergency_point ? sm.emergency_channel : sm.warning_channel
|
||||
)
|
||||
|
||||
/datum/sm_delam/singularity/delaminate(obj/machinery/power/supermatter_crystal/sm)
|
||||
message_admins("Supermatter [sm] at [ADMIN_VERBOSEJMP(sm)] triggered a singularity delam.")
|
||||
sm.investigate_log("triggered a singularity delam.", INVESTIGATE_ENGINE)
|
||||
|
||||
effect_irradiate(sm)
|
||||
effect_demoralize(sm)
|
||||
if(sm.is_main_engine)
|
||||
effect_anomaly(sm)
|
||||
if(!effect_singulo(sm))
|
||||
effect_explosion(sm)
|
||||
qdel(sm)
|
||||
|
||||
/// When we have too much power.
|
||||
/datum/sm_delam/tesla
|
||||
|
||||
/datum/sm_delam/tesla/can_select(obj/machinery/power/supermatter_crystal/sm)
|
||||
return (sm.power > POWER_PENALTY_THRESHOLD)
|
||||
|
||||
/datum/sm_delam/tesla/delam_progress(obj/machinery/power/supermatter_crystal/sm)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
sm.radio.talk_into(
|
||||
sm,
|
||||
"DANGER: CHARGE INERTIA CHAIN REACTION IN PROGRESS.",
|
||||
sm.damage > sm.emergency_point ? sm.emergency_channel : sm.warning_channel
|
||||
)
|
||||
|
||||
/datum/sm_delam/tesla/delaminate(obj/machinery/power/supermatter_crystal/sm)
|
||||
message_admins("Supermatter [sm] at [ADMIN_VERBOSEJMP(sm)] triggered a tesla delam.")
|
||||
sm.investigate_log("triggered a tesla delam.", INVESTIGATE_ENGINE)
|
||||
|
||||
effect_irradiate(sm)
|
||||
effect_demoralize(sm)
|
||||
if(sm.is_main_engine)
|
||||
effect_anomaly(sm)
|
||||
effect_tesla(sm)
|
||||
effect_explosion(sm)
|
||||
qdel(sm)
|
||||
|
||||
/// Default delam.
|
||||
/datum/sm_delam/explosive
|
||||
|
||||
/datum/sm_delam/explosive/can_select(obj/machinery/power/supermatter_crystal/sm)
|
||||
return TRUE
|
||||
|
||||
/datum/sm_delam/explosive/delaminate(obj/machinery/power/supermatter_crystal/sm)
|
||||
message_admins("Supermatter [sm] at [ADMIN_VERBOSEJMP(sm)] triggered a normal delam.")
|
||||
sm.investigate_log("triggered a normal delam.", INVESTIGATE_ENGINE)
|
||||
|
||||
effect_irradiate(sm)
|
||||
effect_demoralize(sm)
|
||||
if(sm.is_main_engine)
|
||||
effect_anomaly(sm)
|
||||
effect_explosion(sm)
|
||||
qdel(sm)
|
||||
@@ -0,0 +1,212 @@
|
||||
// These are supposed to be discrete effects so we can tell at a glance what does each override
|
||||
// of [/datum/sm_delam/proc/delaminate] does.
|
||||
// Please keep them discrete and give them proper, descriptive function names.
|
||||
// Oh and all of them returns true if the effect succeeded.
|
||||
|
||||
/// Irradiates mobs around 20 tiles of the sm.
|
||||
/// Just the mobs apparently.
|
||||
/datum/sm_delam/proc/effect_irradiate(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/turf/sm_turf = get_turf(sm)
|
||||
for (var/mob/living/victim in range(20, sm))
|
||||
if(victim.z != sm_turf.z)
|
||||
continue
|
||||
SSradiation.irradiate(victim)
|
||||
return TRUE
|
||||
|
||||
/// Hallucinates and makes mobs in Z level sad.
|
||||
/datum/sm_delam/proc/effect_demoralize(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/turf/sm_turf = get_turf(sm)
|
||||
for(var/mob/living/victim as anything in GLOB.alive_mob_list)
|
||||
if(!istype(victim) || victim.z != sm_turf.z)
|
||||
continue
|
||||
if(ishuman(victim))
|
||||
//Hilariously enough, running into a closet should make you get hit the hardest.
|
||||
var/mob/living/carbon/human/human = victim
|
||||
human.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(victim, sm) + 1)) ) )
|
||||
|
||||
for(var/mob/victim as anything in GLOB.player_list)
|
||||
var/turf/mob_turf = get_turf(victim)
|
||||
if(sm_turf.z != mob_turf.z)
|
||||
continue
|
||||
SEND_SOUND(victim, 'sound/magic/charge.ogg')
|
||||
if (victim.z != sm_turf.z)
|
||||
to_chat(victim, span_boldannounce("You hold onto \the [victim.loc] as hard as you can, as reality distorts around you. You feel safe."))
|
||||
continue
|
||||
to_chat(victim, span_boldannounce("You feel reality distort for a moment..."))
|
||||
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "delam", /datum/mood_event/delam)
|
||||
return TRUE
|
||||
|
||||
/// Spawns anomalies all over the station. Half instantly, the other half over time.
|
||||
/datum/sm_delam/proc/effect_anomaly(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/anomalies = 10
|
||||
var/list/anomaly_types = list(GRAVITATIONAL_ANOMALY = 55, HALLUCINATION_ANOMALY = 45, DELIMBER_ANOMALY = 35, FLUX_ANOMALY = 25, PYRO_ANOMALY = 5, VORTEX_ANOMALY = 1)
|
||||
var/list/anomaly_places = GLOB.generic_event_spawns
|
||||
|
||||
// Spawns this many anomalies instantly. Spawns the rest with callbacks.
|
||||
var/cutoff_point = round(anomalies * 0.5, 1)
|
||||
|
||||
for(var/i in 1 to anomalies)
|
||||
var/anomaly_to_spawn = pick_weight(anomaly_types)
|
||||
var/anomaly_location = pick_n_take(anomaly_places)
|
||||
|
||||
if(i < cutoff_point)
|
||||
supermatter_anomaly_gen(anomaly_location, anomaly_to_spawn, has_changed_lifespan = FALSE)
|
||||
continue
|
||||
|
||||
var/current_spawn = rand(5 SECONDS, 10 SECONDS)
|
||||
var/next_spawn = rand(5 SECONDS, 10 SECONDS)
|
||||
var/extended_spawn = 0
|
||||
if(DT_PROB(1, next_spawn))
|
||||
extended_spawn = rand(5 MINUTES, 15 MINUTES)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/supermatter_anomaly_gen, anomaly_location, anomaly_to_spawn, TRUE), current_spawn + extended_spawn)
|
||||
return TRUE
|
||||
|
||||
/// Explodes
|
||||
/datum/sm_delam/proc/effect_explosion(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/explosion_power = sm.explosion_power
|
||||
var/power_scaling = sm.gasmix_power_ratio
|
||||
var/turf/sm_turf = get_turf(sm)
|
||||
//Dear mappers, balance the sm max explosion radius to 17.5, 37, 39, 41
|
||||
explosion(origin = sm_turf,
|
||||
devastation_range = explosion_power * max(power_scaling, 0.205) * 0.5,
|
||||
heavy_impact_range = explosion_power * max(power_scaling, 0.205) + 2,
|
||||
light_impact_range = explosion_power * max(power_scaling, 0.205) + 4,
|
||||
flash_range = explosion_power * max(power_scaling, 0.205) + 6,
|
||||
adminlog = TRUE,
|
||||
ignorecap = TRUE
|
||||
)
|
||||
return TRUE
|
||||
|
||||
/// Spawns a scrung and eat the SM.
|
||||
/datum/sm_delam/proc/effect_singulo(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/turf/sm_turf = get_turf(sm)
|
||||
if(!sm_turf)
|
||||
stack_trace("Supermatter [sm] failed to spawn singularity, cant get current turf.")
|
||||
return FALSE
|
||||
var/obj/singularity/created_singularity = new(sm_turf)
|
||||
created_singularity.energy = 800
|
||||
created_singularity.consume(sm)
|
||||
return TRUE
|
||||
|
||||
/// Teslas
|
||||
/datum/sm_delam/proc/effect_tesla(obj/machinery/power/supermatter_crystal/sm)
|
||||
var/turf/sm_turf = get_turf(sm)
|
||||
if(!sm_turf)
|
||||
stack_trace("Supermatter [sm] failed to spawn tesla, cant get current turf.")
|
||||
return FALSE
|
||||
var/obj/energy_ball/created_tesla = new(sm_turf)
|
||||
created_tesla.energy = 200 //Gets us about 9 balls
|
||||
return TRUE
|
||||
|
||||
/// Mail the shuttle off to buy milk.
|
||||
/datum/sm_delam/proc/effect_strand_shuttle()
|
||||
set waitfor = FALSE
|
||||
// set timer to infinity, so shuttle never arrives
|
||||
SSshuttle.emergency.setTimer(INFINITY)
|
||||
// disallow shuttle recalls, so people cannot cheese the timer
|
||||
SSshuttle.emergency_no_recall = TRUE
|
||||
// set supermatter cascade to true, to prevent auto evacuation due to no way of calling the shuttle
|
||||
SSshuttle.supermatter_cascade = TRUE
|
||||
// set hijack completion timer to infinity, so that you cant prematurely end the round with a hijack
|
||||
for(var/obj/machinery/computer/emergency_shuttle/console in GLOB.machines)
|
||||
console.hijack_completion_flight_time_set = INFINITY
|
||||
|
||||
/* This logic is to keep uncalled shuttles uncalled
|
||||
In SSshuttle, there is not much of a way to prevent shuttle calls, unless we mess with admin panel vars
|
||||
SHUTTLE_STRANDED is different here, because it *can* block the shuttle from being called, however if we don't register a hostile
|
||||
environment, it gets unset immediately. Internally, it checks if the count of HEs is zero
|
||||
and that the shuttle is in stranded mode, then frees it with an announcement.
|
||||
This is a botched solution to a problem that could be solved with a small change in shuttle code, however-
|
||||
*/
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_IDLE)
|
||||
SSshuttle.emergency.mode = SHUTTLE_STRANDED
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
return
|
||||
|
||||
// say goodbye to that shuttle of yours
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_ESCAPE)
|
||||
priority_announce("Fatal error occurred in emergency shuttle uplink during transit. Unable to reestablish connection.",
|
||||
"Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
|
||||
else
|
||||
// except if you are on it already, then you are safe c:
|
||||
minor_announce("ERROR: Corruption detected in navigation protocols. Connection with Transponder #XCC-P5831-ES13 lost. \
|
||||
Backup exit route protocol decrypted. Calibrating route...",
|
||||
"Emergency Shuttle", TRUE) // wait out until the rift on the station gets destroyed and the final message plays
|
||||
var/list/mobs = mobs_in_area_type(list(/area/shuttle/escape))
|
||||
for(var/mob/living/mob as anything in mobs) // emulate mob/living/lateShuttleMove() behaviour
|
||||
if(mob.buckled)
|
||||
continue
|
||||
if(mob.client)
|
||||
shake_camera(mob, 3 SECONDS * 0.25, 1)
|
||||
mob.Paralyze(3 SECONDS, TRUE)
|
||||
|
||||
/datum/sm_delam/proc/effect_cascade_demoralize()
|
||||
for(var/mob/player as anything in GLOB.player_list)
|
||||
if(!isdead(player))
|
||||
to_chat(player, span_boldannounce("Everything around you is resonating with a powerful energy. This can't be good."))
|
||||
SEND_SIGNAL(player, COMSIG_ADD_MOOD_EVENT, "cascade", /datum/mood_event/cascade)
|
||||
SEND_SOUND(player, 'sound/magic/charge.ogg')
|
||||
|
||||
/datum/sm_delam/proc/effect_emergency_state()
|
||||
if(SSsecurity_level.get_current_level_as_number() != SEC_LEVEL_DELTA)
|
||||
SSsecurity_level.set_level(SEC_LEVEL_DELTA) // skip the announcement and shuttle timer adjustment in set_security_level()
|
||||
make_maint_all_access()
|
||||
for(var/obj/machinery/light/light_to_break in GLOB.machines)
|
||||
if(prob(35))
|
||||
light_to_break.set_major_emergency_light()
|
||||
continue
|
||||
light_to_break.break_light_tube()
|
||||
|
||||
/// Spawn an evacuation rift for people to go through.
|
||||
/datum/sm_delam/proc/effect_evac_rift_start()
|
||||
var/obj/cascade_portal/rift = new /obj/cascade_portal(get_turf(pick(GLOB.generic_event_spawns)))
|
||||
priority_announce("We have been hit by a sector-wide electromagnetic pulse. All of our systems are heavily damaged, including those \
|
||||
required for shuttle navigation. We can only reasonably conclude that a supermatter cascade is occurring on or near your station.\n\n\
|
||||
Evacuation is no longer possible by conventional means; however, we managed to open a rift near the [get_area_name(rift)]. \
|
||||
All personnel are hereby required to enter the rift by any means available.\n\n\
|
||||
[Gibberish("Retrieval of survivors will be conducted upon recovery of necessary facilities.", FALSE, 5)] \
|
||||
[Gibberish("Good luck--", FALSE, 25)]")
|
||||
return rift
|
||||
|
||||
/// Announce the destruction of the rift and end the round.
|
||||
/datum/sm_delam/proc/effect_evac_rift_end()
|
||||
priority_announce("[Gibberish("The rift has been destroyed, we can no longer help you.", FALSE, 5)]")
|
||||
|
||||
sleep(25 SECONDS)
|
||||
|
||||
priority_announce("Reports indicate formation of crystalline seeds following resonance shift event. \
|
||||
Rapid expansion of crystal mass proportional to rising gravitational force. \
|
||||
Matter collapse due to gravitational pull foreseeable.",
|
||||
"Nanotrasen Star Observation Association")
|
||||
|
||||
sleep(25 SECONDS)
|
||||
|
||||
priority_announce("[Gibberish("All attempts at evacuation have now ceased, and all assets have been retrieved from your sector.\n \
|
||||
To the remaining survivors of [station_name()], farewell.", FALSE, 5)]")
|
||||
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
|
||||
// special message for hijacks
|
||||
var/shuttle_msg = "Navigation protocol set to [SSshuttle.emergency.is_hijacked() ? "\[ERROR\]" : "backup route"]. \
|
||||
Reorienting bluespace vessel to exit vector. ETA 15 seconds."
|
||||
// garble the special message
|
||||
if(SSshuttle.emergency.is_hijacked())
|
||||
shuttle_msg = Gibberish(shuttle_msg, TRUE, 15)
|
||||
minor_announce(shuttle_msg, "Emergency Shuttle", TRUE)
|
||||
SSshuttle.emergency.setTimer(15 SECONDS)
|
||||
return
|
||||
|
||||
sleep(10 SECONDS)
|
||||
|
||||
SSticker.news_report = SUPERMATTER_CASCADE
|
||||
SSticker.force_ending = TRUE
|
||||
|
||||
/// Scatters crystal mass over the event spawns as long as they are at least 30 tiles away from whatever we want to avoid.
|
||||
/datum/sm_delam/proc/effect_crystal_mass(obj/machinery/power/supermatter_crystal/sm, avoid)
|
||||
new /obj/crystal_mass(get_turf(sm))
|
||||
var/list/possible_spawns = GLOB.generic_event_spawns.Copy()
|
||||
for(var/i in 1 to rand(4,6))
|
||||
var/spawn_location
|
||||
do
|
||||
spawn_location = pick_n_take(possible_spawns)
|
||||
while(get_dist(spawn_location, avoid) < 30)
|
||||
new /obj/crystal_mass(get_turf(spawn_location))
|
||||
@@ -39,7 +39,7 @@
|
||||
has_been_powered = TRUE
|
||||
else if(takes_damage)
|
||||
damage += (projectile.damage * bullet_energy) * clamp((emergency_point - damage) / emergency_point, 0, 1)
|
||||
if(damage > damage_penalty_point)
|
||||
if(damage > danger_point)
|
||||
visible_message(span_notice("[src] compresses under stress, resisting further impacts!"))
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
if(istype(item, /obj/item/destabilizing_crystal))
|
||||
var/obj/item/destabilizing_crystal/destabilizing_crystal = item
|
||||
|
||||
if(!anomaly_event)
|
||||
if(!is_main_engine)
|
||||
to_chat(user, span_warning("You can't use \the [destabilizing_crystal] on \a [name]."))
|
||||
return
|
||||
|
||||
@@ -102,11 +102,9 @@
|
||||
log_game("[key_name(user)] attached [destabilizing_crystal] to the supermatter at [AREACOORD(src)]")
|
||||
investigate_log("[key_name(user)] attached [destabilizing_crystal] to a supermatter crystal.", INVESTIGATE_ENGINE)
|
||||
to_chat(user, span_danger("\The [destabilizing_crystal] snaps onto \the [src]."))
|
||||
has_destabilizing_crystal = TRUE
|
||||
cascade_initiated = TRUE
|
||||
set_delam(SM_DELAM_PRIO_IN_GAME, /datum/sm_delam/cascade)
|
||||
damage += 100
|
||||
matter_power += 500
|
||||
addtimer(CALLBACK(src, .proc/announce_incoming_cascade), 2 MINUTES)
|
||||
qdel(destabilizing_crystal)
|
||||
return
|
||||
|
||||
|
||||
@@ -20,13 +20,12 @@
|
||||
//Ok, get the air from the turf
|
||||
var/datum/gas_mixture/env = local_turf.return_air()
|
||||
environment_total_moles = env.total_moles()
|
||||
var/datum/gas_mixture/removed
|
||||
if(produces_gas)
|
||||
//Remove gas from surrounding area
|
||||
removed = env.remove(gasefficency * env.total_moles())
|
||||
absorbed_gasmix = env.remove(absorption_ratio * env.total_moles())
|
||||
else
|
||||
// Pass all the gas related code an empty gas container
|
||||
removed = new()
|
||||
absorbed_gasmix = new()
|
||||
overlays -= psyOverlay
|
||||
if(psy_overlay)
|
||||
overlays -= psyOverlay
|
||||
@@ -36,61 +35,38 @@
|
||||
else
|
||||
psy_overlay = FALSE
|
||||
damage_archived = damage
|
||||
if(!removed || !removed.total_moles() || isspaceturf(local_turf)) //we're in space or there is no gas to process
|
||||
if(!absorbed_gasmix || !absorbed_gasmix.total_moles() || isspaceturf(local_turf)) //we're in space or there is no gas to process
|
||||
if(takes_damage)
|
||||
damage += max((power / 1000) * DAMAGE_INCREASE_MULTIPLIER, 0.1) // always does at least some damage
|
||||
if(!istype(env, /datum/gas_mixture/immutable) && produces_gas && power) //There is no gas to process, but we are not in a space turf. Lets make them.
|
||||
//Power * 0.55 * a value between 1 and 0.8
|
||||
var/device_energy = power * REACTION_POWER_MODIFIER * (1 - (psyCoeff * 0.2))
|
||||
//Can't do stuff if it's null, so lets make a new gasmix.
|
||||
removed = new()
|
||||
absorbed_gasmix = new()
|
||||
//Since there is no gas to process, we will produce as if heat penalty is 1 and temperature at TCMB.
|
||||
removed.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
|
||||
removed.temperature = ((device_energy) / THERMAL_RELEASE_MODIFIER)
|
||||
removed.temperature = max(TCMB, min(removed.temperature, 2500))
|
||||
removed.gases[/datum/gas/plasma][MOLES] = max((device_energy) / PLASMA_RELEASE_MODIFIER, 0)
|
||||
removed.gases[/datum/gas/oxygen][MOLES] = max(((device_energy + TCMB) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)
|
||||
removed.garbage_collect()
|
||||
env.merge(removed)
|
||||
absorbed_gasmix.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
|
||||
absorbed_gasmix.temperature = ((device_energy) / THERMAL_RELEASE_MODIFIER)
|
||||
absorbed_gasmix.temperature = max(TCMB, min(absorbed_gasmix.temperature, 2500))
|
||||
absorbed_gasmix.gases[/datum/gas/plasma][MOLES] = max((device_energy) / PLASMA_RELEASE_MODIFIER, 0)
|
||||
absorbed_gasmix.gases[/datum/gas/oxygen][MOLES] = max(((device_energy + TCMB) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)
|
||||
absorbed_gasmix.garbage_collect()
|
||||
env.merge(absorbed_gasmix)
|
||||
air_update_turf(FALSE, FALSE)
|
||||
else
|
||||
if(takes_damage)
|
||||
//causing damage
|
||||
deal_damage(removed)
|
||||
deal_damage(absorbed_gasmix)
|
||||
|
||||
//registers the current enviromental gases in the various lists and vars
|
||||
setup_lists(removed)
|
||||
setup_lists(absorbed_gasmix)
|
||||
//some gases can have special interactions
|
||||
special_gases_interactions(env, removed)
|
||||
special_gases_interactions(env, absorbed_gasmix)
|
||||
//main power calculations proc
|
||||
power_calculations(env, removed)
|
||||
power_calculations(env, absorbed_gasmix)
|
||||
//irradiate at this point
|
||||
emit_radiation()
|
||||
//handles temperature increase and gases made by the crystal
|
||||
temperature_gas_production(env, removed)
|
||||
|
||||
var/cascading = check_cascade_requirements()
|
||||
if(cascading)
|
||||
if(!cascade_initiated)
|
||||
addtimer(CALLBACK(src, .proc/announce_incoming_cascade), 2 MINUTES, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
log_game("[src] has begun a cascade.")
|
||||
message_admins("[src] has begun a cascade, reasons: [cascading]. [ADMIN_JMP(src)]")
|
||||
investigate_log("has begun a cascade, reasons: [cascading].", INVESTIGATE_ENGINE)
|
||||
cascade_initiated = TRUE
|
||||
if(!warp)
|
||||
warp = new(src)
|
||||
vis_contents += warp
|
||||
animate(warp, time = 1, transform = matrix().Scale(0.5,0.5))
|
||||
animate(time = 9, transform = matrix())
|
||||
else
|
||||
if(warp)
|
||||
vis_contents -= warp
|
||||
QDEL_NULL(warp)
|
||||
if(cascade_initiated)
|
||||
log_game("[src] has stopped its cascade.")
|
||||
message_admins("[src] has stopped its cascade. [ADMIN_JMP(src)]")
|
||||
investigate_log("has stopped its cascade.", INVESTIGATE_ENGINE)
|
||||
cascade_initiated = FALSE
|
||||
temperature_gas_production(env, absorbed_gasmix)
|
||||
|
||||
//handles hallucinations and the presence of a psychiatrist
|
||||
psychological_examination()
|
||||
@@ -105,16 +81,19 @@
|
||||
//After this point power is lowered
|
||||
//This wraps around to the begining of the function
|
||||
//Handle high power zaps/anomaly generation
|
||||
handle_high_power(removed)
|
||||
handle_high_power(absorbed_gasmix)
|
||||
|
||||
if(prob(15))
|
||||
supermatter_pull(loc, min(power/850, 3))//850, 1700, 2550
|
||||
|
||||
//Tells the engi team to get their butt in gear
|
||||
handle_emergency_alerts()
|
||||
if(damage == 0) // Clear any in game forced delams if on full health.
|
||||
set_delam(SM_DELAM_PRIO_IN_GAME, SM_DELAM_STRATEGY_PURGE)
|
||||
else
|
||||
set_delam() // This one cant clear any forced delams.
|
||||
delamination_strategy.delam_progress(src)
|
||||
|
||||
if(damage == 0 && has_destabilizing_crystal)
|
||||
has_destabilizing_crystal = FALSE
|
||||
if(damage > explosion_point && !final_countdown)
|
||||
count_down()
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -148,7 +127,7 @@
|
||||
has_holes = TRUE
|
||||
break
|
||||
|
||||
var/cascade_multiplier = cascade_initiated ? 0.25 : 1
|
||||
var/delam_damage_multipler = delamination_strategy.damage_multiplier(src)
|
||||
|
||||
//Due to DAMAGE_INCREASE_MULTIPLIER, we only deal one 4th of the damage the statements otherwise would cause
|
||||
//((((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
|
||||
@@ -156,9 +135,9 @@
|
||||
//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)
|
||||
//Power only starts affecting damage when it is above 5000 (1250 when a cascade is occurring)
|
||||
damage = max(damage + (max(power - (POWER_PENALTY_THRESHOLD * cascade_multiplier), 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
damage = max(damage + (max(power - (POWER_PENALTY_THRESHOLD * delam_damage_multipler), 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
//Molar count only starts affecting damage when it is above 1800 (450 when a cascade is occurring)
|
||||
damage = max(damage + (max(combined_gas - (MOLE_PENALTY_THRESHOLD * cascade_multiplier), 0)/80) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
damage = max(damage + (max(combined_gas - (MOLE_PENALTY_THRESHOLD * delam_damage_multipler), 0)/80) * DAMAGE_INCREASE_MULTIPLIER, 0)
|
||||
|
||||
//There might be a way to integrate healing and hurting via heat
|
||||
//healing damage
|
||||
@@ -360,7 +339,7 @@
|
||||
psyCoeff = clamp(psyCoeff + psy_coeff_diff, 0, 1)
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/handle_high_power(datum/gas_mixture/removed)
|
||||
if(power <= POWER_PENALTY_THRESHOLD && damage <= damage_penalty_point) //If the power is above 5000 or if the damage is above 550
|
||||
if(power <= POWER_PENALTY_THRESHOLD && damage <= danger_point) //If the power is above 5000 or if the damage is above 550
|
||||
return
|
||||
var/range = 4
|
||||
zap_cutoff = 1500
|
||||
@@ -390,7 +369,7 @@
|
||||
flags |= (ZAP_MOB_STUN | ZAP_MACHINE_EXPLOSIVE | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE)
|
||||
zap_count = 4
|
||||
//Now we deal with damage shit
|
||||
if (damage > damage_penalty_point && prob(20))
|
||||
if (damage > danger_point && prob(20))
|
||||
zap_count += 1
|
||||
|
||||
if(zap_count >= 1)
|
||||
@@ -407,59 +386,38 @@
|
||||
if((power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2)) || (prob(0.3) && power > POWER_PENALTY_THRESHOLD))
|
||||
supermatter_anomaly_gen(src, PYRO_ANOMALY, rand(5, 10))
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/handle_emergency_alerts()
|
||||
if(damage <= warning_point) // while the core is still damaged and it's still worth noting its status
|
||||
return
|
||||
if(damage_archived < warning_point) //If damage_archive is under the warning point, this is the very first cycle that we've reached said point.
|
||||
SEND_SIGNAL(src, COMSIG_SUPERMATTER_DELAM_START_ALARM)
|
||||
if((REALTIMEOFDAY - lastwarning) / 10 >= WARNING_DELAY)
|
||||
alarm()
|
||||
/**
|
||||
* Sets the delam of our sm.
|
||||
*
|
||||
* Arguments:
|
||||
* * priority: Truthy values means a forced delam. If current forced_delam is higher than priority we dont run.
|
||||
* Set to a number higher than [SM_DELAM_PRIO_IN_GAME] to fully force an admin delam.
|
||||
* * delam_path: Typepath of a [/datum/sm_delam]. [SM_DELAM_STRATEGY_PURGE] means reset and put prio back to zero.
|
||||
*
|
||||
* Returns: Not used for anything, just returns true on succesful set, manual and automatic. Helps admins check stuffs.
|
||||
*/
|
||||
/obj/machinery/power/supermatter_crystal/proc/set_delam(priority = SM_DELAM_PRIO_NONE, manual_delam_path = SM_DELAM_STRATEGY_PURGE)
|
||||
if(priority < delam_priority)
|
||||
return FALSE
|
||||
var/datum/sm_delam/new_delam = null
|
||||
|
||||
//Oh shit it's bad, time to freak out
|
||||
if(damage > emergency_point)
|
||||
radio.talk_into(src, "[emergency_alert] Integrity: [get_integrity_percent()]%", common_channel)
|
||||
SEND_SIGNAL(src, COMSIG_SUPERMATTER_DELAM_ALARM)
|
||||
lastwarning = REALTIMEOFDAY
|
||||
if(!has_reached_emergency)
|
||||
investigate_log("has reached the emergency point for the first time.", INVESTIGATE_ENGINE)
|
||||
message_admins("[src] has reached the emergency point [ADMIN_JMP(src)].")
|
||||
has_reached_emergency = TRUE
|
||||
else if(damage >= damage_archived) // The damage is still going up
|
||||
radio.talk_into(src, "[warning_alert] Integrity: [get_integrity_percent()]%", engineering_channel)
|
||||
SEND_SIGNAL(src, COMSIG_SUPERMATTER_DELAM_ALARM)
|
||||
lastwarning = REALTIMEOFDAY - (WARNING_DELAY * 5)
|
||||
if(manual_delam_path == SM_DELAM_STRATEGY_PURGE)
|
||||
for (var/delam_path in GLOB.sm_delam_list)
|
||||
var/datum/sm_delam/delam = GLOB.sm_delam_list[delam_path]
|
||||
if(!delam.can_select(src))
|
||||
continue
|
||||
if(delam == delamination_strategy)
|
||||
return FALSE
|
||||
new_delam = delam
|
||||
break
|
||||
delam_priority = SM_DELAM_PRIO_NONE
|
||||
else
|
||||
new_delam = GLOB.sm_delam_list[manual_delam_path]
|
||||
delam_priority = priority
|
||||
|
||||
else // Phew, we're safe
|
||||
radio.talk_into(src, "[safe_alert] Integrity: [get_integrity_percent()]%", engineering_channel)
|
||||
lastwarning = REALTIMEOFDAY
|
||||
|
||||
if(power > POWER_PENALTY_THRESHOLD)
|
||||
radio.talk_into(src, "Warning: Hyperstructure has reached dangerous power level.", engineering_channel)
|
||||
if(powerloss_inhibitor < 0.5)
|
||||
radio.talk_into(src, "DANGER: CHARGE INERTIA CHAIN REACTION IN PROGRESS.", engineering_channel)
|
||||
|
||||
if(combined_gas > MOLE_PENALTY_THRESHOLD)
|
||||
radio.talk_into(src, "Warning: Critical coolant mass reached.", engineering_channel)
|
||||
|
||||
if(check_cascade_requirements())
|
||||
var/channel_to_talk_to = damage > emergency_point ? common_channel : engineering_channel
|
||||
radio.talk_into(src, "DANGER: HYPERSTRUCTURE OSCILLATION FREQUENCY OUT OF BOUNDS.", channel_to_talk_to)
|
||||
for(var/mob/victim as anything in GLOB.player_list)
|
||||
var/list/messages = list(
|
||||
"Space seems to be shifting around you...",
|
||||
"You hear a high-pitched ringing sound.",
|
||||
"You feel tingling going down your back.",
|
||||
"Something feels very off.",
|
||||
"A drowning sense of dread washes over you."
|
||||
)
|
||||
to_chat(victim, span_danger(pick(messages)))
|
||||
|
||||
//Boom (Mind blown)
|
||||
if(damage > explosion_point)
|
||||
countdown()
|
||||
|
||||
/obj/machinery/power/supermatter_crystal/proc/announce_incoming_cascade()
|
||||
if(check_cascade_requirements())
|
||||
priority_announce("Attention: Long range anomaly scans indicate abnormal quantities of harmonic flux originating from \
|
||||
a subject within [station_name()], a resonance collapse may occur.",
|
||||
"Nanotrasen Star Observation Association")
|
||||
if(!new_delam)
|
||||
return FALSE
|
||||
delamination_strategy?.on_deselect(src)
|
||||
delamination_strategy = new_delam
|
||||
delamination_strategy.on_select(src)
|
||||
return TRUE
|
||||
|
||||
+5
-2
@@ -3967,11 +3967,14 @@
|
||||
#include "code\modules\power\singularity\narsie.dm"
|
||||
#include "code\modules\power\singularity\singularity.dm"
|
||||
#include "code\modules\power\supermatter\supermatter.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_cascade_components.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_delamination.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_hit_procs.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_process.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_radiation.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_delamination\_sm_delam.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_delamination\cascade_delam.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_delamination\cascade_delam_objects.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_delamination\common_delams.dm"
|
||||
#include "code\modules\power\supermatter\supermatter_delamination\delamination_effects.dm"
|
||||
#include "code\modules\power\tesla\coil.dm"
|
||||
#include "code\modules\power\tesla\energy_ball.dm"
|
||||
#include "code\modules\power\turbine\turbine.dm"
|
||||
|
||||
Reference in New Issue
Block a user