Refactors anti-magic into a component (#35639)

* Refactors anti-magic into a component

* plenty o stuff, mainly holy and antimagic traits

* fix

* fix2

* moved to components, moved some of the logic to the component

* don't blame me if the code looks copypastey

* right
This commit is contained in:
XDTM
2018-02-25 21:45:12 +01:00
committed by oranges
parent c7efd2b6a3
commit 2ac902ab3c
42 changed files with 315 additions and 65 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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))

View File

@@ -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("<span class='suicide'>[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!</span>")
return (BRUTELOSS|FIRELOSS)

View File

@@ -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("<span class='suicide'>[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (BRUTELOSS)

View File

@@ -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("<span class='warning'>[L]'s [I.name] [resist_string], protecting them from [src]'s effects!</span>", \
"<span class='userdanger'>Your [I.name] [resist_string], protecting you!</span>")
if(isitem(I))
L.visible_message("<span class='warning'>[L]'s [I.name] [resist_string], protecting them from [src]'s effects!</span>", \
"<span class='userdanger'>Your [I.name] [resist_string], protecting you!</span>")
return
sigil_effects(L)

View File

@@ -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("<span class='warning'>[L]'s eyes flare with dim light as they stumble!</span>", \
"<span class='userdanger'>Your [O] glows white-hot against you as it absorbs some sort of power!</span>")
L.adjustFireLoss(5)
L.Stun(40)
if(isitem(O))
L.visible_message("<span class='warning'>[L]'s eyes flare with dim light!</span>", \
"<span class='userdanger'>Your [O] glows white-hot against you as it absorbs [src]'s power!</span>")
else if(ismob(O))
L.visible_message("<span class='warning'>[L]'s eyes flare with dim light!</span>")
playsound(L, 'sound/weapons/sear.ogg', 50, TRUE)
else
L.visible_message("<span class='warning'>[L]'s eyes blaze with brilliant light!</span>", \

View File

@@ -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("<span class='warning'>[target] shudders violently at [src]'s touch!</span>", "<span class='userdanger'>ERROR: Temperature rising!</span>")
@@ -55,7 +55,7 @@
else
L.visible_message("<span class='warning'>[src] bounces off of [L], as if repelled by an unseen force!</span>")
else if(!..())
if(!L.null_rod_check())
if(!L.anti_magic_check())
if(issilicon(L) || iscultist(L))
L.Knockdown(100)
else

View File

@@ -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("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
if(L.anti_magic_check())
var/atom/I = L.anti_magic_check()
if(isitem(I))
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
continue
L.Knockdown(15) //knocks down briefly when exploding
if(!iscultist(L))

View File

@@ -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

View File

@@ -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)

View File

@@ -681,7 +681,7 @@
else
L.visible_message("<span class='warning'>[src] bounces off of [L], as if repelled by an unseen force!</span>")
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("<span class='warning'>[src] bounces off of [L], as if repelled by an unseen force!</span>")
else if(!..())
if(!L.null_rod_check())
if(!L.anti_magic_check())
if(is_servant_of_ratvar(L))
L.Knockdown(60)
else

View File

@@ -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, "<span class='warning'>You need more invokers to convert [convertee]!</span>")
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, "<span class='warning'>Something is shielding [convertee]'s mind!</span>")
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, "<span class='userdanger'>\The [N] suddenly burns hotly before returning to normal!</span>")
var/atom/I = L.anti_magic_check()
if(I)
if(isitem(I))
to_chat(L, "<span class='userdanger'>[I] suddenly burns hotly before returning to normal!</span>")
continue
to_chat(L, "<span class='cultlarge'>Your blood boils in your veins!</span>")
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))

View File

@@ -54,6 +54,11 @@
reveal(46)
stun(46)
target.visible_message("<span class='warning'>[target] suddenly rises slightly into the air, [target.p_their()] skin turning an ashy gray.</span>")
if(target.anti_magic_check(FALSE, TRUE))
to_chat(src, "<span class='revenminor'>Something's wrong! [target] seems to be resisting the siphoning, leaving you vulnerable!</span>")
target.visible_message("<span class='warning'>[target] slumps onto the ground.</span>", \
"<span class='revenwarning'>Violets lights, dancing in your vision, receding--</span>")
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, "<span class='revenboldnotice'>You transmit to [M]:</span> <span class='revennotice'>[msg]</span>")
to_chat(M, "<span class='revenboldnotice'>You hear something behind you talking...</span> <span class='revennotice'>[msg]</span>")
if(!M.anti_magic_check(FALSE, TRUE)) //hear no evil
to_chat(M, "<span class='revenboldnotice'>You hear something behind you talking...</span> <span class='revennotice'>[msg]</span>")
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, "<span class='revenwarning'>You feel [pick("your sense of direction flicker out", "a stabbing pain in your head", "your mind fill with static")].</span>")
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))

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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()

