mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-20 03:25:49 +01:00
Ports Anti-magic from TG. (#27560)
* the rest of the fucking owl * OK hands need work but otherwise good * fuck time out fix vampire after * temporary codersprite do not merge this lmao * codersprite up * pause, time out * deploy the antimagic * Update code/__HELPERS/trait_helpers.dm Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> * Update code/datums/status_effects/buffs.dm Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com> * Update code/game/gamemodes/wizard/magic_tarot.dm Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com> --------- Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com> Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
@@ -134,5 +134,9 @@
|
||||
#define COMPONENT_NO_MOUSEDROP (1<<0)
|
||||
///from base of atom/MouseDrop_T: (/atom/from, /mob/user)
|
||||
#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto"
|
||||
|
||||
/// Called on the atom being hit, from /datum/component/anti_magic/on_attack() : (obj/item/weapon, mob/user, antimagic_flags)
|
||||
#define COMSIG_ATOM_HOLY_ATTACK "atom_holyattacked"
|
||||
/// On a ranged attack: base of mob/living/carbon/human/RangedAttack (/mob/living/carbon/human)
|
||||
#define COMSIG_ATOM_RANGED_ATTACKED "atom_range_attacked"
|
||||
|
||||
|
||||
@@ -22,11 +22,14 @@
|
||||
#define COMSIG_MOB_ALTCLICKON "mob_altclickon"
|
||||
#define COMSIG_MOB_CANCEL_CLICKON (1<<0)
|
||||
|
||||
///from base of mob/can_cast_magic(): (mob/user, magic_flags, charge_cost)
|
||||
#define COMSIG_MOB_RESTRICT_MAGIC "mob_cast_magic"
|
||||
///from base of mob/can_block_magic(): (mob/user, casted_magic_flags, charge_cost)
|
||||
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic"
|
||||
#define COMPONENT_MAGIC_BLOCKED (1<<0)
|
||||
|
||||
///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
|
||||
#define COMSIG_MOB_ALLOWED "mob_allowed"
|
||||
///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
|
||||
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic"
|
||||
#define COMPONENT_BLOCK_MAGIC (1<<0)
|
||||
///from base of mob/create_mob_hud(): ()
|
||||
#define COMSIG_MOB_HUD_CREATED "mob_hud_created"
|
||||
///from base of atom/attack_hand(): (mob/user)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Bitflags for magic resistance types
|
||||
/// Default magic resistance that blocks normal magic (wizard, spells, magical staff projectiles)
|
||||
#define MAGIC_RESISTANCE (1<<0)
|
||||
/// Tinfoil hat magic resistance that blocks mental magic (telepathy / mind links, mind curses, abductors)
|
||||
#define MAGIC_RESISTANCE_MIND (1<<1)
|
||||
/// Holy magic resistance that blocks unholy magic (revenant, vampire, voice of god)
|
||||
#define MAGIC_RESISTANCE_HOLY (1<<2)
|
||||
|
||||
DEFINE_BITFIELD(antimagic_flags, list(
|
||||
"MAGIC_RESISTANCE" = MAGIC_RESISTANCE,
|
||||
"MAGIC_RESISTANCE_HOLY" = MAGIC_RESISTANCE_HOLY,
|
||||
"MAGIC_RESISTANCE_MIND" = MAGIC_RESISTANCE_MIND,
|
||||
))
|
||||
|
||||
/// Whether the spell can be cast while the user has antimagic on them that corresponds to the spell's own antimagic flags.
|
||||
#define SPELL_REQUIRES_NO_ANTIMAGIC (1 << 0)
|
||||
@@ -244,6 +244,12 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_EMP_RESIST "emp_resist" //The mob will take less damage from EMPs
|
||||
#define TRAIT_MINDFLAYER_NULLIFIED "flayer_nullified" //The mindflayer will not be able to activate their abilities, or drain swarms from people
|
||||
#define TRAIT_FLYING "flying"
|
||||
/// This mob is antimagic, and immune to spells / cannot cast spells
|
||||
#define TRAIT_ANTIMAGIC "anti_magic"
|
||||
/// This allows a person who has antimagic to cast spells without getting blocked
|
||||
#define TRAIT_ANTIMAGIC_NO_SELFBLOCK "anti_magic_no_selfblock"
|
||||
/// This mob recently blocked magic with some form of antimagic
|
||||
#define TRAIT_RECENTLY_BLOCKED_MAGIC "recently_blocked_magic"
|
||||
#define TRAIT_UNKNOWN "unknown" // The person with this trait always appears as 'unknown'.
|
||||
#define TRAIT_CRYO_DESPAWNING "cryo_despawning" // dont adminbus this please
|
||||
|
||||
|
||||
@@ -106,6 +106,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_CANNOT_PULL" = TRAIT_CANNOT_PULL,
|
||||
"TRAIT_BSG_IMMUNE" = TRAIT_BSG_IMMUNE,
|
||||
"TRAIT_FLYING" = TRAIT_FLYING,
|
||||
"TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC,
|
||||
"TRAIT_ANTIMAGIC_NO_SELFBLOCK" = TRAIT_ANTIMAGIC_NO_SELFBLOCK,
|
||||
"TRAIT_RECENTLY_BLOCKED_MAGIC" = TRAIT_RECENTLY_BLOCKED_MAGIC,
|
||||
"TRAIT_UNKNOWN" = TRAIT_UNKNOWN
|
||||
),
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/// This provides different types of magic resistance on an object
|
||||
/datum/component/anti_magic
|
||||
/// A bitflag with the types of magic resistance on the object
|
||||
var/antimagic_flags
|
||||
/// The amount of times the object can protect the user from magic
|
||||
/// Set to INFINITY to have, well, infinite charges.
|
||||
var/charges
|
||||
/// The inventory slot the object must be located at in order to activate
|
||||
var/inventory_flags
|
||||
/// The callback invoked when we have been drained a antimagic charge
|
||||
var/datum/callback/drain_antimagic
|
||||
/// The callback invoked when twe have been depleted of all charges
|
||||
var/datum/callback/expiration
|
||||
/// Whether we should, on equipping, alert the caster that this item can block any of their spells
|
||||
/// This changes between true and false on equip and drop, don't set it outright to something
|
||||
var/alert_caster_on_equip = TRUE
|
||||
|
||||
/**
|
||||
* Adds magic resistances to an object
|
||||
*
|
||||
* Magic resistance will prevent magic from affecting the user if it has the correct resistance
|
||||
* against the type of magic being used
|
||||
*
|
||||
* args:
|
||||
* * antimagic_flags (optional) A bitflag with the types of magic resistance on the object
|
||||
* * charges (optional) The amount of times the object can protect the user from magic
|
||||
* * inventory_flags (optional) The inventory slot the object must be located at in order to activate
|
||||
* * drain_antimagic (optional) The proc that is triggered when an object has been drained a antimagic charge
|
||||
* * expiration (optional) The proc that is triggered when the object is depleted of charges
|
||||
* *
|
||||
* antimagic bitflags: (see code/__DEFINES/magic.dm)
|
||||
* * MAGIC_RESISTANCE - Default magic resistance that blocks normal magic (wizard, spells, staffs)
|
||||
* * MAGIC_RESISTANCE_MIND - Tinfoil hat magic resistance that blocks mental magic (telepathy, abductors, jelly people)
|
||||
* * MAGIC_RESISTANCE_HOLY - Holy magic resistance that blocks unholy magic (revenant, cult, vampire, voice of god)
|
||||
**/
|
||||
/datum/component/anti_magic/Initialize(
|
||||
antimagic_flags = MAGIC_RESISTANCE,
|
||||
charges = INFINITY,
|
||||
inventory_flags = ~ITEM_SLOT_IN_BACKPACK, // items in a backpack won't activate, anywhere else is fine
|
||||
datum/callback/drain_antimagic,
|
||||
datum/callback/expiration,
|
||||
)
|
||||
|
||||
|
||||
var/atom/movable/movable = parent
|
||||
if(!istype(movable))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
var/compatible = FALSE
|
||||
if(isitem(movable))
|
||||
RegisterSignal(movable, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip))
|
||||
RegisterSignal(movable, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
|
||||
RegisterSignal(movable, COMSIG_ATTACK, PROC_REF(on_attack))
|
||||
compatible = TRUE
|
||||
else if(ismob(movable))
|
||||
register_antimagic_signals(movable)
|
||||
compatible = TRUE
|
||||
|
||||
if(movable.can_buckle)
|
||||
RegisterSignal(movable, COMSIG_MOVABLE_BUCKLE, PROC_REF(on_buckle))
|
||||
RegisterSignal(movable, COMSIG_MOVABLE_UNBUCKLE, PROC_REF(on_unbuckle))
|
||||
compatible = TRUE
|
||||
|
||||
if(!compatible)
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.antimagic_flags = antimagic_flags
|
||||
src.charges = charges
|
||||
src.inventory_flags = inventory_flags
|
||||
src.drain_antimagic = drain_antimagic
|
||||
src.expiration = expiration
|
||||
|
||||
/datum/component/anti_magic/Destroy(force)
|
||||
drain_antimagic = null
|
||||
expiration = null
|
||||
return ..()
|
||||
|
||||
/datum/component/anti_magic/proc/register_antimagic_signals(datum/on_what)
|
||||
RegisterSignal(on_what, COMSIG_MOB_RECEIVE_MAGIC, PROC_REF(block_receiving_magic), override = TRUE)
|
||||
RegisterSignal(on_what, COMSIG_MOB_RESTRICT_MAGIC, PROC_REF(restrict_casting_magic), override = TRUE)
|
||||
|
||||
/datum/component/anti_magic/proc/unregister_antimagic_signals(datum/on_what)
|
||||
UnregisterSignal(on_what, list(COMSIG_MOB_RECEIVE_MAGIC, COMSIG_MOB_RESTRICT_MAGIC))
|
||||
|
||||
/datum/component/anti_magic/proc/on_buckle(atom/movable/source, mob/living/bucklee)
|
||||
SIGNAL_HANDLER // COMSIG_MOVABLE_BUCKLE
|
||||
register_antimagic_signals(bucklee)
|
||||
|
||||
/datum/component/anti_magic/proc/on_unbuckle(atom/movable/source, mob/living/bucklee)
|
||||
SIGNAL_HANDLER // COMSIG_MOVABLE_UNBUCKLE
|
||||
unregister_antimagic_signals(bucklee)
|
||||
|
||||
/datum/component/anti_magic/proc/on_equip(atom/movable/source, mob/equipper, slot)
|
||||
SIGNAL_HANDLER // COMSIG_ITEM_EQUIPPED
|
||||
addtimer(CALLBACK(src, PROC_REF(on_equip_part_2), source, equipper, slot), 0.1 SECONDS) //We wait a moment to see if the item grants antimagic flags
|
||||
|
||||
/datum/component/anti_magic/proc/on_equip_part_2(atom/movable/source, mob/equipper, slot)
|
||||
if(!(inventory_flags & slot)) //Check that the slot is valid for antimagic
|
||||
unregister_antimagic_signals(equipper)
|
||||
return
|
||||
|
||||
register_antimagic_signals(equipper)
|
||||
if(HAS_TRAIT(equipper, TRAIT_ANTIMAGIC_NO_SELFBLOCK)) //If they do not care about antimagic, don't warn them
|
||||
return
|
||||
if(!alert_caster_on_equip)
|
||||
return
|
||||
|
||||
// Check to see if we have any spells that are blocked due to antimagic
|
||||
if(!equipper.mind)
|
||||
return
|
||||
for(var/datum/spell/knownspell in equipper.mind.spell_list)
|
||||
if(!(knownspell.spell_requirements & SPELL_REQUIRES_NO_ANTIMAGIC))
|
||||
continue
|
||||
|
||||
if(!(antimagic_flags & knownspell.antimagic_flags))
|
||||
continue
|
||||
|
||||
to_chat(equipper, "<span class='warning'>[parent] is interfering with your ability to cast magic!</span>")
|
||||
alert_caster_on_equip = FALSE
|
||||
break
|
||||
|
||||
/datum/component/anti_magic/proc/on_drop(atom/movable/source, mob/user)
|
||||
SIGNAL_HANDLER //COMSIG_ITEM_DROPPED
|
||||
|
||||
// Reset alert
|
||||
if(source.loc != user)
|
||||
alert_caster_on_equip = TRUE
|
||||
unregister_antimagic_signals(user)
|
||||
|
||||
/datum/component/anti_magic/proc/block_receiving_magic(mob/living/carbon/source, casted_magic_flags, charge_cost, list/antimagic_sources)
|
||||
SIGNAL_HANDLER // COMSIG_MOB_RECEIVE_MAGIC
|
||||
|
||||
// We do not block this type of magic, good day
|
||||
if(!(casted_magic_flags & antimagic_flags))
|
||||
return NONE
|
||||
|
||||
// We have already blocked this spell
|
||||
if(parent in antimagic_sources)
|
||||
return NONE
|
||||
|
||||
// Block success! Add this parent to the list of antimagic sources
|
||||
antimagic_sources += parent
|
||||
|
||||
if((charges != INFINITY) && charge_cost > 0)
|
||||
drain_antimagic?.Invoke(source, parent)
|
||||
charges -= charge_cost
|
||||
if(charges <= 0)
|
||||
expiration?.Invoke(source, parent)
|
||||
qdel(src) // no more antimagic
|
||||
|
||||
return COMPONENT_MAGIC_BLOCKED
|
||||
|
||||
/// cannot cast magic with the same type of antimagic present
|
||||
/datum/component/anti_magic/proc/restrict_casting_magic(mob/user, magic_flags)
|
||||
SIGNAL_HANDLER // COMSIG_MOB_RESTRICT_MAGIC
|
||||
|
||||
if(magic_flags & antimagic_flags)
|
||||
if(HAS_TRAIT(user, TRAIT_ANTIMAGIC_NO_SELFBLOCK)) // this trait bypasses magic casting restrictions
|
||||
return NONE
|
||||
return COMPONENT_MAGIC_BLOCKED
|
||||
|
||||
return NONE
|
||||
|
||||
/datum/component/anti_magic/proc/on_attack(obj/item/source, mob/living/target, mob/living/user)
|
||||
SIGNAL_HANDLER //COMSIG_ATTACK
|
||||
SEND_SIGNAL(target, COMSIG_ATOM_HOLY_ATTACK, source, user, antimagic_flags)
|
||||
@@ -134,6 +134,13 @@ GLOBAL_LIST_INIT(spells, typesof(/datum/spell))
|
||||
var/static/list/spell_handlers = list()
|
||||
/// handles a given spells cooldowns. tracks the time until its off cooldown,
|
||||
var/datum/spell_cooldown/cooldown_handler
|
||||
/// Flag for certain states that the spell requires the user be in to cast.
|
||||
var/spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC
|
||||
/// This determines what type of antimagic is needed to block the spell.
|
||||
/// (MAGIC_RESISTANCE, MAGIC_RESISTANCE_MIND, MAGIC_RESISTANCE_HOLY)
|
||||
/// If SPELL_REQUIRES_NO_ANTIMAGIC is set in Spell requirements,
|
||||
/// The spell cannot be cast if the caster has any of the antimagic flags set.
|
||||
var/antimagic_flags = MAGIC_RESISTANCE
|
||||
|
||||
/* Checks if the user can cast the spell
|
||||
* @param charge_check If the proc should do the cooldown check
|
||||
@@ -467,6 +474,12 @@ GLOBAL_LIST_INIT(spells, typesof(/datum/spell))
|
||||
if(T && is_admin_level(T.z))
|
||||
return FALSE
|
||||
|
||||
// If the spell requires the user has no antimagic equipped, and they're holding antimagic
|
||||
// that corresponds with the spell's antimagic, then they can't actually cast the spell
|
||||
if((spell_requirements & SPELL_REQUIRES_NO_ANTIMAGIC) && !user.can_cast_magic(antimagic_flags))
|
||||
to_chat(user, "<span class='warning'>Some form of antimagic is preventing you from casting [src]!</span>")
|
||||
return FALSE
|
||||
|
||||
if(!holy_area_cancast && user.holy_check())
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ Updates the spell's actions on use as well, so they know when they can or can't
|
||||
create_attack_logs = FALSE
|
||||
/// Every alien spell creates only logs, no attack messages on someone placing weeds, but you DO get attack messages on neurotoxin and corrosive acid
|
||||
create_custom_logs = TRUE
|
||||
antimagic_flags = NONE
|
||||
/// How much plasma it costs to use this
|
||||
var/plasma_cost = 0
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
base_cooldown = 1
|
||||
action_background_icon_state = "bg_alien"
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
create_attack_logs = FALSE
|
||||
/// Every alien spell creates only logs, no attack messages on someone placing weeds, but you DO get attack messages on neurotoxin and corrosive acid
|
||||
create_custom_logs = TRUE
|
||||
|
||||
@@ -27,10 +27,11 @@
|
||||
|
||||
/obj/item/melee/touch_attack/banana/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
|
||||
if(is_apprentice_spell && iswizard(target) && target != user)
|
||||
to_chat(user, "<span class='danger'>Seriously?! Honk THEM, not me!</span>")
|
||||
return
|
||||
if(!proximity_flag || target == user || !ishuman(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))
|
||||
if(!proximity_flag || target == user || blocked_by_antimagic || !ishuman(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))
|
||||
return
|
||||
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
overlay = null
|
||||
action_icon_state = "bloodcrawl"
|
||||
action_background_icon_state = "bg_demon"
|
||||
antimagic_flags = NONE
|
||||
var/allowed_type = /obj/effect/decal/cleanable
|
||||
var/phased = FALSE
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
clothes_req = FALSE
|
||||
invocation = "none"
|
||||
invocation_type = "none"
|
||||
antimagic_flags = NONE
|
||||
|
||||
selection_activated_message = "<span class='notice'>You prepare a blessing. Click on a target to start blessing.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>The crew will be blessed another time.</span>"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
clothes_req = FALSE
|
||||
base_cooldown = 5 SECONDS
|
||||
human_req = TRUE
|
||||
antimagic_flags = NONE
|
||||
action_icon_state = "chef"
|
||||
action_background_icon_state = "bg_default"
|
||||
still_recharging_msg = "All this thinking makes your head hurt, wait a bit longer."
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
if(target.can_block_magic(antimagic_flags))
|
||||
target.visible_message("<span class='danger'>[target]'s face bursts into flames, which instantly burst outward, leaving [target.p_them()] unharmed!</span>",
|
||||
"<span class='danger'>Your face starts burning up, but the flames are repulsed by your anti-magic protection!</span>",
|
||||
)
|
||||
to_chat(user, "<span class='warning'>The spell had no effect!</span>")
|
||||
return FALSE
|
||||
|
||||
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
|
||||
magichead.flags |= NODROP | DROPDEL //curses!
|
||||
magichead.flags_inv = null //so you can still see their face
|
||||
|
||||
@@ -38,6 +38,12 @@
|
||||
origin.Beam(target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = 5)
|
||||
|
||||
/datum/spell/charge_up/bounce/lightning/apply_bounce_effect(mob/origin, mob/living/target, energy, mob/user)
|
||||
if(target.can_block_magic(antimagic_flags))
|
||||
target.visible_message(
|
||||
"<span class='warning'>[target] absorbs the spell, remaining unharmed!</span>",
|
||||
"<span class='danger'>You absorb the spell, remaining unharmed!</span>"
|
||||
)
|
||||
return
|
||||
if(damaging)
|
||||
target.electrocute_act(energy, "Lightning Bolt", flags = SHOCK_NOGLOVES)
|
||||
else
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
clothes_req = FALSE
|
||||
cast_sound = null
|
||||
human_req = TRUE
|
||||
antimagic_flags = NONE
|
||||
|
||||
action_icon_state = "mime"
|
||||
action_background_icon_state = "bg_mime"
|
||||
@@ -87,6 +88,7 @@
|
||||
clothes_req = FALSE
|
||||
base_cooldown = 30 SECONDS
|
||||
human_req = TRUE
|
||||
antimagic_flags = NONE
|
||||
|
||||
action_icon_state = "fingergun"
|
||||
action_background_icon_state = "bg_mime"
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
/obj/item/melee/touch_attack/mime_malaise/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || target == user || !ishuman(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))
|
||||
|
||||
if(!proximity_flag || target == user || blocked_by_antimagic || !ishuman(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))
|
||||
return
|
||||
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
selection_activated_message = "<span class='notice'>You prepare to transfer your mind. Click on a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>You decide that your current form is good enough.</span>"
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_MIND
|
||||
var/list/protected_roles = list(SPECIAL_ROLE_WIZARD, SPECIAL_ROLE_CHANGELING, SPECIAL_ROLE_CULTIST) //which roles are immune to the spell
|
||||
var/paralysis_amount_caster = 40 SECONDS //how much the caster is paralysed for after the spell
|
||||
var/paralysis_amount_victim = 40 SECONDS //how much the victim is paralysed for after the spell
|
||||
@@ -47,6 +48,9 @@ Also, you never added distance checking after target is selected. I've went ahea
|
||||
if(issilicon(target))
|
||||
to_chat(user, "<span class='warning'>You feel this enslaved being is just as dead as its cold, hard exoskeleton.</span>")
|
||||
return
|
||||
if(target.can_block_magic(antimagic_flags))
|
||||
to_chat(user, "<span class='danger'>Their mind is resisting your spell.</span>")
|
||||
return
|
||||
|
||||
var/mob/living/victim = target//The target of the spell whos body will be transferred to.
|
||||
var/mob/living/caster = user//The wizard/whomever doing the body transferring.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
base_cooldown = 10
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
|
||||
message = "<span class='notice'>You toggle your night vision!</span>"
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
/datum/spell/rathens/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/human/H in targets)
|
||||
if(H.can_block_magic(antimagic_flags))
|
||||
continue
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
s.set_up(5, FALSE, H)
|
||||
s.start()
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
desc = "A distortion in spacetime. You can hear faint music..."
|
||||
icon_state = "nothing"
|
||||
/// A flags which save people from being thrown about
|
||||
var/antimagic_flags = MAGIC_RESISTANCE
|
||||
/// A flags which save people from being thrown about
|
||||
var/obj/effect/cross_action/spacetime_dist/linked_dist
|
||||
/// Used to prevent an infinite loop in the space tiime continuum
|
||||
var/cant_teleport = FALSE
|
||||
@@ -101,6 +103,10 @@
|
||||
AddElement(/datum/element/connect_loc, loc_connections)
|
||||
|
||||
/obj/effect/cross_action/spacetime_dist/proc/walk_link(atom/movable/AM)
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
if(M.can_block_magic(antimagic_flags, charge_cost = 0))
|
||||
return
|
||||
if(linked_dist && walks_left > 0)
|
||||
flick("purplesparkles", src)
|
||||
linked_dist.get_walker(AM)
|
||||
|
||||
@@ -313,6 +313,10 @@
|
||||
return
|
||||
|
||||
var/mob/living/target = targets[1]
|
||||
if(target.can_block_magic(antimagic_flags))
|
||||
to_chat(target, "<span class='notice'>Your eye itches, but it passes momentarily.</span>")
|
||||
to_chat(user, "<span class='notice'>The spell had no effect!</span>")
|
||||
return FALSE
|
||||
target.EyeBlurry(40 SECONDS)
|
||||
target.EyeBlind(30 SECONDS)
|
||||
|
||||
@@ -414,6 +418,10 @@
|
||||
playMagSound()
|
||||
for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously.
|
||||
for(var/atom/movable/AM in T)
|
||||
if(ismob(AM))
|
||||
var/mob/victim_mob = AM
|
||||
if(victim_mob.can_block_magic(antimagic_flags))
|
||||
continue
|
||||
thrownatoms += AM
|
||||
|
||||
for(var/am in thrownatoms)
|
||||
@@ -457,6 +465,8 @@
|
||||
|
||||
/datum/spell/sacred_flame/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/L in targets)
|
||||
if(L.can_block_magic(antimagic_flags))
|
||||
continue
|
||||
L.adjust_fire_stacks(20)
|
||||
if(isliving(user))
|
||||
var/mob/living/U = user
|
||||
|
||||
@@ -92,9 +92,12 @@
|
||||
var/found_someone = FALSE
|
||||
|
||||
for(var/mob/living/L in oview(9, owner))
|
||||
found_someone = TRUE
|
||||
playsound(owner, 'sound/magic/teleport_diss.ogg', 50, TRUE)
|
||||
L.Beam(owner, "grabber_beam", time = 1 SECONDS, maxdistance = 9)
|
||||
if(L.can_block_magic(MAGIC_RESISTANCE))
|
||||
to_chat(L, "<span class='warning'>You shake off the tendrils that try to wrap around you!</span>")
|
||||
continue
|
||||
found_someone = TRUE
|
||||
L.apply_status_effect(STATUS_EFFECT_VOID_PRICE)
|
||||
if(found_someone)
|
||||
owner.visible_message("<span class='warning'>The violet light around [owner] glows black... and shoots off to those around [owner.p_them()]!</span>", "<span class='warning'>The tendrils around you cinch tightly... but then unwravel and fly at others!</span>")
|
||||
|
||||
@@ -301,6 +301,7 @@
|
||||
|
||||
clothes_req = FALSE
|
||||
stat_allowed = CONSCIOUS
|
||||
antimagic_flags = NONE
|
||||
|
||||
selection_activated_message = "<span class='notice'>Your mind grow cold. Click on a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind returns to normal.</span>"
|
||||
@@ -372,6 +373,7 @@
|
||||
clothes_req = FALSE
|
||||
stat_allowed = CONSCIOUS
|
||||
invocation_type = "none"
|
||||
antimagic_flags = NONE
|
||||
|
||||
action_icon_state = "genetic_eat"
|
||||
|
||||
@@ -511,6 +513,7 @@
|
||||
clothes_req = FALSE
|
||||
stat_allowed = CONSCIOUS
|
||||
invocation_type = "none"
|
||||
antimagic_flags = NONE
|
||||
|
||||
action_icon_state = "genetic_jump"
|
||||
var/leap_distance = 10
|
||||
@@ -636,6 +639,7 @@
|
||||
selection_deactivated_message = "<span class='notice'>Your body calms down again.</span>"
|
||||
|
||||
invocation_type = "none"
|
||||
antimagic_flags = NONE
|
||||
|
||||
action_icon_state = "genetic_poly"
|
||||
|
||||
@@ -684,6 +688,7 @@
|
||||
human_req = TRUE
|
||||
stat_allowed = CONSCIOUS
|
||||
invocation_type = "none"
|
||||
antimagic_flags = MAGIC_RESISTANCE_MIND
|
||||
|
||||
action_icon_state = "genetic_empath"
|
||||
|
||||
@@ -793,6 +798,7 @@
|
||||
clothes_req = FALSE
|
||||
stat_allowed = CONSCIOUS
|
||||
invocation_type = "none"
|
||||
antimagic_flags = NONE
|
||||
|
||||
action_icon_state = "genetic_morph"
|
||||
|
||||
@@ -983,6 +989,7 @@
|
||||
clothes_req = FALSE
|
||||
stat_allowed = CONSCIOUS
|
||||
invocation_type = "none"
|
||||
antimagic_flags = MAGIC_RESISTANCE_MIND
|
||||
|
||||
action_icon_state = "genetic_project"
|
||||
|
||||
@@ -1017,6 +1024,7 @@
|
||||
base_cooldown = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = CONSCIOUS
|
||||
antimagic_flags = MAGIC_RESISTANCE_MIND
|
||||
invocation_type = "none"
|
||||
action_icon_state = "genetic_mindscan"
|
||||
var/list/expanded_minds = list()
|
||||
@@ -1105,6 +1113,7 @@
|
||||
clothes_req = FALSE
|
||||
stat_allowed = CONSCIOUS
|
||||
invocation_type = "none"
|
||||
antimagic_flags = MAGIC_RESISTANCE_MIND
|
||||
|
||||
action_icon_state = "genetic_view"
|
||||
|
||||
|
||||
@@ -385,6 +385,7 @@
|
||||
var/uses = 1
|
||||
var/health_cost = 0 //The amount of health taken from the user when invoking the spell
|
||||
var/datum/action/innate/cult/blood_spell/source
|
||||
var/antimagic_flags = MAGIC_RESISTANCE_HOLY
|
||||
|
||||
/obj/item/melee/blood_magic/Initialize(mapload, spell)
|
||||
. = ..()
|
||||
@@ -418,6 +419,11 @@
|
||||
uses = 0
|
||||
qdel(src)
|
||||
return
|
||||
if(M.can_block_magic(MAGIC_RESISTANCE_HOLY))
|
||||
to_chat(user, "<span class='danger'>[M] absorbs your spell!</span>")
|
||||
uses = 0
|
||||
qdel(src)
|
||||
return
|
||||
add_attack_logs(user, M, "used a cult spell ([src]) on")
|
||||
M.lastattacker = user.real_name
|
||||
|
||||
|
||||
@@ -249,9 +249,8 @@ 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)
|
||||
return N
|
||||
if(can_block_magic(MAGIC_RESISTANCE_HOLY))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//Rite of Enlightenment: Converts a normal crewmember to the cult, or offer them as sacrifice if cant be converted.
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
base_cooldown = 0
|
||||
var/uses //If we have multiple uses of the same power
|
||||
var/auto_use_uses = TRUE //If we automatically use up uses on each activation
|
||||
antimagic_flags = NONE
|
||||
|
||||
/datum/spell/ai_spell/create_new_targeting()
|
||||
return new /datum/spell_targeting/self
|
||||
|
||||
@@ -212,6 +212,8 @@
|
||||
return
|
||||
hit = TRUE // to prevent double hits from the pull
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
for(var/atom/extinguish_target in range(2, src))
|
||||
extinguish_target.extinguish_light(TRUE)
|
||||
if(!isliving(target))
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
name = "Place Teleportation Beacon"
|
||||
desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon requires an anchor, will not work on space tiles."
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
base_cooldown = 300 SECONDS
|
||||
action_icon_state = "no_state"
|
||||
action_background_icon = 'icons/mob/guardian.dmi'
|
||||
@@ -129,6 +130,7 @@
|
||||
name = "Set Surveillance Snare"
|
||||
desc = "Places an invisible Surveillance Snare on the ground, if someone walks over it you'll be alerted. Max of 6 snares active at a time"
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
base_cooldown = 3 SECONDS
|
||||
action_icon_state = "no_state"
|
||||
action_background_icon = 'icons/mob/guardian.dmi'
|
||||
@@ -160,6 +162,7 @@
|
||||
name = "Change battlecry"
|
||||
desc = "Changes your battlecry."
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
base_cooldown = 1 SECONDS
|
||||
action_icon_state = "no_state"
|
||||
action_background_icon = 'icons/mob/guardian.dmi'
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
action_background_icon_state = "bg_morph"
|
||||
action_icon_state = "morph_airlock"
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
base_cooldown = 10 SECONDS
|
||||
selection_activated_message = "<span class='sinister'>Click on an airlock to try pass it.</span>"
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
/datum/spell/pulse_demon
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
action_background_icon_state = "bg_pulsedemon"
|
||||
var/locked = TRUE
|
||||
var/unlock_cost = 1 KJ
|
||||
|
||||
@@ -134,6 +134,7 @@
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "r_transmit"
|
||||
action_background_icon_state = "bg_revenant"
|
||||
antimagic_flags = MAGIC_RESISTANCE_HOLY|MAGIC_RESISTANCE_MIND
|
||||
|
||||
/datum/spell/revenant_transmit/create_new_targeting()
|
||||
var/datum/spell_targeting/targeted/T = new()
|
||||
@@ -165,6 +166,7 @@
|
||||
var/unlock_amount = 100
|
||||
/// How much essence it costs to use
|
||||
var/cast_amount = 50
|
||||
antimagic_flags = MAGIC_RESISTANCE_HOLY
|
||||
|
||||
/datum/spell/aoe/revenant/New()
|
||||
..()
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
throw_range = 0
|
||||
throw_speed = 0
|
||||
new_attack_chain = TRUE
|
||||
/// Has it been blocked by antimagic? If so, abort.
|
||||
var/blocked_by_antimagic = FALSE
|
||||
|
||||
/obj/item/melee/touch_attack/New(spell)
|
||||
attached_spell = spell
|
||||
@@ -37,6 +39,17 @@
|
||||
to_chat(user, "<span class='warning'>You can't reach out!</span>")
|
||||
return FINISH_ATTACK
|
||||
|
||||
/obj/item/melee/touch_attack/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
var/mob/mob_victim = target
|
||||
if(istype(mob_victim) && mob_victim.can_block_magic(attached_spell.antimagic_flags))
|
||||
to_chat(user, "<span class='danger'>[mob_victim] absorbs your spell!</span>")
|
||||
blocked_by_antimagic = TRUE
|
||||
if(attached_spell && attached_spell.cooldown_handler)
|
||||
attached_spell.cooldown_handler.start_recharge(attached_spell.cooldown_handler.recharge_duration * 0.5)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/melee/touch_attack/proc/handle_delete(mob/user)
|
||||
if(catchphrase)
|
||||
user.say(catchphrase)
|
||||
@@ -53,9 +66,10 @@
|
||||
icon_state = "disintegrate"
|
||||
item_state = "disintegrate"
|
||||
|
||||
|
||||
/obj/item/melee/touch_attack/disintegrate/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || target == user || !ismob(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //exploding after touching yourself would be bad
|
||||
if(!proximity_flag || target == user || blocked_by_antimagic || !ismob(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //exploding after touching yourself would be bad
|
||||
return
|
||||
var/mob/M = target
|
||||
do_sparks(4, 0, M.loc) //no idea what the 0 is
|
||||
@@ -72,7 +86,8 @@
|
||||
|
||||
/obj/item/melee/touch_attack/fleshtostone/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || target == user || !isliving(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //getting hard after touching yourself would also be bad
|
||||
|
||||
if(!proximity_flag || target == user || blocked_by_antimagic || !isliving(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //getting hard after touching yourself would also be bad
|
||||
return
|
||||
var/mob/living/L = target
|
||||
L.Stun(4 SECONDS)
|
||||
@@ -90,12 +105,14 @@
|
||||
|
||||
/obj/item/melee/touch_attack/plushify/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || target == user || !isliving(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //There are better ways to get a good nights sleep in a bed.
|
||||
|
||||
if(!proximity_flag || target == user || blocked_by_antimagic || !isliving(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //There are better ways to get a good nights sleep in a bed.
|
||||
return
|
||||
var/mob/living/L = target
|
||||
L.plushify()
|
||||
handle_delete(user)
|
||||
|
||||
|
||||
/obj/item/melee/touch_attack/fake_disintegrate
|
||||
name = "toy plastic hand"
|
||||
desc = "This hand of mine glows with an awesome power! Ok, maybe just batteries."
|
||||
@@ -107,7 +124,8 @@
|
||||
|
||||
/obj/item/melee/touch_attack/fake_disintegrate/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || target == user || !ismob(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //not exploding after touching yourself would be bad
|
||||
|
||||
if(!proximity_flag || target == user || blocked_by_antimagic || !ismob(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //not exploding after touching yourself would be bad
|
||||
return
|
||||
do_sparks(4, 0, target.loc)
|
||||
playsound(target.loc, 'sound/goonstation/effects/gib.ogg', 50, 1)
|
||||
@@ -123,7 +141,8 @@
|
||||
|
||||
/obj/item/melee/touch_attack/cluwne/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || target == user || !ishuman(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //clowning around after touching yourself would unsurprisingly, be bad
|
||||
|
||||
if(!proximity_flag || target == user || blocked_by_antimagic || !ishuman(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) //clowning around after touching yourself would unsurprisingly, be bad
|
||||
return
|
||||
|
||||
if(iswizard(target))
|
||||
|
||||
@@ -232,6 +232,11 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/item/magic_tarot_card/proc/pre_activate(mob/user, atom/movable/thrower)
|
||||
if(user != thrower) //Ignore antimagic stuff if the user is the thrower (aka self activation)
|
||||
if(user.can_block_magic(our_tarot.antimagic_flags, 1))
|
||||
visible_message("<span class='warning'>[src] burns up in a flash on contact with [user]!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
has_been_activated = TRUE
|
||||
forceMove(user)
|
||||
var/obj/effect/temp_visual/card_preview/tarot/draft = new(user, "tarot_[our_tarot.card_icon]")
|
||||
@@ -288,6 +293,8 @@
|
||||
var/card_icon = "the_unknown"
|
||||
/// Are we reversed? Used for the card back.
|
||||
var/reversed = FALSE
|
||||
/// What antimagic flags do we have?
|
||||
var/antimagic_flags = MAGIC_RESISTANCE
|
||||
|
||||
/datum/tarot/proc/activate(mob/living/target)
|
||||
stack_trace("A bugged tarot card was spawned and used. Please make an issue report! Type was [src.type]")
|
||||
@@ -688,8 +695,11 @@
|
||||
var/sparkle_path = /obj/effect/temp_visual/gravpush
|
||||
for(var/turf/T in range(5, target)) //Done this way so things don't get thrown all around hilariously.
|
||||
for(var/atom/movable/AM in T)
|
||||
if(ismob(AM))
|
||||
var/mob/victim_mob = AM
|
||||
if(victim_mob.can_block_magic(antimagic_flags))
|
||||
continue
|
||||
thrown_atoms += AM
|
||||
|
||||
for(var/atom/movable/AM as anything in thrown_atoms)
|
||||
if(AM == target || AM.anchored || (ismob(AM) && !isliving(AM)))
|
||||
continue
|
||||
@@ -729,6 +739,9 @@
|
||||
|
||||
/datum/tarot/reversed/the_empress/activate(mob/living/target)
|
||||
for(var/mob/living/L in oview(9, target))
|
||||
if(L.can_block_magic(antimagic_flags))
|
||||
to_chat(L, "<span class='notice'>You feel calm for a second, but it quickly passes.</span>")
|
||||
continue
|
||||
L.apply_status_effect(STATUS_EFFECT_PACIFIED)
|
||||
|
||||
/datum/tarot/reversed/the_emperor
|
||||
@@ -763,6 +776,8 @@
|
||||
for(var/mob/living/M in shuffle(orange(7, target)))
|
||||
if(M.stat == DEAD) //Let us not have dead mobs be used to make a disco inferno.
|
||||
continue
|
||||
if(M.can_block_magic(antimagic_flags)) //Be spared!
|
||||
continue
|
||||
if(active_chasers >= 2)
|
||||
return
|
||||
var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(target), target, M, 1, FALSE)
|
||||
@@ -959,6 +974,7 @@
|
||||
desc = "May you remember lost memories."
|
||||
extended_desc = "will reveal the memories of everyone in range to the user."
|
||||
card_icon = "the_moon?"
|
||||
antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_MIND
|
||||
|
||||
/datum/tarot/reversed/the_moon/activate(mob/living/target)
|
||||
for(var/mob/living/L in view(5, target)) //Shorter range as this kinda can give away antagonists, though that is also funny.
|
||||
|
||||
@@ -499,7 +499,9 @@
|
||||
//Weapons and Armors
|
||||
/datum/spellbook_entry/item/battlemage
|
||||
name = "Battlemage Armor"
|
||||
desc = "An ensorceled spaceproof suit of protective yet light armor, protected by a powerful shield. The shield can completely negate 15 attacks before permanently failing."
|
||||
desc = "An ensorceled spaceproof suit of protective yet light armor, protected by a powerful shield. The shield can completely negate 15 attacks before permanently failing. \
|
||||
This armor grants you full protection from magical attacks, and allows you to cast magic despite that. However, this means it will also block wands or staffs of \
|
||||
healing from working on you, and should be removed before application."
|
||||
item_path = /obj/item/storage/box/wizard/hardsuit
|
||||
limit = 1
|
||||
category = "Weapons and Armors"
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
/obj/effect/forcefield/wizard
|
||||
var/mob/wizard
|
||||
/// Flags for what antimagic can just ignore our forcefields
|
||||
var/antimagic_flags = MAGIC_RESISTANCE
|
||||
|
||||
/obj/effect/forcefield/wizard/Initialize(mapload, mob/summoner)
|
||||
. = ..()
|
||||
@@ -25,6 +27,10 @@
|
||||
/obj/effect/forcefield/wizard/CanPass(atom/movable/mover, border_dir)
|
||||
if(mover == wizard)
|
||||
return TRUE
|
||||
if(isliving(mover))
|
||||
var/mob/living/living_mover = mover
|
||||
if(living_mover.can_block_magic(antimagic_flags, charge_cost = 0))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
///////////Mimewalls///////////
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
var/list/fluff_transformations = list()
|
||||
/// Extra 'Holy' burn damage for ERT null rods
|
||||
var/sanctify_force = 0
|
||||
/// The antimagic type the nullrod has.
|
||||
var/antimagic_type = MAGIC_RESISTANCE_HOLY
|
||||
|
||||
/obj/item/nullrod/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/anti_magic, antimagic_type)
|
||||
if(!length(variant_names))
|
||||
for(var/I in typesof(/obj/item/nullrod))
|
||||
var/obj/item/nullrod/rod = I
|
||||
@@ -37,11 +40,6 @@
|
||||
|
||||
/obj/item/nullrod/attack__legacy__attackchain(mob/M, mob/living/carbon/user)
|
||||
..()
|
||||
var/datum/antagonist/vampire/V = M.mind?.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(ishuman(M) && V && HAS_MIND_TRAIT(M, TRAIT_HOLY))
|
||||
if(!V.get_ability(/datum/vampire_passive/full))
|
||||
to_chat(M, "<span class='warning'>The nullrod's power interferes with your own!</span>")
|
||||
V.adjust_nullification(30 + sanctify_force, 15 + sanctify_force)
|
||||
if(!sanctify_force)
|
||||
return
|
||||
if(isliving(M))
|
||||
@@ -593,6 +591,16 @@
|
||||
to_chat(user, "<span class='notice'>Your prayer to [SSticker.Bible_deity_name] was interrupted.</span>")
|
||||
praying = FALSE
|
||||
|
||||
|
||||
/obj/item/nullrod/nazar
|
||||
name = "nazar"
|
||||
icon_state = "nazar"
|
||||
item_state = null
|
||||
desc = "A set of glass beads and amulet, which has been forged to provide powerful magic protection to the wielder."
|
||||
force = 0
|
||||
throwforce = 0
|
||||
antimagic_type = ALL
|
||||
|
||||
/obj/item/nullrod/salt
|
||||
name = "Holy Salt"
|
||||
icon = 'icons/obj/food/containers.dmi'
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "This spell needs a description!"
|
||||
human_req = TRUE
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
/// A reference to the owner mindflayer's antag datum.
|
||||
var/datum/antagonist/mindflayer/flayer
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ RESTRICT_TYPE(/datum/antagonist/vampire)
|
||||
mob_override.dna?.species.hunger_icon = initial(mob_override.dna.species.hunger_icon)
|
||||
owner.current.alpha = 255
|
||||
REMOVE_TRAITS_IN(owner.current, "vampire")
|
||||
UnregisterSignal(owner, COMSIG_ATOM_HOLY_ATTACK)
|
||||
|
||||
#define BLOOD_GAINED_MODIFIER 0.5
|
||||
|
||||
@@ -362,8 +363,21 @@ RESTRICT_TYPE(/datum/antagonist/vampire)
|
||||
|
||||
mob_override.dna?.species.hunger_icon = 'icons/mob/screen_hunger_vampire.dmi'
|
||||
check_vampire_upgrade(FALSE)
|
||||
RegisterSignal(mob_override, COMSIG_ATOM_HOLY_ATTACK, PROC_REF(holy_attack_reaction))
|
||||
|
||||
|
||||
/datum/antagonist/vampire/proc/holy_attack_reaction(mob/target, obj/item/source, mob/user, antimagic_flags)
|
||||
SIGNAL_HANDLER // COMSIG_ATOM_HOLY_ATTACK
|
||||
if(!HAS_MIND_TRAIT(user, TRAIT_HOLY)) // Sec officer with a nullrod, or miner with a talisman, does not get to do this
|
||||
return
|
||||
if(!source.force) // Needs force to work.
|
||||
return
|
||||
var/bonus_force = 0
|
||||
if(istype(source, /obj/item/nullrod))
|
||||
var/obj/item/nullrod/N = source
|
||||
bonus_force = N.sanctify_force
|
||||
if(!get_ability(/datum/vampire_passive/full))
|
||||
to_chat(owner.current, "<span class='warning'>[source]'s power interferes with your own!</span>")
|
||||
adjust_nullification(30 + bonus_force, 15 + bonus_force)
|
||||
|
||||
/datum/antagonist/vampire/custom_blurb()
|
||||
return "On the date [GLOB.current_date_string], at [station_time_timestamp()],\n in the [station_name()], [get_area_name(owner.current, TRUE)]...\nThe hunt begins again..."
|
||||
|
||||
@@ -161,6 +161,10 @@
|
||||
|
||||
/datum/spell/vampire/switch_places/cast(list/targets, mob/user)
|
||||
var/mob/living/target = targets[1]
|
||||
if(target.can_block_magic(antimagic_flags))
|
||||
to_chat(user, "<span class='warning'>The spell had no effect!</span>")
|
||||
to_chat(target, "<span class='warning'>You feel space bending, but it rapidly dissipates.</span>")
|
||||
return FALSE
|
||||
var/turf/user_turf = get_turf(user)
|
||||
var/turf/target_turf = get_turf(target)
|
||||
if(!(SEND_SIGNAL(target, COMSIG_MOVABLE_TELEPORTING, user_turf) & COMPONENT_BLOCK_TELEPORT))
|
||||
|
||||
@@ -157,6 +157,8 @@
|
||||
|
||||
/obj/item/projectile/magic/demonic_grasp/on_hit(atom/target, blocked, hit_zone)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!isliving(target))
|
||||
return
|
||||
var/mob/living/L = target
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
//Other vampires and thralls aren't affected
|
||||
if(mind?.has_antag_datum(/datum/antagonist/vampire) || mind?.has_antag_datum(/datum/antagonist/mindslave/thrall))
|
||||
return FALSE
|
||||
/// Chaplains with their nullrod can block a full power vampire, but a chaplain by themselfs or a crew with a null rod can not.
|
||||
if(can_block_magic(MAGIC_RESISTANCE_HOLY) && HAS_MIND_TRAIT(src, TRAIT_HOLY))
|
||||
return FALSE
|
||||
//Vampires who have reached their full potential can affect nearly everything
|
||||
var/datum/antagonist/vampire/V = user?.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(V?.get_ability(/datum/vampire_passive/full))
|
||||
@@ -10,12 +13,15 @@
|
||||
//Holy characters are resistant to vampire powers
|
||||
if(HAS_MIND_TRAIT(src, TRAIT_HOLY))
|
||||
return FALSE
|
||||
if(can_block_magic(MAGIC_RESISTANCE_HOLY))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/spell/vampire
|
||||
action_background_icon_state = "bg_vampire"
|
||||
human_req = TRUE
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = MAGIC_RESISTANCE_HOLY
|
||||
/// How much blood this ability costs to use
|
||||
var/required_blood
|
||||
var/deduct_blood_on_cast = TRUE
|
||||
@@ -52,6 +58,7 @@
|
||||
action_icon_state = "vampire_rejuvinate"
|
||||
base_cooldown = 20 SECONDS
|
||||
stat_allowed = UNCONSCIOUS
|
||||
antimagic_flags = NONE // So. If you have a null rod on your person, you can't cast vampire spells. I would rather not have officers abuse this by putting a nullrod in their pocket or something to block rejuvinate.
|
||||
|
||||
/datum/spell/vampire/self/rejuvenate/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/U = user
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
action_background_icon_state = "bg_vampire"
|
||||
human_req = TRUE
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
base_cooldown = 0 SECONDS
|
||||
var/list/our_claws = list()
|
||||
var/infection_stage = 1 // mostly for adminbus and testing
|
||||
|
||||
@@ -200,6 +200,17 @@
|
||||
/obj/item/clothing/suit/space/hardsuit/wizard/setup_shielding()
|
||||
AddComponent(/datum/component/shielded, max_charges = 15, recharge_start_delay = 0 SECONDS)
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/wizard/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
ADD_TRAIT(user, TRAIT_ANTIMAGIC, "[UID(src)]")
|
||||
ADD_TRAIT(user, TRAIT_ANTIMAGIC_NO_SELFBLOCK, "[UID(src)]")
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/wizard/dropped(mob/user)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(user, TRAIT_ANTIMAGIC, "[UID(src)]")
|
||||
REMOVE_TRAIT(user, TRAIT_ANTIMAGIC_NO_SELFBLOCK, "[UID(src)]")
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/wizard/arch
|
||||
desc = "For the arch wizard in need of additional protection."
|
||||
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
|
||||
|
||||
@@ -338,6 +338,7 @@
|
||||
max_charges = 1
|
||||
flags = NOBLUDGEON
|
||||
force = 18
|
||||
antimagic_flags = NONE
|
||||
|
||||
/obj/item/ammo_casing/magic/hook
|
||||
name = "hook"
|
||||
@@ -384,7 +385,7 @@
|
||||
//Immortality Talisman
|
||||
|
||||
/obj/item/immortality_talisman
|
||||
name = "Immortality Talisman"
|
||||
name = "\improper Immortality Talisman"
|
||||
desc = "A dread talisman that can render you completely invulnerable."
|
||||
icon = 'icons/obj/lavaland/artefacts.dmi'
|
||||
icon_state = "talisman"
|
||||
@@ -393,6 +394,21 @@
|
||||
actions_types = list(/datum/action/item_action/immortality)
|
||||
var/cooldown = 0
|
||||
|
||||
/obj/item/immortality_talisman/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/anti_magic, ALL)
|
||||
|
||||
/obj/item/immortality_talisman/equipped(mob/user, slot)
|
||||
..()
|
||||
if(slot != ITEM_SLOT_IN_BACKPACK)
|
||||
var/user_UID = user.UID()
|
||||
ADD_TRAIT(user, TRAIT_ANTIMAGIC_NO_SELFBLOCK, user_UID)
|
||||
|
||||
/obj/item/immortality_talisman/dropped(mob/user, silent)
|
||||
. = ..()
|
||||
var/user_UID = user.UID()
|
||||
REMOVE_TRAIT(user, TRAIT_ANTIMAGIC_NO_SELFBLOCK, user_UID)
|
||||
|
||||
/datum/action/item_action/immortality
|
||||
name = "Immortality"
|
||||
|
||||
|
||||
@@ -184,6 +184,10 @@
|
||||
)
|
||||
hide_tail_by_species = list("Unathi", "Tajaran", "Vox", "Vulpkanin")
|
||||
|
||||
/obj/item/clothing/suit/hooded/berserker/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/anti_magic, ALL, inventory_flags = ITEM_SLOT_OUTER_SUIT)
|
||||
|
||||
/obj/item/clothing/head/hooded/berserker
|
||||
name = "berserker helmet"
|
||||
desc = "Peering into the eyes of the helmet is enough to seal damnation."
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
desc = "Allows you to recruit a conscious, non-braindead, non-catatonic human to be part of the Greyshirts, your personal henchmen. This works on Assistants only and you can recruit a maximum of 3!."
|
||||
base_cooldown = 450
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
action_icon_state = "spell_greytide"
|
||||
var/recruiting = 0
|
||||
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
name = "Unfold/Fold Chassis"
|
||||
desc = "Allows you to fold in/out of your mobile form."
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
base_cooldown = 20 SECONDS
|
||||
action_icon_state = "repairbot"
|
||||
action_background_icon_state = "bg_tech_blue"
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
gain_desc = "You can now charge at a target on screen, dealing massive damage and destroying structures."
|
||||
base_cooldown = 30 SECONDS
|
||||
clothes_req = FALSE
|
||||
antimagic_flags = NONE
|
||||
action_icon_state = "terror_prince"
|
||||
|
||||
/datum/spell/princely_charge/create_new_targeting()
|
||||
|
||||
@@ -1428,3 +1428,90 @@ GLOBAL_LIST_INIT(holy_areas, typecacheof(list(
|
||||
if(user.incapacitated())
|
||||
return
|
||||
return relaydrive(user, direction)
|
||||
|
||||
|
||||
/**
|
||||
* Checks to see if the mob can cast normal magic spells.
|
||||
*
|
||||
* args:
|
||||
* * magic_flags (optional) A bitfield with the type of magic being cast (see flags at: /datum/component/anti_magic)
|
||||
**/
|
||||
/mob/proc/can_cast_magic(magic_flags = MAGIC_RESISTANCE)
|
||||
if(magic_flags == NONE) // magic with the NONE flag can always be cast
|
||||
return TRUE
|
||||
|
||||
var/restrict_magic_flags = SEND_SIGNAL(src, COMSIG_MOB_RESTRICT_MAGIC, magic_flags)
|
||||
return restrict_magic_flags == NONE
|
||||
|
||||
/**
|
||||
* Checks to see if the mob can block magic
|
||||
*
|
||||
* args:
|
||||
* * casted_magic_flags (optional) A bitfield with the types of magic resistance being checked (see flags at: /datum/component/anti_magic)
|
||||
* * charge_cost (optional) The cost of charge to block a spell that will be subtracted from the protection used
|
||||
**/
|
||||
/mob/proc/can_block_magic(casted_magic_flags = MAGIC_RESISTANCE, charge_cost = 1)
|
||||
if(casted_magic_flags == NONE) // magic with the NONE flag is immune to blocking
|
||||
return FALSE
|
||||
|
||||
// A list of all things which are providing anti-magic to us
|
||||
var/list/antimagic_sources = list()
|
||||
var/is_magic_blocked = FALSE
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, casted_magic_flags, charge_cost, antimagic_sources) & COMPONENT_MAGIC_BLOCKED)
|
||||
is_magic_blocked = TRUE
|
||||
if(HAS_TRAIT(src, TRAIT_ANTIMAGIC))
|
||||
is_magic_blocked = TRUE
|
||||
if((casted_magic_flags & MAGIC_RESISTANCE_HOLY) && HAS_TRAIT(src, TRAIT_HOLY))
|
||||
is_magic_blocked = TRUE
|
||||
|
||||
if(is_magic_blocked && charge_cost > 0 && !HAS_TRAIT(src, TRAIT_RECENTLY_BLOCKED_MAGIC))
|
||||
on_block_magic_effects(casted_magic_flags, antimagic_sources)
|
||||
|
||||
return is_magic_blocked
|
||||
|
||||
/// Called whenever a magic effect with a charge cost is blocked and we haven't recently blocked magic.
|
||||
/mob/proc/on_block_magic_effects(magic_flags, list/antimagic_sources)
|
||||
return
|
||||
|
||||
/mob/living/on_block_magic_effects(magic_flags, list/antimagic_sources)
|
||||
ADD_TRAIT(src, TRAIT_RECENTLY_BLOCKED_MAGIC, MAGIC_TRAIT)
|
||||
addtimer(CALLBACK(src, PROC_REF(remove_recent_magic_block)), 6 SECONDS)
|
||||
|
||||
var/mutable_appearance/antimagic_effect
|
||||
var/antimagic_color
|
||||
var/atom/antimagic_source = length(antimagic_sources) ? pick(antimagic_sources) : src
|
||||
|
||||
if(magic_flags & MAGIC_RESISTANCE)
|
||||
visible_message(
|
||||
"<span class='warning'>[src] pulses red as [ismob(antimagic_source) ? p_they() : antimagic_source] absorbs magic energy!</span>",
|
||||
"<span class='userdanger'>An intense magical aura pulses around [ismob(antimagic_source) ? "you" : antimagic_source] as it dissipates into the air!</span>",
|
||||
)
|
||||
antimagic_effect = mutable_appearance('icons/effects/effects.dmi', "shield-red", ABOVE_MOB_LAYER)
|
||||
antimagic_color = LIGHT_COLOR_BLOOD_MAGIC
|
||||
playsound(src, 'sound/magic/magic_block.ogg', 50, TRUE)
|
||||
|
||||
else if(magic_flags & MAGIC_RESISTANCE_HOLY)
|
||||
visible_message(
|
||||
"<span class='warning'>[src] starts to glow as [ismob(antimagic_source) ? p_they() : antimagic_source] emits a halo of light!</span>",
|
||||
"<span class='userdanger'>A feeling of warmth washes over [ismob(antimagic_source) ? "you" : antimagic_source] as rays of light surround your body and protect you!</span>",
|
||||
)
|
||||
antimagic_effect = mutable_appearance('icons/mob/genetics.dmi', "servitude", ABOVE_MOB_LAYER)
|
||||
antimagic_color = LIGHT_COLOR_HOLY_MAGIC
|
||||
playsound(src, 'sound/magic/magic_block_holy.ogg', 50, TRUE)
|
||||
|
||||
else if(magic_flags & MAGIC_RESISTANCE_MIND)
|
||||
visible_message(
|
||||
"<span class='warning'>[src] forehead shines as [ismob(antimagic_source) ? p_they() : antimagic_source] repulses magic from their mind!</span>",
|
||||
"<span class='userdanger'>A feeling of cold splashes on [ismob(antimagic_source) ? "you" : antimagic_source] as your forehead reflects magic usering your mind!</span>",
|
||||
)
|
||||
antimagic_effect = mutable_appearance('icons/mob/genetics.dmi', "telekinesishead", ABOVE_MOB_LAYER)
|
||||
antimagic_color = LIGHT_COLOR_DARK_BLUE
|
||||
playsound(src, 'sound/magic/magic_block_mind.ogg', 50, TRUE)
|
||||
|
||||
mob_light(_color = antimagic_color, _range = 2, _power = 2, _duration = 5 SECONDS)
|
||||
add_overlay(antimagic_effect)
|
||||
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, cut_overlay), antimagic_effect), 5 SECONDS)
|
||||
|
||||
/mob/living/proc/remove_recent_magic_block()
|
||||
REMOVE_TRAIT(src, TRAIT_RECENTLY_BLOCKED_MAGIC, MAGIC_TRAIT)
|
||||
|
||||
@@ -366,12 +366,17 @@
|
||||
var/insignia_type = /obj/item/mod/module/insignia
|
||||
/// Additional module we add, as a treat.
|
||||
var/additional_module
|
||||
/// Inquisitorial module, as we have reached that point.
|
||||
var/inquisitorial_module
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/Initialize(mapload, new_theme, new_skin, new_core)
|
||||
applied_modules.Insert(1, insignia_type)
|
||||
if(additional_module)
|
||||
applied_modules += additional_module
|
||||
default_pins += additional_module
|
||||
if(inquisitorial_module)
|
||||
applied_modules += inquisitorial_module
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/commander
|
||||
@@ -410,9 +415,10 @@
|
||||
insignia_type = /obj/item/mod/module/insignia/chaplain
|
||||
additional_module = /obj/item/mod/module/injector
|
||||
|
||||
/// Diffrent look, as well as magic proof on TG. We don't have the magic proof stuff here, but it's perfect for inqusitors. Or if you want to give your ERT a fancy look.
|
||||
/// Diffrent look, as well as magic proof. It's perfect for inqusitors. Or if you want to give your ERT a fancy look. At this time, the other ones are unused, and frankly I don't like the idea of antimagic gamma.
|
||||
/obj/item/mod/control/pre_equipped/responsory/inquisitory
|
||||
applied_skin = "inquisitory"
|
||||
inquisitorial_module = /obj/item/mod/module/anti_magic
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/inquisitory/commander
|
||||
insignia_type = /obj/item/mod/module/insignia/commander
|
||||
|
||||
@@ -527,6 +527,24 @@
|
||||
/obj/item/mod/module/energy_shield/gamma
|
||||
shield_icon = "shield-old"
|
||||
|
||||
///Magic Nullifier - Protects you from magic.
|
||||
/obj/item/mod/module/anti_magic
|
||||
name = "MOD magic nullifier module"
|
||||
desc = "A series of obsidian rods installed into critical points around the suit, \
|
||||
vibrated at a certain low frequency to enable them to resonate. \
|
||||
This creates a low-range, yet strong, magic nullification field around the user, \
|
||||
aided by a full replacement of the suit's normal coolant with holy water. \
|
||||
Spells will spall right off this field, though it'll do nothing to help others believe you about all this."
|
||||
icon_state = "magic_nullifier"
|
||||
removable = FALSE
|
||||
incompatible_modules = list(/obj/item/mod/module/anti_magic)
|
||||
|
||||
/obj/item/mod/module/anti_magic/on_suit_activation()
|
||||
ADD_TRAIT(mod.wearer, TRAIT_ANTIMAGIC, "[UID(src)]")
|
||||
|
||||
/obj/item/mod/module/anti_magic/on_suit_deactivation(deleting = FALSE)
|
||||
REMOVE_TRAIT(mod.wearer, TRAIT_ANTIMAGIC, "[UID(src)]")
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/teslawall
|
||||
name = "MOD arc-shield module" // temp
|
||||
desc = "A module that uses a flux core to project an unstable protective shield." //change
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
/obj/item/projectile/magic/chaos/on_hit(atom/target, blocked = 0)
|
||||
. = ..()
|
||||
|
||||
if(!.)
|
||||
return
|
||||
if(iswallturf(target) || isobj(target))
|
||||
target.color = pick(GLOB.random_color_list)
|
||||
return
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
var/can_charge = TRUE
|
||||
var/ammo_type
|
||||
var/no_den_usage
|
||||
var/antimagic_flags = MAGIC_RESISTANCE
|
||||
origin_tech = null
|
||||
clumsy_check = FALSE
|
||||
trigger_guard = TRIGGER_GUARD_ALLOW_ALL // Has no trigger at all, uses magic instead
|
||||
@@ -31,6 +32,9 @@
|
||||
return
|
||||
else
|
||||
no_den_usage = 0
|
||||
if(!user.can_cast_magic(antimagic_flags))
|
||||
to_chat(user, "<span class='warning'>[src] whizzles quietly.</span>")
|
||||
return FALSE
|
||||
..()
|
||||
|
||||
/obj/item/gun/magic/can_shoot()
|
||||
|
||||
@@ -6,6 +6,28 @@
|
||||
nodamage = 1
|
||||
armour_penetration_percentage = 100
|
||||
flag = MAGIC
|
||||
/// determines what type of antimagic can block the spell projectile
|
||||
var/antimagic_flags = MAGIC_RESISTANCE
|
||||
/// determines the drain cost on the antimagic item
|
||||
var/antimagic_charge_cost = 1
|
||||
|
||||
/obj/item/projectile/magic/prehit(atom/target)
|
||||
if(isliving(target))
|
||||
var/mob/living/victim = target
|
||||
if(victim.can_block_magic(antimagic_flags, antimagic_charge_cost))
|
||||
visible_message("<span class='warning'>[src] fizzles on contact with [victim]!</span>")
|
||||
damage = 0
|
||||
nodamage = 1
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/magic/on_hit(atom/target, blocked, hit_zone)
|
||||
if(isliving(target))
|
||||
var/mob/living/victim = target
|
||||
if(victim.can_block_magic(antimagic_flags, antimagic_charge_cost)) // Yes we have to check this twice welcome to bullet hell code
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/projectile/magic/death
|
||||
name = "bolt of death"
|
||||
@@ -21,7 +43,7 @@
|
||||
muzzle_flash_range = 2
|
||||
muzzle_flash_color_override = LIGHT_COLOR_PURPLE
|
||||
impact_light_intensity = 7
|
||||
impact_light_range = 2.5
|
||||
impact_light_range = 2.5
|
||||
impact_light_color_override = LIGHT_COLOR_PURPLE
|
||||
|
||||
/obj/item/projectile/magic/fireball
|
||||
@@ -41,6 +63,8 @@
|
||||
|
||||
/obj/item/projectile/magic/death/on_hit(mob/living/carbon/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
if(isliving(target))
|
||||
if(target.mob_biotypes & MOB_UNDEAD) //negative energy heals the undead
|
||||
if(target.revive())
|
||||
@@ -75,6 +99,8 @@
|
||||
|
||||
/obj/item/projectile/magic/fireball/on_hit(target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
var/turf/T = get_turf(target)
|
||||
explosion(T, exp_devastate, exp_heavy, exp_light, exp_flash, 0, flame_range = exp_fire)
|
||||
if(ismob(target)) //multiple flavors of pain
|
||||
@@ -95,6 +121,8 @@
|
||||
|
||||
/obj/item/projectile/magic/resurrection/on_hit(mob/living/carbon/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
if(ismob(target))
|
||||
if(target.mob_biotypes & MOB_UNDEAD) //positive energy harms the undead
|
||||
target.death(FALSE)
|
||||
@@ -121,6 +149,8 @@
|
||||
|
||||
/obj/item/projectile/magic/teleport/on_hit(mob/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
var/teleammount = 0
|
||||
var/teleloc = target
|
||||
if(!isturf(target))
|
||||
@@ -142,6 +172,8 @@
|
||||
|
||||
/obj/item/projectile/magic/door/on_hit(atom/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
var/atom/T = target.loc
|
||||
if(isturf(target) && target.density)
|
||||
if(!(istype(target, /turf/simulated/wall/indestructible)))
|
||||
@@ -179,6 +211,8 @@
|
||||
|
||||
/obj/item/projectile/magic/change/on_hit(atom/change)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
wabbajack(change)
|
||||
|
||||
GLOBAL_LIST_INIT(wabbajack_hostile_animals, list(
|
||||
@@ -380,6 +414,9 @@ GLOBAL_LIST_INIT(wabbajack_docile_animals, list(
|
||||
SpinAnimation()
|
||||
|
||||
/obj/item/projectile/magic/slipping/on_hit(atom/target, blocked = 0)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return .
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.slip(src, slip_weaken, 0, FALSE, TRUE) //Slips even with noslips/magboots on. NO ESCAPE!
|
||||
@@ -394,7 +431,6 @@ GLOBAL_LIST_INIT(wabbajack_docile_animals, list(
|
||||
to_chat(target, "<span class='notice'>You get splatted by [src].</span>")
|
||||
L.Weaken(slip_weaken)
|
||||
L.Stun(slip_stun)
|
||||
. = ..()
|
||||
|
||||
/obj/item/projectile/magic/arcane_barrage
|
||||
name = "arcane bolt"
|
||||
|
||||
@@ -506,6 +506,7 @@
|
||||
clothes_req = FALSE
|
||||
invocation = "none"
|
||||
invocation_type = "none"
|
||||
antimagic_flags = NONE
|
||||
selection_activated_message = "You warm up your Binyat deck, there's an idle buzzing at the back of your mind as it awaits a target."
|
||||
selection_deactivated_message = "Your hacking deck makes an almost disappointed sounding buzz at the back of your mind as it powers down."
|
||||
action_icon_state = "hackerman"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
+3
-1
@@ -83,6 +83,7 @@
|
||||
#include "code\__DEFINES\lighting_defines.dm"
|
||||
#include "code\__DEFINES\logs.dm"
|
||||
#include "code\__DEFINES\machines.dm"
|
||||
#include "code\__DEFINES\magic_defines.dm"
|
||||
#include "code\__DEFINES\mappers.dm"
|
||||
#include "code\__DEFINES\martial_arts.dm"
|
||||
#include "code\__DEFINES\MC.dm"
|
||||
@@ -428,6 +429,7 @@
|
||||
#include "code\datums\cache\crew.dm"
|
||||
#include "code\datums\cache\powermonitor.dm"
|
||||
#include "code\datums\components\_component.dm"
|
||||
#include "code\datums\components\anti_magic.dm"
|
||||
#include "code\datums\components\boomerang.dm"
|
||||
#include "code\datums\components\boss_music.dm"
|
||||
#include "code\datums\components\caltrop.dm"
|
||||
@@ -930,8 +932,8 @@
|
||||
#include "code\game\machinery\computer\prisoner.dm"
|
||||
#include "code\game\machinery\computer\robot_control.dm"
|
||||
#include "code\game\machinery\computer\security_records.dm"
|
||||
#include "code\game\machinery\computer\sm_monitor.dm"
|
||||
#include "code\game\machinery\computer\singulo_monitor.dm"
|
||||
#include "code\game\machinery\computer\sm_monitor.dm"
|
||||
#include "code\game\machinery\computer\station_alert.dm"
|
||||
#include "code\game\machinery\computer\arcade_games\recruiter.dm"
|
||||
#include "code\game\machinery\doors\airlock.dm"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user