diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 064f438da46..186d713c717 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -41,6 +41,9 @@ var/datum/subsystem/ticker/ticker
var/totalPlayers = 0 //used for pregame stats on statpanel
var/totalPlayersReady = 0 //used for pregame stats on statpanel
+ var/queue_delay = 0
+ var/list/queued_players = list() //used for join queues when the server exceeds the hard population cap
+
var/obj/screen/cinematic = null //used for station explosion cinematic
@@ -97,6 +100,7 @@ var/datum/subsystem/ticker/ticker
if(GAME_STATE_PLAYING)
mode.process(wait * 0.1)
+ check_queue()
if(!mode.explosion_in_progress && mode.check_finished() || force_ending)
current_state = GAME_STATE_FINISHED
@@ -434,3 +438,23 @@ var/datum/subsystem/ticker/ticker
if(randomtips.len)
world << "Tip of the round: [html_encode(pick(randomtips))]"
+/datum/subsystem/ticker/proc/check_queue()
+ if(!queued_players.len || !config.hard_popcap)
+ return
+
+ queue_delay ++
+ var/mob/new_player/next_in_line = queued_players[1]
+
+ switch(queue_delay)
+ if(5) //every 5 ticks check if there is a slot available
+ if(living_player_count() < config.hard_popcap)
+ if(next_in_line && next_in_line.client)
+ next_in_line << "A slot has opened! You have approximately 20 seconds to join. \>\>Join Game\<\<."
+ next_in_line << sound('sound/misc/notice1.ogg')
+ return
+ queued_players -= next_in_line //Client disconnected, remove he
+ queue_delay = 0 //No vacancy: restart timer
+ if(20 to INFINITY) //No response from the next in line when a vacancy exists, remove he
+ next_in_line << "No response recieved. You have been removed from the line."
+ queued_players -= next_in_line
+ queue_delay = 0
\ No newline at end of file
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 009ecd8ab0f..6792cd67949 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -126,13 +126,28 @@
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
usr << "The round is either not ready, or has already finished..."
return
+
var/relevant_cap
if(config.hard_popcap && config.extreme_popcap)
relevant_cap = min(config.hard_popcap, config.extreme_popcap)
else
relevant_cap = max(config.hard_popcap, config.extreme_popcap)
- if(relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in admin_datums))
+
+ if(ticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in admin_datums)))
+ var/queue_position = ticker.queued_players.Find(usr)
+
+ if(queue_position == 1 && living_player_count() < relevant_cap) //Let them join if there is a slot available and they are the next one in line
+ LateChoices()
+ return
+
usr << "[config.hard_popcap_message]"
+ if(queue_position == 1)
+ usr << "You are next in line to join the game. You will be notified when a slot opens up."
+ else if(queue_position)
+ usr << "There are [queue_position-1] players in front of you in the queue to join the game."
+ else
+ ticker.queued_players += usr
+ usr << "You have been added to the queue to join the game. Your position in queue is [ticker.queued_players.len]."
return
LateChoices()
@@ -234,6 +249,10 @@
src << alert("[rank] is not available. Please try another.")
return 0
+ //Remove the player from the join queue if he was in one and reset the timer
+ ticker.queued_players -= src
+ ticker.queue_delay = 4
+
SSjob.AssignRole(src, rank, 1)
var/mob/living/carbon/human/character = create_character() //creates the human and transfers vars and mind