Event system refactor and changes (#29420)

* meta resolution

* emerald resolution

* delta resolution

* fartgas resolution

* box box

* stay out stay out

* metastation fixes

* faragus fix

* delta fix

* Changes to role impact on event weight

* adds disaster level to the event config

* weight changes and starts adding disaster level to the ui

* ui fixes

* adjust disaster level timing

* changes disaster timing, weights, disease outbreak role requirements and weights

* lots of weight an requirement adjustments

* Update tear.dm

* some fixes

* meta changes

* Starting over with farragus

* Starting over in faragus

* faragus changes

* Update cerestation.dmm

* Update cerestation.dmm

* Update cerestation.dmm

* Update cerestation.dmm

* Update cerestation.dmm

* resolving some faragus conflicts

* resolve faragus conflicts

* resolves delta conflicts

* resolves cyberiad conflicts

* resolves emerald conflicts

* fixes cables in faragus

* fixes meta cables

* fixes delta cables

* more meta fixes

* more farragus cable fixes

* more cable fixes

* meta and faragus fixes

* box and delta fixes

* more mapping fixes

* hopefully the last fix

* Update metastation.dmm

* Update metastation.dmm

* fixes shorts on cyberiad cerebron and farragus

* CI fixes

* move new event listing to new system

* Adds tracking and cost calculation for blob

* finishes setting up blob event detection and costs

* minor boolog corrections

* fixes events being created at the wrong severity

* adds ongoing cost to disease outbreak

* moves terror spider event to new system

* moves to component based event cost calculation

* morph abductor and carps adjusted for new system

* various fixes and adjusts rev event

* Update revenant_spawn_event.dm

* various fixes and adjusts demon incursion to the new system

* adjusts some major event weights

* correct wrong values of autoend on vendor uprising and rev

* Update event_container.dm

* more event timing adjustments

* adds requirements to traders and incursion

* slightly lowers requirements for biohazards

* timing changes

* temporarily disable loading event times from the config and increases major nothing chance

* adjustments to costs and weights of various events

* Update event_container.dm

* additional adjustments to weights and requirements. moves rev to major

* typo fix

* ion storm adjustment

* Update event_container.dm

* more moderate changes

* e

* Update meteors_event.dm

* removes cooldown from nothing event and changes its weight based on the number of remaining enabled events in the container

* increases morph event requirements and chance of nothing moderate event

* makes morph a major event

* Update morph_event.dm

* adds viro requirement for disease outbreak and fixes a bug with incorrect resource calculation

* allows varediting extra roles for the event system for debug and testing

* Adjust weights of traders and abductors and corrects wrong nominal severity for demonic incursion

* Adds crew cound to rev weight

* makes disasters start rolling later

* reduces weight of communications blackout and increases weight of major nothing

* adjusts door runtime and prisonbreak weights to make them less frequent. kudzu now scales with total crew

* apc overload made less frequent

* oopsy

* Gives the scrubber clog event a name

* fixes a type in a define name

* adjusts demonic incursion weight

* changes brand intelligence weight an d reduces door runtime weight

* more adjustments to demon incursion. Makes additional weight from surplus roles diminish

* adjustments to some minor events

* Increases event length and requirements of some engineering events and lowers their weight slightly. Also increases cost of ongoing diseases events

* fixes a type

* Update meteors_event.dm

* corrects traders nominal severity and adjusts demon weights

* shifts anomaly weights down and increases costs

* rebalance rod requirements

* Update cerestation.dmm

* moves net resource calculation to its own proc and changes the ASSIGNMENT_TOTAL macro to ASSIGNMENT_CREW.

* Adds individual first run time for some events and makes majors start rolling slightly later

* reduces weight of major nothing

* minor reduction to rev and apc overload weight

* Changes the way event weight is calculated

* end time corrections for anomaly rod and meteors

* slightly adjusts down the weights of nothing and some minor events

* Adjusts moedrates towards about 3.5 per round and mundanes towards 8 per round

* adds first run restrictions on traders and incursion and increases the cooldown time of events

* resolve faragus conflicts

* resolve emerald conflict

* fix some faragus cabling

* more cabling correction in faragus

* more cable fixes

* Update cerestation.dmm

* remove doubled scrubber pipe on tile

* reduces moderates nothing chance

* slightly reduces crew requirements for disasters and also reduces crew weight for disasters

* fixes meteor event not removing the alert, and makes it announce a bit later

* Adds an event debugging window for real time midround event data

* Revert "Adds an event debugging window for real time midround event data"

This reverts commit ecd99a6c9e.

* Adds a resource view button to the event manager window and fixes a null in the total resource list

* various bug fixes

* slightly lowers chance of meteor and similar events

* Slightly lowers requirement weights on disaster level events

* resolves faragus conflict

* changes the default power input of engineering SMES to 200kw and 80kW respectively

* connects power monitoring computers to the grid that weren't

* meta station elec maints improvements

* adds missing power monitoring computers on box and delta

* removes dirt from wall

* corrects area boundry on meta

* adds missing cable on box sci

* removes dirt from wall on box

* connects cyberiad bridge to the rest of the powernet

* connects box brig to powernet

* Adds catwalks to box maints

* adds catwalks to meta

* Adds catwalks to delta

* Update deltastation.dmm

* adds ability to insulate cables

* Moves stations to using extra insulated cables for high power network

* Removes catwalks from meta

* Removes catwalks from box

* Removes catwalks from delta

* Delays moderates and majors more and increases disaster chance

* resolves box conflicts

* Update cable.dm

* remove floating request console

* corrects position of fire alarm and removes extra intercom on metastation

* resolves faragus conflict

* reduces meteor variant weights. meaty ores event now has the correct nominal severity

* meaty ore weight to 8

* fixes a stray light bulb and light switch in maints as well as a doubled power

* Delays meteor type events to 40 minutes at the earliest. Moves the time check to be against round time instead of world time

* wires kerberos security checkpoint to the grid

* Update cerestation.dmm

* Removes stray extinguisher cabinet from meta station

* resolves area conflict on faragus

* resolves more faragus issues

* fixes faragus cabling issues

* Update cerestation.dmm

* removes another stray fire extinguisher cabinet

* insulates the APC in delta PTL room

* increases pop requirement and weight for demons and increases medbay and viro weights for diseases

* connect delta fore starboard solars to the high power grid instead of the low power

* Update deltastation.dmm

* deconflict

* solves some unconnected cables

* connects delta customs to network and finishes resolving conflicts

* Update deltastation.dmm

* adds the new cables. needs coils and mapping

* moves connection perms to the heavy duty cables. toggled with engineering permission ID. box gets new cables

* sorts cables on stations

* faragus cable connections

* cable corrections. Adds heavy duty cables to the autolathe

* CI fix

* more fixes and makes the new cables show up on t ray scanners

* box station mapping fixes

* delta mapping fixes

* meta fix

* Update deltastation.dmm

* delta and faragus fixes

* Update emeraldstation.dmm

* removes APC overloard(major) from event pool

* adds diagonal sprites to heavy duty cables. allows sillicons to toggle them and

* Makes borg versions of the heavy duty cable coil

* palete consolidation

* Improves visibility of high power cables

* converts shuttle event to new system

* makes disaster event last run calc use round time instead of world time

* fixes wrong define being used in some event requirements. further increases requirements for demons and meteors. lowers weight of major diseases

* Update slaughterevent.dm

* reduces cargo requirements for shuttle load event

* reduces base weight of major disease event and further increases medical requirements

* fixes a wrong wire under the pet store maints door in delta station

* resolve mapping conflicts

* Revert "resolve mapping conflicts"

This reverts commit 129db52501.

* Revert "Merge branch 'HighPowerMaints' into event_timing"

This reverts commit 2594ac8928, reversing
changes made to a738b5f2f2.

* fixes some wonky stuff with xeno code

* Adds a crew cost to diseases

* makes player contribution towards events variable

* changes major event weights and slightly increases demon requirements

* slightly increases major disease outbreak weight

* comment changes

* Adds safeties to protect against null events getting into container or the active list

* blob fix

* Adds a confirmation to random event toggle

* Adjust particulate event weight to fit the new moderate weights

* Adds additional security costs to changeling and vamp

* Update revenant_spawn_event.dm

* uses correct path for rev event cost proc

* changes some lists to alists

* correctly accesses the event container list and actually uses the config for the event timing

---------

Co-authored-by: FunnyMan3595 (Charlie Nolan) <funnyman3595@gmail.com>
Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
This commit is contained in:
Migratingcocofruit
2025-11-07 16:29:47 +00:00
committed by GitHub
co-authored by FunnyMan3595 warriorstar-orion
parent bee4f00416
commit e609a7faf7
102 changed files with 1029 additions and 290 deletions
+3
View File
@@ -988,6 +988,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_SERVER|R_EVENT))
return
if(tgui_alert(usr, "[GLOB.configuration.event.enable_random_events ? "Disable" : "Enable"] random events?", "Confirm", list("Yes", "No")) != "Yes")
return
if(!GLOB.configuration.event.enable_random_events)
GLOB.configuration.event.enable_random_events = TRUE
to_chat(usr, "Random events enabled")
@@ -607,4 +607,7 @@ GLOBAL_LIST_EMPTY(antagonists)
other_team.add_antag_objective(red_team)
red_team.pair_up(blue_team, TRUE)
/datum/antagonist/proc/antag_event_resource_cost()
return list(ASSIGNMENT_SECURITY = 1)
#undef SUCCESSFUL_DETACH
@@ -49,3 +49,6 @@
messages.Add("<span class='userdanger'>You are a scientist of [our_team.name]!</span>")
messages.Add("<span class='boldnotice'>With the help of your teammate, kidnap and experiment on station crew members! Use your tool and ship consoles to support the agent and retrieve humanoid specimens.</span>")
return messages
/datum/antagonist/abductor/antag_event_resource_cost()
return list(ASSIGNMENT_SECURITY = 1.5)
@@ -473,3 +473,7 @@ RESTRICT_TYPE(/datum/antagonist/changeling)
/datum/antagonist/changeling/custom_blurb()
return "We awaken on the [station_name()], [get_area_name(owner.current, TRUE)]...\nWe have our tasks to attend to..."
// Ling Stronk
/datum/antagonist/changeling/antag_event_resource_cost()
return list(ASSIGNMENT_SECURITY = 3)
@@ -409,3 +409,7 @@ RESTRICT_TYPE(/datum/antagonist/vampire)
/datum/antagonist/vampire/custom_blurb()
return "On the date [GLOB.current_date_string], at [station_time_timestamp()],\n in the [station_name()], [get_area_name(owner.current, TRUE)]...\nThe hunt begins again..."
// Ramps up as you get more powerfull
/datum/antagonist/vampire/antag_event_resource_cost()
return list(ASSIGNMENT_SECURITY = 1 + bloodtotal / 500)
@@ -1,4 +1,5 @@
/datum/event/economic_event
name = "Economic News"
endWhen = 50 // this will be set randomly, later
announceWhen = 15
var/datum/event_news/economic/news_story
@@ -1,4 +1,5 @@
/datum/event/mundane_news
name = "Mundane News"
endWhen = 10
/datum/event/mundane_news/announce()
@@ -19,6 +20,7 @@
NC.alert_news(message.title)
/datum/event/trivial_news
name = "Trivial News"
endWhen = 10
/datum/event/trivial_news/announce()
+18 -1
View File
@@ -1,4 +1,20 @@
/datum/event/abductor
name = "Abductor Visit"
noAutoEnd = TRUE
nominal_severity = EVENT_LEVEL_MAJOR
role_weights = list(ASSIGNMENT_SECURITY = 5)
role_requirements = list(ASSIGNMENT_SECURITY = 3)
var/datum/team/abductor/ayys
var/spawned = FALSE
/datum/event/abductor/process()
if(ayys && length(ayys.members) && spawned)
kill()
return ..()
/// abductor costs are calculated independently of event
/datum/event/abductor/event_resource_cost()
return list()
/datum/event/abductor/start()
INVOKE_ASYNC(src, PROC_REF(try_makeAbductorTeam))
@@ -23,7 +39,8 @@
mind.active = TRUE
minds += mind
var/datum/team/abductor/ayys = new /datum/team/abductor(minds)
ayys = new /datum/team/abductor(minds)
ayys.create_agent()
ayys.create_scientist()
spawned = TRUE
return TRUE
+19 -1
View File
@@ -1,9 +1,16 @@
GLOBAL_LIST_INIT(xeno_things, list("xenos" = list(), "eggs" = list()))
/datum/event/alien_infestation
announceWhen = 400
name = "Alien Infestation"
announceWhen = 400
noAutoEnd = TRUE
var/highpop_trigger = 80
var/spawncount = 2
var/list/playercount
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
nominal_severity = EVENT_LEVEL_DISASTER
role_weights = list(ASSIGNMENT_SECURITY = 3, ASSIGNMENT_CREW = 0.9, ASSIGNMENT_MEDICAL = 3)
role_requirements = list(ASSIGNMENT_SECURITY = 4, ASSIGNMENT_CREW = 50, ASSIGNMENT_MEDICAL = 4)
/datum/event/alien_infestation/setup()
announceWhen = rand(announceWhen, announceWhen + 50)
@@ -14,6 +21,17 @@
else
log_and_message_admins("Warning: Could not spawn any mobs for event Alien Infestation")
/datum/event/alien_infestation/process()
// Check for completion every minute
if(!activeFor % 30)
if(successSpawn && !length(event_category_cost(EVENT_XENOS)))
kill()
. = ..()
/// Xeno costs are calculated independently from the event itself
/datum/event/alien_infestation/event_resource_cost()
return list()
/datum/event/alien_infestation/start()
playercount = length(GLOB.clients)//grab playercount when event starts not when game starts
if(playercount >= highpop_trigger) //spawn with 4 if highpop
+3 -1
View File
@@ -1,7 +1,9 @@
/datum/event/anomaly/anomaly_bluespace
name = "Anomaly event"
name = "Bluespace Anomaly"
startWhen = 3
announceWhen = 10
anomaly_path = /obj/effect/anomaly/bluespace
prefix_message = "Unstable bluespace anomaly detected on long range scanners."
announce_sound = 'sound/AI/anomaly_bluespace.ogg'
role_weights = list(ASSIGNMENT_SCIENCE = 1, ASSIGNMENT_ENGINEERING = 1)
role_requirements = list(ASSIGNMENT_SCIENCE = 1, ASSIGNMENT_ENGINEERING = 2)
+1 -1
View File
@@ -1,5 +1,5 @@
/datum/event/anomaly/anomaly_cryo
name = "Anomaly event"
name = "Cryo Anomaly"
startWhen = 3
announceWhen = 10
anomaly_path = /obj/effect/anomaly/cryo
+14 -2
View File
@@ -2,6 +2,10 @@
/datum/event/anomaly
name = "Anomaly: Energetic Flux"
nominal_severity = EVENT_LEVEL_MODERATE
noAutoEnd = TRUE
role_weights = list(ASSIGNMENT_SCIENCE = 1, ASSIGNMENT_ENGINEERING = 1)
role_requirements = list(ASSIGNMENT_SCIENCE = 1, ASSIGNMENT_ENGINEERING = 1)
var/obj/effect/anomaly/anomaly_path = /obj/effect/anomaly/flux
var/turf/target_turf
announceWhen = 1
@@ -9,8 +13,15 @@
var/prefix_message = "Localized hyper-energetic flux wave detected on long range scanners."
/// Sound effect used
var/announce_sound = 'sound/AI/anomaly_flux.ogg'
var/spawned = FALSE
/datum/event/anomaly/tick()
if(spawned && QDELETED(anomaly_path))
// Add 15 minutes for cleanup
endWhen = activeFor + 450
noAutoEnd = FALSE
/datum/event/anomaly/setup()
target_turf = find_targets(TRUE)
@@ -45,7 +56,8 @@
GLOB.minor_announcement.Announce("[prefix_message] Expected location: [target.name].", "Anomaly Alert", announce_sound)
/datum/event/anomaly/start()
var/newAnomaly = new anomaly_path(target_turf)
announce_to_ghosts(newAnomaly)
anomaly_path = new anomaly_path(target_turf)
announce_to_ghosts(anomaly_path)
spawned = TRUE
#undef TURF_FIND_TRIES
+1 -1
View File
@@ -1,4 +1,4 @@
/datum/event/anomaly/anomaly_flux
name = "Anomaly event"
name = "Flux Anomaly"
startWhen = 10
announceWhen = 3
+1 -1
View File
@@ -1,5 +1,5 @@
/datum/event/anomaly/anomaly_grav
name = "Anomaly event"
name = "Gravitational Anomaly"
startWhen = 3
announceWhen = 20
anomaly_path = /obj/effect/anomaly/grav
+1 -1
View File
@@ -1,5 +1,5 @@
/datum/event/anomaly/anomaly_pyro
name = "Anomaly event"
name = "Pyro Anomaly"
startWhen = 3
announceWhen = 10
anomaly_path = /obj/effect/anomaly/pyro
+3 -1
View File
@@ -1,7 +1,9 @@
/datum/event/anomaly/anomaly_vortex
name = "Anomaly event"
name = "Vortex Anomaly"
startWhen = 10
announceWhen = 3
anomaly_path = /obj/effect/anomaly/bhole
prefix_message = "Localized high-intensity vortex anomaly detected on long range scanners."
announce_sound = 'sound/AI/anomaly_vortex.ogg'
role_weights = list(ASSIGNMENT_SCIENCE = 1, ASSIGNMENT_ENGINEERING = 1)
role_requirements = list(ASSIGNMENT_SCIENCE = 1, ASSIGNMENT_ENGINEERING = 3)
+5 -1
View File
@@ -1,6 +1,10 @@
#define APC_BREAK_PROBABILITY 25 // the probability that a given APC will be broken
/datum/event/apc_overload
name = "APC Overload"
nominal_severity = EVENT_LEVEL_MAJOR
role_weights = list(ASSIGNMENT_ENGINEERING = 4, ASSIGNMENT_CREW = 0.5)
role_requirements = list(ASSIGNMENT_ENGINEERING = 5, ASSIGNMENT_CREW = 30)
var/const/announce_after_mc_ticks = 5
var/const/delayed = FALSE
var/const/event_max_duration_mc_ticks = announce_after_mc_ticks * 2
@@ -9,7 +13,7 @@
announceWhen = announce_after_mc_ticks
/datum/event/apc_overload/setup()
endWhen = rand(event_min_duration_mc_ticks, event_max_duration_mc_ticks)
endWhen = rand(event_min_duration_mc_ticks, event_max_duration_mc_ticks) + 2700
/datum/event/apc_overload/start()
apc_overload_failure(announce=delayed)
+7 -2
View File
@@ -1,14 +1,19 @@
#define APC_BREAK_PROBABILITY 25 // the probability that a given APC will be disabled
/datum/event/apc_short
var/const/announce_after_mc_ticks = 5
name = "APC Short"
// Keeps engies busy for a while
role_weights = list(ASSIGNMENT_ENGINEERING = 3)
role_requirements = list(ASSIGNMENT_ENGINEERING = 3)
nominal_severity = EVENT_LEVEL_MODERATE
var/const/announce_after_mc_ticks = 5
var/const/event_max_duration_mc_ticks = announce_after_mc_ticks * 2
var/const/event_min_duration_mc_ticks = announce_after_mc_ticks
announceWhen = announce_after_mc_ticks
/datum/event/apc_short/setup()
endWhen = rand(event_min_duration_mc_ticks, event_max_duration_mc_ticks)
endWhen = rand(event_min_duration_mc_ticks, event_max_duration_mc_ticks) + 1800
/datum/event/apc_short/start()
power_failure(announce = FALSE)
+11
View File
@@ -25,6 +25,12 @@
/mob/living/basic/blob/Initialize(mapload)
. = ..()
GLOB.blob_minions |= src
AddComponent(/datum/component/event_tracker, EVENT_BLOB)
/mob/living/basic/blob/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 3, ASSIGNMENT_MEDICAL = 0.5)
/mob/living/basic/blob/Destroy()
GLOB.blob_minions -= src
@@ -209,6 +215,11 @@
if(name == "blobbernaut")
name = "blobbernaut ([rand(1, 1000)])"
/mob/living/basic/blob/blobbernaut/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 3, ASSIGNMENT_MEDICAL = 0.5)
/datum/action/innate/communicate_overmind_blob
name = "Speak with the overmind"
button_icon = 'icons/mob/guardian.dmi'
@@ -34,6 +34,10 @@
var/image/C = new('icons/mob/blob.dmi', "blob_core_overlay")
overlays += C
/obj/structure/blob/core/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 2, ASSIGNMENT_CREW = 15, ASSIGNMENT_MEDICAL = 2)
/obj/structure/blob/core/Destroy()
if(overmind)
@@ -27,4 +27,9 @@ GLOBAL_VAR_INIT(spores_active, 0)
if(overmind)
overmind.add_mob_to_overmind(BS)
/obj/structure/blob/factory/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 0.33, ASSIGNMENT_CREW = 1)
#undef MAX_GLOBAL_SPORES
@@ -33,3 +33,8 @@
Pulse(5, i, color)
obj_integrity = min(max_integrity, obj_integrity + 1)
color = null
/obj/structure/blob/node/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 0.1, ASSIGNMENT_CREW = 1)
+6
View File
@@ -35,6 +35,12 @@ GLOBAL_LIST_EMPTY(blob_minions)
COMSIG_ATOM_ENTERED = PROC_REF(on_atom_entered)
)
AddElement(/datum/element/connect_loc, loc_connections)
AddComponent(/datum/component/event_tracker, EVENT_BLOB)
/obj/structure/blob/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_CREW = 0.07)
/obj/structure/blob/Destroy()
if(atmosblock)
+32 -4
View File
@@ -1,7 +1,14 @@
/datum/event/blob
announceWhen = 180
endWhen = 240
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
name = "Blob"
announceWhen = 180
noAutoEnd = TRUE
nominal_severity = EVENT_LEVEL_DISASTER
role_weights = list(ASSIGNMENT_SECURITY = 2, ASSIGNMENT_CREW = 0.7, ASSIGNMENT_MEDICAL = 2)
role_requirements = list(ASSIGNMENT_SECURITY = 3, ASSIGNMENT_CREW = 45, ASSIGNMENT_MEDICAL = 3)
/// So we don't make a command report if nothing gets spawned.
var/successSpawn = FALSE
/// List of all blob cores and blob mice related to this event
var/list/blob_things = list("cores" = list(), "mice" = 0)
/datum/event/blob/announce(false_alarm)
if(successSpawn || false_alarm)
@@ -12,6 +19,15 @@
/datum/event/blob/start()
INVOKE_ASYNC(src, PROC_REF(make_blob))
/datum/event/blob/process()
if(!(length(blob_things["cores"]) + blob_things["mice"]) && successSpawn)
return kill()
return ..()
/// Blob costs are calculated independently from the event itself
/datum/event/blob/event_resource_cost()
return list()
/datum/event/blob/proc/make_blob()
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blob infested mouse?", ROLE_BLOB, TRUE, source = /mob/living/basic/mouse/blobinfected)
if(!length(candidates))
@@ -29,7 +45,8 @@
B.mind.special_role = SPECIAL_ROLE_BLOB
B.forceMove(vent)
B.add_ventcrawl(vent)
RegisterSignal(B, COMSIG_BLOB_MOUSE_BURST, PROC_REF(record_core))
blob_things["mice"]++
// Mark it on antag HUD
var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_BLOB]
antaghud.join_hud(B.mind.current)
@@ -40,3 +57,14 @@
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B, action = NOTIFY_FOLLOW)
successSpawn = TRUE
SSevents.biohazards_this_round += BIOHAZARD_BLOB
/datum/event/blob/proc/record_core(atom/source, obj/structure/blob/core/core)
SIGNAL_HANDLER // COMSIG_BLOB_MOUSE_BURST
if(core)
blob_things["cores"] += list(core)
RegisterSignal(core, COMSIG_PARENT_QDELETING, PROC_REF(remove_core))
blob_things["mice"]--
/datum/event/blob/proc/remove_core(obj/structure/blob/core/source)
if(source)
blob_things["cores"] -= source
+6 -2
View File
@@ -1,6 +1,10 @@
/datum/event/brand_intelligence
name = "Brand Intelligence"
nominal_severity = EVENT_LEVEL_MODERATE
role_weights = list(ASSIGNMENT_ENGINEERING = 1, ASSIGNMENT_CREW = 0.4)
role_requirements = list(ASSIGNMENT_ENGINEERING = 2, ASSIGNMENT_CREW = 10)
noAutoEnd = TRUE
announceWhen = 21
endWhen = 1000 //Ends when all vending machines are subverted anyway.
var/list/obj/machinery/economy/vending/vendingMachines = list()
var/list/obj/machinery/economy/vending/infectedMachines = list()
@@ -47,7 +51,7 @@
log_debug("Original brand intelligence machine: [originMachine] ([ADMIN_VV(originMachine,"VV")]) [ADMIN_JMP(originMachine)]")
/datum/event/brand_intelligence/tick()
if(originMachine.shut_up || originMachine.wires.is_all_cut()) //if the original vending machine is missing or has it's voice switch flipped
if(originMachine?.shut_up || originMachine?.wires.is_all_cut()) //if the original vending machine is missing or has it's voice switch flipped
origin_machine_defeated()
return
@@ -1,4 +1,5 @@
/datum/event/bureaucratic_error
name = "Bureaucratic Error"
announceWhen = 1
/// Jobs that are not allowed to be picked for the bureaucratic error
var/list/blacklisted_jobs = list(
+4
View File
@@ -1,3 +1,7 @@
/datum/event/camera_failure
name = "Camera Failure"
role_weights = list(ASSIGNMENT_ENGINEERING = 10)
/datum/event/camera_failure/start()
var/failed_cameras
var/failure_limit = rand(1, 3)
+28 -4
View File
@@ -1,14 +1,35 @@
/datum/event/carp_migration
name = "Carp Migration"
announceWhen = 50
endWhen = 900
noAutoEnd = TRUE
nominal_severity = EVENT_LEVEL_MODERATE
role_weights = list(ASSIGNMENT_ENGINEERING = 1, ASSIGNMENT_SECURITY = 2)
role_requirements = list(ASSIGNMENT_ENGINEERING = 1, ASSIGNMENT_SECURITY = 1.5)
nominal_severity = EVENT_LEVEL_MODERATE
var/list/spawned_mobs = list(
/mob/living/basic/carp = 95,
/mob/living/basic/carp/megacarp = 5)
/// Carps spawned by the event
var/list/my_carps = list()
/// Did we manage to spawn carps
var/spawned = FALSE
/datum/event/carp_migration/process()
if(!length(my_carps) && spawned)
kill()
return ..()
// Resource calculation independent of event
/datum/event/carp_migration/event_resource_cost()
return list()
/datum/event/carp_migration/proc/remove_carp(mob/source)
SIGNAL_HANDLER // COMSIG_MOB_DEATH
my_carps -= source
UnregisterSignal(source, COMSIG_MOB_DEATH)
/datum/event/carp_migration/setup()
announceWhen = rand(40, 60)
endWhen = rand(600, 1200)
/datum/event/carp_migration/announce()
var/announcement = ""
@@ -40,5 +61,8 @@
var/group_size = rand(group_size_min, group_size_max)
for(var/j = 1, j <= group_size, j++)
var/carptype = pickweight(spawned_mobs)
new carptype(spawn_locations[i])
var/mob/carp = new carptype(spawn_locations[i])
RegisterSignal(carp, COMSIG_MOB_DEATH, PROC_REF(remove_carp))
my_carps += carp
spawned = TRUE
i++
+1
View File
@@ -2,6 +2,7 @@
name = "disposals clog"
startWhen = 10
endWhen = 35
nominal_severity = EVENT_LEVEL_MODERATE
var/notify_title = "Clogged Disposals"
var/notify_image = "disposal-flush"
var/list/bins = list()
@@ -1,3 +1,7 @@
/datum/event/communications_blackout
name = "Communication Blackout"
nominal_severity = EVENT_LEVEL_MODERATE
/datum/event/communications_blackout/announce(false_alarm)
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?-BZZZT", \
+27 -2
View File
@@ -2,8 +2,10 @@
name = "demon incursion"
/// Corresponds to the number of process() runs the event has lasted for. Roughly 2 minutes here.
announceWhen = 60
/// Corresponds to the number of process() runs the event has lasted for. Roughly 2 minutes here.
endWhen = 60
noAutoEnd = TRUE
role_weights = list(ASSIGNMENT_SECURITY = 4, ASSIGNMENT_CREW = 1, ASSIGNMENT_MEDICAL = 2)
role_requirements = list(ASSIGNMENT_SECURITY = 3, ASSIGNMENT_CREW = 35, ASSIGNMENT_MEDICAL = 3)
nominal_severity = EVENT_LEVEL_MAJOR
/// The name of the notification for dchat
var/notify_title = "Demonic Incursion"
/// The icon of the notification
@@ -12,6 +14,17 @@
var/list/portal_list = list()
/// The target number of portals
var/target_portals = 100
/// Toggled when the first portal is spawned
var/spawned = FALSE
/datum/event/demon_incursion/tick()
if(!length(portal_list) && spawned)
kill()
// Costs are calculated independently of event
/datum/event/demon_incursion/event_resource_cost()
return list()
/datum/event/demon_incursion/setup()
impact_area = findEventArea()
@@ -55,6 +68,7 @@
if(length(portal_list) > target_portals)
target_portals *= 2
prepare_spawn_elite()
spawned = TRUE
/datum/event/demon_incursion/proc/prepare_spawn_elite()
var/obj/structure/spawner/nether/demon_incursion/elite_portal = pick(portal_list)
@@ -148,6 +162,17 @@
if(turf_to_spread)
spread_turf()
SSticker.mode.incursion_portals += src
AddComponent(/datum/component/event_tracker, EVENT_DEMONIC)
/obj/structure/spawner/nether/demon_incursion/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 1, ASSIGNMENT_CREW = 5, ASSIGNMENT_MEDICAL = 1)
/obj/structure/spawner/nether/demon_incursion/Destroy()
if(linked_incursion)
linked_incursion.portal_list -= src
. = ..()
/obj/structure/spawner/nether/demon_incursion/examine(mob/user)
. = ..()
+16 -3
View File
@@ -2,8 +2,12 @@ GLOBAL_LIST_EMPTY(current_pending_diseases)
/datum/event/disease_outbreak
// We only want the announcement to happen after the virus has spawned on station
announceWhen = -1
// Keep the event running until we announce it
// Keep the event running for as long as we have infected
noAutoEnd = TRUE
name = "Disease Outbreak"
role_weights = list(ASSIGNMENT_MEDICAL = 5, ASSIGNMENT_VIROLOGIST = 5, ASSIGNMENT_BOTANIST = 2, ASSIGNMENT_CHEMIST = 2)
role_requirements = list(ASSIGNMENT_MEDICAL = 4, ASSIGNMENT_VIROLOGIST = 1, ASSIGNMENT_BOTANIST = 0, ASSIGNMENT_CHEMIST = 1)
nominal_severity = EVENT_LEVEL_MODERATE
/// The type of disease that patient zero will be infected with.
var/datum/disease/chosen_disease
@@ -17,6 +21,7 @@ GLOBAL_LIST_EMPTY(current_pending_diseases)
var/static/list/diseases_moderate_major = list()
var/force_disease_time = 300
var/list/infected_players = list()
var/first_infection = FALSE
/datum/event/disease_outbreak/setup()
if(isemptylist(diseases_minor) && isemptylist(diseases_moderate_major))
@@ -57,10 +62,10 @@ GLOBAL_LIST_EMPTY(current_pending_diseases)
GLOB.minor_announcement.Announce("Moderate contagion detected aboard [station_name()].", new_sound = 'sound/misc/notice2.ogg', new_title = "Contagion Alert")
if(EVENT_LEVEL_MUNDANE)
GLOB.minor_announcement.Announce("Minor contagion detected aboard [station_name()].", new_sound = 'sound/misc/notice2.ogg', new_title = "Contagion Alert")
// We did our announcement, the event no longer needs to run
kill()
/datum/event/disease_outbreak/process()
if(length(infected_players) > 0)
first_infection = TRUE
if(activeFor == force_disease_time)
for(var/list/disease_event in GLOB.current_pending_diseases)
if(chosen_disease == disease_event["disease"])
@@ -71,8 +76,16 @@ GLOBAL_LIST_EMPTY(current_pending_diseases)
break
if(length(infected_players) > 2 && announceWhen <= 0)
announceWhen = activeFor + 180
// The event ends when everyone is cured
if(length(infected_players) <= 0 && first_infection)
kill()
. = ..()
/// Cost of ongoing disease outbreak. 1 medical personnal per 2 infected at major severity.
/datum/event/disease_outbreak/event_resource_cost()
return list("[ASSIGNMENT_MEDICAL]" = (severity / nominal_severity) * (length(infected_players) / 3), "[ASSIGNMENT_VIROLOGIST]" = 1)
//Creates a virus with a harmful effect, guaranteed to be spreadable by contact or airborne
/datum/event/disease_outbreak/proc/create_virus(max_severity = 6)
var/datum/disease/advance/A = new /datum/disease/advance(_event = UID())
+3
View File
@@ -1,4 +1,7 @@
/datum/event/door_runtime
name = "Door Runtime"
role_weights = list(ASSIGNMENT_CREW = 0.2)
role_requirements = list(ASSIGNMENT_CREW = 0)
/datum/event/door_runtime/announce()
GLOB.minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert", 'sound/AI/door_runtimes.ogg')
+4
View File
@@ -1,4 +1,8 @@
/datum/event/electrical_storm
name = "Electrical Storm"
nominal_severity = EVENT_LEVEL_MODERATE
role_weights = list(ASSIGNMENT_ENGINEERING = 4, ASSIGNMENT_JANITOR = 3)
role_requirements = list(ASSIGNMENT_ENGINEERING = 3, ASSIGNMENT_JANITOR = 1)
var/lightsoutAmount = 1
var/lightsoutRange = 25
+71 -29
View File
@@ -1,44 +1,50 @@
/datum/event_meta
var/name = ""
var/name = ""
/// Whether or not the event is available for random selection at all.
var/enabled = TRUE
var/enabled = TRUE
/// The base weight of this event. A zero means it may never fire, but see get_weight()
var/weight
/// The minimum weight that this event will have. Only used if non-zero.
var/min_weight
/// The maximum weight that this event will have.
var/max_weight
/// the current severity of this event
var/severity
/// If true, then the event will not be re-added to the list of available events
var/one_shot
/// A modifier applied to all event weights (role and base), respects min and max
var/weight_mod = 1
/// A list of roles that add weight to the event
var/list/role_weights = list()
var/datum/event/event_type
/// Event held by this meta event. Used to do things like calculate weight.
var/datum/event/skeleton
/// How early this specific event can run
var/first_run_time = 0
/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 = INFINITY)
name = event_name
severity = event_severity
event_type = type
/datum/event_meta/New(event_severity, type, event_weight, is_one_shot = FALSE, min_event_weight = 0, max_event_weight = INFINITY, _first_run_time)
if(type)
skeleton = new type(EM = src, skeleton = TRUE, _severity = event_severity)
name = skeleton.name
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
first_run_time = _first_run_time
/datum/event_meta/proc/get_weight(list/active_with_role)
if(!enabled)
/datum/event_meta/proc/change_event(type)
var/event_severity = 0
if(skeleton)
event_severity = skeleton.severity
skeleton.event_meta = null
qdel(skeleton)
skeleton = new type(EM = src, skeleton = TRUE, _severity = event_severity)
/datum/event_meta/proc/get_weight(list/total_resources)
if(!enabled || !skeleton)
return 0
var/job_weight = 0
for(var/role in role_weights)
if(role in active_with_role)
job_weight += active_with_role[role] * role_weights[role]
return clamp((weight + job_weight) * weight_mod, min_weight, max_weight)
var/resource_effect = skeleton.get_weight(total_resources)
var/new_weight = weight
if(resource_effect > 0)
new_weight *= (1.003 ** resource_effect)
if(resource_effect < 0)
new_weight *= 0.95 ** -resource_effect
return clamp((new_weight) * weight_mod, min_weight, max_weight)
/*/datum/event_meta/ninja/get_weight(var/list/active_with_role)
if(toggle_space_ninja)
@@ -57,6 +63,8 @@
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
/// The severity the event has normally
var/nominal_severity = EVENT_LEVEL_MUNDANE
/// 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.
@@ -70,8 +78,29 @@
/// The area the event will hit
var/area/impact_area
var/datum/event_meta/event_meta = null
/// The base weight of each role on the event for the purpose of calculating event weight and resource cost
var/list/role_weights = list()
/// A baseline requirement of different roles the event has at it's nominal severity
var/list/role_requirements = list()
/datum/event/nothing
name = "Nothing"
/datum/event/nothing/has_cooldown()
return FALSE
/datum/event/nothing/is_relative()
return TRUE
/// Calculate the weight for rolling the event based on round circumstances.
/datum/event/proc/get_weight(list/total_resources)
var/job_weight = 0
for(var/role in role_weights)
var/role_available = total_resources[role] ? total_resources[role] : 0
var/difference = (role_available - role_requirements[role] * (severity / nominal_severity)) * role_weights[role]
// We add difference if it's negative, or the square root if it's positive
job_weight += difference
return job_weight
/**
* Called first before processing.
@@ -177,18 +206,27 @@
SSevents.active_events -= src
SSevents.event_complete(src)
/datum/event/New(datum/event_meta/EM, skeleton = FALSE)
// Events have cooldown by default
/datum/event/proc/has_cooldown()
return TRUE
/datum/event/proc/is_relative()
return FALSE
/datum/event/New(datum/event_meta/EM, skeleton = FALSE, _severity)
// event needs to be responsible for this, as stuff like APLUs currently make their own events for curious reasons
if(!skeleton)
SSevents.active_events += src
if(!EM)
EM = new /datum/event_meta(EVENT_LEVEL_MAJOR, "Unknown, Most likely admin called", src.type)
event_meta = EM
severity = event_meta.severity
if(severity < EVENT_LEVEL_MUNDANE) severity = EVENT_LEVEL_MUNDANE
if(severity > EVENT_LEVEL_MAJOR) severity = EVENT_LEVEL_MAJOR
severity = _severity ? _severity : nominal_severity
if(severity < EVENT_LEVEL_MUNDANE)
severity = EVENT_LEVEL_MUNDANE
log_debug("Event of '[type]' with severity below mundane run has run")
if(severity > EVENT_LEVEL_DISASTER)
severity = EVENT_LEVEL_DISASTER
log_debug("Event of '[type]' with severity above disaster has run")
startedAt = world.time
@@ -208,3 +246,7 @@
/// If this proc returns TRUE, the regular Announce() won't be called.
/datum/event/proc/fake_announce()
return FALSE
/// The amount of people in different roles needed to handle an ongoing event.
/datum/event/proc/event_resource_cost()
return role_requirements
+154 -129
View File
@@ -1,16 +1,4 @@
#define ASSIGNMENT_ANY "Any"
#define ASSIGNMENT_AI "AI"
#define ASSIGNMENT_CYBORG "Cyborg"
#define ASSIGNMENT_ENGINEER "Engineer"
#define ASSIGNMENT_BOTANIST "Botanist"
#define ASSIGNMENT_JANITOR "Janitor"
#define ASSIGNMENT_MEDICAL "Medical"
#define ASSIGNMENT_SCIENTIST "Scientist"
#define ASSIGNMENT_SECURITY "Security"
#define ASSIGNMENT_CHEMIST "Chemist"
#define ASSIGNMENT_CARGO "Cargo Bay"
GLOBAL_LIST_INIT(severity_to_string, list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT_LEVEL_MODERATE = "Moderate", EVENT_LEVEL_MAJOR = "Major"))
GLOBAL_LIST_INIT(severity_to_string, alist(EVENT_LEVEL_MUNDANE = "Mundane", EVENT_LEVEL_MODERATE = "Moderate", EVENT_LEVEL_MAJOR = "Major", EVENT_LEVEL_DISASTER = "Disaster"))
GLOBAL_LIST_EMPTY(event_last_fired)
/datum/event_container
@@ -23,6 +11,12 @@ GLOBAL_LIST_EMPTY(event_last_fired)
var/datum/event_meta/next_event = null
var/last_world_time = 0
/// Records the initial amount of events in the available event list
var/initial_event_count = 0
/datum/event_container/New()
. = ..()
initial_event_count = length(available_events)
/datum/event_container/process()
if(!next_event_time)
@@ -47,38 +41,48 @@ GLOBAL_LIST_EMPTY(event_last_fired)
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
new next_event.skeleton.type(next_event, _severity = next_event.skeleton.severity) // Events are added and removed from the processing queue in their New/kill procs
log_debug("Starting event '[next_event.name]' of severity [GLOB.severity_to_string[severity]].")
SSblackbox.record_feedback("nested tally", "events", 1, list(GLOB.severity_to_string[severity], next_event.name))
log_debug("Starting event '[next_event.skeleton.name]' of severity [GLOB.severity_to_string[severity]].")
SSblackbox.record_feedback("nested tally", "events", 1, list(GLOB.severity_to_string[severity], next_event.skeleton.name))
GLOB.event_last_fired[next_event] = world.time
next_event = null // When set to null, a random event will be selected next time
var/datum/event_meta/meta = next_event
next_event = null // When set to null, a random event will be selected next time
// Used for checks about the event we just ran
return meta
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(length(available_events) == 0)
return
var/active_with_role = number_active_with_role()
// A list of the net available resources of each department depending on staffing and active threats/events
var/list/total_resources = get_total_resources()
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
var/event_weight = EM.get_weight(total_resources)
// We use the amount of non disabled events to adjust the value of Nothing, so we count 0 weight events
if(EM.enabled && EM.first_run_time < world.time - SSticker.time_game_started)
possible_events[EM] = max(event_weight, 0)
// For events like nothing we want to have their weight adjusted depending on how many events are left of the original list
if(EM.skeleton.is_relative())
possible_events[EM] *= (length(available_events) / initial_event_count)
for(var/event_meta in last_event_time) if(possible_events[event_meta])
var/time_passed = world.time - GLOB.event_last_fired[event_meta]
var/half_of_round = GLOB.configuration.event.expected_round_length / 2
var/weight_modifier = min(1, 1 - ((half_of_round - time_passed) / half_of_round))
//With this formula, an event ran 30 minutes ago has half weight, and an event ran an hour ago, has 100 % weight. This works better in general for events, as super high weight events are impacted in a meaningful way.
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
for(var/datum/event_meta/event_meta in last_event_time)
if(!event_meta.skeleton)
continue
if(event_meta.skeleton.has_cooldown() && possible_events[event_meta])
var/time_passed = world.time - GLOB.event_last_fired[event_meta]
var/cooldown = GLOB.configuration.event.expected_round_length / 2
var/weight_modifier = 1 - max(0, 0.5 * ((cooldown - time_passed) / cooldown))
// Events that just ran have their base weight reduced by half, tapering to no reduction over half an hour
var/new_weight = max(possible_events[event_meta] * weight_modifier, 0)
if(new_weight)
possible_events[event_meta] = new_weight
if(length(possible_events) == 0)
return null
@@ -88,6 +92,23 @@ GLOBAL_LIST_EMPTY(event_last_fired)
available_events -= picked_event
return picked_event
/datum/event_container/proc/get_playercount_modifier()
switch(length(GLOB.player_list))
if(0 to 10)
return 1.1
if(11 to 15)
return 1.05
if(16 to 25)
return 1
if(26 to 35)
return 0.95
if(36 to 50)
return 0.9
if(50 to 80)
return 0.85
if(80 to 10000)
return 0.8
/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 && GLOB.configuration.event.first_run_times[severity])
@@ -97,30 +118,14 @@ GLOBAL_LIST_EMPTY(event_last_fired)
next_event_time = world.time + event_delay
// Otherwise, follow the standard setup process
else
var/playercount_modifier = 1
switch(length(GLOB.player_list))
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 50)
playercount_modifier = 0.8
if(50 to 80)
playercount_modifier = 0.7
if(80 to 10000)
playercount_modifier = 0.6
playercount_modifier = playercount_modifier * delay_modifier
var/event_delay = rand(GLOB.configuration.event.delay_lower_bound[severity], GLOB.configuration.event.delay_upper_bound[severity]) * playercount_modifier
var/event_delay = calculate_event_delay()
next_event_time = world.time + event_delay
log_debug("Next event of severity [GLOB.severity_to_string[severity]] in [(next_event_time - world.time)/600] minutes.")
/datum/event_container/proc/calculate_event_delay()
return rand(GLOB.configuration.event.delay_lower_bound[severity], GLOB.configuration.event.delay_upper_bound[severity]) * delay_modifier * get_playercount_modifier()
/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)
@@ -135,98 +140,118 @@ GLOBAL_LIST_EMPTY(event_last_fired)
severity = EVENT_LEVEL_MUNDANE
available_events = list(
// Severity level, event name, event type, base weight, role weights, one shot, min weight, max weight. Last two only used if set.
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Nothing", /datum/event/nothing, 1100),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "PDA Spam", /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), FALSE, 25, 50),
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, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Sentience", /datum/event/sentience, 50),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Fungal Growth", /datum/event/wallrot/fungus, 50, list(ASSIGNMENT_CHEMIST = 50)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Koi School", /datum/event/carp_migration/koi, 80),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Camera Failure", /datum/event/camera_failure, 100, list(ASSIGNMENT_ENGINEER = 10)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Fake Virus", /datum/event/fake_virus, 50),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Bureaucratic Error",/datum/event/bureaucratic_error, 40, TRUE),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Disease Outbreak", /datum/event/disease_outbreak, 50, list(ASSIGNMENT_MEDICAL = 25), TRUE)
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/nothing, 252),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/pda_spam, 9),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/economic_event, 7),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/trivial_news, 7),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/mundane_news, 7),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/infestation, 11),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/sentience, 15),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/wallrot, 10),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/wallrot/fungus, 10),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/carp_migration/koi, 12),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/camera_failure, 12),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/fake_virus, 12),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/bureaucratic_error, 12, TRUE),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, /datum/event/disease_outbreak, 12, TRUE)
)
/datum/event_container/moderate
severity = EVENT_LEVEL_MODERATE
available_events = list(
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Nothing", /datum/event/nothing, 1230),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "False Alarm", /datum/event/falsealarm, 200),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 10), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 200, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SECURITY = 20), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 0, list(ASSIGNMENT_SECURITY = 20)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Vines", /datum/event/spacevine, 250, list(ASSIGNMENT_ENGINEER = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Solar Flare", /datum/event/solar_flare, 0, list(ASSIGNMENT_ENGINEER = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ores", /datum/event/dust/meaty, 0, list(ASSIGNMENT_ENGINEER = 20)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/nothing, 800),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/falsealarm, 20),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/spontaneous_appendicitis, 5, TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/carp_migration, 10, , TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/rogue_drone, 7),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/spacevine, 15),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/meteor_wave, 8, _first_run_time = 40 MINUTES),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/solar_flare, 12),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/dust/meaty, 8, _first_run_time = 40 MINUTES),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/communications_blackout, 10),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/prison_break, 7),
//new /datum/event_meta(EVENT_LEVEL_MODERATE, "Virology Breach", /datum/event/prison_break/virology, 0, list(ASSIGNMENT_MEDICAL = 100)),
//new /datum/event_meta(EVENT_LEVEL_MODERATE, "Xenobiology Breach", /datum/event/prison_break/xenobiology, 0, list(ASSIGNMENT_SCIENCE = 100)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "APC Short", /datum/event/apc_short, 200, list(ASSIGNMENT_ENGINEER = 60)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 25, list(ASSIGNMENT_MEDICAL = 50), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ion_storm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/apc_short, 12),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/electrical_storm, 12),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/radiation_storm, 10, TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/spider_infestation, 10, TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/ion_storm, 10),
//new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 15), TRUE),
// NON-BAY EVENTS
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Mass Hallucination", /datum/event/mass_hallucination, 300),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Brand Intelligence", /datum/event/brand_intelligence, 50, list(ASSIGNMENT_ENGINEER = 25), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Dimensional Tear", /datum/event/tear, 0, list(ASSIGNMENT_SECURITY = 35)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Honknomoly", /datum/event/tear/honk, 0, list(ASSIGNMENT_SECURITY = 15)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vent Clog", /datum/event/vent_clog, 250),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Disposals Clog", /datum/event/disposals_clog, 250),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Wormholes", /datum/event/wormholes, 150),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 75, list(ASSIGNMENT_ENGINEER = 60)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Cryo Anomaly", /datum/event/anomaly/anomaly_cryo, 75, list(ASSIGNMENT_ENGINEER = 60)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vortex Anomaly", /datum/event/anomaly/anomaly_vortex, 75, list(ASSIGNMENT_ENGINEER = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 75, list(ASSIGNMENT_ENGINEER = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 75, list(ASSIGNMENT_ENGINEER = 50)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Revenant", /datum/event/revenant, 150),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/spawn_morph, 40, list(ASSIGNMENT_SECURITY = 10), is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Disease Outbreak", /datum/event/disease_outbreak, 50, list(ASSIGNMENT_MEDICAL = 30), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Door Runtime", /datum/event/door_runtime, 50, list(ASSIGNMENT_ENGINEER = 25, ASSIGNMENT_AI = 150), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Tourist Arrivals", /datum/event/tourist_arrivals, 100, list(ASSIGNMENT_SECURITY = 15), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Shuttle Loan", /datum/event/shuttle_loan, 100, list(ASSIGNMENT_CARGO = 15, ASSIGNMENT_SECURITY = 10), is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Anomalous Particulate", /datum/event/anomalous_particulate_event, 250, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/mass_hallucination, 10),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/brand_intelligence, 5, TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/tear, 15),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/tear/honk, 10),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/vent_clog, 12),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/disposals_clog, 12),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/wormholes, 15),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/anomaly/anomaly_pyro, 7),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/anomaly/anomaly_cryo, 7),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/anomaly/anomaly_vortex, 7),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/anomaly/anomaly_bluespace, 7),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/anomaly/anomaly_flux, 7),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/anomaly/anomaly_grav, 7),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/disease_outbreak, 15, TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/door_runtime, 10, TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/tourist_arrivals, 40, TRUE, _first_run_time = 35 MINUTES),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/shuttle_loan, 50, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, /datum/event/anomalous_particulate_event, 60, is_one_shot = TRUE),
)
/datum/event_container/major
severity = EVENT_LEVEL_MAJOR
available_events = list(
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 590),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 10, list(ASSIGNMENT_SECURITY = 3), TRUE),
//new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ANY = 5)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "APC Overload", /datum/event/apc_overload, 0),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 20, list(ASSIGNMENT_ENGINEER = 4), TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 10), TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Abductor Visit", /datum/event/abductor, 20, list(ASSIGNMENT_SECURITY = 3), TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 15, list(ASSIGNMENT_SECURITY = 3), TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Traders", /datum/event/traders, 85, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Terror Spiders", /datum/event/spider_terror, 15, list(ASSIGNMENT_SECURITY = 3), TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 20, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Shadow Demon", /datum/event/spawn_slaughter/shadow, 20, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Demonic Incursion", /datum/event/demon_incursion, 20, list(ASSIGNMENT_SECURITY = 3)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Immovable Rod", /datum/event/immovable_rod, 0, list(ASSIGNMENT_ENGINEER = 10), TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Disease Outbreak", /datum/event/disease_outbreak, 15, list(ASSIGNMENT_MEDICAL = 4), TRUE),
//new /datum/event_meta(EVENT_LEVEL_MAJOR, "Floor Cluwne", /datum/event/spawn_floor_cluwne, 15, is_one_shot = TRUE)
//new /datum/event_meta(EVENT_LEVEL_MAJOR, "Pulse Demon Infiltration", /datum/event/spawn_pulsedemon, 20, is_one_shot = TRUE)
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/nothing, 275),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/carp_migration, 13, TRUE),
//new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/prison_break/station, 10),
//new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/apc_overload, 11),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/meteor_wave, 9, TRUE, _first_run_time = 40 MINUTES),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/abductor, 12, TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/traders, 13, is_one_shot = TRUE, _first_run_time = 35 MINUTES),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_slaughter, 8, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_slaughter/shadow, 8, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/immovable_rod, 9, TRUE, _first_run_time = 40 MINUTES),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/demon_incursion, 10, TRUE, _first_run_time = 35 MINUTES),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/disease_outbreak, 8, TRUE),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/revenant, 9),
new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_morph, 16, is_one_shot = TRUE),
//new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_floor_cluwne, 15, is_one_shot = TRUE)
//new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_pulsedemon, 20, is_one_shot = TRUE)
)
// The weights here are set up to roll an event about 1 in 3 rounds, assuming you roll as much as possible
/datum/event_container/disaster
severity = EVENT_LEVEL_DISASTER
available_events = list(
new /datum/event_meta(EVENT_LEVEL_DISASTER, /datum/event/nothing, 5730),
new /datum/event_meta(EVENT_LEVEL_DISASTER, /datum/event/blob, 100, TRUE),
new /datum/event_meta(EVENT_LEVEL_DISASTER, /datum/event/alien_infestation, 100, TRUE),
new /datum/event_meta(EVENT_LEVEL_DISASTER, /datum/event/spider_terror, 100, TRUE)
)
var/activation_counter = 0
var/event_rolls = 0
#undef ASSIGNMENT_ANY
#undef ASSIGNMENT_AI
#undef ASSIGNMENT_CYBORG
#undef ASSIGNMENT_ENGINEER
#undef ASSIGNMENT_BOTANIST
#undef ASSIGNMENT_JANITOR
#undef ASSIGNMENT_MEDICAL
#undef ASSIGNMENT_SCIENTIST
#undef ASSIGNMENT_SECURITY
#undef ASSIGNMENT_CHEMIST
#undef ASSIGNMENT_CARGO
/datum/event_container/disaster/get_playercount_modifier()
return 1
/datum/event_container/disaster/acquire_event()
// We should only be getting one none nothing disaster roll per round, and doing it this way leaves more room for admins to play around with it.
if(activation_counter > 0)
for(var/datum/event_meta/meta in available_events)
if(istype(meta.skeleton, /datum/event/nothing))
return meta
event_rolls++
. = ..()
/datum/event_container/disaster/start_event()
. = ..()
var/datum/event_meta/meta = .
if(!istype(meta.skeleton, /datum/event/nothing))
activation_counter++
/datum/event_container/disaster/calculate_event_delay()
. = ..()
if(world.time - SSticker.time_game_started + . <= 120 MINUTES && world.time - SSticker.time_game_started + . >= 95 MINUTES)
. += 30 MINUTES
return
+100 -40
View File
@@ -55,61 +55,66 @@
// Returns how many characters are currently active(not logged out, not AFK for more than 10 minutes)
// with a specific role.
// Note that this isn't sorted by department, because e.g. having a roboticist shouldn't make meteors spawn.
// Note that this isn't sorted just by department, because e.g. having a roboticist shouldn't make meteors spawn.
/proc/number_active_with_role()
var/list/active_with_role = list()
active_with_role["Engineer"] = 0
active_with_role["Medical"] = 0
active_with_role["Security"] = 0
active_with_role["Scientist"] = 0
active_with_role["AI"] = 0
active_with_role["Cyborg"] = 0
active_with_role["Janitor"] = 0
active_with_role["Botanist"] = 0
active_with_role["Chemist"] = 0
active_with_role["Any"] = length(GLOB.player_list)
for(var/mob/M in GLOB.player_list)
if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive
var/list/active_with_role = list()
active_with_role[ASSIGNMENT_CREW] = 0
active_with_role[ASSIGNMENT_COMMAND] = 0
active_with_role[ASSIGNMENT_ENGINEERING] = 0
active_with_role[ASSIGNMENT_MEDICAL] = 0
active_with_role[ASSIGNMENT_SECURITY] = 0
active_with_role[ASSIGNMENT_SCIENCE] = 0
active_with_role[ASSIGNMENT_CARGO] = 0
if(length(SSevents.debug_resources))
active_with_role = SSevents.debug_resources.Copy()
for(var/mob/player in GLOB.player_list)
if(!player.mind?.assigned_role || player.stat == DEAD || !player.client || player.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive
continue
if(isrobot(M))
var/mob/living/silicon/robot/R = M
var/capacity = player.get_event_capacity()
if(!capacity)
continue
if(player.mind.assigned_role in (GLOB.exp_jobsmap[EXP_TYPE_CREW]["titles"]))
active_with_role[ASSIGNMENT_CREW] += capacity
if(active_with_role[player.mind.assigned_role])
active_with_role[player.mind.assigned_role]+= capacity
else
active_with_role[player.mind.assigned_role] = capacity
if(isrobot(player))
var/mob/living/silicon/robot/R = player
if(R.module && (R.module.name == "engineering robot module"))
active_with_role["Engineer"]++
active_with_role[ASSIGNMENT_ENGINEERING]+= capacity
if(R.module && (R.module.name == "medical robot module"))
active_with_role["Medical"]++
active_with_role[ASSIGNMENT_MEDICAL]+= capacity
if(R.module && (R.module.name == "security robot module"))
active_with_role["Security"]++
active_with_role[ASSIGNMENT_SECURITY]+= capacity
if(M.mind.assigned_role in list("Chief Engineer", "Station Engineer"))
active_with_role["Engineer"]++
if(player.mind.assigned_role in GLOB.engineering_positions)
active_with_role[ASSIGNMENT_ENGINEERING]+= capacity
if(M.mind.assigned_role in list("Chief Medical Officer", "Medical Doctor"))
active_with_role["Medical"]++
if(player.mind.assigned_role in GLOB.medical_positions)
active_with_role[ASSIGNMENT_MEDICAL]+= capacity
if(M.mind.assigned_role in GLOB.active_security_positions)
active_with_role["Security"]++
if(player.mind.assigned_role in GLOB.active_security_positions)
active_with_role[ASSIGNMENT_SECURITY]+= capacity
if(M.mind.assigned_role in list("Research Director", "Scientist"))
active_with_role["Scientist"]++
if(player.mind.assigned_role in GLOB.science_positions)
active_with_role[ASSIGNMENT_SCIENCE]+= capacity
if(M.mind.assigned_role == "AI")
active_with_role["AI"]++
if(player.mind.assigned_role in GLOB.supply_positions)
active_with_role[ASSIGNMENT_CARGO]+= capacity
if(M.mind.assigned_role == "Cyborg")
active_with_role["Cyborg"]++
if(M.mind.assigned_role == "Janitor")
active_with_role["Janitor"]++
if(M.mind.assigned_role == "Botanist")
active_with_role["Botanist"]++
if(M.mind.assigned_role == "Chemist")
active_with_role["Chemist"]++
if(player.mind.assigned_role in GLOB.command_positions)
active_with_role[ASSIGNMENT_COMMAND]+= capacity
return active_with_role
@@ -119,3 +124,58 @@
if(P.client)
players++
return players
/proc/event_category_cost(category)
. = list()
if(!category)
return
for(var/datum/component/event_tracker/tracker in GLOB.event_trackers["[category]"])
var/costs = tracker.event_cost()
for(var/key in costs)
.["[key]"] += costs[key]
/proc/event_total_cost()
. = list()
for(var/category in GLOB.event_trackers)
var/costs = event_category_cost(category)
for(var/key in costs)
.["[key]"] += costs[key]
/// Returns the net resources available for event rolling
/proc/get_total_resources()
// A list of the amount of active players in each role/department
var/active_with_role = number_active_with_role()
// A list of the net available resources of each department depending on staffing and active threats/events
var/list/total_resources = list()
// Add resources from staffing
for(var/assignment in active_with_role)
total_resources[assignment] += active_with_role[assignment] * ASSIGNMENT_STAFFING_VALUE
// Subtract resources from active antags
for(var/datum/antagonist/active in GLOB.antagonists)
var/list/antag_costs = active.antag_event_resource_cost()
for(var/assignment in antag_costs)
if(total_resources[assignment])
total_resources[assignment] -= antag_costs[assignment]
else
total_resources[assignment] = -antag_costs[assignment]
// Subtract resources from active events
for(var/datum/event/active in SSevents.active_events)
var/list/event_costs = active.event_resource_cost()
for(var/assignment in event_costs)
if(total_resources[assignment])
total_resources[assignment] -= event_costs[assignment]
else
total_resources[assignment] = -event_costs[assignment]
// Subtract resources from various elements
var/list/misc_costs = event_total_cost()
for(var/assignment in misc_costs)
if(total_resources[assignment])
total_resources[assignment] -= misc_costs[assignment]
else
total_resources[assignment] = -misc_costs[assignment]
return total_resources
+3
View File
@@ -1,3 +1,6 @@
/datum/event/fake_virus
name = "Fake Virus"
/datum/event/fake_virus/start()
var/list/valid_targets = list()
for(var/mob/living/carbon/human/victim in shuffle(GLOB.player_list))
+1
View File
@@ -1,4 +1,5 @@
/datum/event/falsealarm
name = "False Alarm"
endWhen = 1
var/static/list/possible_event_types = list(
/datum/event/alien_infestation,
+6
View File
@@ -8,7 +8,13 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
*/
/datum/event/immovable_rod
name = "Immovable Rod"
announceWhen = 5
// We assume the event keeps engies busy for about 30 minutes
endWhen = 900
nominal_severity = EVENT_LEVEL_MAJOR
role_weights = list(ASSIGNMENT_ENGINEERING = 5)
role_requirements = list(ASSIGNMENT_ENGINEERING = 6)
/datum/event/immovable_rod/announce()
GLOB.minor_announcement.Announce("What the fuck was that?!", "General Alert")
+3
View File
@@ -3,6 +3,9 @@
#define VERM_SPIDERS 2
/datum/event/infestation
name = "Vermin Infestation"
role_weights = list(ASSIGNMENT_JANITOR = 0.5)
role_requirements = list(ASSIGNMENT_JANITOR = 1)
announceWhen = 10
endWhen = 11
/// Which kind of vermin we'll be spawning (one of the three defines)
+5 -1
View File
@@ -3,13 +3,17 @@
#define ION_ANNOUNCE 1
/datum/event/ion_storm
name = "Ion Storm"
role_weights = list(ASSIGNMENT_COMMAND = 1)
role_requirements = list(ASSIGNMENT_COMMAND = 1)
nominal_severity = EVENT_LEVEL_MODERATE
var/botEmagChance = 10
var/announceEvent = ION_NOANNOUNCEMENT // -1 means don't announce, 0 means have it randomly announce, 1 means
var/ionMessage = null
var/ionAnnounceChance = 33
announceWhen = 1
/datum/event/ion_storm/New(datum/event_meta/EM, skeleton = FALSE, botEmagChance = 10, announceEvent = ION_NOANNOUNCEMENT, ionMessage = null, ionAnnounceChance = 33)
/datum/event/ion_storm/New(datum/event_meta/EM, skeleton = FALSE, _severity, botEmagChance = 10, announceEvent = ION_NOANNOUNCEMENT, ionMessage = null, ionAnnounceChance = 33)
src.botEmagChance = botEmagChance
src.announceEvent = announceEvent
src.ionMessage = ionMessage
+1
View File
@@ -1,4 +1,5 @@
/datum/event/carp_migration/koi
name = "Koi School"
spawned_mobs = list(
/mob/living/simple_animal/hostile/retaliate/carp/koi = 98,
/mob/living/simple_animal/hostile/retaliate/carp/koi/honk = 2)
@@ -1,6 +1,9 @@
/// at least 75% rad armor is required to be immune to this event
#define RAD_ARMOR_TO_IMMUNITY 150
/datum/event/mass_hallucination
name = "Mass Hallucination"
/datum/event/mass_hallucination/setup()
announceWhen = rand(0, 20)
+7
View File
@@ -1,3 +1,9 @@
/datum/event/dust/meaty
name = "Meaty Ores"
nominal_severity = EVENT_LEVEL_MODERATE
role_weights = list(ASSIGNMENT_ENGINEERING = 4)
role_requirements = list(ASSIGNMENT_ENGINEERING = 4)
/datum/event/dust/meaty/announce()
if(prob(16))
GLOB.minor_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
@@ -6,6 +12,7 @@
/datum/event/dust/meaty/setup()
qnty = rand(45,125)
endWhen = 600 // Make it take up engineering staffing for 20 minutes
/datum/event/dust/meaty/start()
INVOKE_ASYNC(src, PROC_REF(spawn_meaty_ores))
+22 -5
View File
@@ -1,9 +1,16 @@
/datum/event/meteor_wave
name = "Meteor Wave"
startWhen = 5
endWhen = 7
nominal_severity = EVENT_LEVEL_MODERATE
// We set this when the station clears the meteor storm to keep the event ongoing for a bit so it keeps having a cost
noAutoEnd = TRUE
role_weights = list(ASSIGNMENT_ENGINEERING = 5)
role_requirements = list(ASSIGNMENT_ENGINEERING = 4)
var/next_meteor = 6
var/waves = 1
var/atom/movable/screen/alert/augury/meteor/screen_alert
/// The time at which we clear the storm. This is set during the event run so we initialize it to an unreachable value
var/clear_time = -1
/datum/event/meteor_wave/setup()
for(var/mob/dead/observer/O in GLOB.dead_mob_list)
@@ -22,15 +29,25 @@
//meteor showers are lighter and more common,
/datum/event/meteor_wave/tick()
// keep observers updated with the alert
for(var/mob/dead/observer/O in GLOB.dead_mob_list)
O.throw_alert("\ref[src]_augury", /atom/movable/screen/alert/augury/meteor)
if(screen_alert)
for(var/mob/dead/observer/O in GLOB.dead_mob_list)
O.throw_alert("\ref[src]_augury", /atom/movable/screen/alert/augury/meteor)
if(waves && activeFor >= next_meteor)
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(spawn_meteors), get_meteor_count(), get_meteors())
next_meteor += rand(15, 30) / severity
waves--
endWhen = (waves ? next_meteor + 1 : activeFor + 15)
// When the storm is done we set a timer for the event end instead of finishing it.
// This is so it still incurs a cost for the event system for a while.
if(!waves && noAutoEnd)
// Set a 15 cycle(30 second) timer before we announce clearing the storm.
// This is to give the last meteor enough time to finish moving
clear_time = activeFor + 15
endWhen = activeFor + 700
noAutoEnd = FALSE
if(activeFor == clear_time)
announce_clear()
/datum/event/meteor_wave/end()
/datum/event/meteor_wave/proc/announce_clear()
for(var/mob/M in GLOB.dead_mob_list)
M.clear_alert("\ref[src]_augury")
QDEL_NULL(screen_alert)
+2
View File
@@ -1,4 +1,6 @@
/datum/event/pda_spam
name = "PDA Spam"
role_weights = list(ASSIGNMENT_CREW = 4)
endWhen = 36000
var/last_spam_time = 0
var/obj/machinery/message_server/useMS
+4
View File
@@ -1,4 +1,8 @@
/datum/event/prison_break
name = "Prison Break"
role_weights = list(ASSIGNMENT_SECURITY = 0.8, ASSIGNMENT_CREW = 0.2)
role_requirements = list(ASSIGNMENT_SECURITY = 2, ASSIGNMENT_CREW = 0)
nominal_severity = EVENT_LEVEL_MODERATE
startWhen = 40
announceWhen = 75
@@ -1,3 +1,9 @@
/datum/event/radiation_storm
name = "Radiation Storm"
nominal_severity = EVENT_LEVEL_MODERATE
role_weights = list(ASSIGNMENT_MEDICAL = 5)
role_requirements = list(ASSIGNMENT_MEDICAL = 5)
/datum/event/radiation_storm/setup()
startWhen = 3
endWhen = startWhen + 1
@@ -1,8 +1,21 @@
#define REVENANT_SPAWN_THRESHOLD 10
/datum/event/revenant
name = "Revenant"
nominal_severity = EVENT_LEVEL_MAJOR
noAutoEnd = TRUE
role_weights = list(ASSIGNMENT_CHAPLAIN = 5, ASSIGNMENT_CREW = 0.8)
role_requirements = list(ASSIGNMENT_CHAPLAIN = 1, ASSIGNMENT_CREW = 30)
var/key_of_revenant
// Calculated separately from event
/datum/event/revenant/event_resource_cost()
return list()
/datum/event/revenant/proc/on_revenant_death(mob/source)
SIGNAL_HANDLER // COMSIG_MOB_DEATH
UnregisterSignal(source, COMSIG_MOB_DEATH)
kill()
/datum/event/revenant/proc/get_revenant(end_if_fail = 0)
var/deadMobs = 0
@@ -10,6 +23,7 @@
deadMobs++
if(deadMobs < REVENANT_SPAWN_THRESHOLD)
message_admins("Random event attempted to spawn a revenant, but there were only [deadMobs]/[REVENANT_SPAWN_THRESHOLD] dead mobs.")
kill()
return
spawn()
@@ -36,6 +50,7 @@
kill()
return
var/mob/living/basic/revenant/revvie = new /mob/living/basic/revenant/(pick(spawn_locs))
RegisterSignal(revvie, COMSIG_MOB_DEATH, PROC_REF(on_revenant_death))
player_mind.transfer_to(revvie)
dust_if_respawnable(C)
player_mind.assigned_role = SPECIAL_ROLE_REVENANT
+4
View File
@@ -1,6 +1,10 @@
/datum/event/rogue_drone
name = "Rogue Drones"
role_weights = list(ASSIGNMENT_SECURITY = 2)
role_requirements = list(ASSIGNMENT_SECURITY = 1)
startWhen = 10
endWhen = 1000
nominal_severity = EVENT_LEVEL_MODERATE
var/list/drones_list = list()
/datum/event/rogue_drone/start()
+1
View File
@@ -1,4 +1,5 @@
/datum/event/sentience
name = "Sentience"
/datum/event/sentience/start()
INVOKE_ASYNC(src, PROC_REF(make_sentient_mob))
@@ -2,6 +2,9 @@
name = "Shuttle Loan"
announceWhen = 1
endWhen = 500
nominal_severity = EVENT_LEVEL_MODERATE
role_weights = list(ASSIGNMENT_CARGO = 2, ASSIGNMENT_SECURITY = 2)
role_requirements = list(ASSIGNMENT_CARGO = 2, ASSIGNMENT_SECURITY = 2)
/// what type of shuttle loan situation the station faces.
var/datum/shuttle_loan_situation/situation
/// Whether the station has let Centcom commandeer the shuttle yet.
+14
View File
@@ -1,6 +1,15 @@
/datum/event/spawn_slaughter
name = "Slaughter Demon"
noAutoEnd = TRUE
var/key_of_slaughter
var/mob/living/simple_animal/demon/demon = /mob/living/simple_animal/demon/slaughter/lesser
nominal_severity = EVENT_LEVEL_MAJOR
role_weights = list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_JANITOR = 5, ASSIGNMENT_MEDICAL = 3, ASSIGNMENT_CREW = 0.7)
role_requirements = list(ASSIGNMENT_SECURITY = 4, ASSIGNMENT_JANITOR = 1, ASSIGNMENT_MEDICAL = 2, ASSIGNMENT_CREW = 25)
/datum/event/spawn_slaughter/tick()
if(!demon || demon.stat == DEAD)
kill()
/datum/event/spawn_slaughter/proc/get_slaughter()
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [initial(demon.name)]?", ROLE_DEMON, TRUE, source = demon)
@@ -44,10 +53,15 @@
INVOKE_ASYNC(src, PROC_REF(get_slaughter))
/datum/event/spawn_slaughter/greater
name = "Greater Slaughter Demon"
demon = /mob/living/simple_animal/demon/slaughter
/datum/event/spawn_slaughter/shadow
name = "Shadow Demon"
demon = /mob/living/simple_animal/demon/shadow
// Same as slaughter but without Jani
role_weights = list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3, ASSIGNMENT_CREW = 0.7)
role_requirements = list(ASSIGNMENT_SECURITY = 4, ASSIGNMENT_MEDICAL = 2, ASSIGNMENT_CREW = 25)
/datum/event/spawn_slaughter/shadow/get_spawn_loc()
var/turf/spawn_center = ..()
+1
View File
@@ -1,4 +1,5 @@
/datum/event/solar_flare
name = "Solar Flare"
startWhen = 2
endWhen = 3
announceWhen = 1
+6
View File
@@ -1,3 +1,9 @@
/datum/event/spacevine
name = "Space Vines"
role_weights = list(ASSIGNMENT_CREW = 0.4, ASSIGNMENT_ENGINEERING = 1, ASSIGNMENT_BOTANIST = 2)
role_requirements = list(ASSIGNMENT_CREW = 25 , ASSIGNMENT_BOTANIST = 1, ASSIGNMENT_ENGINEERING = 1)
nominal_severity = EVENT_LEVEL_MODERATE
/datum/event/spacevine/start()
var/list/turfs = list() //list of all the empty floor turfs in the hallway areas
@@ -1,4 +1,6 @@
/datum/event/spider_infestation
name = "Spider Infestation"
role_weights = list(ASSIGNMENT_SECURITY = 30)
announceWhen = 400
var/spawncount = 1
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
+17
View File
@@ -1,7 +1,12 @@
#define TS_HIGHPOP_TRIGGER 80
/datum/event/spider_terror
name = "terror spiders"
announceWhen = 240
noAutoEnd = TRUE
nominal_severity = EVENT_LEVEL_DISASTER
role_weights = list(ASSIGNMENT_SECURITY = 2, ASSIGNMENT_CREW = 0.8, ASSIGNMENT_MEDICAL = 2.5)
role_requirements = list(ASSIGNMENT_SECURITY = 3, ASSIGNMENT_CREW = 45, ASSIGNMENT_MEDICAL = 4)
var/spawncount = 1
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
@@ -19,6 +24,16 @@
// It is necessary to wrap this to avoid the event triggering repeatedly.
INVOKE_ASYNC(src, PROC_REF(wrappedstart))
/// Terror spider costs are calculated independently from the event itself
/datum/event/spider_terror/event_resource_cost()
return list()
/datum/event/spider_terror/process()
// End the event once all spiders, eggs and spiderlings are gone from the station Z level.
if(!length(event_category_cost(EVENT_TERROR_SPIDERS)) && successSpawn)
kill()
. = ..()
/datum/event/spider_terror/proc/wrappedstart()
var/spider_type
var/infestation_type
@@ -66,6 +81,8 @@
S.give_intro_text()
spawncount--
successSpawn = TRUE
if(!successSpawn)
kill()
SSticker.record_biohazard_start(infestation_type)
SSevents.biohazards_this_round += infestation_type
@@ -1,3 +1,8 @@
/datum/event/spontaneous_appendicitis
name = "Appendicitis"
role_weights = list(ASSIGNMENT_MEDICAL = 1)
role_requirements = list(ASSIGNMENT_MEDICAL = 1)
/datum/event/spontaneous_appendicitis/start()
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
if(issmall(H)) //don't infect monkies; that's a waste.
+3
View File
@@ -7,6 +7,9 @@
*/
/datum/event/tear
name = "dimensional tear"
nominal_severity = EVENT_LEVEL_MODERATE
role_weights = list(ASSIGNMENT_SECURITY = 2)
role_requirements = list(ASSIGNMENT_SECURITY = 2)
announceWhen = 6
endWhen = 14
var/notify_title = "Dimensional Rift"
+4
View File
@@ -4,6 +4,10 @@ GLOBAL_LIST_INIT(unused_trade_stations, list("sol"))
// Heavily copy-pasted from "heist" gamemode.
/datum/event/traders
name = "Traders"
role_weights = list(ASSIGNMENT_CREW = 0.5)
role_requirements = list(ASSIGNMENT_CREW = 30)
nominal_severity = EVENT_LEVEL_MAJOR
var/success_spawn = 0
var/station = null
var/spawn_count = 2
+2
View File
@@ -1,6 +1,8 @@
/datum/event/vent_clog
name = "Scrubber Clog"
startWhen = 5
endWhen = 35
nominal_severity = EVENT_LEVEL_MODERATE
var/interval = 2
var/list/vents = list()
+8
View File
@@ -1,3 +1,8 @@
/datum/event/wallrot
name = "Wallrot"
role_weights = list(ASSIGNMENT_ENGINEERING = 5)
role_requirements = list(ASSIGNMENT_ENGINEERING = 1)
/datum/event/wallrot/start()
INVOKE_ASYNC(src, PROC_REF(spawn_wallrot))
@@ -36,6 +41,9 @@
break
/datum/event/wallrot/fungus
name = "Fungal Growth"
role_weights = list(ASSIGNMENT_CHEMIST = 5)
role_weights = list(ASSIGNMENT_CHEMIST = 0)
/datum/event/wallrot/fungus/is_valid_candidate(turf/T)
return istype(get_area(T), /area/station/maintenance)
+2
View File
@@ -1,4 +1,6 @@
/datum/event/wormholes
name = "Wormholes"
role_weights = "Vent Clog"
announceWhen = 10
endWhen = 60
@@ -213,6 +213,7 @@
/mob/living/basic/mouse/blobinfected/Initialize(mapload)
. = ..()
AddComponent(/datum/component/event_tracker, EVENT_BLOB)
apply_status_effect(STATUS_EFFECT_BLOB_BURST, 120 SECONDS, CALLBACK(src, PROC_REF(burst), FALSE))
/mob/living/basic/mouse/blobinfected/Life()
@@ -252,6 +253,7 @@
if(core)
core.admin_spawned = admin_spawned
SEND_SIGNAL(src, COMSIG_BLOB_MOUSE_BURST, core)
SSticker.record_biohazard_start(BIOHAZARD_BLOB)
/mob/living/basic/mouse/blobinfected/get_scooped(mob/living/carbon/grabber)
@@ -68,6 +68,12 @@
. = ..()
carp_randomify(rarechance)
AddComponent(/datum/component/aggro_emote, emote_list = list("gnashes"))
AddComponent(/datum/component/event_tracker, EVENT_CARP)
/mob/living/basic/carp/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_CREW = 0.1)
/mob/living/basic/carp/proc/carp_randomify(rarechance)
if(random_color)
@@ -45,6 +45,13 @@
/mob/living/basic/hellhound/Initialize(mapload)
. = ..()
AddElement(/datum/element/ai_retaliate)
AddComponent(/datum/component/event_tracker)
/mob/living/basic/hellhound/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 1, ASSIGNMENT_MEDICAL = 0.5)
/mob/living/basic/hellhound/examine(mob/user)
. = ..()
@@ -156,6 +156,11 @@
remove_from_all_data_huds()
giveSpells()
RegisterSignal(src, COMSIG_BODY_TRANSFER_TO, PROC_REF(make_revenant_antagonist))
AddComponent(/datum/component/event_tracker, EVENT_REVENTANT)
/mob/living/basic/revenant/event_cost()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_CHAPLAIN = 1, ASSIGNMENT_CREW = 10, ASSIGNMENT_MEDICAL = 2)
/mob/living/basic/revenant/proc/make_revenant_antagonist(revenant)
SIGNAL_HANDLER // COMSIG_BODY_TRANSFER_TO
@@ -37,6 +37,13 @@
/mob/living/basic/skeleton/Initialize(mapload)
. = ..()
AddElement(/datum/element/ai_retaliate)
AddComponent(/datum/component/event_tracker)
/mob/living/basic/skeleton/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 1, ASSIGNMENT_MEDICAL = 0.5)
/mob/living/basic/skeleton/arctic
name = "undead arctic explorer"
@@ -36,3 +36,9 @@
update_appearance(UPDATE_NAME)
color = "#5494DA"
AddElement(/datum/element/ai_retaliate)
AddComponent(/datum/component/event_tracker, EVENT_DEMONIC)
/mob/living/basic/netherworld/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 1, ASSIGNMENT_MEDICAL = 0.5)
@@ -34,6 +34,7 @@
set_default_language(GLOB.all_languages["Galactic Common"])
AddElement(/datum/element/ai_retaliate)
update_icons()
AddComponent(/datum/component/event_tracker, EVENT_DRONE)
/mob/living/basic/malf_drone/proc/create_trail(datum/source, atom/oldloc, _dir, forced)
var/turf/T = get_turf(oldloc)
@@ -33,6 +33,12 @@
for(var/organ_path in get_caste_organs())
var/obj/item/organ/internal/organ = new organ_path()
organ.insert(src)
AddComponent(/datum/component/event_tracker, EVENT_XENOS)
/mob/living/carbon/alien/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 1, ASSIGNMENT_CREW = 3, ASSIGNMENT_MEDICAL = 1)
/// returns the list of type paths of the organs that we need to insert into
/// this particular xeno upon its creation
@@ -15,6 +15,11 @@
name = "alien hunter ([rand(1, 1000)])"
real_name = name
/mob/living/carbon/alien/humanoid/hunter/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 0.8, ASSIGNMENT_CREW = 4, ASSIGNMENT_MEDICAL = 0.4)
/mob/living/carbon/alien/humanoid/hunter/get_caste_organs()
. = ..()
. += /obj/item/organ/internal/alien/plasmavessel/hunter
@@ -31,6 +31,11 @@
name = "alien sentinel ([rand(1, 1000)])"
real_name = name
/mob/living/carbon/alien/humenoid/sentinel/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 3, ASSIGNMENT_MEDICAL = 0.2)
/mob/living/carbon/alien/humanoid/sentinel/get_caste_organs()
. = ..()
. += list(
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list(
AddSpell(new /datum/spell/alien_spell/regurgitate)
. = ..()
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW, 0.5, -11)
AddComponent(/datum/component/event_tracker, EVENT_XENOS)
/mob/living/carbon/alien/humanoid/get_strippable_items(datum/source, list/items)
items |= GLOB.strippable_alien_humanoid_items
@@ -19,6 +19,11 @@
ADD_TRAIT(src, TRAIT_FORCE_DOORS, UNIQUE_TRAIT_SOURCE(src))
AddSpell(new /datum/spell/alien_spell/tail_lash)
/mob/living/carbon/alien/humenoid/queen/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 2, ASSIGNMENT_CREW = 12, ASSIGNMENT_MEDICAL = 1)
/mob/living/carbon/alien/humanoid/queen/get_caste_organs()
. = ..()
. += list(
@@ -31,6 +31,11 @@
var/datum/action/innate/hide/alien_larva_hide/hide = new()
hide.Grant(src)
/mob/living/carbon/alien/larva/event_cost()
. = list()
if(is_station_level((get_turf(src)).z))
return list(ASSIGNMENT_SECURITY = 0.2, ASSIGNMENT_CREW = 1)
/mob/living/carbon/alien/larva/Destroy()
for(var/datum/action/innate/hide/alien_larva_hide/hide in actions)
hide.Remove(src)
@@ -235,8 +235,15 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
orig_vendor.forceMove(src)
orig_vendor.aggressive = FALSE // just to be safe, in case this was converted
AddComponent(/datum/component/event_tracker, EVENT_BRAND_INTELLIGENCE)
return ..(mapload, base, creator, destroy_original = FALSE)
/mob/living/simple_animal/hostile/mimic/copy/vendor/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 1)
/mob/living/simple_animal/hostile/mimic/copy/vendor/AttackingTarget()
. = ..()
if(. && target && Adjacent(target))
@@ -97,6 +97,10 @@
else
visible_message("<span class='danger'>[src] bites [target], but cannot inject venom into [target.p_their()] [inject_target]!</span>")
/mob/living/simple_animal/hostile/poison/terror_spider/green/event_cost()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.5, ASSIGNMENT_CREW = 2, ASSIGNMENT_MEDICAL = 0.2)
/obj/structure/spider/terrorweb/green
name = "slimy web"
desc = "This web is partly composed of strands of green slime."
@@ -109,3 +109,7 @@
if(hit_something)
visible_message("<span class='danger'>[src] slams into [hit_atom]!</span>", "<span class='userdanger'>You slam into [hit_atom]!</span>")
playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 100, TRUE)
/mob/living/simple_animal/hostile/poison/terror_spider/prince/event_cost()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 2, ASSIGNMENT_CREW = 20, ASSIGNMENT_MEDICAL = 3)
@@ -123,3 +123,6 @@
return TRUE
return FALSE
/mob/living/simple_animal/hostile/poison/terror_spider/queen/princess/event_cost()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 2, ASSIGNMENT_CREW = 15, ASSIGNMENT_MEDICAL = 2)
@@ -348,6 +348,9 @@
. += "<span class='notice'>[p_they(TRUE)] has laid [eggslaid] egg[eggslaid != 1 ? "s" : ""].</span>"
. += "<span class='notice'>[p_they(TRUE)] has lived for [MinutesAlive()] minutes.</span>"
/mob/living/simple_animal/hostile/poison/terror_spider/queen/event_cost()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 3, ASSIGNMENT_CREW = 30, ASSIGNMENT_MEDICAL = 2)
/obj/item/projectile/terrorqueenspit
name = "acid spit"
@@ -22,6 +22,7 @@
GLOB.ts_spiderling_list += src
if(is_away_level(z))
spider_awaymission = TRUE
AddComponent(/datum/component/event_tracker, EVENT_TERROR_SPIDERS)
/obj/structure/spider/spiderling/terror_spiderling/Destroy()
GLOB.ts_spiderling_list -= src
@@ -216,6 +217,7 @@
name = "prince of terror eggs"
if(/mob/living/simple_animal/hostile/poison/terror_spider/queen)
name = "queen of terror eggs"
AddComponent(/datum/component/event_tracker, EVENT_TERROR_SPIDERS)
/obj/structure/spider/eggcluster/terror_eggcluster/Destroy()
GLOB.ts_egg_list -= src
@@ -238,6 +238,10 @@ GLOBAL_LIST_EMPTY(ts_infected_list)
fed++
qdel(J)
/mob/living/simple_animal/hostile/poison/terror_spider/event_cost()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 0.2, ASSIGNMENT_CREW = 1.5, ASSIGNMENT_MEDICAL = 0.2)
// --------------------------------------------------------------------------------
// --------------------- TERROR SPIDERS: PROC OVERRIDES ---------------------------
// --------------------------------------------------------------------------------
@@ -287,6 +291,7 @@ GLOBAL_LIST_EMPTY(ts_infected_list)
var/datum/atom_hud/U = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
U.add_hud_to(src)
spider_creation_time = world.time
AddComponent(/datum/component/event_tracker, EVENT_TERROR_SPIDERS)
/mob/living/simple_animal/hostile/poison/terror_spider/proc/announcetoghosts()
if(stat == DEAD)
@@ -51,6 +51,10 @@
LoseTarget()
GLOB.move_manager.move_away(src,L,2,1)
/mob/living/simple_animal/hostile/poison/terror_spider/white/event_cost()
if(is_station_level((get_turf(src)).z) && stat != DEAD)
return list(ASSIGNMENT_SECURITY = 1, ASSIGNMENT_CREW = 5, ASSIGNMENT_MEDICAL = 2)
/proc/IsTSInfected(mob/living/carbon/C) // Terror AI requires this
if(C.get_int_organ(/obj/item/organ/internal/body_egg))
return 1
@@ -59,6 +63,12 @@
/obj/item/organ/internal/body_egg/terror_eggs/Initialize(mapload)
. = ..()
GLOB.ts_infected_list += src
AddComponent(/datum/component/event_tracker, EVENT_TERROR_SPIDERS)
/obj/item/organ/internal/body_egg/terror_eggs/event_cost()
. = list()
if(is_station_level((get_turf(src)).z) && owner)
return list(ASSIGNMENT_MEDICAL = 1)
/obj/item/organ/internal/body_egg/terror_eggs/insert(mob/living/carbon/M, special)
. = ..()
+14
View File
@@ -1642,3 +1642,17 @@ GLOBAL_LIST_INIT(holy_areas, typecacheof(list(
client.mouse_pointer_icon = null
return
client.mouse_pointer_icon = mousepointers["[lowest_prio]"]
/mob/proc/get_event_capacity()
. = 1
var/max_symptom_severity = 0
for(var/datum/disease/advance/virus in viruses)
for(var/datum/symptom/curr_symptom in virus.symptoms)
if(curr_symptom.severity > max_symptom_severity)
max_symptom_severity = curr_symptom.severity
switch(max_symptom_severity)
if(4)
. *= 0.5
if(5 to 6)
return 0
+1 -1
View File
@@ -294,7 +294,7 @@
/obj/machinery/satellite/meteor_shield/proc/change_meteor_chance(mod)
for(var/datum/event_container/container in SSevents.event_containers)
for(var/datum/event_meta/M in container.available_events)
if(M.event_type == /datum/event/meteor_wave)
if(M.skeleton.type == /datum/event/meteor_wave)
M.weight_mod *= mod
/obj/machinery/satellite/meteor_shield/Destroy()