Merges tinfoil (hat) protection into the anti_magic component. Implements it on Hivemind gamemode and telepathy.

This commit is contained in:
yogstation13-bot
2019-05-30 09:27:43 +01:00
parent 25c9801794
commit 72efa0c444
31 changed files with 262 additions and 114 deletions

View File

@@ -135,7 +135,7 @@
#define COMSIG_MOB_CLICKON "mob_clickon" //from base of mob/clickon(): (atom/A, params)
#define COMSIG_MOB_CANCEL_CLICKON 1
#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (mob/user, magic, holy, major, self, protection_sources)
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
#define COMPONENT_BLOCK_MAGIC 1
#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //from base of mob/create_mob_hud(): ()
#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //from base of

View File

@@ -1,12 +1,14 @@
/datum/component/anti_magic
var/magic = FALSE
var/holy = FALSE
var/psychic = FALSE
var/allowed_slots = ITEM_SLOT_BACK|ITEM_SLOT_MASK|ITEM_SLOT_NECK|ITEM_SLOT_BELT|ITEM_SLOT_ID|ITEM_SLOT_EARS|ITEM_SLOT_EYES|ITEM_SLOT_GLOVES|ITEM_SLOT_HEAD|ITEM_SLOT_FEET|ITEM_SLOT_OCLOTHING|ITEM_SLOT_ICLOTHING|ITEM_SLOT_POCKET
var/charges = INFINITY
var/blocks_self = TRUE
var/datum/callback/reaction
var/datum/callback/expire
/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE, _charges, _blocks_self = TRUE, datum/callback/_reaction, datum/callback/_expire)
/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE, _psychic = FALSE, _allowed_slots, _charges, _blocks_self = TRUE, datum/callback/_reaction, datum/callback/_expire)
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
@@ -17,6 +19,9 @@
magic = _magic
holy = _holy
psychic = _psychic
if(_allowed_slots)
allowed_slots = _allowed_slots
if(!isnull(_charges))
charges = _charges
blocks_self = _blocks_self
@@ -24,7 +29,7 @@
expire = _expire
/datum/component/anti_magic/proc/on_equip(datum/source, mob/equipper, slot)
if(slot == SLOT_IN_BACKPACK)
if(!CHECK_BITFIELD(allowed_slots, slotdefine2slotbit(slot)))
UnregisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC)
return
RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/protect, TRUE)
@@ -32,12 +37,11 @@
/datum/component/anti_magic/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, COMSIG_MOB_RECEIVE_MAGIC)
/datum/component/anti_magic/proc/protect(datum/source, mob/user, _magic, _holy, major, self, list/protection_sources)
if(((_magic && magic) || (_holy && holy)) && (!self || blocks_self))
/datum/component/anti_magic/proc/protect(datum/source, mob/user, _magic, _holy, _psychic, chargecost, self, list/protection_sources)
if(((_magic && magic) || (_holy && holy) || (_psychic && psychic)) && (!self || blocks_self))
protection_sources += parent
reaction?.Invoke(user, major)
if(major)
charges--
reaction?.Invoke(user, chargecost)
charges -= chargecost
if(charges <= 0)
expire?.Invoke(user)
return COMPONENT_BLOCK_MAGIC

View File

@@ -59,7 +59,7 @@
/obj/effect/proc_holder/spell/targeted/mindread/cast(list/targets, mob/living/carbon/human/user = usr)
for(var/mob/living/M in targets)
if(istype(usr.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat) || istype(M.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
if(usr.anti_magic_check(FALSE, FALSE, TRUE, 0) || M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(usr, "<span class='warning'>As you reach out with your mind, you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
if(M.stat == DEAD)

View File

@@ -229,7 +229,7 @@
/datum/status_effect/belligerent/proc/do_movement_toggle(force_damage)
var/number_legs = owner.get_num_legs(FALSE)
if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check(major = FALSE) && number_legs)
if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check(chargecost = 0) && number_legs)
if(force_damage || owner.m_intent != MOVE_INTENT_WALK)
if(GLOB.ratvar_awakens)
owner.Paralyze(20)
@@ -322,7 +322,7 @@
if(owner.confused)
owner.confused = 0
severity = 0
else if(!owner.anti_magic_check(major = FALSE) && owner.stat != DEAD && severity)
else if(!owner.anti_magic_check(chargecost = 0) && 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

@@ -181,7 +181,7 @@
/obj/item/nullrod/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE, null, FALSE)
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/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>")

View File

@@ -342,8 +342,8 @@
if(QDELETED(G))
return
if(istype(C.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>Your target seems to have some sort of protective headgear on, blocking the message from being sent!</span>")
if(C.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>Your target seems to have some sort of tinfoil protection on, blocking the message from being sent!</span>")
return
G.mind_control(command, user)
@@ -517,10 +517,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/abductor/baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.incapacitated(TRUE, TRUE))
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>The specimen's protective headgear is interfering with the sleep inducement!</span>")
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] headgear protected [L.p_them()]!</span>", \
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your headgear deflects most of it!</span>")
if(L.anti_magic_check(FALSE, FALSE, TRUE))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is interfering with the sleep inducement!</span>")
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] tinfoil protection [L.p_them()]!</span>", \
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your tinfoil protection deflects most of it!</span>")
L.drowsyness += 2
return
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
@@ -529,10 +529,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
L.Sleeping(1200)
log_combat(user, L, "put to sleep")
else
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>The specimen's protective headgear is completely blocking our sleep inducement methods!</span>")
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] headgear completely protected [L.p_them()]!</span>", \
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your headgear deflects the effects!</span>")
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is completely blocking our sleep inducement methods!</span>")
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] tinfoil protection completely protected [L.p_them()]!</span>", \
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your tinfoil protection deflects the effects!</span>")
return
L.drowsyness += 1
to_chat(user, "<span class='warning'>Sleep inducement works fully only on stunned specimens! </span>")

