From 2e1607f611d5cd7efa4764303b9a6367a19c370d Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 3 Aug 2015 11:58:35 -0400 Subject: [PATCH 1/2] Fixes #10414 Antagonists are again drafted in attempt_spawn() and all players in the pending list will be spawned (provided they pass sanity checks). Instead, attempt_spawn() is called in either pre_setup() or post_setup() depending on if the ANTAG_OVERRIDE_JOB flag is set. And all antags have their spawning finalized in post_setup(). In addition, if game mode setup fails, all pending antagonist players have their special roles cleared. --- code/game/antagonist/antagonist.dm | 49 ++++++++++++++++++-------- code/game/antagonist/antagonist_add.dm | 2 ++ code/game/gamemodes/game_mode.dm | 26 +++++++------- code/game/gamemodes/gameticker.dm | 1 + 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 8916316f9a3..966c65ee5b6 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -89,6 +89,11 @@ add_antagonist(player,0,1,0,1,1) return +//Selects players that will be spawned in the antagonist role from the potential candidates +//Selected players are added to the pending_antagonists lists. +//Attempting to spawn an antag role with ANTAG_OVERRIDE_JOB should be done before jobs are assigned, +//so that they do not occupy regular job slots. All other antag roles should be spawned after jobs are +//assigned, so that job restrictions can be respected. /datum/antagonist/proc/attempt_spawn(var/ghosts_only) // Get the raw list of potential players. @@ -99,29 +104,43 @@ if(!candidates.len) return 0 - // Not sure if this is necessary, just in case. - pending_antagonists = candidates - candidates = list() - //Grab candidates randomly until we have enough. while(candidates.len && pending_antagonists.len < cur_max) var/datum/mind/player = pick(candidates) - pending_antagonists |= player candidates -= player + draft_antagonist(player) + return 1 -//Drafting players into the antagonist role must be done when antagonists are finalized. -//This ensures that if a player is a candidate for multiple antag roles, they do not prevent other -//players from being selected for all of the other antag roles that the player was not selected for. +/datum/antagonist/proc/draft_antagonist(var/datum/mind/player) + //Check if the player can join in this antag role, or if the player has already been given an antag role. + if(can_become_antag(player) && !player.special_role) + return 0 + + pending_antagonists |= player + + //Ensure that antags with ANTAG_OVERRIDE_JOB do not occupy job slots. + if(flags & ANTAG_OVERRIDE_JOB) + player.assigned_role = role_text + + //Ensure that a player cannot be drafted for multiple antag roles, taking up slots for antag roles that they will not fill. + player.special_role = role_text + + return 1 + +//Spawns all pending_antagonists. This is done separately from attempt_spawn in case the game mode setup fails. /datum/antagonist/proc/finalize_spawn() if(!pending_antagonists) return - while(pending_antagonists.len && current_antagonists.len < cur_max) - var/datum/mind/player = pick(pending_antagonists) + for(var/datum/mind/player in pending_antagonists) pending_antagonists -= player - - //Check for restricted job status since players will have been assigned jobs by this point. - //Or if the player has already been given an antag role. - if(can_become_antag(player) && !player.special_role) - add_antagonist(player,0,0,1) + add_antagonist(player,0,0,1) + +//Resets all pending_antagonists, clearing their special_role (and assigned_role if ANTAG_OVERRIDE_JOB is set) +/datum/antagonist/proc/reset() + for(var/datum/mind/player in pending_antagonists) + if(flags & ANTAG_OVERRIDE_JOB) + player.assigned_role = null + player.special_role = null + pending_antagonists.Cut() diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm index c16ea0a7c9f..7815167d6fe 100644 --- a/code/game/antagonist/antagonist_add.dm +++ b/code/game/antagonist/antagonist_add.dm @@ -9,6 +9,8 @@ return 0 current_antagonists |= player + + //do this again, just in case if(flags & ANTAG_OVERRIDE_JOB) player.assigned_role = role_text player.special_role = role_text diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 5d5244fcc05..d409b511ca8 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -264,14 +264,9 @@ var/global/list/additional_antag_types = list() /datum/game_mode/proc/pre_setup() //antag roles that replace jobs need to be assigned before the job controller hands out jobs. - if(antag_templates) - for(var/datum/antagonist/antag in antag_templates) - antag.attempt_spawn() //selects antag role candidates - - if(antag.flags & ANTAG_OVERRIDE_JOB) - antag.finalize_spawn() - if(antag.is_latejoin_template()) - latejoin_templates |= antag + for(var/datum/antagonist/antag in antag_templates) + if(antag.flags & ANTAG_OVERRIDE_JOB) + antag.attempt_spawn() ///post_setup() /datum/game_mode/proc/post_setup() @@ -287,11 +282,12 @@ var/global/list/additional_antag_types = list() announce_ert_disabled() //Assign all antag types for this game mode. Any players spawned as antags earlier should have been removed from the pending list, so no need to worry about those. - if(antag_templates && antag_templates.len) - for(var/datum/antagonist/antag in antag_templates) - antag.finalize_spawn() - if(antag.is_latejoin_template()) - latejoin_templates |= antag + for(var/datum/antagonist/antag in antag_templates) + if(!(antag.flags & ANTAG_OVERRIDE_JOB)) + antag.attempt_spawn() + antag.finalize_spawn() + if(antag.is_latejoin_template()) + latejoin_templates |= antag if(emergency_shuttle && auto_recall_shuttle) emergency_shuttle.auto_recall = 1 @@ -302,6 +298,10 @@ var/global/list/additional_antag_types = list() feedback_set_details("server_ip","[world.internet_address]:[world.port]") return 1 +/datum/game_mode/proc/fail_setup() + for(var/datum/antagonist/antag in antag_templates) + antag.reset() + /datum/game_mode/proc/announce_ert_disabled() if(!ert_disabled) return diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index d9a91cb57de..bfffffc8ff9 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -98,6 +98,7 @@ var/global/datum/controller/gameticker/ticker if(!mode_started && !src.mode.can_start()) world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby." current_state = GAME_STATE_PREGAME + mode.fail_setup() mode = null job_master.ResetOccupations() return 0 From 76ceaa904b3bd3f80e0a5f04edf12fe21938f340 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 3 Aug 2015 12:06:23 -0400 Subject: [PATCH 2/2] Fixes admin or event spawned antags not spawning Pending players were selected but the antag roles were never finalized. --- code/game/antagonist/antagonist.dm | 1 + code/modules/admin/verbs/striketeam.dm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 966c65ee5b6..08d21673c7f 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -77,6 +77,7 @@ /datum/antagonist/proc/attempt_random_spawn() attempt_spawn(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) + finalize_spawn() /datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player) if(!can_late_spawn()) diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index ef217b16f96..37fc52eda80 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -52,4 +52,4 @@ var/const/commandos_possible = 6 //if more Commandos are needed in the future usr << "Looks like someone beat you to it." return - team.attempt_spawn(1) + team.attempt_random_spawn()