Skip to content

Commit

Permalink
Adds multitile stairs in wallening style, makes window frames walkabl…
Browse files Browse the repository at this point in the history
…e when you climb onto them
  • Loading branch information
SmArtKar committed Aug 12, 2024
1 parent b46cec4 commit f403dc5
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@
#define COMSIG_ATOM_BLOCKS_PRESSURE (1<<0)
///From base of /datum/move_loop/process() after attempting to move a movable: (datum/move_loop/loop, old_dir)
#define COMSIG_MOVABLE_MOVED_FROM_LOOP "movable_moved_from_loop"
///From base of /atom/proc/CanAllowThrough(atom/movable/mover, border_dir): (atom/movable/mover, border_dir)
#define COMSIG_ATOM_CAN_ALLOW_THROUGH "atom_can_allow_through"
#define COMSIG_FORCE_ALLOW_THROUGH (1<<0)
3 changes: 3 additions & 0 deletions code/__DEFINES/traits/declarations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// This trait lets you attach limbs to any player without surgery.
#define TRAIT_EASY_ATTACH "easy_attach"

///Attached to objects currently on window frames, tables and such, allowing them to walk on other objects without the climbing delay
#define TRAIT_ON_CLIMBABLE "on_climbable"

///Trait given to the birthday boy
#define TRAIT_BIRTHDAY_BOY "birthday_boy"

Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/traits/_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE,
"TRAIT_CHASM_STOPPER" = TRAIT_CHASM_STOPPER,
"TRAIT_INNER_DARKNESS" = TRAIT_INNER_DARKNESS,
"TRAIT_ON_CLIMBABLE" = TRAIT_ON_CLIMBABLE,
),
/datum/controller/subsystem/economy = list(
"TRAIT_MARKET_CRASHING" = TRAIT_MARKET_CRASHING,
Expand Down
28 changes: 28 additions & 0 deletions code/datums/components/climb_walkable.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// Allows things to walk over other objects with this component
/datum/component/climb_walkable

/datum/component/climb_walkable/RegisterWithParent()
var/static/list/turf_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_enter),
COMSIG_ATOM_EXITED = PROC_REF(on_exit),
)
AddComponent(/datum/component/connect_loc_behalf, parent, turf_connections)
RegisterSignal(parent, COMSIG_ATOM_CAN_ALLOW_THROUGH, PROC_REF(can_allow_through))

/datum/component/climb_walkable/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_ATOM_CAN_ALLOW_THROUGH)
for (var/atom/movable/climber in get_turf(parent))
REMOVE_TRAIT(parent, TRAIT_ON_CLIMBABLE, REF(parent))

