From 3b36787d90e15c593adefb2b880b950987d65d1e Mon Sep 17 00:00:00 2001 From: Odairu <39929315+Odairu@users.noreply.github.com> Date: Mon, 9 Sep 2024 21:26:30 -0400 Subject: [PATCH] [Fully-Modular] Adds a keybind to allow for pixel shifting of one's character, and items they are grabbing (#2850) * The whole PR * Modular * merges with mob pixel shifting * Random space for ??? * optimization * Update pixel_shift.dm * fixes bug * Make pixel-shifting a living rather than a mob keybind. --------- Co-authored-by: Lucy --- code/__DEFINES/~monkestation/keybinding.dm | 6 + code/__DEFINES/~monkestation/living.dm | 8 + .../code/datums/components/pixel_shift.dm | 143 ++++++++++++++++++ monkestation/code/datums/keybinding/living.dm | 38 +++++ .../modules/mob/living/living_movement.dm | 4 + tgstation.dme | 3 + 6 files changed, 202 insertions(+) create mode 100644 code/__DEFINES/~monkestation/living.dm create mode 100644 monkestation/code/datums/components/pixel_shift.dm create mode 100644 monkestation/code/modules/mob/living/living_movement.dm diff --git a/code/__DEFINES/~monkestation/keybinding.dm b/code/__DEFINES/~monkestation/keybinding.dm index b074c433ef49..c30dbdebb821 100644 --- a/code/__DEFINES/~monkestation/keybinding.dm +++ b/code/__DEFINES/~monkestation/keybinding.dm @@ -1 +1,7 @@ #define COMSIG_KB_CLIENT_LOOC_DOWN "keybinding_client_looc_down" + +#define COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_DOWN "keybinding_living_item_pixelshift_down" +#define COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_UP "keybinding_living_item_pixelshift_up" +#define COMSIG_KB_LIVING_PIXELSHIFT "keybinding_living_pixelshift" +#define COMSIG_KB_LIVING_PIXEL_SHIFT_DOWN "keybinding_living_pixelshift_down" +#define COMSIG_KB_LIVING_PIXEL_SHIFT_UP "keybinding_living_pixelshift_up" diff --git a/code/__DEFINES/~monkestation/living.dm b/code/__DEFINES/~monkestation/living.dm new file mode 100644 index 000000000000..06134c4aaffa --- /dev/null +++ b/code/__DEFINES/~monkestation/living.dm @@ -0,0 +1,8 @@ +///from base of living/set_pull_offset(): (mob/living/pull_target, grab_state) +#define COMSIG_LIVING_SET_PULL_OFFSET "living_set_pull_offset" +///from base of living/reset_pull_offsets(): (mob/living/pull_target, override) +#define COMSIG_LIVING_RESET_PULL_OFFSETS "living_reset_pull_offsets" +///from base of living/CanAllowThrough(): (atom/movable/mover, border_dir) +#define COMSIG_LIVING_CAN_ALLOW_THROUGH "living_can_allow_through" + /// Allow to movable atoms to pass through this living mob + #define COMPONENT_LIVING_PASSABLE (1<<0) diff --git a/monkestation/code/datums/components/pixel_shift.dm b/monkestation/code/datums/components/pixel_shift.dm new file mode 100644 index 000000000000..18c01bbf9217 --- /dev/null +++ b/monkestation/code/datums/components/pixel_shift.dm @@ -0,0 +1,143 @@ +#define SHIFTING_PARENT 1 +#define SHIFTING_ITEMS 2 + +/datum/component/pixel_shift + dupe_mode = COMPONENT_DUPE_UNIQUE + //what type of shifting parent is doing, or if they aren't shifting at all + var/shifting = FALSE + //the maximum amount we/an item can move + var/maximum_pixel_shift = 16 + //If we are shifted + var/is_shifted = FALSE + //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)) + 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_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 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 + +/datum/component/pixel_shift/proc/pixel_shift_down() + SIGNAL_HANDLER + shifting = SHIFTING_PARENT + return COMSIG_KB_ACTIVATED + +/datum/component/pixel_shift/proc/pixel_shift_up() + SIGNAL_HANDLER + shifting = FALSE + +/// 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 + +/// 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.pixel_x = owner.body_position_pixel_x_offset + owner.base_pixel_x + owner.pixel_y = owner.body_position_pixel_y_offset + owner.base_pixel_y + 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(owner.pixel_y <= maximum_pixel_shift + owner.base_pixel_y) + owner.pixel_y++ + is_shifted = TRUE + if(EAST) + if(owner.pixel_x <= maximum_pixel_shift + owner.base_pixel_x) + owner.pixel_x++ + is_shifted = TRUE + if(SOUTH) + if(owner.pixel_y >= -maximum_pixel_shift + owner.base_pixel_y) + owner.pixel_y-- + is_shifted = TRUE + if(WEST) + if(owner.pixel_x >= -maximum_pixel_shift + owner.base_pixel_x) + owner.pixel_x-- + 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(owner.pixel_y > passthrough_threshold) + passthroughable |= EAST | SOUTH | WEST + else if(owner.pixel_y < -passthrough_threshold) + passthroughable |= NORTH | EAST | WEST + if(owner.pixel_x > passthrough_threshold) + passthroughable |= NORTH | SOUTH | WEST + else if(owner.pixel_x < -passthrough_threshold) + passthroughable |= NORTH | EAST | SOUTH + +#undef SHIFTING_PARENT +#undef SHIFTING_ITEMS diff --git a/monkestation/code/datums/keybinding/living.dm b/monkestation/code/datums/keybinding/living.dm index d3a2f213914d..3cb95168c68a 100644 --- a/monkestation/code/datums/keybinding/living.dm +++ b/monkestation/code/datums/keybinding/living.dm @@ -62,3 +62,41 @@ if(.) return user.imode.keybind_act(5) + +/datum/keybinding/living/item_pixel_shift + hotkey_keys = list("V") + name = "item_pixel_shift" + full_name = "Item Pixel Shift" + description = "Shift a pulled item's offset" + category = CATEGORY_MISC + keybind_signal = COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_DOWN + +/datum/keybinding/living/item_pixel_shift/down(client/user) + . = ..() + if(.) + return + user.mob.AddComponent(/datum/component/pixel_shift) + SEND_SIGNAL(user.mob, COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_DOWN) + +/datum/keybinding/living/item_pixel_shift/up(client/user) + . = ..() + SEND_SIGNAL(user.mob, COMSIG_KB_LIVING_ITEM_PIXEL_SHIFT_UP) + +/datum/keybinding/living/pixel_shift + hotkey_keys = list("B") + name = "pixel_shift" + full_name = "Pixel Shift" + description = "Shift your characters offset." + category = CATEGORY_MOVEMENT + keybind_signal = COMSIG_KB_LIVING_PIXEL_SHIFT_DOWN + +/datum/keybinding/living/pixel_shift/down(client/user) + . = ..() + if(.) + return + user.mob.AddComponent(/datum/component/pixel_shift) + SEND_SIGNAL(user.mob, COMSIG_KB_LIVING_PIXEL_SHIFT_DOWN) + +/datum/keybinding/living/pixel_shift/up(client/user) + . = ..() + SEND_SIGNAL(user.mob, COMSIG_KB_LIVING_PIXEL_SHIFT_UP) diff --git a/monkestation/code/modules/mob/living/living_movement.dm b/monkestation/code/modules/mob/living/living_movement.dm new file mode 100644 index 000000000000..a2efb7be0ec5 --- /dev/null +++ b/monkestation/code/modules/mob/living/living_movement.dm @@ -0,0 +1,4 @@ +/mob/living/CanAllowThrough(atom/movable/mover, border_dir) + if(SEND_SIGNAL(src, COMSIG_LIVING_CAN_ALLOW_THROUGH, mover, border_dir) & COMPONENT_LIVING_PASSABLE) + return TRUE + return ..() diff --git a/tgstation.dme b/tgstation.dme index 7140b7485cc9..f26bb1554462 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -430,6 +430,7 @@ #include "code\__DEFINES\~monkestation\jobs.dm" #include "code\__DEFINES\~monkestation\keybinding.dm" #include "code\__DEFINES\~monkestation\level_traits.dm" +#include "code\__DEFINES\~monkestation\living.dm" #include "code\__DEFINES\~monkestation\logging.dm" #include "code\__DEFINES\~monkestation\maps.dm" #include "code\__DEFINES\~monkestation\market.dm" @@ -5821,6 +5822,7 @@ #include "monkestation\code\datums\components\crafting.dm" #include "monkestation\code\datums\components\irradiated.dm" #include "monkestation\code\datums\components\multi_hit.dm" +#include "monkestation\code\datums\components\pixel_shift.dm" #include "monkestation\code\datums\components\throw_bounce.dm" #include "monkestation\code\datums\components\turf_checker_complex.dm" #include "monkestation\code\datums\components\turf_healing.dm" @@ -7228,6 +7230,7 @@ #include "monkestation\code\modules\mob\dead\new_player\sprite_accessories\tails.dm" #include "monkestation\code\modules\mob\dead\new_player\sprite_accessories\underwear.dm" #include "monkestation\code\modules\mob\living\living_defines.dm" +#include "monkestation\code\modules\mob\living\living_movement.dm" #include "monkestation\code\modules\mob\living\status_procs.dm" #include "monkestation\code\modules\mob\living\basic\animatronic.dm" #include "monkestation\code\modules\mob\living\basic\bots\medbot\medbot.dm"