diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 0dc50b7dc4c..ac2e2b33a68 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -406,6 +406,13 @@
return ishuman(target) && target.dna.species.is_monkeybasic // we deserve a runtime if a human has no DNA
+/proc/is_evolvedslime(mob/living/carbon/human/target)
+ if(!ishuman(target) || !istype(target.dna.species, /datum/species/slime))
+ return FALSE
+ var/datum/species/slime/species = target.dna.species
+ return species.evolved_slime
+
+
/proc/spawn_atom_to_turf(spawn_type, target, amount, admin_spawn=FALSE, list/extra_args)
var/turf/T = get_turf(target)
if(!T)
diff --git a/code/game/gamemodes/antag_paradise/antag_paradise.dm b/code/game/gamemodes/antag_paradise/antag_paradise.dm
index 1d2c015694b..0f0a8896ce6 100644
--- a/code/game/gamemodes/antag_paradise/antag_paradise.dm
+++ b/code/game/gamemodes/antag_paradise/antag_paradise.dm
@@ -1,3 +1,6 @@
+#define AUTOTRAITOR_LOW_BOUND (5 MINUTES)
+#define AUTOTRAITOR_HIGH_BOUND (15 MINUTES)
+
/**
* This is a game mode which has a chance to spawn any minor antagonist.
*/
@@ -16,9 +19,6 @@
var/list/datum/mind/pre_antags = list()
var/list/datum/mind/pre_double_antags = list()
- var/antag_making_cooldown = 5 MINUTES
- var/next_antag_making_time = 0
-
var/list/antag_required_players = list(
ROLE_TRAITOR = 10,
ROLE_THIEF = 10,
@@ -32,25 +32,29 @@
var/list/antags_weights
/// Chosen speciaal antag type.
var/special_antag_type = ROLE_NONE
+ /// Timestamp for autotraitor
+ COOLDOWN_DECLARE(antag_making_cooldown)
/datum/game_mode/antag_paradise/announce()
to_chat(world, "The current game mode is - Antag Paradise")
to_chat(world, "Traitors, thieves, vampires and changelings, oh my! Stay safe as these forces work to bring down the station.")
+
/datum/game_mode/antag_paradise/process()
if(SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
return PROCESS_KILL
- if(world.time < next_antag_making_time)
- return FALSE
+ if(!COOLDOWN_STARTED(src, antag_making_cooldown) || !COOLDOWN_FINISHED(src, antag_making_cooldown))
+ return
- next_antag_making_time = world.time + antag_making_cooldown
+ COOLDOWN_START(src, antag_making_cooldown, rand(AUTOTRAITOR_LOW_BOUND, AUTOTRAITOR_HIGH_BOUND))
var/list/antag_possibilities = list()
antag_possibilities[ROLE_VAMPIRE] = get_alive_players_for_role(ROLE_VAMPIRE)
antag_possibilities[ROLE_CHANGELING] = get_alive_players_for_role(ROLE_CHANGELING)
antag_possibilities[ROLE_TRAITOR] = get_alive_players_for_role(ROLE_TRAITOR)
antag_possibilities[ROLE_THIEF] = get_alive_players_for_role(ROLE_THIEF, list(SPECIES_VOX = 4))
+ antag_possibilities[ROLE_MALF_AI] = get_alive_AIs_for_role(ROLE_MALF_AI)
roll_antagonists(antag_possibilities)
initiate_antags()
@@ -65,15 +69,17 @@
var/special_antag_amount
antags_amount = 1 + round(players / scale)
- //Special antag spawning not on roundstart is currently disabled for testing purposes.
- special_antag_amount = roundstart ? 1 + round(players / 50) : 0
+ special_antag_amount = roundstart ? 1 + round(players / 50) : round(players / 50)
antags_amount = antags_amount - length(GLOB.antagonists)
if(antags_amount <= 0)
return
- if(special_antag_type == ROLE_NINJA && !roundstart)
- special_antag_type = pick(ROLE_HIJACKER, ROLE_THIEF, ROLE_MALF_AI)
+ if(!roundstart)
+ if(length(antag_possibilities[ROLE_MALF_AI]))
+ special_antag_type = pick(ROLE_HIJACKER, ROLE_THIEF, ROLE_MALF_AI)
+ else
+ special_antag_type = pick(ROLE_HIJACKER, ROLE_THIEF)
switch(special_antag_type)
if(ROLE_HIJACKER)
@@ -97,7 +103,7 @@
if(ROLE_MALF_AI)
if(special_antag_amount)
- var/datum/mind/special_antag = roundstart ? safepick(get_players_for_role(ROLE_MALF_AI, req_job_rank = JOB_TITLE_AI)) : safepick(get_alive_players_for_role(ROLE_MALF_AI, req_job_rank = JOB_TITLE_AI))
+ var/datum/mind/special_antag = roundstart ? safepick(get_players_for_role(ROLE_MALF_AI, req_job_rank = JOB_TITLE_AI)) : safepick(antag_possibilities[ROLE_MALF_AI])
if(special_antag)
special_antag.restricted_roles = (restricted_jobs|protected_jobs|protected_jobs_AI)
special_antag.restricted_roles -= JOB_TITLE_AI
@@ -199,6 +205,7 @@
pre_double_antags[antag] = ROLE_CHANGELING
break
+
/datum/game_mode/antag_paradise/pre_setup()
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs
@@ -211,7 +218,8 @@
calculate_antags()
- return roll_antagonists(antag_possibilities, TRUE)
+ return roll_antagonists(antag_possibilities, roundstart = TRUE)
+
/datum/game_mode/antag_paradise/proc/calculate_antags()
var/players = num_players()
@@ -288,7 +296,7 @@
antag.add_antag_datum(ninja_datum)
addtimer(CALLBACK(src, PROC_REF(initiate_antags)), rand(1 SECONDS, 10 SECONDS))
- next_antag_making_time = world.time + antag_making_cooldown
+ COOLDOWN_START(src, antag_making_cooldown, AUTOTRAITOR_LOW_BOUND) // first auto-traitor tick checks all players in 5 minutes
..()
@@ -347,3 +355,7 @@
new_list[index] = check_list[index]
return new_list
+
+#undef AUTOTRAITOR_LOW_BOUND
+#undef AUTOTRAITOR_HIGH_BOUND
+
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index ac8a287a857..13d6f7d0feb 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -326,10 +326,7 @@
if(!player.client \
|| jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, role) \
|| !player_old_enough_antag(player.client, role, req_job_rank) || player.client.prefs?.skip_antag \
- || !(role in player.client.prefs.be_special))
- continue
-
- if(player.mind.has_antag_datum(/datum/antagonist) || player.mind.offstation_role || player.mind.special_role)
+ || !(role in player.client.prefs.be_special) || !is_player_station_relevant(player))
continue
players += player
@@ -356,34 +353,67 @@
return candidates
+
+/datum/game_mode/proc/get_alive_AIs_for_role(role)
+ . = list()
+ for(var/mob/living/silicon/ai/AI in GLOB.alive_mob_list)
+ if(!AI.client || !AI.mind \
+ || jobban_isbanned(AI, "Syndicate") || jobban_isbanned(AI, role) \
+ || !player_old_enough_antag(AI.client, role, JOB_TITLE_AI) || AI.client.prefs?.skip_antag \
+ || !(role in AI.client.prefs.be_special) || AI.stat == DEAD || AI.control_disabled \
+ || AI.mind.offstation_role || AI.mind.special_role)
+ continue
+ . += AI.mind
+
+
+/// All the checks required to find baseline human being
+/proc/is_player_station_relevant(mob/living/carbon/human/player)
+ if(QDELING(player))
+ return FALSE
+ if(!player.client)
+ return FALSE
+ if(!player.mind)
+ return FALSE
+ if(player.mind.special_role) // already "special"
+ return FALSE
+ if(player.mind.offstation_role) // spawned mobs
+ return FALSE
+ if(player.stat == DEAD) // no zombies
+ return FALSE
+ var/turf/player_turf = get_turf(player)
+ if(!player_turf) // nullspace, eh?
+ return FALSE
+ if(!is_level_reachable(player_turf.z) && !is_away_level(player_turf.z)) // taipan is not available, mkay?
+ return FALSE
+ if(is_monkeybasic(player)) // no monkas
+ return FALSE
+ if(isgolem(player)) // get out of here
+ return FALSE
+ if(is_evolvedslime(player)) // no evolved slimes please
+ return FALSE
+ return TRUE // congratulations, you are normal!
+
+
/datum/game_mode/proc/latespawn(mob/player)
/datum/game_mode/proc/num_players()
. = 0
-
for(var/mob/new_player/player in GLOB.player_list)
-
if(player.client && player.ready)
.++
+
/proc/num_station_players()
. = 0
for(var/mob/living/carbon/human/player in GLOB.player_list)
- if(!player)
- continue
-
- if(player.client && player.mind && !player.mind.offstation_role && !player.mind.special_role)
+ if(is_player_station_relevant(player))
.++
/datum/game_mode/proc/num_players_started()
. = 0
-
for(var/mob/living/carbon/human/player in GLOB.player_list)
- if(!player)
- continue
-
if(player.client)
.++
diff --git a/code/modules/mob/living/carbon/human/species/slime.dm b/code/modules/mob/living/carbon/human/species/slime.dm
index a590987e95a..622a3fdebc9 100644
--- a/code/modules/mob/living/carbon/human/species/slime.dm
+++ b/code/modules/mob/living/carbon/human/species/slime.dm
@@ -72,6 +72,8 @@
disliked_food = SUGAR | FRIED
liked_food = MEAT | TOXIC | RAW
+ /// Special flag used for slimeperson evolved from the slime.
+ var/evolved_slime = FALSE
/datum/species/slime/on_species_gain(mob/living/carbon/human/H)
..()
diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm
index b2394fa6190..8bc3dd9be1e 100644
--- a/code/modules/mob/living/simple_animal/slime/powers.dm
+++ b/code/modules/mob/living/simple_animal/slime/powers.dm
@@ -165,7 +165,9 @@
new_slime.update_hair()
new_slime.update_body()
new_slime.blood_color = new_colour
- new_slime.dna.species.blood_color = new_slime.blood_color
+ new_slime.dna.species.blood_color = new_slime.dna.species
+ var/datum/species/slime/species = new_slime.dna.species
+ species.evolved_slime = TRUE
else
to_chat(src, "I am not ready to evolve yet...")