View File

@@ -181,8 +181,8 @@
c.console = src
/obj/machinery/abductor/console/proc/AddSnapshot(mob/living/carbon/human/target)
if(istype(target.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
say("Subject wearing specialized protective headgear, unable to get a proper scan!")
if(target.anti_magic_check(FALSE, FALSE, TRUE, 0))
say("Subject wearing specialized protective tinfoil gear, unable to get a proper scan!")
return
var/datum/icon_snapshot/entry = new
entry.name = target.name

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.anti_magic_check(major = FALSE) && !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(chargecost = 0) && !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>")

View File

@@ -59,6 +59,7 @@
if(target)
if(!(target in validtargets))
lose_target()
<<<<<<< HEAD
else //yogs start: slows warden attack speed so it doesn't stop people from moving
if(last_process + time_between_shots < world.time)
if(isliving(target))
@@ -72,6 +73,16 @@
R.reveal(10)
if(prob(50))
L.playsound_local(null,'sound/machines/clockcult/ocularwarden-dot1.ogg',75 * get_efficiency_mod(),1)
=======
else
if(isliving(target))
var/mob/living/L = target
if(!L.anti_magic_check(chargecost = 0))
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
if(R.revealed)
R.unreveal_time += 2
>>>>>>> 17b3091867... Merges tinfoil (hat) protection into the anti_magic component. Implements it on Hivemind gamemode and telepathy. (#43978)
else
L.playsound_local(null,'sound/machines/clockcult/ocularwarden-dot2.ogg',75 * get_efficiency_mod(),1)
L.adjustFireLoss((!iscultist(L) ? damage_per_tick : damage_per_tick * 2) * get_efficiency_mod()) //Nar-Sian cultists take additional damage

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.anti_magic_check(major = FALSE))
if(!L.anti_magic_check(chargecost = 0))
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)

View File

@@ -237,7 +237,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "<span class='danger'>You need at least two invokers to convert [convertee]!</span>")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
if(convertee.anti_magic_check(TRUE, TRUE, major = FALSE)) //Not major because it can be spammed
if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
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 anti-magic")
@@ -767,7 +767,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/atom/I = L.anti_magic_check(major = FALSE)
var/atom/I = L.anti_magic_check(chargecost = 0)
if(I)
if(isitem(I))
to_chat(L, "<span class='userdanger'>[I] suddenly burns hotly before returning to normal!</span>")
@@ -797,7 +797,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)
if(L.anti_magic_check(major = FALSE))
if(L.anti_magic_check(chargecost = 0))
continue
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
if(is_servant_of_ratvar(L))

View File

@@ -115,6 +115,7 @@
notice = "revennotice"
boldnotice = "revenboldnotice"
holy_check = TRUE
tinfoil_check = FALSE
/obj/effect/proc_holder/spell/aoe_turf/revenant
clothes_req = 0

View File

