Files
Bubberstation/code/datums/components/leanable.dm
SmArtKar d6bcdcf833 Changes wall leaning into a component, makes windows leanable (#85771)
## About The Pull Request

Requires #85491 to be merged first, as otherwise leaning on directional
windows looks incredibly goofy
You can now lean on both fulltile and directional windows, and its
possible to easily extend this functionality to other objects. Dunno if
this even deserves to be called a refactor so not marking it in any way.

## Why It's Good For The Game

Just makes sense that you'd be able to do it

## Changelog
🆑
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
/🆑
2024-08-16 16:59:53 +02:00

112 lines
3.9 KiB
Plaintext

/// 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 (leaner.incapacitated(IGNORE_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_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 [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, pixel_y = base_pixel_y)
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))