Files
Bubberstation/code/controllers/subsystem/events.dm
Jacquerel cfb2d9feb9 Meteor events won't try and run on icebox (#73241)
## About The Pull Request

While I was trying to improve changeling meteor spawning on Icebox I
noticed that several other meteor-like events don't seem to be blocked
on Icebox either even though they don't do anything.
I added a new capability to events which can prevent them being loaded
under certain map conditions (specifically: whether the map is in space
or not). Currently there's no events which _only_ run on a planet but,
now someone could add one I guess?

Now all of the events which spawn meteors are filtered out on icebox and
you can't absent-mindedly try to trigger them.

![image](https://user-images.githubusercontent.com/7483112/216799539-f843bdf6-c70f-4815-a355-0b297acad1a6.png)

Also a couple of dynamic options had this applied too, chiefly ones
which expect you to be able to fly a space ship to the space station.

## Why It's Good For The Game

These events shouldn't run on Icebox (or soon, Chilled) because they
don't do anything there.
AFAICT Meteors were getting as far as trying to spawn, then would retry
trying to find space tiles which didn't exist until they failed 10
times, then give up. Once per every meteor it tried to spawn. Gross.

## Changelog

🆑
fix: Meteors can't be triggered automatically or manually on Icebox,
where they do nothing.
fix: Hacking a comms console as a traitor won't try to summon meteors or
pirates to Icebox, where they do nothing.
/🆑
2023-02-05 19:19:28 -07:00

172 lines
6.0 KiB
Plaintext

SUBSYSTEM_DEF(events)
name = "Events"
init_order = INIT_ORDER_EVENTS
runlevels = RUNLEVEL_GAME
var/list/control = list() //list of all datum/round_event_control. Used for selecting events based on weight and occurrences.
var/list/running = list() //list of all existing /datum/round_event
var/list/currentrun = list()
var/scheduled = 0 //The next world.time that a naturally occuring random event can be selected.
var/frequency_lower = 1800 //3 minutes lower bound.
var/frequency_upper = 6000 //10 minutes upper bound. Basically an event will happen every 3 to 10 minutes.
var/wizardmode = FALSE
/datum/controller/subsystem/events/Initialize()
for(var/type in typesof(/datum/round_event_control))
var/datum/round_event_control/event = new type()
if(!event.typepath || !event.valid_for_map())
continue //don't want this one! leave it for the garbage collector
control += event //add it to the list of all events (controls)
reschedule()
// Instantiate our holidays list if it hasn't been already
if(isnull(GLOB.holidays))
fill_holidays()
return SS_INIT_SUCCESS
/datum/controller/subsystem/events/fire(resumed = FALSE)
if(!resumed)
checkEvent() //only check these if we aren't resuming a paused fire
src.currentrun = running.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/thing = currentrun[currentrun.len]
currentrun.len--
if(thing)
thing.process(wait * 0.1)
else
running.Remove(thing)
if (MC_TICK_CHECK)
return
//checks if we should select a random event yet, and reschedules if necessary
/datum/controller/subsystem/events/proc/checkEvent()
if(scheduled <= world.time)
spawnEvent()
reschedule()
//decides which world.time we should select another random event at.
/datum/controller/subsystem/events/proc/reschedule()
scheduled = world.time + rand(frequency_lower, max(frequency_lower,frequency_upper))
//selects a random event based on whether it can occur and it's 'weight'(probability)
/datum/controller/subsystem/events/proc/spawnEvent()
set waitfor = FALSE //for the admin prompt
if(!CONFIG_GET(flag/allow_random_events))
return
var/players_amt = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
// Only alive, non-AFK human players count towards this.
var/sum_of_weights = 0
for(var/datum/round_event_control/E in control)
if(!E.can_spawn_event(players_amt))
continue
if(E.weight < 0) //for round-start events etc.
var/res = TriggerEvent(E)
if(res == EVENT_INTERRUPTED)
continue //like it never happened
if(res == EVENT_CANT_RUN)
return
sum_of_weights += E.weight
sum_of_weights = rand(0,sum_of_weights) //reusing this variable. It now represents the 'weight' we want to select
for(var/datum/round_event_control/E in control)
if(!E.can_spawn_event(players_amt))
continue
sum_of_weights -= E.weight
if(sum_of_weights <= 0) //we've hit our goal
if(TriggerEvent(E))
return
/datum/controller/subsystem/events/proc/TriggerEvent(datum/round_event_control/E)
. = E.preRunEvent()
if(. == EVENT_CANT_RUN)//we couldn't run this event for some reason, set its max_occurrences to 0
E.max_occurrences = 0
else if(. == EVENT_READY)
E.runEvent(random = TRUE)
/datum/controller/subsystem/events/proc/toggleWizardmode()
wizardmode = !wizardmode
message_admins("Summon Events has been [wizardmode ? "enabled, events will occur every [SSevents.frequency_lower / 600] to [SSevents.frequency_upper / 600] minutes" : "disabled"]!")
log_game("Summon Events was [wizardmode ? "enabled" : "disabled"]!")
/datum/controller/subsystem/events/proc/resetFrequency()
frequency_lower = initial(frequency_lower)
frequency_upper = initial(frequency_upper)
/**
* HOLIDAYS
*
* Uncommenting ALLOW_HOLIDAYS in config.txt will enable holidays
*
* It's easy to add stuff. Just add a holiday datum in code/modules/holiday/holidays.dm
* You can then check if it's a special day in any code in the game by calling check_holidays("Groundhog Day")
*
* You can also make holiday random events easily thanks to Pete/Gia's system.
* simply make a random event normally, then assign it a holidayID string which matches the holiday's name.
* Anything with a holidayID, which isn't in the holidays list, will never occur.
*
* Please, Don't spam stuff up with stupid stuff (key example being april-fools Pooh/ERP/etc),
* and don't forget: CHECK YOUR CODE!!!! We don't want any zero-day bugs which happen only on holidays and never get found/fixed!
*/
GLOBAL_LIST(holidays)
/**
* Checks that the passed holiday is located in the global holidays list.
*
* Returns a holiday datum, or null if it's not that holiday.
*/
/proc/check_holidays(holiday_to_find)
if(!CONFIG_GET(flag/allow_holidays))
return // Holiday stuff was not enabled in the config!
if(isnull(GLOB.holidays) && !fill_holidays())
return // Failed to generate holidays, for some reason
return GLOB.holidays[holiday_to_find]
/**
* Fills the holidays list if applicable, or leaves it an empty list.
*/
/proc/fill_holidays()
if(!CONFIG_GET(flag/allow_holidays))
return FALSE // Holiday stuff was not enabled in the config!
GLOB.holidays = list()
for(var/holiday_type in subtypesof(/datum/holiday))
var/datum/holiday/holiday = new holiday_type()
var/delete_holiday = TRUE
for(var/timezone in holiday.timezones)
var/time_in_timezone = world.realtime + timezone HOURS
var/YYYY = text2num(time2text(time_in_timezone, "YYYY")) // get the current year
var/MM = text2num(time2text(time_in_timezone, "MM")) // get the current month
var/DD = text2num(time2text(time_in_timezone, "DD")) // get the current day
var/DDD = time2text(time_in_timezone, "DDD") // get the current weekday
if(holiday.shouldCelebrate(DD, MM, YYYY, DDD))
holiday.celebrate()
GLOB.holidays[holiday.name] = holiday
delete_holiday = FALSE
break
if(delete_holiday)
qdel(holiday)
if(GLOB.holidays.len)
shuffle_inplace(GLOB.holidays)
// regenerate station name because holiday prefixes.
set_station_name(new_station_name())
world.update_status()
return TRUE