@@ -266,10 +266,17 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = -5,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = -5, "fire" = 0, "acid" = 0)
equip_delay_other = 140
var/datum/brain_trauma/mild/phobia/conspiracies/paranoia
var/warped = FALSE
/obj/item/clothing/head/foilhat/Initialize(mapload)
. = ..()
if(!warped)
AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE, ITEM_SLOT_HEAD, 6, TRUE, null, CALLBACK(src, .proc/warp_up))
/obj/item/clothing/head/foilhat/equipped(mob/living/carbon/human/user, slot)
..()
if(slot == SLOT_HEAD)
. = ..()
if(slot != SLOT_HEAD || warped)
return
if(paranoia)
QDEL_NULL(paranoia)
paranoia = new()
@@ -278,15 +285,48 @@
user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC)
to_chat(user, "<span class='warning'>As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. </span>")
<<<<<<< HEAD
=======
/obj/item/clothing/head/foilhat/MouseDrop(atom/over_object)
//God Im sorry
if(!warped && iscarbon(usr))
var/mob/living/carbon/C = usr
if(src == C.head)
to_chat(C, "<span class='userdanger'>Why would you want to take this off? Do you want them to get into your mind?!</span>")
return
return ..()
>>>>>>> 17b3091867... Merges tinfoil (hat) protection into the anti_magic component. Implements it on Hivemind gamemode and telepathy. (#43978)
/obj/item/clothing/head/foilhat/dropped(mob/user)
..()
. = ..()
if(paranoia)
QDEL_NULL(paranoia)
/obj/item/clothing/head/foilhat/proc/warp_up()
name = "scorched tinfoil hat"
desc = "A badly warped up hat. Quite unprobable this will still work against any of fictional and contemporary dangers it used to."
warped = TRUE
var/datum/component/anti_magic/C = GetComponent(/datum/component/anti_magic)
C.RemoveComponent()
if(!isliving(loc))
return
var/mob/living/target = loc
if(target.get_item_by_slot(SLOT_HEAD) != src)
return
QDEL_NULL(paranoia)
if(!target.IsUnconscious())
to_chat(target, "<span class='warning'>Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.</span>")
/obj/item/clothing/head/foilhat/attack_hand(mob/user)
if(iscarbon(user))
if(!warped && iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.head)
to_chat(user, "<span class='userdanger'>Why would you want to take this off? Do you want them to get into your mind?!</span>")
return
..()
return ..()
/obj/item/clothing/head/foilhat/microwave_act(obj/machinery/microwave/M)
. = ..()
if(!warped)
warp_up()

View File

@@ -423,7 +423,7 @@
/obj/item/clothing/suit/space/hardsuit/wizard/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, FALSE, INFINITY, FALSE)
AddComponent(/datum/component/anti_magic, TRUE, FALSE, FALSE, null, INFINITY, FALSE)
//Medical hardsuit

View File

@@ -329,6 +329,10 @@ Contains:
actions_types = list()
resistance_flags = FIRE_PROOF
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE)
/obj/item/clothing/suit/space/hardsuit/ert/paranormal
name = "paranormal response team hardsuit"
desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats."

View File

@@ -63,7 +63,7 @@
var/uses = 1
if(seed)
uses = round(seed.potency / 20)
AddComponent(/datum/component/anti_magic, TRUE, TRUE, uses, TRUE, CALLBACK(src, .proc/block_magic), CALLBACK(src, .proc/expire)) //deliver us from evil o melon god
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, uses, TRUE, CALLBACK(src, .proc/block_magic), CALLBACK(src, .proc/expire)) //deliver us from evil o melon god
/obj/item/reagent_containers/food/snacks/grown/holymelon/proc/block_magic(mob/user, major)
if(major)

View File

@@ -457,7 +457,7 @@
/obj/item/immortality_talisman/Initialize()
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE)
AddComponent(/datum/component/anti_magic, TRUE, TRUE, TRUE)
/datum/action/item_action/immortality
name = "Immortality"

View File

@@ -95,8 +95,14 @@ Doesn't work on other aliens/AI.*/
var/mob/living/M = input("Select who to whisper to:","Whisper to?",null) as null|mob in options
if(!M)
return 0
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='noticealien'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return FALSE
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
log_directed_talk(user, M, msg, LOG_SAY, tag="alien whisper")
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...</span>[msg]")
to_chat(user, "<span class='noticealien'>You said: \"[msg]\" to [M]</span>")

View File

@@ -595,6 +595,8 @@
return FALSE
if(M.has_trait(TRAIT_MINDSHIELD)) //mindshield implant, no dice
return FALSE
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
return FALSE
if(M in linked_mobs)
return FALSE
linked_mobs.Add(M)
@@ -680,9 +682,14 @@
var/mob/living/M = input("Select who to send your message to:","Send thought to?",null) as null|mob in options
if(!M)
return
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(H, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
var/msg = sanitize(input("Message:", "Telepathy") as text|null)
if(msg)
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(H, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
log_directed_talk(H, M, msg, LOG_SAY, "slime telepathy")
to_chat(M, "<span class='notice'>You hear an alien voice in your head... </span><font color=#008CA2>[msg]</font>")
to_chat(H, "<span class='notice'>You telepathically said: \"[msg]\" to [M]</span>")

View File

@@ -95,7 +95,7 @@
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, FALSE))
if(victim.anti_magic_check(FALSE, TRUE, FALSE, 0))
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

View File

