diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index c9fbfd3117c4..49d185a7aab7 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -21,6 +21,8 @@
#define TRAIT_SLEEPIMMUNE "sleep_immunity"
#define TRAIT_PUSHIMMUNE "push_immunity"
#define TRAIT_SHOCKIMMUNE "shock_immunity"
+#define TRAIT_ANTIMAGIC "anti_magic"
+#define TRAIT_HOLY "holy"
// common trait sources
@@ -29,9 +31,8 @@
#define GENETIC_MUTATION "genetic"
#define OBESITY "obesity"
#define MAGIC_TRAIT "magic"
-#define STASIS_MUTE "stasis"
-#define GENETICS_SPELL "genetics_spell"
#define TRAUMA_TRAIT "trauma"
+#define SPECIES_TRAIT "species"
// unique trait sources, still defines
#define STATUE_MUTE "statue"
@@ -40,3 +41,5 @@
#define ABYSSAL_GAZE_BLIND "abyssal_gaze"
#define HIGHLANDER "highlander"
#define TRAIT_HULK "hulk"
+#define STASIS_MUTE "stasis"
+#define GENETICS_SPELL "genetics_spell"
diff --git a/code/datums/components/anti_magic.dm b/code/datums/components/anti_magic.dm
new file mode 100644
index 000000000000..3d63d9a63e4d
--- /dev/null
+++ b/code/datums/components/anti_magic.dm
@@ -0,0 +1,43 @@
+/datum/component/anti_magic
+ var/magic = FALSE
+ var/holy = FALSE
+
+/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE)
+ magic = _magic
+ holy = _holy
+
+/datum/component/anti_magic/proc/can_protect(_magic = TRUE, _holy = FALSE)
+ if(!enabled)
+ return FALSE
+ if((_magic && magic) || (_holy && holy))
+ return TRUE
+ return FALSE
+
+/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE)
+ if(!magic && !holy)
+ return
+ var/list/obj/item/item_list = list()
+ item_list |= held_items
+ for(var/obj/O in item_list)
+ GET_COMPONENT_FROM(anti_magic, /datum/component/anti_magic, O)
+ if(!anti_magic)
+ continue
+ if(anti_magic.can_protect(magic, holy))
+ return O
+
+/mob/living/anti_magic_check(magic = TRUE, holy = FALSE)
+ if(!magic && !holy)
+ return
+
+ if((magic && has_trait(TRAIT_ANTIMAGIC)) || (holy && has_trait(TRAIT_HOLY)))
+ return src
+
+ var/list/obj/item/item_list = list()
+ item_list |= get_equipped_items(TRUE)
+ item_list |= held_items
+ for(var/obj/O in item_list)
+ GET_COMPONENT_FROM(anti_magic, /datum/component/anti_magic, O)
+ if(!anti_magic)
+ continue
+ if(anti_magic.can_protect(magic, holy))
+ return O
\ No newline at end of file
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 600b8d9679f0..915d5bce8d61 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -125,7 +125,7 @@
/datum/status_effect/belligerent/proc/do_movement_toggle(force_damage)
var/number_legs = owner.get_num_legs()
- if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.null_rod_check() && number_legs)
+ if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check() && number_legs)
if(force_damage || owner.m_intent != MOVE_INTENT_WALK)
if(GLOB.ratvar_awakens)
owner.Knockdown(20)
@@ -218,7 +218,7 @@
if(owner.confused)
owner.confused = 0
severity = 0
- else if(!owner.null_rod_check() && owner.stat != DEAD && severity)
+ else if(!owner.anti_magic_check() && owner.stat != DEAD && severity)
var/static/hum = get_sfx('sound/effects/screech.ogg') //same sound for every proc call
if(owner.getToxLoss() > MANIA_DAMAGE_TO_CONVERT)
if(is_eligible_servant(owner))
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 88e2b40ad666..fd137578348f 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -13,6 +13,10 @@
obj_flags = UNIQUE_RENAME
var/reskinned = FALSE
+/obj/item/nullrod/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+
/obj/item/nullrod/suicide_act(mob/user)
user.visible_message("[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!")
return (BRUTELOSS|FIRELOSS)
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index ec17683fa5b2..875183f9d203 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -17,6 +17,12 @@ GLOBAL_LIST_INIT(biblenames, list("Bible", "Quran", "Scrapbook", "Burning Bible"
GLOBAL_LIST_INIT(biblestates, list("bible", "koran", "scrapbook", "burning", "honk1", "honk2", "creeper", "white", "holylight", "atheist", "tome", "kingyellow", "ithaqua", "scientology", "melted", "necronomicon"))
GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", "bible", "bible", "syringe_kit", "syringe_kit", "syringe_kit", "syringe_kit", "syringe_kit", "kingyellow", "ithaqua", "scientology", "melted", "necronomicon"))
+/mob/proc/bible_check() //The bible, if held, might protect against certain things
+ var/obj/item/storage/book/bible/B = locate() in src
+ if(is_holding(B))
+ return B
+ return 0
+
/obj/item/storage/book/bible
name = "bible"
desc = "Apply to head repeatedly."
@@ -29,6 +35,10 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
var/deity_name = "Christ"
force_string = "holy"
+/obj/item/storage/book/bible/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, FALSE, TRUE)
+
/obj/item/storage/book/bible/suicide_act(mob/user)
user.visible_message("[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!")
return (BRUTELOSS)
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
index a4eed086c852..3f32cdaa59af 100644
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
@@ -11,6 +11,8 @@
var/stat_affected = CONSCIOUS
var/sigil_name = "Sigil"
var/resist_string = "glows blinding white" //string for when a null rod blocks its effects, "glows [resist_string]"
+ var/check_antimagic = TRUE
+ var/check_holy = FALSE
/obj/effect/clockwork/sigil/attackby(obj/item/I, mob/living/user, params)
if(I.force)
@@ -43,10 +45,11 @@
var/mob/living/L = AM
if(L.stat <= stat_affected)
if((!is_servant_of_ratvar(L) || (affects_servants && is_servant_of_ratvar(L))) && (L.mind || L.has_status_effect(STATUS_EFFECT_SIGILMARK)) && !isdrone(L))
- var/obj/item/I = L.null_rod_check()
+ var/atom/I = L.anti_magic_check(check_antimagic, check_holy)
if(I)
- L.visible_message("[L]'s [I.name] [resist_string], protecting them from [src]'s effects!", \
- "Your [I.name] [resist_string], protecting you!")
+ if(isitem(I))
+ L.visible_message("[L]'s [I.name] [resist_string], protecting them from [src]'s effects!", \
+ "Your [I.name] [resist_string], protecting you!")
return
sigil_effects(L)
diff --git a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
index 3cef31a7067d..95a46705f0c7 100644
--- a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
+++ b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
@@ -182,13 +182,14 @@
var/mob/living/L = target
if(is_servant_of_ratvar(L) || L.stat || L.has_status_effect(STATUS_EFFECT_KINDLE))
return
- var/obj/O = L.null_rod_check()
+ var/atom/O = L.anti_magic_check()
playsound(L, 'sound/magic/fireball.ogg', 50, TRUE, frequency = 1.25)
if(O)
- L.visible_message("[L]'s eyes flare with dim light as they stumble!", \
- "Your [O] glows white-hot against you as it absorbs some sort of power!")
- L.adjustFireLoss(5)
- L.Stun(40)
+ if(isitem(O))
+ L.visible_message("[L]'s eyes flare with dim light!", \
+ "Your [O] glows white-hot against you as it absorbs [src]'s power!")
+ else if(ismob(O))
+ L.visible_message("[L]'s eyes flare with dim light!")
playsound(L, 'sound/weapons/sear.ogg', 50, TRUE)
else
L.visible_message("[L]'s eyes blaze with brilliant light!", \
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
index d3365e9e2005..3ad668472520 100644
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
@@ -35,7 +35,7 @@
/obj/item/clockwork/weapon/ratvarian_spear/attack(mob/living/target, mob/living/carbon/human/user)
. = ..()
- if(!QDELETED(target) && target.stat != DEAD && !target.null_rod_check() && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
+ if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check() && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
var/bonus_damage = bonus_burn //normally a total of 20 damage, 30 with ratvar
if(issilicon(target))
target.visible_message("[target] shudders violently at [src]'s touch!", "ERROR: Temperature rising!")
@@ -55,7 +55,7 @@
else
L.visible_message("[src] bounces off of [L], as if repelled by an unseen force!")
else if(!..())
- if(!L.null_rod_check())
+ if(!L.anti_magic_check())
if(issilicon(L) || iscultist(L))
L.Knockdown(100)
else
diff --git a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
index d6b2ddce0ddc..a16a52d7aa54 100644
--- a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
+++ b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
@@ -189,10 +189,11 @@
for(var/mob/living/L in range(1, src))
if(is_servant_of_ratvar(L))
continue
- if(L.null_rod_check())
- var/obj/item/I = L.null_rod_check()
- L.visible_message("Strange energy flows into [L]'s [I.name]!", \
- "Your [I.name] shields you from [src]!")
+ if(L.anti_magic_check())
+ var/atom/I = L.anti_magic_check()
+ if(isitem(I))
+ L.visible_message("Strange energy flows into [L]'s [I.name]!", \
+ "Your [I.name] shields you from [src]!")
continue
L.Knockdown(15) //knocks down briefly when exploding
if(!iscultist(L))
diff --git a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
index 9c2e806537a3..86d94979348a 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
@@ -60,7 +60,7 @@
else
if(isliving(target))
var/mob/living/L = target
- if(!L.null_rod_check())
+ if(!L.anti_magic_check())
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
if(R.revealed)
@@ -110,7 +110,7 @@
if(!(BI.resistance_flags & ON_FIRE))
BI.fire_act()
continue
- if(is_servant_of_ratvar(L) || (L.has_trait(TRAIT_BLIND)) || L.null_rod_check())
+ if(is_servant_of_ratvar(L) || (L.has_trait(TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE))
continue
if(L.stat || L.restrained() || L.buckled || L.lying)
continue
diff --git a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
index e417cbbc3274..3ffe93ff085f 100644
--- a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
@@ -53,7 +53,7 @@
/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
if(istype(L) && !is_servant_of_ratvar(L))
- if(!L.null_rod_check())
+ if(!L.anti_magic_check())
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 459aaa9f2d69..2c24e8cdf7a2 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -681,7 +681,7 @@
else
L.visible_message("[src] bounces off of [L], as if repelled by an unseen force!")
else if(!..())
- if(!L.null_rod_check())
+ if(!L.anti_magic_check())
if(is_servant_of_ratvar(L))
L.Knockdown(100)
else
@@ -974,7 +974,7 @@
else
L.visible_message("[src] bounces off of [L], as if repelled by an unseen force!")
else if(!..())
- if(!L.null_rod_check())
+ if(!L.anti_magic_check())
if(is_servant_of_ratvar(L))
L.Knockdown(60)
else
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 030a59b14bf7..b5fb469a03fd 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -178,18 +178,6 @@ structure_check() searches for nearby cultist structures required for the invoca
..()
qdel(src)
-/mob/proc/null_rod_check() //The null rod, if equipped, will protect the holder from the effects of most runes
- var/obj/item/nullrod/N = locate() in src
- if(N && !GLOB.ratvar_awakens) //If Nar-Sie or Ratvar are alive, null rods won't protect you
- return N
- return 0
-
-/mob/proc/bible_check() //The bible, if held, might protect against certain things
- var/obj/item/storage/book/bible/B = locate() in src
- if(is_holding(B))
- return B
- return 0
-
//Rite of Offering: Converts or sacrifices a target.
/obj/effect/rune/convert
cultist_name = "Offer"
@@ -252,10 +240,10 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "You need more invokers to convert [convertee]!")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
- if(convertee.null_rod_check())
+ if(convertee.anti_magic_check(TRUE, TRUE))
for(var/M in invokers)
to_chat(M, "Something is shielding [convertee]'s mind!")
- log_game("Offer rune failed - convertee had null rod")
+ log_game("Offer rune failed - convertee had anti-magic")
return 0
var/brutedamage = convertee.getBruteLoss()
var/burndamage = convertee.getFireLoss()
@@ -768,9 +756,10 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
- var/obj/item/nullrod/N = L.null_rod_check()
- if(N)
- to_chat(L, "\The [N] suddenly burns hotly before returning to normal!")
+ var/atom/I = L.anti_magic_check()
+ if(I)
+ if(isitem(I))
+ to_chat(L, "[I] suddenly burns hotly before returning to normal!")
continue
to_chat(L, "Your blood boils in your veins!")
if(is_servant_of_ratvar(L))
@@ -797,8 +786,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
- var/obj/item/nullrod/N = L.null_rod_check()
- if(N)
+ if(L.anti_magic_check())
continue
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
if(is_servant_of_ratvar(L))
diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm
index 5530db788194..b83892dd4665 100644
--- a/code/modules/antagonists/revenant/revenant_abilities.dm
+++ b/code/modules/antagonists/revenant/revenant_abilities.dm
@@ -54,6 +54,11 @@
reveal(46)
stun(46)
target.visible_message("[target] suddenly rises slightly into the air, [target.p_their()] skin turning an ashy gray.")
+ if(target.anti_magic_check(FALSE, TRUE))
+ to_chat(src, "Something's wrong! [target] seems to be resisting the siphoning, leaving you vulnerable!")
+ target.visible_message("[target] slumps onto the ground.", \
+ "Violets lights, dancing in your vision, receding--")
+ return
var/datum/beam/B = Beam(target,icon_state="drain_life",time=INFINITY)
if(do_after(src, 46, 0, target)) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining.
change_essence_amount(essence_drained, FALSE, target)
@@ -110,7 +115,8 @@
return
log_talk(user,"RevenantTransmit: [key_name(user)]->[key_name(M)] : [msg]",LOGSAY)
to_chat(user, "You transmit to [M]: [msg]")
- to_chat(M, "You hear something behind you talking... [msg]")
+ if(!M.anti_magic_check(FALSE, TRUE)) //hear no evil
+ to_chat(M, "You hear something behind you talking... [msg]")
for(var/ded in GLOB.dead_mob_list)
if(!isobserver(ded))
continue
@@ -216,7 +222,8 @@
if(M == user)
continue
L.Beam(M,icon_state="purple_lightning",time=5)
- M.electrocute_act(shock_damage, L, safety=1)
+ if(!M.anti_magic_check(FALSE, TRUE))
+ M.electrocute_act(shock_damage, L, safety=TRUE)
do_sparks(4, FALSE, M)
playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
@@ -298,6 +305,8 @@
for(var/mob/living/carbon/human/human in T)
if(human == user)
continue
+ if(human.anti_magic_check(FALSE, TRUE))
+ continue
to_chat(human, "You feel [pick("your sense of direction flicker out", "a stabbing pain in your head", "your mind fill with static")].")
new /obj/effect/temp_visual/revenant(human.loc)
human.emp_act(EMP_HEAVY)
@@ -336,6 +345,8 @@
for(var/mob/living/mob in T)
if(mob == user)
continue
+ if(mob.anti_magic_check(FALSE, TRUE))
+ continue
new /obj/effect/temp_visual/revenant(mob.loc)
if(iscarbon(mob))
if(ishuman(mob))
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 828fe940b76e..41b2334f94a3 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -416,6 +416,10 @@
max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/wizard
+/obj/item/clothing/suit/space/hardsuit/wizard/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, FALSE)
+
//Medical hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/medical
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 79c208f8c2f1..738d298f720c 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -302,9 +302,9 @@ Contains:
max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF
-/obj/item/clothing/suit/space/hardsuit/ert/paranormal/New()
- ..()
- new /obj/item/nullrod(src)
+/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE)
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor
name = "inquisitor's hardsuit"
diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm
index edd8c260405c..232e3c5dce99 100644
--- a/code/modules/fields/timestop.dm
+++ b/code/modules/fields/timestop.dm
@@ -15,6 +15,8 @@
var/duration = 140
var/datum/proximity_monitor/advanced/timestop/chronofield
alpha = 125
+ var/check_anti_magic = FALSE
+ var/check_holy = FALSE
/obj/effect/timestop/Initialize(mapload, radius, time, list/immune_atoms, start = TRUE) //Immune atoms assoc list atom = TRUE
. = ..()
@@ -38,10 +40,11 @@
/obj/effect/timestop/proc/timestop()
target = get_turf(src)
playsound(src, 'sound/magic/timeparadox2.ogg', 75, 1, -1)
- chronofield = make_field(/datum/proximity_monitor/advanced/timestop, list("current_range" = freezerange, "host" = src, "immune" = immune))
+ chronofield = make_field(/datum/proximity_monitor/advanced/timestop, list("current_range" = freezerange, "host" = src, "immune" = immune, "check_anti_magic" = check_anti_magic, "check_holy" = check_holy))
QDEL_IN(src, duration)
/obj/effect/timestop/wizard
+ check_anti_magic = TRUE
duration = 100
/datum/proximity_monitor/advanced/timestop
@@ -53,6 +56,8 @@
var/list/mob/living/frozen_mobs = list()
var/list/obj/item/projectile/frozen_projectiles = list()
var/list/atom/movable/frozen_throws = list()
+ var/check_anti_magic = FALSE
+ var/check_holy = FALSE
var/static/list/global_frozen_atoms = list()
@@ -124,6 +129,8 @@
global_frozen_atoms[P] = TRUE
/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L)
+ if(L.anti_magic_check(check_anti_magic, check_holy))
+ return
L.Stun(20, 1, 1)
frozen_mobs[L] = L.anchored
L.anchored = TRUE
diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm
index a64fc4b15621..7497a10ffbf6 100644
--- a/code/modules/hydroponics/grown/melon.dm
+++ b/code/modules/hydroponics/grown/melon.dm
@@ -54,3 +54,7 @@
icon_state = "holymelon"
filling_color = "#FFD700"
dried_type = null
+
+/obj/item/reagent_containers/food/snacks/grown/holymelon/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE) //deliver us from evil o melon god
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 442a2aa2dc43..246c3226028f 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -323,6 +323,10 @@
actions_types = list(/datum/action/item_action/immortality)
var/cooldown = 0
+/obj/item/device/immortality_talisman/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+
/datum/action/item_action/immortality
name = "Immortality"
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 1884a97985e0..acef80b8ba69 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -329,10 +329,10 @@
//Outdated but still in use apparently. This should at least be a human proc.
//Daily reminder to murder this - Remie.
-/mob/living/proc/get_equipped_items()
+/mob/living/proc/get_equipped_items(include_pockets = FALSE)
return
-/mob/living/carbon/get_equipped_items()
+/mob/living/carbon/get_equipped_items(include_pockets = FALSE)
var/list/items = list()
if(back)
items += back
@@ -344,7 +344,7 @@
items += wear_neck
return items
-/mob/living/carbon/human/get_equipped_items()
+/mob/living/carbon/human/get_equipped_items(include_pockets = FALSE)
var/list/items = ..()
if(belt)
items += belt
@@ -362,6 +362,13 @@
items += wear_suit
if(w_uniform)
items += w_uniform
+ if(include_pockets)
+ if(l_store)
+ items += l_store
+ if(r_store)
+ items += r_store
+ if(s_store)
+ items += s_store
return items
/mob/living/proc/unequip_everything()
diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm
index fed10446f1c9..5ebb10fd5626 100644
--- a/code/modules/mob/living/carbon/human/species_types/angel.dm
+++ b/code/modules/mob/living/carbon/human/species_types/angel.dm
@@ -21,6 +21,7 @@
if(ishuman(H) && !fly)
fly = new
fly.Grant(H)
+ H.add_trait(TRAIT_HOLY, SPECIES_TRAIT)
/datum/species/angel/on_species_loss(mob/living/carbon/human/H)
if(fly)
@@ -31,6 +32,7 @@
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "None") && ("wings" in H.dna.species.mutant_bodyparts)))
H.dna.features["wings"] = "None"
H.update_body()
+ H.remove_trait(TRAIT_HOLY, SPECIES_TRAIT)
..()
/datum/species/angel/spec_life(mob/living/carbon/human/H)
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 621eeb609afc..3619e045845f 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -69,6 +69,14 @@
info_text = "As an Adamantine Golem, you possess special vocal cords allowing you to \"resonate\" messages to all golems."
prefix = "Adamantine"
+/datum/species/golem/adamantine/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ ..()
+ C.add_trait(TRAIT_ANTIMAGIC, SPECIES_TRAIT)
+
+/datum/species/golem/adamantine/on_species_loss(mob/living/carbon/C)
+ C.remove_trait(TRAIT_ANTIMAGIC, SPECIES_TRAIT)
+ ..()
+
//The suicide bombers of golemkind
/datum/species/golem/plasma
name = "Plasma Golem"
@@ -161,6 +169,14 @@
prefix = "Silver"
special_names = list("Surfer", "Chariot", "Lining")
+/datum/species/golem/silver/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ ..()
+ C.add_trait(TRAIT_HOLY, SPECIES_TRAIT)
+
+/datum/species/golem/silver/on_species_loss(mob/living/carbon/C)
+ C.remove_trait(TRAIT_HOLY, SPECIES_TRAIT)
+ ..()
+
//Harder to stun, deals more damage, but it's even slower
/datum/species/golem/plasteel
name = "Plasteel Golem"
@@ -664,6 +680,14 @@
punchdamagehigh = 8 // not as heavy as stone
prefix = "Cloth"
+/datum/species/golem/cloth/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ ..()
+ C.add_trait(TRAIT_HOLY, SPECIES_TRAIT)
+
+/datum/species/golem/cloth/on_species_loss(mob/living/carbon/C)
+ C.remove_trait(TRAIT_HOLY, SPECIES_TRAIT)
+ ..()
+
/datum/species/golem/cloth/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index aff8440930cc..518681133174 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -87,6 +87,10 @@
to_chat(H, "[victim] doesn't have blood!")
return
V.drain_cooldown = world.time + 30
+ if(victim.anti_magic_check(FALSE, TRUE))
+ to_chat(victim, "[H] tries to bite you, but stops before touching you!")
+ to_chat(H, "[victim] is blessed! You stop just in time to avoid catching fire.")
+ return
if(!do_after(H, 30, target = victim))
return
var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index a28cc61f27da..ccd426df25f8 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -15,6 +15,9 @@
. = ..()
if(ismob(target))
var/mob/M = target
+ if(M.anti_magic_check())
+ M.visible_message("[src] vanishes on contact with [target]!")
+ return
M.death(0)
/obj/item/projectile/magic/resurrection
@@ -29,6 +32,8 @@
if(isliving(target))
if(target.hellbound)
return
+ if(target.anti_magic_check())
+ target.visible_message("[src] vanishes on contact with [target]!")
if(iscarbon(target))
var/mob/living/carbon/C = target
C.regenerate_limbs()
@@ -50,6 +55,11 @@
/obj/item/projectile/magic/teleport/on_hit(mob/target)
. = ..()
+ if(ismob(target))
+ var/mob/M = target
+ if(M.anti_magic_check())
+ M.visible_message("[src] fizzles on contact with [target]!")
+ return
var/teleammount = 0
var/teleloc = target
if(!isturf(target))
@@ -100,6 +110,12 @@
/obj/item/projectile/magic/change/on_hit(atom/change)
. = ..()
+ if(ismob(change))
+ var/mob/M = change
+ if(M.anti_magic_check())
+ M.visible_message("[src] fizzles on contact with [M]!")
+ qdel(src)
+ return
wabbajack(change)
qdel(src)
@@ -292,6 +308,15 @@
dismemberment = 50
nodamage = 0
+/obj/item/projectile/magic/spellblade/on_hit(target)
+ if(ismob(target))
+ var/mob/M = target
+ if(M.anti_magic_check())
+ M.visible_message("[src] vanishes on contact with [target]!")
+ qdel(src)
+ return
+ . = ..()
+
/obj/item/projectile/magic/arcane_barrage
name = "arcane bolt"
icon_state = "arcane_barrage"
@@ -301,6 +326,15 @@
armour_penetration = 0
flag = "magic"
+/obj/item/projectile/magic/arcane_barrage/on_hit(target)
+ if(ismob(target))
+ var/mob/M = target
+ if(M.anti_magic_check())
+ M.visible_message("[src] vanishes on contact with [target]!")
+ qdel(src)
+ return
+ . = ..()
+
/obj/item/projectile/magic/aoe
name = "Area Bolt"
desc = "What the fuck does this do?!"
@@ -310,7 +344,7 @@
/obj/item/projectile/magic/aoe/Range()
if(proxdet)
for(var/mob/living/L in range(1, get_turf(src)))
- if(L.stat != DEAD && L != firer)
+ if(L.stat != DEAD && L != firer && !L.anti_magic_check())
return Collide(L)
..()
@@ -336,6 +370,12 @@
/obj/item/projectile/magic/aoe/lightning/on_hit(target)
. = ..()
+ if(ismob(target))
+ var/mob/M = target
+ if(M.anti_magic_check())
+ visible_message("[src] fizzles on contact with [target]!")
+ qdel(src)
+ return
tesla_zap(src, tesla_range, tesla_power, tesla_boom)
qdel(src)
@@ -358,11 +398,14 @@
/obj/item/projectile/magic/aoe/fireball/on_hit(target)
. = ..()
+ if(ismob(target))
+ var/mob/living/M = target
+ if(M.anti_magic_check())
+ visible_message("[src] vanishes into smoke on contact with [target]!")
+ return
+ M.take_overall_damage(0,10) //between this 10 burn, the 10 brute, the explosion brute, and the onfire burn, your at about 65 damage if you stop drop and roll immediately
var/turf/T = get_turf(target)
explosion(T, -1, exp_heavy, exp_light, exp_flash, 0, flame_range = exp_fire)
- if(ismob(target)) //multiple flavors of pain
- var/mob/living/M = target
- M.take_overall_damage(0,10) //between this 10 burn, the 10 brute, the explosion brute, and the onfire burn, your at about 65 damage if you stop drop and roll immediately
/obj/item/projectile/magic/aoe/fireball/infernal
name = "infernal fireball"
@@ -373,6 +416,10 @@
/obj/item/projectile/magic/aoe/fireball/infernal/on_hit(target)
. = ..()
+ if(ismob(target))
+ var/mob/living/M = target
+ if(M.anti_magic_check())
+ return
var/turf/T = get_turf(target)
for(var/i=0, i<50, i+=10)
addtimer(CALLBACK(GLOBAL_PROC, .proc/explosion, T, -1, exp_heavy, exp_light, exp_flash, FALSE, FALSE, exp_fire), i)
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index d9ca4a1f62bf..f486dd1a9504 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -190,6 +190,18 @@
glass_name = "glass of holy water"
glass_desc = "A glass of holy water."
+/datum/reagent/water/holywater/on_mob_add(mob/M)
+ ..()
+ if(isliving(M))
+ var/mob/living/L = M
+ L.add_trait(TRAIT_HOLY, id)
+
+/datum/reagent/water/holywater/on_mob_delete(mob/M)
+ if(isliving(M))
+ var/mob/living/L = M
+ L.remove_trait(TRAIT_HOLY, id)
+ ..()
+
/datum/reagent/water/holywater/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(is_servant_of_ratvar(M))
to_chat(M, "A darkness begins to spread its unholy tendrils through your mind, purging the Justiciar's influence!")
@@ -1778,7 +1790,7 @@
id = "synthpax"
description = "A colorless liquid that suppresses violence on the subjects. Cheaper to synthetize, but wears out faster than normal Pax."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
-
+
/datum/reagent/bz_metabolites
name = "BZ metabolites"
id = "bz_metabolites"
diff --git a/code/modules/spells/spell_types/barnyard.dm b/code/modules/spells/spell_types/barnyard.dm
index cc93644df306..f183f0420e09 100644
--- a/code/modules/spells/spell_types/barnyard.dm
+++ b/code/modules/spells/spell_types/barnyard.dm
@@ -31,6 +31,12 @@
to_chat(user, "They are too far away!")
return
+ if(target.anti_magic_check())
+ to_chat(user, "The spell had no effect!")
+ target.visible_message("[target]'s face bursts into flames, which instantly burst outward, leaving [target] unharmed!", \
+ "Your face starts burning up, but the flames are repulsed by your anti-magic protection!")
+ return
+
var/list/masks = list(/obj/item/clothing/mask/spig, /obj/item/clothing/mask/cowmask, /obj/item/clothing/mask/horsehead)
var/list/mSounds = list('sound/magic/pighead_curse.ogg', 'sound/magic/cowhead_curse.ogg', 'sound/magic/horsehead_curse.ogg')
var/randM = rand(1,3)
diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm
index 087a2a279334..42e11055b723 100644
--- a/code/modules/spells/spell_types/construct_spells.dm
+++ b/code/modules/spells/spell_types/construct_spells.dm
@@ -202,6 +202,10 @@
revert_cast()
return
+ if(target.anti_magic_check(TRUE, TRUE))
+ to_chat(target, "You feel a freezing darkness closing in on you, but it rapidly dissipates.")
+ return
+
to_chat(target, "A freezing darkness surrounds you...")
target.playsound_local(get_turf(target), 'sound/hallucinations/i_see_you1.ogg', 50, 1)
user.playsound_local(get_turf(user), 'sound/effects/ghost2.ogg', 50, 1)
@@ -294,6 +298,7 @@
sound = 'sound/weapons/resonator_blast.ogg'
proj_trigger_range = 0
ignore_factions = list("cult")
+ check_holy = TRUE
/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut
name = "Gauntlet Echo"
diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm
index e9b8a458a8fd..fed720ca1a59 100644
--- a/code/modules/spells/spell_types/devil.dm
+++ b/code/modules/spells/spell_types/devil.dm
@@ -195,6 +195,8 @@
continue
if(locate(/datum/objective/sintouched) in H.mind.objectives)
continue
+ if(H.anti_magic_check(FALSE, TRUE))
+ continue
H.influenceSin()
H.Knockdown(400)
diff --git a/code/modules/spells/spell_types/dumbfire.dm b/code/modules/spells/spell_types/dumbfire.dm
index f4a56fc466f7..fc8c7dd7091c 100644
--- a/code/modules/spells/spell_types/dumbfire.dm
+++ b/code/modules/spells/spell_types/dumbfire.dm
@@ -24,6 +24,9 @@
var/proj_step_delay = 1 //lower = faster
var/list/ignore_factions = list() //Faction types that will be ignored
+ var/check_antimagic = TRUE
+ var/check_holy = FALSE
+
/obj/effect/proc_holder/spell/dumbfire/choose_targets(mob/user = usr)
var/turf/T = get_turf(user)
@@ -74,7 +77,7 @@
break
var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - user
- if(L && L.stat != DEAD)
+ if(L && L.stat != DEAD && L.anti_magic_check(check_antimagic, check_holy))
if(!ignore_factions.len)
projectile.cast(L.loc,user=user)
break
diff --git a/code/modules/spells/spell_types/emplosion.dm b/code/modules/spells/spell_types/emplosion.dm
index 761121f540fa..8c45c0637965 100644
--- a/code/modules/spells/spell_types/emplosion.dm
+++ b/code/modules/spells/spell_types/emplosion.dm
@@ -11,6 +11,8 @@
/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets,mob/user = usr)
playsound(get_turf(user), sound, 50,1)
for(var/mob/living/target in targets)
+ if(target.anti_magic_check())
+ continue
empulse(target.loc, emp_heavy, emp_light)
return
\ No newline at end of file
diff --git a/code/modules/spells/spell_types/explosion.dm b/code/modules/spells/spell_types/explosion.dm
index def7db816f26..bd9d5d005ac2 100644
--- a/code/modules/spells/spell_types/explosion.dm
+++ b/code/modules/spells/spell_types/explosion.dm
@@ -8,8 +8,9 @@
var/ex_flash = 4
/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets,mob/user = usr)
-
for(var/mob/living/target in targets)
+ if(target.anti_magic_check())
+ continue
explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash)
return
\ No newline at end of file
diff --git a/code/modules/spells/spell_types/forcewall.dm b/code/modules/spells/spell_types/forcewall.dm
index 9efbbdf87560..47d6f71f9b79 100644
--- a/code/modules/spells/spell_types/forcewall.dm
+++ b/code/modules/spells/spell_types/forcewall.dm
@@ -32,5 +32,9 @@
/obj/effect/forcefield/wizard/CanPass(atom/movable/mover, turf/target)
if(mover == wizard)
- return 1
- return 0
+ return TRUE
+ if(ismob(mover))
+ var/mob/M = mover
+ if(M.anti_magic_check())
+ return TRUE
+ return FALSE
diff --git a/code/modules/spells/spell_types/genetic.dm b/code/modules/spells/spell_types/genetic.dm
index e42aa182bc0a..37fca86f46b0 100644
--- a/code/modules/spells/spell_types/genetic.dm
+++ b/code/modules/spells/spell_types/genetic.dm
@@ -19,6 +19,8 @@
/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets,mob/user = usr)
playMagSound()
for(var/mob/living/carbon/target in targets)
+ if(target.anti_magic_check())
+ continue
if(!target.dna)
continue
for(var/A in mutations)
diff --git a/code/modules/spells/spell_types/godhand.dm b/code/modules/spells/spell_types/godhand.dm
index 5ddfb704bff9..2def02b4c0f2 100644
--- a/code/modules/spells/spell_types/godhand.dm
+++ b/code/modules/spells/spell_types/godhand.dm
@@ -57,6 +57,20 @@
for(var/mob/living/L in view(src, 7))
if(L != user)
L.flash_act(affect_silicon = FALSE)
+ var/atom/A = M.anti_magic_check()
+ if(A)
+ if(isitem(A))
+ target.visible_message("[target]'s [A] glows brightly as it wards off the spell!")
+ user.visible_message("The feedback blows [user]'s arm off!","The spell bounces from [M]'s skin back into your arm!")
+ user.flash_act()
+ var/obj/item/bodypart/part
+ var/index = user.get_held_index_of_item(src)
+ if(index)
+ part = user.hand_bodyparts[index]
+ if(part)
+ part.dismember()
+ ..()
+ return
M.gib()
..()
@@ -78,6 +92,11 @@
to_chat(user, "You can't get the words out!")
return
var/mob/living/M = target
+ if(M.anti_magic_check())
+ to_chat(user, "The spell can't seem to affect [M]!")
+ to_chat(M, "You feel your flesh turn to stone for a moment, then revert back!")
+ ..()
+ return
M.Stun(40)
M.petrify()
..()
diff --git a/code/modules/spells/spell_types/inflict_handler.dm b/code/modules/spells/spell_types/inflict_handler.dm
index 6a8c82e73772..da0af7a6013f 100644
--- a/code/modules/spells/spell_types/inflict_handler.dm
+++ b/code/modules/spells/spell_types/inflict_handler.dm
@@ -19,10 +19,14 @@
var/summon_type = null //this will put an obj at the target's location
-/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets,mob/user = usr)
+ var/check_anti_magic = TRUE
+ var/check_holy = FALSE
+/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets,mob/user = usr)
for(var/mob/living/target in targets)
playsound(target,sound, 50,1)
+ if(target.anti_magic_check(check_anti_magic, check_holy))
+ return
switch(destroys)
if("gib")
target.gib()
diff --git a/code/modules/spells/spell_types/lightning.dm b/code/modules/spells/spell_types/lightning.dm
index 5726849a98b4..784537238ff8 100644
--- a/code/modules/spells/spell_types/lightning.dm
+++ b/code/modules/spells/spell_types/lightning.dm
@@ -65,6 +65,9 @@
/obj/effect/proc_holder/spell/targeted/tesla/proc/Bolt(mob/origin,mob/target,bolt_energy,bounces,mob/user = usr)
origin.Beam(target,icon_state="lightning[rand(1,12)]",time=5)
var/mob/living/carbon/current = target
+ if(current.anti_magic_check())
+ playsound(get_turf(current), 'sound/magic/lightningshock.ogg', 50, 1, -1)
+ current.visible_message("[current] absorbs the spell, remaining unharmed!", "You absorb the spell, remaining unharmed!")
if(bounces < 1)
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
playsound(get_turf(current), 'sound/magic/lightningshock.ogg', 50, 1, -1)
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
index 2fc6a7381ab3..c08557649bd1 100644
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ b/code/modules/spells/spell_types/mind_transfer.dm
@@ -54,7 +54,7 @@ Also, you never added distance checking after target is selected. I've went ahea
return
var/datum/mind/TM = target.mind
- if((TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
+ if((target.anti_magic_check() || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!")
return
diff --git a/code/modules/spells/spell_types/rod_form.dm b/code/modules/spells/spell_types/rod_form.dm
index dc77615307f2..06f38b83462d 100644
--- a/code/modules/spells/spell_types/rod_form.dm
+++ b/code/modules/spells/spell_types/rod_form.dm
@@ -45,5 +45,9 @@
return ..()
/obj/effect/immovablerod/wizard/penetrate(mob/living/L)
+ if(L.anti_magic_check())
+ L.visible_message("[src] hits [L], but it bounces back, then vanishes!" , "[src] hits you... but it bounces back, then vanishes!" , "You hear a weak, sad, CLANG.")
+ qdel(src)
+ return
L.visible_message("[L] is penetrated by an immovable rod!" , "The rod penetrates you!" , "You hear a CLANG!")
L.adjustBruteLoss(70 + damage_bonus)
diff --git a/code/modules/spells/spell_types/spacetime_distortion.dm b/code/modules/spells/spell_types/spacetime_distortion.dm
index ed6abe1410d9..eebff54d6bed 100644
--- a/code/modules/spells/spell_types/spacetime_distortion.dm
+++ b/code/modules/spells/spell_types/spacetime_distortion.dm
@@ -85,6 +85,10 @@
dir = pick(GLOB.cardinals)
/obj/effect/cross_action/spacetime_dist/proc/walk_link(atom/movable/AM)
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.anti_magic_check())
+ return
if(linked_dist && walks_left > 0)
flick("purplesparkles", src)
linked_dist.get_walker(AM)
diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm
index b36dfc885de5..3d7894f98d4d 100644
--- a/code/modules/spells/spell_types/wizard.dm
+++ b/code/modules/spells/spell_types/wizard.dm
@@ -258,6 +258,7 @@
sound = 'sound/magic/repulse.ogg'
var/maxthrow = 5
var/sparkle_path = /obj/effect/temp_visual/gravpush
+ var/anti_magic_check = TRUE
action_icon_state = "repulse"
@@ -275,6 +276,11 @@
if(AM == user || AM.anchored)
continue
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.anti_magic_check(anti_magic_check, FALSE))
+ continue
+
throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user)))
distfromcaster = get_dist(user, AM)
if(distfromcaster == 0)
@@ -304,6 +310,7 @@
action_icon = 'icons/mob/actions/actions_xeno.dmi'
action_icon_state = "tailsweep"
action_background_icon_state = "bg_alien"
+ anti_magic_check = FALSE
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno/cast(list/targets,mob/user = usr)
if(iscarbon(user))
@@ -328,10 +335,13 @@
/obj/effect/proc_holder/spell/targeted/sacred_flame/cast(list/targets, mob/user = usr)
for(var/mob/living/L in targets)
+ if(L.anti_magic_check(TRUE, TRUE))
+ continue
L.adjust_fire_stacks(20)
if(isliving(user))
var/mob/living/U = user
- U.IgniteMob()
+ if(!U.anti_magic_check(TRUE, TRUE))
+ U.IgniteMob()
/obj/effect/proc_holder/spell/targeted/conjure_item/spellpacket
name = "Thrown Lightning"
@@ -356,7 +366,8 @@
if(!..())
if(isliving(hit_atom))
var/mob/living/M = hit_atom
- M.electrocute_act(80, src, illusion = 1)
+ if(!M.anti_magic_check())
+ M.electrocute_act(80, src, illusion = 1)
qdel(src)
/obj/item/spellpacket/lightningbolt/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 496647acfa22..a07722cb3b64 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -139,7 +139,7 @@
message = lowertext(message)
var/mob/living/list/listeners = list()
for(var/mob/living/L in get_hearers_in_view(8, user))
- if(L.can_hear() && !L.null_rod_check() && L.stat != DEAD)
+ if(L.can_hear() && !L.anti_magic_check(FALSE, TRUE) && L.stat != DEAD)
if(L == user && !include_speaker)
continue
if(ishuman(L))
diff --git a/tgstation.dme b/tgstation.dme
index 71036d5de68d..4730334a7f34 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -298,6 +298,7 @@
#include "code\datums\brain_damage\special.dm"
#include "code\datums\brain_damage\split_personality.dm"
#include "code\datums\components\_component.dm"
+#include "code\datums\components\anti_magic.dm"
#include "code\datums\components\archaeology.dm"
#include "code\datums\components\caltrop.dm"
#include "code\datums\components\chasm.dm"