Merge pull request #6983 from PsiOmegaDelta/Event

Event Manager Control
This commit is contained in:
Chinsky
2014-11-12 23:45:02 +03:00
35 changed files with 456 additions and 279 deletions

View File

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

View File

@@ -1,6 +1,5 @@
/datum/event/mundane_news
name = "Mundande news"
endWhen = 10
/datum/event/mundane_news/announce()
@@ -126,7 +125,6 @@
news_network.SubmitArticle(body, author, channel, null, 1)
/datum/event/trivial_news
name = "Trivial news"
endWhen = 10
/datum/event/trivial_news/announce()

View File

@@ -1,9 +1,7 @@
/var/global/sent_aliens_to_station = 0
/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.

View File

@@ -1,5 +1,4 @@
/datum/event/blob
name = "Blob"
announceWhen = 12
endWhen = 120

View File

@@ -1,9 +1,4 @@
//Cortical borer spawn event - care of RobRichards1997 with minor editing by Zuhayr.
/datum/event/borer_infestation
name = "Borer Infestation"
oneShot = 1
/datum/event/borer_infestation
announceWhen = 400

View File

@@ -1,8 +1,6 @@
/datum/event/brand_intelligence
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()

View File

@@ -1,7 +1,5 @@
/datum/event/carp_migration
name = "Carp Migration"
announceWhen = 50
oneShot = 1
endWhen = 900
var/list/spawned_carp = list()

View File

