Files
RoxyandGitHub 504a8461ec Move pixel shift keybinds/signals to /mob/living (#4167)
## About The Pull Request

Move keybind signal defines and `/datum/keybinding`s to be living
instead of mob

## Why It's Good For The Game
Fixes #4164

## Proof Of Testing

Tested on local no runtimes and still functions

## Changelog

No user facing changes
2025-07-02 22:07:04 -04:00

186 lines
6.2 KiB
Plaintext

#define SHIFTING_ITEMS 1
#define SHIFTING_PARENT 2
#define TILTING_PARENT 3
/datum/component/pixel_shift
dupe_mode = COMPONENT_DUPE_UNIQUE
//whether or not parent is shifting
var/shifting = FALSE
//how tilted the parent is
var/how_tilted
//the maximum amount of tilt parent can achieve
var/maximum_tilt = 45
//the maximum amount we/an item can move
var/maximum_pixel_shift = 16
//If we are shifted
var/is_shifted = FALSE
//Amount of shift in the X axis
var/shift_x = 0
//Amount of shift in the Y axis
var/shift_y = 0
//Allows atoms entering Parent's turf to pass through freely from given directions
var/passthroughable = NONE
//Amount of shifting necessary to make the parent passthroughable
var/passthrough_threshold = 8
/datum/component/pixel_shift/Initialize(...)
. = ..()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
/datum/component/pixel_shift/RegisterWithParent()
RegisterSignal(parent, COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_DOWN, PROC_REF(item_pixel_shift_down))
RegisterSignal(parent, COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_UP, PROC_REF(item_pixel_shift_up))
RegisterSignal(parent, COMSIG_KB_LIVING_PIXEL_SHIFT_DOWN, PROC_REF(pixel_shift_down))
RegisterSignal(parent, COMSIG_KB_LIVING_PIXEL_SHIFT_UP, PROC_REF(pixel_shift_up))
RegisterSignal(parent, COMSIG_KB_LIVING_PIXEL_TILT_DOWN, PROC_REF(pixel_tilt_down))
RegisterSignal(parent, COMSIG_KB_LIVING_PIXEL_TILT_UP, PROC_REF(pixel_tilt_up))
RegisterSignals(parent, list(COMSIG_LIVING_RESET_PULL_OFFSETS, COMSIG_LIVING_SET_PULL_OFFSET, COMSIG_MOVABLE_MOVED), PROC_REF(unpixel_shift))
RegisterSignal(parent, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE, PROC_REF(pre_move_check))
RegisterSignal(parent, COMSIG_LIVING_CAN_ALLOW_THROUGH, PROC_REF(check_passable))
/datum/component/pixel_shift/UnregisterFromParent()
UnregisterSignal(parent, list(
COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_DOWN,
COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_UP,
COMSIG_KB_LIVING_PIXEL_TILT_DOWN,
COMSIG_KB_LIVING_PIXEL_TILT_UP,
COMSIG_KB_LIVING_PIXEL_SHIFT_DOWN,
COMSIG_KB_LIVING_PIXEL_SHIFT_UP,
COMSIG_MOB_CLIENT_PRE_LIVING_MOVE,
COMSIG_LIVING_RESET_PULL_OFFSETS,
COMSIG_LIVING_SET_PULL_OFFSET,
COMSIG_MOVABLE_MOVED,
COMSIG_LIVING_CAN_ALLOW_THROUGH,
))
//locks our movement when holding our keybinds
/datum/component/pixel_shift/proc/pre_move_check(mob/source, new_loc, direct)
SIGNAL_HANDLER
if(shifting)
pixel_shift(source, direct)
return COMSIG_MOB_CLIENT_BLOCK_PRE_LIVING_MOVE
//procs for tilting parent
/datum/component/pixel_shift/proc/pixel_tilt_down()
SIGNAL_HANDLER
shifting = TILTING_PARENT
return COMSIG_KB_ACTIVATED
/datum/component/pixel_shift/proc/pixel_tilt_up()
SIGNAL_HANDLER
shifting = FALSE
//Procs for shifting items
/datum/component/pixel_shift/proc/item_pixel_shift_down()
SIGNAL_HANDLER
shifting = SHIFTING_ITEMS
return COMSIG_KB_ACTIVATED
/datum/component/pixel_shift/proc/item_pixel_shift_up()
SIGNAL_HANDLER
shifting = FALSE
//Procs for shifting mobs
/// Checks if the parent is considered passthroughable from a direction. Projectiles will ignore the check and hit.
/datum/component/pixel_shift/proc/check_passable(mob/source, atom/movable/mover, border_dir)
SIGNAL_HANDLER
if(!isprojectile(mover) && !mover.throwing && passthroughable & border_dir)
return COMPONENT_LIVING_PASSABLE
/// Activates Pixel Shift on Keybind down. Only Pixel Shift movement will be allowed.
/datum/component/pixel_shift/proc/pixel_shift_down()
SIGNAL_HANDLER
shifting = SHIFTING_PARENT
return COMSIG_KB_ACTIVATED
/// Disables Pixel Shift on Keybind up. Allows to Move.
/datum/component/pixel_shift/proc/pixel_shift_up()
SIGNAL_HANDLER
shifting = FALSE
/// Sets parent pixel offsets to default and deletes the component.
/datum/component/pixel_shift/proc/unpixel_shift()
SIGNAL_HANDLER
passthroughable = NONE
if(is_shifted)
var/mob/living/owner = parent
owner.remove_offsets(type)
owner.transform = turn(owner.transform, -how_tilted)
qdel(src)
/// In-turf pixel movement which can allow things to pass through if the threshold is met.
/datum/component/pixel_shift/proc/pixel_shift(mob/source, direct)
passthroughable = NONE
var/mob/living/owner = parent
switch(shifting)
if(SHIFTING_ITEMS)
var/atom/pulled_atom = source.pulling
if(!isitem(pulled_atom))
return
var/obj/item/pulled_item = pulled_atom
switch(direct)
if(NORTH)
if(pulled_item.pixel_y <= maximum_pixel_shift + pulled_item.base_pixel_y)
pulled_item.pixel_y++
if(EAST)
if(pulled_item.pixel_x <= maximum_pixel_shift + pulled_item.base_pixel_x)
pulled_item.pixel_x++
if(SOUTH)
if(pulled_item.pixel_y >= -maximum_pixel_shift + pulled_item.base_pixel_y)
pulled_item.pixel_y--
if(WEST)
if(pulled_item.pixel_x >= -maximum_pixel_shift + pulled_item.base_pixel_x)
pulled_item.pixel_x--
if(SHIFTING_PARENT)
switch(direct)
if(NORTH)
if(shift_y <= maximum_pixel_shift)
shift_y++
owner.add_offsets(type, y_add = shift_y)
is_shifted = TRUE
if(EAST)
if(shift_x <= maximum_pixel_shift)
shift_x++
owner.add_offsets(type, x_add = shift_x)
is_shifted = TRUE
if(SOUTH)
if(shift_y >= -maximum_pixel_shift)
shift_y--
owner.add_offsets(type, y_add = shift_y)
is_shifted = TRUE
if(WEST)
if(shift_x >= -maximum_pixel_shift)
shift_x--
owner.add_offsets(type, x_add = shift_x)
is_shifted = TRUE
if(TILTING_PARENT)
switch(direct)
if(EAST)
if(how_tilted <= maximum_tilt)
owner.transform = turn(owner.transform, 1)
how_tilted++
is_shifted = TRUE
if(WEST)
if(how_tilted >= -maximum_tilt)
owner.transform = turn(owner.transform, -1)
how_tilted--
is_shifted = TRUE
// Yes, I know this sets it to true for everything if more than one is matched.
// Movement doesn't check diagonals, and instead just checks EAST or WEST, depending on where you are for those.
if(shift_y > passthrough_threshold)
passthroughable |= EAST | SOUTH | WEST
else if(shift_y < -passthrough_threshold)
passthroughable |= NORTH | EAST | WEST
if(shift_x > passthrough_threshold)
passthroughable |= NORTH | SOUTH | WEST
else if(shift_x < -passthrough_threshold)
passthroughable |= NORTH | EAST | SOUTH
#undef SHIFTING_ITEMS
#undef SHIFTING_PARENT
#undef TILTING_PARENT