Ported /tg/ style screen alerts, replacing the hunger icon with them

This commit is contained in:
Atermonera
2020-05-30 21:17:50 -07:00
committed by Aronai Sieyes
parent 30cf26ba8e
commit 619e8b1b94
7 changed files with 903 additions and 892 deletions

View File

@@ -52,12 +52,14 @@
animate(alert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
if(alert.timeout)
spawn(alert.timeout)
if(alert.timeout && alerts[category] == alert && world.time >= alert.timeout)
clear_alert(category)
addtimer(CALLBACK(src, .proc/alert_timeout, alert, category), alert.timeout)
alert.timeout = world.time + alert.timeout - world.tick_lag
return alert
/mob/proc/alert_timeout(obj/screen/alert/alert, category)
if(alert.timeout && alerts[category] == alert && world.time >= alert.timeout)
clear_alert(category)
// Proc to clear an existing alert.
/mob/proc/clear_alert(category)
var/obj/screen/alert/alert = alerts[category]
@@ -455,7 +457,7 @@ so as to remain in compliance with the most up-to-date laws."
return
var/paramslist = params2list(params)
if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat
usr << "<span class='boldnotice'>[name]</span> - <span class='info'>[desc]</span>"
to_chat(usr,"<span class='boldnotice'>[name]</span> - <span class='info'>[desc]</span>")
return
if(master)
return usr.client.Click(master, location, control, params)

View File

@@ -1,474 +1,474 @@
/obj/structure/closet
name = "closet"
desc = "It's a basic storage unit."
icon = 'icons/obj/closet.dmi'
icon_state = "closed"
density = 1
w_class = ITEMSIZE_HUGE
layer = UNDER_JUNK_LAYER
var/icon_closed = "closed"
var/icon_opened = "open"
var/opened = 0
var/sealed = 0
var/seal_tool = /obj/item/weapon/weldingtool //Tool used to seal the closet, defaults to welder
var/wall_mounted = 0 //never solid (You can always pass over it)
var/health = 100
var/breakout = 0 //if someone is currently breaking out. mutex
var/breakout_time = 2 //2 minutes by default
var/breakout_sound = 'sound/effects/grillehit.ogg' //Sound that plays while breaking out
var/storage_capacity = 2 * MOB_MEDIUM //This is so that someone can't pack hundreds of items in a locker/crate
//then open it in a populated area to crash clients.
var/storage_cost = 40 //How much space this closet takes up if it's stuffed in another closet
var/open_sound = 'sound/machines/click.ogg'
var/close_sound = 'sound/machines/click.ogg'
var/store_misc = 1 //Chameleon item check
var/store_items = 1 //Will the closet store items?
var/store_mobs = 1 //Will the closet store mobs?
var/max_closets = 0 //Number of other closets allowed on tile before it won't close.
var/list/starts_with
/obj/structure/closet/Initialize()
..()
// Closets need to come later because of spawners potentially creating objects during init.
return INITIALIZE_HINT_LATELOAD
/obj/structure/closet/LateInitialize()
. = ..()
if(starts_with)
create_objects_in_loc(src, starts_with)
starts_with = null
if(!opened) // if closed, any item at the crate's loc is put in the contents
if(istype(loc, /mob/living)) return //VOREStation Edit - No collecting mob organs if spawned inside mob
var/obj/item/I
for(I in src.loc)
if(I.density || I.anchored || I == src) continue
I.forceMove(src)
// adjust locker size to hold all items with 5 units of free store room
var/content_size = 0
for(I in src.contents)
content_size += CEILING(I.w_class/2, 1)
if(content_size > storage_capacity-5)
storage_capacity = content_size + 5
update_icon()
/obj/structure/closet/examine(mob/user)
. = ..()
if(Adjacent(user) || isobserver(user))
var/content_size = 0
for(var/obj/item/I in src.contents)
if(!I.anchored)
content_size += CEILING(I.w_class/2, 1)
if(!content_size)
. += "It is empty."
else if(storage_capacity > content_size*4)
. += "It is barely filled."
else if(storage_capacity > content_size*2)
. += "It is less than half full."
else if(storage_capacity > content_size)
. += "There is still some free space."
else
. += "It is full."
if(!src.opened && isobserver(user))
. += "It contains: [counting_english_list(contents)]"
/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
if(wall_mounted)
return TRUE
return ..()
/obj/structure/closet/proc/can_open()
if(src.sealed)
return 0
return 1
/obj/structure/closet/proc/can_close()
var/closet_count = 0
for(var/obj/structure/closet/closet in get_turf(src))
if(closet != src)
if(!closet.anchored)
closet_count ++
if(closet_count > max_closets)
return 0
return 1
/obj/structure/closet/proc/dump_contents()
//Cham Projector Exception
for(var/obj/effect/dummy/chameleon/AD in src)
AD.forceMove(src.loc)
for(var/obj/I in src)
I.forceMove(src.loc)
for(var/mob/M in src)
M.forceMove(src.loc)
if(M.client)
M.client.eye = M.client.mob
M.client.perspective = MOB_PERSPECTIVE
/obj/structure/closet/proc/open()
if(src.opened)
return 0
if(!src.can_open())
return 0
src.dump_contents()
src.icon_state = src.icon_opened
src.opened = 1
playsound(src, open_sound, 15, 1, -3)
if(initial(density))
density = !density
return 1
/obj/structure/closet/proc/close()
if(!src.opened)
return 0
if(!src.can_close())
return 0
var/stored_units = 0
if(store_misc)
stored_units += store_misc(stored_units)
if(store_items)
stored_units += store_items(stored_units)
if(store_mobs)
stored_units += store_mobs(stored_units)
if(max_closets)
stored_units += store_closets(stored_units)
src.icon_state = src.icon_closed
src.opened = 0
playsound(src, close_sound, 15, 1, -3)
if(initial(density))
density = !density
return 1
//Cham Projector Exception
/obj/structure/closet/proc/store_misc(var/stored_units)
var/added_units = 0
for(var/obj/effect/dummy/chameleon/AD in src.loc)
if((stored_units + added_units) > storage_capacity)
break
AD.forceMove(src)
added_units++
return added_units
/obj/structure/closet/proc/store_items(var/stored_units)
var/added_units = 0
for(var/obj/item/I in src.loc)
var/item_size = CEILING(I.w_class / 2, 1)
if(stored_units + added_units + item_size > storage_capacity)
continue
if(!I.anchored)
I.forceMove(src)
added_units += item_size
return added_units
/obj/structure/closet/proc/store_mobs(var/stored_units)
var/added_units = 0
for(var/mob/living/M in src.loc)
if(M.buckled || M.pinned.len)
continue
if(stored_units + added_units + M.mob_size > storage_capacity)
break
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.forceMove(src)
added_units += M.mob_size
return added_units
/obj/structure/closet/proc/store_closets(var/stored_units)
var/added_units = 0
for(var/obj/structure/closet/C in src.loc)
if(C == src) //Don't store ourself
continue
if(C.anchored) //Don't worry about anchored things on the same tile
continue
if(C.max_closets) //Prevents recursive storage
continue
if(stored_units + added_units + storage_cost > storage_capacity)
break
C.forceMove(src)
added_units += storage_cost
return added_units
/obj/structure/closet/proc/toggle(mob/user as mob)
if(!(src.opened ? src.close() : src.open()))
to_chat(user, "<span class='notice'>It won't budge!</span>")
return
update_icon()
// this should probably use dump_contents()
/obj/structure/closet/ex_act(severity)
switch(severity)
if(1)
for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion
A.forceMove(src.loc)
A.ex_act(severity + 1)
qdel(src)
if(2)
if(prob(50))
for (var/atom/movable/A as mob|obj in src)
A.forceMove(src.loc)
A.ex_act(severity + 1)
qdel(src)
if(3)
if(prob(5))
for(var/atom/movable/A as mob|obj in src)
A.forceMove(src.loc)
qdel(src)
/obj/structure/closet/blob_act()
damage(100)
/obj/structure/closet/proc/damage(var/damage)
health -= damage
if(health <= 0)
for(var/atom/movable/A in src)
A.forceMove(src.loc)
qdel(src)
/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj)
var/proj_damage = Proj.get_structure_damage()
if(!proj_damage)
return
..()
damage(proj_damage)
return
/obj/structure/closet/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(src.opened)
if(istype(W, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = W
src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
return 0
if(istype(W,/obj/item/tk_grab))
return 0
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(!WT.remove_fuel(0,user))
if(!WT.isOn())
return
else
to_chat(user, "<span class='notice'>You need more welding fuel to complete this task.</span>")
return
playsound(src, WT.usesound, 50)
new /obj/item/stack/material/steel(src.loc)
for(var/mob/M in viewers(src))
M.show_message("<span class='notice'>\The [src] has been cut apart by [user] with \the [WT].</span>", 3, "You hear welding.", 2)
qdel(src)
return
if(istype(W, /obj/item/weapon/storage/laundry_basket) && W.contents.len)
var/obj/item/weapon/storage/laundry_basket/LB = W
var/turf/T = get_turf(src)
for(var/obj/item/I in LB.contents)
LB.remove_from_storage(I, T)
user.visible_message("<span class='notice'>[user] empties \the [LB] into \the [src].</span>", \
"<span class='notice'>You empty \the [LB] into \the [src].</span>", \
"<span class='notice'>You hear rustling of clothes.</span>")
return
if(isrobot(user))
return
if(W.loc != user) // This should stop mounted modules ending up outside the module.
return
usr.drop_item()
if(W)
W.forceMove(src.loc)
else if(istype(W, /obj/item/weapon/packageWrap))
return
else if(seal_tool)
if(istype(W, seal_tool))
var/obj/item/weapon/S = W
if(istype(S, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = S
if(!WT.remove_fuel(0,user))
if(!WT.isOn())
return
else
to_chat(user, "<span class='notice'>You need more welding fuel to complete this task.</span>")
return
if(do_after(user, 20 * S.toolspeed))
playsound(src, S.usesound, 50)
src.sealed = !src.sealed
src.update_icon()
for(var/mob/M in viewers(src))
M.show_message("<span class='warning'>[src] has been [sealed?"sealed":"unsealed"] by [user.name].</span>", 3)
else if(W.is_wrench())
if(sealed)
if(anchored)
user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
else
user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
playsound(src, W.usesound, 50)
if(do_after(user, 20 * W.toolspeed))
if(!src) return
to_chat(user, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
anchored = !anchored
else
src.attack_hand(user)
return
/obj/structure/closet/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete
return
if(O.loc == user)
return
if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis)
return
if((!( istype(O, /atom/movable) ) || O.anchored || !Adjacent(user) || !Adjacent(O) || !user.Adjacent(O) || user.contents.Find(src)))
return
if(!isturf(user.loc)) // are you in a container/closet/pod/etc?
return
if(!src.opened)
return
if(istype(O, /obj/structure/closet))
return
step_towards(O, src.loc)
if(user != O)
user.show_viewers("<span class='danger'>[user] stuffs [O] into [src]!</span>")
src.add_fingerprint(user)
return
/obj/structure/closet/attack_robot(mob/user)
if(Adjacent(user))
attack_hand(user)
/obj/structure/closet/relaymove(mob/user as mob)
if(user.stat || !isturf(src.loc))
return
if(!src.open())
to_chat(user, "<span class='notice'>It won't budge!</span>")
/obj/structure/closet/attack_hand(mob/user as mob)
src.add_fingerprint(user)
src.toggle(user)
// tk grab then use on self
/obj/structure/closet/attack_self_tk(mob/user as mob)
src.add_fingerprint(user)
if(!src.toggle())
to_chat(usr, "<span class='notice'>It won't budge!</span>")
/obj/structure/closet/verb/verb_toggleopen()
set src in oview(1)
set category = "Object"
set name = "Toggle Open"
if(!usr.canmove || usr.stat || usr.restrained())
return
if(ishuman(usr) || isrobot(usr))
src.add_fingerprint(usr)
src.toggle(usr)
else
to_chat(usr, "<span class='warning'>This mob type can't use this verb.</span>")
/obj/structure/closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
overlays.Cut()
if(!opened)
icon_state = icon_closed
if(sealed)
overlays += "welded"
else
icon_state = icon_opened
/obj/structure/closet/attack_generic(var/mob/user, var/damage, var/attack_message = "destroys")
if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
return
user.do_attack_animation(src)
visible_message("<span class='danger'>[user] [attack_message] the [src]!</span>")
dump_contents()
spawn(1) qdel(src)
return 1
/obj/structure/closet/proc/req_breakout()
if(opened)
return 0 //Door's open... wait, why are you in it's contents then?
if(!sealed)
return 0 //closed but not sealed...
return 1
/obj/structure/closet/container_resist(var/mob/living/escapee)
if(breakout || !req_breakout())
return
escapee.setClickCooldown(100)
//okay, so the closet is either sealed or locked... resist!!!
to_chat(escapee, "<span class='warning'>You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)</span>")
visible_message("<span class='danger'>\The [src] begins to shake violently!</span>")
breakout = 1 //can't think of a better way to do this right now.
for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2
if(!do_after(escapee, 50)) //5 seconds
breakout = 0
return
if(!escapee || escapee.incapacitated() || escapee.loc != src)
breakout = 0
return //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened
//Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'...
if(!req_breakout())
breakout = 0
return
playsound(src, breakout_sound, 100, 1)
animate_shake()
add_fingerprint(escapee)
//Well then break it!
breakout = 0
to_chat(escapee, "<span class='warning'>You successfully break out!</span>")
visible_message("<span class='danger'>\The [escapee] successfully broke out of \the [src]!</span>")
playsound(src, breakout_sound, 100, 1)
break_open()
animate_shake()
/obj/structure/closet/proc/break_open()
sealed = 0
update_icon()
//Do this to prevent contents from being opened into nullspace (read: bluespace)
if(istype(loc, /obj/structure/bigDelivery))
var/obj/structure/bigDelivery/BD = loc
BD.unwrap()
open()
/obj/structure/closet/proc/animate_shake()
var/init_px = pixel_x
var/shake_dir = pick(-1, 1)
animate(src, transform=turn(matrix(), 8*shake_dir), pixel_x=init_px + 2*shake_dir, time=1)
animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING)
/obj/structure/closet/onDropInto(var/atom/movable/AM)
return
/obj/structure/closet/AllowDrop()
return TRUE
/obj/structure/closet/return_air_for_internal_lifeform(var/mob/living/L)
if(src.loc)
if(istype(src.loc, /obj/structure/closet))
return (loc.return_air_for_internal_lifeform(L))
return return_air()
/obj/structure/closet/take_damage(var/damage)
if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
return
dump_contents()
spawn(1) qdel(src)
return 1
/obj/structure/closet
name = "closet"
desc = "It's a basic storage unit."
icon = 'icons/obj/closet.dmi'
icon_state = "closed"
density = 1
w_class = ITEMSIZE_HUGE
layer = UNDER_JUNK_LAYER
var/icon_closed = "closed"
var/icon_opened = "open"
var/opened = 0
var/sealed = 0
var/seal_tool = /obj/item/weapon/weldingtool //Tool used to seal the closet, defaults to welder
var/wall_mounted = 0 //never solid (You can always pass over it)
var/health = 100
var/breakout = 0 //if someone is currently breaking out. mutex
var/breakout_time = 2 //2 minutes by default
var/breakout_sound = 'sound/effects/grillehit.ogg' //Sound that plays while breaking out
var/storage_capacity = 2 * MOB_MEDIUM //This is so that someone can't pack hundreds of items in a locker/crate
//then open it in a populated area to crash clients.
var/storage_cost = 40 //How much space this closet takes up if it's stuffed in another closet
var/open_sound = 'sound/machines/click.ogg'
var/close_sound = 'sound/machines/click.ogg'
var/store_misc = 1 //Chameleon item check
var/store_items = 1 //Will the closet store items?
var/store_mobs = 1 //Will the closet store mobs?
var/max_closets = 0 //Number of other closets allowed on tile before it won't close.
var/list/starts_with
/obj/structure/closet/Initialize()
..()
// Closets need to come later because of spawners potentially creating objects during init.
return INITIALIZE_HINT_LATELOAD
/obj/structure/closet/LateInitialize()
. = ..()
if(starts_with)
create_objects_in_loc(src, starts_with)
starts_with = null
if(!opened) // if closed, any item at the crate's loc is put in the contents
if(istype(loc, /mob/living)) return //VOREStation Edit - No collecting mob organs if spawned inside mob
var/obj/item/I
for(I in src.loc)
if(I.density || I.anchored || I == src) continue
I.forceMove(src)
// adjust locker size to hold all items with 5 units of free store room
var/content_size = 0
for(I in src.contents)
content_size += CEILING(I.w_class/2, 1)
if(content_size > storage_capacity-5)
storage_capacity = content_size + 5
update_icon()
/obj/structure/closet/examine(mob/user)
. = ..()
if(Adjacent(user) || isobserver(user))
var/content_size = 0
for(var/obj/item/I in src.contents)
if(!I.anchored)
content_size += CEILING(I.w_class/2, 1)
if(!content_size)
. += "It is empty."
else if(storage_capacity > content_size*4)
. += "It is barely filled."
else if(storage_capacity > content_size*2)
. += "It is less than half full."
else if(storage_capacity > content_size)
. += "There is still some free space."
else
. += "It is full."
if(!src.opened && isobserver(user))
. += "It contains: [counting_english_list(contents)]"
/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
if(wall_mounted)
return TRUE
return ..()
/obj/structure/closet/proc/can_open()
if(src.sealed)
return 0
return 1
/obj/structure/closet/proc/can_close()
var/closet_count = 0
for(var/obj/structure/closet/closet in get_turf(src))
if(closet != src)
if(!closet.anchored)
closet_count ++
if(closet_count > max_closets)
return 0
return 1
/obj/structure/closet/proc/dump_contents()
//Cham Projector Exception
for(var/obj/effect/dummy/chameleon/AD in src)
AD.forceMove(src.loc)
for(var/obj/I in src)
I.forceMove(src.loc)
for(var/mob/M in src)
M.forceMove(src.loc)
if(M.client)
M.client.eye = M.client.mob
M.client.perspective = MOB_PERSPECTIVE
/obj/structure/closet/proc/open()
if(src.opened)
return 0
if(!src.can_open())
return 0
src.dump_contents()
src.icon_state = src.icon_opened
src.opened = 1
playsound(src, open_sound, 15, 1, -3)
if(initial(density))
density = !density
return 1
/obj/structure/closet/proc/close()
if(!src.opened)
return 0
if(!src.can_close())
return 0
var/stored_units = 0
if(store_misc)
stored_units += store_misc(stored_units)
if(store_items)
stored_units += store_items(stored_units)
if(store_mobs)
stored_units += store_mobs(stored_units)
if(max_closets)
stored_units += store_closets(stored_units)
src.icon_state = src.icon_closed
src.opened = 0
playsound(src, close_sound, 15, 1, -3)
if(initial(density))
density = !density
return 1
//Cham Projector Exception
/obj/structure/closet/proc/store_misc(var/stored_units)
var/added_units = 0
for(var/obj/effect/dummy/chameleon/AD in src.loc)
if((stored_units + added_units) > storage_capacity)
break
AD.forceMove(src)
added_units++
return added_units
/obj/structure/closet/proc/store_items(var/stored_units)
var/added_units = 0
for(var/obj/item/I in src.loc)
var/item_size = CEILING(I.w_class / 2, 1)
if(stored_units + added_units + item_size > storage_capacity)
continue
if(!I.anchored)
I.forceMove(src)
added_units += item_size
return added_units
/obj/structure/closet/proc/store_mobs(var/stored_units)
var/added_units = 0
for(var/mob/living/M in src.loc)
if(M.buckled || M.pinned.len)
continue
if(stored_units + added_units + M.mob_size > storage_capacity)
break
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.forceMove(src)
added_units += M.mob_size
return added_units
/obj/structure/closet/proc/store_closets(var/stored_units)
var/added_units = 0
for(var/obj/structure/closet/C in src.loc)
if(C == src) //Don't store ourself
continue
if(C.anchored) //Don't worry about anchored things on the same tile
continue
if(C.max_closets) //Prevents recursive storage
continue
if(stored_units + added_units + storage_cost > storage_capacity)
break
C.forceMove(src)
added_units += storage_cost
return added_units
/obj/structure/closet/proc/toggle(mob/user as mob)
if(!(src.opened ? src.close() : src.open()))
to_chat(user, "<span class='notice'>It won't budge!</span>")
return
update_icon()
// this should probably use dump_contents()
/obj/structure/closet/ex_act(severity)
switch(severity)
if(1)
for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion
A.forceMove(src.loc)
A.ex_act(severity + 1)
qdel(src)
if(2)
if(prob(50))
for (var/atom/movable/A as mob|obj in src)
A.forceMove(src.loc)
A.ex_act(severity + 1)
qdel(src)
if(3)
if(prob(5))
for(var/atom/movable/A as mob|obj in src)
A.forceMove(src.loc)
qdel(src)
/obj/structure/closet/blob_act()
damage(100)
/obj/structure/closet/proc/damage(var/damage)
health -= damage
if(health <= 0)
for(var/atom/movable/A in src)
A.forceMove(src.loc)
qdel(src)
/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj)
var/proj_damage = Proj.get_structure_damage()
if(!proj_damage)
return
..()
damage(proj_damage)
return
/obj/structure/closet/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(src.opened)
if(istype(W, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = W
src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
return 0
if(istype(W,/obj/item/tk_grab))
return 0
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(!WT.remove_fuel(0,user))
if(!WT.isOn())
return
else
to_chat(user, "<span class='notice'>You need more welding fuel to complete this task.</span>")
return
playsound(src, WT.usesound, 50)
new /obj/item/stack/material/steel(src.loc)
for(var/mob/M in viewers(src))
M.show_message("<span class='notice'>\The [src] has been cut apart by [user] with \the [WT].</span>", 3, "You hear welding.", 2)
qdel(src)
return
if(istype(W, /obj/item/weapon/storage/laundry_basket) && W.contents.len)
var/obj/item/weapon/storage/laundry_basket/LB = W
var/turf/T = get_turf(src)
for(var/obj/item/I in LB.contents)
LB.remove_from_storage(I, T)
user.visible_message("<span class='notice'>[user] empties \the [LB] into \the [src].</span>", \
"<span class='notice'>You empty \the [LB] into \the [src].</span>", \
"<span class='notice'>You hear rustling of clothes.</span>")
return
if(isrobot(user))
return
if(W.loc != user) // This should stop mounted modules ending up outside the module.
return
usr.drop_item()
if(W)
W.forceMove(src.loc)
else if(istype(W, /obj/item/weapon/packageWrap))
return
else if(seal_tool)
if(istype(W, seal_tool))
var/obj/item/weapon/S = W
if(istype(S, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = S
if(!WT.remove_fuel(0,user))
if(!WT.isOn())
return
else
to_chat(user, "<span class='notice'>You need more welding fuel to complete this task.</span>")
return
if(do_after(user, 20 * S.toolspeed))
playsound(src, S.usesound, 50)
src.sealed = !src.sealed
src.update_icon()
for(var/mob/M in viewers(src))
M.show_message("<span class='warning'>[src] has been [sealed?"sealed":"unsealed"] by [user.name].</span>", 3)
else if(W.is_wrench())
if(sealed)
if(anchored)
user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
else
user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
playsound(src, W.usesound, 50)
if(do_after(user, 20 * W.toolspeed))
if(!src) return
to_chat(user, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
anchored = !anchored
else
src.attack_hand(user)
return
/obj/structure/closet/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete
return
if(O.loc == user)
return
if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis)
return
if((!( istype(O, /atom/movable) ) || O.anchored || !Adjacent(user) || !Adjacent(O) || !user.Adjacent(O) || user.contents.Find(src)))
return
if(!isturf(user.loc)) // are you in a container/closet/pod/etc?
return
if(!src.opened)
return
if(istype(O, /obj/structure/closet))
return
step_towards(O, src.loc)
if(user != O)
user.show_viewers("<span class='danger'>[user] stuffs [O] into [src]!</span>")
src.add_fingerprint(user)
return
/obj/structure/closet/attack_robot(mob/user)
if(Adjacent(user))
attack_hand(user)
/obj/structure/closet/relaymove(mob/user as mob)
if(user.stat || !isturf(src.loc))
return
if(!src.open())
to_chat(user, "<span class='notice'>It won't budge!</span>")
/obj/structure/closet/attack_hand(mob/user as mob)
src.add_fingerprint(user)
src.toggle(user)
// tk grab then use on self
/obj/structure/closet/attack_self_tk(mob/user as mob)
src.add_fingerprint(user)
if(!src.toggle())
to_chat(usr, "<span class='notice'>It won't budge!</span>")
/obj/structure/closet/verb/verb_toggleopen()
set src in oview(1)
set category = "Object"
set name = "Toggle Open"
if(!usr.canmove || usr.stat || usr.restrained())
return
if(ishuman(usr) || isrobot(usr))
src.add_fingerprint(usr)
src.toggle(usr)
else
to_chat(usr, "<span class='warning'>This mob type can't use this verb.</span>")
/obj/structure/closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
overlays.Cut()
if(!opened)
icon_state = icon_closed
if(sealed)
overlays += "welded"
else
icon_state = icon_opened
/obj/structure/closet/attack_generic(var/mob/user, var/damage, var/attack_message = "destroys")
if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
return
user.do_attack_animation(src)
visible_message("<span class='danger'>[user] [attack_message] the [src]!</span>")
dump_contents()
spawn(1) qdel(src)
return 1
/obj/structure/closet/proc/req_breakout()
if(opened)
return 0 //Door's open... wait, why are you in it's contents then?
if(!sealed)
return 0 //closed but not sealed...
return 1
/obj/structure/closet/container_resist(var/mob/living/escapee)
if(breakout || !req_breakout())
return
escapee.setClickCooldown(100)
//okay, so the closet is either sealed or locked... resist!!!
to_chat(escapee, "<span class='warning'>You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)</span>")
visible_message("<span class='danger'>\The [src] begins to shake violently!</span>")
breakout = 1 //can't think of a better way to do this right now.
for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2
if(!do_after(escapee, 50)) //5 seconds
breakout = 0
return
if(!escapee || escapee.incapacitated() || escapee.loc != src)
breakout = 0
return //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened
//Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'...
if(!req_breakout())
breakout = 0
return
playsound(src, breakout_sound, 100, 1)
animate_shake()
add_fingerprint(escapee)
//Well then break it!
breakout = 0
to_chat(escapee, "<span class='warning'>You successfully break out!</span>")
visible_message("<span class='danger'>\The [escapee] successfully broke out of \the [src]!</span>")
playsound(src, breakout_sound, 100, 1)
break_open()
animate_shake()
/obj/structure/closet/proc/break_open()
sealed = 0
update_icon()
//Do this to prevent contents from being opened into nullspace (read: bluespace)
if(istype(loc, /obj/structure/bigDelivery))
var/obj/structure/bigDelivery/BD = loc
BD.unwrap()
open()
/obj/structure/closet/proc/animate_shake()
var/init_px = pixel_x
var/shake_dir = pick(-1, 1)
animate(src, transform=turn(matrix(), 8*shake_dir), pixel_x=init_px + 2*shake_dir, time=1)
animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING)
/obj/structure/closet/onDropInto(var/atom/movable/AM)
return
/obj/structure/closet/AllowDrop()
return TRUE
/obj/structure/closet/return_air_for_internal_lifeform(var/mob/living/L)
if(src.loc)
if(istype(src.loc, /obj/structure/closet))
return (loc.return_air_for_internal_lifeform(L))
return return_air()
/obj/structure/closet/take_damage(var/damage)
if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD)
return
dump_contents()
spawn(1) qdel(src)
return 1

View File

@@ -1,413 +1,413 @@
/mob/living/carbon/Initialize()
. = ..()
//setup reagent holders
bloodstr = new/datum/reagents/metabolism/bloodstream(500, src)
ingested = new/datum/reagents/metabolism/ingested(500, src)
touching = new/datum/reagents/metabolism/touch(500, src)
reagents = bloodstr
if (!default_language && species_language)
default_language = GLOB.all_languages[species_language]
/mob/living/carbon/Life()
..()
handle_viruses()
// Increase germ_level regularly
if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
germ_level++
/mob/living/carbon/Destroy()
qdel(ingested)
qdel(touching)
// We don't qdel(bloodstr) because it's the same as qdel(reagents)
for(var/guts in internal_organs)
qdel(guts)
for(var/food in stomach_contents)
qdel(food)
return ..()
/mob/living/carbon/rejuvenate()
bloodstr.clear_reagents()
ingested.clear_reagents()
touching.clear_reagents()
..()
/* VOREStation Edit - Duplicated in our code
/mob/living/carbon/Moved(atom/old_loc, direction, forced = FALSE)
. = ..()
if(src.nutrition && src.stat != 2)
adjust_nutrition(-DEFAULT_HUNGER_FACTOR / 10)
if(src.m_intent == "run")
adjust_nutrition(-DEFAULT_HUNGER_FACTOR / 10)
if((FAT in src.mutations) && src.m_intent == "run" && src.bodytemperature <= 360)
src.bodytemperature += 2
// Moving around increases germ_level faster
if(germ_level < GERM_LEVEL_MOVE_CAP && prob(8))
germ_level++
/mob/living/carbon/relaymove(var/mob/living/user, direction)
if((user in src.stomach_contents) && istype(user))
if(user.last_special <= world.time)
user.last_special = world.time + 50
src.visible_message("<span class='danger'>You hear something rumbling inside [src]'s stomach...</span>")
var/obj/item/I = user.get_active_hand()
if(I && I.force)
var/d = rand(round(I.force / 4), I.force)
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/organ = H.get_organ(BP_TORSO)
if (istype(organ))
if(organ.take_damage(d, 0))
H.UpdateDamageIcon()
H.updatehealth()
else
src.take_organ_damage(d)
user.visible_message("<span class='danger'>[user] attacks [src]'s stomach wall with the [I.name]!</span>")
playsound(user, 'sound/effects/attackblob.ogg', 50, 1)
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
A.loc = loc
stomach_contents.Remove(A)
src.gib()
*/
/mob/living/carbon/gib()
for(var/mob/M in src)
if(M in src.stomach_contents)
src.stomach_contents.Remove(M)
M.loc = src.loc
for(var/mob/N in viewers(src, null))
if(N.client)
N.show_message(text("<font color='red'><B>[M] bursts out of [src]!</B></font>"), 2)
..()
/mob/living/carbon/attack_hand(mob/M as mob)
if(!istype(M, /mob/living/carbon)) return
if (ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
if (H.hand)
temp = H.organs_by_name["l_hand"]
if(temp && !temp.is_usable())
to_chat(H, "<font color='red'>You can't use your [temp.name]</font>")
return
return
/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null, var/stun = 1)
if(status_flags & GODMODE) return 0 //godmode
if(def_zone == "l_hand" || def_zone == "r_hand") //Diona (And any other potential plant people) hands don't get shocked.
if(species.flags & IS_PLANT)
return 0
shock_damage *= siemens_coeff
if (shock_damage<1)
return 0
src.apply_damage(0.2 * shock_damage, BURN, def_zone, used_weapon="Electrocution") //shock the target organ
src.apply_damage(0.4 * shock_damage, BURN, BP_TORSO, used_weapon="Electrocution") //shock the torso more
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
playsound(src, "sparks", 50, 1, -1)
if (shock_damage > 15)
src.visible_message(
"<span class='warning'>[src] was electrocuted[source ? " by the [source]" : ""]!</span>", \
"<span class='danger'>You feel a powerful shock course through your body!</span>", \
"<span class='warning'>You hear a heavy electrical crack.</span>" \
)
else
src.visible_message(
"<span class='warning'>[src] was shocked[source ? " by the [source]" : ""].</span>", \
"<span class='warning'>You feel a shock course through your body.</span>", \
"<span class='warning'>You hear a zapping sound.</span>" \
)
if(stun)
switch(shock_damage)
if(16 to 20)
Stun(2)
if(21 to 25)
Weaken(2)
if(26 to 30)
Weaken(5)
if(31 to INFINITY)
Weaken(10) //This should work for now, more is really silly and makes you lay there forever
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, loc)
s.start()
return shock_damage
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
if (src.health >= config.health_threshold_crit)
if(src == M && istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/datum/gender/T = gender_datums[H.get_visible_gender()]
src.visible_message( \
"<span class='notice'>[src] examines [T.himself].</span>", \
"<span class='notice'>You check yourself for injuries.</span>" \
)
for(var/obj/item/organ/external/org in H.organs)
var/list/status = list()
var/brutedamage = org.brute_dam
var/burndamage = org.burn_dam
/*
if(halloss > 0) //Makes halloss show up as actual wounds on self examine.
if(prob(30))
brutedamage += halloss
if(prob(30))
burndamage += halloss
*/
switch(brutedamage)
if(1 to 20)
status += "bruised"
if(20 to 40)
status += "wounded"
if(40 to INFINITY)
status += "mangled"
switch(burndamage)
if(1 to 10)
status += "numb"
if(10 to 40)
status += "blistered"
if(40 to INFINITY)
status += "peeling away"
if(org.is_stump())
status += "MISSING"
if(org.status & ORGAN_MUTATED)
status += "weirdly shapen"
if(org.dislocated == 2)
status += "dislocated"
if(org.status & ORGAN_BROKEN)
status += "hurts when touched"
if(org.status & ORGAN_DEAD)
status += "is bruised and necrotic"
if(!org.is_usable() || org.is_dislocated())
status += "dangling uselessly"
if(status.len)
src.show_message("My [org.name] is <span class='warning'> [english_list(status)].</span>",1)
else
src.show_message("My [org.name] is <span class='notice'> OK.</span>",1)
if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit))
H.play_xylophone()
else if (on_fire)
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if (M.on_fire)
M.visible_message("<span class='warning'>[M] tries to pat out [src]'s flames, but to no avail!</span>",
"<span class='warning'>You try to pat out [src]'s flames, but to no avail! Put yourself out first!</span>")
else
M.visible_message("<span class='warning'>[M] tries to pat out [src]'s flames!</span>",
"<span class='warning'>You try to pat out [src]'s flames! Hot!</span>")
if(do_mob(M, src, 15))
src.adjust_fire_stacks(-0.5)
if (prob(10) && (M.fire_stacks <= 0))
M.adjust_fire_stacks(1)
M.IgniteMob()
if (M.on_fire)
M.visible_message("<span class='danger'>The fire spreads from [src] to [M]!</span>",
"<span class='danger'>The fire spreads to you as well!</span>")
else
src.adjust_fire_stacks(-0.5) //Less effective than stop, drop, and roll - also accounting for the fact that it takes half as long.
if (src.fire_stacks <= 0)
M.visible_message("<span class='warning'>[M] successfully pats out [src]'s flames.</span>",
"<span class='warning'>You successfully pat out [src]'s flames.</span>")
src.ExtinguishMob()
src.fire_stacks = 0
else
if (istype(src,/mob/living/carbon/human) && src:w_uniform)
var/mob/living/carbon/human/H = src
H.w_uniform.add_fingerprint(M)
var/show_ssd
var/mob/living/carbon/human/H = src
var/datum/gender/T = gender_datums[H.get_visible_gender()] // make sure to cast to human before using get_gender() or get_visible_gender()!
if(istype(H)) show_ssd = H.species.show_ssd
if(show_ssd && !client && !teleop)
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [T.him] up!</span>", \
"<span class='notice'>You shake [src], but [T.he] [T.does] not respond... Maybe [T.he] [T.has] S.S.D?</span>")
else if(lying || src.sleeping)
src.sleeping = max(0,src.sleeping-5)
if(src.sleeping == 0)
src.resting = 0
if(H) H.in_stasis = 0 //VOREStation Add - Just In Case
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [T.him] up!</span>", \
"<span class='notice'>You shake [src] trying to wake [T.him] up!</span>")
else
var/mob/living/carbon/human/hugger = M
var/datum/gender/TM = gender_datums[M.get_visible_gender()]
if(M.resting == 1) //Are they resting on the ground?
M.visible_message("<span class='notice'>[M] grabs onto [src] and pulls [TM.himself] up</span>", \
"<span class='notice'>You grip onto [src] and pull yourself up off the ground!</span>")
if(M.fire_stacks >= (src.fire_stacks + 3)) //Fire checks.
src.adjust_fire_stacks(1)
M.adjust_fire_stacks(-1)
if(M.on_fire)
src.IgniteMob()
if(do_after(M, 0.5 SECONDS)) //.5 second delay. Makes it a bit stronger than just typing rest.
M.resting = 0 //Hoist yourself up up off the ground. No para/stunned/weakened removal.
else if(istype(hugger))
hugger.species.hug(hugger,src)
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [T.him] feel better!</span>", \
"<span class='notice'>You hug [src] to make [T.him] feel better!</span>")
if(M.fire_stacks >= (src.fire_stacks + 3))
src.adjust_fire_stacks(1)
M.adjust_fire_stacks(-1)
if(M.on_fire)
src.IgniteMob()
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustWeakened(-3)
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/carbon/proc/eyecheck()
return 0
/mob/living/carbon/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash)
if(eyecheck() < intensity || override_blindness_check)
return ..()
// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching.
// Stop! ... Hammertime! ~Carn
/mob/living/carbon/proc/getDNA()
return dna
/mob/living/carbon/proc/setDNA(var/datum/dna/newDNA)
dna = newDNA
// ++++ROCKDTBEN++++ MOB PROCS //END
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
var/temp_inc = max(min(BODYTEMP_HEATING_MAX*(1-get_heat_protection()), exposed_temperature - bodytemperature), 0)
bodytemperature += temp_inc
/mob/living/carbon/can_use_hands()
if(handcuffed)
return 0
if(buckled && istype(buckled, /obj/structure/bed/nest)) // buckling does not restrict hands
return 0
return 1
/mob/living/carbon/restrained()
if (handcuffed)
return 1
return
/mob/living/carbon/u_equip(obj/item/W as obj)
if(!W) return 0
else if (W == handcuffed)
handcuffed = null
update_handcuffed()
if(buckled && buckled.buckle_require_restraints)
buckled.unbuckle_mob()
else if (W == legcuffed)
legcuffed = null
update_inv_legcuffed()
else
..()
//generates realistic-ish pulse output based on preset levels
/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate
var/temp = 0 //see setup.dm:694
switch(src.pulse)
if(PULSE_NONE)
return "0"
if(PULSE_SLOW)
temp = rand(40, 60)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_NORM)
temp = rand(60, 90)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_FAST)
temp = rand(90, 120)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_2FAST)
temp = rand(120, 160)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_THREADY)
return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread"
// output for machines^ ^^^^^^^output for people^^^^^^^^^
/mob/living/carbon/verb/mob_sleep()
set name = "Sleep"
set category = "IC"
if(usr.sleeping)
to_chat(usr, "<font color='red'>You are already sleeping</font>")
return
if(alert(src,"You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes")
usr.sleeping = 20 //Short nap
/mob/living/carbon/Bump(atom/A)
if(now_pushing)
return
..()
if(istype(A, /mob/living/carbon) && prob(10))
spread_disease_to(A, "Contact")
/mob/living/carbon/cannot_use_vents()
return
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
if(buckled)
return 0
stop_pulling()
to_chat(src, "<span class='warning'>You slipped on [slipped_on]!</span>")
playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
Weaken(FLOOR(stun_duration/2, 1))
return 1
/mob/living/carbon/proc/add_chemical_effect(var/effect, var/magnitude = 1)
if(effect in chem_effects)
chem_effects[effect] += magnitude
else
chem_effects[effect] = magnitude
/mob/living/carbon/get_default_language()
if(default_language)
if(can_speak(default_language))
return default_language
else
return GLOB.all_languages[LANGUAGE_GIBBERISH]
if(!species)
return GLOB.all_languages[LANGUAGE_GIBBERISH]
return species.default_language ? GLOB.all_languages[species.default_language] : GLOB.all_languages[LANGUAGE_GIBBERISH]
/mob/living/carbon/proc/should_have_organ(var/organ_check)
return 0
/mob/living/carbon/can_feel_pain(var/check_organ)
if(isSynthetic())
return 0
return !(species.flags & NO_PAIN)
/mob/living/carbon/needs_to_breathe()
if(does_not_breathe)
return FALSE
return ..()
/mob/living/carbon/proc/update_handcuffed()
if(handcuffed)
drop_l_hand()
drop_r_hand()
stop_pulling()
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = handcuffed)
else
clear_alert("handcuffed")
update_action_buttons() //some of our action buttons might be unusable when we're handcuffed.
update_inv_handcuffed()
/mob/living/carbon/Initialize()
. = ..()
//setup reagent holders
bloodstr = new/datum/reagents/metabolism/bloodstream(500, src)
ingested = new/datum/reagents/metabolism/ingested(500, src)
touching = new/datum/reagents/metabolism/touch(500, src)
reagents = bloodstr
if (!default_language && species_language)
default_language = GLOB.all_languages[species_language]
/mob/living/carbon/Life()
..()
handle_viruses()
// Increase germ_level regularly
if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
germ_level++
/mob/living/carbon/Destroy()
qdel(ingested)
qdel(touching)
// We don't qdel(bloodstr) because it's the same as qdel(reagents)
for(var/guts in internal_organs)
qdel(guts)
for(var/food in stomach_contents)
qdel(food)
return ..()
/mob/living/carbon/rejuvenate()
bloodstr.clear_reagents()
ingested.clear_reagents()
touching.clear_reagents()
..()
/* VOREStation Edit - Duplicated in our code
/mob/living/carbon/Moved(atom/old_loc, direction, forced = FALSE)
. = ..()
if(src.nutrition && src.stat != 2)
adjust_nutrition(-DEFAULT_HUNGER_FACTOR / 10)
if(src.m_intent == "run")
adjust_nutrition(-DEFAULT_HUNGER_FACTOR / 10)
if((FAT in src.mutations) && src.m_intent == "run" && src.bodytemperature <= 360)
src.bodytemperature += 2
// Moving around increases germ_level faster
if(germ_level < GERM_LEVEL_MOVE_CAP && prob(8))
germ_level++
/mob/living/carbon/relaymove(var/mob/living/user, direction)
if((user in src.stomach_contents) && istype(user))
if(user.last_special <= world.time)
user.last_special = world.time + 50
src.visible_message("<span class='danger'>You hear something rumbling inside [src]'s stomach...</span>")
var/obj/item/I = user.get_active_hand()
if(I && I.force)
var/d = rand(round(I.force / 4), I.force)
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/organ = H.get_organ(BP_TORSO)
if (istype(organ))
if(organ.take_damage(d, 0))
H.UpdateDamageIcon()
H.updatehealth()
else
src.take_organ_damage(d)
user.visible_message("<span class='danger'>[user] attacks [src]'s stomach wall with the [I.name]!</span>")
playsound(user, 'sound/effects/attackblob.ogg', 50, 1)
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
A.loc = loc
stomach_contents.Remove(A)
src.gib()
*/
/mob/living/carbon/gib()
for(var/mob/M in src)
if(M in src.stomach_contents)
src.stomach_contents.Remove(M)
M.loc = src.loc
for(var/mob/N in viewers(src, null))
if(N.client)
N.show_message(text("<font color='red'><B>[M] bursts out of [src]!</B></font>"), 2)
..()
/mob/living/carbon/attack_hand(mob/M as mob)
if(!istype(M, /mob/living/carbon)) return
if (ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
if (H.hand)
temp = H.organs_by_name["l_hand"]
if(temp && !temp.is_usable())
to_chat(H, "<font color='red'>You can't use your [temp.name]</font>")
return
return
/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null, var/stun = 1)
if(status_flags & GODMODE) return 0 //godmode
if(def_zone == "l_hand" || def_zone == "r_hand") //Diona (And any other potential plant people) hands don't get shocked.
if(species.flags & IS_PLANT)
return 0
shock_damage *= siemens_coeff
if (shock_damage<1)
return 0
src.apply_damage(0.2 * shock_damage, BURN, def_zone, used_weapon="Electrocution") //shock the target organ
src.apply_damage(0.4 * shock_damage, BURN, BP_TORSO, used_weapon="Electrocution") //shock the torso more
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
src.apply_damage(0.2 * shock_damage, BURN, null, used_weapon="Electrocution") //shock a random part!
playsound(src, "sparks", 50, 1, -1)
if (shock_damage > 15)
src.visible_message(
"<span class='warning'>[src] was electrocuted[source ? " by the [source]" : ""]!</span>", \
"<span class='danger'>You feel a powerful shock course through your body!</span>", \
"<span class='warning'>You hear a heavy electrical crack.</span>" \
)
else
src.visible_message(
"<span class='warning'>[src] was shocked[source ? " by the [source]" : ""].</span>", \
"<span class='warning'>You feel a shock course through your body.</span>", \
"<span class='warning'>You hear a zapping sound.</span>" \
)
if(stun)
switch(shock_damage)
if(16 to 20)
Stun(2)
if(21 to 25)
Weaken(2)
if(26 to 30)
Weaken(5)
if(31 to INFINITY)
Weaken(10) //This should work for now, more is really silly and makes you lay there forever
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, loc)
s.start()
return shock_damage
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
if (src.health >= config.health_threshold_crit)
if(src == M && istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/datum/gender/T = gender_datums[H.get_visible_gender()]
src.visible_message( \
"<span class='notice'>[src] examines [T.himself].</span>", \
"<span class='notice'>You check yourself for injuries.</span>" \
)
for(var/obj/item/organ/external/org in H.organs)
var/list/status = list()
var/brutedamage = org.brute_dam
var/burndamage = org.burn_dam
/*
if(halloss > 0) //Makes halloss show up as actual wounds on self examine.
if(prob(30))
brutedamage += halloss
if(prob(30))
burndamage += halloss
*/
switch(brutedamage)
if(1 to 20)
status += "bruised"
if(20 to 40)
status += "wounded"
if(40 to INFINITY)
status += "mangled"
switch(burndamage)
if(1 to 10)
status += "numb"
if(10 to 40)
status += "blistered"
if(40 to INFINITY)
status += "peeling away"
if(org.is_stump())
status += "MISSING"
if(org.status & ORGAN_MUTATED)
status += "weirdly shapen"
if(org.dislocated == 2)
status += "dislocated"
if(org.status & ORGAN_BROKEN)
status += "hurts when touched"
if(org.status & ORGAN_DEAD)
status += "is bruised and necrotic"
if(!org.is_usable() || org.is_dislocated())
status += "dangling uselessly"
if(status.len)
src.show_message("My [org.name] is <span class='warning'> [english_list(status)].</span>",1)
else
src.show_message("My [org.name] is <span class='notice'> OK.</span>",1)
if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit))
H.play_xylophone()
else if (on_fire)
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if (M.on_fire)
M.visible_message("<span class='warning'>[M] tries to pat out [src]'s flames, but to no avail!</span>",
"<span class='warning'>You try to pat out [src]'s flames, but to no avail! Put yourself out first!</span>")
else
M.visible_message("<span class='warning'>[M] tries to pat out [src]'s flames!</span>",
"<span class='warning'>You try to pat out [src]'s flames! Hot!</span>")
if(do_mob(M, src, 15))
src.adjust_fire_stacks(-0.5)
if (prob(10) && (M.fire_stacks <= 0))
M.adjust_fire_stacks(1)
M.IgniteMob()
if (M.on_fire)
M.visible_message("<span class='danger'>The fire spreads from [src] to [M]!</span>",
"<span class='danger'>The fire spreads to you as well!</span>")
else
src.adjust_fire_stacks(-0.5) //Less effective than stop, drop, and roll - also accounting for the fact that it takes half as long.
if (src.fire_stacks <= 0)
M.visible_message("<span class='warning'>[M] successfully pats out [src]'s flames.</span>",
"<span class='warning'>You successfully pat out [src]'s flames.</span>")
src.ExtinguishMob()
src.fire_stacks = 0
else
if (istype(src,/mob/living/carbon/human) && src:w_uniform)
var/mob/living/carbon/human/H = src
H.w_uniform.add_fingerprint(M)
var/show_ssd
var/mob/living/carbon/human/H = src
var/datum/gender/T = gender_datums[H.get_visible_gender()] // make sure to cast to human before using get_gender() or get_visible_gender()!
if(istype(H)) show_ssd = H.species.show_ssd
if(show_ssd && !client && !teleop)
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [T.him] up!</span>", \
"<span class='notice'>You shake [src], but [T.he] [T.does] not respond... Maybe [T.he] [T.has] S.S.D?</span>")
else if(lying || src.sleeping)
src.sleeping = max(0,src.sleeping-5)
if(src.sleeping == 0)
src.resting = 0
if(H) H.in_stasis = 0 //VOREStation Add - Just In Case
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [T.him] up!</span>", \
"<span class='notice'>You shake [src] trying to wake [T.him] up!</span>")
else
var/mob/living/carbon/human/hugger = M
var/datum/gender/TM = gender_datums[M.get_visible_gender()]
if(M.resting == 1) //Are they resting on the ground?
M.visible_message("<span class='notice'>[M] grabs onto [src] and pulls [TM.himself] up</span>", \
"<span class='notice'>You grip onto [src] and pull yourself up off the ground!</span>")
if(M.fire_stacks >= (src.fire_stacks + 3)) //Fire checks.
src.adjust_fire_stacks(1)
M.adjust_fire_stacks(-1)
if(M.on_fire)
src.IgniteMob()
if(do_after(M, 0.5 SECONDS)) //.5 second delay. Makes it a bit stronger than just typing rest.
M.resting = 0 //Hoist yourself up up off the ground. No para/stunned/weakened removal.
else if(istype(hugger))
hugger.species.hug(hugger,src)
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [T.him] feel better!</span>", \
"<span class='notice'>You hug [src] to make [T.him] feel better!</span>")
if(M.fire_stacks >= (src.fire_stacks + 3))
src.adjust_fire_stacks(1)
M.adjust_fire_stacks(-1)
if(M.on_fire)
src.IgniteMob()
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustWeakened(-3)
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/carbon/proc/eyecheck()
return 0
/mob/living/carbon/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash)
if(eyecheck() < intensity || override_blindness_check)
return ..()
// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching.
// Stop! ... Hammertime! ~Carn
/mob/living/carbon/proc/getDNA()
return dna
/mob/living/carbon/proc/setDNA(var/datum/dna/newDNA)
dna = newDNA
// ++++ROCKDTBEN++++ MOB PROCS //END
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
var/temp_inc = max(min(BODYTEMP_HEATING_MAX*(1-get_heat_protection()), exposed_temperature - bodytemperature), 0)
bodytemperature += temp_inc
/mob/living/carbon/can_use_hands()
if(handcuffed)
return 0
if(buckled && istype(buckled, /obj/structure/bed/nest)) // buckling does not restrict hands
return 0
return 1
/mob/living/carbon/restrained()
if (handcuffed)
return 1
return
/mob/living/carbon/u_equip(obj/item/W as obj)
if(!W) return 0
else if (W == handcuffed)
handcuffed = null
update_handcuffed()
if(buckled && buckled.buckle_require_restraints)
buckled.unbuckle_mob()
else if (W == legcuffed)
legcuffed = null
update_inv_legcuffed()
else
..()
//generates realistic-ish pulse output based on preset levels
/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate
var/temp = 0 //see setup.dm:694
switch(src.pulse)
if(PULSE_NONE)
return "0"
if(PULSE_SLOW)
temp = rand(40, 60)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_NORM)
temp = rand(60, 90)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_FAST)
temp = rand(90, 120)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_2FAST)
temp = rand(120, 160)
return num2text(method ? temp : temp + rand(-10, 10))
if(PULSE_THREADY)
return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread"
// output for machines^ ^^^^^^^output for people^^^^^^^^^
/mob/living/carbon/verb/mob_sleep()
set name = "Sleep"
set category = "IC"
if(usr.sleeping)
to_chat(usr, "<font color='red'>You are already sleeping</font>")
return
if(alert(src,"You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes")
usr.sleeping = 20 //Short nap
/mob/living/carbon/Bump(atom/A)
if(now_pushing)
return
..()
if(istype(A, /mob/living/carbon) && prob(10))
spread_disease_to(A, "Contact")
/mob/living/carbon/cannot_use_vents()
return
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
if(buckled)
return 0
stop_pulling()
to_chat(src, "<span class='warning'>You slipped on [slipped_on]!</span>")
playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
Weaken(FLOOR(stun_duration/2, 1))
return 1
/mob/living/carbon/proc/add_chemical_effect(var/effect, var/magnitude = 1)
if(effect in chem_effects)
chem_effects[effect] += magnitude
else
chem_effects[effect] = magnitude
/mob/living/carbon/get_default_language()
if(default_language)
if(can_speak(default_language))
return default_language
else
return GLOB.all_languages[LANGUAGE_GIBBERISH]
if(!species)
return GLOB.all_languages[LANGUAGE_GIBBERISH]
return species.default_language ? GLOB.all_languages[species.default_language] : GLOB.all_languages[LANGUAGE_GIBBERISH]
/mob/living/carbon/proc/should_have_organ(var/organ_check)
return 0
/mob/living/carbon/can_feel_pain(var/check_organ)
if(isSynthetic())
return 0
return !(species.flags & NO_PAIN)
/mob/living/carbon/needs_to_breathe()
if(does_not_breathe)
return FALSE
return ..()
/mob/living/carbon/proc/update_handcuffed()
if(handcuffed)
drop_l_hand()
drop_r_hand()
stop_pulling()
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = handcuffed)
else
clear_alert("handcuffed")
update_action_buttons() //some of our action buttons might be unusable when we're handcuffed.
update_inv_handcuffed()

