diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index fc5d0fe8d4e..5c957445526 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -24,6 +24,9 @@ SUBSYSTEM_DEF(job) var/list/unassigned = list() //Players who need jobs var/initial_players_to_assign = 0 //used for checking against population caps + // Whether to run DivideOccupations pure so that there are no side-effects from calling it other than + // a player's assigned_role being set to some value. + var/run_divide_occupation_pure = FALSE var/list/prioritized_jobs = list() var/list/latejoin_trackers = list() @@ -369,11 +372,11 @@ SUBSYSTEM_DEF(job) * fills var "assigned_role" for all ready players. * This proc must not have any side effect besides of modifying "assigned_role". **/ -/datum/controller/subsystem/job/proc/DivideOccupations() +/datum/controller/subsystem/job/proc/DivideOccupations(pure = FALSE, allow_all = FALSE) //Setup new player list and get the jobs list - JobDebug("Running DO") - - SEND_SIGNAL(src, COMSIG_OCCUPATIONS_DIVIDED) + JobDebug("Running DO, allow_all = [allow_all], pure = [pure]") + run_divide_occupation_pure = pure + SEND_SIGNAL(src, COMSIG_OCCUPATIONS_DIVIDED, pure, allow_all) //Get the players who are ready for(var/i in GLOB.new_player_list) @@ -441,8 +444,9 @@ SUBSYSTEM_DEF(job) // Loop through all unassigned players for(var/mob/dead/new_player/player in unassigned) - if(PopcapReached()) - RejectPlayer(player) + if(!allow_all) + if(PopcapReached()) + RejectPlayer(player) // Loop through all jobs for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY @@ -480,7 +484,7 @@ SUBSYSTEM_DEF(job) // Hand out random jobs to the people who didn't get any in the last check // Also makes sure that they got their preference correct for(var/mob/dead/new_player/player in unassigned) - HandleUnassigned(player) + HandleUnassigned(player, allow_all) JobDebug("DO, Ending handle unassigned.") JobDebug("DO, Handle unrejectable unassigned") @@ -490,21 +494,23 @@ SUBSYSTEM_DEF(job) if(!AssignRole(player, GetJobType(overflow_role))) //If everything is already filled, make them an assistant JobDebug("DO, Forced antagonist could not be assigned any random job or the overflow role. DivideOccupations failed.") JobDebug("---------------------------------------------------") + run_divide_occupation_pure = FALSE return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll JobDebug("DO, Ending handle unrejectable unassigned") JobDebug("All divide occupations tasks completed.") JobDebug("---------------------------------------------------") - + run_divide_occupation_pure = FALSE return TRUE //We couldn't find a job from prefs for this guy. -/datum/controller/subsystem/job/proc/HandleUnassigned(mob/dead/new_player/player) +/datum/controller/subsystem/job/proc/HandleUnassigned(mob/dead/new_player/player, allow_all = FALSE) var/jobless_role = player.client.prefs.read_preference(/datum/preference/choiced/jobless_role) - if(PopcapReached()) - RejectPlayer(player) - return + if(!allow_all) + if(PopcapReached()) + RejectPlayer(player) + return switch (jobless_role) if (BEOVERFLOW) @@ -698,10 +704,11 @@ SUBSYSTEM_DEF(job) if(PopcapReached()) JobDebug("Popcap overflow Check observer located, Player: [player]") JobDebug("Player rejected :[player]") - to_chat(player, "You have failed to qualify for any job you desired.") unassigned -= player - player.ready = PLAYER_NOT_READY - player.client << output(player.ready, "lobby_browser:imgsrc") //SKYRAT EDIT ADDITION + if(!run_divide_occupation_pure) + to_chat(player, "You have failed to qualify for any job you desired.") + player.ready = PLAYER_NOT_READY + player.client << output(player.ready, "lobby_browser:imgsrc") //SKYRAT EDIT ADDITION /datum/controller/subsystem/job/Recover() diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 033deff4358..26dfcb4be76 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -458,11 +458,22 @@ GLOBAL_LIST_EMPTY(dynamic_station_traits) //To new_player and such, and we want the datums to just free when the roundstart work is done var/list/roundstart_rules = init_rulesets(/datum/dynamic_ruleset/roundstart) + SSjob.DivideOccupations(pure = TRUE, allow_all = TRUE) for(var/i in GLOB.new_player_list) var/mob/dead/new_player/player = i if(player.ready == PLAYER_READY_TO_PLAY && player.mind && player.check_preferences()) - roundstart_pop_ready++ - candidates.Add(player) + if(is_unassigned_job(player.mind.assigned_role)) + var/list/job_data = list() + var/job_prefs = player.client.prefs.job_preferences + for(var/job in job_prefs) + var/priority = job_prefs[job] + job_data += "[job]: [SSjob.job_priority_level_to_string(priority)]" + to_chat(player, span_danger("You were unable to qualify for any roundstart antagonist role because you could not qualify for any of the roundstart jobs you were trying to qualify for, along with 'return to lobby if job is unavailable' enabled.")) + log_admin("[player.ckey] failed to qualify for any job and has [player.client.prefs.be_special.len] antag preferences enabled. They will be unable to qualify for any roundstart antagonist role. These are their job preferences - [job_data.Join(" | ")]") + else + roundstart_pop_ready++ + candidates.Add(player) + SSjob.ResetOccupations() log_dynamic("Listing [roundstart_rules.len] round start rulesets, and [candidates.len] players ready.") if (candidates.len <= 0) log_dynamic("[candidates.len] candidates.") diff --git a/code/modules/admin/verbs/ai_triumvirate.dm b/code/modules/admin/verbs/ai_triumvirate.dm index ca7ebfe7cc4..d63994a25c3 100644 --- a/code/modules/admin/verbs/ai_triumvirate.dm +++ b/code/modules/admin/verbs/ai_triumvirate.dm @@ -13,14 +13,15 @@ GLOBAL_DATUM(triple_ai_controller, /datum/triple_ai_controller) . = ..() RegisterSignal(SSjob, COMSIG_OCCUPATIONS_DIVIDED, PROC_REF(on_occupations_divided)) -/datum/triple_ai_controller/proc/on_occupations_divided(datum/source) +/datum/triple_ai_controller/proc/on_occupations_divided(datum/source, pure, allow_all) SIGNAL_HANDLER for(var/datum/job/ai/ai_datum in SSjob.joinable_occupations) ai_datum.spawn_positions = 3 - for(var/obj/effect/landmark/start/ai/secondary/secondary_ai_spawn in GLOB.start_landmarks_list) - secondary_ai_spawn.latejoin_active = TRUE - qdel(src) + if(!pure) + for(var/obj/effect/landmark/start/ai/secondary/secondary_ai_spawn in GLOB.start_landmarks_list) + secondary_ai_spawn.latejoin_active = TRUE + qdel(src) /datum/triple_ai_controller/Destroy(force) UnregisterSignal(SSjob, COMSIG_OCCUPATIONS_DIVIDED)