Random Event Overhaul

Alters the event controller based on http://baystation12.net/forums/viewtopic.php?f=5&t=10706.
Exception is that there is always some start time variance to prevent metagaming.

Mundane, moderate, and major events run on their own timers and start and run independantly of each other.
Multiple events of the same severity degree can run at the same time. However, currently only one instance of the same event can be active at a time.
This commit is contained in:
PsiOmega
2014-11-01 19:18:56 +01:00
parent 7c284141b8
commit ff14da90b3
15 changed files with 368 additions and 126 deletions

View File

@@ -155,6 +155,20 @@
var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect
var/list/player_levels = list(1, 3, 4, 5, 6) // Defines all Z-levels a character can typically reach
var/const/minutes_to_ticks = 60 * 10
// Event settings
var/expected_round_length = 60 * 3 * minutes_to_ticks // 3 hours
// If the first delay has a custom start time
// No custom time, no custom time, between 80 to 100 minutes respectively.
var/list/event_first_run = list(EVENT_LEVEL_MUNDANE = null, EVENT_LEVEL_MODERATE = null, EVENT_LEVEL_MAJOR = list("lower" = 48000, "upper" = 60000))
// The lowest delay until next event
// 10, 30, 50 minutes respectively
var/list/event_delay_lower = list(EVENT_LEVEL_MUNDANE = 6000, EVENT_LEVEL_MODERATE = 18000, EVENT_LEVEL_MAJOR = 30000)
// The upper delay until next event
// 15, 45, 70 minutes respectively
var/list/event_delay_upper = list(EVENT_LEVEL_MUNDANE = 9000, EVENT_LEVEL_MODERATE = 27000, EVENT_LEVEL_MAJOR = 42000)
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -524,6 +538,33 @@
if("player_levels")
config.player_levels = text2numlist(value, ";")
if("expected_round_length")
config.expected_round_length = text2num(value) * minutes_to_ticks
if("event_custom_start_mundane")
var/values = text2numlist(value, ";")
config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = values[1] * minutes_to_ticks, "upper" = values[2] * minutes_to_ticks)
if("event_custom_start_moderate")
var/values = text2numlist(value, ";")
config.event_first_run[EVENT_LEVEL_MODERATE] = list("lower" = values[1] * minutes_to_ticks, "upper" = values[2] * minutes_to_ticks)
if("event_custom_start_major")
var/values = text2numlist(value, ";")
config.event_first_run[EVENT_LEVEL_MAJOR] = list("lower" = values[1] * minutes_to_ticks, "upper" = values[2] * minutes_to_ticks)
if("event_delay_lower")
var/values = text2numlist(value, ";")
config.event_delay_lower[EVENT_LEVEL_MUNDANE] = values[1] * minutes_to_ticks
config.event_delay_lower[EVENT_LEVEL_MODERATE] = values[2] * minutes_to_ticks
config.event_delay_lower[EVENT_LEVEL_MAJOR] = values[3] * minutes_to_ticks
if("event_delay_upper")
var/values = text2numlist(value, ";")
config.event_delay_upper[EVENT_LEVEL_MUNDANE] = values[1] * minutes_to_ticks
config.event_delay_upper[EVENT_LEVEL_MODERATE] = values[2] * minutes_to_ticks
config.event_delay_upper[EVENT_LEVEL_MAJOR] = values[3] * minutes_to_ticks
else
log_misc("Unknown setting in configuration: '[name]'")

View File

@@ -360,6 +360,7 @@ datum/controller/game_controller/proc/process_pipenets()
Powernet.reset()
datum/controller/game_controller/proc/process_nano()
last_thing_processed = /datum/nanoui
var/i = 1
while(i<=nanomanager.processing_uis.len)
var/datum/nanoui/ui = nanomanager.processing_uis[i]
@@ -371,15 +372,7 @@ datum/controller/game_controller/proc/process_nano()
datum/controller/game_controller/proc/process_events()
last_thing_processed = /datum/event
var/i = 1
while(i<=events.len)
var/datum/event/Event = events[i]
if(Event)
Event.process()
i++
continue
events.Cut(i,i+1)
checkEvent()
event_manager.process()
datum/controller/game_controller/proc/Recover() //Mostly a placeholder for now.
var/msg = "## DEBUG: [time2text(world.timeofday)] MC restarted. Reports:\n"

View File

