diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index d9bc5c56901..011ae5ebe6c 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -86,7 +86,8 @@ /datum/antagonist/proc/tick() return 1 -/datum/antagonist/proc/get_candidates(var/ghosts_only) +// Get the raw list of potential players. +/datum/antagonist/proc/build_candidate_list(var/ghosts_only) candidates = list() // Clear. // Prune restricted status. Broke it up for readability. @@ -108,46 +109,57 @@ return candidates /datum/antagonist/proc/attempt_random_spawn() + update_current_antag_max() build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) attempt_spawn() finalize_spawn() -/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player) +/datum/antagonist/proc/attempt_auto_spawn() if(!can_late_spawn()) return 0 - if(!istype(player)) - var/list/players = get_candidates(is_latejoin_template()) - if(players && players.len) - player = pick(players) - if(!istype(player)) - message_admins("AUTO[uppertext(ticker.mode.name)]: Failed to find a candidate for [role_text].") - return 0 - player.current << "You have been selected this round as an antagonist!" - message_admins("AUTO[uppertext(ticker.mode.name)]: Selected [player] as a [role_text].") - if(istype(player.current, /mob/dead)) - create_default(player.current) - else - add_antagonist(player,0,0,0,1,1) - return 1 -/datum/antagonist/proc/build_candidate_list(var/ghosts_only) - // Get the raw list of potential players. update_current_antag_max() - candidates = get_candidates(ghosts_only) + var/active_antags = get_active_antag_count() + log_debug("[uppertext(id)]: Found [active_antags]/[cur_max] active [role_text_plural].") + + if(active_antags >= cur_max) + log_debug("Could not auto-spawn a [role_text], active antag limit reached.") + return 0 + + build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) + if(!candidates.len) + log_debug("Could not auto-spawn a [role_text], no candidates found.") + return 0 + + attempt_spawn(1) //auto-spawn antags one at a time + if(!pending_antagonists.len) + log_debug("Could not auto-spawn a [role_text], none of the available candidates could be selected.") + return 0 + + var/datum/mind/player = pending_antagonists[1] + if(!add_antagonist(player,0,0,0,1,1)) + log_debug("Could not auto-spawn a [role_text], failed to add antagonist.") + return 0 + + reset_antag_selection() + + return 1 //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/rebuild_candidates = 1) +/datum/antagonist/proc/attempt_spawn(var/spawn_target = null) + if(spawn_target == null) + spawn_target = initial_spawn_target // Update our boundaries. if(!candidates.len) return 0 //Grab candidates randomly until we have enough. - while(candidates.len && pending_antagonists.len < initial_spawn_target) + while(candidates.len && pending_antagonists.len < spawn_target) var/datum/mind/player = pick(candidates) candidates -= player draft_antagonist(player) diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index 056fbd18651..37e332d8efb 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -20,6 +20,9 @@ /datum/antagonist/proc/get_antag_count() return current_antagonists ? current_antagonists.len : 0 +/datum/antagonist/proc/get_active_antag_count() + return get_antag_count() //TODO + /datum/antagonist/proc/is_antagonist(var/datum/mind/player) if(player in current_antagonists) return 1 @@ -33,9 +36,6 @@ return (flags & ANTAG_VOTABLE) /datum/antagonist/proc/can_late_spawn() - update_current_antag_max() - if(get_antag_count() >= cur_max) - return 0 return 1 /datum/antagonist/proc/is_latejoin_template() diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm index 52fa7e3f38e..a277df922b2 100644 --- a/code/game/antagonist/station/rogue_ai.dm +++ b/code/game/antagonist/station/rogue_ai.dm @@ -22,13 +22,11 @@ var/datum/antagonist/rogue_ai/malf malf = src -/datum/antagonist/rogue_ai/get_candidates() +/datum/antagonist/rogue_ai/build_candidate_list() ..() for(var/datum/mind/player in candidates) if(player.assigned_role && player.assigned_role != "AI") candidates -= player - if(!candidates.len) - return list() return candidates diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 08a82890602..28f420547fd 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -266,6 +266,7 @@ var/global/list/additional_antag_types = list() /datum/game_mode/proc/pre_setup() for(var/datum/antagonist/antag in antag_templates) + antag.update_current_antag_max() antag.build_candidate_list() //compile a list of all eligible candidates //antag roles that replace jobs need to be assigned before the job controller hands out jobs. diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index 28db276b493..9a10f0ce358 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -3,54 +3,39 @@ /datum/game_mode/var/max_autotraitor_delay = 12000 // Approx 20 minutes. /datum/game_mode/var/process_count = 0 -/datum/game_mode/proc/get_usable_templates(var/list/supplied_templates) - var/list/usable_templates = list() - for(var/datum/antagonist/A in supplied_templates) - if(A.can_late_spawn()) - message_admins("AUTO[uppertext(name)]: [A.id] selected for spawn attempt.") - usable_templates |= A - return usable_templates - ///process() ///Called by the gameticker /datum/game_mode/proc/process() - // Slow this down a bit so latejoiners have a chance of being antags. - process_count++ - if(process_count >= 10) - process_count = 0 - try_latespawn() + if(round_autoantag && world.time < next_spawn && !emergency_shuttle.departed) + process_autoantag() //This can be overriden in case a game mode needs to do stuff when a player latejoins /datum/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character) - if(!character.mind) - return - try_latespawn(character.mind) return 0 -/datum/game_mode/proc/try_latespawn(var/datum/mind/player) +/datum/game_mode/proc/process_autoantag() + message_admins("[uppertext(name)]: Attempting autospawn.") - if(emergency_shuttle.departed || !round_autoantag) - return - - if(world.time < next_spawn) - return - - message_admins("AUTO[uppertext(name)]: Attempting spawn.") - - var/list/usable_templates - if (antag_templates && antag_templates.len) - usable_templates = get_usable_templates(antag_templates) - else - message_admins("AUTO[uppertext(name)]: Failed to find configured mode spawn templates, please disable auto-antagonists until one is added.") + var/list/usable_templates = list() + for(var/datum/antagonist/A in antag_templates) + if(A.can_late_spawn()) + message_admins("[uppertext(name)]: [A.id] selected for spawn attempt.") + usable_templates |= A + + if(!usable_templates.len) + message_admins("[uppertext(name)]: Failed to find configured mode spawn templates, please re-enable auto-antagonists after one is added.") round_autoantag = 0 return - + while(usable_templates.len) var/datum/antagonist/spawn_antag = pick(usable_templates) usable_templates -= spawn_antag - if(spawn_antag.attempt_late_spawn(player)) - message_admins("AUTO[uppertext(name)]: Attempting to latespawn [spawn_antag.id]. ([spawn_antag.get_antag_count()]/[spawn_antag.cur_max])") + + if(spawn_antag.attempt_auto_spawn()) + message_admins("[uppertext(name)]: Auto-added a new [spawn_antag.role_text].") + message_admins("There are now [spawn_antag.get_active_antag_count()]/[spawn_antag.cur_max] active [spawn_antag.role_text_plural].") next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay) return - message_admins("AUTO[uppertext(name)]: Failed to proc a viable spawn template.") + + message_admins("[uppertext(name)]: Failed to proc a viable spawn template.") next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index f02292d81f1..241f394cca4 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1386,7 +1386,7 @@ proc/admin_notice(var/message, var/rights) var/datum/antagonist/antag = all_antag_types[antag_type] message_admins("[key_name(usr)] attempting to force latespawn with template [antag.id].") - antag.attempt_late_spawn() + antag.attempt_auto_spawn() /datum/admins/proc/force_mode_latespawn() set category = "Admin" @@ -1403,6 +1403,5 @@ proc/admin_notice(var/message, var/rights) usr << "Mode has not started." return - message_admins("[key_name(usr)] attempting to force mode latespawn.") - ticker.mode.next_spawn = 0 - ticker.mode.try_latespawn() + message_admins("[key_name(usr)] attempting to force mode autospawn.") + ticker.mode.process_autoantag()