From 2141fcb2bfcdc5888b563e4ca8cef98a50189b89 Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Fri, 3 Nov 2023 13:57:46 -0400 Subject: [PATCH] Slotting Rework part 1 (#40) --- code/game/jobs/role_authority.dm | 141 +++++++++-------------------- code/modules/client/preferences.dm | 14 +++ 2 files changed, 57 insertions(+), 98 deletions(-) diff --git a/code/game/jobs/role_authority.dm b/code/game/jobs/role_authority.dm index c147807f00..efb5e2ae8d 100644 --- a/code/game/jobs/role_authority.dm +++ b/code/game/jobs/role_authority.dm @@ -234,55 +234,16 @@ I hope it's easier to tell what the heck this proc is even doing, unlike previou if(length(overwritten_roles_for_mode)) temp_roles_for_mode = overwritten_roles_for_mode - // Get balancing weight for the readied players. - // Squad marine roles have a weight of 1, and shipside roles have a lower weight of SHIPSIDE_ROLE_WEIGHT. - players_preassigned = assign_roles(temp_roles_for_mode.Copy(), unassigned_players.Copy(), TRUE) - - // Even though we pass a copy of temp_roles_for_mode, job counters still change, so we reset them here. - for(var/title in temp_roles_for_mode) - var/datum/job/J = temp_roles_for_mode[title] - J.current_positions = 0 - - // Set up limits for other roles based on our balancing weight number. - // Set the xeno starting amount based on marines assigned - var/datum/job/antag/xenos/XJ = temp_roles_for_mode[JOB_XENOMORPH] - if(istype(XJ)) - XJ.set_spawn_positions(players_preassigned) - - // Limit the number of SQUAD MARINE roles players can roll initially - var/datum/job/SMJ = GET_MAPPED_ROLE(JOB_SQUAD_MARINE) - if(istype(SMJ)) - SMJ.set_spawn_positions(players_preassigned) - - // Set survivor starting amount based on marines assigned - var/datum/job/SJ = temp_roles_for_mode[JOB_SURVIVOR] - if(istype(SJ)) - SJ.set_spawn_positions(players_preassigned) - - var/datum/job/CO_surv_job = temp_roles_for_mode[JOB_CO_SURVIVOR] - if(istype(CO_surv_job)) - CO_surv_job.set_spawn_positions(players_preassigned) - - if(SSnightmare.get_scenario_value("predator_round")) - SSticker.mode.flags_round_type |= MODE_PREDATOR - // Set predators starting amount based on marines assigned - var/datum/job/PJ = temp_roles_for_mode[JOB_PREDATOR] - if(istype(PJ)) - PJ.set_spawn_positions(players_preassigned) - // Assign the roles, this time for real, respecting limits we have established. var/list/roles_left = assign_roles(temp_roles_for_mode, unassigned_players) - var/alternate_option_assigned = 0; for(var/mob/new_player/M in unassigned_players) switch(M.client.prefs.alternate_option) if(GET_RANDOM_JOB) roles_left = assign_random_role(M, roles_left) //We want to keep the list between assignments. - alternate_option_assigned++ if(BE_MARINE) var/datum/job/marine_job = GET_MAPPED_ROLE(JOB_SQUAD_MARINE) assign_role(M, marine_job) //Should always be available, in all game modes, as a candidate. Even if it may not be a marine. - alternate_option_assigned++ if(BE_XENOMORPH) assign_role(M, temp_roles_for_mode[JOB_XENOMORPH]) if(RETURN_TO_LOBBY) @@ -295,70 +256,54 @@ I hope it's easier to tell what the heck this proc is even doing, unlike previou unassigned_players = null - // Now we take spare unfilled xeno slots and make them larva NEW - var/datum/hive_status/hive = GLOB.hive_datum[XENO_HIVE_NORMAL] - if(istype(hive) && istype(XJ)) - hive.stored_larva += max(0, (XJ.total_positions - XJ.current_positions) \ - + (XJ.calculate_extra_spawn_positions(alternate_option_assigned))) - /*===============================================================*/ -/** -* Assign roles to the players. Return roles that are still avialable. -* If count is true, return role balancing weight instead. -*/ -/datum/authority/branch/role/proc/assign_roles(list/roles_for_mode, list/unassigned_players, count = FALSE) - var/list/roles_left = list() - var/assigned = 0 - for(var/priority in HIGH_PRIORITY to LOW_PRIORITY) - // Assigning xenos first. - assigned += assign_initial_roles(priority, roles_for_mode & ROLES_XENO, unassigned_players) - // Assigning special roles second. (survivor, predator) - assigned += assign_initial_roles(priority, roles_for_mode & (ROLES_WHITELISTED|ROLES_SPECIAL), unassigned_players) - // Assigning command third. - assigned += assign_initial_roles(priority, roles_for_mode & ROLES_COMMAND, unassigned_players) - // Assigning the rest - var/rest_roles_for_mode = roles_for_mode - (roles_for_mode & ROLES_XENO) - (roles_for_mode & ROLES_COMMAND) - (roles_for_mode & (ROLES_WHITELISTED|ROLES_SPECIAL)) - if(count) - assigned += assign_initial_roles(priority, rest_roles_for_mode, unassigned_players) - else - roles_left= assign_initial_roles(priority, rest_roles_for_mode, unassigned_players, FALSE) - if(count) - return assigned - return roles_left - -/datum/authority/branch/role/proc/assign_initial_roles(priority, list/roles_to_iterate, list/unassigned_players, count = TRUE) - var/assigned = 0 - if(!length(roles_to_iterate) || !length(unassigned_players)) +/// Assign roles to the players. Return roles that are still available. +/datum/authority/branch/role/proc/assign_roles(list/roles_to_assign, list/unassigned_players) + if(!length(roles_to_assign) || !length(unassigned_players)) return - for(var/job in roles_to_iterate) - var/datum/job/J = roles_to_iterate[job] - if(!istype(J)) //Shouldn't happen, but who knows. - to_world(SPAN_DEBUG("Error setting up jobs, no job datum set for: [job].")) - log_debug("Error setting up jobs, no job datum set for: [job].") - continue + for(var/mob/new_player/cycled_unassigned in shuffle(unassigned_players)) + var/player_assigned_job = FALSE + log_debug("We have started assigning for [cycled_unassigned]") + + for(var/priority in HIGH_PRIORITY to LOW_PRIORITY) + var/wanted_jobs_by_name = shuffle(cycled_unassigned.client?.prefs?.get_jobs_by_priority(priority)) + log_debug("We have started cycled through priority [priority] for [cycled_unassigned]") + + for(var/job_name in wanted_jobs_by_name) + log_debug("We are cycling through wanted jobs and are at [job_name] for [cycled_unassigned]") + if(job_name in roles_to_assign) + log_debug("We have found [job_name] in roles to assign for [cycled_unassigned]") + var/datum/job/actual_job = roles_to_assign[job_name] + + if(assign_role(cycled_unassigned, actual_job)) + log_debug("We have assigned [job_name] to [cycled_unassigned]") + unassigned_players -= cycled_unassigned + + if(actual_job.spawn_positions != -1 && actual_job.current_positions >= actual_job.spawn_positions) + roles_to_assign -= job_name + log_debug("We have ran out of slots for [job_name] and it has been removed from roles to assign") + + player_assigned_job = TRUE + break + + if(player_assigned_job) + log_debug("[cycled_unassigned] has been assigned a job and we are breaking") + break + + log_debug("[cycled_unassigned] did not get a job at priority [priority], moving to next priority level") + + if(!length(roles_to_assign)) + log_debug("No more roles to assign, breaking") + break + + if(!player_assigned_job) + log_debug("[cycled_unassigned] was unable to be assigned a job based on preferences and roles to assign. We still have roles to assign, continuing to next player") + + log_debug("Assigning complete. Players unassigned: [length(unassigned_players)] Jobs unassigned: [length(roles_to_assign)]") - var/role_weight = calculate_role_weight(J) - for(var/M in unassigned_players) - var/mob/new_player/NP = M - if(!(NP.client.prefs.get_job_priority(J.title) == priority)) - continue //If they don't want the job. //TODO Change the name of the prefs proc? - - if(assign_role(NP, J)) - assigned += role_weight - unassigned_players -= NP - // -1 check is not strictly needed here, since standard marines are - // supposed to have an actual spawn_positions number at this point - if(J.spawn_positions != -1 && J.current_positions >= J.spawn_positions) - roles_to_iterate -= job //Remove the position, since we no longer need it. - break //Maximum position is reached? - - if(!length(unassigned_players)) - break //No players left to assign? Break. - if(count) - return assigned - return roles_to_iterate + return roles_to_assign /** * Calculate role balance weight for one person joining as that role. This weight is used diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 50b0d2977e..fd11ed2931 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -908,6 +908,20 @@ var/const/MAX_SAVE_SLOTS = 10 return job_preference_list[J] +/// Returns a list of all the proference's jobs set to the priority argument +/datum/preferences/proc/get_jobs_by_priority(priority) + var/list/jobs_to_return = list() + + if(!length(job_preference_list)) + ResetJobs() + return jobs_to_return + + for(var/job in job_preference_list) + if(job_preference_list[job] == priority) + jobs_to_return += job + + return jobs_to_return + /datum/preferences/proc/SetJobDepartment(datum/job/J, priority) if(!J || priority < 0 || priority > 4) return FALSE