Files
Aurora.3/code/modules/mining/machine_stacking.dm
naut 8888834897 The Orion Miner + Shuttle Standards Expansion (#21491)
Adds the **Orion Miner** (officially the **Orion Mining Skiff**), an
all-in-one mining mega-shuttle with landing capability. Yes, the entire
ship can land. There is no secondary shuttle to get into.

<img width="704" height="1408" alt="image"
src="https://github.com/user-attachments/assets/b58d1305-2dbd-4c20-9305-f88535522af2"
/>

The Orion Miner is intended to be a lowpop (or solo, if necessary)
mining experience for people to try their hand at mining and exploration
without being critically dependent on other departments for
functionality. If you like mining, often go on low-pop and/or dislike
having to rely on other staff (medical/engineering/etc) for basic
necessities, this ship is for you!

Miners have their own supplies, access to thrust, navigation, and
equipment slightly better than that of the Horizon to compensate for
lack of support. This includes medical equipment and lifesaving
medication, in theory making solo miners on this shuttle statistically
less likely to die of preventable causes like blood loss or lung
ruptures.

While this ship can be crewed by a single person if necessary, it has
space for 4 crew total: 3 fully-equipped miners, plus 1 crewmember or
technician. (They are also provided an EVA suit and can use extra
equipment as necessary). This ship does not come with an explicit
captain.

Ore redemption consoles and mining equipment vendors are also present to
give crew the full mining gameplay loop. Minus the sales, at least -
though you could absolutely sell off or give away your spoils to the
Horizon or other offships if you so desired.

## Ship Features
- Full docking and landing capability. The ship _is_ the shuttle.
- An ore smelting plant and cargo bay.
- Ore redemption consoles and mining vendors, for the full miner's
gameplay loop.
- A Grauwolf for hazard clearing and (secondary) self-defense.
- A canteen and kitchen with adequate supplies.
- A hydroponics bay.
- Three atmosphere-rated airlocks. The rear one (north of the shuttle)
is a docking port.
- Emergency treatment-capable medical bay with adequate medical
supplies. It's no Horizon, but it is capable of saving people from
otherwise ruinous injuries.
- Technical storage and main engineering.
- Full SCC corporate affiliation. As a ship of Orion Express, this ship
can and should be able to interact (and possibly partner) with the
Horizon without a hitch.

## Additionally...
This PR also comes with a minor refactor to the way ore processing
machinery works: code has been streamlined, redundancies have been
eliminated, and machines should now work properly even when moved in
space (for example if it is on a shuttle).

<img width="991" height="351" alt="image"
src="https://github.com/user-attachments/assets/8f99dc29-8927-40e0-9856-b8ad5b2d35cb"
/>

This PR also comes with a minor resprite to the `sleekstab` sleek
stabilization kit. It is basically a recolor of the "small first aid
kit" combined with the stabilization kit's rainbow pattern. See
IconDiffBot for the raw sprite.

And last but definitely not least, this PR expands Odyssey landing zones
to accomodate larger shuttles and expands shuttle standards to be bigger
(45 tiles long).

## Notes
<img width="1292" height="936" alt="image"
src="https://github.com/user-attachments/assets/dbcb0f3e-6509-4ff4-a53c-90f1255e6152"
/>

This is an **oversized** shuttle, about 30% larger than the Intrepid by
size and 20% larger than the Lone Spacer. While tested with many, many
different away sites, stations, and exoplanets, including the Horizon
(which it _can_ dock with), it's not guaranteed to be able to land at
_every_ site nor is it guaranteed to do so safely.

_Do note that this size comparison picture uses an old version of the
ship._

## Pictures

_Pictures may not be fully representative of the final design. See
MapDiffBot or the attached map screenshot at the top of the PR for the
final design._

<details>
<summary>Details</summary>

<img width="1316" height="1310" alt="image"
src="https://github.com/user-attachments/assets/fc58c3a8-6c61-41d7-9e69-9852986c76ca"
/>

<img width="1172" height="1111" alt="image"
src="https://github.com/user-attachments/assets/eb3d9d38-b7e5-42a4-88b1-310ff08a1c5d"
/>

<img width="1209" height="1151" alt="image"
src="https://github.com/user-attachments/assets/d1b1842e-f2f7-4525-a5e5-8d6f8c26f9be"
/>

<img width="1251" height="1253" alt="image"
src="https://github.com/user-attachments/assets/cd2b7a40-cb3f-4151-9057-7dc9dfe69ddd"
/>

<img width="1105" height="1198" alt="image"
src="https://github.com/user-attachments/assets/1ae5a5e3-ba73-433f-8186-0c24a77dcade"
/>


</details>
2025-11-11 16:29:19 +00:00

186 lines
5.7 KiB
Plaintext

/**********************Mineral stacking unit console**************************/
/obj/machinery/mineral/stacking_unit_console
name = "stacking machine console"
desc = "This console allows you to set the max stack size for the stacking machine, as well as letting you eject stacks manually."
icon = 'icons/obj/machinery/wall/terminals.dmi'
icon_state = "production_console"
density = FALSE
anchored = TRUE
var/obj/machinery/mineral/stacking_machine/machine
idle_power_usage = 15
active_power_usage = 50
component_types = list(
/obj/item/circuitboard/stacking_console,
/obj/item/stock_parts/scanning_module,
/obj/item/stock_parts/console_screen
)
/obj/machinery/mineral/stacking_unit_console/Initialize(mapload, d, populate_components)
..()
var/mutable_appearance/screen_overlay = mutable_appearance(icon, "production_console-screen", plane = ABOVE_LIGHTING_PLANE)
AddOverlays(screen_overlay)
set_light(1.4, 1, COLOR_CYAN)
return INITIALIZE_HINT_LATELOAD
/obj/machinery/mineral/stacking_unit_console/LateInitialize()
. = ..()
setup_machine(null)
/obj/machinery/mineral/stacking_unit_console/Destroy()
if(machine)
machine.console = null
return ..()
/obj/machinery/mineral/stacking_unit_console/proc/setup_machine(mob/user)
if(!machine)
var/area/A = get_area(src)
var/best_distance = INFINITY
for(var/obj/machinery/mineral/stacking_machine/checked_machine in SSmachinery.machinery)
if(id)
if(checked_machine.id == id)
machine = checked_machine
else if(!checked_machine.console && A == get_area(checked_machine) && get_dist_euclidian(checked_machine, src) < best_distance)
machine = checked_machine
best_distance = get_dist_euclidian(checked_machine, src)
if(machine)
machine.console = src
else if(user)
to_chat(user, SPAN_WARNING("ERROR: Linked machine not found!"))
return machine
/obj/machinery/mineral/stacking_unit_console/attackby(obj/item/attacking_item, mob/user)
if(default_deconstruction_screwdriver(user, attacking_item))
return
if(default_deconstruction_crowbar(user, attacking_item))
return
if(default_part_replacement(user, attacking_item))
return
return ..()
/obj/machinery/mineral/stacking_unit_console/attack_hand(mob/user)
add_fingerprint(user)
ui_interact(user)
/obj/machinery/mineral/stacking_unit_console/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, datum/ui_state/state = GLOB.default_state)
if(!setup_machine(user))
return
var/list/data = list(
"stack_amt" = machine.stack_amt,
"contents" = list()
)
for(var/stacktype in machine.stack_storage)
if(machine.stack_storage[stacktype] > 0)
data["contents"] += list(list(
"path" = stacktype,
"name" = machine.stack_paths[stacktype],
"amount" = machine.stack_storage[stacktype]
))
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "stacking_machine.tmpl", "Stacking Machine", 500, 400, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/mineral/stacking_unit_console/Topic(href, href_list)
if(..())
return
if(href_list["change_stack"])
var/choice = tgui_input_list(usr, "What would you like to set the stack amount to?", "Stacking", list(1,5,10,20,50))
if(!choice)
return TRUE
machine.stack_amt = choice
return TRUE
if(href_list["release_stack"])
var/stacktype = text2path(href_list["release_stack"])
if(!stacktype || !machine.stack_paths[stacktype])
return
if(machine.stack_storage[stacktype] > 0)
var/obj/item/stack/material/S = new stacktype(machine.output_turf)
S.amount = machine.stack_storage[stacktype]
machine.stack_storage[stacktype] = 0
return TRUE
add_fingerprint(usr)
/**********************Mineral stacking unit**************************/
/obj/machinery/mineral/stacking_machine
name = "stacking machine"
desc = "A machine which takes loose stacks of finished sheets and packs them together into one easily transportable sheet."
icon = 'icons/obj/machinery/mining_machines.dmi'
icon_state = "stacker"
density = TRUE
anchored = TRUE
is_processing_machine = TRUE
var/obj/machinery/mineral/stacking_unit_console/console
var/list/stack_storage = list()
var/list/stack_paths = list()
var/stack_amt = 50 // Amount to stack before releasing
idle_power_usage = 15
active_power_usage = 50
component_types = list(
/obj/item/circuitboard/stacking_machine,
/obj/item/stock_parts/manipulator = 2
)
/obj/machinery/mineral/stacking_machine/Initialize()
. = ..()
for(var/stacktype in subtypesof(/obj/item/stack/material) - typesof(/obj/item/stack/material/cyborg))
var/obj/item/stack/S = stacktype
stack_storage[stacktype] = 0
stack_paths[stacktype] = capitalize(initial(S.name))
setup_io()
/obj/machinery/mineral/stacking_machine/Destroy()
if(console)
console.machine = null
return ..()
/obj/machinery/mineral/stacking_machine/attackby(obj/item/attacking_item, mob/user)
if(default_deconstruction_screwdriver(user, attacking_item))
return
if(default_deconstruction_crowbar(user, attacking_item))
return
if(default_part_replacement(user, attacking_item))
return
return ..()
/obj/machinery/mineral/stacking_machine/process()
if(!console)
return
if(stat & BROKEN)
return
if(stat & NOPOWER)
return
if(output_turf && input_turf)
for(var/obj/item/O in input_turf)
if(!O)
return
var/obj/item/stack/S = O
if(istype(S) && stack_storage[S.type] != null)
stack_storage[S.type] += S.amount
qdel(S)
else
O.forceMove(output_turf)
//Output amounts that are past stack_amt.
for(var/sheet in stack_storage)
if(stack_storage[sheet] >= stack_amt)
new sheet(output_turf, stack_amt)
stack_storage[sheet] -= stack_amt
intent_message(MACHINE_SOUND)