feat: dynamic Lavaland bridge lengths. (#27173)

This commit is contained in:
warriorstar-orion
2024-11-19 10:38:06 +00:00
committed by GitHub
parent 2ec6a3adfc
commit 105a2fa617
18 changed files with 214 additions and 751 deletions
-17
View File
@@ -121,7 +121,6 @@
preloadRuinTemplates()
preloadShelterTemplates()
preloadShuttleTemplates()
preloadBridgeTemplates()
preloadEventTemplates()
/proc/preloadRuinTemplates()
@@ -169,22 +168,6 @@
GLOB.shuttle_templates[S.shuttle_id] = S
GLOB.map_templates[S.shuttle_id] = S
/proc/preloadBridgeTemplates()
for(var/item in subtypesof(/datum/map_template/ruin/bridge/horizontal))
var/datum/map_template/ruin/bridge/horizontal/horizontal_type = item
if(!(initial(horizontal_type.suffix)))
continue
var/datum/map_template/ruin/bridge/horizontal/S = new horizontal_type()
GLOB.bridge_horizontal_templates[S.suffix] = S
GLOB.map_templates[S.suffix] = S
for(var/item in subtypesof(/datum/map_template/ruin/bridge/vertical))
var/datum/map_template/ruin/bridge/horizontal/vertical_type = item
if(!(initial(vertical_type.suffix)))
continue
var/datum/map_template/ruin/bridge/vertical/V = new vertical_type()
GLOB.bridge_vertical_templates[V.suffix] = V
GLOB.map_templates[V.suffix] = V
/proc/preloadEventTemplates()
for(var/item in subtypesof(/datum/map_template/event))
var/datum/map_template/event/event_type = item
+210 -80
View File
@@ -1,87 +1,217 @@
/datum/map_template/ruin/bridge
prefix = "_maps/map_files/RandomRuins/LavaRuins/chasm_bridges/"
ci_exclude = /datum/map_template/ruin/bridge
#define LONG_BRIDGE_THEME_CULT "cult"
#define LONG_BRIDGE_THEME_HIERO "hiero"
#define LONG_BRIDGE_THEME_CLOCKWORK "clockwork"
#define LONG_BRIDGE_THEME_STONE "stone"
#define LONG_BRIDGE_THEME_WOOD "wood"
#define LONG_BRIDGE_THEME_CATWALK "catwalk"
/datum/map_template/ruin/bridge/horizontal
ci_exclude = /datum/map_template/ruin/bridge/horizontal
/**
* A spawner for dynamic bridges, largely with hardcoded expectations to be
* operating on Lavaland.
*
* It does this by starting at its spawn point, placed by a
* [/datum/river_spawner] during generation, and walking in each direction
* "forwards" and "backwards" until it reaches the maximum possible length of
* the bridge, or a tile that doesn't appear to be a valid "passage"
* (essentially a tile that doesn't have lava on both sides and thus wouldn't
* look good or make an effective bridge). If it manages to do this and find two
* tiles that work as the start and end of the bridge, it places the paths,
* pillars, and "cleans up" the tiles contiguous to its entrance and exit turfs,
* removing any lava if present.
*
* It attempts this first in the vertical direction, and then the horizontal. So
* "fowards" and "backwards" can mean NORTH/SOUTH or EAST/WEST depending on the
* direction it's attempting.
*
* There are several bridge "themes" implemented in `make_walkway()` and
* `make_pillar()`, and more can be added if desired.
*/
/obj/effect/spawner/dynamic_bridge
var/max_length = 8
var/min_length = 4
var/bridge_theme = LONG_BRIDGE_THEME_CULT
var/list/forwards_backwards
var/list/side_to_side
/datum/map_template/ruin/bridge/horizontal/one
name = "Horizontal Bridge One"
suffix = "lavaland_bridge_horizontal_1.dmm"
/datum/map_template/ruin/bridge/horizontal/two
name = "Horizontal Bridge Two"
suffix = "lavaland_bridge_horizontal_2.dmm"
/datum/map_template/ruin/bridge/horizontal/three
name = "Horizontal Bridge Three"
suffix = "lavaland_bridge_horizontal_3.dmm"
/datum/map_template/ruin/bridge/horizontal/four
name = "Horizontal Bridge Four"
suffix = "lavaland_bridge_horizontal_4.dmm"
/datum/map_template/ruin/bridge/horizontal/five
name = "Horizontal Bridge Five"
suffix = "lavaland_bridge_horizontal_5.dmm"
/datum/map_template/ruin/bridge/horizontal/six
name = "Horizontal Bridge Six"
suffix = "lavaland_bridge_horizontal_6.dmm"
/datum/map_template/ruin/bridge/vertical
ci_exclude = /datum/map_template/ruin/bridge/vertical
/datum/map_template/ruin/bridge/vertical/one
name = "Vertical Bridge One"
suffix = "lavaland_bridge_vertical_1.dmm"
/datum/map_template/ruin/bridge/vertical/two
name = "Vertical Bridge Two"
suffix = "lavaland_bridge_vertical_2.dmm"
/datum/map_template/ruin/bridge/vertical/three
name = "Vertical Bridge Three"
suffix = "lavaland_bridge_vertical_3.dmm"
/datum/map_template/ruin/bridge/vertical/four
name = "Vertical Bridge Four"
suffix = "lavaland_bridge_vertical_4.dmm"
/datum/map_template/ruin/bridge/vertical/five
name = "Vertical Bridge Five"
suffix = "lavaland_bridge_vertical_5.dmm"
/datum/map_template/ruin/bridge/vertical/six
name = "Vertical Bridge Six"
suffix = "lavaland_bridge_vertical_6.dmm"
/obj/effect/spawner/bridge
name = "Bridge spawner"
var/datum/map_template/ruin/bridge/template
/obj/effect/spawner/bridge/Initialize(mapload)
/obj/effect/spawner/dynamic_bridge/Initialize(mapload)
. = ..()
SSlate_mapping.bridge_spawners += src
bridge_theme = pick(
LONG_BRIDGE_THEME_CULT,
LONG_BRIDGE_THEME_HIERO,
LONG_BRIDGE_THEME_CLOCKWORK,
LONG_BRIDGE_THEME_STONE,
LONG_BRIDGE_THEME_WOOD,
LONG_BRIDGE_THEME_CATWALK,
)
return INITIALIZE_HINT_LATELOAD
/obj/effect/spawner/bridge/Destroy()
SSlate_mapping.bridge_spawners -= src
return ..()
/obj/effect/spawner/dynamic_bridge/LateInitialize()
forwards_backwards = list(NORTH, SOUTH)
side_to_side = list(EAST, WEST)
if(!attempt_bridge())
forwards_backwards = list(EAST, WEST)
side_to_side = list(NORTH, SOUTH)
attempt_bridge()
/obj/effect/spawner/bridge/proc/generate_bridge()
var/turf/east = locate(x + 3, y, z)
var/turf/west = locate(x - 3, y, z)
var/turf/north = locate(x, y + 3, z)
var/turf/south = locate(x, y - 3, z)
var/turf/e1 = locate(x + 1, y, z)
var/turf/w1 = locate(x - 1, y, z)
var/turf/n1 = locate(x, y + 1, z)
var/turf/s1 = locate(x, y - 1, z)
qdel(src)
/// Returns whether the passed in turf is a valid "landing". A valid landing is
/// a tile that hasn't been reserved by another bridge, and has a non-lava tile
/// leading directly to it.
/obj/effect/spawner/dynamic_bridge/proc/valid_landing(turf/T, direction)
if(T.flags & LAVA_BRIDGE || T.flags & NO_LAVA_GEN)
return FALSE
if((ismineralturf(east) || istype(east, /turf/simulated/floor/plating/asteroid)) && (ismineralturf(west) || istype(west, /turf/simulated/floor/plating/asteroid)) && !(ismineralturf(n1) || istype(n1, /turf/simulated/floor/plating/asteroid)) && !(ismineralturf(s1) || istype(s1, /turf/simulated/floor/plating/asteroid)))
template = GLOB.bridge_horizontal_templates[pick("lavaland_bridge_horizontal_1.dmm", "lavaland_bridge_horizontal_2.dmm", "lavaland_bridge_horizontal_3.dmm", "lavaland_bridge_horizontal_4.dmm", "lavaland_bridge_horizontal_5.dmm", "lavaland_bridge_horizontal_6.dmm")]
template.load(loc, centered = TRUE)
else if((ismineralturf(north) || istype(north, /turf/simulated/floor/plating/asteroid)) && (ismineralturf(south) || istype(south, /turf/simulated/floor/plating/asteroid)) && !(ismineralturf(e1) || istype(e1, /turf/simulated/floor/plating/asteroid)) && !(ismineralturf(w1) || istype(w1, /turf/simulated/floor/plating/asteroid)))
template = GLOB.bridge_vertical_templates[pick("lavaland_bridge_vertical_1.dmm", "lavaland_bridge_vertical_2.dmm", "lavaland_bridge_vertical_3.dmm", "lavaland_bridge_vertical_4.dmm", "lavaland_bridge_vertical_5.dmm", "lavaland_bridge_vertical_6.dmm")]
template.load(loc, centered = TRUE)
var/turf/end = get_step(T, direction)
if(end.flags & LAVA_BRIDGE || !(ismineralturf(end) || istype(end, /turf/simulated/floor/plating/asteroid)))
return FALSE
return TRUE
/// Returns whether the passed in turf is a valid "passage". A valid passage is
/// a lava tile that has lava on both sides of it. Invalid passage tiles do not
/// look good as bridge walkways and defeat the purpose of there is floor right
/// next to it.
/obj/effect/spawner/dynamic_bridge/proc/valid_passage(turf/T)
if(T.flags & LAVA_BRIDGE)
return FALSE
if(!istype(T, /turf/simulated/floor/lava/mapping_lava))
return FALSE
if(!istype(get_step(T, side_to_side[1]), /turf/simulated/floor/lava/mapping_lava))
return FALSE
if(!istype(get_step(T, side_to_side[2]), /turf/simulated/floor/lava/mapping_lava))
return FALSE
return TRUE
/obj/effect/spawner/dynamic_bridge/proc/make_pillar(turf/T)
for(var/obj/structure/spawner/S in T)
qdel(S)
for(var/mob/living/M in T)
qdel(M)
for(var/obj/structure/flora/F in T)
qdel(F)
switch(bridge_theme)
if(LONG_BRIDGE_THEME_CULT)
T.ChangeTurf(/turf/simulated/wall/cult)
if(LONG_BRIDGE_THEME_HIERO)
T.ChangeTurf(/turf/simulated/wall/indestructible/hierophant)
if(LONG_BRIDGE_THEME_CLOCKWORK)
T.ChangeTurf(/turf/simulated/wall/clockwork)
if(LONG_BRIDGE_THEME_STONE)
T.ChangeTurf(/turf/simulated/wall/cult)
if(LONG_BRIDGE_THEME_WOOD)
T.ChangeTurf(/turf/simulated/wall/mineral/wood/nonmetal)
if(LONG_BRIDGE_THEME_CATWALK)
new /obj/structure/lattice/catwalk/mining(T)
new /obj/structure/marker_beacon/dock_marker/collision(T)
T.flags |= LAVA_BRIDGE
/obj/effect/spawner/dynamic_bridge/proc/make_walkway(turf/T)
for(var/obj/structure/spawner/S in T)
qdel(S)
for(var/mob/living/M in T)
qdel(M)
for(var/obj/structure/flora/F in T)
qdel(F)
switch(bridge_theme)
if(LONG_BRIDGE_THEME_CULT)
T.ChangeTurf(/turf/simulated/floor/engine/cult/lavaland_air)
if(LONG_BRIDGE_THEME_HIERO)
T.ChangeTurf(/turf/simulated/floor/indestructible/hierophant)
if(LONG_BRIDGE_THEME_CLOCKWORK)
T.ChangeTurf(/turf/simulated/floor/clockwork/lavaland_air)
if(LONG_BRIDGE_THEME_STONE)
// Stone tiles are different sizes and shapes so these are
// "safe-looking" arrangements
switch(rand(1, 5))
if(1)
new /obj/structure/stone_tile/block(T)
var/obj/structure/stone_tile/block/cracked/C = new(T)
C.dir = NORTH
if(2)
new /obj/structure/stone_tile/slab(T)
if(3)
new /obj/structure/stone_tile/surrounding(T)
new /obj/structure/stone_tile/center(T)
if(4)
new /obj/structure/stone_tile/slab/cracked(T)
if(5)
new /obj/structure/stone_tile/burnt(T)
var/obj/structure/stone_tile/surrounding_tile/ST = new(T)
ST.dir = WEST
var/obj/structure/stone_tile/block/B = new(T)
B.dir = NORTH
if(LONG_BRIDGE_THEME_WOOD)
T.ChangeTurf(/turf/simulated/floor/wood/lavaland_air)
if(prob(20))
new /obj/effect/landmark/damageturf(T)
if(LONG_BRIDGE_THEME_CATWALK)
new /obj/structure/lattice/catwalk/mining(T)
T.flags |= LAVA_BRIDGE
/// Make a tile safe for player passage, for use at the bridge entrance and exits
/obj/effect/spawner/dynamic_bridge/proc/cleanup_edge(turf/T)
if(istype(T, /turf/simulated/floor/lava/mapping_lava))
T.ChangeTurf(/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface)
T.icon_state = "basalt" // hate
/obj/effect/spawner/dynamic_bridge/proc/attempt_bridge()
var/count = 1
var/walk_dir = forwards_backwards[1]
var/turf/forward_step = get_turf(src)
var/turf/backward_step = get_turf(src)
var/turf/forward_goal
var/turf/backward_goal
var/bad_passage = FALSE
while(count <= max_length && !(forward_goal && backward_goal) && !bad_passage)
if(walk_dir == forwards_backwards[1])
if(!forward_goal)
forward_step = get_step(forward_step, walk_dir)
if(valid_landing(forward_step, walk_dir))
forward_goal = forward_step
else if(!valid_passage(forward_step))
bad_passage = TRUE
count++
walk_dir = forwards_backwards[2]
else
if(!backward_goal)
backward_step = get_step(backward_step, walk_dir)
if(valid_landing(backward_step, walk_dir))
backward_goal = backward_step
else if(!valid_passage(backward_step))
bad_passage = TRUE
count++
walk_dir = forwards_backwards[1]
if(!bad_passage && count >= min_length && forward_goal && backward_goal)
for(var/turf/T in get_line(forward_goal, backward_goal))
make_walkway(T)
for(var/turf/T in list(
get_step(forward_goal, side_to_side[1]),
get_step(forward_goal, side_to_side[2]),
get_step(backward_goal, side_to_side[1]),
get_step(backward_goal, side_to_side[2])))
make_pillar(T)
for(var/turf/T in get_line(
get_step(get_step(forward_goal, side_to_side[1]), forwards_backwards[1]),
get_step(get_step(forward_goal, side_to_side[2]), forwards_backwards[1])))
cleanup_edge(T)
for(var/turf/T in get_line(
get_step(get_step(backward_goal, side_to_side[1]), forwards_backwards[2]),
get_step(get_step(backward_goal, side_to_side[2]), forwards_backwards[2])))
cleanup_edge(T)
return TRUE
#undef LONG_BRIDGE_THEME_CULT
#undef LONG_BRIDGE_THEME_HIERO
#undef LONG_BRIDGE_THEME_CLOCKWORK
#undef LONG_BRIDGE_THEME_STONE
#undef LONG_BRIDGE_THEME_WOOD
#undef LONG_BRIDGE_THEME_CATWALK