From 1d21a7881433b8d7d209f4c659608ae62a10849a Mon Sep 17 00:00:00 2001 From: GDN <96800819+GDNgit@users.noreply.github.com> Date: Wed, 28 Jun 2023 08:29:39 -0500 Subject: [PATCH] adds contort body to changelings (#21259) * adds contort body to changelings * more changes * sprite by mcramon * Update code/game/machinery/doors/firedoor.dm Co-authored-by: SteelSlayer <42044220+SteelSlayer@users.noreply.github.com> * steels review --------- Co-authored-by: SteelSlayer <42044220+SteelSlayer@users.noreply.github.com> --- code/__HELPERS/trait_helpers.dm | 1 + code/_globalvars/traits.dm | 3 +- code/datums/components/caltrop.dm | 3 ++ code/game/machinery/OpTable.dm | 4 +++ code/game/machinery/doors/airlock.dm | 8 ++++-- code/game/machinery/doors/firedoor.dm | 8 ++++++ code/game/machinery/doors/windowdoor.dm | 12 ++++++-- .../structures/crates_lockers/crates.dm | 4 ++- code/game/objects/structures/morgue.dm | 13 +++++---- code/game/objects/structures/railings.dm | 8 +++--- code/game/objects/structures/tables_racks.dm | 12 +++++--- .../changeling/powers/contort_body.dm | 26 ++++++++++++++++++ .../modules/mob/living/living_status_procs.dm | 7 +++-- icons/mob/actions/actions.dmi | Bin 141585 -> 142295 bytes paradise.dme | 1 + 15 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 code/modules/antagonists/changeling/powers/contort_body.dm diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm index 387fdae5c68..8dd96b8d9bc 100644 --- a/code/__HELPERS/trait_helpers.dm +++ b/code/__HELPERS/trait_helpers.dm @@ -203,6 +203,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_CULT_IMMUNITY "cult_immunity" #define TRAIT_FLATTENED "flattened" #define SM_HALLUCINATION_IMMUNE "supermatter_hallucination_immune" +#define TRAIT_CONTORTED_BODY "contorted_body" //***** ITEM AND MOB TRAITS *****// /// Show what machine/door wires do when held. diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index ddf721f7632..96a02b3ec8a 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -75,7 +75,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO, "TRAIT_CAN_BE_EATEN_BY_LIZARDS" = TRAIT_EDIBLE_BUG, "TRAIT_FLATTENED" = TRAIT_FLATTENED, - "TRAIT_SM_HALLUCINATION_IMMUNE" = SM_HALLUCINATION_IMMUNE + "TRAIT_SM_HALLUCINATION_IMMUNE" = SM_HALLUCINATION_IMMUNE, + "TRAIT_CONTORTED_BODY" = TRAIT_CONTORTED_BODY ), /obj/item = list( "TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO, diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm index c26560d2d20..4446dde3a26 100644 --- a/code/datums/components/caltrop.dm +++ b/code/datums/components/caltrop.dm @@ -45,6 +45,9 @@ if(H.flying || H.floating || H.buckled) return + if(IS_HORIZONTAL(H) && HAS_TRAIT(H, TRAIT_CONTORTED_BODY)) + return TRUE + var/damage = rand(min_damage, max_damage) H.apply_damage(damage, BRUTE, picked_def_zone) diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 42f993cd9bb..7f74df70595 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -49,6 +49,10 @@ return TRUE if(istype(mover) && mover.checkpass(PASSTABLE)) return TRUE + if(isliving(mover)) + var/mob/living/our_mover = mover + if(IS_HORIZONTAL(our_mover) && HAS_TRAIT(our_mover, TRAIT_CONTORTED_BODY)) + return TRUE else return FALSE diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index d8ca792f6cc..3a146a7d15f 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -748,8 +748,12 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays) attack_ai(user) /obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=0) - if(istype(mover) && mover.checkpass(PASSDOOR) && !locked) // We really dont want mice/drones to get shocked on a door they're passing through - return TRUE + if(istype(mover) && !locked) + if(mover.checkpass(PASSDOOR)) + return TRUE + var/mob/living/living_mover = mover + if((istype(living_mover) && HAS_TRAIT(living_mover, TRAIT_CONTORTED_BODY) && IS_HORIZONTAL(living_mover))) // We really dont want people to get shocked on a door they're passing through + return TRUE if(isElectrified() && density && isitem(mover)) var/obj/item/I = mover if(I.flags & CONDUCT) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 303523f8f58..d829305b3d6 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -289,6 +289,14 @@ F.update_icon() qdel(src) +/obj/machinery/door/firedoor/CanPass(atom/movable/mover, turf/target) + if(..()) + return TRUE + if(isliving(mover) && !locked) + var/mob/living/living_mover = mover + if(HAS_TRAIT(living_mover, TRAIT_CONTORTED_BODY) && IS_HORIZONTAL(living_mover)) + return TRUE + /obj/machinery/door/firedoor/border_only icon = 'icons/obj/doors/edge_doorfire.dmi' flags = ON_BORDER diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index c5d34376ead..0d3d3111056 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -134,7 +134,11 @@ /obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=0) if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 + return TRUE + if(isliving(mover)) + var/mob/living/living_mover = mover + if(HAS_TRAIT(living_mover, TRAIT_CONTORTED_BODY) && IS_HORIZONTAL(living_mover)) + return TRUE if(get_dir(loc, target) == dir) //Make sure looking at appropriate border return !density if(istype(mover, /obj/structure/window)) @@ -162,7 +166,11 @@ /obj/machinery/door/window/CheckExit(atom/movable/mover, turf/target) if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 + return TRUE + if(isliving(mover)) + var/mob/living/living_mover = mover + if(HAS_TRAIT(living_mover, TRAIT_CONTORTED_BODY) && IS_HORIZONTAL(living_mover)) + return TRUE if(get_dir(loc, target) == dir) return !density else diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index bd6009ce3d6..035de168476 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -70,11 +70,13 @@ playsound(loc, close_sound, close_sound_volume, TRUE, -3) var/itemcount = 0 - for(var/obj/O in get_turf(src)) + for(var/atom/movable/O in get_turf(src)) if(itemcount >= storage_capacity) break if(O.density || O.anchored || istype(O,/obj/structure/closet)) continue + if(ismob(O) && !HAS_TRAIT(O, TRAIT_CONTORTED_BODY)) + continue if(istype(O, /obj/structure/bed)) //This is only necessary because of rollerbeds and swivel chairs. var/obj/structure/bed/B = O if(B.has_buckled_mobs()) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 0e7ad16c155..0b71005e3e8 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -254,18 +254,21 @@ connected = null return ..() -/obj/structure/tray/m_tray/CanPass(atom/movable/mover, turf/target, height=0) +/obj/structure/m_tray/CanPass(atom/movable/mover, turf/target, height=0) if(height == 0) return TRUE - - if(istype(mover) && mover.checkpass(PASSTABLE)) - return TRUE + if(istype(mover)) + if(mover.checkpass(PASSTABLE)) + return TRUE + var/mob/living/our_mover = mover + if(istype(our_mover) && IS_HORIZONTAL(our_mover) && HAS_TRAIT(our_mover, TRAIT_CONTORTED_BODY)) + return TRUE if(locate(/obj/structure/table) in get_turf(mover)) return TRUE return FALSE -/obj/structure/tray/m_tray/CanPathfindPass(obj/item/card/id/ID, dir, caller, no_id = FALSE) +/obj/structure/m_tray/CanPathfindPass(obj/item/card/id/ID, dir, caller, no_id = FALSE) . = !density if(ismovable(caller)) var/atom/movable/mover = caller diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index a63c83f8bdf..2d93cf9b154 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -80,8 +80,8 @@ if(istype(mover, /obj/item/projectile)) return TRUE if(ismob(mover)) - var/mob/M = mover - if(M.flying) + var/mob/living/M = mover + if(M.flying || (IS_HORIZONTAL(M) && HAS_TRAIT(M, TRAIT_CONTORTED_BODY))) return TRUE if(mover.throwing) return TRUE @@ -107,8 +107,8 @@ return TRUE if(istype(O, /obj/item/projectile)) return TRUE - if(ismob(O)) - if(M.flying || M.floating) + if(istype(M)) + if(M.flying || M.floating || (IS_HORIZONTAL(M) && HAS_TRAIT(M, TRAIT_CONTORTED_BODY))) return TRUE if(O.throwing) return TRUE diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 5e96f473b7e..cd742fffd70 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -122,8 +122,8 @@ if(istype(mover,/obj/item/projectile)) return (check_cover(mover,target)) if(ismob(mover)) - var/mob/M = mover - if(M.flying) + var/mob/living/M = mover + if(M.flying || (IS_HORIZONTAL(M) && HAS_TRAIT(M, TRAIT_CONTORTED_BODY))) return TRUE if(istype(mover) && mover.checkpass(PASSTABLE)) return TRUE @@ -868,8 +868,12 @@ return 1 if(!density) //Because broken racks -Agouri |TODO: SPRITE!| return 1 - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 + if(istype(mover)) + if(mover.checkpass(PASSTABLE)) + return TRUE + var/mob/living/living_mover = mover + if(istype(living_mover) && IS_HORIZONTAL(living_mover) && HAS_TRAIT(living_mover, TRAIT_CONTORTED_BODY)) + return TRUE if(mover.throwing) return 1 else diff --git a/code/modules/antagonists/changeling/powers/contort_body.dm b/code/modules/antagonists/changeling/powers/contort_body.dm new file mode 100644 index 00000000000..c79146f93ec --- /dev/null +++ b/code/modules/antagonists/changeling/powers/contort_body.dm @@ -0,0 +1,26 @@ +/datum/action/changeling/contort_body + name = "Contort Body" + desc = "We contort our body, allowing us to fit in and under things we normally wouldn't be able to. Costs 5 chemicals." + button_icon_state = "contort_body" + chemical_cost = 5 + dna_cost = 2 + power_type = CHANGELING_PURCHASABLE_POWER + +/datum/action/changeling/contort_body/Remove(mob/M) + REMOVE_TRAIT(M, TRAIT_CONTORTED_BODY, CHANGELING_TRAIT) + ..() + +/datum/action/changeling/contort_body/sting_action(mob/living/user) + if(HAS_TRAIT_FROM(user, TRAIT_CONTORTED_BODY, CHANGELING_TRAIT)) + REMOVE_TRAIT(user, TRAIT_CONTORTED_BODY, CHANGELING_TRAIT) + to_chat(user, "Our body stiffens and returns to form.") + if(IS_HORIZONTAL(user)) + user.layer = initial(user.layer) + else + ADD_TRAIT(user, TRAIT_CONTORTED_BODY, CHANGELING_TRAIT) + to_chat(user, "We contort our form to allow us to fit in and under things we normally wouldn't be able to.") + if(IS_HORIZONTAL(user)) + user.layer = TURF_LAYER + 0.2 + + SSblackbox.record_feedback("nested tally", "changeling_powers", 1, list("[name]")) + return TRUE diff --git a/code/modules/mob/living/living_status_procs.dm b/code/modules/mob/living/living_status_procs.dm index 87d4f424998..6d5bd6726a4 100644 --- a/code/modules/mob/living/living_status_procs.dm +++ b/code/modules/mob/living/living_status_procs.dm @@ -111,7 +111,10 @@ STATUS EFFECTS /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 + if(HAS_TRAIT(src, TRAIT_CONTORTED_BODY)) + layer = TURF_LAYER + 0.2 + else + layer = LYING_MOB_LAYER //so mob lying always appear behind standing mobs pixel_y = PIXEL_Y_OFFSET_LYING ADD_TRAIT(src, TRAIT_UI_BLOCKED, LYING_DOWN_TRAIT) ADD_TRAIT(src, TRAIT_CANNOT_PULL, LYING_DOWN_TRAIT) @@ -120,7 +123,7 @@ STATUS EFFECTS set_lying_angle(pick(90, 270)) /mob/living/proc/on_standing_up() - if(layer == LYING_MOB_LAYER) + if(layer == LYING_MOB_LAYER || HAS_TRAIT(src, TRAIT_CONTORTED_BODY)) layer = initial(layer) set_density(initial(density)) REMOVE_TRAITS_IN(src, LYING_DOWN_TRAIT) diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index e52e343bf0394ac416b292b7dd3cb79cc4f11b72..205b92496f7b045308e995c9eb92ac029840283e 100644 GIT binary patch delta 5651 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 CC3#5z diff --git a/paradise.dme b/paradise.dme index 9be879f59bf..898ce5fe0b0 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1312,6 +1312,7 @@ #include "code\modules\antagonists\changeling\powers\become_headslug.dm" #include "code\modules\antagonists\changeling\powers\biodegrade.dm" #include "code\modules\antagonists\changeling\powers\chameleon_skin.dm" +#include "code\modules\antagonists\changeling\powers\contort_body.dm" #include "code\modules\antagonists\changeling\powers\digitalcamo.dm" #include "code\modules\antagonists\changeling\powers\epinephrine.dm" #include "code\modules\antagonists\changeling\powers\fakedeath.dm"