diff --git a/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm b/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm index 41abfb21689..278fd1222a1 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm @@ -29,12 +29,20 @@ /area/ruin/space/methlab) "g" = ( /obj/effect/decal/cleanable/blood, +/obj/machinery/atmospherics/pipe/simple/visible{ + dir = 6 + }, /turf/simulated/floor/plating, /area/ruin/space/methlab) "h" = ( /obj/machinery/door/airlock/external{ name = "Crackden Airlock" }, +/obj/machinery/atmospherics/pipe/simple/visible{ + dir = 8 + }, +/obj/machinery/access_button/offset/south, +/obj/effect/map_effect/dynamic_airlock/door/interior, /turf/simulated/floor/plating, /area/ruin/space/methlab) "i" = ( @@ -48,6 +56,8 @@ /obj/machinery/door/airlock/external{ name = "Plain Airlock" }, +/obj/machinery/access_button/offset/southeast, +/obj/effect/map_effect/dynamic_airlock/door/exterior, /turf/simulated/floor/plating, /area/ruin/space/methlab) "l" = ( @@ -93,15 +103,6 @@ /obj/machinery/chem_master, /turf/simulated/floor/plating, /area/ruin/space/methlab) -"s" = ( -/obj/effect/decal/cleanable/blood/oil, -/turf/simulated/floor/plating, -/area/ruin/space/methlab) -"t" = ( -/obj/machinery/power/port_gen/pacman, -/obj/structure/cable, -/turf/simulated/floor/plating, -/area/ruin/space/methlab) "u" = ( /obj/machinery/chem_dispenser, /turf/simulated/floor/plating, @@ -124,9 +125,49 @@ /obj/machinery/kitchen_machine/microwave, /turf/simulated/floor/plating, /area/ruin/space/methlab) +"A" = ( +/obj/item/grenade/chem_grenade/drugs, +/obj/machinery/atmospherics/pipe/simple/visible, +/turf/simulated/floor/plating, +/area/ruin/space/methlab) +"B" = ( +/obj/machinery/atmospherics/pipe/simple/visible{ + dir = 5 + }, +/turf/simulated/floor/plating, +/area/ruin/space/methlab) +"C" = ( +/obj/effect/decal/cleanable/blood/oil, +/turf/simulated/floor/plating, +/area/ruin/space/methlab) "K" = ( /turf/simulated/mineral/random/high_chance/space, /area/ruin/space/methlab) +"L" = ( +/obj/machinery/airlock_controller/air_cycler/directional/north, +/obj/effect/map_effect/dynamic_airlock, +/turf/simulated/floor/plating, +/area/ruin/space/methlab) +"M" = ( +/obj/machinery/atmospherics/unary/portables_connector{ + dir = 8 + }, +/obj/machinery/atmospherics/portable/canister/air, +/turf/simulated/floor/plating, +/area/ruin/space/methlab) +"N" = ( +/obj/machinery/power/port_gen/pacman, +/obj/structure/cable, +/turf/simulated/floor/plating, +/area/ruin/space/methlab) +"Z" = ( +/obj/item/grenade/chem_grenade/drugs, +/obj/machinery/atmospherics/unary/vent_pump/high_volume{ + dir = 8 + }, +/obj/effect/map_effect/dynamic_airlock, +/turf/simulated/floor/plating, +/area/ruin/space/methlab) (1,1,1) = {" a @@ -245,7 +286,7 @@ b d j j -s +C j j y @@ -263,7 +304,7 @@ b e j p -t +N K K b @@ -315,11 +356,11 @@ b b K g -i +A +B j j -j -x +q b a a @@ -334,7 +375,7 @@ b b h b -q +M b b b @@ -350,7 +391,7 @@ a a b b -i +Z b b b @@ -368,7 +409,7 @@ a b b b -j +L b b b diff --git a/code/__DEFINES/airlock_control_defines.dm b/code/__DEFINES/airlock_control_defines.dm index c61518a3f16..9193da53d43 100644 --- a/code/__DEFINES/airlock_control_defines.dm +++ b/code/__DEFINES/airlock_control_defines.dm @@ -12,3 +12,9 @@ // Airlock controller button modes #define MODE_INTERIOR "int" #define MODE_EXTERIOR "ext" + +#define VENT_ID(_id_to_link) "[_id_to_link]_vent" +#define EXT_DOOR_ID(_id_to_link) "[_id_to_link]_door_ext" +#define INT_DOOR_ID(_id_to_link) "[_id_to_link]_door_int" +#define EXT_BTN_ID(_id_to_link) "[_id_to_link]_btn_ext" +#define INT_BTN_ID(_id_to_link) "[_id_to_link]_btn_int" diff --git a/code/__DEFINES/mappers.dm b/code/__DEFINES/mappers.dm index adff62e6900..dfd99145534 100644 --- a/code/__DEFINES/mappers.dm +++ b/code/__DEFINES/mappers.dm @@ -16,6 +16,48 @@ pixel_x = -offset_x; \ } +#define BUTTON_HELPERS(path, offset_1, offset_2) \ +##path/offset/northwest {\ + dir = NORTHWEST; \ + pixel_x = -offset_2; \ + pixel_y = offset_1; \ +} \ +##path/offset/north {\ + dir = NORTH; \ + pixel_x = offset_2; \ + pixel_y = offset_1; \ +} \ +##path/offset/northeast {\ + dir = NORTHEAST; \ + pixel_x = offset_1; \ + pixel_y = offset_2; \ +} \ +##path/offset/east {\ + dir = EAST; \ + pixel_x = offset_1; \ + pixel_y = -offset_2; \ +} \ +##path/offset/southeast {\ + dir = SOUTHEAST; \ + pixel_x = offset_2; \ + pixel_y = -offset_1; \ +} \ +##path/offset/south {\ + dir = SOUTH; \ + pixel_x = -offset_2; \ + pixel_y = -offset_1; \ +} \ +##path/offset/southwest {\ + dir = SOUTHWEST; \ + pixel_x = -offset_1; \ + pixel_y = -offset_2; \ +} \ +##path/offset/west {\ + dir = WEST; \ + pixel_x = -offset_1; \ + pixel_y = offset_2; \ +} + // If we want to set custom offset to each cardinal direction #define MAPPING_DIRECTIONAL_HELPERS_CUSTOM(path, offset_north, offset_south, offset_east, offset_west) ##path/directional/north {\ dir = NORTH; \ diff --git a/code/game/machinery/airlock_control/airlock_button.dm b/code/game/machinery/airlock_control/airlock_button.dm index 7316b8098cc..f4f85636bda 100644 --- a/code/game/machinery/airlock_control/airlock_button.dm +++ b/code/game/machinery/airlock_control/airlock_button.dm @@ -67,3 +67,4 @@ GLOBAL_LIST_EMPTY(all_airlock_access_buttons) controller_uid = C.UID() assigned_command = mode +BUTTON_HELPERS(/obj/machinery/access_button, 25, 7) diff --git a/code/game/machinery/airlock_control/airlock_controllers.dm b/code/game/machinery/airlock_control/airlock_controllers.dm index 24dfd9a5ed0..1b39bb81f71 100644 --- a/code/game/machinery/airlock_control/airlock_controllers.dm +++ b/code/game/machinery/airlock_control/airlock_controllers.dm @@ -47,9 +47,9 @@ /obj/machinery/airlock_controller/LateInitialize() for(var/obj/machinery/door/airlock/A in GLOB.airlocks) if(A.id_tag == int_door_link_id) - interior_doors += A.UID() + interior_doors |= A.UID() if(A.id_tag == ext_door_link_id) - exterior_doors += A.UID() + exterior_doors |= A.UID() if(!length(interior_doors)) stack_trace("[src] at [x],[y],[z] didnt setup any interior airlocks! Please double check the IDs!") @@ -72,7 +72,6 @@ if(!eb_setup) stack_trace("[src] at [x],[y],[z] didnt setup any exterior buttons! Please double check the IDs!") - /obj/machinery/airlock_controller/attack_ghost(mob/user) ui_interact(user) @@ -415,3 +414,5 @@ send an additional command to open the door again. begin_cycle_in() if(MODE_EXTERIOR) begin_cycle_out() + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airlock_controller/air_cycler, 25, 25) diff --git a/code/game/objects/effects/spawners/airlock_spawner.dm b/code/game/objects/effects/spawners/airlock_spawner.dm index 592a7b58404..df9fdf340b7 100644 --- a/code/game/objects/effects/spawners/airlock_spawner.dm +++ b/code/game/objects/effects/spawners/airlock_spawner.dm @@ -11,12 +11,6 @@ This spawner places pipe leading up to the interior door, you will need to finis #define DOOR_NORMAL_PLACEMENT 1 #define DOOR_FLIPPED_PLACEMENT 2 -#define VENT_ID "[id_to_link]_vent" -#define EXT_DOOR_ID "[id_to_link]_door_ext" -#define INT_DOOR_ID "[id_to_link]_door_int" -#define EXT_BTN_ID "[id_to_link]_btn_ext" -#define INT_BTN_ID "[id_to_link]_btn_int" - /obj/effect/spawner/airlock name = "1 by 1 airlock spawner (interior north, exterior south)" desc = "If you can see this, there's probably a missing airlock here. Better tell an admin and report this on the github." @@ -95,7 +89,7 @@ This spawner places pipe leading up to the interior door, you will need to finis the_button.forceMove(get_step(the_button, NORTH)) /obj/effect/spawner/airlock/proc/handle_door_stuff(obj/machinery/door/airlock/A, is_this_an_interior_airlock) //This sets up the door vars correctly and then locks it before first use - A.id_tag = is_this_an_interior_airlock ? INT_DOOR_ID : EXT_DOOR_ID + A.id_tag = is_this_an_interior_airlock ? INT_DOOR_ID(id_to_link) : EXT_DOOR_ID(id_to_link) set_access_helper(A) A.name = door_name A.lock() @@ -103,9 +97,9 @@ This spawner places pipe leading up to the interior door, you will need to finis /obj/effect/spawner/airlock/proc/spawn_button(turf/T, some_direction, interior) var/obj/machinery/access_button/the_button = new(T) if(interior) - the_button.autolink_id = INT_BTN_ID + the_button.autolink_id = INT_BTN_ID(id_to_link) else - the_button.autolink_id = EXT_BTN_ID + the_button.autolink_id = EXT_BTN_ID(id_to_link) switch(some_direction) if(NORTH) @@ -127,11 +121,11 @@ This spawner places pipe leading up to the interior door, you will need to finis var/turf/T = get_turf(src) var/obj/machinery/airlock_controller/air_cycler/AC = new(T) set_access_helper(AC) - AC.vent_link_id = VENT_ID - AC.int_door_link_id = INT_DOOR_ID - AC.ext_door_link_id = EXT_DOOR_ID - AC.int_button_link_id = INT_BTN_ID - AC.ext_button_link_id = EXT_BTN_ID + AC.vent_link_id = VENT_ID(id_to_link) + AC.int_door_link_id = INT_DOOR_ID(id_to_link) + AC.ext_door_link_id = EXT_DOOR_ID(id_to_link) + AC.int_button_link_id = INT_BTN_ID(id_to_link) + AC.ext_button_link_id = EXT_BTN_ID(id_to_link) if(interior_direction != WEST && exterior_direction != WEST) //If west wall is free, place it there AC.pixel_x -= 25 AC.pixel_y += 9 @@ -197,7 +191,7 @@ This spawner places pipe leading up to the interior door, you will need to finis A.on_construction(A.dir, initialization_directions ? initialization_directions : A.dir) if(istype(A, /obj/machinery/atmospherics/unary/vent_pump/high_volume)) var/obj/machinery/atmospherics/unary/vent_pump/high_volume/created_pump = A - created_pump.autolink_id = VENT_ID + created_pump.autolink_id = VENT_ID(id_to_link) /obj/effect/spawner/airlock/proc/set_access_helper(obj/I) var/obj/machinery/door/airlock/airlock = I @@ -320,8 +314,3 @@ This spawner places pipe leading up to the interior door, you will need to finis #undef CHAMBER_BIGGER #undef DOOR_NORMAL_PLACEMENT #undef DOOR_FLIPPED_PLACEMENT -#undef VENT_ID -#undef EXT_DOOR_ID -#undef INT_DOOR_ID -#undef EXT_BTN_ID -#undef INT_BTN_ID diff --git a/code/modules/mapping/dynamic_airlock_linker.dm b/code/modules/mapping/dynamic_airlock_linker.dm new file mode 100644 index 00000000000..3265a0d6ee6 --- /dev/null +++ b/code/modules/mapping/dynamic_airlock_linker.dm @@ -0,0 +1,131 @@ +RESTRICT_TYPE(/datum/dynamic_airlock_linker) + +/// A manager that is used on mapload to generate airlock chambers based on the +/// usage of [/obj/effect/map_effect/dynamic_airlock] helpers. These helpers +/// make up the "zone" of an airlock chamber, as well as indicate which airlocks +/// are exterior or interior, what access should be applied to the doors and +/// controls, And what buttons, vents, and airlock controllers should be linked +/// together. This is performed on Initialize of one of the related helpers. +/// Once done, all the other helpers are deleted to prevent it happening again +/// for that zone. +/datum/dynamic_airlock_linker + /// A list of [/obj/effect/map_effect/dynamic_airlock/door/interior]s to integrate into the airlock. + var/list/interior_helpers = list() + /// A list of [/obj/effect/map_effect/dynamic_airlock/door/exterior]s to integrate into the airlock. + var/list/exterior_helpers = list() + /// A collection of "all" access defines collated from any + /// [/obj/effect/map_effect/dynamic_airlock/access] helpers present in the airlock. + var/list/req_access = list() + /// A collection of "any" access defines collated from any + /// [/obj/effect/map_effect/dynamic_airlock/access] helpers present in the airlock. + var/list/req_one_access = list() + /// A list of all [/obj/machinery/airlock_controller]s found in the airlock zone. + var/list/airlock_controllers = list() + /// A list of all [/obj/machinery/atmospherics/unary/vent_pump/high_volume] vent pumps found in the airlock zone. + var/list/vent_pumps = list() + +/// Starting from an arbitrary initial helper, search out from all adjacent +/// tiles and find all other helpers that are part of this zone. +/// +/// Right now this is a (relatively) busy proc that can't leave any setup to +/// the Initialize of any helpers in its zone, because airlock controllers need +/// all of their airlocks etc known when linkage occurs, which is in +/// LateInitialize. I'm not sure if that's something that can be "fixed". +/datum/dynamic_airlock_linker/proc/extend_zone(obj/effect/map_effect/dynamic_airlock/helper, list/visited_helpers) + if(helper in visited_helpers) + return + + visited_helpers |= helper + for(var/atom/A in get_turf(helper)) + helper.collect_sibling_item(A) + + helper.collect_neighbor_helpers() + + if(length(helper.sibling_items)) + for(var/atom/sibling_item as anything in helper.sibling_items) + if(istype(sibling_item, /obj/machinery/airlock_controller)) + airlock_controllers |= sibling_item + if(istype(sibling_item, /obj/machinery/atmospherics/unary/vent_pump)) + vent_pumps |= sibling_item + + if(istype(helper, /obj/effect/map_effect/dynamic_airlock/door/interior)) + interior_helpers |= helper + if(istype(helper, /obj/effect/map_effect/dynamic_airlock/door/exterior)) + exterior_helpers |= helper + + consume_access_helpers(helper) + + for(var/obj/effect/map_effect/dynamic_airlock/neighbor in helper.neighbor_helpers) + extend_zone(neighbor, visited_helpers) + +/// Use all the information discovered about the airlock zone to link up the +/// included airlock controllers, buttons, airlocks, and vent pumps. Make sure +/// that all helpers found in this process are qdel'd so that no other helper +/// attempts to do the same thing with this zone. +/datum/dynamic_airlock_linker/proc/build(obj/effect/map_effect/dynamic_airlock/origin_helper) + var/list/visited_helpers = list() + var/list/interior_airlocks = list() + var/list/exterior_airlocks = list() + + extend_zone(origin_helper, visited_helpers) + var/id_to_link = UID() + + for(var/obj/machinery/atmospherics/unary/vent_pump/high_volume/vent_pump as anything in vent_pumps) + vent_pump.autolink_id = VENT_ID(id_to_link) + + for(var/obj/effect/map_effect/dynamic_airlock/door/door_helper as anything in interior_helpers) + if(!door_helper.airlock) + stack_trace("dynamic airlock interior door helper without a door at [COORD(door_helper)]") + + door_helper.assign_ids(INT_BTN_ID(id_to_link), INT_DOOR_ID(id_to_link)) + door_helper.assign_access(src) + interior_airlocks |= door_helper.airlock.UID() + for(var/obj/effect/map_effect/dynamic_airlock/door/door_helper as anything in exterior_helpers) + if(!door_helper.airlock) + stack_trace("dynamic airlock exterior door helper without a door at [COORD(door_helper)]") + + door_helper.assign_ids(EXT_BTN_ID(id_to_link), EXT_DOOR_ID(id_to_link)) + door_helper.assign_access(src) + exterior_airlocks |= door_helper.airlock.UID() + + for(var/obj/machinery/airlock_controller/controller as anything in airlock_controllers) + controller.vent_link_id = VENT_ID(id_to_link) + + controller.int_door_link_id = INT_DOOR_ID(id_to_link) + controller.int_button_link_id = INT_BTN_ID(id_to_link) + + controller.ext_door_link_id = EXT_DOOR_ID(id_to_link) + controller.ext_button_link_id = EXT_BTN_ID(id_to_link) + + controller.req_access = req_access + controller.req_one_access = req_one_access + + // despite airlock controllers looking this up in GLOB.airlocks in + // LateInitialize, we need to hold their hand here because *we're* + // (typically) in Initialize, so not all relevant airlocks may have been + // added to GLOB.airlocks yet. + controller.interior_doors = interior_airlocks.Copy() + controller.exterior_doors = exterior_airlocks.Copy() + + QDEL_LIST_CONTENTS(interior_helpers) + QDEL_LIST_CONTENTS(exterior_helpers) + QDEL_LIST_CONTENTS(visited_helpers) + + airlock_controllers.Cut() + interior_airlocks.Cut() + exterior_airlocks.Cut() + vent_pumps.Cut() + + +/// Find all the [/obj/effect/mapping_helpers/airlock/access] helpers on the +/// passed in helper's tile, and add them to the list of accesses we'll assign +/// to the linked objects later. Make sure that all mapping helpers found in +/// this process are qdel'd so they don't attempt to assign access to anything +/// else later. +/datum/dynamic_airlock_linker/proc/consume_access_helpers(obj/effect/map_effect/dynamic_airlock/helper) + for(var/obj/effect/mapping_helpers/airlock/access/any/any_helper as anything in get_turf(helper)) + req_one_access |= any_helper.access + qdel(any_helper) + for(var/obj/effect/mapping_helpers/airlock/access/all/all_helper as anything in get_turf(helper)) + req_access |= all_helper.access + qdel(all_helper) diff --git a/code/modules/mapping/dynamic_airlocks.dm b/code/modules/mapping/dynamic_airlocks.dm new file mode 100644 index 00000000000..82103f70697 --- /dev/null +++ b/code/modules/mapping/dynamic_airlocks.dm @@ -0,0 +1,82 @@ +/// A mapping helper that defines the zone of a dynamically arranged airlock +/// chamber. This can be used as an alternative to +/// [/obj/effect/spawner/airlock]s. +/// +/// The disadvantage compared to airlock spawners is that all related buttons, +/// airlock controllers, doors, vent pumps and piping must be manually mapped +/// in. The advantages are that chambers of any arbitrary size and shape can be +/// created, and that maps using these helpers instead of the airlock spawners +/// can have the RandomOrientation mapmanip applied to them with confidence that +/// the airlock chambers will be properly constructed, no matter what the +/// orientation of the map is. +/obj/effect/map_effect/dynamic_airlock + icon = 'icons/effects/mapping_helpers.dmi' + icon_state = "airlock_zone" + name = "dynamic airlock zone" + layer = POINT_LAYER + var/list/sibling_items + var/list/neighbor_helpers + var/list/valid_siblings = list( + /obj/machinery/airlock_controller/air_cycler, + /obj/machinery/atmospherics/unary/vent_pump/high_volume, + ) + +/obj/effect/map_effect/dynamic_airlock/Initialize(mapload) + ..() + + . = INITIALIZE_HINT_QDEL + // One helper out of all the connected ones will actually set everything up + // and qdel all the connected ones so the linker doesn't attempt to do its + // thing more than once per zone + if(QDELETED(src)) + return + + var/datum/dynamic_airlock_linker/linker = new() + linker.build(src) + +/obj/effect/map_effect/dynamic_airlock/proc/collect_sibling_item(atom/A) + if(is_type_in_list(A, valid_siblings)) + LAZYADD(sibling_items, A) + +/// Look around us in a 1 tile range and aggregate all the adjacent helpers. +/obj/effect/map_effect/dynamic_airlock/proc/collect_neighbor_helpers() + var/turf/center = get_turf(src) + for(var/turf/T as anything in RANGE_EDGE_TURFS(1, center)) + for(var/obj/effect/map_effect/dynamic_airlock/A as anything in T) + LAZYOR(neighbor_helpers, A) + +/// A helper used to indicate what doors are connected to an airlock zone. Comes +/// in interior and exterior variants as subtypes. +/obj/effect/map_effect/dynamic_airlock/door + var/list/buttons = list() + var/obj/machinery/door/airlock/external/airlock + +/obj/effect/map_effect/dynamic_airlock/door/proc/assign_access(datum/dynamic_airlock_linker/linker) + for(var/obj/machinery/access_button/button in buttons) + button.req_access = linker.req_access + button.req_one_access = linker.req_one_access + + airlock.req_access = linker.req_access + airlock.req_one_access = linker.req_one_access + +/obj/effect/map_effect/dynamic_airlock/door/proc/assign_ids(btn_id, door_id) + for(var/obj/machinery/access_button/button as anything in buttons) + button.autolink_id = btn_id + + airlock.id_tag = door_id + airlock.lock() + +/obj/effect/map_effect/dynamic_airlock/door/collect_sibling_item(atom/A) + . = ..() + if(istype(A, /obj/machinery/door/airlock/external)) + airlock = A + if(istype(A, /obj/machinery/access_button)) + buttons |= A + +/obj/effect/map_effect/dynamic_airlock/door/interior + name = "dynamic airlock interior door" + icon_state = "airlock_interior" + +/obj/effect/map_effect/dynamic_airlock/door/exterior + name = "dynamic airlock exterior door" + icon_state = "airlock_exterior" diff --git a/icons/effects/mapping_helpers.dmi b/icons/effects/mapping_helpers.dmi index 3de45ba567d..c8a0845528c 100644 Binary files a/icons/effects/mapping_helpers.dmi and b/icons/effects/mapping_helpers.dmi differ diff --git a/paradise.dme b/paradise.dme index 31d8b28e142..09a306d4dcf 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2212,6 +2212,8 @@ #include "code\modules\lighting\lighting_turf.dm" #include "code\modules\mapping\access_helpers.dm" #include "code\modules\mapping\base_map_datum.dm" +#include "code\modules\mapping\dynamic_airlock_linker.dm" +#include "code\modules\mapping\dynamic_airlocks.dm" #include "code\modules\mapping\mapping_helpers.dm" #include "code\modules\mapping\merge_conflicts.dm" #include "code\modules\mapping\station_datums.dm" diff --git a/rust/src/mapmanip/mod.rs b/rust/src/mapmanip/mod.rs index f9f43bbc108..5536c78a378 100644 --- a/rust/src/mapmanip/mod.rs +++ b/rust/src/mapmanip/mod.rs @@ -234,40 +234,70 @@ fn rotate_cable(dir_i: i32, rotation: &MapRotation) -> i32 { } } -fn directional_mapper_rotate(path: String, rotation: &MapRotation) -> String { +fn directional_rotate(path: String, rotation: &MapRotation) -> String { match rotation { MapRotation::None => path, MapRotation::Clockwise90 => { - if path.ends_with("/directional/north") { - path.replace("/directional/north", "/directional/east") - } else if path.ends_with("/directional/south") { - path.replace("/directional/south", "/directional/west") - } else if path.ends_with("/directional/east") { - path.replace("/directional/east", "/directional/south") + if path.ends_with("/north") { + path.replace("/north", "/east") + } else if path.ends_with("/south") { + path.replace("/south", "/west") + } else if path.ends_with("/east") { + path.replace("/east", "/south") + } else if path.ends_with("/west") { + path.replace("/west", "/north") + } else if path.ends_with("/northeast") { + path.replace("/northeast", "/southeast") + } else if path.ends_with("/northwest") { + path.replace("/northwest", "/northeast") + } else if path.ends_with("/southeast") { + path.replace("/southeast", "/southwest") + } else if path.ends_with("/southwest") { + path.replace("/southwest", "/northwest") } else { - path.replace("/directional/west", "/directional/north") + path } } MapRotation::Clockwise180 => { - if path.ends_with("/directional/north") { - path.replace("/directional/north", "/directional/south") - } else if path.ends_with("/directional/south") { - path.replace("/directional/south", "/directional/north") - } else if path.ends_with("/directional/east") { - path.replace("/directional/east", "/directional/west") + if path.ends_with("/north") { + path.replace("/north", "/south") + } else if path.ends_with("/south") { + path.replace("/south", "/north") + } else if path.ends_with("/east") { + path.replace("/east", "/west") + } else if path.ends_with("/west") { + path.replace("/west", "/east") + } else if path.ends_with("/northeast") { + path.replace("/northeast", "/southwest") + } else if path.ends_with("/northwest") { + path.replace("/northwest", "/southeast") + } else if path.ends_with("/southeast") { + path.replace("/southeast", "/northwest") + } else if path.ends_with("/southwest") { + path.replace("/southwest", "/northeast") } else { - path.replace("/directional/west", "/directional/east") + path } } MapRotation::Clockwise270 => { - if path.ends_with("/directional/north") { - path.replace("/directional/north", "/directional/west") - } else if path.ends_with("/directional/south") { - path.replace("/directional/south", "/directional/east") - } else if path.ends_with("/directional/east") { - path.replace("/directional/east", "/directional/north") + if path.ends_with("/north") { + path.replace("/north", "/west") + } else if path.ends_with("/south") { + path.replace("/south", "/east") + } else if path.ends_with("/east") { + path.replace("/east", "/north") + } else if path.ends_with("/west") { + path.replace("/west", "/south") + } else if path.ends_with("/northeast") { + path.replace("/northeast", "/northwest") + } else if path.ends_with("/northwest") { + path.replace("/northwest", "/southwest") + } else if path.ends_with("/southeast") { + path.replace("/southeast", "/northeast") + } else if path.ends_with("/southwest") { + path.replace("/southwest", "/southeast") } else { - path.replace("/directional/west", "/directional/south") + path } } } @@ -342,8 +372,8 @@ fn mapmanip_orientation_randomize(map: &mut GridMap) -> eyre::Result<()> { for t in map.grid.values_mut() { t.prefabs.iter_mut().for_each(|f| { - if f.path.contains("/directional/") { - f.path = directional_mapper_rotate(f.path.to_string(), rotation); + if f.path.contains("/directional/") || f.path.contains("/offset/") { + f.path = directional_rotate(f.path.to_string(), rotation); } else if f.path.starts_with("/obj/structure/cable") { let cable_dirs = f .vars diff --git a/rustlibs_515.dll b/rustlibs_515.dll index e113234c59e..c637067d43a 100644 Binary files a/rustlibs_515.dll and b/rustlibs_515.dll differ diff --git a/rustlibs_515_prod.dll b/rustlibs_515_prod.dll index 685066e1963..6ebbf7d5695 100644 Binary files a/rustlibs_515_prod.dll and b/rustlibs_515_prod.dll differ diff --git a/rustlibs_516.dll b/rustlibs_516.dll index 621fc86ff05..3b4ef7d03c8 100644 Binary files a/rustlibs_516.dll and b/rustlibs_516.dll differ diff --git a/rustlibs_516_prod.dll b/rustlibs_516_prod.dll index 3fe5ef23c76..ab03fa796e6 100644 Binary files a/rustlibs_516_prod.dll and b/rustlibs_516_prod.dll differ diff --git a/tools/ci/librustlibs_ci_515.so b/tools/ci/librustlibs_ci_515.so index a962da729c4..a15d87fe489 100644 Binary files a/tools/ci/librustlibs_ci_515.so and b/tools/ci/librustlibs_ci_515.so differ diff --git a/tools/ci/librustlibs_ci_516.so b/tools/ci/librustlibs_ci_516.so index 46756f8f404..eb97862d752 100644 Binary files a/tools/ci/librustlibs_ci_516.so and b/tools/ci/librustlibs_ci_516.so differ