[MIRROR] Climbable Element (#11096)

Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-06-21 22:38:18 +02:00
committed by GitHub
co-authored by Will Kashargul
parent 573e286496
commit eaca591b85
75 changed files with 486 additions and 493 deletions
+4
View File
@@ -13,6 +13,10 @@
//max_integrity = 60
var/obj/item/canvas/painting = null
/obj/structure/easel/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
//Adding canvases
/obj/structure/easel/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/canvas))
+4 -16
View File
@@ -19,6 +19,7 @@ When mapping these in, be sure to give at least a one tile clearance, as NORTH f
two tiles on initialization, and which way a cliff is facing may change during maploading.
*/
#define CLIFF_CLIMB_DELAY 10
/obj/structure/cliff
name = "cliff"
desc = "A steep rock ledge. You might be able to climb it if you feel bold enough."
@@ -31,8 +32,6 @@ two tiles on initialization, and which way a cliff is facing may change during m
anchored = TRUE
density = TRUE
opacity = FALSE
climbable = TRUE
climb_delay = 10 SECONDS
unacidable = TRUE
block_turf_edges = TRUE // Don't want turf edges popping up from the cliff edge.
plane = TURF_PLANE
@@ -48,6 +47,7 @@ two tiles on initialization, and which way a cliff is facing may change during m
/obj/structure/cliff/Initialize(mapload)
. = ..()
register_dangerous_to_step()
AddElement(/datum/element/climbable/cliff,CLIFF_CLIMB_DELAY SECONDS)
/obj/structure/cliff/Destroy()
unregister_dangerous_to_step()
@@ -106,11 +106,8 @@ two tiles on initialization, and which way a cliff is facing may change during m
// Now make the bottom cliff have mostly the same variables.
var/obj/structure/cliff/bottom/bottom = new(T)
is_double_cliff = TRUE
climb_delay /= 2 // Since there are two cliffs to climb when going north, both take half the time.
bottom.dir = dir
bottom.is_double_cliff = TRUE
bottom.climb_delay = climb_delay
bottom.icon_variant = icon_variant
bottom.corner = corner
bottom.ramp = ramp
@@ -254,19 +251,10 @@ two tiles on initialization, and which way a cliff is facing may change during m
sleep(5)
bottom_cliff.fall_off_cliff(L)
/obj/structure/cliff/can_climb(mob/living/user, post_climb_check = FALSE)
// Cliff climbing requires climbing gear.
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/clothing/shoes/shoes = H.shoes
if(shoes && shoes.rock_climbing)
return ..() // Do the other checks too.
to_chat(user, span_warning("\The [src] is too steep to climb unassisted."))
return FALSE
// This tells AI mobs to not be dumb and step off cliffs willingly.
/obj/structure/cliff/is_safe_to_step(mob/living/L)
if(should_fall(L))
return FALSE
return ..()
#undef CLIFF_CLIMB_DELAY
@@ -359,6 +359,9 @@
if(!isturf(user.loc)) // are you in a container/closet/pod/etc?
return
if(!opened)
// Attempt to climb if not opened!
if(O == user)
SEND_SIGNAL(src, COMSIG_CLIMBABLE_START_CLIMB, user)
return
if(istype(O, /obj/structure/closet))
return
@@ -1,3 +1,7 @@
/obj/structure/closet/secure_closet/freezer/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/closet/secure_closet/freezer/kitchen
name = "kitchen cabinet"
req_access = list(access_kitchen)
@@ -5,7 +5,6 @@
desc = "A rectangular steel crate."
icon = 'icons/obj/closets/bases/crate.dmi'
closet_appearance = /decl/closet_appearance/crate
climbable = TRUE
dir = 4 //Spawn facing 'forward' by default.
var/points_per_crate = 5
var/rigged = 0
@@ -13,6 +12,10 @@
open_sound = 'sound/effects/crate_open.ogg'
close_sound = 'sound/effects/crate_close.ogg'
/obj/structure/closet/crate/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/closet/crate/can_open()
return 1
@@ -40,8 +43,7 @@
O.forceMove(get_turf(src))
src.opened = 1
if(climbable)
structure_shaken()
SEND_SIGNAL(src, COMSIG_CLIMBABLE_SHAKE_CLIMBERS, null)
update_icon()
return 1
@@ -69,14 +71,6 @@
update_icon()
return 1
/obj/structure/closet/crate/MouseDrop_T(mob/target, mob/user)
// Adds climbing from drag, You can't put yourself in crates with a drag anyway... Nore anyone else actually.
var/mob/living/H = user
if(istype(H) && can_climb(H) && target == user)
do_climb(target)
else
return ..()
/obj/structure/closet/crate/verb/rotate_clockwise()
set name = "Rotate Crate Clockwise"
set category = "Object"
+2 -2
View File
@@ -102,11 +102,11 @@
if(MEDIUM_HOLE)
visible_message(span_notice("\The [user] cuts into \the [src] some more."))
to_chat(user, span_notice("You could probably fit yourself through that hole now. Although climbing through would be much faster if you made it even bigger."))
climbable = TRUE
AddElement(/datum/element/climbable)
if(LARGE_HOLE)
visible_message(span_notice("\The [user] completely cuts through \the [src]."))
to_chat(user, span_notice("The hole in \the [src] is now big enough to walk through."))
climbable = FALSE
RemoveElement(/datum/element/climbable)
update_cut_status()
return TRUE
+4 -34
View File
@@ -5,11 +5,14 @@
icon_state = "ropes"
density = TRUE
throwpass = TRUE
climbable = TRUE
layer = WINDOW_LAYER
anchored = TRUE
flags = ON_BORDER
/obj/structure/fitness/boxing_ropes/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable, vaulting = TRUE)
/obj/structure/fitness/boxing_ropes/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && mover.checkpass(PASSTABLE))
return TRUE
@@ -23,39 +26,6 @@
if(get_dir(mover, target) == dir) // From here to elsewhere, can't move in our dir
return !density
return TRUE
/obj/structure/fitness/boxing_ropes/do_climb(var/mob/living/user) //Sets it so that players can climb *over* the turf and will enter the the turf **this** turf is facing.
if(!can_climb(user))
return
user.visible_message(span_warning("[user] starts climbing onto \the [src]!"))
LAZYDISTINCTADD(climbers, user)
if(!do_after(user,(issmall(user) ? 20 : 34)))
LAZYREMOVE(climbers, user)
return
if(!can_climb(user, post_climb_check=1))
LAZYREMOVE(climbers, user)
return
if(get_turf(user) == get_turf(src))
user.forceMove(get_step(src, src.dir))
else
user.forceMove(get_turf(src))
user.visible_message(span_warning("[user] climbed over \the [src]!"))
LAZYREMOVE(climbers, user)
/obj/structure/fitness/boxing_ropes/can_climb(var/mob/living/user, post_climb_check=0) //Sets it to keep people from climbing over into the next turf if it is occupied.
if(!..())
return 0
if(get_turf(user) == get_turf(src))
var/obj/occupied = neighbor_turf_impassable()
if(occupied)
to_chat(user, span_danger("You can't climb there, there's \a [occupied] in the way."))
return 0
return 1
/obj/structure/fitness/boxing_ropes/bottom
plane = MOB_PLANE
+1 -1
View File
@@ -6,7 +6,6 @@
density = TRUE
anchored = TRUE
throwpass = 1
climbable = TRUE
layer = ABOVE_JUNK_LAYER
@@ -27,6 +26,7 @@
if(!material)
return INITIALIZE_HINT_QDEL
color = material.icon_colour
AddElement(/datum/element/climbable)
/obj/structure/gravemarker/examine(mob/user)
. = ..()
+4 -1
View File
@@ -9,7 +9,6 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
anchored = FALSE
density = TRUE
flags = OPENCONTAINER
climbable = TRUE
//copypaste sorry
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
var/obj/item/storage/bag/trash/mybag = null
@@ -24,6 +23,10 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
var/static/list/equippable_item_whitelist
/obj/structure/janitorialcart/Initialize(mapload, ...)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/janitorialcart/proc/equip_janicart_item(mob/user, obj/item/I)
if(!equippable_item_whitelist)
equippable_item_whitelist = typecacheof(list(
+8 -36
View File
@@ -4,13 +4,16 @@
icon = 'icons/obj/ledges.dmi'
density = TRUE
throwpass = 1
climbable = TRUE
anchored = TRUE
var/solidledge = 1
flags = ON_BORDER
layer = STAIRS_LAYER
icon_state = "ledge"
/obj/structure/ledge/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable, vaulting = TRUE)
/obj/structure/ledge_corner
icon_state = "ledge-corner"
flags = 0
@@ -19,10 +22,13 @@
icon = 'icons/obj/ledges.dmi'
density = TRUE
throwpass = 1
climbable = TRUE
anchored = TRUE
layer = STAIRS_LAYER
/obj/structure/ledge_corner/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable, vaulting = TRUE)
/obj/structure/ledge/ledge_nub
desc = "Part of a rocky ledge."
icon_state = "ledge-nub"
@@ -49,37 +55,3 @@
if(solidledge && get_dir(mover, target) == dir) // From here to elsewhere, can't move in our dir
return FALSE
return TRUE
/obj/structure/ledge/do_climb(var/mob/living/user)
if(!can_climb(user))
return
user.visible_message(span_warning("[user] starts climbing onto \the [src]!"))
LAZYDISTINCTADD(climbers, user)
if(!do_after(user,(issmall(user) ? 20 : 34)))
LAZYREMOVE(climbers, user)
return
if(!can_climb(user, post_climb_check=1))
LAZYREMOVE(climbers, user)
return
if(get_turf(user) == get_turf(src))
user.forceMove(get_step(src, src.dir))
else
user.forceMove(get_turf(src))
user.visible_message(span_warning("[user] climbed over \the [src]!"))
LAZYREMOVE(climbers, user)
/obj/structure/ledge/can_climb(var/mob/living/user, post_climb_check=0)
if(!..())
return 0
if(get_turf(user) == get_turf(src))
var/obj/occupied = neighbor_turf_impassable()
if(occupied)
to_chat(user, span_danger("You can't climb there, there's \a [occupied] in the way."))
return 0
return 1
+4 -4
View File
@@ -11,7 +11,6 @@
//atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE | ATOM_FLAG_CAN_BE_PAINTED | ATOM_FLAG_ADJACENT_EXCEPTION
anchored = TRUE
density = TRUE
climbable = TRUE
throwpass = 1
layer = TABLE_LAYER
@@ -43,6 +42,8 @@
health = material.integrity
AddElement(/datum/element/climbable)
return INITIALIZE_HINT_LATELOAD
/obj/structure/low_wall/LateInitialize()
@@ -123,9 +124,8 @@
/obj/structure/low_wall/MouseDrop_T(atom/movable/AM, mob/user, src_location, over_location, src_control, over_control, params)
if(AM == user)
var/mob/living/H = user
if(istype(H) && can_climb(H))
do_climb(AM)
SEND_SIGNAL(src, COMSIG_CLIMBABLE_START_CLIMB, user)
return
var/obj/O = AM
if(!istype(O))
return
+1 -1
View File
@@ -4,7 +4,6 @@
icon = 'icons/obj/janitor.dmi'
icon_state = "mopbucket"
density = TRUE
climbable = TRUE
w_class = ITEMSIZE_NORMAL
pressure_resistance = 5
flags = OPENCONTAINER
@@ -15,6 +14,7 @@ GLOBAL_LIST_BOILERPLATE(all_mopbuckets, /obj/structure/mopbucket)
/obj/structure/mopbucket/Initialize(mapload, ...)
create_reagents(300)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/mopbucket/examine(mob/user)
. = ..()
+3 -60
View File
@@ -5,7 +5,6 @@
icon = 'icons/obj/railing.dmi'
density = TRUE
throwpass = 1
climbable = TRUE
layer = WINDOW_LAYER
anchored = TRUE
flags = ON_BORDER
@@ -27,11 +26,7 @@
// TODO - "constructed" is not passed to us. We need to find a way to do this safely.
if (constructed) // player-constructed railings
anchored = FALSE
if(climbable)
verbs += /obj/structure/proc/climb_on
/obj/structure/railing/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable/unanchored_can_break, 3.4 SECONDS, TRUE) // It's a RAILING!
if(src.anchored)
update_icon(0)
@@ -190,7 +185,7 @@
to_chat(usr, "It is fastened to the floor therefore you can't flip it!")
return 0
var/obj/occupied = neighbor_turf_impassable()
var/obj/occupied = can_climb_neighbor_turf(src)
if(occupied)
to_chat(usr, "You can't flip \the [src] because there's \a [occupied] in the way.")
return 0
@@ -235,7 +230,7 @@
var/obj/item/grab/G = W
if (isliving(G.affecting))
var/mob/living/M = G.affecting
var/obj/occupied = turf_is_crowded()
var/obj/occupied = can_climb_turf(src)
if(occupied)
to_chat(user, span_danger("There's \a [occupied] in the way."))
return
@@ -278,55 +273,3 @@
qdel(src)
return
return
// Duplicated from structures.dm, but its a bit different.
/obj/structure/railing/do_climb(var/mob/living/user)
if(!can_climb(user))
return
user.visible_message(span_warning("[user] starts climbing onto \the [src]!"))
LAZYDISTINCTADD(climbers, user)
if(!do_after(user,(issmall(user) ? 20 : 34)))
LAZYREMOVE(climbers, user)
return
if(!can_climb(user, post_climb_check=1))
LAZYREMOVE(climbers, user)
return
if(get_turf(user) == get_turf(src))
user.forceMove(get_step(src, src.dir))
else
user.forceMove(get_turf(src))
user.visible_message(span_warning("[user] climbed over \the [src]!"))
if(!anchored) take_damage(maxhealth) // Fatboy
LAZYREMOVE(climbers, user)
/obj/structure/railing/can_climb(var/mob/living/user, post_climb_check=0)
if(!..())
return 0
// Normal can_climb() handles climbing from adjacent turf onto our turf. But railings also allow climbing
// from our turf onto an adjacent! If that is the case we need to do checks for that too...
if(get_turf(user) == get_turf(src))
var/obj/occupied = neighbor_turf_impassable()
if(occupied)
to_chat(user, span_danger("You can't climb there, there's \a [occupied] in the way."))
return 0
return 1
// TODO - This here might require some investigation
/obj/structure/proc/neighbor_turf_impassable()
var/turf/T = get_step(src, src.dir)
if(!T || !istype(T))
return 0
if(T.density == 1)
return T
for(var/obj/O in T.contents)
if(istype(O,/obj/structure))
var/obj/structure/S = O
if(S.climbable) continue
if(O && O.density && !(O.flags & ON_BORDER && !(turn(O.dir, 180) & dir)))
return O
@@ -45,6 +45,7 @@
"trashbag",
"brokecomp")
mouse_nest = new(src)
AddElement(/datum/element/climbable)
/obj/structure/trash_pile/Destroy()
qdel(mouse_nest)
@@ -5,6 +5,10 @@
icon_state = "wardrobe"
density = TRUE
/obj/structure/undies_wardrobe/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
/obj/structure/undies_wardrobe/attack_hand(var/mob/user)
if(!human_who_can_use_underwear(user))
to_chat(user, span_warning("Sadly there's nothing in here for you to wear."))