View File

@@ -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)

View File

@@ -69,6 +69,14 @@
info_text = "As an <span class='danger'>Adamantine Golem</span>, 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

View File

@@ -87,6 +87,10 @@
to_chat(H, "<span class='notice'>[victim] doesn't have blood!</span>")
return
V.drain_cooldown = world.time + 30
if(victim.anti_magic_check(FALSE, TRUE))
to_chat(victim, "<span class='warning'>[H] tries to bite you, but stops before touching you!</span>")
to_chat(H, "<span class='warning'>[victim] is blessed! You stop just in time to avoid catching fire.</span>")
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

View File

@@ -15,6 +15,9 @@
. = ..()
if(ismob(target))
var/mob/M = target
if(M.anti_magic_check())
M.visible_message("<span class='warning'>[src] vanishes on contact with [target]!</span>")
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("<span class='warning'>[src] vanishes on contact with [target]!</span>")
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("<span class='warning'>[src] fizzles on contact with [target]!</span>")
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("<span class='warning'>[src] fizzles on contact with [M]!</span>")
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("<span class='warning'>[src] vanishes on contact with [target]!</span>")
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("<span class='warning'>[src] vanishes on contact with [target]!</span>")
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("<span class='warning'>[src] fizzles on contact with [target]!</span>")
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("<span class='warning'>[src] vanishes into smoke on contact with [target]!</span>")
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)

View File

@@ -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, "<span class='userdanger'>A darkness begins to spread its unholy tendrils through your mind, purging the Justiciar's influence!</span>")
@@ -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"

View File

@@ -31,6 +31,12 @@
to_chat(user, "<span class='notice'>They are too far away!</span>")
return
if(target.anti_magic_check())
to_chat(user, "<span class='warning'>The spell had no effect!</span>")
target.visible_message("<span class='danger'>[target]'s face bursts into flames, which instantly burst outward, leaving [target] unharmed!</span>", \
"<span class='danger'>Your face starts burning up, but the flames are repulsed by your anti-magic protection!</span>")
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)

View File

@@ -202,6 +202,10 @@
revert_cast()
return
if(target.anti_magic_check(TRUE, TRUE))
to_chat(target, "<span class='warning'>You feel a freezing darkness closing in on you, but it rapidly dissipates.</span>")
return
to_chat(target, "<span class='userdanger'>A freezing darkness surrounds you...</span>")
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"

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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("<span class='warning'>[target]'s [A] glows brightly as it wards off the spell!</span>")
user.visible_message("<span class='warning'>The feedback blows [user]'s arm off!</span>","<span class='userdanger'>The spell bounces from [M]'s skin back into your arm!</span>")
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, "<span class='notice'>You can't get the words out!</span>")
return
var/mob/living/M = target
if(M.anti_magic_check())
to_chat(user, "<span class='warning'>The spell can't seem to affect [M]!</span>")
to_chat(M, "<span class='warning'>You feel your flesh turn to stone for a moment, then revert back!</span>")
..()
return
M.Stun(40)
M.petrify()
..()

View File

@@ -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()

View File

@@ -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("<span class='warning'>[current] absorbs the spell, remaining unharmed!</span>", "<span class='userdanger'>You absorb the spell, remaining unharmed!</span>")
if(bounces < 1)
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
playsound(get_turf(current), 'sound/magic/lightningshock.ogg', 50, 1, -1)

View File

@@ -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, "<span class='warning'>[target.p_their(TRUE)] mind is resisting your spell!</span>")
return

View File

@@ -45,5 +45,9 @@
return ..()
/obj/effect/immovablerod/wizard/penetrate(mob/living/L)
if(L.anti_magic_check())
L.visible_message("<span class='danger'>[src] hits [L], but it bounces back, then vanishes!</span>" , "<span class='userdanger'>[src] hits you... but it bounces back, then vanishes!</span>" , "<span class ='danger'>You hear a weak, sad, CLANG.</span>")
qdel(src)
return
L.visible_message("<span class='danger'>[L] is penetrated by an immovable rod!</span>" , "<span class='userdanger'>The rod penetrates you!</span>" , "<span class ='danger'>You hear a CLANG!</span>")
L.adjustBruteLoss(70 + damage_bonus)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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))

View File

@@ -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"