diff --git a/code/modules/events/apc_overload.dm b/code/modules/events/apc_overload.dm new file mode 100644 index 00000000000..a773e71a173 --- /dev/null +++ b/code/modules/events/apc_overload.dm @@ -0,0 +1,63 @@ +#define APC_BREAK_PROBABILITY 25 // the probability that a given APC will be broken + +/datum/event/apc_overload + var/const/announce_after_mc_ticks = 5 + var/const/delayed = FALSE + var/const/event_max_duration_mc_ticks = announce_after_mc_ticks * 2 + var/const/event_min_duration_mc_ticks = announce_after_mc_ticks + + announceWhen = announce_after_mc_ticks + +/datum/event/apc_overload/setup() + endWhen = rand(event_min_duration_mc_ticks, event_max_duration_mc_ticks) + +/datum/event/apc_overload/start() + apc_overload_failure(announce=delayed) + var/sound/S = sound('sound/effects/powerloss.ogg') + for(var/mob/living/M in GLOB.player_list) + var/turf/T = get_turf(M) + if(!M.client || !is_station_level(T.z)) + continue + SEND_SOUND(M, S) + +/datum/event/apc_overload/announce() + GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", new_sound = 'sound/AI/apc_overload.ogg') + +/datum/event/apc_overload/end() + return TRUE + +/proc/apc_overload_failure(announce=TRUE) + var/list/skipped_areas_apc = list( + /area/engine/engineering, + /area/turret_protected/ai) + + if(announce) + GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", new_sound = 'sound/AI/apc_overload.ogg') + + // break APC_BREAK_PROBABILITY% of all of the APCs on the station + var/affected_apc_count = 0 + for(var/obj/machinery/power/apc/C in GLOB.apcs) + // skip any APCs that are too critical to break + var/area/current_area = get_area(C) + if((current_area.type in skipped_areas_apc) || !is_station_level(C.z)) + continue + // if we are going to break this one + if(prob(APC_BREAK_PROBABILITY)) + // if it has a cell, drain all the charge from the cell + if(C.cell) + C.cell.charge = 0 + // if it has a terminal, disconnect and delete the terminal + if(C.terminal) + var/obj/machinery/power/terminal/T = C.terminal + C.terminal.master = null + C.terminal = null + qdel(T) + // if it was operating, toggle off the breaker + if(C.operating) + C.toggle_breaker() + // no matter what, ensure the area knows something happened to the power + current_area.power_change() + affected_apc_count++ + log_and_message_admins("APC Overload event deleted [affected_apc_count] underfloor APC terminals.") + +#undef APC_BREAK_PROBABILITY diff --git a/code/modules/events/apc_short.dm b/code/modules/events/apc_short.dm new file mode 100644 index 00000000000..b128fe6c2e9 --- /dev/null +++ b/code/modules/events/apc_short.dm @@ -0,0 +1,78 @@ +#define APC_BREAK_PROBABILITY 25 // the probability that a given APC will be disabled + +/datum/event/apc_short + var/const/announce_after_mc_ticks = 5 + var/const/delayed = FALSE + var/const/event_max_duration_mc_ticks = announce_after_mc_ticks * 2 + var/const/event_min_duration_mc_ticks = announce_after_mc_ticks + + announceWhen = announce_after_mc_ticks + +/datum/event/apc_short/setup() + endWhen = rand(event_min_duration_mc_ticks, event_max_duration_mc_ticks) + +/datum/event/apc_short/start() + power_failure(announce=delayed) + var/sound/S = sound('sound/effects/powerloss.ogg') + for(var/mob/living/M in GLOB.player_list) + var/turf/T = get_turf(M) + if(!M.client || !is_station_level(T.z)) + continue + SEND_SOUND(M, S) + +/datum/event/apc_short/announce() + GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", new_sound = 'sound/AI/apc_short.ogg') + +/datum/event/apc_short/end() + return TRUE + +/proc/power_failure(announce=TRUE) + var/list/skipped_areas_apc = list( + /area/engine/engineering, + /area/turret_protected/ai) + + if(announce) + GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", new_sound = 'sound/AI/apc_short.ogg') + + // break APC_BREAK_PROBABILITY% of all of the APCs on the station + var/affected_apc_count = 0 + for(var/obj/machinery/power/apc/C in GLOB.apcs) + // skip any APCs that are too critical to disable + var/area/current_area = get_area(C) + if((current_area.type in skipped_areas_apc) || !is_station_level(C.z)) + continue + // if we are going to break this one + if(prob(APC_BREAK_PROBABILITY)) + // if it has internal wires, cut the power wires + if(C.wires) + if(!C.wires.IsIndexCut(APC_WIRE_MAIN_POWER1)) + C.wires.CutWireIndex(APC_WIRE_MAIN_POWER1) + if(!C.wires.IsIndexCut(APC_WIRE_MAIN_POWER2)) + C.wires.CutWireIndex(APC_WIRE_MAIN_POWER2) + // if it was operating, toggle off the breaker + if(C.operating) + C.toggle_breaker() + // no matter what, ensure the area knows something happened to the power + current_area.power_change() + affected_apc_count++ + log_and_message_admins("APC Short event shorted out [affected_apc_count] APCs.") + +/proc/power_restore(announce=TRUE) + power_restore_quick(announce) + +/proc/power_restore_quick(announce=TRUE) + if(announce) + GLOB.event_announcement.Announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg') + + // fix all of the SMESs + for(var/obj/machinery/power/smes/S in GLOB.machines) + if(!is_station_level(S.z)) + continue + S.charge = S.capacity + S.output_level = S.output_level_max + S.output_attempt = 1 + S.input_attempt = 1 + S.update_icon() + S.power_change() + +#undef APC_BREAK_PROBABILITY diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 9c744b8060a..908bc762315 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -128,7 +128,7 @@ GLOBAL_LIST_EMPTY(event_last_fired) /datum/event_container/mundane severity = EVENT_LEVEL_MUNDANE available_events = list( - // Severity level, event name, even type, base weight, role weights, one shot, min weight, max weight. Last two only used if set and non-zero + // Severity level, event name, event type, base weight, role weights, one shot, min weight, max weight. Last two only used if set and non-zero new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Nothing", /datum/event/nothing, 1100), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "PDA Spam", /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), 0, 25, 50), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 1, 5, 15), @@ -157,7 +157,7 @@ GLOBAL_LIST_EMPTY(event_last_fired) new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)), //new /datum/event_meta(EVENT_LEVEL_MODERATE, "Virology Breach", /datum/event/prison_break/virology, 0, list(ASSIGNMENT_MEDICAL = 100)), //new /datum/event_meta(EVENT_LEVEL_MODERATE, "Xenobiology Breach", /datum/event/prison_break/xenobiology, 0, list(ASSIGNMENT_SCIENCE = 100)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_ENGINEER = 60)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "APC Short", /datum/event/apc_short, 200, list(ASSIGNMENT_ENGINEER = 60)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 25, list(ASSIGNMENT_MEDICAL = 50), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1), @@ -191,6 +191,7 @@ GLOBAL_LIST_EMPTY(event_last_fired) new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 1320), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 3), 1), //new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ANY = 5)), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "APC Overload", /datum/event/apc_overload, 0), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 30), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 5), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Abductor Visit", /datum/event/abductor, 80, is_one_shot = 1), diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm deleted file mode 100644 index 8da2a6d707e..00000000000 --- a/code/modules/events/grid_check.dm +++ /dev/null @@ -1,82 +0,0 @@ -/datum/event/grid_check //NOTE: Times are measured in master controller ticks! - announceWhen = 5 - -/datum/event/grid_check/setup() - endWhen = rand(30,120) - -/datum/event/grid_check/start() - power_failure(0) - var/sound/S = sound('sound/effects/powerloss.ogg') - for(var/mob/living/M in GLOB.player_list) - var/turf/T = get_turf(M) - if(!M.client || !is_station_level(T.z)) - continue - SEND_SOUND(M, S) - -/datum/event/grid_check/announce() - GLOB.event_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Automated Grid Check", new_sound = 'sound/AI/poweroff.ogg') - -/datum/event/grid_check/end() - power_restore() - -/proc/power_failure(var/announce = 1) - if(announce) - GLOB.event_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", new_sound = 'sound/AI/poweroff.ogg') - - var/list/skipped_areas = list(/area/turret_protected/ai) - var/list/skipped_areas_apc = list(/area/engine/engineering) - - for(var/obj/machinery/power/smes/S in GLOB.machines) - var/area/current_area = get_area(S) - if((current_area.type in skipped_areas) || !is_station_level(S.z)) - continue - S.last_charge = S.charge - S.last_output_attempt = S.output_attempt - S.last_input_attempt = S.input_attempt - S.charge = 0 - S.inputting(0) - S.outputting(0) - S.update_icon() - S.power_change() - - for(var/obj/machinery/power/apc/C in GLOB.apcs) - var/area/current_area = get_area(C) - if((current_area.type in skipped_areas_apc) || !is_station_level(C.z)) - continue - if(C.cell) - C.cell.charge = 0 - -/proc/power_restore(var/announce = 1) - var/list/skipped_areas = list(/area/turret_protected/ai) - var/list/skipped_areas_apc = list(/area/engine/engineering) - - if(announce) - GLOB.event_announcement.Announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg') - for(var/obj/machinery/power/apc/C in GLOB.apcs) - var/area/current_area = get_area(C) - if((current_area.type in skipped_areas_apc) || !is_station_level(C.z)) - continue - if(C.cell) - C.cell.charge = C.cell.maxcharge - for(var/obj/machinery/power/smes/S in GLOB.machines) - var/area/current_area = get_area(S) - if((current_area.type in skipped_areas) || !is_station_level(S.z)) - continue - S.charge = S.last_charge - S.output_attempt = S.last_output_attempt - S.input_attempt = S.last_input_attempt - S.update_icon() - S.power_change() - -/proc/power_restore_quick(var/announce = 1) - if(announce) - GLOB.event_announcement.Announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg') - for(var/obj/machinery/power/smes/S in GLOB.machines) - if(!is_station_level(S.z)) - continue - S.charge = S.capacity - S.output_level = S.output_level_max - S.output_attempt = 1 - S.input_attempt = 1 - S.update_icon() - S.power_change() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 89988ec9f55..234b885284e 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -244,7 +244,7 @@ else if(has_electronics && !terminal) . += "Electronics installed but not wired." else /* if(!has_electronics && !terminal) */ - . += "There is no electronics nor connected wires." + . += "There are no electronics nor connected wires." else if(stat & MAINT) . += "The cover is closed. Something wrong with it: it doesn't work." diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index f2e8fa53a8d..f88128ab974 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -29,11 +29,6 @@ var/output_level_max = 200000 // cap on output_level var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power - //Holders for powerout event. - var/last_output_attempt = 0 - var/last_input_attempt = 0 - var/last_charge = 0 - var/name_tag = null var/obj/machinery/power/terminal/terminal = null diff --git a/paradise.dme b/paradise.dme index c3dcfbd3c2d..f2dbf198ebd 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1485,7 +1485,8 @@ #include "code\modules\events\event_procs.dm" #include "code\modules\events\false_alarm.dm" #include "code\modules\events\floorcluwne.dm" -#include "code\modules\events\grid_check.dm" +#include "code\modules\events\apc_overload.dm" +#include "code\modules\events\apc_short.dm" #include "code\modules\events\headcrabs.dm" #include "code\modules\events\immovable_rod.dm" #include "code\modules\events\infestation.dm" diff --git a/sound/AI/apc_overload.ogg b/sound/AI/apc_overload.ogg new file mode 100644 index 00000000000..ef9357b9eb6 Binary files /dev/null and b/sound/AI/apc_overload.ogg differ diff --git a/sound/AI/apc_short.ogg b/sound/AI/apc_short.ogg new file mode 100644 index 00000000000..90afc50f6fb Binary files /dev/null and b/sound/AI/apc_short.ogg differ