mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 04:30:44 +01:00
## About The Pull Request 50 files, plus additonal file that was necessary because I slightly refactored windoor construction. This ended up like three and a half times larger than most of the other ones, I really wasn't meaning for that to happen. Maybe its because I more vigorously enforced the empty line after every return thing. The only way to find out is to read 1700 lines of changes, and I don't feel like doing that again. I pinky promise it all works, and I've tested every item changed individually. Changes beyond conversion: You can't welder down reinforced falsewalls anymore, pretty sure it was an oversight because they're supposed to be taken down by wirecutters You can right click to close gun lockers with an empty hand, because otherwise you can't close the lockers at all if there's a gun in them Meatspikes no longer runtime on construction due to the old trick of balloon alert + qdel Windoor assembly no longer SUCKS DICK!!, it's no longer storing essentially a boolean in an undocumented number in a string, it no longer requires a VERB to flip its direction. on a related note, the creator of the windoor assembly construction steps has been sent to live on a farm far out in the country Also, a quick note about how these prs are gonna fuck everything up until they're all together. There's a lot more places where `attackby()` is directly called than I would have assumed, and given as those are being changed to call `item_interaction()` potentially(usually) in a different pr than the pr in which that atom's `attackby()` is actually converted, that function's not going to work at all until both are merged. The good news is that almost every instance this is happening, it's pure convenience, where the user would have access to both items anyway and could just manually call the attack chain by clicking them together. Instances where this is not the case are being skipped over until they can be packaged together to avoid the issue, but I'm not bothering to do this on ones where the desync won't make an interaction actually unusable, because that would require me to turn a 1700 line pr into a 3500 line pr and I really was aiming for like 500 ## Why It's Good For The Game Ignore the paragraph about how I expect this to create a hostage situation where the only fix to the bugs I make is to merge my other prs, and instead think about how cool swing combat would be and how much you want it ## Changelog 🆑 fix: you now can only use a wirecutter to take down a reinforced falsewall fix: meatspikes no longer runtime on construction fix: you no longer have to use a verb that you can't use to flip windoor assemblies qol: you can right click a gun locker to close it code: 50 files have been moved from attackby() to item_interaction() /🆑
482 lines
16 KiB
Plaintext
482 lines
16 KiB
Plaintext
#define STAIR_TERMINATOR_AUTOMATIC 0
|
|
#define STAIR_TERMINATOR_NO 1
|
|
#define STAIR_TERMINATOR_YES 2
|
|
|
|
/// Range within which stair indicators will appear for approaching mobs
|
|
#define STAIR_INDICATOR_RANGE 3
|
|
/// Minimum tile spacing between stair minimap blips
|
|
#define STAIR_BLIP_MIN_DISTANCE 2
|
|
|
|
// dir determines the direction of travel to go upwards
|
|
// stairs require /turf/open/openspace as the tile above them to work, unless your stairs have 'force_open_above' set to TRUE
|
|
// multiple stair objects can be chained together; the Z level transition will happen on the final stair object in the chain
|
|
|
|
/obj/structure/stairs
|
|
name = "stairs"
|
|
icon = 'icons/obj/stairs.dmi'
|
|
icon_state = "stairs"
|
|
base_icon_state = "stairs"
|
|
anchored = TRUE
|
|
move_resist = INFINITY
|
|
plane = FLOOR_PLANE
|
|
layer = ABOVE_OPEN_TURF_LAYER
|
|
|
|
/// If TRUE replaces the turf above this stair obj with /turf/open/openspace
|
|
var/force_open_above = FALSE
|
|
/// Determines if this stair is the last in a "chain" of stairs, ie next step is upstairs
|
|
VAR_FINAL/terminator_mode = STAIR_TERMINATOR_AUTOMATIC
|
|
/// Upstairs turf. Is observed for changes if force_open_above is TRUE (to re-open if necessary)
|
|
VAR_FINAL/turf/directly_above
|
|
/// If TRUE, we have left/middle/right sprites.
|
|
var/has_merged_sprites = TRUE
|
|
/// Current atoms used as this stair's minimap blip targets.
|
|
var/list/minimap_blip_targets
|
|
/// Lazyassoc list of weakef to mob viewing stair indicators to their images
|
|
VAR_PRIVATE/list/mob_to_image
|
|
|
|
/obj/structure/stairs/north
|
|
dir = NORTH
|
|
|
|
/obj/structure/stairs/south
|
|
dir = SOUTH
|
|
|
|
/obj/structure/stairs/east
|
|
dir = EAST
|
|
|
|
/obj/structure/stairs/west
|
|
dir = WEST
|
|
|
|
/obj/structure/stairs/wood
|
|
icon_state = "stairs_wood"
|
|
has_merged_sprites = FALSE
|
|
|
|
/obj/structure/stairs/stone
|
|
icon_state = "stairs_stone"
|
|
has_merged_sprites = FALSE
|
|
|
|
/obj/structure/stairs/material
|
|
icon_state = "stairs_material"
|
|
material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
|
has_merged_sprites = FALSE
|
|
|
|
/obj/structure/stairs/Initialize(mapload)
|
|
. = ..()
|
|
|
|
GLOB.stairs += src
|
|
if(force_open_above)
|
|
force_open_above()
|
|
build_signal_listener()
|
|
update_surrounding()
|
|
update_minimap_blip()
|
|
|
|
var/static/list/exit_connections = list(
|
|
COMSIG_ATOM_EXIT = PROC_REF(on_exit_stairs),
|
|
)
|
|
|
|
AddElement(/datum/element/connect_loc, exit_connections)
|
|
|
|
var/static/list/range_connections = list(
|
|
COMSIG_ATOM_ENTERED = PROC_REF(on_enter_range),
|
|
COMSIG_ATOM_EXITED = PROC_REF(on_exit_range),
|
|
)
|
|
AddComponent(/datum/component/connect_range, tracked = src, connections = range_connections, range = STAIR_INDICATOR_RANGE)
|
|
|
|
|
|
/obj/structure/stairs/Destroy()
|
|
clear_minimap_blips()
|
|
if(directly_above)
|
|
UnregisterSignal(directly_above, COMSIG_TURF_MULTIZ_NEW)
|
|
directly_above = null
|
|
for(var/climber_ref in mob_to_image)
|
|
clear_climber_image(climber_ref, instant = TRUE)
|
|
GLOB.stairs -= src
|
|
return ..()
|
|
|
|
/obj/structure/stairs/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change) //Look this should never happen but...
|
|
. = ..()
|
|
if(force_open_above)
|
|
build_signal_listener()
|
|
update_surrounding()
|
|
|
|
/// Updates the sprite and the sprites of neighboring stairs to reflect merged sprites
|
|
/obj/structure/stairs/proc/update_surrounding()
|
|
if(!has_merged_sprites)
|
|
return
|
|
|
|
update_appearance()
|
|
|
|
for(var/obj/structure/stairs/stair in get_step(src, turn(dir, 90)))
|
|
stair.update_appearance()
|
|
|
|
for(var/obj/structure/stairs/stair in get_step(src, turn(dir, -90)))
|
|
stair.update_appearance()
|
|
update_minimap_blip()
|
|
|
|
/obj/structure/stairs/proc/update_minimap_blip()
|
|
var/bottom_state = isTerminator() ? "stairs_up" : "stairs_down"
|
|
var/top_state = (bottom_state == "stairs_up") ? "stairs_down" : "stairs_up"
|
|
var/turf/current_turf = get_turf(src)
|
|
|
|
clear_minimap_blips()
|
|
if(isnull(current_turf))
|
|
return
|
|
|
|
add_minimap_blip_if_valid(current_turf, bottom_state)
|
|
add_minimap_blip_if_valid(get_step_multiz(current_turf, UP), top_state)
|
|
|
|
/obj/structure/stairs/proc/clear_minimap_blips()
|
|
if(!islist(minimap_blip_targets))
|
|
return
|
|
for(var/atom/target as anything in minimap_blip_targets)
|
|
remove_minimap_blip(MINIMAP_STAIR_BLIP, target)
|
|
LAZYCLEARLIST(minimap_blip_targets)
|
|
|
|
/obj/structure/stairs/proc/add_minimap_blip_if_valid(atom/target, state)
|
|
if(isnull(target))
|
|
return
|
|
if(!should_place_minimap_blip(target))
|
|
return
|
|
|
|
var/atom/movable/screen/minimap_element/blip/blip = get_minimap_blip(MINIMAP_STAIR_BLIP, target)
|
|
if(!isnull(blip))
|
|
blip.icon_state = state
|
|
else
|
|
add_minimap_blip(target, MINIMAP_STAIR_BLIP, state)
|
|
LAZYADD(minimap_blip_targets, target)
|
|
|
|
/obj/structure/stairs/proc/should_place_minimap_blip(atom/target)
|
|
var/turf/target_turf = get_turf(target)
|
|
if(isnull(target_turf))
|
|
return FALSE
|
|
if(length(get_minimap_blips_in_area(MINIMAP_STAIR_BLIP, target_turf, STAIR_BLIP_MIN_DISTANCE)))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/structure/stairs/update_icon_state()
|
|
. = ..()
|
|
if(!has_merged_sprites)
|
|
return
|
|
|
|
var/has_left_stairs = FALSE
|
|
var/has_right_stairs = FALSE
|
|
for(var/obj/structure/stairs/stair in get_step(src, turn(dir, 90)))
|
|
if(stair.dir == dir)
|
|
has_left_stairs = TRUE
|
|
break
|
|
|
|
for(var/obj/structure/stairs/stair in get_step(src, turn(dir, -90)))
|
|
if(stair.dir == dir)
|
|
has_right_stairs = TRUE
|
|
break
|
|
|
|
if(has_left_stairs && has_right_stairs)
|
|
icon_state = "[base_icon_state]-m"
|
|
else if(has_left_stairs)
|
|
icon_state = "[base_icon_state]-r"
|
|
else if(has_right_stairs)
|
|
icon_state = "[base_icon_state]-l"
|
|
else
|
|
icon_state = base_icon_state
|
|
|
|
/obj/structure/stairs/proc/on_exit_stairs(datum/source, atom/movable/leaving, direction)
|
|
SIGNAL_HANDLER
|
|
|
|
if(leaving == src)
|
|
return //Let's not block ourselves.
|
|
|
|
if(!isobserver(leaving) && isTerminator() && 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
|
|
|
|
#define POINT_X_COMPONENT(pdir) ((pdir & EAST) ? 2 : ((pdir & WEST) ? -2 : 0))
|
|
#define POINT_Y_COMPONENT(pdir) ((pdir & SOUTH) ? 2 : ((pdir & NORTH) ? -2 : 0))
|
|
|
|
/obj/structure/stairs/proc/on_enter_range(datum/source, atom/movable/entered)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!isliving(entered))
|
|
return
|
|
|
|
var/mob/living/climber = entered
|
|
var/datum/weakref/climber_ref = WEAKREF(climber)
|
|
if(!climber.client || !climber.client.prefs.read_preference(/datum/preference/toggle/stair_indicator))
|
|
return
|
|
if(climber.dir == REVERSE_DIR(dir))
|
|
return // walking away
|
|
if(LAZYACCESS(mob_to_image, climber_ref))
|
|
return // already see it
|
|
if(!(climber in viewers(STAIR_INDICATOR_RANGE + 1, src)))
|
|
return // can't see the staircase (+1 tile for some leeway)
|
|
if(!isopenturf(get_step_multiz(src, UP)))
|
|
return // no place to go up to
|
|
|
|
var/image/pointing_image = get_pointing_image()
|
|
climber.client.images += pointing_image
|
|
pointing_image.alpha = 0
|
|
animate(pointing_image, pixel_x = POINT_X_COMPONENT(dir), pixel_y = POINT_Y_COMPONENT(dir), time = 0.5 SECONDS, easing = SINE_EASING|EASE_OUT, loop = -1, tag = "point_xy")
|
|
animate(pixel_x = 0, pixel_y = 0, time = 0.5 SECONDS, easing = SINE_EASING|EASE_IN)
|
|
animate(pointing_image, alpha = 180, time = 0.75 SECONDS, tag = "point_fadein")
|
|
LAZYSET(mob_to_image, climber_ref, pointing_image)
|
|
|
|
/obj/structure/stairs/proc/on_exit_range(datum/source, atom/movable/exited)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!isliving(exited))
|
|
return
|
|
|
|
var/datum/weakref/climber_ref = WEAKREF(exited)
|
|
if(!LAZYACCESS(mob_to_image, climber_ref))
|
|
return // not seeing anything
|
|
if(exited in viewers(STAIR_INDICATOR_RANGE, src))
|
|
return // still in range and can see the staircase
|
|
|
|
clear_climber_image(climber_ref)
|
|
|
|
/obj/structure/stairs/proc/clear_climber_image(datum/weakref/climber_ref, instant = FALSE)
|
|
var/image/pointing_image = LAZYACCESS(mob_to_image, climber_ref)
|
|
if(!pointing_image)
|
|
LAZYREMOVE(mob_to_image, climber_ref) // just in case
|
|
return
|
|
if(instant)
|
|
clear_climber_image_callback(climber_ref, pointing_image)
|
|
return
|
|
|
|
animate(pointing_image, alpha = 0, time = 0.75 SECONDS, tag = "point_fadeout")
|
|
// note: the player won't see a new indicator until the image is fully a removed, so this timer also serves as a cooldown
|
|
addtimer(CALLBACK(src, PROC_REF(clear_climber_image_callback), climber_ref, pointing_image), 1.5 SECONDS, TIMER_UNIQUE)
|
|
|
|
/obj/structure/stairs/proc/clear_climber_image_callback(datum/weakref/climber_ref, image/pointing_image)
|
|
PRIVATE_PROC(TRUE)
|
|
var/mob/living/climber = climber_ref?.resolve()
|
|
climber?.client?.images -= pointing_image
|
|
LAZYREMOVE(mob_to_image, climber_ref)
|
|
|
|
/obj/structure/stairs/proc/get_pointing_image()
|
|
PROTECTED_PROC(TRUE)
|
|
var/image/point_image = image('icons/hud/screen_gen.dmi', src, "arrow_large_white_still")
|
|
point_image.color = COLOR_DARK_MODERATE_LIME_GREEN
|
|
point_image.appearance_flags |= KEEP_APART
|
|
point_image.transform = matrix().Turn(dir2angle(REVERSE_DIR(dir)))
|
|
point_image.layer = BELOW_MOB_LAYER
|
|
SET_PLANE(point_image, GAME_PLANE, src)
|
|
return point_image
|
|
|
|
#undef POINT_X_COMPONENT
|
|
#undef POINT_Y_COMPONENT
|
|
|
|
/obj/structure/stairs/Cross(atom/movable/AM)
|
|
if(isTerminator() && (get_dir(src, AM) == dir))
|
|
return FALSE
|
|
return ..()
|
|
|
|
/obj/structure/stairs/proc/stair_ascend(atom/movable/climber)
|
|
var/turf/checking = get_step_multiz(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(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/stairs/vv_edit_var(var_name, var_value)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
if(var_name != NAMEOF(src, force_open_above))
|
|
return
|
|
if(!var_value)
|
|
if(directly_above)
|
|
UnregisterSignal(directly_above, COMSIG_TURF_MULTIZ_NEW)
|
|
directly_above = null
|
|
else
|
|
build_signal_listener()
|
|
force_open_above()
|
|
|
|
/obj/structure/stairs/proc/build_signal_listener()
|
|
if(directly_above)
|
|
UnregisterSignal(directly_above, COMSIG_TURF_MULTIZ_NEW)
|
|
var/turf/open/openspace/T = get_step_multiz(src, UP)
|
|
RegisterSignal(T, COMSIG_TURF_MULTIZ_NEW, PROC_REF(on_multiz_new))
|
|
directly_above = T
|
|
|
|
/obj/structure/stairs/proc/force_open_above()
|
|
var/turf/open/openspace/T = get_step_multiz(src, UP)
|
|
if(T && !istype(T))
|
|
T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
|
|
|
|
/obj/structure/stairs/proc/on_multiz_new(turf/source, dir)
|
|
SIGNAL_HANDLER
|
|
|
|
if(dir == UP)
|
|
var/turf/open/openspace/T = get_step_multiz(src, UP)
|
|
if(T && !istype(T))
|
|
T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
|
|
|
|
/obj/structure/stairs/intercept_zImpact(list/falling_movables, levels = 1)
|
|
. = ..()
|
|
// falling from a higher z level onto stairs
|
|
if(levels != 1 || !isTerminator())
|
|
return
|
|
for(var/mob/living/guy in falling_movables)
|
|
if(!can_fall_down_stairs(guy))
|
|
continue
|
|
to_chat(guy, span_warning("You fall down [src]!"))
|
|
on_fall(guy)
|
|
. |= FALL_INTERCEPTED | FALL_NO_MESSAGE | FALL_RETAIN_PULL
|
|
|
|
/// Will the passed mob tumble down the stairs instead of walking?
|
|
/obj/structure/stairs/proc/can_fall_down_stairs(mob/living/falling)
|
|
if(falling.buckled || falling.pulledby)
|
|
return FALSE
|
|
if(falling.stat >= UNCONSCIOUS) // if you shove someone unconscious down the stairs, they'd probably roll
|
|
return TRUE
|
|
if(falling.has_status_effect(/datum/status_effect/staggered)) // off balance
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/// What happens when a mob tumbles down the stairs
|
|
/obj/structure/stairs/proc/on_fall(mob/living/falling)
|
|
falling.AdjustParalyzed(2 SECONDS)
|
|
falling.adjust_staggered(2 SECONDS)
|
|
falling.AdjustKnockdown(5 SECONDS)
|
|
falling.spin(1 SECONDS, 0.25 SECONDS)
|
|
falling.apply_damage(rand(4, 8), BRUTE, spread_damage = TRUE)
|
|
GLOB.move_manager.move_towards(falling, get_ranged_target_turf(src, REVERSE_DIR(dir), 2), delay = 0.4 SECONDS, timeout = 1 SECONDS)
|
|
|
|
/obj/structure/stairs/proc/isTerminator() //If this is the last stair in a chain and should move mobs up
|
|
if(terminator_mode != STAIR_TERMINATOR_AUTOMATIC)
|
|
return (terminator_mode == STAIR_TERMINATOR_YES)
|
|
var/turf/T = get_turf(src)
|
|
if(!T)
|
|
return FALSE
|
|
var/turf/them = get_step(T, dir)
|
|
if(!them)
|
|
return FALSE
|
|
for(var/obj/structure/stairs/S in them)
|
|
if(S.dir == dir)
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/structure/stairs_frame
|
|
name = "stairs frame"
|
|
desc = "Everything you need to call something a staircase, aside from the stuff you actually step on."
|
|
icon = 'icons/obj/stairs.dmi'
|
|
icon_state = "stairs_frame"
|
|
density = FALSE
|
|
anchored = FALSE
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 5)
|
|
/// What type of stack will this drop on deconstruction?
|
|
var/frame_stack = /obj/item/stack/rods
|
|
/// How much of frame_stack should this drop on deconstruction?
|
|
var/frame_stack_amount = 10
|
|
|
|
/obj/structure/stairs_frame/wood
|
|
name = "wooden stairs frame"
|
|
desc = "Everything you need to build a staircase, minus the actual stairs. This one is made of wood."
|
|
frame_stack = /obj/item/stack/sheet/mineral/wood
|
|
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 10)
|
|
|
|
/obj/structure/stairs_frame/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/simple_rotation)
|
|
|
|
/obj/structure/stairs_frame/examine(mob/living/carbon/human/user)
|
|
. = ..()
|
|
if(anchored)
|
|
. += span_notice("The frame is anchored and can be made into proper stairs with 10 sheets of material.")
|
|
else
|
|
. += span_notice("The frame will need to be secured with a wrench before it can be completed.")
|
|
|
|
/obj/structure/stairs_frame/wrench_act(mob/living/user, obj/item/used_tool)
|
|
user.balloon_alert_to_viewers("securing stairs frame", "securing frame")
|
|
used_tool.play_tool_sound(src)
|
|
if(!used_tool.use_tool(src, user, 3 SECONDS))
|
|
return TRUE
|
|
if(anchored)
|
|
anchored = FALSE
|
|
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
return TRUE
|
|
anchored = TRUE
|
|
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
return TRUE
|
|
|
|
/obj/structure/stairs_frame/wrench_act_secondary(mob/living/user, obj/item/used_tool)
|
|
to_chat(user, span_notice("You start disassembling [src]..."))
|
|
used_tool.play_tool_sound(src)
|
|
if(!used_tool.use_tool(src, user, 3 SECONDS))
|
|
return TRUE
|
|
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
deconstruct(TRUE)
|
|
return TRUE
|
|
|
|
/obj/structure/stairs_frame/atom_deconstruct(disassembled = TRUE)
|
|
new frame_stack(get_turf(src), frame_stack_amount)
|
|
|
|
/obj/structure/stairs_frame/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
|
if(!isstack(tool))
|
|
return NONE
|
|
if(!anchored)
|
|
user.balloon_alert(user, "secure the frame first!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/obj/item/stack/material = tool
|
|
if(material.stairs_type)
|
|
if(material.get_amount() < 10)
|
|
to_chat(user, span_warning("You need ten [material.name] sheets to do this!"))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if(locate(/obj/structure/stairs) in loc)
|
|
to_chat(user, span_warning("There's already stairs built here!"))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
to_chat(user, span_notice("You start adding [material] to [src]..."))
|
|
if(!do_after(user, 10 SECONDS, target = src) || !material.use(10) || (locate(/obj/structure/table) in loc))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
make_new_stairs(material.stairs_type)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
if(istype(material, /obj/item/stack/sheet))
|
|
if(material.get_amount() < 10)
|
|
to_chat(user, span_warning("You need ten sheets to do this!"))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if(locate(/obj/structure/stairs) in loc)
|
|
to_chat(user, span_warning("There's already stairs built here!"))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
to_chat(user, span_notice("You start adding [material] to [src]..."))
|
|
if(!do_after(user, 10 SECONDS, target = src) || !material.use(10) || (locate(/obj/structure/table) in loc))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/list/material_list = list()
|
|
if(material.material_type)
|
|
material_list[material.material_type] = SHEET_MATERIAL_AMOUNT * 10
|
|
make_new_stairs(/obj/structure/stairs/material, material_list)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
return NONE
|
|
|
|
/obj/structure/stairs_frame/proc/make_new_stairs(stairs_type, custom_materials)
|
|
var/obj/structure/stairs/new_stairs = new stairs_type(loc)
|
|
new_stairs.setDir(dir)
|
|
if(custom_materials)
|
|
new_stairs.set_custom_materials(custom_materials)
|
|
qdel(src)
|
|
|
|
#undef STAIR_TERMINATOR_AUTOMATIC
|
|
#undef STAIR_TERMINATOR_NO
|
|
#undef STAIR_TERMINATOR_YES
|
|
|
|
#undef STAIR_INDICATOR_RANGE
|
|
#undef STAIR_BLIP_MIN_DISTANCE
|