Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slotting Rework part 1 #40

Merged
merged 1 commit into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 43 additions & 98 deletions code/game/jobs/role_authority.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
14 changes: 14 additions & 0 deletions code/modules/client/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading