Mining machine construction (#19658)

* the horrors persist

* fix

* more work

* attempt to drop all sheets

* comment

* Techwebs

* oops

* organize

* fix warns

* Use a lookup

* Use bumps instead of input dir

* Smart direction search

* wrong machine!

* Update mineral.dm

* cleaned unneeded global list

* raise range slightly

---------

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
Will
2026-08-15 10:56:42 -04:00
committed by GitHub
co-authored by Cameron Lennox
parent 9cce04f4ef
commit 7a313aa961
12 changed files with 541 additions and 172 deletions
@@ -6,11 +6,10 @@
/obj/machinery/mineral/processing_unit_console
name = "production machine console"
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "console"
layer = ABOVE_WINDOW_LAYER
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/mat_processor_console
var/obj/item/card/id/inserted_id // Inserted ID card, for points
@@ -19,36 +18,75 @@
/obj/machinery/mineral/processing_unit_console/Initialize(mapload)
. = ..()
src.machine = locate(/obj/machinery/mineral/processing_unit) in range(5, src)
if (machine)
machine.console = src
else
default_apply_parts()
processor_link()
if(!machine && mapload) // Delete mapped ones if they fail
log_mapping("Ore processing machine console at [src.x], [src.y], [src.z] could not find its machine!")
qdel(src)
return INITIALIZE_HINT_QDEL
/obj/machinery/mineral/processing_unit_console/Destroy()
if(inserted_id)
inserted_id.forceMove(loc) //Prevents deconstructing from deleting whatever ID was inside it.
processor_unlink()
. = ..()
/obj/machinery/mineral/processing_unit_console/update_icon()
if(!machine || machine.console != src)
icon_state = "[initial(icon_state)]_bad"
return
icon_state = initial(icon_state)
/obj/machinery/mineral/processing_unit_console/attack_hand(mob/user)
if(..())
return
if(!allowed(user))
to_chat(user, span_warning("Access denied."))
return
if(!machine)
to_chat(user, span_danger("Ore processor not detected."))
return
tgui_interact(user)
/obj/machinery/mineral/processing_unit_console/attackby(obj/item/I, mob/user)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
if(istype(I, /obj/item/card/id))
if(!powered())
return
if(!machine)
to_chat(user, span_danger("Material processor not detected."))
return
if(!inserted_id && (user.unEquip(I) || isrobot(user)))
I.forceMove(src)
inserted_id = I
SStgui.update_uis(src)
return
..()
. = ..()
/obj/machinery/mineral/processing_unit_console/proc/processor_link(obj/machinery/mineral/processing_unit/new_machine = null)
if(!new_machine)
new_machine = find_nearest_linkable(/obj/machinery/mineral/processing_unit)
if(!new_machine)
update_icon()
return
// Perform the actual link!
machine = new_machine
machine.console = src
update_icon()
/obj/machinery/mineral/processing_unit_console/proc/processor_unlink()
if(machine?.console == src)
machine.console = null
SStgui.close_uis(src)
machine = null
update_icon()
/obj/machinery/mineral/processing_unit_console/has_link()
return machine
/obj/machinery/mineral/processing_unit_console/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -95,6 +133,10 @@
return TRUE
add_fingerprint(ui.user)
if(!machine)
return FALSE
switch(action)
if("toggleSmelting")
var/ore = params["ore"]
@@ -155,9 +197,10 @@
density = TRUE
anchored = TRUE
light_range = 3
var/obj/machinery/mineral/input = null
var/obj/machinery/mineral/output = null
var/obj/machinery/mineral/console = null
circuit = /obj/item/circuitboard/mat_processor
sets_direction = TRUE
var/obj/machinery/mineral/processing_unit_console/console = null
var/sheets_per_tick = 10
var/list/ores_processing = list()
var/list/ores_stored = list()
@@ -189,23 +232,36 @@
/obj/machinery/mineral/processing_unit/Initialize(mapload)
. = ..()
default_apply_parts()
for(var/ore, value in GLOB.ore_data)
var/datum/ore/OD = value
ores_processing[OD.name] = 0
ores_stored[OD.name] = 0
// TODO - Eschew input/output machinery and just use dirs ~Leshana
//Locate our output and input machinery.
for (var/dir in GLOB.cardinal)
src.input = locate(/obj/machinery/mineral/input, get_step(src, dir))
if(src.input) break
for (var/dir in GLOB.cardinal)
src.output = locate(/obj/machinery/mineral/output, get_step(src, dir))
if(src.output) break
return
// Mapload uses direction hints
if(!mapload)
// If we were constructed, try to get a console to attach to us
var/obj/machinery/mineral/processing_unit_console/console = find_nearest_linkable(/obj/machinery/mineral/processing_unit_console)
if(console)
console.processor_link(src)
return
find_output_direction()
/obj/machinery/mineral/processing_unit/Destroy()
if(console)
console.processor_unlink()
if(speed_process) // high gear
STOP_PROCESSING(SSfastprocess, src)
else
STOP_MACHINE_PROCESSING(src)
// We don't drop stored ores, just to avoid point exploits. Maybe this should drop slag instead?
. = ..()
/obj/machinery/mineral/processing_unit/has_link()
return console
/obj/machinery/mineral/processing_unit/proc/toggle_speed(forced)
var/area/refinery_area = get_area(src)
if(forced)
speed_process = forced
else
@@ -216,48 +272,54 @@
else // low gear
STOP_PROCESSING(SSfastprocess, src)
START_MACHINE_PROCESSING(src)
for(var/obj/machinery/mineral/unloading_machine/unloader in refinery_area.contents)
unloader.toggle_speed()
for(var/obj/machinery/conveyor_switch/cswitch in refinery_area.contents)
cswitch.toggle_speed()
for(var/obj/machinery/mineral/stacking_machine/stacker in refinery_area.contents)
stacker.toggle_speed()
// There is no danger of recursion here, because the other toggle_speed procs do no broadcast like this one on change
for(var/obj/machinery/mach in range(connection_range + 2, src)) // a little more than the link range
if(mach == src)
continue
if(istype(mach, /obj/machinery/mineral/unloading_machine))
var/obj/machinery/mineral/unloading_machine/unloader = mach
unloader.toggle_speed(speed_process)
continue
if(istype(mach, /obj/machinery/conveyor_switch))
var/obj/machinery/conveyor_switch/cswitch = mach
cswitch.toggle_speed(speed_process)
continue
if(istype(mach, /obj/machinery/mineral/stacking_machine))
var/obj/machinery/mineral/stacking_machine/stacker = mach
stacker.toggle_speed(speed_process)
continue
/obj/machinery/mineral/processing_unit/attackby(obj/item/I, mob/user)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
. = ..()
/obj/machinery/mineral/processing_unit/process()
if (!src.output || !src.input)
if(!output_dir)
return
var/turf/output = get_step(src,output_dir)
if(!output)
return
if(panel_open || !powered())
return
var/list/tick_alloys = list()
//Grab some more ore to process this tick.
for(var/obj/structure/ore_box/OB in input.loc)
for(var/ore in OB.stored_ore)
if(OB.stored_ore[ore] > 0)
var/ore_amount = OB.stored_ore[ore] // How many ores does the box have?
ores_stored[ore] += ore_amount // Add the ore to the machine.
points += (ore_values[ore]*points_mult*ore_amount) // Give Points! VOREStation Edit - or give lots of points! or less points! or no points!
OB.stored_ore[ore] = 0 // Set the value of the ore in the box to 0.
for(var/obj/item/ore_chunk/ore_chunk in input.loc) //Special ore chunk item. For conveyor belt. Completely unneeded but keeps asthetics.
for(var/ore in ore_chunk.stored_ore)
if(ore_chunk.stored_ore[ore] > 0)
var/ore_amount = ore_chunk.stored_ore[ore]
ores_stored[ore] += ore_amount
points += (ore_values[ore]*points_mult*ore_amount)
ore_chunk.stored_ore[ore] = 0
qdel(ore_chunk)
for(var/obj/item/ore/O in input.loc)
if(!isnull(ores_stored[O.material]))
ores_stored[O.material]++
points += (ore_values[O.material]*points_mult)
qdel(O)
var/turf/input = get_step(src, reverse_direction(output_dir)) // Only applies to unloading oreboxes DIRECTLY with no conveyors... Did anyone even know this was a feature?
if(input)
for(var/obj/structure/ore_box/OB in input)
for(var/ore in OB.stored_ore)
if(OB.stored_ore[ore] > 0)
var/ore_amount = OB.stored_ore[ore] // How many ores does the box have?
ores_stored[ore] += ore_amount // Add the ore to the machine.
points += (ore_values[ore]*points_mult*ore_amount) // Give Points! VOREStation Edit - or give lots of points! or less points! or no points!
OB.stored_ore[ore] = 0 // Set the value of the ore in the box to 0.
if(!active)
return
@@ -305,7 +367,7 @@
sheets += total-1
for(var/i=0,i<total,i++)
new A.product(output.loc)
new A.product(output)
else if(ores_processing[metal] == PROCESS_COMPRESS && O.compresses_to) //Compressing.
@@ -320,7 +382,7 @@
for(var/i=0,i<can_make,i+=2)
ores_stored[metal]-=2
sheets+=2
new M.stack_type(output.loc)
new M.stack_type(output)
else if(ores_processing[metal] == PROCESS_SMELT && O.smelts_to) //Smelting.
@@ -333,14 +395,34 @@
for(var/i=0,i<can_make,i++)
ores_stored[metal]--
sheets++
new M.stack_type(output.loc)
new M.stack_type(output)
else
ores_stored[metal]--
sheets++
new /obj/item/ore/slag(output.loc)
new /obj/item/ore/slag(output)
else
continue
/obj/machinery/mineral/processing_unit/Bumped(AM)
. = ..()
if(istype(AM, /obj/item/ore_chunk))
var/obj/item/ore_chunk/ore_chunk = AM
for(var/ore in ore_chunk.stored_ore)
if(ore_chunk.stored_ore[ore] > 0)
var/ore_amount = ore_chunk.stored_ore[ore]
ores_stored[ore] += ore_amount
points += (ore_values[ore]*points_mult*ore_amount)
ore_chunk.stored_ore[ore] = 0
qdel(ore_chunk)
return
if(istype(AM, /obj/item/ore))
var/obj/item/ore/O = AM
if(!isnull(ores_stored[O.material]))
ores_stored[O.material]++
points += (ore_values[O.material]*points_mult)
qdel(O)
return
#undef PROCESS_NONE
#undef PROCESS_SMELT
#undef PROCESS_COMPRESS
+129 -38
View File
@@ -2,29 +2,67 @@
/obj/machinery/mineral/stacking_unit_console
name = "stacking machine console"
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "console"
layer = ABOVE_WINDOW_LAYER
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/mat_stacker_console
var/obj/machinery/mineral/stacking_machine/machine = null
//var/machinedir = SOUTHEAST //This is really dumb, so lets burn it with fire.
/obj/machinery/mineral/stacking_unit_console/Initialize(mapload)
. = ..()
//src.machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir)) //No.
src.machine = locate(/obj/machinery/mineral/stacking_machine) in range(5,src)
if (machine)
machine.console = src
else
//Silently failing and causing mappers to scratch their heads while runtiming isn't ideal.
default_apply_parts()
stacker_link()
if(!machine && mapload) // Delete mapped ones if they fail
stack_trace(span_danger("Warning: Stacking machine console at [src.x], [src.y], [src.z] could not find its machine!"))
return INITIALIZE_HINT_QDEL
/obj/machinery/mineral/stacking_unit_console/Destroy()
stacker_unlink()
. = ..()
/obj/machinery/mineral/stacking_unit_console/has_link()
return machine
/obj/machinery/mineral/stacking_unit_console/update_icon()
if(!machine || machine.console != src)
icon_state = "[initial(icon_state)]_bad"
return
icon_state = initial(icon_state)
/obj/machinery/mineral/stacking_unit_console/proc/stacker_link(obj/machinery/mineral/stacking_machine/new_machine = null)
if(!new_machine)
new_machine = find_nearest_linkable(/obj/machinery/mineral/stacking_machine)
if(!new_machine)
update_icon()
return
// Perform the actual link!
machine = new_machine
machine.console = src
update_icon()
/obj/machinery/mineral/stacking_unit_console/proc/stacker_unlink()
if(machine?.console == src)
machine.console = null
SStgui.close_uis(src)
machine = null
update_icon()
/obj/machinery/mineral/stacking_unit_console/attack_hand(mob/user)
add_fingerprint(user)
if(!machine)
to_chat(user, span_danger("Stacking machine not detected."))
return
tgui_interact(user)
/obj/machinery/mineral/stacking_unit_console/attackby(obj/item/I, mob/user)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
. = ..()
/obj/machinery/mineral/stacking_unit_console/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -50,6 +88,11 @@
if(..())
return TRUE
add_fingerprint(ui.user)
if(!machine)
return FALSE
switch(action)
if("change_stack")
machine.stack_amt = clamp(text2num(params["amt"]), 1, 50)
@@ -59,12 +102,13 @@
var/stack = params["stack"]
if(machine.stack_storage[stack] > 0)
var/stacktype = machine.stack_paths[stack]
new stacktype(get_turf(machine.output), machine.stack_storage[stack])
machine.stack_storage[stack] = 0
if(machine.output_dir)
var/turf/output = get_step(machine,machine.output_dir)
if(output)
new stacktype(output, machine.stack_storage[stack])
machine.stack_storage[stack] = 0
. = TRUE
add_fingerprint(ui.user)
/**********************Mineral stacking unit**************************/
@@ -74,26 +118,52 @@
icon_state = "stacker"
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/mat_stacker
var/obj/machinery/mineral/stacking_unit_console/console
var/obj/machinery/mineral/input = null
var/obj/machinery/mineral/output = null
var/list/stack_storage[0]
var/list/stack_paths[0]
var/stack_amt = 50; // Amount to stack before releassing
sets_direction = TRUE
/obj/machinery/mineral/stacking_machine/Initialize(mapload)
. = ..()
default_apply_parts()
for(var/obj/item/stack/material/S as anything in (subtypesof(/obj/item/stack/material) - typesof(/obj/item/stack/material/cyborg)))
var/s_matname = initial(S.default_type)
stack_storage[s_matname] = 0
stack_paths[s_matname] = S
for (var/dir in GLOB.cardinal)
src.input = locate(/obj/machinery/mineral/input, get_step(src, dir))
if(src.input) break
for (var/dir in GLOB.cardinal)
src.output = locate(/obj/machinery/mineral/output, get_step(src, dir))
if(src.output) break
// Mapload uses direction hints
if(!mapload)
// If we were constructed, try to get a console to attach to us
var/obj/machinery/mineral/stacking_unit_console/console = find_nearest_linkable(/obj/machinery/mineral/stacking_unit_console)
if(console)
console.stacker_link(src)
return
find_output_direction()
/obj/machinery/mineral/stacking_machine/Destroy()
if(console)
console.stacker_unlink()
if(speed_process) // high gear
STOP_PROCESSING(SSfastprocess, src)
else
STOP_MACHINE_PROCESSING(src)
// Release all sheets
for(var/stack in stack_storage)
if(stack_storage[stack] <= 0)
continue
var/obj/item/stack/stacktype = stack_paths[stack]
var/turf/output = get_turf(src)
while(stack_storage[stack] > 0) // Not really a nicer way to do this unless we just delete the stacks...
var/amnt = min(stack_storage[stack], initial(stacktype.max_amount))
new stacktype(output, amnt)
stack_storage[stack] -= amnt
. = ..()
/obj/machinery/mineral/stacking_machine/has_link()
return console
/obj/machinery/mineral/stacking_machine/proc/toggle_speed(forced)
if(forced)
@@ -107,26 +177,47 @@
STOP_PROCESSING(SSfastprocess, src)
START_MACHINE_PROCESSING(src)
/obj/machinery/mineral/stacking_machine/process()
if (src.output && src.input)
var/turf/T = get_turf(input)
for(var/obj/item/O in T.contents)
if(!O) return
if(istype(O,/obj/item/stack/material))
var/obj/item/stack/material/S = O
var/matname = S.material.name
if(!isnull(stack_storage[matname]))
stack_storage[matname] += S.get_amount()
qdel(S)
else
O.loc = output.loc
else
O.loc = output.loc
/obj/machinery/mineral/stacking_machine/attackby(obj/item/I, mob/user)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
. = ..()
/obj/machinery/mineral/stacking_machine/process()
if(!output_dir)
return
var/turf/output = get_step(src,output_dir)
if(panel_open || !powered())
return
if (!output)
return
//Output amounts that are past stack_amt.
for(var/sheet in stack_storage)
if(stack_storage[sheet] >= stack_amt)
var/stacktype = stack_paths[sheet]
new stacktype (get_turf(output), stack_amt)
new stacktype (output, stack_amt)
stack_storage[sheet] -= stack_amt
return
/obj/machinery/mineral/stacking_machine/Bumped(AM)
. = ..()
if(!isitem(AM))
return
var/turf/output = get_step(src,output_dir)
if(!output)
return
var/obj/item/O = AM
if(!istype(O,/obj/item/stack/material))
O.forceMove(output)
return
var/obj/item/stack/material/S = O
var/matname = S.material.name
if(!isnull(stack_storage[matname]))
stack_storage[matname] += S.get_amount()
qdel(S)
return
O.forceMove(output)
@@ -3,23 +3,37 @@
/obj/machinery/mineral/unloading_machine
name = "unloading machine"
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "unloader"
density = TRUE
anchored = TRUE
var/obj/machinery/mineral/input = null
var/obj/machinery/mineral/output = null
circuit = /obj/item/circuitboard/mat_unloader
sets_direction = TRUE
var/static/list/ore_iconstates = null
/obj/machinery/mineral/unloading_machine/Initialize(mapload)
. = ..()
for(var/dir in GLOB.cardinal)
input = locate(/obj/machinery/mineral/input, get_step(src, dir))
if(input)
break
for(var/dir in GLOB.cardinal)
output = locate(/obj/machinery/mineral/output, get_step(src, dir))
if(output)
break
default_apply_parts()
// Populate icons for unloaded ores, lookup is faster than the if-else monster it was before
if(!ore_iconstates)
ore_iconstates = list()
for(var/obj/item/ore/ore as anything in subtypesof(/obj/item/ore))
var/mat = ore.material
if(!mat)
continue
ore_iconstates[mat] = ore.icon_state
// Mapload uses direction hints
if(!mapload)
return
find_output_direction()
/obj/machinery/mineral/unloading_machine/Destroy()
if(speed_process) // high gear
STOP_PROCESSING(SSfastprocess, src)
else
STOP_MACHINE_PROCESSING(src)
. = ..()
/obj/machinery/mineral/unloading_machine/proc/toggle_speed(forced)
if(forced)
@@ -33,72 +47,50 @@
STOP_PROCESSING(SSfastprocess, src)
START_MACHINE_PROCESSING(src)
/obj/machinery/mineral/unloading_machine/attackby(obj/item/I, mob/user)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
. = ..()
/obj/machinery/mineral/unloading_machine/process()
if (src.output && src.input)
if (locate(/obj/structure/ore_box, input.loc))
var/obj/structure/ore_box/BOX = locate(/obj/structure/ore_box, input.loc)
var/i = 0
for (var/ore in BOX.stored_ore)
if(BOX.stored_ore[ore] > 0)
var/obj/item/ore_chunk/ore_chunk = new /obj/item/ore_chunk(src.output.loc)
var/ore_amount = BOX.stored_ore[ore]
ore_chunk.stored_ore[ore] += ore_amount
BOX.stored_ore[ore] = 0
if(!output_dir)
return
//Icon code here. Going from most to least common.
if(ore == ORE_SAND)
ore_chunk.icon_state = "ore_glass"
else if(ore == ORE_CARBON)
ore_chunk.icon_state = "ore_coal"
else if(ore == ORE_HEMATITE)
ore_chunk.icon_state = "ore_iron"
else if(ore == ORE_PHORON)
ore_chunk.icon_state = "ore_phoron"
else if(ore == ORE_SILVER)
ore_chunk.icon_state = "ore_silver"
else if(ore == ORE_GOLD)
ore_chunk.icon_state = "ore_gold"
else if(ore == ORE_URANIUM)
ore_chunk.icon_state = "ore_uranium"
else if(ore == ORE_DIAMOND)
ore_chunk.icon_state = "ore_diamond"
else if(ore == ORE_PLATINUM)
ore_chunk.icon_state = "ore_platinum"
else if(ore == ORE_MARBLE)
ore_chunk.icon_state = "ore_marble"
else if(ore == ORE_LEAD)
ore_chunk.icon_state = "ore_lead"
else if(ore == ORE_RUTILE)
ore_chunk.icon_state = "ore_rutile"
else if(ore == ORE_QUARTZ)
ore_chunk.icon_state = "ore_quartz"
else if(ore == ORE_MHYDROGEN)
ore_chunk.icon_state = "ore_hydrogen"
else if(ore == ORE_VERDANTIUM)
ore_chunk.icon_state = "ore_verdantium"
else if(ore == ORE_COPPER)
ore_chunk.icon_state = "ore_copper"
else if(ore == ORE_TIN)
ore_chunk.icon_state = "ore_tin"
else if(ore == ORE_VOPAL)
ore_chunk.icon_state = "ore_void_opal"
else if(ore == ORE_BAUXITE)
ore_chunk.icon_state = "ore_bauxite"
else if(ore == ORE_PAINITE)
ore_chunk.icon_state = "ore_painite"
else
ore_chunk.icon_state = "boulder[rand(1,4)]"
var/turf/output = get_step(src,output_dir)
var/turf/input = get_step(src,reverse_direction(output_dir))
if(panel_open || !powered())
return
if (!output || !input)
return
if (locate(/obj/structure/ore_box, input))
var/obj/structure/ore_box/BOX = locate(/obj/structure/ore_box, input)
var/i = 0
for (var/ore in BOX.stored_ore)
if(BOX.stored_ore[ore] > 0)
var/obj/item/ore_chunk/ore_chunk = new /obj/item/ore_chunk(output)
var/ore_amount = BOX.stored_ore[ore]
ore_chunk.stored_ore[ore] += ore_amount
BOX.stored_ore[ore] = 0
if (i>=3) //Let's make it staggered so it looks like a lot is happening.
return
if (locate(/obj/item, input.loc))
var/obj/item/O
var/i
for (i = 0; i<10; i++)
O = locate(/obj/item, input.loc)
if (O)
O.loc = src.output.loc
// Icon code here.
if(ore in ore_iconstates)
ore_chunk.icon_state = ore_iconstates[ore]
else
ore_chunk.icon_state = "boulder[rand(1,4)]"
if (i>=3) //Let's make it staggered so it looks like a lot is happening.
return
return
if (locate(/obj/item, input))
var/obj/item/O
var/i
for (i = 0; i<10; i++)
O = locate(/obj/item, input)
if(!O)
return
O.forceMove(output)
+80
View File
@@ -0,0 +1,80 @@
/obj/machinery/mineral
name = DEVELOPER_WARNING_NAME
desc = DEVELOPER_WARNING_NAME
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "furnace_old"
var/static/connection_range = 8
var/sets_direction = FALSE // We don't want to set the direction of consoles
var/output_dir = 0 // direction that we output material
/obj/machinery/mineral/proc/has_link()
return FALSE
/obj/machinery/mineral/proc/find_nearest_linkable(filtering_type)
var/nearest_distance = INFINITY
var/nearest_machine = null
for(var/obj/machinery/mineral/checking in range(src, connection_range))
if(!istype(checking, filtering_type))
continue
if(checking.has_link())
continue
var/turf/A = get_turf(src)
var/turf/B = get_turf(checking)
var/distcheck = A.Distance(B)
if(distcheck >= nearest_distance)
continue
nearest_distance = distcheck
nearest_machine = checking
return nearest_machine
/obj/machinery/mineral/examine(mob/user, infix, suffix)
. = ..()
if(!sets_direction)
return
if(output_dir)
. += span_notice("Currently configured to drop processed material <b>[dir2text(output_dir)]</b>.")
. += span_notice("Alt-click to reset.")
else
. += span_notice("Drag towards a direction (while next to it) to change drop direction.")
/obj/machinery/mineral/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
if(!sets_direction)
return ..()
var/mob/user = usr
if(!Adjacent(user))
return
if(isobserver(user) || user.is_incorporeal())
return
var/direction = get_dir(src, over_location)
if(!direction)
return
output_dir = direction
balloon_alert(user, "dropping [dir2text(output_dir)]")
/obj/machinery/mineral/click_alt(mob/user)
if(!sets_direction)
return ..()
if(!output_dir)
return CLICK_ACTION_BLOCKING
balloon_alert(user, "drop direction reset")
output_dir = 0
return CLICK_ACTION_SUCCESS
// Attempt to detect our output direction from various context clues, used by mapload init
/obj/machinery/mineral/proc/find_output_direction()
var/turf/our_turf = get_turf(src)
for(var/check_dir in GLOB.cardinal)
var/turf/check = get_step(src, check_dir)
// Don't go off the edge of the map
if(!check)
continue
// Walls are obviously bad
if(check.density)
continue
// Look for conveyors that points away from us
var/obj/machinery/conveyor/convey = locate() in check
if(convey)
var/turf/conveyor_goal_turf = get_step(convey,convey.dir)
if(conveyor_goal_turf != our_turf)
output_dir = check_dir
break