@@ -986,7 +986,7 @@
apply_effect((amount*RAD_MOB_COEFFICIENT)/max(1, (radiation**2)*RAD_OVERDOSE_REDUCTION), EFFECT_IRRADIATE, blocked)
/mob/living/anti_magic_check(magic = TRUE, holy = FALSE, major = TRUE, self = FALSE)
/mob/living/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE)
. = ..()
if(.)
return

View File

@@ -704,11 +704,11 @@
mob_spell_list -= S
qdel(S)
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, major = TRUE, self = FALSE)
if(!magic && !holy)
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE)
if(!magic && !holy && !tinfoil)
return
var/list/protection_sources = list()
if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, src, magic, holy, major, self, protection_sources) & COMPONENT_BLOCK_MAGIC)
if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, src, magic, holy, tinfoil, chargecost, self, protection_sources) & COMPONENT_BLOCK_MAGIC)
if(protection_sources.len)
return pick(protection_sources)
else

View File

@@ -33,7 +33,7 @@
return
else
no_den_usage = 0
if(checks_antimagic && user.anti_magic_check(TRUE, FALSE, major = FALSE, self = TRUE))
if(checks_antimagic && user.anti_magic_check(TRUE, FALSE, FALSE, 0, TRUE))
add_fingerprint(user)
to_chat(user, "<span class='warning'>Something is interfering with [src].</span>")
return

View File

@@ -167,7 +167,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
return FALSE
if(!antimagic_allowed)
var/antimagic = user.anti_magic_check(TRUE, FALSE, major = FALSE, self = TRUE)
var/antimagic = user.anti_magic_check(TRUE, FALSE, FALSE, 0, TRUE)
if(antimagic)
if(isitem(antimagic))
to_chat(user, "<span class='notice'>[antimagic] is interfering with your magic.</span>")
@@ -513,7 +513,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(user.stat && !stat_allowed)
return FALSE
if(!antimagic_allowed && user.anti_magic_check(TRUE, FALSE, major = FALSE, self = TRUE))
if(!antimagic_allowed && user.anti_magic_check(TRUE, FALSE, FALSE, 0, TRUE))
return FALSE
if(!ishuman(user))

View File

