diff --git a/code/controllers/subsystems/job.dm b/code/controllers/subsystems/job.dm index 72c323ff3d5..c49927cde87 100644 --- a/code/controllers/subsystems/job.dm +++ b/code/controllers/subsystems/job.dm @@ -38,6 +38,8 @@ ProcessSanitizationQueue() + SSticker.setup_player_ready_list() + /datum/controller/subsystem/jobs/Recover() occupations = SSjobs.occupations unassigned = SSjobs.unassigned diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index a04a8a1eab1..6391d61c63b 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -63,6 +63,11 @@ var/datum/controller/subsystem/ticker/SSticker var/list/roundstart_callbacks + // Pre-game ready menu handling + var/total_players = 0 + var/total_players_ready = 0 + var/list/ready_player_jobs + /datum/controller/subsystem/ticker/New() NEW_SS_GLOBAL(SSticker) @@ -130,6 +135,8 @@ var/datum/controller/subsystem/ticker/SSticker if (round_progressing) pregame_timeleft-- + total_players = length(player_list) + if (current_state == GAME_STATE_PREGAME && pregame_timeleft == config.vote_autogamemode_timeleft) if (!SSvote.time_remaining) SSvote.autogamemode() @@ -322,6 +329,76 @@ var/datum/controller/subsystem/ticker/SSticker return 1 +/datum/controller/subsystem/ticker/proc/update_ready_list(var/mob/abstract/new_player/NP, force_rdy = FALSE, force_urdy = FALSE) + if(current_state >= GAME_STATE_PLAYING || SSjobs?.init_state < SS_INITSTATE_DONE) + return FALSE // don't bother once the game has started + + if(!LAZYLEN(ready_player_jobs)) + ready_player_jobs = DEPARTMENTS_LIST_INIT + + if(!isclient(NP.client) || force_urdy) + // Logged out, so force unready + return unready_player(NP.last_ready_name) + else if(NP.ready || force_rdy) + if(NP.last_ready_name != NP.client.prefs.real_name) + NP.last_ready_name = NP.client.prefs.real_name + return ready_player(NP.client.prefs) + else + return unready_player(NP.client.prefs) + +/datum/controller/subsystem/ticker/proc/ready_player(var/datum/preferences/prefs) + var/datum/job/ready_job = prefs.return_chosen_high_job() + if(!istype(ready_job)) + return FALSE + + for(var/dept in ready_job.departments) + LAZYDISTINCTADD(ready_player_jobs[dept], prefs.real_name) + LAZYSET(ready_player_jobs[dept], prefs.real_name, ready_job.title) + sortTim(ready_player_jobs[dept], /proc/cmp_text_asc) + . = TRUE + + if(.) + total_players_ready++ + +/datum/controller/subsystem/ticker/proc/unready_player(var/ident, var/force_name = FALSE) + if(isnull(ident)) + return FALSE + + var/datum/preferences/prefs = ident + if(!istype(prefs) || force_name) + // trawl the whole list - we only do this on logout or job swap, aka when we can't guarantee the job datum being accurate + for(var/dept in ready_player_jobs) + if(ready_player_jobs[dept][ident]) + . = TRUE + ready_player_jobs[dept] -= ident + if(.) + total_players_ready-- + return + + var/datum/job/ready_job = prefs.return_chosen_high_job() + + for(var/dept in ready_job.departments) + if(ready_player_jobs[dept][prefs.real_name]) + . = TRUE + LAZYREMOVE(ready_player_jobs[dept], prefs.real_name) + + if(.) + total_players_ready-- + +/datum/controller/subsystem/ticker/proc/cycle_player(var/mob/abstract/new_player/NP, var/datum/job/job) + // exclusively used for occupation.dm, when players swap job priority while readied + if(current_state >= GAME_STATE_PLAYING || SSjobs?.init_state < SS_INITSTATE_DONE || !NP.ready) + return FALSE + + update_ready_list(NP, force_urdy = TRUE) + update_ready_list(NP) + +/datum/controller/subsystem/ticker/proc/setup_player_ready_list() + for(var/mob/abstract/new_player/NP in player_list) + // initial setup to catch people who readied 0.1 seconds into init + if(NP.ready) + update_ready_list(NP) + /datum/controller/subsystem/ticker/proc/send_tip_of_the_round() var/m if(selected_tip) @@ -353,6 +430,8 @@ var/datum/controller/subsystem/ticker/SSticker else var/mc_init_time = round(Master.initialization_time_taken, 1) var/dynamic_time = LOBBY_TIME - mc_init_time + total_players = length(player_list) + LAZYINITLIST(ready_player_jobs) if (dynamic_time <= config.vote_autogamemode_timeleft) pregame_timeleft = config.vote_autogamemode_timeleft + 10 @@ -361,6 +440,8 @@ var/datum/controller/subsystem/ticker/SSticker pregame_timeleft = dynamic_time log_debug("SSticker: dynamic set pregame time [dynamic_time]s was greater than configured autogamemode time, not clamping.") + setup_player_ready_list() + to_world("Welcome to the pre-game lobby!") to_world("Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds.") callHook("pregame_start") diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm index 7852c6ed2aa..62062aaeac6 100644 --- a/code/modules/client/preference_setup/occupation/occupation.dm +++ b/code/modules/client/preference_setup/occupation/occupation.dm @@ -325,15 +325,19 @@ pref.job_civilian_low &= ~job.flag else pref.job_civilian_low |= job.flag + + SSticker.cycle_player(user, job) return TRUE - if(pref.GetJobDepartment(job, 1) & job.flag) + if(pref.GetJobDepartment(job, 1) & job.flag) // HIGH -> NONE SetJobDepartment(job, 1) - else if(pref.GetJobDepartment(job, 2) & job.flag) + SSticker.cycle_player(user, job) + else if(pref.GetJobDepartment(job, 2) & job.flag) // MED -> HIGH SetJobDepartment(job, 2) - else if(pref.GetJobDepartment(job, 3) & job.flag) + SSticker.cycle_player(user, job) + else if(pref.GetJobDepartment(job, 3) & job.flag) // LOW -> MED SetJobDepartment(job, 3) - else//job = Never + else // NONE -> LOW SetJobDepartment(job, 4) return 1 diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index ff9f1383d1b..b4256b0b582 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -48,6 +48,12 @@ /datum/preferences/proc/load_character(slot) var/savefile/S + var/mob/abstract/new_player/NP = src.client.mob + var/readied + if(istype(NP) && NP.ready) + readied = TRUE + SSticker.update_ready_list(NP, force_urdy=TRUE) + if (!config.sql_saves) if (!path) return 0 @@ -75,6 +81,9 @@ else save_preferences() + if(istype(NP) && readied) + SSticker.update_ready_list(NP) + return 1 /datum/preferences/proc/save_character() diff --git a/code/modules/mob/abstract/new_player/logout.dm b/code/modules/mob/abstract/new_player/logout.dm index 03a9fffde12..7dd17bd0f6e 100644 --- a/code/modules/mob/abstract/new_player/logout.dm +++ b/code/modules/mob/abstract/new_player/logout.dm @@ -1,5 +1,6 @@ /mob/abstract/new_player/Logout() - ready = 0 + ready = FALSE + SSticker.update_ready_list(src) // see login.dm if(my_client) diff --git a/code/modules/mob/abstract/new_player/menu.dm b/code/modules/mob/abstract/new_player/menu.dm index 2a79ec03958..8b4fc81c0d6 100644 --- a/code/modules/mob/abstract/new_player/menu.dm +++ b/code/modules/mob/abstract/new_player/menu.dm @@ -234,6 +234,9 @@ return ready = readying + if(ready) + last_ready_name = client.prefs.real_name + SSticker.update_ready_list(src) else ready = FALSE diff --git a/code/modules/mob/abstract/new_player/new_player.dm b/code/modules/mob/abstract/new_player/new_player.dm index ef24b2c88df..d82b7c7c367 100644 --- a/code/modules/mob/abstract/new_player/new_player.dm +++ b/code/modules/mob/abstract/new_player/new_player.dm @@ -3,8 +3,6 @@ /mob/abstract/new_player var/ready = 0 var/spawning = 0 //Referenced when you want to delete the new_player later on in the code - var/totalPlayers = 0 //Player counts for the Lobby tab - var/totalPlayersReady = 0 var/datum/late_choices/late_choices_ui = null universal_speak = 1 @@ -17,6 +15,8 @@ anchored = 1 // don't get pushed around simulated = FALSE + var/last_ready_name // This has to be saved because the client is nulled prior to Logout() + INITIALIZE_IMMEDIATE(/mob/abstract/new_player) /mob/abstract/new_player/Initialize() @@ -41,19 +41,14 @@ INITIALIZE_IMMEDIATE(/mob/abstract/new_player) stat("Game Mode:", "[master_mode]") // Old setting for showing the game mode if(SSticker.current_state == GAME_STATE_PREGAME) - if (SSticker.lobby_ready) - stat("Time To Start:", "[SSticker.pregame_timeleft][round_progressing ? "" : " (DELAYED)"]") - else - stat("Time To Start:", "Waiting for Server") - stat("Players: [totalPlayers]", "Players Ready: [totalPlayersReady]") - totalPlayers = 0 - totalPlayersReady = 0 - for(var/mob/abstract/new_player/player in player_list) - totalPlayers++ - if(player.ready) - var/job_ready = player.client.prefs.return_chosen_high_job(TRUE) - stat("[copytext_char(player.client.prefs.real_name, 1, 18)]", job_ready ? "[job_ready]" : "N/A") - totalPlayersReady++ + stat("Time To Start:", "[SSticker.pregame_timeleft][round_progressing ? "" : " (DELAYED)"]") + stat("Players: [length(player_list)]", "Players Ready: [SSticker.total_players_ready]") + if(SSjobs.init_state >= SS_INITSTATE_DONE) + for(var/dept in SSticker.ready_player_jobs) + if(LAZYLEN(SSticker.ready_player_jobs[dept])) + stat(uppertext(dept), null) + for(var/char in SSticker.ready_player_jobs[dept]) + stat("[copytext_char(char, 1, 18)]", "[SSticker.ready_player_jobs[dept][char]]") /mob/abstract/new_player/Topic(href, href_list[]) if(!client) return 0 diff --git a/html/changelogs/johnwildkins-fixlobby.yml b/html/changelogs/johnwildkins-fixlobby.yml new file mode 100644 index 00000000000..10a8f90e4f1 --- /dev/null +++ b/html/changelogs/johnwildkins-fixlobby.yml @@ -0,0 +1,7 @@ +author: JohnWildkins + +delete-after: True + +changes: + - refactor: "The list of readied players has been optimized, lowering pre-game server load." + - tweak: "The readied player list now sorts by department and name, displaying readied players by department."