diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 3e571009d27..f89aa2edc91 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -8,11 +8,21 @@
var/parts
var/list/climbers = list()
var/block_turf_edges = FALSE // If true, turf edge icons will not be made on the turf this occupies.
+
+ var/list/connections = list("0", "0", "0", "0")
+ var/list/other_connections = list("0", "0", "0", "0")
+ var/list/blend_objects = newlist() // Objects which to blend with
+ var/list/noblend_objects = newlist() //Objects to avoid blending with (such as children of listed blend objects.
+
+/obj/structure/Initialize()
+ . = ..()
+ if(climbable)
+ verbs += /obj/structure/proc/climb_on
/obj/structure/Destroy()
if(parts)
new parts(loc)
- . = ..()
+ return ..()
/obj/structure/attack_hand(mob/user)
if(breakable)
@@ -46,13 +56,7 @@
if(3.0)
return
-/obj/structure/New()
- ..()
- if(climbable)
- verbs += /obj/structure/proc/climb_on
-
/obj/structure/proc/climb_on()
-
set name = "Climb structure"
set desc = "Climbs onto a structure."
set category = "Object"
@@ -61,7 +65,6 @@
do_climb(usr)
/obj/structure/MouseDrop_T(mob/target, mob/user)
-
var/mob/living/H = user
if(istype(H) && can_climb(H) && target == user)
do_climb(target)
@@ -185,3 +188,72 @@
user.do_attack_animation(src)
spawn(1) qdel(src)
return 1
+
+/obj/structure/proc/can_visually_connect()
+ return anchored
+
+/obj/structure/proc/can_visually_connect_to(var/obj/structure/S)
+ return istype(S, src)
+
+/obj/structure/proc/update_connections(propagate = 0)
+ var/list/dirs = list()
+ var/list/other_dirs = list()
+
+ for(var/obj/structure/S in orange(src, 1))
+ if(can_visually_connect_to(S))
+ if(S.can_visually_connect())
+ if(propagate)
+ //S.update_connections() //Not here
+ S.update_icon()
+ dirs += get_dir(src, S)
+
+ if(!can_visually_connect())
+ connections = list("0", "0", "0", "0")
+ other_connections = list("0", "0", "0", "0")
+ return FALSE
+
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src, direction)
+ var/success = 0
+ for(var/b_type in blend_objects)
+ if(istype(T, b_type))
+ success = 1
+ if(propagate)
+ var/turf/simulated/wall/W = T
+ if(istype(W))
+ W.update_connections(1)
+ if(success)
+ break
+ if(success)
+ break
+ if(!success)
+ for(var/obj/O in T)
+ for(var/b_type in blend_objects)
+ if(istype(O, b_type))
+ success = 1
+ for(var/obj/structure/S in T)
+ if(istype(S, src))
+ success = 0
+ for(var/nb_type in noblend_objects)
+ if(istype(O, nb_type))
+ success = 0
+
+ if(success)
+ break
+ if(success)
+ break
+
+ if(success)
+ dirs += get_dir(src, T)
+ other_dirs += get_dir(src, T)
+
+ refresh_neighbors()
+
+ connections = dirs_to_corner_states(dirs)
+ other_connections = dirs_to_corner_states(other_dirs)
+ return TRUE
+
+/obj/structure/proc/refresh_neighbors()
+ for(var/thing in RANGE_TURFS(1, src))
+ var/turf/T = thing
+ T.update_icon()
diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm
index 26e040c7e9e..325cfff923b 100644
--- a/code/game/objects/structures/catwalk.dm
+++ b/code/game/objects/structures/catwalk.dm
@@ -1,102 +1,111 @@
-// Based on catwalk.dm from https://github.com/Endless-Horizon/CEV-Eris
/obj/structure/catwalk
name = "catwalk"
desc = "Cats really don't like these things."
- plane = DECAL_PLANE
- layer = ABOVE_UTILITY
icon = 'icons/turf/catwalks.dmi'
icon_state = "catwalk"
+ plane = DECAL_PLANE
+ layer = ABOVE_UTILITY
density = 0
+ anchored = 1.0
+ var/hatch_open = FALSE
+ var/plating_color = null
+ var/obj/item/stack/tile/plated_tile = null
+ var/static/plating_colors = list(
+ /obj/item/stack/tile/floor = "#858a8f",
+ /obj/item/stack/tile/floor/dark = "#4f4f4f",
+ /obj/item/stack/tile/floor/white = "#e8e8e8")
var/health = 100
var/maxhealth = 100
- anchored = 1.0
/obj/structure/catwalk/Initialize()
. = ..()
- for(var/obj/structure/catwalk/O in range(1))
- O.update_icon()
for(var/obj/structure/catwalk/C in get_turf(src))
if(C != src)
- warning("Duplicate [type] in [loc] ([x], [y], [z])")
- return INITIALIZE_HINT_QDEL
+ qdel(C)
+ update_connections(1)
update_icon()
+
/obj/structure/catwalk/Destroy()
- var/turf/location = loc
- . = ..()
- location.alpha = initial(location.alpha)
- for(var/obj/structure/catwalk/L in orange(location, 1))
- L.update_icon()
+ redraw_nearby_catwalks()
+ return ..()
+
+/obj/structure/catwalk/proc/redraw_nearby_catwalks()
+ for(var/direction in alldirs)
+ var/obj/structure/catwalk/L = locate() in get_step(src, direction)
+ if(L)
+ L.update_connections()
+ L.update_icon() //so siding get updated properly
+
/obj/structure/catwalk/update_icon()
- var/connectdir = 0
- for(var/direction in cardinal)
- if(locate(/obj/structure/catwalk, get_step(src, direction)))
- connectdir |= direction
-
- //Check the diagonal connections for corners, where you have, for example, connections both north and east. In this case it checks for a north-east connection to determine whether to add a corner marker or not.
- var/diagonalconnect = 0 //1 = NE; 2 = SE; 4 = NW; 8 = SW
- //NORTHEAST
- if(connectdir & NORTH && connectdir & EAST)
- if(locate(/obj/structure/catwalk, get_step(src, NORTHEAST)))
- diagonalconnect |= 1
- //SOUTHEAST
- if(connectdir & SOUTH && connectdir & EAST)
- if(locate(/obj/structure/catwalk, get_step(src, SOUTHEAST)))
- diagonalconnect |= 2
- //NORTHWEST
- if(connectdir & NORTH && connectdir & WEST)
- if(locate(/obj/structure/catwalk, get_step(src, NORTHWEST)))
- diagonalconnect |= 4
- //SOUTHWEST
- if(connectdir & SOUTH && connectdir & WEST)
- if(locate(/obj/structure/catwalk, get_step(src, SOUTHWEST)))
- diagonalconnect |= 8
-
- icon_state = "catwalk[connectdir]-[diagonalconnect]"
-
+ update_connections()
+ cut_overlays()
+ icon_state = ""
+ var/image/I
+ if(!hatch_open)
+ for(var/i = 1 to 4)
+ I = image(icon, "catwalk[connections[i]]", dir = 1<<(i-1))
+ add_overlay(I)
+ if(plating_color)
+ I = image(icon, "plated")
+ I.color = plating_color
+ add_overlay(I)
/obj/structure/catwalk/ex_act(severity)
switch(severity)
- if(1.0)
+ if(1)
+ new /obj/item/stack/rods(src.loc)
qdel(src)
- if(2.0)
+ if(2)
+ new /obj/item/stack/rods(src.loc)
qdel(src)
- if(3.0)
- qdel(src)
- return
+
+/obj/structure/catwalk/attack_robot(var/mob/user)
+ if(Adjacent(user))
+ attack_hand(user)
+
+/obj/structure/catwalk/proc/deconstruct(mob/user)
+ playsound(src, 'sound/items/Welder.ogg', 100, 1)
+ to_chat(user, "Slicing \the [src] joints ...")
+ new /obj/item/stack/rods(src.loc)
+ new /obj/item/stack/rods(src.loc)
+ //Lattice would delete itself, but let's save ourselves a new obj
+ if(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open))
+ new /obj/structure/lattice/(src.loc)
+ if(plated_tile)
+ new plated_tile(src.loc)
+ qdel(src)
/obj/structure/catwalk/attackby(obj/item/C as obj, mob/user as mob)
- if(istype(C, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/WT = C
- if(WT.isOn())
- if(WT.remove_fuel(0, user))
- to_chat(user, "Slicing lattice joints ...")
- new /obj/item/stack/rods(src.loc)
- new /obj/item/stack/rods(src.loc)
- new /obj/structure/lattice(src.loc)
- qdel(src)
- if(C.is_screwdriver())
- if(health < maxhealth)
- to_chat(user, "You begin repairing \the [src.name] with \the [C.name].")
- if(do_after(user, 20, src))
- health = maxhealth
- else
- take_damage(C.force)
- user.setClickCooldown(user.get_attack_speed(C))
- return ..()
+ if(C.is_crowbar() && plated_tile)
+ hatch_open = !hatch_open
+ if(hatch_open)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 2)
+ to_chat(user, "You pry open \the [src]'s maintenance hatch.")
+ else
+ playsound(src, 'sound/items/Deconstruct.ogg', 100, 2)
+ to_chat(user, "You shut \the [src]'s maintenance hatch.")
+ update_icon()
+ return
+ if(istype(C, /obj/item/stack/tile/floor) && !plated_tile)
+ var/obj/item/stack/tile/floor/ST = C
+ to_chat(user, "Placing tile...")
+ if (!do_after(user, 10))
+ return
+ if(!ST.use(1))
+ return
+ to_chat(user, "You plate \the [src]")
+ name = "plated catwalk"
+ plated_tile = C.type
+ src.add_fingerprint(user)
+ for(var/tiletype in plating_colors)
+ if(istype(ST, tiletype))
+ plating_color = plating_colors[tiletype]
+ update_icon()
-/obj/structure/catwalk/Crossed()
- . = ..()
- if(isliving(usr) && !usr.is_incorporeal())
- playsound(src, pick('sound/effects/footstep/catwalk1.ogg', 'sound/effects/footstep/catwalk2.ogg', 'sound/effects/footstep/catwalk3.ogg', 'sound/effects/footstep/catwalk4.ogg', 'sound/effects/footstep/catwalk5.ogg'), 25, 1)
-
-/obj/structure/catwalk/CheckExit(atom/movable/O, turf/target)
- if(O.checkpass(PASSGRILLE))
- return 1
- if(target && target.z < src.z)
- return 0
- return 1
+/obj/structure/catwalk/refresh_neighbors()
+ return
/obj/structure/catwalk/take_damage(amount)
health -= amount
@@ -104,4 +113,67 @@
visible_message("\The [src] breaks down!")
playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
new /obj/item/stack/rods(get_turf(src))
- Destroy()
\ No newline at end of file
+ Destroy()
+
+/obj/structure/catwalk/Crossed()
+ . = ..()
+ if(isliving(usr) && !usr.is_incorporeal())
+ playsound(src, pick('sound/effects/footstep/catwalk1.ogg', 'sound/effects/footstep/catwalk2.ogg', 'sound/effects/footstep/catwalk3.ogg', 'sound/effects/footstep/catwalk4.ogg', 'sound/effects/footstep/catwalk5.ogg'), 25, 1)
+
+/obj/effect/catwalk_plated
+ name = "plated catwalk spawner"
+ icon = 'icons/turf/catwalks.dmi'
+ icon_state = "catwalk_plated"
+ density = 1
+ anchored = 1.0
+ var/activated = FALSE
+ plane = DECAL_PLANE
+ layer = ABOVE_UTILITY
+ var/tile = /obj/item/stack/tile/floor
+ var/platecolor = "#858a8f"
+
+/obj/effect/catwalk_plated/Initialize(mapload)
+ . = ..()
+ if(SSticker?.current_state < GAME_STATE_PLAYING)
+ activate()
+
+/obj/effect/catwalk_plated/CanPass()
+ return 0
+
+/obj/effect/catwalk_plated/attack_hand()
+ attack_generic()
+
+/obj/effect/catwalk_plated/attack_ghost()
+ attack_generic()
+
+/obj/effect/catwalk_plated/attack_generic()
+ activate()
+
+/obj/effect/catwalk_plated/proc/activate()
+ if(activated) return
+
+ if(locate(/obj/structure/catwalk) in loc)
+ warning("Frame Spawner: A catwalk already exists at [loc.x]-[loc.y]-[loc.z]")
+ else
+ var/obj/structure/catwalk/C = new /obj/structure/catwalk(loc)
+ C.plated_tile = tile
+ C.plating_color = platecolor
+ C.name = "plated catwalk"
+ C.update_icon()
+ activated = 1
+ /* We don't have wallframes - yet
+ for(var/turf/T in orange(src, 1))
+ for(var/obj/effect/wallframe_spawn/other in T)
+ if(!other.activated) other.activate()
+ */
+ qdel(src)
+
+/obj/effect/catwalk_plated/dark
+ icon_state = "catwalk_plateddark"
+ tile = /obj/item/stack/tile/floor/dark
+ platecolor = "#4f4f4f"
+
+/obj/effect/catwalk_plated/white
+ icon_state = "catwalk_platedwhite"
+ tile = /obj/item/stack/tile/floor/white
+ platecolor = "#e8e8e8"
diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm
index 31b112e9bdf..f853e224fcb 100644
--- a/code/modules/tables/tables.dm
+++ b/code/modules/tables/tables.dm
@@ -28,8 +28,6 @@ var/list/table_icon_cache = list()
var/carpeted = 0
var/carpeted_type = /obj/item/stack/tile/carpet
- var/list/connections = list("nw0", "ne0", "sw0", "se0")
-
var/item_place = 1 //allows items to be placed on the table, but not on benches.
/obj/structure/table/proc/update_material()
@@ -402,60 +400,6 @@ var/list/table_icon_cache = list()
if(carpeted)
overlays += "carpet_flip[type]"
-// set propagate if you're updating a table that should update tables around it too, for example if it's a new table or something important has changed (like material).
-/obj/structure/table/proc/update_connections(propagate=0)
- if(!material)
- connections = list("0", "0", "0", "0")
-
- if(propagate)
- for(var/obj/structure/table/T in oview(src, 1))
- T.update_connections()
- return
-
- var/list/blocked_dirs = list()
- for(var/obj/structure/window/W in get_turf(src))
- if(W.is_fulltile())
- connections = list("0", "0", "0", "0")
- return
- blocked_dirs |= W.dir
-
- for(var/D in list(NORTH, SOUTH, EAST, WEST) - blocked_dirs)
- var/turf/T = get_step(src, D)
- for(var/obj/structure/window/W in T)
- if(W.is_fulltile() || W.dir == reverse_dir[D])
- blocked_dirs |= D
- break
- else
- if(W.dir != D) // it's off to the side
- blocked_dirs |= W.dir|D // blocks the diagonal
-
- for(var/D in list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) - blocked_dirs)
- var/turf/T = get_step(src, D)
-
- for(var/obj/structure/window/W in T)
- if(W.is_fulltile() || W.dir & reverse_dir[D])
- blocked_dirs |= D
- break
-
- // Blocked cardinals block the adjacent diagonals too. Prevents weirdness with tables.
- for(var/x in list(NORTH, SOUTH))
- for(var/y in list(EAST, WEST))
- if((x in blocked_dirs) || (y in blocked_dirs))
- blocked_dirs |= x|y
-
- var/list/connection_dirs = list()
-
- for(var/obj/structure/table/T in orange(src, 1))
- var/T_dir = get_dir(src, T)
- if(T_dir in blocked_dirs) continue
- if(material && T.material && material.name == T.material.name && flipped == T.flipped)
- connection_dirs |= T_dir
- if(propagate)
- spawn(0)
- T.update_connections()
- T.update_icon()
-
- connections = dirs_to_corner_states(connection_dirs)
#define CORNER_NONE 0
#define CORNER_COUNTERCLOCKWISE 1
diff --git a/icons/turf/catwalks.dmi b/icons/turf/catwalks.dmi
index 9e3d3d977ca..20c5e1f4d98 100644
Binary files a/icons/turf/catwalks.dmi and b/icons/turf/catwalks.dmi differ