mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-28 10:12:01 +00:00
Some functional updates to events: **Comms Blackouts:** Now has a variant (min. 6 pop, engineering-weighted) which gives each machine a 10% chance to take a little integrity damage. Additionally, Telecomms Processors now factor their integrity damage into their ability to decompress messages, so this alternative comms blackout might cause radio transmissions (either global or for a given department) to start getting a little garbled- not enough to genuinely impede comms, but enough to justify Engi to fix them up. **Prison Break:** Given how rarely we actually have people sitting around in the prison waiting for breakouts over the course of a given round, this event has been changed to be more akin to the existing Containment events- the entire department (minus armory, nuke storage, checkpoints, etc.) are at risk of lights blown, access issues, etc. Just a little more variety added to the mix. **Space Vines:** Minimum 4 pop to fire. Shouldn't matter much in the grand scheme of things, just reduces annoyance factor for extremely low-pop if they roll some vines that fuck them up. Will look into refactoring that event so that the danger factor of the vines increases with population, and remove the min pop requirement again. **Drone Revolution:** Minimum 4 pop to fire. Again, shouldn't matter much in the grand scheme of things but this highest tier event will seriously fuck up anyone who latejoins and uses the maints to, say, help set the ship up during low pop! No I'm not salty! **Electrical Storm:** Refactored this and restored the Mundane and Major variants. While we want this event to keep Engineers on their toes and provide openings for people to break regs if they so wished, most of the event is theater (lots of flickering lights now!) While the Mundane and Moderate variants are mostly flavorful and will just give Engineers a few excuses to visit different departments and RP with people, Major events will be your 'all hands on deck' affairs (as Major events are ought) and in very rare circumstances could even cascade into more serious issues. Did a ton of unit testing on this and feel very good about how each variant actually looks, will make any additional tweaks if needed once we see how it plays with an actual population! The Event Probabilities sheet was also very out of date, missing Comet Expulsion, had the old Viral Outbreak, lots of old values, etc. Updated all the events, and also updated the % formulas to factor in minimum population- changing the 'Assumed Personnel' values at the top to a level below the minimum population for a given event will now correctly set its probability to 0%, making it clearer what actual odds are given different pop levels. I also don't think pop_needed was working correctly: various changes in there to get it behaving. Obv this PR grew in scope from outset and touches a small handful of different things, so lmk anything to mix and match and change and drop. !review
295 lines
8.3 KiB
Plaintext
295 lines
8.3 KiB
Plaintext
/datum/event_meta
|
|
var/name = ""
|
|
|
|
///Whether or not the event is available for random selection at all
|
|
var/enabled = TRUE
|
|
|
|
///The base weight of this event. A zero means it may never fire, but see get_weight()
|
|
var/weight = 0
|
|
|
|
///The minimum weight that this event will have. Only used if non-zero
|
|
var/min_weight = 0
|
|
|
|
///The maximum weight that this event will have. Only use if non-zero
|
|
var/max_weight = 0
|
|
|
|
///The current severity of this event
|
|
var/severity = 0
|
|
|
|
///If TRUE, then the event will not be re-added to the list of available events
|
|
var/one_shot = FALSE
|
|
|
|
///If TRUE, add back to the queue of events upon finishing
|
|
var/add_to_queue = TRUE
|
|
|
|
var/list/role_weights = list()
|
|
|
|
///Minimum amount of jobs required for the event to fire
|
|
var/list/minimum_job_requirement = list()
|
|
|
|
///Minimum amount of player_list mobs for this to fire
|
|
var/pop_requirement = 1
|
|
|
|
/// A lazylist of gamemodes during which this event won't fire
|
|
var/list/excluded_gamemodes
|
|
|
|
var/datum/event/event_type
|
|
|
|
/datum/event_meta/New(event_severity, event_name, datum/event/type, event_weight, list/job_weights,
|
|
is_one_shot = FALSE, min_event_weight = 0, max_event_weight = 0, list/excluded_roundtypes,
|
|
add_to_queue = TRUE, list/minimum_job_requirement_list, pop_needed = 1)
|
|
|
|
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
|
|
src.add_to_queue = add_to_queue
|
|
pop_requirement = pop_needed
|
|
if(job_weights)
|
|
role_weights = job_weights
|
|
if(minimum_job_requirement_list)
|
|
minimum_job_requirement = minimum_job_requirement_list
|
|
if(excluded_roundtypes)
|
|
excluded_gamemodes = excluded_roundtypes
|
|
|
|
/datum/event_meta/proc/get_weight(list/active_with_role)
|
|
if(!enabled)
|
|
return 0
|
|
|
|
var/n = 0
|
|
for (var/mob/living in GLOB.player_list)
|
|
n++
|
|
if(n <= pop_requirement)
|
|
return 0
|
|
|
|
if(LAZYISIN(excluded_gamemodes, SSticker.mode.name))
|
|
// There's no way it'll be run this round anyways.
|
|
enabled = FALSE
|
|
return 0
|
|
|
|
var/job_weight = 0
|
|
var/minimum_met = TRUE
|
|
if(minimum_job_requirement)
|
|
for(var/role in minimum_job_requirement)
|
|
if(active_with_role[role] >= minimum_job_requirement[role])
|
|
minimum_met = TRUE
|
|
else
|
|
minimum_met = FALSE
|
|
if(minimum_met)
|
|
for(var/role in role_weights)
|
|
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 non-zero
|
|
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 //NOTE: Times are measured in master controller ticks!
|
|
|
|
///When in the lifetime to call start()
|
|
var/startWhen = 0
|
|
|
|
///When in the lifetime to call announce()
|
|
var/announceWhen = 0
|
|
|
|
///When in the lifetime the event should end
|
|
var/endWhen = 0
|
|
|
|
///Severity. Lower means less severe, higher means more severe. Does not have to be supported. Is set on New()
|
|
var/severity = 0
|
|
|
|
///How long the event has existed. You don't need to change this
|
|
var/activeFor = 0
|
|
|
|
///If this event is currently running. You should not change this
|
|
var/isRunning = TRUE
|
|
|
|
///When this event started
|
|
var/startedAt = 0
|
|
|
|
///When this event ended
|
|
var/endedAt = 0
|
|
|
|
var/datum/event_meta/event_meta = null
|
|
var/list/affecting_z
|
|
|
|
///If set to TRUE, this event will not be picked for false announcements
|
|
///This should really only be used for events that have no announcement
|
|
var/no_fake = FALSE
|
|
|
|
///A lore-suitable name that maintains the mystery, used for faking events
|
|
var/ic_name = null
|
|
|
|
///If TRUE, this event is a dummy instance used for retrieving values, it should not run or add/remove itself from any lists
|
|
var/dummy = FALSE
|
|
|
|
///used for events that run secondary announcements, like releasing maint access
|
|
var/two_part = FALSE
|
|
|
|
var/has_skybox_image = FALSE
|
|
var/obj/effect/overmap/visitable/ship/affected_ship
|
|
var/announce_to_sensor_console = FALSE
|
|
|
|
/datum/event/nothing
|
|
no_fake = 1
|
|
|
|
///Called first before processing.
|
|
///Allows you to setup your event, such as randomly
|
|
///setting the startWhen and or announceWhen variables.
|
|
///Only called once.
|
|
/datum/event/proc/setup()
|
|
return
|
|
|
|
///Called when the tick is equal to the startWhen variable.
|
|
///Allows you to start before announcing or vice versa.
|
|
///Only called once.
|
|
/datum/event/proc/start()
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
if(has_skybox_image)
|
|
SSskybox.rebuild_skyboxes(affecting_z)
|
|
announce_start()
|
|
|
|
///Called when the tick is equal to the announceWhen variable.
|
|
///Allows you to announce before starting or vice versa.
|
|
///Only called once.
|
|
/datum/event/proc/announce()
|
|
return
|
|
|
|
/datum/event/proc/announce_start()
|
|
if(announce_to_sensor_console)
|
|
send_sensor_message("Entering [ic_name].")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/event/proc/announce_end(var/faked)
|
|
if(announce_to_sensor_console)
|
|
send_sensor_message("Exiting [ic_name].")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
///Called on or after the tick counter is equal to startWhen.
|
|
///You can include code related to your event or add your own
|
|
///time stamped events.
|
|
///Called more than once.
|
|
/datum/event/proc/tick()
|
|
return
|
|
|
|
///Called on or after the tick is equal or more than endWhen
|
|
///You can include code related to the event ending.
|
|
///Do not place spawn() in here, instead use tick() to check for
|
|
///the activeFor variable.
|
|
///For example: if(activeFor == myOwnVariable + 30) doStuff()
|
|
///Only called once.
|
|
///faked indicates this is a false alarm. Used to prevent announcements and other things from happening during false alarms.
|
|
/datum/event/proc/end(var/faked)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
announce_end(faked)
|
|
|
|
///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
|
|
/datum/event/process()
|
|
SHOULD_NOT_OVERRIDE(TRUE)
|
|
|
|
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.
|
|
if(activeFor >= lastProcessAt())
|
|
kill()
|
|
|
|
activeFor++
|
|
|
|
///Called when start(), announce() and end() has all been called
|
|
/datum/event/proc/kill(failed_to_spawn = FALSE)
|
|
// If this event was forcefully killed run end() for individual cleanup
|
|
|
|
if(!dummy && isRunning)
|
|
end()
|
|
|
|
if(failed_to_spawn)
|
|
var/datum/event_container/killed_ec = SSevents.event_containers[severity]
|
|
killed_ec.start_event()
|
|
|
|
isRunning = 0
|
|
endedAt = world.time
|
|
|
|
if(has_skybox_image)
|
|
SSskybox.rebuild_skyboxes(affecting_z)
|
|
|
|
if(!dummy)
|
|
SSevents.active_events -= src
|
|
SSevents.event_complete(src)
|
|
|
|
|
|
/datum/event/New(datum/event_meta/EM = null, is_dummy = 0, obj/effect/overmap/visitable/ship/overmap_ship, obj/effect/overmap/event/overmap_hazard)
|
|
dummy = is_dummy
|
|
event_meta = EM
|
|
if (event_meta)
|
|
severity = event_meta.severity
|
|
if(severity < EVENT_LEVEL_MUNDANE) severity = EVENT_LEVEL_MUNDANE
|
|
if(severity > EVENT_LEVEL_MAJOR) severity = EVENT_LEVEL_MAJOR
|
|
else
|
|
severity = EVENT_LEVEL_MODERATE//Fixes runtime errors with admin triggered events
|
|
|
|
if (dummy)
|
|
return
|
|
|
|
setup()
|
|
if(overmap_ship && overmap_hazard)
|
|
setup_for_overmap(overmap_ship, overmap_hazard)
|
|
|
|
if(!affecting_z)
|
|
affecting_z = SSmapping.levels_by_trait(ZTRAIT_STATION)
|
|
|
|
// event needs to be responsible for this, as stuff like APLUs currently make their own events for curious reasons
|
|
SSevents.active_events += src
|
|
startedAt = world.time
|
|
|
|
..()
|
|
|
|
/datum/event/proc/location_name()
|
|
if(!SSatlas.current_map.use_overmap)
|
|
return station_name()
|
|
|
|
var/obj/effect/overmap/O = GLOB.map_sectors["[pick(affecting_z)]"]
|
|
return O ? O.name : "Unknown Location"
|
|
|
|
/datum/event/proc/get_skybox_image()
|
|
return
|
|
|
|
/datum/event/proc/setup_for_overmap(obj/effect/overmap/visitable/ship/ship, obj/effect/overmap/event/hazard)
|
|
startWhen = 0
|
|
endWhen = INFINITY
|
|
affecting_z = ship.map_z
|
|
affected_ship = ship
|
|
announce_to_sensor_console = istype(ship, /obj/effect/overmap/visitable/ship/landable)
|
|
if(announce_to_sensor_console)
|
|
announceWhen = -1
|
|
ic_name = hazard.name
|
|
|
|
/datum/event/proc/send_sensor_message(message)
|
|
for(var/obj/machinery/computer/ship/sensors/console in affected_ship.consoles)
|
|
console.display_message(message)
|