mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-29 19:52:12 +00:00
This commit ports /tg/'s move refactor. The throwing system has been replaced entirely, removing the necessity of throw_at_fast and resolving multiple outstanding issues, such as crossbows being unusable. Spacedrifting has also been upgraded to function with the new throwing system. It is now it's own process. Tickcomp has been killed, and the config values have been adjusted to more or less match live Paradise. All mobs now share a common Bump() proc. There are only four mobtypes which do not, including humans and simple animals. With the exception of mob types that do not ever want to Bump() or be Bumped(), they should call the parent proc. Human movement slowdown has been moderately tweaked in how it stacks effects; It shouldn't be significantly different from a player perspective. Mobs will now spread fire if they bump into another mob. I don't want to set the world on fiiiire, I just want start a flame in your heart~ For player facing changes: Input delay has been reduced by roughly ~50ms for any direction keys, by advantage of a previously unknown flag on byond verbs which allow them to operate independently from the tick rate of the server. You may need to clear your interface.dmf file if you have a custom skin for this change to function.
518 lines
14 KiB
Plaintext
518 lines
14 KiB
Plaintext
/* Morgue stuff
|
|
* Contains:
|
|
* Morgue
|
|
* Morgue trays
|
|
* Creamatorium
|
|
* Creamatorium trays
|
|
*/
|
|
|
|
/*
|
|
* Morgue
|
|
*/
|
|
|
|
/obj/structure/morgue
|
|
name = "morgue"
|
|
desc = "Used to keep bodies in until someone fetches them."
|
|
icon = 'icons/obj/stationobjs.dmi'
|
|
icon_state = "morgue1"
|
|
density = 1
|
|
dir = EAST
|
|
var/obj/structure/m_tray/connected = null
|
|
var/list/status_descriptors = list(
|
|
"The tray is currently extended.",
|
|
"The tray is currently empty.",
|
|
"The tray contains an unviable body.",
|
|
"The tray contains a body that is responsive to revival techniques.",
|
|
"The tray contains something that is not a body.",
|
|
"The tray contains a body that might be responsive."
|
|
)
|
|
anchored = 1.0
|
|
var/open_sound = 'sound/items/Deconstruct.ogg'
|
|
|
|
/obj/structure/morgue/initialize()
|
|
. = ..()
|
|
update()
|
|
|
|
/obj/structure/morgue/proc/update()
|
|
if(connected)
|
|
icon_state = "morgue0"
|
|
desc = initial(desc) + "\n[status_descriptors[1]]"
|
|
else
|
|
if(contents.len)
|
|
|
|
var/mob/living/M = locate() in contents
|
|
|
|
var/obj/structure/closet/body_bag/B = locate() in contents
|
|
if(M==null) M = locate() in B
|
|
|
|
if(M)
|
|
var/mob/dead/observer/G = M.get_ghost()
|
|
|
|
if(M.client)
|
|
icon_state = "morgue3"
|
|
desc = initial(desc) + "\n[status_descriptors[4]]"
|
|
else if(G && G.client) //There is a ghost and it is connected to the server
|
|
icon_state = "morgue5"
|
|
desc = initial(desc) + "\n[status_descriptors[6]]"
|
|
else
|
|
icon_state = "morgue2"
|
|
desc = initial(desc) + "\n[status_descriptors[3]]"
|
|
|
|
|
|
else
|
|
icon_state = "morgue4"
|
|
desc = initial(desc) + "\n[status_descriptors[5]]"
|
|
else
|
|
icon_state = "morgue1"
|
|
desc = initial(desc) + "\n[status_descriptors[2]]"
|
|
return
|
|
|
|
|
|
/obj/structure/morgue/ex_act(severity)
|
|
switch(severity)
|
|
if(1.0)
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(loc)
|
|
ex_act(severity)
|
|
qdel(src)
|
|
return
|
|
if(2.0)
|
|
if(prob(50))
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(loc)
|
|
ex_act(severity)
|
|
qdel(src)
|
|
return
|
|
if(3.0)
|
|
if(prob(5))
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(loc)
|
|
ex_act(severity)
|
|
qdel(src)
|
|
return
|
|
return
|
|
|
|
/obj/structure/morgue/alter_health()
|
|
return loc
|
|
|
|
|
|
/obj/structure/morgue/attack_hand(mob/user as mob)
|
|
if(connected)
|
|
for(var/atom/movable/A as mob|obj in connected.loc)
|
|
if(!( A.anchored ))
|
|
A.forceMove(src)
|
|
playsound(loc, open_sound, 50, 1)
|
|
qdel(connected)
|
|
connected = null
|
|
else
|
|
playsound(loc, open_sound, 50, 1)
|
|
connected = new /obj/structure/m_tray( loc )
|
|
step(connected, dir)
|
|
connected.layer = OBJ_LAYER
|
|
var/turf/T = get_step(src, dir)
|
|
if(T.contents.Find(connected))
|
|
connected.connected = src
|
|
icon_state = "morgue0"
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(connected.loc)
|
|
connected.icon_state = "morguet"
|
|
connected.dir = dir
|
|
else
|
|
qdel(connected)
|
|
connected = null
|
|
add_fingerprint(user)
|
|
update()
|
|
return
|
|
|
|
/obj/structure/morgue/attackby(P as obj, mob/user as mob, params)
|
|
if(istype(P, /obj/item/weapon/pen))
|
|
var/t = input(user, "What would you like the label to be?", text("[]", name), null) as text
|
|
if(user.get_active_hand() != P)
|
|
return
|
|
if((!in_range(src, usr) && loc != user))
|
|
return
|
|
t = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
|
|
if(t)
|
|
name = text("Morgue- '[]'", t)
|
|
overlays += image(icon, "morgue_label")
|
|
else
|
|
name = "Morgue"
|
|
overlays.Cut()
|
|
add_fingerprint(user)
|
|
return
|
|
|
|
/obj/structure/morgue/relaymove(mob/user as mob)
|
|
if(user.stat)
|
|
return
|
|
connected = new /obj/structure/m_tray( loc )
|
|
step(connected, dir)
|
|
connected.layer = OBJ_LAYER
|
|
var/turf/T = get_step(src, dir)
|
|
if(T.contents.Find(connected))
|
|
connected.connected = src
|
|
icon_state = "morgue0"
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(connected.loc)
|
|
connected.icon_state = "morguet"
|
|
else
|
|
qdel(connected)
|
|
connected = null
|
|
return
|
|
|
|
/obj/structure/morgue/Destroy()
|
|
QDEL_NULL(connected)
|
|
return ..()
|
|
|
|
/obj/structure/morgue/container_resist(var/mob/living/L)
|
|
var/mob/living/carbon/CM = L
|
|
if(!istype(CM))
|
|
return
|
|
if(CM.stat || CM.restrained())
|
|
return
|
|
|
|
to_chat(CM, "<span class='alert'>You attempt to slide yourself out of \the [src]...</span>")
|
|
src.attack_hand(CM)
|
|
|
|
|
|
/obj/structure/morgue/get_remote_view_fullscreens(mob/user)
|
|
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
|
user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 2)
|
|
|
|
/*
|
|
* Morgue tray
|
|
*/
|
|
/obj/structure/m_tray
|
|
name = "morgue tray"
|
|
desc = "Apply corpse before closing. May float away in no-gravity."
|
|
icon = 'icons/obj/stationobjs.dmi'
|
|
icon_state = "morguet"
|
|
density = 1
|
|
layer = 2.0
|
|
var/obj/structure/morgue/connected = null
|
|
anchored = 1.0
|
|
pass_flags = LETPASSTHROW
|
|
|
|
|
|
/obj/structure/m_tray/attack_hand(mob/user as mob)
|
|
if(connected)
|
|
for(var/atom/movable/A as mob|obj in loc)
|
|
if(!( A.anchored ))
|
|
A.forceMove(connected)
|
|
connected.connected = null
|
|
connected.update()
|
|
add_fingerprint(user)
|
|
qdel(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
|
|
if(!ismob(user) || user.stat || user.lying || user.stunned)
|
|
return
|
|
O.forceMove(loc)
|
|
if(user != O)
|
|
for(var/mob/B in viewers(user, 3))
|
|
if((B.client && !( B.blinded )))
|
|
to_chat(B, text("<span class='warning'>[] stuffs [] into []!</span>", user, O, src))
|
|
return
|
|
|
|
/obj/structure/m_tray/Destroy()
|
|
if(connected && connected.connected == src)
|
|
connected.connected = null
|
|
connected = null
|
|
return ..()
|
|
|
|
/obj/structure/tray/m_tray/CanPass(atom/movable/mover, turf/target, height=0)
|
|
if(height == 0)
|
|
return 1
|
|
|
|
if(istype(mover) && mover.checkpass(PASSTABLE))
|
|
return 1
|
|
if(locate(/obj/structure/table) in get_turf(mover))
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
/obj/structure/tray/m_tray/CanAStarPass(ID, dir, caller)
|
|
. = !density
|
|
if(ismovableatom(caller))
|
|
var/atom/movable/mover = caller
|
|
. = . || mover.checkpass(PASSTABLE)
|
|
|
|
/*
|
|
* 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
|
|
var/open_sound = 'sound/items/Deconstruct.ogg'
|
|
|
|
/obj/structure/crematorium/proc/update()
|
|
if(connected)
|
|
icon_state = "crema0"
|
|
else
|
|
if(contents.len)
|
|
icon_state = "crema2"
|
|
else
|
|
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.forceMove(loc)
|
|
ex_act(severity)
|
|
qdel(src)
|
|
return
|
|
if(2.0)
|
|
if(prob(50))
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(loc)
|
|
ex_act(severity)
|
|
qdel(src)
|
|
return
|
|
if(3.0)
|
|
if(prob(5))
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(loc)
|
|
ex_act(severity)
|
|
qdel(src)
|
|
return
|
|
return
|
|
|
|
/obj/structure/crematorium/alter_health()
|
|
return loc
|
|
|
|
|
|
/obj/structure/crematorium/attack_hand(mob/user as mob)
|
|
if(cremating)
|
|
to_chat(usr, "<span class='warning'>It's locked.</span>")
|
|
return
|
|
if((connected) && (locked == 0))
|
|
for(var/atom/movable/A as mob|obj in connected.loc)
|
|
if(!( A.anchored ))
|
|
A.forceMove(src)
|
|
playsound(loc, open_sound, 50, 1)
|
|
qdel(connected)
|
|
connected = null
|
|
else if(locked == 0)
|
|
playsound(loc, open_sound, 50, 1)
|
|
connected = new /obj/structure/c_tray( loc )
|
|
step(connected, SOUTH)
|
|
connected.layer = OBJ_LAYER
|
|
var/turf/T = get_step(src, SOUTH)
|
|
if(T.contents.Find(connected))
|
|
connected.connected = src
|
|
icon_state = "crema0"
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(connected.loc)
|
|
connected.icon_state = "cremat"
|
|
else
|
|
qdel(connected)
|
|
connected = null
|
|
add_fingerprint(user)
|
|
update()
|
|
|
|
/obj/structure/crematorium/attackby(P as obj, mob/user as mob, params)
|
|
if(istype(P, /obj/item/weapon/pen))
|
|
var/t = input(user, "What would you like the label to be?", text("[]", name), null) as text
|
|
if(user.get_active_hand() != P)
|
|
return
|
|
if((!in_range(src, usr) > 1 && loc != user))
|
|
return
|
|
t = sanitize(copytext(t,1,MAX_MESSAGE_LEN))
|
|
if(t)
|
|
name = text("Crematorium- '[]'", t)
|
|
else
|
|
name = "Crematorium"
|
|
add_fingerprint(user)
|
|
return
|
|
|
|
/obj/structure/crematorium/relaymove(mob/user as mob)
|
|
if(user.stat || locked)
|
|
return
|
|
connected = new /obj/structure/c_tray( loc )
|
|
step(connected, SOUTH)
|
|
connected.layer = OBJ_LAYER
|
|
var/turf/T = get_step(src, SOUTH)
|
|
if(T.contents.Find(connected))
|
|
connected.connected = src
|
|
icon_state = "crema0"
|
|
for(var/atom/movable/A as mob|obj in src)
|
|
A.forceMove(connected.loc)
|
|
connected.icon_state = "cremat"
|
|
else
|
|
qdel(connected)
|
|
connected = null
|
|
return
|
|
|
|
/obj/structure/crematorium/proc/cremate(mob/user as mob)
|
|
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("<span class='warning'>You hear a hollow crackle.</span>", 1)
|
|
return
|
|
|
|
else
|
|
for(var/mob/M in viewers(src))
|
|
M.show_message("<span class='warning'>You hear a roar as the crematorium activates.</span>", 1)
|
|
|
|
cremating = 1
|
|
locked = 1
|
|
icon_state = "crema_active"
|
|
|
|
for(var/mob/living/M in search_contents_for(/mob/living))
|
|
if(!M || !isnull(M.gcDestroyed))
|
|
continue
|
|
if(M.stat!=2)
|
|
M.emote("scream")
|
|
if(istype(user))
|
|
M.create_attack_log("<font color='orange'>Has been cremated by [user.name] ([user.ckey])</font>")
|
|
user.create_attack_log("<font color='red'>Cremated [M.name] ([M.ckey])</font>")
|
|
log_attack("[user.name] ([user.ckey]) cremated [M.name] ([M.ckey])")
|
|
M.death(1)
|
|
if(!M || !isnull(M.gcDestroyed))
|
|
continue // Re-check for mobs that delete themselves on death
|
|
M.ghostize()
|
|
qdel(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
|
|
qdel(O)
|
|
|
|
new /obj/effect/decal/cleanable/ash(src)
|
|
sleep(30)
|
|
cremating = 0
|
|
locked = 0
|
|
update()
|
|
playsound(loc, 'sound/machines/ding.ogg', 50, 1)
|
|
return
|
|
|
|
/obj/structure/crematorium/Destroy()
|
|
QDEL_NULL(connected)
|
|
return ..()
|
|
|
|
/obj/structure/crematorium/container_resist(var/mob/living/L)
|
|
var/mob/living/carbon/CM = L
|
|
if(!istype(CM))
|
|
return
|
|
if(CM.stat || CM.restrained())
|
|
return
|
|
|
|
to_chat(CM, "<span class='alert'>You attempt to slide yourself out of \the [src]...</span>")
|
|
src.attack_hand(CM)
|
|
|
|
/obj/structure/crematorium/get_remote_view_fullscreens(mob/user)
|
|
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
|
user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 2)
|
|
|
|
/*
|
|
* 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
|
|
pass_flags = LETPASSTHROW
|
|
|
|
/obj/structure/c_tray/attack_hand(mob/user as mob)
|
|
if(connected)
|
|
for(var/atom/movable/A as mob|obj in loc)
|
|
if(!( A.anchored ))
|
|
A.forceMove(connected)
|
|
//Foreach goto(26)
|
|
connected.connected = null
|
|
connected.update()
|
|
add_fingerprint(user)
|
|
qdel(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
|
|
if(!ismob(user) || user.stat || user.lying || user.stunned)
|
|
return
|
|
O.forceMove(loc)
|
|
if(user != O)
|
|
for(var/mob/B in viewers(user, 3))
|
|
if((B.client && !( B.blinded )))
|
|
to_chat(B, text("<span class='warning'>[] stuffs [] into []!</span>", user, O, src))
|
|
//Foreach goto(99)
|
|
return
|
|
|
|
/obj/structure/c_tray/Destroy()
|
|
if(connected && connected.connected == src)
|
|
connected.connected = null
|
|
connected = null
|
|
return ..()
|
|
|
|
// Crematorium switch
|
|
/obj/machinery/crema_switch
|
|
desc = "Burn baby burn!"
|
|
name = "crematorium igniter"
|
|
icon = 'icons/obj/power.dmi'
|
|
icon_state = "crema_switch"
|
|
anchored = 1.0
|
|
req_access = list(access_crematorium)
|
|
var/on = 0
|
|
var/area/area = null
|
|
var/otherarea = null
|
|
var/id = 1
|
|
|
|
/obj/machinery/crema_switch/attack_ghost(mob/user)
|
|
if(user.can_advanced_admin_interact())
|
|
return attack_hand(user)
|
|
|
|
/obj/machinery/crema_switch/attack_hand(mob/user)
|
|
if(allowed(usr) || user.can_advanced_admin_interact())
|
|
for(var/obj/structure/crematorium/C in world)
|
|
if(C.id == id)
|
|
if(!C.cremating)
|
|
C.cremate(user)
|
|
else
|
|
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
|
|
|
/mob/proc/update_morgue()
|
|
if(stat == DEAD)
|
|
var/obj/structure/morgue/morgue
|
|
var/mob/living/C = src
|
|
var/mob/dead/observer/G = src
|
|
if(istype(G) && G.can_reenter_corpse && G.mind) //We're a ghost, let's find our corpse
|
|
C = G.mind.current
|
|
if(istype(C)) //We found our corpse, is it inside a morgue?
|
|
morgue = get(C.loc, /obj/structure/morgue)
|
|
if(morgue)
|
|
morgue.update()
|
|
|
|
/hook/mob_login/proc/update_morgue(var/client/client, var/mob/mob)
|
|
//Update morgues on login
|
|
mob.update_morgue()
|
|
return 1
|
|
|
|
/hook/mob_logout/proc/update_morgue(var/client/client, var/mob/mob)
|
|
//Update morgues on logout
|
|
mob.update_morgue()
|
|
return 1
|