@@ -48,7 +48,7 @@
message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
return
/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data"))
/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event"))
set category = "Debug"
set name = "Debug Controller"
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
@@ -102,6 +102,9 @@
feedback_add_details("admin_verb","DAutovoter")
if("Gas Data")
debug_variables(gas_data)
feedback_add_details("admin_verv","DGasdata")
feedback_add_details("admin_verb","DGasdata")
if("Event")
debug_variables(event_manager)
feedback_add_details("admin_verb", "DEvent")
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
return

View File

@@ -82,6 +82,14 @@
return 1
/datum/game_mode/calamity/post_setup()
// Reduce the interval between moderate/major events
event_manager.delay_modifier[EVENT_LEVEL_MODERATE] = 0.5
event_manager.delay_modifier[EVENT_LEVEL_MAJOR] = 0.75
// Add the cortical borer event
var/list/moderate_event_list = event_manager.available_events[EVENT_LEVEL_MODERATE]
var/event = new /datum/event_meta(/datum/event/borer_infestation, 400)
moderate_event_list.Add(event)
if(chosen_atypes)
for(var/atype in chosen_atypes)

View File

@@ -9,7 +9,6 @@ var/global/list/all_areas = list()
var/global/list/machines = list()
var/global/list/processing_objects = list()
var/global/list/active_diseases = list()
var/global/list/events = list()
var/global/list/med_hud_users = list() //list of all entities using a medical HUD.
var/global/list/sec_hud_users = list() //list of all entities using a security HUD.
//items that ask to be called every cycle
@@ -179,6 +178,9 @@ var/forceblob = 0
// nanomanager, the manager for Nano UIs
var/datum/nanomanager/nanomanager = new()
// event manager, the manager for events
var/datum/event_manager/event_manager = new()
//airlockWireColorToIndex takes a number representing the wire color, e.g. the orange wire is always 1, the dark red wire is always 2, etc. It returns the index for whatever that wire does.
//airlockIndexToWireColor does the opposite thing - it takes the index for what the wire does, for example AIRLOCK_WIRE_IDSCAN is 1, AIRLOCK_WIRE_POWER1 is 2, etc. It returns the wire color number.
//airlockWireColorToFlag takes the wire color number and returns the flag for it (1, 2, 4, 8, 16, etc)
@@ -213,6 +215,10 @@ var/list/AAlarmWireColorToIndex
#define shuttle_time_in_station 1800 // 3 minutes in the station
#define shuttle_time_to_arrive 6000 // 10 minutes to arrive
#define EVENT_LEVEL_MUNDANE 1
#define EVENT_LEVEL_MODERATE 2
#define EVENT_LEVEL_MAJOR 3
//away missions
var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to

View File

@@ -1,5 +1,6 @@
/datum/event/economic_event
name = "Economic event"
endWhen = 50 //this will be set randomly, later
announceWhen = 15
var/event_type = 0

View File

@@ -1,5 +1,6 @@
/datum/event/mundane_news
name = "Mundande news"
endWhen = 10
/datum/event/mundane_news/announce()
@@ -127,6 +128,7 @@
news_network.add_news("Nyx Daily", newMsg)
/datum/event/trivial_news
name = "Trivial news"
endWhen = 10
/datum/event/trivial_news/announce()

View File

@@ -1,7 +1,9 @@
/datum/event/carp_migration
name = "Carp Migration"
announceWhen = 50
oneShot = 1
endWhen = 900
endWhen = 900
var/list/spawned_carp = list()
/datum/event/carp_migration/setup()
@@ -9,12 +11,28 @@
endWhen = rand(600,1200)
/datum/event/carp_migration/announce()
command_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
var/announcement = ""
if(severity == EVENT_LEVEL_MAJOR)
announcement = "Massive migration of unknown biological entities has been detected near [station_name()], please stand-by."
else
announcement = "Unknown biological [spawned_carp.len == 1 ? "entity has" : "entities have"] been detected near [station_name()], please stand-by."
command_announcement.Announce(announcement, "Lifesign Alert")
/datum/event/carp_migration/start()
if(severity == EVENT_LEVEL_MAJOR)
for(var/i = 1 to rand(3,5))
spawn_fish(landmarks_list.len)
else if(severity == EVENT_LEVEL_MODERATE)
spawn_fish(landmarks_list.len)
else
spawn_fish(rand(1, 5))
/datum/event/carp_migration/proc/spawn_fish(var/limit)
for(var/obj/effect/landmark/C in landmarks_list)
if(C.name == "carpspawn")
spawned_carp.Add(new /mob/living/simple_animal/hostile/carp(C.loc))
if(spawned_carp.len >= limit)
return
/datum/event/carp_migration/end()
for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp)

