diff --git a/code/__DEFINES/misc_defines.dm b/code/__DEFINES/misc_defines.dm index f344f422427..ba08edc8af7 100644 --- a/code/__DEFINES/misc_defines.dm +++ b/code/__DEFINES/misc_defines.dm @@ -745,3 +745,8 @@ do { \ //! The number of seconds between the start of the UNIX and BYOND epochs. #define BYOND_EPOCH_UNIX 946702800 + +#define BRIDGE_SPAWN_SUCCESS 0 +#define BRIDGE_SPAWN_TOO_WIDE 1 +#define BRIDGE_SPAWN_TOO_NARROW 2 +#define BRIDGE_SPAWN_BAD_TERRAIN 3 diff --git a/code/datums/ruins/bridges/bridges.dm b/code/datums/ruins/bridges/bridges.dm index f8e1b51df56..35155716682 100644 --- a/code/datums/ruins/bridges/bridges.dm +++ b/code/datums/ruins/bridges/bridges.dm @@ -29,7 +29,7 @@ /obj/effect/spawner/dynamic_bridge var/max_length = 8 var/min_length = 4 - var/bridge_theme = LONG_BRIDGE_THEME_CULT + var/bridge_theme var/list/forwards_backwards var/list/side_to_side var/turf/forward_goal @@ -37,20 +37,21 @@ /obj/effect/spawner/dynamic_bridge/Initialize(mapload) . = ..() - 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, - ) + if(!bridge_theme) + 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/dynamic_bridge/LateInitialize() forwards_backwards = list(NORTH, SOUTH) side_to_side = list(EAST, WEST) - if(!attempt_bridge()) + if(attempt_bridge() != BRIDGE_SPAWN_SUCCESS) forward_goal = null backward_goal = null forwards_backwards = list(EAST, WEST) @@ -85,6 +86,16 @@ return TRUE +/obj/effect/spawner/dynamic_bridge/proc/bridgeable_turf(turf/T) + // Pre SSlatemapping, before we've replaced mapping turfs with their river theme + if(istype(T, /turf/simulated/floor/lava/mapping_lava)) + return TRUE + // Everything else + if(istype(T, /turf/simulated/floor/chasm)) + return TRUE + if(istype(T, /turf/simulated/floor/lava)) + 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 @@ -92,11 +103,11 @@ /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)) + if(!bridgeable_turf(T)) return FALSE - if(!istype(get_step(T, side_to_side[1]), /turf/simulated/floor/lava/mapping_lava)) + if(!bridgeable_turf(get_step(T, side_to_side[1]))) return FALSE - if(!istype(get_step(T, side_to_side[2]), /turf/simulated/floor/lava/mapping_lava)) + if(!bridgeable_turf(get_step(T, side_to_side[2]))) return FALSE var/area/A = get_area(T) if(istype(A, /area/lavaland/surface/gulag_rock)) @@ -225,7 +236,7 @@ /// 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)) + if(bridgeable_turf(T)) T.ChangeTurf(/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface) T.icon_state = "basalt" // hate @@ -260,6 +271,13 @@ count++ walk_dir = forwards_backwards[1] + if(bad_passage) + return BRIDGE_SPAWN_BAD_TERRAIN + if(count < min_length) + return BRIDGE_SPAWN_TOO_NARROW + if(count > max_length) + return BRIDGE_SPAWN_TOO_WIDE + if(!bad_passage && count >= min_length && forward_goal && backward_goal) for(var/turf/T in get_line(forward_goal, backward_goal)) make_walkway(T) @@ -278,7 +296,7 @@ get_step(get_step(backward_goal, side_to_side[2]), forwards_backwards[2]))) cleanup_edge(T) - return TRUE + return BRIDGE_SPAWN_SUCCESS /// Checks if we are going out of bounds. Returns TRUE if we are close (less than or equal to 2 turfs) to a border /obj/effect/spawner/dynamic_bridge/proc/out_of_bounds(direction, turf/current_turf) @@ -296,6 +314,20 @@ return current_turf.x <= 2 return TRUE +/obj/effect/spawner/dynamic_bridge/capsule + bridge_theme = LONG_BRIDGE_THEME_CATWALK + +/obj/effect/spawner/dynamic_bridge/capsule/Initialize(mapload, thrown_dir) + . = ..() + if(thrown_dir in list(EAST, WEST)) + forwards_backwards = list(EAST, WEST) + side_to_side = list(NORTH, SOUTH) + else + forwards_backwards = list(NORTH, SOUTH) + side_to_side = list(EAST, WEST) + + return INITIALIZE_HINT_NORMAL + /datum/map_template/ruin/lavaland/zlvl_bridge prefix = "_maps/map_files/RandomRuins/LavaRuins/zlvl_bridges/" ci_exclude = /datum/map_template/ruin/lavaland/zlvl_bridge diff --git a/code/game/turfs/simulated/floor/chasm.dm b/code/game/turfs/simulated/floor/chasm.dm index 2a41fb32514..1f34b58e429 100644 --- a/code/game/turfs/simulated/floor/chasm.dm +++ b/code/game/turfs/simulated/floor/chasm.dm @@ -146,9 +146,11 @@ if(!AM.simulated || is_type_in_typecache(AM, forbidden_types) || AM.throwing) return FALSE //Flies right over the chasm + if(HAS_TRAIT(AM, TRAIT_FLYING)) + return FALSE if(isliving(AM)) var/mob/living/M = AM - if(HAS_TRAIT(M, TRAIT_FLYING) || M.floating) + if(M.floating) return FALSE if(istype(M.buckled, /obj/tgvehicle/scooter/skateboard/hoverboard)) return FALSE diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm index 9d8393db817..bb75c9f9147 100644 --- a/code/game/turfs/simulated/floor/lava.dm +++ b/code/game/turfs/simulated/floor/lava.dm @@ -76,7 +76,10 @@ var/thing_to_check = src if(AM) thing_to_check = list(AM) - for(var/thing in thing_to_check) + for(var/atom/thing in thing_to_check) + if(HAS_TRAIT(thing, TRAIT_FLYING)) + continue //YOU'RE FLYING OVER IT + if(isobj(thing)) var/obj/O = thing if(!O.simulated) @@ -97,8 +100,6 @@ else if(isliving(thing)) . = TRUE var/mob/living/L = thing - if(HAS_TRAIT(L, TRAIT_FLYING)) - continue //YOU'RE FLYING OVER IT var/buckle_check = L.buckling if(!buckle_check) buckle_check = L.buckled @@ -206,7 +207,10 @@ var/thing_to_check = src if(AM) thing_to_check = list(AM) - for(var/thing in thing_to_check) + for(var/atom/thing in thing_to_check) + if(HAS_TRAIT(thing, TRAIT_FLYING)) + continue //YOU'RE FLYING OVER IT + if(isobj(thing)) var/obj/O = thing if(!O.simulated) diff --git a/code/modules/mining/bridge_capsule.dm b/code/modules/mining/bridge_capsule.dm new file mode 100644 index 00000000000..454bc862b8d --- /dev/null +++ b/code/modules/mining/bridge_capsule.dm @@ -0,0 +1,70 @@ +/obj/item/bridge_capsule + name = "bluespace bridge capsule" + desc = "A bridge stored within a pocket of bluespace." + icon_state = "bridge_capsule" + icon = 'icons/obj/mining.dmi' + w_class = WEIGHT_CLASS_TINY + origin_tech = "engineering=3;bluespace=3" + new_attack_chain = TRUE + var/used = FALSE + var/thrown_dir + +/obj/item/bridge_capsule/examine(mob/user) + . = ..() + . += "To use, activate it in-hand and throw it between the middle of the two areas you are trying to bridge." + . += "For best results, ensure the land on both sides of the span are smooth." + +/obj/item/bridge_capsule/throw_at(atom/target, range, speed, mob/thrower, spin, diagonals_first, datum/callback/callback, force, dodgeable) + . = ..() + if(used) + ADD_TRAIT(src, TRAIT_FLYING, "[UID()]") + thrown_dir = get_dir(thrower, target) + to_chat(thrower, "[src] hovers above the ground as it prepares to deploy...") + +/obj/item/bridge_capsule/activate_self(mob/user) + . = ..() + if(!used) + loc.visible_message("[src] begins to shake. Stand back!") + used = TRUE + addtimer(CALLBACK(src, PROC_REF(deploy)), 5 SECONDS) + +/obj/item/bridge_capsule/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) + . = ..() + thrown_dir = throwingdatum.init_dir + +/obj/item/bridge_capsule/proc/deploy() + if(ismob(loc)) + to_chat(loc, "[src] stops shaking. Looks like it needs to be thrown to deploy.") + used = FALSE + return + + if(istype(loc, SSmapping.lavaland_theme?.primary_turf_type)) + loc.visible_message("[src] suddenly bursts!") + var/obj/effect/spawner/dynamic_bridge/capsule/spawner = new(loc, thrown_dir) + var/result = spawner.attempt_bridge() + var/fail_message = "[src] buzzes loudly and falls to the ground!" + switch(result) + if(BRIDGE_SPAWN_SUCCESS) + qdel(src) + if(BRIDGE_SPAWN_BAD_TERRAIN) + loc.visible_message("[fail_message] It looks like the terrain here is too uneven for a bridge.") + stop_flying() + if(BRIDGE_SPAWN_TOO_NARROW) + loc.visible_message("[fail_message] It looks like the span here is too narrow.") + stop_flying() + if(BRIDGE_SPAWN_TOO_WIDE) + loc.visible_message("[fail_message] It looks like the span here is too wide.") + stop_flying() + + qdel(spawner) + return + + stop_flying() + to_chat(loc, "[src] flutters to the ground, refusing to deploy. Maybe you can't do that here?") + +/obj/item/bridge_capsule/proc/stop_flying() + REMOVE_TRAIT(src, TRAIT_FLYING, "[UID()]") + // Easiest/fastest way to trigger chasms/lava underneath us to + // determine if something needs to happen when we lose our trait + if(isturf(loc)) + loc.process() diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index f53b72938ab..1998a12f84b 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -59,6 +59,7 @@ EQUIPMENT("Mining Charge Detonator", /obj/item/detonator, 150), EQUIPMENT("Shelter Capsule", /obj/item/survivalcapsule, 400), EQUIPMENT("Luxury Shelter Capsule", /obj/item/survivalcapsule/luxury, 3000), + EQUIPMENT("Bridge Capsule", /obj/item/bridge_capsule, 300), EQUIPMENT("Stabilizing Serum", /obj/item/hivelordstabilizer, 400), EQUIPMENT("Survival Medipen", /obj/item/reagent_containers/hypospray/autoinjector/survival, 500), ) diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index adf10d0a2d6..d869254834e 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/paradise.dme b/paradise.dme index a4a18400f65..efdd4e56593 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2260,6 +2260,7 @@ #include "code\modules\maze_generation\loot_modules\_loot_module_base.dm" #include "code\modules\maze_generation\loot_modules\turf_painter.dm" #include "code\modules\mining\abandonedcrates.dm" +#include "code\modules\mining\bridge_capsule.dm" #include "code\modules\mining\fulton.dm" #include "code\modules\mining\machine_processing.dm" #include "code\modules\mining\machine_redemption.dm"