mirror of
https://github.com/goonstation/goonstation-2020.git
synced 2026-07-11 23:22:19 +01:00
673 lines
22 KiB
Plaintext
673 lines
22 KiB
Plaintext
/datum/abilityHolder/wraith
|
|
topBarRendered = 1
|
|
pointName = "Wraith Points"
|
|
cast_while_dead = 1
|
|
var/corpsecount = 0
|
|
|
|
/obj/screen/ability/topBar/wraith
|
|
tens_offset_x = 19
|
|
tens_offset_y = 7
|
|
secs_offset_x = 23
|
|
secs_offset_y = 7
|
|
|
|
MouseEntered(location, control, params)
|
|
if (usr.client.tooltipHolder && control == "mapwindow.map")
|
|
if (!istype(owner, /datum/targetable/wraithAbility/poltergeist))
|
|
var/theme = src.owner.theme
|
|
|
|
usr.client.tooltipHolder.showHover(src, list(
|
|
"params" = params,
|
|
"title" = src.name,
|
|
"content" = (src.desc ? src.desc : null),
|
|
"theme" = theme
|
|
))
|
|
|
|
/datum/targetable/wraithAbility
|
|
icon = 'icons/mob/wraith_ui.dmi'
|
|
icon_state = "template"
|
|
cooldown = 0
|
|
last_cast = 0
|
|
targeted = 1
|
|
target_anything = 1
|
|
preferred_holder_type = /datum/abilityHolder/wraith
|
|
theme = "wraith"
|
|
|
|
New()
|
|
var/obj/screen/ability/topBar/wraith/B = new /obj/screen/ability/topBar/wraith(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)
|
|
if (!holder || !holder.owner)
|
|
return 1
|
|
//if (!iswraith(holder.owner))
|
|
// boutput(holder.owner, "<span style=\"color:red\">Yo, you're not a wraith, stop that. (like how the hell did you get this. report this to a coder asap)</span>")
|
|
// return 1
|
|
return 0
|
|
|
|
doCooldown()
|
|
if (!holder)
|
|
return
|
|
last_cast = world.time + cooldown
|
|
holder.updateButtons()
|
|
SPAWN_DBG(cooldown + 5)
|
|
holder.updateButtons()
|
|
|
|
|
|
/datum/targetable/wraithAbility/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, "<span style=\"color:blue\"><strong>Help Mode has been activated To disable it, click on this button again.</strong></span>")
|
|
boutput(holder.owner, "<span style=\"color:blue\">Hold down Shift, Ctrl or Alt while clicking the button to set it to that key.</span>")
|
|
boutput(holder.owner, "<span style=\"color:blue\">You will then be able to use it freely by holding that button and left-clicking a tile.</span>")
|
|
boutput(holder.owner, "<span style=\"color:blue\">Alternatively, you can click with your middle mouse button to use the ability on your current tile.</span>")
|
|
src.object.icon_state = "help[holder.help_mode]"
|
|
holder.updateButtons()
|
|
|
|
|
|
/datum/targetable/wraithAbility/absorbCorpse
|
|
name = "Absorb Corpse"
|
|
icon_state = "absorbcorpse"
|
|
desc = "Steal life essence from a corpse. You cannot use this on a skeleton!"
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 20
|
|
cooldown = 450 //Starts at 45 seconds and scales upward exponentially
|
|
|
|
cast(atom/T)
|
|
if (..())
|
|
return 1
|
|
if (!T)
|
|
T = get_turf(holder.owner)
|
|
|
|
//Find a suitable corpse
|
|
var/error = 0
|
|
var/mob/living/carbon/human/M
|
|
if (isturf(T))
|
|
for (var/mob/living/carbon/human/target in T.contents)
|
|
if (isdead(target))
|
|
error = 1
|
|
if (target:decomp_stage != 4)
|
|
M = target
|
|
break
|
|
else if (ishuman(T))
|
|
M = T
|
|
if (!isdead(M))
|
|
boutput(holder.owner, "<span style=\"color:red\">The living consciousness controlling this body shields it from being absorbed.</span>")
|
|
return 1
|
|
else if (M.decomp_stage == 4)
|
|
M = null
|
|
error = 1
|
|
else
|
|
M = T
|
|
else
|
|
boutput(holder.owner, "<span style=\"color:red\">Absorbing [src] does not satisfy your ethereal taste.</span>")
|
|
return 1
|
|
|
|
if (!M && !error)
|
|
boutput(holder.owner, "<span style=\"color:red\">There are no usable corpses here!</span>")
|
|
return 1
|
|
if (!M && error)
|
|
boutput(holder.owner, "<span style=\"color:red\">[pick("This body is too decrepit to be of any use.", "This corpse has already been run through the wringer.", "There's nothing useful left.", "This corpse is worthless now.")]</span>")
|
|
return 1
|
|
|
|
logTheThing("combat", usr, null, "absorbs the corpse of [key_name(M)] as a wraith.")
|
|
|
|
//Make the corpse all grody and skeleton-y
|
|
M.decomp_stage = 4
|
|
if (M.organHolder && M.organHolder.brain)
|
|
qdel(M.organHolder.brain)
|
|
M.set_face_icon_dirty()
|
|
M.set_body_icon_dirty()
|
|
particleMaster.SpawnSystem(new /datum/particleSystem/localSmoke("#000000", 5, locate(M.x, M.y, M.z)))
|
|
|
|
holder.regenRate *= 2.0
|
|
holder.owner:onAbsorb(M)
|
|
//Messages for everyone!
|
|
boutput(holder.owner, "<span style=\"color:red\"><strong>[pick("You draw the essence of death out of [M]'s corpse!", "You drain the last scraps of life out of [M]'s corpse!")]</strong></span>")
|
|
for (var/mob/living/V in viewers(7, holder.owner))
|
|
boutput(V, "<span style=\"color:red\"><strong>[pick("Black smoke rises from [M]'s corpse! Freaky!", "[M]'s corpse suddenly rots to nothing but bone in moments!")]</strong></span>")
|
|
|
|
return 0
|
|
|
|
|
|
doCooldown() //This makes it so wraith early game is much faster but hits a wall of high absorb cooldowns after ~5 corpses
|
|
if (!holder) //so wraiths don't hit scientific notation rates of regen without playing perfectly for a million years
|
|
return
|
|
var/datum/abilityHolder/wraith/W = holder
|
|
if (istype(W))
|
|
if (W.corpsecount == 0)
|
|
cooldown = 450
|
|
W.corpsecount += 1
|
|
else
|
|
cooldown += W.corpsecount * 150
|
|
W.corpsecount += 1
|
|
last_cast = world.time + cooldown
|
|
holder.updateButtons()
|
|
SPAWN_DBG(cooldown + 5)
|
|
holder.updateButtons()
|
|
|
|
|
|
/datum/targetable/wraithAbility/possessObject
|
|
name = "Possess Object"
|
|
icon_state = "possessobject"
|
|
desc = "Possess and control an everyday object. Freakout level: high."
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 300
|
|
cooldown = 1500 //Tweaked this down from 3 minutes to 2 1/2, let's see if that ruins anything
|
|
|
|
cast(atom/T)
|
|
if (..())
|
|
return 1
|
|
|
|
if (src.holder.owner.density)
|
|
boutput(usr, "<span style=\"color:red\">You cannot force your consciousness into a body while corporeal.</span>")
|
|
return 1
|
|
|
|
if (!isitem(T) || istype(T, /obj/item/storage/bible))
|
|
boutput(holder.owner, "<span style=\"color:red\">You cannot possess this!</span>")
|
|
return 1
|
|
|
|
boutput(holder.owner, "<span style=\"color:red\"><strong>[pick("You extend your will into [T].", "You force [T] to do your bidding.")]</strong></span>")
|
|
var/mob/living/object/O = new/mob/living/object(T, holder.owner)
|
|
|
|
SPAWN_DBG (450)
|
|
if (O)
|
|
boutput(O, "<span style=\"color:red\">You feel your control of this vessel slipping away!</span>")
|
|
SPAWN_DBG (600) //time limit on possession: 1 minute
|
|
if (O)
|
|
boutput(O, "<span style=\"color:red\"><strong>Your control is wrested away! The item is no longer yours.</strong></span>")
|
|
O.death(0)
|
|
|
|
return 0
|
|
|
|
|
|
/datum/targetable/wraithAbility/makeRevenant
|
|
name = "Raise Revenant"
|
|
icon_state = "revenant"
|
|
desc = "Take control of an intact corpse as a powerful Revenant! You will not be able to absorb this corpse later. As a revenant, you gain increased point generation, but your revenant abilities cost much more points than normal."
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 1000
|
|
cooldown = 5000 //5 minutes
|
|
|
|
cast(atom/T)
|
|
if (..())
|
|
return 1
|
|
|
|
if (src.holder.owner.density)
|
|
boutput(usr, "<span style=\"color:red\">You cannot force your consciousness into a body while corporeal.</span>")
|
|
return 1
|
|
|
|
//If you targeted a turf for some reason, find a corpse on it
|
|
if (istype(T, /turf))
|
|
for (var/mob/living/carbon/human/target in T.contents)
|
|
if (isdead(target) && target:decomp_stage != 4)
|
|
T = target
|
|
break
|
|
|
|
if (ishuman(T))
|
|
var/mob/wraith/W = holder.owner
|
|
return W.makeRevenant(T)
|
|
//return 0
|
|
else
|
|
boutput(usr, "<span style=\"color:red\">There are no corpses here to possess!</span>")
|
|
return 1
|
|
|
|
/datum/targetable/wraithAbility/decay
|
|
name = "Decay"
|
|
icon_state = "decay"
|
|
desc = "Cause a human to lose stamina, or an object to malfunction."
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 30
|
|
cooldown = 600 //1 minute
|
|
|
|
cast(atom/T)
|
|
if (..())
|
|
return 1
|
|
|
|
//If you targeted a turf for some reason, find a valid target on it
|
|
var/atom/target = null
|
|
if (istype(T, /turf))
|
|
for (var/mob/living/carbon/human/M in T.contents)
|
|
if (!isdead(M))
|
|
target = M
|
|
break
|
|
if (!target)
|
|
for (var/obj/O in T.contents)
|
|
target = O //todo: emaggable check
|
|
break
|
|
else
|
|
target = T
|
|
|
|
if (ishuman(T))
|
|
var/mob/living/carbon/H = T
|
|
if (H.traitHolder.hasTrait("training_chaplain"))
|
|
boutput(usr, "<span style=\"color:red\">Some mysterious force protects [T] from your influence.</span>")
|
|
return 1
|
|
else
|
|
boutput(usr, "<span style=\"color:blue\">[pick("You sap [T]'s energy.", "You suck the breath out of [T].")]</span>")
|
|
boutput(T, "<span style=\"color:red\">You feel really tired all of a sudden!</span>")
|
|
H.emote("pale")
|
|
H.remove_stamina( rand(100, 120) )//might be nice if decay was useful.
|
|
H.changeStatus("stunned", 4 SECONDS)
|
|
return 0
|
|
else if (isobj(T))
|
|
var/obj/O = T
|
|
if(istype(O, /obj/machinery/computer/shuttle/embedded))
|
|
boutput(usr, "<span style='color:red'>You cannot seem to alter the energy off [O].</span>" )
|
|
return 0
|
|
// go to jail, do not pass src, do not collect pushed messages
|
|
if (O.emag_act(null, null))
|
|
boutput(usr, "<span style=\"color:blue\">You alter the energy of [O].</span>")
|
|
return 0
|
|
else
|
|
boutput(usr, "<span style=\"color:red\">You fail to alter the energy of the [O].</span>")
|
|
return 1
|
|
else
|
|
boutput(usr, "<span style=\"color:red\">There is nothing to decay here!</span>")
|
|
return 1
|
|
|
|
/datum/targetable/wraithAbility/command
|
|
name = "Command"
|
|
icon_state = "command"
|
|
desc = "Command a few objects to hurl themselves at the target location."
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 50
|
|
cooldown = 200 // 20 seconds
|
|
|
|
cast(atom/T)
|
|
var/list/thrown = list()
|
|
var/current_prob = 100
|
|
if (ishuman(T))
|
|
var/mob/living/carbon/H = T
|
|
if (H.traitHolder.hasTrait("training_chaplain"))
|
|
boutput(usr, "<span style=\"color:red\">Some mysterious force protects [T] from your influence.</span>")
|
|
return 1
|
|
else
|
|
H.setStatus("stunned", max(H.getStatusDuration("weakened"), max(H.getStatusDuration("stunned"), 3))) // change status "stunned" to max(stunned,weakened,3)
|
|
// T:stunned = max(max(T:weakened, T:stunned), 3)
|
|
H.delStatus("weakened")
|
|
H.lying = 0
|
|
H.show_message("<span style=\"color:red\">A ghostly force compels you to be still on your feet.</span>")
|
|
for (var/obj/O in view(7, holder.owner))
|
|
if (!O.anchored && isturf(O.loc))
|
|
if (prob(current_prob))
|
|
current_prob *= 0.35 // very steep. probably grabs 3 or 4 objects per cast -- much less effective than revenant command
|
|
thrown += O
|
|
animate_float(O)
|
|
SPAWN_DBG(1 SECOND)
|
|
for (var/obj/O in thrown)
|
|
O.throw_at(T, 32, 2)
|
|
|
|
return 0
|
|
|
|
/datum/targetable/wraithAbility/raiseSkeleton
|
|
name = "Raise Skeleton"
|
|
icon_state = "skeleton"
|
|
desc = "Raise a skeletonized dead body as an indurable skeletal servant."
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 150
|
|
cooldown = 600 // 1 minute
|
|
|
|
cast(atom/T)
|
|
if (..())
|
|
return 1
|
|
|
|
//If you targeted a turf for some reason, find a corpse on it
|
|
if (istype(T, /turf))
|
|
for (var/mob/living/carbon/human/target in T.contents)
|
|
if (isdead(target) && target:decomp_stage == 4)
|
|
T = target
|
|
break
|
|
|
|
if (ishuman(T))
|
|
var/mob/living/carbon/human/H = T
|
|
if (!isdead(H) || H.decomp_stage != 4)
|
|
boutput(usr, "<span style=\"color:red\">That body refuses to submit its skeleton to your will.</span>")
|
|
return 1
|
|
var/personname = H.real_name
|
|
var/obj/critter/wraithskeleton/S = new /obj/critter/wraithskeleton(get_turf(T))
|
|
S.name = "[personname]'s skeleton"
|
|
S.health = 1
|
|
H.gib()
|
|
return 0
|
|
else
|
|
boutput(usr, "<span style=\"color:red\">There are no skeletonized corpses here to raise!</span>")
|
|
return 1
|
|
|
|
/datum/targetable/wraithAbility/animateObject
|
|
name = "Animate Object"
|
|
icon_state = "animobject"
|
|
desc = "Animate an inanimate object to attack nearby humans."
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 100
|
|
cooldown = 300 //30 seconds
|
|
|
|
cast(atom/T)
|
|
if (..())
|
|
return 1
|
|
|
|
var/obj/O = T
|
|
//If you targeted a turf for some reason, find an object on it
|
|
if (istype(T, /turf))
|
|
for (var/obj/target in T.contents)
|
|
if (istype(target, /obj/critter) || istype(target, /obj/machinery/bot) || istype(target, /obj/decal) || target.anchored || target.invisibility)
|
|
continue
|
|
O = target
|
|
break
|
|
|
|
if (istype(O))
|
|
if(istype(O, /obj/critter) || istype(O, /obj/machinery/bot) || istype(O, /obj/decal) || O.anchored || O.invisibility)
|
|
boutput(usr, "<span style=\"color:red\">That is not a valid target for animation!</span>")
|
|
return 1
|
|
O.visible_message("<span style=\"color:red\">The [O] comes to life!</span>")
|
|
var/obj/critter/livingobj/L = new/obj/critter/livingobj(O.loc)
|
|
O.loc = L
|
|
L.name = "Living [O.name]"
|
|
L.desc = "[O.desc]. It appears to be alive!"
|
|
L.overlays += O
|
|
L.health = rand(10, 50)
|
|
L.atk_brute_amt = rand(5, 20)
|
|
L.defensive = 1
|
|
L.aggressive = 1
|
|
L.atkcarbon = 1
|
|
L.atksilicon = 1
|
|
L.opensdoors = 1
|
|
L.stunprob = 15
|
|
L.original_object = O
|
|
animate_levitate(L, -1, 30)
|
|
return 0
|
|
else
|
|
boutput(usr, "<span style=\"color:red\">There is no object here to animate!</span>")
|
|
return 1
|
|
|
|
/datum/targetable/wraithAbility/haunt
|
|
name = "Haunt"
|
|
icon_state = "haunt"
|
|
desc = "Become corporeal for 30 seconds. During this time, you gain additional biopoints, depending on the amount of humans in your vicinity. You cannot use this ability while already corporeal."
|
|
targeted = 0
|
|
pointCost = 0
|
|
cooldown = 600 //1 minute
|
|
|
|
cast()
|
|
if (..())
|
|
return 1
|
|
|
|
var/mob/wraith/W = src.holder.owner
|
|
return W.haunt()
|
|
|
|
/obj/poltergeistMarker
|
|
name = "Spooky Marker"
|
|
desc = "What is this? You feel like you shouldn't be able to see it."
|
|
icon = 'icons/effects/particles.dmi'
|
|
icon_state = "32x32circle"
|
|
color = "#222222"
|
|
// invisibility = 101
|
|
invisibility = 16
|
|
anchored = 1
|
|
density = 0
|
|
opacity = 0
|
|
mouse_opacity = 0
|
|
alpha = 100
|
|
|
|
New()
|
|
..()
|
|
var/matrix/M = matrix()
|
|
M.Scale(0.5,0.5)
|
|
animate(src, transform = M, time = 3 SECONDS, loop = -1,easing = ELASTIC_EASING)
|
|
|
|
/datum/targetable/wraithAbility/poltergeist
|
|
name = "Poltergeist - Mark Location"
|
|
icon_state = "poltergeist"
|
|
desc = "Cause freaky, weird, creepy or spooky stuff to happen in an area around you. Use this ability to mark your current tile as the origin of these events, then activate it by using this ability again."
|
|
targeted = 0
|
|
pointCost = 0
|
|
cooldown = 200
|
|
special_screen_loc="NORTH,EAST"
|
|
|
|
var/datum/radio_frequency/pda_connection
|
|
var/obj/poltergeistMarker/marker = new /obj/poltergeistMarker() //removed for now
|
|
var/status = 0
|
|
var/static/list/effects = list("Flip light switches" = 1, "Burn out lights" = 2, "Create smoke" = 3, "Create ectoplasm" = 4, "Sap APC" = 5, "Haunt PDAs" = 6, "Open doors, lockers, crates" = 7, "Random" = 8)
|
|
var/list/effects_buttons = list()
|
|
|
|
|
|
New()
|
|
..()
|
|
pda_connection = radio_controller.return_frequency("1149")
|
|
object.contextLayout = new /datum/contextLayout/screen_HUD_default(2, 16, 16)//, -32, -32)
|
|
if (!object.contextActions)
|
|
object.contextActions = list()
|
|
|
|
for(var/i=1, i<=8, i++)
|
|
var/datum/contextAction/wraith_poltergeist_button/newcontext = new /datum/contextAction/wraith_poltergeist_button(i)
|
|
object.contextActions += newcontext
|
|
|
|
disposing()
|
|
radio_controller.remove_object(src,"1149")
|
|
..()
|
|
|
|
proc/haunt_pda(var/obj/item/device/pda2/pda)
|
|
if (!pda_connection)
|
|
return
|
|
var/message = pick("boo", "git spooked", "BOOM", "there's a skeleton inside of you", "DEHUMANIZE YOURSELF AND FACE TO BLOODSHED", "ICARUS HAS FOUND YOU!!!!! RUN WHILE YOU CAN!!!!!!!!!!!")
|
|
|
|
var/datum/signal/signal = get_free_signal()
|
|
signal.source = src.holder.owner
|
|
signal.transmission_method = TRANSMISSION_RADIO
|
|
signal.data["command"] = "text_message"
|
|
signal.data["sender_name"] = holder.owner.name
|
|
signal.data["message"] = "[message]" // (?)
|
|
signal.data["sender"] = "00000000" // surely this isn't going to be a problem
|
|
signal.data["address_1"] = pda.net_id
|
|
|
|
pda_connection.post_signal(src, signal)
|
|
|
|
cast()
|
|
if (..())
|
|
return 1
|
|
|
|
proc/do_poltergeist_ability(var/effect as text)
|
|
if (effect == 8)
|
|
effect = rand(1, 7)
|
|
switch (effect)
|
|
if (1)
|
|
boutput(holder.owner, "<span style=\"color:blue\">You flip some light switches near the designated location!!</span>")
|
|
for (var/obj/machinery/light_switch/L in range(10, holder.owner))
|
|
L.attack_hand(holder.owner)
|
|
return 0
|
|
if (2)
|
|
boutput(holder.owner, "<span style=\"color:blue\">You cause a few lights to burn out near the designated location!.</span>")
|
|
var/c_prob = 100
|
|
for (var/obj/machinery/light/L in range(10, holder.owner))
|
|
if (L.status == 2 || L.status == 1)
|
|
continue
|
|
if (prob(c_prob))
|
|
L.broken()
|
|
c_prob *= 0.5
|
|
return 0
|
|
if (3)
|
|
boutput(holder.owner, "<span style=\"color:blue\">Smoke rises in the designated location.</span>")
|
|
var/turf/trgloc = get_turf(holder.owner)
|
|
var/list/affected = block(locate(trgloc.x - 3,trgloc.y - 3,trgloc.z), locate(trgloc.x + 3,trgloc.y + 3,trgloc.z))
|
|
if(!affected.len) return
|
|
var/list/centerview = view(4, trgloc)
|
|
for(var/atom/A in affected)
|
|
if(!(A in centerview)) continue
|
|
//if (A == holder.owner) continue
|
|
var/obj/smokeDummy/D = new(A)
|
|
SPAWN_DBG(15 SECONDS)
|
|
qdel(D)
|
|
particleMaster.SpawnSystem(new/datum/particleSystem/areaSmoke("#ffffff", 30, trgloc))
|
|
return 0
|
|
if (4)
|
|
boutput(holder.owner, "<span style=\"color:blue\">Matter from your realm appears near the designated location!</span>")
|
|
var/count = rand(5,9)
|
|
var/turf/trgloc = get_turf(holder.owner)
|
|
var/list/affected = block(locate(trgloc.x - 8,trgloc.y - 8,trgloc.z), locate(trgloc.x + 8,trgloc.y + 8,trgloc.z))
|
|
for (var/i = 0, i < count, i++)
|
|
new/obj/item/reagent_containers/food/snacks/ectoplasm(pick(affected))
|
|
return 0
|
|
if (5)
|
|
var/sapped_amt = src.holder.regenRate * 100
|
|
var/obj/machinery/power/apc/apc = locate() in get_area(holder.owner)
|
|
if (!apc)
|
|
boutput(holder.owner, "<span style=\"color:red\">Power sap failed: local APC not found.</span>")
|
|
return 0
|
|
boutput(holder.owner, "<span style=\"color:blue\">You sap the power of the chamber's power source.</span>")
|
|
var/obj/item/cell/cell = apc.cell
|
|
if (cell)
|
|
cell.use(sapped_amt)
|
|
return 0
|
|
if (6)
|
|
boutput(holder.owner, "<span style=\"color:blue\">Mysterious messages haunt PDAs near the designated location!</span>")
|
|
for (var/mob/living/L in range(10, holder.owner))
|
|
var/obj/item/device/pda2/pda = locate() in L
|
|
if (pda)
|
|
src.haunt_pda(pda)
|
|
for (var/obj/item/device/pda2/pda in range(10, holder.owner))
|
|
src.haunt_pda(pda)
|
|
if (7)
|
|
boutput(holder.owner, "<span style=\"color:blue\">Crates, lockers and doors mysteriously open and close in the designated area!</span>")
|
|
var/c_prob = 100
|
|
for(var/obj/machinery/door/G in range(10, holder.owner))
|
|
if (prob(c_prob))
|
|
c_prob *= 0.4
|
|
SPAWN_DBG(1 DECI SECOND)
|
|
if (G.density)
|
|
G.open()
|
|
else
|
|
G.close()
|
|
c_prob = 100
|
|
for(var/obj/storage/F in range(10, holder.owner))
|
|
if (prob(c_prob))
|
|
c_prob *= 0.4
|
|
SPAWN_DBG(1 DECI SECOND)
|
|
if (F.open)
|
|
F.close()
|
|
else
|
|
F.open()
|
|
|
|
return 0
|
|
|
|
afterCast()
|
|
if (status == 0)
|
|
name = "Poltergeist - Cast"
|
|
pointCost = 0
|
|
cooldown = 300
|
|
status = 1
|
|
icon_state = "poltergeist1"
|
|
else
|
|
name = "Poltergeist - Mark Location"
|
|
pointCost = 20
|
|
cooldown = 0
|
|
status = 0
|
|
icon_state = "poltergeist"
|
|
// holder.owner.contents += marker
|
|
|
|
/datum/targetable/wraithAbility/whisper
|
|
name = "Whisper"
|
|
icon_state = "whisper"
|
|
desc = "Send an ethereal message to a living being."
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 1
|
|
cooldown = 2 SECONDS
|
|
|
|
proc/ghostify_message(var/message)
|
|
return message
|
|
|
|
cast(atom/target)
|
|
if (..())
|
|
return 1
|
|
|
|
if (ishuman(target))
|
|
var/mob/living/carbon/human/H = target
|
|
if (isdead(H))
|
|
boutput(usr, "<span style=\"color:red\">They can hear you just fine without the use of your abilities.</span>")
|
|
return 1
|
|
else
|
|
var/message = html_encode(input("What would you like to whisper to [target]?", "Whisper", "") as text)
|
|
logTheThing("say", usr, target, "WRAITH WHISPER TO %target%: [message]")
|
|
message = ghostify_message(trim(copytext(sanitize(message), 1, 255)))
|
|
boutput(usr, "<b>You whisper to [target]:</b> [message]")
|
|
boutput(target, "<b>A netherworldly voice whispers into your ears... </b> [message]")
|
|
else
|
|
boutput(usr, "<span style=\"color:red\">It would be futile to attempt to force your voice to the consciousness of that.</span>")
|
|
return 1
|
|
|
|
//this is the spooky_writing ability from spooktober ghosts
|
|
/datum/targetable/wraithAbility/blood_writing
|
|
name = "Blood Writing"
|
|
desc = "Write a spooky character on the ground."
|
|
icon_state = "bloodwriting"
|
|
targeted = 1
|
|
target_anything = 1
|
|
pointCost = 10
|
|
cooldown = 5 SECONDS
|
|
var/in_use = 0
|
|
|
|
// cast(turf/target, params)
|
|
cast(atom/target, params)
|
|
if (..())
|
|
return 1
|
|
|
|
var/turf/T = get_turf(target)
|
|
if (isturf(T))
|
|
write_on_turf(T, holder.owner, params)
|
|
|
|
|
|
proc/write_on_turf(var/turf/T as turf, var/mob/user as mob, params)
|
|
if (!T || !user || src.in_use)
|
|
return
|
|
src.in_use = 1
|
|
var/list/c_default = list("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Exclamation Point", "Question Mark", "Period", "Comma", "Colon", "Semicolon", "Ampersand", "Left Parenthesis", "Right Parenthesis",
|
|
"Left Bracket", "Right Bracket", "Percent", "Plus", "Minus", "Times", "Divided", "Equals", "Less Than", "Greater Than")
|
|
var/list/c_symbol = list("Dollar", "Euro", "Arrow North", "Arrow East", "Arrow South", "Arrow West",
|
|
"Square", "Circle", "Triangle", "Heart", "Star", "Smile", "Frown", "Neutral Face", "Bee", "Pentagram")
|
|
|
|
var/t = input(user, "What do you want to write?", null, null) as null|anything in (c_default + c_symbol)
|
|
|
|
if (!t)
|
|
src.in_use = 0
|
|
return 1
|
|
var/obj/decal/cleanable/writing/spooky/G = make_cleanable(/obj/decal/cleanable/writing/spooky,T)
|
|
G.artist = user.key
|
|
|
|
logTheThing("station", user, null, "writes on [T] with [src] [log_loc(T)]: [t]")
|
|
G.icon_state = t
|
|
G.words = t
|
|
if (islist(params) && params["icon-y"] && params["icon-x"])
|
|
// playsound(src.loc, "sound/impact_sounds/Slimy_Splat_1.ogg", 50, 1)
|
|
|
|
G.pixel_x = text2num(params["icon-x"]) - 16
|
|
G.pixel_y = text2num(params["icon-y"]) - 16
|
|
else
|
|
G.pixel_x = rand(-4,4)
|
|
G.pixel_y = rand(-4,4)
|
|
src.in_use = 0
|