View File

@@ -1,10 +1,56 @@
/datum/event_meta
var/weight = 1
var/min_weight = 1
var/max_weight = 1
var/severity = 0
var/has_fired = 0
var/list/role_weights = list()
var/datum/event/event_type
/datum/event_meta/New(var/event_severity, var/datum/event/type, var/event_weight, var/list/job_weights, var/min_event_weight, var/max_event_weight)
severity = event_severity
event_type = type
weight = event_weight
if(job_weights)
role_weights = job_weights
/datum/event_meta/proc/get_weight(var/list/active_with_role)
var/job_weight = 0
for(var/role in role_weights)
job_weight = active_with_role[role] * role_weights[role]
var/total_weight = weight + job_weight
// Only min/max the weight if the values are set
if(min_weight && total_weight < min_weight) total_weight = min_weight
if(max_weight && total_weight > max_weight) total_weight = max_weight
return total_weight
/datum/event_meta/alien/get_weight(var/list/active_with_role)
if(aliens_allowed)
return ..(active_with_role)
return 0
/datum/event_meta/ninja/get_weight(var/list/active_with_role)
if(toggle_space_ninja)
return ..(active_with_role)
return 0
/datum/event //NOTE: Times are measured in master controller ticks!
var/name = ""//Name of the event
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.
var/oneShot = 0 //If true, then the event removes itself from the list of potential events on creation.
var/severity = 0 //Severity. Lower means less severe, higher means more severe. Does not have to be supported. Is set on New().
var/activeFor = 0 //How long the event has existed. You don't need to change this.
var/isRunning = 1 //If this event is currently running. You should not change this.
var/datum/event_meta/event_meta = null
/datum/event/nothing
name = "Nothing"
//Called first before processing.
//Allows you to setup your event, such as randomly
@@ -42,21 +88,21 @@
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 && activeFor < endWhen)
tick()
if(activeFor == startWhen)
isRunning = 1
start()
if(activeFor == announceWhen)
announce()
if(activeFor == endWhen)
isRunning = 0
end()
// Everything is done, let's clean up.
@@ -65,19 +111,24 @@
activeFor++
//Garbage collects the event by removing it from the global events list,
//which should be the only place it's referenced.
//Called when start(), announce() and end() has all been called.
/datum/event/proc/kill()
events.Remove(src)
// If this event was forcefully killed run end() for individual cleanup
if(isRunning)
isRunning = 0
end()
event_manager.active_events -= src
event_manager.event_complete(src)
/datum/event/New(var/datum/event_meta/EM)
// event needs to be responsible for this, as stuff like APLUs currently make their own events for curious reasons
event_manager.active_events += src
event_meta = EM
severity = event_meta.severity
if(severity < EVENT_LEVEL_MUNDANE) severity = EVENT_LEVEL_MUNDANE
if(severity > EVENT_LEVEL_MAJOR) severity = EVENT_LEVEL_MAJOR
//Adds the event to the global events list, and removes it from the list
//of potential events.
/datum/event/New()
setup()
events.Add(src)
/*if(oneShot)
potentialRandomEvents.Remove(type)*/
..()

View File

@@ -187,7 +187,7 @@ var/list/event_last_fired = list()
// Returns how many characters are currently active(not logged out, not AFK for more than 10 minutes)
// with a specific role.
// Note that this isn't sorted by department, because e.g. having a roboticist shouldn't make meteors spawn.
/proc/number_active_with_role(role)
/proc/number_active_with_role()
var/list/active_with_role = list()
active_with_role["Engineer"] = 0
active_with_role["Medical"] = 0
@@ -197,6 +197,7 @@ var/list/event_last_fired = list()
active_with_role["Cyborg"] = 0
active_with_role["Janitor"] = 0
active_with_role["Gardener"] = 0
active_with_role["Any"] = player_list.len
for(var/mob/M in player_list)
if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive

View File

