mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
Adds Groundwork for New Event System
Adds what I hope to be able to make a sort of intelligent system that in the future will be able to decide what event would be the best to choose at any given moment. A lot of this will probably get rewritten later. You can use the new debug verb Show GM Status to have it show some data about itself, such as player activity across the whole server. Currently, the system cannot actually run any events, as they don't exist and it's been disabled. The plan is to have the events themselves do most of the heavy lifting for stuff like set-up and weights. When the overarching system is more refined, a lot of new events will be madem and most of our old ones will be ported, and improved upon too. For now, adding this lets me see what the system thinks about a round that has people playing on it and not just me on a test server.
This commit is contained in:
6
code/controllers/Processes/game_master.dm
Normal file
6
code/controllers/Processes/game_master.dm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/datum/controller/process/event/setup()
|
||||||
|
name = "\improper GM controller"
|
||||||
|
schedule_interval = 600 // every 60 seconds
|
||||||
|
|
||||||
|
/datum/controller/process/event/doWork()
|
||||||
|
game_master.process()
|
||||||
@@ -118,6 +118,7 @@ var/join_motd = null
|
|||||||
|
|
||||||
var/datum/nanomanager/nanomanager = new() // NanoManager, the manager for Nano UIs.
|
var/datum/nanomanager/nanomanager = new() // NanoManager, the manager for Nano UIs.
|
||||||
var/datum/event_manager/event_manager = new() // Event Manager, the manager for events.
|
var/datum/event_manager/event_manager = new() // Event Manager, the manager for events.
|
||||||
|
var/datum/game_master/game_master = new() // Game Master, an AI for choosing events.
|
||||||
|
|
||||||
var/list/awaydestinations = list() // Away missions. A list of landmarks that the warpgate can take you to.
|
var/list/awaydestinations = list() // Away missions. A list of landmarks that the warpgate can take you to.
|
||||||
|
|
||||||
|
|||||||
@@ -197,7 +197,8 @@ var/list/admin_verbs_debug = list(
|
|||||||
/client/proc/dsay,
|
/client/proc/dsay,
|
||||||
/client/proc/toggle_debug_logs,
|
/client/proc/toggle_debug_logs,
|
||||||
/client/proc/admin_ghost, //allows us to ghost/reenter body at will,
|
/client/proc/admin_ghost, //allows us to ghost/reenter body at will,
|
||||||
/datum/admins/proc/view_runtimes
|
/datum/admins/proc/view_runtimes,
|
||||||
|
/client/proc/show_gm_status
|
||||||
)
|
)
|
||||||
|
|
||||||
var/list/admin_verbs_paranoid_debug = list(
|
var/list/admin_verbs_paranoid_debug = list(
|
||||||
|
|||||||
29
code/modules/gamemaster/actions/action.dm
Normal file
29
code/modules/gamemaster/actions/action.dm
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/datum/gm_action
|
||||||
|
var/name = "no name" // Simple name, for organization.
|
||||||
|
var/enabled = TRUE // If not enabled, this action is never taken.
|
||||||
|
var/departments = list() // What kinds of departments are affected by this action. Multiple departments can be listed.
|
||||||
|
var/chaotic = 0 // A number showing how chaotic the action may be. If danger is high, the GM will avoid it.
|
||||||
|
var/reusable = FALSE // If true, the event does not become disabled upon being used. Should be used sparingly.
|
||||||
|
var/observers_used = FALSE // Determines if the GM should check if ghosts are available before using this.
|
||||||
|
var/datum/game_master/gm = null
|
||||||
|
|
||||||
|
/datum/gm_action/New(var/datum/game_master/new_gm)
|
||||||
|
..()
|
||||||
|
gm = new_gm
|
||||||
|
|
||||||
|
/datum/gm_action/proc/set_up()
|
||||||
|
return
|
||||||
|
|
||||||
|
/datum/gm_action/proc/get_weight()
|
||||||
|
return
|
||||||
|
|
||||||
|
/datum/gm_action/proc/start()
|
||||||
|
if(!reusable)
|
||||||
|
enabled = FALSE
|
||||||
|
return
|
||||||
|
|
||||||
|
/datum/gm_action/proc/end()
|
||||||
|
return
|
||||||
|
|
||||||
|
/datum/gm_action/proc/announce()
|
||||||
|
return
|
||||||
6
code/modules/gamemaster/actions/comms_blackout.dm
Normal file
6
code/modules/gamemaster/actions/comms_blackout.dm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Comms blackout is, just like grid check, mostly the same as always, yet engineering has an option to get it back sooner.
|
||||||
|
|
||||||
|
/datum/gm_action/comms_blackout
|
||||||
|
name = "communications blackout"
|
||||||
|
departments = list(ROLE_ENGINEERING, ROLE_EVERYONE)
|
||||||
|
chaotic = 35
|
||||||
9
code/modules/gamemaster/actions/grid_check.dm
Normal file
9
code/modules/gamemaster/actions/grid_check.dm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// New grid check event:
|
||||||
|
// Very similar to the old one, power goes out in most of the colony, however the new feature is the ability for engineering to
|
||||||
|
// get power back on sooner, if they are able to reach a special machine and initiate a manual reboot. If no one is able to do so,
|
||||||
|
// it will reboot itself after a few minutes, just like the old one.
|
||||||
|
|
||||||
|
/datum/gm_action/grid_check
|
||||||
|
name = "grid check"
|
||||||
|
departments = list(ROLE_ENGINEERING, ROLE_EVERYONE)
|
||||||
|
chaotic = 20
|
||||||
6
code/modules/gamemaster/actions/waste_disposal.dm
Normal file
6
code/modules/gamemaster/actions/waste_disposal.dm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// A shuttle full of junk docks, and cargo is tasked with sifting through it all to find valuables, or just dispose of it.
|
||||||
|
|
||||||
|
/datum/gm_action/waste_disposal
|
||||||
|
name = "waste disposal"
|
||||||
|
departments = list(ROLE_CARGO)
|
||||||
|
chaotic = 0
|
||||||
40
code/modules/gamemaster/controller.dm
Normal file
40
code/modules/gamemaster/controller.dm
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/client/proc/show_gm_status()
|
||||||
|
set category = "Debug"
|
||||||
|
set name = "Show GM Status"
|
||||||
|
set desc = "Shows you what the GM is thinking. If only that existed in real life..."
|
||||||
|
|
||||||
|
game_master.interact(usr)
|
||||||
|
|
||||||
|
/datum/game_master/proc/interact(var/client/user)
|
||||||
|
if(!user)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/HTML = "<html><head><title>Game Master AI</title></head><body>"
|
||||||
|
|
||||||
|
HTML += "Staleness: [staleness]<br>"
|
||||||
|
HTML += "Danger: [danger]<br><br>"
|
||||||
|
|
||||||
|
HTML += "Actions available;<br>"
|
||||||
|
for(var/datum/gm_action/action in available_actions)
|
||||||
|
if(action.enabled == FALSE)
|
||||||
|
continue
|
||||||
|
HTML += "[action.name] ([english_list(action.departments)])<br>"
|
||||||
|
|
||||||
|
HTML += "<br>"
|
||||||
|
HTML += "All living mobs activity: [assess_all_living_mobs()]<br>"
|
||||||
|
|
||||||
|
HTML += "<br>"
|
||||||
|
HTML += "Departmental activity;<br>"
|
||||||
|
for(var/department in departments)
|
||||||
|
var/number_of_people = count_people_in_department(department)
|
||||||
|
HTML += " [department] : [assess_department(department)] / [number_of_people * 100]<br>"
|
||||||
|
|
||||||
|
HTML += "<br>"
|
||||||
|
HTML += "Activity of players;<br>"
|
||||||
|
for(var/mob/player in player_list)
|
||||||
|
HTML += " [player] : [assess_player_activity(player)]<br>"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HTML +="</body></html>"
|
||||||
|
user << browse(HTML, "window=log;size=400x450;border=1;can_resize=1;can_close=1;can_minimize=1")
|
||||||
10
code/modules/gamemaster/defines.dm
Normal file
10
code/modules/gamemaster/defines.dm
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#define ROLE_COMMAND "command"
|
||||||
|
#define ROLE_SECURITY "security"
|
||||||
|
#define ROLE_ENGINEERING "engineering"
|
||||||
|
#define ROLE_MEDICAL "medical"
|
||||||
|
#define ROLE_RESEARCH "research"
|
||||||
|
#define ROLE_CARGO "cargo"
|
||||||
|
#define ROLE_CIVILIAN "civilian"
|
||||||
|
#define ROLE_SYNTHETIC "synthetic"
|
||||||
|
#define ROLE_UNKNOWN "unknown"
|
||||||
|
#define ROLE_EVERYONE "everyone"
|
||||||
207
code/modules/gamemaster/game_master.dm
Normal file
207
code/modules/gamemaster/game_master.dm
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
// This is a sort of successor to the various event systems created over the years. It is designed to be just a tad smarter than the
|
||||||
|
// previous ones, checking various things like player count, department size and composition, individual player activity,
|
||||||
|
// individual player (IC) skill, and such, in order to try to choose the best actions to take in order to add spice or variety to
|
||||||
|
// the round.
|
||||||
|
|
||||||
|
/datum/game_master
|
||||||
|
var/suspended = FALSE // If true, it will not do anything.
|
||||||
|
var/list/available_actions = list() // A list of 'actions' that the GM has access to, to spice up a round, such as events.
|
||||||
|
var/danger = 0 // The GM's best guess at how chaotic the round is. High danger makes it hold back.
|
||||||
|
var/staleness = -20 // Determines liklihood of the GM doing something, increases over time.
|
||||||
|
var/danger_modifier = 1 // Multiplier for how much 'danger' is accumulated.
|
||||||
|
var/staleness_modifier = 1 // Ditto. Higher numbers generally result in more events occuring in a round.
|
||||||
|
var/ticks_completed = 0 // Counts amount of ticks completed. Note that this ticks once a minute.
|
||||||
|
var/next_action = 0 // Minimum amount of time of nothingness until the GM can pick something again.
|
||||||
|
var/departments = list( // List of departments the GM considers for choosing events for.
|
||||||
|
ROLE_COMMAND,
|
||||||
|
ROLE_SECURITY,
|
||||||
|
ROLE_ENGINEERING,
|
||||||
|
ROLE_MEDICAL,
|
||||||
|
ROLE_RESEARCH,
|
||||||
|
ROLE_CARGO,
|
||||||
|
ROLE_CIVILIAN,
|
||||||
|
ROLE_SYNTHETIC
|
||||||
|
)
|
||||||
|
|
||||||
|
/datum/game_master/New()
|
||||||
|
..()
|
||||||
|
available_actions = init_subtypes(/datum/gm_action)
|
||||||
|
// var/actions = typesof(/datum/gm_actions)
|
||||||
|
// for(var/type in actions)
|
||||||
|
// available_actions.Add(new type)
|
||||||
|
|
||||||
|
/datum/game_master/proc/process()
|
||||||
|
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
|
||||||
|
adjust_staleness(1)
|
||||||
|
adjust_danger(-1)
|
||||||
|
ticks_completed++
|
||||||
|
|
||||||
|
var/global_afk = assess_all_living_mobs()
|
||||||
|
global_afk -= 100
|
||||||
|
global_afk = abs(global_afk)
|
||||||
|
global_afk = round(global_afk / 100, 0.1)
|
||||||
|
adjust_staleness(global_afk) // Staleness increases faster if more people are less active.
|
||||||
|
|
||||||
|
if(world.time < next_action && prob(staleness * 2) )
|
||||||
|
log_debug("Game Master going to start something.")
|
||||||
|
start_action()
|
||||||
|
|
||||||
|
/datum/game_master/proc/assess_all_living_mobs()
|
||||||
|
var/num = 0
|
||||||
|
for(var/mob/living/L in player_list) // Ghosts being AFK isn't that much of a concern.
|
||||||
|
. += assess_player_activity(L)
|
||||||
|
num++
|
||||||
|
if(num)
|
||||||
|
. = round(. / num, 0.1)
|
||||||
|
|
||||||
|
// This is run before committing to an action/event.
|
||||||
|
/datum/game_master/proc/pre_action_checks()
|
||||||
|
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
|
||||||
|
log_debug("Game Master unable to start event: Ticker is nonexistant, or the game is not ongoing.")
|
||||||
|
return FALSE
|
||||||
|
// Last minute antagging is bad for humans to do, so the GM will respect the start and end of the round.
|
||||||
|
var/mills = round_duration_in_ticks
|
||||||
|
var/mins = round((mills % 36000) / 600)
|
||||||
|
var/hours = round(mills / 36000)
|
||||||
|
|
||||||
|
if(hours < 1 && mins <= 20) // Don't do anything for the first twenty minutes of the round.
|
||||||
|
log_debug("Game Master unable to start event: It is too early.")
|
||||||
|
return FALSE
|
||||||
|
if(hours >= 2 && mins >= 40) // Don't do anything in the last twenty minutes of the round, as well.
|
||||||
|
log_debug("Game Master unable to start event: It is too late.")
|
||||||
|
return FALSE
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/game_master/proc/start_action()
|
||||||
|
if(!pre_action_checks()) // Make sure we're not doing last minute events, or early events.
|
||||||
|
return
|
||||||
|
log_debug("Game Master now starting action decision.")
|
||||||
|
var/list/best_actions = assess_round() // Checks the whole round for active people, and returns a list of the most activie departments.
|
||||||
|
if(best_actions && best_actions.len)
|
||||||
|
var/datum/gm_action/choice = pick(best_actions)
|
||||||
|
if(choice)
|
||||||
|
// log_debug("[choice.name] was chosen by the Game Master, and is now being ran.")
|
||||||
|
// choice.set_up()
|
||||||
|
// choice.start()
|
||||||
|
// choice.annnounce()
|
||||||
|
next_action = world.time + rand(15 MINUTES, 30 MINUTES)
|
||||||
|
|
||||||
|
/datum/game_master/proc/assess_round()
|
||||||
|
var/list/activity = list()
|
||||||
|
for(var/department in departments)
|
||||||
|
activity[department] = assess_department(department)
|
||||||
|
log_debug("Assessing department [department]. They have activity of [activity[department]].")
|
||||||
|
|
||||||
|
var/list/most_active_departments = list() // List of winners.
|
||||||
|
var/highest_activity = null // Department who is leading in activity, if one exists.
|
||||||
|
var/highest_number = 0 // Activity score needed to beat to be the most active department.
|
||||||
|
for(var/i = 1, i <= 3, i++)
|
||||||
|
log_debug("Doing [i]\th round of counting.")
|
||||||
|
for(var/department in activity)
|
||||||
|
if(activity[department] > highest_number && activity[department] > 0) // More active than the current highest department?
|
||||||
|
highest_activity = department
|
||||||
|
highest_number = activity[department]
|
||||||
|
|
||||||
|
if(highest_activity) // Someone's a winner.
|
||||||
|
most_active_departments.Add(highest_activity) // Add to the list of most active.
|
||||||
|
activity.Remove(highest_activity) // Remove them from the other list so they don't win more than once.
|
||||||
|
log_debug("[highest_activity] has won the [i]\th round of activity counting.")
|
||||||
|
highest_activity = null // Now reset for the next round.
|
||||||
|
highest_number = 0
|
||||||
|
//todo: finish
|
||||||
|
var/list/best_actions = decide_best_action(most_active_departments)
|
||||||
|
return best_actions
|
||||||
|
|
||||||
|
// By now, we should have a list of departments populated. The GM will prefer events tailored to these departments.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/datum/game_master/proc/decide_best_action(var/list/most_active_departments)
|
||||||
|
if(!most_active_departments.len) // Server's empty?
|
||||||
|
log_debug("Game Master failed to find any active departments.")
|
||||||
|
return list()
|
||||||
|
|
||||||
|
var/list/best_actions = list() // List of actions which involve the most active departments.
|
||||||
|
if(most_active_departments.len >= 2)
|
||||||
|
for(var/datum/gm_action/action in available_actions)
|
||||||
|
if(!action.enabled)
|
||||||
|
continue
|
||||||
|
// Try to incorporate an action with the top two departments first.
|
||||||
|
if(most_active_departments[1] in action.departments && most_active_departments[2] in action.departments)
|
||||||
|
best_actions.Add(action)
|
||||||
|
log_debug("[action.name] is being considered because both most active departments are involved.")
|
||||||
|
|
||||||
|
if(best_actions.len) // We found something for those two, let's do it.
|
||||||
|
return best_actions
|
||||||
|
|
||||||
|
// Otherwise we probably couldn't find something for the second highest group, so let's ignore them.
|
||||||
|
for(var/datum/gm_action/action in available_actions)
|
||||||
|
if(!action.enabled)
|
||||||
|
continue
|
||||||
|
if(most_active_departments[1] in action.departments)
|
||||||
|
best_actions.Add(action)
|
||||||
|
log_debug("[action.name] is being considered because the most active department is involved.")
|
||||||
|
|
||||||
|
if(best_actions.len) // Found something for the one guy.
|
||||||
|
return best_actions
|
||||||
|
|
||||||
|
// At this point we should expand our horizons.
|
||||||
|
for(var/datum/gm_action/action in available_actions)
|
||||||
|
if(!action.enabled)
|
||||||
|
continue
|
||||||
|
if(ROLE_EVERYONE in action.departments)
|
||||||
|
best_actions.Add(action)
|
||||||
|
log_debug("[action.name] is being considered because it involves everyone.")
|
||||||
|
|
||||||
|
if(best_actions.len) // Finally, perhaps?
|
||||||
|
return best_actions
|
||||||
|
|
||||||
|
// Just give a random event if for some reason it still can't make up its mind.
|
||||||
|
for(var/datum/gm_action/action in available_actions)
|
||||||
|
if(!action.enabled)
|
||||||
|
continue
|
||||||
|
best_actions.Add(action)
|
||||||
|
log_debug("[action.name] is being considered because everything else failed.")
|
||||||
|
|
||||||
|
if(best_actions.len) // Finally, perhaps?
|
||||||
|
return best_actions
|
||||||
|
else
|
||||||
|
log_debug("Game Master failed to find a suitable event, something very wrong is going on.")
|
||||||
|
|
||||||
|
// This checks a whole department's viability to receive an event.
|
||||||
|
/datum/game_master/proc/assess_department(var/department)
|
||||||
|
if(!department)
|
||||||
|
return
|
||||||
|
var/departmental_activitiy = 0
|
||||||
|
for(var/mob/M in player_list)
|
||||||
|
if(guess_department(M) != department) // Ignore people outside the department we're assessing.
|
||||||
|
continue
|
||||||
|
departmental_activitiy += assess_player_activity(M)
|
||||||
|
return departmental_activitiy
|
||||||
|
|
||||||
|
// This checks an individual player's activity level. People who have been afk for a few minutes aren't punished as much as those
|
||||||
|
// who were afk for hours, as they're most likely gone for good.
|
||||||
|
/datum/game_master/proc/assess_player_activity(var/mob/M)
|
||||||
|
. = 100
|
||||||
|
if(!M)
|
||||||
|
. = 0
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!M.mind || !M.client) // Logged out. They might come back but we can't do any meaningful assessments for now.
|
||||||
|
. = 0
|
||||||
|
return
|
||||||
|
|
||||||
|
var/afk = M.client.is_afk(1 MINUTE)
|
||||||
|
if(afk) // Deduct points based on length of AFK-ness.
|
||||||
|
switch(afk) // One minute is equal to 600, for reference.
|
||||||
|
if(1 MINUTE to 10 MINUTES) // People gone for this emough of time hopefully will come back soon.
|
||||||
|
. -= round( (afk / 200), 1)
|
||||||
|
// . -= 30
|
||||||
|
if(10 MINUTES to 30 MINUTES)
|
||||||
|
. -= round( (afk / 150), 1)
|
||||||
|
// . -= 70
|
||||||
|
if(30 MINUTES to INFINITY) // They're probably not coming back if it's been 30 minutes.
|
||||||
|
. -= 100
|
||||||
|
. = max(. , 0) // No negative numbers, or else people could drag other, non-afk players down.
|
||||||
|
|
||||||
72
code/modules/gamemaster/helpers.dm
Normal file
72
code/modules/gamemaster/helpers.dm
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// Tell the game master that something dangerous happened, e.g. someone dying.
|
||||||
|
/datum/game_master/proc/adjust_danger(var/amt)
|
||||||
|
amt = amt * danger_modifier
|
||||||
|
danger = round( Clamp(danger + amt, 0, 1000), 0.1)
|
||||||
|
|
||||||
|
// Tell the game master that something interesting happened.
|
||||||
|
/datum/game_master/proc/adjust_staleness(var/amt)
|
||||||
|
amt = amt * staleness_modifier
|
||||||
|
staleness = round( Clamp(staleness + amt, -50, 200), 0.1)
|
||||||
|
|
||||||
|
// This proc tries to find the department of an arbitrary mob.
|
||||||
|
/datum/game_master/proc/guess_department(var/mob/M)
|
||||||
|
var/datum/data/record/R = find_general_record("name", M.real_name)
|
||||||
|
. = ROLE_UNKNOWN
|
||||||
|
if(R) // We found someone with a record.
|
||||||
|
var/recorded_rank = R.fields["real_rank"]
|
||||||
|
. = role_name_to_department(recorded_rank)
|
||||||
|
if(. != ROLE_UNKNOWN) // We found the correct department, so we can stop now.
|
||||||
|
return
|
||||||
|
|
||||||
|
// They have a custom title, aren't crew, or someone deleted their record, so we need a fallback method.
|
||||||
|
// Let's check the mind.
|
||||||
|
if(M.mind)
|
||||||
|
. = role_name_to_department(M.mind.assigned_role)
|
||||||
|
if(. != ROLE_UNKNOWN)
|
||||||
|
return
|
||||||
|
|
||||||
|
// At this point, they don't have a mind, or for some reason assigned_role didn't work.
|
||||||
|
if(ishuman(M))
|
||||||
|
var/mob/living/carbon/human/H = M
|
||||||
|
. = role_name_to_department(H.job)
|
||||||
|
if(. != ROLE_UNKNOWN)
|
||||||
|
return
|
||||||
|
|
||||||
|
return ROLE_UNKNOWN // Welp.
|
||||||
|
|
||||||
|
|
||||||
|
// Feed this proc the name of a job, and it will try to figure out what department they are apart of.
|
||||||
|
/datum/game_master/proc/role_name_to_department(var/role_name)
|
||||||
|
if(role_name in security_positions)
|
||||||
|
return ROLE_SECURITY
|
||||||
|
|
||||||
|
if(role_name in engineering_positions)
|
||||||
|
return ROLE_ENGINEERING
|
||||||
|
|
||||||
|
if(role_name in medical_positions)
|
||||||
|
return ROLE_MEDICAL
|
||||||
|
|
||||||
|
if(role_name in science_positions)
|
||||||
|
return ROLE_RESEARCH
|
||||||
|
|
||||||
|
if(role_name in cargo_positions)
|
||||||
|
return ROLE_CARGO
|
||||||
|
|
||||||
|
if(role_name in civilian_positions)
|
||||||
|
return ROLE_CIVILIAN
|
||||||
|
|
||||||
|
if(role_name in nonhuman_positions)
|
||||||
|
return ROLE_SYNTHETIC
|
||||||
|
|
||||||
|
if(role_name in command_positions) // We do command last, so that only the Captain and command secretaries get caught.
|
||||||
|
return ROLE_COMMAND
|
||||||
|
|
||||||
|
return ROLE_UNKNOWN
|
||||||
|
|
||||||
|
/datum/game_master/proc/count_people_in_department(var/department)
|
||||||
|
if(!department)
|
||||||
|
return
|
||||||
|
for(var/mob/M in player_list)
|
||||||
|
if(guess_department(M) != department) // Ignore people outside the department we're counting.
|
||||||
|
continue
|
||||||
|
. += 1
|
||||||
@@ -140,6 +140,7 @@
|
|||||||
#include "code\controllers\Processes\chemistry.dm"
|
#include "code\controllers\Processes\chemistry.dm"
|
||||||
#include "code\controllers\Processes\emergencyShuttle.dm"
|
#include "code\controllers\Processes\emergencyShuttle.dm"
|
||||||
#include "code\controllers\Processes\event.dm"
|
#include "code\controllers\Processes\event.dm"
|
||||||
|
#include "code\controllers\Processes\game_master.dm"
|
||||||
#include "code\controllers\Processes\garbage.dm"
|
#include "code\controllers\Processes\garbage.dm"
|
||||||
#include "code\controllers\Processes\inactivity.dm"
|
#include "code\controllers\Processes\inactivity.dm"
|
||||||
#include "code\controllers\Processes\machinery.dm"
|
#include "code\controllers\Processes\machinery.dm"
|
||||||
@@ -1334,6 +1335,14 @@
|
|||||||
#include "code\modules\flufftext\Hallucination.dm"
|
#include "code\modules\flufftext\Hallucination.dm"
|
||||||
#include "code\modules\flufftext\TextFilters.dm"
|
#include "code\modules\flufftext\TextFilters.dm"
|
||||||
#include "code\modules\food\recipes_microwave.dm"
|
#include "code\modules\food\recipes_microwave.dm"
|
||||||
|
#include "code\modules\gamemaster\controller.dm"
|
||||||
|
#include "code\modules\gamemaster\defines.dm"
|
||||||
|
#include "code\modules\gamemaster\game_master.dm"
|
||||||
|
#include "code\modules\gamemaster\helpers.dm"
|
||||||
|
#include "code\modules\gamemaster\actions\action.dm"
|
||||||
|
#include "code\modules\gamemaster\actions\comms_blackout.dm"
|
||||||
|
#include "code\modules\gamemaster\actions\grid_check.dm"
|
||||||
|
#include "code\modules\gamemaster\actions\waste_disposal.dm"
|
||||||
#include "code\modules\games\cah.dm"
|
#include "code\modules\games\cah.dm"
|
||||||
#include "code\modules\games\cah_black_cards.dm"
|
#include "code\modules\games\cah_black_cards.dm"
|
||||||
#include "code\modules\games\cah_white_cards.dm"
|
#include "code\modules\games\cah_white_cards.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user