Files
Bubberstation/code/game/objects/structures/morgue.dm
supersayu 475042a212 Click code rework
Fixes #646, #579, #863

Completely redoes the click code.  Moves all click related code into code/_onclick for reference.  Also moves hud datum code and all the screen object code I could find into code/_onclick/hud, as it is related.  Item attack(), attackby(), afterattack(), and attack_self() have been moved into item_attack.dm for consistency.

Completely removes dummy objects and adds atom.Adjacent(user).  This proc checks for border items and anything marked with throwpass for determining whether or not you can reach a given square.  A turf helper, ClickCross(), was added to facilitate this.

Removes the monolithic Atom.Click() proc in favor of an overridable click handler attached to mobs.  Click code no longer uses the : path operator as a consequence, and mob/lastDblClick has been moved to Client/next_click.  A few end arounds were necessary (screen objects, buildmode, and spells), but this has been handled by repurposing Atom.Click(); if you have special click code, insert it in the object's Click() function and return 1 to prevent normal processing.

This update adds support for attack_ghost(); the previous "new" click handler had support for it but was never finished.  I have taken the liberty of letting ghosts click portals, the gateway, and the teleporter to jump to the intended target square, and kept the previous default action of examine()ing every damn thing you click.  It is to be suggested that you could do more with this proc when ghost interactions are enabled.

This update also adds support for double clicking.  It is currently only used for ghosts and AIs, because the original (first) click still registers normally.  For both of these, double clicking a square will jump you to it, and double clicking a mob will follow it.  In the case of ghosts, double clicking bots and the singularity will also set you following it; if you double click your own corpse, you will re-enter it; this also works if your body is in a closet, sleeper, DNA scanner, etc.  Default mobs ignore double clicks as normal.

-- NOTE --

There are two flags which were previously unused or misused by click code: USEDELAY and NODELAY.  Ostensibly, USEDELAY would double the normal 1sec delay, and NODELAY would remove it.

Using either of these flags as intended would significantly affect the timing of the game.  In particular, USEDELAY is currently applied to guns and about everything else that acts at range.  I am adding USEDELAY as a half-second increase for now, but I have not put a significant amount of thought into it.  I considered lowering the normal 1sec delay to .8sec to balance it, but the consequences of that on combat involve more calculations than I care to make.

NODELAY seems to never have been used, and I did not implement it, but I could do so trivially.
2013-09-17 18:15:54 -04:00

392 lines
10 KiB
Plaintext