@@ -1,23 +1,130 @@
var/list/allEvents = typesof(/datum/event) - /datum/event
var/list/potentialRandomEvents = typesof(/datum/event) - /datum/event
//var/list/potentialRandomEvents = typesof(/datum/event) - /datum/event - /datum/event/spider_infestation - /datum/event/alien_infestation
#define ASSIGNMENT_ANY "Any"
#define ASSIGNMENT_AI "AI"
#define ASSIGNMENT_CYBORG "Cyborg"
#define ASSIGNMENT_ENGINEER "Engineer"
#define ASSIGNMENT_GARDENER "Gardener"
#define ASSIGNMENT_JANITOR "Janitor"
#define ASSIGNMENT_MEDICAL "Medical"
#define ASSIGNMENT_SCIENTIST "Scientist"
#define ASSIGNMENT_SECURITY "Security"
var/eventTimeLower = 12000 //20 minutes
var/eventTimeUpper = 24000 //40 minutes
var/scheduledEvent = null
/datum/event_manager
var/list/available_events = list(
EVENT_LEVEL_MUNDANE = list(
// Severity level, even type, base weight, role weights, min weight, max weight. Last two only used if set and non-zero
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), 25, 200),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 5, 50),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/money_hacker, 0, list(ASSIGNMENT_ANY = 4), 25, 200),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/economic_event, 300),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/trivial_news, 400),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/mundane_news, 300),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/brand_intelligence, 20, list(ASSIGNMENT_JANITOR = 25)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)),
),
EVENT_LEVEL_MODERATE = list(
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/nothing, 10),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/rogue_drone, 5, list(ASSIGNMENT_ENGINEER = 25, ASSIGNMENT_SECURITY = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/spacevine, 10, list(ASSIGNMENT_ENGINEER = 5)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/meteor_shower, 0, list(ASSIGNMENT_ENGINEER = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/communications_blackout, 50, list(ASSIGNMENT_AI = 25, ASSIGNMENT_SECURITY = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/grid_check, 25, list(ASSIGNMENT_ENGINEER = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/electrical_storm, 15, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_JANITOR = 15)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/radiation_storm, 0, list(ASSIGNMENT_MEDICAL = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/spider_infestation, 5, list(ASSIGNMENT_SECURITY = 5)),
new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, /datum/event/alien_infestation, 2.5,list(ASSIGNMENT_SECURITY = 1), max_event_weight = 5),
new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 1), max_event_weight = 5),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/ionstorm, 0, list(ASSIGNMENT_AI = 25, ASSIGNMENT_CYBORG = 25, ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SCIENTIST = 5)),
),
EVENT_LEVEL_MAJOR = list(
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/nothing, 100),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 10)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 10)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 10)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 10)),
)
)
var/list/datum/event/active_events = list()
var/list/datum/event/finished_events = list()
//Currently unused. Needs an admin panel for messing with events.
/*/proc/addPotentialEvent(var/type)
potentialRandomEvents |= type
var/list/datum/event/allEvents
/proc/removePotentialEvent(var/type)
potentialRandomEvents -= type*/
var/list/last_event_time = list()
var/list/next_event_time = list(EVENT_LEVEL_MUNDANE = 1, EVENT_LEVEL_MODERATE = 0, EVENT_LEVEL_MAJOR = 0)
var/list/delay_modifier = list(EVENT_LEVEL_MUNDANE = 1, EVENT_LEVEL_MODERATE = 1, EVENT_LEVEL_MAJOR = 1)
/datum/event_manager/New()
allEvents = typesof(/datum/event) - /datum/event
/proc/checkEvent()
if(!scheduledEvent)
//more players = more time between events, less players = less time between events
/datum/event_manager/proc/process()
for(var/datum/event/E in event_manager.active_events)
E.process()
for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
if(next_event_time[i] == 0)
// Our first time running, setup start times
set_event_delay(i)
else
// Is it time to fire a new event of this severity level?
if(world.timeofday > next_event_time[i])
start_event(i)
/datum/event_manager/proc/start_event(var/severity)
var/datum/event_meta/EM = acquire_event(available_events[severity])
if(!EM)
// If no event was available now, check again in one minute (rather than next process tick)
next_event_time[severity] = next_event_time[severity] + (60 * 10)
return
log_debug("Starting event of severity [severity].")
new EM.event_type(EM)
// Remove the event meta data from the list of available events
available_events[severity] -= EM
/datum/event_manager/proc/acquire_event(var/list/events)
if(events.len == 0)
return
var/active_with_role = number_active_with_role()
var/list/possible_events = list()
for(var/datum/event_meta/EM in events)
var/event_weight = EM.get_weight(active_with_role)
if(event_weight)
possible_events[EM] = event_weight
for(var/event_meta in last_event_time) if(possible_events[event_meta])
var/time_passed = world.time - event_last_fired[event_meta]
var/weight_modifier = max(0, (config.expected_round_length - time_passed) / 300)
var/new_weight = max(possible_events[event_meta] - weight_modifier, 0)
if(new_weight)
possible_events[event_meta] = new_weight
else
possible_events -= event_meta
if(possible_events.len == 0)
return null
var/picked_event = pickweight(possible_events)
last_event_time[picked_event] = world.time
return picked_event
/datum/event_manager/proc/set_event_delay(var/severity)
// If the next event time has not yet been set and we have a custom first time start
if(next_event_time[severity] == 0 && config.event_first_run[severity])
var/lower = config.event_first_run[severity]["lower"]
var/upper = config.event_first_run[severity]["upper"]
var/event_delay = rand(lower, upper)
next_event_time[severity] = world.timeofday + event_delay
// Otherwise, follow the standard setup process
else
var/playercount_modifier = 1
switch(player_list.len)
if(0 to 10)
@@ -30,36 +137,30 @@ var/scheduledEvent = null
playercount_modifier = 0.9
if(36 to 100000)
playercount_modifier = 0.8
playercount_modifier = playercount_modifier * delay_modifier[severity]
if(ticker.mode && ticker.mode.name == "calamity") //Calamity mode lowers the time required between events drastically.
playercount_modifier = playercount_modifier * 0.5
var/event_delay = rand(config.event_delay_lower[severity], config.event_delay_upper[severity]) * playercount_modifier
next_event_time[severity] = world.timeofday + event_delay
var/next_event_delay = rand(eventTimeLower, eventTimeUpper) * playercount_modifier
scheduledEvent = world.timeofday + next_event_delay
log_debug("Next event in [next_event_delay/600] minutes.")
log_debug("Next event of severity [severity] in [(next_event_time[severity] - world.timeofday)/600] minutes.")
else if(world.timeofday > scheduledEvent)
spawn_dynamic_event()
scheduledEvent = null
checkEvent()
//unused, see proc/dynamic_event()
/*
/proc/spawnEvent()
if(!config.allow_random_events)
/datum/event_manager/proc/event_complete(var/datum/event/E)
if(!E.event_meta) // datum/event is used here and there for random reasons
log_debug("Event of '[E.type]' with missing meta-data has completed.")
return
var/Type = pick(potentialRandomEvents)
if(!Type)
return
finished_events += E
// Add the event back to the list of available events, unless it's a oneShot
if(!E.oneShot)
var/list/datum/event_meta/AE = available_events[E.event_meta.severity]
AE.Add(E.event_meta)
//The event will add itself to the MC's event list
//and start working via the constructor.
new Type
*/
log_debug("Event '[E.name]' has completed.")
/client/proc/forceEvent(var/type in allEvents)
/proc/debugStartEvent(var/severity)
event_manager.start_event(severity)
/client/proc/forceEvent(var/type in event_manager.allEvents)
set name = "Trigger Event (Debug Only)"
set category = "Debug"
@@ -67,5 +168,15 @@ var/scheduledEvent = null
return
if(ispath(type))
new type
new type(new /datum/event_meta(EVENT_LEVEL_MAJOR))
message_admins("[key_name_admin(usr)] has triggered an event. ([type])", 1)
#undef ASSIGNMENT_ANY
#undef ASSIGNMENT_AI
#undef ASSIGNMENT_CYBORG
#undef ASSIGNMENT_ENGINEER
#undef ASSIGNMENT_GARDENER
#undef ASSIGNMENT_JANITOR
#undef ASSIGNMENT_MEDICAL
#undef ASSIGNMENT_SCIENTIST
#undef ASSIGNMENT_SECURITY