@@ -1,6 +1,3 @@
/datum/event/communications_blackout
name = "Communications Blackout"
/datum/event/communications_blackout/announce()
var/alert = pick( "Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you*%fj00)`5vc-BZZT", \
"Ionospheric anomalies detected. Temporary telecommunication failu*3mga;b4;'1v<31>-BZZZT", \

View File

@@ -1,7 +1,5 @@
/datum/event/disease_outbreak
name = "Disease Outbreak"
announceWhen = 15
oneShot = 1
/datum/event/disease_outbreak/announce()

View File

@@ -1,5 +1,4 @@
/datum/event/electrical_storm
name = "Electrical Storm"
var/lightsoutAmount = 1
var/lightsoutRange = 25

View File

@@ -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
@@ -40,19 +48,18 @@
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/startedAt = 0 //When this event started.
var/endedAt = 0 //When this event ended.
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
@@ -89,6 +96,9 @@
/datum/event/proc/end()
return
//Returns the latest point of event processing.
/datum/event/proc/lastProcessAt()
return max(startWhen, max(announceWhen, endWhen))
//Do not override this proc, instead use the appropiate procs.
//This proc will handle the calls to the appropiate procs.
@@ -108,7 +118,7 @@
end()
// Everything is done, let's clean up.
if(activeFor >= endWhen && activeFor >= announceWhen && activeFor >= startWhen)
if(activeFor >= lastProcessAt())
kill()
activeFor++
@@ -120,6 +130,7 @@
isRunning = 0
end()
endedAt = world.time
event_manager.active_events -= src
event_manager.event_complete(src)
@@ -132,5 +143,7 @@
if(severity < EVENT_LEVEL_MUNDANE) severity = EVENT_LEVEL_MUNDANE
if(severity > EVENT_LEVEL_MAJOR) severity = EVENT_LEVEL_MAJOR
startedAt = world.time
setup()
..()

View File

@@ -0,0 +1,179 @@
#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.time - last_world_time)
else if(world.time > next_event_time)
start_event()
last_world_time = world.time
/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.time
set_event_delay()
next_event.enabled = !next_event.one_shot // This event will no longer be available in the random rotation if one shot
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 '[next_event.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.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
// 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.time + 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.time + event_delay
log_debug("Next event of severity [severity_to_string[severity]] in [(next_event_time - world.time)/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
return 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, "Wallrot", /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

View File

@@ -1,72 +1,24 @@
#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/report_at_round_end = 0
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,99 +28,22 @@ 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
if(!E.event_meta) // datum/event is used here and there for random reasons, maintaining "backwards compatibility"
log_debug("Event of '[E.type]' with missing meta-data has completed.")
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)
log_debug("Event '[E.name]' has completed.")
// Add the event back to the list of available events
var/datum/event_container/EC = event_containers[E.severity]
var/datum/event_meta/EM = E.event_meta
EC.available_events += EM
log_debug("Event '[EM.name]' has completed at [worldtime2text()].")
/datum/event_manager/proc/Interact(var/mob/living/user)
@@ -178,40 +53,130 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
popup.set_content(html)
popup.open()
/datum/event_manager/proc/RoundEnd()
if(!report_at_round_end)
return
world << "<br><br><br><font size=3><b>Random Events This Round:</b></font>"
for(var/datum/event/E in active_events|finished_events)
var/datum/event_meta/EM = E.event_meta
if(EM.name == "Nothing")
continue
var/message = "'[EM.name]' began at [worldtime2text(E.startedAt)] "
if(E.isRunning)
message += "and is still running."
else
if(E.endedAt - E.startedAt > MinutesToTicks(5)) // Only mention end time if the entire duration was more than 5 minutes
message += "and ended at [worldtime2text(E.endedAt)]."
else
message += "and ran to completion."
world << message
/datum/event_manager/proc/GetInteractWindow()
var html = "<A align='right' href='?src=\ref[src];refresh=1'>Refresh</A><br>"
var/html = "<A align='right' href='?src=\ref[src];refresh=1'>Refresh</A>"
html += "<div class='block'>"
html += "<h2>Event Start</h2>"
html += "<table[table_options]>"
html += "<tr><td>Severity</td><td>Until start</td><td>Adjust start</td></tr>"
for(var/severity = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
var/event_time = max(0, next_event_time[severity] - world.timeofday)
html += "<tr>"
html += "<td[row_options1]>[severity_to_string[severity]]</font></td>"
html += "<td[row_options1]>[event_time / 600]</td>"
html += "<td[row_options2]>"
html += "<A align='right' href='?src=\ref[src];dec_timer=2;severity=[severity]'>--</A>"
html += "<A align='right' href='?src=\ref[src];dec_timer=1;severity=[severity]'>-</A>"
html += "<A align='right' href='?src=\ref[src];inc_timer=1;severity=[severity]'>+</A>"
html += "<A align='right' href='?src=\ref[src];inc_timer=2;severity=[severity]'>++</A>"
html += "</td>"
html += "</tr>"
html += "</table>"
html += "</div>"
if(selected_event_container)
var/event_time = max(0, selected_event_container.next_event_time - world.time)
html += "<A align='right' href='?src=\ref[src];back=1'>Back</A><br>"
html += "Time till start: [round(event_time / 600, 0.1)]<br>"
html += "<div class='block'>"
html += "<h2>Available [severity_to_string[selected_event_container.severity]] Events (queued & running events will not be displayed)</h2>"
html += "<table[table_options]>"
html += "<tr><td[row_options2]>Name </td><td>Weight </td><td>MinWeight </td><td>MaxWeight </td><td>OneShot </td><td>Enabled </td><td><span class='alert'>CurrWeight </span></td><td>Remove</td></tr>"
for(var/datum/event_meta/EM in selected_event_container.available_events)
html += "<tr>"
html += "<td>[EM.name]</td>"
html += "<td><A align='right' href='?src=\ref[src];set_weight=\ref[EM]'>[EM.weight]</A></td>"
html += "<td>[EM.min_weight]</td>"
html += "<td>[EM.max_weight]</td>"
html += "<td><A align='right' href='?src=\ref[src];toggle_oneshot=\ref[EM]'>[EM.one_shot]</A></td>"
html += "<td><A align='right' href='?src=\ref[src];toggle_enabled=\ref[EM]'>[EM.enabled]</A></td>"
html += "<td><span class='alert'>[EM.get_weight()]</span></td>"
html += "<td><A align='right' href='?src=\ref[src];remove=\ref[EM];EC=\ref[selected_event_container]'>Remove</A></td>"
html += "</tr>"
html += "</table>"
html += "</div>"
html += "<div class='block'>"
html += "<h2>Next Event</h2>"
html += "<table[table_options]>"
html += "<tr><td>Severity</td><td>Name</td></tr>"
for(var/severity = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
var/datum/event_meta/EM = next_event[severity]
html += "<div class='block'>"
html += "<h2>Add Event</h2>"
html += "<table[table_options]>"
html += "<tr><td[row_options2]>Name</td><td[row_options2]>Type</td><td[row_options1]>Weight</td><td[row_options1]>OneShot</td></tr>"
html += "<tr>"
html += "<td[row_options1]>[severity_to_string[severity]]</font></td>"
html += "<td[row_options2]><A align='right' href='?src=\ref[src];select_event=1;severity=[severity]'>[EM ? EM.name : "Nothing"]</A></td>"
html += "<td><A align='right' href='?src=\ref[src];set_name=\ref[new_event]'>[new_event.name ? new_event.name : "Enter Event"]</A></td>"
html += "<td><A align='right' href='?src=\ref[src];set_type=\ref[new_event]'>[new_event.event_type ? new_event.event_type : "Select Type"]</A></td>"
html += "<td><A align='right' href='?src=\ref[src];set_weight=\ref[new_event]'>[new_event.weight ? new_event.weight : 0]</A></td>"
html += "<td><A align='right' href='?src=\ref[src];set_oneshot=\ref[new_event]'>[new_event.one_shot]</A></td>"
html += "</tr>"
html += "</table>"
html += "</div>"
html += "</table>"
html += "<A align='right' href='?src=\ref[src];add=\ref[selected_event_container]'>Add</A><br>"
html += "</div>"
else
html += "<A align='right' href='?src=\ref[src];toggle_report=1'>Round End Report: [report_at_round_end ? "On": "Off"]</A><br>"
html += "<div class='block'>"
html += "<h2>Event Start</h2>"
html += "<table[table_options]>"
html += "<tr><td[row_options1]>Severity</td><td[row_options1]>Starts At</td><td[row_options1]>Starts In</td><td[row_options3]>Adjust Start</td><td[row_options1]>Pause</td><td[row_options1]>Interval Mod</td></tr>"
for(var/severity = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
var/datum/event_container/EC = event_containers[severity]
var/next_event_at = max(0, EC.next_event_time - world.time)
html += "<tr>"
html += "<td>[severity_to_string[severity]]</td>"
html += "<td>[worldtime2text(max(EC.next_event_time, world.time))]</td>"
html += "<td>[round(next_event_at / 600, 0.1)]</td>"
html += "<td>"
html += "<A align='right' href='?src=\ref[src];dec_timer=2;event=\ref[EC]'>--</A>"
html += "<A align='right' href='?src=\ref[src];dec_timer=1;event=\ref[EC]'>-</A>"
html += "<A align='right' href='?src=\ref[src];inc_timer=1;event=\ref[EC]'>+</A>"
html += "<A align='right' href='?src=\ref[src];inc_timer=2;event=\ref[EC]'>++</A>"
html += "</td>"
html += "<td>"
html += "<A align='right' href='?src=\ref[src];pause=\ref[EC]'>[EC.delayed ? "Resume" : "Pause"]</A>"
html += "</td>"
html += "<td>"
html += "<A align='right' href='?src=\ref[src];interval=\ref[EC]'>[EC.delay_modifier]</A>"
html += "</td>"
html += "</tr>"
html += "</table>"
html += "</div>"
html += "<div class='block'>"
html += "<h2>Next Event</h2>"
html += "<table[table_options]>"
html += "<tr><td[row_options1]>Severity</td><td[row_options2]>Name</td><td[row_options3]>Event Rotation</td><td>Clear</td></tr>"
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 += "<tr>"
html += "<td>[severity_to_string[severity]]</td>"
html += "<td><A align='right' href='?src=\ref[src];select_event=\ref[EC]'>[EM ? EM.name : "Random"]</A></td>"
html += "<td><A align='right' href='?src=\ref[src];view_events=\ref[EC]'>View</A></td>"
html += "<td><A align='right' href='?src=\ref[src];clear=\ref[EC]'>Clear</A></td>"
html += "</tr>"
html += "</table>"
html += "</div>"
html += "<div class='block'>"
html += "<h2>Running Events</h2>"
html += "Estimated times, affected by master controller delays."
html += "<table[table_options]>"
html += "<tr><td[row_options1]>Severity</td><td[row_options2]>Name</td><td[row_options1]>Ends At</td><td[row_options1]>Ends In</td><td[row_options3]>Stop</td></tr>"
for(var/datum/event/E in active_events)
if(!E.event_meta)
continue
var/datum/event_meta/EM = E.event_meta
var/ends_at = E.startedAt + (E.lastProcessAt() * master_controller.minimum_ticks) // A best estimate
var/ends_in = max(0, round((ends_at - world.time) / 600, 0.1))
html += "<tr>"
html += "<td>[severity_to_string[EM.severity]]</td>"
html += "<td>[EM.name]</td>"
html += "<td>[worldtime2text(ends_at)]</td>"
html += "<td>[ends_in]</td>"
html += "<td><A align='right' href='?src=\ref[src];stop=\ref[E]'>Stop</A></td>"
html += "</tr>"
html += "</table>"
html += "</div>"
return html
@@ -219,28 +184,95 @@ 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"])))
if(href_list["toggle_report"])
report_at_round_end = !report_at_round_end
admin_log_and_message_admins("has [report_at_round_end ? "enabled" : "disabled"] the round end event report.")
else if(href_list["dec_timer"])
var/datum/event_container/EC = locate(href_list["event"])
var/decrease = (60 * RaiseToPower(10, text2num(href_list["dec_timer"])))
EC.next_event_time -= decrease
admin_log_and_message_admins("decreased timer for [severity_to_string[EC.severity]] events by [decrease/600] minute(s).")
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"])
var/increase = (60 * RaiseToPower(10, text2num(href_list["inc_timer"])))
EC.next_event_time += increase
admin_log_and_message_admins("increased timer for [severity_to_string[EC.severity]] events by [increase/600] minute(s).")
else if(href_list["select_event"])
SelectEvent(severity)
var/datum/event_container/EC = locate(href_list["select_event"])
var/datum/event_meta/EM = EC.SelectEvent()
if(EM)
admin_log_and_message_admins("has queued the [severity_to_string[EC.severity]] event '[EM.name]'.")
else if(href_list["pause"])
var/datum/event_container/EC = locate(href_list["pause"])
EC.delayed = !EC.delayed
admin_log_and_message_admins("has [EC.delayed ? "paused" : "resumed"] countdown for [severity_to_string[EC.severity]] events.")
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
admin_log_and_message_admins("has set the interval modifier for [severity_to_string[EC.severity]] events to [EC.delay_modifier].")
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"])
var/datum/event_meta/EM = E.event_meta
admin_log_and_message_admins("has stopped the [severity_to_string[EM.severity]] event '[EM.name]'.")
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
if(EM != new_event)
admin_log_and_message_admins("has changed the weight of the [severity_to_string[EM.severity]] event '[EM.name]' to [EM.weight].")
else if(href_list["toggle_oneshot"])
var/datum/event_meta/EM = locate(href_list["toggle_oneshot"])
EM.one_shot = !EM.one_shot
if(EM != new_event)
admin_log_and_message_admins("has [EM.one_shot ? "set" : "unset"] the oneshot flag for the [severity_to_string[EM.severity]] event '[EM.name]'.")
else if(href_list["toggle_enabled"])
var/datum/event_meta/EM = locate(href_list["toggle_enabled"])
EM.enabled = !EM.enabled
admin_log_and_message_admins("has [EM.enabled ? "enabled" : "disabled"] the [severity_to_string[EM.severity]] event '[EM.name]'.")
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
admin_log_and_message_admins("has removed the [severity_to_string[EM.severity]] event '[EM.name]'.")
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
admin_log_and_message_admins("has added \a [severity_to_string[new_event.severity]] event '[new_event.name]' of type [new_event.event_type] with weight [new_event.weight].")
new_event = new
else if(href_list["clear"])
var/datum/event_container/EC = locate(href_list["clear"])
if(EC.next_event)
admin_log_and_message_admins("has unqueued the [severity_to_string[EC.severity]] event '[EC.next_event.name]'.")
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)
/client/proc/forceEvent(var/type in event_manager.allEvents)
set name = "Trigger Event (Debug Only)"
set category = "Debug"
@@ -259,13 +291,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

View File

@@ -1,5 +1,4 @@
/datum/event/grid_check //NOTE: Times are measured in master controller ticks!
name = "Grid Check"
announceWhen = 5
/datum/event/grid_check/setup()

View File

@@ -14,7 +14,6 @@
#define VERM_SPIDERS 2
/datum/event/infestation
name = "Vermin Infestation"
announceWhen = 10
endWhen = 11
var/location

View File

@@ -1,7 +1,6 @@
//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:04
/datum/event/ionstorm
name = "Ion Storm"
var/botEmagChance = 0.5
var/list/players = list()

View File

@@ -2,7 +2,6 @@
//meteor storms are much heavier
/datum/event/meteor_wave
name = "Meteor Wave"
startWhen = 6
endWhen = 33
@@ -21,7 +20,6 @@
//
/datum/event/meteor_shower
name = "Meteor Shower"
startWhen = 5
endWhen = 7
var/next_meteor = 6

View File

@@ -1,7 +1,6 @@
/var/global/account_hack_attempted = 0
/datum/event/money_hacker
name = "Money Hacker"
var/datum/money_account/affected_account
endWhen = 100
var/end_time

View File

@@ -1,5 +1,4 @@
/datum/event/money_lotto
name = "Money Lotto"
var/winner_name = "John Smith"
var/winner_sum = 0
var/deposit_success = 0

View File

@@ -1,5 +1,4 @@
/datum/event/pda_spam
name = "PDA Spam"
endWhen = 36000
var/last_spam_time = 0
var/obj/machinery/message_server/useMS

View File

@@ -1,7 +1,5 @@
/datum/event/prison_break
name = "Prison Break"
announceWhen = 50
oneShot = 1
var/releaseWhen = 25
var/list/area/prisonAreas = list()

View File

@@ -1,11 +1,9 @@
/datum/event/radiation_storm
name = "Radiation Storm"
var/const/enterBelt = 60
var/const/leaveBelt = 170
var/const/revokeAccess = 230
endWhen = revokeAccess
oneShot = 1
var/postStartTicks

View File

@@ -1,6 +1,4 @@
/datum/event/rogue_drone
name = "Rogue Drones"
startWhen = 10
endWhen = 1000
var/list/drones_list = list()

View File

@@ -1,5 +1 @@
/datum/event/space_ninja
name = "Space Ninja"
/datum/event/space_ninja/setup()
space_ninja_arrival()

View File

@@ -1,9 +1,5 @@
/var/global/spacevines_spawned = 0
/datum/event/spacevine
name = "Space Vines"
oneShot = 1
/datum/event/spacevine/start()
//biomass is basically just a resprited version of space vines
if(prob(50))

View File

@@ -1,9 +1,7 @@
/var/global/sent_spiders_to_station = 0
/datum/event/spider_infestation
name = "Large Spider Infestation"
announceWhen = 400
oneShot = 1
var/spawncount = 1

View File

@@ -1,6 +1,3 @@
/datum/event/spontaneous_appendicitis
name = "Communicatinos Blackout"
/datum/event/spontaneous_appendicitis/start()
for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) if(H.client && H.stat != DEAD)
var/foundAlready = 0 //don't infect someone that already has the virus

View File

@@ -1,5 +1,4 @@
datum/event/viral_infection/setup()
name = "Viral Outbreak"
announceWhen = rand(0, 3000)
endWhen = announceWhen + 1

View File

@@ -1,5 +1,4 @@
datum/event/wallrot/setup()
name = "Wallroot"
announceWhen = rand(0, 300)
endWhen = announceWhen + 1