diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index 65aaa36fbb9f..020efe8d0858 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -342,7 +342,13 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list(
#define HUNTER_PACK_PSYKER "Psyker Shikaris"
// This flag disables certain checks that presume antagonist datums mean 'baddie'.
-#define FLAG_FAKE_ANTAG (1 << 0)
+#define FLAG_FAKE_ANTAG (1 << 0)
+/// monkestation addition: Whether the antagonist can see exploitable info on people they examine.
+#define FLAG_CAN_SEE_EXPOITABLE_INFO (1 << 1)
+// monkestation addition: The storyteller will ignore this antag datum as counting against the antag cap.
+#define FLAG_ANTAG_CAP_IGNORE (1 << 2)
+// monkestation addition: The storyteller will count everyone on this antag's team as a singular antag instead.
+#define FLAG_ANTAG_CAP_TEAM (1 << 3)
#define FREEDOM_IMPLANT_CHARGES 4
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 5634f11b172c..5fb06027a5fc 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -287,7 +287,7 @@ GLOBAL_REAL(Master, /datum/controller/master)
if(sleep_offline_after_initializations && CONFIG_GET(flag/resume_after_initializations))
world.sleep_offline = FALSE
initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10
- SSgamemode.handle_picking_stroyteller() //monkestation edit
+ SSgamemode.handle_picking_storyteller() //monkestation edit
/**
* Initialize a given subsystem and handle the results.
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index 19a346e3654c..9ea41eca4aba 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -54,7 +54,7 @@ GLOBAL_LIST_EMPTY(antagonists)
/// The typepath for the outfit to show in the preview for the preferences menu.
var/preview_outfit
/// Flags for antags to turn on or off and check!
- var/antag_flags = NONE
+ var/antag_flags = FLAG_CAN_SEE_EXPOITABLE_INFO // monkestation edit: allow antags to see exploitable info.
/// If true, this antagonist can assign themself a new objective
var/can_assign_self_objectives = FALSE
/// Default to fill in when entering a custom objective.
diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm
index d3d5bf24b66c..ed32ca368d5a 100644
--- a/code/modules/antagonists/abductor/abductor.dm
+++ b/code/modules/antagonists/abductor/abductor.dm
@@ -7,6 +7,7 @@
show_in_antagpanel = FALSE //should only show subtypes
show_to_ghosts = TRUE
suicide_cry = "FOR THE MOTHERSHIP!!" // They can't even talk but y'know
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_TEAM // monkestation addition
var/datum/team/abductor_team/team
var/sub_role
var/outfit
diff --git a/code/modules/antagonists/blob/blob_minion.dm b/code/modules/antagonists/blob/blob_minion.dm
index 9bf37e961d5d..3e3f7647bcfd 100644
--- a/code/modules/antagonists/blob/blob_minion.dm
+++ b/code/modules/antagonists/blob/blob_minion.dm
@@ -4,6 +4,7 @@
show_name_in_check_antagonists = TRUE
show_to_ghosts = TRUE
show_in_antagpanel = FALSE
+ antag_flags = FLAG_ANTAG_CAP_IGNORE // monkestation addition
/// The blob core that this minion is attached to
var/datum/weakref/overmind
diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm
index 8218544a305e..22991570da91 100644
--- a/code/modules/antagonists/brother/brother.dm
+++ b/code/modules/antagonists/brother/brother.dm
@@ -8,6 +8,7 @@
ui_name = "AntagInfoBrother"
suicide_cry = "FOR MY BROTHER!!"
antag_moodlet = /datum/mood_event/focused
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_TEAM // monkestation addition
VAR_PRIVATE
datum/team/brother_team/team
diff --git a/code/modules/antagonists/changeling/fallen_changeling.dm b/code/modules/antagonists/changeling/fallen_changeling.dm
index c44c1b66cd3d..ba5d3c3976ba 100644
--- a/code/modules/antagonists/changeling/fallen_changeling.dm
+++ b/code/modules/antagonists/changeling/fallen_changeling.dm
@@ -6,6 +6,7 @@
job_rank = ROLE_CHANGELING
antag_moodlet = /datum/mood_event/fallen_changeling
antag_hud_name = "changeling"
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/mood_event/fallen_changeling
description = "My powers! Where are my powers?!"
diff --git a/code/modules/antagonists/heretic/heretic_monsters.dm b/code/modules/antagonists/heretic/heretic_monsters.dm
index 4e76b11c90c6..db220e93bd5d 100644
--- a/code/modules/antagonists/heretic/heretic_monsters.dm
+++ b/code/modules/antagonists/heretic/heretic_monsters.dm
@@ -8,6 +8,7 @@
antag_hud_name = "heretic_beast"
suicide_cry = "MY MASTER SMILES UPON ME!!"
show_in_antagpanel = FALSE
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE // monkestation addition
/// Our master (a heretic)'s mind.
var/datum/mind/master
diff --git a/code/modules/antagonists/magic_servant/servant.dm b/code/modules/antagonists/magic_servant/servant.dm
index f6ecaf80cf6c..8851776213fe 100644
--- a/code/modules/antagonists/magic_servant/servant.dm
+++ b/code/modules/antagonists/magic_servant/servant.dm
@@ -3,6 +3,7 @@
show_in_roundend = FALSE
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/antagonist/magic_servant/proc/setup_master(mob/M)
var/datum/objective/O = new("Serve [M.real_name].")
diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm
index d499a8034d80..8812de960ddd 100644
--- a/code/modules/antagonists/pirate/pirate.dm
+++ b/code/modules/antagonists/pirate/pirate.dm
@@ -7,6 +7,7 @@
show_to_ghosts = TRUE
suicide_cry = "FOR ME MATEYS!!"
hijack_speed = 2 // That is without doubt the worst pirate I have ever seen.
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_TEAM // monkestation addition
var/datum/team/pirate/crew
/datum/antagonist/pirate/greet()
diff --git a/code/modules/antagonists/pyro_slime/pyro_slime.dm b/code/modules/antagonists/pyro_slime/pyro_slime.dm
index aed278d261d9..7f63d0f5482f 100644
--- a/code/modules/antagonists/pyro_slime/pyro_slime.dm
+++ b/code/modules/antagonists/pyro_slime/pyro_slime.dm
@@ -5,6 +5,7 @@
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
show_to_ghosts = TRUE
+ antag_flags = FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/antagonist/pyro_slime/on_gain()
forge_objectives()
diff --git a/code/modules/antagonists/revolution/enemy_of_the_revolution.dm b/code/modules/antagonists/revolution/enemy_of_the_revolution.dm
index 93a205a02cd2..0e20463d4898 100644
--- a/code/modules/antagonists/revolution/enemy_of_the_revolution.dm
+++ b/code/modules/antagonists/revolution/enemy_of_the_revolution.dm
@@ -7,6 +7,7 @@
name = "\improper Enemy of the Revolution"
show_in_antagpanel = FALSE
suicide_cry = "FOR NANOTRASEN, NOW AND FOREVER!!"
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/antagonist/enemy_of_the_revolution/forge_objectives()
var/datum/objective/survive/survive = new
diff --git a/code/modules/antagonists/sentient_creature/sentient_creature.dm b/code/modules/antagonists/sentient_creature/sentient_creature.dm
index 4b68a288be12..000fa8b51aff 100644
--- a/code/modules/antagonists/sentient_creature/sentient_creature.dm
+++ b/code/modules/antagonists/sentient_creature/sentient_creature.dm
@@ -4,6 +4,7 @@
show_in_roundend = FALSE
count_against_dynamic_roll_chance = FALSE
ui_name = "AntagInfoSentient"
+ antag_flags = FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/antagonist/sentient_creature/get_preview_icon()
var/icon/final_icon = icon('icons/mob/simple/pets.dmi', "corgi")
diff --git a/code/modules/antagonists/space_dragon/space_carp.dm b/code/modules/antagonists/space_dragon/space_carp.dm
index 0d06ea3991d9..ad84d0ee4337 100644
--- a/code/modules/antagonists/space_dragon/space_carp.dm
+++ b/code/modules/antagonists/space_dragon/space_carp.dm
@@ -5,6 +5,7 @@
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
show_to_ghosts = TRUE
+ antag_flags = FLAG_ANTAG_CAP_IGNORE // monkestation addition
/// The rift to protect
var/datum/weakref/rift
diff --git a/code/modules/antagonists/venus_human_trap/venus_human_trap.dm b/code/modules/antagonists/venus_human_trap/venus_human_trap.dm
index c84f20d05965..04ffc1dcd51c 100644
--- a/code/modules/antagonists/venus_human_trap/venus_human_trap.dm
+++ b/code/modules/antagonists/venus_human_trap/venus_human_trap.dm
@@ -5,6 +5,7 @@
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
show_to_ghosts = TRUE
+ antag_flags = FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/antagonist/venus_human_trap/on_gain()
forge_objectives()
diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm
index bfac673535af..d27ad3df8a10 100644
--- a/code/modules/antagonists/wishgranter/wishgranter.dm
+++ b/code/modules/antagonists/wishgranter/wishgranter.dm
@@ -4,6 +4,7 @@
show_name_in_check_antagonists = TRUE
hijack_speed = 2 //You literally are here to do nothing else. Might as well be fast about it.
suicide_cry = "HAHAHAHAHA!!"
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/antagonist/wishgranter/forge_objectives()
var/datum/objective/hijack/hijack = new
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index f86c46f83b6c..f3f6c810baa9 100644
--- a/code/modules/antagonists/wizard/wizard.dm
+++ b/code/modules/antagonists/wizard/wizard.dm
@@ -38,6 +38,7 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
antag_hud_name = "apprentice"
show_in_roundend = FALSE
show_name_in_check_antagonists = TRUE
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE // monkestation addition
/// The wizard team this wizard minion is part of.
var/datum/team/wizard/wiz_team
diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm
index 115e40ca595c..eff0866999cf 100644
--- a/code/modules/antagonists/xeno/xeno.dm
+++ b/code/modules/antagonists/xeno/xeno.dm
@@ -66,6 +66,7 @@
return
captive_team = new
captive_team.progenitor = owner
+ antag_flags |= FLAG_ANTAG_CAP_IGNORE // monkestation edit: first captive xeno does not count against cap
else
if(!istype(new_team))
CRASH("Wrong xeno team type provided to create_team")
diff --git a/code/modules/bitrunning/antagonists/cyber_police.dm b/code/modules/bitrunning/antagonists/cyber_police.dm
index 73ff96ff7c8c..9d99520dec76 100644
--- a/code/modules/bitrunning/antagonists/cyber_police.dm
+++ b/code/modules/bitrunning/antagonists/cyber_police.dm
@@ -10,6 +10,7 @@
show_to_ghosts = TRUE
suicide_cry = "ALT F4!"
ui_name = "AntagInfoCyberAuth"
+ antag_flags = FLAG_ANTAG_CAP_IGNORE // monkestation addition
/datum/antagonist/cyber_police/greet()
. = ..()
diff --git a/code/modules/events/ghost_role/alien_infestation.dm b/code/modules/events/ghost_role/alien_infestation.dm
index 9b35b2145dcf..db3fd898e9ae 100644
--- a/code/modules/events/ghost_role/alien_infestation.dm
+++ b/code/modules/events/ghost_role/alien_infestation.dm
@@ -87,25 +87,26 @@
if(temp_vent_parent.other_atmos_machines.len > 20)
vents += temp_vent
- if(!vents.len)
+ if(!length(vents))
message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.")
return MAP_ERROR
- for(var/i in 1 to antag_count)
- if(!length(candidates))
- break
-
- var/client/mob_client = pick_n_take_weighted(weighted_candidates)
- var/mob/candidate = mob_client.mob
- if(candidate.client) //I hate this
- candidate.client.prefs.reset_antag_rep()
+ var/selected_count = 0
+ while(length(weighted_candidates) && selected_count < antag_count)
+ var/client/candidate_ckey = pick_n_take_weighted(weighted_candidates)
+ var/client/candidate_client = GLOB.directory[candidate_ckey]
+ if(QDELETED(candidate_client) || QDELETED(candidate_client.mob))
+ continue
+ var/mob/candidate = candidate_client.mob
+ candidate_client.prefs?.reset_antag_rep()
if(!candidate.mind)
candidate.mind = new /datum/mind(candidate.key)
var/obj/vent = pick_n_take(vents)
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
- new_xeno.key = candidate.key
+ new_xeno.ckey = candidate_ckey
new_xeno.move_into_vent(vent)
+ selected_count++
message_admins("[ADMIN_LOOKUPFLW(new_xeno)] has been made into an alien by an event.")
new_xeno.log_message("was spawned as an alien by an event.", LOG_GAME)
diff --git a/monkestation/code/__DEFINES/antag_defines.dm b/monkestation/code/__DEFINES/antag_defines.dm
deleted file mode 100644
index 33358561c55a..000000000000
--- a/monkestation/code/__DEFINES/antag_defines.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/// Whether the antagonist can see exploitable info on people they examine.
-#define FLAG_CAN_SEE_EXPOITABLE_INFO (1<<1)
diff --git a/monkestation/code/controllers/subsystem/job.dm b/monkestation/code/controllers/subsystem/job.dm
index cbe28992efda..d3ca62b5b386 100644
--- a/monkestation/code/controllers/subsystem/job.dm
+++ b/monkestation/code/controllers/subsystem/job.dm
@@ -65,9 +65,10 @@
mass_adjust_antag_rep(cliented_list, 1)
var/list/weighted_candidates = return_antag_rep_weight(candidates)
-
var/antag_selection_loops = SSgamemode.current_roundstart_event.get_antag_amount()
- for(var/i in 1 to antag_selection_loops)
+ var/iter = 0
+ while(iter < antag_selection_loops)
+ iter++
if(antag_selection_loops >= 100)
log_storyteller("h_r_a failed, antag_selection_loops went over 100")
return FALSE
@@ -78,7 +79,11 @@
log_storyteller("h_r_a failed, below required candidates for selected roundstart event")
return FALSE
break
- var/client/dead_client = pick_n_take_weighted(weighted_candidates)
+ var/candidate_ckey = pick_n_take_weighted(weighted_candidates)
+ var/client/dead_client = GLOB.directory[candidate_ckey]
+ if(QDELETED(dead_client))
+ antag_selection_loops++
+ continue
var/mob/dead/new_player/candidate = dead_client.mob
if(!candidate.mind || !istype(candidate))
antag_selection_loops++
@@ -105,12 +110,16 @@
continue
var/mob/dead/new_player/candidate
var/sanity = 0
- while(!candidate && length(weighted_candidates) && !sanity >= 100)
+ while(QDELETED(candidate) && length(weighted_candidates) && sanity < 100)
sanity++
- candidate = pick_n_take_weighted(weighted_candidates)
- if(!candidate.mind || !istype(candidate))
+ var/candidate_ckey = pick_n_take_weighted(weighted_candidates)
+ var/client/candidate_client = GLOB.directory[candidate_ckey]
+ if(QDELETED(candidate_client))
+ continue
+ candidate = candidate_client.mob
+ if(!isnewplayer(candidate) || QDELING(candidate) || QDELETED(candidate.mind))
candidate = null
- if(!candidate)
+ if(QDELETED(candidate))
if(length(SSgamemode.roundstart_antag_minds) < SSgamemode.current_roundstart_event.base_antags)
log_storyteller("h_r_a failed, removing unassigned antag player put us below current event minimum candidates and we were unable to find a replacement")
return FALSE
diff --git a/monkestation/code/modules/antagonists/_common/antag_datum.dm b/monkestation/code/modules/antagonists/_common/antag_datum.dm
index 5995594cf332..177b48b11b54 100644
--- a/monkestation/code/modules/antagonists/_common/antag_datum.dm
+++ b/monkestation/code/modules/antagonists/_common/antag_datum.dm
@@ -1,6 +1,4 @@
/datum/antagonist
- /// Allows antags to check exploitable info
- antag_flags = FLAG_CAN_SEE_EXPOITABLE_INFO
///The list of keys that are valid to see our antag hud/of huds we can see
var/list/hud_keys
/// If this antagonist should be removed from the crew manifest upon gain.
diff --git a/monkestation/code/modules/antagonists/clock_cult/antag_datums/clock_cultist.dm b/monkestation/code/modules/antagonists/clock_cult/antag_datums/clock_cultist.dm
index 3c4ff85f2aa8..22beb4158965 100644
--- a/monkestation/code/modules/antagonists/clock_cult/antag_datums/clock_cultist.dm
+++ b/monkestation/code/modules/antagonists/clock_cult/antag_datums/clock_cultist.dm
@@ -203,6 +203,7 @@
/datum/antagonist/clock_cultist/eminence
name = "Eminence"
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE
give_slab = FALSE
antag_moodlet = null
communicate = null
diff --git a/monkestation/code/modules/antagonists/evil_clone/evil_clone.dm b/monkestation/code/modules/antagonists/evil_clone/evil_clone.dm
index a3b4bc9591db..f9616c0fa198 100644
--- a/monkestation/code/modules/antagonists/evil_clone/evil_clone.dm
+++ b/monkestation/code/modules/antagonists/evil_clone/evil_clone.dm
@@ -5,6 +5,7 @@
antagpanel_category = "Evil Clones"
show_name_in_check_antagonists = TRUE
show_to_ghosts = TRUE
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE
/datum/antagonist/evil_clone/greet()
. = ..()
diff --git a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_shaded.dm b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_shaded.dm
index ecaaaae89223..8384c6b6c1be 100644
--- a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_shaded.dm
+++ b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_shaded.dm
@@ -5,6 +5,7 @@
show_in_roundend = FALSE
job_rank = ROLE_BLOODSUCKER
antag_hud_name = "bloodsucker"
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE
/obj/item/soulstone/bloodsucker
theme = THEME_WIZARD
diff --git a/monkestation/code/modules/bloodsuckers/vassals/ex_vassal.dm b/monkestation/code/modules/bloodsuckers/vassals/ex_vassal.dm
index 0599972c219e..977ccdf851f8 100644
--- a/monkestation/code/modules/bloodsuckers/vassals/ex_vassal.dm
+++ b/monkestation/code/modules/bloodsuckers/vassals/ex_vassal.dm
@@ -12,6 +12,7 @@
silent = TRUE
ui_name = FALSE
hud_icon = 'monkestation/icons/bloodsuckers/bloodsucker_icons.dmi'
+ antag_flags = FLAG_ANTAG_CAP_IGNORE
///The revenge vassal that brought us into the fold.
var/datum/antagonist/vassal/revenge/revenge_vassal
diff --git a/monkestation/code/modules/bloodsuckers/vassals/vassal_datum.dm b/monkestation/code/modules/bloodsuckers/vassals/vassal_datum.dm
index c2dd662cce12..72acb40a6d79 100644
--- a/monkestation/code/modules/bloodsuckers/vassals/vassal_datum.dm
+++ b/monkestation/code/modules/bloodsuckers/vassals/vassal_datum.dm
@@ -8,6 +8,7 @@
roundend_category = "vassals"
antagpanel_category = "Bloodsucker"
job_rank = ROLE_BLOODSUCKER
+ antag_flags = parent_type::antag_flags | FLAG_ANTAG_CAP_IGNORE
antag_hud_name = "vassal"
show_in_roundend = FALSE
hud_icon = 'monkestation/icons/bloodsuckers/bloodsucker_icons.dmi'
diff --git a/monkestation/code/modules/storytellers/antag_rep/helper_procs.dm b/monkestation/code/modules/storytellers/antag_rep/helper_procs.dm
index 5970239e1287..86f54be69e97 100644
--- a/monkestation/code/modules/storytellers/antag_rep/helper_procs.dm
+++ b/monkestation/code/modules/storytellers/antag_rep/helper_procs.dm
@@ -37,27 +37,21 @@ GLOBAL_LIST_INIT(blessed_ckeys, list(
///give it a list of clients and the value aswell if it should be affected by multipliers and let er rip
/proc/mass_adjust_antag_rep(list/clients, value, mulitplier = TRUE)
for(var/client/listed_client as anything in clients)
- if(!listed_client.prefs || !IS_CLIENT_OR_MOCK(listed_client))
+ if(!IS_CLIENT_OR_MOCK(listed_client) || QDELETED(listed_client) || QDELETED(listed_client.prefs))
continue
listed_client.prefs.adjust_antag_rep(value, mulitplier)
/proc/return_antag_rep_weight(list/candidates)
- var/list/returning_list = list()
+ . = list()
for(var/anything in candidates)
var/client/client_source
if(ismob(anything))
var/mob/mob = anything
client_source = mob.client
- if(IS_CLIENT_OR_MOCK(anything))
+ else if(IS_CLIENT_OR_MOCK(anything))
client_source = anything
- if(!client_source)
+ if(QDELETED(client_source) || !client_source.ckey)
continue
+ .[client_source.ckey] = client_source.prefs?.antag_rep || 10
- returning_list += client_source
- var/return_value = 10
- if(client_source.prefs?.antag_rep)
- return_value = client_source.prefs.antag_rep
- returning_list[client_source] = return_value
-
- log_antag_rep("Returned Weighted List of [length(returning_list)]", list("before_weight" = candidates, "after_weight" = returning_list))
- return returning_list
+ log_antag_rep("Returned Weighted List of [length(.)]", list("before_weight" = candidates, "after_weight" = .))
diff --git a/monkestation/code/modules/storytellers/converted_events/_base_event.dm b/monkestation/code/modules/storytellers/converted_events/_base_event.dm
index 84ae021d7840..0faa795d6aa3 100644
--- a/monkestation/code/modules/storytellers/converted_events/_base_event.dm
+++ b/monkestation/code/modules/storytellers/converted_events/_base_event.dm
@@ -240,9 +240,12 @@
var/list/weighted_candidates = return_antag_rep_weight(possible_candidates)
- while(length(possible_candidates) && length(candidates) < antag_count) //both of these pick_n_take from possible_candidates so this should be fine
+ while(length(weighted_candidates) && length(candidates) < antag_count) //both of these pick_n_take from weighted_candidates so this should be fine
if(prompted_picking)
- var/client/picked_client = pick_n_take_weighted(weighted_candidates)
+ var/picked_ckey = pick_n_take_weighted(weighted_candidates)
+ var/client/picked_client = GLOB.directory[picked_ckey]
+ if(QDELETED(picked_client))
+ continue
var/mob/picked_mob = picked_client.mob
log_storyteller("Prompted antag event mob: [picked_mob], special role: [picked_mob.mind?.special_role ? picked_mob.mind.special_role : "none"]")
if(picked_mob)
@@ -258,9 +261,10 @@
show_candidate_amount = FALSE,
)
else
- if(!length(weighted_candidates))
- break
- var/client/picked_client = pick_n_take_weighted(weighted_candidates)
+ var/picked_ckey = pick_n_take_weighted(weighted_candidates)
+ var/client/picked_client = GLOB.directory[picked_ckey]
+ if(QDELETED(picked_client))
+ continue
var/mob/picked_mob = picked_client.mob
log_storyteller("Picked antag event mob: [picked_mob], special role: [picked_mob.mind?.special_role ? picked_mob.mind.special_role : "none"]")
candidates |= picked_mob
@@ -353,22 +357,21 @@
)
var/list/weighted_candidates = return_antag_rep_weight(candidates)
+ var/selected_count = 0
+ while(length(weighted_candidates) && selected_count < antag_count)
+ var/candidate_ckey = pick_n_take_weighted(weighted_candidates)
+ var/client/candidate_client = GLOB.directory[candidate_ckey]
+ if(QDELETED(candidate_client) || QDELETED(candidate_client.mob))
+ continue
+ var/mob/candidate = candidate_client.mob
- for(var/i in 1 to antag_count)
- if(!length(weighted_candidates))
- break
-
- var/client/mob_client = pick_n_take_weighted(weighted_candidates)
- var/mob/candidate = mob_client.mob
-
- if(candidate.client) //I hate this
- candidate.client.prefs.reset_antag_rep()
+ candidate_client.prefs?.reset_antag_rep()
if(!candidate.mind)
candidate.mind = new /datum/mind(candidate.key)
-
var/mob/living/carbon/human/new_human = make_body(candidate)
new_human.mind.special_role = antag_flag
new_human.mind.restricted_roles = restricted_roles
setup_minds += new_human.mind
+ selected_count++
setup = TRUE
diff --git a/monkestation/code/modules/storytellers/converted_events/solo/ghosts/paradox_clone.dm b/monkestation/code/modules/storytellers/converted_events/solo/ghosts/paradox_clone.dm
index 8a1a3223575a..5721f446cf30 100644
--- a/monkestation/code/modules/storytellers/converted_events/solo/ghosts/paradox_clone.dm
+++ b/monkestation/code/modules/storytellers/converted_events/solo/ghosts/paradox_clone.dm
@@ -52,26 +52,24 @@
)
var/list/weighted_candidates = return_antag_rep_weight(candidates)
-
- for(var/i in 1 to antag_count)
- if(!length(candidates))
- break
-
- var/client/mob_client = pick_n_take(weighted_candidates)
- var/mob/candidate = mob_client.mob
-
- if(candidate.client) //I hate this
- candidate.client.prefs.reset_antag_rep()
-
+ var/selected_count = 0
+ while(length(weighted_candidates) && selected_count < antag_count)
+ var/client/candidate_ckey = pick_n_take_weighted(weighted_candidates)
+ var/client/candidate_client = GLOB.directory[candidate_ckey]
+ if(QDELETED(candidate_client) || QDELETED(candidate_client.mob))
+ continue
+ var/mob/candidate = candidate_client.mob
+ candidate_client.prefs?.reset_antag_rep()
if(!candidate.mind)
candidate.mind = new /datum/mind(candidate.key)
clone_victim = find_original()
new_human = duplicate_object(clone_victim, pick(possible_spawns))
- new_human.key = candidate.key
+ new_human.ckey = candidate_ckey
new_human.mind.special_role = antag_flag
new_human.mind.restricted_roles = restricted_roles
setup_minds += new_human.mind
+ selected_count++
setup = TRUE
diff --git a/monkestation/code/modules/storytellers/gamemode_subsystem.dm b/monkestation/code/modules/storytellers/gamemode_subsystem.dm
index 561149220487..01275488fc43 100644
--- a/monkestation/code/modules/storytellers/gamemode_subsystem.dm
+++ b/monkestation/code/modules/storytellers/gamemode_subsystem.dm
@@ -157,8 +157,6 @@ SUBSYSTEM_DEF(gamemode)
var/ran_roundstart = FALSE
var/list/triggered_round_events = list()
- var/total_valid_antags = 0
-
/datum/controller/subsystem/gamemode/Initialize(time, zlevel)
// Populate event pools
for(var/track in event_tracks)
@@ -233,20 +231,29 @@ SUBSYSTEM_DEF(gamemode)
var/cap = FLOOR((total_number / ANTAG_CAP_DENOMINATOR), 1) + ANTAG_CAP_FLAT
return cap
-/// Whether events can inject more antagonists into the round
-/datum/controller/subsystem/gamemode/proc/can_inject_antags()
- total_valid_antags = 0
- for(var/mob/checked_mob in GLOB.mob_list)
- if(!checked_mob.mind)
+/datum/controller/subsystem/gamemode/proc/get_antag_count()
+ . = 0
+ var/list/already_counted = list() // Never count the same mind twice
+ for(var/datum/antagonist/antag as anything in GLOB.antagonists)
+ if(QDELETED(antag) || QDELETED(antag.owner) || already_counted[antag.owner])
continue
- if(!checked_mob.mind.special_role)
+ if(!antag.count_against_dynamic_roll_chance || (antag.antag_flags & (FLAG_FAKE_ANTAG | FLAG_ANTAG_CAP_IGNORE)))
continue
- if(checked_mob.stat == DEAD)
+ if(antag.antag_flags & FLAG_ANTAG_CAP_TEAM)
+ var/datum/team/antag_team = antag.get_team()
+ if(antag_team)
+ if(already_counted[antag_team])
+ continue
+ already_counted[antag_team] = TRUE
+ var/mob/antag_mob = antag.owner.current
+ if(QDELETED(antag_mob) || !antag_mob.key || antag_mob.stat == DEAD || antag_mob.client?.is_afk())
continue
- total_valid_antags++
-
+ already_counted[antag.owner] = TRUE
+ .++
- return (get_antag_cap() > total_valid_antags)
+/// Whether events can inject more antagonists into the round
+/datum/controller/subsystem/gamemode/proc/can_inject_antags()
+ return (get_antag_cap() > get_antag_count())
/// Gets candidates for antagonist roles.
/datum/controller/subsystem/gamemode/proc/get_candidates(be_special, job_ban, observers, ready_newplayers, living_players, required_time, inherit_required_time = TRUE, midround_antag_pref, no_antags = TRUE, list/restricted_roles, list/required_roles)
@@ -798,7 +805,9 @@ SUBSYSTEM_DEF(gamemode)
point_thresholds[EVENT_TRACK_ROLESET] = CONFIG_GET(number/roleset_point_threshold)
point_thresholds[EVENT_TRACK_OBJECTIVES] = CONFIG_GET(number/objectives_point_threshold)
-/datum/controller/subsystem/gamemode/proc/handle_picking_stroyteller()
+/datum/controller/subsystem/gamemode/proc/handle_picking_storyteller()
+ if(CONFIG_GET(flag/disable_storyteller))
+ return
if(length(GLOB.clients) > MAX_POP_FOR_STORYTELLER_VOTE)
secret_storyteller = TRUE
selected_storyteller = pick_weight(get_valid_storytellers(TRUE))
@@ -867,23 +876,13 @@ SUBSYSTEM_DEF(gamemode)
/// Panel containing information, variables and controls about the gamemode and scheduled event
/datum/controller/subsystem/gamemode/proc/admin_panel(mob/user)
update_crew_infos()
- total_valid_antags = 0
- for(var/mob/checked_mob in GLOB.mob_list)
- if(!checked_mob.mind)
- continue
- if(!checked_mob.mind.special_role)
- continue
- if(checked_mob.stat == DEAD)
- continue
- total_valid_antags++
-
var/round_started = SSticker.HasRoundStarted()
var/list/dat = list()
dat += "Storyteller: [storyteller ? "[storyteller.name]" : "None"] "
dat += " HALT Storyteller Event Panel Set Storyteller Refresh"
dat += "
Storyteller determines points gained, event chances, and is the entity responsible for rolling events."
dat += "
Active Players: [active_players] (Head: [head_crew], Sec: [sec_crew], Eng: [eng_crew], Med: [med_crew])"
- dat += "
Antagonist Count vs Maximum: [total_valid_antags] / [get_antag_cap()]"
+ dat += "
Antagonist Count vs Maximum: [get_antag_count()] / [get_antag_cap()]"
dat += "