/datum/event_manager
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/datum/event_meta/new_event = new
/datum/event_manager/New()
allEvents = typesof(/datum/event) - /datum/event
/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)
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, 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
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)
var/html = GetInteractWindow()
var/datum/browser/popup = new(user, "event_manager", "Event Manager", window_x, window_y)
popup.set_content(html)
popup.open()
/datum/event_manager/proc/RoundEnd()
if(!report_at_round_end)
return
world << "
Random Events This Round:"
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 = "Refresh"
if(selected_event_container)
var/event_time = max(0, selected_event_container.next_event_time - world.time)
html += "Back
"
html += "Time till start: [round(event_time / 600, 0.1)]
"
html += "
"
html += "
Available [severity_to_string[selected_event_container.severity]] Events (queued & running 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 += "
Add Event
"
html += "
"
html += "
Add"
html += "
"
else
html += "Round End Report: [report_at_round_end ? "On": "Off"]
"
html += ""
html += "
Event Start
"
html += "
"
html += "| Severity | Starts At | Starts In | Adjust Start | Pause | Interval Mod |
"
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 += ""
html += "| [severity_to_string[severity]] | "
html += "[worldtime2text(max(EC.next_event_time, world.time))] | "
html += "[round(next_event_at / 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 += "| Severity | Name | Event Rotation | Clear |
"
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 += "Estimated times, affected by master controller delays."
html += "
"
html += "| Severity | Name | Ends At | Ends In | Stop |
"
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 += ""
html += "| [severity_to_string[EM.severity]] | "
html += "[EM.name] | "
html += "[worldtime2text(ends_at)] | "
html += "[ends_in] | "
html += "Stop | "
html += "
"
html += "
"
html += "
"
return html
/datum/event_manager/Topic(href, href_list)
if(..())
return
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"])
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"])
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)
/client/proc/forceEvent(var/type in event_manager.allEvents)
set name = "Trigger Event (Debug Only)"
set category = "Debug"
if(!holder)
return
if(ispath(type))
new type(new /datum/event_meta(EVENT_LEVEL_MAJOR))
message_admins("[key_name_admin(usr)] has triggered an event. ([type])", 1)
/client/proc/event_manager_panel()
set name = "Event Manager Panel"
set category = "Admin"
if(event_manager)
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