/
githubmirror
/
vgstation13
Обзор
Документация
Войти
/
githubmirror
/
vgstation13
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
Bleeding-Edge
code/modules/events/event_dynamic.dm
229 строк
7 KB
mentgah
Telecomms script event quick active role fix (#39360)
31 май 2026, 18:27
Не верифицирован
31 май 2026, 18:27
8033685
Код
Авторство
О чём код?
var/list/possibleEvents = list() //A list of events and their weights. These range from quite uncommon like a rod (15) to very common like carp (40) var/datum/event/queued_event = null var/queued_event_expiry = 0 //Always triggers an event when called, dynamically chooses events based on job population /proc/spawn_dynamic_event(var/forced=FALSE) // Any queued event is preempted by a new natural roll if(queued_event) message_admins("EVENT QUEUE CLEARED: [queued_event] preempted by new event roll.") queued_event = null if(!forced) if(!config.allow_random_events || (map && map.dorf)) return var/minutes_passed = world.time/600 var/roundstart_delay = 15 if (admin_disable_events) message_admins("A random event was prevented from firing by admins.") log_admin("A random event was prevented from firing by admins.") return if(minutes_passed < roundstart_delay) //No events near roundstart message_admins("Too early to trigger random event, aborting.") return if(universe.name != "Normal") message_admins("Universe isn't normal, aborting random event spawn.") return if(player_list.len < 1) //minimum pop of 1 to trigger events message_admins("Too few players to trigger random event, aborting.") return var/list/active_with_role = number_active_with_role() //Scraped PDA text events (like random news events) can be found in // code\modules\Economy\Economy_Events.dm // code\modules\Economy\Economy_Events_Mundane.dm if(!possibleEvents.len) for(var/type in subtypesof(/datum/event)) if((map.event_blacklist.len && map.event_blacklist.Find(type)) || (map.event_whitelist.len && !map.event_whitelist.Find(type))) continue //Blacklisted, don't even create them var/datum/event/E = new type(FALSE) possibleEvents += E var/list/drawing = list() for(var/datum/event/E in possibleEvents) drawing[E] = max(0,E.can_start(active_with_role) - E.recency_weight()) //Reminder: never have negatives when using pickweight var/datum/event/picked_event = pickweight(drawing) if(!picked_event) return // Map-specific check: queue if the picked event fails the map's gate if(!map.map_specific_event_checks(picked_event)) queued_event = picked_event queued_event_expiry = world.time + 5 MINUTES message_admins("EVENT QUEUED: [picked_event] failed map_specific_event_checks, waiting up to 5 minutes.") spawn(15 SECONDS) retry_queued_event(picked_event) return 1 message_admins("EVENT: [picked_event] started with [drawing[picked_event]] weight.") possibleEvents -= picked_event if(!picked_event.oneShot) var/newtype = picked_event.type var/datum/event/to_add = new newtype(FALSE) to_add.last_fired = world.time possibleEvents += to_add //Replace with a new datum if it's not oneshot // Debug code below here, very useful for testing so don't delete please. var/debug_message = "Firing random event. " for(var/V in active_with_role) debug_message += "#[V]:[active_with_role[V]] " debug_message += "||| " for(var/V in possibleEvents) debug_message += "[V]:[possibleEvents[V]]" debug_message += "|||Picked:[picked_event]" log_debug(debug_message) picked_event.setup() events.Add(picked_event) score.eventsendured++ return 1 /proc/retry_queued_event(var/datum/event/my_event) // Exit silently if preempted by a new natural roll (or cleared). if(queued_event != my_event) return // Map gate now satisfied — fire normally. if(map.map_specific_event_checks(my_event)) message_admins("EVENT QUEUE FIRED: [my_event] map gate satisfied.") fire_queued_event(my_event) queued_event = null return // Expired; re-roll. if(world.time >= queued_event_expiry) message_admins("EVENT QUEUE EXPIRED: [my_event] timed out, re-rolling.") queued_event = null reroll_on_queue_expiry() return // Still waiting; poll again. spawn(15 SECONDS) retry_queued_event(my_event) /proc/fire_queued_event(var/datum/event/E) possibleEvents -= E if(!E.oneShot) var/newtype = E.type var/datum/event/to_add = new newtype(FALSE) to_add.last_fired = world.time possibleEvents += to_add var/debug_message = "Firing queued event. " for(var/datum/event/O in possibleEvents) debug_message += "[O]:[possibleEvents[O]]" debug_message += "|||Picked:[E]" log_debug(debug_message) E.setup() events.Add(E) score.eventsendured++ /proc/reroll_on_queue_expiry() var/list/active_with_role = number_active_with_role() var/list/drawing = list() for(var/datum/event/E in possibleEvents) drawing[E] = max(0, E.can_start(active_with_role) - E.recency_weight()) for(var/i = 1 to 10) var/datum/event/picked = pickweight(drawing) if(!picked) break if(map.map_specific_event_checks(picked)) message_admins("EVENT (queue fallback): [picked] started (attempt [i]).") fire_queued_event(picked) return // Map gate still unmet for this event; remove it from drawing and retry drawing -= picked message_admins("EVENT QUEUE FALLBACK: no valid event found in 10 rolls.") // Returns a list of how many characters are currently active with a specific role // see: (not logged out, not AFK for more than 10 minutes) // Note that this isn't sorted by department, because e.g. having a roboticist shouldn't make meteors spawn. // Minor roles have lesser influence on events, Any just cares about active players at all /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["Minor"] = 0 active_with_role["Telecomms"] = 0 active_with_role["Any"] = 0 for(var/mob/M in player_list) if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive continue active_with_role["Any"]++ if(isrobot(M)) var/mob/living/silicon/robot/tincan = M if(tincan.module) switch(tincan.module.name) if("engineering robot module") active_with_role["Engineer"]++ if("medical robot module") active_with_role["Medical"]++ if("security robot module") active_with_role["Security"]++ if("combat robot module") active_with_role["Security"]++ if("janitorial robot module") active_with_role["Janitor"]++ else active_with_role["Minor"]++ if((M.mind.assigned_role in engineering_positions) && M.mind.assigned_role != "Mechanic") active_with_role["Engineer"]++ if (M.mind.assigned_role == "Chief Engineer") active_with_role["Telecomms"]++ continue if(M.mind.assigned_role in medical_positions) active_with_role["Medical"]++ continue if(M.mind.assigned_role in security_positions) active_with_role["Security"]++ continue if(M.mind.assigned_role in science_positions) active_with_role["Scientist"]++ if(M.mind.assigned_role == "Mechanic" || M.mind.assigned_role == "Research Director") active_with_role["Telecomms"]++ continue if(M.mind.assigned_role == "AI") active_with_role["AI"]++ continue if(M.mind.assigned_role == "Cyborg") active_with_role["Cyborg"]++ continue if(M.mind.assigned_role == "Janitor") active_with_role["Janitor"]++ continue if(M.mind.assigned_role == "Botanist") active_with_role["Botanist"]++ continue active_with_role["Minor"]++ return active_with_role