diff --git a/code/datums/trading/traders/ai.dm b/code/datums/trading/traders/ai.dm index 2166a7ba1cf..ca86637d32d 100644 --- a/code/datums/trading/traders/ai.dm +++ b/code/datums/trading/traders/ai.dm @@ -90,7 +90,8 @@ They sell generic supplies and ask for generic supplies. /obj/item/stack/material/ingot/mapped/osmium = TRADER_THIS_TYPE, /obj/item/stack/material/sheet/mapped/steel = TRADER_THIS_TYPE, /obj/item/stack/material/sheet/reinforced/mapped/plasteel = TRADER_THIS_TYPE, - /obj/machinery/mining = TRADER_SUBTYPES_ONLY + /obj/machinery/mining_drill = TRADER_THIS_TYPE, + /obj/structure/drill_brace = TRADER_THIS_TYPE ) /datum/trader/trading_beacon/manufacturing diff --git a/code/datums/trading/traders/goods.dm b/code/datums/trading/traders/goods.dm index 5935889e632..d260685de19 100644 --- a/code/datums/trading/traders/goods.dm +++ b/code/datums/trading/traders/goods.dm @@ -454,8 +454,8 @@ Sells devices, odds and ends, and medical stuff ) possible_trading_items = list( - /obj/machinery/mining/drill = TRADER_THIS_TYPE, - /obj/machinery/mining/brace = TRADER_THIS_TYPE, + /obj/machinery/mining_drill = TRADER_THIS_TYPE, + /obj/structure/drill_brace = TRADER_THIS_TYPE, /obj/machinery/floodlight = TRADER_THIS_TYPE, /obj/item/box/greenglowsticks = TRADER_THIS_TYPE, /obj/item/clothing/suit/space/void/engineering/salvage/prepared = TRADER_THIS_TYPE, diff --git a/code/game/objects/items/weapons/circuitboards/machinery/mining_drill.dm b/code/game/objects/items/weapons/circuitboards/machinery/mining_drill.dm index a625fb1edaf..6835b272aa6 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/mining_drill.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/mining_drill.dm @@ -1,21 +1,15 @@ /obj/item/stock_parts/circuitboard/miningdrill name = "circuitboard (mining drill head)" - build_path = /obj/machinery/mining/drill + build_path = /obj/machinery/mining_drill board_type = "machine" origin_tech = @'{"programming":1,"engineering":1}' req_components = list( /obj/item/stock_parts/capacitor = 1, /obj/item/stock_parts/matter_bin = 1, - /obj/item/stock_parts/micro_laser = 1) + /obj/item/stock_parts/micro_laser = 1, + /obj/item/stock_parts/scanning_module = 1 + ) additional_spawn_components = list( /obj/item/stock_parts/power/battery/buildable/stock, /obj/item/cell = 1 ) - -/obj/item/stock_parts/circuitboard/miningdrillbrace - name = "circuitboard (mining drill brace)" - build_path = /obj/machinery/mining/brace - board_type = "machine" - origin_tech = @'{"programming":1,"engineering":1}' - req_components = list() - additional_spawn_components = null \ No newline at end of file diff --git a/code/game/turfs/flooring/flooring_reinforced.dm b/code/game/turfs/flooring/flooring_reinforced.dm index 88756a989e3..826db236938 100644 --- a/code/game/turfs/flooring/flooring_reinforced.dm +++ b/code/game/turfs/flooring/flooring_reinforced.dm @@ -15,22 +15,28 @@ gender = NEUTER /decl/flooring/reinforced/circuit - name = "processing strata" - desc = "A complex network of circuits beneath reinforced glass." - icon = 'icons/turf/flooring/circuit.dmi' - icon_base = "bcircuit" - build_type = null - flooring_flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_WRENCH - can_paint = 1 - can_engrave = FALSE + name = "processing strata" + desc = "A complex network of circuits beneath reinforced glass." + icon = 'icons/turf/flooring/circuit.dmi' + icon_base = "bcircuit" + build_type = null + flooring_flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_WRENCH + can_paint = 1 + can_engrave = FALSE + turf_light_range = 2 + turf_light_power = 3 + turf_light_color = COLOR_BLUE /decl/flooring/reinforced/circuit/green - icon_base = "gcircuit" + icon_base = "gcircuit" + turf_light_color = COLOR_GREEN /decl/flooring/reinforced/circuit/red - icon_base = "rcircuit" - flooring_flags = TURF_ACID_IMMUNE - can_paint = 0 + icon_base = "rcircuit" + flooring_flags = TURF_ACID_IMMUNE + can_paint = 0 + turf_light_power = 2 + turf_light_color = COLOR_RED /decl/flooring/reinforced/shuttle name = "floor" diff --git a/code/game/turfs/floors/subtypes/floor_circuit.dm b/code/game/turfs/floors/subtypes/floor_circuit.dm index 7f934481deb..5d458a43d9a 100644 --- a/code/game/turfs/floors/subtypes/floor_circuit.dm +++ b/code/game/turfs/floors/subtypes/floor_circuit.dm @@ -3,9 +3,6 @@ icon = 'icons/turf/flooring/circuit.dmi' icon_state = "bcircuit" _flooring = /decl/flooring/reinforced/circuit - light_range = 2 - light_power = 3 - light_color = COLOR_BLUE /turf/floor/bluegrid/airless name = "airless floor" @@ -17,9 +14,6 @@ icon = 'icons/turf/flooring/circuit.dmi' icon_state = "gcircuit" _flooring = /decl/flooring/reinforced/circuit/green - light_range = 2 - light_power = 3 - light_color = COLOR_GREEN /turf/floor/greengrid/airless name = "airless floor" @@ -34,6 +28,3 @@ icon = 'icons/turf/flooring/circuit.dmi' icon_state = "rcircuit" _flooring = /decl/flooring/reinforced/circuit/red - light_range = 2 - light_power = 2 - light_color = COLOR_RED diff --git a/code/modules/ZAS/Turf.dm b/code/modules/ZAS/Turf.dm index e0a7767b212..82312858622 100644 --- a/code/modules/ZAS/Turf.dm +++ b/code/modules/ZAS/Turf.dm @@ -231,6 +231,10 @@ var/global/list/STANDARD_AIRMIX = list( /turf/return_air() RETURN_TYPE(/datum/gas_mixture) + // TODO: immutable gas mixtures for stuff like this, to avoid creating new datums every time. + if(!simulated) + return make_air() + // ZAS participation if(zone && !zone.invalid) SSair.mark_zone_update(zone) @@ -261,7 +265,7 @@ var/global/list/STANDARD_AIRMIX = list( return FALSE /turf/proc/make_air() - air = new/datum/gas_mixture + air = new /datum/gas_mixture air.temperature = temperature if(initial_gas) if(initial_gas == GAS_STANDARD_AIRMIX) diff --git a/code/modules/codex/entries/machinery.dm b/code/modules/codex/entries/machinery.dm index 6854c68862d..62f34de3efe 100644 --- a/code/modules/codex/entries/machinery.dm +++ b/code/modules/codex/entries/machinery.dm @@ -150,4 +150,16 @@ lore_text = "A signal repeater, capable of transmitting and decoding hyperintense radio waves to and from PLEXUS uplinks." mechanics_text = "Allows for network devices in its sector to connect to and communicate with distant networks over PLEXUS.
Networks requires a modem to utilize PLEXUS connections." disambiguator = "machine" + available_to_map_tech_level = MAP_TECH_LEVEL_SPACE + +/datum/codex_entry/mining_drill + associated_paths = list(/obj/machinery/mining_drill) + mechanics_text = "When properly supported by two adjacent braces, the mining drill can automatically mine underground mineral deposits.
\ + You can empty the ore storage by click-dragging the drill onto an ore box, or using the Unload Drill verb.
\ + The drill head can be upgraded using a number of different components:
\ + - Micro lasers control the drill's mining speed. The drill's energy usage proportionally increases with faster speed.
\ + - Matter bins expand the drill's internal ore storage, allowing it to mine for longer before it gets fill.
\ + - Scanning modules expand the drill's ore scanner radius, allowing it to mine from farther away.
\ + - Capacitors improve the drill's energy efficiency, reducing how much energy is required to extract a piece of ore from the ground." + disambiguator = "machine" available_to_map_tech_level = MAP_TECH_LEVEL_SPACE \ No newline at end of file diff --git a/code/modules/crafting/stack_recipes/recipes_steel.dm b/code/modules/crafting/stack_recipes/recipes_steel.dm index 8175e180629..8f15300c367 100644 --- a/code/modules/crafting/stack_recipes/recipes_steel.dm +++ b/code/modules/crafting/stack_recipes/recipes_steel.dm @@ -105,3 +105,6 @@ /decl/stack_recipe/steel/furniture/tank result_type = /obj/item/pipe/tank + +/decl/stack_recipe/steel/furniture/drill_brace + result_type = /obj/structure/drill_brace diff --git a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm index 2f251c975da..c817352197f 100644 --- a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm +++ b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm @@ -302,9 +302,6 @@ /datum/fabricator_recipe/imprinter/circuit/miningdrill path = /obj/item/stock_parts/circuitboard/miningdrill -/datum/fabricator_recipe/imprinter/circuit/miningdrillbrace - path = /obj/item/stock_parts/circuitboard/miningdrillbrace - /datum/fabricator_recipe/imprinter/circuit/floodlight path = /obj/item/stock_parts/circuitboard/floodlight diff --git a/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm b/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm index 2a5173d788d..26ad0dee2a5 100644 --- a/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm +++ b/code/modules/maps/template_types/random_exoplanet/random_planet_level_data.dm @@ -82,11 +82,12 @@ //Rename the surface area if we have one yet adapt_location_name(parent_planetoid.name) -///If we're getting atmos from our parent planet, decide if we're going to apply it, or ignore it +///If we're getting atmos from our parent planet, apply it. /datum/level_data/planetoid/proc/apply_planet_atmosphere(var/datum/planetoid_data/P) - if(istype(exterior_atmosphere)) - return //level atmos takes priority over planet atmos - exterior_atmosphere = P.atmosphere.Clone() //Make sure we get one instance per level + if(istype(P) && istype(P.atmosphere)) + exterior_atmosphere = P.atmosphere.Clone() + exterior_atmosphere.update_values() + exterior_atmosphere.check_tile_graphic() ///Apply our parent planet's ambient lighting settings if we want to. /datum/level_data/planetoid/proc/apply_planet_ambient_lighting(var/datum/planetoid_data/P) diff --git a/code/modules/mining/drilling/brace.dm b/code/modules/mining/drilling/brace.dm new file mode 100644 index 00000000000..44441e2f834 --- /dev/null +++ b/code/modules/mining/drilling/brace.dm @@ -0,0 +1,56 @@ +/obj/structure/drill_brace + name = "mining drill brace" + desc = "A machinery brace for an industrial drill. It looks like it's about half a metre thick." + icon = 'icons/obj/mining_drill.dmi' + icon_state = "mining_brace" + density = TRUE + layer = ABOVE_HUMAN_LAYER + obj_flags = OBJ_FLAG_ROTATABLE|OBJ_FLAG_ANCHORABLE + var/obj/machinery/mining_drill/connected = null + +/obj/structure/drill_brace/Destroy() + if(connected) + disconnect_from_drill() + return ..() + +/obj/structure/drill_brace/on_update_icon() + icon_state = "mining_brace[connected ? "_active" : ""]" + return ..() + +/obj/structure/drill_brace/wrench_floor_bolts(mob/user, delay, obj/item/tool) + if(connected && connected.use_power != POWER_USE_OFF) + to_chat(user, SPAN_NOTICE("You can't work with the brace of a running drill!")) + return + if(isspaceturf(get_turf(src))) + to_chat(user, SPAN_NOTICE("You can't anchor something to empty space. Idiot.")) + return + + var/old_anchored = anchored + ..() // Call parent to try to actually anchor/unanchor it. + if(anchored != old_anchored) + if(anchored && connect_to_drill()) + to_chat(user, SPAN_NOTICE("You attach \the [src] to \the [connected].")) + else if(disconnect_from_drill()) + to_chat(user, SPAN_NOTICE("You detatch \the [src].")) + +/obj/structure/drill_brace/proc/connect_to_drill() + var/turf/front_turf = get_step(get_turf(src), dir) + if(!istype(front_turf)) + return FALSE + var/obj/machinery/mining_drill/drill = locate(/obj/machinery/mining_drill) in front_turf + if(drill) + connected = drill + connected.supports += src + connected.handle_supports() + update_icon() + return TRUE + return FALSE + +/obj/structure/drill_brace/proc/disconnect_from_drill() + if(!connected) + return FALSE + connected.supports -= src + connected.handle_supports() + connected = null + update_icon() + return TRUE diff --git a/code/modules/mining/drilling/drill.dm b/code/modules/mining/drilling/drill.dm index fea0961004f..7dd751cd744 100644 --- a/code/modules/mining/drilling/drill.dm +++ b/code/modules/mining/drilling/drill.dm @@ -1,299 +1,203 @@ -/obj/machinery/mining +/obj/machinery/mining_drill + name = "mining drill head" + desc = "An enormous drill." icon = 'icons/obj/mining_drill.dmi' + icon_state = "mining_drill_off" + layer = ABOVE_HUMAN_LAYER anchored = FALSE - use_power = POWER_USE_OFF //The drill takes power directly from a cell. density = TRUE - layer = ABOVE_HUMAN_LAYER //So it draws over mobs in the tile north of it. + use_power = POWER_USE_OFF + power_channel = LOCAL + active_power_usage = 10 KILOWATTS + idle_power_usage = 500 construct_state = /decl/machine_construction/default/panel_closed uncreated_component_parts = null stat_immune = 0 + base_type = /obj/machinery/mining_drill -/obj/machinery/mining/drill - name = "mining drill head" - desc = "An enormous drill." - icon_state = "mining_drill" - power_channel = LOCAL - active_power_usage = 10 KILOWATTS - base_type = /obj/machinery/mining/drill - var/list/generated_ore = list() - var/braces_needed = 2 - var/list/supports = list() - var/supported = 0 - var/active = FALSE - var/list/resource_field = list() - - //Upgrades - var/harvest_speed - var/capacity - - //Flags - var/need_update_field = 0 - var/need_player_check = 0 + /// The drill's FSM, keeping track of which state the drill is currently in. + var/datum/state_machine/drill/state_machine = null -/obj/machinery/mining/drill/Process() - if(need_player_check) - return - - check_supports() + /// Ore that is presently inside of the drill, ready to be extracted. + var/list/contained_ore = list() - if(!active) return - - if(!anchored) - system_error("system configuration error") - return - - if(stat & NOPOWER) - system_error("insufficient charge") - return + /// Drill supports presently connected to the drill head. + var/list/supports = list() - if(need_update_field) - get_resource_field() + /// How many braces are required for the drill to operate. + var/const/MINIMUM_SUPPORT_NUMBER = 2 - if(world.time % 10 == 0) - update_icon() + /// List of turfs that the drill will attempt to mine. + var/list/turfs_to_mine = list() - if(!active) - return + /// The turf that the drill is presently mining. + var/turf/current_turf = null - //Drill through the flooring, if any. - var/turf/T = get_turf(src) - if(T) - T.drill_act() - - while(length(resource_field)) - var/turf/harvesting = pick(resource_field) - var/datum/extension/buried_resources/resources = get_extension(harvesting, /datum/extension/buried_resources) - if(!length(resources?.resources)) - if(resources) - remove_extension(harvesting, /datum/extension/buried_resources) - resource_field -= harvesting - continue - break - - if(!length(resource_field)) - set_active(FALSE) - need_player_check = 1 - update_icon() - return + //Upgrades + /// The radius for the drill to use when populating `turfs_to_mine`. Upgraded with scanning modules. + var/drill_radius = 2 - var/turf/harvesting = pick(resource_field) - var/datum/extension/buried_resources/resources = get_extension(harvesting, /datum/extension/buried_resources) - var/harvested = 0 - for(var/metal in resources.resources) + /// The ore capacity for the drill. The drill will stop mining if it gets full. Upgraded with matter bins. + var/ore_capacity = 200 - if(length(generated_ore) >= capacity) - system_error("insufficient storage space") - set_active(FALSE) - need_player_check = 1 - update_icon() - return + /// How fast the drill mines out the ore contained within `turfs_to_mine`. Faster speed requires more power. Upgraded with micro lasers. + var/mining_speed = 1 - var/generating_ore = min(capacity - length(generated_ore), resources.resources[metal]) - resources.resources[metal] -= generating_ore - if(resources.resources[metal] <= 0) - resources.resources -= metal - - for(var/i=1, i <= generating_ore, i++) - harvested++ - if(harvested >= harvest_speed) - break - generated_ore += new /obj/item/stack/material/ore(src, metal) - if(harvested >= harvest_speed) - break + /// Modifies how much energy is required to extract one piece of ore, with diminishing returns for higher values. Upgraded with capacitors. + var/efficiency_rating = 1 - if(!length(resources.resources)) - remove_extension(harvesting, /datum/extension/buried_resources) - resource_field -= harvesting + /// Determines how much less energy each capacitor rating reduces. Every capacitor after the first reduces the power draw by this amount each time. + var/const/EFFICIENCY_EXPONENT = 0.8 // Raise this closer to 1 to make capacitors less powerful. -/obj/machinery/mining/drill/proc/set_active(var/new_active) - if(active != new_active) - active = new_active - update_use_power(active ? POWER_USE_ACTIVE : POWER_USE_OFF) +/obj/machinery/mining_drill/Initialize() + state_machine = add_state_machine(src, /datum/state_machine/drill) + return ..() -/obj/machinery/mining/drill/cannot_transition_to(state_path) - if(active) - return SPAN_NOTICE("You must turn \the [src] off first.") +/obj/machinery/mining_drill/Destroy() + remove_state_machine(src, /datum/state_machine/drill) + turfs_to_mine.Cut() + current_turf = null + QDEL_NULL_LIST(contained_ore) + for(var/thing in supports) + var/obj/structure/drill_brace/B = thing + B.disconnect_from_drill() return ..() -/obj/machinery/mining/drill/components_are_accessible(path) - return !active && ..() - -/obj/machinery/mining/drill/physical_attack_hand(mob/user) - check_supports() - if(need_player_check) - if(can_use_power_oneoff(10 KILOWATTS) > 0) - system_error("insufficient charge") - else if(anchored) - get_resource_field() - to_chat(user, "You hit the manual override and reset the drill's error checking.") - need_player_check = 0 - update_icon() - return TRUE - if(supported && !panel_open) - if(!(stat & NOPOWER)) - set_active(!active) - if(active) - visible_message("\The [src] lurches downwards, grinding noisily.") - need_update_field = 1 - else - visible_message("\The [src] shudders to a grinding halt.") +/obj/machinery/mining_drill/Process() + state_machine.evaluate() + var/decl/state/drill/current_state = state_machine.current_state + current_state.process(src) + +/obj/machinery/mining_drill/physical_attack_hand(mob/user) + if(!panel_open) + var/on = use_power ? TRUE : FALSE + on = !on + if(on) + update_use_power(POWER_USE_IDLE) else - to_chat(user, "The drill is unpowered.") + update_use_power(POWER_USE_OFF) + playsound(src, "button", 60) + to_chat(user, SPAN_NOTICE("You turn \the [src] [use_power ? "on" : "off"].")) + state_machine.evaluate() + +/obj/machinery/mining_drill/on_update_icon() + icon_state = "mining_drill_[use_power == POWER_USE_ACTIVE ? "on" : "off"]" + z_flags &= ~ZMM_MANGLE_PLANES + cut_overlays() + var/decl/state/drill/current_state = state_machine.current_state + if(current_state.light_icon_state) + add_overlay(emissive_overlay(icon, current_state.light_icon_state, src, SOUTH, current_state.light_color)) + z_flags |= ZMM_MANGLE_PLANES + set_light(2, 0.4, current_state.light_color) else - to_chat(user, "Turning on a piece of industrial machinery without sufficient bracing or wires exposed is a bad idea.") - - update_icon() - return TRUE - -/obj/machinery/mining/drill/on_update_icon() - if(need_player_check) - icon_state = "mining_drill_error" - else if(active) - var/status = clamp(round( (length(generated_ore) / capacity) * 4 ), 0, 3) - icon_state = "mining_drill_active[status]" - else if(supported) - icon_state = "mining_drill_braced" - else - icon_state = "mining_drill" - return + set_light(0) + return ..() -/obj/machinery/mining/drill/RefreshParts() - ..() - harvest_speed = clamp(total_component_rating_of_type(/obj/item/stock_parts/micro_laser), 0, 10) - capacity = 200 * clamp(total_component_rating_of_type(/obj/item/stock_parts/matter_bin), 0, 10) - var/charge_multiplier = clamp(total_component_rating_of_type(/obj/item/stock_parts/capacitor), 0.1, 10) - change_power_consumption(initial(active_power_usage) / charge_multiplier, POWER_USE_ACTIVE) +/obj/machinery/mining_drill/proc/handle_supports() + state_machine.evaluate() + anchored = length(supports) >= 1 ? TRUE : FALSE + if(can_fall()) + fall() -/obj/machinery/mining/drill/proc/check_supports() - anchored = initial(anchored) - if(length(supports) <= 0) - set_active(FALSE) - else - anchored = TRUE +/obj/machinery/mining_drill/proc/reset_drill() + turfs_to_mine.Cut() + current_turf = null - var/last_supported = supported - supported = (length(supports) >= braces_needed) - if(supported != last_supported && !supported && can_fall()) - fall() +/obj/machinery/mining_drill/cannot_transition_to(state_path) + if(use_power != POWER_USE_OFF) + return SPAN_NOTICE("You must turn \the [src] off first.") + return ..() - update_icon() +/obj/machinery/mining_drill/components_are_accessible(path) + return (use_power == POWER_USE_OFF) && ..() -/obj/machinery/mining/drill/can_fall() - . = (length(supports) <= 0) -/obj/machinery/mining/drill/proc/system_error(var/error) +/obj/machinery/mining_drill/RefreshParts() + . = ..() + drill_radius = 1 + total_component_rating_of_type(/obj/item/stock_parts/scanning_module) + ore_capacity = 200 * total_component_rating_of_type(/obj/item/stock_parts/matter_bin) + mining_speed = total_component_rating_of_type(/obj/item/stock_parts/micro_laser) + efficiency_rating = total_component_rating_of_type(/obj/item/stock_parts/capacitor) - if(error) - src.visible_message("\The [src] flashes a '[error]' warning.") - need_player_check = 1 - set_active(FALSE) - update_icon() + var/efficiency = EFFICIENCY_EXPONENT ** (efficiency_rating - 1) + change_power_consumption(initial(active_power_usage) * efficiency * mining_speed, POWER_USE_ACTIVE) -/obj/machinery/mining/drill/proc/get_resource_field() +/obj/machinery/mining_drill/proc/populate_turfs_to_mine() + turfs_to_mine.Cut() + var/list/turf_candidates = RANGE_TURFS(src, drill_radius) + for(var/thing in turf_candidates) + var/turf/T = thing + if(turf_has_ore(T)) + turfs_to_mine += T - resource_field = list() - need_update_field = 0 +/obj/machinery/mining_drill/proc/scan_visuals() + for(var/thing in RANGE_TURFS(src, drill_radius)) + var/turf/T = thing + var/delay = (get_dist(get_turf(src), T) + 1) * 3 + addtimer(CALLBACK(src, PROC_REF(scan_visual_tile), T), delay) - var/turf/T = get_turf(src) - if(!istype(T)) return - var/tx = T.x - 2 - var/ty = T.y - 2 - var/turf/mine_turf - for(var/iy = 0,iy < 5, iy++) - for(var/ix = 0, ix < 5, ix++) - mine_turf = locate(tx + ix, ty + iy, T.z) - if(mine_turf && has_extension(mine_turf, /datum/extension/buried_resources)) - resource_field += mine_turf +/obj/machinery/mining_drill/proc/scan_visual_tile(turf/T) + var/obj/effect/temporary/temp = new(T, 1 SECOND, 'icons/effects/effects.dmi', "sonar_ping") + temp.color = "#00ffff77" - if(!resource_field.len) - system_error("resources depleted") +/obj/machinery/mining_drill/proc/turf_has_ore(turf/T) + if(!istype(T) || !has_extension(T, /datum/extension/buried_resources)) + return FALSE + var/datum/extension/buried_resources/resources = get_extension(T, /datum/extension/buried_resources) + return length(resources?.resources) -/obj/machinery/mining/drill/verb/unload() +/obj/machinery/mining_drill/proc/mine_ore(turf/T) + if(!T) + return + // Was tempted to add a drilling sound but it was awful. + var/datum/extension/buried_resources/resources = get_extension(T, /datum/extension/buried_resources) + for(var/i in 1 to mining_speed) + if(!length(resources.resources)) + break + var/material_typepath = pick(resources.resources) + contained_ore += new /obj/item/stack/material/ore(src, 1, material_typepath) + resources.resources[material_typepath] -= 1 + if(resources.resources[material_typepath] <= 0) + // Remove the typepath if it ran out. + resources.resources -= material_typepath + +/obj/machinery/mining_drill/proc/deplete_turf(turf/T) + if(!turf_has_ore(T)) + if(istype(T)) + turfs_to_mine -= T + if(has_extension(T, /datum/extension/buried_resources)) + remove_extension(T, /datum/extension/buried_resources) + +/obj/machinery/mining_drill/proc/choose_turf_to_mine() + current_turf = turfs_to_mine[1] + +/obj/machinery/mining_drill/verb/unload_verb() set name = "Unload Drill" set category = "Object" set src in oview(1) - if(usr.stat) return - var/obj/structure/ore_box/B = locate() in orange(1) if(B) - B.insert_ores(generated_ore, usr) - generated_ore.Cut() - to_chat(usr, "You unload the drill's storage cache into the ore box.") - else - to_chat(usr, "You must move an ore box up to the drill before you can unload it.") - - -/obj/machinery/mining/brace - name = "mining drill brace" - desc = "A machinery brace for an industrial drill. It looks easily two feet thick." - icon_state = "mining_brace" - obj_flags = OBJ_FLAG_ROTATABLE - interact_offline = 1 + unload_into_box(B, usr) - var/obj/machinery/mining/drill/connected - -/obj/machinery/mining/brace/cannot_transition_to(state_path) - if(connected && connected.active) - return SPAN_NOTICE("You can't work with the brace of a running drill!") - return ..() - -/obj/machinery/mining/brace/attackby(obj/item/W, mob/user) - if(connected && connected.active) - to_chat(user, "You can't work with the brace of a running drill!") - return TRUE - if(component_attackby(W, user)) - return TRUE - if(IS_WRENCH(W)) - - if(isspaceturf(get_turf(src))) - to_chat(user, "You can't anchor something to empty space. Idiot.") - return - - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - to_chat(user, "You [anchored ? "un" : ""]anchor the brace.") - - anchored = !anchored - if(anchored) - connect() - else - disconnect() - -/obj/machinery/mining/brace/proc/connect() - - var/turf/T = get_step(get_turf(src), src.dir) - - for(var/thing in T.contents) - if(istype(thing, /obj/machinery/mining/drill)) - connected = thing - break - - if(!connected) +/obj/machinery/mining_drill/proc/unload_into_box(obj/structure/ore_box/box, mob/user) + if(!CanPhysicallyInteract(user)) return - if(!connected.supports) - connected.supports = list() - - icon_state = "mining_brace_active" - - connected.supports += src - connected.check_supports() - -/obj/machinery/mining/brace/proc/disconnect() - - if(!connected) return - - if(!connected.supports) connected.supports = list() - - icon_state = "mining_brace" - - connected.supports -= src - connected.check_supports() - connected = null - -/obj/machinery/mining/brace/dismantle() - if(connected) - disconnect() - ..() \ No newline at end of file + if(box?.Adjacent(src)) + if(!length(contained_ore)) + to_chat(user, SPAN_NOTICE("\The [src]'s storage cache is empty.")) + return + box.insert_ores(contained_ore, user) + contained_ore.Cut() + playsound(src, 'sound/machines/vending_machine.ogg', 60, 1) + playsound(box, 'sound/effects/rockcrumble.ogg', 60, 1) + visible_message( + SPAN_NOTICE("\The [user] unloads \the [src]'s storage cache into \the [box]."), + SPAN_NOTICE("You unload \the [src]'s storage cache into \the [box]."), + SPAN_NOTICE("You hear rocks falling into a container.") + ) + else + to_chat(user, SPAN_NOTICE("You must move an ore box up to \the [src] before you can unload it.")) diff --git a/code/modules/mining/drilling/drill_fsm.dm b/code/modules/mining/drilling/drill_fsm.dm new file mode 100644 index 00000000000..de129e235ed --- /dev/null +++ b/code/modules/mining/drilling/drill_fsm.dm @@ -0,0 +1,212 @@ +/datum/state_machine/drill + current_state = /decl/state/drill/unpowered + expected_type = /obj/machinery/mining_drill + base_type = /datum/state_machine/drill + + +/decl/state/drill + var/light_color = null + var/light_icon_state = "blink_slow" + var/entered_sound = null + var/exited_sound = null + var/power_usage = POWER_USE_IDLE + +/decl/state/drill/entered_state(obj/machinery/mining_drill/drill) + drill.queue_icon_update() + if(entered_sound) + playsound(drill, entered_sound, 40, FALSE) + drill.update_use_power(power_usage) + +/decl/state/drill/exited_state(obj/machinery/mining_drill/drill) + if(exited_sound) + playsound(drill, exited_sound, 40, FALSE) + +/decl/state/drill/proc/process(obj/machinery/mining_drill/drill) + + +/decl/state_transition/drill/is_open(obj/machinery/mining_drill/drill) + return drill.operable() + + +/// Unpowered state. Occurs when the battery dies or when turned off. +/decl/state/drill/unpowered + light_color = "#00000000" + power_usage = POWER_USE_OFF + light_icon_state = null + entered_sound = 'sound/mecha/mech-shutdown.ogg' + exited_sound = 'sound/mecha/powerup.ogg' + transitions = list( + /decl/state_transition/drill/recover_from_unpowered + ) + +/decl/state_transition/drill/unpowered + target = /decl/state/drill/unpowered + +/decl/state_transition/drill/unpowered/is_open(obj/machinery/mining_drill/drill) + return drill.inoperable() || drill.use_power == POWER_USE_OFF + + +/decl/state_transition/drill/recover_from_unpowered + target = /decl/state/drill/idle + +/decl/state_transition/drill/recover_from_unpowered/is_open(obj/machinery/mining_drill/drill) + return drill.operable() && drill.use_power != POWER_USE_OFF + + +/// Starting state for drills that are turned on or recovered from an issue. +/decl/state/drill/idle + light_color = "#ffffff" + transitions = list( + /decl/state_transition/drill/unpowered, + /decl/state_transition/drill/error, + /decl/state_transition/drill/storage_full, + /decl/state_transition/drill/scanning, + /decl/state_transition/drill/switching_target, + /decl/state_transition/drill/mining, + /decl/state_transition/drill/finished + ) + +/decl/state/drill/idle/entered_state(obj/machinery/mining_drill/drill) + . = ..() + drill.reset_drill() + + +/// State that occurs if there is a problem with the drill setup, such as lacking braces. +/decl/state/drill/error + light_color = "#ff0000" + entered_sound = 'sound/machines/buzz-sigh.ogg' + transitions = list( + /decl/state_transition/drill/unpowered, + /decl/state_transition/drill/recover_from_error + ) + +/decl/state_transition/drill/error + target = /decl/state/drill/error + +/decl/state_transition/drill/error/is_open(obj/machinery/mining_drill/drill) + return ..() && length(drill.supports) < drill.MINIMUM_SUPPORT_NUMBER + + +/decl/state_transition/drill/recover_from_error + target = /decl/state/drill/idle + +/decl/state_transition/drill/recover_from_error/is_open(obj/machinery/mining_drill/drill) + return ..() && length(drill.supports) >= drill.MINIMUM_SUPPORT_NUMBER + + +/// State that follows the starting state, where it determines which turfs to mine, and gives a visual effect of it scanning the surrounding ground. +/decl/state/drill/scanning + light_color = "#00ffff" + entered_sound = 'sound/effects/scanbeep.ogg' + transitions = list( + /decl/state_transition/drill/unpowered, + /decl/state_transition/drill/error, + /decl/state_transition/drill/switching_target, + /decl/state_transition/drill/finished + ) + +/decl/state/drill/scanning/process(obj/machinery/mining_drill/drill) + drill.populate_turfs_to_mine() + drill.scan_visuals() + + +/decl/state_transition/drill/scanning + target = /decl/state/drill/scanning + +/decl/state_transition/drill/scanning/is_open(obj/machinery/mining_drill/drill) + return ..() && !length(drill.turfs_to_mine) + + +/// State where the drill is actively mining a specific turf. +/decl/state/drill/mining + light_color = "#00ff00" + light_icon_state = "blink_fast" + power_usage = POWER_USE_ACTIVE + transitions = list( + /decl/state_transition/drill/unpowered, + /decl/state_transition/drill/error, + /decl/state_transition/drill/storage_full, + /decl/state_transition/drill/switching_target, + /decl/state_transition/drill/finished + ) + +/decl/state/drill/mining/process(obj/machinery/mining_drill/drill) + drill.mine_ore(drill.current_turf) + +/decl/state_transition/drill/mining + target = /decl/state/drill/mining + +/decl/state_transition/drill/mining/is_open(obj/machinery/mining_drill/drill) + return ..() && length(drill.turfs_to_mine) && drill.current_turf + + +/// State which occurs when the currently mined turf is depleted, and there is another turf to mine from, +/// thus the drill visually targets the next spot and provides some feedback to the player on how fast the mining is going. +/decl/state/drill/switching_target + light_color = "#008800" + light_icon_state = "blink_fast" + power_usage = POWER_USE_IDLE + entered_sound = 'sound/machines/airlock_open_force.ogg' + exited_sound = 'sound/machines/airlock_close_force.ogg' + transitions = list( + /decl/state_transition/drill/unpowered, + /decl/state_transition/drill/error, + /decl/state_transition/drill/mining, + /decl/state_transition/drill/finished + ) + +/decl/state/drill/switching_target/process(obj/machinery/mining_drill/drill) + if(!drill.turf_has_ore(drill.current_turf)) + if(istype(drill.current_turf)) + drill.turfs_to_mine -= drill.current_turf + if(has_extension(drill.current_turf, /datum/extension/buried_resources)) + remove_extension(drill.current_turf, /datum/extension/buried_resources) + if(length(drill.turfs_to_mine)) + drill.current_turf = drill.turfs_to_mine[1] + else + drill.current_turf = null + +/decl/state_transition/drill/switching_target + target = /decl/state/drill/switching_target + +/decl/state_transition/drill/switching_target/is_open(obj/machinery/mining_drill/drill) + return ..() && length(drill.turfs_to_mine) && !drill.turf_has_ore(drill.current_turf) + + +/// State which occurs when the ore storage is full, and the player needs to unload the ore for it to resume mining. +/decl/state/drill/storage_full + light_color = "#ffff00" + entered_sound = 'sound/machines/buzz-two.ogg' + transitions = list( + /decl/state_transition/drill/unpowered, + /decl/state_transition/drill/error, + /decl/state_transition/drill/recover_from_storage_full + ) + +/decl/state_transition/drill/storage_full + target = /decl/state/drill/storage_full + +/decl/state_transition/drill/storage_full/is_open(obj/machinery/mining_drill/drill) + return ..() && length(drill.contained_ore) >= drill.ore_capacity + +/decl/state_transition/drill/recover_from_storage_full + target = /decl/state/drill/idle + +/decl/state_transition/drill/recover_from_storage_full/is_open(obj/machinery/mining_drill/drill) + return ..() && length(drill.contained_ore) < drill.ore_capacity + + +/// State which occurs when there is no more ore to mine from the surrounding tiles. +/decl/state/drill/finished + light_color = "#0000ff" + entered_sound = 'sound/machines/ping.ogg' + transitions = list( + /decl/state_transition/drill/unpowered, + /decl/state_transition/drill/error + ) + +/decl/state_transition/drill/finished + target = /decl/state/drill/finished + +/decl/state_transition/drill/finished/is_open(obj/machinery/mining_drill/drill) + return ..() && !drill.current_turf && !length(drill.turfs_to_mine) \ No newline at end of file diff --git a/code/modules/mining/ore_box.dm b/code/modules/mining/ore_box.dm index 7c0adf71070..7dff5769a88 100644 --- a/code/modules/mining/ore_box.dm +++ b/code/modules/mining/ore_box.dm @@ -134,6 +134,13 @@ if(. && !QDELETED(src) && (severity == 1 || prob(50))) physically_destroyed() +/obj/structure/ore_box/receive_mouse_drop(atom/dropping, mob/user, params) + . = ..() + if(!. && istype(dropping, /obj/machinery/mining_drill)) + var/obj/machinery/mining_drill/D = dropping + D.unload_into_box(src, user) + + /obj/structure/ore_box/get_alt_interactions(mob/user) . = ..() LAZYADD(., /decl/interaction_handler/empty/ore_box) diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 16fd08aed18..4357110ccbb 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -761,7 +761,7 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new if(transferred_phases & MAT_PHASE_SOLID) var/solid_transferred = NONUNIT_FLOOR(min(amount_remaining, SOLID_VOLUME(src, type)), MINIMUM_CHEMICAL_VOLUME) F.add_reagent(type, solid_transferred, REAGENT_DATA(src, type), defer_update = TRUE, phase = MAT_PHASE_SOLID) - remove_reagent(type, solid_transferred, defer_update = TRUE, removed_phases = MAT_PHASE_LIQUID) + remove_reagent(type, solid_transferred, defer_update = TRUE, removed_phases = MAT_PHASE_SOLID) amount_remaining -= solid_transferred // Now that both liquid and solid components are removed, we can update if necessary. diff --git a/html/changelog.html b/html/changelog.html index 3fa1b06d356..b652d7d7973 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -52,6 +52,14 @@ -->
+

05 November 2024

+

Neerti updated:

+ +

01 November 2024

MistakeNot4892 updated:

- -

07 September 2024

-

MistakeNot4892 updated:

- - -

05 September 2024

-

Penelope Haze updated:

-
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index afedde036bc..6cfd2d0be5e 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -14907,3 +14907,10 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. MistakeNot4892: - tweak: Curries, soups and stews have been rewritten, please refer to the codex for recipes. +2024-11-05: + Neerti: + - tweak: Mining drill braces are now crafted from steel sheets directly. + - balance: Microlasers added to mining drills no longer multiply ore out of the + ground, but make the drill mine faster, proportionally increasing the energy + usage. + - balance: Capacitors added to mining drills are less powerful. diff --git a/icons/obj/mining_drill.dmi b/icons/obj/mining_drill.dmi index 95aab5f5bea..108c4a0a4a9 100644 Binary files a/icons/obj/mining_drill.dmi and b/icons/obj/mining_drill.dmi differ diff --git a/maps/antag_spawn/mercenary/mercenary_base.dmm b/maps/antag_spawn/mercenary/mercenary_base.dmm index 082f05c1afe..438c763609c 100644 --- a/maps/antag_spawn/mercenary/mercenary_base.dmm +++ b/maps/antag_spawn/mercenary/mercenary_base.dmm @@ -1700,7 +1700,7 @@ /turf/floor/plating, /area/map_template/merc_spawn) "fV" = ( -/obj/machinery/mining/drill, +/obj/machinery/mining_drill, /obj/structure/railing/mapped/no_density{ dir = 8 }, @@ -1953,7 +1953,7 @@ /turf/floor/airless, /area/space) "ls" = ( -/obj/machinery/mining/drill, +/obj/machinery/mining_drill, /obj/structure/railing/mapped/no_density{ dir = 8 }, @@ -2070,7 +2070,7 @@ /turf/floor/tiled, /area/map_template/merc_spawn) "qq" = ( -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /obj/machinery/light/spot, /turf/floor/plating, /area/map_template/merc_spawn) @@ -2450,7 +2450,7 @@ /turf/floor/plating, /area/map_template/merc_spawn) "LI" = ( -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /turf/floor/plating, /area/map_template/merc_spawn) "LY" = ( @@ -2529,7 +2529,7 @@ /turf/floor/airless, /area/map_template/merc_spawn) "Ok" = ( -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /obj/structure/railing/mapped/no_density{ dir = 1 }, diff --git a/maps/away/bearcat/bearcat-1.dmm b/maps/away/bearcat/bearcat-1.dmm index 9a6fc4c3102..8f082aaaa21 100644 --- a/maps/away/bearcat/bearcat-1.dmm +++ b/maps/away/bearcat/bearcat-1.dmm @@ -814,7 +814,7 @@ icon_state = "bulb1" }, /obj/effect/floor_decal/industrial/warning/corner, -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /turf/floor/tiled/usedup, /area/ship/scrap/cargo/lower) "bP" = ( diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm index e23c53d0a88..d41458d755d 100644 --- a/maps/exodus/exodus-2.dmm +++ b/maps/exodus/exodus-2.dmm @@ -23358,7 +23358,7 @@ /area/exodus/research/mixing) "aXM" = ( /obj/effect/floor_decal/industrial/hatch/yellow, -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /turf/floor/tiled/steel_grid, /area/exodus/quartermaster/storage) "aXN" = ( @@ -51492,7 +51492,7 @@ /area/exodus/maintenance/research_starboard) "ccN" = ( /obj/effect/floor_decal/industrial/hatch/yellow, -/obj/machinery/mining/drill, +/obj/machinery/mining_drill, /turf/floor/tiled/steel_grid, /area/exodus/quartermaster/storage) "ccO" = ( diff --git a/maps/ministation/ministation-0.dmm b/maps/ministation/ministation-0.dmm index 1b1735e85d0..d3503643c1e 100644 --- a/maps/ministation/ministation-0.dmm +++ b/maps/ministation/ministation-0.dmm @@ -1588,7 +1588,7 @@ dir = 9 }, /obj/effect/floor_decal/industrial/hatch/yellow, -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /turf/floor/tiled, /area/ministation/cargo) "gk" = ( @@ -1749,7 +1749,7 @@ /area/ministation/hall/n) "gL" = ( /obj/effect/floor_decal/industrial/hatch/yellow, -/obj/machinery/mining/drill, +/obj/machinery/mining_drill, /turf/floor/tiled, /area/ministation/cargo) "gM" = ( @@ -5517,7 +5517,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden{ dir = 6 }, -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /obj/effect/floor_decal/industrial/hatch/yellow, /turf/floor/tiled, /area/ministation/cargo) @@ -11751,7 +11751,7 @@ /area/space) "Rm" = ( /obj/machinery/atmospherics/pipe/simple/hidden, -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /obj/effect/floor_decal/industrial/hatch/yellow, /turf/floor/tiled, /area/ministation/cargo) diff --git a/maps/random_ruins/exoplanet_ruins/drill_site/drill_site.dmm b/maps/random_ruins/exoplanet_ruins/drill_site/drill_site.dmm index e098bd7694c..3e1ee2d531e 100644 --- a/maps/random_ruins/exoplanet_ruins/drill_site/drill_site.dmm +++ b/maps/random_ruins/exoplanet_ruins/drill_site/drill_site.dmm @@ -19,7 +19,7 @@ /turf/template_noop, /area/template_noop) "f" = ( -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /obj/abstract/landmark/clear, /turf/template_noop, /area/template_noop) @@ -40,7 +40,7 @@ /turf/template_noop, /area/template_noop) "k" = ( -/obj/machinery/mining/drill, +/obj/machinery/mining_drill, /obj/abstract/landmark/clear, /turf/template_noop, /area/template_noop) diff --git a/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm b/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm index a750e66c114..2a8d646fe05 100644 --- a/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm +++ b/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm @@ -6778,7 +6778,7 @@ /turf/floor/tiled/techfloor, /area/map_template/colony/jail) "mZ" = ( -/obj/machinery/mining/brace{ +/obj/structure/drill_brace{ dir = 4 }, /obj/effect/floor_decal/industrial/outline/yellow, @@ -6924,7 +6924,7 @@ /turf/floor/fake_grass, /area/map_template/colony/hydroponics) "nm" = ( -/obj/machinery/mining/drill, +/obj/machinery/mining_drill, /obj/effect/floor_decal/industrial/outline/yellow, /turf/floor/concrete, /area/template_noop) @@ -6952,7 +6952,7 @@ /turf/floor/tiled/dark/monotile, /area/map_template/colony/jail) "nq" = ( -/obj/machinery/mining/brace{ +/obj/structure/drill_brace{ dir = 8 }, /obj/effect/floor_decal/industrial/outline/yellow, diff --git a/maps/tradeship/tradeship-1.dmm b/maps/tradeship/tradeship-1.dmm index b28e804a66e..1557c94e48e 100644 --- a/maps/tradeship/tradeship-1.dmm +++ b/maps/tradeship/tradeship-1.dmm @@ -189,7 +189,7 @@ /area/ship/trade/maintenance/eva) "ax" = ( /obj/effect/floor_decal/corner/beige, -/obj/machinery/mining/drill, +/obj/machinery/mining_drill, /turf/floor/tiled, /area/ship/trade/cargo/lower) "ay" = ( @@ -411,7 +411,7 @@ /obj/structure/handrail{ dir = 4 }, -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /obj/effect/floor_decal/corner/beige{ dir = 9 }, @@ -2901,7 +2901,7 @@ /area/ship/trade/science/fabricaton) "Js" = ( /obj/effect/floor_decal/industrial/outline/yellow, -/obj/machinery/mining/brace, +/obj/structure/drill_brace, /turf/floor/tiled/monotile, /area/ship/trade/cargo/lower) "JM" = ( diff --git a/nebula.dme b/nebula.dme index e25d3366696..8aff38e3f8a 100644 --- a/nebula.dme +++ b/nebula.dme @@ -2748,8 +2748,10 @@ #include "code\modules\mining\mine_items.dm" #include "code\modules\mining\mine_turfs.dm" #include "code\modules\mining\ore_box.dm" +#include "code\modules\mining\drilling\brace.dm" #include "code\modules\mining\drilling\drill.dm" #include "code\modules\mining\drilling\drill_act.dm" +#include "code\modules\mining\drilling\drill_fsm.dm" #include "code\modules\mining\machinery\_material_processing.dm" #include "code\modules\mining\machinery\material_compressor.dm" #include "code\modules\mining\machinery\material_extractor.dm" diff --git a/tools/map_migrations/4545_mining_drills.txt b/tools/map_migrations/4545_mining_drills.txt new file mode 100644 index 00000000000..3f8e0cdc4e3 --- /dev/null +++ b/tools/map_migrations/4545_mining_drills.txt @@ -0,0 +1,2 @@ +/obj/machinery/mining/drill/@SUBTYPES : /obj/machinery/mining_drill/@SUBTYPES{@OLD} +/obj/machinery/mining/brace/@SUBTYPES : /obj/structure/drill_brace/@SUBTYPES{@OLD}