From 59d7d4411d20e20ccaf634c0c426b59972670d99 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:17:53 -0400 Subject: [PATCH 1/2] shuttle templates and some ports from shuttles branch (#6755) to enable new shuttles to be made. --- citadel.dme | 12 +- code/__DEFINES/_flags/turf_flags.dm | 4 +- code/__DEFINES/_planes+layers.dm | 1 + code/__HELPERS/game/turfs/blocks.dm | 83 ++ code/__HELPERS/game/turfs/line.dm | 2 +- code/__HELPERS/game/turfs/offsets.dm | 2 +- .../subsystem/mapping/reservations.dm | 2 +- code/game/area/area.dm | 4 + code/game/objects/effects/misc.dm | 10 - code/modules/mapping/turf_reservation.dm | 19 +- .../shuttles/effects/shuttle_landing.dm | 30 + code/modules/shuttles/shuttle.dm | 3 - code/modules/shuttles/shuttle/shuttle.dm | 37 + .../shuttles/shuttle/shuttle_anchor.dm | 135 ++ code/modules/shuttles/shuttle/shuttle_area.dm | 42 + .../shuttles/shuttle/shuttle_descriptor.dm | 35 + code/modules/shuttles/shuttle/shuttle_port.dm | 188 +++ .../shuttles/shuttle/shuttle_template.dm | 143 ++ icons/effects/effects.dmi | Bin 444844 -> 446134 bytes icons/modules/shuttles/bounding_3x3.dmi | Bin 0 -> 2784 bytes .../shuttles/effects/shuttle_landing.dmi | Bin 0 -> 405 bytes icons/modules/shuttles/shuttle_anchor.dmi | Bin 0 -> 1999 bytes icons/modules/shuttles/shuttle_anchor_2x2.dmi | Bin 0 -> 3241 bytes icons/modules/shuttles/shuttle_anchor_3x3.dmi | Bin 0 -> 5015 bytes maps/shuttles/README.md | 33 + .../nanotrasen/drone_prototype.dm | 17 + .../nanotrasen/drone_prototype.dmm | 412 ++++++ .../corporations/nanotrasen/sci_vector.dm | 34 + .../corporations/nanotrasen/sci_vector.dmm | 1233 +++++++++++++++++ 29 files changed, 2459 insertions(+), 22 deletions(-) create mode 100644 code/__HELPERS/game/turfs/blocks.dm create mode 100644 code/modules/shuttles/effects/shuttle_landing.dm create mode 100644 code/modules/shuttles/shuttle/shuttle.dm create mode 100644 code/modules/shuttles/shuttle/shuttle_anchor.dm create mode 100644 code/modules/shuttles/shuttle/shuttle_area.dm create mode 100644 code/modules/shuttles/shuttle/shuttle_descriptor.dm create mode 100644 code/modules/shuttles/shuttle/shuttle_port.dm create mode 100644 code/modules/shuttles/shuttle/shuttle_template.dm create mode 100644 icons/modules/shuttles/bounding_3x3.dmi create mode 100644 icons/modules/shuttles/effects/shuttle_landing.dmi create mode 100644 icons/modules/shuttles/shuttle_anchor.dmi create mode 100644 icons/modules/shuttles/shuttle_anchor_2x2.dmi create mode 100644 icons/modules/shuttles/shuttle_anchor_3x3.dmi create mode 100644 maps/shuttles/README.md create mode 100644 maps/shuttles/factions/corporations/nanotrasen/drone_prototype.dm create mode 100644 maps/shuttles/factions/corporations/nanotrasen/drone_prototype.dmm create mode 100644 maps/shuttles/factions/corporations/nanotrasen/sci_vector.dm create mode 100644 maps/shuttles/factions/corporations/nanotrasen/sci_vector.dmm diff --git a/citadel.dme b/citadel.dme index 0da2380ea275..e308edc24ad8 100644 --- a/citadel.dme +++ b/citadel.dme @@ -399,6 +399,7 @@ #include "code\__HELPERS\files\walk.dm" #include "code\__HELPERS\game\depth.dm" #include "code\__HELPERS\game\combat\arc.dm" +#include "code\__HELPERS\game\turfs\blocks.dm" #include "code\__HELPERS\game\turfs\line.dm" #include "code\__HELPERS\game\turfs\offsets.dm" #include "code\__HELPERS\graphs\astar.dm" @@ -3497,10 +3498,10 @@ #include "code\modules\mob\logout.dm" #include "code\modules\mob\mob-damage.dm" #include "code\modules\mob\mob-defense.dm" +#include "code\modules\mob\mob-iff.dm" #include "code\modules\mob\mob-keybind-triggers.dm" #include "code\modules\mob\mob.dm" #include "code\modules\mob\mob_defines.dm" -#include "code\modules\mob\mob-iff.dm" #include "code\modules\mob\mob_helpers.dm" #include "code\modules\mob\mob_transformation_simple.dm" #include "code\modules\mob\mobility.dm" @@ -4705,6 +4706,13 @@ #include "code\modules\shuttles\shuttles_vr.dm" #include "code\modules\shuttles\shuttles_web.dm" #include "code\modules\shuttles\web_datums.dm" +#include "code\modules\shuttles\effects\shuttle_landing.dm" +#include "code\modules\shuttles\shuttle\shuttle.dm" +#include "code\modules\shuttles\shuttle\shuttle_anchor.dm" +#include "code\modules\shuttles\shuttle\shuttle_area.dm" +#include "code\modules\shuttles\shuttle\shuttle_descriptor.dm" +#include "code\modules\shuttles\shuttle\shuttle_port.dm" +#include "code\modules\shuttles\shuttle\shuttle_template.dm" #include "code\modules\species\abilites.dm" #include "code\modules\species\character_species.dm" #include "code\modules\species\physiology.dm" @@ -5289,6 +5297,8 @@ #include "maps\sectors\virgo4_140\virgo4_140.dm" #include "maps\sectors\wasteland_140\wasteland_140.dm" #include "maps\sectors\wasteland_192\wasteland_192.dm" +#include "maps\shuttles\factions\corporations\nanotrasen\drone_prototype.dm" +#include "maps\shuttles\factions\corporations\nanotrasen\sci_vector.dm" #include "maps\submaps\_helpers.dm" #include "maps\submaps\_readme.dm" #include "maps\submaps\level_specific\debrisfield_vr\debrisfield_things.dm" diff --git a/code/__DEFINES/_flags/turf_flags.dm b/code/__DEFINES/_flags/turf_flags.dm index 4ebcf6344bbd..41ea17828880 100644 --- a/code/__DEFINES/_flags/turf_flags.dm +++ b/code/__DEFINES/_flags/turf_flags.dm @@ -2,7 +2,7 @@ /// This is used in literally one place, turf.dm, to block ethwereal jaunt. #define NO_JAUNT (1<<0) /// Unused reservation turf -#define UNUSED_RESERVATION_TURF (1<<2) +#define TURF_FLAG_UNUSED_RESERVATION (1<<2) /// queued for planet turf addition #define TURF_PLANET_QUEUED (1<<3) /// registered to a planet @@ -28,7 +28,7 @@ DEFINE_BITFIELD(turf_flags, list( BITFIELD(NO_JAUNT), - BITFIELD(UNUSED_RESERVATION_TURF), + BITFIELD(TURF_FLAG_UNUSED_RESERVATION), BITFIELD(TURF_PLANET_QUEUED), BITFIELD(TURF_PLANET_REGISTERED), BITFIELD(TURF_ZONE_REBUILD_QUEUED), diff --git a/code/__DEFINES/_planes+layers.dm b/code/__DEFINES/_planes+layers.dm index b38ab1a0fdd9..4dad67ea7f6a 100644 --- a/code/__DEFINES/_planes+layers.dm +++ b/code/__DEFINES/_planes+layers.dm @@ -329,6 +329,7 @@ */ #define DEBUG_PLANE 23 #define DEBUG_LAYER_AREA_OVERLAYS 100 +#define DEBUG_LAYER_SHUTTLE_MARKERS 500 /** *! -- Ghost Plane diff --git a/code/__HELPERS/game/turfs/blocks.dm b/code/__HELPERS/game/turfs/blocks.dm new file mode 100644 index 000000000000..d0a5e064a0a2 --- /dev/null +++ b/code/__HELPERS/game/turfs/blocks.dm @@ -0,0 +1,83 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * get turfs bordering a block of turfs + * + * * returned list will be empty if distance = 0 + * * returned list will have all nulls incurred by turfs being outside world border + * * returned list **has no particular order.** + * + * @params + * * ll_x - lowerleft x + * * ll_y - lowerleft y + * * ur_x - upperright x + * * ur_y - upperright y + * * z - z level + * * distance - border distance + * + * @return list() if distance = 0, list of turfs otherwise. turfs outside of world border will be null. + */ +/proc/border_of_turf_block(ll_x, ll_y, ur_x, ur_y, z, distance) + if(distance <= 0) + return list() + . = block( + ll_x - distance, + ll_y - distance, + z, + ll_x - 1, + ur_y + distance, + ) + block( + ur_x + 1, + ll_y - distance, + z, + ur_x + distance, + ur_y + distance, + ) + block( + ll_x, + ur_y + 1, + z, + ur_x, + ur_y + distance, + ) + block( + ll_x, + ll_y - distance, + z, + ur_x, + ll_y - 1, + ) + +/** + * get turfs bordering a block of turfs + * + * * returned list will be empty if distance = 0 + * * returned list will have all nulls incurred by turfs being outside world border + * * returned list is in clockwise order from the **upper left** turf, spiralling outwards from there. + * + * @params + * * ll_x - lowerleft x + * * ll_y - lowerleft y + * * ur_x - upperright x + * * ur_y - upperright y + * * z - z level + * * distance - border distance + * + * @return list() if distance = 0, list of turfs otherwise. turfs outside of world border will be null. + */ +/proc/border_of_turf_block_spiral_outwards_clockwise(ll_x, ll_y, ur_x, ur_y, z, distance) + if(distance <= 0) + return list() + . = list() + for(var/radius in distance) + // gather top left to right + for(var/x in (ll_x - radius) to (ur_x + radius)) + . += locate(x, ur_y + radius, z) + // gather right top to bottom excluding top and bottom turf + for(var/y in (ur_y + radius - 1) to (ll_y - radius + 1) step -1) + . += locate(ur_x + radius, y, z) + // gather bottom right to left + for(var/x in (ur_x + radius) to (ll_x - radius) step -1) + . += locate(x, ll_y - radius, z) + // gather left bottom to top excluding top and bottom turf + for(var/y in (ll_y - radius + 1) to (ur_y + radius - 1)) + . += locate(ll_x - radius, y, z) diff --git a/code/__HELPERS/game/turfs/line.dm b/code/__HELPERS/game/turfs/line.dm index c07645d3eb27..59a213720cd8 100644 --- a/code/__HELPERS/game/turfs/line.dm +++ b/code/__HELPERS/game/turfs/line.dm @@ -1,5 +1,5 @@ //* This file is explicitly licensed under the MIT license. *// -//* Copyright (c) 2024 silicons *// +//* Copyright (c) 2024 Citadel Station Developers *// /** * line drawing algorithm diff --git a/code/__HELPERS/game/turfs/offsets.dm b/code/__HELPERS/game/turfs/offsets.dm index cd206ffe0742..df4508beb427 100644 --- a/code/__HELPERS/game/turfs/offsets.dm +++ b/code/__HELPERS/game/turfs/offsets.dm @@ -1,5 +1,5 @@ //* This file is explicitly licensed under the MIT license. *// -//* Copyright (c) 2024 silicons *// +//* Copyright (c) 2024 Citadel Station Developers *// /** * get coordinate and direction tuple when entity is moved relative with a 'block' movement, diff --git a/code/controllers/subsystem/mapping/reservations.dm b/code/controllers/subsystem/mapping/reservations.dm index b9338097e3df..cd329e039ca7 100644 --- a/code/controllers/subsystem/mapping/reservations.dm +++ b/code/controllers/subsystem/mapping/reservations.dm @@ -99,7 +99,7 @@ /datum/controller/subsystem/mapping/proc/reserve_turfs(list/turf/turfs) for(var/turf/T as anything in turfs) T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE) - T.turf_flags |= UNUSED_RESERVATION_TURF + T.turf_flags |= TURF_FLAG_UNUSED_RESERVATION CHECK_TICK // todo: area.assimilate_turfs? reservation_unallocated_area.contents.Add(turfs) diff --git a/code/game/area/area.dm b/code/game/area/area.dm index cb17cde47363..e0a0850c0318 100644 --- a/code/game/area/area.dm +++ b/code/game/area/area.dm @@ -53,6 +53,10 @@ /// default initial gas mix var/initial_gas_mix = GAS_STRING_STP + //* Identity *// + /// player-facing name, overrides name when / if necessary. + var/display_name + //? nightshift /// nightshift level /// in general, nightshift must be at or above this level for it to proc on areas. diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index d03e8a0d3c43..d5befd0dc5ad 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -38,16 +38,6 @@ . = ..() animate(src, alpha = 0, time = time_to_die - 1) -/obj/effect/temporary_effect/shuttle_landing - name = "shuttle landing" - desc = "You better move if you don't want to go splat!" - icon_state = "shuttle_warning_still" - time_to_die = 4.9 SECONDS - -/obj/effect/temporary_effect/shuttle_landing/Initialize(mapload) - flick("shuttle_warning", src) // flick() forces the animation to always begin at the start. - . = ..() - // The manifestation of Zeus's might. Or just a really unlucky day. // This is purely a visual effect, this isn't the part of the code that hurts things. /obj/effect/temporary_effect/lightning_strike diff --git a/code/modules/mapping/turf_reservation.dm b/code/modules/mapping/turf_reservation.dm index 5404480cfd07..d58ff598bd11 100644 --- a/code/modules/mapping/turf_reservation.dm +++ b/code/modules/mapping/turf_reservation.dm @@ -75,6 +75,19 @@ release() return ..() +/datum/turf_reservation/proc/get_approximately_center_turf() + return locate( + bottom_left_coords[1] + floor(top_right_coords[1] - bottom_left_coords[1]), + bottom_left_coords[2] + floor(top_right_coords[2] - bottom_left_coords[2]), + bottom_left_coords[3], + ) + +/datum/turf_reservation/proc/is_atom_inside(atom/A) + A = get_turf(A) + return A.z == bottom_left_coords[3] && \ + A.x >= bottom_left_coords[1] && A.x <= top_right_coords[1] && \ + A.y >= bottom_left_coords[2] && A.y <= top_right_coords[2] + /datum/turf_reservation/proc/release() if(border) SSmapping.reserve_turfs(block(locate( @@ -170,7 +183,7 @@ 1 + (inner_y - 1) * TURF_CHUNK_RESOLUTION, level_index, ) - if(!(checking.turf_flags & UNUSED_RESERVATION_TURF)) + if(!(checking.turf_flags & TURF_FLAG_UNUSED_RESERVATION)) passing = FALSE break if(!passing) @@ -245,7 +258,7 @@ SSmapping.reservation_blocking_op = FALSE return FALSE for(var/turf/T as anything in final) - T.turf_flags &= ~UNUSED_RESERVATION_TURF + T.turf_flags &= ~TURF_FLAG_UNUSED_RESERVATION if(T.type != turf_type) T.ChangeTurf(turf_type, turf_type) @@ -262,7 +275,7 @@ // todo: take_turfs src.border_area.contents.Add(final_border) for(var/turf/T as anything in final_border) - T.turf_flags &= ~UNUSED_RESERVATION_TURF + T.turf_flags &= ~TURF_FLAG_UNUSED_RESERVATION // get just the first layer, but also init them at the same time var/list/turf/final_immediate_border // left diff --git a/code/modules/shuttles/effects/shuttle_landing.dm b/code/modules/shuttles/effects/shuttle_landing.dm new file mode 100644 index 000000000000..94469c5609d8 --- /dev/null +++ b/code/modules/shuttles/effects/shuttle_landing.dm @@ -0,0 +1,30 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +// todo: maybe orchestrate this with lists and timers on shuttle_transit_cycle? +/obj/effect/temporary_effect/shuttle_landing + name = "shuttle landing" + desc = "A massive entity is about to land here. You should not be here." + icon = 'icons/modules/shuttles/effects/shuttle_landing.dmi' + icon_state = "still" + time_to_die = 4.9 SECONDS + +/obj/effect/temporary_effect/shuttle_landing/Initialize(mapload, time_to_dock) + if(!isnull(time_to_dock)) + time_to_die = time_to_dock + run_animation() + return ..() + +/obj/effect/temporary_effect/shuttle_landing/proc/run_animation() + var/half_time = time_to_die / 2 + + var/matrix/using_matrix = matrix() + using_matrix.Scale(0.1, 0.1) + + transform = using_matrix + alpha = 75 + + using_matrix.Scale(10, 10) + animate(src, time = half_time, transform = using_matrix, alpha = 150) + + animate(src, time = half_time, alpha = 255) diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm index c1add76a05a9..604792f7ba2a 100644 --- a/code/modules/shuttles/shuttle.dm +++ b/code/modules/shuttles/shuttle.dm @@ -1,7 +1,6 @@ //shuttle moving state defines are in setup.dm /datum/shuttle - var/name = "" var/warmup_time = 0 var/moving_status = SHUTTLE_IDLE @@ -14,8 +13,6 @@ var/category = /datum/shuttle var/multiz = 0 // How many multiz levels, starts at 0 TODO Leshana - Are we porting this? - var/ceiling_type = /turf/simulated/shuttle_ceiling // Type path of turf to roof over the shuttle when at multi-z landmarks. Ignored if null. - var/sound_takeoff = 'sound/effects/shuttles/shuttle_takeoff.ogg' var/sound_landing = 'sound/effects/shuttles/shuttle_landing.ogg' diff --git a/code/modules/shuttles/shuttle/shuttle.dm b/code/modules/shuttles/shuttle/shuttle.dm new file mode 100644 index 000000000000..e4dab761d4c1 --- /dev/null +++ b/code/modules/shuttles/shuttle/shuttle.dm @@ -0,0 +1,37 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * # Shuttles + * + * Core datum for shuttles. + * + * ## Controllers + * + * All shuttle behaviors are now in controllers whenever possible. The base datum just handles the actual shuttle itself. + * Moving to transit and staying in transit? That's a controller thing. Temporary dynamic transit? That's a controller thing, too. + * + * todo: nestable-shuttle support ? e.g. transport ship on a shuttle ; this is not optimal for performance but sure is cool + * todo: multi-z shuttles; is this even possible? very long term. + * todo: areas is a shit system. this is probably not fixable, because how else would we do bounding boxes? + * todo: it would sure be nice to be able to dynamically expand shuttles in-game though; probably a bad idea too. + * todo: serialize/deserialize, but should it be on this side or the map tempalte side? we want save/loadable. + */ +/datum/shuttle + //* Intrinsics *// + /// our unique template id; this is *not* our ID and is *not* unique! + var/template_id + /// our descriptor instance; this is what determines how we act + /// to our controller, as well as things like overmaps. + var/datum/shuttle_descriptor/descriptor + + //* Identity *// + /// real / code name + var/name = "Unnamed Shuttle" + /// description for things like admin interfaces + var/desc = "Some kind of shuttle. The coder forgot to set this." + + //* Structure *// + /// if set, we generate a ceiling above the shuttle of this type, on the bottom of the turf stack. + // todo: vv hook this + var/ceiling_type = /turf/simulated/shuttle_ceiling diff --git a/code/modules/shuttles/shuttle/shuttle_anchor.dm b/code/modules/shuttles/shuttle/shuttle_anchor.dm new file mode 100644 index 000000000000..4f3051e4cd08 --- /dev/null +++ b/code/modules/shuttles/shuttle/shuttle_anchor.dm @@ -0,0 +1,135 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * the physical shuttle object + * + * for aligned docks, we align the direction and the tile to the shuttle dock. + * + * ## Bounds + * + * size_x, size_y describes our total bounding box size when facing NORTH. + * offset_x, offset_y describes where the anchor is when facing NORTH. + * + * The anchor is always aligned to the top left, with no offsets, in this way. + * When rotated it is where it would be when rotated counterclockwise to the new position. + * + * For a size_x, size_y of 6, 4: + * + * offset_x, offset_y = 0, dir NORTH + * + * ^00000 + * 000000 + * 000000 + * 000000 + * + * offset_x, offset_y = 0, dir SOUTH + * + * 000000 + * 000000 + * 000000 + * 00000V + * + * offset_x, offset_y = 0, dir WEST + * + * 0000 + * 0000 + * 0000 + * 0000 + * 0000 + * <000 + * + * offset_x, offset_y = 3, -1, dir NORTH + * + * 000000 + * 000^00 + * 000000 + * 000000 + * + * offset_x, offset_y = 3, -1, dir SOUTH + * + * 000000 + * 000000 + * 00V000 + * 000000 + * + * offset_x, offset_y = 3, -1, dir WEST + * + * 0000 + * 0000 + * 0<00 + * 0000 + * 0000 + * 0000 + * + * Offsets can position the anchor outside. This works, albeit is a bad idea. + * + * ## Mappers + * + * * You don't need to put down anchors at all, they auto-generate. + * * If you place one anyways, it'll be respected. That said, the size will be auto-generated too. + * + * Do not mess with the variables; the init system will set them. + */ +/obj/shuttle_anchor + name = "Shuttle (uninitialized)" + desc = "Why do you see this?" + // by default this should be north. + dir = NORTH + icon = 'icons/modules/shuttles/shuttle_anchor.dmi' + icon_state = "main" + plane = DEBUG_PLANE + layer = DEBUG_LAYER_SHUTTLE_MARKERS + atom_flags = ATOM_ABSTRACT | ATOM_NONWORLD + +#ifndef CF_SHUTTLE_VISUALIZE_BOUNDING_BOXES + invisibility = INVISIBILITY_ABSTRACT +#else + invisibility = INVISIBILITY_NONE +#endif + + /// shuttle datum + var/tmp/datum/shuttle/shuttle + + /// see main documentation + var/tmp/size_x + /// see main documentation + var/tmp/size_y + /// see main documentation + var/tmp/offset_x + /// see main documentation + var/tmp/offset_y + + /// are we moving right now? + var/tmp/anchor_moving = FALSE + +// This file is WIP, and is just here so mappers can start using them. + +//* Movement Hooks ; We don't allow normal movement. *// + +/obj/shuttle_anchor/forceMove() + CRASH("attempted to forcemove a shuttle anchor") + +/obj/shuttle_anchor/setDir(ndir) + if(!anchor_moving) + CRASH("attempted to setDir an anchor") + return ..() + +/obj/shuttle_anchor/abstract_move(atom/new_loc) + if(!anchor_moving) + CRASH("attempted to abstract_move a shuttle anchor") + return ..() + +//* Grid Hooks ; Shuttle manually moves us. *// + +/obj/shuttle_anchor/grid_move(grid_flags, turf/new_turf) + return + +/obj/shuttle_anchor/grid_after(grid_flags, rotation_angle, list/late_call_hooks) + return + +/obj/shuttle_anchor/grid_collect(grid_flags, turf/new_turf, loc_opinion) + return + +/obj/shuttle_anchor/grid_finished(grid_flags, rotation_angle) + return diff --git a/code/modules/shuttles/shuttle/shuttle_area.dm b/code/modules/shuttles/shuttle/shuttle_area.dm new file mode 100644 index 000000000000..1aabc5e4c34e --- /dev/null +++ b/code/modules/shuttles/shuttle/shuttle_area.dm @@ -0,0 +1,42 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * shuttle areas + */ +/area/shuttle + unique = FALSE + /// will be assigned the shuttle's ref post-init + var/datum/shuttle/shuttle + +/area/shuttle/proc/before_bounds_initializing(datum/shuttle/from_shuttle, datum/turf_reservation/from_reservation, datum/shuttle_template/from_template) + shuttle = from_shuttle + +/** + * autodetecting area + */ +/area/shuttle/auto + /// [name] [count?] [descriptor?] + var/count + /// [name] [count?] [descriptor?] + var/descriptor = "Compartment" + +/area/shuttle/auto/before_bounds_initializing(datum/shuttle/from_shuttle, datum/turf_reservation/from_reservation, datum/shuttle_template/from_template) + // todo: shuttle + +/area/shuttle/auto/proc/auto_name_instance(real_name, display_name) + src.name = "[real_name][count && " [count]"][descriptor && " [descriptor]"]" + src.display_name = display_name + +/area/shuttle/auto/primary + count = "Primary" + +/area/shuttle/auto/secondary + count = "Secondary" + +/area/shuttle/auto/tertiary + count = "Tertiary" + +/area/shuttle/auto/one_single_area + count = "" + descriptor = "" diff --git a/code/modules/shuttles/shuttle/shuttle_descriptor.dm b/code/modules/shuttles/shuttle/shuttle_descriptor.dm new file mode 100644 index 000000000000..7ebfbdfc003c --- /dev/null +++ b/code/modules/shuttles/shuttle/shuttle_descriptor.dm @@ -0,0 +1,35 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * while /datum/shuttle_template describes the physical shuttle, this describes features + * like mass. + */ +/datum/shuttle_descriptor + //* Flight (overmaps / web) *// + /// mass in kilotons + // todo: in-game mass calculations? only really relevant for drone tbh + var/mass = 5 + /// if set to false, this is absolute-ly unable to land on a planet + var/allow_atmospheric_landing = TRUE + /// preferred flight orientation + /// + /// * null = use orientation at takeoff + var/preferred_orientation + + //* Jumps (ferry & moving to/from overmaps) *// + /// engine charging time when starting a move + // todo: should have support for being based on in game machinery (?) + var/jump_charging_time = 10 SECONDS + /// time spent in transit when performing a move + var/jump_move_time = 10 SECONDS + +/datum/shuttle_descriptor/clone(include_contents) + var/datum/shuttle_descriptor/clone = ..() + + clone.mass = mass + clone.allow_atmospheric_landing = allow_atmospheric_landing + clone.preferred_orientation = preferred_orientation + + clone.jump_charging_time = jump_charging_time + clone.jump_move_time = jump_move_time diff --git a/code/modules/shuttles/shuttle/shuttle_port.dm b/code/modules/shuttles/shuttle/shuttle_port.dm new file mode 100644 index 000000000000..159df194b80d --- /dev/null +++ b/code/modules/shuttles/shuttle/shuttle_port.dm @@ -0,0 +1,188 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * shuttle-side docking port; put this on airlocks + */ +/obj/shuttle_port + /// port name - used in interfaces + name = "docking port" + /// port desc - used in interfaces + desc = "A port that allows the shuttle to align to a dock." + icon = 'icons/modules/shuttles/shuttle_anchor.dmi' + icon_state = "dock" + plane = DEBUG_PLANE + layer = DEBUG_LAYER_SHUTTLE_MARKERS + atom_flags = ATOM_ABSTRACT | ATOM_NONWORLD + +#ifndef CF_SHUTTLE_VISUALIZE_BOUNDING_BOXES + invisibility = INVISIBILITY_ABSTRACT +#else + invisibility = INVISIBILITY_NONE +#endif + + /// shuttle datum + var/tmp/datum/shuttle/shuttle + + /// dock width - this is how wide the airlock/otherwise opening is. + /// + /// the port is left-aligned to the width when looking north + /// so if it's width 3, + /// we have this: + /// ^XX + /// + /// if the port is rotated, we are left-aligned to the *direction of the port*, e.g. + /// east, = + /// > + /// x + /// x + var/port_width = 1 + /// offset the port right in the width + /// + /// width 3, offset 2: + /// XX^ + /// + /// this is needed because port alignment must always be + /// exact, so things like power lines and atmos lines can be connected. + var/port_offset = 0 + /// how many tiles of 'safety' extends to both sides of the width + /// this means that an airtight seal can be formed as long as the dock accomodates the safety region, + /// even if it's too big for the width + var/port_margin = 1 + /// port id - must be unique per shuttle instance + /// the maploader will handle ID scrambling + /// + /// * if this doesn't exist, stuff that need to hook it won't work. + /// * if this isn't set, we'll assign it a random one on init + var/port_id + + /// registered shuttle hooks + var/tmp/list/datum/shuttle_hook/hooks + + /// is this the primary port? + /// if it is, this is what we align with for roundstart loading. + var/primary_port = FALSE + + /// are we moving right now? + var/tmp/port_moving = FALSE + +/obj/shuttle_port/preloading_instance(with_id) + . = ..() + port_id = SSmapping.mangled_persistent_id(port_id, with_id) + +// This file is WIP, and is just here so mappers can start using them. + +//* Movement Hooks ; We don't allow normal movement. *// + +/obj/shuttle_port/forceMove() + CRASH("attempted to forceMove a shuttle port") + +/obj/shuttle_port/setDir(ndir) + if(!port_moving) + CRASH("attempted to setDir a shuttle port") + return ..() + +/obj/shuttle_port/abstract_move(atom/new_loc) + if(!port_moving) + CRASH("attempted to abstract_move a shuttle port") + return ..() + +//* Grid Hooks ; Shuttle manually moves us. *// + +/obj/shuttle_port/grid_move(grid_flags, turf/new_turf) + return + +/obj/shuttle_port/grid_after(grid_flags, rotation_angle, list/late_call_hooks) + return + +/obj/shuttle_port/grid_collect(grid_flags, turf/new_turf, loc_opinion) + return + +/obj/shuttle_port/grid_finished(grid_flags, rotation_angle) + return + +#define SHUTTLE_PORT_PATH(PATH) \ +/obj/shuttle_port/##PATH/primary { \ + primary_port = TRUE; \ + color = "#88ff88"; \ +} \ +/obj/shuttle_port/##PATH + +/obj/shuttle_port/north + dir = NORTH + +SHUTTLE_PORT_PATH(south) + dir = SOUTH + +SHUTTLE_PORT_PATH(east) + dir = EAST + +SHUTTLE_PORT_PATH(west) + dir = WEST + +SHUTTLE_PORT_PATH(two_wide) + abstract_type = /obj/shuttle_port/two_wide + icon = 'icons/modules/shuttles/shuttle_anchor_2x2.dmi' + icon_state = "dock" + port_width = 2 + +SHUTTLE_PORT_PATH(two_wide/left_aligned) + +SHUTTLE_PORT_PATH(two_wide/left_aligned/north) + dir = NORTH + +SHUTTLE_PORT_PATH(two_wide/left_aligned/south) + dir = SOUTH + port_offset = 1 + pixel_x = -32 + +SHUTTLE_PORT_PATH(two_wide/left_aligned/east) + dir = EAST + port_offset = 1 + pixel_y = -32 + +SHUTTLE_PORT_PATH(two_wide/left_aligned/west) + dir = WEST + +SHUTTLE_PORT_PATH(two_wide/right_aligned) + +SHUTTLE_PORT_PATH(two_wide/right_aligned/north) + dir = NORTH + port_offset = 1 + pixel_x = -32 + +SHUTTLE_PORT_PATH(two_wide/right_aligned/south) + dir = SOUTH + +SHUTTLE_PORT_PATH(two_wide/right_aligned/east) + dir = EAST + +SHUTTLE_PORT_PATH(two_wide/right_aligned/west) + dir = WEST + port_offset = 1 + pixel_y = -32 + +SHUTTLE_PORT_PATH(three_wide) + icon = 'icons/modules/shuttles/shuttle_anchor_3x3.dmi' + icon_state = "dock" + port_width = 3 + +SHUTTLE_PORT_PATH(three_wide/north) + dir = NORTH + port_offset = 1 + pixel_x = -32 + +SHUTTLE_PORT_PATH(three_wide/south) + dir = SOUTH + port_offset = 1 + pixel_x = -32 + +SHUTTLE_PORT_PATH(three_wide/east) + dir = EAST + port_offset = 1 + pixel_y = -32 + +SHUTTLE_PORT_PATH(three_wide/west) + dir = WEST + port_offset = 1 + pixel_y = -32 diff --git a/code/modules/shuttles/shuttle/shuttle_template.dm b/code/modules/shuttles/shuttle/shuttle_template.dm new file mode 100644 index 000000000000..ac947798b71f --- /dev/null +++ b/code/modules/shuttles/shuttle/shuttle_template.dm @@ -0,0 +1,143 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * the shuttle templates in charge of holding definitions of shuttles. + * + * each can be instantiated multiple times unless otherwise stated. + */ +/datum/shuttle_template + abstract_type = /datum/shuttle_template + + //* Basics + /// unique ID - use snake_case, must be unique & stable, including across rounds. + /// this means hardcoded ones shouldn't be changed willy-nilly. + var/id + + //* Identity + /// Full name + var/name + /// Full description + var/desc + /// lore fluff + var/fluff + + //* File + /// absolute path to file + var/absolute_path + /// relative path to file from current directory + var/relative_path + + //* Functionality + /// our shuttle typepath + /// + /// * yeah uh you probably shouldn't mess with this unless you know what you're doing + var/shuttle_type = /datum/shuttle + /// our descriptor, used for cross-interaction with other systems + /// this should not be a cached typepath, as opposed to a directly made typepath + /// or an instance. + /// + /// * because we intentionally don't cache typepaths, anonymous typepaths are allowed **and encouraged**. + /// + /// typepaths will be initialized. + /// instances will be cloned. + var/datum/shuttle_descriptor/descriptor = /datum/shuttle_descriptor + + //* .dmm + /// should we keep parsed map once first loaded? + var/cache_parsed_map = FALSE + /// our parsed map + var/datum/dmm_parsed/parsed_map + /// direction the shuttle is facing, in the map + /// please try to map shuttles in facing north. + var/facing_dir = NORTH + +/datum/shuttle_template/New(map_resource, use_dir) + if(map_resource) + absolute_path = map_resource + facing_dir = use_dir || NORTH + else + if(relative_path && !absolute_path) + var/our_file = __FILE__ + var/our_directory = copytext_char(our_file, 1, findlasttext_char(our_file, "/")) + absolute_path = "[our_directory]/[relative_path]" + + if(cache_parsed_map) + parsed_map = new(get_file()) + +/datum/shuttle_template/proc/get_file() + return isfile(absolute_path)? absolute_path : file(absolute_path) + +/** + * Do not directly use. Use create_shuttle() on SSshuttles! + * This will not automatically register the shuttle with the subsystem. + */ +/datum/shuttle_template/proc/instance(list/datum/map_injection/map_injections) + RETURN_TYPE(/datum/shuttle) + + var/datum/dmm_parsed/parsed_map = src.parsed_map + if(isnull(parsed_map)) + parsed_map = new(get_file()) + if(cache_parsed_map) + src.parsed_map = parsed_map + + var/datum/shuttle/instance = new shuttle_type + var/width = parsed_map.width + var/height = parsed_map.height + + // make reservation + var/datum/turf_reservation/reservation = SSmapping.request_block_reservation( + width + 2, + height + 2, + /datum/turf_reservation, + ) + + // create context + var/datum/dmm_context/context = create_dmm_context() + context.mangling_id = generate_mangling_id() + for(var/datum/map_injection/injection as anything in map_injections) + context.register_injection(injection) + + // load into reservation + var/datum/dmm_context/loaded_context = parsed_map.load( + reservation.bottom_left_coords[1] + 1, + reservation.bottom_left_coords[2] + 1, + reservation.bottom_left_coords[3], + context = context, + ) + var/list/loaded_bounds = loaded_context.loaded_bounds + + // set descriptor + instance.descriptor = instance_descriptor() + + // let shuttle do black magic first + // instance.before_bounds_init(reservation, src) + + // init the bounds + SSatoms.init_map_bounds(loaded_bounds) + + // let shuttle do post-init things + // instance.after_bounds_init(reservation, src) + + // set vars on shuttle + instance.template_id = id + + return instance + +/datum/shuttle_template/proc/instance_descriptor() + if(istype(descriptor)) + return descriptor.clone() + else if(IS_ANONYMOUS_TYPEPATH(descriptor)) + return new descriptor + else if(ispath(descriptor, /datum/shuttle_descriptor)) + return new descriptor + CRASH("what? [descriptor] ([REF(descriptor)])") + +/datum/shuttle_template/proc/generate_mangling_id() + var/static/notch = 0 + if(notch >= SHORT_REAL_LIMIT) + stack_trace("how the hell are we at this number?") + return "shuttle-[++notch]-[SSmapping.round_global_descriptor]" + +/datum/map_template/shuttle + abstract_type = /datum/map_template/shuttle diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 0dca1a9633c3a563c785b28d666a54dc7cbb2686..6a7bac7c7333516350e26e1a2287edba8c394aec 100644 GIT binary patch delta 100727 zcmX`T2RN4P8$bTol8}UCh3t@QvUf&gXJ_xdxs4D)5wb(bD`am^lAa_
J`C2e=OH}xTI26`{^|G8a8;!7nTnFiPq%`(-Zd$&GdLMei
zj{#X*%QBWDA|(o}^C+*7mZBTht(Yw1S(wiA=9tUzBe>j9XX={X3J#SSM~U>&pm=X4
zF8($A
E8ttz2$K6{b_hLf@~M-DV+isAfH04VE0hSv8MC)4*9w+==gzI4#Ra$a02
zW$5}7!S>HKPTRR=nH@nm2bN03#mDpLU07cQ?t<^`fK5oX5C%ZtFv2aYQy#OFYIph}Q1X1=G1;`;H1ZzJJRD$Hw#PT*b9XjJf
zH(Hvq)JNNJlnkB;2Ti)dBFCPA1iMeA_wN1Z#^tVaW(~<<$ztKYhvKheaBy&7_cd|f
zJ{T6F5M<@@Yhq^2e0zXCf44+-wJln-Xixf|HV}}l1}sDLBu-vl$}g*`^mg%!!uepp
z5?$u+K
9J_arh5&7_=uV87{DYC6iS9)7{{enL8$YN3P(H8TQ~~Q
z5m+3mP$fc8DXT{w9e=gb-M(bv6>6O>&>FTY)I
z-i7y{KJnua?!d210urbbsI-dH3h
4rICH
z=Hwi!xwU?l3ak4Cw#R);i%SrFh%JgYOuha3=z;aZ{Qq5-?UxU;lk4mvyZn%vrUKQ1
z=cS5c>a&@)vo0;YN#r>`V%q4o;wnMnDww6+$X9xMTS-#HnpgG4-2yG&`NTC8x!Qr_
zebKbAEZlbC5baEV^KG%l8NW_->(*08jvg((DZ2o*-Dez$xDYZTatA7fbj}7L|E9iV
z
tUHGYl^
zH-Wh!{uA|h=#f9W&;+3k5d_Ep$RQWa1o%u6kmcc}d_2(fGQwo|XBn)kLvL+`FH&yK
zL#WJho$d
z=bCwmDRfQE;X77!QaegWdx`+wkc{*3{kLzA+Asqs3D5fySes`!0vz>(muQU1F-Fe<
zNY>IPO>vPSEc$O)*8$a=)cX-h%XIJJhN1Vw#E_OfnAz%uD^Ak8 aFY=AL?28ZirOk9jf?Y{~ooX(nBFUk;a`y)X6i{r~NE#M#!Axy7{?D8WY
zEIXwW!cCwuyV#BWsbED>&>5!{@BW(aO(j#oG~!@6=_*h;Zk{fBhzW*wqdl=Ap{Vo*AtlH2
zeJ^xI7bpUB1{PWQLuS5r-`H