@@ -16,12 +16,9 @@ GLOBAL_VAR_INIT(curse_of_madness_triggered, FALSE)
var/turf/T = get_turf(H)
if(T && !is_station_level(T.z))
continue
if(H.anti_magic_check(TRUE, FALSE))
if(H.anti_magic_check(TRUE, FALSE, TRUE))
to_chat(H, "<span class='notice'>You have a strange feeling for a moment, but then it passes.</span>")
continue
if(istype(H.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(H, "<span class='warning'>Your protective headgear successfully deflects mind controlling brainwaves!</span>")
continue
give_madness(H, message)
/proc/give_madness(mob/living/carbon/human/H, message)

View File

@@ -35,6 +35,6 @@
return TRUE
if(ismob(mover))
var/mob/M = mover
if(M.anti_magic_check(major = FALSE))
if(M.anti_magic_check(chargecost = 0))
return TRUE
return FALSE

View File

@@ -49,13 +49,13 @@
charge_max = 50
range = 7
target_external = 1
var/ignore_mindshield = FALSE
var/bruteforce = FALSE
/obj/effect/proc_holder/spell/target_hive/hive_add/cast(list/targets, mob/living/user = usr)
var/mob/living/carbon/target = targets[1]
var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind)
var/success = FALSE
<<<<<<< HEAD
if(target.mind && target.client && target.stat != DEAD)
if(!target.has_trait(TRAIT_MINDSHIELD) || ignore_mindshield)
if(target.has_trait(TRAIT_MINDSHIELD) && ignore_mindshield)
@@ -84,9 +84,42 @@
else
to_chat(user, "<span class='warning'>Powerful technology protects [target.name]'s mind.</span>")
else
=======
if(!target.mind || !target.client || target.stat == DEAD)
>>>>>>> 17b3091867... Merges tinfoil (hat) protection into the anti_magic component. Implements it on Hivemind gamemode and telepathy. (#43978)
to_chat(user, "<span class='notice'>We detect no neural activity in this body.</span>")
if(!success)
var/shielded = HAS_TRAIT(target, TRAIT_MINDSHIELD)
var/foiled = target.anti_magic_check(FALSE, FALSE, TRUE, 0)
if(shielded && !bruteforce)
to_chat(user, "<span class='warning'>Powerful technology protects [target.name]'s mind.</span>")
revert_cast()
return
if((shielded || foiled) && bruteforce)
to_chat(user, "<span class='notice'>We [bruteforce ? "bruteforce" : "force"] our way past the mental barriers of [target.name] and begin linking our minds!</span>")
else
to_chat(user, "<span class='notice'>We begin linking our mind with [target.name]!</span>")
var/multiplier = (!foiled || bruteforce) ? 5 : 10
if(!do_after(user,multiplier*(1.5**get_dist(user, target)),0,user) || !(target in view(range)))
to_chat(user, "<span class='notice'>We fail to connect to [target.name].</span>")
revert_cast()
return
if((HAS_TRAIT(target, TRAIT_MINDSHIELD) && !bruteforce))
to_chat(user, "<span class='notice'>We fail to connect to [target.name].</span>")
revert_cast()
return
to_chat(user, "<span class='notice'>[target.name] was added to the Hive!</span>")
hive.add_to_hive(target)
hive.threat_level = max(0, hive.threat_level-0.1)
if(bruteforce)
if(target.anti_magic_check(FALSE, FALSE, TRUE, 6))
target.adjustBrainLoss(10)
to_chat(user, "<span class='warning'>We are briefly exhausted by the effort required by our enhanced assimilation abilities.</span>")
user.Immobilize(50)
SEND_SIGNAL(target, COMSIG_NANITE_SET_VOLUME, 0)
for(var/obj/item/implant/mindshield/M in target.implants)
qdel(M)
else
target.anti_magic_check(FALSE, FALSE, TRUE)
/obj/effect/proc_holder/spell/target_hive/hive_remove
name = "Release Vessel"
@@ -124,6 +157,7 @@
action_icon_state = "see"
var/mob/living/carbon/vessel
var/mob/living/host //Didn't really have any other way to auto-reset the perspective if the other mob got qdeled
var/limited = FALSE
charge_max = 20
@@ -135,6 +169,13 @@
if(!active)
vessel = targets[1]
if(vessel)
if(vessel.anti_magic_check(FALSE, FALSE, TRUE, 0))
if(get_dist(src, vessel) > 42)
to_chat(user, "<span class='warning'>We were unable to link our view with [vessel.name]. A barrier of tinfoil prevents us to do so at this distance.</span>")
revert_cast()
return
limited = TRUE
to_chat(user, "<span class='warning'>A barrier of tinfoil drastically dampens our link with [vessel.name]. We'll be able to sustain the link as long as they remain within 42 tiles from us.</span>")
vessel.apply_status_effect(STATUS_EFFECT_BUGGED, user)
user.reset_perspective(vessel)
active = TRUE
@@ -150,14 +191,16 @@
if(the_spell && the_spell.active)
user.overlay_fullscreen("hive_mc", /obj/screen/fullscreen/hive_mc)
active = FALSE
limited = FALSE
revert_cast()
/obj/effect/proc_holder/spell/target_hive/hive_see/process()
if(active && (!vessel || !is_hivemember(vessel) || QDELETED(vessel)))
if(active && (!vessel || !is_hivemember(vessel) || QDELETED(vessel) || (limited && get_dist(vessel, host) > 42)))
to_chat(host, "<span class='warning'>Our vessel is one of us no more!</span>")
host.reset_perspective()
host.clear_fullscreen("hive_eyes")
active = FALSE
limited = FALSE
if(!QDELETED(vessel))
vessel.remove_status_effect(STATUS_EFFECT_BUGGED)
..()
@@ -195,6 +238,8 @@
power *= 2.5
else
power *= 3
if(target.anti_magic_check(FALSE, FALSE, TRUE))
power *= 0.5
if(power > 50 && user.z == target.z)
to_chat(user, "<span class='notice'>We have overloaded the vessel for a short time!</span>")
target.Jitter(round(power/10))
@@ -239,7 +284,8 @@
if(user.z != L.z || L.stat == DEAD)
message += " could not be found."
else
switch(distance)
var/multiplier = L.anti_magic_check(FALSE, FALSE, TRUE) ? rand(0.6, 1.4) : 1
switch(distance*multiplier)
if(0 to 2)
message += " is right next to us!"
if(2 to 14)
@@ -256,13 +302,15 @@
var/mob/living/carbon/C = enemy.owner?.current
if(!C)
continue
var/multiplier = C.anti_magic_check(FALSE, FALSE, TRUE) ? rand(0.6, 1.4) : 1
var/mob/living/real_enemy = C.get_real_hivehost()
distance = get_dist(user, real_enemy)
message = "A host that we can track for [(hive.individual_track_bonus[enemy])/10] extra seconds"
if(user.z != real_enemy.z || real_enemy.stat == DEAD)
message += " could not be found."
else
switch(distance)
multiplier = real_enemy.anti_magic_check(FALSE, FALSE, TRUE) ? rand(0.6, 1.4) : 1
switch(distance*multiplier)
if(0 to 2)
message += " is right next to us!"
if(2 to 14)
@@ -310,11 +358,12 @@
if(!target)
to_chat(user, "<span class='warning'>We have run out of vessels to drain.</span>")
break
target.adjustBrainLoss(5)
var/regen = target.anti_magic_check(FALSE, FALSE, TRUE) ? 2.5 : 5
target.adjustBrainLoss(regen)
if(user.getBruteLoss() > user.getFireLoss())
user.heal_ordered_damage(5, list(CLONE, BRUTE, BURN))
user.heal_ordered_damage(regen, list(CLONE, BRUTE, BURN))
else
user.heal_ordered_damage(5, list(CLONE, BURN, BRUTE))
user.heal_ordered_damage(regen, list(CLONE, BURN, BRUTE))
if(!user.getBruteLoss() && !user.getFireLoss() && !user.getCloneLoss()) //If we don't have any of these, stop looping
to_chat(user, "<span class='warning'>We finish our healing</span>")
break
@@ -350,6 +399,7 @@
var/power = 600
var/time_initialized = 0
var/out_of_range = FALSE
var/restricted_range = FALSE
/obj/effect/proc_holder/spell/target_hive/hive_control/proc/release_control() //If the spell is active, force everybody into their original bodies if they exist, ghost them otherwise, delete the backseat
if(!active)
@@ -383,6 +433,8 @@
if(hive)
hive.threat_level += 1
restricted_range = FALSE
/obj/effect/proc_holder/spell/target_hive/hive_control/on_lose(mob/user)
release_control()
@@ -397,11 +449,15 @@
original_body = user
vessel = targets[1]
to_chat(user, "<span class='notice'>We begin merging our mind with [vessel.name].</span>")
if(!do_after(user,50,0,user))
var/timely = 50
if(vessel.anti_magic_check(FALSE, FALSE, TRUE))
timely = 100
restricted_range = TRUE
if(!do_after(user, timely, FALSE, user))
to_chat(user, "<span class='notice'>We fail to assume control of the target.</span>")
revert_cast()
return
if(user.z != vessel.z)
if(user.z != vessel.z || (restricted_range && get_dist(vessel, user) > 35))
to_chat(user, "<span class='notice'>Our vessel is too far away to control.</span>")
revert_cast()
return
@@ -448,6 +504,10 @@
else
release_control()
/obj/effect/proc_holder/spell/target_hive/hive_control/revert_cast()
. = ..()
restricted_range = FALSE
/obj/effect/proc_holder/spell/target_hive/hive_control/process()
if(active)
if(QDELETED(vessel)) //If we've been gibbed or otherwise deleted, ghost both of them and kill the original
@@ -466,20 +526,22 @@
else if(QDELETED(original_body) || original_body.stat == DEAD) //Return vessel to its body, either return or ghost the original
to_chat(vessel, "<span class='userdanger'>Our body has been destroyed, the hive cannot survive without its host!</span>")
release_control()
else if(!out_of_range && get_dist(starting_spot, vessel) > 14)
else
var/multiplier = restricted_range ? 0.5 : 1
if(!out_of_range && get_dist(starting_spot, vessel) > 14*multiplier)
out_of_range = TRUE
flash_color(vessel, flash_color="#800080", flash_time=10)
to_chat(vessel, "<span class='warning'>Our vessel has been moved too far away from the initial point of control, we will be disconnected if we go much further!</span>")
addtimer(CALLBACK(src, "range_check"), 30)
else if(get_dist(starting_spot, vessel) > 21)
addtimer(CALLBACK(src, .proc/range_check, multiplier), 30)
else if(get_dist(starting_spot, vessel) > 21*multiplier)
release_control()
..()
/obj/effect/proc_holder/spell/target_hive/hive_control/proc/range_check()
/obj/effect/proc_holder/spell/target_hive/hive_control/proc/range_check(multiplier = 1)
if(!active)
return
if(get_dist(starting_spot, vessel) > 14)
if(get_dist(starting_spot, vessel) > 14 * multiplier)
release_control()
out_of_range = FALSE
@@ -513,7 +575,7 @@
continue
target.Jitter(14)
target.apply_damage(35 + rand(0,15), STAMINA, target.get_bodypart(BODY_ZONE_HEAD))
if(target.is_real_hivehost())
if(target.is_real_hivehost() || target.anti_magic_check(FALSE, FALSE, TRUE))
continue
if(prob(20))
var/text = pick(":h Help!!",":h Run!",":h They're here!",":h Get out!",":h Hide!",":h Kill them!",":h Cult!",":h Changeling!",":h Traitor!",":h Nuke ops!",":h Revolutionaries!",":h Wizard!",":h Zombies!",":h Ghosts!",":h AI rogue!",":h Borgs emagged!",":h Maint!!",":h Dying!!",":h AI lock down the borgs law 1!",":h I'm losing control of the situation!!")
@@ -571,10 +633,18 @@
if(target.is_real_hivehost() || (!iscarbon(target) && !issilicon(target)))
continue
victims += target
var/sleepytime = max(80,240/(1+round(victims.len/3)))
for(var/mob/living/carbon/victim in victims)
victim.Sleeping(max(80,240/(1+round(victims.len/3))))
if(victim.anti_magic_check(FALSE, FALSE, TRUE))
to_chat(victim, "You suddendly feel so tired you could take a nap")
victim.apply_damage(max(30 - victims.len, 15), STAMINA, victim.get_bodypart(BODY_ZONE_HEAD))
victim.drowsyness += max(30 - victims.len, 15)
victim.confused += max(30 - victims.len, 15)
else
victim.Sleeping(sleepytime)
for(var/mob/living/silicon/victim in victims)
victim.Unconscious(240)
var/multiplier = victim.anti_magic_check(FALSE, FALSE, TRUE) ? 0.5 : 1
victim.Unconscious(sleepytime * multiplier)
var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind)
if(victims.len && hive)
hive.threat_level += 1
@@ -589,8 +659,15 @@
/obj/effect/proc_holder/spell/target_hive/hive_attack/cast(list/targets, mob/living/user = usr)
var/mob/living/carbon/target = targets[1]
if(!target.undergoing_cardiac_arrest() && target.can_heartattack())
to_chat(target, "<span class='userdanger'>You start feeling a sharp pain, and foreign presence in your mind!!</span>")
var/success = TRUE
if(target.anti_magic_check(FALSE, FALSE, TRUE))
to_chat(user, "<span class='notice'>We begin bruteforcing the tinfoil barriers of [target.name] and overload [target.p_their()] medulla.</span>")
if(!do_after(user, 50, FALSE, user) || !(target in view(range)))
to_chat(user, "<span class='warning'>we fail to overload the vessel's medulla.</span>")
success = FALSE
if(success)
target.set_heartattack(TRUE)
to_chat(target, "<span class='userdanger'>You feel a sharp pain, and foreign presence in your mind!!</span>")
to_chat(user, "<span class='notice'>We have overloaded the vessel's medulla! Without medical attention, they will shortly die.</span>")
if(target.stat == CONSCIOUS)
target.visible_message("<span class='userdanger'>[target] clutches at [target.p_their()] chest as if [target.p_their()] heart stopped!</span>")
@@ -621,26 +698,27 @@
var/pulse_cap = min(12, 8+(round(hive.hive_size/20)))
distort(user, target, pulse_cap)
/obj/effect/proc_holder/spell/target_hive/hive_warp/proc/distort(user, target, pulse_cap, pulses = 0)
/obj/effect/proc_holder/spell/target_hive/hive_warp/proc/distort(user, target, pulse_cap, pulses = 0, chargecost = 1)
for(var/mob/living/carbon/human/victim in view(7,target))
if(user == victim || victim.is_real_hivehost())
continue
var/multiplier = victim.anti_magic_check(FALSE, FALSE, TRUE, chargecost) ? 0.5 : 1
if(pulses < 4)
victim.apply_damage(10, STAMINA, victim.get_bodypart(BODY_ZONE_HEAD)) // 25 over 10 seconds when taking stamina regen (3 per tick(2 seconds)) into account
victim.hallucination += 5
victim.apply_damage(10*multiplier, STAMINA, victim.get_bodypart(BODY_ZONE_HEAD)) // 25 over 10 seconds when taking stamina regen (3 per tick(2 seconds)) into account
victim.hallucination += 5*multiplier
else if(pulses < 8)
victim.apply_damage(15, STAMINA, victim.get_bodypart(BODY_ZONE_HEAD)) // 45 over 10 seconds when taking stamina regen into account
victim.hallucination += 10
victim.apply_damage(15*multiplier, STAMINA, victim.get_bodypart(BODY_ZONE_HEAD)) // 45 over 10 seconds when taking stamina regen into account
victim.hallucination += 10*multiplier
else
victim.apply_damage(20, STAMINA, victim.get_bodypart(BODY_ZONE_HEAD)) // 65 over 10 seconds when taking stamina regen into account
victim.hallucination += 15
victim.apply_damage(20*multiplier, STAMINA, victim.get_bodypart(BODY_ZONE_HEAD)) // 65 over 10 seconds when taking stamina regen into account
victim.hallucination += 15*multiplier
if(pulses < pulse_cap && user && target)
addtimer(CALLBACK(src, "distort", user, target, pulse_cap, pulses+1), 25)
addtimer(CALLBACK(src, "distort", user, target, pulse_cap, pulses+1, 0), 25)
/obj/effect/proc_holder/spell/targeted/hive_hack
name = "Network Invasion"
desc = "We probe the mind of an adjacent target and extract valuable information on any enemy hives they may belong to. Takes longer if the target is not in our hive."
desc = "We probe the mind of an adjacent target and extract valuable information on any enemy hives they may belong to. Takes longer if the target is not in our hive or wearing tinfoil protection."
panel = "Hivemind Abilities"
charge_max = 600
range = 1
@@ -662,10 +740,12 @@
var/list/enemies = list()
to_chat(user, "<span class='notice'>We begin probing [target.name]'s mind!</span>")
if(do_after(user,100,0,target))
if(!in_hive)
if(!do_after(user,100,0,target))
var/foiled = target.anti_magic_check(FALSE, FALSE, TRUE)
if(!in_hive || foiled)
var/timely = !in_hive ? 200 : 100
to_chat(user, "<span class='notice'>Their mind slowly opens up to us.</span>")
if(!do_after(user,200,0,target))
if(!do_after(user,timely,FALSE,target))
to_chat(user, "<span class='notice'>Our concentration has been broken!</span>")
revert_cast()
return
@@ -777,11 +857,7 @@
var/list/valid_targets = list()
for(var/datum/mind/M in hive.hivemembers)
var/mob/living/carbon/C = M.current
if(!C)
continue
if(is_hivehost(C) || C.is_wokevessel())
continue
if(C.stat == DEAD || C.InCritical())
if(!C || is_hivehost(C) || C.is_wokevessel() || C.stat == DEAD || C.InCritical() || C.anti_magic_check(FALSE, FALSE, TRUE, 4))
continue
valid_targets += C
@@ -803,7 +879,7 @@
/obj/effect/proc_holder/spell/self/hive_loyal
name = "Bruteforce"
desc = "Our ability to assimilate is boosted at the cost of, allowing us to crush the technology shielding the minds of Security and Command personnel and assimilate them. This power comes at a small price, and we will be immobilized for a few seconds after assimilation."
desc = "Our ability to assimilate is boosted at the cost of, allowing us to crush the technology shielding the minds of savyy personnel and assimilate them. This power comes at a small price, and we will be immobilized for a few seconds after assimilation."
panel = "Hivemind Abilities"
charge_max = 600
invocation_type = "none"
@@ -823,7 +899,7 @@
if(!the_spell)
to_chat(user, "<span class='notice'>This is a bug. Error:HIVE5</span>")
return
the_spell.ignore_mindshield = !active
the_spell.bruteforce = !active
to_chat(user, "<span class='notice'>We [active?"let our minds rest and cancel our crushing power.":"prepare to crush mindshielding technology!"]</span>")
active = !active
if(active)
@@ -926,6 +1002,7 @@
continue
C.Jitter(15)
C.Unconscious(150)
C.anti_magic_check(FALSE, FALSE, TRUE, 6)
to_chat(C, "<span class='boldwarning'>Something's wrong...</span>")
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, C, "<span class='boldwarning'>...your memories are becoming fuzzy.</span>"), 45)
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, C, "<span class='boldwarning'>You try to remember who you are...</span>"), 90)

