diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm
index 75526f7d86d..ba99b2e1e7f 100644
--- a/code/__HELPERS/traits.dm
+++ b/code/__HELPERS/traits.dm
@@ -28,3 +28,16 @@
else if(isatom(target))
var/atom/the_atom2 = target
REMOVE_TRAIT(the_atom2,trait,source)
+
+
+/// Proc that handles adding multiple traits to a target via a list. Must have a common source and target.
+/datum/proc/add_traits(list/list_of_traits, source)
+ ASSERT(islist(list_of_traits), "Invalid arguments passed to add_traits! Invoked on [src] with [list_of_traits], source being [source].")
+ for(var/trait in list_of_traits)
+ ADD_TRAIT(src, trait, source)
+
+/// Proc that handles removing multiple traits from a target via a list. Must have a common source and target.
+/datum/proc/remove_traits(list/list_of_traits, source)
+ ASSERT(islist(list_of_traits), "Invalid arguments passed to remove_traits! Invoked on [src] with [list_of_traits], source being [source].")
+ for(var/trait in list_of_traits)
+ REMOVE_TRAIT(src, trait, source)
diff --git a/code/datums/actions/mobs/lava_swoop.dm b/code/datums/actions/mobs/lava_swoop.dm
index 6a769a56758..c309686755a 100644
--- a/code/datums/actions/mobs/lava_swoop.dm
+++ b/code/datums/actions/mobs/lava_swoop.dm
@@ -14,13 +14,11 @@
/datum/action/cooldown/mob_cooldown/lava_swoop/Grant(mob/M)
. = ..()
- ADD_TRAIT(M, TRAIT_LAVA_IMMUNE, REF(src))
- ADD_TRAIT(M, TRAIT_NOFIRE, REF(src))
+ M.add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE), REF(src))
/datum/action/cooldown/mob_cooldown/lava_swoop/Remove(mob/M)
. = ..()
- REMOVE_TRAIT(M, TRAIT_LAVA_IMMUNE, REF(src))
- REMOVE_TRAIT(M, TRAIT_NOFIRE, REF(src))
+ M.remove_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE), REF(src))
/datum/action/cooldown/mob_cooldown/lava_swoop/Activate(atom/target_atom)
StartCooldown(360 SECONDS, 360 SECONDS)
diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm
index 9f3d83964e7..177ff7940ea 100644
--- a/code/datums/brain_damage/special.dm
+++ b/code/datums/brain_damage/special.dm
@@ -262,13 +262,11 @@
lose_text = span_warning("You realize you can feel pain again.")
/datum/brain_trauma/special/tenacity/on_gain()
- ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAUMA_TRAIT)
- ADD_TRAIT(owner, TRAIT_NOHARDCRIT, TRAUMA_TRAIT)
+ owner.add_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT), TRAUMA_TRAIT)
..()
/datum/brain_trauma/special/tenacity/on_lose()
- REMOVE_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAUMA_TRAIT)
- REMOVE_TRAIT(owner, TRAIT_NOHARDCRIT, TRAUMA_TRAIT)
+ owner.remove_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT), TRAUMA_TRAIT)
..()
/datum/brain_trauma/special/death_whispers
diff --git a/code/datums/components/curse_of_hunger.dm b/code/datums/components/curse_of_hunger.dm
index 8912b704662..296e014196a 100644
--- a/code/datums/components/curse_of_hunger.dm
+++ b/code/datums/components/curse_of_hunger.dm
@@ -72,8 +72,7 @@
awakened = TRUE
START_PROCESSING(SSobj, src)
ADD_TRAIT(cursed_item, TRAIT_NODROP, CURSED_ITEM_TRAIT(cursed_item.type))
- ADD_TRAIT(cursed, TRAIT_CLUMSY, CURSED_ITEM_TRAIT(cursed_item.type))
- ADD_TRAIT(cursed, TRAIT_PACIFISM, CURSED_ITEM_TRAIT(cursed_item.type))
+ cursed.add_traits(list(TRAIT_CLUMSY, TRAIT_PACIFISM), CURSED_ITEM_TRAIT(cursed_item.type))
if(add_dropdel)
cursed_item.item_flags |= DROPDEL
@@ -83,8 +82,7 @@
var/obj/item/cursed_item = parent
STOP_PROCESSING(SSobj, src)
REMOVE_TRAIT(cursed_item, TRAIT_NODROP, CURSED_ITEM_TRAIT(cursed_item.type))
- REMOVE_TRAIT(uncursed, TRAIT_CLUMSY, CURSED_ITEM_TRAIT(cursed_item.type))
- REMOVE_TRAIT(uncursed, TRAIT_PACIFISM, CURSED_ITEM_TRAIT(cursed_item.type))
+ uncursed.remove_traits(list(TRAIT_CLUMSY, TRAIT_PACIFISM), CURSED_ITEM_TRAIT(cursed_item.type))
//remove either one of the signals that could have called this proc
UnregisterSignal(cursed_item, COMSIG_ITEM_DROPPED)
diff --git a/code/datums/components/echolocation.dm b/code/datums/components/echolocation.dm
index 0ac93fe92a7..12547587ff8 100644
--- a/code/datums/components/echolocation.dm
+++ b/code/datums/components/echolocation.dm
@@ -60,8 +60,7 @@
if(ispath(color_path))
client_color = echolocator.add_client_colour(color_path)
src.echo_group = echo_group || REF(src)
- ADD_TRAIT(echolocator, TRAIT_ECHOLOCATION_RECEIVER, echo_group)
- ADD_TRAIT(echolocator, TRAIT_TRUE_NIGHT_VISION, echo_group) //so they see all the tiles they echolocated, even if they are in the dark
+ echolocator.add_traits(list(TRAIT_ECHOLOCATION_RECEIVER, TRAIT_TRUE_NIGHT_VISION), echo_group) //so they see all the tiles they echolocated, even if they are in the dark
echolocator.become_blind(ECHOLOCATION_TRAIT)
echolocator.overlay_fullscreen("echo", /atom/movable/screen/fullscreen/echo, echo_icon)
START_PROCESSING(SSfastprocess, src)
@@ -70,8 +69,7 @@
STOP_PROCESSING(SSfastprocess, src)
var/mob/living/echolocator = parent
QDEL_NULL(client_color)
- REMOVE_TRAIT(echolocator, TRAIT_ECHOLOCATION_RECEIVER, echo_group)
- REMOVE_TRAIT(echolocator, TRAIT_TRUE_NIGHT_VISION, echo_group)
+ echolocator.remove_traits(list(TRAIT_ECHOLOCATION_RECEIVER, TRAIT_TRUE_NIGHT_VISION), echo_group)
echolocator.cure_blind(ECHOLOCATION_TRAIT)
echolocator.clear_fullscreen("echo")
for(var/timeframe in images)
diff --git a/code/datums/components/nuclear_bomb_operator.dm b/code/datums/components/nuclear_bomb_operator.dm
index a6372c0275e..835783d6851 100644
--- a/code/datums/components/nuclear_bomb_operator.dm
+++ b/code/datums/components/nuclear_bomb_operator.dm
@@ -34,9 +34,7 @@
RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(owner_attacked_atom)) // This only works for players, but I am not sure this should have AI anyway
RegisterSignal(parent, COMSIG_ATOM_EXITED, PROC_REF(atom_exited_owner))
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
- ADD_TRAIT(parent, TRAIT_DISK_VERIFIER, NUKE_OP_MINION_TRAIT) // Can identify the real disk
- ADD_TRAIT(parent, TRAIT_CAN_STRIP, NUKE_OP_MINION_TRAIT) // Can take the disk off people
- ADD_TRAIT(parent, TRAIT_CAN_USE_NUKE, NUKE_OP_MINION_TRAIT) // Can put the disk into the bomb
+ parent.add_traits(list(TRAIT_DISK_VERIFIER, TRAIT_CAN_STRIP, TRAIT_CAN_USE_NUKE), NUKE_OP_MINION_TRAIT)
/datum/component/nuclear_bomb_operator/UnregisterFromParent()
. = ..()
@@ -48,9 +46,7 @@
COMSIG_ATOM_EXITED,
COMSIG_ATOM_UPDATE_OVERLAYS,
))
- REMOVE_TRAIT(parent, TRAIT_DISK_VERIFIER, NUKE_OP_MINION_TRAIT)
- REMOVE_TRAIT(parent, TRAIT_CAN_STRIP, NUKE_OP_MINION_TRAIT)
- REMOVE_TRAIT(parent, TRAIT_CAN_USE_NUKE, NUKE_OP_MINION_TRAIT)
+ parent.remove_traits(list(TRAIT_DISK_VERIFIER, TRAIT_CAN_STRIP, TRAIT_CAN_USE_NUKE), NUKE_OP_MINION_TRAIT)
/datum/component/nuclear_bomb_operator/Destroy(force, silent)
QDEL_NULL(disky)
diff --git a/code/datums/components/soulstoned.dm b/code/datums/components/soulstoned.dm
index dbe47748be7..bb22030c210 100644
--- a/code/datums/components/soulstoned.dm
+++ b/code/datums/components/soulstoned.dm
@@ -11,8 +11,7 @@
stoned.forceMove(container)
stoned.fully_heal()
- ADD_TRAIT(stoned, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT)
- ADD_TRAIT(stoned, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT)
+ stoned.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), SOULSTONE_TRAIT)
stoned.status_flags |= GODMODE
RegisterSignal(stoned, COMSIG_MOVABLE_MOVED, PROC_REF(free_prisoner))
@@ -27,5 +26,4 @@
/datum/component/soulstoned/UnregisterFromParent()
var/mob/living/stoned = parent
stoned.status_flags &= ~GODMODE
- REMOVE_TRAIT(stoned, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT)
- REMOVE_TRAIT(stoned, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT)
+ stoned.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), SOULSTONE_TRAIT)
diff --git a/code/datums/elements/organ_set_bonus.dm b/code/datums/elements/organ_set_bonus.dm
index 290e9865798..1680a0eb0dc 100644
--- a/code/datums/elements/organ_set_bonus.dm
+++ b/code/datums/elements/organ_set_bonus.dm
@@ -55,8 +55,8 @@
var/bonus_deactivate_text = span_notice("Your DNA is no longer majority ???. You did make an issue report, right?")
/// Required mob bio-type. Also checks DNA validity it's set to MOB_ORGANIC.
var/required_biotype = MOB_ORGANIC
- /// A Trait or list of Traits added to the mob upon bonus activation.
- var/bonus_traits
+ /// A list of traits added to the mob upon bonus activation, can be of any length.
+ var/list/bonus_traits = list()
/datum/status_effect/organ_set_bonus/proc/set_organs(new_value)
organs = new_value
@@ -76,12 +76,8 @@
if((required_biotype == MOB_ORGANIC) && !owner.can_mutate())
return FALSE
bonus_active = TRUE
- if(bonus_traits)
- if(islist(bonus_traits))
- for(var/trait in bonus_traits)
- ADD_TRAIT(owner, trait, REF(src))
- else
- ADD_TRAIT(owner, bonus_traits, REF(src))
+ if(length(bonus_traits))
+ owner.add_traits(bonus_traits, REF(src))
if(bonus_activate_text)
to_chat(owner, bonus_activate_text)
return TRUE
@@ -89,11 +85,7 @@
/datum/status_effect/organ_set_bonus/proc/disable_bonus()
SHOULD_CALL_PARENT(TRUE)
bonus_active = FALSE
- if(bonus_traits)
- if(islist(bonus_traits))
- for(var/trait in bonus_traits)
- REMOVE_TRAIT(owner, trait, REF(src))
- else
- REMOVE_TRAIT(owner, bonus_traits, REF(src))
+ if(length(bonus_traits))
+ owner.remove_traits(bonus_traits, REF(src))
if(bonus_deactivate_text)
to_chat(owner, bonus_deactivate_text)
diff --git a/code/datums/martial/plasma_fist.dm b/code/datums/martial/plasma_fist.dm
index fba91158776..a7eac3d329b 100644
--- a/code/datums/martial/plasma_fist.dm
+++ b/code/datums/martial/plasma_fist.dm
@@ -93,8 +93,7 @@
if (ishuman(user))
var/mob/living/carbon/human/human_attacker = user
human_attacker.set_species(/datum/species/plasmaman)
- ADD_TRAIT(human_attacker, TRAIT_FORCED_STANDING, type)
- ADD_TRAIT(human_attacker, TRAIT_BOMBIMMUNE, type)
+ human_attacker.add_traits(list(TRAIT_FORCED_STANDING, TRAIT_BOMBIMMUNE), type)
human_attacker.unequip_everything()
human_attacker.underwear = "Nude"
human_attacker.undershirt = "Nude"
@@ -117,8 +116,7 @@
plasma_power = 1 //just in case there is any clever way to cause it to happen again
/datum/martial_art/plasma_fist/proc/Apotheosis_end(mob/living/dying)
- REMOVE_TRAIT(dying, TRAIT_FORCED_STANDING, type)
- REMOVE_TRAIT(dying, TRAIT_BOMBIMMUNE, type)
+ dying.remove_traits(list(TRAIT_FORCED_STANDING, TRAIT_BOMBIMMUNE), type)
if(dying.stat == DEAD)
return
dying.investigate_log("has been killed by plasma fist apotheosis.", INVESTIGATE_DEATHS)
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index 3914cf071a0..7d74a945723 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -13,16 +13,12 @@
. = ..()
if(!.)
return
- ADD_TRAIT(target, TRAIT_NOGUNS, SLEEPING_CARP_TRAIT)
- ADD_TRAIT(target, TRAIT_HARDLY_WOUNDED, SLEEPING_CARP_TRAIT)
- ADD_TRAIT(target, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
+ target.add_traits(list(TRAIT_NOGUNS, TRAIT_HARDLY_WOUNDED, TRAIT_NODISMEMBER), SLEEPING_CARP_TRAIT)
RegisterSignal(target, COMSIG_PARENT_ATTACKBY, PROC_REF(on_attackby))
target.faction |= FACTION_CARP //:D
/datum/martial_art/the_sleeping_carp/on_remove(mob/living/target)
- REMOVE_TRAIT(target, TRAIT_NOGUNS, SLEEPING_CARP_TRAIT)
- REMOVE_TRAIT(target, TRAIT_HARDLY_WOUNDED, SLEEPING_CARP_TRAIT)
- REMOVE_TRAIT(target, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
+ target.remove_traits(list(TRAIT_NOGUNS, TRAIT_HARDLY_WOUNDED, TRAIT_NODISMEMBER), SLEEPING_CARP_TRAIT)
UnregisterSignal(target, COMSIG_PARENT_ATTACKBY)
target.faction -= FACTION_CARP //:(
. = ..()
diff --git a/code/datums/mutations/adaptation.dm b/code/datums/mutations/adaptation.dm
index e56d4cff066..7fd90326c00 100644
--- a/code/datums/mutations/adaptation.dm
+++ b/code/datums/mutations/adaptation.dm
@@ -18,14 +18,12 @@
/datum/mutation/human/temperature_adaptation/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- ADD_TRAIT(owner, TRAIT_RESISTCOLD, GENETIC_MUTATION)
- ADD_TRAIT(owner, TRAIT_RESISTHEAT, GENETIC_MUTATION)
+ owner.add_traits(list(TRAIT_RESISTCOLD, TRAIT_RESISTHEAT), GENETIC_MUTATION)
/datum/mutation/human/temperature_adaptation/on_losing(mob/living/carbon/human/owner)
if(..())
return
- REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, GENETIC_MUTATION)
- REMOVE_TRAIT(owner, TRAIT_RESISTHEAT, GENETIC_MUTATION)
+ owner.remove_traits(list(TRAIT_RESISTCOLD, TRAIT_RESISTHEAT), GENETIC_MUTATION)
/datum/mutation/human/pressure_adaptation
name = "Pressure Adaptation"
@@ -47,11 +45,9 @@
/datum/mutation/human/pressure_adaptation/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, GENETIC_MUTATION)
- ADD_TRAIT(owner, TRAIT_RESISTHIGHPRESSURE, GENETIC_MUTATION)
+ owner.add_traits(list(TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTHIGHPRESSURE), GENETIC_MUTATION)
/datum/mutation/human/pressure_adaptation/on_losing(mob/living/carbon/human/owner)
if(..())
return
- REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, GENETIC_MUTATION)
- REMOVE_TRAIT(owner, TRAIT_RESISTHIGHPRESSURE, GENETIC_MUTATION)
+ owner.remove_traits(list(TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTHIGHPRESSURE), GENETIC_MUTATION)
diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm
index a26d37579c7..de0d97274a7 100644
--- a/code/datums/mutations/hulk.dm
+++ b/code/datums/mutations/hulk.dm
@@ -11,16 +11,20 @@
instability = 40
var/scream_delay = 50
var/last_scream = 0
+ /// List of traits to add/remove when someone gets this mutation.
+ var/static/list/mutation_traits = list(
+ TRAIT_CHUNKYFINGERS,
+ TRAIT_HULK,
+ TRAIT_IGNOREDAMAGESLOWDOWN,
+ TRAIT_PUSHIMMUNE,
+ TRAIT_STUNIMMUNE,
+ )
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- ADD_TRAIT(owner, TRAIT_STUNIMMUNE, GENETIC_MUTATION)
- ADD_TRAIT(owner, TRAIT_PUSHIMMUNE, GENETIC_MUTATION)
- ADD_TRAIT(owner, TRAIT_CHUNKYFINGERS, GENETIC_MUTATION)
- ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, GENETIC_MUTATION)
- ADD_TRAIT(owner, TRAIT_HULK, GENETIC_MUTATION)
+ owner.add_traits(mutation_traits, GENETIC_MUTATION)
for(var/obj/item/bodypart/part as anything in owner.bodyparts)
part.variable_color = "#00aa00"
owner.update_body_parts()
@@ -75,11 +79,7 @@
/datum/mutation/human/hulk/on_losing(mob/living/carbon/human/owner)
if(..())
return
- REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, GENETIC_MUTATION)
- REMOVE_TRAIT(owner, TRAIT_PUSHIMMUNE, GENETIC_MUTATION)
- REMOVE_TRAIT(owner, TRAIT_CHUNKYFINGERS, GENETIC_MUTATION)
- REMOVE_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, GENETIC_MUTATION)
- REMOVE_TRAIT(owner, TRAIT_HULK, GENETIC_MUTATION)
+ owner.remove_traits(mutation_traits, GENETIC_MUTATION)
for(var/obj/item/bodypart/part as anything in owner.bodyparts)
part.variable_color = null
owner.update_body_parts()
diff --git a/code/datums/mutations/passive.dm b/code/datums/mutations/passive.dm
index 1c6d130b9e5..9d694aaf1eb 100644
--- a/code/datums/mutations/passive.dm
+++ b/code/datums/mutations/passive.dm
@@ -23,11 +23,9 @@
/datum/mutation/human/clever/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- ADD_TRAIT(owner, TRAIT_ADVANCEDTOOLUSER, GENETIC_MUTATION)
- ADD_TRAIT(owner, TRAIT_LITERATE, GENETIC_MUTATION)
+ owner.add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE), GENETIC_MUTATION)
/datum/mutation/human/clever/on_losing(mob/living/carbon/human/owner)
if(..())
return
- REMOVE_TRAIT(owner, TRAIT_ADVANCEDTOOLUSER, GENETIC_MUTATION)
- REMOVE_TRAIT(owner, TRAIT_LITERATE, GENETIC_MUTATION)
+ owner.remove_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE), GENETIC_MUTATION)
diff --git a/code/datums/proximity_monitor/fields/timestop.dm b/code/datums/proximity_monitor/fields/timestop.dm
index 85f3c787987..f66fe0e3012 100644
--- a/code/datums/proximity_monitor/fields/timestop.dm
+++ b/code/datums/proximity_monitor/fields/timestop.dm
@@ -210,8 +210,7 @@
/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/victim)
frozen_mobs += victim
victim.Stun(20, ignore_canstun = TRUE)
- ADD_TRAIT(victim, TRAIT_MUTE, TIMESTOP_TRAIT)
- ADD_TRAIT(victim, TRAIT_EMOTEMUTE, TIMESTOP_TRAIT)
+ victim.add_traits(list(TRAIT_MUTE, TRAIT_EMOTEMUTE), TIMESTOP_TRAIT)
SSmove_manager.stop_looping(victim) //stops them mid pathing even if they're stunimmune //This is really dumb
if(isanimal(victim))
var/mob/living/simple_animal/animal_victim = victim
@@ -225,8 +224,7 @@
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/victim)
victim.AdjustStun(-20, ignore_canstun = TRUE)
- REMOVE_TRAIT(victim, TRAIT_MUTE, TIMESTOP_TRAIT)
- REMOVE_TRAIT(victim, TRAIT_EMOTEMUTE, TIMESTOP_TRAIT)
+ victim.remove_traits(list(TRAIT_MUTE, TRAIT_EMOTEMUTE), TIMESTOP_TRAIT)
frozen_mobs -= victim
if(isanimal(victim))
var/mob/living/simple_animal/animal_victim = victim
diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm
index 01e47b7a4bd..c1814772f1d 100644
--- a/code/datums/status_effects/debuffs/debuffs.dm
+++ b/code/datums/status_effects/debuffs/debuffs.dm
@@ -30,17 +30,12 @@
. = ..()
if(!.)
return
- ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
+ owner.add_traits(list(TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_STATUS_EFFECT(id))
/datum/status_effect/incapacitating/stun/on_remove()
- REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
- REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
+ owner.remove_traits(list(TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_STATUS_EFFECT(id))
return ..()
-
//KNOCKDOWN
/datum/status_effect/incapacitating/knockdown
id = "knockdown"
@@ -79,16 +74,10 @@
. = ..()
if(!.)
return
- ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_FLOORED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
+ owner.add_traits(list(TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED, TRAIT_HANDS_BLOCKED), TRAIT_STATUS_EFFECT(id))
/datum/status_effect/incapacitating/paralyzed/on_remove()
- REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
- REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- REMOVE_TRAIT(owner, TRAIT_FLOORED, TRAIT_STATUS_EFFECT(id))
- REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
+ owner.remove_traits(list(TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED, TRAIT_HANDS_BLOCKED), TRAIT_STATUS_EFFECT(id))
return ..()
//INCAPACITATED
@@ -261,9 +250,7 @@
. = ..()
if(!.)
return
- ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
- ADD_TRAIT(owner, TRAIT_NUMBED, TRAIT_STATUS_EFFECT(id)) //SKYRAT EDIT START - STASIS APPLIES NUMBING
+ owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_NUMBED), TRAIT_STATUS_EFFECT(id))//SKYRAT EDIT START - STASIS APPLIES NUMBING
owner.throw_alert("stasis numbed", /atom/movable/screen/alert/numbed) //SKYRAT EDIT END
owner.add_filter("stasis_status_ripple", 2, list("type" = "ripple", "flags" = WAVE_BOUNDED, "radius" = 0, "size" = 2))
var/filter = owner.get_filter("stasis_status_ripple")
@@ -279,11 +266,8 @@
owner.Sleeping(15 SECONDS) //SKYRAT EDIT END
/datum/status_effect/grouped/stasis/on_remove()
- REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
- REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
- if(HAS_TRAIT(owner, TRAIT_NUMBED)) //SKYRAT EDIT START - STASIS END REMOVES NUMBING
- REMOVE_TRAIT(owner, TRAIT_NUMBED, TRAIT_STATUS_EFFECT(id))
- owner.clear_alert("stasis numbed") //SKYRAT EDIT END
+ owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_NUMBED), TRAIT_STATUS_EFFECT(id)) //SKYRAT EDIT START - STASIS END REMOVES NUMBING
+ owner.clear_alert("stasis numbed") //SKYRAT EDIT END
owner.remove_filter("stasis_status_ripple")
update_time_of_death()
if(iscarbon(owner))
@@ -523,14 +507,12 @@
/datum/status_effect/gonbola_pacify/on_apply()
. = ..()
- ADD_TRAIT(owner, TRAIT_PACIFISM, CLOTHING_TRAIT)
- ADD_TRAIT(owner, TRAIT_MUTE, CLOTHING_TRAIT)
+ owner.add_traits(list(TRAIT_PACIFISM, TRAIT_MUTE), CLOTHING_TRAIT)
owner.add_mood_event(type, /datum/mood_event/gondola)
to_chat(owner, span_notice("You suddenly feel at peace and feel no need to make any sudden or rash actions..."))
/datum/status_effect/gonbola_pacify/on_remove()
- REMOVE_TRAIT(owner, TRAIT_PACIFISM, CLOTHING_TRAIT)
- REMOVE_TRAIT(owner, TRAIT_MUTE, CLOTHING_TRAIT)
+ owner.remove_traits(list(TRAIT_PACIFISM, TRAIT_MUTE), CLOTHING_TRAIT)
owner.clear_mood_event(type)
return ..()
diff --git a/code/datums/status_effects/drug_effects.dm b/code/datums/status_effects/drug_effects.dm
index ea9327a54e5..d01a92743b5 100644
--- a/code/datums/status_effects/drug_effects.dm
+++ b/code/datums/status_effects/drug_effects.dm
@@ -78,8 +78,7 @@
human_owner.eye_color_left = BLOODCULT_EYE //makes cult eyes less obvious
human_owner.eye_color_right = BLOODCULT_EYE //makes cult eyes less obvious
human_owner.update_body() //updates eye color
- ADD_TRAIT(human_owner, TRAIT_BLOODSHOT_EYES, type) //dilates blood vessels in eyes
- ADD_TRAIT(human_owner, TRAIT_CLUMSY, type) //impairs motor coordination
+ human_owner.add_traits(list(TRAIT_CLUMSY, TRAIT_BLOODSHOT_EYES), type) // impairs motor coordination and dilates blood vessels in eyes
human_owner.add_mood_event("stoned", /datum/mood_event/stoned) //improves mood
human_owner.sound_environment_override = SOUND_ENVIRONMENT_DRUGGED //not realistic but very immersive
return TRUE
@@ -92,8 +91,7 @@
human_owner.eye_color_left = original_eye_color_left
human_owner.eye_color_right = original_eye_color_right
human_owner.update_body()
- REMOVE_TRAIT(human_owner, TRAIT_BLOODSHOT_EYES, type)
- REMOVE_TRAIT(human_owner, TRAIT_CLUMSY, type)
+ human_owner.remove_traits(list(TRAIT_CLUMSY, TRAIT_BLOODSHOT_EYES), type)
human_owner.clear_mood_event("stoned")
human_owner.sound_environment_override = SOUND_ENVIRONMENT_NONE
diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm
index 9c8e4706bc3..e97769599a7 100644
--- a/code/datums/wounds/_wounds.dm
+++ b/code/datums/wounds/_wounds.dm
@@ -241,12 +241,10 @@
RegisterSignal(new_value, COMSIG_PARENT_QDELETING, PROC_REF(source_died))
if(. && disabling)
var/obj/item/bodypart/old_limb = .
- REMOVE_TRAIT(old_limb, TRAIT_PARALYSIS, REF(src))
- REMOVE_TRAIT(old_limb, TRAIT_DISABLED_BY_WOUND, REF(src))
+ old_limb.remove_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src))
if(limb)
if(disabling)
- ADD_TRAIT(limb, TRAIT_PARALYSIS, REF(src))
- ADD_TRAIT(limb, TRAIT_DISABLED_BY_WOUND, REF(src))
+ limb.add_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src))
/// Proc called to change the variable `disabling` and react to the event.
@@ -257,11 +255,9 @@
disabling = new_value
if(disabling)
if(!. && limb) //Gained disabling.
- ADD_TRAIT(limb, TRAIT_PARALYSIS, REF(src))
- ADD_TRAIT(limb, TRAIT_DISABLED_BY_WOUND, REF(src))
+ limb.add_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src))
else if(. && limb) //Lost disabling.
- REMOVE_TRAIT(limb, TRAIT_PARALYSIS, REF(src))
- REMOVE_TRAIT(limb, TRAIT_DISABLED_BY_WOUND, REF(src))
+ limb.remove_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src))
if(limb?.can_be_disabled)
limb.update_disabled()
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 5415ff92f24..c700cade9f6 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -1547,16 +1547,14 @@
grab_state = newstate
switch(grab_state) // Current state.
if(GRAB_PASSIVE)
- REMOVE_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
- REMOVE_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
+ pulling.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), CHOKEHOLD_TRAIT)
if(. >= GRAB_NECK) // Previous state was a a neck-grab or higher.
REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
if(GRAB_AGGRESSIVE)
if(. >= GRAB_NECK) // Grab got downgraded.
REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
else // Grab got upgraded from a passive one.
- ADD_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
- ADD_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
+ pulling.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), CHOKEHOLD_TRAIT)
if(GRAB_NECK, GRAB_KILL)
if(. <= GRAB_AGGRESSIVE)
ADD_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
diff --git a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm
index 0835ce5aa09..9208ae40fdf 100644
--- a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm
@@ -9,7 +9,7 @@
organs_needed = 4
bonus_activate_text = span_notice("Carp DNA is deeply infused with you! You've learned how to propel yourself through space!")
bonus_deactivate_text = span_notice("Your DNA is once again mostly yours, and so fades your ability to space-swim...")
- bonus_traits = TRAIT_SPACEWALK
+ bonus_traits = list(TRAIT_SPACEWALK)
///Carp lungs! You can breathe in space! Oh... you can't breathe on the station, you need low oxygen environments.
/// Inverts behavior of lungs. Bypasses suffocation due to space / lack of gas, but also allows Oxygen to suffocate.
diff --git a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm
index 66283804e77..c23a8a5307e 100644
--- a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm
@@ -9,7 +9,7 @@
organs_needed = 4
bonus_activate_text = span_notice("goliath DNA is deeply infused with you! You can now endure walking on lava!")
bonus_deactivate_text = span_notice("You feel your muscle mass shrink and the tendrils around your skin wither. Your Goliath DNA is mostly gone and so is your ability to survive lava.")
- bonus_traits = TRAIT_LAVA_IMMUNE
+ bonus_traits = list(TRAIT_LAVA_IMMUNE)
///goliath eyes, simple night vision
/obj/item/organ/internal/eyes/night_vision/goliath
diff --git a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm
index 805ae2290be..7ed3a874655 100644
--- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm
@@ -24,7 +24,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah...
icon_state = "heart"
greyscale_config = /datum/greyscale_config/mutant_organ
greyscale_colors = GONDOLA_COLORS
- organ_traits = TRAIT_PACIFISM
+ organ_traits = list(TRAIT_PACIFISM)
///keeps track of whether the reciever actually gained factions
var/list/factions_to_remove = list()
@@ -56,7 +56,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah...
icon_state = "tongue"
greyscale_config = /datum/greyscale_config/mutant_organ
greyscale_colors = GONDOLA_COLORS
- organ_traits = TRAIT_MUTE
+ organ_traits = list(TRAIT_MUTE)
/obj/item/organ/internal/tongue/gondola/Initialize(mapload)
. = ..()
diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
index d107bf42534..56307b09a35 100644
--- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
@@ -9,7 +9,7 @@
organs_needed = 4
bonus_activate_text = span_notice("Rodent DNA is deeply infused with you! You've learned how to traverse ventilation!")
bonus_deactivate_text = span_notice("Your DNA is no longer majority rat, and so fades your ventilation skills...")
- bonus_traits = TRAIT_VENTCRAWLER_NUDE
+ bonus_traits = list(TRAIT_VENTCRAWLER_NUDE)
///way better night vision, super sensitive. lotta things work like this, huh?
/obj/item/organ/internal/eyes/night_vision/rat
diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm
index 0f66ab45afc..6717d263bf0 100644
--- a/code/game/objects/items/body_egg.dm
+++ b/code/game/objects/items/body_egg.dm
@@ -15,20 +15,19 @@
if(iscarbon(loc))
Insert(loc)
-/obj/item/organ/internal/body_egg/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
+/obj/item/organ/internal/body_egg/Insert(mob/living/carbon/egg_owner, special = FALSE, drop_if_replaced = TRUE)
. = ..()
- ADD_TRAIT(owner, TRAIT_XENO_HOST, ORGAN_TRAIT)
- ADD_TRAIT(owner, TRAIT_XENO_IMMUNE, ORGAN_TRAIT)
- owner.med_hud_set_status()
- INVOKE_ASYNC(src, PROC_REF(AddInfectionImages), owner)
+ if(!.)
+ return
+ egg_owner.add_traits(list(TRAIT_XENO_HOST, TRAIT_XENO_IMMUNE), ORGAN_TRAIT)
+ egg_owner.med_hud_set_status()
+ INVOKE_ASYNC(src, PROC_REF(AddInfectionImages), egg_owner)
-/obj/item/organ/internal/body_egg/Remove(mob/living/carbon/M, special = FALSE)
- if(owner)
- REMOVE_TRAIT(owner, TRAIT_XENO_HOST, ORGAN_TRAIT)
- REMOVE_TRAIT(owner, TRAIT_XENO_IMMUNE, ORGAN_TRAIT)
- owner.med_hud_set_status()
- INVOKE_ASYNC(src, PROC_REF(RemoveInfectionImages), owner)
- return ..()
+/obj/item/organ/internal/body_egg/Remove(mob/living/carbon/egg_owner, special = FALSE)
+ . = ..()
+ egg_owner.remove_traits(list(TRAIT_XENO_HOST, TRAIT_XENO_IMMUNE), ORGAN_TRAIT)
+ egg_owner.med_hud_set_status()
+ INVOKE_ASYNC(src, PROC_REF(RemoveInfectionImages), egg_owner)
/obj/item/organ/internal/body_egg/on_death(delta_time, times_fired)
. = ..()
diff --git a/code/modules/admin/smites/puzzgrid.dm b/code/modules/admin/smites/puzzgrid.dm
index d2f2a197899..481f85a191f 100644
--- a/code/modules/admin/smites/puzzgrid.dm
+++ b/code/modules/admin/smites/puzzgrid.dm
@@ -54,8 +54,7 @@
name = "[victim]'s fiendish curse"
- ADD_TRAIT(victim, TRAIT_HANDS_BLOCKED, "[type]")
- ADD_TRAIT(victim, TRAIT_IMMOBILIZED, "[type]")
+ victim.add_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_IMMOBILIZED), "[type]")
add_puzzgrid_component(puzzgrid)
@@ -80,7 +79,7 @@
span_notice("You are unshackled from your fiendish prison!"),
)
- remove_traits()
+ victim.remove_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_IMMOBILIZED), "[type]")
victim = null
@@ -103,7 +102,7 @@
victim.forceMove(loc)
victim.Paralyze(5 SECONDS)
victim.visible_message(span_bolddanger("Despite completely failing the puzzle, through unbelievable luck, [victim] manages to break out anyway!"))
- remove_traits()
+ victim.remove_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_IMMOBILIZED), "[type]")
qdel(src)
victim = null
return
@@ -112,7 +111,3 @@
// Defer until after the fail proc finishes, since that will qdel the component.
addtimer(CALLBACK(src, PROC_REF(add_puzzgrid_component), puzzgrid), 0)
-
-/obj/structure/puzzgrid_effect/proc/remove_traits()
- REMOVE_TRAIT(victim, TRAIT_HANDS_BLOCKED, "[type]")
- REMOVE_TRAIT(victim, TRAIT_IMMOBILIZED, "[type]")
diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm
index 3d42ec59b0d..70761013ae3 100644
--- a/code/modules/antagonists/abductor/abductor.dm
+++ b/code/modules/antagonists/abductor/abductor.dm
@@ -113,14 +113,12 @@
break
/datum/antagonist/abductor/scientist/on_gain()
- ADD_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
- ADD_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
- . = ..()
+ owner.add_traits(list(TRAIT_ABDUCTOR_SCIENTIST_TRAINING, TRAIT_SURGEON), ABDUCTOR_ANTAGONIST)
+ return ..()
/datum/antagonist/abductor/scientist/on_removal()
- REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
- REMOVE_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
- . = ..()
+ owner.remove_traits(list(TRAIT_ABDUCTOR_SCIENTIST_TRAINING, TRAIT_SURGEON), ABDUCTOR_ANTAGONIST)
+ return ..()
/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
var/list/current_teams = list()
diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm
index 7274f4c6d8c..215340945fb 100644
--- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm
@@ -224,5 +224,5 @@
existing_beam_spell.cooldown_time *= 0.66 // Lower cooldown
user.client?.give_award(/datum/award/achievement/misc/ash_ascension, user)
- for(var/trait in traits_to_apply)
- ADD_TRAIT(user, trait, MAGIC_TRAIT)
+ if(length(traits_to_apply))
+ user.add_traits(traits_to_apply, MAGIC_TRAIT)
diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm
index fb0943b26d8..fc9ebbc20bf 100644
--- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm
@@ -261,8 +261,7 @@
/datum/heretic_knowledge/duel_stance/on_lose(mob/user, datum/antagonist/heretic/our_heretic)
REMOVE_TRAIT(user, TRAIT_NODISMEMBER, type)
if(in_duelist_stance)
- REMOVE_TRAIT(user, TRAIT_HARDLY_WOUNDED, type)
- REMOVE_TRAIT(user, TRAIT_BATON_RESISTANCE, type)
+ user.remove_traits(list(TRAIT_HARDLY_WOUNDED, TRAIT_BATON_RESISTANCE), type)
UnregisterSignal(user, list(COMSIG_PARENT_EXAMINE, COMSIG_CARBON_GAIN_WOUND, COMSIG_LIVING_HEALTH_UPDATE))
@@ -287,15 +286,13 @@
if(in_duelist_stance && source.health > source.maxHealth * 0.5)
source.balloon_alert(source, "exited duelist stance")
in_duelist_stance = FALSE
- REMOVE_TRAIT(source, TRAIT_HARDLY_WOUNDED, type)
- REMOVE_TRAIT(source, TRAIT_BATON_RESISTANCE, type)
+ source.remove_traits(list(TRAIT_HARDLY_WOUNDED, TRAIT_BATON_RESISTANCE), type)
return
if(!in_duelist_stance && source.health <= source.maxHealth * 0.5)
source.balloon_alert(source, "entered duelist stance")
in_duelist_stance = TRUE
- ADD_TRAIT(source, TRAIT_HARDLY_WOUNDED, type)
- ADD_TRAIT(source, TRAIT_BATON_RESISTANCE, type)
+ source.add_traits(list(TRAIT_HARDLY_WOUNDED, TRAIT_BATON_RESISTANCE), type)
return
#undef BLOOD_FLOW_PER_SEVEIRTY
@@ -404,8 +401,7 @@
. = ..()
priority_announce("[generate_heretic_text()] Master of blades, the Torn Champion's disciple, [user.real_name] has ascended! Their steel is that which will cut reality in a maelstom of silver! [generate_heretic_text()]","[generate_heretic_text()]", ANNOUNCER_SPANOMALIES)
user.client?.give_award(/datum/award/achievement/misc/blade_ascension, user)
- ADD_TRAIT(user, TRAIT_STUNIMMUNE, name)
- ADD_TRAIT(user, TRAIT_NEVER_WOUNDED, name)
+ user.add_traits(list(TRAIT_STUNIMMUNE, TRAIT_NEVER_WOUNDED), name)
RegisterSignal(user, COMSIG_HERETIC_BLADE_ATTACK, PROC_REF(on_eldritch_blade))
user.apply_status_effect(/datum/status_effect/protective_blades/recharging, null, 8, 30, 0.25 SECONDS, 1 MINUTES)
diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm
index 4b3ef319593..8b21ae7db74 100644
--- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm
@@ -30,7 +30,7 @@
name = "Blacksmith's Tale"
desc = "Opens up the Path of Rust to you. \
Allows you to transmute a knife with any trash item into a Rusty Blade. \
- You can only create five at a time." //SKYRAT EDIT two to five
+ You can only create two at a time."
gain_text = "\"Let me tell you a story\", said the Blacksmith, as he gazed deep into his rusty blade."
next_knowledge = list(/datum/heretic_knowledge/rust_fist)
required_atoms = list(
@@ -219,20 +219,20 @@
var/area/ritual_location = /area/station/command/bridge
/// A static list of traits we give to the heretic when on rust.
var/static/list/conditional_immunities = list(
- TRAIT_STUNIMMUNE,
- TRAIT_SLEEPIMMUNE,
- TRAIT_PUSHIMMUNE,
- TRAIT_SHOCKIMMUNE,
+ TRAIT_BOMBIMMUNE,
TRAIT_NO_SLIP_ALL,
+ TRAIT_NOBREATH,
+ TRAIT_PIERCEIMMUNE,
+ TRAIT_PUSHIMMUNE,
TRAIT_RADIMMUNE,
- TRAIT_RESISTHIGHPRESSURE,
- TRAIT_RESISTLOWPRESSURE,
TRAIT_RESISTCOLD,
TRAIT_RESISTHEAT,
- TRAIT_PIERCEIMMUNE,
- TRAIT_BOMBIMMUNE,
- TRAIT_NOBREATH,
- )
+ TRAIT_RESISTHIGHPRESSURE,
+ TRAIT_RESISTLOWPRESSURE,
+ TRAIT_SHOCKIMMUNE,
+ TRAIT_SLEEPIMMUNE,
+ TRAIT_STUNIMMUNE,
+ )
/datum/heretic_knowledge/ultimate/rust_final/on_research(mob/user, datum/antagonist/heretic/our_heretic)
. = ..()
@@ -270,15 +270,13 @@
var/turf/our_turf = get_turf(source)
if(HAS_TRAIT(our_turf, TRAIT_RUSTY))
if(!immunities_active)
- for(var/trait in conditional_immunities)
- ADD_TRAIT(source, trait, type)
+ source.add_traits(conditional_immunities, type)
immunities_active = TRUE
// If we're not on a rust turf, and we have given out our traits, nerf our guy
else
if(immunities_active)
- for(var/trait in conditional_immunities)
- REMOVE_TRAIT(source, trait, type)
+ source.remove_traits(conditional_immunities, type)
immunities_active = FALSE
/**
diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm
index 476392b539e..7a03bace105 100644
--- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm
+++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm
@@ -19,15 +19,11 @@
return ..()
/datum/status_effect/unholy_determination/on_apply()
- ADD_TRAIT(owner, TRAIT_COAGULATING, type)
- ADD_TRAIT(owner, TRAIT_NOCRITDAMAGE, type)
- ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, type)
+ owner.add_traits(list(TRAIT_COAGULATING, TRAIT_NOCRITDAMAGE, TRAIT_NOSOFTCRIT), type)
return TRUE
/datum/status_effect/unholy_determination/on_remove()
- REMOVE_TRAIT(owner, TRAIT_COAGULATING, type)
- REMOVE_TRAIT(owner, TRAIT_NOCRITDAMAGE, type)
- REMOVE_TRAIT(owner, TRAIT_NOSOFTCRIT, type)
+ owner.remove_traits(list(TRAIT_COAGULATING, TRAIT_NOCRITDAMAGE, TRAIT_NOSOFTCRIT), type)
/datum/status_effect/unholy_determination/tick()
// The amount we heal of each damage type per tick. If we're missing legs we heal better because we can't dodge.
diff --git a/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm
index 5d3d56244d8..384076b8cf6 100644
--- a/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm
+++ b/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm
@@ -44,16 +44,14 @@
return
to_chat(chosen_mob, span_danger("You suddenly lose feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!"))
- ADD_TRAIT(chosen_mob, TRAIT_PARALYSIS_L_LEG, type)
- ADD_TRAIT(chosen_mob, TRAIT_PARALYSIS_R_LEG, type)
+ chosen_mob.add_traits(list(TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG), type)
return ..()
/datum/heretic_knowledge/curse/paralysis/uncurse(mob/living/carbon/human/chosen_mob, boosted = FALSE)
if(QDELETED(chosen_mob))
return
- REMOVE_TRAIT(chosen_mob, TRAIT_PARALYSIS_L_LEG, type)
- REMOVE_TRAIT(chosen_mob, TRAIT_PARALYSIS_R_LEG, type)
+ chosen_mob.remove_traits(list(TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG), type)
if(chosen_mob.usable_legs > 1)
to_chat(chosen_mob, span_green("You regain feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!"))
return ..()
diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm
index 1c4e5dcaa01..d6a229b02b9 100644
--- a/code/modules/antagonists/heretic/knowledge/void_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm
@@ -91,12 +91,10 @@
route = PATH_VOID
/datum/heretic_knowledge/cold_snap/on_gain(mob/user, datum/antagonist/heretic/our_heretic)
- ADD_TRAIT(user, TRAIT_RESISTCOLD, type)
- ADD_TRAIT(user, TRAIT_NOBREATH, type)
+ user.add_traits(list(TRAIT_NOBREATH, TRAIT_RESISTCOLD), type)
/datum/heretic_knowledge/cold_snap/on_lose(mob/user, datum/antagonist/heretic/our_heretic)
- REMOVE_TRAIT(user, TRAIT_RESISTCOLD, type)
- REMOVE_TRAIT(user, TRAIT_NOBREATH, type)
+ user.remove_traits(list(TRAIT_RESISTCOLD, TRAIT_NOBREATH), type)
/datum/heretic_knowledge/mark/void_mark
name = "Mark of Void"
diff --git a/code/modules/antagonists/heretic/magic/shadow_cloak.dm b/code/modules/antagonists/heretic/magic/shadow_cloak.dm
index 7c701a36445..80bdfeae470 100644
--- a/code/modules/antagonists/heretic/magic/shadow_cloak.dm
+++ b/code/modules/antagonists/heretic/magic/shadow_cloak.dm
@@ -138,8 +138,7 @@
animate(cloak_image, alpha = 255, 0.2 SECONDS)
owner.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, id, cloak_image)
// Add the relevant traits and modifiers
- ADD_TRAIT(owner, TRAIT_UNKNOWN, id)
- ADD_TRAIT(owner, TRAIT_SILENT_FOOTSTEPS, id)
+ owner.add_traits(list(TRAIT_UNKNOWN, TRAIT_SILENT_FOOTSTEPS), id)
owner.add_movespeed_modifier(/datum/movespeed_modifier/shadow_cloak)
owner.add_actionspeed_modifier(/datum/actionspeed_modifier/shadow_cloak)
// Register signals to cause effects
@@ -155,8 +154,7 @@
owner.remove_alt_appearance(id)
QDEL_NULL(cloak_image)
// Remove traits and modifiers
- REMOVE_TRAIT(owner, TRAIT_UNKNOWN, id)
- REMOVE_TRAIT(owner, TRAIT_SILENT_FOOTSTEPS, id)
+ owner.remove_traits(list(TRAIT_UNKNOWN, TRAIT_SILENT_FOOTSTEPS), id)
owner.remove_movespeed_modifier(/datum/movespeed_modifier/shadow_cloak)
owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/shadow_cloak)
// Clear signals
diff --git a/code/modules/antagonists/highlander/highlander.dm b/code/modules/antagonists/highlander/highlander.dm
index 9998e1939b8..c740de9279f 100644
--- a/code/modules/antagonists/highlander/highlander.dm
+++ b/code/modules/antagonists/highlander/highlander.dm
@@ -6,25 +6,25 @@
can_elimination_hijack = ELIMINATION_ENABLED
suicide_cry = "FOR SCOTLAND!!" // If they manage to lose their no-drop stuff somehow
count_against_dynamic_roll_chance = FALSE
+ /// Traits we apply/remove to our target on-demand.
+ var/static/list/applicable_traits = list(
+ TRAIT_NOBREATH,
+ TRAIT_NODISMEMBER,
+ TRAIT_NOFIRE,
+ TRAIT_NOGUNS,
+ TRAIT_SHOCKIMMUNE,
+ )
/datum/antagonist/highlander/apply_innate_effects(mob/living/mob_override)
- var/mob/living/L = owner.current || mob_override
- ADD_TRAIT(L, TRAIT_NOGUNS, HIGHLANDER_TRAIT)
- ADD_TRAIT(L, TRAIT_NODISMEMBER, HIGHLANDER_TRAIT)
- ADD_TRAIT(L, TRAIT_SHOCKIMMUNE, HIGHLANDER_TRAIT)
- ADD_TRAIT(L, TRAIT_NOFIRE, HIGHLANDER_TRAIT)
- ADD_TRAIT(L, TRAIT_NOBREATH, HIGHLANDER_TRAIT)
- REMOVE_TRAIT(L, TRAIT_PACIFISM, ROUNDSTART_TRAIT)
+ var/mob/living/subject = owner.current || mob_override
+ subject.add_traits(applicable_traits, HIGHLANDER_TRAIT)
+ REMOVE_TRAIT(subject, TRAIT_PACIFISM, ROUNDSTART_TRAIT)
/datum/antagonist/highlander/remove_innate_effects(mob/living/mob_override)
- var/mob/living/L = owner.current || mob_override
- REMOVE_TRAIT(L, TRAIT_NOGUNS, HIGHLANDER_TRAIT)
- REMOVE_TRAIT(L, TRAIT_NODISMEMBER, HIGHLANDER_TRAIT)
- REMOVE_TRAIT(L, TRAIT_SHOCKIMMUNE, HIGHLANDER_TRAIT)
- REMOVE_TRAIT(L, TRAIT_NOFIRE, HIGHLANDER_TRAIT)
- REMOVE_TRAIT(L, TRAIT_NOBREATH, HIGHLANDER_TRAIT)
- if(L.has_quirk(/datum/quirk/nonviolent))
- ADD_TRAIT(L, TRAIT_PACIFISM, ROUNDSTART_TRAIT)
+ var/mob/living/subject = owner.current || mob_override
+ subject.remove_traits(applicable_traits, HIGHLANDER_TRAIT)
+ if(subject.has_quirk(/datum/quirk/nonviolent))
+ ADD_TRAIT(subject, TRAIT_PACIFISM, ROUNDSTART_TRAIT)
/datum/antagonist/highlander/forge_objectives()
var/datum/objective/steal/steal_objective = new
diff --git a/code/modules/antagonists/santa/santa.dm b/code/modules/antagonists/santa/santa.dm
index 0dc55c942c0..2a5eb75e5c8 100644
--- a/code/modules/antagonists/santa/santa.dm
+++ b/code/modules/antagonists/santa/santa.dm
@@ -10,8 +10,7 @@
give_equipment()
give_objective()
- ADD_TRAIT(owner, TRAIT_CANNOT_OPEN_PRESENTS, TRAIT_SANTA)
- ADD_TRAIT(owner, TRAIT_PRESENT_VISION, TRAIT_SANTA)
+ owner.add_traits(list(TRAIT_CANNOT_OPEN_PRESENTS, TRAIT_PRESENT_VISION), TRAIT_SANTA)
/datum/antagonist/santa/greet()
. = ..()
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index ae6acc64ea0..16373e02ac7 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -188,8 +188,7 @@
to_chat(current_owner, span_notice("Your otherworldly vision fades..."))
- REMOVE_TRAIT(current_owner, TRAIT_SIXTHSENSE, SCRYING_ORB)
- REMOVE_TRAIT(current_owner, TRAIT_XRAY_VISION, SCRYING_ORB)
+ current_owner.remove_traits(list(TRAIT_SIXTHSENSE, TRAIT_XRAY_VISION), SCRYING_ORB)
current_owner.update_sight()
current_owner = null
@@ -199,8 +198,7 @@
to_chat(current_owner, span_notice("You can see...everything!"))
- ADD_TRAIT(current_owner, TRAIT_SIXTHSENSE, SCRYING_ORB)
- ADD_TRAIT(current_owner, TRAIT_XRAY_VISION, SCRYING_ORB)
+ current_owner.add_traits(list(TRAIT_SIXTHSENSE, TRAIT_XRAY_VISION), SCRYING_ORB)
current_owner.update_sight()
/obj/item/scrying/attack_self(mob/user)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index 279c639b219..7319717b533 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -40,8 +40,7 @@
if(occupant)
vis_contents -= occupant
occupant.vis_flags &= ~VIS_INHERIT_PLANE
- REMOVE_TRAIT(occupant, TRAIT_IMMOBILIZED, CRYO_TRAIT)
- REMOVE_TRAIT(occupant, TRAIT_FORCED_STANDING, CRYO_TRAIT)
+ occupant.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FORCED_STANDING), CRYO_TRAIT)
occupant = new_occupant
if(!occupant)
@@ -52,9 +51,8 @@
occupant.vis_flags |= VIS_INHERIT_PLANE
vis_contents += occupant
pixel_y = 22
- ADD_TRAIT(occupant, TRAIT_IMMOBILIZED, CRYO_TRAIT)
// Keep them standing! They'll go sideways in the tube when they fall asleep otherwise.
- ADD_TRAIT(occupant, TRAIT_FORCED_STANDING, CRYO_TRAIT)
+ occupant.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_FORCED_STANDING), CRYO_TRAIT)
/// COMSIG_CRYO_SET_ON callback
/atom/movable/visual/cryo_occupant/proc/on_set_on(datum/source, on)
diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm
index b7f00ba3144..99a64640021 100644
--- a/code/modules/capture_the_flag/ctf_game.dm
+++ b/code/modules/capture_the_flag/ctf_game.dm
@@ -430,8 +430,7 @@
M.faction += team
M.equipOutfit(chosen_class)
RegisterSignal(M, COMSIG_PARENT_QDELETING, PROC_REF(ctf_qdelled_player)) //just in case CTF has some map hazards (read: chasms). bit shorter than dust
- for(var/trait in player_traits)
- ADD_TRAIT(M, trait, CAPTURE_THE_FLAG_TRAIT)
+ M.add_traits(player_traits, CAPTURE_THE_FLAG_TRAIT)
spawned_mobs[M] = chosen_class
return M //used in medisim.dm
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 570bf7efcdb..c43e2475626 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -591,16 +591,13 @@
for(var/hud in hudlist)
var/datum/atom_hud/our_hud = GLOB.huds[hud]
our_hud.show_to(user)
- ADD_TRAIT(user, TRAIT_MEDICAL_HUD, GLASSES_TRAIT)
- ADD_TRAIT(user, TRAIT_SECURITY_HUD, GLASSES_TRAIT)
+ user.add_traits(list(TRAIT_MEDICAL_HUD, TRAIT_SECURITY_HUD), GLASSES_TRAIT)
if(xray)
ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
/obj/item/clothing/glasses/debug/dropped(mob/user)
. = ..()
- REMOVE_TRAIT(user, TRAIT_MEDICAL_HUD, GLASSES_TRAIT)
- REMOVE_TRAIT(user, TRAIT_SECURITY_HUD, GLASSES_TRAIT)
- REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
+ user.remove_traits(list(TRAIT_MEDICAL_HUD, TRAIT_SECURITY_HUD, TRAIT_XRAY_VISION), GLASSES_TRAIT)
if(ishuman(user))
for(var/hud in hudlist)
var/datum/atom_hud/our_hud = GLOB.huds[hud]
diff --git a/code/modules/hallucination/fake_death.dm b/code/modules/hallucination/fake_death.dm
index 369fbf6eeeb..9492f2f2ebc 100644
--- a/code/modules/hallucination/fake_death.dm
+++ b/code/modules/hallucination/fake_death.dm
@@ -14,8 +14,7 @@
/datum/hallucination/death/start()
hallucinator.Paralyze(30 SECONDS)
hallucinator.apply_status_effect(/datum/status_effect/grouped/screwy_hud/fake_dead, REF(src))
- ADD_TRAIT(hallucinator, TRAIT_MUTE, REF(src))
- ADD_TRAIT(hallucinator, TRAIT_EMOTEMUTE, REF(src))
+ hallucinator.add_traits(list(TRAIT_MUTE, TRAIT_EMOTEMUTE), REF(src))
to_chat(hallucinator, span_deadsay("[hallucinator.real_name] has died at [get_area_name(hallucinator)]."))
@@ -74,8 +73,7 @@
if(!QDELETED(hallucinator))
hallucinator.remove_status_effect(/datum/status_effect/grouped/screwy_hud/fake_dead, REF(src))
hallucinator.SetParalyzed(0 SECONDS)
- REMOVE_TRAIT(hallucinator, TRAIT_MUTE, REF(src))
- REMOVE_TRAIT(hallucinator, TRAIT_EMOTEMUTE, REF(src))
+ hallucinator.remove_traits(list(TRAIT_MUTE, TRAIT_EMOTEMUTE), REF(src))
if(!QDELETED(src))
qdel(src)
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index fedcd97df0e..8dc12f4916d 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -156,13 +156,12 @@
/datum/job/proc/after_spawn(mob/living/spawned, client/player_client)
SHOULD_CALL_PARENT(TRUE)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_JOB_AFTER_SPAWN, src, spawned, player_client)
- for(var/trait in mind_traits)
- ADD_TRAIT(spawned.mind, trait, JOB_TRAIT)
+ if(length(mind_traits))
+ spawned.mind.add_traits(mind_traits, JOB_TRAIT)
var/obj/item/organ/internal/liver/liver = spawned.getorganslot(ORGAN_SLOT_LIVER)
- if(liver)
- for(var/trait in liver_traits)
- ADD_TRAIT(liver, trait, JOB_TRAIT)
+ if(liver && length(liver_traits))
+ liver.add_traits(liver_traits, JOB_TRAIT)
if(!ishuman(spawned))
return
diff --git a/code/modules/library/skill_learning/skillchip.dm b/code/modules/library/skill_learning/skillchip.dm
index a096ff4904f..9c39651c0d9 100644
--- a/code/modules/library/skill_learning/skillchip.dm
+++ b/code/modules/library/skill_learning/skillchip.dm
@@ -149,8 +149,8 @@
if(!silent && activate_message)
to_chat(user, activate_message)
- for(var/trait in auto_traits)
- ADD_TRAIT(user, trait, SKILLCHIP_TRAIT)
+ if(length(auto_traits))
+ user.add_traits(auto_traits, SKILLCHIP_TRAIT)
active = TRUE
@@ -183,8 +183,8 @@
if(!silent && deactivate_message)
to_chat(user, deactivate_message)
- for(var/trait in auto_traits)
- REMOVE_TRAIT(user, trait, SKILLCHIP_TRAIT)
+ if(length(auto_traits))
+ user.remove_traits(auto_traits, SKILLCHIP_TRAIT)
active = FALSE
diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm
index 1866a6dec1c..3d696b50e4b 100644
--- a/code/modules/mafia/controller.dm
+++ b/code/modules/mafia/controller.dm
@@ -576,9 +576,7 @@
for(var/datum/mafia_role/role in all_roles)
var/mob/living/carbon/human/H = new(get_turf(role.assigned_landmark))
- ADD_TRAIT(H, TRAIT_NOFIRE, MAFIA_TRAIT)
- ADD_TRAIT(H, TRAIT_NOBREATH, MAFIA_TRAIT)
- ADD_TRAIT(H, TRAIT_CANNOT_CRYSTALIZE, MAFIA_TRAIT)
+ H.add_traits(list(TRAIT_NOFIRE, TRAIT_NOBREATH, TRAIT_CANNOT_CRYSTALIZE), MAFIA_TRAIT)
H.equipOutfit(outfit_to_distribute)
H.status_flags |= GODMODE
RegisterSignal(H,COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(display_votes))
diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm
index 6c85031517e..91d653cc6d5 100644
--- a/code/modules/mining/lavaland/tendril_loot.dm
+++ b/code/modules/mining/lavaland/tendril_loot.dm
@@ -166,9 +166,7 @@
to_chat(user, span_warning("You feel your life being drained by the pendant..."))
if(do_after(user, 40, target = user))
to_chat(user, span_notice("Your lifeforce is now linked to the pendant! You feel like removing it would kill you, and yet you instinctively know that until then, you won't die."))
- ADD_TRAIT(user, TRAIT_NODEATH, CLOTHING_TRAIT)
- ADD_TRAIT(user, TRAIT_NOHARDCRIT, CLOTHING_TRAIT)
- ADD_TRAIT(user, TRAIT_NOCRITDAMAGE, CLOTHING_TRAIT)
+ user.add_traits(list(TRAIT_NODEATH, TRAIT_NOHARDCRIT, TRAIT_NOCRITDAMAGE), CLOTHING_TRAIT)
RegisterSignal(user, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(check_health))
icon_state = "memento_mori_active"
active_owner = user
diff --git a/code/modules/mob/living/basic/lavaland/mining.dm b/code/modules/mob/living/basic/lavaland/mining.dm
index 50c896012ec..91680eeb059 100644
--- a/code/modules/mob/living/basic/lavaland/mining.dm
+++ b/code/modules/mob/living/basic/lavaland/mining.dm
@@ -9,6 +9,5 @@
/mob/living/basic/mining/Initialize(mapload)
. = ..()
- ADD_TRAIT(src, TRAIT_LAVA_IMMUNE, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, INNATE_TRAIT)
+ add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), INNATE_TRAIT)
AddElement(/datum/element/mob_killed_tally, "mobs_killed_mining")
diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm
index bc6f00171df..b297a89e9de 100644
--- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm
+++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm
@@ -86,9 +86,7 @@
/mob/living/basic/carp/Initialize(mapload, mob/tamer)
. = ..()
apply_colour()
- ADD_TRAIT(src, TRAIT_HEALS_FROM_CARP_RIFTS, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_FREE_HYPERSPACE_MOVEMENT, INNATE_TRAIT)
+ add_traits(list(TRAIT_HEALS_FROM_CARP_RIFTS, TRAIT_SPACEWALK, TRAIT_FREE_HYPERSPACE_MOVEMENT), INNATE_TRAIT)
if (cell_line)
AddElement(/datum/element/swabable, cell_line, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
diff --git a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm
index 30fbe0956f7..f6a9f5a685a 100644
--- a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm
+++ b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm
@@ -109,8 +109,7 @@
AddComponent(/datum/component/swarming)
AddComponent(/datum/component/ground_sinking, target_icon_state = icon_state, outline_colour = chosen_hat_colour, damage_res_sinked = resistance_when_sinked)
AddComponent(/datum/component/caltrop, min_damage = 5, max_damage = 10, paralyze_duration = 1 SECONDS, flags = CALTROP_BYPASS_SHOES)
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ add_traits(list(TRAIT_SPACEWALK, TRAIT_VENTCRAWLER_ALWAYS), INNATE_TRAIT)
/mob/living/basic/garden_gnome/proc/apply_colour()
if(!greyscale_config)
diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm
index 2abc8bea6cc..e25c7a38643 100644
--- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm
+++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm
@@ -50,8 +50,7 @@
/mob/living/basic/wumborian_fugu/Initialize(mapload)
. = ..()
AddElement(/datum/element/death_drops, loot = list(/obj/item/fugu_gland))
- ADD_TRAIT(src, TRAIT_LAVA_IMMUNE, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, ROUNDSTART_TRAIT)
+ add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), ROUNDSTART_TRAIT)
expand = new(src)
expand.Grant(src)
ai_controller.blackboard[BB_FUGU_INFLATE] = WEAKREF(expand)
diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm
index a1956aa9f64..c72821b81bc 100644
--- a/code/modules/mob/living/brain/MMI.dm
+++ b/code/modules/mob/living/brain/MMI.dm
@@ -179,15 +179,12 @@
brainmob = new_brainmob
if(new_brainmob)
if(mecha)
- REMOVE_TRAIT(new_brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED)
- REMOVE_TRAIT(new_brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED)
+ new_brainmob.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), BRAIN_UNAIDED)
else
- ADD_TRAIT(new_brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED)
- ADD_TRAIT(new_brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED)
+ new_brainmob.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), BRAIN_UNAIDED)
if(.)
var/mob/living/brain/old_brainmob = .
- ADD_TRAIT(old_brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED)
- ADD_TRAIT(old_brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED)
+ old_brainmob.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), BRAIN_UNAIDED)
/// Proc to hook behavior associated to the change in value of the [obj/vehicle/sealed/var/mecha] variable.
@@ -198,11 +195,9 @@
mecha = new_mecha
if(new_mecha)
if(!. && brainmob) // There was no mecha, there now is, and we have a brain mob that is no longer unaided.
- REMOVE_TRAIT(brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED)
- REMOVE_TRAIT(brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED)
+ brainmob.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), BRAIN_UNAIDED)
else if(. && brainmob) // There was a mecha, there no longer is one, and there is a brain mob that is now again unaided.
- ADD_TRAIT(brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED)
- ADD_TRAIT(brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED)
+ brainmob.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), BRAIN_UNAIDED)
/obj/item/mmi/proc/replacement_ai_name()
diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm
index 866496fb29e..f45e0c6c42e 100644
--- a/code/modules/mob/living/brain/brain.dm
+++ b/code/modules/mob/living/brain/brain.dm
@@ -16,8 +16,7 @@
OB.brainmob = src
forceMove(OB)
if(!container?.mecha) //Unless inside a mecha, brains are rather helpless.
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, BRAIN_UNAIDED)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED)
+ add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), BRAIN_UNAIDED)
/mob/living/brain/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 4ab682b38dd..2ec16fb4fbd 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -29,8 +29,7 @@
create_internal_organs()
- ADD_TRAIT(src, TRAIT_NEVER_WOUNDED, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ add_traits(list(TRAIT_NEVER_WOUNDED, TRAIT_VENTCRAWLER_ALWAYS), INNATE_TRAIT)
. = ..()
diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
index 7970b230ffa..80586887814 100644
--- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
+++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
@@ -111,8 +111,7 @@
var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
new_xeno.key = ghost.key
SEND_SOUND(new_xeno, sound('sound/voice/hiss5.ogg',0,0,0,100)) //To get the player's attention
- ADD_TRAIT(new_xeno, TRAIT_IMMOBILIZED, type) //so we don't move during the bursting animation
- ADD_TRAIT(new_xeno, TRAIT_HANDS_BLOCKED, type)
+ new_xeno.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), type) //so we don't move during the bursting animation
new_xeno.notransform = 1
new_xeno.invisibility = INVISIBILITY_MAXIMUM
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index e71d6a98e37..b54559333c7 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -48,8 +48,7 @@
. = ..()
if(movement_type & (FLYING | FLOATING) && !(old_movement_type & (FLYING | FLOATING)))
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
- REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
- REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
+ remove_traits(list(TRAIT_FLOORED, TRAIT_IMMOBILIZED), LACKING_LOCOMOTION_APPENDAGES_TRAIT)
/mob/living/carbon/on_movement_type_flag_disabled(datum/source, flag, old_movement_type)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index a248403b94e..dabf04a2dbf 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -478,8 +478,8 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path)
new_organ.Insert(human, special=TRUE, drop_if_replaced=FALSE)
- for(var/X in inherent_traits)
- ADD_TRAIT(C, X, SPECIES_TRAIT)
+ if(length(inherent_traits))
+ C.add_traits(inherent_traits, SPECIES_TRAIT)
if(TRAIT_VIRUSIMMUNE in inherent_traits)
for(var/datum/disease/A in C.diseases)
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 fd66833d34e..65252ee2bf6 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -283,13 +283,11 @@
/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
- ADD_TRAIT(C, TRAIT_LAVA_IMMUNE, SPECIES_TRAIT)
- ADD_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)
+ C.add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), SPECIES_TRAIT)
/datum/species/golem/plastitanium/on_species_loss(mob/living/carbon/C)
. = ..()
- REMOVE_TRAIT(C, TRAIT_LAVA_IMMUNE, SPECIES_TRAIT)
- REMOVE_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)
+ C.remove_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), SPECIES_TRAIT)
//Fast and regenerates... but can only speak like an abductor
/datum/species/golem/alloy
diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm
index de35eb8872b..411ded8c4d4 100644
--- a/code/modules/mob/living/carbon/status_procs.dm
+++ b/code/modules/mob/living/carbon/status_procs.dm
@@ -13,11 +13,8 @@
if(absorb_stun(0)) //continuous effect, so we don't want it to increment the stuns absorbed.
return
to_chat(src, span_notice("You're too exhausted to keep going..."))
- ADD_TRAIT(src, TRAIT_INCAPACITATED, STAMINA)
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, STAMINA)
- ADD_TRAIT(src, TRAIT_FLOORED, STAMINA)
- filters += FILTER_STAMINACRIT
- if(getStaminaLoss() < 162) // Puts you a little further into the initial stamcrit, makes stamcrit harder to outright counter with chems. // SKYRAT EDIT: ORIGINAL if(getStaminaLoss() < 120 * 1.35)
+ add_traits(list(TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED), STAMINA)
+ if(getStaminaLoss() < 162) // Puts you a little further into the initial stamcrit, makes stamcrit harder to outright counter with chems. //SKYRAT EDIT CHANGE
adjustStaminaLoss(30, FALSE)
/mob/living/carbon/adjust_disgust(amount)
diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm
index 3fdd1a2059c..4ed321a6b54 100644
--- a/code/modules/mob/living/init_signals.dm
+++ b/code/modules/mob/living/init_signals.dm
@@ -160,15 +160,13 @@
/// Called when [TRAIT_INCAPACITATED] is added to the mob.
/mob/living/proc/on_incapacitated_trait_gain(datum/source)
SIGNAL_HANDLER
- ADD_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_INCAPACITATED)
- ADD_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_INCAPACITATED)
+ add_traits(list(TRAIT_UI_BLOCKED, TRAIT_PULL_BLOCKED), TRAIT_INCAPACITATED)
update_appearance()
/// Called when [TRAIT_INCAPACITATED] is removed from the mob.
/mob/living/proc/on_incapacitated_trait_loss(datum/source)
SIGNAL_HANDLER
- REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_INCAPACITATED)
- REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_INCAPACITATED)
+ remove_traits(list(TRAIT_UI_BLOCKED, TRAIT_PULL_BLOCKED), TRAIT_INCAPACITATED)
update_appearance()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index d4c5d31646e..e977f2952ca 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -669,8 +669,7 @@
/mob/living/proc/on_lying_down(new_lying_angle)
if(layer == initial(layer)) //to avoid things like hiding larvas.
layer = LYING_MOB_LAYER //so mob lying always appear behind standing mobs
- ADD_TRAIT(src, TRAIT_UI_BLOCKED, LYING_DOWN_TRAIT)
- ADD_TRAIT(src, TRAIT_PULL_BLOCKED, LYING_DOWN_TRAIT)
+ add_traits(list(TRAIT_UI_BLOCKED, TRAIT_PULL_BLOCKED), LYING_DOWN_TRAIT)
set_density(FALSE) // We lose density and stop bumping passable dense things.
if(HAS_TRAIT(src, TRAIT_FLOORED) && !(dir & (NORTH|SOUTH)))
setDir(pick(NORTH, SOUTH)) // We are and look helpless.
@@ -682,12 +681,9 @@
if(layer == LYING_MOB_LAYER)
layer = initial(layer)
set_density(initial(density)) // We were prone before, so we become dense and things can bump into us again.
- REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, LYING_DOWN_TRAIT)
- REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, LYING_DOWN_TRAIT)
+ remove_traits(list(TRAIT_UI_BLOCKED, TRAIT_PULL_BLOCKED), LYING_DOWN_TRAIT)
body_position_pixel_y_offset = 0
-
-
//Recursive function to find everything a mob is holding. Really shitty proc tbh.
/mob/living/get_contents()
var/list/ret = list()
@@ -1349,8 +1345,7 @@
return
notransform = TRUE
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, MAGIC_TRAIT)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, MAGIC_TRAIT)
+ add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), MAGIC_TRAIT)
icon = null
cut_overlays()
invisibility = INVISIBILITY_ABSTRACT
@@ -2111,9 +2106,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
if(CONSCIOUS)
if(stat >= UNCONSCIOUS)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT)
- ADD_TRAIT(src, TRAIT_INCAPACITATED, STAT_TRAIT)
- ADD_TRAIT(src, TRAIT_FLOORED, STAT_TRAIT)
+ add_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_INCAPACITATED, TRAIT_FLOORED), STAT_TRAIT)
if(SOFT_CRIT)
if(stat >= UNCONSCIOUS)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) //adding trait sources should come before removing to avoid unnecessary updates
@@ -2132,10 +2125,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
if(CONSCIOUS)
if(. >= UNCONSCIOUS)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
- REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT)
- REMOVE_TRAIT(src, TRAIT_INCAPACITATED, STAT_TRAIT)
- REMOVE_TRAIT(src, TRAIT_FLOORED, STAT_TRAIT)
- REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
+ remove_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_INCAPACITATED, TRAIT_FLOORED), STAT_TRAIT)
if(SOFT_CRIT)
if(pulledby)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) //adding trait sources should come before removing to avoid unnecessary updates
@@ -2181,8 +2171,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
set_body_position(LYING_DOWN)
set_lying_angle(buckled.buckle_lying)
else
- REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT)
- REMOVE_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT)
+ remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), BUCKLED_TRAIT)
if(.) // We unbuckled from something.
var/atom/movable/old_buckled = .
if(old_buckled.buckle_lying == 0 && (resting || HAS_TRAIT(src, TRAIT_FLOORED))) // The buckle forced us to stay up (like a chair)
@@ -2341,14 +2330,12 @@ GLOBAL_LIST_EMPTY(fire_appearances)
/// Proc to append behavior to the condition of being handsblocked. Called when the condition starts.
/mob/living/proc/on_handsblocked_start()
drop_all_held_items()
- ADD_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_HANDS_BLOCKED)
- ADD_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED)
+ add_traits(list(TRAIT_UI_BLOCKED, TRAIT_PULL_BLOCKED), TRAIT_HANDS_BLOCKED)
/// Proc to append behavior to the condition of being handsblocked. Called when the condition ends.
/mob/living/proc/on_handsblocked_end()
- REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_HANDS_BLOCKED)
- REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED)
+ remove_traits(list(TRAIT_UI_BLOCKED, TRAIT_PULL_BLOCKED), TRAIT_HANDS_BLOCKED)
/// Returns the attack damage type of a living mob such as [BRUTE].
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 7d24cb2de8d..4d7aa771c94 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -192,8 +192,7 @@
builtInCamera = new (src)
builtInCamera.network = list("ss13")
- ADD_TRAIT(src, TRAIT_PULL_BLOCKED, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, ROUNDSTART_TRAIT)
+ add_traits(list(TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED), ROUNDSTART_TRAIT)
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z), camera_view = TRUE)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, PROC_REF(alarm_triggered))
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 0ea9af192f1..a7c958a601e 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -770,9 +770,8 @@
hands.icon_state = model.model_select_icon
REMOVE_TRAITS_IN(src, MODEL_TRAIT)
- if(model.model_traits)
- for(var/trait in model.model_traits)
- ADD_TRAIT(src, trait, MODEL_TRAIT)
+ if(length(model.model_traits))
+ add_traits(model.model_traits, MODEL_TRAIT)
hat_offset = model.hat_offset
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 4aed087fb6b..2a456e194a5 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -62,13 +62,17 @@
diag_hud_set_status()
diag_hud_set_health()
add_sensors()
- ADD_TRAIT(src, TRAIT_ADVANCEDTOOLUSER, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_LITERATE, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_NOFIRE_SPREAD, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_MADNESS_IMMUNE, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_MARTIAL_ARTS_IMMUNE, ROUNDSTART_TRAIT)
+ var/static/list/traits_to_apply = list(
+ TRAIT_ADVANCEDTOOLUSER,
+ TRAIT_ASHSTORM_IMMUNE,
+ TRAIT_LITERATE,
+ TRAIT_MADNESS_IMMUNE,
+ TRAIT_MARTIAL_ARTS_IMMUNE,
+ TRAIT_NOFIRE_SPREAD,
+ )
+
+ add_traits(traits_to_apply, ROUNDSTART_TRAIT)
/mob/living/silicon/Destroy()
QDEL_NULL(radio)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 8b7e7edea4b..efb8e53236a 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -133,9 +133,7 @@
if(stat)
return FALSE
bot_mode_flags |= BOT_MODE_ON
- REMOVE_TRAIT(src, TRAIT_INCAPACITATED, POWER_LACK_TRAIT)
- REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, POWER_LACK_TRAIT)
- REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, POWER_LACK_TRAIT)
+ remove_traits(list(TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), POWER_LACK_TRAIT)
set_light_on(bot_mode_flags & BOT_MODE_ON ? TRUE : FALSE)
update_appearance()
balloon_alert(src, "turned on")
@@ -144,9 +142,7 @@
/mob/living/simple_animal/bot/proc/turn_off()
bot_mode_flags &= ~BOT_MODE_ON
- ADD_TRAIT(src, TRAIT_INCAPACITATED, POWER_LACK_TRAIT)
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, POWER_LACK_TRAIT)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, POWER_LACK_TRAIT)
+ add_traits(list(TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), POWER_LACK_TRAIT)
set_light_on(bot_mode_flags & BOT_MODE_ON ? TRUE : FALSE)
bot_reset() //Resets an AI's call, should it exist.
balloon_alert(src, "turned off")
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index f669e1b0e6f..356b6b18cba 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -195,10 +195,7 @@
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_atom_to_hud(src)
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_NEGATES_GRAVITY, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_LITERATE, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_KNOW_ENGI_WIRES, INNATE_TRAIT)
+ add_traits(list(TRAIT_VENTCRAWLER_ALWAYS, TRAIT_NEGATES_GRAVITY, TRAIT_LITERATE, TRAIT_KNOW_ENGI_WIRES), INNATE_TRAIT)
listener = new(list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER), list(z))
RegisterSignal(listener, COMSIG_ALARM_LISTENER_TRIGGERED, PROC_REF(alarm_triggered))
diff --git a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm
index 7c75c78caf9..ff38ec6e601 100644
--- a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm
+++ b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm
@@ -23,9 +23,7 @@
/mob/living/simple_animal/robot_customer/Initialize(mapload, datum/customer_data/customer_data = /datum/customer_data/american, datum/venue/attending_venue = SSrestaurant.all_venues[/datum/venue/restaurant])
- ADD_TRAIT(src, TRAIT_NOMOBSWAP, INNATE_TRAIT) //dont push me bitch
- ADD_TRAIT(src, TRAIT_NO_TELEPORT, INNATE_TRAIT) //dont teleport me bitch
- ADD_TRAIT(src, TRAIT_STRONG_GRABBER, INNATE_TRAIT) //strong arms bitch
+ ADD_TRAIT(src, list(TRAIT_NOMOBSWAP, TRAIT_NO_TELEPORT, TRAIT_STRONG_GRABBER), INNATE_TRAIT) // never suffer a bitch to fuck with you
AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE)
var/datum/customer_data/customer_info = SSrestaurant.all_customers[customer_data]
clothes_set = pick(customer_info.clothing_sets)
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index fc6d5f30821..c842f66955e 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -62,8 +62,7 @@
/mob/living/simple_animal/hostile/bee/Initialize(mapload)
. = ..()
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ add_traits(list(TRAIT_SPACEWALK, TRAIT_VENTCRAWLER_ALWAYS), INNATE_TRAIT)
generate_bee_visuals()
AddElement(/datum/element/simple_flying)
AddComponent(/datum/component/clickbox, x_offset = -2, y_offset = -2)
diff --git a/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm b/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm
index 79d81a8b4d2..2449c2d3e20 100644
--- a/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm
@@ -53,8 +53,7 @@
/mob/living/simple_animal/hostile/construct/Initialize(mapload)
. = ..()
AddElement(/datum/element/simple_flying)
- ADD_TRAIT(src, TRAIT_HEALS_FROM_CULT_PYLONS, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
+ add_traits(list(TRAIT_HEALS_FROM_CULT_PYLONS, TRAIT_SPACEWALK), INNATE_TRAIT)
for(var/spell in construct_spells)
var/datum/action/new_spell = new spell(src)
new_spell.Grant(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm
index 68d2de73bc2..a433c43e4ac 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm
@@ -58,9 +58,8 @@
AddElement(/datum/element/simple_flying)
if(gps_name && true_spawn)
AddComponent(/datum/component/gps, gps_name)
- ADD_TRAIT(src, TRAIT_NO_TELEPORT, MEGAFAUNA_TRAIT)
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_MARTIAL_ARTS_IMMUNE, MEGAFAUNA_TRAIT)
+ add_traits(list(TRAIT_NO_TELEPORT, TRAIT_MARTIAL_ARTS_IMMUNE), MEGAFAUNA_TRAIT)
for(var/action_type in attack_action_types)
var/datum/action/innate/megafauna_attack/attack_action = new action_type()
attack_action.Grant(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
index ee3e7d85a0c..8928ef18ceb 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
@@ -35,5 +35,4 @@
/mob/living/simple_animal/hostile/retaliate/bat/Initialize(mapload)
. = ..()
AddElement(/datum/element/simple_flying)
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ add_traits(list(TRAIT_SPACEWALK, TRAIT_VENTCRAWLER_ALWAYS), INNATE_TRAIT)
diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
index f40bdbcdc89..8a385700e92 100644
--- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
@@ -85,10 +85,7 @@
/mob/living/simple_animal/hostile/space_dragon/Initialize(mapload)
. = ..()
AddElement(/datum/element/simple_flying)
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_FREE_HYPERSPACE_MOVEMENT, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_NO_FLOATING_ANIM, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_HEALS_FROM_CARP_RIFTS, INNATE_TRAIT)
+ add_traits(list(TRAIT_SPACEWALK, TRAIT_FREE_HYPERSPACE_MOVEMENT, TRAIT_NO_FLOATING_ANIM, TRAIT_HEALS_FROM_CARP_RIFTS), INNATE_TRAIT)
AddElement(/datum/element/content_barfer)
small_sprite = new
small_sprite.Grant(src)
diff --git a/code/modules/mob/living/simple_animal/revenant.dm b/code/modules/mob/living/simple_animal/revenant.dm
index 9b298fcde77..822a0ab2319 100644
--- a/code/modules/mob/living/simple_animal/revenant.dm
+++ b/code/modules/mob/living/simple_animal/revenant.dm
@@ -71,9 +71,7 @@
/mob/living/simple_animal/revenant/Initialize(mapload)
. = ..()
AddElement(/datum/element/simple_flying)
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_SIXTHSENSE, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_FREE_HYPERSPACE_MOVEMENT, INNATE_TRAIT)
+ add_traits(list(TRAIT_SPACEWALK, TRAIT_SIXTHSENSE, TRAIT_FREE_HYPERSPACE_MOVEMENT), INNATE_TRAIT)
// Starting spells
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
index a786aa82742..87e6f536cb6 100644
--- a/code/modules/mob/living/simple_animal/shade.dm
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -37,9 +37,7 @@
/mob/living/simple_animal/shade/Initialize(mapload)
. = ..()
AddElement(/datum/element/simple_flying)
- ADD_TRAIT(src, TRAIT_HEALS_FROM_CULT_PYLONS, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ add_traits(list(TRAIT_HEALS_FROM_CULT_PYLONS, TRAIT_SPACEWALK, TRAIT_VENTCRAWLER_ALWAYS), INNATE_TRAIT)
/mob/living/simple_animal/shade/death()
if(death_message == initial(death_message))
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 10dabd378eb..7e35aca237b 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -182,11 +182,10 @@
update_simplemob_varspeed()
if(dextrous)
AddComponent(/datum/component/personal_crafting)
- ADD_TRAIT(src, TRAIT_ADVANCEDTOOLUSER, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_CAN_STRIP, ROUNDSTART_TRAIT)
+ add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP), ROUNDSTART_TRAIT)
ADD_TRAIT(src, TRAIT_NOFIRE_SPREAD, ROUNDSTART_TRAIT)
- for(var/trait in weather_immunities)
- ADD_TRAIT(src, trait, ROUNDSTART_TRAIT)
+ if(length(weather_immunities))
+ add_traits(weather_immunities, ROUNDSTART_TRAIT)
if (environment_smash >= ENVIRONMENT_SMASH_WALLS)
AddElement(/datum/element/wall_smasher, strength_flag = environment_smash)
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index c61c5a21abc..08b64ff7be9 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -533,8 +533,7 @@
ADD_TRAIT(src, TRAIT_HUSK, source)
/mob/living/proc/cure_fakedeath(source)
- REMOVE_TRAIT(src, TRAIT_FAKEDEATH, source)
- REMOVE_TRAIT(src, TRAIT_DEATHCOMA, source)
+ remove_traits(list(TRAIT_FAKEDEATH, TRAIT_DEATHCOMA), source)
if(stat != DEAD)
tod = null
@@ -544,8 +543,7 @@
return
if(!silent)
emote("deathgasp")
- ADD_TRAIT(src, TRAIT_FAKEDEATH, source)
- ADD_TRAIT(src, TRAIT_DEATHCOMA, source)
+ add_traits(list(TRAIT_FAKEDEATH, TRAIT_DEATHCOMA), source)
tod = station_time_timestamp()
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index df45e2722ef..e9babd492bf 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -190,8 +190,7 @@
if (notransform)
return
notransform = TRUE
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_GENERIC)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_GENERIC)
+ add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_GENERIC)
for(var/obj/item/W in src)
dropItemToGround(W)
regenerate_icons()
@@ -222,8 +221,7 @@
if (notransform)
return
notransform = TRUE
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_GENERIC)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_GENERIC)
+ add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_GENERIC)
for(var/obj/item/W in src)
dropItemToGround(W)
regenerate_icons()
diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm
index a1c6b39cac7..c7221c100f3 100644
--- a/code/modules/mod/modules/modules_antag.dm
+++ b/code/modules/mod/modules/modules_antag.dm
@@ -163,12 +163,10 @@
incompatible_modules = list(/obj/item/mod/module/anti_magic)
/obj/item/mod/module/anti_magic/on_suit_activation()
- ADD_TRAIT(mod.wearer, TRAIT_ANTIMAGIC, MOD_TRAIT)
- ADD_TRAIT(mod.wearer, TRAIT_HOLY, MOD_TRAIT)
+ mod.wearer.add_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), MOD_TRAIT)
/obj/item/mod/module/anti_magic/on_suit_deactivation(deleting = FALSE)
- REMOVE_TRAIT(mod.wearer, TRAIT_ANTIMAGIC, MOD_TRAIT)
- REMOVE_TRAIT(mod.wearer, TRAIT_HOLY, MOD_TRAIT)
+ mod.wearer.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), MOD_TRAIT)
/obj/item/mod/module/anti_magic/wizard
name = "MOD magic neutralizer module"
@@ -179,12 +177,10 @@
icon_state = "magic_neutralizer"
/obj/item/mod/module/anti_magic/wizard/on_suit_activation()
- ADD_TRAIT(mod.wearer, TRAIT_ANTIMAGIC, MOD_TRAIT)
- ADD_TRAIT(mod.wearer, TRAIT_ANTIMAGIC_NO_SELFBLOCK, MOD_TRAIT)
+ mod.wearer.add_traits(list(TRAIT_ANTIMAGIC, TRAIT_ANTIMAGIC_NO_SELFBLOCK), MOD_TRAIT)
/obj/item/mod/module/anti_magic/wizard/on_suit_deactivation(deleting = FALSE)
- REMOVE_TRAIT(mod.wearer, TRAIT_ANTIMAGIC, MOD_TRAIT)
- REMOVE_TRAIT(mod.wearer, TRAIT_ANTIMAGIC_NO_SELFBLOCK, MOD_TRAIT)
+ mod.wearer.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_ANTIMAGIC_NO_SELFBLOCK), MOD_TRAIT)
///Insignia - Gives you a skin specific stripe.
/obj/item/mod/module/insignia
@@ -490,13 +486,11 @@
mod.item_flags &= ~EXAMINE_SKIP
/obj/item/mod/module/infiltrator/on_suit_activation()
- ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT)
- ADD_TRAIT(mod.wearer, TRAIT_UNKNOWN, MOD_TRAIT)
+ mod.wearer.add_traits(list(TRAIT_SILENT_FOOTSTEPS, TRAIT_UNKNOWN), MOD_TRAIT)
mod.helmet.flash_protect = FLASH_PROTECTION_WELDER
/obj/item/mod/module/infiltrator/on_suit_deactivation(deleting = FALSE)
- REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT)
- REMOVE_TRAIT(mod.wearer, TRAIT_UNKNOWN, MOD_TRAIT)
+ mod.wearer.remove_traits(list(TRAIT_SILENT_FOOTSTEPS, TRAIT_UNKNOWN), MOD_TRAIT)
if(deleting)
return
mod.helmet.flash_protect = initial(mod.helmet.flash_protect)
diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm
index 5fbf6747581..718b5575fe8 100644
--- a/code/modules/mod/modules/modules_engineering.dm
+++ b/code/modules/mod/modules/modules_engineering.dm
@@ -59,8 +59,7 @@
. = ..()
if(!.)
return
- for(var/new_trait in active_traits)
- ADD_TRAIT(mod.wearer, new_trait, MOD_TRAIT)
+ mod.wearer.add_traits(active_traits, MOD_TRAIT)
mod.slowdown += slowdown_active
mod.wearer.update_equipment_speed_mods()
@@ -68,8 +67,7 @@
. = ..()
if(!.)
return
- for(var/old_trait in active_traits)
- REMOVE_TRAIT(mod.wearer, old_trait, MOD_TRAIT)
+ mod.wearer.remove_traits(active_traits, MOD_TRAIT)
mod.slowdown -= slowdown_active
mod.wearer.update_equipment_speed_mods()
diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm
index 946f49e9c5d..3da8e0aebc5 100644
--- a/code/modules/mod/modules/modules_supply.dm
+++ b/code/modules/mod/modules/modules_supply.dm
@@ -82,7 +82,7 @@
else
balloon_alert(mod.wearer, "invalid target!")
-/obj/item/mod/module/clamp/on_suit_deactivation(deleting = FALSE)
+/obj/item/mod/module/clamp/on_suit_deactivation(deleting = FALSE) //SKYRAT EDIT
if(deleting)
return
for(var/atom/movable/crate as anything in stored_crates)
@@ -227,12 +227,6 @@
/// User overlay
var/mutable_appearance/lightning
-/obj/item/mod/module/hydraulic/on_suit_activation()
- ADD_TRAIT(mod.wearer, TRAIT_TRASHMAN, MOD_TRAIT)
-
-/obj/item/mod/module/hydraulic/on_suit_deactivation(deleting = FALSE) //SKYRAT EDIT
- REMOVE_TRAIT(mod.wearer, TRAIT_TRASHMAN, MOD_TRAIT)
-
/obj/item/mod/module/hydraulic/on_select_use(atom/target)
. = ..()
if(!.)
@@ -415,13 +409,11 @@
))
/obj/item/mod/module/ash_accretion/on_suit_activation()
- ADD_TRAIT(mod.wearer, TRAIT_ASHSTORM_IMMUNE, MOD_TRAIT)
- ADD_TRAIT(mod.wearer, TRAIT_SNOWSTORM_IMMUNE, MOD_TRAIT)
+ mod.wearer.add_traits(list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), MOD_TRAIT)
RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
/obj/item/mod/module/ash_accretion/on_suit_deactivation(deleting = FALSE)
- REMOVE_TRAIT(mod.wearer, TRAIT_ASHSTORM_IMMUNE, MOD_TRAIT)
- REMOVE_TRAIT(mod.wearer, TRAIT_SNOWSTORM_IMMUNE, MOD_TRAIT)
+ mod.wearer.remove_traits(list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), MOD_TRAIT)
UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED)
if(!traveled_tiles)
return
@@ -486,6 +478,13 @@
cooldown_time = 1.25 SECONDS
/// Time it takes us to complete the animation.
var/animate_time = 0.25 SECONDS
+ /// List of traits to add/remove from our subject as needed.
+ var/static/list/user_traits = list(
+ TRAIT_FORCED_STANDING,
+ TRAIT_HANDS_BLOCKED,
+ TRAIT_LAVA_IMMUNE,
+ TRAIT_NO_SLIP_ALL,
+ )
/obj/item/mod/module/sphere_transform/on_activation()
if(!mod.wearer.has_gravity())
@@ -501,10 +500,7 @@
mod.wearer.base_pixel_y -= 4
animate(mod.wearer, animate_time, pixel_y = mod.wearer.base_pixel_y, flags = ANIMATION_PARALLEL)
mod.wearer.SpinAnimation(1.5)
- ADD_TRAIT(mod.wearer, TRAIT_LAVA_IMMUNE, MOD_TRAIT)
- ADD_TRAIT(mod.wearer, TRAIT_HANDS_BLOCKED, MOD_TRAIT)
- ADD_TRAIT(mod.wearer, TRAIT_FORCED_STANDING, MOD_TRAIT)
- ADD_TRAIT(mod.wearer, TRAIT_NO_SLIP_ALL, MOD_TRAIT)
+ mod.wearer.add_traits(user_traits, MOD_TRAIT)
mod.wearer.RemoveElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6)
mod.wearer.AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE)
mod.wearer.add_movespeed_modifier(/datum/movespeed_modifier/sphere)
@@ -516,13 +512,10 @@
return
if(!deleting)
playsound(src, 'sound/items/modsuit/ballin.ogg', 100, TRUE, frequency = -1)
- mod.wearer.base_pixel_y = 0
+ mod.wearer.base_pixel_y += 4
animate(mod.wearer, animate_time, pixel_y = mod.wearer.base_pixel_y)
addtimer(CALLBACK(mod.wearer, TYPE_PROC_REF(/datum, remove_filter), list("mod_ball", "mod_blur", "mod_outline")), animate_time)
- REMOVE_TRAIT(mod.wearer, TRAIT_LAVA_IMMUNE, MOD_TRAIT)
- REMOVE_TRAIT(mod.wearer, TRAIT_HANDS_BLOCKED, MOD_TRAIT)
- REMOVE_TRAIT(mod.wearer, TRAIT_FORCED_STANDING, MOD_TRAIT)
- REMOVE_TRAIT(mod.wearer, TRAIT_NO_SLIP_ALL, MOD_TRAIT)
+ mod.wearer.remove_traits(user_traits, MOD_TRAIT)
mod.wearer.remove_movespeed_mod_immunities(MOD_TRAIT, /datum/movespeed_modifier/damage_slowdown)
mod.wearer.RemoveElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE)
mod.wearer.AddElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6)
diff --git a/code/modules/mod/modules/modules_visor.dm b/code/modules/mod/modules/modules_visor.dm
index e447bfa1354..33ee50a7ed0 100644
--- a/code/modules/mod/modules/modules_visor.dm
+++ b/code/modules/mod/modules/modules_visor.dm
@@ -21,8 +21,8 @@
if(hud_type)
var/datum/atom_hud/hud = GLOB.huds[hud_type]
hud.show_to(mod.wearer)
- for(var/trait in visor_traits)
- ADD_TRAIT(mod.wearer, trait, MOD_TRAIT)
+ if(length(visor_traits))
+ mod.wearer.add_traits(visor_traits, MOD_TRAIT)
mod.wearer.update_sight()
/obj/item/mod/module/visor/on_deactivation(display_message = TRUE, deleting = FALSE)
@@ -32,8 +32,8 @@
if(hud_type)
var/datum/atom_hud/hud = GLOB.huds[hud_type]
hud.hide_from(mod.wearer)
- for(var/trait in visor_traits)
- REMOVE_TRAIT(mod.wearer, trait, MOD_TRAIT)
+ if(length(visor_traits))
+ mod.wearer.remove_traits(visor_traits, MOD_TRAIT)
mod.wearer.update_sight()
//Medical Visor - Gives you a medical HUD.
diff --git a/code/modules/modular_computers/computers/item/disks/virus_disk.dm b/code/modules/modular_computers/computers/item/disks/virus_disk.dm
index f6e643cdc8d..d566c1f6f44 100644
--- a/code/modules/modular_computers/computers/item/disks/virus_disk.dm
+++ b/code/modules/modular_computers/computers/item/disks/virus_disk.dm
@@ -89,8 +89,7 @@
charges--
user.show_message(span_notice("Success!"))
var/reference = REF(src)
- ADD_TRAIT(target, TRAIT_PDA_CAN_EXPLODE, reference)
- ADD_TRAIT(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference)
+ target.add_traits(list(TRAIT_PDA_CAN_EXPLODE, TRAIT_PDA_MESSAGE_MENU_RIGGED), reference)
addtimer(TRAIT_CALLBACK_REMOVE(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference), 10 SECONDS)
return TRUE
diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm
index 97de72da257..acb1fba2a40 100644
--- a/code/modules/pai/pai.dm
+++ b/code/modules/pai/pai.dm
@@ -221,8 +221,7 @@
card = pai_card
addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_INIT_TIME)
if(!holoform)
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, PAI_FOLDED)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, PAI_FOLDED)
+ add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), PAI_FOLDED)
desc = "A pAI hard-light holographics emitter. This one appears in the form of a [chassis]."
RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(on_cult_sacrificed))
diff --git a/code/modules/pai/shell.dm b/code/modules/pai/shell.dm
index e1f685a2d05..711e19ead51 100644
--- a/code/modules/pai/shell.dm
+++ b/code/modules/pai/shell.dm
@@ -92,8 +92,7 @@
var/turf/target = drop_location()
card.forceMove(target)
forceMove(card)
- ADD_TRAIT(src, TRAIT_IMMOBILIZED, PAI_FOLDED)
- ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, PAI_FOLDED)
+ add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), PAI_FOLDED)
set_density(FALSE)
set_light_on(FALSE)
holoform = FALSE
diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
index ce3acc6ec96..6e584a596af 100644
--- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
@@ -511,14 +511,23 @@
inverse_chem = /datum/reagent/inverse/penthrite
inverse_chem_val = 0.25
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ /// List of traits to add/remove from our subject when we are in their system
+ var/static/list/subject_traits = list(
+ TRAIT_STABLEHEART,
+ TRAIT_NOHARDCRIT,
+ TRAIT_NOSOFTCRIT,
+ TRAIT_NOCRITDAMAGE,
+ )
+
+/atom/movable/screen/alert/penthrite
+ name = "Strong Heartbeat"
+ desc = "Your heart beats with great force!"
+ icon_state = "penthrite"
/datum/reagent/medicine/c2/penthrite/on_mob_metabolize(mob/living/user)
. = ..()
- user.balloon_alert(user, "your heart beats with a great force")
- ADD_TRAIT(user, TRAIT_STABLEHEART, type)
- ADD_TRAIT(user, TRAIT_NOHARDCRIT,type)
- ADD_TRAIT(user, TRAIT_NOSOFTCRIT,type)
- ADD_TRAIT(user, TRAIT_NOCRITDAMAGE,type)
+ user.throw_alert("penthrite", /atom/movable/screen/alert/penthrite)
+ user.add_traits(subject_traits, type)
/datum/reagent/medicine/c2/penthrite/on_mob_life(mob/living/carbon/human/H, delta_time, times_fired)
H.adjustStaminaLoss(-25 * REM) //SKYRAT EDIT ADDITION - COMBAT - makes your heart beat faster, fills you with energy. For miners
@@ -549,11 +558,8 @@
. = ..()
/datum/reagent/medicine/c2/penthrite/on_mob_end_metabolize(mob/living/user)
- user.balloon_alert(user, "your heart relaxes")
- REMOVE_TRAIT(user, TRAIT_STABLEHEART, type)
- REMOVE_TRAIT(user, TRAIT_NOHARDCRIT,type)
- REMOVE_TRAIT(user, TRAIT_NOSOFTCRIT,type)
- REMOVE_TRAIT(user, TRAIT_NOCRITDAMAGE,type)
+ user.clear_alert("penthrite")
+ user.remove_traits(subject_traits, type)
. = ..()
/datum/reagent/medicine/c2/penthrite/overdose_process(mob/living/carbon/human/H, delta_time, times_fired)
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 72a314feb75..9344ba73897 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -216,16 +216,14 @@
/datum/reagent/drug/bath_salts/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_STUNIMMUNE, type)
- ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, type)
+ L.add_traits(list(TRAIT_STUNIMMUNE, TRAIT_SLEEPIMMUNE), type)
if(iscarbon(L))
var/mob/living/carbon/C = L
rage = new()
C.gain_trauma(rage, TRAUMA_RESILIENCE_ABSOLUTE)
/datum/reagent/drug/bath_salts/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, type)
- REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, type)
+ L.remove_traits(list(TRAIT_STUNIMMUNE, TRAIT_SLEEPIMMUNE), type)
if(rage)
QDEL_NULL(rage)
..()
@@ -711,8 +709,7 @@
if(invisible_man.has_status_effect(/datum/status_effect/grouped/stasis))
return
- ADD_TRAIT(invisible_man, TRAIT_INVISIBLE_MAN, name)
- ADD_TRAIT(invisible_man, TRAIT_HIDE_EXTERNAL_ORGANS, name)
+ invisible_man.add_traits(list(TRAIT_INVISIBLE_MAN, TRAIT_HIDE_EXTERNAL_ORGANS), name)
var/datum/dna/druggy_dna = invisible_man.has_dna()
if(druggy_dna?.species)
@@ -726,8 +723,8 @@
. = ..()
if(HAS_TRAIT(invisible_man, TRAIT_INVISIBLE_MAN))
invisible_man.add_to_all_human_data_huds() //Is this safe, what do you think, Floyd?
- REMOVE_TRAIT(invisible_man, TRAIT_INVISIBLE_MAN, name)
- REMOVE_TRAIT(invisible_man, TRAIT_HIDE_EXTERNAL_ORGANS, name)
+ invisible_man.remove_traits(list(TRAIT_INVISIBLE_MAN, TRAIT_HIDE_EXTERNAL_ORGANS), name)
+
to_chat(invisible_man, span_notice("As you sober up, opacity once again returns to your body meats."))
var/datum/dna/druggy_dna = invisible_man.has_dna()
diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm
index 6ecf4c4de6f..2b4032c7ef7 100644
--- a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm
@@ -513,18 +513,22 @@ Basically, we fill the time between now and 2s from now with hands based off the
chemical_flags = REAGENT_DONOTSPLIT | REAGENT_DEAD_PROCESS
///If we brought someone back from the dead
var/back_from_the_dead = FALSE
+ /// List of trait buffs to give to the affected mob, and remove as needed.
+ var/static/list/trait_buffs = list(
+ TRAIT_NOCRITDAMAGE,
+ TRAIT_NOCRITOVERLAY,
+ TRAIT_NODEATH,
+ TRAIT_NOHARDCRIT,
+ TRAIT_NOSOFTCRIT,
+ TRAIT_STABLEHEART,
+ )
/datum/reagent/inverse/penthrite/on_mob_dead(mob/living/carbon/affected_mob, delta_time)
var/obj/item/organ/internal/heart/heart = affected_mob.getorganslot(ORGAN_SLOT_HEART)
if(!heart || heart.organ_flags & ORGAN_FAILING)
return ..()
metabolization_rate = 0.2 * REM
- ADD_TRAIT(affected_mob, TRAIT_STABLEHEART, type)
- ADD_TRAIT(affected_mob, TRAIT_NOHARDCRIT, type)
- ADD_TRAIT(affected_mob, TRAIT_NOSOFTCRIT, type)
- ADD_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type)
- ADD_TRAIT(affected_mob, TRAIT_NODEATH, type)
- ADD_TRAIT(affected_mob, TRAIT_NOCRITOVERLAY, type)
+ affected_mob.add_traits(trait_buffs, type)
affected_mob.set_stat(CONSCIOUS) //This doesn't touch knocked out
affected_mob.updatehealth()
affected_mob.update_sight()
@@ -581,12 +585,7 @@ Basically, we fill the time between now and 2s from now with hands based off the
return..()
/datum/reagent/inverse/penthrite/proc/remove_buffs(mob/living/carbon/affected_mob)
- REMOVE_TRAIT(affected_mob, TRAIT_STABLEHEART, type)
- REMOVE_TRAIT(affected_mob, TRAIT_NOHARDCRIT, type)
- REMOVE_TRAIT(affected_mob, TRAIT_NOSOFTCRIT, type)
- REMOVE_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type)
- REMOVE_TRAIT(affected_mob, TRAIT_NODEATH, type)
- REMOVE_TRAIT(affected_mob, TRAIT_NOCRITOVERLAY, type)
+ affected_mob.remove_traits(trait_buffs, type)
affected_mob.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/nooartrium)
affected_mob.remove_actionspeed_modifier(/datum/actionspeed_modifier/nooartrium)
affected_mob.update_sight()
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 0725c59f655..c7d21b3a1de 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -1339,14 +1339,12 @@
/datum/reagent/medicine/changelingadrenaline/on_mob_metabolize(mob/living/affected_mob)
..()
- ADD_TRAIT(affected_mob, TRAIT_SLEEPIMMUNE, type)
- ADD_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type)
+ affected_mob.add_traits(list(TRAIT_SLEEPIMMUNE, TRAIT_BATON_RESISTANCE), type)
affected_mob.add_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown)
/datum/reagent/medicine/changelingadrenaline/on_mob_end_metabolize(mob/living/affected_mob)
..()
- REMOVE_TRAIT(affected_mob, TRAIT_SLEEPIMMUNE, type)
- REMOVE_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type)
+ affected_mob.remove_traits(list(TRAIT_SLEEPIMMUNE, TRAIT_BATON_RESISTANCE), type)
affected_mob.remove_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown)
affected_mob.remove_status_effect(/datum/status_effect/dizziness)
affected_mob.remove_status_effect(/datum/status_effect/jitter)
@@ -1400,13 +1398,11 @@
/datum/reagent/medicine/cordiolis_hepatico/on_mob_add(mob/living/affected_mob)
..()
- ADD_TRAIT(affected_mob, TRAIT_STABLELIVER, type)
- ADD_TRAIT(affected_mob, TRAIT_STABLEHEART, type)
+ affected_mob.add_traits(list(TRAIT_STABLELIVER, TRAIT_STABLEHEART), type)
/datum/reagent/medicine/cordiolis_hepatico/on_mob_end_metabolize(mob/living/affected_mob)
..()
- REMOVE_TRAIT(affected_mob, TRAIT_STABLEHEART, type)
- REMOVE_TRAIT(affected_mob, TRAIT_STABLELIVER, type)
+ affected_mob.remove_traits(list(TRAIT_STABLELIVER, TRAIT_STABLEHEART), type)
/datum/reagent/medicine/muscle_stimulant
name = "Muscle Stimulant"
diff --git a/code/modules/spells/spell_types/jaunt/_jaunt.dm b/code/modules/spells/spell_types/jaunt/_jaunt.dm
index 9b6b417d2fd..e2fc4324ad9 100644
--- a/code/modules/spells/spell_types/jaunt/_jaunt.dm
+++ b/code/modules/spells/spell_types/jaunt/_jaunt.dm
@@ -57,8 +57,7 @@
var/obj/effect/dummy/phased_mob/jaunt = new jaunt_type(loc_override || get_turf(jaunter), jaunter)
RegisterSignal(jaunt, COMSIG_MOB_EJECTED_FROM_JAUNT, PROC_REF(on_jaunt_exited))
spell_requirements |= SPELL_CASTABLE_WHILE_PHASED
- ADD_TRAIT(jaunter, TRAIT_MAGICALLY_PHASED, REF(src))
- ADD_TRAIT(jaunter, TRAIT_RUNECHAT_HIDDEN, REF(src))
+ jaunter.add_traits(list(TRAIT_MAGICALLY_PHASED, TRAIT_RUNECHAT_HIDDEN), REF(src))
// Don't do the feedback until we have runechat hidden.
// Otherwise the text will follow the jaunt holder, which reveals where our caster is travelling.
spell_feedback()
@@ -102,8 +101,7 @@
/datum/action/cooldown/spell/jaunt/proc/on_jaunt_exited(obj/effect/dummy/phased_mob/jaunt, mob/living/unjaunter)
SHOULD_CALL_PARENT(TRUE)
spell_requirements &= ~SPELL_CASTABLE_WHILE_PHASED
- REMOVE_TRAIT(unjaunter, TRAIT_MAGICALLY_PHASED, REF(src))
- REMOVE_TRAIT(unjaunter, TRAIT_RUNECHAT_HIDDEN, REF(src))
+ unjaunter.remove_traits(list(TRAIT_MAGICALLY_PHASED, TRAIT_RUNECHAT_HIDDEN), REF(src))
// This needs to happen at the end, after all the traits and stuff is handled
SEND_SIGNAL(unjaunter, COMSIG_MOB_AFTER_EXIT_JAUNT, src)
diff --git a/code/modules/station_goals/vault_mutation.dm b/code/modules/station_goals/vault_mutation.dm
new file mode 100644
index 00000000000..eab862d0824
--- /dev/null
+++ b/code/modules/station_goals/vault_mutation.dm
@@ -0,0 +1,147 @@
+
+/datum/mutation/human/breathless
+ name = "Breathless"
+ desc = "A mutation within the skin that allows for filtering and absorption of oxygen from the skin."
+ text_gain_indication = span_notice("Your lungs feel great.")
+ text_lose_indication = span_warning("Your lungs feel normal again.")
+ locked = TRUE
+ mutadone_proof = TRUE
+
+/datum/mutation/human/breathless/on_acquiring(mob/living/carbon/human/acquirer)
+ . = ..()
+ ADD_TRAIT(acquirer, TRAIT_NOBREATH, GENETIC_MUTATION)
+
+/datum/mutation/human/breathless/on_losing(mob/living/carbon/human/owner)//this shouldnt happen under normal condition but just to be sure
+ . = ..()
+ REMOVE_TRAIT(owner, TRAIT_NOBREATH, GENETIC_MUTATION)
+
+/datum/mutation/human/quick
+ name = "Quick"
+ desc = "A mution within the leg muscles that allows it to operate at 20% more than the usual capacity."
+ text_gain_indication = span_notice("Your legs feel faster and stronger.")
+ text_lose_indication = span_warning("Your legs feel weaker and slower.")
+ locked = TRUE
+ mutadone_proof = TRUE
+
+/datum/mutation/human/quick/on_acquiring(mob/living/carbon/human/acquirer)
+ . = ..()
+ acquirer.add_movespeed_modifier(/datum/movespeed_modifier/dna_vault_speedup)
+
+/datum/mutation/human/quick/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ owner.remove_movespeed_modifier(/datum/movespeed_modifier/dna_vault_speedup)
+
+/datum/mutation/human/tough
+ name = "Tough"
+ desc = "A mutation within the epidermis that makes it more resistant to tear."
+ text_gain_indication = span_notice("Your skin feels tougher.")
+ text_lose_indication = span_warning("Your skin feels weaker.")
+ locked = TRUE
+ mutadone_proof = TRUE
+
+/datum/mutation/human/tough/on_acquiring(mob/living/carbon/human/acquirer)
+ . = ..()
+ acquirer.physiology.brute_mod *= 0.7
+ ADD_TRAIT(acquirer, TRAIT_PIERCEIMMUNE, GENETIC_MUTATION)
+
+/datum/mutation/human/tough/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ owner.physiology.brute_mod /= 0.7
+ REMOVE_TRAIT(owner, TRAIT_PIERCEIMMUNE, GENETIC_MUTATION)
+
+/datum/mutation/human/dextrous
+ name = "Dextrous"
+ desc = "A mutation within the nerve system that allows for more responsive and quicker action."
+ text_gain_indication = span_notice("Your limbs feel more dextrous and responsive.")
+ text_lose_indication = span_warning("Your limbs feel less dextrous and responsive.")
+ locked = TRUE
+ mutadone_proof = TRUE
+
+/datum/mutation/human/dextrous/on_acquiring(mob/living/carbon/human/acquirer)
+ . = ..()
+ acquirer.next_move_modifier *= 0.5
+
+/datum/mutation/human/dextrous/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ owner.next_move_modifier /= 0.5
+
+/datum/mutation/human/fire_immunity
+ name = "Fire Immunity"
+ desc = "A mutation within the body that allows it to become nonflammable and withstand higher temperature."
+ text_gain_indication = span_notice("Your body feels like it can withstand fire.")
+ text_lose_indication = span_warning("Your body feels vulnerable to fire again.")
+ locked = TRUE
+ mutadone_proof = TRUE
+
+/datum/mutation/human/fire_immunity/on_acquiring(mob/living/carbon/human/acquirer)
+ . = ..()
+ acquirer.physiology.burn_mod *= 0.5
+ acquirer.add_traits(list(TRAIT_RESISTHEAT, TRAIT_NOFIRE), GENETIC_MUTATION)
+
+/datum/mutation/human/fire_immunity/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ owner.physiology.burn_mod /= 0.5
+ owner.remove_traits(list(TRAIT_RESISTHEAT, TRAIT_NOFIRE), GENETIC_MUTATION)
+
+/datum/mutation/human/quick_recovery
+ name = "Quick Recovery"
+ desc = "A mutation within the nervouse system that allows it to recover from being knocked down."
+ text_gain_indication = span_notice("You feel like you can recover from a fall easier.")
+ text_lose_indication = span_warning("You feel like recovering from a fall is a challenge again.")
+ locked = TRUE
+ mutadone_proof = TRUE
+
+/datum/mutation/human/quick_recovery/on_acquiring(mob/living/carbon/human/acquirer)
+ . = ..()
+ acquirer.physiology.stun_mod *= 0.5
+
+/datum/mutation/human/quick_recovery/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ owner.physiology.stun_mod /= 0.5
+
+/datum/mutation/human/plasmocile
+ name = "Plasmocile"
+ desc = "A mutation in the lungs that provides it immunity to plasma's toxic nature."
+ text_gain_indication = span_notice("Your lungs feel resistant to airborne contaminant.")
+ text_lose_indication = span_warning("Your lungs feel vulnerable to airborne contaminant again.")
+ locked = TRUE
+ mutadone_proof = TRUE
+
+/datum/mutation/human/plasmocile/on_acquiring(mob/living/carbon/human/acquirer)
+ . = ..()
+ var/obj/item/organ/internal/lungs/improved_lungs = acquirer.getorganslot(ORGAN_SLOT_LUNGS)
+ ADD_TRAIT(owner, TRAIT_VIRUSIMMUNE, GENETIC_MUTATION)
+ if(improved_lungs)
+ apply_buff(improved_lungs)
+ RegisterSignal(acquirer, COMSIG_CARBON_LOSE_ORGAN, PROC_REF(remove_modification))
+ RegisterSignal(acquirer, COMSIG_CARBON_GAIN_ORGAN, PROC_REF(reapply_modification))
+
+/datum/mutation/human/plasmocile/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ var/obj/item/organ/internal/lungs/improved_lungs = owner.getorganslot(ORGAN_SLOT_LUNGS)
+ REMOVE_TRAIT(owner, TRAIT_VIRUSIMMUNE, GENETIC_MUTATION)
+ UnregisterSignal(owner, COMSIG_CARBON_LOSE_ORGAN)
+ UnregisterSignal(owner, COMSIG_CARBON_GAIN_ORGAN)
+ if(improved_lungs)
+ remove_buff(improved_lungs)
+
+/datum/mutation/human/plasmocile/proc/remove_modification(mob/source, obj/item/organ/old_organ)
+ SIGNAL_HANDLER
+
+ if(istype(old_organ, /obj/item/organ/internal/lungs))
+ remove_buff(old_organ)
+
+/datum/mutation/human/plasmocile/proc/reapply_modification(mob/source, obj/item/organ/new_organ)
+ SIGNAL_HANDLER
+
+ if(istype(new_organ, /obj/item/organ/internal/lungs))
+ apply_buff(new_organ)
+
+/datum/mutation/human/plasmocile/proc/apply_buff(obj/item/organ/internal/lungs/our_lungs)
+ our_lungs.plas_breath_dam_min *= 0
+ our_lungs.plas_breath_dam_max *= 0
+
+/datum/mutation/human/plasmocile/proc/remove_buff(obj/item/organ/internal/lungs/our_lungs)
+ our_lungs.plas_breath_dam_min = initial(our_lungs.plas_breath_dam_min)
+ our_lungs.plas_breath_dam_max = initial(our_lungs.plas_breath_dam_max)
+
diff --git a/code/modules/surgery/advanced/bioware/ligament_hook.dm b/code/modules/surgery/advanced/bioware/ligament_hook.dm
index f2e45aeb380..4d263641769 100644
--- a/code/modules/surgery/advanced/bioware/ligament_hook.dm
+++ b/code/modules/surgery/advanced/bioware/ligament_hook.dm
@@ -48,10 +48,8 @@
/datum/bioware/hooked_ligaments/on_gain()
..()
- ADD_TRAIT(owner, TRAIT_LIMBATTACHMENT, EXPERIMENTAL_SURGERY_TRAIT)
- ADD_TRAIT(owner, TRAIT_EASYDISMEMBER, EXPERIMENTAL_SURGERY_TRAIT)
+ owner.add_traits(list(TRAIT_LIMBATTACHMENT, TRAIT_EASYDISMEMBER), EXPERIMENTAL_SURGERY_TRAIT)
/datum/bioware/hooked_ligaments/on_lose()
..()
- REMOVE_TRAIT(owner, TRAIT_LIMBATTACHMENT, EXPERIMENTAL_SURGERY_TRAIT)
- REMOVE_TRAIT(owner, TRAIT_EASYDISMEMBER, EXPERIMENTAL_SURGERY_TRAIT)
+ owner.remove_traits(list(TRAIT_LIMBATTACHMENT, TRAIT_EASYDISMEMBER), EXPERIMENTAL_SURGERY_TRAIT)
diff --git a/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm b/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm
index 88de751473e..1aa4d5e18fb 100644
--- a/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm
+++ b/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm
@@ -49,10 +49,8 @@
/datum/bioware/reinforced_ligaments/on_gain()
..()
- ADD_TRAIT(owner, TRAIT_NODISMEMBER, EXPERIMENTAL_SURGERY_TRAIT)
- ADD_TRAIT(owner, TRAIT_EASILY_WOUNDED, EXPERIMENTAL_SURGERY_TRAIT)
+ owner.add_traits(list(TRAIT_NODISMEMBER, TRAIT_EASILY_WOUNDED), EXPERIMENTAL_SURGERY_TRAIT)
/datum/bioware/reinforced_ligaments/on_lose()
..()
- REMOVE_TRAIT(owner, TRAIT_NODISMEMBER, EXPERIMENTAL_SURGERY_TRAIT)
- REMOVE_TRAIT(owner, TRAIT_EASILY_WOUNDED, EXPERIMENTAL_SURGERY_TRAIT)
+ owner.remove_traits(list(TRAIT_NODISMEMBER, TRAIT_EASILY_WOUNDED), EXPERIMENTAL_SURGERY_TRAIT)
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 938acd7c0e0..f3cde8cfb3f 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -704,8 +704,10 @@
return old_owner
/obj/item/bodypart/proc/on_removal()
- for(var/trait in bodypart_traits)
- REMOVE_TRAIT(owner, trait, bodypart_trait_source)
+ if(!length(bodypart_traits))
+ return
+
+ owner.remove_traits(bodypart_traits, bodypart_trait_source)
///Proc to change the value of the `can_be_disabled` variable and react to the event of its change.
/obj/item/bodypart/proc/set_can_be_disabled(new_can_be_disabled)
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 4b1c5ede997..44a5bc77039 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -130,8 +130,8 @@
continue
organ.transfer_to_limb(src, phantom_owner)
- for(var/trait in bodypart_traits)
- REMOVE_TRAIT(phantom_owner, trait, bodypart_trait_source)
+ if(length(bodypart_traits))
+ phantom_owner.remove_traits(bodypart_traits, bodypart_trait_source)
update_icon_dropped()
synchronize_bodytypes(phantom_owner)
@@ -355,8 +355,8 @@
if(can_be_disabled)
update_disabled()
- for(var/trait in bodypart_traits)
- ADD_TRAIT(owner, trait, bodypart_trait_source)
+ if(length(bodypart_traits))
+ owner.add_traits(bodypart_traits, bodypart_trait_source)
// Bodyparts need to be sorted for leg masking to be done properly. It also will allow for some predictable
// behavior within said bodyparts list. We sort it here, as it's the only place we make changes to bodyparts.
diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm
index 94e993182fc..b55e82a421f 100644
--- a/code/modules/surgery/organs/_organ.dm
+++ b/code/modules/surgery/organs/_organ.dm
@@ -133,8 +133,8 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
owner = null
for(var/datum/action/action as anything in actions)
action.Remove(organ_owner)
- for(var/trait in organ_traits)
- REMOVE_TRAIT(organ_owner, trait, REF(src))
+ if(length(organ_traits))
+ organ_owner.remove_traits(organ_traits, REF(src))
for(var/datum/action/action as anything in actions)
action.Remove(organ_owner)
@@ -148,8 +148,8 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
/// Updates the traits of the organ on the specific organ it is called on. Should be called anytime an organ is given a trait while it is already in a body.
/obj/item/organ/proc/update_organ_traits()
- for(var/trait in organ_traits)
- ADD_TRAIT(owner, trait, REF(src))
+ if(length(organ_traits))
+ owner.add_traits(organ_traits, REF(src))
/// Add a trait to an organ that it will give its owner.
/obj/item/organ/proc/add_organ_trait(trait)
diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm
index 50d245da28f..859aa8f9402 100644
--- a/code/modules/surgery/organs/external/wings/functional_wings.dm
+++ b/code/modules/surgery/organs/external/wings/functional_wings.dm
@@ -107,14 +107,12 @@
/obj/item/organ/external/wings/functional/proc/toggle_flight(mob/living/carbon/human/human)
if(!HAS_TRAIT_FROM(human, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT))
human.physiology.stun_mod *= 2
- ADD_TRAIT(human, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT)
- ADD_TRAIT(human, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
+ human.add_traits(list(TRAIT_NO_FLOATING_ANIM, TRAIT_MOVE_FLYING), SPECIES_FLIGHT_TRAIT)
passtable_on(human, SPECIES_TRAIT)
open_wings()
else
human.physiology.stun_mod *= 0.5
- REMOVE_TRAIT(human, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT)
- REMOVE_TRAIT(human, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
+ human.remove_traits(list(TRAIT_NO_FLOATING_ANIM, TRAIT_MOVE_FLYING), SPECIES_FLIGHT_TRAIT)
passtable_off(human, SPECIES_TRAIT)
close_wings()
human.update_body_parts()
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index fe78f924937..060db1006f9 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -219,6 +219,7 @@
#include "teleporters.dm"
#include "tgui_create_message.dm"
#include "timer_sanity.dm"
+#include "trait_addition_and_removal.dm"
#include "traitor.dm"
#include "tutorial_sanity.dm"
#include "unit_test.dm"
diff --git a/code/modules/unit_tests/trait_addition_and_removal.dm b/code/modules/unit_tests/trait_addition_and_removal.dm
new file mode 100644
index 00000000000..dcab577d661
--- /dev/null
+++ b/code/modules/unit_tests/trait_addition_and_removal.dm
@@ -0,0 +1,94 @@
+/// Simple Unit Test to ensure multiple methods of adding/removing a trait work as intended.
+/datum/unit_test/trait_addition_and_removal
+
+#define TRAIT_UNIT_TEST_MAIN "trait_main"
+#define TRAIT_UNIT_TEST_ALT "trait_alternate"
+#define TRAIT_UNIT_TEST_A "trait_a"
+#define TRAIT_UNIT_TEST_B "trait_b"
+#define TRAIT_UNIT_TEST_C "trait_c"
+#define UNIT_TEST_SOURCE_MAIN "source_main"
+#define UNIT_TEST_SOURCE_ALT "source_alt"
+#define UNIT_TEST_SOURCE_A "source_a"
+#define UNIT_TEST_SOURCE_B "source_b"
+
+/datum/unit_test/trait_addition_and_removal/Run()
+ var/datum/trait_target = allocate(/datum) // traits work on the datum-level, so use a datum to ensure that it'll work on all children
+
+ // We want to ensure that what we add is also removed when we're done with our "block" of tests, if it starts to get messy we might just have to reset the datum between tests to ensure cleanliness
+
+ // The basics, if these fail burn down the codebase
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_A, UNIT_TEST_SOURCE_A)
+ TEST_ASSERT(HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_A), "Basic trait addition failed for [TRAIT_UNIT_TEST_A], source being [UNIT_TEST_SOURCE_A]!")
+
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_B, UNIT_TEST_SOURCE_B)
+ TEST_ASSERT(HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_B), "Basic trait addition failed for [TRAIT_UNIT_TEST_B], source being [UNIT_TEST_SOURCE_B]!")
+ TEST_ASSERT(HAS_TRAIT_FROM(trait_target, TRAIT_UNIT_TEST_B, UNIT_TEST_SOURCE_B), "Failed to verify source for [TRAIT_UNIT_TEST_B], expected source being [UNIT_TEST_SOURCE_B]!")
+ TEST_ASSERT(HAS_TRAIT_NOT_FROM(trait_target, TRAIT_UNIT_TEST_B, UNIT_TEST_SOURCE_A), "Failed to verify source for [TRAIT_UNIT_TEST_B], expected source being [UNIT_TEST_SOURCE_B] but was actually [UNIT_TEST_SOURCE_A]!")
+
+ REMOVE_TRAIT(trait_target, TRAIT_UNIT_TEST_B, UNIT_TEST_SOURCE_B)
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_B), "Basic trait removal failed for [TRAIT_UNIT_TEST_B], source being [UNIT_TEST_SOURCE_B]!")
+ TEST_ASSERT(HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_A), "Trait [TRAIT_UNIT_TEST_A] was removed when it shouldn't have been!")
+ REMOVE_TRAIT(trait_target, TRAIT_UNIT_TEST_A, UNIT_TEST_SOURCE_A)
+
+ // Test adding the trait multiple times from different sources
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_MAIN, UNIT_TEST_SOURCE_A)
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_MAIN, UNIT_TEST_SOURCE_B)
+ TEST_ASSERT(!HAS_TRAIT_FROM_ONLY(trait_target, TRAIT_UNIT_TEST_MAIN, UNIT_TEST_SOURCE_A), "Failed to recognize that [TRAIT_UNIT_TEST_MAIN] was added by both [UNIT_TEST_SOURCE_A] and [UNIT_TEST_SOURCE_B]!")
+
+ // as well as its removal
+ REMOVE_TRAIT_NOT_FROM(trait_target, TRAIT_UNIT_TEST_MAIN, UNIT_TEST_SOURCE_A)
+ TEST_ASSERT(!HAS_TRAIT_FROM(trait_target, TRAIT_UNIT_TEST_MAIN, UNIT_TEST_SOURCE_B), "Failed to remove [TRAIT_UNIT_TEST_MAIN] with [UNIT_TEST_SOURCE_B] when removal was expected!")
+ TEST_ASSERT(HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_MAIN), "[TRAIT_UNIT_TEST_MAIN] was completely removed when it should not have been!")
+ REMOVE_TRAIT(trait_target, TRAIT_UNIT_TEST_MAIN, UNIT_TEST_SOURCE_A)
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_MAIN), "[TRAIT_UNIT_TEST_MAIN] was not removed when it should have been!")
+
+ // Test adding multiple traits from the same source
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_A, UNIT_TEST_SOURCE_MAIN)
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_B, UNIT_TEST_SOURCE_MAIN)
+ TEST_ASSERT(HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_B), "Failed to add [TRAIT_UNIT_TEST_B] with common source [UNIT_TEST_SOURCE_MAIN]!")
+
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_C, UNIT_TEST_SOURCE_ALT)
+ REMOVE_TRAITS_NOT_IN(trait_target, UNIT_TEST_SOURCE_MAIN)
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_C), "Failed to remove [TRAIT_UNIT_TEST_C] when expected to be removed with remove_traits_NOT_IN(), was added with source [UNIT_TEST_SOURCE_ALT]!")
+
+ // as well as its removal
+ REMOVE_TRAITS_IN(trait_target, UNIT_TEST_SOURCE_MAIN)
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_A), "Failed to remove [TRAIT_UNIT_TEST_A] with common source [UNIT_TEST_SOURCE_MAIN]!")
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_B), "Failed to remove [TRAIT_UNIT_TEST_B] with common source [UNIT_TEST_SOURCE_MAIN]!")
+
+ // Lastly, let's ensure that adding/removing traits using lists still works.
+ var/static/list/standardized_traits_list = list(TRAIT_UNIT_TEST_A, TRAIT_UNIT_TEST_B, TRAIT_UNIT_TEST_C)
+ trait_target.add_traits(standardized_traits_list, UNIT_TEST_SOURCE_MAIN)
+ for(var/trait in standardized_traits_list)
+ TEST_ASSERT(HAS_TRAIT(trait_target, trait), "Failed to add [trait] when using add_traits() using [UNIT_TEST_SOURCE_MAIN]!")
+ trait_target.remove_traits(standardized_traits_list, UNIT_TEST_SOURCE_MAIN)
+ for(var/trait in standardized_traits_list)
+ TEST_ASSERT(!HAS_TRAIT(trait_target, trait), "Failed to remove [trait] when using remove_traits() using [UNIT_TEST_SOURCE_MAIN]!")
+
+ // As well as ensure mixing-and-matching types of trait addition/removal works.
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_A, UNIT_TEST_SOURCE_MAIN)
+ ADD_TRAIT(trait_target, TRAIT_UNIT_TEST_B, UNIT_TEST_SOURCE_MAIN)
+ trait_target.remove_traits(standardized_traits_list, UNIT_TEST_SOURCE_MAIN)
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_A), "Failed to remove [TRAIT_UNIT_TEST_A] when using remove_traits() using [UNIT_TEST_SOURCE_MAIN] (was added using ADD_TRAIT())!")
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_B), "Failed to remove [TRAIT_UNIT_TEST_B] when using remove_traits() using [UNIT_TEST_SOURCE_MAIN] (was added using ADD_TRAIT())!")
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_C), "[TRAIT_UNIT_TEST_C] somehow came into existence when using remove_traits() using [UNIT_TEST_SOURCE_MAIN] (what the actual fuck)!")
+
+ trait_target.add_traits(standardized_traits_list, UNIT_TEST_SOURCE_MAIN)
+ REMOVE_TRAIT(trait_target, TRAIT_UNIT_TEST_A, UNIT_TEST_SOURCE_MAIN)
+ REMOVE_TRAIT(trait_target, TRAIT_UNIT_TEST_B, UNIT_TEST_SOURCE_MAIN)
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_A), "Failed to remove [TRAIT_UNIT_TEST_A] when using REMOVE_TRAIT() using [UNIT_TEST_SOURCE_MAIN] (was added using add_traits())!")
+ TEST_ASSERT(!HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_B), "Failed to remove [TRAIT_UNIT_TEST_B] when using REMOVE_TRAIT() using [UNIT_TEST_SOURCE_MAIN] (was added using add_traits())!")
+ TEST_ASSERT(HAS_TRAIT(trait_target, TRAIT_UNIT_TEST_C), "[TRAIT_UNIT_TEST_C] was unexpectedly removed when using REMOVE_TRAIT() using [UNIT_TEST_SOURCE_MAIN] (was added using add_traits())!")
+ REMOVE_TRAIT(trait_target, TRAIT_UNIT_TEST_C, UNIT_TEST_SOURCE_MAIN) //just for cleanliness+completeness
+
+ TEST_ASSERT(!length(trait_target.status_traits), "Failed to clean up all status traits at the end of the unit test!")
+
+#undef TRAIT_UNIT_TEST_MAIN
+#undef TRAIT_UNIT_TEST_ALT
+#undef TRAIT_UNIT_TEST_A
+#undef TRAIT_UNIT_TEST_B
+#undef TRAIT_UNIT_TEST_C
+#undef UNIT_TEST_SOURCE_MAIN
+#undef UNIT_TEST_SOURCE_ALT
+#undef UNIT_TEST_SOURCE_A
+#undef UNIT_TEST_SOURCE_B
diff --git a/tgstation.dme b/tgstation.dme
index 8965ac14c1a..59ba5b7fa1d 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4841,6 +4841,7 @@
#include "code\modules\station_goals\dna_vault.dm"
#include "code\modules\station_goals\shield.dm"
#include "code\modules\station_goals\station_goal.dm"
+#include "code\modules\station_goals\vault_mutation.dm"
#include "code\modules\surgery\amputation.dm"
#include "code\modules\surgery\blood_filter.dm"
#include "code\modules\surgery\bone_mending.dm"