mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-15 00:53:23 +01:00
Removes Shadowstep. replace it with 2 powers for each vampire type. (#18951)
* WIP * shadow boxing * garg + hemomancer * dantalion and stuff * oops * some tweaks * sprites, tweaks and TGUI * ready for review * review * forgot some sean comments * oops * prevents people walking over shockwaves * shadow boxing DPS down to 20 * oops * affected review
This commit is contained in:
@@ -21,8 +21,7 @@
|
||||
/obj/effect/proc_holder/spell/vampire/glare = 0,
|
||||
/datum/vampire_passive/vision = 100,
|
||||
/obj/effect/proc_holder/spell/vampire/self/specialize = 150,
|
||||
/datum/vampire_passive/regen = 200,
|
||||
/obj/effect/proc_holder/spell/turf_teleport/shadow_step = 250)
|
||||
/datum/vampire_passive/regen = 200)
|
||||
|
||||
/// list of the peoples UIDs that we have drained, and how much blood from each one
|
||||
var/list/drained_humans = list()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/mindslave/thrall)
|
||||
|
||||
/datum/vampire_passive/increment_thrall_cap/on_apply(datum/antagonist/vampire/V)
|
||||
V.subclass.thrall_cap += 1
|
||||
V.subclass.thrall_cap++
|
||||
gain_desc = "You can now thrall one more person, up to a maximum of [V.subclass.thrall_cap]"
|
||||
|
||||
/datum/vampire_passive/increment_thrall_cap/two
|
||||
@@ -143,6 +143,30 @@
|
||||
for(var/mob/living/carbon/human/H as anything in targets)
|
||||
H.apply_status_effect(STATUS_EFFECT_PACIFIED)
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/switch_places
|
||||
name = "Subspace Swap (30)"
|
||||
desc = "Switch positions with a target."
|
||||
gain_desc = "You have gained the ability to switch positions with a targeted mob."
|
||||
centcom_cancast = FALSE
|
||||
action_icon_state = "subspace_swap"
|
||||
base_cooldown = 30 SECONDS
|
||||
required_blood = 30
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/switch_places/create_new_targeting()
|
||||
var/datum/spell_targeting/click/T = new
|
||||
T.range = 7
|
||||
T.click_radius = 1
|
||||
T.try_auto_target = FALSE
|
||||
T.allowed_type = /mob/living
|
||||
return T
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/switch_places/cast(list/targets, mob/user)
|
||||
var/mob/living/target = targets[1]
|
||||
var/turf/user_turf = get_turf(user)
|
||||
var/turf/target_turf = get_turf(target)
|
||||
target.forceMove(user_turf)
|
||||
user.forceMove(target_turf)
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/decoy
|
||||
name = "Deploy Decoy (30)"
|
||||
desc = "Briefly turn invisible and deploy a decoy illusion to fool your prey."
|
||||
@@ -186,6 +210,20 @@
|
||||
H.add_overlay(I)
|
||||
addtimer(CALLBACK(H, /atom/.proc/cut_overlay, I), 6 SECONDS) // this makes it obvious who your thralls are for a while.
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/share_damage
|
||||
name = "Blood Bond"
|
||||
desc = "Creates a net between you and your nearby thralls that evenly shares all damage recieved."
|
||||
gain_desc = "You have gained the ability to share damage between you and your thralls."
|
||||
action_icon_state = "blood_bond"
|
||||
required_blood = 5
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/share_damage/cast(list/targets, mob/living/user)
|
||||
var/datum/status_effect/thrall_net/T = user.has_status_effect(STATUS_EFFECT_THRALL_NET)
|
||||
if(!T)
|
||||
user.apply_status_effect(STATUS_EFFECT_THRALL_NET, user.mind.has_antag_datum(/datum/antagonist/vampire))
|
||||
return
|
||||
qdel(T)
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/hysteria
|
||||
name = "Mass Hysteria (70)"
|
||||
desc = "Casts a powerful illusion to make everyone nearby percieve others to looks like random animals after briefly blinding them."
|
||||
|
||||
@@ -12,6 +12,63 @@
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.apply_status_effect(STATUS_EFFECT_BLOOD_SWELL)
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/stomp
|
||||
name = "Seismic Stomp (30)"
|
||||
desc = "You slam your foot into the ground sending a powerful shockwave through the station's hull, sending people flying away. Cannot be cast if you legs are impared by a bola or similar."
|
||||
gain_desc = "You have gained the ability to knock people back using a powerful stomp."
|
||||
action_icon_state = "seismic_stomp"
|
||||
base_cooldown = 60 SECONDS
|
||||
required_blood = 30
|
||||
var/max_range = 4
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/stomp/can_cast(mob/living/carbon/user, charge_check, show_message)
|
||||
if(user.legcuffed)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/stomp/cast(list/targets, mob/user)
|
||||
var/turf/T = get_turf(user)
|
||||
playsound(T, 'sound/effects/meteorimpact.ogg', 100, TRUE)
|
||||
addtimer(CALLBACK(src, .proc/hit_check, 1, T, user), 0.2 SECONDS)
|
||||
new /obj/effect/temp_visual/stomp(T)
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/stomp/proc/hit_check(range, turf/start_turf, mob/user, safe_targets = list())
|
||||
// gets the two outermost turfs in a ring, we get two so people cannot "walk over" the shockwave
|
||||
var/list/targets = view(range, start_turf) - view(range - 2, start_turf)
|
||||
for(var/turf/simulated/floor/flooring in targets)
|
||||
if(prob(100 - (range * 20)))
|
||||
flooring.ex_act(EXPLODE_LIGHT)
|
||||
|
||||
for(var/mob/living/L in targets)
|
||||
if(L in safe_targets)
|
||||
continue
|
||||
if(L.throwing) // no double hits
|
||||
continue
|
||||
if(!L.affects_vampire(user))
|
||||
continue
|
||||
if(L.move_resist > MOVE_FORCE_VERY_STRONG)
|
||||
continue
|
||||
var/throw_target = get_edge_target_turf(L, get_dir(start_turf, L))
|
||||
INVOKE_ASYNC(L, /atom/movable/.proc/throw_at, throw_target, 3, 4)
|
||||
L.KnockDown(1 SECONDS)
|
||||
safe_targets += L
|
||||
var/new_range = range + 1
|
||||
if(new_range <= max_range)
|
||||
addtimer(CALLBACK(src, .proc/hit_check, new_range, start_turf, user, safe_targets), 0.2 SECONDS)
|
||||
|
||||
/obj/effect/temp_visual/stomp
|
||||
icon = 'icons/effects/seismic_stomp_effect.dmi'
|
||||
icon_state = "stomp_effect"
|
||||
duration = 0.8 SECONDS
|
||||
pixel_y = -16
|
||||
pixel_x = -16
|
||||
|
||||
/obj/effect/temp_visual/stomp/Initialize(mapload)
|
||||
. = ..()
|
||||
var/matrix/M = matrix() * 0.5
|
||||
transform = M
|
||||
animate(src, transform = M * 8, time = duration, alpha = 0)
|
||||
|
||||
/datum/vampire_passive/blood_swell_upgrade
|
||||
gain_desc = "While blood swell is active all of your melee attacks deal increased damage."
|
||||
|
||||
@@ -48,6 +105,79 @@
|
||||
to_chat(H, "<span class='notice'>You feel a rush of energy!</span>")
|
||||
H.apply_status_effect(STATUS_EFFECT_BLOOD_RUSH)
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/demonic_grasp
|
||||
name = "Demonic Grasp (20)"
|
||||
desc = "Fire a hand of demonic energy, snaring and throwing its target around, based on your intent. Disarm pushes, grab pulls."
|
||||
gain_desc = "You have gained the ability to snare and disrupt people with demonic apendages."
|
||||
base_cooldown = 30 SECONDS
|
||||
fireball_type = /obj/item/projectile/magic/demonic_grasp
|
||||
|
||||
selection_activated_message = "<span class='notice'>You raise your hand, full of demonic energy! <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>You re-absorb the energy...for now.</span>"
|
||||
|
||||
action_icon_state = "demonic_grasp"
|
||||
|
||||
panel = "Vampire"
|
||||
school = "vampire"
|
||||
action_background_icon_state = "bg_vampire"
|
||||
sound = null
|
||||
invocation_type = "none"
|
||||
invocation = null
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/demonic_grasp/update_icon_state()
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/demonic_grasp/create_new_handler()
|
||||
var/datum/spell_handler/vampire/V = new()
|
||||
V.required_blood = 20
|
||||
return V
|
||||
|
||||
/obj/item/projectile/magic/demonic_grasp
|
||||
name = "demonic grasp"
|
||||
// parry this you filthy casual
|
||||
reflectability = REFLECTABILITY_NEVER
|
||||
icon_state = null
|
||||
|
||||
/obj/item/projectile/magic/demonic_grasp/pixel_move(trajectory_multiplier)
|
||||
. = ..()
|
||||
new /obj/effect/temp_visual/demonic_grasp(loc)
|
||||
|
||||
/obj/item/projectile/magic/demonic_grasp/on_hit(atom/target, blocked, hit_zone)
|
||||
. = ..()
|
||||
if(!isliving(target))
|
||||
return
|
||||
var/mob/living/L = target
|
||||
L.Immobilize(1 SECONDS)
|
||||
var/throw_target
|
||||
if(!firer)
|
||||
return
|
||||
|
||||
if(!L.affects_vampire(firer))
|
||||
return
|
||||
|
||||
new /obj/effect/temp_visual/demonic_grasp(loc)
|
||||
|
||||
switch(firer.a_intent)
|
||||
if(INTENT_DISARM)
|
||||
throw_target = get_edge_target_turf(L, get_dir(firer, L))
|
||||
L.throw_at(throw_target, 2, 5, spin = FALSE, callback = CALLBACK(src, .proc/create_snare, L)) // shove away
|
||||
if(INTENT_GRAB)
|
||||
throw_target = get_step(firer, get_dir(firer, L))
|
||||
L.throw_at(throw_target, 2, 5, spin = FALSE, diagonals_first = TRUE, callback = CALLBACK(src, .proc/create_snare, L)) // pull towards
|
||||
|
||||
/obj/item/projectile/magic/demonic_grasp/proc/create_snare(mob/target)
|
||||
new /obj/effect/temp_visual/demonic_snare(target.loc)
|
||||
|
||||
/obj/effect/temp_visual/demonic_grasp
|
||||
icon = 'icons/effects/vampire_effects.dmi'
|
||||
icon_state = "demonic_grasp"
|
||||
duration = 3.5 SECONDS
|
||||
|
||||
/obj/effect/temp_visual/demonic_snare
|
||||
icon = 'icons/effects/vampire_effects.dmi'
|
||||
icon_state = "immobilized"
|
||||
duration = 1 SECONDS
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/charge
|
||||
name = "Charge (30)"
|
||||
desc = "You charge at wherever you click on screen, dealing large amounts of damage, stunning and destroying walls and other objects."
|
||||
@@ -61,7 +191,7 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/charge/can_cast(mob/user, charge_check, show_message)
|
||||
var/mob/living/L = user
|
||||
if(L.IsWeakened() || IS_HORIZONTAL(L))
|
||||
if(IS_HORIZONTAL(L))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut", "savaged", "clawed")
|
||||
sprite_sheets_inhand = list("Vox" = 'icons/mob/clothing/species/vox/held.dmi', "Drask" = 'icons/mob/clothing/species/drask/held.dmi')
|
||||
var/durability = 20
|
||||
var/durability = 15
|
||||
var/blood_drain_amount = 15
|
||||
var/blood_absorbed_amount = 5
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
return
|
||||
|
||||
var/datum/antagonist/vampire/V = user.mind?.has_antag_datum(/datum/antagonist/vampire)
|
||||
var/mob/living/attacker = user
|
||||
|
||||
if(!V)
|
||||
return
|
||||
@@ -56,23 +57,15 @@
|
||||
if(C.ckey && C.stat != DEAD && C.affects_vampire() && !(NO_BLOOD in C.dna.species.species_traits))
|
||||
C.bleed(blood_drain_amount)
|
||||
V.adjust_blood(C, blood_absorbed_amount)
|
||||
durability--
|
||||
if(durability <= 0)
|
||||
qdel(src)
|
||||
to_chat(user, "<span class='warning'>Your claws shatter!</span>")
|
||||
attacker.adjustStaminaLoss(-20) // security is dead
|
||||
attacker.heal_overall_damage(4, 4) // the station is full
|
||||
attacker.AdjustKnockDown(-1 SECONDS) // blood is fuel
|
||||
|
||||
/obj/item/twohanded/required/vamp_claws/Initialize(mapload)
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/twohanded/required/vamp_claws/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/required/vamp_claws/process()
|
||||
durability--
|
||||
if(durability <= 0)
|
||||
qdel(src)
|
||||
if(!V.get_ability(/datum/vampire_passive/blood_spill))
|
||||
durability--
|
||||
if(durability <= 0)
|
||||
qdel(src)
|
||||
to_chat(user, "<span class='warning'>Your claws shatter!</span>")
|
||||
|
||||
/obj/item/twohanded/required/vamp_claws/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text, final_block_chance, damage, attack_type)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
@@ -133,6 +126,101 @@
|
||||
/obj/effect/temp_visual/blood_tendril/long
|
||||
duration = 2 SECONDS
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/blood_barrier
|
||||
name = "Blood Barrier (40)"
|
||||
desc = "Select two points within 3 tiles of each other and make a barrier between them."
|
||||
gain_desc = "You have gained the ability to summon a crystaline wall of blood between two points, the barrier is easily destructable, however you can walk freely through it."
|
||||
required_blood = 40
|
||||
base_cooldown = 1 MINUTES
|
||||
should_recharge_after_cast = FALSE
|
||||
deduct_blood_on_cast = FALSE
|
||||
action_icon_state = "blood_barrier"
|
||||
|
||||
var/max_walls = 3
|
||||
var/turf/start_turf = null
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/blood_barrier/create_new_targeting()
|
||||
var/datum/spell_targeting/click/T = new
|
||||
T.allowed_type = /atom
|
||||
T.try_auto_target = FALSE
|
||||
return T
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/blood_barrier/remove_ranged_ability(mob/user, msg)
|
||||
. = ..()
|
||||
if(msg) // this is only true if the user intentionally turned off the spell
|
||||
start_turf = null
|
||||
should_recharge_after_cast = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/blood_barrier/should_remove_click_intercept()
|
||||
if(start_turf)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/blood_barrier/cast(list/targets, mob/user)
|
||||
var/turf/target_turf = get_turf(targets[1])
|
||||
if(target_turf == start_turf)
|
||||
to_chat(user, "<span class='notice'>You deselect the targeted turf.</span>")
|
||||
start_turf = null
|
||||
should_recharge_after_cast = FALSE
|
||||
return
|
||||
if(!start_turf)
|
||||
start_turf = target_turf
|
||||
should_recharge_after_cast = TRUE
|
||||
return
|
||||
var/wall_count
|
||||
for(var/turf/T in getline(target_turf, start_turf))
|
||||
if(max_walls <= wall_count)
|
||||
break
|
||||
new /obj/structure/blood_barrier(T)
|
||||
wall_count++
|
||||
var/datum/spell_handler/vampire/V = custom_handler
|
||||
var/datum/antagonist/vampire/vampire = user.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
var/blood_cost = V.calculate_blood_cost(vampire)
|
||||
vampire.bloodusable -= blood_cost
|
||||
start_turf = null
|
||||
should_recharge_after_cast = FALSE
|
||||
|
||||
/obj/structure/blood_barrier
|
||||
name = "blood barrier"
|
||||
desc = "a grotesque structure of crystalised blood. It's slowly melting away..."
|
||||
max_integrity = 100
|
||||
icon_state = "blood_barrier"
|
||||
icon = 'icons/effects/vampire_effects.dmi'
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
opacity = FALSE
|
||||
|
||||
/obj/structure/blood_barrier/Initialize(mapload)
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/structure/blood_barrier/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/structure/blood_barrier/process()
|
||||
take_damage(20, sound_effect = FALSE)
|
||||
|
||||
/obj/structure/blood_barrier/obj_destruction(damage_flag)
|
||||
new /obj/effect/decal/cleanable/blood(loc)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/structure/blood_barrier/CanPass(atom/movable/mover, turf/target, height)
|
||||
if(!isliving(mover))
|
||||
return FALSE
|
||||
var/mob/living/L = mover
|
||||
if(!L.mind)
|
||||
return FALSE
|
||||
var/datum/antagonist/vampire/V = L.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
if(!V)
|
||||
return FALSE
|
||||
if(is_type_in_list(V.subclass, list(SUBCLASS_HEMOMANCER, SUBCLASS_ANCIENT)))
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/ethereal_jaunt/blood_pool
|
||||
name = "Sanguine Pool (50)"
|
||||
desc = "You shift your form into a pool of blood, making you invulnerable and able to move through anything that's not a wall or space. You leave a trail of blood behind you when you do this."
|
||||
@@ -155,6 +243,36 @@
|
||||
H.required_blood = 50
|
||||
return H
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/predator_senses
|
||||
name = "Predator Senses"
|
||||
desc = "Hunt down your prey, there's nowhere to hide..."
|
||||
gain_desc = "Your senses are heightened, nobody can hide from you now."
|
||||
action_icon_state = "predator_sense"
|
||||
base_cooldown = 20 SECONDS
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/predator_senses/create_new_targeting()
|
||||
var/datum/spell_targeting/alive_mob_list/A = new()
|
||||
A.allowed_type = /mob/living/carbon/human
|
||||
A.max_targets = 300 // hopefully we never hit this number
|
||||
return A
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/predator_senses/valid_target(mob/target, mob/user)
|
||||
return target.z == user.z && target.mind
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/predator_senses/cast(list/targets, mob/user)
|
||||
var/targets_by_name = list()
|
||||
for(var/mob/living/carbon/human/H as anything in targets)
|
||||
targets_by_name[H.real_name] = H
|
||||
|
||||
var/target_name = input(user, "Person to Locate", "Blood Stench") in targets_by_name
|
||||
if(!target_name)
|
||||
return
|
||||
var/mob/living/carbon/human/target = targets_by_name[target_name]
|
||||
var/message = "[target_name] is in [get_area(target)], [dir2text(get_dir(user, target))] from you."
|
||||
if(target.get_damage_amount() >= 40 || target.bleed_rate)
|
||||
message += "<i> They are wounded...</i>"
|
||||
to_chat(user, "<span class='cultlarge'>[message]</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/blood_eruption
|
||||
name = "Blood Eruption (100)"
|
||||
desc = "Every pool of blood in 4 tiles erupts with a spike of living blood, damaging anyone stood on it."
|
||||
@@ -194,7 +312,7 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/blood_spill
|
||||
name = "The Blood Bringers Rite"
|
||||
desc = "When toggled, everyone around you begins to bleed profusely."
|
||||
desc = "When toggled, everyone around you begins to bleed profusely. You will drain their blood and rejuvenate yourself with it."
|
||||
gain_desc = "You have gained the ability to rip the very life force out of people and absorb it, healing you."
|
||||
base_cooldown = 10 SECONDS
|
||||
action_icon_state = "blood_bringers_rite"
|
||||
@@ -221,9 +339,8 @@
|
||||
|
||||
/datum/vampire_passive/blood_spill/process()
|
||||
var/beam_number = 0
|
||||
var/turf/T = get_turf(owner)
|
||||
var/datum/antagonist/vampire/V = owner.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
for(var/mob/living/carbon/human/H in view(7, T))
|
||||
for(var/mob/living/carbon/human/H in view(7, owner))
|
||||
if(NO_BLOOD in H.dna.species.species_traits)
|
||||
continue
|
||||
|
||||
@@ -245,6 +362,8 @@
|
||||
|
||||
if(beam_number >= max_beams)
|
||||
break
|
||||
|
||||
V.bloodusable = max(V.bloodusable - 10, 0)
|
||||
|
||||
if(!V.bloodusable || owner.stat == DEAD)
|
||||
V.remove_ability(src)
|
||||
|
||||
@@ -106,6 +106,96 @@
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/soul_anchor
|
||||
name = "Soul Anchor (30)"
|
||||
desc = "You summon a dimenional anchor after a delay, casting again will teleport you back to the anchor. You are forced back after 2 minutes if you have not cast again."
|
||||
gain_desc = "You have gained the ability to save a point in space and teleport back to it at will. Unless you willingly teleport back to that point within 2 minutes, you are forced back."
|
||||
required_blood = 30
|
||||
centcom_cancast = FALSE
|
||||
base_cooldown = 3 MINUTES
|
||||
action_icon_state = "shadow_anchor"
|
||||
should_recharge_after_cast = FALSE
|
||||
deduct_blood_on_cast = FALSE
|
||||
var/obj/structure/shadow_anchor/anchor
|
||||
/// Are we making an anchor?
|
||||
var/making_anchor = FALSE
|
||||
/// Holds a reference to the timer until the caster is forced to recall
|
||||
var/timer
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/soul_anchor/create_new_targeting()
|
||||
return new /datum/spell_targeting/self
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/soul_anchor/cast(list/targets, mob/user)
|
||||
if(making_anchor) // second cast, but we are impatient
|
||||
to_chat(user, "<span class='notice'>Your anchor isn't ready yet!</span>")
|
||||
return
|
||||
|
||||
if(!making_anchor && !anchor) // first cast, setup the anchor
|
||||
var/turf/anchor_turf = get_turf(user)
|
||||
making_anchor = TRUE
|
||||
if(do_mob(user, user, 10 SECONDS, only_use_extra_checks = TRUE)) // no checks, cant fail
|
||||
make_anchor(user, anchor_turf)
|
||||
making_anchor = FALSE
|
||||
return
|
||||
|
||||
if(anchor) // second cast, teleport us back
|
||||
recall(user)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/soul_anchor/proc/make_anchor(mob/user, turf/anchor_turf)
|
||||
anchor = new(anchor_turf)
|
||||
timer = addtimer(CALLBACK(src, .proc/recall, user), 2 MINUTES, TIMER_STOPPABLE)
|
||||
should_recharge_after_cast = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/soul_anchor/proc/recall(mob/user)
|
||||
if(timer)
|
||||
deltimer(timer)
|
||||
timer = null
|
||||
var/turf/start_turf = get_turf(user)
|
||||
var/turf/end_turf = get_turf(anchor)
|
||||
QDEL_NULL(anchor)
|
||||
if(end_turf.z != start_turf.z)
|
||||
return
|
||||
if(!is_teleport_allowed(end_turf.z))
|
||||
return
|
||||
|
||||
user.forceMove(end_turf)
|
||||
|
||||
if(end_turf.z == start_turf.z)
|
||||
shadow_to_animation(start_turf, end_turf, user)
|
||||
|
||||
var/datum/spell_handler/vampire/V = custom_handler
|
||||
var/datum/antagonist/vampire/vampire = user.mind.has_antag_datum(/datum/antagonist/vampire)
|
||||
var/blood_cost = V.calculate_blood_cost(vampire)
|
||||
vampire.bloodusable -= blood_cost
|
||||
addtimer(VARSET_CALLBACK(src, should_recharge_after_cast, FALSE), 1 SECONDS) // this is needed so that the spell handler knows we casted it properly
|
||||
|
||||
/proc/shadow_to_animation(turf/start_turf, turf/end_turf, mob/user)
|
||||
var/x_difference = end_turf.x - start_turf.x
|
||||
var/y_difference = end_turf.y - start_turf.y
|
||||
var/distance = sqrt(x_difference ** 2 + y_difference ** 2) // pythag baby
|
||||
|
||||
var/obj/effect/immortality_talisman/effect = new(start_turf)
|
||||
effect.dir = user.dir
|
||||
effect.can_destroy = TRUE
|
||||
|
||||
var/animation_time = distance
|
||||
animate(effect, time = animation_time, alpha = 0, pixel_x = x_difference * 32, pixel_y = y_difference * 32) //each turf is 32 pixels long
|
||||
QDEL_IN(effect, animation_time)
|
||||
|
||||
// an indicator that shows where the vampire will land
|
||||
/obj/structure/shadow_anchor
|
||||
name = "shadow anchor"
|
||||
desc = "Looking at this thing makes you feel uneasy..."
|
||||
icon = 'icons/obj/cult.dmi'
|
||||
icon_state = "pylon"
|
||||
alpha = 120
|
||||
color = "#545454"
|
||||
density = TRUE
|
||||
opacity = FALSE
|
||||
anchored = TRUE
|
||||
flags = INDESTRUCTIBLE
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/dark_passage
|
||||
name = "Dark Passage (30)"
|
||||
desc = "You teleport to a targeted turf."
|
||||
@@ -152,6 +242,26 @@
|
||||
for(var/atom/A in T.contents)
|
||||
A.extinguish_light()
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/shadow_boxing
|
||||
name = "Shadow Boxing (50)"
|
||||
desc = "Target someone to have your shadow beat them up. You must stay within 2 tiles for this to work."
|
||||
gain_desc = "You have gained the ability to make your shadow fight for you."
|
||||
base_cooldown = 30 SECONDS
|
||||
action_icon_state = "shadow_boxing"
|
||||
required_blood = 50
|
||||
var/target_UID
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/shadow_boxing/create_new_targeting()
|
||||
var/datum/spell_targeting/click/C = new
|
||||
C.allowed_type = /mob/living
|
||||
C.range = 2
|
||||
C.try_auto_target = FALSE
|
||||
return C
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/shadow_boxing/cast(list/targets, mob/user)
|
||||
var/mob/living/target = targets[1]
|
||||
target.apply_status_effect(STATUS_EFFECT_SHADOW_BOXING, user)
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/self/eternal_darkness
|
||||
name = "Eternal Darkness"
|
||||
desc = "When toggled, you shroud the area around you in darkness and slowly lower the body temperature of people nearby."
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
/obj/effect/proc_holder/spell/vampire/self/specialize/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "SpecMenu", "Specialisation Menu", 1200, 600, master_ui, state)
|
||||
ui = new(user, src, ui_key, "SpecMenu", "Specialisation Menu", 1200, 760, master_ui, state)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
@@ -330,30 +330,3 @@
|
||||
H.mind.make_vampire()
|
||||
H.revive()
|
||||
H.Weaken(40 SECONDS)
|
||||
|
||||
/obj/effect/proc_holder/spell/turf_teleport/shadow_step
|
||||
name = "Shadow Step (30)"
|
||||
desc = "Teleport to a nearby dark region"
|
||||
gain_desc = "You have gained the ability to shadowstep, which makes you disappear into nearby shadows at the cost of blood."
|
||||
action_icon_state = "shadowblink"
|
||||
base_cooldown = 2 SECONDS
|
||||
clothes_req = FALSE
|
||||
centcom_cancast = FALSE
|
||||
include_space = FALSE
|
||||
panel = "Vampire"
|
||||
school = "vampire"
|
||||
action_background_icon_state = "bg_vampire"
|
||||
|
||||
// Teleport radii
|
||||
inner_tele_radius = 0
|
||||
outer_tele_radius = 6
|
||||
|
||||
include_light_turfs = FALSE
|
||||
|
||||
sound1 = null
|
||||
sound2 = null
|
||||
|
||||
/obj/effect/proc_holder/spell/turf_teleport/shadow_step/create_new_handler()
|
||||
var/datum/spell_handler/vampire/H = new
|
||||
H.required_blood = 30
|
||||
return H
|
||||
|
||||
@@ -25,8 +25,10 @@
|
||||
name = "umbrae"
|
||||
standard_powers = list(/obj/effect/proc_holder/spell/vampire/self/cloak = 150,
|
||||
/obj/effect/proc_holder/spell/vampire/shadow_snare = 250,
|
||||
/obj/effect/proc_holder/spell/vampire/soul_anchor = 250,
|
||||
/obj/effect/proc_holder/spell/vampire/dark_passage = 400,
|
||||
/obj/effect/proc_holder/spell/vampire/vamp_extinguish = 600)
|
||||
/obj/effect/proc_holder/spell/vampire/vamp_extinguish = 600,
|
||||
/obj/effect/proc_holder/spell/vampire/shadow_boxing = 800)
|
||||
fully_powered_abilities = list(/datum/vampire_passive/full,
|
||||
/obj/effect/proc_holder/spell/vampire/self/eternal_darkness,
|
||||
/datum/vampire_passive/xray)
|
||||
@@ -35,8 +37,10 @@
|
||||
name = "hemomancer"
|
||||
standard_powers = list(/obj/effect/proc_holder/spell/vampire/self/vamp_claws = 150,
|
||||
/obj/effect/proc_holder/spell/vampire/blood_tendrils = 250,
|
||||
/obj/effect/proc_holder/spell/vampire/blood_barrier = 250,
|
||||
/obj/effect/proc_holder/spell/ethereal_jaunt/blood_pool = 400,
|
||||
/obj/effect/proc_holder/spell/vampire/blood_eruption = 600)
|
||||
/obj/effect/proc_holder/spell/vampire/predator_senses = 600,
|
||||
/obj/effect/proc_holder/spell/vampire/blood_eruption = 800)
|
||||
fully_powered_abilities = list(/datum/vampire_passive/full,
|
||||
/obj/effect/proc_holder/spell/vampire/self/blood_spill)
|
||||
|
||||
@@ -44,8 +48,10 @@
|
||||
name = "gargantua"
|
||||
standard_powers = list(/obj/effect/proc_holder/spell/vampire/self/blood_swell = 150,
|
||||
/obj/effect/proc_holder/spell/vampire/self/blood_rush = 250,
|
||||
/obj/effect/proc_holder/spell/vampire/self/stomp = 250,
|
||||
/datum/vampire_passive/blood_swell_upgrade = 400,
|
||||
/obj/effect/proc_holder/spell/vampire/self/overwhelming_force = 600)
|
||||
/obj/effect/proc_holder/spell/vampire/self/overwhelming_force = 600,
|
||||
/obj/effect/proc_holder/spell/fireball/demonic_grasp = 800)
|
||||
fully_powered_abilities = list(/datum/vampire_passive/full,
|
||||
/obj/effect/proc_holder/spell/vampire/charge)
|
||||
improved_rejuv_healing = TRUE
|
||||
@@ -55,10 +61,12 @@
|
||||
standard_powers = list(/obj/effect/proc_holder/spell/vampire/enthrall = 150,
|
||||
/obj/effect/proc_holder/spell/vampire/thrall_commune = 150,
|
||||
/obj/effect/proc_holder/spell/vampire/pacify = 250,
|
||||
/obj/effect/proc_holder/spell/vampire/switch_places = 250,
|
||||
/obj/effect/proc_holder/spell/vampire/self/decoy = 400,
|
||||
/datum/vampire_passive/increment_thrall_cap = 400,
|
||||
/obj/effect/proc_holder/spell/vampire/rally_thralls = 600,
|
||||
/datum/vampire_passive/increment_thrall_cap/two = 600)
|
||||
/datum/vampire_passive/increment_thrall_cap/two = 600,
|
||||
/obj/effect/proc_holder/spell/vampire/self/share_damage = 800)
|
||||
fully_powered_abilities = list(/datum/vampire_passive/full,
|
||||
/obj/effect/proc_holder/spell/vampire/hysteria,
|
||||
/datum/vampire_passive/increment_thrall_cap/three)
|
||||
@@ -72,17 +80,25 @@
|
||||
/obj/effect/proc_holder/spell/vampire/enthrall,
|
||||
/obj/effect/proc_holder/spell/vampire/thrall_commune,
|
||||
/obj/effect/proc_holder/spell/vampire/blood_tendrils,
|
||||
/obj/effect/proc_holder/spell/vampire/blood_barrier,
|
||||
/obj/effect/proc_holder/spell/vampire/self/blood_rush,
|
||||
/obj/effect/proc_holder/spell/vampire/self/stomp,
|
||||
/obj/effect/proc_holder/spell/vampire/shadow_snare,
|
||||
/obj/effect/proc_holder/spell/vampire/soul_anchor,
|
||||
/obj/effect/proc_holder/spell/vampire/pacify,
|
||||
/obj/effect/proc_holder/spell/vampire/switch_places,
|
||||
/obj/effect/proc_holder/spell/ethereal_jaunt/blood_pool,
|
||||
/datum/vampire_passive/blood_swell_upgrade,
|
||||
/obj/effect/proc_holder/spell/vampire/dark_passage,
|
||||
/obj/effect/proc_holder/spell/vampire/self/decoy,
|
||||
/obj/effect/proc_holder/spell/vampire/blood_eruption,
|
||||
/obj/effect/proc_holder/spell/vampire/predator_senses,
|
||||
/obj/effect/proc_holder/spell/vampire/self/overwhelming_force,
|
||||
/obj/effect/proc_holder/spell/vampire/vamp_extinguish,
|
||||
/obj/effect/proc_holder/spell/vampire/rally_thralls,
|
||||
/obj/effect/proc_holder/spell/vampire/self/share_damage,
|
||||
/obj/effect/proc_holder/spell/fireball/demonic_grasp,
|
||||
/obj/effect/proc_holder/spell/vampire/shadow_boxing,
|
||||
/datum/vampire_passive/full,
|
||||
/obj/effect/proc_holder/spell/vampire/self/blood_spill,
|
||||
/obj/effect/proc_holder/spell/vampire/charge,
|
||||
|
||||
@@ -564,7 +564,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
|
||||
var/atom/movable/AM = hit_atom
|
||||
var/atom/throw_target = get_edge_target_turf(AM, dir)
|
||||
if(!AM.anchored || ismecha(AM))
|
||||
AM.throw_at(throw_target, 3, 14, src)
|
||||
AM.throw_at(throw_target, 5, 12, src)
|
||||
hit_something = TRUE
|
||||
if(isobj(hit_atom))
|
||||
var/obj/O = hit_atom
|
||||
@@ -573,7 +573,8 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
|
||||
if(isliving(hit_atom))
|
||||
var/mob/living/L = hit_atom
|
||||
L.adjustBruteLoss(60)
|
||||
L.Weaken(6 SECONDS)
|
||||
L.KnockDown(12 SECONDS)
|
||||
L.Confused(10 SECONDS)
|
||||
shake_camera(L, 4, 3)
|
||||
hit_something = TRUE
|
||||
if(isturf(hit_atom))
|
||||
|
||||
Reference in New Issue
Block a user