From b8091a2e5da2be8e2f5569d924f3f8ec6a01e90e Mon Sep 17 00:00:00 2001 From: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:54:44 +0200 Subject: [PATCH] Changes wall leaning into a component, makes windows leanable #2 (#87390) ## About The Pull Request Recovery of #85771, minus directional window leaning (because it looks goofy) ## Changelog :cl: add: You can now lean on windows the same way you can lean on walls fix: You no longer stop leaning on walls after clicking on anything /:cl: --- .../signals/signals_mob/signals_mob_living.dm | 2 + code/datums/components/leanable.dm | 111 ++++++++++++++++++ code/game/objects/structures/window.dm | 11 ++ code/game/turfs/closed/walls.dm | 73 ++---------- tgstation.dme | 1 + 5 files changed, 136 insertions(+), 62 deletions(-) create mode 100644 code/datums/components/leanable.dm diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 633282001f67a..ef47b6f4b8243 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -297,3 +297,5 @@ #define COMSIG_MOB_ENSLAVED_TO "mob_enslaved_to" /// From /obj/item/proc/attack_atom: (mob/living/attacker, atom/attacked) #define COMSIG_LIVING_ATTACK_ATOM "living_attack_atom" +/// From /mob/living/proc/stop_leaning() +#define COMSIG_LIVING_STOPPED_LEANING "living_stopped_leaning" diff --git a/code/datums/components/leanable.dm b/code/datums/components/leanable.dm new file mode 100644 index 0000000000000..3d2a4e0b73e5b --- /dev/null +++ b/code/datums/components/leanable.dm @@ -0,0 +1,111 @@ +/// Things with this component can be leaned onto, optionally exclusive to RMB dragging +/datum/component/leanable + /// How much will mobs that lean onto this object be offset + var/leaning_offset = 11 + /// List of click modifiers that are required to be present for leaning to trigger + var/list/click_mods = null + /// Callback called for additional checks if a lean is valid + var/datum/callback/lean_check = null + /// Whenever this object can be leaned on from the same turf as its' own. Do not use without a custom lean_check! + var/same_turf = FALSE + /// List of mobs currently leaning on our parent + var/list/leaning_mobs = list() + +/datum/component/leanable/Initialize(leaning_offset = 11, list/click_mods = null, datum/callback/lean_check = null, same_turf = FALSE) + . = ..() + src.leaning_offset = leaning_offset + src.click_mods = click_mods + src.lean_check = lean_check + src.same_turf = same_turf + +/datum/component/leanable/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(mousedrop_receive)) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + +/datum/component/leanable/Destroy(force) + for (var/mob/living/leaner as anything in leaning_mobs) + leaner.stop_leaning() + leaning_mobs = null + return ..() + +/datum/component/leanable/proc/on_moved(datum/source) + SIGNAL_HANDLER + for (var/mob/living/leaner as anything in leaning_mobs) + leaner.stop_leaning() + +/datum/component/leanable/proc/mousedrop_receive(atom/source, atom/movable/dropped, mob/user, params) + if (dropped != user) + return + if (islist(click_mods)) + var/list/modifiers = params2list(params) + for (var/modifier in click_mods) + if (!LAZYACCESS(modifiers, modifier)) + return + if (!iscarbon(dropped) && !iscyborg(dropped)) + return + var/mob/living/leaner = dropped + if (INCAPACITATED_IGNORING(leaner, INCAPABLE_RESTRAINTS) || leaner.stat != CONSCIOUS || HAS_TRAIT(leaner, TRAIT_NO_TRANSFORM)) + return + if (HAS_TRAIT_FROM(leaner, TRAIT_UNDENSE, LEANING_TRAIT)) + return + var/turf/checked_turf = get_step(leaner, REVERSE_DIR(leaner.dir)) + if (checked_turf != get_turf(source) && (!same_turf || get_turf(source) != get_turf(leaner))) + return + if (!isnull(lean_check) && !lean_check.Invoke(dropped, params)) + return + leaner.start_leaning(source, leaning_offset) + leaning_mobs += leaner + RegisterSignals(leaner, list(COMSIG_LIVING_STOPPED_LEANING, COMSIG_QDELETING), PROC_REF(stopped_leaning)) + return COMPONENT_CANCEL_MOUSEDROPPED_ONTO + +/datum/component/leanable/proc/stopped_leaning(datum/source) + SIGNAL_HANDLER + leaning_mobs -= source + UnregisterSignal(source, list(COMSIG_LIVING_STOPPED_LEANING, COMSIG_QDELETING)) + +/mob/living/proc/start_leaning(atom/lean_target, leaning_offset) + var/new_x = lean_target.pixel_x + base_pixel_x + body_position_pixel_x_offset + var/new_y = lean_target.pixel_y + base_pixel_y + body_position_pixel_y_offset + switch(dir) + if(SOUTH) + new_y += leaning_offset + if(NORTH) + new_y -= leaning_offset + if(WEST) + new_x += leaning_offset + if(EAST) + new_x -= leaning_offset + + animate(src, 0.2 SECONDS, pixel_x = new_x, pixel_y = new_y) + add_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) + visible_message( + span_notice("[src] leans against [lean_target]."), + span_notice("You lean against [lean_target]."), + ) + RegisterSignals(src, list( + COMSIG_MOB_CLIENT_PRE_MOVE, + COMSIG_LIVING_DISARM_HIT, + COMSIG_LIVING_GET_PULLED, + COMSIG_MOVABLE_TELEPORTING, + ), PROC_REF(stop_leaning)) + RegisterSignal(src, COMSIG_ATOM_POST_DIR_CHANGE, PROC_REF(lean_dir_changed)) + update_fov() + +/mob/living/proc/stop_leaning() + SIGNAL_HANDLER + UnregisterSignal(src, list( + COMSIG_MOB_CLIENT_PRE_MOVE, + COMSIG_LIVING_DISARM_HIT, + COMSIG_LIVING_GET_PULLED, + COMSIG_MOVABLE_TELEPORTING, + COMSIG_ATOM_POST_DIR_CHANGE, + )) + animate(src, 0.2 SECONDS, pixel_x = base_pixel_x + body_position_pixel_x_offset, pixel_y = base_pixel_y + body_position_pixel_y_offset) + remove_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) + SEND_SIGNAL(src, COMSIG_LIVING_STOPPED_LEANING) + update_fov() + +/mob/living/proc/lean_dir_changed(atom/source, old_dir, new_dir) + SIGNAL_HANDLER + if (old_dir != new_dir) + INVOKE_ASYNC(src, PROC_REF(stop_leaning)) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 032b86721b0bb..0d5fc1e5c5d08 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -37,6 +37,8 @@ var/datum/material/glass_material_datum = /datum/material/glass /// Whether or not we're disappearing but dramatically var/dramatically_disappearing = FALSE + /// If we added a leaning component to ourselves + var/added_leaning = FALSE /datum/armor/structure_window melee = 50 @@ -78,6 +80,15 @@ if (flags_1 & ON_BORDER_1) AddElement(/datum/element/connect_loc, loc_connections) +/obj/structure/window/mouse_drop_receive(atom/dropping, mob/user, params) + . = ..() + if (added_leaning || (flags_1 & ON_BORDER_1)) + return + /// For performance reasons and to cut down on init times we are "lazy-loading" the leaning component when someone drags their sprite onto us, and then calling dragging code again to trigger the component + AddComponent(/datum/component/leanable, 11) + added_leaning = TRUE + dropping.base_mouse_drop_handler(src, null, null, params) + /obj/structure/window/examine(mob/user) . = ..() diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index f1297e4a02258..df15a8ef303e4 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -1,5 +1,3 @@ -#define LEANING_OFFSET 11 - /turf/closed/wall name = "wall" desc = "A huge chunk of iron used to separate rooms." @@ -31,67 +29,11 @@ var/girder_type = /obj/structure/girder /// A turf that will replace this turf when this turf is destroyed var/decon_type + /// If we added a leaning component to ourselves + var/added_leaning = FALSE var/list/dent_decals -/turf/closed/wall/mouse_drop_receive(atom/dropping, mob/user, params) - if(dropping != user) - return - if(!iscarbon(dropping) && !iscyborg(dropping)) - return - var/mob/living/leaner = dropping - if(INCAPACITATED_IGNORING(leaner, INCAPABLE_RESTRAINTS) || leaner.stat != CONSCIOUS || HAS_TRAIT(leaner, TRAIT_NO_TRANSFORM)) - return - if(!leaner.density || leaner.pulledby || leaner.buckled || !(leaner.mobility_flags & MOBILITY_STAND)) - return - if(HAS_TRAIT_FROM(leaner, TRAIT_UNDENSE, LEANING_TRAIT)) - return - var/turf/checked_turf = get_step(leaner, REVERSE_DIR(leaner.dir)) - if(checked_turf != src) - return - leaner.start_leaning(src) - -/mob/living/proc/start_leaning(turf/closed/wall/wall) - var/new_y = base_pixel_y + pixel_y - var/new_x = base_pixel_x + pixel_x - switch(dir) - if(SOUTH) - new_y += LEANING_OFFSET - if(NORTH) - new_y -= LEANING_OFFSET - if(WEST) - new_x += LEANING_OFFSET - if(EAST) - new_x -= LEANING_OFFSET - - animate(src, 0.2 SECONDS, pixel_x = new_x, pixel_y = new_y) - add_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) - visible_message( - span_notice("[src] leans against [wall]."), - span_notice("You lean against [wall]."), - ) - RegisterSignals(src, list( - COMSIG_MOB_CLIENT_PRE_MOVE, - COMSIG_LIVING_DISARM_HIT, - COMSIG_LIVING_GET_PULLED, - COMSIG_MOVABLE_TELEPORTING, - COMSIG_ATOM_DIR_CHANGE, - ), PROC_REF(stop_leaning)) - update_fov() - -/mob/living/proc/stop_leaning() - SIGNAL_HANDLER - UnregisterSignal(src, list( - COMSIG_MOB_CLIENT_PRE_MOVE, - COMSIG_LIVING_DISARM_HIT, - COMSIG_LIVING_GET_PULLED, - COMSIG_MOVABLE_TELEPORTING, - COMSIG_ATOM_DIR_CHANGE, - )) - animate(src, 0.2 SECONDS, pixel_x = base_pixel_x, pixel_y = base_pixel_y) - remove_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) - update_fov() - /turf/closed/wall/Initialize(mapload) . = ..() if(!can_engrave) @@ -108,6 +50,15 @@ fixed_underlay = string_assoc_list(fixed_underlay) underlays += underlay_appearance +/turf/closed/wall/mouse_drop_receive(atom/dropping, mob/user, params) + . = ..() + if (added_leaning) + return + /// For performance reasons and to cut down on init times we are "lazy-loading" the leaning component when someone drags their sprite onto us, and then calling dragging code again to trigger the component + AddComponent(/datum/component/leanable, 11) + added_leaning = TRUE + dropping.base_mouse_drop_handler(src, null, null, params) + /turf/closed/wall/atom_destruction(damage_flag) . = ..() dismantle_wall(TRUE, FALSE) @@ -378,5 +329,3 @@ /turf/closed/wall/Exited(atom/movable/gone, direction) . = ..() SEND_SIGNAL(gone, COMSIG_LIVING_WALL_EXITED, src) - -#undef LEANING_OFFSET diff --git a/tgstation.dme b/tgstation.dme index 3b9556408754b..f6b649ee67021 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1156,6 +1156,7 @@ #include "code\datums\components\jukebox.dm" #include "code\datums\components\keep_me_secure.dm" #include "code\datums\components\knockoff.dm" +#include "code\datums\components\leanable.dm" #include "code\datums\components\leash.dm" #include "code\datums\components\life_link.dm" #include "code\datums\components\light_eater.dm"