diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index e5d1f4c19e10..670a1778fb15 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -2,6 +2,11 @@ //Misc mob defines +//Ready states at roundstart for mob/dead/new_player +#define PLAYER_NOT_READY 0 +#define PLAYER_READY_TO_PLAY 1 +#define PLAYER_READY_TO_OBSERVE 2 + //movement intent defines for the m_intent var #define MOVE_INTENT_WALK "walk" #define MOVE_INTENT_RUN "run" @@ -128,4 +133,4 @@ #define INCORPOREAL_MOVE_BASIC 1 #define INCORPOREAL_MOVE_SHADOW 2 // leaves a trail of shadows -#define INCORPOREAL_MOVE_JAUNT 3 // is blocked by holy water/salt \ No newline at end of file +#define INCORPOREAL_MOVE_JAUNT 3 // is blocked by holy water/salt diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 05d8dbb5b7e9..731166e0a9f5 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -224,7 +224,7 @@ SUBSYSTEM_DEF(job) //Get the players who are ready for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.ready && player.mind && !player.mind.assigned_role) + if(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role) unassigned += player initial_players_to_assign = unassigned.len @@ -456,7 +456,7 @@ SUBSYSTEM_DEF(job) var/level5 = 0 //banned var/level6 = 0 //account too young for(var/mob/dead/new_player/player in GLOB.player_list) - if(!(player.ready && player.mind && !player.mind.assigned_role)) + if(!(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role)) continue //This player is not ready if(jobban_isbanned(player, job.title)) level5++ @@ -489,7 +489,7 @@ SUBSYSTEM_DEF(job) Debug("Popcap overflow Check observer located, Player: [player]") to_chat(player, "You have failed to qualify for any job you desired.") unassigned -= player - player.ready = 0 + player.ready = PLAYER_NOT_READY /datum/controller/subsystem/job/Recover() diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 55f3fc26afae..2a1f54e1712e 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -83,6 +83,8 @@ SUBSYSTEM_DEF(ticker) window_flash(C, ignorepref = TRUE) //let them know lobby has opened up. to_chat(world, "Welcome to [station_name()]!") current_state = GAME_STATE_PREGAME + //Everyone who wants to be an observer is now spawned + create_observers() fire() if(GAME_STATE_PREGAME) //lobby stats for statpanels @@ -92,7 +94,7 @@ SUBSYSTEM_DEF(ticker) totalPlayersReady = 0 for(var/mob/dead/new_player/player in GLOB.player_list) ++totalPlayers - if(player.ready) + if(player.ready == PLAYER_READY_TO_PLAY) ++totalPlayersReady if(start_immediately) @@ -131,6 +133,7 @@ SUBSYSTEM_DEF(ticker) declare_completion(force_ending) Master.SetRunLevel(RUNLEVEL_POSTGAME) + /datum/controller/subsystem/ticker/proc/setup() to_chat(world, "Starting game...") var/init_start = world.timeofday @@ -402,7 +405,7 @@ SUBSYSTEM_DEF(ticker) /datum/controller/subsystem/ticker/proc/create_characters() for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.ready && player.mind) + if(player.ready == PLAYER_READY_TO_PLAY && player.mind) GLOB.joined_player_list += player.ckey player.create_character(FALSE) else @@ -793,6 +796,13 @@ SUBSYSTEM_DEF(ticker) else timeLeft = newtime +//Everyone who wanted to be an observer gets made one now +/datum/controller/subsystem/ticker/proc/create_observers() + for(var/mob/dead/new_player/player in GLOB.player_list) + if(player.ready == PLAYER_READY_TO_OBSERVE && player.mind) + //Break chain since this has a sleep input in it + addtimer(CALLBACK(player, /mob/dead/new_player.proc/make_me_an_observer), 1) + /datum/controller/subsystem/ticker/proc/load_mode() var/mode = trim(file2text("data/mode.txt")) if(mode) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 1fe8fcac652d..b5f2b1cec125 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -54,7 +54,7 @@ /datum/game_mode/proc/can_start() var/playerC = 0 for(var/mob/dead/new_player/player in GLOB.player_list) - if((player.client)&&(player.ready)) + if((player.client)&&(player.ready == PLAYER_READY_TO_PLAY)) playerC++ if(!GLOB.Debug2) if(playerC < required_players || (maximum_players >= 0 && playerC > maximum_players)) @@ -308,7 +308,7 @@ // Ultimate randomizing code right here for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.client && player.ready) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) players += player // Shuffling, the players list is now ping-independent!!! @@ -316,7 +316,7 @@ players = shuffle(players) for(var/mob/dead/new_player/player in players) - if(player.client && player.ready) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) if(role in player.client.prefs.be_special) if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans if(age_check(player.client)) //Must be older than the minimum age @@ -330,7 +330,7 @@ if(candidates.len < recommended_enemies) for(var/mob/dead/new_player/player in players) - if(player.client && player.ready) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) if(!(role in player.client.prefs.be_special)) // We don't have enough people who want to be antagonist, make a seperate list of people who don't want to be one if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans drafted += player.mind @@ -352,13 +352,7 @@ else // Not enough scrubs, ABORT ABORT ABORT break -/* - if(candidates.len < recommended_enemies && override_jobbans) //If we still don't have enough people, we're going to start drafting banned people. - for(var/mob/dead/new_player/player in players) - if (player.client && player.ready) - if(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans - drafted += player.mind -*/ + if(restricted_jobs) for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist for(var/job in restricted_jobs) @@ -381,17 +375,12 @@ // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies, // Less if there are not enough valid players in the game entirely to make recommended_enemies. -/* -/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/dead/new_player/player) - if(player.preferences.be_special & role) - return 1 - return 0 -*/ + /datum/game_mode/proc/num_players() . = 0 for(var/mob/dead/new_player/P in GLOB.player_list) - if(P.client && P.ready) + if(P.client && P.ready == PLAYER_READY_TO_PLAY) . ++ /////////////////////////////////// diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 039b4cc3a45c..21b1180b3d32 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -658,7 +658,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) var/n_p = 1 //autowin if (SSticker.current_state == GAME_STATE_SETTING_UP) for(var/mob/dead/new_player/P in GLOB.player_list) - if(P.client && P.ready && P.mind!=owner) + if(P.client && P.ready == PLAYER_READY_TO_PLAY && P.mind!=owner) n_p ++ else if (SSticker.IsRoundInProgress()) for(var/mob/living/carbon/human/P in GLOB.player_list) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index c8bc7f4ff5b1..39f4afba5960 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -1,4 +1,4 @@ - +#define LINKIFY_READY(string, value) "[string]" /mob/dead/new_player var/ready = 0 @@ -30,20 +30,20 @@ return /mob/dead/new_player/proc/new_player_panel() + var/output = "

