mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-23 18:16:46 +01:00
186 lines
5.4 KiB
Plaintext
186 lines
5.4 KiB
Plaintext
/mob/living/update_mobility(blocked, forced)
|
|
// this proc looks mildly heretical and pyramid of doomy
|
|
// for micro-optimization purposes.
|
|
if(!IS_CONSCIOUS(src))
|
|
blocked |= MOBILITY_FLAGS_REAL | MOBILITY_IS_CONSCIOUS
|
|
else
|
|
if(restrained())
|
|
blocked |= MOBILITY_CAN_USE | MOBILITY_CAN_PICKUP | MOBILITY_CAN_HOLD | MOBILITY_CAN_PULL | MOBILITY_CAN_STORAGE | MOBILITY_CAN_UI
|
|
if(pulledby || buckled)
|
|
blocked |= MOBILITY_CAN_MOVE
|
|
for(var/obj/item/grab/G as anything in grabbed_by)
|
|
if(G.state >= GRAB_AGGRESSIVE)
|
|
blocked |= MOBILITY_CAN_MOVE | MOBILITY_CAN_USE | MOBILITY_CAN_HOLD | MOBILITY_CAN_PICKUP | MOBILITY_CAN_STORAGE | MOBILITY_CAN_UI
|
|
if(resting)
|
|
blocked |= MOBILITY_IS_STANDING
|
|
|
|
. = ..()
|
|
|
|
if(!(mobility_flags & MOBILITY_CAN_HOLD))
|
|
drop_held_items()
|
|
if(!(mobility_flags & MOBILITY_CAN_PULL))
|
|
stop_pulling()
|
|
if(!(mobility_flags & MOBILITY_CAN_STAND))
|
|
set_resting(TRUE)
|
|
else if(resting)
|
|
auto_resist_rest()
|
|
|
|
/**
|
|
* immediately sets whether or not we're prone.
|
|
* does not check mobility flags.
|
|
* does not set other mobility flags or update mobility.
|
|
*/
|
|
/mob/living/proc/set_resting(value)
|
|
if(HAS_TRAIT(src, TRAIT_MOB_FORCED_STANDING))
|
|
value = FALSE
|
|
if(resting == value)
|
|
return
|
|
resting = value
|
|
if(resting)
|
|
add_movespeed_modifier(/datum/movespeed_modifier/mob_crawling)
|
|
else
|
|
remove_movespeed_modifier(/datum/movespeed_modifier/mob_crawling)
|
|
set_density(!resting)
|
|
if(value)
|
|
mobility_flags &= ~(MOBILITY_IS_STANDING)
|
|
else
|
|
mobility_flags |= MOBILITY_IS_STANDING
|
|
SEND_SIGNAL(src, COMSIG_MOB_ON_SET_RESTING, value)
|
|
update_lying()
|
|
update_water()
|
|
|
|
/**
|
|
* immediately toggles resting
|
|
* does not check, or update mobility flags.
|
|
*/
|
|
/mob/living/proc/toggle_resting()
|
|
set_resting(!resting)
|
|
|
|
/**
|
|
* starts to resist up from a resting state
|
|
*
|
|
* @return TRUE / FALSE based on if we started a new resist operation.
|
|
*/
|
|
/mob/living/proc/resist_a_rest(instant = FALSE)
|
|
if(!resting) // already up
|
|
return FALSE
|
|
if(!CHECK_MOBILITY(src, MOBILITY_CAN_STAND))
|
|
return FALSE // nah
|
|
if(getting_up)
|
|
return FALSE // already doing so
|
|
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob/living, _resist_a_rest), instant)
|
|
return TRUE
|
|
|
|
/mob/living/proc/_resist_a_rest(instant)
|
|
PRIVATE_PROC(TRUE)
|
|
getting_up = TRUE
|
|
getting_up_loc = loc
|
|
getting_up_penalized = world.time
|
|
getting_up_original = get_up_delay()
|
|
if(isturf(loc) && !instant)
|
|
visible_message(
|
|
SPAN_NOTICE("[src] starts to get up off the ground."),
|
|
SPAN_NOTICE("You start pushing yourself off the ground."),
|
|
)
|
|
else
|
|
innate_feedback(SPAN_NOTICE("You start pushing yourself off the ground."))
|
|
if(instant || do_self(src, getting_up_original, flags = DO_AFTER_IGNORE_ACTIVE_ITEM | DO_AFTER_IGNORE_MOVEMENT, mobility_flags = MOBILITY_CAN_RESIST, additional_checks = CALLBACK(src, PROC_REF(_resisting_a_rest))))
|
|
if(isturf(loc))
|
|
visible_message(
|
|
SPAN_NOTICE("[src] gets up from the ground."),
|
|
SPAN_NOTICE("You get up."),
|
|
)
|
|
else
|
|
innate_feedback(SPAN_NOTICE("You get up."))
|
|
set_resting(FALSE)
|
|
else
|
|
if(isturf(loc))
|
|
visible_message(
|
|
SPAN_NOTICE("[src] falls back down."),
|
|
SPAN_NOTICE("You fall back down."),
|
|
)
|
|
else
|
|
innate_feedback(SPAN_NOTICE("You get up."))
|
|
getting_up = FALSE
|
|
getting_up_loc = null
|
|
|
|
/mob/living/proc/get_up_delay()
|
|
// todo: redo
|
|
return 5 + (1 - clamp(health / getMaxHealth(), 0, 1)) * 33 + min(halloss, 100) * 0.33
|
|
|
|
#define PENALIZE_FACTOR 0.5
|
|
|
|
/mob/living/proc/_resisting_a_rest(list/do_after_args)
|
|
var/current_delay = get_up_delay()
|
|
if(current_delay != getting_up_original)
|
|
do_after_args[DO_AFTER_ARG_DELAY] += current_delay - getting_up_original
|
|
getting_up_original = current_delay
|
|
if(getting_up_loc != loc)
|
|
var/penalizing = world.time - getting_up_penalized
|
|
getting_up_penalized = world.time
|
|
getting_up_loc = loc
|
|
// penalize up to 1.5 seconds retroactively
|
|
do_after_args[DO_AFTER_ARG_DELAY] += min(1.5 SECONDS, penalizing) * PENALIZE_FACTOR
|
|
return TRUE
|
|
|
|
#undef PENALIZE_FACTOR
|
|
|
|
/mob/living/proc/auto_resist_rest()
|
|
if(resting_intentionally || !resting)
|
|
return
|
|
if(!CHECK_MOBILITY(src, MOBILITY_CAN_STAND))
|
|
return
|
|
resist_a_rest()
|
|
|
|
/mob/living/proc/set_intentionally_resting(value, instant)
|
|
resting_intentionally = value
|
|
if(resting_intentionally && !resting)
|
|
set_resting(TRUE)
|
|
else if(!resting_intentionally && resting)
|
|
resist_a_rest(instant)
|
|
|
|
/mob/living/proc/toggle_intentionally_resting(instant)
|
|
set_intentionally_resting(!resting_intentionally, instant)
|
|
|
|
/**
|
|
* sets our lying value to the correct value,
|
|
* updates icons if necessary,
|
|
* and updates mobility if necessary.
|
|
*/
|
|
/mob/living/proc/update_lying()
|
|
var/wanted = 0
|
|
// check if we're standing
|
|
if(IS_PRONE(src))
|
|
// fall onto side if not already down
|
|
if(!lying)
|
|
switch(dir)
|
|
if(NORTH, SOUTH)
|
|
wanted = pick(90, -90)
|
|
if(EAST)
|
|
wanted = 90
|
|
if(WEST)
|
|
wanted = -90
|
|
else
|
|
wanted = lying
|
|
// allow buckled override
|
|
var/overriding = buckled?.buckle_lying(src)
|
|
if(!isnull(overriding))
|
|
wanted = overriding
|
|
// check if we need to update
|
|
if(wanted == lying)
|
|
return
|
|
var/old = lying
|
|
lying = wanted
|
|
SEND_SIGNAL(src, COMSIG_MOB_ON_UPDATE_LYING, old, lying)
|
|
update_transform()
|
|
|
|
/mob/proc/cannot_stand()
|
|
return incapacitated(INCAPACITATION_KNOCKDOWN)
|
|
|
|
/mob/living/verb/lay_down()
|
|
set name = "Rest"
|
|
set category = VERB_CATEGORY_IC
|
|
|
|
to_chat(src, "<span class='notice'>You are now [resting_intentionally ? "attempting to stay upright." : "resting intentionally."]</span>")
|
|
toggle_intentionally_resting()
|