/* Morgue stuff
* Contains:
* Morgue
* Morgue trays
* Creamatorium
* Creamatorium trays
*/
/*
* Morgue
*/
/obj/structure/morgue
name = "morgue"
desc = "Used to keep bodies in untill someone fetches them."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "morgue1"
density = 1
var/obj/structure/m_tray/connected = null
anchored = 1.0
/obj/structure/morgue/proc/update()
if (src.connected)
src.icon_state = "morgue0"
else
if (src.contents.len)
src.icon_state = "morgue2"
else
src.icon_state = "morgue1"
return
/obj/structure/morgue/ex_act(severity)
switch(severity)
if(1.0)
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
del(src)
return
if(2.0)
if (prob(50))
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
del(src)
return
if(3.0)
if (prob(5))
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
del(src)
return
return
/obj/structure/morgue/alter_health()
return src.loc
/obj/structure/morgue/attack_paw(mob/user as mob)
return src.attack_hand(user)
/obj/structure/morgue/attack_hand(mob/user as mob)
if (src.connected)
for(var/atom/movable/A as mob|obj in src.connected.loc)
if (!( A.anchored ))
A.loc = src
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
//src.connected = null
del(src.connected)
else
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
src.connected = new /obj/structure/m_tray( src.loc )
step(src.connected, EAST)
src.connected.layer = OBJ_LAYER
var/turf/T = get_step(src, EAST)
if (T.contents.Find(src.connected))
src.connected.connected = src
src.icon_state = "morgue0"
for(var/atom/movable/A as mob|obj in src)
A.loc = src.connected.loc
src.connected.icon_state = "morguet"
else
//src.connected = null
del(src.connected)
src.add_fingerprint(user)
update()
return
/obj/structure/morgue/attackby(P as obj, mob/user as mob)
if (istype(P, /obj/item/weapon/pen))
var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text
if (user.get_active_hand() != P)
return
if ((!in_range(src, usr) && src.loc != user))
return
t = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if (t)
src.name = text("Morgue- '[]'", t)
else
src.name = "Morgue"
src.add_fingerprint(user)
return
/obj/structure/morgue/relaymove(mob/user as mob)
if (user.stat)
return
src.connected = new /obj/structure/m_tray( src.loc )
step(src.connected, EAST)
src.connected.layer = OBJ_LAYER
var/turf/T = get_step(src, EAST)
if (T.contents.Find(src.connected))
src.connected.connected = src
src.icon_state = "morgue0"
for(var/atom/movable/A as mob|obj in src)
A.loc = src.connected.loc
//Foreach goto(106)
src.connected.icon_state = "morguet"
else
//src.connected = null
del(src.connected)
return
/*
* Morgue tray
*/
/obj/structure/m_tray
name = "morgue tray"
desc = "Apply corpse before closing."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "morguet"
density = 1
layer = 2.0
var/obj/structure/morgue/connected = null
anchored = 1.0
throwpass = 1
/obj/structure/m_tray/attack_paw(mob/user as mob)
return src.attack_hand(user)
/obj/structure/m_tray/attack_hand(mob/user as mob)
if (src.connected)
for(var/atom/movable/A as mob|obj in src.loc)
if (!( A.anchored ))
A.loc = src.connected
//Foreach goto(26)
src.connected.connected = null
src.connected.update()
add_fingerprint(user)
//SN src = null
del(src)
return
return
/obj/structure/m_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O)))
return
if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag))
return
O.loc = src.loc
if (user != O)
for(var/mob/B in viewers(user, 3))
if ((B.client && !( B.blinded )))
B << text("\red [] stuffs [] into []!", user, O, src)
return
/*
* Crematorium
*/
/obj/structure/crematorium
name = "crematorium"
desc = "A human incinerator. Works well on barbeque nights."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "crema1"
density = 1
var/obj/structure/c_tray/connected = null
anchored = 1.0
var/cremating = 0
var/id = 1
var/locked = 0
/obj/structure/crematorium/proc/update()
if (src.connected)
src.icon_state = "crema0"
else
if (src.contents.len)
src.icon_state = "crema2"
else
src.icon_state = "crema1"
return
/obj/structure/crematorium/ex_act(severity)
switch(severity)
if(1.0)
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
del(src)
return
if(2.0)
if (prob(50))
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
del(src)
return
if(3.0)
if (prob(5))
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
del(src)
return
return
/obj/structure/crematorium/alter_health()
return src.loc
/obj/structure/crematorium/attack_paw(mob/user as mob)
return src.attack_hand(user)
/obj/structure/crematorium/attack_hand(mob/user as mob)
// if (cremating) AWW MAN! THIS WOULD BE SO MUCH MORE FUN ... TO WATCH
// user.show_message("\red Uh-oh, that was a bad idea.", 1)
// //usr << "Uh-oh, that was a bad idea."
// src:loc:poison += 20000000
// src:loc:firelevel = src:loc:poison
// return
if (cremating)
usr << "\red It's locked."
return
if ((src.connected) && (src.locked == 0))
for(var/atom/movable/A as mob|obj in src.connected.loc)
if (!( A.anchored ))
A.loc = src
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
//src.connected = null
del(src.connected)
else if (src.locked == 0)
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
src.connected = new /obj/structure/c_tray( src.loc )
step(src.connected, SOUTH)
src.connected.layer = OBJ_LAYER
var/turf/T = get_step(src, SOUTH)
if (T.contents.Find(src.connected))
src.connected.connected = src
src.icon_state = "crema0"
for(var/atom/movable/A as mob|obj in src)
A.loc = src.connected.loc
src.connected.icon_state = "cremat"
else
//src.connected = null
del(src.connected)
src.add_fingerprint(user)
update()
/obj/structure/crematorium/attackby(P as obj, mob/user as mob)
if (istype(P, /obj/item/weapon/pen))
var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text
if (user.get_active_hand() != P)
return
if ((!in_range(src, usr) > 1 && src.loc != user))
return
t = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if (t)
src.name = text("Crematorium- '[]'", t)
else
src.name = "Crematorium"
src.add_fingerprint(user)
return
/obj/structure/crematorium/relaymove(mob/user as mob)
if (user.stat || locked)
return
src.connected = new /obj/structure/c_tray( src.loc )
step(src.connected, SOUTH)
src.connected.layer = OBJ_LAYER
var/turf/T = get_step(src, SOUTH)
if (T.contents.Find(src.connected))
src.connected.connected = src
src.icon_state = "crema0"
for(var/atom/movable/A as mob|obj in src)
A.loc = src.connected.loc
//Foreach goto(106)
src.connected.icon_state = "cremat"
else
//src.connected = null
del(src.connected)
return
/obj/structure/crematorium/proc/cremate(atom/A, mob/user as mob)
// for(var/obj/machinery/crema_switch/O in src) //trying to figure a way to call the switch, too drunk to sort it out atm
// if(var/on == 1)
// return
if(cremating)
return //don't let you cremate something twice or w/e
if(contents.len <= 0)
for (var/mob/M in viewers(src))
M.show_message("\red You hear a hollow crackle.", 1)
return
else
if(!isemptylist(src.search_contents_for(/obj/item/weapon/disk/nuclear)))
usr << "You get the feeling that you shouldn't cremate one of the items in the cremator."
return
for (var/mob/M in viewers(src))
M.show_message("\red You hear a roar as the crematorium activates.", 1)
cremating = 1
locked = 1
for(var/mob/living/M in contents)
if (M.stat!=2)
M.emote("scream")
//Logging for this causes runtimes resulting in the cremator locking up. Commenting it out until that's figured out.
//M.attack_log += "\[[time_stamp()]\] Has been cremated by <b>[user]/[user.ckey]</b>" //No point in this when the mob's about to be deleted
//user.attack_log +="\[[time_stamp()]\] Cremated <b>[M]/[M.ckey]</b>"
//log_attack("\[[time_stamp()]\] <b>[user]/[user.ckey]</b> cremated <b>[M]/[M.ckey]</b>")
M.death(1)
M.ghostize()
del(M)
for(var/obj/O in contents) //obj instead of obj/item so that bodybags and ashes get destroyed. We dont want tons and tons of ash piling up
del(O)
new /obj/effect/decal/cleanable/ash(src)
sleep(30)
cremating = 0
locked = 0
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
return
/*
* Crematorium tray
*/
/obj/structure/c_tray
name = "crematorium tray"
desc = "Apply body before burning."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "cremat"
density = 1
layer = 2.0
var/obj/structure/crematorium/connected = null
anchored = 1.0
throwpass = 1
/obj/structure/c_tray/attack_paw(mob/user as mob)
return src.attack_hand(user)
/obj/structure/c_tray/attack_hand(mob/user as mob)
if (src.connected)
for(var/atom/movable/A as mob|obj in src.loc)
if (!( A.anchored ))
A.loc = src.connected
//Foreach goto(26)
src.connected.connected = null
src.connected.update()
add_fingerprint(user)
//SN src = null
del(src)
return
return
/obj/structure/c_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O)))
return
if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag))
return
O.loc = src.loc
if (user != O)
for(var/mob/B in viewers(user, 3))
if ((B.client && !( B.blinded )))
B << text("\red [] stuffs [] into []!", user, O, src)
//Foreach goto(99)
return
/obj/machinery/crema_switch/attack_hand(mob/user as mob)
if(src.allowed(usr))
for (var/obj/structure/crematorium/C in world)
if (C.id == id)
if (!C.cremating)
C.cremate(user)
else
usr << "\red Access denied."
return