View File

@@ -61,7 +61,7 @@ Also, you never added distance checking after target is selected. I've went ahea
return
var/datum/mind/TM = target.mind
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),"@"))
if((target.anti_magic_check(TRUE, FALSE) || 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(!silent)
to_chat(user, "<span class='warning'>[target.p_their(TRUE)] mind is resisting your spell!</span>")
return

View File

@@ -86,7 +86,7 @@
/obj/effect/cross_action/spacetime_dist/proc/walk_link(atom/movable/AM)
if(ismob(AM))
var/mob/M = AM
if(M.anti_magic_check(major = FALSE))
if(M.anti_magic_check(chargecost = 0))
return
if(linked_dist && walks_left > 0)
flick("purplesparkles", src)

View File

@@ -12,6 +12,7 @@
var/boldnotice = "boldnotice"
var/magic_check = FALSE
var/holy_check = FALSE
var/tinfoil_check = TRUE
/obj/effect/proc_holder/spell/targeted/telepathy/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
for(var/mob/living/M in targets)
@@ -21,7 +22,7 @@
return
log_directed_talk(user, M, msg, LOG_SAY, "[name]")
to_chat(user, "<span class='[boldnotice]'>You transmit to [M]:</span> <span class='[notice]'>[msg]</span>")
if(!M.anti_magic_check(magic_check, holy_check)) //hear no evil
if(!M.anti_magic_check(magic_check, holy_check, tinfoil_check, 0)) //hear no evil
to_chat(M, "<span class='[boldnotice]'>You hear something behind you talking...</span> <span class='[notice]'>[msg]</span>")
for(var/ded in GLOB.dead_mob_list)
if(!isobserver(ded))