From 8f917ff1d9dcc4e4cecef3dc2590f219ca14e549 Mon Sep 17 00:00:00 2001 From: Rohesie Date: Mon, 10 Aug 2020 23:44:01 -0300 Subject: [PATCH] immobilized (#52578) Adds an immobilized trait. Adds procs for several variable changes so we can respond to their events. Adds some signals for said variables changing. Need to turn the variation in number of usable legs and arms (get_num_legs() and get_num_arms()) into events we can respond to, but they are pretty annoying to do so. Probably for a different PR. --- code/__DEFINES/dcs/signals.dm | 4 ++ code/__DEFINES/traits.dm | 6 ++ code/datums/components/chasm.dm | 3 +- code/datums/status_effects/debuffs.dm | 25 ++++++++- code/datums/status_effects/gas.dm | 10 ++++ code/game/atoms_movable.dm | 28 +++++++++- code/game/objects/buckling.dm | 4 +- code/game/objects/items/robot/robot_parts.dm | 6 +- .../structures/crates_lockers/closets.dm | 6 +- code/modules/mining/fulton.dm | 3 +- code/modules/mob/living/living.dm | 56 +++++++++++++++++-- code/modules/mob/living/silicon/robot/life.dm | 2 +- .../modules/mob/living/silicon/robot/robot.dm | 23 ++++++-- .../mob/living/simple_animal/simple_animal.dm | 11 +++- 14 files changed, 160 insertions(+), 27 deletions(-) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 2a542d85378..504dc89e3a7 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -278,6 +278,8 @@ #define COMSIG_MOVABLE_DISPOSING "movable_disposing" ///called when the movable sucessfully has it's anchored var changed, from base atom/movable/set_anchored(): (value) #define COMSIG_MOVABLE_SET_ANCHORED "movable_set_anchored" +///from base of atom/movable/setGrabState(): (newstate) +#define COMSIG_MOVABLE_SET_GRAB_STATE "living_set_grab_state" // /mob signals @@ -364,6 +366,8 @@ #define COMSIG_LIVING_REVIVE "living_revive" ///from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) #define COMSIG_LIVING_REGENERATE_LIMBS "living_regen_limbs" +///from base of mob/living/set_buckled(): (new_buckled) +#define COMSIG_LIVING_SET_BUCKLED "living_set_buckled" ///sent from borg recharge stations: (amount, repairs) #define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 73137890942..60153034da0 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -77,6 +77,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai //mob traits #define TRAIT_KNOCKEDOUT "knockedout" //Forces the user to stay unconscious. +#define TRAIT_IMMOBILIZED "immobilized" //Prevents voluntary movement. #define TRAIT_INCAPACITATED "incapacitated" #define TRAIT_BLIND "blind" #define TRAIT_MUTE "mute" @@ -274,6 +275,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define CRIT_HEALTH_TRAIT "crit_health" #define OXYLOSS_TRAIT "oxyloss" #define TURF_TRAIT "turf" +#define BUCKLED_TRAIT "buckled" //trait associated to being buckled +#define CHOKEHOLD_TRAIT "chokehold" //trait associated to being held in a chokehold +#define RESTING_TRAIT "resting" //trait associated to resting // unique trait sources, still defines #define CLONING_POD_TRAIT "cloning-pod" @@ -316,3 +320,5 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TIMESTOP_TRAIT "timestop" #define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name #define SKILLCHIP_TRAIT "skillchip" +#define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit" +#define LOCKED_BORG_TRAIT "locked-borg" diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index ab000892ba4..680ab83e99a 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -110,8 +110,7 @@ if (isliving(AM)) var/mob/living/L = AM L.notransform = TRUE - L.Stun(200) - L.resting = TRUE + L.Paralyze(20 SECONDS) var/oldtransform = AM.transform var/oldcolor = AM.color diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index a31203acd62..3a13359f572 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -33,19 +33,33 @@ if(!.) return ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id)) + ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) /datum/status_effect/incapacitating/stun/on_remove() REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id)) + REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) return ..() //KNOCKDOWN /datum/status_effect/incapacitating/knockdown id = "knockdown" + //IMMOBILIZED /datum/status_effect/incapacitating/immobilized id = "immobilized" +/datum/status_effect/incapacitating/immobilized/on_apply() + . = ..() + if(!.) + return + ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) + +/datum/status_effect/incapacitating/immobilized/on_remove() + REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) + return ..() + + /datum/status_effect/incapacitating/paralyzed id = "paralyzed" @@ -54,9 +68,11 @@ if(!.) return ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id)) + ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) /datum/status_effect/incapacitating/paralyzed/on_remove() REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id)) + REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) return ..() //UNCONSCIOUS @@ -163,12 +179,19 @@ if(.) update_time_of_death() owner.reagents?.end_metabolization(owner, FALSE) - owner.update_mobility() + +/datum/status_effect/grouped/stasis/on_apply() + . = ..() + if(!.) + return + ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) + owner.update_mobility() /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)) owner.update_mobility() update_time_of_death() return ..() diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm index 454bdb395b6..78ceaf3bd87 100644 --- a/code/datums/status_effects/gas.dm +++ b/code/datums/status_effects/gas.dm @@ -6,6 +6,16 @@ var/icon/cube var/can_melt = TRUE +/datum/status_effect/freon/on_apply() + . = ..() + if(!.) + return + ADD_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) + +/datum/status_effect/freon/on_remove() + REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) + return ..() + /obj/screen/alert/status_effect/freon name = "Frozen Solid" desc = "You're frozen inside an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!" diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 3e9eade3782..3d6dcfc3167 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -224,7 +224,7 @@ log_combat(AM, AM.pulledby, "pulled from", src) AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = AM - AM.pulledby = src + AM.set_pulledby(src) setGrabState(state) if(ismob(AM)) var/mob/M = AM @@ -236,14 +236,23 @@ /atom/movable/proc/stop_pulling() if(pulling) - pulling.pulledby = null + pulling.set_pulledby(null) var/mob/living/ex_pulled = pulling + setGrabState(GRAB_PASSIVE) pulling = null - setGrabState(0) if(isliving(ex_pulled)) var/mob/living/L = ex_pulled L.update_mobility()// mob gets up if it was lyng down in a chokehold + +///Reports the event of the change in value of the pulledby variable. +/atom/movable/proc/set_pulledby(new_pulledby) + if(new_pulledby == pulledby) + return FALSE //null signals there was a change, be sure to return FALSE if none happened here. + . = pulledby + pulledby = new_pulledby + + /atom/movable/proc/Move_Pulled(atom/A) if(!pulling) return @@ -969,7 +978,20 @@ * This exists to act as a hook for behaviour */ /atom/movable/proc/setGrabState(newstate) + if(newstate == grab_state) + return + SEND_SIGNAL(src, COMSIG_MOVABLE_SET_GRAB_STATE, newstate) + . = grab_state grab_state = newstate + switch(.) //Previous state. + if(GRAB_PASSIVE, GRAB_AGGRESSIVE) + if(grab_state >= GRAB_NECK) + ADD_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT) + switch(grab_state) //Current state. + if(GRAB_PASSIVE, GRAB_AGGRESSIVE) + if(. >= GRAB_NECK) + REMOVE_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT) + /obj/item/proc/do_pickup_animation(atom/target) set waitfor = FALSE diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 504bcf37bae..cb5a5879f17 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -94,7 +94,7 @@ M.forceMove(loc) M.buckling = null - M.buckled = src + M.set_buckled(src) M.setDir(dir) buckled_mobs |= M M.update_mobility() @@ -114,7 +114,7 @@ /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.buckled = null + buckled_mob.set_buckled(null) buckled_mob.set_anchored(initial(buckled_mob.anchored)) buckled_mob.update_mobility() buckled_mob.clear_alert("buckled") diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index f8a3a5f846f..88d18b11c72 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -304,8 +304,7 @@ log_game("[key_name(user)] has put the MMI/posibrain of [key_name(M.brainmob)] into a cyborg shell at [AREACOORD(src)]") if(!locomotion) - O.lockcharge = TRUE - O.update_mobility() + O.set_lockcharge(TRUE) to_chat(O, "Error: Servo motors unresponsive.") else @@ -342,8 +341,7 @@ forceMove(O) O.robot_suit = src if(!locomotion) - O.lockcharge = TRUE - O.update_mobility() + O.set_lockcharge(TRUE) else if(istype(W, /obj/item/pen)) to_chat(user, "You need to use a multitool to name [src]!") diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 72639c20ce0..fbe2fe73096 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -528,11 +528,11 @@ step_towards(user, T2) T1 = get_turf(user) if(T1 == T2) - user.resting = TRUE //so people can jump into crates without slamming the lid on their head + user.set_resting(TRUE) //so people can jump into crates without slamming the lid on their head if(!close(user)) to_chat(user, "You can't get [src] to close!") - user.resting = FALSE + user.set_resting(FALSE) return - user.resting = FALSE + user.set_resting(FALSE) togglelock(user) T1.visible_message("[user] dives into [src]!") diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index 1f970b121a0..f9486a89776 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -79,7 +79,8 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) if(isliving(A)) var/mob/living/M = A M.Paralyze(320) // Keep them from moving during the duration of the extraction - M.buckled = 0 // Unbuckle them to prevent anchoring problems + if(M.buckled) + M.buckled.unbuckle_mob(M, TRUE) // Unbuckle them to prevent anchoring problems else A.set_anchored(TRUE) A.density = FALSE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 92f836bae15..aa09f11d51b 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -267,7 +267,7 @@ AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = AM - AM.pulledby = src + AM.set_pulledby(src) SEND_SIGNAL(src, COMSIG_LIVING_START_PULL, AM, state, force) @@ -451,19 +451,26 @@ else to_chat(src, "You fail to get up!") + +///Proc to hook behavior to the change of value in the resting variable. /mob/living/proc/set_resting(rest, silent = TRUE) + if(rest == resting) + return if(!silent) if(rest) to_chat(src, "You are now resting.") else to_chat(src, "You get up.") + . = rest resting = rest update_resting() + /mob/living/proc/update_resting() update_rest_hud_icon() update_mobility() + //Recursive function to find everything a mob is holding. Really shitty proc tbh. /mob/living/get_contents() var/list/ret = list() @@ -1197,10 +1204,9 @@ var/has_legs = get_num_legs() var/has_arms = get_num_arms() var/paralyzed = IsParalyzed() - var/stun = IsStun() var/knockdown = IsKnockdown() var/ignore_legs = get_leg_ignore() - var/canmove = !IsImmobilized() && !stun && stat_conscious && !paralyzed && !buckled && (!stat_softcrit || !pulledby) && !chokehold && !IsFrozen() && !IS_IN_STASIS(src) && (has_arms || ignore_legs || has_legs) + var/canmove = !HAS_TRAIT(src, TRAIT_IMMOBILIZED) && (has_arms || ignore_legs || has_legs) if(canmove) mobility_flags |= MOBILITY_MOVE else @@ -1231,7 +1237,7 @@ - var/canitem = !paralyzed && !stun && stat_conscious && !chokehold && !restrained && has_arms + var/canitem = !paralyzed && !IsStun() && stat_conscious && !chokehold && !restrained && has_arms if(canitem) mobility_flags |= (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_STORAGE) else @@ -1627,12 +1633,54 @@ if(isnull(.)) return switch(.) //Previous stat. + if(CONSCIOUS) + if(stat >= UNCONSCIOUS) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) + if(SOFT_CRIT) + if(stat >= UNCONSCIOUS) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) //adding trait sources should come before removing to avoid unnecessary updates + if(pulledby) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) if(UNCONSCIOUS) cure_blind(UNCONSCIOUS_BLIND) switch(stat) //Current stat. + if(CONSCIOUS) + if(. >= UNCONSCIOUS) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) + 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) if(UNCONSCIOUS) become_blind(UNCONSCIOUS_BLIND) + +///Reports the event of the change in value of the buckled variable. +/mob/living/proc/set_buckled(new_buckled) + if(new_buckled == buckled) + return + SEND_SIGNAL(src, COMSIG_LIVING_SET_BUCKLED, new_buckled) + . = buckled + buckled = new_buckled + if(buckled) + if(!.) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT) + else if(.) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT) + + +/mob/living/set_pulledby(new_pulledby) + . = ..() + if(. == FALSE) //null is a valid value here, we only want to return if FALSE is explicitly passed. + return + if(pulledby) + if(!. && stat == SOFT_CRIT) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) + else if(. && stat == SOFT_CRIT) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) + + /// Only defined for carbons who can wear masks and helmets, we just assume other mobs have visible faces /mob/living/proc/is_face_visible() return TRUE diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index afad167f231..d51a332655c 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -93,7 +93,7 @@ cut_overlay(fire_overlay) /mob/living/silicon/robot/update_mobility() - if(stat || buckled || lockcharge) + if(HAS_TRAIT(src, TRAIT_IMMOBILIZED)) mobility_flags &= ~MOBILITY_MOVE else mobility_flags = MOBILITY_FLAGS_DEFAULT diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 70f46207645..5132a310251 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -464,8 +464,7 @@ connected_ai.connected_robots -= src src.connected_ai = null lawupdate = FALSE - lockcharge = FALSE - mobility_flags |= MOBILITY_FLAGS_DEFAULT + set_lockcharge(FALSE) scrambledcodes = TRUE //Disconnect it's camera so it's not so easily tracked. if(!QDELETED(builtInCamera)) @@ -487,17 +486,31 @@ W.attack_self(src) -/mob/living/silicon/robot/proc/SetLockdown(state = 1) +/mob/living/silicon/robot/proc/SetLockdown(state = TRUE) // They stay locked down if their wire is cut. if(wires.is_cut(WIRE_LOCKDOWN)) - state = 1 + state = TRUE if(state) throw_alert("locked", /obj/screen/alert/locked) else clear_alert("locked") - lockcharge = state + set_lockcharge(state) + + +///Reports the event of the change in value of the lockcharge variable. +/mob/living/silicon/robot/proc/set_lockcharge(new_lockcharge) + if(new_lockcharge == lockcharge) + return + . = lockcharge + lockcharge = new_lockcharge + if(lockcharge) + if(!.) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, LOCKED_BORG_TRAIT) + else if(.) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LOCKED_BORG_TRAIT) update_mobility() + /mob/living/silicon/robot/proc/SetEmagged(new_state) emagged = new_state module.rebuild_modules() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 78e282f15c9..9afe35bc144 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -527,8 +527,17 @@ else ..() + +/mob/living/simple_animal/update_resting() + if(resting) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, RESTING_TRAIT) + else + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, RESTING_TRAIT) + return ..() + + /mob/living/simple_animal/update_mobility(value_otherwise = TRUE) - if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT) || IsParalyzed() || IsStun() || IsKnockdown() || IsParalyzed() || stat || resting) + if(HAS_TRAIT_NOT_FROM(src, TRAIT_IMMOBILIZED, BUCKLED_TRAIT)) drop_all_held_items() mobility_flags = NONE else if(buckled)