From d4368954dc984e979df5007dddb7d152c11a8a48 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Mon, 10 Nov 2014 15:00:40 +0100 Subject: [PATCH] Event Manager Control Admins can now: Pause event start countdown. Add/Remove events to rotation. Affect the likelihood of events occurring. Allow one shot events to fire again. --- baystation12.dme | 1 + code/game/gamemodes/calamity/calamity.dm | 10 +- code/modules/events/alien_infestation.dm | 1 - code/modules/events/borers.dm | 1 - code/modules/events/brand_intelligence.dm | 1 - code/modules/events/carp_migration.dm | 1 - code/modules/events/disease_outbreak.dm | 1 - code/modules/events/event.dm | 27 +- code/modules/events/event_container.dm | 178 +++++++++++ code/modules/events/event_manager.dm | 366 ++++++++++------------ code/modules/events/prison_break.dm | 1 - code/modules/events/radiation_storm.dm | 1 - code/modules/events/spacevine.dm | 1 - code/modules/events/spider_infestation.dm | 1 - 14 files changed, 373 insertions(+), 218 deletions(-) create mode 100644 code/modules/events/event_container.dm diff --git a/baystation12.dme b/baystation12.dme index 7c4e4f1554c..d13c5536497 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -848,6 +848,7 @@ #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_container.dm" #include "code\modules\events\event_dynamic.dm" #include "code\modules\events\event_manager.dm" #include "code\modules\events\grid_check.dm" diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm index d22b8fad01b..8120153b561 100644 --- a/code/game/gamemodes/calamity/calamity.dm +++ b/code/game/gamemodes/calamity/calamity.dm @@ -83,12 +83,14 @@ /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 + var/datum/event_container/EModerate = event_manager.event_containers[EVENT_LEVEL_MODERATE] + var/datum/event_container/EMajor = event_manager.event_containers[EVENT_LEVEL_MAJOR] + EModerate.delay_modifier = 0.5 + EMajor.delay_modifier = 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(EVENT_LEVEL_MODERATE, "Borer Infestation", /datum/event/borer_infestation, 400) + var/list/moderate_event_list = EModerate.available_events + var/event = new /datum/event_meta(EVENT_LEVEL_MODERATE, "Borer Infestation", /datum/event/borer_infestation, 400, one_shot = 1) moderate_event_list.Add(event) if(chosen_atypes) diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index a84a4fefdab..813becdccfc 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -3,7 +3,6 @@ /datum/event/alien_infestation name = "Alien Infestation" announceWhen = 400 - oneShot = 1 var/spawncount = 1 var/successSpawn = 0 //So we don't make a command report if nothing gets spawned. diff --git a/code/modules/events/borers.dm b/code/modules/events/borers.dm index 54c16deaed8..38d560175e7 100644 --- a/code/modules/events/borers.dm +++ b/code/modules/events/borers.dm @@ -2,7 +2,6 @@ /datum/event/borer_infestation name = "Borer Infestation" - oneShot = 1 /datum/event/borer_infestation announceWhen = 400 diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index 0f9412527bd..3ea8e0e0231 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -2,7 +2,6 @@ name = "Brand Intelligence" announceWhen = 21 endWhen = 1000 //Ends when all vending machines are subverted anyway. - oneShot = 1 var/list/obj/machinery/vending/vendingMachines = list() var/list/obj/machinery/vending/infectedVendingMachines = list() diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index 94ca69c9a5b..ceb4bac0bf0 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -1,7 +1,6 @@ /datum/event/carp_migration name = "Carp Migration" announceWhen = 50 - oneShot = 1 endWhen = 900 var/list/spawned_carp = list() diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index 65f56391c39..67409a9ea01 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -1,7 +1,6 @@ /datum/event/disease_outbreak name = "Disease Outbreak" announceWhen = 15 - oneShot = 1 /datum/event/disease_outbreak/announce() diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm index 4fc288ab6d4..f2e0e890f32 100644 --- a/code/modules/events/event.dm +++ b/code/modules/events/event.dm @@ -1,29 +1,37 @@ /datum/event_meta - var/name = "" - var/weight = 1 - var/min_weight = 1 - var/max_weight = 1 - var/severity = 0 - var/has_fired = 0 + var/name = "" + var/enabled = 1 // Whether or not the event is available for random selection at all + var/weight = 0 // The base weight of this event. A zero means it may never fire, but see get_weight() + var/min_weight = 0 // The minimum weight that this event will have. Only used if non-zero. + var/max_weight = 0 // The maximum weight that this event will have. Only use if non-zero. + var/severity = 0 // The current severity of this event + var/one_shot = 0 //If true, then the event will not be re-added to the list of available events var/list/role_weights = list() var/datum/event/event_type -/datum/event_meta/New(var/event_severity, var/event_name, var/datum/event/type, var/event_weight, var/list/job_weights, var/min_event_weight, var/max_event_weight) +/datum/event_meta/New(var/event_severity, var/event_name, var/datum/event/type, var/event_weight, var/list/job_weights, var/is_one_shot = 0, var/min_event_weight = 0, var/max_event_weight = 0) name = event_name severity = event_severity event_type = type + one_shot = is_one_shot weight = event_weight + min_weight = min_event_weight + max_weight = max_event_weight if(job_weights) role_weights = job_weights /datum/event_meta/proc/get_weight(var/list/active_with_role) + if(!enabled) + return 0 + var/job_weight = 0 for(var/role in role_weights) - job_weight = active_with_role[role] * role_weights[role] + if(role in active_with_role) + 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 + // Only min/max the weight if the values are non-zero if(min_weight && total_weight < min_weight) total_weight = min_weight if(max_weight && total_weight > max_weight) total_weight = max_weight @@ -44,7 +52,6 @@ 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. diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm new file mode 100644 index 00000000000..0220ea17cbd --- /dev/null +++ b/code/modules/events/event_container.dm @@ -0,0 +1,178 @@ +#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/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT_LEVEL_MODERATE = "Moderate", EVENT_LEVEL_MAJOR = "Major") + +/datum/event_container + var/severity = -1 + var/delayed = 0 + var/delay_modifier = 1 + var/next_event_time = 0 + var/list/available_events + var/list/last_event_time = list() + var/datum/event_meta/next_event = null + + var/last_world_time = 0 + +/datum/event_container/proc/process() + if(!next_event_time) + set_event_delay() + + if(delayed) + next_event_time += (world.timeofday - last_world_time) + else if(world.timeofday > next_event_time) + start_event() + + last_world_time = world.timeofday + +/datum/event_container/proc/start_event() + if(!next_event) // If non-one has explicitly set an event, randomly pick one + next_event = acquire_event() + + // Has an event been acquired? + if(next_event) + // Set when the event of this type was last fired, and prepare the next event start + last_event_time[next_event] = world.timeofday + set_event_delay() + next_event.enabled = !next_event.one_shot // This event will no longer be available in the random rotation if one shot + + var/datum/event/E = new next_event.event_type(next_event) // Events are added and removed from the processing queue in their New/kill procs + + log_debug("Starting event '[E.name]' of severity [severity_to_string[severity]].") + next_event = null // When set to null, a random event will be selected next time + else + // If not, wait for one minute, instead of one tick, before checking again. + next_event_time += (60 * 10) + + +/datum/event_container/proc/acquire_event() + if(available_events.len == 0) + return + var/active_with_role = number_active_with_role() + + var/list/possible_events = list() + for(var/datum/event_meta/EM in available_events) + var/event_weight = EM.get_weight(active_with_role) + if(EM.enabled && event_weight) + possible_events[EM] = event_weight + + for(var/event_meta in last_event_time) if(possible_events[event_meta]) + var/time_passed = world.timeofday - 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 + + // Select an event and remove it from the pool of available events + var/picked_event = pickweight(possible_events) + available_events -= picked_event + return picked_event + +/datum/event_container/proc/set_event_delay() + // If the next event time has not yet been set and we have a custom first time start + if(next_event_time == 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 = world.timeofday + event_delay + // Otherwise, follow the standard setup process + else + var/playercount_modifier = 1 + switch(player_list.len) + if(0 to 10) + playercount_modifier = 1.2 + if(11 to 15) + playercount_modifier = 1.1 + if(16 to 25) + playercount_modifier = 1 + if(26 to 35) + playercount_modifier = 0.9 + if(36 to 100000) + playercount_modifier = 0.8 + playercount_modifier = playercount_modifier * delay_modifier + + var/event_delay = rand(config.event_delay_lower[severity], config.event_delay_upper[severity]) * playercount_modifier + next_event_time = world.timeofday + event_delay + + log_debug("Next event of severity [severity_to_string[severity]] in [(next_event_time - world.timeofday)/600] minutes.") + +/datum/event_container/proc/SelectEvent() + var/datum/event_meta/EM = input("Select an event to queue up.", "Event Selection", null) as null|anything in available_events + if(!EM) + return + if(next_event) + available_events += next_event + available_events -= EM + next_event = EM + +/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 + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Nothing", /datum/event/nothing, 100), + 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), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Hacker", /datum/event/money_hacker, 0, list(ASSIGNMENT_ANY = 4), 1, 10, 25), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Economic News", /datum/event/economic_event, 300), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Lost Carp", /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Brand Intelligence",/datum/event/brand_intelligence,20, list(ASSIGNMENT_JANITOR = 25), 1), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wall root", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)), + ) + +/datum/event_container/moderate + severity = EVENT_LEVEL_MODERATE + available_events = list( + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Nothing", /datum/event/nothing, 10), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 5, list(ASSIGNMENT_ENGINEER = 25, ASSIGNMENT_SECURITY = 25)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space vines", /datum/event/spacevine, 10, list(ASSIGNMENT_ENGINEER = 5)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_shower, 0, list(ASSIGNMENT_ENGINEER = 10)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 50, list(ASSIGNMENT_AI = 25, ASSIGNMENT_SECURITY = 25)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 50)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 25, list(ASSIGNMENT_ENGINEER = 10)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 15, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_JANITOR = 15)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 0, list(ASSIGNMENT_MEDICAL = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 10)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 5, list(ASSIGNMENT_SECURITY = 5), 1), + new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 2.5,list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), + new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ionstorm, 0, list(ASSIGNMENT_AI = 25, ASSIGNMENT_CYBORG = 25, ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SCIENTIST = 5)), + ) + +/datum/event_container/major + severity = EVENT_LEVEL_MAJOR + available_events = list( + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 50), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 10), 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 diff --git a/code/modules/events/event_manager.dm b/code/modules/events/event_manager.dm index c74e302b46c..e01b835352c 100644 --- a/code/modules/events/event_manager.dm +++ b/code/modules/events/event_manager.dm @@ -1,72 +1,23 @@ -#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/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT_LEVEL_MODERATE = "Moderate", EVENT_LEVEL_MAJOR = "Major") - /datum/event_manager - var/list/available_events = list( - EVENT_LEVEL_MUNDANE = list( - // Severity level, event name, 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, "Nothing", /datum/event/nothing, 100), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "PDA Spam", /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), 25, 200), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 5, 50), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Hacker", /datum/event/money_hacker, 0, list(ASSIGNMENT_ANY = 4), 25, 200), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Economic News", /datum/event/economic_event, 300), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Carp", /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10)), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wall root", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Brand Intelligence", /datum/event/brand_intelligence, 20, list(ASSIGNMENT_JANITOR = 25)), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation", /datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)), - ), - EVENT_LEVEL_MODERATE = list( - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Nothing", /datum/event/nothing, 10), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp Infestation", /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 5, list(ASSIGNMENT_ENGINEER = 25, ASSIGNMENT_SECURITY = 25)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space vines", /datum/event/spacevine, 10, list(ASSIGNMENT_ENGINEER = 5)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_shower, 0, list(ASSIGNMENT_ENGINEER = 10)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 50, list(ASSIGNMENT_AI = 25, ASSIGNMENT_SECURITY = 25)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 25, list(ASSIGNMENT_ENGINEER = 10)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 15, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_JANITOR = 15)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 0, list(ASSIGNMENT_MEDICAL = 10)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 10)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 10)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation",/datum/event/spider_infestation, 5, list(ASSIGNMENT_SECURITY = 5)), - new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 2.5,list(ASSIGNMENT_SECURITY = 1), max_event_weight = 5), - new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 1), max_event_weight = 5), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /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, "Nothing", /datum/event/nothing, 100), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 10)), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 10)), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 10)), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 10)), - ) - ) - - var/window_x = 370 - var/window_y = 530 + var/window_x = 700 + var/window_y = 600 var/table_options = " align='center'" var/row_options1 = " width='85px'" var/row_options2 = " width='260px'" + var/row_options3 = " width='150px'" + var/datum/event_container/selected_event_container = null var/list/datum/event/active_events = list() var/list/datum/event/finished_events = list() var/list/datum/event/allEvents + var/list/datum/event_container/event_containers = list( + EVENT_LEVEL_MUNDANE = new/datum/event_container/mundane, + EVENT_LEVEL_MODERATE = new/datum/event_container/moderate, + EVENT_LEVEL_MAJOR = new/datum/event_container/major + ) - var/list/last_event_time = list() - var/list/next_event = list(EVENT_LEVEL_MUNDANE = null, EVENT_LEVEL_MODERATE = null, EVENT_LEVEL_MAJOR = null) - var/list/next_event_time = list(EVENT_LEVEL_MUNDANE = 0, 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) + var/datum/event_meta/new_event = new /datum/event_manager/New() allEvents = typesof(/datum/event) - /datum/event @@ -76,85 +27,8 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT E.process() for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) - // Is it time to fire a new event of this severity level? - if(world.timeofday > next_event_time[i]) - process_event_start(i) - -/datum/event_manager/proc/process_event_start(var/severity) - var/event = next_event[severity] - if(event) - start_event(event) - - // Attempt to select a new event - next_event[severity] = acquire_event(available_events[severity]) - if(next_event[severity]) // If we got an event, set the next delay proper - set_event_delay(severity) - else // Otherwise, wait for one minute (rather than next process tick) before checking again - next_event_time[severity] += (60 * 10) - -/datum/event_manager/proc/start_event(var/datum/event_meta/EM) - // Set when the event of this type was last fired - last_event_time[EM] = world.timeofday - - log_debug("Starting event of severity [EM.severity].") - new EM.event_type(EM) // Events are added and removed from the processing queue in New/Del - -/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.timeofday - 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 - - // Select an event and remove it from the pool of available events - var/picked_event = pickweight(possible_events) - events -= picked_event - 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) - playercount_modifier = 1.2 - if(11 to 15) - playercount_modifier = 1.1 - if(16 to 25) - playercount_modifier = 1 - if(26 to 35) - playercount_modifier = 0.9 - if(36 to 100000) - playercount_modifier = 0.8 - playercount_modifier = playercount_modifier * delay_modifier[severity] - - var/event_delay = rand(config.event_delay_lower[severity], config.event_delay_upper[severity]) * playercount_modifier - next_event_time[severity] = world.timeofday + event_delay - - log_debug("Next event of severity [severity] in [(next_event_time[severity] - world.timeofday)/600] minutes.") + var/list/datum/event_container/EC = event_containers[i] + EC.process() /datum/event_manager/proc/event_complete(var/datum/event/E) if(!E.event_meta) // datum/event is used here and there for random reasons @@ -162,10 +36,10 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT 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) + + // Add the event back to the list of available events + var/datum/event_container/EC = event_containers[E.severity] + EC.available_events += E.event_meta log_debug("Event '[E.name]' has completed.") @@ -179,39 +53,103 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT popup.open() /datum/event_manager/proc/GetInteractWindow() - var html = "Refresh
" + var/html = "Refresh" - html += "
" - html += "