View File

@@ -1652,6 +1652,11 @@
msg += get_display_species()
return msg
/mob/living/carbon/human/reduce_cuff_time()
if(istype(gloves, /obj/item/clothing/gloves/gauntlets/rig))
return 2
return ..()
/mob/living/carbon/human/pull_damage()
if(((health - halloss) <= config.health_threshold_softcrit))
for(var/name in organs_by_name)

View File

@@ -1229,12 +1229,14 @@
fat_alert = /obj/screen/alert/fat/synth
hungry_alert = /obj/screen/alert/hungry/synth
starving_alert = /obj/screen/alert/starving/synth
//VOREStation Add - Vampire hunger alert
else if(get_species() == SPECIES_CUSTOM)
var/datum/species/custom/C = species
if(/datum/trait/bloodsucker in C.traits)
fat_alert = /obj/screen/alert/fat/vampire
hungry_alert = /obj/screen/alert/hungry/vampire
starving_alert = /obj/screen/alert/starving/vampire
//VOREStation Add End
switch(nutrition)
if(450 to INFINITY)

View File

@@ -158,6 +158,8 @@
healths.screen_loc = ui_health
hud_elements |= healths
pain = new /obj/screen( null )
zone_sel = new /obj/screen/zone_sel( null )

View File

@@ -1383,5 +1383,5 @@ Note that amputating the affected organ does in fact remove the infection from t
. = 0
for(var/obj/item/organ/external/L in organs)
for(var/obj/item/I in L.implants)
if(!istype(I,/obj/item/weapon/implant) && !istype(I,/obj/item/device/nif))
if(!istype(I,/obj/item/weapon/implant) && !istype(I,/obj/item/device/nif)) //VOREStation Add - NIFs
return 1