Setup Character

" - var/output = "

Setup Character

" - - if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME) - if(ready) - output += "

\[ Ready | Not Ready \]

" - else - output += "

\[ Ready | Not Ready \]

" - + if(SSticker && SSticker.current_state <= GAME_STATE_PREGAME) + switch(ready) + if(PLAYER_NOT_READY) + output += "

\[ [LINKIFY_READY("Ready", PLAYER_READY_TO_PLAY)] | Not Ready | [LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)] \]

" + if(PLAYER_READY_TO_PLAY) + output += "

\[ Ready | [LINKIFY_READY("Not Ready", PLAYER_NOT_READY)] | [LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)] \]

" + if(PLAYER_READY_TO_OBSERVE) + output += "

\[ [LINKIFY_READY("Ready", PLAYER_READY_TO_PLAY)] | [LINKIFY_READY("Not Ready", PLAYER_NOT_READY)] | Observe \]

" else - output += "

View the Crew Manifest

" - output += "

Join Game!

" - - output += "

Observe

" + output += "

View the Crew Manifest

" + output += "

Join Game!

" + output += "

[LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)]

" if(!IsGuestKey(src.key)) if (SSdbcore.Connect()) @@ -65,7 +65,7 @@ output += "
" //src << browse(output,"window=playersetup;size=210x240;can_close=0") - var/datum/browser/popup = new(src, "playersetup", "
New Player Options
", 220, 265) + var/datum/browser/popup = new(src, "playersetup", "
New Player Options
", 250, 265) popup.set_window_options("can_close=0") popup.set_content(output) popup.open(0) @@ -108,42 +108,23 @@ return 1 if(href_list["ready"]) - if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started - ready = text2num(href_list["ready"]) + if(SSticker) + var/tready = text2num(href_list["ready"]) + //Avoid updating ready if we're after PREGAME (they should use latejoin instead) + //This is likely not an actual issue but I don't have time to prove that this + //no longer is required + if(SSticker.current_state <= GAME_STATE_PREGAME) + ready = tready + //if it's post initialisation and they're trying to observe we do the needful + if(!SSticker.current_state < GAME_STATE_PREGAME && tready == PLAYER_READY_TO_OBSERVE) + ready = tready + make_me_an_observer() + return if(href_list["refresh"]) src << browse(null, "window=playersetup") //closes the player setup window new_player_panel() - if(href_list["observe"]) - - if(alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") == "Yes") - if(!client) - return 1 - var/mob/dead/observer/observer = new() - - spawning = 1 - - observer.started_as_observer = 1 - close_spawn_windows() - var/obj/O = locate("landmark*Observer-Start") - to_chat(src, "Now teleporting.") - if (O) - observer.loc = O.loc - else - to_chat(src, "Teleporting failed. The map is probably still loading...") - observer.key = key - observer.client = client - observer.set_ghost_appearance() - if(observer.client && observer.client.prefs) - observer.real_name = observer.client.prefs.real_name - observer.name = observer.real_name - observer.update_icon() - observer.stop_sound_channel(CHANNEL_LOBBYMUSIC) - QDEL_NULL(mind) - qdel(src) - return 1 - if(href_list["late_join"]) if(!SSticker || !SSticker.IsRoundInProgress()) to_chat(usr, "The round is either not ready, or has already finished...") @@ -273,6 +254,44 @@ return to_chat(src, "Vote successful.") +//When you cop out of the round (NB: this HAS A SLEEP FOR PLAYER INPUT IN IT) +/mob/dead/new_player/proc/make_me_an_observer() + if(QDELETED(src) || !src.client) + ready = PLAYER_NOT_READY + return FALSE + + var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") + + if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes") + ready = PLAYER_NOT_READY + src << browse(null, "window=playersetup") //closes the player setup window + new_player_panel() + return FALSE + + var/mob/dead/observer/observer = new() + spawning = TRUE + + observer.started_as_observer = TRUE + close_spawn_windows() + var/obj/O = locate("landmark*Observer-Start") + to_chat(src, "Now teleporting.") + if (O) + observer.loc = O.loc + else + to_chat(src, "Teleporting failed. Ahelp an admin please") + stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised") + observer.key = key + observer.client = client + observer.set_ghost_appearance() + if(observer.client && observer.client.prefs) + observer.real_name = observer.client.prefs.real_name + observer.name = observer.real_name + observer.update_icon() + observer.stop_sound_channel(CHANNEL_LOBBYMUSIC) + QDEL_NULL(mind) + qdel(src) + return TRUE + /mob/dead/new_player/proc/IsJobAvailable(rank) var/datum/job/job = SSjob.GetJob(rank) if(!job)