Event Start

" - html += "" - html += "SeverityUntil startAdjust start" - for(var/severity = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) - var/event_time = max(0, next_event_time[severity] - world.timeofday) - html += "" - html += "[severity_to_string[severity]]" - html += "[event_time / 600]" - html += "" - html += "--" - html += "-" - html += "+" - html += "++" - html += "" - html += "" - html += "" - html += "
" + if(selected_event_container) + var/event_time = max(0, selected_event_container.next_event_time - world.timeofday) + html += "Back
" + html += "Time till start: [round(event_time / 600, 0.1)]
" + html += "
" + html += "

Available [severity_to_string[selected_event_container.severity]] Events (queued events will not be displayed)

" + html += "" + html += "Name Weight MinWeight MaxWeight OneShot Enabled CurrWeight Remove" + for(var/datum/event_meta/EM in selected_event_container.available_events) + html += "" + html += "[EM.name]" + html += "[EM.weight]" + html += "[EM.min_weight]" + html += "[EM.max_weight]" + html += "[EM.one_shot]" + html += "[EM.enabled]" + html += "[EM.get_weight()]" + html += "Remove" + html += "" + html += "" + html += "
" - html += "
" - html += "

Next Event

" - html += "" - html += "SeverityName" - for(var/severity = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) - var/datum/event_meta/EM = next_event[severity] + html += "
" + html += "

