Mobility refactor: UI, pull and lying down edition (#54078)

This commit is contained in:
Rohesie
2020-10-03 17:23:21 -07:00
committed by GitHub
parent 2b53da383b
commit db54913fe6
18 changed files with 285 additions and 119 deletions
+3
View File
@@ -515,3 +515,6 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE)))
#define ANON_DISABLED "" //so it's falsey
#define ANON_RANDOMNAMES "Random Default"
#define ANON_EMPLOYEENAMES "Employees"
/// Possible value of [/atom/movable/buckle_lying]. If set to a different (positive-or-zero) value than this, the buckling thing will force a lying angle on the buckled.
#define NO_BUCKLE_LYING -1
+4
View File
@@ -209,6 +209,10 @@
#define SENTIENCE_BOSS 5
//Mob AI Status
#define POWER_RESTORATION_OFF 0
#define POWER_RESTORATION_START 1
#define POWER_RESTORATION_SEARCH_APC 2
#define POWER_RESTORATION_APC_FOUND 3
//Hostile simple animals
//If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm
+8
View File
@@ -81,6 +81,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_FLOORED "floored" //Prevents standing or staying up on its own.
/// Prevents usage of manipulation appendages (picking, holding or using items, manipulating storage).
#define TRAIT_HANDS_BLOCKED "handsblocked"
/// Inability to access UI hud elements. Turned into a trait from [MOBILITY_UI] to be able to track sources.
#define TRAIT_UI_BLOCKED "uiblocked"
/// Inability to pull things. Turned into a trait from [MOBILITY_PULL] to be able to track sources.
#define TRAIT_PULL_BLOCKED "pullblocked"
/// Abstract condition that prevents movement if being pulled and might be resisted against. Handcuffs and straight jackets, basically.
#define TRAIT_RESTRAINED "restrained"
#define TRAIT_INCAPACITATED "incapacitated"
@@ -292,6 +296,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define MAPPING_HELPER_TRAIT "mapping-helper" //obtained from mapping helper
/// Trait associated to wearing a suit
#define SUIT_TRAIT "suit"
/// Trait associated to lying down (having a [lying_angle] of a different value than zero).
#define LYING_DOWN_TRAIT "lying-down"
/// Trait associated to lacking electrical power.
#define POWER_LACK_TRAIT "power-lack"
// unique trait sources, still defines
#define CLONING_POD_TRAIT "cloning-pod"
+2
View File
@@ -230,6 +230,7 @@
if(!.)
return
ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
owner.update_mobility()
/datum/status_effect/grouped/stasis/tick()
@@ -237,6 +238,7 @@
/datum/status_effect/grouped/stasis/on_remove()
REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id))
owner.update_mobility()
update_time_of_death()
return ..()
+2 -1
View File
@@ -1,6 +1,7 @@
/atom/movable
var/can_buckle = FALSE
var/buckle_lying = -1 //bed-like behaviour, forces mob.lying = buckle_lying if != -1
/// Bed-like behaviour, forces mob.lying = buckle_lying if not set to [NO_BUCKLE_LYING].
var/buckle_lying = NO_BUCKLE_LYING
var/buckle_requires_restraints = FALSE //require people to be handcuffed before being able to buckle. eg: pipes
var/list/mob/living/buckled_mobs = null //list()
var/max_buckled_mobs = 1
@@ -9,7 +9,7 @@
anchored = FALSE
density = TRUE
max_integrity = 100
buckle_lying = FALSE
buckle_lying = 0
layer = ABOVE_MOB_LAYER
var/view_range = 2.5
var/cooldown = 0
+1 -1
View File
@@ -552,7 +552,7 @@
smoothing_groups = null
canSmoothWith = null
can_buckle = 1
buckle_lying = -1
buckle_lying = NO_BUCKLE_LYING
buckle_requires_restraints = TRUE
var/mob/living/carbon/human/patient = null
var/obj/machinery/computer/operating/computer = null
+1 -1
View File
@@ -7,7 +7,7 @@
flags_1 = CONDUCT_1
can_buckle = TRUE
max_buckled_mobs = 1
buckle_lying = FALSE
buckle_lying = 0
var/obj/item/target/pinned_target
/obj/structure/target_stake/Destroy()
@@ -2,7 +2,7 @@
var/minimum_temperature_difference = 20
var/thermal_conductivity = WINDOW_HEAT_TRANSFER_COEFFICIENT
color = "#404040"
buckle_lying = -1
buckle_lying = NO_BUCKLE_LYING
var/icon_temperature = T20C //stop small changes in temperature causing icon refresh
resistance_flags = LAVA_PROOF | FIRE_PROOF
@@ -12,7 +12,7 @@
//Buckling
can_buckle = TRUE
buckle_requires_restraints = TRUE
buckle_lying = -1
buckle_lying = NO_BUCKLE_LYING
/obj/machinery/atmospherics/pipe/New()
add_atom_colour(pipe_color, FIXED_COLOUR_PRIORITY)
+10 -7
View File
@@ -542,12 +542,17 @@
if(dna)
dna.real_name = real_name
/mob/living/carbon/update_mobility()
/mob/living/carbon/set_lying_angle(new_lying)
. = ..()
if(!(mobility_flags & MOBILITY_STAND))
add_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling)
else
remove_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling)
if(isnull(.))
return
switch(lying_angle)
if(90, 270)
add_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling)
else
remove_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling)
//Updates the mob's health from bodyparts and mob damage variables
/mob/living/carbon/updatehealth()
@@ -1281,7 +1286,5 @@
if(.)
if(!handcuffed)
REMOVE_TRAIT(src, TRAIT_RESTRAINED, HANDCUFFED_TRAIT)
REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, HANDCUFFED_TRAIT)
else if(handcuffed)
ADD_TRAIT(src, TRAIT_RESTRAINED, HANDCUFFED_TRAIT)
ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, HANDCUFFED_TRAIT)
@@ -64,11 +64,22 @@
. = ..()
if(isnull(.))
return
if(. & !(FLYING | FLOATING))
if(!(. & (FLYING | FLOATING)))
if(movement_type & (FLYING | FLOATING)) //From not flying to flying.
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
else if(!(movement_type & (FLYING | FLOATING)) && !usable_legs) //From flying to no longer flying.
ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
if(!usable_hands)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
else if(!(movement_type & (FLYING | FLOATING))) //From flying to no longer flying.
var/limbless_slowdown = 0
if(usable_legs < default_num_legs)
limbless_slowdown += (default_num_legs - usable_legs) * 3
if(!usable_legs)
ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
if(usable_hands < default_num_hands)
limbless_slowdown += (default_num_hands - usable_hands) * 3
if(!usable_hands)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
if(limbless_slowdown)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown)
else
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
@@ -149,7 +149,6 @@
update_inv_w_uniform()
if(wear_suit.breakouttime) //when equipping a straightjacket
ADD_TRAIT(src, TRAIT_RESTRAINED, SUIT_TRAIT)
ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, SUIT_TRAIT)
stop_pulling() //can't pull if restrained
update_action_buttons_icon() //certain action buttons will no longer be usable.
update_inv_wear_suit()
@@ -206,7 +205,6 @@
dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit.
if(wear_suit.breakouttime) //when unequipping a straightjacket
REMOVE_TRAIT(src, TRAIT_RESTRAINED, SUIT_TRAIT)
REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, SUIT_TRAIT)
drop_all_held_items() //suit is restraining
update_action_buttons_icon() //certain action buttons may be usable again.
wear_suit = null
+110 -11
View File
@@ -1,4 +1,4 @@
///Called on /mob/living/Initialize(), for the mob to register to relevant signals.
/// Called on [/mob/living/Initialize()], for the mob to register to relevant signals.
/mob/living/proc/register_init_signals()
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_KNOCKEDOUT), .proc/on_knockedout_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT), .proc/on_knockedout_trait_loss)
@@ -9,9 +9,24 @@
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_IMMOBILIZED), .proc/on_immobilized_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_IMMOBILIZED), .proc/on_immobilized_trait_loss)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_FLOORED), .proc/on_floored_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_FLOORED), .proc/on_floored_trait_loss)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), .proc/on_handsblocked_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_HANDS_BLOCKED), .proc/on_handsblocked_trait_loss)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_UI_BLOCKED), .proc/on_ui_blocked_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_UI_BLOCKED), .proc/on_ui_blocked_trait_loss)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_PULL_BLOCKED), .proc/on_pull_blocked_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_PULL_BLOCKED), .proc/on_pull_blocked_trait_loss)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_INCAPACITATED), .proc/on_incapacitated_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_INCAPACITATED), .proc/on_incapacitated_trait_loss)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_RESTRAINED), .proc/on_restrained_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_RESTRAINED), .proc/on_restrained_trait_loss)
RegisterSignal(src, list(
SIGNAL_ADDTRAIT(TRAIT_CRITICAL_CONDITION),
SIGNAL_REMOVETRAIT(TRAIT_CRITICAL_CONDITION),
@@ -21,48 +36,132 @@
), .proc/update_succumb_action)
///Called when TRAIT_KNOCKEDOUT is added to the mob.
/// Called when [TRAIT_KNOCKEDOUT] is added to the mob.
/mob/living/proc/on_knockedout_trait_gain(datum/source)
SIGNAL_HANDLER
if(stat < UNCONSCIOUS)
set_stat(UNCONSCIOUS)
///Called when TRAIT_KNOCKEDOUT is removed from the mob.
/// Called when [TRAIT_KNOCKEDOUT] is removed from the mob.
/mob/living/proc/on_knockedout_trait_loss(datum/source)
SIGNAL_HANDLER
if(stat <= UNCONSCIOUS)
update_stat()
///Called when TRAIT_DEATHCOMA is added to the mob.
/// Called when [TRAIT_DEATHCOMA] is added to the mob.
/mob/living/proc/on_deathcoma_trait_gain(datum/source)
SIGNAL_HANDLER
ADD_TRAIT(src, TRAIT_KNOCKEDOUT, TRAIT_DEATHCOMA)
///Called when TRAIT_DEATHCOMA is removed from the mob.
/// Called when [TRAIT_DEATHCOMA] is removed from the mob.
/mob/living/proc/on_deathcoma_trait_loss(datum/source)
SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, TRAIT_DEATHCOMA)
///Called when TRAIT_IMMOBILIZED is added to the mob.
/// Called when [TRAIT_IMMOBILIZED] is added to the mob.
/mob/living/proc/on_immobilized_trait_gain(datum/source)
SIGNAL_HANDLER
mobility_flags &= ~MOBILITY_MOVE
///Called when TRAIT_IMMOBILIZED is removed from the mob.
/// Called when [TRAIT_IMMOBILIZED] is removed from the mob.
/mob/living/proc/on_immobilized_trait_loss(datum/source)
SIGNAL_HANDLER
mobility_flags |= MOBILITY_MOVE
///Called when TRAIT_HANDS_BLOCKED is added to the mob.
/// Called when [TRAIT_FLOORED] is added to the mob.
/mob/living/proc/on_floored_trait_gain(datum/source)
SIGNAL_HANDLER
if(buckled && buckled.buckle_lying != NO_BUCKLE_LYING)
return // Handled by the buckle.
mobility_flags &= ~MOBILITY_STAND
if(lying_angle == 0) //force them on the ground
set_lying_angle(pick(90, 270))
on_fall()
/// Called when [TRAIT_FLOORED] is removed from the mob.
/mob/living/proc/on_floored_trait_loss(datum/source)
SIGNAL_HANDLER
mobility_flags |= MOBILITY_STAND
if(!resting)
get_up()
/// Called when [TRAIT_HANDS_BLOCKED] is added to the mob.
/mob/living/proc/on_handsblocked_trait_gain(datum/source)
SIGNAL_HANDLER
mobility_flags &= ~(MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_STORAGE)
drop_all_held_items()
ADD_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_HANDS_BLOCKED)
ADD_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED)
///Called when TRAIT_HANDS_BLOCKED is removed from the mob.
/// Called when [TRAIT_HANDS_BLOCKED] is removed from the mob.
/mob/living/proc/on_handsblocked_trait_loss(datum/source)
SIGNAL_HANDLER
mobility_flags |= (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_STORAGE)
REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_HANDS_BLOCKED)
REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED)
/// Called when traits that alter succumbing are added/removed.
/// Will show or hide the succumb alert prompt.
/// Called when [TRAIT_UI_BLOCKED] is added to the mob.
/mob/living/proc/on_ui_blocked_trait_gain(datum/source)
SIGNAL_HANDLER
mobility_flags &= ~(MOBILITY_UI)
unset_machine()
/// Called when [TRAIT_UI_BLOCKED] is removed from the mob.
/mob/living/proc/on_ui_blocked_trait_loss(datum/source)
SIGNAL_HANDLER
mobility_flags |= MOBILITY_UI
/// Called when [TRAIT_PULL_BLOCKED] is added to the mob.
/mob/living/proc/on_pull_blocked_trait_gain(datum/source)
SIGNAL_HANDLER
mobility_flags &= ~(MOBILITY_PULL)
if(pulling)
stop_pulling()
/// Called when [TRAIT_PULL_BLOCKED] is removed from the mob.
/mob/living/proc/on_pull_blocked_trait_loss(datum/source)
SIGNAL_HANDLER
mobility_flags |= MOBILITY_PULL
/// Called when [TRAIT_INCAPACITATED] is added to the mob.
/mob/living/proc/on_incapacitated_trait_gain(datum/source)
SIGNAL_HANDLER
ADD_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_INCAPACITATED)
ADD_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_INCAPACITATED)
/// Called when [TRAIT_INCAPACITATED] is removed from the mob.
/mob/living/proc/on_incapacitated_trait_loss(datum/source)
SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_INCAPACITATED)
REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_INCAPACITATED)
/// Called when [TRAIT_RESTRAINED] is added to the mob.
/mob/living/proc/on_restrained_trait_gain(datum/source)
SIGNAL_HANDLER
ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_RESTRAINED)
/// Called when [TRAIT_RESTRAINED] is removed from the mob.
/mob/living/proc/on_restrained_trait_loss(datum/source)
SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_RESTRAINED)
/**
* Called when traits that alter succumbing are added/removed.
*
* Will show or hide the succumb alert prompt.
*/
/mob/living/proc/update_succumb_action()
SIGNAL_HANDLER
if (CAN_SUCCUMB(src))
throw_alert("succumb", /obj/screen/alert/succumb)
else
+102 -67
View File
@@ -385,7 +385,7 @@
death()
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_stasis = FALSE)
if(stat || HAS_TRAIT(src, TRAIT_INCAPACITATED) || (!ignore_restraints && (HAS_TRAIT(src, TRAIT_RESTRAINED) || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))) || (!ignore_stasis && IS_IN_STASIS(src)))
if(HAS_TRAIT(src, TRAIT_INCAPACITATED) || (!ignore_restraints && (HAS_TRAIT(src, TRAIT_RESTRAINED) || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))) || (!ignore_stasis && IS_IN_STASIS(src)))
return TRUE
/mob/living/canUseStorage()
@@ -427,30 +427,43 @@
/mob/proc/get_contents()
/mob/living/proc/lay_down()
set name = "Rest"
set category = "IC"
if(!resting)
set_resting(TRUE, FALSE)
else
if(do_after(src, 10, target = src))
set_resting(FALSE, FALSE)
else
to_chat(src, "<span class='warning'>You fail to get up!</span>")
set_resting(!resting, FALSE)
///Proc to hook behavior to the change of value in the resting variable.
/mob/living/proc/set_resting(rest, silent = TRUE)
if(rest == resting)
/mob/living/proc/set_resting(new_resting, silent = TRUE)
if(new_resting == resting)
return
if(!silent)
if(rest)
to_chat(src, "<span class='notice'>You are now resting.</span>")
. = resting
resting = new_resting
if(new_resting)
if(lying_angle == 90 || lying_angle == 270)
if(!silent)
to_chat(src, "<span class='notice'>You will now try to stay lying down on the floor.</span>")
else if(buckled && buckled.buckle_lying != NO_BUCKLE_LYING)
if(!silent)
to_chat(src, "<span class='notice'>You will now lay down as soon as you are able to.</span>")
else
to_chat(src, "<span class='notice'>You get up.</span>")
. = rest
resting = rest
if(!silent)
to_chat(src, "<span class='notice'>You lay down.</span>")
set_lying_down()
else
if(lying_angle == 0)
if(!silent)
to_chat(src, "<span class='notice'>You will now try to remain standing up.</span>")
else if(HAS_TRAIT(src, TRAIT_FLOORED) || (buckled && buckled.buckle_lying != NO_BUCKLE_LYING))
if(!silent)
to_chat(src, "<span class='notice'>You will now stand up as soon as you are able to.</span>")
else
if(!silent)
to_chat(src, "<span class='notice'>You stand up.</span>")
get_up()
update_resting()
@@ -459,6 +472,31 @@
update_mobility()
/mob/living/proc/get_up()
set waitfor = FALSE
var/static/datum/callback/rest_checks = CALLBACK(src, .proc/rest_checks_callback)
if(!do_mob(src, src, 2 SECONDS, uninterruptible = TRUE, extra_checks = rest_checks))
return
if(resting || lying_angle == 0 || HAS_TRAIT(src, TRAIT_FLOORED))
return
set_lying_angle(0)
/mob/living/proc/rest_checks_callback()
if(resting || lying_angle == 0 || HAS_TRAIT(src, TRAIT_FLOORED))
return FALSE
return TRUE
/mob/living/proc/set_lying_down(new_lying_angle)
if(buckled && buckled.buckle_lying == 0)
return
if(!new_lying_angle)
set_lying_angle(pick(90, 270))
else
set_lying_angle(new_lying_angle)
//Recursive function to find everything a mob is holding. Really shitty proc tbh.
/mob/living/get_contents()
var/list/ret = list()
@@ -1177,53 +1215,9 @@
return ..() && !(buckled && buckled.buckle_prevents_pull)
//Updates lying and icons. Could perhaps do with a rename but I can't think of anything to describe it.
//Robots, animals and brains have their own version so don't worry about them
//Updates lying and icons on robots, animals and brains. Needs to be refactored to use traits and update based on events.
/mob/living/proc/update_mobility()
var/canstand_involuntary = !HAS_TRAIT(src, TRAIT_FLOORED)
var/canstand = canstand_involuntary && !resting
if(buckled && buckled.buckle_lying != -1)
if(buckled.buckle_lying != 0)
mobility_flags &= ~MOBILITY_STAND
else
mobility_flags |= MOBILITY_STAND
set_lying_angle(buckled.buckle_lying)
else if(!canstand)
mobility_flags &= ~MOBILITY_STAND
if(lying_angle == 0) //force them on the ground
set_lying_angle(pick(90, 270))
if(!canstand_involuntary)
on_fall()
else
mobility_flags |= MOBILITY_STAND
set_lying_angle(0)
if(lying_angle != 0 || HAS_TRAIT(src, TRAIT_HANDS_BLOCKED) || incapacitated())
mobility_flags &= ~(MOBILITY_UI|MOBILITY_PULL)
else
mobility_flags |= MOBILITY_UI|MOBILITY_PULL
if(!(mobility_flags & MOBILITY_PULL))
if(pulling)
stop_pulling()
if(!(mobility_flags & MOBILITY_UI))
unset_machine()
// Movespeed mods based on arms/legs quantity
if(movement_type & (FLYING | FLOATING))
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
else
var/limbless_slowdown = 0
// These checks for <2 should be swapped out for something else if we ever end up with a species with more than 2
if(usable_legs < default_num_legs)
limbless_slowdown += (default_num_legs * 3) - (usable_legs * 3)
if(!usable_legs && usable_hands < default_num_hands)
limbless_slowdown += (default_num_hands * 3) - (usable_hands * 3)
if(limbless_slowdown)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown)
else
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
return
///Called when mob changes from a standing position into a prone while lacking the ability to stand up at the moment, through update_mobility()
@@ -1437,13 +1431,19 @@
if(lying_angle != 0) //We are not standing up.
if(layer == initial(layer)) //to avoid things like hiding larvas.
layer = LYING_MOB_LAYER //so mob lying always appear behind standing mobs
if(. == 0) //We became prone and were not before. We lose density and stop bumping passable dense things.
density = FALSE
if(. == 0) // We became prone and were not before.
ADD_TRAIT(src, TRAIT_UI_BLOCKED, LYING_DOWN_TRAIT)
ADD_TRAIT(src, TRAIT_PULL_BLOCKED, LYING_DOWN_TRAIT)
density = FALSE // We lose density and stop bumping passable dense things.
if(HAS_TRAIT(src, TRAIT_FLOORED) && !(dir & (NORTH|SOUTH)))
setDir(pick(NORTH, SOUTH)) // We are and look helpless.
else //We are prone.
if(layer == LYING_MOB_LAYER)
layer = initial(layer)
if(.) //We were prone before, so we become dense and things can bump into us again.
density = initial(density)
REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, LYING_DOWN_TRAIT)
REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, LYING_DOWN_TRAIT)
/**
@@ -1601,6 +1601,7 @@
switch(.) //Previous stat.
if(CONSCIOUS)
if(stat >= UNCONSCIOUS)
ADD_TRAIT(src, TRAIT_INCAPACITATED, TRAIT_KNOCKEDOUT)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_KNOCKEDOUT)
ADD_TRAIT(src, TRAIT_FLOORED, UNCONSCIOUS_TRAIT)
@@ -1619,6 +1620,7 @@
switch(stat) //Current stat.
if(CONSCIOUS)
if(. >= UNCONSCIOUS)
REMOVE_TRAIT(src, TRAIT_INCAPACITATED, TRAIT_KNOCKEDOUT)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_KNOCKEDOUT)
REMOVE_TRAIT(src, TRAIT_FLOORED, UNCONSCIOUS_TRAIT)
@@ -1655,11 +1657,21 @@
if(buckled)
if(!.)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT)
if(buckled.buckle_lying)
ADD_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT)
else if(.)
switch(buckled.buckle_lying)
if(NO_BUCKLE_LYING) // The buckle doesn't force a lying angle.
REMOVE_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT)
return
if(0) // Forcing to a standing position.
REMOVE_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT)
else // Forcing to a lying position.
ADD_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT)
set_lying_angle(buckled.buckle_lying)
else if(.) // We unbuckled from something.
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT)
REMOVE_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT)
var/atom/movable/old_buckled = .
if(old_buckled.buckle_lying == 0 && resting) // The buckle forced us to stay up (like a chair) and our preference is set to resting...
set_lying_down() // ...so let's drop on the ground.
/mob/living/set_pulledby(new_pulledby)
@@ -1707,6 +1719,23 @@
. = usable_legs
usable_legs = new_value
if(new_value > .) // Gained leg usage.
REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
else if(!(movement_type & (FLYING | FLOATING))) //Lost leg usage, not flying.
if(!usable_legs)
ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
if(!usable_hands)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
if(usable_legs < default_num_legs)
var/limbless_slowdown = (default_num_legs - usable_legs) * 3
if(!usable_legs && usable_hands < default_num_hands)
limbless_slowdown += (default_num_hands - usable_hands) * 3
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown)
else
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
///Proc to modify the value of num_hands and hook behavior associated to this event.
/mob/living/proc/set_num_hands(new_value)
@@ -1723,6 +1752,12 @@
. = usable_hands
usable_hands = new_value
if(new_value > .) // Gained hand usage.
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
else if(!(movement_type & (FLYING | FLOATING)) && !usable_hands && !usable_legs) //Lost a hand, not flying, no hands left, no legs.
ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
/// Whether or not this mob will escape from storages while being picked up/held.
/mob/living/proc/will_escape_storage()
return FALSE
+17 -5
View File
@@ -34,7 +34,7 @@
var/list/network = list("ss13")
var/obj/machinery/camera/current
var/list/connected_robots = list()
var/aiRestorePowerRoutine = 0
var/aiRestorePowerRoutine = POWER_RESTORATION_OFF
var/requires_power = POWER_REQ_ALL
var/can_be_carded = TRUE
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
@@ -170,6 +170,9 @@
builtInCamera = new (src)
builtInCamera.network = list("ss13")
ADD_TRAIT(src, TRAIT_PULL_BLOCKED, ROUNDSTART_TRAIT)
/mob/living/silicon/ai/key_down(_key, client/user)
if(findtext(_key, "numpad")) //if it's a numpad number, we can convert it to just the number
_key = _key[7] //strings, lists, same thing really
@@ -798,10 +801,6 @@
/mob/living/silicon/ai/can_buckle()
return FALSE
/mob/living/silicon/ai/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_stasis = FALSE)
if(aiRestorePowerRoutine)
return TRUE
return ..()
/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
if(control_disabled || incapacitated())
@@ -1032,3 +1031,16 @@
/mob/living/silicon/ai/zMove(dir, feedback = FALSE)
. = eyeobj.zMove(dir, feedback)
/// Proc to hook behavior to the changes of the value of [aiRestorePowerRoutine].
/mob/living/silicon/ai/proc/setAiRestorePowerRoutine(new_value)
if(new_value == aiRestorePowerRoutine)
return
. = aiRestorePowerRoutine
aiRestorePowerRoutine = new_value
if(aiRestorePowerRoutine)
if(!.)
ADD_TRAIT(src, TRAIT_INCAPACITATED, POWER_LACK_TRAIT)
else if(.)
REMOVE_TRAIT(src, TRAIT_INCAPACITATED, POWER_LACK_TRAIT)
+5 -15
View File
@@ -1,8 +1,3 @@
#define POWER_RESTORATION_OFF 0
#define POWER_RESTORATION_START 1
#define POWER_RESTORATION_SEARCH_APC 2
#define POWER_RESTORATION_APC_FOUND 3
/mob/living/silicon/ai/Life()
if (stat == DEAD)
return
@@ -110,7 +105,7 @@
T = get_turf(src)
if(isspaceturf(T))
to_chat(src, "<span class='alert'>Unable to verify! No power connection detected!</span>")
aiRestorePowerRoutine = POWER_RESTORATION_SEARCH_APC
setAiRestorePowerRoutine(POWER_RESTORATION_SEARCH_APC)
return
to_chat(src, "<span class='notice'>Connection verified. Searching for APC in power network.</span>")
sleep(50)
@@ -131,7 +126,7 @@
to_chat(src, "<span class='alert'>Unable to locate APC!</span>")
else
to_chat(src, "<span class='alert'>Lost connection with the APC!</span>")
aiRestorePowerRoutine = POWER_RESTORATION_SEARCH_APC
setAiRestorePowerRoutine(POWER_RESTORATION_SEARCH_APC)
return
if(AIarea.power_equip)
if(!isspaceturf(T))
@@ -152,7 +147,7 @@
apc_override = 1
theAPC.ui_interact(src)
apc_override = 0
aiRestorePowerRoutine = POWER_RESTORATION_APC_FOUND
setAiRestorePowerRoutine(POWER_RESTORATION_APC_FOUND)
sleep(50)
theAPC = null
@@ -162,19 +157,14 @@
to_chat(src, "<span class='notice'>Alert cancelled. Power has been restored.</span>")
else
to_chat(src, "<span class='notice'>Alert cancelled. Power has been restored without our assistance.</span>")
aiRestorePowerRoutine = POWER_RESTORATION_OFF
setAiRestorePowerRoutine(POWER_RESTORATION_OFF)
set_blindness(0)
update_sight()
/mob/living/silicon/ai/proc/ai_lose_power()
disconnect_shell()
aiRestorePowerRoutine = POWER_RESTORATION_START
setAiRestorePowerRoutine(POWER_RESTORATION_START)
blind_eyes(1)
update_sight()
to_chat(src, "<span class='alert'>You've lost power!</span>")
addtimer(CALLBACK(src, .proc/start_RestorePowerRoutine), 20)
#undef POWER_RESTORATION_OFF
#undef POWER_RESTORATION_START
#undef POWER_RESTORATION_SEARCH_APC
#undef POWER_RESTORATION_APC_FOUND
+1 -1
View File
@@ -375,7 +375,7 @@
icon_state_on = "protoemitter_+a"
icon_state_underpowered = "protoemitter_+u"
can_buckle = TRUE
buckle_lying = FALSE
buckle_lying = 0
var/view_range = 4.5
var/datum/action/innate/protoemitter/firing/auto