From f27399bcd526d2b1f1fec7330284e7c39463c447 Mon Sep 17 00:00:00 2001 From: "petethegoat@gmail.com" Date: Thu, 10 Jan 2013 23:45:57 +0000 Subject: [PATCH] Added a new events system! The old one still exists, mainly so the associated admin buttons still work. At some point I'll add a nice little panel for event stuff and remove the old procs. event.dm is pretty well commented, and it should be pretty easy to figure it out. Casualties of the change are space dust (which should probably be implemented separately if we want it back), the black hole event (which was awful), space ninjas (which didn't turn up), ionstorms (the non-admin ones sucked anyway) and CLANG, which I will probably add at some point, if no one else does first. Also, I removed pierott's throat from the disease outbreak list. f that s. Thanks to Sukasa and BS12, as my system is loosely based off of theirs. Thanks Giacom for help with structuring and especially commenting this. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@5511 316c924e-a436-60f5-8080-3fe189b3f50e --- code/controllers/master_controller.dm | 17 +++- code/game/gamemodes/gameticker.dm | 3 +- code/global.dm | 1 + code/modules/events/alien_infestation.dm | 32 ++++++++ code/modules/events/blob.dm | 25 ++++++ code/modules/events/carp_migration.dm | 14 ++++ .../modules/events/communications_blackout.dm | 17 ++++ code/modules/events/disease_outbreak.dm | 44 ++++++++++ code/modules/events/electrical_storm.dm | 28 +++++++ code/modules/events/event.dm | 82 +++++++++++++++++++ code/modules/events/event_manager.dm | 39 +++++++++ code/modules/events/meteor_wave.dm | 12 +++ code/modules/events/prison_break.dm | 46 +++++++++++ code/modules/events/radiation_storm.dm | 37 +++++++++ code/modules/events/spacevine.dm | 5 ++ .../events/spontaneous_appendicitis.dm | 13 +++ tgstation.dme | 13 +++ 17 files changed, 426 insertions(+), 2 deletions(-) create mode 100644 code/modules/events/alien_infestation.dm create mode 100644 code/modules/events/blob.dm create mode 100644 code/modules/events/carp_migration.dm create mode 100644 code/modules/events/communications_blackout.dm create mode 100644 code/modules/events/disease_outbreak.dm create mode 100644 code/modules/events/electrical_storm.dm create mode 100644 code/modules/events/event.dm create mode 100644 code/modules/events/event_manager.dm create mode 100644 code/modules/events/meteor_wave.dm create mode 100644 code/modules/events/prison_break.dm create mode 100644 code/modules/events/radiation_storm.dm create mode 100644 code/modules/events/spacevine.dm create mode 100644 code/modules/events/spontaneous_appendicitis.dm diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index c2ba3db8151..8cafa13345a 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -21,6 +21,7 @@ datum/controller/game_controller var/objects_cost = 0 var/networks_cost = 0 var/powernets_cost = 0 + var/events_cost = 0 var/ticker_cost = 0 var/total_cost = 0 @@ -218,6 +219,20 @@ datum/controller/game_controller/proc/process() sleep(breather_ticks) + //EVENTS + timer = world.timeofday + last_thing_processed = /datum/event + i = 1 + while(i<=events.len) + var/datum/event/Event = events[i] + if(Event) + Event.process() + i++ + continue + events.Cut(i,i+1) + checkEvent() + events_cost = (world.timeofday - timer) / 10 + //TICKER timer = world.timeofday last_thing_processed = ticker.type @@ -225,7 +240,7 @@ datum/controller/game_controller/proc/process() ticker_cost = (world.timeofday - timer) / 10 //TIMING - total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + objects_cost + networks_cost + powernets_cost + ticker_cost + total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + objects_cost + networks_cost + powernets_cost + events_cost + ticker_cost var/end_time = world.timeofday if(end_time < start_time) diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 4183ac322da..df1674f3152 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -122,7 +122,8 @@ var/global/datum/controller/gameticker/ticker //Holiday Round-start stuff ~Carn Holiday_Game_Start() - start_events() //handles random events and space dust. +// start_events() //handles random events and space dust. +//new random event system is handled from the MC. var/admins_number = 0 for(var/client/C) diff --git a/code/global.dm b/code/global.dm index cd9570b5d87..e887fea82f0 100644 --- a/code/global.dm +++ b/code/global.dm @@ -9,6 +9,7 @@ var/global/obj/effect/overlay/slmaster = null var/global/list/machines = list() var/global/list/processing_objects = list() var/global/list/active_diseases = list() +var/global/list/events = list() //items that ask to be called every cycle var/global/defer_powernet_rebuild = 0 // true if net rebuild will be called manually after an event diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm new file mode 100644 index 00000000000..1a0cb0d220b --- /dev/null +++ b/code/modules/events/alien_infestation.dm @@ -0,0 +1,32 @@ +/datum/event/alien_infestation + announceWhen = 75 + endWhen = 75 + oneShot = 1 + + var/spawncount = 1 + +/datum/event/alien_infestation/announce() + command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") + world << sound('sound/AI/aliens.ogg') + + +/datum/event/alien_infestation/start() + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) + if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network) + if(temp_vent.network.normal_members.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology + vents += temp_vent + + var/list/candidates = get_alien_candidates() + + if(prob(50)) spawncount++ //sometimes, have two larvae spawn instead of one + while((spawncount >= 1) && vents.len && candidates.len) + var/obj/vent = pick(vents) + var/candidate = pick(candidates) + + var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc) + new_xeno.key = candidate + + candidates -= candidate + vents -= vent + spawncount-- \ No newline at end of file diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm new file mode 100644 index 00000000000..9766757d29a --- /dev/null +++ b/code/modules/events/blob.dm @@ -0,0 +1,25 @@ +/datum/event/blob + announceWhen = 12 + endWhen = 120 + + var/obj/effect/blob/core/Blob + + +/datum/event/blob/announce() + command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") + world << sound('sound/AI/outbreak5.ogg') + + +/datum/event/blob/start() + var/turf/T = pick(blobstart) + if(!T) kill() + Blob = new /obj/effect/blob/core(T, 200) + Blob.Life() + Blob.Life() + Blob.Life() + + +/datum/event/blob/tick() + if(!Blob) kill() + if(IsMultiple(activeFor, 3)) + Blob.Life() \ No newline at end of file diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm new file mode 100644 index 00000000000..e6c9a34dde2 --- /dev/null +++ b/code/modules/events/carp_migration.dm @@ -0,0 +1,14 @@ +/datum/event/carp_migration + announceWhen = 50 + endWhen = 50 + oneShot = 1 + + +/datum/event/carp_migration/announce() + command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") + + +/datum/event/carp_migration/start() + for(var/obj/effect/landmark/C in landmarks_list) + if(C.name == "carpspawn") + new /mob/living/simple_animal/hostile/carp(C.loc) \ No newline at end of file diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm new file mode 100644 index 00000000000..18d0c13f979 --- /dev/null +++ b/code/modules/events/communications_blackout.dm @@ -0,0 +1,17 @@ +/datum/event/communications_blackout + var/silent = 1 //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts. + +/datum/event/communications_blackout/announce() + if(!silent) + command_alert("Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT") + + +/datum/event/communications_blackout/start() + if(prob(25)) + silent = 0 + for(var/mob/living/silicon/ai/A in player_list) //AIs are always aware of communication blackouts. + A << "
" + A << "Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT" + A << "
" + for(var/obj/machinery/telecomms/T in telecomms_list) + T.emp_act(1) \ No newline at end of file diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm new file mode 100644 index 00000000000..9e035a8e274 --- /dev/null +++ b/code/modules/events/disease_outbreak.dm @@ -0,0 +1,44 @@ +/datum/event/disease_outbreak + announceWhen = 15 + endWhen = 15 + oneShot = 1 + + +/datum/event/disease_outbreak/announce() + command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") + world << sound('sound/AI/outbreak7.ogg') + +/datum/event/disease_outbreak/start() + var/virus_type = pick(/datum/disease/dnaspread, /datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis) + + for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) + var/foundAlready = 0 // don't infect someone that already has the virus + var/turf/T = get_turf(H) + if(!T) + continue + if(T.z != 1) + continue + for(var/datum/disease/D in H.viruses) + foundAlready = 1 + if(H.stat == 2 || foundAlready) + continue + + if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work. + if((!H.dna) || (H.sdisabilities & BLIND)) //A blindness disease would be the worst. + continue + var/datum/disease/dnaspread/D = new + D.strain_data["name"] = H.real_name + D.strain_data["UI"] = H.dna.uni_identity + D.strain_data["SE"] = H.dna.struc_enzymes + D.carrier = 1 + D.holder = H + D.affected_mob = H + H.viruses += D + break + else + var/datum/disease/D = new virus_type + D.carrier = 1 + D.holder = H + D.affected_mob = H + H.viruses += D + break \ No newline at end of file diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm new file mode 100644 index 00000000000..dacaa09c47a --- /dev/null +++ b/code/modules/events/electrical_storm.dm @@ -0,0 +1,28 @@ +/datum/event/electrical_storm + var/lightsoutAmount = 1 + var/lightsoutRange = 25 + + +/datum/event/electrical_storm/announce() + command_alert("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert") + + +/datum/event/electrical_storm/start() + var/list/epicentreList = list() + + for(var/i=1, i <= lightsoutAmount, i++) + var/list/possibleEpicentres = list() + for(var/obj/effect/landmark/newEpicentre in landmarks_list) + if(newEpicentre.name == "lightsout" && !(newEpicentre in epicentreList)) + possibleEpicentres += newEpicentre + if(possibleEpicentres.len) + epicentreList += pick(possibleEpicentres) + else + break + + if(!epicentreList.len) + return + + for(var/obj/effect/landmark/epicentre in epicentreList) + for(var/obj/machinery/power/apc/apc in range(epicentre,lightsoutRange)) + apc.overload_lighting() \ No newline at end of file diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm new file mode 100644 index 00000000000..b6c64b89aac --- /dev/null +++ b/code/modules/events/event.dm @@ -0,0 +1,82 @@ +/datum/event //NOTE: Times are measured in master controller ticks! + var/startWhen = 0 //When in the lifetime to call start(). + var/announceWhen = 0 //When in the lifetime to call announce(). + var/endWhen = 0 //When in the lifetime the event should end. Include time for delayed announcements. + var/oneShot = 0 //If true, then the event removes itself from the list of potential events on creation. + + var/activeFor = 0 //How long the event has existed. You don't need to change this. + + + + +//Called when the tick is equal to the startWhen variable. +//Allows you to announce before starting or vice versa. +//Only called once. +/datum/event/proc/start() + return + +//Called when the tick is equal to the announceWhen variable. +//Allows you to start before announcing or vice versa. +//Only called once. +/datum/event/proc/announce() + return + +//Called on or after the tick counter is equal to startWhen. +//You can include code related to your event or add your own +//time stamped events. +//Called more than once. +/datum/event/proc/tick() + return + +//Called on or after the tick is equal or more than endWhen +//You can include code related to the event ending. +//Do not place spawn() in here, instead use tick() to check for +//the activeFor variable. +//For example: if(activeFor == myOwnVariable + 30) doStuff() +//Only called once. +/datum/event/proc/end() + return + + + + +//Do not override this proc, instead use the appropiate procs. +//This proc will handle the calls to the appropiate procs. +/datum/event/proc/process() + if(activeFor == startWhen) + start() + + if(activeFor > startWhen) + tick() + + if(activeFor == announceWhen) + announce() + + if(activeFor >= endWhen) + end() + kill() + + activeFor++ + + +//Garbage collects the event by removing it from the global events list, +//which should be the only place it's referenced. +/datum/event/proc/kill() + events.Remove(src) + + +//Adds the event to the global events list, and removes it from the list +//of potential events. +/datum/event/New() + events.Add(src) + + if(oneShot) + potentialRandomEvents.Remove(type) + + +//This shouldn't be called, but it ensures that the event doesn't persist in +//the events list if it'd deleted instead of garbage collected with kill(). +//The master controller will also remove it from the events list if it +//doesn't exist, so there's redundancy here. +/datum/event/Del() + events.Remove(src) \ No newline at end of file diff --git a/code/modules/events/event_manager.dm b/code/modules/events/event_manager.dm new file mode 100644 index 00000000000..78e89cac7e8 --- /dev/null +++ b/code/modules/events/event_manager.dm @@ -0,0 +1,39 @@ +var/list/allEvents = typesof(/datum/event) - /datum/event +var/list/potentialRandomEvents = typesof(/datum/event) - /datum/event + +var/eventTimeLower = 5000 +var/eventTimeUpper = 10000 + +var/scheduledEvent = null + + +//Currently unused. Needs an admin panel for messing with events. +/proc/addPotentialEvent(var/type) + potentialRandomEvents |= type + +/proc/removePotentialEvent(var/type) + potentialRandomEvents -= type + + +/proc/checkEvent() + if(!scheduledEvent) + scheduledEvent = world.timeofday + rand(eventTimeLower, eventTimeUpper) + + else if(world.timeofday > scheduledEvent) + spawnEvent() + + scheduledEvent = null + checkEvent() + + +/proc/spawnEvent() + if(!config.allow_random_events) + return + + var/Type = pick(potentialRandomEvents) + if(!Type) + return + + //The event will add itself to the MC's event list + //and start working via the constructor. + new Type \ No newline at end of file diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm new file mode 100644 index 00000000000..fb52bc0582d --- /dev/null +++ b/code/modules/events/meteor_wave.dm @@ -0,0 +1,12 @@ +/datum/event/meteor_wave + startWhen = 6 + endWhen = 66 + +/datum/event/meteor_wave/announce() + command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert") + world << sound('sound/AI/meteors.ogg') + + +/datum/event/meteor_wave/tick() + if(IsMultiple(activeFor, 3)) + spawn_meteors(5) \ No newline at end of file diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm new file mode 100644 index 00000000000..783dc6c8fb2 --- /dev/null +++ b/code/modules/events/prison_break.dm @@ -0,0 +1,46 @@ +/datum/event/prison_break + announceWhen = 50 + endWhen = 50 + oneShot = 1 + + var/releaseWhen = 25 + var/list/area/prisonAreas = list() + + +/datum/event/prison_break/announce() + if(prisonAreas && prisonAreas.len > 0) + command_alert("Gr3y.T1d3 virus detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") + else + world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area." + + +/datum/event/prison_break/start() + for(var/area/A in world) + if(istype(A, /area/security/prison) || istype(A, /area/security/brig)) + prisonAreas += A + + if(prisonAreas && prisonAreas.len > 0) + for(var/area/A in prisonAreas) + for(var/obj/machinery/light/L in A) + L.flicker(10) + + +/datum/event/prison_break/tick() + if(activeFor == releaseWhen) + if(prisonAreas && prisonAreas.len > 0) + for(var/area/A in prisonAreas) + for(var/obj/machinery/power/apc/temp_apc in A) + temp_apc.overload_lighting() + + for(var/obj/structure/closet/secure_closet/brig/temp_closet in A) + temp_closet.locked = 0 + temp_closet.icon_state = temp_closet.icon_closed + + for(var/obj/machinery/door/airlock/security/temp_airlock in A) + temp_airlock.prison_open() + + for(var/obj/machinery/door/airlock/glass_security/temp_glassairlock in A) + temp_glassairlock.prison_open() + + for(var/obj/machinery/door_timer/temp_timer in A) + temp_timer.releasetime = 1 \ No newline at end of file diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm new file mode 100644 index 00000000000..d709438428d --- /dev/null +++ b/code/modules/events/radiation_storm.dm @@ -0,0 +1,37 @@ +/datum/event/radiation_storm + announceWhen = 5 + endWhen = 5 + oneShot = 1 + + +/datum/event/radiation_storm/announce() + command_alert("High levels of radiation detected near the station. Please report to the Med-bay if you feel strange.", "Anomaly Alert") + world << sound('sound/AI/radiation.ogg') + + +/datum/event/radiation_storm/start() + for(var/mob/living/carbon/human/H in living_mob_list) + var/turf/T = get_turf(H) + if(!T) + continue + if(T.z != 1) + continue + if(istype(H,/mob/living/carbon/human)) + H.apply_effect((rand(15,75)),IRRADIATE,0) + if(prob(5)) + H.apply_effect((rand(90,150)),IRRADIATE,0) + if(prob(25)) + if (prob(75)) + randmutb(H) + domutcheck(H,null,1) + else + randmutg(H) + domutcheck(H,null,1) + + for(var/mob/living/carbon/monkey/M in living_mob_list) + var/turf/T = get_turf(M) + if(!T) + continue + if(T.z != 1) + continue + M.apply_effect((rand(15,75)),IRRADIATE,0) \ No newline at end of file diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm new file mode 100644 index 00000000000..ee47cc0abbc --- /dev/null +++ b/code/modules/events/spacevine.dm @@ -0,0 +1,5 @@ +/datum/event/spacevine + oneShot = 1 + +/datum/event/spacevine/start() + spacevine_infestation() \ No newline at end of file diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm new file mode 100644 index 00000000000..470439a29c8 --- /dev/null +++ b/code/modules/events/spontaneous_appendicitis.dm @@ -0,0 +1,13 @@ +/datum/event/spontaneous_appendicitis/start() + for(var/mob/living/carbon/human/H in living_mob_list) + var/foundAlready = 0 //don't infect someone that already has the virus + for(var/datum/disease/D in H.viruses) + foundAlready = 1 + if(H.stat == 2 || foundAlready) + continue + + var/datum/disease/D = new /datum/disease/appendicitis + D.holder = H + D.affected_mob = H + H.viruses += D + break \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index 0589a10585c..ffc9133a64a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -719,6 +719,19 @@ #include "code\modules\detectivework\evidence.dm" #include "code\modules\detectivework\footprints_and_rag.dm" #include "code\modules\detectivework\scanner.dm" +#include "code\modules\events\alien_infestation.dm" +#include "code\modules\events\blob.dm" +#include "code\modules\events\carp_migration.dm" +#include "code\modules\events\communications_blackout.dm" +#include "code\modules\events\disease_outbreak.dm" +#include "code\modules\events\electrical_storm.dm" +#include "code\modules\events\event.dm" +#include "code\modules\events\event_manager.dm" +#include "code\modules\events\meteor_wave.dm" +#include "code\modules\events\prison_break.dm" +#include "code\modules\events\radiation_storm.dm" +#include "code\modules\events\spacevine.dm" +#include "code\modules\events\spontaneous_appendicitis.dm" #include "code\modules\flufftext\Dreaming.dm" #include "code\modules\flufftext\Hallucination.dm" #include "code\modules\flufftext\TextFilters.dm"