View File

@@ -1,58 +1,57 @@
/datum/event/radiation_storm
announceWhen = 1
oneShot = 1
var/const/enterBelt = 60
var/const/leaveBelt = 170
var/const/revokeAccess = 230
endWhen = revokeAccess
oneShot = 1
var/postStartTicks
/datum/event/radiation_storm/announce()
// Don't do anything, we want to pack the announcement with the actual event
command_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
/datum/event/radiation_storm/start()
spawn()
command_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
make_maint_all_access()
sleep(600)
make_maint_all_access()
/datum/event/radiation_storm/tick()
if(activeFor == enterBelt)
command_announcement.Announce("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert")
radiate()
for(var/i = 0, i < 10, i++)
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(T.loc, /area/maintenance) || istype(T.loc, /area/crew_quarters))
continue
if(istype(H,/mob/living/carbon/human))
H.apply_effect((rand(15,35)),IRRADIATE,0)
if(prob(5))
H.apply_effect((rand(40,70)),IRRADIATE,0)
if (prob(75))
randmutb(H) // Applies bad mutation
domutcheck(H,null,MUTCHK_FORCED)
else
randmutg(H) // Applies good mutation
domutcheck(H,null,MUTCHK_FORCED)
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(5,25)),IRRADIATE,0)
sleep(100)
if(activeFor > enterBelt && activeFor < leaveBelt)
postStartTicks++
if(postStartTicks == 10)
postStartTicks = 0
radiate()
else if(activeFor == leaveBelt)
command_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
/datum/event/radiation_storm/proc/radiate()
for(var/mob/living/carbon/C in living_mob_list)
var/turf/T = get_turf(C)
if(!T)
continue
if(!(T.z in config.station_levels))
continue
if(istype(T.loc, /area/maintenance) || istype(T.loc, /area/crew_quarters))
continue
sleep(600) // Want to give them time to get out of maintenance.
if(istype(C,/mob/living/carbon/human))
var/mob/living/carbon/human/H = C
H.apply_effect((rand(15,35)),IRRADIATE,0)
if(prob(5))
H.apply_effect((rand(40,70)),IRRADIATE,0)
if (prob(75))
randmutb(H) // Applies bad mutation
domutcheck(H,null,MUTCHK_FORCED)
else
randmutg(H) // Applies good mutation
domutcheck(H,null,MUTCHK_FORCED)
else if(istype(C,/mob/living/carbon/monkey))
C.apply_effect((rand(5,25)),IRRADIATE,0)
revoke_maint_all_access()
/datum/event/radiation_storm/end()
revoke_maint_all_access()