Add Event

" + html += "" + html += "NameTypeWeightOneShot" html += "" - html += "[severity_to_string[severity]]" - html += "[EM ? EM.name : "Nothing"]" + html += "[new_event.name ? new_event.name : "Enter Event"]" + html += "[new_event.event_type ? new_event.event_type : "Select Type"]" + html += "[new_event.weight ? new_event.weight : 0]" + html += "[new_event.one_shot]" html += "" - html += "" - html += "
" + html += "" + html += "Add
" + html += "
" + else + html += "
" + html += "
" + html += "

Event Start

" + + html += "" + html += "SeverityUntil startAdjust startPauseInterval Mod" + for(var/severity = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) + var/datum/event_container/EC = event_containers[severity] + var/event_time = max(0, EC.next_event_time - world.timeofday) + html += "" + html += "[severity_to_string[severity]]" + html += "[round(event_time / 600, 0.1)]" + html += "" + html += "--" + html += "-" + html += "+" + html += "++" + html += "" + html += "" + html += "[EC.delayed ? "Resume" : "Pause"]" + html += "" + html += "" + html += "[EC.delay_modifier]" + html += "" + html += "" + html += "" + html += "
" + + html += "
" + html += "

Next Event

" + html += "" + html += "SeverityNameEvent RotationClear" + for(var/severity = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) + var/datum/event_container/EC = event_containers[severity] + var/datum/event_meta/EM = EC.next_event + html += "" + html += "[severity_to_string[severity]]" + html += "[EM ? EM.name : "Random"]" + html += "View" + html += "Clear" + html += "" + html += "" + html += "
" + + html += "
" + html += "

