/datum/abilityHolder/revenant topBarRendered = 1 usesPoints = 1 var/channeling = 0 var/datum/abilityHolder/wraith/relay = null var/datum/bioEffect/hidden/revenant/revenant = null pointName = "Wraith Points" Stat() if (relay) relay.Stat() if (owner) stat("Human vessel integrity:", "[(owner.max_health + 50) / 1.5]%") generatePoints() if (relay) relay.generatePoints() deductPoints(cost) if (relay) return relay.deductPoints(cost) return 1 pointCheck(cost) if (!relay) return 1 if (!relay.usesPoints) return 1 if (relay.points < 0) // Just-in-case fallback. logTheThing("debug", usr, null, "'s ability holder ([relay.type]) was set to an invalid value (points less than 0), resetting.") relay.points = 0 if (cost > relay.points) boutput(owner, relay.notEnoughPointsMessage) return 0 return 1 /datum/bioEffect/hidden/revenant name = "Revenant" desc = "The subject appears to be possessed by a wraith." id = "revenant" effectType = effectTypePower isBad = 0 // depends on who you ask really var/isDying = 0 var/mob/wraith/wraith = null var/ghoulTouchActive = 0 var/list/abilities proc/ghoulTouch(var/mob/living/carbon/human/poorSob, var/obj/item/affecting) if (poorSob.bioHolder.HasEffect("training_chaplain")) poorSob.visible_message("[poorSob]'s faith shields them from [owner]'s ethereal force!", "Your faith protects you from [owner]'s ethereal force!") return else poorSob.visible_message("[poorSob] is hit by [owner]'s ethereal force!", "You are hit by [owner]'s ethereal force!") if (istype(affecting)) affecting.take_damage(4, 4, 0, DAMAGE_BLUNT) else poorSob.TakeDamage("All", 4, 4, 0, DAMAGE_BLUNT) poorSob.weakened += 2 step_away(poorSob, owner, 15) sleep(3) step_away(poorSob, owner, 15) proc/wraithPossess(var/mob/wraith/W) if (!W.mind && !W.client) return if (owner.client || owner.mind) var/mob/dead/observer/O = owner.ghostize() if (O) O.corpse = null owner.ghost = null if (owner.ghost) owner.ghost.corpse = null owner.ghost = null src.wraith = W W.invisibility = 50 W.set_loc(src.owner) W.abilityHolder.suspendAllAbilities() message_admins("[key_name(wraith)] possessed the corpse of [owner] as a revenant at [showCoords(owner.x, owner.y, owner.z)].") logTheThing("combat", usr, null, "possessed the corpse of [owner] as a revenant at [showCoords(owner.x, owner.y, owner.z)].") if (src.wraith.mind) // theoretically shouldn't happen src.wraith.mind.transfer_to(owner) else src.wraith.client.mob = owner owner.visible_message("[pick("[owner] suddenly rises from the floor!", "[owner] suddenly looks a lot less dead!", "A dark light shines from [owner]'s eyes!")]",\ "[pick("You force your will into [owner]'s corpse.", "Your dark will forces [owner] to rise.", "You assume direct control of [owner].")]") src.addRevenantVerbs() OnAdd() if (ishuman(owner) && owner.stat == 2) switch (owner:decomp_stage) if (0) owner.max_health = 100 if (1) owner.max_health = 75 if (2) owner.max_health = 50 if (3) owner.max_health = 25 if (4) // todo: send message, tell the player to fuck off, or something owner.bioHolder.RemoveEffect("revenant") qdel(src) return else // do not possess non-humans; do not possess living people; do not pass go; do not collect $200 qdel(src) return owner.full_heal() owner.reagents.clear_reagents() owner.blinded = 0 owner.lying = 0 if (owner.bioHolder.HasEffect("husk")) owner.bioHolder.RemoveEffect("husk") owner.set_mutantrace(null) owner.set_face_icon_dirty() owner.set_body_icon_dirty() animate_levitate(owner) proc/RevenantDeath() if (isDying) return isDying = 1 if (!src.wraith) src.owner.bioHolder.RemoveEffect("revenant") return if (!src.owner.mind && !src.owner.client) return message_admins("Revenant [key_name(owner)] died at [showCoords(owner.x, owner.y, owner.z)].") logTheThing("combat", usr, null, "died as a revenant at [showCoords(owner.x, owner.y, owner.z)].") if (owner.mind) owner.mind.transfer_to(src.wraith) else if (owner.client) owner.client.mob = src.wraith src.wraith.invisibility = 10 src.wraith.set_loc(get_turf(owner)) src.wraith.abilityHolder.resumeAllAbilities() src.wraith.abilityHolder.regenRate /= 3 owner.bioHolder.RemoveEffect("revenant") owner:decomp_stage = 4 if (ishuman(owner) && owner:organHolder && owner:organHolder:brain) qdel(owner:organHolder:brain) particleMaster.SpawnSystem(new /datum/particleSystem/localSmoke("#000000", 5, locate(owner.x, owner.y, owner.z))) animate(owner) src.wraith = null return OnLife() if (!src.wraith) return if (ghoulTouchActive) ghoulTouchActive-- if (!ghoulTouchActive) owner.show_message("You are no longer empowered by the netherworld.") src.wraith.Life() owner.max_health -= 1.5 owner:ailments.len = 0 owner.take_toxin_damage(-INFINITY) owner.take_oxygen_deprivation(-INFINITY) owner.take_eye_damage(-INFINITY) owner.take_eye_damage(-INFINITY, 1) owner.losebreath = 0 owner.paralysis = 0 owner.stunned = 0 owner.weakened = 0 owner.slowed = 0 owner.radiation = 0 owner.take_ear_damage(-INFINITY) owner.take_ear_damage(-INFINITY, 1) owner.take_brain_damage(-120) owner.bodytemperature = owner.base_body_temp owner.stat = 0 owner.updatehealth() if (owner.health < -50) boutput(owner, "This vessel has grown too weak to maintain your presence.") owner.death(0) // todo: add custom death return var/e_decomp_stage = 0 if (owner.max_health < 75) e_decomp_stage++ if (owner.max_health < 50) e_decomp_stage++ if (owner.max_health < 25) e_decomp_stage++ if (owner.max_health < 0) e_decomp_stage++ if (ishuman(owner)) // technically we won't let it be anything else but who knows what might happen if (owner:decomp_stage != e_decomp_stage) owner:decomp_stage = e_decomp_stage owner.set_face_icon_dirty() owner.set_body_icon_dirty() proc/addRevenantVerbs() var/datum/abilityHolder/revenant/RH = owner.add_ability_holder(/datum/abilityHolder/revenant) RH.relay = src.wraith.abilityHolder RH.revenant = src src.wraith.abilityHolder.regenRate *= 3 RH.addAbility(/datum/targetable/revenantAbility/massCommand) RH.addAbility(/datum/targetable/revenantAbility/shockwave) RH.addAbility(/datum/targetable/revenantAbility/touchOfEvil) RH.addAbility(/datum/targetable/revenantAbility/push) RH.addAbility(/datum/targetable/revenantAbility/crush) RH.addAbility(/datum/targetable/revenantAbility/help) /*proc/removeRevenantVerbs() if (owner.mind) owner.mind.spells.len = 0 return*/ /datum/targetable/revenantAbility icon = 'icons/mob/wraith_ui.dmi' preferred_holder_type = /datum/abilityHolder/revenant New() var/obj/screen/ability/topBar/B = new /obj/screen/ability/topBar(null) B.icon = src.icon B.icon_state = src.icon_state B.owner = src B.name = src.name B.desc = src.desc src.object = B cast(atom/target) return castcheck() if (holder && holder.owner) return 1 else boutput(usr, "You're not a revenant, what the heck are you doing?") return 0 doCooldown() if (!holder) return last_cast = world.time + cooldown holder.updateButtons() spawn(cooldown + 5) holder.updateButtons() /datum/targetable/revenantAbility/massCommand name = "Mass Command" desc = "Launch an assortment of nearby objects at a target location." icon_state = "masscomm" special_screen_loc = "NORTH-1,WEST" targeted = 1 target_anything = 1 pointCost = 500 cooldown = 300 cast(atom/target) if (istype(holder, /datum/abilityHolder/revenant)) var/datum/abilityHolder/revenant/RH = holder RH.channeling = 0 holder.owner.visible_message("[holder.owner] gestures upwards, then at [target] with a swift striking motion!") var/list/thrown = list() var/current_prob = 100 if (ishuman(target)) var/mob/living/carbon/T = target if (T.bioHolder.HasEffect("training_chaplain")) target.visible_message(" [target] gives a rude gesture right back to [holder.owner]!") return 1 else target:stunned = max(max(target:weakened, target:stunned), 3) target:lying = 0 target:weakened = 0 target:show_message("A ghostly force compels you to be still on your feet.") for (var/obj/O in view(7, holder.owner)) if (!O.anchored && isturf(O.loc)) if (prob(current_prob)) current_prob *= 0.75 thrown += O animate_float(O) spawn(10) for (var/obj/O in thrown) O.throw_at(target, 32, 2) /datum/targetable/revenantAbility/shockwave name = "Shockwave" desc = "Emit a shockwave, breaking nearby lights and walls, and stunning nearby humans for a short time." icon_state = "shockwave" targeted = 0 pointCost = 750 cooldown = 350 // 35s var/propagation_percentage = 60 var/iteration_depth = 6 special_screen_loc = "NORTH-1,WEST+1" var/static/list/prev = list("1" = NORTHWEST, "5" = NORTH, "4" = NORTHEAST, "6" = EAST, "2" = SOUTHEAST, "10" = SOUTH, "8" = SOUTHWEST, "9" = WEST) var/static/list/next = list("1" = NORTHEAST, "5" = EAST, "4" = SOUTHEAST, "6" = SOUTH, "2" = SOUTHWEST, "10" = WEST, "8" = NORTHWEST, "9" = NORTH) proc/shock(var/turf/T) spawn(0) for (var/mob/living/carbon/human/M in T) if (M != holder.owner && !M.bioHolder.HasEffect("training_chaplain")) M.weakened += 2 animate_revenant_shockwave(T, 1, 3) spawn(3) for (var/mob/living/carbon/human/M in T) if (M != holder.owner && !M.bioHolder.HasEffect("training_chaplain")) M.weakened += 6 M.show_message("A shockwave sweeps you off your feet!") for (var/obj/machinery/light/L in T) L.broken() for (var/obj/window/W in T) W.health = 0 W.smash() if (istype(T, /turf/simulated/wall)) T:dismantle_wall() else if (istype(T, /turf/simulated/floor) && prob(75)) if (prob(50)) T:to_plating() else T:break_tile() spawn(10) T.pixel_y = 0 T.transform = null cast() var/list/next = list() var/list/NN = list() var/turf/origin = get_turf(holder.owner) if (!origin) return 1 if (istype(holder, /datum/abilityHolder/revenant)) var/datum/abilityHolder/revenant/RH = holder RH.channeling = 0 shock(origin) for (var/turf/T in orange(1, origin)) next += T next[T] = get_dir(origin, T) spawn(0) for (var/i = 1, i <= iteration_depth, i++) for (var/turf/T in next) shock(T) if (!T.density) var/base_dir = next[T] var/left_dir = src.prev["[base_dir]"] var/right_dir = src.next["[base_dir]"] // ugly & fuck you byond for making me do this if (prob(propagation_percentage / 2)) var/turf/A = get_step(T, left_dir) if (A && !(A in NN)) NN += A NN[A] = left_dir if (prob(propagation_percentage)) var/turf/B = get_step(T, base_dir) if (B && !(B in NN)) NN += B NN[B] = base_dir if (prob(propagation_percentage / 2)) var/turf/C = get_step(T, right_dir) if (C && !(C in NN)) NN += C NN[C] = right_dir next = NN NN = list() sleep(3) return 0 /datum/targetable/revenantAbility/touchOfEvil name = "Touch of Evil" desc = "Empower your hand-to-hand attacks for a short time, causing additional damage and knockdown." icon_state = "eviltouch" targeted = 0 pointCost = 1000 cooldown = 300 special_screen_loc = "NORTH-1,WEST+2" cast() if (istype(holder, /datum/abilityHolder/revenant)) var/datum/abilityHolder/revenant/RH = holder RH.channeling = 0 var/datum/bioEffect/hidden/revenant/R = RH.revenant R.ghoulTouchActive = 4 holder.owner.visible_message("[holder.owner] glows with ethereal power!", "You feel ghostly strength pulsing through you.") return 0 holder.owner.show_message("You cannot cast that ability!") /datum/targetable/revenantAbility/push name = "Push" desc = "Pushes a target object or mob away from the revenant." icon_state = "push" targeted = 1 target_anything = 1 pointCost = 50 cooldown = 150 special_screen_loc = "NORTH-1,WEST+3" cast(atom/target) if (isturf(target)) holder.owner.show_message("You must target an object or mob with this ability.") return 1 if (istype(holder, /datum/abilityHolder/revenant)) var/datum/abilityHolder/revenant/RH = holder RH.channeling = 0 var/mob/source = src.holder.owner var/throwat = get_edge_target_turf(target, get_dir(source, target)) var/atom/movable/M = target if (ismob(target)) var/mob/T = target if (T.bioHolder && T.bioHolder.HasEffect("training_chaplain")) holder.owner.show_message("Some mysterious force protects [target] from your influence.") return 1 else holder.owner.show_message("You hurl [target] away from you!") T.throw_at(throwat, 32, 2) T.show_message("An unknown force hurls you away!") else holder.owner.show_message("You hurl [target] away from you!") M.throw_at(throwat, 32, 2) return 0 /datum/targetable/revenantAbility/crush name = "Crush" desc = "Channel your telekinetic abilities at a human target, causing damage as long as you stand still. Casting any other spell will interrupt this!" icon_state = "crush" targeted = 1 pointCost = 2500 cooldown = 600 special_screen_loc = "NORTH-1,WEST+4" cast(atom/target) if (!ishuman(target)) holder.owner.show_message("You must target a human with this ability.") return 1 var/mob/living/carbon/human/H = target if (!isturf(holder.owner.loc)) holder.owner.show_message("You cannot cast this ability inside a [holder.owner.loc].") return 1 if (holder.owner.equipped()) holder.owner.show_message("You require a free hand to cast this ability.") return 1 if (H.bioHolder.HasEffect("training_chaplain")) holder.owner.show_message("Some mysterious force shields [target] from your influence.") return 1 var/location = holder.owner.loc holder.owner.visible_message("[holder.owner] reaches out towards [H], making a crushing motion.", "You reach out towards [H].") H.weakened += 2 var/datum/abilityHolder/revenant/RH if (istype(holder, /datum/abilityHolder/revenant)) RH = holder RH.channeling = 1 if (!RH || !istype(RH, /datum/abilityHolder/revenant/)) return spawn(5) var/iterations = 0 while (holder.owner.loc == location && !holder.owner.equipped()) iterations++ if (!holder.owner) RH.channeling = 0 break if (RH.channeling == 0) holder.owner.show_message("You were interrupted!") break if (!H) holder.owner.show_message("You were interrupted!") RH.channeling = 0 break if (get_dist(holder.owner, H) > 7) holder.owner.show_message("[H] is pulled from your telekinetic grip!") RH.channeling = 0 break H.weakened += (2 + rand(0, iterations)) H.TakeDamage("chest", 4 + rand(0, iterations), 0, 0, DAMAGE_CRUSH) if (prob(40)) H.visible_message("[H]'s bones crack loudly!", "You feel like you're about to be [pick("crushed", "destroyed", "vaporized")].") if (prob(50)) H.emote("scream") if (iterations > 12 && prob((iterations - 12) * 5)) H.visible_message("[H]'s body gives in to the telekinetic grip!", "You are completely crushed.") H.gib() return sleep(7) holder.owner.show_message("You were interrupted!") return 0 /datum/targetable/revenantAbility/help name = "Toggle Help Mode" desc = "Enter or exit help mode." icon_state = "help0" targeted = 0 cooldown = 0 helpable = 0 special_screen_loc = "SOUTH,EAST" cast(atom/target) if (..()) return 1 if (holder.help_mode) holder.help_mode = 0 else holder.help_mode = 1 boutput(holder.owner, "Help Mode has been activated To disable it, click on this button again.") boutput(holder.owner, "Hold down Shift, Ctrl or Alt while clicking the button to set it to that key.") boutput(holder.owner, "You will then be able to use it freely by holding that button and left-clicking a tile.") boutput(holder.owner, "Alternatively, you can click with your middle mouse button to use the ability on your current tile.") src.object.icon_state = "help[holder.help_mode]" holder.updateButtons() return 0