// Contains all /mob/procs that relate to vampire. // Makes vampire's victim not get paralyzed, and remember the suckings /mob/living/carbon/human/proc/vampire_alertness() set category = "Vampire" set name = "Victim Alertness" set desc = "Toggle whether you wish for your victims to get paralyzed and forget your deeds." var/datum/vampire/vampire = vampire_power(0, 0) vampire.stealth = !vampire.stealth if(vampire.stealth) to_chat(src, SPAN_NOTICE("Your victims will now forget your interactions, and get paralyzed when you do them.")) else to_chat(src, SPAN_NOTICE("Your victims will now remember your interactions, and stay completely mobile during them.")) // Drains the target's blood. /mob/living/carbon/human/proc/vampire_drain_blood() set category = "Vampire" set name = "Drain Blood" set desc = "Drain the blood of a humanoid creature." var/datum/vampire/vampire = vampire_power(0, 0) if (!vampire) return var/obj/item/grab/G = get_active_hand() if (!istype(G)) to_chat(src, SPAN_WARNING("You must be grabbing a victim in your active hand to drain their blood.")) return if (G.state == GRAB_PASSIVE || G.state == GRAB_UPGRADING) to_chat(src, SPAN_WARNING("You must have the victim pinned to the ground to drain their blood.")) return var/mob/living/carbon/human/T = G.affecting if (!istype(T) || T.species.flags & NO_BLOOD) //Added this to prevent vampires draining diona and IPCs //Diona have 'blood' but its really green sap and shouldn't help vampires //IPCs leak oil to_chat(src, SPAN_WARNING("[T] is not a creature you can drain useful blood from.")) return if(T.head && (T.head.item_flags & AIRTIGHT)) to_chat(src, SPAN_WARNING("[T]'s headgear is blocking the way to the neck.")) return var/obj/item/blocked = check_mouth_coverage() if(blocked) to_chat(src, SPAN_WARNING("\The [blocked] is in the way of your fangs!")) return if (vampire.status & VAMP_DRAINING) to_chat(src, SPAN_WARNING("Your fangs are already sunk into a victim's neck!")) return var/datum/vampire/draining_vamp = null if (T.mind && T.mind.vampire) draining_vamp = T.mind.vampire var/target_aware = !!T.client var/blood = 0 var/blood_total = 0 var/blood_usable = 0 vampire.status |= VAMP_DRAINING visible_message("[src.name] bites [T.name]'s neck!", "You bite [T.name]'s neck and begin to drain their blood.", "You hear a soft puncture and a wet sucking noise") var/remembrance if(vampire.stealth) remembrance = "forgot" else remembrance = "remembered" admin_attack_log(src, T, "drained blood from [key_name(T)], who [remembrance] the encounter.", "had their blood drained by [key_name(src)] and [remembrance] the encounter.", "is draining blood from") if(vampire.stealth) to_chat(T, SPAN_WARNING("You are unable to resist or even move. Your mind blanks as you're being fed upon.")) T.paralysis = 3400 else to_chat(T, SPAN_WARNING("You are unable to resist or even move. Your mind is acutely aware of what's occuring.")) T.paralysis = 3400 playsound(src.loc, 'sound/effects/drain_blood_new.ogg', 50, 1) while (do_mob(src, T, 50)) if (!mind.vampire) to_chat(src, SPAN_DANGER("Your fangs have disappeared!")) return blood_total = vampire.blood_total blood_usable = vampire.blood_usable if (!T.vessel.get_reagent_amount(/datum/reagent/blood)) to_chat(src, SPAN_DANGER("[T] has no more blood left to give.")) break if (!T.stunned) T.Stun(10) var/frenzy_lower_chance = 0 // Alive and not of empty mind. if (check_drain_target_state(T)) blood = min(15, T.vessel.get_reagent_amount(/datum/reagent/blood)) vampire.blood_total += blood vampire.blood_usable += blood frenzy_lower_chance = 40 if (draining_vamp) vampire.blood_vamp += blood // Each point of vampire blood will increase your chance to frenzy. vampire.frenzy += blood // And drain the vampire as well. draining_vamp.blood_usable -= min(blood, draining_vamp.blood_usable) vampire_check_frenzy() frenzy_lower_chance = 0 // SSD/protohuman or dead. else blood = min(5, T.vessel.get_reagent_amount(/datum/reagent/blood)) vampire.blood_usable += blood frenzy_lower_chance = 40 if (prob(frenzy_lower_chance) && vampire.frenzy > 0) vampire.frenzy-- if (blood_total != vampire.blood_total) var/update_msg = "You have accumulated [vampire.blood_total] [vampire.blood_total > 1 ? "units" : "unit"] of blood" if (blood_usable != vampire.blood_usable) update_msg += " and have [vampire.blood_usable] left to use." else update_msg += "." to_chat(src, update_msg) check_vampire_upgrade() T.vessel.remove_reagent(/datum/reagent/blood, 5) vampire.status &= ~VAMP_DRAINING var/endsuckmsg = "You extract your fangs from [T.name]'s neck and stop draining them of blood." if(vampire.stealth) endsuckmsg += "They will remember nothing of this occurance, provided they survived." visible_message("[src.name] stops biting [T.name]'s neck!", "[endsuckmsg]") if(target_aware) T.paralysis = 0 if(T.stat != DEAD && vampire.stealth) to_chat(T.find_mob_consciousness(), SPAN_WARNING("You remember nothing about being fed upon. Instead, you simply remember having a pleasant encounter with [src.name].")) else if(T.stat != DEAD) to_chat(T.find_mob_consciousness(), SPAN_WARNING("You remember everything about being fed upon. How you react to [src.name]'s actions is up to you.")) // Check that our target is alive, logged in, and any other special cases /mob/living/carbon/human/proc/check_drain_target_state(var/mob/living/carbon/human/T) if(T.stat < DEAD) if(T.client || (T.bg && T.bg.client)) return TRUE // Small area of effect stun. /mob/living/carbon/human/proc/vampire_glare() set category = "Vampire" set name = "Glare" set desc = "Your eyes flash a bright light, stunning any who are watching." if (!vampire_power(0, 1)) return if (!has_eyes()) to_chat(src, "You don't have eyes!") return if (istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) to_chat(src, "You're blindfolded!") return visible_message("[src.name]'s eyes emit a blinding flash!") var/list/victims = list() for (var/mob/living/carbon/human/H in view(2)) if (H == src) continue if (!vampire_can_affect_target(H, 0)) continue H.Weaken(8) H.stuttering = 20 H.confused = 10 to_chat(H, "You are blinded by [src]'s glare!") flick("flash", H.flash) victims += H admin_attacker_log_many_victims(src, victims, "used glare to stun", "was stunned by [key_name(src)] using glare", "used glare to stun") verbs -= /mob/living/carbon/human/proc/vampire_glare ADD_VERB_IN_IF(src, 800, /mob/living/carbon/human/proc/vampire_glare, CALLBACK(src, .proc/finish_vamp_timeout)) // Targeted stun ability, moderate duration. /mob/living/carbon/human/proc/vampire_hypnotise() set category = "Vampire" set name = "Hypnotise (10)" set desc = "Through blood magic, you dominate the victim's mind and force them into a hypnotic transe." var/datum/vampire/vampire = vampire_power(10, 1) if (!vampire) return if (!has_eyes()) to_chat(src, "You don't have eyes!") return var/list/victims = list() for (var/mob/living/carbon/human/H in view(3)) if (H == src) continue victims += H if (!victims.len) to_chat(src, "No suitable targets.") return var/mob/living/carbon/human/T = input(src, "Select Victim") as null|mob in victims if (!vampire_can_affect_target(T)) return to_chat(src, "You begin peering into [T.name]'s mind, looking for a way to render them useless.") if (do_mob(src, T, 50)) to_chat(src, "You dominate [T.name]'s mind and render them temporarily powerless to resist.") to_chat(T, "You are captivated by [src.name]'s gaze, and find yourself unable to move or even speak.") T.Weaken(25) T.Stun(25) T.silent += 30 vampire.use_blood(10) admin_attack_log(src, T, "used hypnotise to stun [key_name(T)]", "was stunned by [key_name(src)] using hypnotise", "used hypnotise on") verbs -= /mob/living/carbon/human/proc/vampire_hypnotise ADD_VERB_IN_IF(src, 1200, /mob/living/carbon/human/proc/vampire_hypnotise, CALLBACK(src, .proc/finish_vamp_timeout)) else to_chat(src, "You broke your gaze.") // Targeted teleportation, must be to a low-light tile. /mob/living/carbon/human/proc/vampire_veilstep(var/turf/T in turfs) set category = "Vampire" set name = "Veil Step (20)" set desc = "For a moment, move through the Veil and emerge at a shadow of your choice." if (!T || T.density || T.contains_dense_objects()) to_chat(src, "You cannot do that.") return var/datum/vampire/vampire = vampire_power(20, 1) if (!vampire) return if (!istype(loc, /turf)) to_chat(src, "You cannot teleport out of your current location.") return if (T.z != src.z || get_dist(T, get_turf(src)) > world.view) to_chat(src, "Your powers are not capable of taking you that far.") return if (T.get_lumcount() > 0.1) // Too bright, cannot jump into. to_chat(src, "The destination is too bright.") return vampire_phase_out(get_turf(loc)) forceMove(T) vampire_phase_in(T) for (var/obj/item/grab/G in contents) if (G.affecting && (vampire.status & VAMP_FULLPOWER)) G.affecting.vampire_phase_out(get_turf(G.affecting.loc)) G.affecting.forceMove(locate(T.x + rand(-1,1), T.y + rand(-1,1), T.z)) G.affecting.vampire_phase_in(get_turf(G.affecting.loc)) else qdel(G) log_and_message_admins("activated veil step.") vampire.use_blood(20) verbs -= /mob/living/carbon/human/proc/vampire_veilstep ADD_VERB_IN_IF(src, 300, /mob/living/carbon/human/proc/vampire_veilstep, CALLBACK(src, .proc/finish_vamp_timeout)) // Summons bats. /mob/living/carbon/human/proc/vampire_bats() set category = "Vampire" set name = "Summon Bats (60)" set desc = "You tear open the Veil for just a moment, in order to summon a pair of bats to assist you in combat." var/datum/vampire/vampire = vampire_power(60, 0) if (!vampire) return var/list/locs = list() for (var/direction in alldirs) if (locs.len == 2) break var/turf/T = get_step(src, direction) if (AStar(src.loc, T, /turf/proc/AdjacentTurfs, /turf/proc/Distance, 1)) locs += T var/list/spawned = list() if (locs.len) for (var/turf/to_spawn in locs) spawned += new /mob/living/simple_animal/hostile/scarybat(to_spawn, src) if (spawned.len != 2) spawned += new /mob/living/simple_animal/hostile/scarybat(src.loc, src) else spawned += new /mob/living/simple_animal/hostile/scarybat(src.loc, src) spawned += new /mob/living/simple_animal/hostile/scarybat(src.loc, src) if (!spawned.len) return for (var/mob/living/simple_animal/hostile/scarybat/bat in spawned) LAZYADD(bat.friends, src) if (vampire.thralls.len) LAZYADD(bat.friends, vampire.thralls) log_and_message_admins("summoned bats.") vampire.use_blood(60) verbs -= /mob/living/carbon/human/proc/vampire_bats ADD_VERB_IN_IF(src, 1200, /mob/living/carbon/human/proc/vampire_bats, CALLBACK(src, .proc/finish_vamp_timeout)) // Chiropteran Screech /mob/living/carbon/human/proc/vampire_screech() set category = "Vampire" set name = "Chiropteran Screech (90)" set desc = "Emit a powerful screech which shatters glass within a seven-tile radius, and stuns hearers in a four-tile radius." var/datum/vampire/vampire = vampire_power(90, 0) if (!vampire) return visible_message("[src.name] lets out an ear piercin shriek!", "You let out an ear-shattering shriek!", "You hear a painfully loud shriek!") var/list/victims = list() for (var/mob/living/carbon/human/T in hearers(4, src)) if (T == src) continue if (istype(T) && (T.l_ear || T.r_ear) && istype((T.l_ear || T.r_ear), /obj/item/clothing/ears/earmuffs)) continue if (!vampire_can_affect_target(T, 0)) continue to_chat(T, "You hear an ear piercing shriek and feel your senses go dull!") T.Weaken(5) T.ear_deaf = 20 T.stuttering = 20 T.Stun(5) victims += T for (var/obj/structure/window/W in view(7)) W.shatter() for (var/obj/machinery/light/L in view(7)) L.broken() playsound(src.loc, 'sound/effects/creepyshriek.ogg', 100, 1) vampire.use_blood(90) if (victims.len) admin_attacker_log_many_victims(src, victims, "used chriopteran screech to stun", "was stunned by [key_name(src)] using chriopteran screech", "used chiropteran screech to stun") else log_and_message_admins("used chiropteran screech.") verbs -= /mob/living/carbon/human/proc/vampire_screech ADD_VERB_IN_IF(src, 3600, /mob/living/carbon/human/proc/vampire_screech, CALLBACK(src, .proc/finish_vamp_timeout)) // Enables the vampire to be untouchable and walk through walls and other solid things. /mob/living/carbon/human/proc/vampire_veilwalk() set category = "Vampire" set name = "Toggle Veil Walking (80)" set desc = "You enter the veil, leaving only an incorporeal manifestation of you visible to the others." var/datum/vampire/vampire = vampire_power(0, 0, 1) if (!vampire) return if (vampire.holder) vampire.holder.deactivate() else vampire = vampire_power(80, 0, 1) if (!vampire) return var/obj/effect/dummy/veil_walk/holder = new /obj/effect/dummy/veil_walk(get_turf(loc)) holder.activate(src) log_and_message_admins("activated veil walk.") vampire.use_blood(80) // Veilwalk's dummy holder /obj/effect/dummy/veil_walk name = "a red ghost" desc = "A red, shimmering presence." icon = 'icons/mob/mob.dmi' icon_state = "blank" density = FALSE var/last_valid_turf = null var/can_move = TRUE var/mob/owner_mob = null var/datum/vampire/owner_vampire = null var/warning_level = 0 /obj/effect/dummy/veil_walk/Destroy() eject_all() STOP_PROCESSING(SSprocessing, src) return ..() /obj/effect/dummy/veil_walk/proc/eject_all() for (var/atom/movable/A in src) A.forceMove(loc) if (ismob(A)) var/mob/M = A M.reset_view(null) /obj/effect/dummy/veil_walk/relaymove(var/mob/user, direction) if (!can_move) return var/turf/new_loc = get_step(src, direction) if (new_loc.flags & NOJAUNT || istype(new_loc.loc, /area/chapel)) to_chat(usr, "Some strange aura is blocking the way!") return forceMove(new_loc) var/turf/T = get_turf(loc) if (!T.contains_dense_objects()) last_valid_turf = T can_move = 0 addtimer(CALLBACK(src, .proc/unlock_move), 2, TIMER_UNIQUE) /obj/effect/dummy/veil_walk/process() if (owner_mob.stat) if (owner_mob.stat == 1) to_chat(owner_mob, "You cannot maintain this form while unconcious.") addtimer(CALLBACK(src, .proc/kick_unconcious), 10, TIMER_UNIQUE) else deactivate() return if (owner_vampire.blood_usable >= 5) owner_vampire.use_blood(5) switch (warning_level) if (0) if (owner_vampire.blood_usable <= 5 * 20) to_chat(owner_mob, "Your pool of blood is diminishing. You cannot stay in the veil for too long.") warning_level = 1 if (1) if (owner_vampire.blood_usable <= 5 * 10) to_chat(owner_mob, "You will be ejected from the veil soon, as your pool of blood is running dry.") warning_level = 2 if (2) if (owner_vampire.blood_usable <= 5 * 5) to_chat(owner_mob, "You cannot sustain this form for any longer!") warning_level = 3 else deactivate() /obj/effect/dummy/veil_walk/proc/activate(var/mob/owner) if (!owner) qdel(src) return owner_mob = owner owner_vampire = owner.vampire_power() if (!owner_vampire) qdel(src) return owner_vampire.holder = src owner.vampire_phase_out(get_turf(owner.loc)) icon_state = "veil_ghost" last_valid_turf = get_turf(owner.loc) owner.forceMove(src) desc += " Its features look faintly alike [owner.name]'s." START_PROCESSING(SSprocessing, src) /obj/effect/dummy/veil_walk/proc/deactivate() STOP_PROCESSING(SSprocessing, src) can_move = 0 icon_state = "blank" owner_mob.vampire_phase_in(get_turf(loc)) eject_all() owner_mob = null owner_vampire.holder = null owner_vampire = null qdel(src) /obj/effect/dummy/veil_walk/proc/unlock_move() can_move = 1 /obj/effect/dummy/veil_walk/proc/kick_unconcious() if (owner_mob && owner_mob.stat == 1) to_chat(owner_mob, "You are ejected from the Veil.") deactivate() return /obj/effect/dummy/veil_walk/ex_act(vars) return /obj/effect/dummy/veil_walk/bullet_act(vars) return // Heals the vampire at the cost of blood. /mob/living/carbon/human/proc/vampire_bloodheal() set category = "Vampire" set name = "Blood Heal" set desc = "At the cost of blood and time, heal any injuries you have sustained." var/datum/vampire/vampire = vampire_power(0, 0) if (!vampire) return // Kick out of the already running loop. if (vampire.status & VAMP_HEALING) vampire.status &= ~VAMP_HEALING return else if (vampire.blood_usable < 15) to_chat(src, "You do not have enough usable blood. 15 needed.") return vampire.status |= VAMP_HEALING to_chat(src, "You begin the process of blood healing. Do not move, and ensure that you are not interrupted.") log_and_message_admins("activated blood heal.") while (do_after(src, 20, 0)) if (!(vampire.status & VAMP_HEALING)) to_chat(src, "Your concentration is broken! You are no longer regenerating!") break var/tox_loss = getToxLoss() var/oxy_loss = getOxyLoss() var/ext_loss = getBruteLoss() + getFireLoss() var/clone_loss = getCloneLoss() var/blood_used = 0 var/to_heal = 0 if (tox_loss) to_heal = min(10, tox_loss) adjustToxLoss(0 - to_heal) blood_used += round(to_heal * 1.2) if (oxy_loss) to_heal = min(10, oxy_loss) adjustOxyLoss(0 - to_heal) blood_used += round(to_heal * 1.2) if (ext_loss) to_heal = min(20, ext_loss) heal_overall_damage(min(10, getBruteLoss()), min(10, getFireLoss())) blood_used += round(to_heal * 1.2) if (clone_loss) to_heal = min(10, clone_loss) adjustCloneLoss(0 - to_heal) blood_used += round(to_heal * 1.2) var/list/organs = get_damaged_organs(1, 1) if (organs.len) // Heal an absurd amount, basically regenerate one organ. heal_organ_damage(50, 50) blood_used += 12 for (var/A in organs) var/healed = FALSE var/obj/item/organ/external/E = A if(E.status & ORGAN_ARTERY_CUT) E.status &= ~ORGAN_ARTERY_CUT blood_used += 12 if(E.status & ORGAN_TENDON_CUT) E.status &= ~ORGAN_TENDON_CUT blood_used += 12 if(E.status & ORGAN_BROKEN) E.status &= ~ORGAN_BROKEN E.stage = 0 blood_used += 12 healed = TRUE if (healed) break var/list/emotes_lookers = list("[src]'s skin appears to liquefy for a moment, sealing up their wounds.", "[src]'s veins turn black as their damaged flesh regenerates before your eyes!", "[src]'s skin begins to split open. It turns to ash and falls away, revealing the wound to be fully healed.", "Whispering arcane things, [src]'s damaged flesh appears to regenerate.", "Thick globs of blood cover a wound on [src]'s body, eventually melding to be one with [get_pronoun("his")] flesh.", "[src]'s body crackles, skin and bone shifting back into place.") var/list/emotes_self = list("Your skin appears to liquefy for a moment, sealing up your wounds.", "Your veins turn black as their damaged flesh regenerates before your eyes!", "Your skin begins to split open. It turns to ash and falls away, revealing the wound to be fully healed.", "Whispering arcane things, your damaged flesh appears to regenerate.", "Thick globs of blood cover a wound on your body, eventually melding to be one with your flesh.", "Your body crackles, skin and bone shifting back into place.") if (prob(20)) visible_message("[pick(emotes_lookers)]", "[pick(emotes_self)]") if (vampire.blood_usable <= blood_used) vampire.blood_usable = 0 vampire.status &= ~VAMP_HEALING to_chat(src, "You ran out of blood, and are unable to continue!") break else if (!blood_used) vampire.status &= ~VAMP_HEALING to_chat(src, "Your body has finished healing. You are ready to continue.") break // We broke out of the loop naturally. Gotta catch that. if (vampire.status & VAMP_HEALING) vampire.status &= ~VAMP_HEALING to_chat(src, "Your concentration is broken! You are no longer regenerating!") return // Dominate a victim, imbed a thought into their mind. /mob/living/carbon/human/proc/vampire_dominate() set category = "Vampire" set name = "Dominate (50)" set desc = "Dominate the mind of a victim, make them obey your will." var/datum/vampire/vampire = vampire_power(25, 0) if (!vampire) return var/list/victims = list() for (var/mob/living/carbon/human/H in view(7)) if (H == src) continue victims += H if (!victims.len) to_chat(src, "No suitable targets.") return var/mob/living/carbon/human/T = input(src, "Select Victim") as null|mob in victims if (!vampire_can_affect_target(T, 1, 1)) return if (!(vampire.status & VAMP_FULLPOWER)) to_chat(src, "You begin peering into [T]'s mind, looking for a way to gain control.") if (!do_mob(src, T, 50)) to_chat(src, "Your concentration is broken!") return to_chat(src, "You succeed in dominating [T]'s mind. They are yours to command.") else to_chat(src, "You instantly dominate [T]'s mind, forcing them to obey your command.") var/command = input(src, "Command your victim.", "Your command.") as text|null if (!command) to_chat(src, "Cancelled.") return command = sanitizeSafe(command, extra = 0) admin_attack_log(src, T, "used dominate on [key_name(T)]", "was dominated by [key_name(src)]", "used dominate and issued the command of '[command]' to") show_browser(T, "