Running Events

" + html += "" + html += "SeverityNameStop" + for(var/datum/event/E in active_events) + if(!E.event_meta) + continue + var/datum/event_meta/EM = E.event_meta + html += "" + html += "[severity_to_string[EM.severity]]" + html += "[EM.name]" + html += "Stop" + html += "" + html += "" + html += "
" return html @@ -219,27 +157,75 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT if(..()) return - var/severity = text2num(href_list["severity"]) if(href_list["dec_timer"]) - next_event_time[severity] -= (60 * RaiseToPower(10, text2num(href_list["dec_timer"]))) + var/datum/event_container/EC = locate(href_list["event"]) + EC.next_event_time -= (60 * RaiseToPower(10, text2num(href_list["dec_timer"]))) else if(href_list["inc_timer"]) - next_event_time[severity] += (60 * RaiseToPower(10, text2num(href_list["inc_timer"]))) + var/datum/event_container/EC = locate(href_list["event"]) + EC.next_event_time += (60 * RaiseToPower(10, text2num(href_list["inc_timer"]))) else if(href_list["select_event"]) - SelectEvent(severity) + var/datum/event_container/EC = locate(href_list["select_event"]) + EC.SelectEvent() + else if(href_list["pause"]) + var/datum/event_container/EC = locate(href_list["pause"]) + EC.delayed = !EC.delayed + else if(href_list["interval"]) + var/delay = input("Enter delay modifier. A value less than one means events fire more often, higher than one less often.", "Set Interval Modifier") as num|null + if(delay && delay > 0) + var/datum/event_container/EC = locate(href_list["interval"]) + EC.delay_modifier = delay + else if(href_list["stop"]) + if(alert("Stopping an event may have unintended side-effects. Continue?","Stopping Event!","Yes","No") != "Yes") + return + var/datum/event/E = locate(href_list["stop"]) + E.kill() + else if(href_list["view_events"]) + selected_event_container = locate(href_list["view_events"]) + else if(href_list["back"]) + selected_event_container = null + else if(href_list["set_name"]) + var/name = input("Enter event name.", "Set Name") as text|null + if(name) + var/datum/event_meta/EM = locate(href_list["set_name"]) + EM.name = name + else if(href_list["set_type"]) + var/type = input("Select event type.", "Select") as null|anything in allEvents + if(type) + var/datum/event_meta/EM = locate(href_list["set_type"]) + EM.event_type = type + else if(href_list["set_weight"]) + var/weight = input("Enter weight. A higher value means higher chance for the event of being selected.", "Set Weight") as num|null + if(weight && weight > 0) + var/datum/event_meta/EM = locate(href_list["set_weight"]) + EM.weight = weight + else if(href_list["set_oneshot"]) + var/datum/event_meta/EM = locate(href_list["set_oneshot"]) + EM.one_shot = !EM.one_shot + else if(href_list["set_enabled"]) + var/datum/event_meta/EM = locate(href_list["set_enabled"]) + EM.enabled = !EM.enabled + else if(href_list["remove"]) + if(alert("This will remove the event from rotation. Continue?","Removing Event!","Yes","No") != "Yes") + return + var/datum/event_meta/EM = locate(href_list["remove"]) + var/datum/event_container/EC = locate(href_list["EC"]) + EC.available_events -= EM + else if(href_list["add"]) + if(!new_event.name || !new_event.event_type) + return + if(alert("This will add a new event to the rotation. Continue?","Add Event!","Yes","No") != "Yes") + return + selected_event_container.available_events += new_event + new_event = new + else if(href_list["clear"]) + var/datum/event_container/EC = locate(href_list["clear"]) + EC.next_event = null Interact(usr) -/datum/event_manager/proc/SelectEvent(var/severity) - var/datum/event_meta/EM = input("Select an event to queue up.", "Event Selection", null) as null|anything in available_events[severity] - if(!EM) - return - if(next_event[severity]) - available_events[severity] += next_event[severity] - available_events[severity] -= EM - next_event[severity] = EM - /proc/debugStartEvent(var/severity) - event_manager.start_event(severity) + var/datum/event_container/EC = event_manager.event_containers[severity] + EC.start_event() /client/proc/forceEvent(var/type in event_manager.allEvents) set name = "Trigger Event (Debug Only)" @@ -259,13 +245,3 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT event_manager.Interact(usr) feedback_add_details("admin_verb","EMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return - -#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 \ No newline at end of file diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index b1eed0fc033..9c3008e4d05 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -1,7 +1,6 @@ /datum/event/prison_break name = "Prison Break" announceWhen = 50 - oneShot = 1 var/releaseWhen = 25 var/list/area/prisonAreas = list() diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 3e7249b368a..b88fe7f1b6f 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -5,7 +5,6 @@ var/const/revokeAccess = 230 endWhen = revokeAccess - oneShot = 1 var/postStartTicks diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index c8f270fe134..d6af6f7b5b3 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -2,7 +2,6 @@ /datum/event/spacevine name = "Space Vines" - oneShot = 1 /datum/event/spacevine/start() //biomass is basically just a resprited version of space vines diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm index 6f256e0b8c8..6e38f787155 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -3,7 +3,6 @@ /datum/event/spider_infestation name = "Large Spider Infestation" announceWhen = 400 - oneShot = 1 var/spawncount = 1