diff --git a/beestation.dme b/beestation.dme index 7d4ee725adf3c..c608a2fe02a0e 100644 --- a/beestation.dme +++ b/beestation.dme @@ -102,6 +102,7 @@ #include "code\__DEFINES\language.dm" #include "code\__DEFINES\layers.dm" #include "code\__DEFINES\lighting.dm" +#include "code\__DEFINES\living.dm" #include "code\__DEFINES\logging.dm" #include "code\__DEFINES\machines.dm" #include "code\__DEFINES\magic.dm" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm index 6cf54105127f3..66dd862db99d7 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_living.dm @@ -39,13 +39,20 @@ #define COMSIG_LIVING_HANDLE_BREATHING "living_handle_breathing" //ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! -#define COMSIG_LIVING_STATUS_STUN "living_stun" //! from base of mob/living/Stun() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //! from base of mob/living/Knockdown() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" //! from base of mob/living/Paralyze() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" //! from base of mob/living/Immobilize() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" //! from base of mob/living/Unconscious() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" //! from base of mob/living/Sleeping() (amount, update, ignore) - #define COMPONENT_NO_STUN 1 //For all of them + +///from base of mob/living/Stun() (amount, ignore_canstun) +#define COMSIG_LIVING_STATUS_STUN "living_stun" +///from base of mob/living/Knockdown() (amount, ignore_canstun) +#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" +///from base of mob/living/Paralyze() (amount, ignore_canstun) +#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" +///from base of mob/living/Immobilize() (amount, ignore_canstun) +#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" +///from base of mob/living/Unconscious() (amount, ignore_canstun) +#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" +///from base of mob/living/Sleeping() (amount, ignore_canstun) +#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" + #define COMPONENT_NO_STUN (1<<0) //For all of them #define COMSIG_LIVING_ENTER_STASIS "living_enter_stasis" //! sent when a mob is put into stasis. #define COMSIG_LIVING_EXIT_STASIS "living_exit_stasis" //! sent when a mob exits stasis. diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index f9aab906c789c..b849ed37652c6 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -177,7 +177,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define MOBILITY_PULL (1<<6) //! can pull things #define MOBILITY_FLAGS_DEFAULT (MOBILITY_MOVE | MOBILITY_STAND | MOBILITY_PICKUP | MOBILITY_USE | MOBILITY_UI | MOBILITY_STORAGE | MOBILITY_PULL) -#define MOBILITY_FLAGS_INTERACTION (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_UI | MOBILITY_STORAGE) // radiation #define RAD_PROTECT_CONTENTS (1<<0) diff --git a/code/__DEFINES/living.dm b/code/__DEFINES/living.dm new file mode 100644 index 0000000000000..1f2316e8e1240 --- /dev/null +++ b/code/__DEFINES/living.dm @@ -0,0 +1,3 @@ +// living_flags +/// Simple mob trait, indicating it may follow continuous move actions controlled by code instead of by user input. +#define MOVES_ON_ITS_OWN (1<<0) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index d76313c7d350f..be398a7d46e8e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -85,10 +85,6 @@ #define BODYTYPE_DIGITIGRADE (1<<4) //Cancer #define NUMBER_OF_BODYTYPES 5 //KEEP THIS UPDATED OR SHIT WILL BREAK -#define BODYPART_NOT_DISABLED 0 -#define BODYPART_DISABLED_DAMAGE 1 -#define BODYPART_DISABLED_PARALYSIS 2 - #define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi' #define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi' @@ -318,6 +314,10 @@ GLOBAL_LIST_INIT(available_random_trauma_list, list( #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 @@ -594,3 +594,12 @@ GLOBAL_LIST_INIT(available_random_trauma_list, list( /// Returns whether or not the given mob can succumb #define CAN_SUCCUMB(target) (HAS_TRAIT(target, TRAIT_CRITICAL_CONDITION) && !HAS_TRAIT(target, TRAIT_NODEATH)) + +/// 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 + +// Body position defines. +/// Mob is standing up, usually associated with lying_angle value of 0. +#define STANDING_UP 0 +/// Mob is lying down, usually associated with lying_angle values of 90 or 270. +#define LYING_DOWN 1 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 6e994b1668858..acc70f70fabcd 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -134,12 +134,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FORCED_STANDING "forcedstanding" /// Prevents usage of manipulation appendages (picking, holding or using items, manipulating storage). #define TRAIT_HANDS_BLOCKED "handsblocked" -/* All to replace update_mobility with traits /// 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" @@ -283,11 +281,13 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_MADNESS_IMMUNE "supermatter_madness_immune" //non-mob traits -//Used for limb-based paralysis, where replacing the limb will fix it +/// Used for limb-based paralysis, where replacing the limb will fix it. #define TRAIT_PARALYSIS "paralysis" +/// Used for limbs. +#define TRAIT_DISABLED_BY_WOUND "disabled-by-wound" ///Used for managing KEEP_TOGETHER in [appearance_flags] -#define TRAIT_KEEP_TOGETHER "keep-together" +#define TRAIT_KEEP_TOGETHER "keep-together" #define TRAIT_HEARING_SENSITIVE "hearing_sensitive" @@ -396,6 +396,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define STAT_TRAIT "stat" /// 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" #define GLASSES_TRAIT "glasses" #define CURSE_TRAIT "eldritch" #define STATION_TRAIT "station-trait" @@ -462,10 +466,21 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define BUSY_FLOORBOT_TRAIT "busy-floorbot" #define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit" #define LOCKED_BORG_TRAIT "locked-borg" +#define LACKING_LOCOMOTION_APPENDAGES_TRAIT "lacking-locomotion-appengades" //trait associated to not having locomotion appendages nor the ability to fly or float #define LACKING_MANIPULATION_APPENDAGES_TRAIT "lacking-manipulation-appengades" //trait associated to not having fine manipulation appendages such as hands #define HANDCUFFED_TRAIT "handcuffed" /// Trait granted by [/obj/item/warpwhistle] #define WARPWHISTLE_TRAIT "warpwhistle" +/// Trait applied by by [/datum/component/soulstoned] +#define SOULSTONE_TRAIT "soulstone" +/// Trait applied to slimes by low temperature +#define SLIME_COLD "slime-cold" +/// Trait applied to bots by being tipped over +#define BOT_TIPPED_OVER "bot-tipped-over" +/// Trait applied to PAIs by being folded +#define PAI_FOLDED "pai-folded" +/// Trait applied to brain mobs when they lack external aid for locomotion, such as being inside a mech. +#define BRAIN_UNAIDED "brain-unaided" #define TRAIT_PRESERVE_UI_WITHOUT_CLIENT "preserve_ui_without_client" //this mob should never close ui even if it doesn't have a client #define EXPERIMENTAL_SURGERY_TRAIT "experimental_surgery" #define NINJA_KIDNAPPED_TRAIT "ninja_kidnapped" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 17fd243d2adf0..3a763818771b6 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -489,6 +489,18 @@ GLOBAL_LIST_EMPTY(species_list) if(!HAS_TRAIT(L, TRAIT_PASSTABLE)) L.pass_flags &= ~PASSTABLE +/proc/dance_rotate(atom/movable/AM, datum/callback/callperrotate, set_original_dir=FALSE) + set waitfor = FALSE + var/originaldir = AM.dir + for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) + if(!AM) + return + AM.setDir(i) + callperrotate?.Invoke() + sleep(0.1 SECONDS) + if(set_original_dir) + AM.setDir(originaldir) + //Gets the sentient mobs that are not on centcom and are alive /proc/get_sentient_mobs() . = list() @@ -552,7 +564,7 @@ GLOBAL_LIST_EMPTY(species_list) /*This can be used to add additional effects on interactions between mobs depending on how the mobs are facing each other, such as adding a crit damage to blows to the back of a guy's head. Given how click code currently works (Nov '13), the initiating mob will be facing the target mob most of the time That said, this proc should not be used if the change facing proc of the click code is overridden at the same time*/ - if(!ismob(target) || !(target.mobility_flags & MOBILITY_STAND)) + if(!isliving(target) || target.body_position == LYING_DOWN) //Make sure we are not doing this for things that can't have a logical direction to the players given that the target would be on their side return FALSE if(initator.dir == target.dir) //mobs are facing the same direction diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 0b7dc05d69e64..6cd08e9b59b55 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -11,10 +11,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_INCAPACITATED" = TRAIT_INCAPACITATED, "TRAIT_FORCED_STANDING" = TRAIT_FORCED_STANDING, "TRAIT_HANDS_BLOCKED" = TRAIT_HANDS_BLOCKED, - /* "TRAIT_UI_BLOCKED" = TRAIT_UI_BLOCKED, "TRAIT_PULL_BLOCKED" = TRAIT_PULL_BLOCKED, - */ "TRAIT_RESTRAINED" = TRAIT_RESTRAINED, "TRAIT_BLIND" = TRAIT_BLIND, "TRAIT_MUTE" = TRAIT_MUTE, diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 80d5d5004d917..a693513d24988 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -23,8 +23,7 @@ /mob/living/changeNext_move(num) var/mod = next_move_modifier var/adj = next_move_adjust - for(var/i in status_effects) - var/datum/status_effect/S = i + for(var/datum/status_effect/S as anything in status_effects) mod *= S.nextmove_modifier() adj += S.nextmove_adjust() next_move = world.time + ((num + adj)*mod) @@ -41,6 +40,7 @@ /atom/Click(location,control,params) if(flags_1 & INITIALIZED_1) SEND_SIGNAL(src, COMSIG_CLICK, location, control, params, usr) + usr.ClickOn(src, params) /atom/DblClick(location,control,params) diff --git a/code/_onclick/hud/pai.dm b/code/_onclick/hud/pai.dm index f236d1e2e1c51..2afd8a2b069eb 100644 --- a/code/_onclick/hud/pai.dm +++ b/code/_onclick/hud/pai.dm @@ -54,7 +54,7 @@ if(!..()) return var/mob/living/silicon/pai/pAI = usr - pAI.lay_down() + pAI.toggle_resting() /atom/movable/screen/pai/light name = "Toggle Integrated Lights" diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index c8f2eeca53e30..d12383cc8c265 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -419,7 +419,7 @@ /atom/movable/screen/rest/Click() if(isliving(usr)) var/mob/living/L = usr - L.lay_down() + L.toggle_resting() /atom/movable/screen/rest/update_icon_state() var/mob/living/user = hud?.mymob diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index cd7b82c039e5a..a6559a9ec4c06 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -10,6 +10,11 @@ check_self_for_injuries() return if(!has_active_hand()) //can't attack without a hand. + var/obj/item/bodypart/check_arm = get_active_hand() + if(check_arm?.bodypart_disabled) + to_chat(src, "Your [check_arm.name] is in no condition to be used.") + return + to_chat(src, "You look at your arm and sigh.") return diff --git a/code/datums/action.dm b/code/datums/action.dm index 13d3f405c7469..6792456a3f271 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -116,7 +116,7 @@ return FALSE if((check_flags & AB_CHECK_LYING) && isliving(owner)) var/mob/living/action_user = owner - if(!(action_user.mobility_flags & MOBILITY_STAND)) + if(action_user.body_position == LYING_DOWN) return FALSE if((check_flags & AB_CHECK_CONSCIOUS) && owner.stat != CONSCIOUS) return FALSE @@ -542,11 +542,14 @@ owner.put_in_hands(target_item) target_item.attack_self(owner) return + if(!isliving(owner)) + to_chat(owner, "You lack the necessary living force for this action.") + return + var/mob/living/living_owner = owner + if (living_owner.usable_hands <= 0) + to_chat(living_owner, "You dont have any usable hands!") else - if (owner.get_num_arms() <= 0) - to_chat(owner, "You don't have any usable hands!") - else - to_chat(owner, "Your hands are full!") + to_chat(living_owner, "Your hands are full!") ///MGS BOX! diff --git a/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm b/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm index 2621efabb7eec..baed780fddba9 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm @@ -40,4 +40,4 @@ /datum/ai_planning_subtree/random_speech/mothroach speech_chance = 2 - emote_hear = list("flutters.", "flaps its wings.", "flaps its wings agressively!") + emote_hear = list("flutters.", "flaps its wings.", "flaps its wings aggressively!") diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm index 208dab1926203..32e993533bf4f 100644 --- a/code/datums/brain_damage/mild.dm +++ b/code/datums/brain_damage/mild.dm @@ -134,7 +134,7 @@ var/fall_chance = 1 if(owner.m_intent == MOVE_INTENT_RUN) fall_chance += 2 - if(prob(fall_chance) && (owner.mobility_flags & MOBILITY_STAND)) + if(prob(fall_chance) && owner.body_position == STANDING_UP) to_chat(owner, "Your leg gives out!") owner.Paralyze(35) diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index 2a961c2404f22..e57177fff103b 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -104,13 +104,11 @@ ..() for(var/X in paralysis_traits) ADD_TRAIT(owner, X, "trauma_paralysis") - owner.update_disabled_bodyparts() /datum/brain_trauma/severe/paralysis/on_lose() ..() for(var/X in paralysis_traits) REMOVE_TRAIT(owner, X, "trauma_paralysis") - owner.update_disabled_bodyparts() /datum/brain_trauma/severe/paralysis/paraplegic paralysis_type = "legs" diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index 2742b95b6b448..0a68478904236 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -129,7 +129,7 @@ return if(QDELETED(wielder) || is_obscured()) return - if(!(wielder.mobility_flags & MOBILITY_STAND) || !wielder.has_gravity(wielder.loc)) + if(wielder.body_position == LYING_DOWN || !wielder.has_gravity(wielder.loc)) return var/half_our_blood = bloody_shoes[last_blood_state] / 2 @@ -262,7 +262,7 @@ for(var/X in wielder.bodyparts) var/obj/item/bodypart/affecting = X if(affecting.body_part == LEG_RIGHT || affecting.body_part == LEG_LEFT) - if(!affecting.disabled) + if(!affecting.bodypart_disabled) FP.species_types |= affecting.limb_id break @@ -273,13 +273,13 @@ return ITEM_SLOT_FEET in wielder.check_obscured_slots(TRUE) /datum/component/bloodysoles/feet/on_moved(datum/source, OldLoc, Dir, Forced) - if(wielder.get_num_legs(FALSE) < 2) + if(wielder.num_legs < 2) return ..() /datum/component/bloodysoles/feet/on_step_blood(datum/source, obj/effect/decal/cleanable/pool) - if(wielder.get_num_legs(FALSE) < 2) + if(wielder.num_legs < 2) return ..() diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm index 107fe33b95dc7..4c0b708a0be17 100644 --- a/code/datums/components/caltrop.dm +++ b/code/datums/components/caltrop.dm @@ -55,7 +55,7 @@ if(!(flags & CALTROP_BYPASS_SHOES) && (H.shoes || feetCover)) return - if((H.movement_type & FLYING) || !(H.mobility_flags & MOBILITY_STAND)|| H.buckled) + if((H.movement_type & FLYING) || (H.body_position == LYING_DOWN)|| H.buckled) return var/damage = rand(min_damage, max_damage) diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index a8969ec2fecd2..3f6e065279a0f 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -136,7 +136,7 @@ if(pain_stam_pct && HAS_TRAIT_FROM(victim, TRAIT_INCAPACITATED, STAMINA)) //if it's a less-lethal embed, give them a break if they're already stamcritted pain_chance_current *= 0.2 damage *= 0.5 - else if(victim.mobility_flags & ~MOBILITY_STAND) + else if(victim.body_position == LYING_DOWN) pain_chance_current *= 0.2 if(harmful && prob(pain_chance_current)) @@ -164,7 +164,7 @@ var/mob/living/carbon/victim = parent var/chance = jostle_chance - if(victim.m_intent == MOVE_INTENT_WALK || !(victim.mobility_flags & MOBILITY_STAND)) + if(victim.m_intent == MOVE_INTENT_WALK || victim.body_position == LYING_DOWN) chance *= 0.5 if(harmful && prob(chance)) diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index ae11b38318ea8..369c05a9e8d19 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -207,7 +207,7 @@ return override_allow_spacemove || AM.has_gravity() /datum/component/riding/proc/account_limbs(mob/living/M) - if(M.get_num_legs() < 2 && !slowed) + if(M.usable_legs < 2 && !slowed) vehicle_move_delay = vehicle_move_delay + slowvalue slowed = TRUE else if(slowed) @@ -289,7 +289,7 @@ return if(iscarbon(user)) var/mob/living/carbon/carbonuser = user - if(!carbonuser.get_num_arms()) + if(!carbonuser.usable_hands) Unbuckle(user) to_chat(user, "You can't grab onto [AM] with no hands!") return diff --git a/code/datums/components/toggle_suit.dm b/code/datums/components/toggle_suit.dm index d52b98b823937..7721f14d6fe15 100644 --- a/code/datums/components/toggle_suit.dm +++ b/code/datums/components/toggle_suit.dm @@ -49,7 +49,7 @@ source.balloon_alert(user, "you're incapacitated!") return - if(living_user.get_num_arms() <= 0) + if(living_user.usable_hands <= 0) source.balloon_alert(user, "you don't have hands!") return diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm index 373244c56fbbc..6b7efd812e1d5 100644 --- a/code/datums/components/twohanded.dm +++ b/code/datums/components/twohanded.dm @@ -175,7 +175,7 @@ else to_chat(user, "You need your other hand to be empty!") return - if(user.get_num_arms() < 2) + if(user.usable_hands < 2) if(require_twohands) user.dropItemToGround(parent, force=TRUE) to_chat(user, "You don't have enough intact hands.") diff --git a/code/datums/components/waddling.dm b/code/datums/components/waddling.dm index e2df2656ad730..c86c81c93bf47 100644 --- a/code/datums/components/waddling.dm +++ b/code/datums/components/waddling.dm @@ -13,16 +13,21 @@ /datum/component/waddling/proc/LivingWaddle() SIGNAL_HANDLER - var/mob/living/L = parent - if(L.incapacitated() || !(L.mobility_flags & MOBILITY_STAND)) - return + if(isliving(parent)) + var/mob/living/L = parent + if(L.incapacitated() || L.body_position == LYING_DOWN) + return Waddle() /datum/component/waddling/proc/Waddle() SIGNAL_HANDLER - var/rot_degrees = pick(-12, 0, 12) - var/atom/movable/AM = parent - animate(AM, pixel_z = 4, time = 0) - animate(pixel_z = 0, transform = turn(AM.transform, rot_degrees), time=2) - animate(pixel_z = 0, transform = turn(AM.transform, -rot_degrees), time = 0) + if(!isatom(parent)) + return + + var/atom/movable/target = parent + + animate(target, pixel_z = 4, time = 0) + var/prev_trans = matrix(target.transform) + animate(pixel_z = 0, transform = turn(target.transform, pick(-12, 0, 12)), time=2) + animate(pixel_z = 0, transform = prev_trans, time = 0) diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 99a6eac4d65e6..d5f73ba464c86 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -134,12 +134,12 @@ active_coma = TRUE addtimer(CALLBACK(src, PROC_REF(coma), M), 60) + /datum/symptom/heal/coma/proc/coma(mob/living/M) if(deathgasp) M.fakedeath(TRAIT_REGEN_COMA) else M.Unconscious(300, TRUE, TRUE) - M.update_mobility() addtimer(CALLBACK(src, PROC_REF(uncoma), M), 300) /datum/symptom/heal/coma/proc/uncoma(mob/living/M) @@ -150,7 +150,6 @@ M.cure_fakedeath(TRAIT_REGEN_COMA) else M.SetUnconscious(0) - M.update_mobility() /datum/symptom/heal/coma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) var/heal_amt = 4 * actual_power diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm index 0961557f5e3b4..0e2254d6d9450 100644 --- a/code/datums/diseases/cold.dm +++ b/code/datums/diseases/cold.dm @@ -13,7 +13,7 @@ ..() switch(stage) if(2) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(40)) //changed FROM prob(10) until sleeping is fixed + if(affected_mob.body_position == LYING_DOWN && prob(40)) //changed FROM prob(10) until sleeping is fixed to_chat(affected_mob, "You feel better.") cure() return @@ -30,7 +30,7 @@ if(prob(1)) to_chat(affected_mob, "Mucus runs down the back of your throat.") if(3) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(25)) //changed FROM prob(5) until sleeping is fixed + if(affected_mob.body_position == LYING_DOWN && prob(25)) //changed FROM prob(5) until sleeping is fixed to_chat(affected_mob, "You feel better.") cure() return diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index 3cb6e91e7f6dd..9989f839c5a9b 100644 --- a/code/datums/diseases/flu.dm +++ b/code/datums/diseases/flu.dm @@ -15,7 +15,7 @@ ..() switch(stage) if(2) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(20)) + if(affected_mob.body_position == LYING_DOWN && prob(20)) to_chat(affected_mob, "You feel better.") stage-- return @@ -34,7 +34,7 @@ affected_mob.updatehealth() if(3) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(15)) + if(affected_mob.body_position == LYING_DOWN && prob(15)) to_chat(affected_mob, "You feel better.") stage-- return diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index 88fcb44d56be9..589d0903c8cca 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -31,7 +31,7 @@ switch(stage) if(1) if(restcure) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(30)) + if(affected_mob.body_position == LYING_DOWN && prob(30)) to_chat(affected_mob, "You feel better.") cure() return @@ -43,7 +43,7 @@ to_chat(affected_mob, "You feel angry.") if(2) if(restcure) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(20)) + if(affected_mob.body_position == LYING_DOWN && prob(20)) to_chat(affected_mob, "You feel better.") cure() return @@ -58,7 +58,7 @@ to_chat(affected_mob, "Your stomach churns.") if(3) if(restcure) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(20)) + if(affected_mob.body_position == LYING_DOWN && prob(20)) to_chat(affected_mob, "You feel better.") cure() return @@ -73,7 +73,7 @@ if(4) if(restcure) - if(!(affected_mob.mobility_flags & MOBILITY_STAND) && prob(5)) + if(affected_mob.body_position == LYING_DOWN && prob(5)) to_chat(affected_mob, "You feel better.") cure() return diff --git a/code/datums/elements/cleaning.dm b/code/datums/elements/cleaning.dm index 18a99f0c0407a..e4c72604c1d4d 100644 --- a/code/datums/elements/cleaning.dm +++ b/code/datums/elements/cleaning.dm @@ -25,7 +25,7 @@ // Clean humans that are lying down else if(ishuman(A)) var/mob/living/carbon/human/cleaned_human = A - if(!(cleaned_human.mobility_flags & MOBILITY_STAND)) + if(cleaned_human.body_position == LYING_DOWN) cleaned_human.wash(CLEAN_WASH) cleaned_human.regenerate_icons() to_chat(cleaned_human, "[AM] cleans your face!") diff --git a/code/datums/elements/footstep.dm b/code/datums/elements/footstep.dm index 6693317fab36b..e7eb666df0d39 100644 --- a/code/datums/elements/footstep.dm +++ b/code/datums/elements/footstep.dm @@ -65,7 +65,7 @@ if(!turf.footstep || source.buckled || source.throwing || source.movement_type & (VENTCRAWLING | FLYING)) return - if(!(source.mobility_flags & MOBILITY_STAND)) //play crawling sound if we're lying + if(source.body_position == LYING_DOWN) //play crawling sound if we're lying playsound(source, 'sound/effects/footstep/crawl1.ogg', 15 * volume, falloff_distance = 1, vary = sound_vary) return diff --git a/code/datums/elements/squish.dm b/code/datums/elements/squish.dm index 71324f14fefff..03e721c99ff2b 100644 --- a/code/datums/elements/squish.dm +++ b/code/datums/elements/squish.dm @@ -10,7 +10,7 @@ return ELEMENT_INCOMPATIBLE var/mob/living/carbon/C = target - var/was_lying = !(C.mobility_flags & MOBILITY_STAND) + var/was_lying = C.body_position == LYING_DOWN addtimer(CALLBACK(src, PROC_REF(Detach), C, was_lying), duration) C.transform = C.transform.Scale(TALL, SHORT) @@ -18,7 +18,7 @@ /datum/element/squish/Detach(mob/living/carbon/C, was_lying) . = ..() if(istype(C)) - var/is_lying = !(C.mobility_flags & MOBILITY_STAND) + var/is_lying = C.body_position == LYING_DOWN if(was_lying == is_lying) C.transform = C.transform.Scale(SHORT, TALL) diff --git a/code/datums/keybinding/living.dm b/code/datums/keybinding/living.dm index 7e41be6a3106a..3127e29ec1497 100644 --- a/code/datums/keybinding/living.dm +++ b/code/datums/keybinding/living.dm @@ -34,7 +34,7 @@ if(.) return var/mob/living/L = user.mob - L.lay_down() + L.toggle_resting() return TRUE /datum/keybinding/living/look_up @@ -93,7 +93,7 @@ /datum/keybinding/living/primary_species_action/down(client/user) . = ..() - if(. || !iscarbon(user.mob)) + if(. || !iscarbon(user.mob)) return var/mob/living/carbon/L = user.mob L.dna.species.primary_species_action() diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm index 6089b55d5b36e..065a874e6de87 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -53,7 +53,7 @@ var/def_check = D.getarmor(BODY_ZONE_CHEST, MELEE) if(!can_use(A)) return FALSE - if(D.mobility_flags & MOBILITY_STAND) + if(D.body_position == STANDING_UP) D.visible_message("[A] slams [D] into the ground!", \ "[A] slams you into the ground!") playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1) @@ -155,7 +155,7 @@ A.do_attack_animation(D) var/picked_hit_type = pick("CQC'd", "Big Bossed") var/bonus_damage = 13 - if(!(D.mobility_flags & MOBILITY_STAND)) + if(D.body_position == LYING_DOWN) bonus_damage += 5 picked_hit_type = "stomps on" D.apply_damage(bonus_damage, BRUTE, blocked = def_check) diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 56aa658965cdd..9bc879c7a815e 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -133,7 +133,7 @@ var/armor_block = D.run_armor_check(affecting, MELEE) var/picked_hit_type = pick("punched", "kicked") var/bonus_damage = 0 - if(!(D.mobility_flags & MOBILITY_STAND)) + if(D.body_position == LYING_DOWN) bonus_damage += 5 picked_hit_type = "stomped" D.apply_damage(rand(5,10) + bonus_damage, A.dna.species.attack_type, affecting, armor_block) @@ -153,7 +153,7 @@ return 1 var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.get_combat_bodyzone(D))) var/armor_block = D.run_armor_check(affecting, MELEE) - if((D.mobility_flags & MOBILITY_STAND)) + if(D.body_position == STANDING_UP) D.visible_message("[A] reprimands [D]!", \ "You're slapped by [A]!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) to_chat(A, "You jab [D]!") @@ -161,7 +161,7 @@ playsound(D, 'sound/effects/hit_punch.ogg', 50, TRUE, -1) D.apply_damage(rand(5,10), STAMINA, affecting, armor_block) log_combat(A, D, "punched nonlethally", name) - if(!(D.mobility_flags & MOBILITY_STAND)) + if(D.body_position == LYING_DOWN) D.visible_message("[A] reprimands [D]!", \ "You're manhandled by [A]!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) to_chat(A, "You stomp [D]!") diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 301848bb247a2..9dbb88f08eda3 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -127,7 +127,6 @@ /datum/status_effect/wish_granters_gift/on_remove() owner.revive(full_heal = TRUE, admin_revive = TRUE) owner.visible_message("[owner] appears to wake from the dead, having healed all wounds!", "You have regenerated.") - owner.update_mobility() /atom/movable/screen/alert/status_effect/wish_granters_gift name = "Wish Granter's Immortality" diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index c80ea67bd707d..49066989dbbc5 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -8,18 +8,14 @@ alert_type = null var/needs_update_stat = FALSE -/datum/status_effect/incapacitating/on_creation(mob/living/new_owner, set_duration, updating_canmove) +/datum/status_effect/incapacitating/on_creation(mob/living/new_owner, set_duration) if(isnum_safe(set_duration)) duration = set_duration . = ..() - if(.) - if(updating_canmove) - owner.update_mobility() - if(needs_update_stat || issilicon(owner)) - owner.update_stat() + if(. && (needs_update_stat || issilicon(owner))) + owner.update_stat() /datum/status_effect/incapacitating/on_remove() - owner.update_mobility() if(needs_update_stat || issilicon(owner)) //silicons need stat updates in addition to normal canmove updates owner.update_stat() return ..() @@ -121,7 +117,7 @@ var/mob/living/carbon/carbon_owner var/mob/living/carbon/human/human_owner -/datum/status_effect/incapacitating/sleeping/on_creation(mob/living/new_owner, updating_canmove) +/datum/status_effect/incapacitating/sleeping/on_creation(mob/living/new_owner) . = ..() if(.) if(iscarbon(owner)) //to avoid repeated istypes @@ -189,7 +185,7 @@ if(owner.stat == DEAD) last_dead_time = world.time -/datum/status_effect/grouped/stasis/on_creation(mob/living/new_owner, set_duration, updating_canmove) +/datum/status_effect/grouped/stasis/on_creation(mob/living/new_owner, set_duration) . = ..() if(.) update_time_of_death() @@ -201,16 +197,14 @@ if(!.) return ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) - //ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id)) - owner.update_mobility() // TEMPORARY + ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id)) /datum/status_effect/grouped/stasis/tick() update_time_of_death() /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() + REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, TRAIT_STATUS_EFFECT(id)) update_time_of_death() SEND_SIGNAL(owner, COMSIG_LIVING_EXIT_STASIS) return ..() @@ -627,7 +621,7 @@ /datum/status_effect/trance/tick() if(stun) - owner.Stun(60, TRUE, TRUE) + owner.Stun(60, TRUE) owner.dizziness = 20 /datum/status_effect/trance/on_apply() @@ -757,7 +751,7 @@ alert_type = /atom/movable/screen/alert/status_effect/dna_melt var/kill_either_way = FALSE //no amount of removing mutations is gonna save you now -/datum/status_effect/dna_melt/on_creation(mob/living/new_owner, set_duration, updating_canmove) +/datum/status_effect/dna_melt/on_creation(mob/living/new_owner, set_duration) . = ..() to_chat(new_owner, "My body can't handle the mutations! I need to get my mutations removed fast!") @@ -781,7 +775,7 @@ alert_type = /atom/movable/screen/alert/status_effect/go_away var/direction -/datum/status_effect/go_away/on_creation(mob/living/new_owner, set_duration, updating_canmove) +/datum/status_effect/go_away/on_creation(mob/living/new_owner, set_duration) . = ..() direction = pick(NORTH, SOUTH, EAST, WEST) new_owner.setDir(direction) diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm index 2033a4097582d..640a1a58162a4 100644 --- a/code/datums/status_effects/gas.dm +++ b/code/datums/status_effects/gas.dm @@ -16,7 +16,7 @@ to_chat(owner, "You become frozen in a cube!") cube = icon('icons/effects/freeze.dmi', "ice_cube") owner.add_overlay(cube) - owner.update_mobility() + /datum/status_effect/freon/on_remove() if(!owner.stat) @@ -25,7 +25,6 @@ REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) owner.cut_overlay(cube) owner.adjust_bodytemperature(100) - owner.update_mobility() return ..() /atom/movable/screen/alert/status_effect/freon @@ -43,7 +42,6 @@ /datum/status_effect/freon/tick() - owner.update_mobility() if(can_melt && owner.bodytemperature >= owner.get_body_temp_normal()) qdel(src) @@ -58,7 +56,6 @@ if(!QDELETED(src)) to_chat(owner, "You break out of the ice cube!") owner.remove_status_effect(/datum/status_effect/freon) - owner.update_mobility() /datum/status_effect/freon/watcher duration = 8 SECONDS diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 7739fd3b7f4e1..0deec87f6c61d 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -791,7 +791,7 @@ * Default behaviour is to send a warning that the user can't move while buckled as long * as the buckle_message_cooldown has expired (50 ticks) */ -/atom/proc/relaymove(mob/user) +/atom/proc/relaymove(mob/living/user, direction) if(buckle_message_cooldown <= world.time) buckle_message_cooldown = world.time + 50 to_chat(user, "You can't move while buckled to [src]!") diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index dc0a7bdb2b6a2..3a911bc9a40fc 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -38,7 +38,8 @@ var/datum/movement_packet/move_packet var/list/acted_explosions //for explosion dodging var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm - var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc. + ///In case you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc. Should only be changed through setMovetype() + var/movement_type = GROUND var/atom/movable/pulling var/grab_state = 0 var/throwforce = 0 @@ -194,9 +195,6 @@ var/mob/living/ex_pulled = pulling setGrabState(GRAB_PASSIVE) pulling = null - if(isliving(ex_pulled)) - var/mob/living/L = ex_pulled - L.update_mobility()// mob gets up if it was lyng down in a chokehold SEND_SIGNAL(ex_pulled, COMSIG_MOVABLE_NO_LONGER_PULLED) ///Reports the event of the change in value of the pulledby variable. @@ -643,9 +641,14 @@ Moved(oldloc, NONE, TRUE) +///Proc to modify the movement_type and hook behavior associated with it changing. /atom/movable/proc/setMovetype(newval) + if(movement_type == newval) + return + . = movement_type movement_type = newval + //Called whenever an object moves and by mobs when they attempt to move themselves through space //And when an object or action applies a force on src, see newtonian_move() below //Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index cb25e403e242c..7e6497177ac85 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -290,9 +290,6 @@ Class Procs: continue movable_atom.forceMove(this_turf) - if(isliving(movable_atom)) - var/mob/living/living_mob = movable_atom - living_mob.update_mobility() if(occupant == movable_atom) occupant = null diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index f0664b7345b5b..a0ba1bfae7ab6 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -313,9 +313,9 @@ user_image = image(icon,loc,icon_state,FLY_LAYER) eye_user.client.images += user_image -/mob/camera/ai_eye/remote/relaymove(mob/user,direct) - if(direct == UP || direct == DOWN) - zMove(direct, FALSE) +/mob/camera/ai_eye/remote/relaymove(mob/living/user, direction) + if(direction == UP || direction == DOWN) + zMove(direction, FALSE) return var/initial = initial(sprint) var/max_sprint = 50 @@ -324,7 +324,7 @@ sprint = initial for(var/i = 0; i < max(sprint, initial); i += 20) - var/turf/step = get_turf(get_step(src, direct)) + var/turf/step = get_turf(get_step(src, direction)) if(step) setLoc(step) diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 94440ccf9bc1e..6fd03e5cc675a 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -76,15 +76,13 @@ else if(anchored) to_chat(user,"You unsecure and disconnect [src].") set_anchored(FALSE) - playsound(src, 'sound/items/deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) return return ..() -/obj/machinery/jukebox/update_icon() - if(active) - icon_state = "[initial(icon_state)]-active" - else - icon_state = "[initial(icon_state)]" +/obj/machinery/jukebox/update_icon_state() + icon_state = "[initial(icon_state)][active ? "-active" : null]" + return ..() /obj/machinery/jukebox/ui_status(mob/user) if(!anchored) @@ -137,7 +135,7 @@ if(!active) if(stop > world.time) to_chat(usr, "Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].") - playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) + playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE) return activate_music() START_PROCESSING(SSobj, src) @@ -328,10 +326,12 @@ if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up INVOKE_ASYNC(src, PROC_REF(hierofunk)) sleep(selection.song_beat) + if(QDELETED(src)) + return #undef DISCO_INFENO_RANGE -/obj/machinery/jukebox/disco/proc/dance(var/mob/living/M) //Show your moves +/obj/machinery/jukebox/disco/proc/dance(mob/living/M) //Show your moves set waitfor = FALSE switch(rand(0,9)) if(0 to 1) @@ -343,44 +343,63 @@ if(7 to 9) dance5(M) -/obj/machinery/jukebox/disco/proc/dance2(var/mob/living/M) - for(var/i = 1, i < 10, i++) - for(var/d in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) - M.setDir(d) - if(i == WEST) - M.emote("flip") - sleep(1) - sleep(20) +/obj/machinery/jukebox/disco/proc/dance2(mob/living/M) + for(var/i in 0 to 9) + dance_rotate(M, CALLBACK(M, TYPE_PROC_REF(/mob, dance_flip))) + sleep(2 SECONDS) -/obj/machinery/jukebox/disco/proc/dance3(var/mob/living/M) +/mob/proc/dance_flip() + if(dir == WEST) + emote("flip") + +/obj/machinery/jukebox/disco/proc/dance3(mob/living/M) + var/matrix/initial_matrix = matrix(M.transform) for (var/i in 1 to 75) if (!M) return switch(i) if (1 to 15) - animate(M, pixel_y = M.pixel_y + 1, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(0,1) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (16 to 30) - animate(M, pixel_x = M.pixel_x + 1, pixel_y = M.pixel_y - 1, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(1,-1) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (31 to 45) - animate(M, pixel_x = M.pixel_x - 1, pixel_y = M.pixel_y - 1, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(-1,-1) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (46 to 60) - animate(M, pixel_x = M.pixel_x - 1, pixel_y = M.pixel_y + 1, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(-1,1) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (61 to 75) - animate(M, pixel_x = M.pixel_x + 1, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(1,0) + animate(M, transform = initial_matrix, time = 1, loop = 0) M.setDir(turn(M.dir, 90)) switch (M.dir) if (NORTH) - animate(M, pixel_y = M.pixel_y + 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(0,3) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (SOUTH) - animate(M, pixel_y = M.pixel_y - 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(0,-3) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (EAST) - animate(M, pixel_x = M.pixel_x + 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(3,0) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (WEST) - animate(M, pixel_x = M.pixel_x - 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(-3,0) + animate(M, transform = initial_matrix, time = 1, loop = 0) sleep(1) - animate(M, pixel_x = M.body_position_pixel_x_offset, pixel_y = M.body_position_pixel_y_offset, time = 1, loop = 0) + M.lying_fix() -/obj/machinery/jukebox/disco/proc/dance4(var/mob/living/M) +/obj/machinery/jukebox/disco/proc/dance4(mob/living/M) var/speed = rand(1,3) set waitfor = 0 var/time = 30 @@ -389,30 +408,47 @@ for(var/i in 1 to speed) M.setDir(pick(GLOB.cardinals)) for(var/mob/living/carbon/NS in rangers) - NS.set_resting(!NS.resting, TRUE) + NS.set_resting(!NS.resting, TRUE, TRUE) time-- -/obj/machinery/jukebox/disco/proc/dance5(var/mob/living/M) - animate(M, transform = matrix(M.transform).Scale(-1), time = 1, loop = 0) +/obj/machinery/jukebox/disco/proc/dance5(mob/living/M) + animate(M, transform = matrix(180, MATRIX_ROTATE), time = 1, loop = 0) + var/matrix/initial_matrix = matrix(M.transform) for (var/i in 1 to 60) if (!M) return if (i<31) - animate(M, pixel_y = M.pixel_y + 1, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(0,1) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (i>30) - animate(M, pixel_y = M.pixel_y - 1, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(0,-1) + animate(M, transform = initial_matrix, time = 1, loop = 0) M.setDir(turn(M.dir, 90)) switch (M.dir) if (NORTH) - animate(M, pixel_y = M.pixel_y + 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(0,3) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (SOUTH) - animate(M, pixel_y = M.pixel_y - 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(0,-3) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (EAST) - animate(M, pixel_x = M.pixel_x + 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(3,0) + animate(M, transform = initial_matrix, time = 1, loop = 0) if (WEST) - animate(M, pixel_x = M.pixel_x - 3, time = 1, loop = 0) + initial_matrix = matrix(M.transform) + initial_matrix.Translate(-3,0) + animate(M, transform = initial_matrix, time = 1, loop = 0) sleep(1) - animate(M, transform = matrix(M.transform).Scale(-1), pixel_x = M.body_position_pixel_x_offset, pixel_y = M.body_position_pixel_y_offset, time = 1, loop = 0) //dance end + M.lying_fix() + +/mob/living/proc/lying_fix() + animate(src, transform = null, time = 1, loop = 0) + lying_prev = 0 /obj/machinery/jukebox/proc/dance_over() for(var/mob/living/L in rangers) @@ -430,7 +466,7 @@ if(world.time < stop && active) var/sound/song_played = sound(selection.song_path) - for(var/mob/L as() in rangers) + for(var/mob/L as anything in rangers) if(get_dist(src,L) > 10) rangers -= L if(!L || !L.client) @@ -444,20 +480,17 @@ M.playsound_local(get_turf(M), null, volume, channel = CHANNEL_JUKEBOX, S = song_played, use_reverb = FALSE) else if(active) active = FALSE + STOP_PROCESSING(SSobj, src) dance_over() - playsound(src,'sound/machines/terminal_off.ogg',50,1) + playsound(src,'sound/machines/terminal_off.ogg',50,TRUE) update_icon() stop = world.time + 100 ui_update() return PROCESS_KILL -/obj/machinery/jukebox/disco/process(delta_time) +/obj/machinery/jukebox/disco/process() . = ..() if(active) - for(var/mob/M as() in rangers) - if(DT_PROB(5+(allowed(M)*4), delta_time)) - if(isliving(M)) - var/mob/living/L = M - if(!(L.mobility_flags & MOBILITY_MOVE)) - continue - dance(L) + for(var/mob/living/M in rangers) + if(prob(5+(allowed(M)*4)) && (M.mobility_flags & MOBILITY_MOVE)) + dance(M) diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm index f1931a655c929..acb42123e8b20 100644 --- a/code/game/machinery/dna_scanner.dm +++ b/code/game/machinery/dna_scanner.dm @@ -118,7 +118,7 @@ return TRUE -/obj/machinery/dna_scannernew/relaymove(mob/user as mob) +/obj/machinery/dna_scannernew/relaymove(mob/living/user, direction) if(user.stat || (locked && !state_open)) if(message_cooldown <= world.time) message_cooldown = world.time + 50 @@ -148,8 +148,7 @@ toggle_open(user) /obj/machinery/dna_scannernew/MouseDrop_T(mob/target, mob/user) - var/mob/living/L = user - if(user.stat || (isliving(user) && (!(L.mobility_flags & MOBILITY_STAND) || !(L.mobility_flags & MOBILITY_UI))) || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser() || locked) + if(user.stat != CONSCIOUS || HAS_TRAIT(user, TRAIT_UI_BLOCKED) || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser() || locked) return close_machine(target) diff --git a/code/game/machinery/gulag_teleporter.dm b/code/game/machinery/gulag_teleporter.dm index ded37ac96dfaa..008481d41a3e5 100644 --- a/code/game/machinery/gulag_teleporter.dm +++ b/code/game/machinery/gulag_teleporter.dm @@ -82,7 +82,7 @@ The console is located at computer/gulag_teleporter.dm return -/obj/machinery/gulag_teleporter/relaymove(mob/user) +/obj/machinery/gulag_teleporter/relaymove(mob/living/user, direction) if(user.stat != CONSCIOUS) return if(locked) diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index eb1ee900063d0..f66e7754e1ad0 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -182,7 +182,7 @@ if (!state_open && gone == occupant) container_resist(gone) -/obj/machinery/harvester/relaymove(mob/user) +/obj/machinery/harvester/relaymove(mob/living/user, direction) if (!state_open) container_resist(user) diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 710e46fb019f7..7e9930432e63d 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -42,7 +42,7 @@ process_occupant(delta_time) return 1 -/obj/machinery/recharge_station/relaymove(mob/user) +/obj/machinery/recharge_station/relaymove(mob/living/user, direction) if(user.stat) return open_machine() diff --git a/code/game/machinery/sleeper.dm b/code/game/machinery/sleeper.dm index 699b39f2de350..aad043793efa0 100644 --- a/code/game/machinery/sleeper.dm +++ b/code/game/machinery/sleeper.dm @@ -129,7 +129,7 @@ if (!state_open && gone == occupant) container_resist(gone) -/obj/machinery/sleeper/relaymove(mob/user) +/obj/machinery/sleeper/relaymove(mob/living/user, direction) if (!state_open) container_resist(user) @@ -156,15 +156,14 @@ if(is_operational && occupant) open_machine() + /obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user) - if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) + if(HAS_TRAIT(user, TRAIT_UI_BLOCKED) || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) return - if(isliving(user)) - var/mob/living/L = user - if(!(L.mobility_flags & MOBILITY_STAND)) - return + close_machine(target) + /obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I) . = TRUE if(..()) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index e5c79f0a49f2d..c0e616567412b 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -366,7 +366,7 @@ return if(isliving(user)) var/mob/living/L = user - if(!(L.mobility_flags & MOBILITY_STAND)) + if(L.body_position == LYING_DOWN) return var/mob/living/target = A if(!state_open) @@ -486,7 +486,7 @@ if(electrocute_mob(user, src, src, 1, TRUE)) return 1 -/obj/machinery/suit_storage_unit/relaymove(mob/user) +/obj/machinery/suit_storage_unit/relaymove(mob/living/user, direction) if(locked) if(message_cooldown <= world.time) message_cooldown = world.time + 50 diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index e9884d629b4e9..737a712d92544 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -50,10 +50,11 @@ // Only humans can enter from the west side, while lying down. var/move_dir = get_dir(loc, AM.loc) var/mob/living/carbon/human/H = AM - if((transform_standing || !(H.mobility_flags & MOBILITY_STAND)) && move_dir == EAST)// || move_dir == WEST) + if((transform_standing || H.body_position == LYING_DOWN) && move_dir == EAST)// || move_dir == WEST) AM.forceMove(drop_location()) do_transform(AM) + /obj/machinery/transformer/CanAllowThrough(atom/movable/mover, border_dir) . = ..() // Allows items to go through, diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 601f1e68a95a1..d1520a6ad6f47 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -365,7 +365,7 @@ GLOBAL_LIST_INIT(dye_registry, list( new /obj/item/restraints/handcuffs(loc) ..() -/obj/machinery/washing_machine/relaymove(mob/user) +/obj/machinery/washing_machine/relaymove(mob/living/user, direction) container_resist(user) /obj/machinery/washing_machine/container_resist(mob/living/user) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 3ef541ccb225a..db3e273c46293 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -1,7 +1,7 @@ /atom/movable var/can_buckle = FALSE - /// Bed-like behaviour, forces mob.lying = buckle_lying if != -1 - var/buckle_lying = -1 + /// Bed-like behaviour, forces mob.lying = buckle_lying if not set to [NO_BUCKLE_LYING]. + var/buckle_lying = NO_BUCKLE_LYING /// Require people to be handcuffed before being able to buckle. eg: pipes var/buckle_requires_restraints = FALSE var/list/mob/living/buckled_mobs = null //list() @@ -102,7 +102,6 @@ M.set_buckled(src) M.setDir(dir) buckled_mobs |= M - M.update_mobility() M.throw_alert("buckled", /atom/movable/screen/alert/restrained/buckled) /* M.set_glide_size(glide_size) @@ -124,17 +123,24 @@ M.adjust_fire_stacks(1) M.IgniteMob() -/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force=FALSE) - if(istype(buckled_mob) && buckled_mob.buckled == src && (buckled_mob.can_unbuckle() || force)) - . = buckled_mob - buckled_mob.set_buckled(null) - buckled_mob.set_anchored(initial(buckled_mob.anchored)) - buckled_mob.update_mobility() - buckled_mob.clear_alert("buckled") - buckled_mobs -= buckled_mob - SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force) - - post_unbuckle_mob(.) + +/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE) + if(!isliving(buckled_mob)) + CRASH("Non-living [buckled_mob] thing called unbuckle_mob() for source.") + if(buckled_mob.buckled != src) + CRASH("[buckled_mob] called unbuckle_mob() for source while having buckled as [buckled_mob.buckled].") + if(!force && !buckled_mob.can_unbuckle()) + return + . = buckled_mob + buckled_mob.set_buckled(null) + buckled_mob.set_anchored(initial(buckled_mob.anchored)) + buckled_mob.clear_alert("buckled") + //buckled_mob.set_glide_size(DELAY_TO_GLIDE_SIZE(buckled_mob.total_multiplicative_slowdown())) + buckled_mobs -= buckled_mob + SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force) + + post_unbuckle_mob(.) + /atom/movable/proc/unbuckle_all_mobs(force=FALSE) if(!has_buckled_mobs()) diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm index cb85c98cc456b..ffd84411841df 100644 --- a/code/game/objects/effects/step_triggers.dm +++ b/code/game/objects/effects/step_triggers.dm @@ -68,10 +68,8 @@ if(AM in T.affecting) return - if(isliving(AM)) - var/mob/living/M = AM - if(immobilize) - M.mobility_flags &= ~MOBILITY_MOVE + if(immobilize) + ADD_TRAIT(AM, TRAIT_IMMOBILIZED, src) affecting[AM] = AM.dir var/datum/move_loop/loop = SSmove_manager.move(AM, direction, speed, tiles ? tiles * speed : INFINITY) @@ -107,11 +105,8 @@ SIGNAL_HANDLER var/atom/movable/being_moved = source.moving affecting -= being_moved - if(isliving(being_moved)) - var/mob/living/M = being_moved - if(immobilize) - M.mobility_flags |= MOBILITY_MOVE - M.update_mobility() + REMOVE_TRAIT(being_moved, TRAIT_IMMOBILIZED, REF(src)) + /* Stops things thrown by a thrower, doesn't do anything */ diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6a433b3db0ba3..5a21f635f38b8 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -574,7 +574,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) blockhand = (locate(/obj/item/bodypart/l_arm) in owner.bodyparts) if(!blockhand) return 0 - if(blockhand.is_disabled()) + if(blockhand?.bodypart_disabled) to_chat(owner, "You're too exausted to block the attack!") return 0 else if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE) && owner.getStaminaLoss() >= 30) diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm index 3a58d75db273e..e835909745a4f 100644 --- a/code/game/objects/items/chrono_eraser.dm +++ b/code/game/objects/items/chrono_eraser.dm @@ -111,7 +111,7 @@ if(field == F) var/turf/currentpos = get_turf(src) var/mob/living/user = loc - if(currentpos == startpos && isliving(user) && (user.mobility_flags & MOBILITY_STAND) && (user.stat == CONSCIOUS) && (field in view(CHRONO_BEAM_RANGE, currentpos))) + if(currentpos == startpos && isliving(user) && user.body_position == STANDING_UP && !HAS_TRAIT(user, TRAIT_INCAPACITATED) && (field in view(CHRONO_BEAM_RANGE, currentpos))) return TRUE field_disconnect(F) return FALSE diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 6180c25b71e6d..cc3cf0f0af015 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -1018,7 +1018,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(prob(5))//small chance for the vape to break and deal damage if it's emagged playsound(get_turf(src), 'sound/effects/pop_expl.ogg', 50, 0) M.apply_damage(20, BURN, BODY_ZONE_HEAD) - M.Paralyze(300, 1, 0) + M.Paralyze(300) var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread sp.set_up(5, 1, src) sp.start() diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index e3ba5227963ef..b97e1707c6159 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -187,7 +187,7 @@ else names[M.name] = 1 dat += "[M.name]" - if(!(M.mobility_flags & MOBILITY_STAND)) + if(M.body_position == LYING_DOWN) if(M.buckled) dat += " (Sitting)" else diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index c55f91eca42f0..ed801cfa5e9c0 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -161,7 +161,7 @@ . = ..() master.disrupt() -/obj/effect/dummy/chameleon/relaymove(mob/user, direction) +/obj/effect/dummy/chameleon/relaymove(mob/living/user, direction) if(isspaceturf(loc) || !direction) return //No magical space movement! diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index dc48ec35dff31..e0a8ea48ed4f2 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -148,7 +148,7 @@ return var/mob/living/carbon/human/H = M if(iscatperson(H) && !H.is_blind()) //catpeople! - if(user.mobility_flags & MOBILITY_STAND) + if(user.body_position == STANDING_UP) H.setDir(get_dir(H,targloc)) // kitty always looks at the light if(prob(effectchance)) H.visible_message("[H] makes a grab for the light!","LIGHT!") @@ -161,9 +161,11 @@ else if(iscat(M)) //cats! var/mob/living/simple_animal/pet/cat/C = M if(prob(50)) + if(C.resting) + C.set_resting(FALSE, instant = TRUE) C.visible_message("[C] pounces on the light!","LIGHT!") C.Move(targloc) - C.set_resting(TRUE, FALSE) + C.Immobilize(1 SECONDS) else C.visible_message("[C] looks uninterested in your games.","You spot [user] shining [src] at you. How insulting!") diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 0c5249ca9aa32..f10620228adfb 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -6,19 +6,6 @@ user.visible_message("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!") return OXYLOSS -/obj/item/restraints/Destroy() - if(iscarbon(loc)) - var/mob/living/carbon/M = loc - if(M.handcuffed == src) - M.set_handcuffed(null) - M.update_handcuffed() - if(M.buckled?.buckle_requires_restraints) - M.buckled.unbuckle_mob(M) - if(M.legcuffed == src) - M.legcuffed = null - M.update_inv_legcuffed() - return ..() - //Handcuffs /obj/item/restraints/handcuffs @@ -55,12 +42,12 @@ return if(!C.handcuffed) - if(C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()) + if(C.canBeHandcuffed()) C.visible_message("[user] is trying to put [src.name] on [C]!", \ "[user] is trying to put [src.name] on you!") playsound(loc, cuffsound, 30, 1, -2) - if(do_after(user, 4 SECONDS, C) && (C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore())) + if(do_after(user, 4 SECONDS, C) && C.canBeHandcuffed()) if(iscyborg(user)) apply_cuffs(C, user, TRUE) else @@ -272,9 +259,9 @@ var/def_zone = BODY_ZONE_CHEST if(snap && iscarbon(L)) var/mob/living/carbon/C = L - if(C.mobility_flags & MOBILITY_STAND) + if(C.body_position == STANDING_UP) def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - if(!C.legcuffed && C.get_num_legs(FALSE) >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. + if(!C.legcuffed && C.num_legs >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. C.legcuffed = src forceMove(C) C.update_equipment_speed_mods() @@ -347,7 +334,7 @@ * * C - the carbon that we will try to ensnare */ /obj/item/restraints/legcuffs/bola/proc/ensnare(mob/living/carbon/C) - if(!C.legcuffed && C.get_num_legs(FALSE) >= 2) + if(!C.legcuffed && C.num_legs >= 2) visible_message("\The [src] ensnares [C]!") C.legcuffed = src forceMove(C) diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm index c47136f77d836..e4692b910edf5 100644 --- a/code/game/objects/items/his_grace.dm +++ b/code/game/objects/items/his_grace.dm @@ -72,7 +72,7 @@ else . += "[src] is latched closed." -/obj/item/his_grace/relaymove(mob/living/user) //Allows changelings, etc. to climb out of Him after they revive, provided He isn't active +/obj/item/his_grace/relaymove(mob/living/user, direction) //Allows changelings, etc. to climb out of Him after they revive, provided He isn't active if(!awakened) user.forceMove(get_turf(src)) user.visible_message("[user] scrambles out of [src]!", "You climb out of [src]!") diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 201f7bb1d21ef..d3aab132c132a 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -490,7 +490,7 @@ hitsound = 'sound/weapons/rapierhit.ogg' var/possessed = FALSE -/obj/item/nullrod/scythe/talking/relaymove(mob/user) +/obj/item/nullrod/scythe/talking/relaymove(mob/living/user, direction) return //stops buckled message spam for the ghost. /obj/item/nullrod/scythe/talking/attack_self(mob/living/user) diff --git a/code/game/objects/items/hot_potato.dm b/code/game/objects/items/hot_potato.dm index 9d05a23523b47..cb9ecb13a97d3 100644 --- a/code/game/objects/items/hot_potato.dm +++ b/code/game/objects/items/hot_potato.dm @@ -103,7 +103,7 @@ return FALSE if(!victim.client) to_chat(user, "[src] refuses to attach to a non-sapient creature!") - if(victim.stat != CONSCIOUS || !victim.get_num_legs()) + if(victim.stat != CONSCIOUS || !victim.usable_legs) to_chat(user, "[src] refuses to attach to someone incapable of using it!") user.temporarilyRemoveItemFromInventory(src, TRUE) . = FALSE diff --git a/code/game/objects/items/implants/implant_misc.dm b/code/game/objects/items/implants/implant_misc.dm index 5f3c40b2a6f38..1cc169de68e8f 100644 --- a/code/game/objects/items/implants/implant_misc.dm +++ b/code/game/objects/items/implants/implant_misc.dm @@ -41,7 +41,6 @@ imp_in.SetImmobilized(0) imp_in.adjustStaminaLoss(-200) imp_in.set_resting(FALSE) - imp_in.update_mobility() imp_in.reagents.add_reagent(/datum/reagent/medicine/synaptizine, 10) imp_in.reagents.add_reagent(/datum/reagent/medicine/omnizine, 10) diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm index c8f4dc1e23c9f..d982a4eab9f28 100644 --- a/code/game/objects/items/implants/implantchair.dm +++ b/code/game/objects/items/implants/implantchair.dm @@ -134,7 +134,7 @@ "You successfully break out of [src]!") open_machine() -/obj/machinery/implantchair/relaymove(mob/user) +/obj/machinery/implantchair/relaymove(mob/living/user, direction) if(message_cooldown <= world.time) message_cooldown = world.time + 50 to_chat(user, "[src]'s door won't budge!") @@ -144,9 +144,10 @@ return if(isliving(user)) var/mob/living/L = user - if(!(L.mobility_flags & MOBILITY_STAND)) + if(L.body_position == LYING_DOWN) return close_machine(target) + /obj/machinery/implantchair/close_machine(mob/living/user) if((isnull(user) || istype(user)) && state_open) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 97be530b0e914..ec62cb221aa5b 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -76,7 +76,7 @@ user.do_attack_animation(M, ATTACK_EFFECT_BOOP) playsound(loc, 'sound/weapons/tap.ogg', 50, 1, -1) else if(ishuman(M)) - if(!(user.mobility_flags & MOBILITY_STAND)) + if(user.body_position == LYING_DOWN) user.visible_message("[user] shakes [M] trying to get [M.p_them()] up!", \ "You shake [M] trying to get [M.p_them()] up!") else @@ -91,7 +91,7 @@ if(1) if(M.health >= 0) if(ishuman(M)) - if(!(M.mobility_flags & MOBILITY_STAND)) + if(M.body_position == LYING_DOWN) user.visible_message("[user] shakes [M] trying to get [M.p_them()] up!", \ "You shake [M] trying to get [M.p_them()] up!") else if(user.is_zone_selected(BODY_ZONE_HEAD, precise_only = TRUE)) @@ -114,7 +114,6 @@ M.electrocute_act(5, "[user]", flags = SHOCK_NOGLOVES) user.visible_message("[user] electrocutes [M] with [user.p_their()] touch!", \ "You electrocute [M] with your touch!") - M.update_mobility() else if(!iscyborg(M)) M.adjustFireLoss(10) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 7b8ad020717bc..f6d0983296766 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -388,7 +388,7 @@ /obj/structure/closet/MouseDrop_T(atom/movable/O, mob/living/user) if(!istype(O) || O.anchored || istype(O, /atom/movable/screen)) return - if(!istype(user) || user.incapacitated() || !(user.mobility_flags & MOBILITY_STAND)) + if(!istype(user) || user.incapacitated() || user.body_position == LYING_DOWN) return if(!Adjacent(user) || !user.Adjacent(O)) return @@ -426,8 +426,8 @@ O.forceMove(T) return TRUE -/obj/structure/closet/relaymove(mob/user) - if(user.stat || !isturf(loc) || !isliving(user)) +/obj/structure/closet/relaymove(mob/living/user, direction) + if(user.stat || !isturf(loc)) return if(locked) if(message_cooldown <= world.time) @@ -440,12 +440,13 @@ . = ..() if(.) return - if(!(user.mobility_flags & MOBILITY_STAND) && get_dist(src, user) > 0) + if(user.body_position == LYING_DOWN && get_dist(src, user) > 0) return if(!toggle(user)) togglelock(user) + /obj/structure/closet/attack_paw(mob/user) return attack_hand(user) diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 41a835ef7681a..edb692aa3e896 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -23,13 +23,14 @@ var/egged = 0 /obj/structure/closet/cardboard/relaymove(mob/living/user, direction) - if(!istype(user) || opened || move_delay || user.incapacitated() || !isturf(loc) || !has_gravity(loc)) + if(opened || move_delay || user.incapacitated() || !isturf(loc) || !has_gravity(loc)) return move_delay = TRUE - if(step(src, direction)) + var/oldloc = loc + if(oldloc != loc) addtimer(CALLBACK(src, PROC_REF(ResetMoveDelay)), CONFIG_GET(number/movedelay/walk_delay) * move_speed_multiplier) else - ResetMoveDelay() + move_delay = FALSE /obj/structure/closet/cardboard/proc/ResetMoveDelay() move_delay = FALSE @@ -77,14 +78,3 @@ close_sound_volume = 50 material_drop = /obj/item/stack/sheet/plasteel #undef SNAKE_SPAM_TICKS - -/obj/structure/closet/cardboard/relaymove(mob/living/user, direction) - if(!istype(user) || opened || move_delay || user.incapacitated() || !isturf(loc) || !has_gravity(loc)) - return - move_delay = TRUE - var/oldloc = loc - step(src, direction) - if(oldloc != loc) - addtimer(CALLBACK(src, PROC_REF(ResetMoveDelay)), CONFIG_GET(number/movedelay/walk_delay) * move_speed_multiplier) - else - move_delay = FALSE diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index a9ad8a66a82a1..d46b64636271b 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -9,7 +9,7 @@ anchored = FALSE density = TRUE max_integrity = 100 - buckle_lying = FALSE + buckle_lying = 0 layer = ABOVE_MOB_LAYER move_resist = MOVE_FORCE_STRONG var/view_range = 2.5 diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 6251008eaebda..f24d4caef73ad 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -48,7 +48,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /obj/structure/bodycontainer/update_icon() return -/obj/structure/bodycontainer/relaymove(mob/user) +/obj/structure/bodycontainer/relaymove(mob/living/user, direction) if(user.stat || !isturf(loc)) return if(locked) @@ -375,7 +375,7 @@ GLOBAL_LIST_EMPTY(crematoriums) return if(isliving(user)) var/mob/living/L = user - if(!(L.mobility_flags & MOBILITY_STAND)) + if(L.body_position == LYING_DOWN) return O.forceMove(src.loc) if (user != O) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 59ba933331159..6448ce0a74dc2 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -561,7 +561,7 @@ smoothing_groups = null canSmoothWith = null can_buckle = 1 - buckle_lying = -1 + buckle_lying = NO_BUCKLE_LYING buckle_requires_restraints = 1 var/mob/living/carbon/human/patient = null var/obj/machinery/computer/operating/computer = null @@ -707,7 +707,7 @@ . = ..() if(.) return - if(!(user.mobility_flags & MOBILITY_STAND) || user.get_num_legs() < 2) + if(user.body_position == LYING_DOWN || user.usable_legs < 2) return user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src, ATTACK_EFFECT_KICK) diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm index 6f5d5463cfb82..35959589b5093 100644 --- a/code/game/objects/structures/target_stake.dm +++ b/code/game/objects/structures/target_stake.dm @@ -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() diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index ddcdb05e101a7..869b85ca5f0bc 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -180,28 +180,32 @@ /obj/structure/transit_tube_pod/transfer_air_ratio(datum/gas_mixture/taker, ratio) return air_contents.transfer_ratio_to(taker, ratio) -/obj/structure/transit_tube_pod/relaymove(mob/mob, direction) - if(istype(mob) && mob.client) - if(!moving) - for(var/obj/structure/transit_tube/station/station in loc) - if(!station.pod_moving) - if(direction == turn(station.boarding_dir,180)) - if(station.open_status == STATION_TUBE_OPEN) - mob.forceMove(loc) - update_icon() - else - station.open_animation() - - else if(direction in station.tube_dirs) - setDir(direction) - station.launch_pod() - return - - for(var/obj/structure/transit_tube/TT in loc) - if(dir in TT.tube_dirs) - if(TT.has_exit(direction)) - setDir(direction) - return + +/obj/structure/transit_tube_pod/relaymove(mob/living/user, direction) + if(!user.client || moving) + return + + for(var/obj/structure/transit_tube/station/station in loc) + if(station.pod_moving) + return + if(direction == turn(station.boarding_dir,180)) + if(station.open_status == STATION_TUBE_OPEN) + user.forceMove(loc) + update_icon() + else + station.open_animation() + else if(direction in station.tube_dirs) + setDir(direction) + station.launch_pod() + return + + for(var/obj/structure/transit_tube/transit_tube in loc) + if(!(dir in transit_tube.tube_dirs)) + continue + if(!transit_tube.has_exit(direction)) + continue + setDir(direction) + return /obj/structure/transit_tube_pod/return_temperature() return air_contents.return_temperature() diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 7705511521ae9..22d7187f89a31 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -553,11 +553,11 @@ Congratulations! You are now trained for invasive xenobiology research!"} return var/mob/living/carbon/C = L if(!C.handcuffed) - if(C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()) + if(C.canBeHandcuffed()) playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2) C.visible_message("[user] begins restraining [C] with [src]!", \ "[user] begins shaping an energy field around your hands!") - if(do_after(user, 3 SECONDS, C) && (C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore())) + if(do_after(user, 3 SECONDS, C) && C.canBeHandcuffed()) if(!C.handcuffed) C.set_handcuffed(new /obj/item/restraints/handcuffs/energy/used(C)) C.update_handcuffed() diff --git a/code/modules/antagonists/abductor/machinery/experiment.dm b/code/modules/antagonists/abductor/machinery/experiment.dm index 0da1bab7e2a6a..403a1e55bce35 100644 --- a/code/modules/antagonists/abductor/machinery/experiment.dm +++ b/code/modules/antagonists/abductor/machinery/experiment.dm @@ -16,8 +16,7 @@ var/breakout_time = 450 /obj/machinery/abductor/experiment/MouseDrop_T(mob/target, mob/user) - var/mob/living/L = user - if(user.stat || (isliving(user) && (!(L.mobility_flags & MOBILITY_STAND) || !(L.mobility_flags & MOBILITY_UI))) || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target)) + if(user.stat != CONSCIOUS || HAS_TRAIT(user, TRAIT_UI_BLOCKED) || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target)) return if(isabductor(target)) return diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm index 13a40871292d9..1d068e1352658 100644 --- a/code/modules/antagonists/changeling/powers/fakedeath.dm +++ b/code/modules/antagonists/changeling/powers/fakedeath.dm @@ -24,7 +24,6 @@ else to_chat(user, "We begin our stasis, preparing energy to arise once more.") user.fakedeath("changeling") //play dead - user.update_mobility() addtimer(CALLBACK(src, PROC_REF(ready_to_regenerate), user.mind), LING_FAKEDEATH_TIME, TIMER_UNIQUE) return TRUE diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm index 787e04af944b6..63ea1ce18d084 100644 --- a/code/modules/antagonists/changeling/powers/regenerate.dm +++ b/code/modules/antagonists/changeling/powers/regenerate.dm @@ -73,7 +73,6 @@ "Our [BP] forms into a horrifying snake and heads towards our attackers!") BP.dismember() BP.Destroy() - C.update_mobility() //Deploy limbsnake var/mob/living/snek = new /mob/living/simple_animal/hostile/poison/limbsnake(get_turf(user)) //assign faction diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 11024cdb515d4..53275e42a6004 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -512,7 +512,7 @@ /obj/item/melee/blood_magic/shackles/afterattack(atom/target, mob/living/carbon/user, proximity) if(iscultist(user) && iscarbon(target) && proximity) var/mob/living/carbon/C = target - if(C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()) + if(C.canBeHandcuffed()) CuffAttack(C, user) else user.visible_message("This victim doesn't have enough arms to complete the restraint!") diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm index 02140568d4254..e8edb05639551 100644 --- a/code/modules/antagonists/devil/true_devil/_true_devil.dm +++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm @@ -19,8 +19,14 @@ spacewalk = TRUE mob_size = MOB_SIZE_LARGE held_items = list(null, null) - bodyparts = list(/obj/item/bodypart/chest/devil, /obj/item/bodypart/head/devil, /obj/item/bodypart/l_arm/devil, - /obj/item/bodypart/r_arm/devil, /obj/item/bodypart/r_leg/devil, /obj/item/bodypart/l_leg/devil) + bodyparts = list( + /obj/item/bodypart/chest/devil, + /obj/item/bodypart/head/devil, + /obj/item/bodypart/l_arm/devil, + /obj/item/bodypart/r_arm/devil, + /obj/item/bodypart/r_leg/devil, + /obj/item/bodypart/l_leg/devil + ) hud_type = /datum/hud/devil var/ascended = FALSE var/mob/living/oldform diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm index 025238b8cdf2f..b1defc3b27bc6 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm @@ -32,7 +32,7 @@ /datum/status_effect/unholy_determination/tick() // The amount we heal of each damage type per tick. If we're missing legs we heal better because we can't dodge. - var/healing_amount = 1 + (2 - owner.get_num_legs()) + var/healing_amount = 1 + (2 - owner.usable_legs) // In softcrit you're, strong enough to stay up. if(owner.health <= owner.crit_threshold && owner.health >= HEALTH_THRESHOLD_FULLCRIT) diff --git a/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm index 7715f45988a4f..b8cc3ee7df2f8 100644 --- a/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm +++ b/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm @@ -38,22 +38,25 @@ route = HERETIC_PATH_SIDE /datum/heretic_knowledge/curse/paralysis/curse(mob/living/carbon/human/chosen_mob) - if(chosen_mob.get_num_legs() <= 0) // What're you gonna do, curse someone who already can't walk? + if(chosen_mob.usable_legs <= 0) // What're you gonna do, curse someone who already can't walk? to_chat(chosen_mob, "You feel a slight pain for a moment, but it passes shortly. Odd.") else - to_chat(chosen_mob, "You suddenly lose feeling in your leg[chosen_mob.get_num_legs() == 1 ? "":"s"]!") + to_chat(chosen_mob, "You suddenly lose feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!") ADD_TRAIT(chosen_mob, TRAIT_PARALYSIS_L_LEG, type) ADD_TRAIT(chosen_mob, TRAIT_PARALYSIS_R_LEG, type) /datum/heretic_knowledge/curse/paralysis/uncurse(mob/living/carbon/human/chosen_mob) + if(QDELETED(chosen_mob)) + return + REMOVE_TRAIT(chosen_mob, TRAIT_PARALYSIS_L_LEG, type) REMOVE_TRAIT(chosen_mob, TRAIT_PARALYSIS_R_LEG, type) - if(chosen_mob.get_num_legs() <= 0) // What're you gonna do, curse someone who already can't walk? + if(chosen_mob.usable_legs <= 0) // What're you gonna do, curse someone who already can't walk? to_chat(chosen_mob, "The slight pain returns, but disperses shortly.") else - to_chat(chosen_mob, "You regain feeling in your leg[chosen_mob.get_num_legs() == 1 ? "":"s"]!") + to_chat(chosen_mob, "You regain feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!") /datum/heretic_knowledge/summon/ashy name = "Ashen Ritual" diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm index 5ac98e68db402..fd4c1bd5423f5 100644 --- a/code/modules/antagonists/revenant/revenant_blight.dm +++ b/code/modules/antagonists/revenant/revenant_blight.dm @@ -29,7 +29,7 @@ /datum/disease/revblight/stage_act() ..() affected_mob.adjustStaminaLoss(1) //Provides gradual exhaustion, but mostly to prevent regeneration and set an upper limit on disease duration to about five minutes - if(!(affected_mob.mobility_flags & MOBILITY_STAND)) + if(affected_mob.body_position == LYING_DOWN) if(HAS_TRAIT_FROM(affected_mob, TRAIT_INCAPACITATED, STAMINA) && !finalstage) stage = 5 if(!startresting || restingat != get_turf(affected_mob)) diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index 494bcf7d613dc..b90cc238e660f 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -462,7 +462,6 @@ user.invisibility = initial(user.invisibility) user.status_flags &= ~GODMODE REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, WARPWHISTLE_TRAIT) - user.update_mobility() /obj/item/warpwhistle/attack_self(mob/living/carbon/user) if(!istype(user) || on_cooldown) diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index fd338255106c6..411269dfffb60 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -72,7 +72,8 @@ if(istype(S)) // Things that *really should always* happen to the shade when it comes out should go here. S.status_flags &= ~GODMODE - S.mobility_flags = MOBILITY_FLAGS_DEFAULT + REMOVE_TRAIT(S, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT) + REMOVE_TRAIT(S, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT) S.cancel_camera() if(theme == THEME_HOLY) S.icon_state = "shade_angelic" @@ -346,7 +347,8 @@ T.dust_animation() var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src) S.status_flags |= GODMODE //So they won't die inside the stone somehow - S.mobility_flags = NONE //Can't move out of the soul stone + ADD_TRAIT(S, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT) + ADD_TRAIT(S, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT) S.name = "Shade of [T.real_name]" S.real_name = "Shade of [T.real_name]" S.key = shade_controller.key diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 4728101cdb604..3ef275765c9ce 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -261,7 +261,7 @@ update_parents() -/obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/user) +/obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/living/user, direction) if(message_cooldown <= world.time) message_cooldown = world.time + 50 to_chat(user, "[src]'s door won't budge!") @@ -271,9 +271,6 @@ on = FALSE for(var/mob/M in contents) //only drop mobs M.forceMove(get_turf(src)) - if(isliving(M)) - var/mob/living/L = M - L.update_mobility() set_occupant(null) flick("pod-open-anim", src) ..() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index c03e608a92018..b0070488a00af 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -2,7 +2,7 @@ var/minimum_temperature_difference = 1 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 hide = TRUE diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm index d01b60d5b508a..fce8afee3f138 100644 --- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm +++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm @@ -129,12 +129,12 @@ back_nodes[i] = null update_appearance() -/obj/machinery/atmospherics/pipe/layer_manifold/relaymove(mob/living/user, dir) - if(initialize_directions & dir) +/obj/machinery/atmospherics/pipe/layer_manifold/relaymove(mob/living/user, direction) + if(initialize_directions & direction) return ..() - if((NORTH|EAST) & dir) + if((NORTH|EAST) & direction) user.ventcrawl_layer = clamp(user.ventcrawl_layer + 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX) - if((SOUTH|WEST) & dir) + if((SOUTH|WEST) & direction) user.ventcrawl_layer = clamp(user.ventcrawl_layer - 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX) to_chat(user, "You align yourself with the [user.ventcrawl_layer]\th output.") diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index 4ace48b93e9cf..1258f5504392b 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -10,13 +10,13 @@ //Buckling can_buckle = 1 buckle_requires_restraints = 1 - buckle_lying = -1 + buckle_lying = NO_BUCKLE_LYING FASTDMM_PROP(\ set_instance_vars(\ icon_state = INSTANCE_VAR_DEFAULT\ - ),\ - ) + ),\ + ) /obj/machinery/atmospherics/pipe/New() add_atom_colour(pipe_color, FIXED_COLOUR_PRIORITY) diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm index 7b27d3609fb2d..7efa781d7818b 100644 --- a/code/modules/fields/timestop.dm +++ b/code/modules/fields/timestop.dm @@ -146,7 +146,7 @@ /datum/proximity_monitor/advanced/timestop/process() for(var/i in frozen_mobs) var/mob/living/m = i - m.Stun(20, 1, 1) + m.Stun(20, ignore_canstun = TRUE) /datum/proximity_monitor/advanced/timestop/setup_field_turf(turf/T) for(var/i in T.contents) @@ -165,7 +165,7 @@ if(L.anti_magic_check(check_anti_magic, check_holy)) immune += L return - L.Stun(20, 1, 1) + L.Stun(20, ignore_canstun = TRUE) SSmove_manager.stop_looping(src) //stops them mid pathing even if they're stunimmune //This is really dumb if(isanimal(L)) var/mob/living/simple_animal/S = L @@ -175,7 +175,7 @@ H.LoseTarget() /datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L) - L.AdjustStun(-20, 1, 1) + L.AdjustStun(-20, ignore_canstun = TRUE) frozen_mobs -= L if(isanimal(L)) var/mob/living/simple_animal/S = L diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 62a221e032ede..829315e552629 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -57,7 +57,7 @@ /obj/machinery/gibber/container_resist(mob/living/user) go_out() -/obj/machinery/gibber/relaymove(mob/living/user) +/obj/machinery/gibber/relaymove(mob/living/user, direction) go_out() /obj/machinery/gibber/attack_hand(mob/user) diff --git a/code/modules/mining/aux_base_camera.dm b/code/modules/mining/aux_base_camera.dm index 186904ea06743..747fbe11bc53f 100644 --- a/code/modules/mining/aux_base_camera.dm +++ b/code/modules/mining/aux_base_camera.dm @@ -16,9 +16,10 @@ return ..() //While players are only allowed to build in the base area, but consoles starting outside the base can move into the base area to begin work. -/mob/camera/ai_eye/remote/base_construction/relaymove(mob/user, direct) - dir = direct //This camera eye is visible as a drone, and needs to keep the dir updated - ..() + +/mob/camera/ai_eye/remote/base_construction/relaymove(mob/living/user, direction) + dir = direction //This camera eye is visible as a drone, and needs to keep the dir updated + return ..() /obj/item/construction/rcd/internal //Base console's internal RCD. Roundstart consoles are filled, rebuilt cosoles start empty. name = "internal RCD" diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 70fc560d7c1ee..7851d62ac9e6a 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -27,9 +27,9 @@ /mob/proc/get_item_for_held_index(i) - if(!length(held_items)) - return null - return held_items[i] + if(!length(held_items)) + return null + return held_items[i] //Odd = left. Even = right /mob/proc/held_index_to_dir(i) @@ -507,7 +507,7 @@ var/obj/item/bodypart/BP = new path () BP.owner = src BP.held_index = i - bodyparts += BP + add_bodypart(BP) hand_bodyparts[i] = BP ..() //Don't redraw hands until we have organs for them diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 6faef22b7178b..e853c16df621a 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -134,14 +134,13 @@ // copied from simplemobs /mob/living/basic/revive(full_heal = 0, admin_revive = 0) - if(..()) //successfully ressuscitated from death - icon = initial(icon) - icon_state = icon_living - set_density(initial(density)) - mobility_flags = MOBILITY_FLAGS_DEFAULT - update_mobility() - . = 1 - setMovetype(initial(movement_type)) + . = ..() + if(!.) + return + icon = initial(icon) + icon_state = icon_living + density = initial(density) + setMovetype(initial(movement_type)) /mob/living/basic/proc/melee_attack(atom/target) src.face_atom(target) diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index 48d30725dfe27..d909cea4e0eb2 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -8,7 +8,7 @@ invisibility = 60 resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF -/obj/effect/dummy/phased_mob/slaughter/relaymove(mob/user, direction) +/obj/effect/dummy/phased_mob/slaughter/relaymove(mob/living/user, direction) forceMove(get_step(src,direction)) /obj/effect/dummy/phased_mob/slaughter/ex_act() diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm index 9856506f8e6f9..1cd2ac78d6863 100644 --- a/code/modules/mob/living/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -24,7 +24,7 @@ if(iscyborg(loc)) var/mob/living/silicon/robot/borg = loc borg.mmi = null - mecha = null + set_mecha(null) QDEL_NULL(brainmob) QDEL_NULL(brain) QDEL_NULL(radio) @@ -68,7 +68,7 @@ log_attack("[key_name(user)] inserted [newbrain] into \the [src] at [AREACOORD(src)].") SEND_SIGNAL(src, COMSIG_MMI_SET_BRAINMOB, newbrain.brainmob) - brainmob = newbrain.brainmob + set_brainmob(newbrain.brainmob) newbrain.brainmob = null brainmob.forceMove(src) brainmob.container = src @@ -144,7 +144,7 @@ brain.organ_flags |= ORGAN_FROZEN brain.transfer_identity(L) - brainmob = brain.brainmob + set_brainmob(brain.brainmob) brainmob.container = src brain.name = "[L.real_name]'s brain" @@ -152,6 +152,39 @@ update_icon() return +/// Proc to hook behavior associated to the change in value of the [/obj/item/mmi/var/brainmob] variable. +/obj/item/mmi/proc/set_brainmob(mob/living/brain/new_brainmob) + if(brainmob == new_brainmob) + return FALSE + . = brainmob + brainmob = new_brainmob + if(new_brainmob) + if(mecha) + REMOVE_TRAIT(new_brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED) + REMOVE_TRAIT(new_brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED) + else + ADD_TRAIT(new_brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED) + ADD_TRAIT(new_brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED) + if(.) + var/mob/living/brain/old_brainmob = . + ADD_TRAIT(old_brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED) + ADD_TRAIT(old_brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED) + + +/// Proc to hook behavior associated to the change in value of the [obj/vehicle/sealed/var/mecha] variable. +/obj/item/mmi/proc/set_mecha(obj/vehicle/sealed/mecha/new_mecha) + if(mecha == new_mecha) + return FALSE + . = mecha + mecha = new_mecha + if(new_mecha) + if(!. && brainmob) // There was no mecha, there now is, and we have a brain mob that is no longer unaided. + REMOVE_TRAIT(brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED) + REMOVE_TRAIT(brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED) + else if(. && brainmob) // There was a mecha, there no longer is one, and there is a brain mob that is now again unaided. + ADD_TRAIT(brainmob, TRAIT_IMMOBILIZED, BRAIN_UNAIDED) + ADD_TRAIT(brainmob, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED) + /obj/item/mmi/proc/replacement_ai_name() return brainmob.name @@ -206,7 +239,7 @@ else . += "The MMI indicates the brain is active." -/obj/item/mmi/relaymove(mob/user) +/obj/item/mmi/relaymove(mob/living/user, direction) return //so that the MMI won't get a warning about not being able to move if it tries to move /obj/item/mmi/proc/brain_check(mob/user) diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 1bc31d5427f68..ef41226772bf9 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -16,6 +16,9 @@ var/obj/item/organ/brain/OB = new(loc) //we create a new brain organ for it. OB.brainmob = src forceMove(OB) + if(!container?.mecha) //Unless inside a mecha, brains are rather helpless. + ADD_TRAIT(src, TRAIT_IMMOBILIZED, BRAIN_UNAIDED) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, BRAIN_UNAIDED) /mob/living/brain/proc/create_dna() @@ -35,12 +38,6 @@ QDEL_NULL(stored_dna) return ..() -/mob/living/brain/update_mobility() - if(in_contents_of(/obj/vehicle/sealed/mecha)) - mobility_flags = MOBILITY_FLAGS_DEFAULT - else - mobility_flags = NONE - /mob/living/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up. return diff --git a/code/modules/mob/living/brain/posibrain.dm b/code/modules/mob/living/brain/posibrain.dm index 352a37cf114dc..a8e4655e2276e 100644 --- a/code/modules/mob/living/brain/posibrain.dm +++ b/code/modules/mob/living/brain/posibrain.dm @@ -9,9 +9,7 @@ GLOBAL_VAR(posibrain_notify_cooldown) var/next_ask var/askDelay = 600 //one minute var/searching = FALSE - brainmob = null req_access = list(ACCESS_ROBOTICS) - mecha = null//This does not appear to be used outside of reference in mecha.dm. braintype = "Android" var/autoping = TRUE //if it pings on creation immediately var/begin_activation_message = "You carefully locate the manual activation switch and start the positronic brain's boot process." @@ -42,7 +40,7 @@ GLOBAL_VAR(posibrain_notify_cooldown) /obj/item/mmi/posibrain/attack_self(mob/user) if(!brainmob) - brainmob = new(src) + set_brainmob(new /mob/living/brain(src)) if(!(GLOB.ghost_role_flags & GHOSTROLE_SILICONS)) to_chat(user, "Central Command has temporarily outlawed posibrain sentience in this sector...") return @@ -171,7 +169,7 @@ GLOBAL_VAR(posibrain_notify_cooldown) /obj/item/mmi/posibrain/Initialize(mapload) . = ..() - brainmob = new(src) + set_brainmob(new /mob/living/brain(src)) var/new_name if(!LAZYLEN(possible_names)) new_name = pick(GLOB.posibrain_names) @@ -184,6 +182,7 @@ GLOBAL_VAR(posibrain_notify_cooldown) if(autoping) ping_ghosts("created", TRUE) + /obj/item/mmi/posibrain/attackby(obj/item/O, mob/user) return diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 4d216614734a0..594fb65d2a303 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -25,7 +25,8 @@ /mob/living/carbon/alien/Initialize(mapload) add_verb(/mob/living/proc/mob_sleep) - add_verb(/mob/living/proc/lay_down) + add_verb(/mob/living/proc/toggle_resting) + create_bodyparts() //initialize bodyparts create_internal_organs() return ..() @@ -104,6 +105,8 @@ Des: Removes all infected images from the alien. return /mob/living/carbon/alien/canBeHandcuffed() + if(num_hands < 2) + return FALSE return TRUE /mob/living/carbon/alien/proc/alien_evolve(mob/living/carbon/alien/new_xeno) @@ -119,3 +122,11 @@ Des: Removes all infected images from the alien. /mob/living/carbon/alien/can_hold_items() return has_fine_manipulation + +/mob/living/carbon/alien/on_lying_down(new_lying_angle) + . = ..() + update_icons() + +/mob/living/carbon/alien/on_standing_up() + . = ..() + update_icons() diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 3a80e4617dadc..1b024ec6aa2b5 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -29,7 +29,7 @@ #define MAX_ALIEN_LEAP_DIST 7 /mob/living/carbon/alien/humanoid/hunter/proc/leap_at(atom/A) - if((mobility_flags & (MOBILITY_MOVE | MOBILITY_STAND)) != (MOBILITY_MOVE | MOBILITY_STAND) || leaping) + if(body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_IMMOBILIZED) || leaping) return if(!(COOLDOWN_FINISHED(src, pounce_cooldown))) @@ -77,17 +77,16 @@ sleep(0.2 SECONDS)//Runtime prevention (infinite bump() calls on hulks) step_towards(src, L) else - Paralyze(40, 1, 1) + Paralyze(40, ignore_canstun = TRUE) toggle_leap(FALSE) else if(hit_atom.density && !hit_atom.CanPass(src, get_dir(hit_atom, src))) visible_message("[src] smashes into [hit_atom]!", "[src] smashes into [hit_atom]!") - Paralyze(40, 1, 1) + Paralyze(40, ignore_canstun = TRUE) if(leaping) //check that toggles out of leaping mode if the alien gets hit or otherwise interrupted leaping = FALSE update_icons() - update_mobility() /mob/living/carbon/alien/humanoid/float(on) if(leaping) diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 8fab76f902be7..1b19cd7eb2b4e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -7,8 +7,14 @@ limb_destroyer = TRUE hud_type = /datum/hud/alien deathsound = 'sound/voice/hiss6.ogg' - bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien, - /obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien) + bodyparts = list( + /obj/item/bodypart/chest/alien, + /obj/item/bodypart/head/alien, + /obj/item/bodypart/l_arm/alien, + /obj/item/bodypart/r_arm/alien, + /obj/item/bodypart/r_leg/alien, + /obj/item/bodypart/l_leg/alien, + ) var/caste = "" var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files. var/leap_on_click = FALSE diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm index b21d8a356b2c1..42264f2534440 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -17,7 +17,7 @@ else if(leap_on_click) icon_state = "alien[caste]_pounce" - else if(!(mobility_flags & MOBILITY_STAND)) + else if(body_position == LYING_DOWN) icon_state = "alien[caste]_sleep" else if(mob_size == MOB_SIZE_LARGE) icon_state = "alien[caste]" diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 0a1f7f00083a3..2702d366724b5 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -11,12 +11,22 @@ health = 25 hardcrit_threshold = HEALTH_THRESHOLD_CRIT + rotate_on_lying = FALSE + + default_num_legs = 1 + num_legs = 1 //Alien larvas always have a movable apendage. + usable_legs = 1 //Alien larvas always have a movable apendage. + default_num_hands = 0 + + bodyparts = list( + /obj/item/bodypart/chest/larva, + /obj/item/bodypart/head/larva, + ) + var/amount_grown = 0 var/max_grown = 100 var/time_of_birth - rotate_on_lying = 0 - bodyparts = list(/obj/item/bodypart/chest/larva, /obj/item/bodypart/head/larva) flavor_text = FLAVOR_TEXT_EVIL playable = TRUE @@ -63,3 +73,6 @@ /mob/living/carbon/alien/larva/stripPanelEquip(obj/item/what, mob/who) to_chat(src, "You don't have the dexterity to do this!") return + +/mob/living/carbon/alien/larva/canBeHandcuffed() + return TRUE diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index fe53dfa71772e..1eb88506709c9 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -24,6 +24,5 @@ if(stat == UNCONSCIOUS) set_resting(FALSE) set_stat(CONSCIOUS) - update_mobility() update_damage_hud() update_health_hud() diff --git a/code/modules/mob/living/carbon/alien/larva/update_icons.dm b/code/modules/mob/living/carbon/alien/larva/update_icons.dm index 983544e8c72e9..24734a31851c5 100644 --- a/code/modules/mob/living/carbon/alien/larva/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/larva/update_icons.dm @@ -14,10 +14,10 @@ icon_state = "larva[state]_dead" else if(handcuffed || legcuffed) //This should be an overlay. Who made this an icon_state? icon_state = "larva[state]_cuff" - else if(!(mobility_flags & MOBILITY_STAND)) - icon_state = "larva[state]_sleep" - else if(IsStun()) + else if(HAS_TRAIT(src, TRAIT_INCAPACITATED)) icon_state = "larva[state]_stun" + else if(body_position == LYING_DOWN) + icon_state = "larva[state]_sleep" else icon_state = "larva[state]" @@ -28,4 +28,5 @@ /mob/living/carbon/alien/larva/update_inv_handcuffed() update_icons() //larva icon_state changes if cuffed/uncuffed. - +/mob/living/carbon/alien/larva/lying_angle_on_lying_down(new_lying_angle) + return // Larvas don't rotate on lying down, they have their own custom icons. diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index c7ff101a5236c..a54238d10635f 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -102,17 +102,20 @@ var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc) new_xeno.key = ghost.key SEND_SOUND(new_xeno, sound('sound/voice/hiss5.ogg',0,0,0,100)) //To get the player's attention - new_xeno.mobility_flags = NONE //so we don't move during the bursting animation + ADD_TRAIT(new_xeno, TRAIT_IMMOBILIZED, type) //so we don't move during the bursting animation + ADD_TRAIT(new_xeno, TRAIT_HANDS_BLOCKED, type) new_xeno.notransform = 1 new_xeno.invisibility = INVISIBILITY_MAXIMUM sleep(6) if(QDELETED(src) || QDELETED(owner)) - return + qdel(new_xeno) + CRASH("AttemptGrow failed due to the early qdeletion of source or owner.") if(new_xeno) - new_xeno.mobility_flags = MOBILITY_FLAGS_DEFAULT + REMOVE_TRAIT(new_xeno, TRAIT_IMMOBILIZED, type) + REMOVE_TRAIT(new_xeno, TRAIT_HANDS_BLOCKED, type) new_xeno.notransform = 0 new_xeno.invisibility = 0 diff --git a/code/modules/mob/living/carbon/alien/status_procs.dm b/code/modules/mob/living/carbon/alien/status_procs.dm index 0affc187a12f0..cd8ada8bd7adf 100644 --- a/code/modules/mob/living/carbon/alien/status_procs.dm +++ b/code/modules/mob/living/carbon/alien/status_procs.dm @@ -4,17 +4,17 @@ /////////////////////////////////// STUN //////////////////////////////////// -/mob/living/carbon/alien/Stun(amount, updating = 1, ignore_canstun = 0) +/mob/living/carbon/alien/Stun(amount, ignore_canstun = FALSE) . = ..() if(!.) move_delay_add = min(move_delay_add + round(amount / 2), 10) //a maximum delay of 10 -/mob/living/carbon/alien/SetStun(amount, updating = 1, ignore_canstun = 0) +/mob/living/carbon/alien/SetStun(amount, ignore_canstun = FALSE) . = ..() if(!.) move_delay_add = min(move_delay_add + round(amount / 2), 10) -/mob/living/carbon/alien/AdjustStun(amount, updating = 1, ignore_canstun = 0) +/mob/living/carbon/alien/AdjustStun(amount, ignore_canstun = FALSE) . = ..() if(!.) move_delay_add = clamp(move_delay_add + round(amount/2), 0, 10) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index a143200fd1f8e..82ca66a8cb04d 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -61,7 +61,7 @@ /mob/living/carbon/attackby(obj/item/I, mob/user, params) for(var/datum/surgery/S in surgeries) - if(!(mobility_flags & MOBILITY_STAND) || !S.lying_required) + if(body_position == LYING_DOWN || !S.lying_required) if((S.self_operable || user != src) && (user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)) if(S.next_step(user,user.a_intent)) return TRUE @@ -236,7 +236,7 @@ /mob/living/carbon/resist_fire() fire_stacks -= 5 - Paralyze(60, TRUE, TRUE) + Paralyze(60, ignore_canstun = TRUE) spin(32,2) visible_message("[src] rolls on the floor, trying to put [p_them()]self out!", \ "You stop, drop, and roll!") @@ -326,21 +326,23 @@ /mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break) if(!I.loc || buckled) - return + return FALSE + if(I != handcuffed && I != legcuffed) + return FALSE visible_message("[src] manages to [cuff_break ? "break" : "remove"] [I]!") to_chat(src, "You successfully [cuff_break ? "break" : "remove"] [I].") if(cuff_break) . = !((I == handcuffed) || (I == legcuffed)) qdel(I) - return + return TRUE else if(I == handcuffed) handcuffed.forceMove(drop_location()) set_handcuffed(null) I.dropped(src) - if(buckled && buckled.buckle_requires_restraints) + if(buckled?.buckle_requires_restraints) buckled.unbuckle_mob(src) update_handcuffed() return @@ -349,10 +351,8 @@ legcuffed = null I.dropped(src) update_inv_legcuffed() - return - else - dropItemToGround(I) - return + return TRUE + /mob/living/carbon/proc/accident(obj/item/I) if(!I || (I.item_flags & ABSTRACT) || HAS_TRAIT(I, TRAIT_NODROP)) @@ -474,9 +474,11 @@ if(dna) dna.real_name = real_name -/mob/living/carbon/update_mobility() +/mob/living/carbon/set_body_position(new_value) . = ..() - if(!(mobility_flags & MOBILITY_STAND)) + if(isnull(.)) + return + if(new_value == LYING_DOWN) add_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling) else remove_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling) @@ -495,7 +497,6 @@ set_health(round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION)) staminaloss = round(total_stamina, DAMAGE_PRECISION) update_stat() - update_mobility() if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD*2) && stat == DEAD ) become_husk("burn") med_hud_set_health() @@ -509,7 +510,7 @@ /mob/living/carbon/update_stamina(extend_stam_crit = FALSE) var/stam = getStaminaLoss() if(stam >= DAMAGE_PRECISION && (maxHealth - stam) <= crit_threshold && !stat && !HAS_TRAIT(src, TRAIT_NOSTAMCRIT)) - if(extend_stam_crit || !HAS_TRAIT_FROM(src, TRAIT_INCAPACITATED, STAMINA)) + if(!stat) enter_stamcrit() else if(HAS_TRAIT_FROM(src, TRAIT_INCAPACITATED, STAMINA)) REMOVE_TRAIT(src, TRAIT_INCAPACITATED, STAMINA) @@ -768,7 +769,6 @@ if(!is_blind()) var/datum/component/blind_sense/B = GetComponent(/datum/component/blind_sense) B?.RemoveComponent() - update_mobility() update_damage_hud() update_health_hud() med_hud_set_status() @@ -786,7 +786,7 @@ update_action_buttons_icon() //some of our action buttons might be unusable when we're handcuffed. update_inv_handcuffed() update_hud_handcuffed() - update_mobility() + /mob/living/carbon/heal_and_revive(heal_to = 75, revive_message) // We can't heal them if they're missing a heart @@ -873,29 +873,57 @@ /mob/living/carbon/proc/create_bodyparts() var/l_arm_index_next = -1 var/r_arm_index_next = 0 - for(var/X in bodyparts) - var/obj/item/bodypart/O = new X() - O.owner = src - bodyparts.Remove(X) - bodyparts.Add(O) - if(O.body_part == ARM_LEFT) - l_arm_index_next += 2 - O.held_index = l_arm_index_next //1, 3, 5, 7... - hand_bodyparts += O - else if(O.body_part == ARM_RIGHT) - r_arm_index_next += 2 - O.held_index = r_arm_index_next //2, 4, 6, 8... - hand_bodyparts += O + for(var/bodypart_path in bodyparts) + var/obj/item/bodypart/bodypart_instance = new bodypart_path() + bodypart_instance.set_owner(src) + bodyparts.Remove(bodypart_path) + add_bodypart(bodypart_instance) + switch(bodypart_instance.body_part) + if(ARM_LEFT) + l_arm_index_next += 2 + bodypart_instance.held_index = l_arm_index_next //1, 3, 5, 7... + hand_bodyparts += bodypart_instance + if(ARM_RIGHT) + r_arm_index_next += 2 + bodypart_instance.held_index = r_arm_index_next //2, 4, 6, 8... + hand_bodyparts += bodypart_instance + + +///Proc to hook behavior on bodypart additions. +/mob/living/carbon/proc/add_bodypart(obj/item/bodypart/new_bodypart) + bodyparts += new_bodypart + new_bodypart.set_owner(src) + + switch(new_bodypart.body_part) + if(LEG_LEFT, LEG_RIGHT) + set_num_legs(num_legs + 1) + if(!new_bodypart.bodypart_disabled) + set_usable_legs(usable_legs + 1) + if(ARM_LEFT, ARM_RIGHT) + set_num_hands(num_hands + 1) + if(!new_bodypart.bodypart_disabled) + set_usable_hands(usable_hands + 1) + + +///Proc to hook behavior on bodypart removals. +/mob/living/carbon/proc/remove_bodypart(obj/item/bodypart/old_bodypart) + bodyparts -= old_bodypart + + switch(old_bodypart.body_part) + if(LEG_LEFT, LEG_RIGHT) + set_num_legs(num_legs - 1) + if(!old_bodypart.bodypart_disabled) + set_usable_legs(usable_legs - 1) + if(ARM_LEFT, ARM_RIGHT) + set_num_hands(num_hands - 1) + if(!old_bodypart.bodypart_disabled) + set_usable_hands(usable_hands - 1) /mob/living/carbon/proc/create_internal_organs() for(var/X in internal_organs) var/obj/item/organ/I = X I.Insert(src) -/mob/living/carbon/proc/update_disabled_bodyparts() - for(var/obj/item/bodypart/BP as() in bodyparts) - BP.update_disabled() - /mob/living/carbon/vv_get_dropdown() . = ..() VV_DROPDOWN_OPTION("", "---------") @@ -1151,7 +1179,19 @@ 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) + + +/mob/living/carbon/on_lying_down(new_lying_angle) + . = ..() + if(!buckled || buckled.buckle_lying != 0) + lying_angle_on_lying_down(new_lying_angle) + + +/// Special carbon interaction on lying down, to transform its sprite by a rotation. +/mob/living/carbon/proc/lying_angle_on_lying_down(new_lying_angle) + if(!new_lying_angle) + set_lying_angle(pick(90, 270)) + else + set_lying_angle(new_lying_angle) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 5e5901766ed86..1188bf081fead 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -351,6 +351,8 @@ AdjustParalyzed(-60) AdjustImmobilized(-60) set_resting(FALSE) + if(body_position != STANDING_UP && !resting && !buckled && !HAS_TRAIT(src, TRAIT_FLOORED)) + get_up(TRUE) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1) diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 6c0a149f894cc..f8b65dad3234a 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -5,6 +5,10 @@ hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,GLAND_HUD,NANITE_HUD,DIAG_NANITE_FULL_HUD) has_limbs = 1 held_items = list(null, null) + num_legs = 0 //Populated on init through list/bodyparts + usable_legs = 0 //Populated on init through list/bodyparts + num_hands = 0 //Populated on init through list/bodyparts + usable_hands = 0 //Populated on init through list/bodyparts var/list/internal_organs = list() //List of /obj/item/organ in the mob. They don't go in the contents for some reason I don't want to know. var/list/internal_organs_slot= list() //Same as above, but stores "slot ID" - "organ" pairs for easy access. var/silent = FALSE //Can't talk. Value goes down every life proc. //NOTE TO FUTURE CODERS: DO NOT INITIALIZE NUMERICAL VARS AS NULL OR I WILL MURDER YOU. diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm index ee3e69b02cafd..33b556e736336 100644 --- a/code/modules/mob/living/carbon/carbon_movement.dm +++ b/code/modules/mob/living/carbon/carbon_movement.dm @@ -28,3 +28,55 @@ adjust_nutrition(-(HUNGER_FACTOR/10)) if(m_intent == MOVE_INTENT_RUN) adjust_nutrition(-(HUNGER_FACTOR/10)) + +/mob/living/carbon/set_usable_legs(new_value) + . = ..() + if(isnull(.)) + return + if(. == 0) + if(usable_legs != 0) //From having no usable legs to having some. + REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + else if(usable_legs == 0 && !(movement_type & (FLYING | FLOATING))) //From having usable legs to no longer having them. + ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + if(!usable_hands) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + + +/mob/living/carbon/set_usable_hands(new_value) + . = ..() + if(isnull(.)) + return + if(. == 0) + REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, LACKING_MANIPULATION_APPENDAGES_TRAIT) + if(usable_hands != 0) //From having no usable hands to having some. + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + else if(usable_hands == 0 && default_num_hands > 0) //From having usable hands to no longer having them. + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, LACKING_MANIPULATION_APPENDAGES_TRAIT) + if(!usable_legs && !(movement_type & (FLYING | FLOATING))) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + + +/mob/living/carbon/setMovetype(newval) + . = ..() + if(isnull(.)) + return + 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))) //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) diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 6d1d236fa8e86..5b817e0757e12 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -37,8 +37,8 @@ var/list/msg = list("") var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) var/list/disabled = list() - for(var/obj/item/bodypart/BP as() in bodyparts) - if(BP.disabled) + for(var/obj/item/bodypart/BP as anything in bodyparts) + if(BP.bodypart_disabled) disabled += BP missing -= BP.body_zone for(var/obj/item/I in BP.embedded_objects) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 15d16372a1a4d..c755e27290862 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -59,9 +59,8 @@ if(gloves && !(obscured & ITEM_SLOT_GLOVES) && !(gloves.item_flags & EXAMINE_SKIP)) . += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands." else if(FR && length(FR.blood_DNA)) - var/hand_number = get_num_arms(FALSE) - if(hand_number) - . += "[t_He] [t_has] [hand_number > 1 ? "" : "a"] blood-stained hand[hand_number > 1 ? "s" : ""]!" + if(num_hands) + . += "[t_He] [t_has] [num_hands > 1 ? "" : "a"] blood-stained hand[num_hands > 1 ? "s" : ""]!" //belt if(belt && !(belt.item_flags & EXAMINE_SKIP)) @@ -136,7 +135,7 @@ var/list/disabled = list() for(var/obj/item/bodypart/BP as() in bodyparts) - if(BP.disabled) + if(BP.bodypart_disabled) disabled += BP missing -= BP.body_zone for(var/obj/item/I in BP.embedded_objects) @@ -146,13 +145,17 @@ msg += "[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [BP.name]!\n" for(var/X in disabled) - var/obj/item/bodypart/BP = X + var/obj/item/bodypart/body_part = X var/damage_text - if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //Stamina is disabling the limb + /* + if(HAS_TRAIT(body_part, TRAIT_DISABLED_BY_WOUND)) + continue // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!) + */ + if(!(body_part.get_damage(include_stamina = FALSE) >= body_part.max_damage)) //we don't care if it's stamcritted damage_text = "limp and lifeless" else - damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg - msg += "[capitalize(t_his)] [BP.name] is [damage_text]!\n" + damage_text = (body_part.brute_dam >= body_part.burn_dam) ? body_part.heavy_brute_msg : body_part.heavy_burn_msg + msg += "[capitalize(t_his)] [body_part.name] is [damage_text]!\n" //stores missing limbs var/l_limbs_missing = 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 824df2dcefaa2..554a602578b66 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -7,7 +7,7 @@ /mob/living/carbon/human/Initialize(mapload) add_verb(/mob/living/proc/mob_sleep) - add_verb(/mob/living/proc/lay_down) + add_verb(/mob/living/proc/toggle_resting) icon_state = "" //Remove the inherent human icon that is visible on the map editor. We're rendering ourselves limb by limb, having it still be there results in a bug where the basic human icon appears below as south in all directions and generally looks nasty. @@ -1030,7 +1030,7 @@ return (istype(target) && target.stat == CONSCIOUS && (target.mobility_flags & MOBILITY_STAND)) /mob/living/carbon/human/proc/can_be_firemanned(mob/living/carbon/target) - return ((ishuman(target) || ismonkey(target)) && !(target.mobility_flags & MOBILITY_STAND)) + return ((ishuman(target) || ismonkey(target)) && target.body_position == LYING_DOWN) /mob/living/carbon/human/proc/fireman_carry(mob/living/carbon/target) var/carrydelay = 50 //if you have latex you are faster at grabbing diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index dea570726a922..fc2801bf06906 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -647,6 +647,9 @@ missing -= LB.body_zone if(LB.is_pseudopart) //don't show injury text for fake bodyparts; ie chainsaw arms or synthetic armblades continue + var/self_aware = FALSE + if(HAS_TRAIT(src, TRAIT_SELF_AWARE)) + self_aware = TRUE var/limb_max_damage = LB.max_damage var/status = "" var/brutedamage = LB.brute_dam @@ -684,7 +687,14 @@ var/no_damage if(status == "OK" || status == "no damage") no_damage = TRUE - to_chat(src, "\t Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].") + var/isdisabled = " " + if(LB.bodypart_disabled) + isdisabled = " is disabled " + if(no_damage) + isdisabled += " but otherwise " + else + isdisabled += " and " + to_chat(src, "\t Your [LB.name][isdisabled][self_aware ? " has " : " is "][status].") for(var/obj/item/I in LB.embedded_objects) if(I.isEmbedHarmless()) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 08d190c2f4999..f268c0dae5a83 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -1,8 +1,7 @@ /mob/living/carbon/human/canBeHandcuffed() - if(get_num_arms(FALSE) >= 2) - return TRUE - else + if(num_hands < 2) return FALSE + return TRUE //gets assignment from ID or ID inside PDA or PDA itself //Useful when player do something with computers diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index e6de200042cbb..6a4e59b5da79e 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -42,7 +42,7 @@ /mob/living/carbon/human/Move(NewLoc, direct) . = ..() - if(shoes && (mobility_flags & MOBILITY_STAND) && loc == NewLoc && has_gravity(loc)) + if(shoes && body_position == STANDING_UP && loc == NewLoc && has_gravity(loc)) SEND_SIGNAL(shoes, COMSIG_SHOES_STEP_ACTION) /mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee. diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index fd0ce7c60b9a5..c235f766776a4 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -119,7 +119,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() @@ -167,7 +166,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 diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index e0d3382477e21..bfb786627edee 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -806,7 +806,7 @@ GLOBAL_LIST_EMPTY(features_by_species) else standing += mutable_appearance(undershirt.icon, undershirt.icon_state, CALCULATE_MOB_OVERLAY_LAYER(BODY_LAYER)) - if(H.socks && H.get_num_legs(FALSE) >= 2 && !(H.dna.species.bodytype & BODYTYPE_DIGITIGRADE) && !(NOSOCKS in species_traits)) + if(H.socks && H.num_legs >= 2 && !(H.dna.species.bodytype & BODYTYPE_DIGITIGRADE) && !(NOSOCKS in species_traits)) var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks] if(socks) standing += mutable_appearance(socks.icon, socks.icon_state, CALCULATE_MOB_OVERLAY_LAYER(BODY_LAYER)) @@ -1113,8 +1113,6 @@ GLOBAL_LIST_EMPTY(features_by_species) if(I.species_restricted & H.dna?.species.bodyflag) to_chat(H, "Your species cannot wear this item!") return FALSE - var/num_arms = H.get_num_arms(FALSE) - var/num_legs = H.get_num_legs(FALSE) switch(slot) if(ITEM_SLOT_HANDS) @@ -1152,7 +1150,7 @@ GLOBAL_LIST_EMPTY(features_by_species) return FALSE if( !(I.slot_flags & ITEM_SLOT_GLOVES) ) return FALSE - if(num_arms < 2) + if(H.num_hands < 2) return FALSE return equip_delay_self_check(I, H, bypass_equip_delay_self) if(ITEM_SLOT_FEET) @@ -1160,7 +1158,7 @@ GLOBAL_LIST_EMPTY(features_by_species) return FALSE if( !(I.slot_flags & ITEM_SLOT_FEET) ) return FALSE - if(num_legs < 2) + if(H.num_legs < 2) return FALSE if((bodytype & BODYTYPE_DIGITIGRADE) && !(I.supports_variations & DIGITIGRADE_VARIATION)) if(!disable_warning) @@ -1279,7 +1277,7 @@ GLOBAL_LIST_EMPTY(features_by_species) return FALSE if(!istype(I, /obj/item/restraints/handcuffs)) return FALSE - if(num_arms < 2) + if(H.num_legs < 2) return FALSE return TRUE if(ITEM_SLOT_LEGCUFFED) @@ -1287,7 +1285,7 @@ GLOBAL_LIST_EMPTY(features_by_species) return FALSE if(!istype(I, /obj/item/restraints/legcuffs)) return FALSE - if(num_legs < 2) + if(H.num_legs < 2) return FALSE return TRUE if(ITEM_SLOT_BACKPACK) @@ -1538,11 +1536,11 @@ GLOBAL_LIST_EMPTY(features_by_species) return /datum/species/proc/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) - if(!((target.health < 0 || HAS_TRAIT(target, TRAIT_FAKEDEATH)) && !(target.mobility_flags & MOBILITY_STAND))) + if(target.body_position == STANDING_UP || (target.health >= 0 && !HAS_TRAIT(target, TRAIT_FAKEDEATH))) target.help_shake_act(user) if(target != user) log_combat(user, target, "shaken") - return 1 + return TRUE else var/we_breathe = !HAS_TRAIT(user, TRAIT_NOBREATH) var/we_lung = user.getorganslot(ORGAN_SLOT_LUNGS) @@ -1563,7 +1561,7 @@ GLOBAL_LIST_EMPTY(features_by_species) return TRUE else //Steal them shoes - if(!(target.mobility_flags & MOBILITY_STAND) && (user.is_zone_selected(BODY_ZONE_L_LEG) || user.is_zone_selected(BODY_ZONE_R_LEG)) && user.a_intent == INTENT_GRAB && target.shoes) + if(target.body_position == LYING_DOWN && (user.is_zone_selected(BODY_ZONE_L_LEG) || user.is_zone_selected(BODY_ZONE_R_LEG)) && user.a_intent == INTENT_GRAB && target.shoes) if(HAS_TRAIT(target.shoes, TRAIT_NODROP)) target.grabbedby(user) return TRUE @@ -1591,7 +1589,7 @@ GLOBAL_LIST_EMPTY(features_by_species) else var/atk_verb = user.dna.species.attack_verb - if(!(target.mobility_flags & MOBILITY_STAND)) + if(target.body_position == LYING_DOWN) atk_verb = ATTACK_EFFECT_KICK switch(atk_verb)//this code is really stupid but some genius apparently made "claw" and "slash" two attack types but also the same one so it's needed i guess @@ -2279,7 +2277,7 @@ GLOBAL_LIST_EMPTY(features_by_species) var/obj/item/organ/wings/wings = H.getorganslot(ORGAN_SLOT_WINGS) if(!H.getorgan(/obj/item/organ/wings)) return FALSE - if(H.stat || !(H.mobility_flags & MOBILITY_STAND)) + if(H.stat || H.body_position == LYING_DOWN) return FALSE var/turf/T = get_turf(H) if(!T) @@ -2321,7 +2319,6 @@ GLOBAL_LIST_EMPTY(features_by_species) H.setMovetype(H.movement_type | FLYING) override_float = TRUE H.pass_flags |= PASSTABLE - H.update_mobility() if(("wings" in H.dna.species.mutant_bodyparts) || ("moth_wings" in H.dna.species.mutant_bodyparts)) H.Togglewings() else diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index d0cb954bb596b..acda8d150343a 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -99,7 +99,7 @@ //Check to make sure legs are working var/obj/item/bodypart/left_leg = H.get_bodypart(BODY_ZONE_L_LEG) var/obj/item/bodypart/right_leg = H.get_bodypart(BODY_ZONE_R_LEG) - if(!left_leg || !right_leg || left_leg.disabled || right_leg.disabled) + if(!left_leg || !right_leg || left_leg.bodypart_disabled || right_leg.bodypart_disabled) return ..() if(levels == 1) //Nailed it! diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm index f61f5e5ae8964..337cba0d5413e 100644 --- a/code/modules/mob/living/carbon/human/status_procs.dm +++ b/code/modules/mob/living/carbon/human/status_procs.dm @@ -1,27 +1,27 @@ -/mob/living/carbon/human/Stun(amount, updating = TRUE, ignore_canstun = FALSE) +/mob/living/carbon/human/Stun(amount, ignore_canstun = FALSE) amount = dna.species.spec_stun(src,amount) return ..() -/mob/living/carbon/human/Knockdown(amount, updating = TRUE, ignore_canstun = FALSE) +/mob/living/carbon/human/Knockdown(amount, ignore_canstun = FALSE) amount = dna.species.spec_stun(src,amount) return ..() -/mob/living/carbon/human/Paralyze(amount, updating = TRUE, ignore_canstun = FALSE) +/mob/living/carbon/human/Paralyze(amount, ignore_canstun = FALSE) amount = dna.species.spec_stun(src, amount) return ..() -/mob/living/carbon/human/Immobilize(amount, updating = TRUE, ignore_canstun = FALSE) +/mob/living/carbon/human/Immobilize(amount, ignore_canstun = FALSE) amount = dna.species.spec_stun(src, amount) return ..() -/mob/living/carbon/human/Unconscious(amount, updating = 1, ignore_canunconscious = 0) +/mob/living/carbon/human/Unconscious(amount, ignore_canstun = FALSE) amount = dna.species.spec_stun(src,amount) if(HAS_TRAIT(src, TRAIT_HEAVY_SLEEPER)) amount *= rand(1.25, 1.3) return ..() -/mob/living/carbon/human/Sleeping(amount, updating = 1, ignore_sleepimmune = 0) +/mob/living/carbon/human/Sleeping(amount) if(HAS_TRAIT(src, TRAIT_HEAVY_SLEEPER)) amount *= rand(1.25, 1.3) return ..() diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 649f6d8dd4f53..3cfd6927dda71 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -218,7 +218,7 @@ There are several things that need to be remembered: if(!gloves && blood_in_hands) var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER) - if(get_num_arms(FALSE) < 2) + if(num_hands < 2) if(has_left_hand(FALSE)) bloody_overlay.icon_state = "bloodyhands_left" else if(has_right_hand(FALSE)) @@ -342,7 +342,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_shoes() remove_overlay(SHOES_LAYER) - if(get_num_legs(FALSE) <2) + if(num_legs < 2) return if(client && hud_used) diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index e317af6a671b3..4d5ac25067f0e 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -14,8 +14,14 @@ gib_type = /obj/effect/decal/cleanable/blood/gibs unique_name = TRUE blocks_emissive = EMISSIVE_BLOCK_UNIQUE - bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey, - /obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey) + bodyparts = list( + /obj/item/bodypart/chest/monkey, + /obj/item/bodypart/head/monkey, + /obj/item/bodypart/l_arm/monkey, + /obj/item/bodypart/r_arm/monkey, + /obj/item/bodypart/r_leg/monkey, + /obj/item/bodypart/l_leg/monkey + ) hud_type = /datum/hud/monkey mobchatspan = "monkeyhive" ai_controller = /datum/ai_controller/monkey @@ -39,7 +45,7 @@ GLOBAL_LIST_INIT(strippable_monkey_items, create_strippable_list(list( /mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner) add_verb(/mob/living/proc/mob_sleep) - add_verb(/mob/living/proc/lay_down) + add_verb(/mob/living/proc/toggle_resting) icon_state = null @@ -136,6 +142,8 @@ GLOBAL_LIST_INIT(strippable_monkey_items, create_strippable_list(list( return FALSE /mob/living/carbon/monkey/canBeHandcuffed() + if(num_hands < 2) + return FALSE return TRUE /mob/living/carbon/monkey/assess_threat(judgment_criteria, lasercolor = "", datum/callback/weaponcheck=null) diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm index e54a50bcfbc76..ae540b3b78506 100644 --- a/code/modules/mob/living/carbon/status_procs.dm +++ b/code/modules/mob/living/carbon/status_procs.dm @@ -16,7 +16,7 @@ ADD_TRAIT(src, TRAIT_INCAPACITATED, STAMINA) ADD_TRAIT(src, TRAIT_IMMOBILIZED, STAMINA) ADD_TRAIT(src, TRAIT_FLOORED, STAMINA) - update_mobility() + /mob/living/carbon/adjust_drugginess(amount) druggy = max(druggy+amount, 0) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 7737f0629daa1..78891afb06589 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -72,7 +72,6 @@ update_action_buttons_icon() update_health_hud() - update_mobility() med_hud_set_health() med_hud_set_status() diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 2dbe321d48597..6908a0bbb88da 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -245,8 +245,8 @@ message_param = initial(message_param) // reset if(ishuman(user) && intentional) var/mob/living/carbon/human/H = user - if(H.get_num_arms() == 0) - if(H.get_num_legs() != 0) + if(H.usable_hands == 0) + if(H.usable_legs != 0) message_param = "tries to point at %t with a leg, falling down in the process!" H.Paralyze(20) else @@ -389,6 +389,9 @@ message = null mob_type_blacklist_typecache = /mob/living/brain +/datum/emote/living/custom/can_run_emote(mob/user, status_check, intentional) + . = ..() && intentional + /datum/emote/living/custom/proc/check_invalid(mob/user, input) var/static/regex/stop_bad_mime = regex(@"says|exclaims|yells|asks") if(stop_bad_mime.Find(input, 1, 1)) @@ -396,9 +399,6 @@ return TRUE return FALSE -/datum/emote/living/custom/can_run_emote(mob/user, status_check, intentional) - . = ..() && intentional - /datum/emote/living/custom/run_emote(mob/user, params, type_override = null, intentional = FALSE) if(!can_run_emote(user, TRUE, intentional)) return FALSE diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm index 3181de18cd9c8..61a25fa4d2728 100644 --- a/code/modules/mob/living/inhand_holder.dm +++ b/code/modules/mob/living/inhand_holder.dm @@ -86,7 +86,7 @@ releasing = FALSE return TRUE -/obj/item/clothing/head/mob_holder/relaymove(mob/user) +/obj/item/clothing/head/mob_holder/relaymove(mob/living/user, direction) release() /obj/item/clothing/head/mob_holder/container_resist() diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index 290c774b656a8..108570a584da3 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -9,12 +9,27 @@ RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_IMMOBILIZED), PROC_REF(on_immobilized_trait_gain)) RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_IMMOBILIZED), PROC_REF(on_immobilized_trait_loss)) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_FLOORED), PROC_REF(on_floored_trait_gain)) + RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_FLOORED), PROC_REF(on_floored_trait_loss)) + + //RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_FORCED_STANDING), PROC_REF(on_forced_standing_trait_gain)) + //RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_FORCED_STANDING), PROC_REF(on_forced_standing_trait_loss)) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), PROC_REF(on_handsblocked_trait_gain)) RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_HANDS_BLOCKED), PROC_REF(on_handsblocked_trait_loss)) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_UI_BLOCKED), PROC_REF(on_ui_blocked_trait_gain)) + RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_UI_BLOCKED), PROC_REF(on_ui_blocked_trait_loss)) + + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_PULL_BLOCKED), PROC_REF(on_pull_blocked_trait_gain)) + RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_PULL_BLOCKED), PROC_REF(on_pull_blocked_trait_loss)) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_INCAPACITATED), PROC_REF(on_incapacitated_trait_gain)) RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_INCAPACITATED), PROC_REF(on_incapacitated_trait_loss)) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_RESTRAINED), PROC_REF(on_restrained_trait_gain)) + RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_RESTRAINED), PROC_REF(on_restrained_trait_loss)) + RegisterSignals(src, list( SIGNAL_ADDTRAIT(TRAIT_CRITICAL_CONDITION), SIGNAL_REMOVETRAIT(TRAIT_CRITICAL_CONDITION), @@ -35,7 +50,6 @@ if(stat <= UNCONSCIOUS) update_stat() - ///Called when TRAIT_DEATHCOMA is added to the mob. /mob/living/proc/on_deathcoma_trait_gain(datum/source) SIGNAL_HANDLER @@ -51,42 +65,111 @@ /mob/living/proc/on_immobilized_trait_gain(datum/source) SIGNAL_HANDLER mobility_flags &= ~MOBILITY_MOVE + if(living_flags & MOVES_ON_ITS_OWN) + walk(src, 0) //stop mid walk ///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 + on_floored_start() + + +/// Called when [TRAIT_FLOORED] is removed from the mob. +/mob/living/proc/on_floored_trait_loss(datum/source) + SIGNAL_HANDLER + mobility_flags |= MOBILITY_STAND + on_floored_end() + + +/// 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() + on_handsblocked_start() if (active_storage) active_storage.hide_from(src) update_action_buttons_icon(TRUE) -///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) + on_handsblocked_end() update_action_buttons_icon(TRUE) -/// Called when traits that alter succumbing are added/removed. -/// Will show or hide the succumb alert prompt. -/mob/living/proc/update_succumb_action() + +/// Called when [TRAIT_UI_BLOCKED] is added to the mob. +/mob/living/proc/on_ui_blocked_trait_gain(datum/source) SIGNAL_HANDLER - if (CAN_SUCCUMB(src)) - throw_alert("succumb", /atom/movable/screen/alert/succumb) - else - clear_alert("succumb") + mobility_flags &= ~(MOBILITY_UI) + unset_machine() + update_action_buttons_icon() + +/// 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 + update_action_buttons_icon() + + +/// 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. +/// 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) + update_icon() update_action_buttons_icon(TRUE) -///Called when TRAIT_INCAPACITATED is removed from the mob. +/// 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) + update_icon() update_action_buttons_icon(TRUE) + + +/// 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", /atom/movable/screen/alert/succumb) + else + clear_alert("succumb") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b5b61b73a2edc..b5bec880ef9e1 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -432,11 +432,11 @@ 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_NECK))) || (!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_NECK))) || (!ignore_stasis && IS_IN_STASIS(src))) return TRUE /mob/living/canUseStorage() - if (get_num_arms() <= 0) + if (usable_hands <= 0) return FALSE return TRUE @@ -481,42 +481,97 @@ else if(alert(src, "You sure you want to sleep for a while?", "Sleep", "Yes", "No") == "Yes") SetSleeping(400) //Short nap - update_mobility() + /mob/proc/get_contents() -/mob/living/proc/lay_down() + +/mob/living/proc/toggle_resting() set name = "Rest" set category = "IC" - if(!resting) - set_resting(TRUE, FALSE) - else - if(do_after(src, 10, target = src, timed_action_flags = IGNORE_RESTRAINED | IGNORE_HELD_ITEM | IGNORE_USER_LOC_CHANGE)) - set_resting(FALSE, FALSE) - else - to_chat(src, "You fail to get up.") + 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, instant = FALSE) + if(new_resting == resting) return - if(!silent) - if(rest) - to_chat(src, "You are now resting.") + . = resting + resting = new_resting + if(new_resting) + if(body_position == LYING_DOWN) + if(!silent) + to_chat(src, "You will now try to stay lying down on the floor.") + else if(buckled && buckled.buckle_lying != NO_BUCKLE_LYING) + if(!silent) + to_chat(src, "You will now lay down as soon as you are able to.") + else + if(!silent) + to_chat(src, "You lay down.") + set_lying_down() + else + if(body_position == STANDING_UP) + if(!silent) + to_chat(src, "You will now try to remain standing up.") + else if(HAS_TRAIT(src, TRAIT_FLOORED) || (buckled && buckled.buckle_lying != NO_BUCKLE_LYING)) + if(!silent) + to_chat(src, "You will now stand up as soon as you are able to.") else - to_chat(src, "You get up.") - . = rest - resting = rest + if(!silent) + to_chat(src, "You stand up.") + get_up(instant) + update_resting() +/// Proc to append and redefine behavior to the change of the [/mob/living/var/resting] variable. /mob/living/proc/update_resting() update_rest_hud_icon() - update_mobility() SEND_SIGNAL(src, COMSIG_LIVING_RESTING_UPDATED, resting) +/mob/living/proc/get_up(instant = FALSE) + set waitfor = FALSE + if(!instant && !do_after(src, 1 SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, TYPE_PROC_REF(/mob/living, rest_checks_callback)))) + return + if(resting || body_position == STANDING_UP || HAS_TRAIT(src, TRAIT_FLOORED)) + return + set_body_position(STANDING_UP) + set_lying_angle(0) + + +/mob/living/proc/rest_checks_callback() + if(resting || lying_angle == 0 || HAS_TRAIT(src, TRAIT_FLOORED)) + return FALSE + return TRUE + + +/// Change the [body_position] to [LYING_DOWN] and update associated behavior. +/mob/living/proc/set_lying_down(new_lying_angle) + set_body_position(LYING_DOWN) + + +/// Proc to append behavior related to lying down. +/mob/living/proc/on_lying_down(new_lying_angle) + if(layer == initial(layer)) //to avoid things like hiding larvas. + layer = LYING_MOB_LAYER //so mob lying always appear behind standing mobs + 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. + + +/// Proc to append behavior related to lying down. +/mob/living/proc/on_standing_up() + if(layer == LYING_MOB_LAYER) + layer = initial(layer) + density = initial(density) // We were prone before, so we become dense and things can bump into us again. + REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, LYING_DOWN_TRAIT) + REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, LYING_DOWN_TRAIT) + + //Recursive function to find everything a mob is holding. Really shitty proc tbh. /mob/living/get_contents() var/list/ret = list() @@ -572,7 +627,6 @@ set_suicide(FALSE) set_stat(UNCONSCIOUS) //the mob starts unconscious, updatehealth() //then we check if the mob should wake up. - update_mobility() update_sight() clear_alert("not_enough_oxy") reload_fullscreen() @@ -626,16 +680,15 @@ return stat != DEAD -/mob/living/proc/remove_CC(should_update_mobility = TRUE) - SetStun(0, FALSE) - SetKnockdown(0, FALSE) - SetImmobilized(0, FALSE) - SetParalyzed(0, FALSE) - SetSleeping(0, FALSE) +/mob/living/proc/remove_CC() + SetStun(0) + SetKnockdown(0) + SetImmobilized(0) + SetParalyzed(0) + SetSleeping(0) setStaminaLoss(0) - SetUnconscious(0, FALSE) - if(should_update_mobility) - update_mobility() + SetUnconscious(0) + //proc used to completely heal a mob. /mob/living/proc/fully_heal(admin_revive = FALSE) @@ -675,9 +728,9 @@ var/datum/component/mood/mood = GetComponent(/datum/component/mood) if (mood) mood.remove_temp_moods(admin_revive) - update_mobility() stop_sound_channel(CHANNEL_HEARTBEAT) + //proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again) /mob/living/proc/can_be_revived() . = 1 @@ -714,9 +767,10 @@ if(active_storage && !(CanReach(active_storage.parent,view_only = TRUE))) active_storage.close(src) - if(!(mobility_flags & MOBILITY_STAND) && !buckled && prob(getBruteLoss()*200/maxHealth)) + if(body_position == LYING_DOWN && !buckled && prob(getBruteLoss()*200/maxHealth)) makeTrail(newloc, T, old_direction) + ///Called by mob Move() when the lying_angle is different than zero, to better visually simulate crawling. /mob/living/proc/lying_angle_on_movement(direct) if(direct & EAST) @@ -1199,65 +1253,8 @@ /mob/living/can_be_pulled() return ..() && !(buckled && buckled.buckle_prevents_pull) -//Updates canmove, 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 -/mob/living/proc/update_mobility() - var/has_legs = get_num_legs() - var/has_arms = get_num_arms() - var/ignore_legs = get_leg_ignore() - var/canmove = !HAS_TRAIT(src, TRAIT_IMMOBILIZED) && (has_arms || ignore_legs || has_legs) - if(canmove) - mobility_flags |= MOBILITY_MOVE - else - mobility_flags &= ~MOBILITY_MOVE - var/canstand_involuntary = !HAS_TRAIT(src, TRAIT_FLOORED) && (ignore_legs || has_legs) - 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 - - update_action_buttons_icon(TRUE) - - if(stat == UNCONSCIOUS) - drop_all_held_items() - if(!(mobility_flags & MOBILITY_PULL)) - if(pulling) - stop_pulling() - if(!(mobility_flags & MOBILITY_UI)) - unset_machine() - - // Movespeed mods based on arms/legs quantity - if(!get_leg_ignore()) - 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(has_legs < 2) - limbless_slowdown += 6 - (has_legs * 3) - if(!has_legs && has_arms < 2) - limbless_slowdown += 6 - (has_arms * 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) - -///Called when mob changes from a standing position into a prone while lacking the ability to stand up at the moment, through update_mobility() +/// Called when mob changes from a standing position into a prone while lacking the ability to stand up at the moment. /mob/living/proc/on_fall() return @@ -1298,7 +1295,7 @@ if(.) if(client) reset_perspective() - update_mobility() //if the mob was asleep inside a container and then got forceMoved out we need to make them fall. + /mob/living/set_stat(new_stat) . = ..() @@ -1308,12 +1305,12 @@ if(CONSCIOUS) if(stat >= UNCONSCIOUS) ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) - ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_KNOCKEDOUT) - ADD_TRAIT(src, TRAIT_FLOORED, UNCONSCIOUS_TRAIT) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT) + ADD_TRAIT(src, TRAIT_INCAPACITATED, STAT_TRAIT) + ADD_TRAIT(src, TRAIT_FLOORED, STAT_TRAIT) if(SOFT_CRIT) if(stat >= UNCONSCIOUS) ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) //adding trait sources should come before removing to avoid unnecessary updates - ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_KNOCKEDOUT) if(pulledby) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) if(UNCONSCIOUS) @@ -1326,15 +1323,15 @@ if(CONSCIOUS) if(. >= UNCONSCIOUS) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) - REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_KNOCKEDOUT) - REMOVE_TRAIT(src, TRAIT_FLOORED, UNCONSCIOUS_TRAIT) + REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT) + REMOVE_TRAIT(src, TRAIT_INCAPACITATED, STAT_TRAIT) + REMOVE_TRAIT(src, TRAIT_FLOORED, STAT_TRAIT) REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT) if(SOFT_CRIT) if(pulledby) ADD_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) //adding trait sources should come before removing to avoid unnecessary updates if(. >= UNCONSCIOUS) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) - REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_KNOCKEDOUT) ADD_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT) if(UNCONSCIOUS) if(. != HARD_CRIT) @@ -1358,14 +1355,25 @@ . = buckled buckled = new_buckled if(buckled) - if(!.) - if(!HAS_TRAIT(buckled, TRAIT_NO_IMMOBILIZE)) //check if the object being buckled to that would normally immobilize has the NO_Immobilize trait, i.e. Wheelchairs. People buckled to wheelchairs obviously have more free movement that those buckled to stasis beds - ADD_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT) - if(buckled.buckle_lying) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT) + switch(buckled.buckle_lying) + if(NO_BUCKLE_LYING) // The buckle doesn't force a lying angle. + REMOVE_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT) + if(0) // Forcing to a standing position. + REMOVE_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT) + set_body_position(STANDING_UP) + set_lying_angle(0) + else // Forcing to a lying position. ADD_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT) - else if(.) + set_body_position(LYING_DOWN) + set_lying_angle(buckled.buckle_lying) + else REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT) REMOVE_TRAIT(src, TRAIT_FLOORED, BUCKLED_TRAIT) + if(.) // We unbuckled from something. + var/atom/movable/old_buckled = . + if(old_buckled.buckle_lying == 0 && (resting || HAS_TRAIT(src, TRAIT_FLOORED))) // The buckle forced us to stay up (like a chair) + set_lying_down() // We want to rest or are otherwise floored, so let's drop on the ground. /mob/living/set_pulledby(new_pulledby) @@ -1540,16 +1548,6 @@ if(lying_angle != lying_prev) update_transform() lying_prev = lying_angle - 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 - else //We are prone. - if(layer == LYING_MOB_LAYER) - layer = initial(layer) - if(.) //We weren't pone before, so we become dense and things can bump into us again. - density = initial(density) /** * add_body_temperature_change Adds modifications to the body temperature @@ -1607,3 +1605,96 @@ remove_client_colour(current_correction) add_client_colour(entered.color_correction) current_correction = entered.color_correction + + +///Proc to modify the value of num_legs and hook behavior associated to this event. +/mob/living/proc/set_num_legs(new_value) + if(num_legs == new_value) + return + . = num_legs + num_legs = new_value + + +///Proc to modify the value of usable_legs and hook behavior associated to this event. +/mob/living/proc/set_usable_legs(new_value) + if(usable_legs == new_value) + return + . = 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) + if(num_hands == new_value) + return + . = num_hands + num_hands = new_value + + +///Proc to modify the value of usable_hands and hook behavior associated to this event. +/mob/living/proc/set_usable_hands(new_value) + if(usable_hands == new_value) + return + . = 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) + + +/// Changes the value of the [living/body_position] variable. +/mob/living/proc/set_body_position(new_value) + if(body_position == new_value) + return + . = body_position + body_position = new_value + if(new_value == LYING_DOWN) // From standing to lying down. + on_lying_down() + else // From lying down to standing up. + on_standing_up() + + +/// Proc to append behavior to the condition of being floored. Called when the condition starts. +/mob/living/proc/on_floored_start() + if(body_position == STANDING_UP) //force them on the ground + set_lying_angle(pick(90, 270)) + set_body_position(LYING_DOWN) + on_fall() + + +/// Proc to append behavior to the condition of being floored. Called when the condition ends. +/mob/living/proc/on_floored_end() + if(!resting) + get_up() + + +/// Proc to append behavior to the condition of being handsblocked. Called when the condition starts. +/mob/living/proc/on_handsblocked_start() + drop_all_held_items() + ADD_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_HANDS_BLOCKED) + ADD_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED) + + +/// Proc to append behavior to the condition of being handsblocked. Called when the condition ends. +/mob/living/proc/on_handsblocked_end() + REMOVE_TRAIT(src, TRAIT_UI_BLOCKED, TRAIT_HANDS_BLOCKED) + REMOVE_TRAIT(src, TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 3a8100582d674..1cf6ee18abf98 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -194,14 +194,12 @@ log_combat(user, src, "grabbed", addition="neck grab") visible_message("[user] grabs [src] by the neck!",\ "[user] grabs you by the neck!") - update_mobility() //we fall down if(!buckled && !density) Move(user.loc) if(GRAB_KILL) log_combat(user, src, "strangled", addition="kill grab") visible_message("[user] is strangling [src]!", \ "[user] is strangling you!") - update_mobility() //we fall down if(!buckled && !density) Move(user.loc) user.set_pull_offsets(src, grab_state) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index fb7c267d1d8e9..5cbc07f08120c 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -26,12 +26,20 @@ ///When the mob enters hard critical state and is fully incapacitated. var/hardcrit_threshold = HEALTH_THRESHOLD_FULLCRIT + /// Generic bitflags for boolean conditions at the [/mob/living] level. Keep this for inherent traits of living types, instead of runtime-changeable ones. + var/living_flags = NONE + + /// Flags that determine the potential of a mob to perform certain actions. Do not change this directly. var/mobility_flags = MOBILITY_FLAGS_DEFAULT var/resting = FALSE - VAR_PROTECTED/lying_angle = 0 ///number of degrees. DO NOT USE THIS IN CHECKS. CHECK FOR MOBILITY FLAGS INSTEAD!! - var/lying_prev = 0 //last value of lying on update_mobility + /// Variable to track the body position of a mob, regardless of the actual angle of rotation (usually matching it, but not necessarily). + var/body_position = STANDING_UP + /// Number of degrees of rotation of a mob. 0 means no rotation, up-side facing NORTH. 90 means up-side rotated to face EAST, and so on. + VAR_PROTECTED/lying_angle = 0 + /// Value of lying lying_angle before last change. TODO: Remove the need for this. + var/lying_prev = 0 var/confused = 0 //Makes the mob move in random directions. @@ -63,6 +71,20 @@ var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature.. var/has_limbs = 0 //does the mob have distinct limbs?(arms,legs, chest,head) + ///How many legs does this mob have by default. This shouldn't change at runtime. + var/default_num_legs = 2 + ///How many legs does this mob currently have. Should only be changed through set_num_legs() + var/num_legs = 2 + ///How many usable legs this mob currently has. Should only be changed through set_usable_legs() + var/usable_legs = 2 + + ///How many hands does this mob have by default. This shouldn't change at runtime. + var/default_num_hands = 2 + ///How many hands hands does this mob currently have. Should only be changed through set_num_hands() + var/num_hands = 2 + ///How many usable hands does this mob currently have. Should only be changed through set_usable_hands() + var/usable_hands = 2 + var/list/pipes_shown = list() var/last_played_vent diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 24c834a72e20b..eaf9b84962334 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -3,17 +3,18 @@ update_turf_movespeed(loc) update_looking_move() + /mob/living/CanAllowThrough(atom/movable/mover, border_dir) . = ..() if(.) return if(mover.throwing) - return (!density || !(mobility_flags & MOBILITY_STAND) || (mover.throwing.thrower == src && !ismob(mover))) + return (!density || (body_position == LYING_DOWN) || (mover.throwing.thrower == src && !ismob(mover))) if(buckled == mover) return TRUE if(ismob(mover) && (mover in buckled_mobs)) return TRUE - return !mover.density || !(mobility_flags & MOBILITY_STAND) + return !mover.density || body_position == LYING_DOWN /mob/living/toggle_move_intent() . = ..() @@ -32,11 +33,12 @@ else remove_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown) + /mob/living/proc/update_pull_movespeed() if(pulling) if(isliving(pulling)) var/mob/living/L = pulling - if(!slowed_by_drag || (L.mobility_flags & MOBILITY_STAND) || L.buckled || grab_state >= GRAB_AGGRESSIVE) + if(!slowed_by_drag || L.body_position == STANDING_UP || L.buckled || grab_state >= GRAB_AGGRESSIVE) remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag) return add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = PULL_PRONE_SLOWDOWN) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1971406933154..710b0f1cdea03 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -19,7 +19,6 @@ icon_state = "ai" move_resist = MOVE_FORCE_VERY_STRONG density = TRUE - mobility_flags = ALL status_flags = CANSTUN|CANPUSH a_intent = INTENT_HARM //so we always get pushed instead of trying to swap sight = SEE_TURFS | SEE_MOBS | SEE_OBJS @@ -37,7 +36,7 @@ /// Station alert datum for showing alerts UI var/datum/station_alert/alert_control - var/aiRestorePowerRoutine = 0 + var/aiRestorePowerRoutine = POWER_RESTORATION_OFF var/requires_power = POWER_REQ_ALL var/can_be_carded = TRUE var/icon/holo_icon //Default is assigned when AI is created. @@ -178,6 +177,9 @@ builtInCamera = new (src) builtInCamera.network = list("ss13") + ADD_TRAIT(src, TRAIT_PULL_BLOCKED, ROUNDSTART_TRAIT) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, ROUNDSTART_TRAIT) + alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z), camera_view = TRUE) RegisterSignal(alert_control.listener, COMSIG_ALARM_TRIGGERED, PROC_REF(alarm_triggered)) RegisterSignal(alert_control.listener, COMSIG_ALARM_CLEARED, PROC_REF(alarm_cleared)) @@ -398,12 +400,6 @@ if(ai_tracking_target) ai_stop_tracking() -/mob/living/silicon/ai/update_mobility() //If the AI dies, mobs won't go through it anymore - if(stat != CONSCIOUS) - mobility_flags = NONE - else - mobility_flags = ALL - /mob/living/silicon/ai/proc/ai_cancel_call() set category = "Malfunction" if(control_disabled) @@ -797,11 +793,6 @@ /mob/living/silicon/ai/can_buckle() return 0 -/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()) to_chat(src, "You can't do that right now!") @@ -1063,3 +1054,23 @@ /mob/living/silicon/ai/zMove(dir, feedback = FALSE, feedback_to = src) . = eyeobj.zMove(dir, feedback, feedback_to) + + +/// 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) + + +/mob/living/silicon/on_handsblocked_start() + return // AIs have no hands + +/mob/living/silicon/on_handsblocked_end() + return // AIs have no hands diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index c7e70556d3d00..81e5ff91e12a8 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -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(delta_time) if (stat == DEAD) return @@ -112,7 +107,7 @@ T = get_turf(src) if(isspaceturf(T)) to_chat(src, "Unable to verify! No power connection detected!") - aiRestorePowerRoutine = POWER_RESTORATION_SEARCH_APC + setAiRestorePowerRoutine(POWER_RESTORATION_SEARCH_APC) return to_chat(src, "Connection verified. Searching for APC in power network.") sleep(5 SECONDS) @@ -130,7 +125,7 @@ to_chat(src, "Unable to locate APC!") else to_chat(src, "Lost connection with the APC!") - aiRestorePowerRoutine = POWER_RESTORATION_SEARCH_APC + setAiRestorePowerRoutine(POWER_RESTORATION_SEARCH_APC) return if(AIarea.power_equip) if(!isspaceturf(T)) @@ -151,7 +146,7 @@ to_chat(src, "APC ready for connection.") apc_override = theAPC theAPC.ui_interact(src) - aiRestorePowerRoutine = POWER_RESTORATION_APC_FOUND + setAiRestorePowerRoutine(POWER_RESTORATION_APC_FOUND) sleep(5 SECONDS) theAPC = null @@ -163,20 +158,15 @@ to_chat(src, "APC Backdoor has been closed.") //No change in behavior, just tells the AI why they have to rehack their APC and turn the power back on else to_chat(src, "Alert cancelled. Power has been restored without our assistance.") - aiRestorePowerRoutine = POWER_RESTORATION_OFF + setAiRestorePowerRoutine(POWER_RESTORATION_OFF) set_blindness(0) apc_override = null update_sight() /mob/living/silicon/ai/proc/ai_lose_power() disconnect_shell() - aiRestorePowerRoutine = POWER_RESTORATION_START + setAiRestorePowerRoutine(POWER_RESTORATION_START) adjust_blindness(1) update_sight() to_chat(src, "You've lost power!") addtimer(CALLBACK(src, PROC_REF(start_RestorePowerRoutine)), 20) - -#undef POWER_RESTORATION_OFF -#undef POWER_RESTORATION_START -#undef POWER_RESTORATION_SEARCH_APC -#undef POWER_RESTORATION_APC_FOUND diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm index fd5e049e67fea..6adcb4949cd9d 100644 --- a/code/modules/mob/living/silicon/pai/death.dm +++ b/code/modules/mob/living/silicon/pai/death.dm @@ -2,7 +2,6 @@ if(stat == DEAD) return set_stat(DEAD) - mobility_flags = NONE update_sight() clear_fullscreens() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 3fd62b6140a8c..5814bbcc9d661 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -175,6 +175,11 @@ emittersemicd = TRUE addtimer(CALLBACK(src, PROC_REF(emittercool)), 600) + + if(!holoform) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, PAI_FOLDED) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, PAI_FOLDED) + return INITIALIZE_HINT_LATELOAD @@ -296,7 +301,7 @@ /datum/action/innate/pai/rest/Trigger() ..() - P.lay_down() + P.toggle_resting() /datum/action/innate/pai/light name = "Toggle Integrated Lights" diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm index de891dda0bdbc..f237bf6c1b078 100644 --- a/code/modules/mob/living/silicon/pai/pai_shell.dm +++ b/code/modules/mob/living/silicon/pai/pai_shell.dm @@ -18,7 +18,8 @@ emittersemicd = TRUE addtimer(CALLBACK(src, PROC_REF(emittercool)), emittercd) - mobility_flags = MOBILITY_FLAGS_DEFAULT + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, PAI_FOLDED) + REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, PAI_FOLDED) set_density(TRUE) if(isliving(card.loc)) var/mob/living/L = card.loc @@ -63,7 +64,8 @@ var/turf/T = drop_location() card.forceMove(T) forceMove(card) - mobility_flags = NONE + ADD_TRAIT(src, TRAIT_IMMOBILIZED, PAI_FOLDED) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, PAI_FOLDED) set_density(FALSE) set_light_on(FALSE) holoform = FALSE diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 7f4c27719abbf..193438412356a 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -98,11 +98,3 @@ else cut_overlay(fire_overlay) -/mob/living/silicon/robot/update_mobility() - if(HAS_TRAIT(src, TRAIT_IMMOBILIZED)) - mobility_flags &= ~MOBILITY_MOVE - else - mobility_flags = MOBILITY_FLAGS_DEFAULT - update_transform() - update_action_buttons_icon() - diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 1fbb99af208e1..676b9b4add05c 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -164,7 +164,7 @@ mmi.brain.organ_flags |= ORGAN_FROZEN mmi.brain.name = "[real_name]'s brain" mmi.name = "[initial(mmi.name)]: [real_name]" - mmi.brainmob = new(mmi) + mmi.set_brainmob(new /mob/living/brain(mmi)) mmi.brainmob.name = src.real_name mmi.brainmob.real_name = src.real_name mmi.brainmob.container = mmi @@ -707,7 +707,6 @@ ADD_TRAIT(src, TRAIT_IMMOBILIZED, LOCKED_BORG_TRAIT) else if(.) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LOCKED_BORG_TRAIT) - update_mobility() logevent("System lockdown [lockcharge?"triggered":"released"].") @@ -1027,7 +1026,6 @@ set_stat(UNCONSCIOUS) else set_stat(CONSCIOUS) - update_mobility() diag_hud_set_status() diag_hud_set_health() diag_hud_set_aishell() @@ -1256,7 +1254,7 @@ M.visible_message("Unfortunately, [M] just can't seem to hold onto [src]!") return if(iscarbon(M) && (!riding_datum.equip_buckle_inhands(M, 1))) - if (M.get_num_arms() <= 0) + if(M.usable_hands == 0) M.visible_message("[M] can't climb onto [src] because [M.p_they()] don't have any usable arms!") else M.visible_message("[M] can't climb onto [src] because [M.p_their()] hands are full!") diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 4327ac64e5c91..be6024e1f743c 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -12,7 +12,7 @@ /mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) if (M.a_intent == INTENT_DISARM) - if(mobility_flags & MOBILITY_STAND) + if(body_position == STANDING_UP) M.do_attack_animation(src, ATTACK_EFFECT_DISARM) var/obj/item/I = get_active_held_item() if(I) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 8c9f416283761..6a47c88edca87 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -469,6 +469,18 @@ /mob/living/silicon/hears_radio() return FALSE +/mob/living/silicon/on_floored_start() + return // Silicons are always standing by default. + +/mob/living/silicon/on_floored_end() + return // Silicons are always standing by default. + +/mob/living/silicon/on_lying_down() + return // Silicons are always standing by default. + +/mob/living/silicon/on_standing_up() + return // Silicons are always standing by default. + /** * Records an IC event log entry in the cyborg's internal tablet. * diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index cdc7c63d497ff..feb949acb46fd 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -138,7 +138,9 @@ booting = FALSE on = TRUE INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, say), "Boot sequence complete, [name] operational") - update_mobility() + REMOVE_TRAIT(src, TRAIT_INCAPACITATED, POWER_LACK_TRAIT) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, POWER_LACK_TRAIT) + REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, POWER_LACK_TRAIT) set_light_on(on) update_icon() diag_hud_set_botstat() @@ -155,7 +157,9 @@ /mob/living/simple_animal/bot/proc/turn_off() on = FALSE - update_mobility() + ADD_TRAIT(src, TRAIT_INCAPACITATED, POWER_LACK_TRAIT) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, POWER_LACK_TRAIT) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, POWER_LACK_TRAIT) set_light_on(on) bot_reset() //Resets an AI's call, should it exist. update_icon() @@ -194,11 +198,6 @@ RegisterSignal(src, COMSIG_ATOM_ON_EMAG, PROC_REF(on_emag)) RegisterSignal(src, COMSIG_ATOM_SHOULD_EMAG, PROC_REF(should_emag)) -/mob/living/simple_animal/bot/update_mobility() - . = ..() - if(!on) - mobility_flags = NONE - /mob/living/simple_animal/bot/Destroy() if(path_hud) QDEL_NULL(path_hud) diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index bd920202f842f..4ebba0bbabbf7 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -92,7 +92,7 @@ /mob/living/simple_animal/bot/cleanbot/process_scan(atom/A) if(iscarbon(A)) var/mob/living/carbon/C = A - if(C.stat != DEAD && !(C.mobility_flags & MOBILITY_STAND)) + if(C.stat != DEAD && C.body_position == LYING_DOWN) return C else if(is_type_in_typecache(A, target_types)) return A diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index b9fb425e6d425..aa01445a95c57 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -91,7 +91,7 @@ GLOBAL_VAR(medibot_unique_id_gen) if(!on) icon_state = "medibot0" return - if(IsStun() || IsParalyzed()) + if(HAS_TRAIT(src, TRAIT_INCAPACITATED)) icon_state = "medibota" return if(mode == BOT_HEALING) @@ -129,10 +129,6 @@ GLOBAL_VAR(medibot_unique_id_gen) medibot_counter = GLOB.medibot_unique_id_gen GLOB.medibot_unique_id_gen++ -/mob/living/simple_animal/bot/medbot/update_mobility() - . = ..() - update_icon() - /mob/living/simple_animal/bot/medbot/bot_reset() ..() set_patient(null) @@ -337,7 +333,7 @@ GLOBAL_VAR(medibot_unique_id_gen) return /mob/living/simple_animal/bot/medbot/proc/tip_over(mob/user) - mobility_flags &= ~MOBILITY_MOVE + ADD_TRAIT(src, TRAIT_IMMOBILIZED, BOT_TIPPED_OVER) playsound(src, 'sound/machines/warning-buzzer.ogg', 50) user.visible_message("[user] tips over [src]!", "You tip [src] over!") tipped = TRUE @@ -346,7 +342,7 @@ GLOBAL_VAR(medibot_unique_id_gen) tipper_name = user.name /mob/living/simple_animal/bot/medbot/proc/set_right(mob/user) - mobility_flags &= MOBILITY_MOVE + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, BOT_TIPPED_OVER) var/list/messagevoice if(user) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 5840d67551316..55c9fff6eb1e9 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -131,12 +131,6 @@ /mob/living/simple_animal/bot/mulebot/proc/has_power(bypass_open_check) return (!open || bypass_open_check) && cell && cell.charge > 0 && (!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2)) -/mob/living/simple_animal/bot/mulebot/update_mobility() - . = ..() - if(!on) - mobility_flags |= MOBILITY_STAND //base bots removes all mobility flags when turned off, resulting in the bot becoming passable. we don't want this since it's a large device that should block things. - update_action_buttons_icon(TRUE) - /mob/living/simple_animal/bot/mulebot/proc/set_id(new_id) id = new_id if(paicard) @@ -442,7 +436,7 @@ if (!istype(L)) return - if(user.incapacitated() || (istype(L) && !(L.mobility_flags & MOBILITY_STAND))) + if(user.incapacitated() || (istype(L) && L.body_position == LYING_DOWN)) return if(!istype(AM) || isdead(AM) || iscameramob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) @@ -800,7 +794,7 @@ bloodiness += 4 // player on mulebot attempted to move -/mob/living/simple_animal/bot/mulebot/relaymove(mob/user) +/mob/living/simple_animal/bot/mulebot/relaymove(mob/living/user, direction) if(user.incapacitated()) return if(load == user) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 067c92f2898cf..f4eabf999266a 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -48,11 +48,8 @@ mobchatspan = "cultmobsay" discovery_points = 1000 -/mob/living/simple_animal/hostile/construct/get_num_legs() - return 0 - -/mob/living/simple_animal/hostile/construct/get_num_arms() - return 0 + usable_legs = 0 + usable_hands = 0 /mob/living/simple_animal/hostile/construct/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 1fc686bcf12a7..1301235f2f963 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -41,7 +41,7 @@ /mob/living/simple_animal/pet/cat/Initialize(mapload) . = ..() - add_verb(/mob/living/proc/lay_down) + add_verb(/mob/living/proc/toggle_resting) /mob/living/simple_animal/pet/cat/space name = "space cat" @@ -182,34 +182,36 @@ /mob/living/simple_animal/pet/cat/update_resting() . = ..() - if(stat != DEAD) - if (resting) - icon_state = "[icon_living]_rest" - collar_type = "[initial(collar_type)]_rest" - else - icon_state = "[icon_living]" - collar_type = "[initial(collar_type)]" + if(stat == DEAD) + return + if (resting) + icon_state = "[icon_living]_rest" + collar_type = "[initial(collar_type)]_rest" + else + icon_state = "[icon_living]" + collar_type = "[initial(collar_type)]" + regenerate_icons() + /mob/living/simple_animal/pet/cat/Life() if(!stat && !buckled && !client) - if(prob(3)) - switch(rand(1, 3)) - if (1) - INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "me", 1, pick("stretches out for a belly rub.", "wags its tail.", "lies down.")) - set_resting(TRUE) - if (2) - INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "me", 1, pick("sits down.", "crouches on its hind legs.", "looks alert.")) - set_resting(TRUE) - icon_state = "[icon_living]_sit" - collar_type = "[initial(collar_type)]_sit" - if (3) - if (resting) - INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "me", 1, pick("gets up and meows.", "walks around.", "stops resting.")) - set_resting(FALSE) - else - INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "me", 1, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat.")) + if(prob(1)) + manual_emote(pick("stretches out for a belly rub.", "wags its tail.", "lies down.")) + set_resting(TRUE) + else if (prob(1)) + manual_emote(pick("sits down.", "crouches on its hind legs.", "looks alert.")) + set_resting(TRUE) + icon_state = "[icon_living]_sit" + collar_type = "[initial(collar_type)]_sit" + else if (prob(1)) + if (resting) + manual_emote(pick("gets up and meows.", "walks around.", "stops resting.")) + set_resting(FALSE) + else + manual_emote(pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat.")) ..() + if(next_scan_time <= world.time) make_babies() diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 136a813ca81df..e585d8143522f 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -156,7 +156,7 @@ /mob/living/simple_animal/hostile/bear/butter/AttackingTarget() //Makes some attacks by the butter bear slip those who dare cross its path. if(isliving(target)) var/mob/living/L = target - if((L.mobility_flags & MOBILITY_STAND)) + if((L.body_position == STANDING_UP)) L.Knockdown(20) playsound(loc, 'sound/misc/slip.ogg', 15) L.visible_message("[L] slips on butter!") diff --git a/code/modules/mob/living/simple_animal/hostile/floor_cluwne.dm b/code/modules/mob/living/simple_animal/hostile/floor_cluwne.dm index a3ac4a531dc78..d16cf8de121b3 100644 --- a/code/modules/mob/living/simple_animal/hostile/floor_cluwne.dm +++ b/code/modules/mob/living/simple_animal/hostile/floor_cluwne.dm @@ -192,14 +192,12 @@ GLOBAL_VAR_INIT(floor_cluwnes, 0) /mob/living/simple_animal/hostile/floor_cluwne/proc/Manifest()//handles disappearing and appearance anim if(manifested) mobility_flags &= ~MOBILITY_MOVE - update_mobility() cluwnehole = new(src.loc) addtimer(CALLBACK(src, TYPE_PROC_REF(/mob/living/simple_animal/hostile/floor_cluwne, Appear)), MANIFEST_DELAY) else invisibility = INVISIBILITY_SPIRIT density = FALSE mobility_flags |= MOBILITY_MOVE - update_mobility() if(cluwnehole) qdel(cluwnehole) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 9da9ce66d624b..52bd3f1bdfc30 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -308,13 +308,12 @@ Difficulty: Hard return TRUE return FALSE + /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/be_aggressive() if(BUBBLEGUM_IS_ENRAGED) return TRUE - if(isliving(target)) - var/mob/living/livingtarget = target - return (livingtarget.stat != CONSCIOUS || !(livingtarget.mobility_flags & MOBILITY_STAND)) - return FALSE + return isliving(target) && HAS_TRAIT(target, TRAIT_INCAPACITATED) + /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_retreat_distance() return (be_aggressive() ? null : initial(retreat_distance)) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 263d12722d678..c81712dff034d 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -4,7 +4,7 @@ health = 20 maxHealth = 20 gender = PLURAL //placeholder - + living_flags = MOVES_ON_ITS_OWN status_flags = CANPUSH var/icon_living = "" @@ -409,15 +409,15 @@ /mob/living/simple_animal/ExtinguishMob() return + /mob/living/simple_animal/revive(full_heal = 0, admin_revive = 0) - if(..()) //successfully ressuscitated from death - icon = initial(icon) - icon_state = icon_living - set_density(initial(density)) - mobility_flags = MOBILITY_FLAGS_DEFAULT - update_mobility() - . = 1 - setMovetype(initial(movement_type)) + . = ..() + if(!.) + return + icon = initial(icon) + icon_state = icon_living + density = initial(density) + setMovetype(initial(movement_type)) /mob/living/simple_animal/proc/make_babies() // <3 <3 <3 set waitfor = 0 @@ -476,23 +476,6 @@ REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, RESTING_TRAIT) return ..() -/mob/living/simple_animal/update_mobility(value_otherwise = TRUE) - if(HAS_TRAIT_NOT_FROM(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT)) - drop_all_held_items() - mobility_flags = NONE - else if(buckled || IsImmobilized()) - mobility_flags = MOBILITY_FLAGS_INTERACTION - else - if(value_otherwise) - mobility_flags = MOBILITY_FLAGS_DEFAULT - else - mobility_flags = NONE - if(!(mobility_flags & MOBILITY_MOVE)) - SSmove_manager.stop_looping(src) //stop mid walk - - update_transform() - update_action_buttons_icon() - /mob/living/simple_animal/update_transform() var/matrix/ntransform = matrix(transform) //aka transform.Copy() var/changed = FALSE @@ -611,7 +594,7 @@ M.forceMove(get_turf(src)) return ..() -/mob/living/simple_animal/relaymove(mob/user, direction) +/mob/living/simple_animal/relaymove(mob/living/user, direction) var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding) if(tame && riding_datum) riding_datum.handle_ride(user, direction) diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 7eb8018945080..5a1bb1e264b51 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -110,13 +110,11 @@ set_stat(UNCONSCIOUS) powerlevel = 0 rabid = FALSE - update_mobility() regenerate_icons() if(UNCONSCIOUS, HARD_CRIT) if(!stasis) to_chat(src, "You wake up from the stasis.") set_stat(CONSCIOUS) - update_mobility() regenerate_icons() updatehealth() @@ -220,8 +218,6 @@ powerlevel += gainpower /mob/living/simple_animal/slime/proc/handle_targets() - update_mobility() - if(attacked > 50) attacked = 50 @@ -284,19 +280,19 @@ if (Leader) if(holding_still) holding_still = max(holding_still - 1, 0) - else if((mobility_flags & MOBILITY_MOVE) && isturf(loc)) + else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc)) step_to(src, Leader) else if(hungry) if (holding_still) holding_still = max(holding_still - hungry, 0) - else if((mobility_flags & MOBILITY_MOVE) && isturf(loc) && prob(50)) + else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc) && prob(50)) step(src, pick(GLOB.cardinals)) else if(holding_still) holding_still = max(holding_still - 1, 0) else if (docile && pulledby) holding_still = 10 - else if((mobility_flags & MOBILITY_MOVE) && isturf(loc) && prob(33)) + else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc) && prob(33)) step(src, pick(GLOB.cardinals)) else if(!special_process) special_process = TRUE diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 651a7b3cf3ea9..1573e7404b8c6 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -497,16 +497,15 @@ SStun = world.time + rand(20,60) - mobility_flags &= ~MOBILITY_MOVE + Stun(3) if(user) step_away(src,user,15) - addtimer(CALLBACK(src, PROC_REF(slime_move), user), 3) + addtimer(CALLBACK(src, PROC_REF(slime_move), user), 0.3 SECONDS) /mob/living/simple_animal/slime/proc/slime_move(mob/user) if(user) step_away(src,user,15) - update_mobility() /mob/living/simple_animal/slime/pet docile = 1 diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 1c4cfcaf20081..051b1e3ac7735 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -14,8 +14,8 @@ return S.duration - world.time return 0 -/mob/living/proc/Stun(amount, updating = TRUE, ignore_canstun = FALSE) //Can't go below remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_STUN, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/Stun(amount, ignore_canstun = FALSE) //Can't go below remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_STUN, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANSTUN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -24,11 +24,11 @@ if(S) S.duration = max(world.time + amount, S.duration) else if(amount > 0) - S = apply_status_effect(STATUS_EFFECT_STUN, amount, updating) + S = apply_status_effect(STATUS_EFFECT_STUN, amount) return S -/mob/living/proc/SetStun(amount, updating = TRUE, ignore_canstun = FALSE) //Sets remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_STUN, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/SetStun(amount, ignore_canstun = FALSE) //Sets remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_STUN, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANSTUN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) var/datum/status_effect/incapacitating/stun/S = IsStun() @@ -41,11 +41,11 @@ if(S) S.duration = world.time + amount else - S = apply_status_effect(STATUS_EFFECT_STUN, amount, updating) + S = apply_status_effect(STATUS_EFFECT_STUN, amount) return S -/mob/living/proc/AdjustStun(amount, updating = TRUE, ignore_canstun = FALSE) //Adds to remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_STUN, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/AdjustStun(amount, ignore_canstun = FALSE) //Adds to remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_STUN, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANSTUN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -54,7 +54,7 @@ if(S) S.duration += amount else if(amount > 0) - S = apply_status_effect(STATUS_EFFECT_STUN, amount, updating) + S = apply_status_effect(STATUS_EFFECT_STUN, amount) return S ///////////////////////////////// KNOCKDOWN ///////////////////////////////////// @@ -69,8 +69,8 @@ return K.duration - world.time return 0 -/mob/living/proc/Knockdown(amount, updating = TRUE, ignore_canstun = FALSE) //Can't go below remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_KNOCKDOWN, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/Knockdown(amount, ignore_canstun = FALSE) //Can't go below remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_KNOCKDOWN, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -79,11 +79,11 @@ if(K) K.duration = max(world.time + amount, K.duration) else if(amount > 0) - K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount, updating) + K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount) return K -/mob/living/proc/SetKnockdown(amount, updating = TRUE, ignore_canstun = FALSE) //Sets remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_KNOCKDOWN, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/SetKnockdown(amount, ignore_canstun = FALSE) //Sets remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_KNOCKDOWN, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) var/datum/status_effect/incapacitating/knockdown/K = IsKnockdown() @@ -96,11 +96,11 @@ if(K) K.duration = world.time + amount else - K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount, updating) + K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount) return K -/mob/living/proc/AdjustKnockdown(amount, updating = TRUE, ignore_canstun = FALSE) //Adds to remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_KNOCKDOWN, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/AdjustKnockdown(amount, ignore_canstun = FALSE) //Adds to remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_KNOCKDOWN, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -109,7 +109,7 @@ if(K) K.duration += amount else if(amount > 0) - K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount, updating) + K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount) return K ///////////////////////////////// IMMOBILIZED //////////////////////////////////// @@ -122,8 +122,8 @@ return I.duration - world.time return 0 -/mob/living/proc/Immobilize(amount, updating = TRUE, ignore_canstun = FALSE) //Can't go below remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_IMMOBILIZE, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/Immobilize(amount, ignore_canstun = FALSE) //Can't go below remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_IMMOBILIZE, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -132,11 +132,11 @@ if(I) I.duration = max(world.time + amount, I.duration) else if(amount > 0) - I = apply_status_effect(STATUS_EFFECT_IMMOBILIZED, amount, updating) + I = apply_status_effect(STATUS_EFFECT_IMMOBILIZED, amount) return I -/mob/living/proc/SetImmobilized(amount, updating = TRUE, ignore_canstun = FALSE) //Sets remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_IMMOBILIZE, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/SetImmobilized(amount, ignore_canstun = FALSE) //Sets remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_IMMOBILIZE, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) var/datum/status_effect/incapacitating/immobilized/I = IsImmobilized() @@ -149,11 +149,11 @@ if(I) I.duration = world.time + amount else - I = apply_status_effect(STATUS_EFFECT_IMMOBILIZED, amount, updating) + I = apply_status_effect(STATUS_EFFECT_IMMOBILIZED, amount) return I -/mob/living/proc/AdjustImmobilized(amount, updating = TRUE, ignore_canstun = FALSE) //Adds to remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_IMMOBILIZE, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/AdjustImmobilized(amount, ignore_canstun = FALSE) //Adds to remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_IMMOBILIZE, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -162,7 +162,7 @@ if(I) I.duration += amount else if(amount > 0) - I = apply_status_effect(STATUS_EFFECT_IMMOBILIZED, amount, updating) + I = apply_status_effect(STATUS_EFFECT_IMMOBILIZED, amount) return I ///////////////////////////////// PARALYZED ////////////////////////////////// @@ -175,8 +175,8 @@ return P.duration - world.time return 0 -/mob/living/proc/Paralyze(amount, updating = TRUE, ignore_canstun = FALSE) //Can't go below remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_PARALYZE, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/Paralyze(amount, ignore_canstun = FALSE) //Can't go below remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_PARALYZE, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -186,11 +186,11 @@ if(P) P.duration = max(world.time + amount, P.duration) else if(amount > 0) - P = apply_status_effect(STATUS_EFFECT_PARALYZED, amount, updating) + P = apply_status_effect(STATUS_EFFECT_PARALYZED, amount) return P -/mob/living/proc/SetParalyzed(amount, updating = TRUE, ignore_canstun = FALSE) //Sets remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_PARALYZE, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/SetParalyzed(amount, ignore_canstun = FALSE) //Sets remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_PARALYZE, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) var/datum/status_effect/incapacitating/paralyzed/P = IsParalyzed(FALSE) @@ -203,11 +203,11 @@ if(P) P.duration = world.time + amount else - P = apply_status_effect(STATUS_EFFECT_PARALYZED, amount, updating) + P = apply_status_effect(STATUS_EFFECT_PARALYZED, amount) return P -/mob/living/proc/AdjustParalyzed(amount, updating = TRUE, ignore_canstun = FALSE) //Adds to remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_PARALYZE, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/AdjustParalyzed(amount, ignore_canstun = FALSE) //Adds to remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_PARALYZE, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) if(absorb_stun(amount, ignore_canstun)) @@ -216,33 +216,30 @@ if(P) P.duration += amount else if(amount > 0) - P = apply_status_effect(STATUS_EFFECT_PARALYZED, amount, updating) + P = apply_status_effect(STATUS_EFFECT_PARALYZED, amount) return P //Blanket -/mob/living/proc/AllImmobility(amount, updating) - Paralyze(amount, FALSE) - Knockdown(amount, FALSE) - Stun(amount, FALSE) - Immobilize(amount, FALSE) - if(updating) - update_mobility() - -/mob/living/proc/SetAllImmobility(amount, updating) - SetParalyzed(amount, FALSE) - SetKnockdown(amount, FALSE) - SetStun(amount, FALSE) - SetImmobilized(amount, FALSE) - if(updating) - update_mobility() - -/mob/living/proc/AdjustAllImmobility(amount, updating) - AdjustParalyzed(amount, FALSE) - AdjustKnockdown(amount, FALSE) - AdjustStun(amount, FALSE) - AdjustImmobilized(amount, FALSE) - if(updating) - update_mobility() +/mob/living/proc/AllImmobility(amount) + Paralyze(amount) + Knockdown(amount) + Stun(amount) + Immobilize(amount) + + +/mob/living/proc/SetAllImmobility(amount) + SetParalyzed(amount) + SetKnockdown(amount) + SetStun(amount) + SetImmobilized(amount) + + +/mob/living/proc/AdjustAllImmobility(amount) + AdjustParalyzed(amount) + AdjustKnockdown(amount) + AdjustStun(amount) + AdjustImmobilized(amount) + //////////////////UNCONSCIOUS /mob/living/proc/IsUnconscious() //If we're unconscious @@ -254,19 +251,19 @@ return U.duration - world.time return 0 -/mob/living/proc/Unconscious(amount, updating = TRUE, ignore_canstun = FALSE) //Can't go below remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/Unconscious(amount, ignore_canstun = FALSE) //Can't go below remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANUNCONSCIOUS) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) var/datum/status_effect/incapacitating/unconscious/U = IsUnconscious() if(U) U.duration = max(world.time + amount, U.duration) else if(amount > 0) - U = apply_status_effect(STATUS_EFFECT_UNCONSCIOUS, amount, updating) + U = apply_status_effect(STATUS_EFFECT_UNCONSCIOUS, amount) return U -/mob/living/proc/SetUnconscious(amount, updating = TRUE, ignore_canstun = FALSE) //Sets remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/SetUnconscious(amount, ignore_canstun = FALSE) //Sets remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANUNCONSCIOUS) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) var/datum/status_effect/incapacitating/unconscious/U = IsUnconscious() @@ -276,18 +273,18 @@ else if(U) U.duration = world.time + amount else - U = apply_status_effect(STATUS_EFFECT_UNCONSCIOUS, amount, updating) + U = apply_status_effect(STATUS_EFFECT_UNCONSCIOUS, amount) return U -/mob/living/proc/AdjustUnconscious(amount, updating = TRUE, ignore_canstun = FALSE) //Adds to remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/AdjustUnconscious(amount, ignore_canstun = FALSE) //Adds to remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_UNCONSCIOUS, amount, ignore_canstun) & COMPONENT_NO_STUN) return if(((status_flags & CANUNCONSCIOUS) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canstun) var/datum/status_effect/incapacitating/unconscious/U = IsUnconscious() if(U) U.duration += amount else if(amount > 0) - U = apply_status_effect(STATUS_EFFECT_UNCONSCIOUS, amount, updating) + U = apply_status_effect(STATUS_EFFECT_UNCONSCIOUS, amount) return U /////////////////////////////////// SLEEPING //////////////////////////////////// @@ -301,41 +298,57 @@ return S.duration - world.time return 0 -/mob/living/proc/Sleeping(amount, updating = TRUE, ignore_canstun = FALSE) //Can't go below remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/Sleeping(amount) //Can't go below remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount) & COMPONENT_NO_STUN) return - if((!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) || ignore_canstun) - var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() - if(S) - S.duration = max(world.time + amount, S.duration) - else if(amount > 0) - S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) - return S - -/mob/living/proc/SetSleeping(amount, updating = TRUE, ignore_canstun = FALSE) //Sets remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) + if(status_flags & GODMODE) return - if((!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) || ignore_canstun) - var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() - if(amount <= 0) - if(S) - qdel(S) - else if(S) - S.duration = world.time + amount - else - S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) - return S + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(S) + S.duration = max(world.time + amount, S.duration) + else if(amount > 0) + S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount) + return S -/mob/living/proc/AdjustSleeping(amount, updating = TRUE, ignore_canstun = FALSE) //Adds to remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/SetSleeping(amount) //Sets remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount) & COMPONENT_NO_STUN) return - if((!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) || ignore_canstun) - var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(status_flags & GODMODE) + return + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(amount <= 0) if(S) - S.duration += amount - else if(amount > 0) - S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) - return S + qdel(S) + else if(S) + S.duration = world.time + amount + else + S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount) + return S + +/mob/living/proc/AdjustSleeping(amount) //Adds to remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount) & COMPONENT_NO_STUN) + return + if(status_flags & GODMODE) + return + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(S) + S.duration += amount + else if(amount > 0) + S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount) + return S + +///Allows us to set a permanent sleep on a player (use with caution and remember to unset it with SetSleeping() after the effect is over) +/mob/living/proc/PermaSleeping() + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, -1) & COMPONENT_NO_STUN) + return + if(status_flags & GODMODE) + return + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(S) + S.duration = -1 + else + S = apply_status_effect(STATUS_EFFECT_SLEEPING, -1) + return S ///////////////////////////////// FROZEN ///////////////////////////////////// diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 10b6ed5d1be45..0350d6ee576a1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -518,7 +518,7 @@ //you can only initiate exaimines if you have a hand, it's not disabled, and only as many examines as you have hands /// our active hand, to check if it's disabled/detatched var/obj/item/bodypart/active_hand = has_active_hand()? get_active_hand() : null - if(!active_hand || active_hand.is_disabled() || LAZYLEN(do_afters) >= get_num_arms()) + if(!active_hand || active_hand.bodypart_disabled || LAZYLEN(do_afters) >= usable_hands) to_chat(src, "You don't have a free hand to examine this!") return FALSE @@ -1227,9 +1227,10 @@ /mob/proc/set_nutrition(var/change) //Seriously fuck you oldcoders. nutrition = max(0, change) -///Set the movement type of the mob and update it's movespeed -/mob/setMovetype(newval) +/mob/setMovetype(newval) //Set the movement type of the mob and update it's movespeed . = ..() + if(isnull(.)) + return update_movespeed(FALSE) /mob/proc/update_equipment_speed_mods() diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index d7bbc303bffc1..51f84602cb15e 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -164,21 +164,23 @@ * Called by client/Move() */ /client/proc/Process_Grab() - if(mob.pulledby) - if((mob.pulledby == mob.pulling) && (mob.pulledby.grab_state == GRAB_PASSIVE)) //Don't autoresist passive grabs if we're grabbing them too. - return - if(mob.incapacitated(ignore_restraints = 1)) - move_delay = world.time + 10 - return TRUE - else if(HAS_TRAIT(mob, TRAIT_RESTRAINED)) - move_delay = world.time + 10 - to_chat(src, "You're restrained! You can't move!") - return TRUE - else if(mob.pulledby.grab_state == GRAB_AGGRESSIVE) - move_delay = world.time + 10 - return TRUE - else - return mob.resist_grab(1) + if(!mob.pulledby) + return FALSE + + if(mob.pulledby == mob.pulling && mob.pulledby.grab_state == GRAB_PASSIVE) //Don't autoresist passive grabs if we're grabbing them too. + return FALSE + if(mob.incapacitated(ignore_restraints = TRUE)) + COOLDOWN_START(src, move_delay, 1 SECONDS) + return TRUE + else if(HAS_TRAIT(mob, TRAIT_RESTRAINED)) + COOLDOWN_START(src, move_delay, 1 SECONDS) + to_chat(src, "You're restrained! You can't move!") + return TRUE + else if(mob.pulledby.grab_state == GRAB_AGGRESSIVE) + COOLDOWN_START(src, move_delay, 1 SECONDS) + return TRUE + else + return mob.resist_grab(1) /** * Allows mobs to ignore density and phase through objects diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index cbbb753e510df..69bd4086c1916 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -471,6 +471,8 @@ if(notransform) return TRUE notransform = TRUE + ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_GENERIC) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, TRAIT_GENERIC) Paralyze(1, ignore_canstun = TRUE) if(delete_items) diff --git a/code/modules/multiz/movement/mob/living_zfall.dm b/code/modules/multiz/movement/mob/living_zfall.dm index 45f2daa43f03f..9599a1f5bdcfc 100644 --- a/code/modules/multiz/movement/mob/living_zfall.dm +++ b/code/modules/multiz/movement/mob/living_zfall.dm @@ -33,10 +33,10 @@ var/total_damage_percent_left = 1 var/obj/item/bodypart/left_leg = get_bodypart(BODY_ZONE_L_LEG) var/obj/item/bodypart/right_leg = get_bodypart(BODY_ZONE_R_LEG) - if(left_leg && !left_leg.disabled) + if(left_leg && !left_leg.bodypart_disabled) total_damage_percent_left -= 0.45 apply_damage(amount_total * 0.45, BRUTE, BODY_ZONE_L_LEG) - if(right_leg && !right_leg.disabled) + if(right_leg && !right_leg.bodypart_disabled) total_damage_percent_left -= 0.45 apply_damage(amount_total * 0.45, BRUTE, BODY_ZONE_R_LEG) adjustBruteLoss(amount_total * total_damage_percent_left) diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm index 9cd1dafa1db60..aee33924f9453 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm @@ -11,7 +11,6 @@ H.SetParalyzed(0) H.adjustStaminaLoss(-75) H.stuttering = 0 - H.update_mobility() H.reagents.add_reagent(/datum/reagent/medicine/amphetamine, 5) H.say(pick("A CORNERED FOX IS MORE DANGEROUS THAN A JACKAL!","HURT ME MOOORRREEE!","IMPRESSIVE!"), forced = "ninjaboost") a_boost-- diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 6bef2d1f561e4..95c50ffb478cc 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -379,7 +379,7 @@ icon_state_on = "protoemitter_+a" icon_state_underpowered = "protoemitter_+u" can_buckle = TRUE - buckle_lying = FALSE + buckle_lying = 0 ///Sets the view size for the user var/view_range = 4.5 ///Grants the buckled mob the action button diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index dc0461daa9e91..a84ef9e2cdc8f 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -881,7 +881,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) icon_state = "darkmatter" /obj/machinery/power/supermatter_crystal/proc/supermatter_pull(turf/center, pull_range = 10) - playsound(src.loc, 'sound/weapons/marauder.ogg', 100, 1, extrarange = 7) + playsound(src.loc, 'sound/weapons/marauder.ogg', 100, TRUE, extrarange = 7) for(var/atom/movable/P in orange(pull_range,center)) if(P.anchored || P.move_resist >= MOVE_FORCE_EXTREMELY_STRONG) //move resist memes. return @@ -889,7 +889,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/mob/living/carbon/human/H = P if(H.incapacitated() || !(H.mobility_flags & MOBILITY_STAND) || H.mob_negates_gravity()) return //You can't knock down someone who is already knocked down or has immunity to gravity - H.visible_message("[H] is suddenly knocked down, as if [H.p_their()] [(H.get_num_legs() == 1) ? "leg had" : "legs have"] been pulled out from underneath [H.p_them()]!",\ + H.visible_message("[H] is suddenly knocked down, as if [H.p_their()] [(H.usable_legs == 1) ? "leg had" : "legs have"] been pulled out from underneath [H.p_them()]!",\ "A sudden gravitational pulse knocks you down!",\ "You hear a thud.") H.apply_effect(40, EFFECT_PARALYZE, 0) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 72fe814ef336c..c9731dbc2bf7c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -507,9 +507,9 @@ if (!(L.mobility_flags & MOBILITY_STAND) && L.last_move_time + max(L.inertia_move_delay, CRAWLING_ADD_SLOWDOWN + CONFIG_GET(number/movedelay/run_delay)) > world.time) return TRUE return FALSE - if (L.mobility_flags & MOBILITY_STAND)// if you stand, it returns true and you get hit. If you arent standing(i.e. resting), it returns false and you dont get hit. Such stupid code. + if(L.body_position != LYING_DOWN)// if you stand, it returns true and you get hit. If you arent standing(i.e. resting), it returns false and you dont get hit. Such stupid code. return TRUE - var/stunned = !CHECK_BITFIELD(L.mobility_flags, MOBILITY_USE | MOBILITY_STAND | MOBILITY_MOVE) + var/stunned = HAS_TRAIT(L, TRAIT_IMMOBILIZED) && HAS_TRAIT(L, TRAIT_FLOORED) && HAS_TRAIT(L, TRAIT_HANDS_BLOCKED) return !stunned || hit_stunned_targets return TRUE diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index afa648077f6c8..f38c9be149308 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -160,7 +160,8 @@ return M.notransform = TRUE - M.mobility_flags = NONE + ADD_TRAIT(M, TRAIT_IMMOBILIZED, MAGIC_TRAIT) + ADD_TRAIT(M, TRAIT_HANDS_BLOCKED, MAGIC_TRAIT) M.icon = null M.cut_overlays() M.invisibility = INVISIBILITY_ABSTRACT diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 806e446cffdff..a22ded82d5407 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -380,7 +380,6 @@ addiction_tick++ if(C && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates. C.updatehealth() - C.update_mobility() C.update_stamina() update_total() diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index fbf05aae1dad2..6b483e41f06d7 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -162,7 +162,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/kahlua/on_mob_life(mob/living/carbon/M) M.dizziness = max(0,M.dizziness-5) M.drowsyness = max(0,M.drowsyness-3) - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) if(!HAS_TRAIT(M, TRAIT_ALCOHOL_TOLERANCE)) M.Jitter(5) ..() @@ -1352,10 +1352,10 @@ All effects don't start immediately, but rather get worse over time; the rate is M.slurring += 3 switch(current_cycle) if(51 to 200) - M.Sleeping(100, FALSE) + M.Sleeping(100) . = 1 if(201 to INFINITY) - M.AdjustSleeping(40, FALSE) + M.AdjustSleeping(40) M.adjustToxLoss(2, 0) . = 1 ..() diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index a38a27bb81b8b..4d67bdd2f423d 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -319,7 +319,7 @@ /datum/reagent/consumable/coffee/on_mob_life(mob/living/carbon/M) M.dizziness = max(0,M.dizziness-5) M.drowsyness = max(0,M.drowsyness-3) - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) //310.15 is the normal bodytemp. M.adjust_bodytemperature(25 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) if(holder.has_reagent(/datum/reagent/consumable/frostoil)) @@ -393,7 +393,7 @@ /datum/reagent/consumable/icecoffee/on_mob_life(mob/living/carbon/M) M.dizziness = max(0,M.dizziness-5) M.drowsyness = max(0,M.drowsyness-3) - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, M.get_body_temp_normal()) M.Jitter(5) ..() @@ -413,7 +413,7 @@ /datum/reagent/consumable/icetea/on_mob_life(mob/living/carbon/M) M.dizziness = max(0,M.dizziness-2) M.drowsyness = max(0,M.drowsyness-1) - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) if(M.getToxLoss() && prob(20)) M.adjustToxLoss(-1, 0) M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, M.get_body_temp_normal()) @@ -459,7 +459,7 @@ M.set_drugginess(30) M.dizziness += 1.5 M.drowsyness = 0 - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, M.get_body_temp_normal()) M.radiation += 4 ..() @@ -488,7 +488,7 @@ M.Jitter(20) M.dizziness +=1 M.drowsyness = 0 - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, M.get_body_temp_normal()) ..() @@ -611,7 +611,7 @@ /datum/reagent/consumable/tonic/on_mob_life(mob/living/carbon/M) M.dizziness = max(0,M.dizziness-5) M.drowsyness = max(0,M.drowsyness-3) - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, M.get_body_temp_normal()) ..() . = 1 @@ -630,7 +630,7 @@ M.Jitter(20) M.dizziness +=1 M.drowsyness = 0 - M.AdjustSleeping(-40, FALSE) + M.AdjustSleeping(-40) M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, M.get_body_temp_normal()) ..() @@ -672,7 +672,7 @@ /datum/reagent/consumable/soy_latte/on_mob_life(mob/living/carbon/M) M.dizziness = max(0,M.dizziness-5) M.drowsyness = max(0,M.drowsyness-3) - M.SetSleeping(0, FALSE) + M.SetSleeping(0) M.adjust_bodytemperature(5 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) M.Jitter(5) if(M.getBruteLoss() && prob(20)) @@ -694,7 +694,7 @@ /datum/reagent/consumable/cafe_latte/on_mob_life(mob/living/carbon/M) M.dizziness = max(0,M.dizziness-5) M.drowsyness = max(0,M.drowsyness-3) - M.SetSleeping(0, FALSE) + M.SetSleeping(0) M.adjust_bodytemperature(5 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) M.Jitter(5) if(M.getBruteLoss() && prob(20)) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index a17407ad18330..612ccc4b8f744 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -19,7 +19,7 @@ /datum/reagent/drug/space_drugs/on_mob_life(mob/living/carbon/M) M.set_drugginess(15) if(isturf(M.loc) && !isspaceturf(M.loc)) - if(M.mobility_flags & MOBILITY_MOVE) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED)) if(prob(10)) step(M, pick(GLOB.cardinals)) if(prob(7)) @@ -52,11 +52,11 @@ var/smoke_message = pick("You feel relaxed.", "You feel calmed.","You feel alert.","You feel rugged.") to_chat(M, "[smoke_message]") SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "smoked", /datum/mood_event/smoked, name) - M.AdjustStun(-5, FALSE) - M.AdjustKnockdown(-5, FALSE) - M.AdjustUnconscious(-5, FALSE) - M.AdjustParalyzed(-5, FALSE) - M.AdjustImmobilized(-5, FALSE) + M.AdjustStun(-5) + M.AdjustKnockdown(-5) + M.AdjustUnconscious(-5) + M.AdjustParalyzed(-5) + M.AdjustImmobilized(-5) ..() . = 1 @@ -91,13 +91,13 @@ M.adjustBruteLoss(rand(1,4)) M.Stun(5, 0) to_chat(M, "You stop to furiously scratch at your skin.") - M.AdjustStun(-20, FALSE) - M.AdjustKnockdown(-20, FALSE) - M.AdjustUnconscious(-20, FALSE) - M.AdjustImmobilized(-20, FALSE) - M.AdjustParalyzed(-20, FALSE) - M.adjustToxLoss(0.75, 0) - M.adjustStaminaLoss(-18, 0) + M.AdjustStun(-20) + M.AdjustKnockdown(-20) + M.AdjustUnconscious(-20) + M.AdjustImmobilized(-20) + M.AdjustParalyzed(-20) + M.adjustToxLoss(0.75) + M.adjustStaminaLoss(-18) ..() . = 1 @@ -214,12 +214,12 @@ var/high_message = pick("You feel hyper.", "You feel like you need to go faster.", "You feel like you can run the world.") if(prob(5)) to_chat(M, "[high_message]") - M.AdjustStun(-40, FALSE) - M.AdjustKnockdown(-40, FALSE) - M.AdjustUnconscious(-40, FALSE) - M.AdjustParalyzed(-40, FALSE) - M.AdjustImmobilized(-40, FALSE) - M.adjustStaminaLoss(-40, 0) + M.AdjustStun(-40) + M.AdjustKnockdown(-40) + M.AdjustUnconscious(-40) + M.AdjustParalyzed(-40) + M.AdjustImmobilized(-40) + M.adjustStaminaLoss(-40) M.drowsyness = max(0,M.drowsyness-30) M.Jitter(2) M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1) @@ -229,7 +229,7 @@ . = 1 /datum/reagent/drug/methamphetamine/overdose_process(mob/living/M) - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i in 1 to 4) step(M, pick(GLOB.cardinals)) if(prob(20)) @@ -256,7 +256,7 @@ ..() /datum/reagent/drug/methamphetamine/addiction_act_stage3(mob/living/M) - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i = 0, i < 4, i++) step(M, pick(GLOB.cardinals)) M.Jitter(15) @@ -266,7 +266,7 @@ ..() /datum/reagent/drug/methamphetamine/addiction_act_stage4(mob/living/carbon/human/M) - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i = 0, i < 8, i++) step(M, pick(GLOB.cardinals)) M.Jitter(20) @@ -318,7 +318,7 @@ M.adjustStaminaLoss(-5, 0) M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) M.hallucination += 5 - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) step(M, pick(GLOB.cardinals)) step(M, pick(GLOB.cardinals)) ..() @@ -326,7 +326,7 @@ /datum/reagent/drug/bath_salts/overdose_process(mob/living/M) M.hallucination += 5 - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i in 1 to 8) step(M, pick(GLOB.cardinals)) if(prob(20)) @@ -337,7 +337,7 @@ /datum/reagent/drug/bath_salts/addiction_act_stage1(mob/living/M) M.hallucination += 10 - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i = 0, i < 8, i++) step(M, pick(GLOB.cardinals)) M.Jitter(5) @@ -348,7 +348,7 @@ /datum/reagent/drug/bath_salts/addiction_act_stage2(mob/living/M) M.hallucination += 20 - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i = 0, i < 8, i++) step(M, pick(GLOB.cardinals)) M.Jitter(10) @@ -360,7 +360,7 @@ /datum/reagent/drug/bath_salts/addiction_act_stage3(mob/living/M) M.hallucination += 30 - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i = 0, i < 12, i++) step(M, pick(GLOB.cardinals)) M.Jitter(15) @@ -372,7 +372,7 @@ /datum/reagent/drug/bath_salts/addiction_act_stage4(mob/living/carbon/human/M) M.hallucination += 30 - if((M.mobility_flags & MOBILITY_MOVE) && !ismovable(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) for(var/i = 0, i < 16, i++) step(M, pick(GLOB.cardinals)) M.Jitter(50) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 4dbd49cc71059..edc67bc114664 100755 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -183,11 +183,11 @@ /datum/reagent/consumable/sugar/overdose_start(mob/living/M) to_chat(M, "You go into hyperglycaemic shock! Lay off the twinkies!") - M.AdjustSleeping(600, FALSE) + M.AdjustSleeping(600) . = 1 /datum/reagent/consumable/sugar/overdose_process(mob/living/M) - M.AdjustSleeping(40, FALSE) + M.AdjustSleeping(40) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index d6bae0797ad6c..c38ccc49a781d 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -63,11 +63,11 @@ REMOVE_TRAITS_NOT_IN(M, list(SPECIES_TRAIT, ROUNDSTART_TRAIT, ORGAN_TRAIT, TRAIT_GENERIC)) M.set_blurriness(0) M.set_blindness(0) - M.SetKnockdown(0, FALSE) - M.SetStun(0, FALSE) - M.SetUnconscious(0, FALSE) - M.SetParalyzed(0, FALSE) - M.SetImmobilized(0, FALSE) + M.SetKnockdown(0) + M.SetStun(0) + M.SetUnconscious(0) + M.SetParalyzed(0) + M.SetImmobilized(0) M.silent = FALSE M.dizziness = 0 M.disgust = 0 @@ -105,11 +105,11 @@ /datum/reagent/medicine/synaptizine/on_mob_life(mob/living/carbon/M) M.drowsyness = max(M.drowsyness-5, 0) - M.AdjustStun(-20, FALSE) - M.AdjustKnockdown(-20, FALSE) - M.AdjustUnconscious(-20, FALSE) - M.AdjustImmobilized(-20, FALSE) - M.AdjustParalyzed(-20, FALSE) + M.AdjustStun(-20) + M.AdjustKnockdown(-20) + M.AdjustUnconscious(-20) + M.AdjustImmobilized(-20) + M.AdjustParalyzed(-20) if(holder.has_reagent(/datum/reagent/toxin/mindbreaker)) holder.remove_reagent(/datum/reagent/toxin/mindbreaker, 5) M.hallucination = max(0, M.hallucination - 10) @@ -682,7 +682,7 @@ to_chat(M, "Your hands spaz out and you drop what you were holding!") M.Jitter(10) - M.AdjustAllImmobility(-20, FALSE) + M.AdjustAllImmobility(-20) M.adjustStaminaLoss(-10*REM, FALSE) ..() return TRUE @@ -791,7 +791,7 @@ if(12 to 24) M.drowsyness += 1 if(24 to INFINITY) - M.Sleeping(40, 0) + M.Sleeping(40) . = 1 ..() @@ -926,7 +926,7 @@ M.adjustStaminaLoss(-0.5*REM, 0) . = 1 if(prob(20)) - M.AdjustAllImmobility(-20, FALSE) + M.AdjustAllImmobility(-20) ..() /datum/reagent/medicine/epinephrine/overdose_process(mob/living/M) @@ -1069,7 +1069,7 @@ M.adjustToxLoss(-1*REM, 0) M.adjustBruteLoss(-1*REM, 0) M.adjustFireLoss(-1*REM, 0) - M.AdjustAllImmobility(-60, FALSE) + M.AdjustAllImmobility(-60) M.adjustStaminaLoss(-35*REM, 0) ..() . = 1 @@ -1129,7 +1129,7 @@ metabolization_rate = 0.5 * REAGENTS_METABOLISM /datum/reagent/medicine/insulin/on_mob_life(mob/living/carbon/M) - if(M.AdjustSleeping(-20, FALSE)) + if(M.AdjustSleeping(-20)) . = 1 M.reagents.remove_reagent(/datum/reagent/consumable/sugar, 3) ..() @@ -1474,7 +1474,7 @@ overdose_threshold = 30 /datum/reagent/medicine/changelingadrenaline/on_mob_life(mob/living/carbon/M as mob) - M.AdjustAllImmobility(-20, FALSE) + M.AdjustAllImmobility(-20) M.adjustStaminaLoss(-20, 0) ..() return TRUE @@ -1567,7 +1567,7 @@ /datum/reagent/medicine/modafinil/on_mob_life(mob/living/carbon/M) if(!overdosed) // We do not want any effects on OD overdose_threshold = overdose_threshold + rand(-10,10)/10 // for extra fun - M.AdjustAllImmobility(-20, FALSE) + M.AdjustAllImmobility(-20) M.adjustStaminaLoss(-15*REM, 0) M.Jitter(1) metabolization_rate = 0.01 * REAGENTS_METABOLISM * rand(5,20) // randomizes metabolism between 0.02 and 0.08 per tick @@ -1598,13 +1598,13 @@ if(prob(20)) to_chat(M, "You have a sudden fit!") M.emote("moan") - M.Paralyze(20, 1, 0) // you should be in a bad spot at this point unless epipen has been used + M.Paralyze(20) // you should be in a bad spot at this point unless epipen has been used if(81) to_chat(M, "You feel too exhausted to continue!") // at this point you will eventually die unless you get charcoal M.adjustOxyLoss(0.1*REM, 0) M.adjustStaminaLoss(0.1*REM, 0) if(82 to INFINITY) - M.Sleeping(100, 0, TRUE) + M.Sleeping(100) M.adjustOxyLoss(1.5*REM, 0) M.adjustStaminaLoss(1.5*REM, 0) ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 100afadf44b2f..10b8e0b0fa486 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -329,7 +329,7 @@ /datum/reagent/fuel/unholywater/on_mob_life(mob/living/carbon/M) if(iscultist(M)) M.drowsyness = max(M.drowsyness-5, 0) - M.AdjustAllImmobility(-40, FALSE) + M.AdjustAllImmobility(-40) M.adjustStaminaLoss(-10, 0) M.adjustToxLoss(-2, 0) M.adjustOxyLoss(-2, 0) @@ -853,7 +853,7 @@ taste_mult = 0 // apparently tasteless. /datum/reagent/mercury/on_mob_life(mob/living/carbon/M) - if((M.mobility_flags & MOBILITY_MOVE) && !isspaceturf(M.loc)) + if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && !isspaceturf(M.loc)) step(M, pick(GLOB.cardinals)) if(prob(5)) M.emote(pick("twitch","drool","moan")) @@ -934,7 +934,7 @@ taste_description = "metal" /datum/reagent/lithium/on_mob_life(mob/living/carbon/M) - if((M.mobility_flags & MOBILITY_MOVE) && !isspaceturf(M.loc) && isturf(M.loc)) + if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !isspaceturf(M.loc) && isturf(M.loc)) step(M, pick(GLOB.cardinals)) if(prob(5)) M.emote(pick("twitch","drool","moan")) @@ -2166,7 +2166,7 @@ /datum/reagent/eldritch/on_mob_life(mob/living/carbon/M) if(IS_HERETIC(M)) M.drowsyness = max(M.drowsyness-5, 0) - M.AdjustAllImmobility(-40, FALSE) + M.AdjustAllImmobility(-40) M.adjustStaminaLoss(-10, FALSE) M.adjustToxLoss(-2, FALSE) M.adjustOxyLoss(-2, FALSE) diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index 3d8aa24424613..c22f01d136836 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -283,7 +283,7 @@ /datum/reagent/teslium/energized_jelly/on_mob_life(mob/living/carbon/M) if(isoozeling(M)) shock_timer = 0 //immune to shocks - M.AdjustAllImmobility(-40, FALSE) + M.AdjustAllImmobility(-40) M.adjustStaminaLoss(-2, 0) if(isluminescent(M)) var/mob/living/carbon/human/H = M diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 9892217b880e5..567fc0d499958 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -288,10 +288,10 @@ M.confused += 2 M.drowsyness += 2 if(10 to 50) - M.Sleeping(40, 0) + M.Sleeping(40) . = 1 if(51 to INFINITY) - M.Sleeping(40, 0) + M.Sleeping(40) M.adjustToxLoss((current_cycle - 50)*REM, 0) . = 1 ..() @@ -310,9 +310,9 @@ /datum/reagent/toxin/fakebeer/on_mob_life(mob/living/carbon/M) switch(current_cycle) if(1 to 50) - M.Sleeping(40, 0) + M.Sleeping(40) if(51 to INFINITY) - M.Sleeping(40, 0) + M.Sleeping(40) M.adjustToxLoss((current_cycle - 50)*REM, 0) return ..() @@ -486,7 +486,7 @@ if(M.toxloss <= 60) M.adjustToxLoss(1*REM, 0) if(current_cycle >= 18) - M.Sleeping(40, 0) + M.Sleeping(40) ..() return TRUE @@ -504,7 +504,7 @@ M.losebreath += 1 if(prob(8)) to_chat(M, "You feel horrendously weak!") - M.Stun(40, 0) + M.Stun(40) M.adjustToxLoss(2*REM, 0) return ..() @@ -566,7 +566,7 @@ var/picked_option = rand(1,3) switch(picked_option) if(1) - C.Paralyze(60, 0) + C.Paralyze(60) . = TRUE if(2) C.losebreath += 10 @@ -596,7 +596,7 @@ /datum/reagent/toxin/pancuronium/on_mob_life(mob/living/carbon/M) if(current_cycle >= 10) - M.Stun(40, 0) + M.Stun(40) . = TRUE if(prob(20)) M.losebreath += 4 @@ -614,7 +614,7 @@ /datum/reagent/toxin/sodium_thiopental/on_mob_life(mob/living/carbon/M) if(current_cycle >= 10) - M.Sleeping(40, 0) + M.Sleeping(40) M.adjustStaminaLoss(10*REM, 0) ..() return TRUE @@ -631,7 +631,7 @@ /datum/reagent/toxin/sulfonal/on_mob_life(mob/living/carbon/M) if(current_cycle >= 22) - M.Sleeping(40, 0) + M.Sleeping(40) return ..() /datum/reagent/toxin/amanitin @@ -718,7 +718,7 @@ /datum/reagent/toxin/curare/on_mob_life(mob/living/carbon/M) if(current_cycle >= 11) - M.Paralyze(60, 0) + M.Paralyze(60) M.adjustOxyLoss(1*REM, 0) . = 1 ..() @@ -856,7 +856,7 @@ holder.remove_reagent(type, actual_metaboliztion_rate * M.metabolism_efficiency) M.adjustToxLoss(actual_toxpwr*REM, 0) if(prob(10)) - M.Paralyze(20, 0) + M.Paralyze(20) . = 1 ..() diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 457950ed9a53c..ae636947e99ae 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -62,7 +62,9 @@ /obj/item/reagent_containers/spray/proc/spray(atom/A, mob/user) var/range = max(min(current_range, get_dist(src, A)), 1) + var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src)) + D.create_reagents(amount_per_transfer_from_this) var/puff_reagent_left = range //how many turf, mob or dense objet we can react with before we consider the chem puff consumed if(stream_mode) @@ -72,6 +74,7 @@ reagents.trans_to(D, amount_per_transfer_from_this, 1/range) D.color = mix_color_from_reagents(D.reagents.reagent_list) var/wait_step = max(round(2+3/range), 2) + do_spray(A, wait_step, D, range, puff_reagent_left, user) /obj/item/reagent_containers/spray/proc/do_spray(atom/A, wait_step, obj/effect/decal/chempuff/D, range, puff_reagent_left, mob/user) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 3addaeb41f56b..b279a252b4716 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -143,7 +143,7 @@ . = TRUE update_appearance() -/obj/machinery/disposal/relaymove(mob/user) +/obj/machinery/disposal/relaymove(mob/living/user, direction) attempt_escape(user) // resist to escape the bin diff --git a/code/modules/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm index 159024937c109..4ff466db0f06c 100644 --- a/code/modules/recycling/disposal/holder.dm +++ b/code/modules/recycling/disposal/holder.dm @@ -135,7 +135,7 @@ // called when player tries to move while in a pipe -/obj/structure/disposalholder/relaymove(mob/user) +/obj/structure/disposalholder/relaymove(mob/living/user, direction) if(user.incapacitated()) return for(var/mob/M as() in hearers(5, get_turf(src))) diff --git a/code/modules/research/nanites/nanite_chamber.dm b/code/modules/research/nanites/nanite_chamber.dm index 112b178a58aec..966c9dc4207b8 100644 --- a/code/modules/research/nanites/nanite_chamber.dm +++ b/code/modules/research/nanites/nanite_chamber.dm @@ -187,7 +187,7 @@ return TRUE -/obj/machinery/nanite_chamber/relaymove(mob/user as mob) +/obj/machinery/nanite_chamber/relaymove(mob/living/user, direction) if(user.stat || locked) if(message_cooldown <= world.time) message_cooldown = world.time + 50 diff --git a/code/modules/research/nanites/nanite_programs/buffing.dm b/code/modules/research/nanites/nanite_programs/buffing.dm index 3a3e0c357cc2c..eb11675deeff4 100644 --- a/code/modules/research/nanites/nanite_programs/buffing.dm +++ b/code/modules/research/nanites/nanite_programs/buffing.dm @@ -31,7 +31,6 @@ host_mob.SetAllImmobility(0) host_mob.adjustStaminaLoss(-75) host_mob.set_resting(FALSE) - host_mob.update_mobility() /datum/nanite_program/hardening name = "Dermal Hardening" diff --git a/code/modules/research/nanites/public_chamber.dm b/code/modules/research/nanites/public_chamber.dm index 527ca9c96339b..a1aa67d48c595 100644 --- a/code/modules/research/nanites/public_chamber.dm +++ b/code/modules/research/nanites/public_chamber.dm @@ -183,7 +183,7 @@ return TRUE -/obj/machinery/public_nanite_chamber/relaymove(mob/user as mob) +/obj/machinery/public_nanite_chamber/relaymove(mob/living/user, direction) if(user.stat || locked) if(message_cooldown <= world.time) message_cooldown = world.time + 50 diff --git a/code/modules/ruins/lavalandruin_code/puzzle.dm b/code/modules/ruins/lavalandruin_code/puzzle.dm index 432c4b2ea9155..0c2557c16398a 100644 --- a/code/modules/ruins/lavalandruin_code/puzzle.dm +++ b/code/modules/ruins/lavalandruin_code/puzzle.dm @@ -298,7 +298,7 @@ /obj/structure/puzzle_element/prison armor = list(MELEE = 50, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 50, BIO = 50, RAD = 50, FIRE = 50, ACID = 50, STAMINA = 0, BLEED = 0) -/obj/structure/puzzle_element/prison/relaymove(mob/user) +/obj/structure/puzzle_element/prison/relaymove(mob/living/user, direction) return /obj/item/prisoncube diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index d99a5678b07f0..ccfc1768b2995 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -257,7 +257,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) tugged_on = 0 return if(alert(user, "Hilbert's Hotel would like to remind you that while we will do everything we can to protect the belongings you leave behind, we make no guarantees of their safety while you're gone, especially that of the health of any living creatures. With that in mind, are you ready to leave?", "Exit", "Leave", "Stay") == "Leave") - if(!(user.mobility_flags & MOBILITY_MOVE) || (get_dist(get_turf(src), get_turf(user)) > 1)) //no teleporting around if they're dead or moved away during the prompt. + if(HAS_TRAIT(user, TRAIT_IMMOBILIZED) || (get_dist(get_turf(src), get_turf(user)) > 1)) //no teleporting around if they're dead or moved away during the prompt. return user.forceMove(get_turf(parentSphere)) do_sparks(3, FALSE, get_turf(user)) diff --git a/code/modules/spells/spell_types/ethereal_jaunt.dm b/code/modules/spells/spell_types/ethereal_jaunt.dm index 7527ca9d9ac26..198cd51b0ee4c 100644 --- a/code/modules/spells/spell_types/ethereal_jaunt.dm +++ b/code/modules/spells/spell_types/ethereal_jaunt.dm @@ -52,7 +52,7 @@ return mobloc = get_turf(target.loc) jaunt_steam(mobloc) - target.mobility_flags &= ~MOBILITY_MOVE + ADD_TRAIT(target, TRAIT_IMMOBILIZED, type) holder.reappearing = 1 play_sound("exit",target) sleep(25 - jaunt_in_time) @@ -67,7 +67,7 @@ if(T) if(target.Move(T)) break - target.mobility_flags |= MOBILITY_MOVE + REMOVE_TRAIT(target, TRAIT_IMMOBILIZED, type) /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_steam(mobloc) var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread() @@ -99,7 +99,7 @@ AM.forceMove(get_turf(src)) return ..() -/obj/effect/dummy/phased_mob/spell_jaunt/relaymove(var/mob/user, direction) +/obj/effect/dummy/phased_mob/spell_jaunt/relaymove(mob/living/user, direction) if ((movedelay > world.time) || reappearing || !direction) return var/turf/newLoc = get_step(src,direction) diff --git a/code/modules/spells/spell_types/shadow_walk.dm b/code/modules/spells/spell_types/shadow_walk.dm index 67d2fe2e0d989..992c303edecda 100644 --- a/code/modules/spells/spell_types/shadow_walk.dm +++ b/code/modules/spells/spell_types/shadow_walk.dm @@ -45,7 +45,7 @@ invisibility = 60 resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF -/obj/effect/dummy/phased_mob/shadow/relaymove(mob/user, direction) +/obj/effect/dummy/phased_mob/shadow/relaymove(mob/living/user, direction) var/turf/newLoc = get_step(src,direction) if(isspaceturf(newLoc)) to_chat(user, "It really would not be wise to go into space.") diff --git a/code/modules/spells/spell_types/touch_attacks.dm b/code/modules/spells/spell_types/touch_attacks.dm index 43c8f54d5dfb5..9af90c350c286 100644 --- a/code/modules/spells/spell_types/touch_attacks.dm +++ b/code/modules/spells/spell_types/touch_attacks.dm @@ -50,7 +50,7 @@ attached_hand = create_hand() if(!user.put_in_hands(attached_hand)) remove_hand() - if (user.get_num_arms() <= 0) + if (user.usable_hands == 0) to_chat(user, "You dont have any usable hands!") else to_chat(user, "Your hands are full!") diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index e6d288b648ef5..0cdd5a7539030 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -35,7 +35,13 @@ var/held_index = 0 //are we a hand? if so, which one! var/is_pseudopart = FALSE //For limbs that don't really exist, eg chainsaws - var/disabled = BODYPART_NOT_DISABLED //If disabled, limb is as good as missing + ///If disabled, limb is as good as missing. + var/bodypart_disabled = FALSE + ///Multiplied by max_damage it returns the threshold which defines a limb being disabled or not. From 0 to 1. + var/disable_threshold = 1 + ///Controls whether bodypart_disabled makes sense or not for this limb. + var/can_be_disabled = FALSE + var/body_damage_coeff = 1 //Multiplier of the limb's damage that gets applied to the mob var/stam_damage_coeff = 0.7 //Why is this the default??? var/brutestate = 0 @@ -76,13 +82,32 @@ var/medium_burn_msg = "blistered" var/heavy_burn_msg = "peeling away" + /// So we know if we need to scream if this limb hits max damage + var/last_maxed + /obj/item/bodypart/Initialize(mapload) . = ..() + if(can_be_disabled) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS), PROC_REF(on_paralysis_trait_gain)) + RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS), PROC_REF(on_paralysis_trait_loss)) name = "[limb_id] [parse_zone(body_zone)]" if(is_dimorphic) limb_gender = pick("m", "f") update_icon_dropped() +/obj/item/bodypart/Destroy() + if(owner) + owner.remove_bodypart(src) + set_owner(null) + /* + for(var/wound in wounds) + qdel(wound) // wounds is a lazylist, and each wound removes itself from it on deletion. + if(length(wounds)) + stack_trace("[type] qdeleted with [length(wounds)] uncleared wounds") + wounds.Cut() + */ + return ..() + /obj/item/bodypart/forceMove(atom/destination) //Please. Never forcemove a limb if its's actually in use. This is only for borgs. . = ..() if(isturf(destination)) @@ -100,12 +125,6 @@ /obj/item/bodypart/blob_act() take_damage(max_damage) -/obj/item/bodypart/Destroy() - if(owner) - owner.bodyparts -= src - owner = null - return ..() - /obj/item/bodypart/attack(mob/living/carbon/C, mob/user) if(ishuman(C)) var/mob/living/carbon/human/H = C @@ -139,7 +158,7 @@ /obj/item/bodypart/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(IS_ORGANIC_LIMB(src)) - playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1) + playsound(get_turf(src), 'sound/misc/splort.ogg', 50, TRUE, -1) pixel_x = rand(-3, 3) pixel_y = rand(-3, 3) @@ -151,17 +170,11 @@ for(var/obj/item/I in src) I.forceMove(T) -/obj/item/bodypart/proc/consider_processing() - if(stamina_dam >= DAMAGE_PRECISION) - . = TRUE - //else if.. else if.. so on. - else - . = FALSE - needs_processing = . - //Return TRUE to get whatever mob this is in to update health. /obj/item/bodypart/proc/on_life(stam_regen) - if(stamina_dam >= DAMAGE_PRECISION && stam_regen) //DO NOT update health here, it'll be done in the carbon's life. + SHOULD_CALL_PARENT(TRUE) + //DO NOT update health here, it'll be done in the carbon's life. + if(stamina_dam >= DAMAGE_PRECISION && stam_regen) heal_damage(0, 0, stam_regen, null, FALSE) . |= BODYPART_LIFE_UPDATE_HEALTH @@ -169,6 +182,8 @@ //Damage will not exceed max_damage using this proc //Cannot apply negative damage /obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null) + SHOULD_CALL_PARENT(TRUE) + var/hit_percent = (100-blocked)/100 if((!brute && !burn && !stamina) || hit_percent <= 0) return FALSE @@ -195,53 +210,91 @@ var/can_inflict = (max_damage * 2) - get_damage() if(can_inflict <= 0) return FALSE - var/total_damage = brute + burn - if(total_damage > can_inflict) brute = round(brute * (can_inflict / total_damage),DAMAGE_PRECISION) burn = round(burn * (can_inflict / total_damage),DAMAGE_PRECISION) - brute_dam += brute - burn_dam += burn + if(brute) + set_brute_dam(brute_dam + brute) + if(burn) + set_burn_dam(burn_dam + burn) //We've dealt the physical damages, if there's room lets apply the stamina damage. - var/current_damage = get_damage(TRUE) //This time around, count stamina loss too. - var/available_damage = max_damage - current_damage - var/applied_damage = min(max_stamina_damage - stamina_dam, available_damage) - stamina_dam += round(clamp(stamina, 0, applied_damage), DAMAGE_PRECISION) - + if(stamina) + set_stamina_dam(stamina_dam + round(clamp(stamina, 0, max_stamina_damage - stamina_dam), DAMAGE_PRECISION)) - if(owner && updating_health) - owner.updatehealth() - if(stamina >= DAMAGE_PRECISION) - owner.update_stamina(TRUE) - owner.stam_regen_start_time = max(owner.stam_regen_start_time, world.time + STAMINA_REGEN_BLOCK_TIME) - consider_processing() - update_disabled() - return update_bodypart_damage_state() + if(owner) + if(can_be_disabled) + update_disabled() + if(updating_health) + owner.updatehealth() + if(stamina >= DAMAGE_PRECISION) + owner.update_stamina(TRUE) + owner.stam_regen_start_time = max(owner.stam_regen_start_time, world.time + STAMINA_REGEN_BLOCK_TIME) + . = TRUE + return update_bodypart_damage_state() || . //Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all. //Damage cannot go below zero. //Cannot remove negative damage (i.e. apply damage) /obj/item/bodypart/proc/heal_damage(brute, burn, stamina, required_status, updating_health = TRUE) + SHOULD_CALL_PARENT(TRUE) if(required_status && !(bodytype & required_status)) //So we can only heal certain kinds of limbs, ie robotic vs organic. return - brute_dam = round(max(brute_dam - brute, 0), DAMAGE_PRECISION) - burn_dam = round(max(burn_dam - burn, 0), DAMAGE_PRECISION) - stamina_dam = round(max(stamina_dam - stamina, 0), DAMAGE_PRECISION) - if(owner && updating_health) - owner.updatehealth() - if(owner.dna && owner.dna.species && (REVIVESBYHEALING in owner.dna.species.species_traits)) - if(owner.health > 0 && !owner.ishellbound()) - owner.revive(0) - owner.cure_husk(0) // If it has REVIVESBYHEALING, it probably can't be cloned. No husk cure. - consider_processing() - update_disabled() + if(brute) + set_brute_dam(round(max(brute_dam - brute, 0), DAMAGE_PRECISION)) + if(burn) + set_burn_dam(round(max(burn_dam - burn, 0), DAMAGE_PRECISION)) + if(stamina) + set_stamina_dam(round(max(stamina_dam - stamina, 0), DAMAGE_PRECISION)) + + if(owner) + if(can_be_disabled) + update_disabled() + if(updating_health) + owner.updatehealth() + if(owner.dna?.species && (REVIVESBYHEALING in owner.dna.species.species_traits)) + if(owner.health > 0 && !owner.ishellbound()) + owner.revive(0) + owner.cure_husk(0) // If it has REVIVESBYHEALING, it probably can't be cloned. No husk cure. return update_bodypart_damage_state() +///Proc to hook behavior associated to the change of the brute_dam variable's value. +/obj/item/bodypart/proc/set_brute_dam(new_value) + PROTECTED_PROC(TRUE) + + if(brute_dam == new_value) + return + . = brute_dam + brute_dam = new_value + + +///Proc to hook behavior associated to the change of the burn_dam variable's value. +/obj/item/bodypart/proc/set_burn_dam(new_value) + PROTECTED_PROC(TRUE) + + if(burn_dam == new_value) + return + . = burn_dam + burn_dam = new_value + + +///Proc to hook behavior associated to the change of the stamina_dam variable's value. +/obj/item/bodypart/proc/set_stamina_dam(new_value) + PROTECTED_PROC(TRUE) + + if(stamina_dam == new_value) + return + . = stamina_dam + stamina_dam = new_value + if(stamina_dam > DAMAGE_PRECISION) + needs_processing = TRUE + else + needs_processing = FALSE + //Returns total damage. /obj/item/bodypart/proc/get_damage(include_stamina = FALSE) var/total = brute_dam + burn_dam @@ -255,28 +308,144 @@ //Checks disabled status thresholds /obj/item/bodypart/proc/update_disabled() - set_disabled(is_disabled()) + SHOULD_CALL_PARENT(TRUE) + + if(!owner) + return + + if(!can_be_disabled) + set_disabled(FALSE) + CRASH("update_disabled called with can_be_disabled false") -/obj/item/bodypart/proc/is_disabled() if(HAS_TRAIT(src, TRAIT_PARALYSIS)) - return BODYPART_DISABLED_PARALYSIS - if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) - . = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled - if((get_damage(TRUE) >= max_damage) || (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) && (get_damage(TRUE) >= (max_damage * 0.6)))) //Easy limb disable disables the limb at 40% health instead of 0% - return BODYPART_DISABLED_DAMAGE - if(disabled && (get_damage(TRUE) <= (max_damage * 0.5))) - return BODYPART_NOT_DISABLED - else - return BODYPART_NOT_DISABLED + set_disabled(TRUE) + return + var/total_damage = max(brute_dam + burn_dam, stamina_dam) + + if(total_damage >= max_damage * disable_threshold) //Easy limb disable disables the limb at 40% health instead of 0% + if(!last_maxed) + if(owner.stat < UNCONSCIOUS) + INVOKE_ASYNC(owner, TYPE_PROC_REF(/mob, emote), "scream") + last_maxed = TRUE + set_disabled(TRUE) + return + + if(bodypart_disabled && total_damage <= max_damage * 0.5) + last_maxed = FALSE + set_disabled(FALSE) + + +///Proc to change the value of the `disabled` variable and react to the event of its change. /obj/item/bodypart/proc/set_disabled(new_disabled) - if(disabled == new_disabled) + SHOULD_CALL_PARENT(TRUE) + PROTECTED_PROC(TRUE) + + if(bodypart_disabled == new_disabled) + return + . = bodypart_disabled + bodypart_disabled = new_disabled + + if(!owner) return - disabled = new_disabled owner.update_health_hud() //update the healthdoll owner.update_body() - owner.update_mobility() - return TRUE //if there was a change. + +///Proc to change the value of the `owner` variable and react to the event of its change. +/obj/item/bodypart/proc/set_owner(mob/living/carbon/new_owner) + SHOULD_CALL_PARENT(TRUE) + + if(owner == new_owner) + return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made. + var/mob/living/carbon/old_owner = owner + owner = new_owner + var/needs_update_disabled = FALSE //Only really relevant if there's an owner + if(old_owner) + if(initial(can_be_disabled)) + if(HAS_TRAIT(old_owner, TRAIT_NOLIMBDISABLE)) + if(!owner || !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) + set_can_be_disabled(initial(can_be_disabled)) + needs_update_disabled = TRUE + UnregisterSignal(old_owner, list( + SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), + SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), + )) + if(owner) + if(initial(can_be_disabled)) + if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) + set_can_be_disabled(FALSE) + needs_update_disabled = FALSE + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_loss)) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_gain)) + + if(needs_update_disabled) + update_disabled() + + return old_owner + + +///Proc to change the value of the `can_be_disabled` variable and react to the event of its change. +/obj/item/bodypart/proc/set_can_be_disabled(new_can_be_disabled) + if(can_be_disabled == new_can_be_disabled) + return + . = can_be_disabled + can_be_disabled = new_can_be_disabled + if(can_be_disabled) + if(owner) + if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) + CRASH("set_can_be_disabled to TRUE with for limb whose owner has TRAIT_NOLIMBDISABLE") + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS), PROC_REF(on_paralysis_trait_gain)) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS), PROC_REF(on_paralysis_trait_loss)) + update_disabled() + else if(.) + if(owner) + UnregisterSignal(owner, list( + SIGNAL_ADDTRAIT(TRAIT_PARALYSIS), + SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS), + )) + set_disabled(FALSE) + + +///Called when TRAIT_PARALYSIS is added to the limb. +/obj/item/bodypart/proc/on_paralysis_trait_gain(obj/item/bodypart/source) + SIGNAL_HANDLER + if(can_be_disabled) + set_disabled(TRUE) + + +///Called when TRAIT_PARALYSIS is removed from the limb. +/obj/item/bodypart/proc/on_paralysis_trait_loss(obj/item/bodypart/source) + SIGNAL_HANDLER + if(can_be_disabled) + update_disabled() + + +///Called when TRAIT_NOLIMBDISABLE is added to the owner. +/obj/item/bodypart/proc/on_owner_nolimbdisable_trait_gain(mob/living/carbon/source) + SIGNAL_HANDLER + set_can_be_disabled(FALSE) + + +///Called when TRAIT_NOLIMBDISABLE is removed from the owner. +/obj/item/bodypart/proc/on_owner_nolimbdisable_trait_loss(mob/living/carbon/source) + SIGNAL_HANDLER + set_can_be_disabled(initial(can_be_disabled)) + + +///Called when TRAIT_EASYLIMBWOUND is added to the owner. +/obj/item/bodypart/proc/on_owner_easylimbwound_trait_gain(mob/living/carbon/source) + SIGNAL_HANDLER + disable_threshold = 0.6 + if(can_be_disabled) + update_disabled() + + +///Called when TRAIT_EASYLIMBWOUND is removed from the owner. +/obj/item/bodypart/proc/on_owner_easylimbwound_trait_loss(mob/living/carbon/source) + SIGNAL_HANDLER + disable_threshold = initial(disable_threshold) + if(can_be_disabled) + update_disabled() //Updates an organ's brute/burn states for use by update_damage_overlays() //Returns 1 if we need to update overlays. 0 otherwise. @@ -552,32 +721,64 @@ held_index = 1 px_x = -6 px_y = 0 + can_be_disabled = TRUE + + +/obj/item/bodypart/l_arm/set_owner(new_owner) + . = ..() + if(. == FALSE) + return + if(owner) + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) + if(.) + var/mob/living/carbon/old_owner = . + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) + if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) + + +///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait. +/obj/item/bodypart/l_arm/proc/on_owner_paralysis_gain(mob/living/carbon/source) + SIGNAL_HANDLER + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) + + +///Proc to react to the owner losing the TRAIT_PARALYSIS_L_ARM trait. +/obj/item/bodypart/l_arm/proc/on_owner_paralysis_loss(mob/living/carbon/source) + SIGNAL_HANDLER + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) -/obj/item/bodypart/l_arm/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - return BODYPART_DISABLED_PARALYSIS - return ..() /obj/item/bodypart/l_arm/set_disabled(new_disabled) . = ..() - if(!.) + if(isnull(.) || !owner) return - if(disabled == BODYPART_DISABLED_DAMAGE) - if(owner.stat < UNCONSCIOUS) - owner.emote("scream") - if(owner.stat < DEAD) - to_chat(owner, "Your [name] is too damaged to function!") - if(held_index) - owner.dropItemToGround(owner.get_item_for_held_index(held_index)) - else if(disabled == BODYPART_DISABLED_PARALYSIS) - if(owner.stat < DEAD) - to_chat(owner, "You can't feel your [name]!") + + if(!.) + if(bodypart_disabled) + owner.set_usable_hands(owner.usable_hands - 1) + if(owner.stat < UNCONSCIOUS) + to_chat(owner, "Your lose control of your [name]!") if(held_index) owner.dropItemToGround(owner.get_item_for_held_index(held_index)) + else if(!bodypart_disabled) + owner.set_usable_hands(owner.usable_hands + 1) + if(owner.hud_used) - var/atom/movable/screen/inventory/hand/L = owner.hud_used.hand_slots["[held_index]"] - if(L) - L.update_icon() + var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] + hand_screen_object?.update_icon() /obj/item/bodypart/l_arm/monkey icon = 'icons/mob/animal_parts.dmi' @@ -596,12 +797,14 @@ icon_state = "alien_l_arm" px_x = 0 px_y = 0 - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 100 animal_origin = ALIEN_BODYPART /obj/item/bodypart/l_arm/devil - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 5000 animal_origin = DEVIL_BODYPART @@ -622,32 +825,64 @@ held_index = 2 px_x = 6 px_y = 0 + can_be_disabled = TRUE + + +/obj/item/bodypart/r_arm/set_owner(new_owner) + . = ..() + if(. == FALSE) + return + if(owner) + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) + if(.) + var/mob/living/carbon/old_owner = . + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) + if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) + + +///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_ARM trait. +/obj/item/bodypart/r_arm/proc/on_owner_paralysis_gain(mob/living/carbon/source) + SIGNAL_HANDLER + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) + + +///Proc to react to the owner losing the TRAIT_PARALYSIS_R_ARM trait. +/obj/item/bodypart/r_arm/proc/on_owner_paralysis_loss(mob/living/carbon/source) + SIGNAL_HANDLER + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) -/obj/item/bodypart/r_arm/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - return BODYPART_DISABLED_PARALYSIS - return ..() /obj/item/bodypart/r_arm/set_disabled(new_disabled) . = ..() - if(!.) + if(isnull(.) || !owner) return - if(disabled == BODYPART_DISABLED_DAMAGE) - if(owner.stat < UNCONSCIOUS) - owner.emote("scream") - if(owner.stat < DEAD) - to_chat(owner, "Your [name] is too damaged to function!") - if(held_index) - owner.dropItemToGround(owner.get_item_for_held_index(held_index)) - else if(disabled == BODYPART_DISABLED_PARALYSIS) - if(owner.stat < DEAD) - to_chat(owner, "You can't feel your [name]!") + + if(!.) + if(bodypart_disabled) + owner.set_usable_hands(owner.usable_hands - 1) + if(owner.stat < UNCONSCIOUS) + to_chat(owner, "Your lose control of your [name]!") if(held_index) owner.dropItemToGround(owner.get_item_for_held_index(held_index)) + else if(!bodypart_disabled) + owner.set_usable_hands(owner.usable_hands + 1) + if(owner.hud_used) - var/atom/movable/screen/inventory/hand/R = owner.hud_used.hand_slots["[held_index]"] - if(R) - R.update_icon() + var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] + hand_screen_object?.update_icon() /obj/item/bodypart/r_arm/monkey icon = 'icons/mob/animal_parts.dmi' @@ -667,12 +902,14 @@ icon_state = "alien_r_arm" px_x = 0 px_y = 0 - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 100 animal_origin = ALIEN_BODYPART /obj/item/bodypart/r_arm/devil - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 5000 animal_origin = DEVIL_BODYPART @@ -690,24 +927,58 @@ px_x = -2 px_y = 12 max_stamina_damage = 50 + can_be_disabled = TRUE + + +/obj/item/bodypart/l_leg/set_owner(new_owner) + . = ..() + if(. == FALSE) + return + if(owner) + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) + if(.) + var/mob/living/carbon/old_owner = . + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_LEG)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) + if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) + + +///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_LEG trait. +/obj/item/bodypart/l_leg/proc/on_owner_paralysis_gain(mob/living/carbon/source) + SIGNAL_HANDLER + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) + + +///Proc to react to the owner losing the TRAIT_PARALYSIS_L_LEG trait. +/obj/item/bodypart/l_leg/proc/on_owner_paralysis_loss(mob/living/carbon/source) + SIGNAL_HANDLER + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) -/obj/item/bodypart/l_leg/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) - return BODYPART_DISABLED_PARALYSIS - return ..() /obj/item/bodypart/l_leg/set_disabled(new_disabled) . = ..() - if(!.) + if(isnull(.) || !owner) return - if(disabled == BODYPART_DISABLED_DAMAGE) - if(owner.stat < UNCONSCIOUS) - owner.emote("scream") - if(owner.stat < DEAD) - to_chat(owner, "Your [name] is too damaged to function!") - else if(disabled == BODYPART_DISABLED_PARALYSIS) - if(owner.stat < DEAD) - to_chat(owner, "You can't feel your [name]!") + + if(!.) + if(bodypart_disabled) + owner.set_usable_legs(owner.usable_legs - 1) + if(owner.stat < UNCONSCIOUS) + to_chat(owner, "Your lose control of your [name]!") + else if(!bodypart_disabled) + owner.set_usable_legs(owner.usable_legs + 1) /obj/item/bodypart/l_leg/monkey @@ -727,12 +998,14 @@ icon_state = "alien_l_leg" px_x = 0 px_y = 0 - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 100 animal_origin = ALIEN_BODYPART /obj/item/bodypart/l_leg/devil - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 5000 animal_origin = DEVIL_BODYPART @@ -752,24 +1025,58 @@ px_x = 2 px_y = 12 max_stamina_damage = 50 + can_be_disabled = TRUE + + +/obj/item/bodypart/r_leg/set_owner(new_owner) + . = ..() + if(. == FALSE) + return + if(owner) + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_gain)) + if(.) + var/mob/living/carbon/old_owner = . + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_LEG)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG)) + if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) + + +///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_LEG trait. +/obj/item/bodypart/r_leg/proc/on_owner_paralysis_gain(mob/living/carbon/source) + SIGNAL_HANDLER + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) + + +///Proc to react to the owner losing the TRAIT_PARALYSIS_R_LEG trait. +/obj/item/bodypart/r_leg/proc/on_owner_paralysis_loss(mob/living/carbon/source) + SIGNAL_HANDLER + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_gain)) -/obj/item/bodypart/r_leg/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) - return BODYPART_DISABLED_PARALYSIS - return ..() /obj/item/bodypart/r_leg/set_disabled(new_disabled) . = ..() - if(!.) + if(isnull(.) || !owner) return - if(disabled == BODYPART_DISABLED_DAMAGE) - if(owner.stat < UNCONSCIOUS) - owner.emote("scream") - if(owner.stat < DEAD) - to_chat(owner, "Your [name] is too damaged to function!") - else if(disabled == BODYPART_DISABLED_PARALYSIS) - if(owner.stat < DEAD) - to_chat(owner, "You can't feel your [name]!") + + if(!.) + if(bodypart_disabled) + owner.set_usable_legs(owner.usable_legs - 1) + if(owner.stat < UNCONSCIOUS) + to_chat(owner, "Your lose control of your [name]!") + else if(!bodypart_disabled) + owner.set_usable_legs(owner.usable_legs + 1) /obj/item/bodypart/r_leg/monkey @@ -789,11 +1096,13 @@ icon_state = "alien_r_leg" px_x = 0 px_y = 0 - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 100 animal_origin = ALIEN_BODYPART /obj/item/bodypart/r_leg/devil - dismemberable = 0 + dismemberable = FALSE + can_be_disabled = FALSE max_damage = 5000 animal_origin = DEVIL_BODYPART diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 630aa534ff260..c8079b137523c 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -83,7 +83,7 @@ SEND_SIGNAL(owner, COMSIG_CARBON_REMOVE_LIMB, src, dismembered) SEND_SIGNAL(src, COMSIG_BODYPART_REMOVED, owner, dismembered) update_limb(TRUE) - C.bodyparts -= src + C.remove_bodypart(src) if(held_index) C.dropItemToGround(owner.get_item_for_held_index(held_index), 1) @@ -125,7 +125,6 @@ C.update_health_hud() //update the healthdoll C.update_body() C.update_hair() - C.update_mobility() if(!Tsec) // Tsec = null happens when a "dummy human" used for rendering icons on prefs screen gets its limbs replaced. qdel(src) @@ -273,8 +272,8 @@ SEND_SIGNAL(C, COMSIG_CARBON_ATTACH_LIMB, src, special) SEND_SIGNAL(src, COMSIG_BODYPART_ATTACHED, C, special) moveToNullspace() - owner = C - C.bodyparts += src + set_owner(C) + C.add_bodypart(src) if(held_index) if(held_index > C.hand_bodyparts.len) C.hand_bodyparts.len = held_index @@ -307,7 +306,6 @@ C.updatehealth() C.update_body() C.update_hair() - C.update_mobility() SEND_SIGNAL(C, COMSIG_CARBON_POST_ATTACH_LIMB, src, special) diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 3d0ff10c90b4f..7dc048255c424 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -5,28 +5,39 @@ RETURN_TYPE(/obj/item/bodypart) if(!zone) zone = BODY_ZONE_CHEST - for(var/obj/item/bodypart/L as() in bodyparts) + for(var/obj/item/bodypart/L as anything in bodyparts) if(L.body_zone == zone) return L /mob/living/carbon/has_hand_for_held_index(i) - if(i) - var/obj/item/bodypart/L = hand_bodyparts[i] - if(L && !L.disabled) - return L + if(!i) + return FALSE + var/obj/item/bodypart/hand_instance = hand_bodyparts[i] + if(hand_instance && !hand_instance.bodypart_disabled) + return hand_instance return FALSE +///Get the bodypart for whatever hand we have active, Only relevant for carbons +/mob/proc/get_active_hand() + return FALSE + +/mob/living/carbon/get_active_hand() + var/which_hand = BODY_ZONE_PRECISE_L_HAND + if(!(active_hand_index % 2)) + which_hand = BODY_ZONE_PRECISE_R_HAND + return get_bodypart(check_zone(which_hand)) /mob/proc/has_left_hand(check_disabled = TRUE) return TRUE + /mob/living/carbon/has_left_hand(check_disabled = TRUE) - for(var/obj/item/bodypart/L in hand_bodyparts) - if(L.held_index % 2) - if(!check_disabled || !L.disabled) - return TRUE + for(var/obj/item/bodypart/hand_instance in hand_bodyparts) + if(!(hand_instance.held_index % 2) || (check_disabled && hand_instance.bodypart_disabled)) + continue + return TRUE return FALSE /mob/living/carbon/alien/larva/has_left_hand() @@ -36,70 +47,24 @@ /mob/proc/has_right_hand(check_disabled = TRUE) return TRUE + /mob/living/carbon/has_right_hand(check_disabled = TRUE) - for(var/obj/item/bodypart/L in hand_bodyparts) - if(!(L.held_index % 2)) - if(!check_disabled || !L.disabled) - return TRUE + for(var/obj/item/bodypart/hand_instance in hand_bodyparts) + if(hand_instance.held_index % 2 || (check_disabled && hand_instance.bodypart_disabled)) + continue + return TRUE return FALSE + /mob/living/carbon/alien/larva/has_right_hand() return 1 - -//Limb numbers -/mob/proc/get_num_arms(check_disabled = TRUE) - return 2 - -/mob/living/carbon/get_num_arms(check_disabled = TRUE) - . = 0 - for(var/obj/item/bodypart/affecting as() in bodyparts) - if(affecting.body_part == ARM_RIGHT) - if(!check_disabled || !affecting.disabled) - .++ - if(affecting.body_part == ARM_LEFT) - if(!check_disabled || !affecting.disabled) - .++ - - -//sometimes we want to ignore that we don't have the required amount of arms. -/mob/proc/get_arm_ignore() - return 0 - -/mob/living/carbon/alien/larva/get_arm_ignore() - return 1 //so we can still handcuff larvas. - - -/mob/proc/get_num_legs(check_disabled = TRUE) - return 2 - -/mob/living/carbon/get_num_legs(check_disabled = TRUE) - . = 0 - for(var/obj/item/bodypart/affecting as() in bodyparts) - if(affecting.body_part == LEG_RIGHT) - if(!check_disabled || !affecting.disabled) - .++ - if(affecting.body_part == LEG_LEFT) - if(!check_disabled || !affecting.disabled) - .++ - -//sometimes we want to ignore that we don't have the required amount of legs. -/mob/proc/get_leg_ignore() - return FALSE - -/mob/living/carbon/alien/larva/get_leg_ignore() - return TRUE - -/mob/living/carbon/human/get_leg_ignore() - if(movement_type & (FLYING | FLOATING)) - return TRUE - return FALSE - /mob/living/proc/get_missing_limbs() return list() /mob/living/carbon/get_missing_limbs() + RETURN_TYPE(/list) var/list/full = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) for(var/zone in full) if(get_bodypart(zone)) @@ -121,7 +86,7 @@ var/list/disabled = list() for(var/zone in full) var/obj/item/bodypart/affecting = get_bodypart(zone) - if(affecting && affecting.disabled) + if(affecting?.bodypart_disabled) disabled += zone return disabled @@ -130,7 +95,7 @@ var/list/disabled = list() for(var/zone in full) var/obj/item/bodypart/affecting = get_bodypart(zone) - if(affecting?.disabled) + if(affecting?.bodypart_disabled) disabled += zone return disabled @@ -151,16 +116,6 @@ continue return TRUE -///Get the bodypart for whatever hand we have active, Only relevant for carbons -/mob/proc/get_active_hand() - return FALSE - -/mob/living/carbon/get_active_hand() - var/which_hand = BODY_ZONE_PRECISE_L_HAND - if(!(active_hand_index % 2)) - which_hand = BODY_ZONE_PRECISE_R_HAND - return get_bodypart(check_zone(which_hand)) - //Helper for quickly creating a new limb - used by augment code in species.dm spec_attacked_by // // FUCK YOU AUGMENT CODE - With love, Kapu diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index c9c2d9d1111cd..20430836f2ac9 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -22,17 +22,18 @@ to_chat(user, "[tool] isn't the right type for [parse_zone(surgery.location)].") return -1 L = surgery.operated_bodypart - if(L) - if(L.is_disabled() == BODYPART_DISABLED_PARALYSIS) - to_chat(user, "You can't augment a limb with paralysis!") - return -1 - else - display_results(user, target, "You begin to augment [target]'s [parse_zone(surgery.location)]...", - "[user] begins to augment [target]'s [parse_zone(surgery.location)] with [aug].", - "[user] begins to augment [target]'s [parse_zone(surgery.location)].") - else + + if(!L) user.visible_message("[user] looks for [target]'s [parse_zone(surgery.location)].", "You look for [target]'s [parse_zone(surgery.location)]...") + return + if(L?.bodypart_disabled) + to_chat(user, "You can't augment a limb with paralysis!") + return -1 + else + display_results(user, target, "You begin to augment [target]'s [parse_zone(surgery.location)]...", + "[user] begins to augment [target]'s [parse_zone(surgery.location)] with [aug].", + "[user] begins to augment [target]'s [parse_zone(surgery.location)].") //ACTUAL SURGERIES diff --git a/code/modules/tgui/states/not_incapacitated.dm b/code/modules/tgui/states/not_incapacitated.dm index 16dcb7881ed03..4d38c62392f0f 100644 --- a/code/modules/tgui/states/not_incapacitated.dm +++ b/code/modules/tgui/states/not_incapacitated.dm @@ -25,12 +25,8 @@ GLOBAL_DATUM_INIT(not_incapacitated_turf_state, /datum/ui_state/not_incapacitate turf_check = no_turfs /datum/ui_state/not_incapacitated_state/can_use_topic(src_object, mob/user) - if(user.stat) + if(user.stat != CONSCIOUS) return UI_CLOSE - if(user.incapacitated() || (turf_check && !isturf(user.loc))) + if(HAS_TRAIT(src, TRAIT_UI_BLOCKED) || user.incapacitated() || (turf_check && !isturf(user.loc))) return UI_DISABLED - if(isliving(user)) - var/mob/living/L = user - if(!(L.mobility_flags & MOBILITY_STAND)) - return UI_DISABLED return UI_INTERACTIVE diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm index 868028da55a0b..29dc5b3dfaf7c 100644 --- a/code/modules/vehicles/_vehicle.dm +++ b/code/modules/vehicles/_vehicle.dm @@ -115,12 +115,12 @@ /obj/vehicle/proc/after_remove_occupant(mob/M) -/obj/vehicle/relaymove(mob/user, direction) +/obj/vehicle/relaymove(mob/living/user, direction) if(is_driver(user)) return driver_move(user, direction) return FALSE -/obj/vehicle/proc/driver_move(mob/user, direction) +/obj/vehicle/proc/driver_move(mob/living/user, direction) if(key_type && !is_key(inserted_key)) to_chat(user, "[src] has no key inserted!") return FALSE diff --git a/code/modules/vehicles/cars/car.dm b/code/modules/vehicles/cars/car.dm index 75b59507e9510..68a332beee868 100644 --- a/code/modules/vehicles/cars/car.dm +++ b/code/modules/vehicles/cars/car.dm @@ -20,7 +20,7 @@ if(car_traits & CAN_KIDNAP) initialize_controller_action_type(/datum/action/vehicle/sealed/DumpKidnappedMobs, VEHICLE_CONTROL_DRIVE) -/obj/vehicle/sealed/car/driver_move(mob/user, direction) +/obj/vehicle/sealed/car/driver_move(mob/living/user, direction) if(key_type && !is_key(inserted_key)) to_chat(user, "[src] has no key inserted!") return FALSE diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm index 464ea93ad551e..b90c3e781043b 100644 --- a/code/modules/vehicles/cars/clowncar.dm +++ b/code/modules/vehicles/cars/clowncar.dm @@ -96,11 +96,13 @@ /obj/vehicle/sealed/car/clowncar/proc/restraintarget(mob/living/carbon/C) if(istype(C)) - if(!C.handcuffed) - if(C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()) - C.set_handcuffed(new /obj/item/restraints/handcuffs/energy/used(C)) - C.update_handcuffed() - to_chat(C, " Your hands are restrained by the sheer volume of occupants in the car!") + // Dont try and apply more handcuffs if already handcuffed, obviously + if(C.handcuffed) + return + if(C.canBeHandcuffed()) + C.set_handcuffed(new /obj/item/restraints/handcuffs/energy/used(C)) + C.update_handcuffed() + to_chat(C, " Your hands are restrained by the sheer volume of occupants in the car!") /obj/item/restraints/handcuffs/energy/used/clown name = "tangle of limbs" diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index ecf6168e53570..5565a41802307 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -890,7 +890,6 @@ AI.cancel_camera() AI.controlled_mech = src AI.remote_control = src - AI.mobility_flags = ALL //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow. to_chat(AI, AI.can_dominate_mechs ? "Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!" :\ "You have been uploaded to a mech's onboard computer.") to_chat(AI, "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.") @@ -1039,12 +1038,11 @@ return FALSE - brain_obj.mecha = src + brain_obj.set_mecha(src) add_occupant(brain_mob)//Note this forcemoves the brain into the mech to allow relaymove mecha_flags |= SILICON_PILOT brain_mob.reset_perspective(src) brain_mob.remote_control = src - brain_mob.update_mobility() brain_mob.update_mouse_pointer() setDir(dir_in) log_message("[brain_obj] moved in as pilot.", LOG_MECHA) @@ -1112,9 +1110,8 @@ L.forceMove(mmi) L.reset_perspective() remove_occupant(L) - mmi.mecha = null + mmi.set_mecha(null) mmi.update_appearance() - L.mobility_flags = NONE setDir(dir_in) return ..() diff --git a/code/modules/vehicles/motorized_wheelchair.dm b/code/modules/vehicles/motorized_wheelchair.dm index 7cc5ceae0c855..7cc942c5cbec8 100644 --- a/code/modules/vehicles/motorized_wheelchair.dm +++ b/code/modules/vehicles/motorized_wheelchair.dm @@ -32,12 +32,10 @@ /obj/vehicle/ridden/wheelchair/motorized/obj_destruction(damage_flag) var/turf/T = get_turf(src) - for(var/atom/movable/A in contents) - A.forceMove(T) - if(isliving(A)) - var/mob/living/L = A - L.update_mobility() - ..() + for(var/c in contents) + var/atom/movable/thing = c + thing.forceMove(T) + return ..() /obj/vehicle/ridden/wheelchair/motorized/driver_move(mob/living/user, direction) if(istype(user)) @@ -53,7 +51,7 @@ canmove = FALSE addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20) return FALSE - if(user.get_num_arms() < arms_required) + if(user.usable_hands < arms_required) to_chat(user, "You don't have enough arms to operate the motor controller!") canmove = FALSE addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20) @@ -130,11 +128,9 @@ new /obj/item/stack/rods(drop_location(), 8) new /obj/item/stack/sheet/iron(drop_location(), 10) var/turf/T = get_turf(src) - for(var/atom/movable/A in contents) - A.forceMove(T) - if(isliving(A)) - var/mob/living/L = A - L.update_mobility() + for(var/c in contents) + var/atom/movable/thing = c + thing.forceMove(T) qdel(src) return TRUE diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm index 1d01fb781dfad..ce22644b19de0 100644 --- a/code/modules/vehicles/ridden.dm +++ b/code/modules/vehicles/ridden.dm @@ -59,20 +59,18 @@ inserted_key = null return -/obj/vehicle/ridden/driver_move(mob/user, direction) +/obj/vehicle/ridden/driver_move(mob/living/user, direction) if(key_type && !is_key(inserted_key)) if(message_cooldown < world.time) to_chat(user, "[src] has no key inserted!") message_cooldown = world.time + 5 SECONDS return FALSE if(legs_required) - var/how_many_legs = user.get_num_legs() - if(how_many_legs < legs_required) - to_chat(user, "You can't seem to manage that with[how_many_legs ? " your leg[how_many_legs > 1 ? "s" : null]" : "out legs"]...") + if(user.usable_legs < legs_required) + to_chat(user, "You can't seem to manage that with[user.usable_legs ? " your leg[user.usable_legs > 1 ? "s" : null]" : "out legs"]...") return FALSE if(arms_required) - var/how_many_arms = user.get_num_arms() - if(how_many_arms < arms_required) + if(user.usable_hands < arms_required) if(fall_off_if_missing_arms) unbuckle_mob(user, TRUE) user.visible_message("[user] falls off of \the [src].",\ @@ -82,7 +80,7 @@ L.Stun(30) return FALSE - to_chat(user, "You can't seem to manage that with[how_many_arms ? " your arm[how_many_arms > 1 ? "s" : null]" : "out arms"]...") + to_chat(user, "You can't seem to manage that with[user.usable_hands ? " your arm[user.usable_hands > 1 ? "s" : null]" : "out arms"]...") return FALSE var/datum/component/riding/R = GetComponent(/datum/component/riding) R.handle_ride(user, direction) diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index 665400bcdefeb..6a7b97c5b40f3 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -28,7 +28,7 @@ . = ..() for(var/m in buckled_mobs) var/mob/living/buckled_mob = m - if(buckled_mob.get_num_legs(FALSE) > 0) + if(buckled_mob.num_legs > 0) buckled_mob.pixel_y = 5 else buckled_mob.pixel_y = -4 @@ -36,7 +36,7 @@ /obj/vehicle/ridden/scooter/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) if(!istype(M)) return FALSE - if(M.get_num_legs() < legs_required && M.get_num_arms() < arms_required) + if(M.usable_legs < legs_required && M.usable_hands < arms_required) to_chat(M, "You don't think it'd be a good idea trying to ride \the [src]...") return FALSE return ..() @@ -77,7 +77,7 @@ QDEL_NULL(sparks) . = ..() -/obj/vehicle/ridden/scooter/skateboard/relaymove() +/obj/vehicle/ridden/scooter/skateboard/relaymove(mob/living/user, direction) if (grinding || world.time < next_crash) return FALSE return ..() diff --git a/code/modules/vehicles/wheelchair.dm b/code/modules/vehicles/wheelchair.dm index 5ff32254a062a..abd6ec9dc7787 100644 --- a/code/modules/vehicles/wheelchair.dm +++ b/code/modules/vehicles/wheelchair.dm @@ -40,7 +40,7 @@ /obj/vehicle/ridden/wheelchair/driver_move(mob/living/user, direction) if(istype(user)) - if(canmove && (user.get_num_arms() < arms_required)) + if(canmove && (user.usable_hands < arms_required)) to_chat(user, "You don't have enough arms to operate the wheels!") canmove = FALSE addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20) @@ -52,7 +52,7 @@ var/datum/component/riding/D = GetComponent(/datum/component/riding) //1.5 (movespeed as of this change) multiplied by 6.7 gets ABOUT 10 (rounded), the old constant for the wheelchair that gets divided by how many arms they have //if that made no sense this simply makes the wheelchair speed change along with movement speed delay - D.vehicle_move_delay = round(1.5 * delay_multiplier) / clamp(user.get_num_arms(), arms_required, 2) + D.vehicle_move_delay = round(1.5 * delay_multiplier) / clamp(user.usable_hands, 1, 2) /obj/vehicle/ridden/wheelchair/Moved() . = ..() @@ -112,5 +112,5 @@ /obj/vehicle/ridden/wheelchair/the_whip/driver_move(mob/living/user, direction) if(istype(user)) var/datum/component/riding/D = GetComponent(/datum/component/riding) - D.vehicle_move_delay = round(1.5 * 6.7) / user.get_num_arms() + D.vehicle_move_delay = round(1.5 * 6.7) / max(user.usable_hands, 1) return ..()