diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 16cb5b3c795..97486374e99 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -290,3 +290,19 @@
#define GRAB_PIXEL_SHIFT_PASSIVE 6
#define GRAB_PIXEL_SHIFT_AGGRESSIVE 12
#define GRAB_PIXEL_SHIFT_NECK 16
+
+//Flags that control what things can spawn species (whitelist)
+//Badmin magic mirror
+#define MIRROR_BADMIN (1<<0)
+//Standard magic mirror (wizard)
+#define MIRROR_MAGIC (1<<1)
+//Pride ruin mirror
+#define MIRROR_PRIDE (1<<2)
+//Race swap wizard event
+#define RACE_SWAP (1<<3)
+//ERT spawn template (avoid races that don't function without correct gear)
+#define ERT_SPAWN (1<<4)
+//xenobio black crossbreed
+#define SLIME_EXTRACT (1<<5)
+//Wabbacjack staff projectiles
+#define WABBAJACK (1<<6)
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 3bce0949c53..5ab1cd591f1 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -97,15 +97,14 @@
name = "magic mirror"
desc = "Turn and face the strange... face."
icon_state = "magic_mirror"
- var/list/races_blacklist = list("skeleton", "agent", "angel", "military_synth", "memezombies", "clockwork golem servant", "android", "synth", "mush", "zombie")
var/list/choosable_races = list()
/obj/structure/mirror/magic/New()
if(!choosable_races.len)
for(var/speciestype in subtypesof(/datum/species))
- var/datum/species/S = new speciestype()
- if(!(S.id in races_blacklist))
- choosable_races += S.id
+ var/datum/species/S = speciestype
+ if(initial(S.changesource_flags) & MIRROR_MAGIC)
+ choosable_races += initial(S.id)
..()
/obj/structure/mirror/magic/lesser/New()
@@ -114,8 +113,9 @@
/obj/structure/mirror/magic/badmin/New()
for(var/speciestype in subtypesof(/datum/species))
- var/datum/species/S = new speciestype()
- choosable_races += S.id
+ var/datum/species/S = speciestype
+ if(initial(S.changesource_flags) & MIRROR_BADMIN)
+ choosable_races += initial(S.id)
..()
/obj/structure/mirror/magic/attack_hand(mob/user)
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index ae4241796b0..5c9f8af8b3f 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -414,7 +414,7 @@
chosen_candidate.client.prefs.copy_to(ERTOperative)
ERTOperative.key = chosen_candidate.key
- if(ertemplate.enforce_human || ERTOperative.dna.species.dangerous_existence) // Don't want any exploding plasmemes
+ if(ertemplate.enforce_human || !ERTOperative.dna.species.changesource_flags & ERT_SPAWN) // Don't want any exploding plasmemes
ERTOperative.set_species(/datum/species/human)
//Give antag datum
diff --git a/code/modules/events/wizard/race.dm b/code/modules/events/wizard/race.dm
index e890e4952e1..dabc5268458 100644
--- a/code/modules/events/wizard/race.dm
+++ b/code/modules/events/wizard/race.dm
@@ -10,10 +10,10 @@
var/all_the_same = 0
var/all_species = list()
- for(var/speciestype in subtypesof(/datum/species))
- var/datum/species/S = new speciestype()
- if(!S.dangerous_existence && !S.blacklisted)
- all_species += speciestype
+ for(var/stype in subtypesof(/datum/species))
+ var/datum/species/S = stype
+ if(initial(S.changesource_flags) & RACE_SWAP)
+ all_species += stype
var/datum/species/new_species = pick(all_species)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 2a27595f55f..2b32eeb2696 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -25,8 +25,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/toxic_food = TOXIC
var/list/no_equip = list() // slots the race can't equip stuff to
var/nojumpsuit = 0 // this is sorta... weird. it basically lets you equip stuff that usually needs jumpsuits without one, like belts and pockets and ids
- var/blacklisted = 0 //Flag to exclude from green slime core species.
- var/dangerous_existence //A flag for transformation spells that tells them "hey if you turn a person into one of these without preperation, they'll probably die!"
var/say_mod = "says" // affects the speech message
var/list/default_features = list() // Default mutant bodyparts for this species. Don't forget to set one for every mutant bodypart you allow this species to have.
var/list/mutant_bodyparts = list() // Visible CURRENT bodyparts that are unique to a species. DO NOT USE THIS AS A LIST OF ALL POSSIBLE BODYPARTS AS IT WILL FUCK SHIT UP! Changes to this list for non-species specific bodyparts (ie cat ears and tails) should be assigned at organ level if possible. Layer hiding is handled by handle_mutant_bodyparts() below.
@@ -76,6 +74,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/obj/item/organ/liver/mutantliver
var/obj/item/organ/stomach/mutantstomach
var/override_float = FALSE
+
+ //Bitflag that controls what in game ways can select this species as a spawnable source
+ //Think magic mirror and pride mirror, slime extract, ERT etc, see defines
+ //in __DEFINES/mobs.dm, defaults to NONE, so people actually have to think about it
+ var/changesource_flags = NONE
///////////
// PROCS //
///////////
diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm
index 9c5c6d5e2fd..b791d8961a1 100644
--- a/code/modules/mob/living/carbon/human/species_types/abductors.dm
+++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm
@@ -6,6 +6,7 @@
species_traits = list(NOBLOOD,NOEYES)
inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NOGUNS,TRAIT_NOHUNGER,TRAIT_NOBREATH)
mutanttongue = /obj/item/organ/tongue/abductor
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
/datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm
index c4665b5d6d6..c021e3bb907 100644
--- a/code/modules/mob/living/carbon/human/species_types/android.dm
+++ b/code/modules/mob/living/carbon/human/species_types/android.dm
@@ -9,6 +9,7 @@
damage_overlay_type = "synth"
mutanttongue = /obj/item/organ/tongue/robot
limbs_id = "synth"
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
/datum/species/android/on_species_gain(mob/living/carbon/C)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm
index e8873e79ce4..a240782bf3f 100644
--- a/code/modules/mob/living/carbon/human/species_types/angel.dm
+++ b/code/modules/mob/living/carbon/human/species_types/angel.dm
@@ -7,9 +7,9 @@
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "Angel")
use_skintones = 1
no_equip = list(SLOT_BACK)
- blacklisted = 1
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
var/datum/action/innate/flight/fly
diff --git a/code/modules/mob/living/carbon/human/species_types/corporate.dm b/code/modules/mob/living/carbon/human/species_types/corporate.dm
index 56fdec3c5ae..077e6b1498b 100644
--- a/code/modules/mob/living/carbon/human/species_types/corporate.dm
+++ b/code/modules/mob/living/carbon/human/species_types/corporate.dm
@@ -13,8 +13,8 @@
punchstunthreshold = 25
attack_verb = "smash"
attack_sound = 'sound/weapons/resonator_blast.ogg'
- blacklisted = 1
use_skintones = 0
species_traits = list(NOBLOOD,EYECOLOR)
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER)
- sexes = 0
\ No newline at end of file
+ sexes = 0
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
index da7de39a03c..f2e6562af41 100644
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
@@ -10,9 +10,9 @@
mutanteyes = /obj/item/organ/eyes/dullahan
mutanttongue = /obj/item/organ/tongue/dullahan
mutantears = /obj/item/organ/ears/dullahan
- blacklisted = TRUE
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN
var/obj/item/dullahan_relay/myhead
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index 4e8edc78902..2114d5b423f 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -13,6 +13,7 @@
attack_type = BURN //burn bish
damage_overlay_type = "" //We are too cool for regular damage overlays
species_traits = list(DYNCOLORS, NOSTOMACH, AGENDER, NO_UNDERWEAR)
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
inherent_traits = list(TRAIT_NOHUNGER)
sexes = FALSE //no fetish content allowed
toxic_food = NONE
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
index 1d82614fb17..3b1a6101109 100644
--- a/code/modules/mob/living/carbon/human/species_types/felinid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -9,6 +9,7 @@
mutantears = /obj/item/organ/ears/cat
mutanttail = /obj/item/organ/tail/cat
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
/datum/species/human/felinid/qualifies_for_rank(rank, list/features)
return TRUE
diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
index 6f05eb393db..934112ceab4 100644
--- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
@@ -10,6 +10,7 @@
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/fly
disliked_food = null
liked_food = GROSS
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "pestkiller")
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 719b0adbbc0..50572bb47ec 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -14,13 +14,12 @@
punchstunthreshold = 11 //about 40% chance to stun
no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM, SLOT_S_STORE)
nojumpsuit = 1
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC
sexes = 1
damage_overlay_type = ""
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/golem
// To prevent golem subtypes from overwhelming the odds when random species
// changes, only the Random Golem type can be chosen
- blacklisted = TRUE
- dangerous_existence = TRUE
limbs_id = "golem"
fixed_mut_color = "aaa"
var/info_text = "As an Iron Golem, you don't have any special traits."
@@ -46,8 +45,7 @@
/datum/species/golem/random
name = "Random Golem"
- blacklisted = FALSE
- dangerous_existence = FALSE
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN
var/static/list/random_golem_types
/datum/species/golem/random/on_species_gain(mob/living/carbon/C, datum/species/old_species)
@@ -638,6 +636,7 @@
attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
sexes = FALSE
speedmod = 0
+ changesource_flags = MIRROR_BADMIN | WABBAJACK
damage_overlay_type = "synth"
prefix = "Clockwork"
special_names = list("Remnant", "Relic", "Scrap", "Vestige") //RIP Ratvar
@@ -673,8 +672,6 @@
no_equip = list()
nojumpsuit = FALSE
has_corpse = TRUE
- blacklisted = TRUE
- dangerous_existence = TRUE
random_eligible = FALSE
info_text = "As a Clockwork Golem Servant, you are faster than other types of golems." //warcult golems leave a corpse
@@ -1017,12 +1014,12 @@
prefix = "Capitalist"
attack_verb = "monopoliz"
limbs_id = "ca_golem"
- blacklisted = TRUE
special_names = list("John D. Rockefeller","Rich Uncle Pennybags","Commodore Vanderbilt","Entrepreneur","Mr Moneybags", "Adam Smith")
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES)
fixed_mut_color = null
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
info_text = "As a Capitalist Golem, your fist spreads the powerful industrializing light of capitalism."
+ changesource_flags = MIRROR_BADMIN
var/last_cash = 0
var/cash_cooldown = 100
@@ -1060,12 +1057,12 @@
prefix = "Comrade"
attack_verb = "nationalis"
limbs_id = "s_golem"
- blacklisted = TRUE
special_names = list("Stalin","Lenin","Trotsky","Marx","Comrade") //comrade comrade
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES)
fixed_mut_color = null
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
info_text = "As a Soviet Golem, your fist spreads the bright soviet light of communism."
+ changesource_flags = MIRROR_BADMIN
/datum/species/golem/soviet/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index 0f947b7293e..055ba80c555 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -8,6 +8,7 @@
skinned_type = /obj/item/stack/sheet/animalhide/human
disliked_food = GROSS | RAW
liked_food = JUNKFOOD | FRIED
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT
/datum/species/human/qualifies_for_rank(rank, list/features)
return TRUE //Pure humans are always allowed in all roles.
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 93b792751e1..47ada1bcaf4 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -14,6 +14,7 @@
coldmod = 6 // = 3x cold damage
heatmod = 0.5 // = 1/4x heat damage
burnmod = 0.5 // = 1/2x generic burn damage
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index 9c7482c1020..e3ba239ec2e 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -12,6 +12,7 @@
coldmod = 1.5
heatmod = 0.67
default_features = list("mcolor" = "0F0", "tail_lizard" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs")
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
index 1d2a1867185..6f405eff8e4 100644
--- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
@@ -15,6 +15,7 @@
disliked_food = FRUIT | GROSS
toxic_food = MEAT | RAW
mutanteyes = /obj/item/organ/eyes/moth
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT
/datum/species/moth/regenerate_organs(mob/living/carbon/C,datum/species/old_species,replace_current=TRUE)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
index 67005fad316..9c9f63d5d89 100644
--- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
@@ -3,6 +3,7 @@
id = "mush"
mutant_bodyparts = list("caps")
default_features = list("caps" = "Round")
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
fixed_mut_color = "DBBF92"
hair_color = "FF4B19" //cap color, spot color uses eye color
@@ -25,7 +26,6 @@
mutanteyes = /obj/item/organ/eyes/night_vision/mushroom
use_skintones = FALSE
var/datum/martial_art/mushpunch/mush
- blacklisted = TRUE //See comment below about locking it out of roundstart. The species is not intended to be available to players yet - and this means wizards, too.
/datum/species/mush/check_roundstart_eligible()
return FALSE //hard locked out of roundstart on the order of design lead kor, this can be removed in the future when planetstation is here OR SOMETHING but right now we have a problem with races.
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index 48535ed8da4..5da74788b18 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -11,8 +11,6 @@
mutanttongue = /obj/item/organ/tongue/bone/plasmaman
mutantliver = /obj/item/organ/liver/plasmaman
mutantstomach = /obj/item/organ/stomach/plasmaman
- dangerous_existence = 1 //So so much
- blacklisted = 1 //See above
burnmod = 1.5
heatmod = 1.5
breathid = "tox"
@@ -20,6 +18,7 @@
var/internal_fire = FALSE //If the bones themselves are burning clothes won't help you much
disliked_food = FRUIT
liked_food = VEGETABLES
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
var/datum/gas_mixture/environment = H.loc.return_air()
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index f09053b8770..a38b89f6407 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -13,6 +13,7 @@
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant
disliked_food = MEAT | DAIRY
liked_food = VEGETABLES | FRUIT | GRAIN
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index 7b235eddd42..142012b5fe9 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -6,13 +6,12 @@
name = "???"
id = "shadow"
sexes = 0
- blacklisted = 1
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
species_traits = list(NOBLOOD,NOEYES)
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH)
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC
- dangerous_existence = 1
mutanteyes = /obj/item/organ/eyes/night_vision
@@ -36,7 +35,6 @@
id = "nightmare"
limbs_id = "shadow"
burnmod = 1.5
- blacklisted = TRUE
no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM, SLOT_S_STORE)
species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYES)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER)
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index f2624a139b7..bbeaf077ad0 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -3,7 +3,6 @@
name = "Spooky Scary Skeleton"
id = "skeleton"
say_mod = "rattles"
- blacklisted = 1
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
species_traits = list(NOBLOOD)
@@ -13,6 +12,8 @@
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
disliked_food = NONE
liked_food = GROSS | MEAT | RAW
+ //They can technically be in an ERT
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
/datum/species/skeleton/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
index 044df98e047..1847bb0eb21 100644
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synths.dm
@@ -6,8 +6,6 @@
species_traits = list(NOTRANSSTING) //all of these + whatever we inherit from the real species
inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER,TRAIT_NOBREATH)
inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID)
- dangerous_existence = 1
- blacklisted = 1
meat = null
damage_overlay_type = "synth"
limbs_id = "synth"
@@ -15,6 +13,7 @@
var/datum/species/fake_species //a species to do most of our work for us, unless we're damaged
var/list/initial_species_traits //for getting these values back for assume_disguise()
var/list/initial_inherent_traits
+ changesource_flags = MIRROR_BADMIN | WABBAJACK
/datum/species/synth/New()
initial_species_traits = species_traits.Copy()
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 12a887e3b84..3f1d3afb22b 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -6,11 +6,11 @@
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None")
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN
exotic_bloodtype = "U"
use_skintones = TRUE
mutant_heart = /obj/item/organ/heart/vampire
mutanttongue = /obj/item/organ/tongue/vampire
- blacklisted = TRUE
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 504dbb514bd..d341c668df1 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -6,7 +6,6 @@
id = "zombie"
say_mod = "moans"
sexes = 0
- blacklisted = 1
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH)
@@ -15,6 +14,7 @@
var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
disliked_food = NONE
liked_food = GROSS | MEAT | RAW
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN
/datum/species/zombie/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
@@ -31,6 +31,7 @@
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
var/heal_rate = 1
var/regen_cooldown = 0
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
/datum/species/zombie/infectious/check_roundstart_eligible()
return FALSE
@@ -88,5 +89,6 @@
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
mutanttongue = /obj/item/organ/tongue/zombie
+ changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
#undef REGENERATION_DELAY
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index 2c38e15a7a5..368efd8ea20 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -244,7 +244,13 @@
if(prob(50))
new_mob = new /mob/living/carbon/human(M.loc)
else
- var/hooman = pick(subtypesof(/mob/living/carbon/human/species))
+ var/chooseable_races = list()
+ for(var/speciestype in subtypesof(/datum/species))
+ var/datum/species/S = speciestype
+ if(initial(S.changesource_flags) & WABBAJACK)
+ chooseable_races += speciestype
+
+ var/hooman = pick(chooseable_races)
new_mob =new hooman(M.loc)
var/datum/preferences/A = new() //Randomize appearance for the human
diff --git a/code/modules/research/xenobiology/crossbreeding/charged.dm b/code/modules/research/xenobiology/crossbreeding/charged.dm
index 62048ce6163..bfdab8b6db2 100644
--- a/code/modules/research/xenobiology/crossbreeding/charged.dm
+++ b/code/modules/research/xenobiology/crossbreeding/charged.dm
@@ -217,10 +217,11 @@ Charged extracts:
to_chat(user, "You have to be able to have a species to get your species changed.")
return
var/list/allowed_species = list()
- for(var/X in subtypesof(/datum/species))
- var/datum/species/temp = X
- if(!initial(temp.blacklisted))
- allowed_species += X
+ for(var/stype in subtypesof(/datum/species))
+ var/datum/species/X = stype
+ if(initial(X.changesource_flags) & SLIME_EXTRACT)
+ allowed_species += stype
+
var/datum/species/changed = pick(allowed_species)
if(changed)
H.set_species(changed, icon_update = 1)
diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
index caa2ca7adff..7c0c8ca1486 100644
--- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm
+++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
@@ -98,6 +98,13 @@
desc = "Pride cometh before the..."
icon_state = "magic_mirror"
+/obj/structure/mirror/magic/pride/New()
+ for(var/speciestype in subtypesof(/datum/species))
+ var/datum/species/S = speciestype
+ if(initial(S.changesource_flags) & MIRROR_PRIDE)
+ choosable_races += initial(S.id)
+ ..()
+
/obj/structure/mirror/magic/pride/curse(mob/user)
user.visible_message("The ground splits beneath [user] as [user.p_their()] hand leaves the mirror!", \
"Perfect. Much better! Now nobody will be able to resist yo-")
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index aae422bc517..2e920c7e2f5 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -7,6 +7,7 @@
#include "reagent_id_typos.dm"
#include "reagent_recipe_collisions.dm"
#include "spawn_humans.dm"
+#include "species_whitelists.dm"
#include "subsystem_init.dm"
#include "timer_sanity.dm"
#include "unit_test.dm"
diff --git a/code/modules/unit_tests/species_whitelists.dm b/code/modules/unit_tests/species_whitelists.dm
new file mode 100644
index 00000000000..acc5c5c121a
--- /dev/null
+++ b/code/modules/unit_tests/species_whitelists.dm
@@ -0,0 +1,5 @@
+/datum/unit_test/species_whitelist_check/Run()
+ for(var/typepath in subtypesof(/datum/species))
+ var/datum/species/S = typepath
+ if(initial(S.changesource_flags) == NONE)
+ Fail("A species type was detected with no changesource flags: [S]")