diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 6172121533a..b2fad9e88d2 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -22239,7 +22239,7 @@ /obj/machinery/conveyor{ id = "mining" }, -/obj/machinery/bouldertech/brm, +/obj/machinery/brm, /turf/open/floor/iron, /area/station/cargo/miningfoundry) "hZP" = ( diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 3b78dacec06..f1137f100e9 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -41240,7 +41240,7 @@ }, /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, -/obj/machinery/bouldertech/brm, +/obj/machinery/brm, /turf/open/floor/iron, /area/mine/production) "mHu" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 6b8edaaba10..443f7049dea 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -23833,7 +23833,7 @@ /obj/machinery/conveyor{ id = "mining" }, -/obj/machinery/bouldertech/brm, +/obj/machinery/brm, /turf/open/floor/iron, /area/station/cargo/miningoffice) "iIf" = ( diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 9a1372065a6..63a8be2d8cf 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -73293,7 +73293,7 @@ /area/station/security/detectives_office/private_investigators_office) "thH" = ( /obj/structure/cable, -/obj/machinery/bouldertech/brm, +/obj/machinery/brm, /obj/machinery/conveyor{ dir = 4; id = "mining" diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 57379c2353e..82c5377741f 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -17448,7 +17448,7 @@ /turf/open/floor/iron/dark, /area/station/cargo/miningdock/oresilo) "fdc" = ( -/obj/machinery/bouldertech/brm, +/obj/machinery/brm, /obj/machinery/conveyor{ dir = 8; id = "mining" diff --git a/code/controllers/subsystem/ore_generation.dm b/code/controllers/subsystem/ore_generation.dm index 162bc2e99d9..ca8aa09d611 100644 --- a/code/controllers/subsystem/ore_generation.dm +++ b/code/controllers/subsystem/ore_generation.dm @@ -6,11 +6,11 @@ SUBSYSTEM_DEF(ore_generation) runlevels = RUNLEVEL_GAME /// All ore vents that are currently producing boulders. - var/list/processed_vents = list() - /// All the boulders that have been produced by ore vents to be pulled by BRM machines. - var/list/available_boulders = list() + var/list/obj/structure/ore_vent/processed_vents = list() /// All the ore vents that are currently in the game, not just the ones that are producing boulders. - var/list/possible_vents = list() + var/list/obj/structure/ore_vent/possible_vents = list() + /// All the boulders that have been produced by ore vents to be pulled by BRM machines. + var/list/obj/item/boulder/available_boulders = list() /** * A list of all the minerals that are being mined by ore vents. We reset this list every time cave generation is done. * Generally Should be empty by the time initialize ends on lavaland. @@ -18,6 +18,7 @@ SUBSYSTEM_DEF(ore_generation) * If we call cave_generation more than once, we copy a list from the lists in lists/ores_spawned.dm */ var/list/ore_vent_minerals = list() + /// A tracker of how many of each ore vent size we have in the game. Useful for tracking purposes. var/list/ore_vent_sizes = list( LARGE_VENT_TYPE = 0, @@ -60,7 +61,7 @@ SUBSYSTEM_DEF(ore_generation) return SS_INIT_SUCCESS /datum/controller/subsystem/ore_generation/fire(resumed) - available_boulders = list() // reset upon new fire. + available_boulders.Cut() // reset upon new fire. for(var/obj/structure/ore_vent/current_vent as anything in processed_vents) var/local_vent_count = 0 @@ -71,6 +72,4 @@ SUBSYSTEM_DEF(ore_generation) if(local_vent_count >= MAX_BOULDERS_PER_VENT) continue //We don't want to be accountable for literally hundreds of unprocessed boulders for no reason. - var/obj/item/boulder/new_rock = current_vent.produce_boulder() - available_boulders += new_rock - + available_boulders += current_vent.produce_boulder() diff --git a/code/datums/wires/brm.dm b/code/datums/wires/brm.dm deleted file mode 100644 index c00d7875035..00000000000 --- a/code/datums/wires/brm.dm +++ /dev/null @@ -1,14 +0,0 @@ -/datum/wires/brm - holder_type = /obj/machinery/bouldertech/brm - proper_name = "Boulder Retrieval Matrix" - -/datum/wires/brm/New(atom/holder) - add_duds(1) - return ..() - -/datum/wires/brm/on_pulse(wire) - var/obj/machinery/bouldertech/brm/brm_holder = holder - if(brm_holder.panel_open) - return - brm_holder.toggle_auto_on() - diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index 8e5f2d1dfc5..382cf60ddc6 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -1559,7 +1559,7 @@ /obj/item/circuitboard/machine/brm name = "Boulder Retrieval Matrix" greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/bouldertech/brm + build_path = /obj/machinery/brm req_components = list( /datum/stock_part/capacitor = 1, /datum/stock_part/scanning_module = 1, @@ -1571,10 +1571,9 @@ greyscale_colors = CIRCUIT_COLOR_SUPPLY build_path = /obj/machinery/bouldertech/refinery req_components = list( - /obj/item/reagent_containers/cup/beaker = 1, /obj/item/assembly/igniter/condenser = 1, /datum/stock_part/servo = 2, - /datum/stock_part/matter_bin = 1, + /datum/stock_part/matter_bin = 2, ) /obj/item/circuitboard/machine/smelter diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index fe663efec48..08a4394346a 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -2,6 +2,7 @@ #define MINERAL_TYPE_OPTIONS_RANDOM 4 #define OVERLAY_OFFSET_START 0 #define OVERLAY_OFFSET_EACH 5 +#define MINERALS_PER_BOULDER 3 /obj/structure/ore_vent name = "ore vent" @@ -22,13 +23,8 @@ var/unique_vent = FALSE /// What icon_state do we use when the ore vent has been tapped? var/icon_state_tapped = "ore_vent_active" - /// A weighted list of what minerals are contained in this vent, with weight determining how likely each mineral is to be picked in produced boulders. var/list/mineral_breakdown = list() - /// How many rolls on the mineral_breakdown list are made per boulder produced? EG: 3 rolls means 3 minerals per boulder, with order determining percentage. - var/minerals_per_boulder = 3 - /// How many minerals are picked to be in the ore vent? These are added to the mineral_breakdown list. - var/minerals_per_breakdown = MINERAL_TYPE_OPTIONS_RANDOM /// What size boulders does this vent produce? var/boulder_size = BOULDER_SIZE_SMALL /// Reference to this ore vent's NODE drone, to track wave success. @@ -67,9 +63,9 @@ var/artifact_chance = 0 /// We use a cooldown to prevent the wave defense from being started multiple times. COOLDOWN_DECLARE(wave_cooldown) + /// We use a cooldown to prevent players from tapping boulders rapidly from vents. COOLDOWN_DECLARE(manual_vent_cooldown) - /obj/structure/ore_vent/Initialize(mapload) if(mapload) generate_description() @@ -121,14 +117,14 @@ if(do_after(user, boulder_size * 1 SECONDS, src)) user.apply_damage(20, STAMINA) playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) - produce_boulder() + produce_boulder(TRUE) visible_message(span_notice("You've successfully produced a boulder! Boy are your arms tired.")) /obj/structure/ore_vent/attack_basic_mob(mob/user, list/modifiers) . = ..() if(!HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) return - produce_boulder() + produce_boulder(TRUE) /obj/structure/ore_vent/is_buckle_possible(mob/living/target, force, check_loc) . = ..() @@ -155,17 +151,6 @@ context[SCREENTIP_CONTEXT_LMB] = "Scan vent" return CONTEXTUAL_SCREENTIP_SET -/** - * Picks n types of materials to pack into a boulder created by this ore vent, where n is this vent's minerals_per_boulder. - * Then assigns custom_materials based on boulder_size, assigned via the ore_quantity_function - */ -/obj/structure/ore_vent/proc/create_mineral_contents() - var/list/refined_list = list() - for(var/iteration in 1 to minerals_per_boulder) - var/datum/material/material = pick_weight(mineral_breakdown) - refined_list[material] += ore_quantity_function(iteration) - return refined_list - /** * This proc is called when the ore vent is initialized, in order to determine what minerals boulders it spawns can contain. * The materials available are determined by SSore_generation.ore_vent_minerals, which is a list of all minerals that can be contained in ore vents for a given cave generation. @@ -372,22 +357,38 @@ * @params apply_cooldown Should we apply a cooldown to producing boulders? Default's false, used by manual boulder production (goldgrubs, golems, etc). */ /obj/structure/ore_vent/proc/produce_boulder(apply_cooldown = FALSE) - if(!COOLDOWN_FINISHED(src, manual_vent_cooldown)) + RETURN_TYPE(/obj/item/boulder) + + //cooldown applies only for manual processing by hand + if(apply_cooldown && !COOLDOWN_FINISHED(src, manual_vent_cooldown)) return + + //produce the boulder var/obj/item/boulder/new_rock if(prob(artifact_chance)) new_rock = new /obj/item/boulder/artifact(loc) else new_rock = new /obj/item/boulder(loc) - var/list/mats_list = create_mineral_contents() Shake(duration = 1.5 SECONDS) + + //decorate the boulder with materials + var/list/mats_list = list() + for(var/iteration in 1 to MINERALS_PER_BOULDER) + var/datum/material/material = pick_weight(mineral_breakdown) + mats_list[material] += ore_quantity_function(iteration) new_rock.set_custom_materials(mats_list) - new_rock.flavor_boulder(src) + + //set size & durability + new_rock.boulder_size = boulder_size + new_rock.durability = rand(2, boulder_size) //randomize durability a bit for some flavor. + new_rock.boulder_string = boulder_icon_state + new_rock.update_appearance(UPDATE_ICON_STATE) + + //start the cooldown & return the boulder if(apply_cooldown) COOLDOWN_START(src, manual_vent_cooldown, 10 SECONDS) return new_rock - //comes with the station, and is already tapped. /obj/structure/ore_vent/starter_resources name = "active ore vent" @@ -402,12 +403,6 @@ ) /obj/structure/ore_vent/random - /// Static list of ore vent types, for random generation. - var/static/list/ore_vent_types = list( - BOULDER_SIZE_SMALL, - BOULDER_SIZE_MEDIUM, - BOULDER_SIZE_LARGE, - ) /obj/structure/ore_vent/random/Initialize(mapload) . = ..() @@ -446,7 +441,7 @@ /mob/living/simple_animal/hostile/asteroid/wolf, ) ore_vent_options = list( - "small", + SMALL_VENT_TYPE, ) /obj/structure/ore_vent/random/icebox/lower @@ -459,12 +454,11 @@ /mob/living/simple_animal/hostile/asteroid/wolf, ) ore_vent_options = list( - "small", - "medium", - "large", + SMALL_VENT_TYPE = 3, + MEDIUM_VENT_TYPE = 5, + LARGE_VENT_TYPE = 7, ) - /obj/structure/ore_vent/boss name = "menacing ore vent" desc = "An ore vent, brimming with underground ore. This one has an evil aura about it. Better be careful." @@ -536,3 +530,4 @@ #undef MINERAL_TYPE_OPTIONS_RANDOM #undef OVERLAY_OFFSET_START #undef OVERLAY_OFFSET_EACH +#undef MINERALS_PER_BOULDER diff --git a/code/modules/mining/boulder_processing/_boulder_processing.dm b/code/modules/mining/boulder_processing/_boulder_processing.dm index 3372f77ebb5..d7d4be2557e 100644 --- a/code/modules/mining/boulder_processing/_boulder_processing.dm +++ b/code/modules/mining/boulder_processing/_boulder_processing.dm @@ -3,185 +3,264 @@ desc = "You shouldn't be seeing this! And bouldertech isn't even a real company!" icon = 'icons/obj/machines/mining_machines.dmi' icon_state = "ore_redemption" + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.5 anchored = TRUE density = TRUE /// What is the efficiency of minerals produced by the machine? var/refining_efficiency = 1 - /// How many boulders can we process maximum per loop? - var/boulders_processing_max = 1 - /// What boulder(s) are we holding? - var/list/boulders_contained = list() + /// How much durability of an boulder can we reduce + var/boulders_processing_count = 2 /// How many boulders can we hold maximum? var/boulders_held_max = 1 - /// Does this machine have a mineral storage link to the silo? - var/holds_minerals = FALSE - /// What materials do we accept and process out of boulders? Removing iron from an iron/glass boulder would leave a boulder with glass. - var/list/processable_materials = list() - /// If we get a boulder with one of these inside, we'll drop it back out. - var/static/list/drop_if_contained = list( - /obj/item/relic, - ) - /// What sound plays when a thing operates? var/usage_sound = 'sound/machines/mining/wooping_teleport.ogg' - /// Cooldown associated with the usage_sound played. - COOLDOWN_DECLARE(sound_cooldown) - /// Silo link to it's materials list. var/datum/component/remote_materials/silo_materials - ///Does this machine hold mining points? - var/holds_mining_points = FALSE /// Mining points held by the machine for miners. var/points_held = 0 + ///The action verb to display to players + var/action = "processing" + + /// Cooldown associated with the sound played for collecting mining points. + COOLDOWN_DECLARE(sound_cooldown) + /// Cooldown associated with taking in boulds. + COOLDOWN_DECLARE(accept_cooldown) /obj/machinery/bouldertech/Initialize(mapload) . = ..() + + silo_materials = AddComponent( + /datum/component/remote_materials, \ + mapload, \ + mat_container_flags = MATCONTAINER_NO_INSERT \ + ) + register_context() - if(holds_minerals) - silo_materials = AddComponent(/datum/component/remote_materials, mapload) /obj/machinery/bouldertech/LateInitialize() . = ..() - if(!holds_minerals) - return var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) AddElement(/datum/element/connect_loc, loc_connections) /obj/machinery/bouldertech/Destroy() - boulders_contained = null silo_materials = null return ..() -/obj/machinery/bouldertech/update_icon_state() - . = ..() - if(anchored) - icon_state ="[initial(icon_state)]" - else - icon_state ="[initial(icon_state)]-off" - -/obj/machinery/bouldertech/wrench_act(mob/living/user, obj/item/tool) - . = ITEM_INTERACT_BLOCKING - if(default_unfasten_wrench(user, tool, time = 1.5 SECONDS) == SUCCESSFUL_UNFASTEN) - update_appearance(UPDATE_ICON_STATE) - START_PROCESSING(SSmachines, src) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/bouldertech/screwdriver_act(mob/living/user, obj/item/tool) - . = ..() - if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-off", initial(icon_state), tool)) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/bouldertech/crowbar_act(mob/living/user, obj/item/tool) - . = ..() - if(default_pry_open(tool, close_after_pry = TRUE, closed_density = FALSE)) - return ITEM_INTERACT_SUCCESS - if(default_deconstruction_crowbar(tool)) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/bouldertech/attackby(obj/item/attacking_item, mob/user, params) - if(holds_minerals && istype(attacking_item, /obj/item/boulder)) - var/obj/item/boulder/my_boulder = attacking_item - update_boulder_count() - if(!accept_boulder(my_boulder)) - balloon_alert_to_viewers("full!") - return - balloon_alert_to_viewers("accepted") - START_PROCESSING(SSmachines, src) - return TRUE - if(istype(attacking_item, /obj/item/card/id) && holds_mining_points) - if(points_held <= 0) - balloon_alert_to_viewers("no points to claim!") - if(!COOLDOWN_FINISHED(src, sound_cooldown)) - return TRUE - COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) - playsound(src, 'sound/machines/buzz-sigh.ogg', 30, FALSE) - return FALSE - var/obj/item/card/id/id_card = attacking_item - var/amount = tgui_input_number(user, "How many mining points do you wish to claim? ID Balance: [id_card.registered_account.mining_points], stored mining points: [points_held]", "Transfer Points", max_value = points_held, min_value = 0, round_value = 1) - if(!amount) - return TRUE - if(amount > points_held) - amount = points_held - id_card.registered_account.mining_points += amount - points_held = round(points_held - amount) - to_chat(user, span_notice("You claim [amount] mining points from \the [src] to [id_card].")) - return TRUE - return ..() - -/obj/machinery/bouldertech/attack_hand_secondary(mob/user, list/modifiers) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return - if(!anchored) - balloon_alert(user, "anchor first!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(!holds_minerals) - return SECONDARY_ATTACK_CONTINUE_CHAIN - if(!length(boulders_contained)) - balloon_alert_to_viewers("No boulders to remove!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - remove_boulder(pick(boulders_contained)) - return SECONDARY_ATTACK_CONTINUE_CHAIN - /obj/machinery/bouldertech/on_deconstruction(disassembled) if(length(contents)) for(var/obj/item/boulder/boulder in contents) remove_boulder(boulder) -/obj/machinery/bouldertech/process() - if(!anchored) - return PROCESS_KILL - var/stop_processing_check = FALSE - var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call - for(var/obj/item/potential_boulder as anything in boulders_contained) - if(QDELETED(potential_boulder)) - boulders_contained -= potential_boulder - break - if(boulders_concurrent <= 0) - break //Try again next time +/obj/machinery/bouldertech/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = CONTEXTUAL_SCREENTIP_SET - if(!istype(potential_boulder, /obj/item/boulder)) - potential_boulder.forceMove(drop_location()) - CRASH("\The [src] had a non-boulder in it's boulders contained!") + if(isnull(held_item)) + context[SCREENTIP_CONTEXT_RMB] = "Remove Boulder" + return - var/obj/item/boulder/boulder = potential_boulder - if(boulder.durability < 0) - CRASH("\The [src] had a boulder with negative durability!") - if(!check_for_processable_materials(boulder.custom_materials)) //Checks for any new materials we can process. - boulders_concurrent-- //We count skipped boulders - remove_boulder(boulder) - continue - boulders_concurrent-- - boulder.durability-- //One less durability to the processed boulder. - if(COOLDOWN_FINISHED(src, sound_cooldown)) - COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) - playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) //This can get annoying. One play per process() call. - stop_processing_check = TRUE - if(boulder.durability <= 0) - breakdown_boulder(boulder) //Crack that bouwlder open! - continue - if(!stop_processing_check) - playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) - return PROCESS_KILL + if(istype(held_item, /obj/item/boulder)) + context[SCREENTIP_CONTEXT_LMB] = "Insert boulder" + else if(istype(held_item, /obj/item/card/id) && points_held > 0) + context[SCREENTIP_CONTEXT_LMB] = "Claim mining points" + else if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" + else if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "" : "Un"] Anchor" + else if(panel_open && held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" +/obj/machinery/bouldertech/examine(mob/user) + . = ..() + . += span_notice("The machine reads that it has [span_bold("[points_held] mining points")] stored. Swipe an ID to claim them.") + . += span_notice("Click to remove a stored boulder.") + + var/boulder_count = 0 + for(var/obj/item/boulder/potential_boulder in contents) + boulder_count += 1 + . += span_notice("Storage capacity = [boulder_count]/[boulders_held_max] boulders.") + . += span_notice("Can process upto [boulders_processing_count] boulders at a time.") + + if(anchored) + . += span_notice("Its [EXAMINE_HINT("anchored")] in place.") + else + . += span_warning("It needs to be [EXAMINE_HINT("anchored")] to start operations.") + + . += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "closed" : "open"].") + + if(panel_open) + . += span_notice("The whole machine can be [EXAMINE_HINT("pried")] apart.") + +/obj/machinery/bouldertech/update_icon_state() + . = ..() + var/suffix = "" + if(!anchored || !is_operational || (machine_stat & (BROKEN | NOPOWER)) || panel_open) + suffix = "-off" + icon_state ="[initial(icon_state)][suffix]" + +/obj/machinery/bouldertech/wrench_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_unfasten_wrench(user, tool, time = 1.5 SECONDS) == SUCCESSFUL_UNFASTEN) + if(anchored) + begin_processing() + else + end_processing() + update_appearance(UPDATE_ICON_STATE) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/bouldertech/screwdriver_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-off", initial(icon_state), tool)) + update_appearance(UPDATE_ICON_STATE) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/bouldertech/crowbar_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_crowbar(tool)) + return ITEM_INTERACT_SUCCESS /obj/machinery/bouldertech/CanAllowThrough(atom/movable/mover, border_dir) if(!anchored) return FALSE - if(boulders_contained.len >= boulders_held_max) - return FALSE if(istype(mover, /obj/item/boulder)) var/obj/item/boulder/boulder = mover - return boulder.can_get_processed() + return can_process_boulder(boulder) return ..() -/obj/machinery/bouldertech/examine(mob/user) +/** + * Can we process the boulder, checks only the boulders state & machines capacity + * Arguments + * + * * obj/item/boulder/new_boulder - the boulder we are checking + */ +/obj/machinery/bouldertech/proc/can_process_boulder(obj/item/boulder/new_boulder) + PRIVATE_PROC(TRUE) + SHOULD_BE_PURE(TRUE) + + //machine not operational + if(!anchored || panel_open || !is_operational || machine_stat & (BROKEN | NOPOWER)) + return FALSE + + //not a valid boulder + if(!istype(new_boulder) || QDELETED(new_boulder)) + return FALSE + + //someone just processed this + if(new_boulder.processed_by) + return FALSE + + //no space to hold boulders + var/boulder_count = 0 + for(var/obj/item/boulder/potential_boulder in contents) + boulder_count += 1 + if(boulder_count >= boulders_held_max) + return FALSE + + //did we cooldown enough to accept a boulder + return COOLDOWN_FINISHED(src, accept_cooldown) + +/** + * Accepts a boulder into the machine. Used when a boulder is first placed into the machine. + * Arguments + * + * * obj/item/boulder/new_boulder - the boulder to accept + */ +/obj/machinery/bouldertech/proc/accept_boulder(obj/item/boulder/new_boulder) + if(!can_process_boulder(new_boulder)) + return FALSE + + new_boulder.forceMove(src) + + COOLDOWN_START(src, accept_cooldown, 1.5 SECONDS) + + return TRUE + +/obj/machinery/bouldertech/proc/on_entered(datum/source, atom/movable/atom_movable) + SIGNAL_HANDLER + + if(!can_process_boulder(atom_movable)) + return + + INVOKE_ASYNC(src, PROC_REF(accept_boulder), atom_movable) + +/** + * Looks for a boost to the machine's efficiency, and applies it if found. + * Applied more on the chemistry integration but can be used for other things if desired. + */ +/obj/machinery/bouldertech/proc/check_for_boosts() + PROTECTED_PROC(TRUE) + + refining_efficiency = initial(refining_efficiency) //Reset refining efficiency to 100%. + +/** + * Checks if this machine can process this material + * Arguments + * + * * datum/material/mat - the material to process + */ +/obj/machinery/bouldertech/proc/can_process_material(datum/material/mat) + PROTECTED_PROC(TRUE) + + return FALSE + +/obj/machinery/bouldertech/attackby(obj/item/attacking_item, mob/user, params) + if(panel_open) + return ..() + + if(istype(attacking_item, /obj/item/boulder)) + . = TRUE + var/obj/item/boulder/my_boulder = attacking_item + if(!accept_boulder(my_boulder)) + balloon_alert_to_viewers("cannot accept!") + return + balloon_alert_to_viewers("accepted") + return + + if(istype(attacking_item, /obj/item/card/id)) + . = TRUE + if(points_held <= 0) + balloon_alert_to_viewers("no points to claim!") + if(!COOLDOWN_FINISHED(src, sound_cooldown)) + return + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, FALSE) + return + + var/obj/item/card/id/id_card = attacking_item + var/amount = tgui_input_number(user, "How many mining points do you wish to claim? ID Balance: [id_card.registered_account.mining_points], stored mining points: [points_held]", "Transfer Points", max_value = points_held, min_value = 0, round_value = 1) + if(!amount) + return + if(amount > points_held) + amount = points_held + id_card.registered_account.mining_points += amount + points_held = round(points_held - amount) + to_chat(user, span_notice("You claim [amount] mining points from \the [src] to [id_card].")) + return + + return ..() + +/obj/machinery/bouldertech/attack_hand_secondary(mob/user, list/modifiers) . = ..() - if(holds_mining_points) - . += span_notice("The machine reads that it has [span_bold("[points_held] mining points")] stored. Swipe an ID to claim them.") + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || panel_open) + return + if(!anchored) + balloon_alert(user, "anchor first!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(panel_open) + balloon_alert(user, "close panel!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/obj/item/boulder/boulder = locate(/obj/item/boulder) in src + if(!boulder) + balloon_alert_to_viewers("no boulders to remove!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(!remove_boulder(boulder)) + balloon_alert_to_viewers("no space to remove!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN /** * Accepts a boulder into the machinery, then converts it into minerals. @@ -190,159 +269,93 @@ * @param chosen_boulder The boulder to being breaking down into minerals. */ /obj/machinery/bouldertech/proc/breakdown_boulder(obj/item/boulder/chosen_boulder) + PRIVATE_PROC(TRUE) + if(QDELETED(chosen_boulder)) return FALSE if(chosen_boulder.loc != src) return FALSE - if(!length(chosen_boulder.custom_materials)) - qdel(chosen_boulder) - playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - update_boulder_count() - return FALSE - if(isnull(silo_materials)) - return FALSE - //here we loop through the boulder's ores - var/list/processable_ores = list() - var/tripped = FALSE - //If a material is in the boulder's custom_materials, but not in the processable_materials list, we add it to the processable_ores list to add back to a leftover boulder. - for(var/datum/material/possible_mat as anything in chosen_boulder.custom_materials) - if(!is_type_in_list(possible_mat, processable_materials)) - continue - var/quantity = chosen_boulder.custom_materials[possible_mat] - points_held = round(points_held + (quantity * possible_mat.points_per_unit * MINING_POINT_MACHINE_MULTIPLIER)) // put point total here into machine - processable_ores += possible_mat - processable_ores[possible_mat] = quantity - chosen_boulder.custom_materials -= possible_mat //Remove it from the boulder now that it's tracked - tripped = TRUE - if(!tripped) - remove_boulder(chosen_boulder) - say("Nothing to process!") - return FALSE //we shouldn't spend more time processing a boulder with contents we don't care about. - use_power(BASE_MACHINE_ACTIVE_CONSUMPTION) - check_for_boosts() //Calls the relevant behavior for boosting the machine's efficiency, if able. - var/is_artifact = (istype(chosen_boulder, /obj/item/boulder/artifact)) //We need to know if it's an artifact so we can carry it over to the new boulder. - var/obj/item/boulder/disposable_boulder = new (src) - disposable_boulder.custom_materials = processable_ores - silo_materials.insert_item(disposable_boulder, refining_efficiency) - qdel(disposable_boulder) + //if boulders are kept inside because there is no space to eject them, then they could be reprocessed, lets avoid that + if(!chosen_boulder.processed_by) + check_for_boosts() - refining_efficiency = initial(refining_efficiency) //Reset refining efficiency to 100% now that we've processed any relevant ores. - if(!length(chosen_boulder.custom_materials)) - playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - if(is_artifact) - points_held = round((points_held + MINER_POINT_MULTIPLIER) * MINING_POINT_MACHINE_MULTIPLIER) /// Artifacts give bonus points! - chosen_boulder.break_apart() - update_boulder_count() - return TRUE //We've processed all the materials in the boulder, so we can just destroy it in break_apart. + //here we loop through the boulder's ores + var/list/rejected_mats = list() + for(var/datum/material/possible_mat as anything in chosen_boulder.custom_materials) + var/quantity = chosen_boulder.custom_materials[possible_mat] * refining_efficiency + if(!can_process_material(possible_mat)) + rejected_mats[possible_mat] = quantity + continue + points_held = round(points_held + (quantity * possible_mat.points_per_unit * MINING_POINT_MACHINE_MULTIPLIER)) // put point total here into machine + if(!silo_materials.mat_container.insert_amount_mat(quantity, possible_mat)) + rejected_mats[possible_mat] = quantity + use_power(active_power_usage) - chosen_boulder.restart_processing_cooldown() //So that we don't pick it back up! - chosen_boulder.durability = rand(chosen_boulder.boulder_size, chosen_boulder.boulder_size + BOULDER_SIZE_SMALL) //Reset durability to a random value between the boulder's size and a little more. + //puts back materials that couldn't be processed + chosen_boulder.set_custom_materials(rejected_mats, refining_efficiency) + + //break the boulder down if we have processed all its materials + if(!length(chosen_boulder.custom_materials)) + playsound(loc, usage_sound, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + if(istype(chosen_boulder, /obj/item/boulder/artifact)) + points_held = round((points_held + MINER_POINT_MULTIPLIER) * MINING_POINT_MACHINE_MULTIPLIER) /// Artifacts give bonus points! + chosen_boulder.break_apart() + return TRUE //We've processed all the materials in the boulder, so we can just destroy it in break_apart. + + chosen_boulder.processed_by = src + + //eject the boulder since we are done with it remove_boulder(chosen_boulder) - return TRUE -/** - * Accepts a boulder into the machine. Used when a boulder is first placed into the machine. - * @param new_boulder The boulder to be accepted. - */ -/obj/machinery/bouldertech/proc/accept_boulder(obj/item/boulder/new_boulder) - if(isnull(new_boulder)) - return FALSE - if(boulders_contained.len >= boulders_held_max) //Full already - return FALSE - if(!istype(new_boulder)) //Can't be processed - return FALSE - if(!new_boulder.custom_materials) //Shouldn't happen, but just in case. - qdel(new_boulder) - playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - return FALSE - new_boulder.forceMove(src) - boulders_contained += new_boulder - SSore_generation.available_boulders -= new_boulder - START_PROCESSING(SSmachines, src) //Starts processing if we aren't already. - return TRUE +/obj/machinery/bouldertech/process() + if(!anchored || panel_open || !is_operational || machine_stat & (BROKEN | NOPOWER)) + return + + var/boulders_found = FALSE + var/boulders_processed = boulders_processing_count + for(var/obj/item/boulder/potential_boulder in contents) + boulders_found = TRUE + if(boulders_processed <= 0) + break //Try again next time + boulders_processed-- + + if(potential_boulder.durability > 0) + potential_boulder.durability -= 1 + if(potential_boulder.durability > 0) + continue + + breakdown_boulder(potential_boulder) + boulders_found = FALSE + + //when the boulder is removed it plays sound and displays a balloon alert. don't overlap when that happens + if(boulders_found) + playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) + balloon_alert_to_viewers(action) /** * Ejects a boulder from the machine. Used when a boulder is finished processing, or when a boulder can't be processed. - * @param drop_turf The location to eject the boulder to. If null, it will eject to the machine's drop_location(). - * @param specific_boulder The boulder to be ejected. + * Arguments + * + * * obj/item/boulder/specific_boulder - the boulder to remove */ -/obj/machinery/bouldertech/proc/remove_boulder(obj/item/boulder/specific_boulder, turf/drop_turf = null) - if(isnull(specific_boulder)) - CRASH("remove_boulder() called with no boulder!") - if(!length(specific_boulder.custom_materials)) - qdel(specific_boulder) - update_boulder_count() - playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - return FALSE - specific_boulder.restart_processing_cooldown() //Reset the cooldown so we don't pick it back up by the same machine. - if(isturf(drop_turf)) - specific_boulder.forceMove(drop_turf) - else - specific_boulder.forceMove(drop_location()) - if(!update_boulder_count()) +/obj/machinery/bouldertech/proc/remove_boulder(obj/item/boulder/specific_boulder) + PRIVATE_PROC(TRUE) + + if(QDELETED(specific_boulder)) return TRUE - STOP_PROCESSING(SSmachines, src) - balloon_alert_to_viewers("clear!") + if(locate(/obj/item/boulder) in loc) //There is an boulder in our loc. it has be removed so we don't clog up our loc with even more boulders + return FALSE + + //Reset durability to little random lower value cause we have crushed it so many times + var/size = specific_boulder.boulder_size + if(size == BOULDER_SIZE_SMALL) + specific_boulder.durability = rand(2, BOULDER_SIZE_SMALL - 1) + else + specific_boulder.durability = rand(BOULDER_SIZE_SMALL, size - 1) + specific_boulder.processed_by = src //so we don't take in the boulder again after we just ejected it + specific_boulder.forceMove(drop_location()) + specific_boulder.processed_by = null //now since move is done we can safely clear the reference playsound(loc, 'sound/machines/ping.ogg', 50, FALSE) + return TRUE - -/** - * Getter proc to determine how many boulders are contained in the machine. - * Also adds their reference to the boulders_contained list. - */ -/obj/machinery/bouldertech/proc/update_boulder_count() - boulders_contained = list() - for(var/obj/item/boulder/boulder in contents) - boulders_contained += boulder - return boulders_contained.len - -/obj/machinery/bouldertech/proc/on_entered(datum/source, atom/movable/atom_movable) - SIGNAL_HANDLER - INVOKE_ASYNC(src, PROC_REF(accept_boulder), atom_movable) - -/** - * Looks for a boost to the machine's efficiency, and applies it if found. - * Applied more on the chemistry integration but can be used for other things if desired. - */ -/obj/machinery/bouldertech/proc/check_for_boosts() - refining_efficiency = initial(refining_efficiency) //Reset refining efficiency to 100%. - -/** - * Checks if a custom_material is in a list of processable materials in the machine. - * @param list/custom_material A list of materials, presumably taken from a boulder. If a material that this machine can process is in this list, it will return true, inclusively. - */ -/obj/machinery/bouldertech/proc/check_for_processable_materials(list/boulder_mats) - for(var/material as anything in boulder_mats) - if(is_type_in_list(material, processable_materials)) - return TRUE - return FALSE - -///Beacon to launch a new mining setup when activated. For testing and speed! -/obj/item/boulder_beacon - name = "boulder beacon" - desc = "N.T. approved boulder beacon, toss it down and you will have a full bouldertech mining station." - icon = 'icons/obj/machines/floor.dmi' - icon_state = "floor_beacon" - /// Number of activations left on this beacon. Uses will be removed as the beacon is used and each triggers a different machine to be spawned from it. - var/uses = 3 - -/obj/item/boulder_beacon/attack_self() - loc.visible_message(span_warning("\The [src] begins to beep loudly!")) - addtimer(CALLBACK(src, PROC_REF(launch_payload)), 1 SECONDS) - -/** - * Spawns a new bouldertech machine from the beacon, then removes a use from the beacon. - * Use one spawns a BRM teleporter, then a refinery, and lastly a smelter. - */ -/obj/item/boulder_beacon/proc/launch_payload() - playsound(src, SFX_SPARKS, 80, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - switch(uses) - if(3) - new /obj/machinery/bouldertech/brm(drop_location()) - if(2) - new /obj/machinery/bouldertech/refinery(drop_location()) - if(1) - new /obj/machinery/bouldertech/refinery/smelter(drop_location()) - qdel(src) - uses-- diff --git a/code/modules/mining/boulder_processing/beacon.dm b/code/modules/mining/boulder_processing/beacon.dm new file mode 100644 index 00000000000..576e05baf53 --- /dev/null +++ b/code/modules/mining/boulder_processing/beacon.dm @@ -0,0 +1,28 @@ +///Beacon to launch a new mining setup when activated. For testing and speed! +/obj/item/boulder_beacon + name = "boulder beacon" + desc = "N.T. approved boulder beacon, toss it down and you will have a full bouldertech mining station." + icon = 'icons/obj/machines/floor.dmi' + icon_state = "floor_beacon" + /// Number of activations left on this beacon. Uses will be removed as the beacon is used and each triggers a different machine to be spawned from it. + var/uses = 3 + +/obj/item/boulder_beacon/attack_self() + visible_message(span_warning("\The [src] begins to beep loudly!")) + addtimer(CALLBACK(src, PROC_REF(launch_payload)), 1 SECONDS) + +/** + * Spawns a new bouldertech machine from the beacon, then removes a use from the beacon. + * Use one spawns a BRM teleporter, then a refinery, and lastly a smelter. + */ +/obj/item/boulder_beacon/proc/launch_payload() + playsound(src, SFX_SPARKS, 80, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + switch(uses) + if(3) + new /obj/machinery/brm(drop_location()) + if(2) + new /obj/machinery/bouldertech/refinery(drop_location()) + if(1) + new /obj/machinery/bouldertech/refinery/smelter(drop_location()) + qdel(src) + uses-- diff --git a/code/modules/mining/boulder_processing/boulder.dm b/code/modules/mining/boulder_processing/boulder.dm index 77260eef088..699358c6adb 100644 --- a/code/modules/mining/boulder_processing/boulder.dm +++ b/code/modules/mining/boulder_processing/boulder.dm @@ -12,38 +12,15 @@ throw_range = 2 throw_speed = 0.5 drag_slowdown = 1.5 // It's still a big rock. + ///When a refinery machine is working on this boulder, we'll set this. Re reset when the process is finished, but the boulder may still be refined/operated on further. - var/obj/machinery/bouldertech/processed_by = null + var/obj/machinery/processed_by = null /// How many steps of refinement this boulder has gone through. Starts at 5-8, goes down one each machine process. var/durability = 5 /// What was the size of the boulder when it was spawned? This is used for inheiriting the icon_state. var/boulder_size = BOULDER_SIZE_SMALL /// Used in inheriting the icon_state from our parent vent in update_icon. var/boulder_string = "boulder" - /// Cooldown used to prevents boulders from getting processed back into a machine immediately after being processed. - COOLDOWN_DECLARE(processing_cooldown) - - /// Static list of all minerals to populate gulag boulders with. - var/list/static/gulag_minerals = list( - /datum/material/diamond = 1, - /datum/material/gold = 8, - /datum/material/iron = 95, - /datum/material/plasma = 30, - /datum/material/silver = 20, - /datum/material/titanium = 8, - /datum/material/uranium = 3, - ) - /// Static list of all minerals to populate gulag boulders with, but with bluespace added where safe. - var/list/static/expanded_gulag_minerals = list( - /datum/material/bluespace = 1, - /datum/material/diamond = 1, - /datum/material/gold = 8, - /datum/material/iron = 94, - /datum/material/plasma = 30, - /datum/material/silver = 20, - /datum/material/titanium = 8, - /datum/material/uranium = 3, - ) /obj/item/boulder/Initialize(mapload) . = ..() @@ -55,18 +32,37 @@ processed_by = null return ..() +/obj/item/boulder/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) + if(held_item?.tool_behaviour == TOOL_MINING || HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + context[SCREENTIP_CONTEXT_RMB] = "Crush boulder into ore" + return CONTEXTUAL_SCREENTIP_SET + /obj/item/boulder/examine(mob/user) . = ..() . += span_notice("This boulder would take [durability] more steps to refine or break.") + if(HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + . += span_notice("You can crush this boulder with your bare hands.") /obj/item/boulder/examine_more(mob/user) . = ..() . += span_notice("[span_bold("Boulders")] can either be cracked open by [span_bold("mining tools")], or processed into sheets with [span_bold("refineries or smelters")]. Undisturbed boulders can be collected by the [span_bold("BRM")].") -/obj/item/boulder/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) - if(held_item?.tool_behaviour == TOOL_MINING || HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) - context[SCREENTIP_CONTEXT_RMB] = "Crush boulder into ore" - return CONTEXTUAL_SCREENTIP_SET +/obj/item/boulder/update_icon_state() + . = ..() + switch(boulder_size) + if(BOULDER_SIZE_SMALL) + icon_state = "[boulder_string]_small" + if(BOULDER_SIZE_MEDIUM) + icon_state = "[boulder_string]_medium" + if(BOULDER_SIZE_LARGE) + icon_state = "[boulder_string]_large" + else + icon_state = "[boulder_string]_small" + +/obj/item/boulder/CanAllowThrough(atom/movable/mover, border_dir) + . = ..() + if(istype(mover, /obj/item/boulder)) //This way, boulders can only go one at a time on conveyor belts, but everyone else can go through. + return FALSE /obj/item/boulder/attack_self(mob/user, list/modifiers) . = ..() @@ -84,11 +80,6 @@ manual_process(null, user, INATE_BOULDER_SPEED_MULTIPLIER) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/item/boulder/CanAllowThrough(atom/movable/mover, border_dir) - . = ..() - if(istype(mover, /obj/item/boulder)) //This way, boulders can only go one at a time on conveyor belts, but everyone else can go through. - return FALSE - /obj/item/boulder/attackby_secondary(obj/item/weapon, mob/user, params) . = ..() if(HAS_TRAIT(user, TRAIT_BOULDER_BREAKER) || HAS_TRAIT(weapon, TRAIT_BOULDER_BREAKER)) @@ -107,18 +98,6 @@ manual_process(null, user, INATE_BOULDER_SPEED_MULTIPLIER) //A little hacky but it works around the speed of the blackboard task selection process for now. return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/item/boulder/update_icon_state() - . = ..() - switch(boulder_size) - if(BOULDER_SIZE_SMALL) - icon_state = "[boulder_string]_small" - if(BOULDER_SIZE_MEDIUM) - icon_state = "[boulder_string]_medium" - if(BOULDER_SIZE_LARGE) - icon_state = "[boulder_string]_large" - else - icon_state = "[boulder_string]_small" - /** * This is called when a boulder is processed by a mob or tool, and reduces the durability of the boulder. * @param obj/item/weapon The weapon that is being used to process the boulder, that we pull toolspeed from. If null, we use the override_speed_multiplier instead. @@ -185,104 +164,12 @@ cracked_ore = new cracked_ore_type (drop_location(), quantity) SSblackbox.record_feedback("tally", "ore_mined", quantity, cracked_ore) -/** - * Handles the boulder's processing cooldown to check if it's ready to be processed again. - */ -/obj/item/boulder/proc/can_get_processed() - return COOLDOWN_FINISHED(src, processing_cooldown) - -/** - * Starts the boulder's processing cooldown. - */ -/obj/item/boulder/proc/restart_processing_cooldown() - COOLDOWN_START(src, processing_cooldown, 2 SECONDS) - -/** - * Moves boulder contents to the drop location, and then deletes the boulder. - */ +///Moves boulder contents to the drop location, and then deletes the boulder. /obj/item/boulder/proc/break_apart() - var/list/quips = list("Clang!", "Crack!", "Bang!", "Clunk!", "Clank!") if(length(contents)) + var/list/quips = list("Clang!", "Crack!", "Bang!", "Clunk!", "Clank!") visible_message(span_notice("[pick(quips)] Something falls out of \the [src]!")) playsound(loc, 'sound/effects/picaxe1.ogg', 60, FALSE) for(var/obj/item/content as anything in contents) content.forceMove(get_turf(src)) qdel(src) - -/** - * This is called when a boulder is spawned from a vent, and is used to set the boulder's icon as well as durability. - * We also set our boulder_size variable, which is used for inheiriting the icon_state later on if processed. - * @param obj/structure/ore_vent/parent_vent The vent that spawned this boulder to generate consistent boulder icons. If null, we use the default size. - * @param size The size of the boulder to spawn. If parent_vent is defined, this is ignored. - * @param is_artifact Whether or not this boulder is an artifact boulder. If true, we use the artifact boulder icon state regardless of size. - */ -/obj/item/boulder/proc/flavor_boulder(obj/structure/ore_vent/parent_vent, size = BOULDER_SIZE_SMALL, is_artifact = FALSE) - var/durability_min = size - var/durability_max = size + BOULDER_SIZE_SMALL - if(parent_vent) - durability_min = parent_vent.boulder_size - durability_max = parent_vent.boulder_size + BOULDER_SIZE_SMALL - durability = rand(durability_min, durability_max) //randomize durability a bit for some flavor. - boulder_size = size - if(parent_vent) - boulder_size = parent_vent.boulder_size - boulder_string = parent_vent.boulder_icon_state - update_appearance(UPDATE_ICON_STATE) - -/** - * Unique proc for gulag-style boulders, which adds a random amount of minerals to the boulder. - */ -/obj/item/boulder/proc/add_gulag_minerals() - var/datum/material/new_material = pick_weight(gulag_minerals) - var/list/new_mats = list() - new_mats[new_material] = SHEET_MATERIAL_AMOUNT * rand(1,3) //We only want a few sheets of material in the gulag boulders - set_custom_materials(new_mats) - -/obj/item/boulder/artifact - name = "artifact boulder" - desc = "This boulder is brimming with strange energy. Cracking it open could contain something unusual for science." - icon_state = "boulder_artifact" - /// This is the type of item that will be inside the boulder. Default is a strange object. - var/artifact_type = /obj/item/relic - /// References to the relic inside the boulder, if any. - var/obj/item/artifact_inside - -/obj/item/boulder/artifact/Initialize(mapload) - . = ..() - artifact_inside = new artifact_type(src) /// This could be poggers for archaeology in the future. - -/obj/item/boulder/artifact/Destroy(force) - QDEL_NULL(artifact_inside) - return ..() - -/obj/item/boulder/artifact/convert_to_ore() - . = ..() - artifact_inside.forceMove(drop_location()) - artifact_inside = null - -/obj/item/boulder/artifact/break_apart() - artifact_inside = null - return ..() - - -/obj/item/boulder/gulag - name = "low-quality boulder" - desc = "This rocks. It's a low quality boulder, so it's probably not worth as much." - -/obj/item/boulder/gulag/Initialize(mapload) - . = ..() - add_gulag_minerals(gulag_minerals) - -/obj/item/boulder/gulag_expanded - name = "low-density boulder" - desc = "This rocks. It's not very well packed, and can't contain as many minerals." - -/obj/item/boulder/gulag_expanded/Initialize(mapload) - . = ..() - add_gulag_minerals(expanded_gulag_minerals) - -/obj/item/boulder/shabby - name = "shabby boulder" - desc = "A bizzare, twisted boulder. Wait, wait no, it's just a rock." - custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.1, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.1) - durability = 1 diff --git a/code/modules/mining/boulder_processing/boulder_types.dm b/code/modules/mining/boulder_processing/boulder_types.dm new file mode 100644 index 00000000000..08ed961404c --- /dev/null +++ b/code/modules/mining/boulder_processing/boulder_types.dm @@ -0,0 +1,76 @@ +///Boulders with special artificats that can give higher mining points +/obj/item/boulder/artifact + name = "artifact boulder" + desc = "This boulder is brimming with strange energy. Cracking it open could contain something unusual for science." + icon_state = "boulder_artifact" + /// This is the type of item that will be inside the boulder. Default is a strange object. + var/artifact_type = /obj/item/relic + /// References to the relic inside the boulder, if any. + var/obj/item/artifact_inside + +/obj/item/boulder/artifact/Initialize(mapload) + . = ..() + artifact_inside = new artifact_type(src) /// This could be poggers for archaeology in the future. + +/obj/item/boulder/artifact/Destroy(force) + QDEL_NULL(artifact_inside) + return ..() + +/obj/item/boulder/artifact/convert_to_ore() + . = ..() + artifact_inside.forceMove(drop_location()) + artifact_inside = null + +/obj/item/boulder/artifact/break_apart() + artifact_inside = null + return ..() + +///Boulders usually spawned in lavaland labour camp area +/obj/item/boulder/gulag + name = "low-quality boulder" + desc = "This rocks. It's a low quality boulder, so it's probably not worth as much." + +/obj/item/boulder/gulag/Initialize(mapload) + . = ..() + + /// Static list of all minerals to populate gulag boulders with. + var/list/static/gulag_minerals = list( + /datum/material/diamond = 1, + /datum/material/gold = 8, + /datum/material/iron = 95, + /datum/material/plasma = 30, + /datum/material/silver = 20, + /datum/material/titanium = 8, + /datum/material/uranium = 3, + ) + + set_custom_materials(list(pick_weight(gulag_minerals) = SHEET_MATERIAL_AMOUNT * rand(1, 3))) + +///Boulders usually spawned in lavaland labour camp area but with bluespace material +/obj/item/boulder/gulag_expanded + name = "low-density boulder" + desc = "This rocks. It's not very well packed, and can't contain as many minerals." + +/obj/item/boulder/gulag_expanded/Initialize(mapload) + . = ..() + + /// Static list of all minerals to populate gulag boulders with, but with bluespace added where safe. + var/list/static/expanded_gulag_minerals = list( + /datum/material/bluespace = 1, + /datum/material/diamond = 1, + /datum/material/gold = 8, + /datum/material/iron = 94, + /datum/material/plasma = 30, + /datum/material/silver = 20, + /datum/material/titanium = 8, + /datum/material/uranium = 3, + ) + + set_custom_materials(list(pick_weight(expanded_gulag_minerals) = SHEET_MATERIAL_AMOUNT * rand(1, 3))) + +///lowgrade boulder, most commonly spawned +/obj/item/boulder/shabby + name = "shabby boulder" + desc = "A bizzare, twisted boulder. Wait, wait no, it's just a rock." + custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.1, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.1) + durability = 1 diff --git a/code/modules/mining/boulder_processing/brm.dm b/code/modules/mining/boulder_processing/brm.dm index c76ec9dabbd..8c1205f5d4e 100644 --- a/code/modules/mining/boulder_processing/brm.dm +++ b/code/modules/mining/boulder_processing/brm.dm @@ -1,187 +1,319 @@ +///Sound played when boulders are teleported manually by hand #define MANUAL_TELEPORT_SOUND 'sound/machines/mining/manual_teleport.ogg' +///Sound played when boulders are teleported automatically in process() #define AUTO_TELEPORT_SOUND 'sound/machines/mining/auto_teleport.ogg' +///Time taken to spawn a boulder, also the cooldown applied before the next manual teleportation +#define TELEPORTATION_TIME (1.5 SECONDS) +///Cooldown for automatic teleportation after processing boulders_processing_max number of boulders +#define BATCH_COOLDOWN (3 SECONDS) +///Special case when we are trying to teleport a boulder but there is already another boulder in our loc +#define TURF_BLOCKED_BY_BOULDER -1 -/obj/machinery/bouldertech/brm +/obj/machinery/brm name = "boulder retrieval matrix" desc = "A teleportation matrix used to retrieve boulders excavated by mining NODEs from ore vents." + icon = 'icons/obj/machines/mining_machines.dmi' icon_state = "brm" + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.5 circuit = /obj/item/circuitboard/machine/brm - usage_sound = MANUAL_TELEPORT_SOUND processing_flags = START_PROCESSING_MANUALLY - boulders_held_max = 2 + anchored = TRUE + density = TRUE + + /// How many boulders can we process maximum per loop? + var/boulders_processing_max = 1 /// Are we trying to actively collect boulders automatically? var/toggled_on = FALSE - /// How long does it take to collect a boulder? - var/teleportation_time = 1.5 SECONDS + ///Have we finished processing a full batch of boulders + var/batch_processing = FALSE + /// Cooldown used for left click teleportation. COOLDOWN_DECLARE(manual_teleport_cooldown) + /// Cooldown used for automatic teleportation after processing boulders_processing_max number of boulders. + COOLDOWN_DECLARE(batch_start_cooldown) -/obj/machinery/bouldertech/brm/Initialize(mapload) +/obj/machinery/brm/Initialize(mapload) . = ..() - set_wires(new /datum/wires/brm(src)) + register_context() + +/obj/machinery/brm/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = CONTEXTUAL_SCREENTIP_SET + + if(isnull(held_item)) + context[SCREENTIP_CONTEXT_LMB] = "Teleport single boulder" + context[SCREENTIP_CONTEXT_RMB] = "Toggle [toggled_on ? "Off" : "On"] automatic boulder retrieval" + return + + if(!isnull(held_item)) + if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "" : "Un"] Anchor" + return + if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" + return + + if(panel_open) + if(held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/brm/examine(mob/user) + . = ..() + . += span_notice("The small screen reads there are [span_boldnotice("[SSore_generation.available_boulders.len] boulders")] available to teleport.") + . += span_notice("Can collect upto [boulders_processing_max] boulders at a time.") + . += span_notice("Automatic boulder retrival can be toggled [EXAMINE_HINT("[toggled_on ? "Off" : "On"]")] with [EXAMINE_HINT("Right Click")].") + + if(anchored) + . += span_notice("Its [EXAMINE_HINT("anchored")] in place.") + else + . += span_warning("It needs to be [EXAMINE_HINT("anchored")] to start operations.") + + . += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "Closed" : "Open"].") + + if(panel_open) + . += span_notice("The whole machine can be [EXAMINE_HINT("pried")] apart.") + +/obj/machinery/brm/update_icon_state() + icon_state = initial(icon_state) + + if(!anchored || !is_operational || machine_stat & (BROKEN | NOPOWER) || panel_open) + icon_state = "[icon_state]-off" + return + + if(toggled_on) + icon_state = "[icon_state]-toggled" + return -/obj/machinery/bouldertech/brm/Destroy() - QDEL_NULL(wires) return ..() -/obj/machinery/bouldertech/brm/attack_hand(mob/living/user, list/modifiers) - . = ..() - if(!handle_teleport_conditions(user)) - return - pre_collect_boulder() +/obj/machinery/brm/wrench_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_unfasten_wrench(user, tool, time = 1.5 SECONDS) == SUCCESSFUL_UNFASTEN) + update_appearance(UPDATE_ICON_STATE) + return ITEM_INTERACT_SUCCESS - COOLDOWN_START(src, manual_teleport_cooldown, teleportation_time) +/obj/machinery/brm/screwdriver_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-off", initial(icon_state), tool)) + update_appearance(UPDATE_ICON_STATE) + return ITEM_INTERACT_SUCCESS -/obj/machinery/bouldertech/brm/attack_robot(mob/user) - if(!handle_teleport_conditions(user)) - return - pre_collect_boulder() +/obj/machinery/brm/crowbar_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_crowbar(tool)) + return ITEM_INTERACT_SUCCESS - COOLDOWN_START(src, manual_teleport_cooldown, teleportation_time) - -/obj/machinery/bouldertech/brm/attackby(obj/item/attacking_item, mob/user, params) - if(is_wire_tool(attacking_item) && panel_open) - wires.interact(user) +///To allow boulders on a conveyer belt to move unobstructed if multiple machines are made on a single line +/obj/machinery/brm/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(istype(mover, /obj/item/boulder)) return TRUE return ..() -/obj/machinery/bouldertech/brm/attack_hand_secondary(mob/user, list/modifiers) +/obj/machinery/brm/RefreshParts() . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + + boulders_processing_max = 0 + for(var/datum/stock_part/part in component_parts) + boulders_processing_max += part.tier + + boulders_processing_max = ROUND_UP((boulders_processing_max / 12) * 7) + +/obj/machinery/brm/attack_hand(mob/living/user, list/modifiers) + . = ..() + if(. || panel_open) return - if(!anchored) - balloon_alert(user, "anchor first!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - toggle_auto_on(user) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - -/obj/machinery/bouldertech/brm/attack_robot_secondary(mob/user, list/modifiers) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + if(!handle_teleport_conditions(user)) return - if(!anchored) - balloon_alert(user, "anchor first!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - toggle_auto_on(user) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/machinery/bouldertech/brm/process() - if(SSore_generation.available_boulders.len < 1) - say("No boulders to collect. Entering idle mode.") - toggled_on = FALSE - update_appearance(UPDATE_ICON_STATE) - return PROCESS_KILL - for(var/i in 1 to boulders_processing_max) - if(pre_collect_boulder()) - continue - toggled_on = FALSE - update_appearance(UPDATE_ICON_STATE) - return PROCESS_KILL - for(var/obj/item/boulder/ground_rocks in loc.contents) - boulders_contained += ground_rocks - if(boulders_contained.len < boulders_held_max) - continue - toggled_on = FALSE - boulders_contained.Cut() - update_appearance(UPDATE_ICON_STATE) - return PROCESS_KILL + var/result = pre_collect_boulder() + if(result == TURF_BLOCKED_BY_BOULDER) + balloon_alert(user, "no space") + else if(result) + balloon_alert(user, "teleporting") + COOLDOWN_START(src, manual_teleport_cooldown, TELEPORTATION_TIME) -/obj/machinery/bouldertech/brm/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() - context[SCREENTIP_CONTEXT_LMB] = "Teleport single boulder" - context[SCREENTIP_CONTEXT_RMB] = "Toggle automatic boulder retrieval" - return CONTEXTUAL_SCREENTIP_SET - -/obj/machinery/bouldertech/brm/examine(mob/user) - . = ..() - . += span_notice("The small screen reads there are [span_boldnotice("[SSore_generation.available_boulders.len] boulders")] available to teleport.") - -/obj/machinery/bouldertech/brm/RefreshParts() - . = ..() - var/scanner_stack = 0 - var/laser_stack = 0 - for(var/datum/stock_part/scanning_module/scanner in component_parts) - scanner_stack += scanner.tier - boulders_processing_max = scanner_stack - for(var/datum/stock_part/micro_laser/laser in component_parts) - laser_stack += laser.tier - boulders_held_max = laser_stack + 1 - -/obj/machinery/bouldertech/brm/update_icon_state() - if(toggled_on && !panel_open) - icon_state = "[initial(icon_state)]-toggled" - return - return ..() + return TRUE /** * Handles qualifiers for enabling teleportation of boulders. * Returns TRUE if the teleportation can proceed, FALSE otherwise. + * Arguments + * + * * mob/user - the mob to inform if conditions aren't met */ -/obj/machinery/bouldertech/brm/proc/handle_teleport_conditions(mob/user) +/obj/machinery/brm/proc/handle_teleport_conditions(mob/user) + PRIVATE_PROC(TRUE) + if(!COOLDOWN_FINISHED(src, manual_teleport_cooldown)) return FALSE if(panel_open) balloon_alert(user, "close panel first!") return FALSE + if(batch_processing) + balloon_alert(user, "batch still processing!") + return FALSE playsound(src, MANUAL_TELEPORT_SOUND, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) return TRUE -/** - * Begins to collect a boulder from the available boulders list in SSore_generation. - * Boulders must not be processed by another BRM or machine, and must be in the available boulders list. - * A selected boulder is picked randomly. - * The actual movement is then handled by collect_boulder() after a timed callback. - */ -/obj/machinery/bouldertech/brm/proc/pre_collect_boulder() - if(!SSore_generation.available_boulders.len) - playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE) - balloon_alert_to_viewers("no boulders to collect!") - return FALSE //Nothing to collect - var/obj/item/boulder/random_boulder = pick(SSore_generation.available_boulders) - if(random_boulder.processed_by) - return FALSE +/obj/machinery/brm/attack_robot(mob/user) + . = ..() + if(. || panel_open) + return + if(!handle_teleport_conditions(user)) + return + + var/result = pre_collect_boulder() + if(result == TURF_BLOCKED_BY_BOULDER) + balloon_alert(user, "no space") + else if(result) + balloon_alert(user, "teleporting") + + COOLDOWN_START(src, manual_teleport_cooldown, TELEPORTATION_TIME) - random_boulder.processed_by = src - random_boulder.Shake(duration = 1.5 SECONDS) - SSore_generation.available_boulders -= random_boulder - addtimer(CALLBACK(src, PROC_REF(collect_boulder), random_boulder), 1.5 SECONDS) return TRUE -/** - * Collects a boulder from the available boulders list in SSore_generation. - * Handles the movement of the boulder as well as visual effects on the BRM. - * @param obj/item/boulder/random_boulder The boulder to collect. - */ -/obj/machinery/bouldertech/brm/proc/collect_boulder(obj/item/boulder/random_boulder) - flick("brm-flash", src) - if(QDELETED(random_boulder)) - playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE) - balloon_alert_to_viewers("target lost!") - return FALSE - playsound(src, AUTO_TELEPORT_SOUND, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - random_boulder.forceMove(drop_location()) - random_boulder.processed_by = null - random_boulder.pixel_x = rand(-2, 2) - random_boulder.pixel_y = rand(-2, 2) - balloon_alert_to_viewers("boulder appears!") - random_boulder.visible_message(span_warning("[random_boulder] suddenly appears!")) - use_power(BASE_MACHINE_ACTIVE_CONSUMPTION * 0.1) - return TRUE +/obj/machinery/brm/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || panel_open) + return + if(!anchored) + balloon_alert(user, "anchor first!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + toggle_auto_on(user) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN /** * Toggles automatic boulder retrieval on. * Adjusts the teleportation sound, icon state, and begins processing. * @param mob/user The user who toggled the BRM. */ -/obj/machinery/bouldertech/brm/proc/toggle_auto_on(mob/user) +/obj/machinery/brm/proc/toggle_auto_on(mob/user) + PRIVATE_PROC(TRUE) + if(panel_open) - if(user) - balloon_alert(user, "close panel first!") + balloon_alert(user, "close panel first!") return - toggled_on = TRUE - START_PROCESSING(SSmachines, src) + if(!anchored) + balloon_alert(user, "anchor first!") + return + if(!is_operational || machine_stat & (BROKEN | NOPOWER)) + return + + toggled_on = ! toggled_on + if(toggled_on) + begin_processing() + else + end_processing() update_appearance(UPDATE_ICON_STATE) - usage_sound = AUTO_TELEPORT_SOUND + +/obj/machinery/brm/attack_robot_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || panel_open) + return + if(!anchored) + balloon_alert(user, "anchor first!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + toggle_auto_on(user) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/machinery/brm/process() + if(!toggled_on) + return PROCESS_KILL + + //have some cooldown after processing the previous batch of boulders + if(!COOLDOWN_FINISHED(src, batch_start_cooldown)) + return + + pre_collect_boulder(FALSE, boulders_processing_max) + +/** + * Begins to collect a boulder from the available boulders list in SSore_generation. + * Boulders must be in the available boulders list. + * A selected boulder is picked randomly. + * The actual movement is then handled by collect_boulder() after a timed callback. + * Arguments + * + * * feedback - should we play sound and display allert if now boulders are available + * * boulders_remaining - how many boulders we want to try & collect spawning a boulder every TELEPORTATION_TIME seconds + * * new_batch - is this the very 1st boulder processed from boulders_remaining. Used to wait for all the boulders to be collected + */ +/obj/machinery/brm/proc/pre_collect_boulder(feedback = TRUE, boulders_remaining = 1, new_batch = TRUE) + PRIVATE_PROC(TRUE) + + if(!anchored || panel_open || !is_operational || machine_stat & (BROKEN | NOPOWER)) + return FALSE + + //There is an boulder in our loc. it has be removed so we don't clog up our loc with even more boulders + if(locate(/obj/item/boulder) in loc) + batch_processing = FALSE + return TURF_BLOCKED_BY_BOULDER + + //no more boulders + if(!SSore_generation.available_boulders.len) + if(feedback) + playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE) + balloon_alert_to_viewers("no boulders to collect!") + batch_processing = FALSE + return FALSE + + //we are trying to process a new batch of boulders + if(new_batch) + if(batch_processing) //the previous one hasen't completed yet, wait + return FALSE + batch_processing = TRUE + + var/obj/item/boulder/random_boulder = pick(SSore_generation.available_boulders) + if(random_boulder.processed_by) + return FALSE + SSore_generation.available_boulders -= random_boulder + random_boulder.processed_by = src + random_boulder.Shake(shake_interval = TELEPORTATION_TIME) + addtimer(CALLBACK(src, PROC_REF(collect_boulder), random_boulder, feedback, boulders_remaining), TELEPORTATION_TIME) + return TRUE + +/** + * Callback to spawn a boulder collected in pre_collect_boulder(). Can be used to collect + * multiple boulders by setting boulders_remaining but must only be called by pre_collect_boulder() + * and not directly + * Arguments + * + * * obj/item/boulder/random_boulder - the boulder we are trying to move out + * * feedback - see pre_collect_boulder() + * * boulders_remaining - passed back to pre_collect_boulder() if count > 0 + */ +/obj/machinery/brm/proc/collect_boulder(obj/item/boulder/random_boulder, feedback, boulders_remaining) + if(QDELETED(random_boulder)) + playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE) + balloon_alert_to_viewers("target lost!") + return FALSE + + if(locate(/obj/item/boulder) in loc) + batch_processing = FALSE + return + + flick("brm-flash", src) + playsound(src, toggled_on ? AUTO_TELEPORT_SOUND : MANUAL_TELEPORT_SOUND, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + random_boulder.forceMove(drop_location()) + random_boulder.pixel_x = rand(-2, 2) + random_boulder.pixel_y = rand(-2, 2) + random_boulder.processed_by = null + balloon_alert_to_viewers("boulder appears!") + use_power(active_power_usage) + + boulders_remaining -= 1 + if(boulders_remaining <= 0) + COOLDOWN_START(src, batch_start_cooldown, BATCH_COOLDOWN) + batch_processing = FALSE + return TRUE + else + return pre_collect_boulder(feedback, boulders_remaining, FALSE) #undef MANUAL_TELEPORT_SOUND #undef AUTO_TELEPORT_SOUND +#undef TELEPORTATION_TIME +#undef BATCH_COOLDOWN +#undef TURF_BLOCKED_BY_BOULDER diff --git a/code/modules/mining/boulder_processing/refinery.dm b/code/modules/mining/boulder_processing/refinery.dm index 764816ec6d3..662bb3e75e1 100644 --- a/code/modules/mining/boulder_processing/refinery.dm +++ b/code/modules/mining/boulder_processing/refinery.dm @@ -7,44 +7,34 @@ name = "boulder refinery" desc = "BR for short. Accepts boulders and refines non-metallic ores into sheets using internal chemicals." icon_state = "stacker" - holds_minerals = TRUE - processable_materials = list( - /datum/material/glass, - /datum/material/plasma, - /datum/material/diamond, - /datum/material/bluespace, - /datum/material/bananium, - /datum/material/plastic, - ) circuit = /obj/item/circuitboard/machine/refinery usage_sound = 'sound/machines/mining/refinery.ogg' - holds_mining_points = TRUE + action = "crushing" -/// okay so var that holds mining points to claim -/// add total of pts from minerals mined in parent proc -/// then, little mini UI showing points to collect? +/obj/machinery/bouldertech/refinery/can_process_material(datum/material/possible_mat) + var/static/list/processable_materials + if(!length(processable_materials)) + processable_materials = list( + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + return is_type_in_list(possible_mat, processable_materials) /obj/machinery/bouldertech/refinery/RefreshParts() . = ..() - var/manipulator_stack = 0 - var/matter_bin_stack = 0 - for(var/datum/stock_part/servo/servo in component_parts) - manipulator_stack += servo.tier - 1 - boulders_processing_max = clamp(manipulator_stack, 1, 6) + + boulders_held_max = 0 for(var/datum/stock_part/matter_bin/bin in component_parts) - matter_bin_stack += bin.tier - boulders_held_max = matter_bin_stack - - -/obj/machinery/bouldertech/refinery/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() - if(istype(held_item, /obj/item/boulder)) - context[SCREENTIP_CONTEXT_LMB] = "Insert boulder" - if(istype(held_item, /obj/item/card/id) && points_held > 0) - context[SCREENTIP_CONTEXT_LMB] = "Claim mining points" - context[SCREENTIP_CONTEXT_RMB] = "Remove boulder" - return CONTEXTUAL_SCREENTIP_SET + boulders_held_max += bin.tier + boulders_processing_count = 0 + for(var/datum/stock_part/servo/servo in component_parts) + boulders_processing_count += servo.tier + boulders_processing_count = ROUND_UP((boulders_processing_count / 8) * boulders_held_max) /** * Your other new favorite industrial waste magnet! @@ -55,36 +45,43 @@ name = "boulder smelter" desc = "BS for short. Accept boulders and refines metallic ores into sheets." icon_state = "smelter" - processable_materials = list( - /datum/material/iron, - /datum/material/titanium, - /datum/material/silver, - /datum/material/gold, - /datum/material/uranium, - /datum/material/mythril, - /datum/material/adamantine, - /datum/material/runite, - ) light_system = OVERLAY_LIGHT - light_range = 1 - light_power = 2 + light_range = 2 + light_power = 3 light_color = "#ffaf55" - light_on = FALSE circuit = /obj/item/circuitboard/machine/smelter usage_sound = 'sound/machines/mining/smelter.ogg' + action = "smelting" -/obj/machinery/bouldertech/refinery/smelter/RefreshParts() +/obj/machinery/bouldertech/refinery/smelter/Initialize(mapload) . = ..() - light_power = boulders_processing_max + set_light_on(TRUE) -/obj/machinery/bouldertech/refinery/smelter/accept_boulder(obj/item/boulder/new_boulder) +/obj/machinery/bouldertech/refinery/smelter/can_process_material(datum/material/possible_mat) + var/static/list/processable_materials + if(!length(processable_materials)) + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + ) + return is_type_in_list(possible_mat, processable_materials) + +/obj/machinery/bouldertech/refinery/smelter/set_light_on(new_value) + if(panel_open || !anchored || !is_operational || machine_stat & (BROKEN | NOPOWER)) + new_value = FALSE + return ..() + +/obj/machinery/bouldertech/refinery/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) . = ..() - if(.) - set_light_on(TRUE) - return TRUE + set_light_on(TRUE) -/obj/machinery/bouldertech/refinery/smelter/process() +/obj/machinery/bouldertech/refinery/default_unfasten_wrench(mob/user, obj/item/wrench, time) . = ..() - if(. == PROCESS_KILL) - set_light_on(FALSE) + set_light_on(TRUE) + +/obj/machinery/bouldertech/refinery/smelter/on_set_is_operational(old_value) + set_light_on(TRUE) diff --git a/icons/obj/machines/mining_machines.dmi b/icons/obj/machines/mining_machines.dmi index 91f7f434ad3..c1a4076e3a2 100644 Binary files a/icons/obj/machines/mining_machines.dmi and b/icons/obj/machines/mining_machines.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 5930f2bd0ec..44599fa69d9 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1834,7 +1834,6 @@ #include "code\datums\wires\airlock.dm" #include "code\datums\wires\apc.dm" #include "code\datums\wires\autolathe.dm" -#include "code\datums\wires\brm.dm" #include "code\datums\wires\conveyor.dm" #include "code\datums\wires\ecto_sniffer.dm" #include "code\datums\wires\emitter.dm" @@ -4442,7 +4441,9 @@ #include "code\modules\mining\shelters.dm" #include "code\modules\mining\voucher_sets.dm" #include "code\modules\mining\boulder_processing\_boulder_processing.dm" +#include "code\modules\mining\boulder_processing\beacon.dm" #include "code\modules\mining\boulder_processing\boulder.dm" +#include "code\modules\mining\boulder_processing\boulder_types.dm" #include "code\modules\mining\boulder_processing\brm.dm" #include "code\modules\mining\boulder_processing\refinery.dm" #include "code\modules\mining\equipment\explorer_gear.dm" diff --git a/tools/UpdatePaths/Scripts/81358_brm.txt b/tools/UpdatePaths/Scripts/81358_brm.txt new file mode 100644 index 00000000000..c0970d41fa2 --- /dev/null +++ b/tools/UpdatePaths/Scripts/81358_brm.txt @@ -0,0 +1 @@ +/obj/machinery/bouldertech/brm : /obj/machinery/brm{@OLD} \ No newline at end of file