mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-08 22:50:51 +01:00
cf14dcfc1a
## About The Pull Request `adjust_fishing_difficulty` is a good one to make into a bespoke element since a number of the same clothing item are created in the wardrobe system. climb_walkable is also good due to how prevalent it is, and it is a bit of a two for one since it also removes the need for the `/component/connect_loc_behalf` Also stops adding the on_climbable trait to literally everything in the turf, it now only applies it to atoms with density. So no more pipes and stuff getting trait lists created for no reason. <details><summary> Tested + things still work as before </summary> <img width="422" height="122" alt="image" src="https://github.com/user-attachments/assets/b23696f5-cd16-4150-aeb3-14ea6bd256fc" /> </details> ## Why It's Good For The Game Lessens overhead, fixes a bug as well. ## Changelog 🆑 fix: fixes a pushed crate not removing on_climbable trait properly off the mob standing atop it /🆑
137 lines
5.1 KiB
Plaintext
137 lines
5.1 KiB
Plaintext
/datum/element/simple_rotation
|
|
element_flags = ELEMENT_BESPOKE
|
|
argument_hash_start_idx = 2
|
|
/// Rotation flags for special behavior
|
|
var/rotation_flags
|
|
/// Optional proc to call()() after the thing is successfully rotated
|
|
var/post_rotation_proccall
|
|
|
|
/**
|
|
* 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/element/simple_rotation/Attach(datum/target, rotation_flags = NONE, post_rotation_proccall)
|
|
. = ..()
|
|
if(!ismovable(target))
|
|
return ELEMENT_INCOMPATIBLE
|
|
|
|
var/atom/movable/source = target
|
|
source.flags_1 |= HAS_CONTEXTUAL_SCREENTIPS_1
|
|
|
|
src.rotation_flags = rotation_flags
|
|
src.post_rotation_proccall = post_rotation_proccall
|
|
|
|
RegisterSignal(target, COMSIG_CLICK_ALT, PROC_REF(rotate_left))
|
|
RegisterSignal(target, COMSIG_CLICK_ALT_SECONDARY, PROC_REF(rotate_right))
|
|
RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(ExamineMessage))
|
|
RegisterSignal(target, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item))
|
|
|
|
/datum/element/simple_rotation/Detach(datum/source, ...)
|
|
. = ..()
|
|
UnregisterSignal(source, list(
|
|
COMSIG_CLICK_ALT,
|
|
COMSIG_CLICK_ALT_SECONDARY,
|
|
COMSIG_ATOM_EXAMINE,
|
|
COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM,
|
|
))
|
|
return ..()
|
|
|
|
/datum/element/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/element/simple_rotation/proc/rotate_right(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
rotate(user, source, ROTATION_CLOCKWISE)
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/datum/element/simple_rotation/proc/rotate_left(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
rotate(user, source, ROTATION_COUNTERCLOCKWISE)
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/datum/element/simple_rotation/proc/rotate(mob/user, obj/object_to_rotate, 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, object_to_rotate, degrees) || !can_user_rotate(user, object_to_rotate, degrees))
|
|
return
|
|
|
|
object_to_rotate.setDir(turn(object_to_rotate.dir, degrees))
|
|
if(rotation_flags & ROTATION_REQUIRE_WRENCH)
|
|
playsound(object_to_rotate, 'sound/items/tools/ratchet.ogg', 50, TRUE)
|
|
|
|
if(post_rotation_proccall)
|
|
call(object_to_rotate, post_rotation_proccall)(user, degrees)
|
|
|
|
/datum/element/simple_rotation/proc/can_user_rotate(mob/user, obj/object_to_rotate, degrees)
|
|
if(isliving(user) && user.can_perform_action(object_to_rotate, NEED_DEXTERITY))
|
|
return TRUE
|
|
if((rotation_flags & ROTATION_GHOSTS_ALLOWED) && isobserver(user) && CONFIG_GET(flag/ghost_interaction))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/datum/element/simple_rotation/proc/can_be_rotated(mob/user, obj/object_to_rotate, degrees, silent = FALSE)
|
|
if(!object_to_rotate.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)
|
|
object_to_rotate.balloon_alert(user, "need a wrench!")
|
|
return FALSE
|
|
|
|
if(!(rotation_flags & ROTATION_IGNORE_ANCHORED) && object_to_rotate.anchored)
|
|
if(istype(object_to_rotate, /obj/structure/window) && !silent)
|
|
object_to_rotate.balloon_alert(user, "need to unscrew!")
|
|
else if(!silent)
|
|
object_to_rotate.balloon_alert(user, "need to unwrench!")
|
|
return FALSE
|
|
|
|
if(rotation_flags & ROTATION_NEEDS_ROOM)
|
|
var/target_dir = turn(object_to_rotate.dir, degrees)
|
|
var/obj/structure/window/window_to_rotate = object_to_rotate
|
|
var/fulltile = istype(window_to_rotate) ? window_to_rotate.fulltile : FALSE
|
|
if(!valid_build_direction(object_to_rotate.loc, target_dir, is_fulltile = fulltile))
|
|
if(!silent)
|
|
object_to_rotate.balloon_alert(user, "can't rotate in that direction!")
|
|
return FALSE
|
|
|
|
if(rotation_flags & ROTATION_NEEDS_UNBLOCKED)
|
|
var/turf/rotate_turf = get_turf(object_to_rotate)
|
|
if(rotate_turf.is_blocked_turf(source_atom = object_to_rotate))
|
|
if(!silent)
|
|
object_to_rotate.balloon_alert(user, "rotation is blocked!")
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
// maybe we don't need the item context proc but instead the hand one? since we don't need to check held_item
|
|
/datum/element/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, source, ROTATION_CLOCKWISE, silent=TRUE))
|
|
context[SCREENTIP_CONTEXT_ALT_LMB] = "Rotate left"
|
|
rotation_screentip = TRUE
|
|
if(can_be_rotated(user, source, ROTATION_COUNTERCLOCKWISE, silent=TRUE))
|
|
context[SCREENTIP_CONTEXT_ALT_RMB] = "Rotate right"
|
|
rotation_screentip = TRUE
|
|
|
|
if(rotation_screentip)
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
return NONE
|