mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-15 12:11:45 +00:00
## About The Pull Request
Improved code quality of both so they resemble each other. Some of the
new specs are as follows
1. Moved` COMSIG_CLICK_ALT` & `COMSIG_CLICK_ALT_SECONDARY` up i.e.
before `can_perform_action()` making them pure hooks not bound by any
action checks giving components full control over them
2. Removed range check(`CAN_I_SEE`) & view check(`is_blind()`) out of
the base alt click proc. They now only apply to living mobs and don't
apply to ghosts(ghosts don't get blind & see everything) & revenants
(the range check still applies for revenants though).
This was actually a bug because these 2 checks were only meant to see if
the loot panel could be opened (as stated in
https://github.com/tgstation/tgstation/pull/83736#discussion_r1628097941)
but because they are at the top of the proc they also apply to all alt
click actions which is not intended. Also, by moving these checks down
to mob subtype levels some of the snowflake checks like this
7579e0e173/code/_onclick/click_alt.dm (L23)
can be removed. We should not check for subtypes within the parent type
proc but instead have subtypes override their parent procs to implement
custom behaviour
3. Removed redundant signals like` COMSIG_XENO_SLIME_CLICK_ALT` in
favour of just `COMSIG_MOB_ALTCLICKON`
4. While looking for alt click signal overrides I found alt click for
style meter was run timing, that's fixed now
## Changelog
🆑
fix: alt click runtime no more when using style meter
code: improved alt & ctrl click code
/🆑
140 lines
5.1 KiB
Plaintext
140 lines
5.1 KiB
Plaintext
/datum/component/simple_rotation
|
|
/// Additional stuff to do after rotation
|
|
var/datum/callback/post_rotation
|
|
/// Rotation flags for special behavior
|
|
var/rotation_flags = NONE
|
|
|
|
/**
|
|
* Adds the ability to rotate an object by Alt-click or using Right-click verbs.
|
|
*
|
|
* args:
|
|
* * rotation_flags (optional) Bitflags that determine behavior for rotation (defined at the top of this file)
|
|
* * post_rotation (optional) Callback proc that is used after the object is rotated (sound effects, balloon alerts, etc.)
|
|
**/
|
|
/datum/component/simple_rotation/Initialize(rotation_flags = NONE, post_rotation)
|
|
if(!ismovable(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
var/atom/movable/source = parent
|
|
source.flags_1 |= HAS_CONTEXTUAL_SCREENTIPS_1
|
|
|
|
src.rotation_flags = rotation_flags
|
|
src.post_rotation = post_rotation || CALLBACK(src, PROC_REF(default_post_rotation))
|
|
|
|
/datum/component/simple_rotation/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(rotate_left))
|
|
RegisterSignal(parent, COMSIG_CLICK_ALT_SECONDARY, PROC_REF(rotate_right))
|
|
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(ExamineMessage))
|
|
RegisterSignal(parent, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item))
|
|
return ..()
|
|
|
|
/datum/component/simple_rotation/PostTransfer()
|
|
//Because of the callbacks which we don't track cleanly we can't transfer this
|
|
//item cleanly, better to let the new of the new item create a new rotation datum
|
|
//instead (there's no real state worth transferring)
|
|
return COMPONENT_NOTRANSFER
|
|
|
|
/datum/component/simple_rotation/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_CLICK_ALT,
|
|
COMSIG_CLICK_ALT_SECONDARY,
|
|
COMSIG_ATOM_EXAMINE,
|
|
COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM,
|
|
))
|
|
return ..()
|
|
|
|
/datum/component/simple_rotation/Destroy()
|
|
post_rotation = null
|
|
return ..()
|
|
|
|
/datum/component/simple_rotation/proc/ExamineMessage(datum/source, mob/user, list/examine_list)
|
|
SIGNAL_HANDLER
|
|
if(rotation_flags & ROTATION_REQUIRE_WRENCH)
|
|
examine_list += span_notice("This requires a wrench to be rotated.")
|
|
|
|
/datum/component/simple_rotation/proc/rotate_right(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
rotate(user, ROTATION_CLOCKWISE)
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/datum/component/simple_rotation/proc/rotate_left(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
rotate(user, ROTATION_COUNTERCLOCKWISE)
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/datum/component/simple_rotation/proc/rotate(mob/user, degrees)
|
|
if(QDELETED(user))
|
|
CRASH("[src] is being rotated [user ? "with a qdeleting" : "without a"] user")
|
|
if(!istype(user))
|
|
CRASH("[src] is being rotated without a user of the wrong type: [user.type]")
|
|
if(!isnum(degrees))
|
|
CRASH("[src] is being rotated without providing the amount of degrees needed")
|
|
|
|
if(!can_be_rotated(user, degrees) || !can_user_rotate(user, degrees))
|
|
return
|
|
|
|
var/obj/rotated_obj = parent
|
|
rotated_obj.setDir(turn(rotated_obj.dir, degrees))
|
|
if(rotation_flags & ROTATION_REQUIRE_WRENCH)
|
|
playsound(rotated_obj, 'sound/items/ratchet.ogg', 50, TRUE)
|
|
|
|
post_rotation.Invoke(user, degrees)
|
|
|
|
/datum/component/simple_rotation/proc/can_user_rotate(mob/user, degrees)
|
|
if(isliving(user) && user.can_perform_action(parent, NEED_DEXTERITY))
|
|
return TRUE
|
|
if((rotation_flags & ROTATION_GHOSTS_ALLOWED) && isobserver(user) && CONFIG_GET(flag/ghost_interaction))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/datum/component/simple_rotation/proc/can_be_rotated(mob/user, degrees, silent=FALSE)
|
|
var/obj/rotated_obj = parent
|
|
if(!rotated_obj.Adjacent(user))
|
|
silent = TRUE
|
|
|
|
if(rotation_flags & ROTATION_REQUIRE_WRENCH)
|
|
if(!isliving(user))
|
|
return FALSE
|
|
var/obj/item/tool = user.get_active_held_item()
|
|
if(!tool || tool.tool_behaviour != TOOL_WRENCH)
|
|
if(!silent)
|
|
rotated_obj.balloon_alert(user, "need a wrench!")
|
|
return FALSE
|
|
if(!(rotation_flags & ROTATION_IGNORE_ANCHORED) && rotated_obj.anchored)
|
|
if(istype(rotated_obj, /obj/structure/window) && !silent)
|
|
rotated_obj.balloon_alert(user, "need to unscrew!")
|
|
else if(!silent)
|
|
rotated_obj.balloon_alert(user, "need to unwrench!")
|
|
return FALSE
|
|
|
|
if(rotation_flags & ROTATION_NEEDS_ROOM)
|
|
var/target_dir = turn(rotated_obj.dir, degrees)
|
|
var/obj/structure/window/rotated_window = rotated_obj
|
|
var/fulltile = istype(rotated_window) ? rotated_window.fulltile : FALSE
|
|
if(!valid_build_direction(rotated_obj.loc, target_dir, is_fulltile = fulltile))
|
|
if(!silent)
|
|
rotated_obj.balloon_alert(user, "can't rotate in that direction!")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/component/simple_rotation/proc/default_post_rotation(mob/user, degrees)
|
|
return
|
|
|
|
// maybe we don't need the item context proc but instead the hand one? since we don't need to check held_item
|
|
/datum/component/simple_rotation/proc/on_requesting_context_from_item(atom/source, list/context, obj/item/held_item, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
var/rotation_screentip = FALSE
|
|
|
|
if(can_be_rotated(user, ROTATION_CLOCKWISE, silent=TRUE))
|
|
context[SCREENTIP_CONTEXT_ALT_LMB] = "Rotate left"
|
|
rotation_screentip = TRUE
|
|
if(can_be_rotated(user, ROTATION_COUNTERCLOCKWISE, silent=TRUE))
|
|
context[SCREENTIP_CONTEXT_ALT_RMB] = "Rotate right"
|
|
rotation_screentip = TRUE
|
|
|
|
if(rotation_screentip)
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
return NONE
|