/datum/component/climb_walkable/proc/on_enter(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
SIGNAL_HANDLER
ADD_TRAIT(arrived, TRAIT_ON_CLIMBABLE, REF(source))

/datum/component/climb_walkable/proc/on_exit(datum/source, atom/movable/gone, direction)
SIGNAL_HANDLER
REMOVE_TRAIT(gone, TRAIT_ON_CLIMBABLE, REF(source))

/datum/component/climb_walkable/proc/can_allow_through(datum/source, atom/movable/mover, border_dir)
SIGNAL_HANDLER
if(HAS_TRAIT(mover, TRAIT_ON_CLIMBABLE))
return COMSIG_FORCE_ALLOW_THROUGH
2 changes: 2 additions & 0 deletions code/game/atom/_atom.dm
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@
return TRUE
if(mover.throwing && (pass_flags_self & LETPASSTHROW))
return TRUE
if(SEND_SIGNAL(src, COMSIG_ATOM_CAN_ALLOW_THROUGH, mover, border_dir) & COMSIG_FORCE_ALLOW_THROUGH)
return TRUE
return !density

/**
Expand Down
10 changes: 1 addition & 9 deletions code/game/objects/structures/tables_racks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
///Adds the element used to make the object climbable, and also the one that shift the mob buckled to it up.
/obj/structure/table/proc/make_climbable()
AddElement(/datum/element/climbable)
AddComponent(/datum/component/climb_walkable)
AddElement(/datum/element/elevation, pixel_shift = 12)

/obj/structure/table/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
Expand Down Expand Up @@ -149,15 +150,6 @@
/obj/structure/table/attack_tk(mob/user)
return

/obj/structure/table/CanAllowThrough(atom/movable/mover, border_dir)
. = ..()
if(.)
return
if(mover.throwing)
return TRUE
if(locate(/obj/structure/table) in get_turf(mover))
return TRUE

/obj/structure/table/CanAStarPass(to_dir, datum/can_pass_info/pass_info)
if(!density)
return TRUE
Expand Down
175 changes: 175 additions & 0 deletions code/game/objects/structures/tall_stairs.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/obj/structure/tall_stairs
name = "stairs"
icon = 'icons/obj/structures_tall.dmi'
icon_state = "stairs_start"
anchored = TRUE
move_resist = INFINITY

/// Our paired stairs, used for tracking destruction
var/obj/structure/tall_stairs/paired
/// Should we destroy our paired stairs?
var/destroy_paired = TRUE

/obj/structure/tall_stairs/Initialize(mapload)
. = ..()
AddComponent(/datum/component/climb_walkable)
locate_pair()

/obj/structure/tall_stairs/proc/locate_pair()
return

/obj/structure/tall_stairs/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
if (!isnull(paired))
paired.paired = null
paired = null
locate_pair()

/obj/structure/tall_stairs/Destroy(force)
. = ..()
if (!QDELETED(paired) && destroy_paired)
paired.destroy_paired = FALSE
QDEL_NULL(paired)

/obj/structure/tall_stairs/start
icon_state = "stairs_start"

/obj/structure/tall_stairs/start/Initialize(mapload)
. = ..()
AddElement(/datum/element/elevation, pixel_shift = 8)

/obj/structure/tall_stairs/start/locate_pair()
if (paired)
return
paired = locate(/obj/structure/tall_stairs/end) in get_step(src, dir)
if (paired)
paired.paired = src

/obj/structure/tall_stairs/end
icon_state = "stairs_end"

/obj/structure/tall_stairs/end/Initialize(mapload)
. = ..()
AddElement(/datum/element/elevation, pixel_shift = 20)
var/static/list/loc_connections = list(
COMSIG_ATOM_EXIT = PROC_REF(on_exit),
)
AddElement(/datum/element/connect_loc, loc_connections)

/obj/structure/tall_stairs/end/intercept_zImpact(list/falling_movables, levels = 1)
. = ..()
if (levels > 1)
return
for(var/mob/living/fallen_mob in falling_movables)
if (fallen_mob.get_timed_status_effect_duration(/datum/status_effect/staggered) || HAS_TRAIT(fallen_mob, TRAIT_WADDLING) && prob(5))
addtimer(CALLBACK(src, PROC_REF(flop), fallen_mob), 1)

. |= FALL_INTERCEPTED | FALL_NO_MESSAGE | FALL_RETAIN_PULL

/obj/structure/tall_stairs/end/proc/flop(mob/living/fallen_mob)
var/turf/target_turf = get_step(get_step(src, REVERSE_DIR(dir)), REVERSE_DIR(dir))
fallen_mob.throw_at(target_turf, 2, 1, spin = TRUE)
fallen_mob.visible_message(span_warning("[fallen_mob] falls down [src]!"), span_userdanger("You painfully fall down [src]!"))
fallen_mob.Knockdown(5 SECONDS)
fallen_mob.apply_damage(5, BRUTE)

/obj/structure/tall_stairs/end/proc/on_exit(datum/source, atom/movable/leaving, direction)
SIGNAL_HANDLER

if(leaving == src)
return

if(isobserver(leaving))
return

if (direction & dir)
leaving.set_currently_z_moving(CURRENTLY_Z_ASCENDING)
INVOKE_ASYNC(src, PROC_REF(stair_ascend), leaving)
leaving.Bump(src)
return COMPONENT_ATOM_BLOCK_EXIT

if (!isliving(leaving) || (!isnull(paired) && get_turf(paired) == get_step(src, direction)))
return

var/mob/living/loser = leaving
var/graceful_landing = FALSE
if(!loser.incapacitated(IGNORE_RESTRAINTS))
var/obj/item/organ/external/wings/gliders = loser.get_organ_by_type(/obj/item/organ/external/wings)
if(HAS_TRAIT(loser, TRAIT_FREERUNNING) || gliders?.can_soften_fall())
graceful_landing = HAS_TRAIT(loser, TRAIT_CATLIKE_GRACE)

if(graceful_landing)
loser.add_movespeed_modifier(/datum/movespeed_modifier/landed_on_feet)
addtimer(CALLBACK(loser, TYPE_PROC_REF(/mob, remove_movespeed_modifier), /datum/movespeed_modifier/landed_on_feet), 2 SECONDS)
new /obj/effect/temp_visual/mook_dust/small(get_step(src, direction))
else
loser.Knockdown(3 SECONDS)

loser.visible_message(span_warning("[loser] falls from [src]!"), span_warning("You fall from [src]!"))

/obj/structure/tall_stairs/end/proc/stair_ascend(atom/movable/climber)
var/turf/checking = get_step_multiz(get_turf(src), UP)
if(!istype(checking))
return
// I'm only interested in if the pass is unobstructed, not if the mob will actually make it
if(!climber.can_z_move(UP, get_turf(src), checking, z_move_flags = ZMOVE_ALLOW_BUCKLED))
return
var/turf/target = get_step_multiz(get_turf(src), (dir|UP))
if(istype(target) && !climber.can_z_move(DOWN, target, z_move_flags = ZMOVE_FALL_FLAGS)) //Don't throw them into a tile that will just dump them back down.
climber.zMove(target = target, z_move_flags = ZMOVE_STAIRS_FLAGS)
/// Moves anything that's being dragged by src or anything buckled to it to the stairs turf.
climber.pulling?.move_from_pull(climber, loc, climber.glide_size)
for(var/mob/living/buckled as anything in climber.buckled_mobs)
buckled.pulling?.move_from_pull(buckled, loc, buckled.glide_size)

/obj/structure/tall_stairs/end/locate_pair()
if (paired)
return
paired = locate(/obj/structure/tall_stairs/start) in get_step(src, REVERSE_DIR(dir))
if (paired)
paired.paired = src

/obj/structure/tall_stairs/end/CanAllowThrough(atom/movable/mover, border_dir)
if (isnull(paired) || get_turf(mover) != get_turf(paired))
return FALSE
return ..()

/obj/structure/tall_stairs/small
icon_state = "stairs_small"
destroy_paired = FALSE

/obj/structure/tall_stairs/start/north
dir = NORTH

/obj/structure/tall_stairs/start/south
dir = SOUTH

/obj/structure/tall_stairs/start/east
dir = EAST

/obj/structure/tall_stairs/start/west
dir = WEST

/obj/structure/tall_stairs/end/north
dir = NORTH

/obj/structure/tall_stairs/end/south
dir = SOUTH

/obj/structure/tall_stairs/end/east
dir = EAST

/obj/structure/tall_stairs/end/west
dir = WEST

/obj/structure/tall_stairs/small/north
dir = NORTH

/obj/structure/tall_stairs/small/south
dir = SOUTH

/obj/structure/tall_stairs/small/east
dir = EAST

/obj/structure/tall_stairs/small/west
dir = WEST
3 changes: 2 additions & 1 deletion code/game/objects/structures/window_frames.dm
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
. = ..()

update_appearance()
AddElement(/datum/element/climbable, on_try_climb_procpath = TYPE_PROC_REF(/obj/structure/window_frame/, on_try_climb))
AddComponent(/datum/component/climb_walkable)
AddElement(/datum/element/climbable, on_try_climb_procpath = TYPE_PROC_REF(/obj/structure/window_frame, on_try_climb))

if(mapload && start_with_window)
create_structure_window(window_type)
Expand Down
Binary file modified icons/obj/structures_tall.dmi
Binary file not shown.
2 changes: 2 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,7 @@
#include "code\datums\components\chuunibyou.dm"
#include "code\datums\components\cleaner.dm"
#include "code\datums\components\clickbox.dm"
#include "code\datums\components\climb_walkable.dm"
#include "code\datums\components\clothing_fov_visor.dm"
#include "code\datums\components\codeword_hearing.dm"
#include "code\datums\components\combo_attacks.dm"
Expand Down Expand Up @@ -2725,6 +2726,7 @@
#include "code\game\objects\structures\syndicate_uplink_beacon.dm"
#include "code\game\objects\structures\table_frames.dm"
#include "code\game\objects\structures\tables_racks.dm"
#include "code\game\objects\structures\tall_stairs.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
#include "code\game\objects\structures\tank_holder.dm"
#include "code\game\objects\structures\toiletbong.dm"
Expand Down

0 comments on commit f403dc5

Please sign in to comment.