View File

@@ -1,11 +1,6 @@
datum/event/viral_infection
var/severity = 1
datum/event/viral_infection/setup()
announceWhen = rand(0, 3000)
endWhen = announceWhen + 1
severity = rand(1, 3)
datum/event/viral_infection/announce()
command_announcement.Announce("Confirmed outbreak of level five biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak5.ogg')
@@ -18,7 +13,9 @@ datum/event/viral_infection/start()
if(!candidates.len) return
candidates = shuffle(candidates)//Incorporating Donkie's list shuffle
while(severity > 0 && candidates.len)
severity = severity == 1 ? 1 : severity - 1
var/actual_severity = severity * rand(1, 3)
while(actual_severity > 0 && candidates.len)
infect_mob_random_lesser(candidates[1])
candidates.Remove(candidates[1])
severity--
actual_severity--

View File

@@ -1,20 +1,13 @@
/turf/simulated/wall
datum/event/wallrot
var/severity = 1
datum/event/wallrot/setup()
announceWhen = rand(0, 300)
endWhen = announceWhen + 1
severity = rand(5, 10)
datum/event/wallrot/announce()
command_announcement.Announce("Harmful fungi detected on station. Station structures may be contaminated.", "Biohazard Alert")
datum/event/wallrot/start()
spawn()
var/turf/center = null
var/turf/simulated/wall/center = null
// 100 attempts
for(var/i=0, i<100, i++)
@@ -24,14 +17,15 @@ datum/event/wallrot/start()
if(center)
// Make sure at least one piece of wall rots!
center:rot()
center.rot()
// Have a chance to rot lots of other walls.
var/rotcount = 0
var/actual_severity = severity * rand(5, 10)
for(var/turf/simulated/wall/W in range(5, center)) if(prob(50))
W:rot()
W.rot()
rotcount++
// Only rot up to severity walls
if(rotcount >= severity)
if(rotcount >= actual_severity)
break

View File

@@ -272,3 +272,20 @@ CONTACT_LEVELS 1;5
## Defines all Z-levels a character can typically reach
PLAYER_LEVELS 1;3;4;5;6
## Expected round length in minutes
EXPECTED_ROUND_LENGTH 180
## The lower delay between events in minutes.
## Affect mundane, moderate, and major events respectively
EVENT_DELAY_LOWER 10;30;50
## The upper delay between events in minutes.
## Affect mundane, moderate, and major events respectively
EVENT_DELAY_UPPER 15;45;70
## The delay until the first time an event of the given severity runs in minutes.
## Unset setting use the EVENT_DELAY_LOWER and EVENT_DELAY_UPPER values instead.
# EVENT_CUSTOM_START_MINOR 10;15
# EVENT_CUSTOM_START_MODERATE 30;45
EVENT_CUSTOM_START_MAJOR 80;100