Skip to content

Commit

Permalink
General maintenance for all things boulder related. (tgstation#81358)
Browse files Browse the repository at this point in the history
## About The Pull Request
**1. Qol**
- Adds screen tips & examines for screwdriver & crowbar acts on BRM,
Refinery & Smelter
- Adds examines to display number of boulders stored inside a refinery &
maximum number of boulders it can hold. Right click screentip to remove
boulders
- Adds examines to display maximum number of boulders than can be
teleported by a BRM & screentips for interacting with wires
- More audio & visual feedback for refinery processing. If a boulder
requires multiple steps you will get a balloon alert saying "crushing"
for refineries & "smelting" for smelters along with a sound per process
tick(which is every 2 seconds so no need for cooldown) giving you a
better idea of what's happening in the pipeline
- BRM now will display all lights when the "Automatic boulder retrieval"
is on & turn off the lights when disabled along with examines giving you
a visual indicator of its state

**2. Code Improvements**
- Splits types of boulders into its own file `boulder_types.dm` for easy
maintainability
- Moves beacon for refinery machines into its own file
`boulder_processing/beacon.dm` for easy maintainability
- Moves the cooldown for processing a boulder `processing_cooldown` into
the refinery machine itself. Since 100's of boulders can be created per
round this var can take up memory quickly so by moving them into the
refinery machine it gives us some savings
- Compressed & merged procs such as `create_mineral_contents()` ,
`flavour_boulder()` etc with the vent code. These procs were only used
by the vent 1 time & by merging the code we removed if conditions to
check if a parent vent was passed or not(since now that's always the
case). Helped in removing boilder plate code

**3. Fixes**
- **Fixes vents always spawning "Small size boulders" & not medium, nor
large boulders.**
 Once a vent generates a boulder it calls  `flavour_boulder()`

https://github.com/tgstation/tgstation/blob/084f56938c0169aeeee0b5f41453f31d072f3f67/code/game/objects/structures/lavaland/ore_vent.dm#L385
however this proc also accepts 2 more params `size` which would always
default to `BOULDER_SIZE_SMALL` and `is_artifact` which is simply unused
in the proc

https://github.com/tgstation/tgstation/blob/fb83617ff94d6294b0d48c8c6c57488237508d11/code/modules/mining/boulder_processing/boulder.dm#L219
Therefore vents would always generate small boulders giving us no
varity. Now the boulder size is set depending on the vent size &
durability for each boulder is set to a random value between 2 & the
boulder max size giving us the flavour we actually wanted

- **Fixes "Expanded Gulag boulders" using "normal gulag material list"
when setting its custom materials.**
If you look at the `add_gulag_minerals()` proc it always picks from the
`gulag_minerals` list & accepts no params

https://github.com/tgstation/tgstation/blob/fb83617ff94d6294b0d48c8c6c57488237508d11/code/modules/mining/boulder_processing/boulder.dm#L235-L236
So when we try to pass params to this proc which in reality doesn't
accept any we were wasting our time doing this

https://github.com/tgstation/tgstation/blob/fb83617ff94d6294b0d48c8c6c57488237508d11/code/modules/mining/boulder_processing/boulder.dm#L274
And for our case `expanded_gulag_minerals` list was simply unused
because our proc doesn't care about it and it went back to just using
`gulag_minerals` list thus ignoring our list

https://github.com/tgstation/tgstation/blob/fb83617ff94d6294b0d48c8c6c57488237508d11/code/modules/mining/boulder_processing/boulder.dm#L282
As i said in the "Code Improvement` section when i moved boulder types
into it's own unique file this was fixed & now expanded gulag boulders
actually has a chance to spawn with bluespace crystals inside them

- **Fixes manual tapping of ore vents by hand not using a cooldown**
`produce_boulder()` accepts a cooldown var for when you need to manually
tap the vent by hand.

https://github.com/tgstation/tgstation/blob/e8b5b52d54a60b651d72e610cfb35a237aef6efe/code/game/objects/structures/lavaland/ore_vent.dm#L374
This var was always set to FALSE because we never passed `TRUE` into it.
Not once here

https://github.com/tgstation/tgstation/blob/e8b5b52d54a60b651d72e610cfb35a237aef6efe/code/game/objects/structures/lavaland/ore_vent.dm#L124
Nor here

https://github.com/tgstation/tgstation/blob/e8b5b52d54a60b651d72e610cfb35a237aef6efe/code/game/objects/structures/lavaland/ore_vent.dm#L131
Now we just pass `TRUE` so tapping these vents by hand have a cooldown

- **Fixes BRM off icon state never being used**
When the room ran out of power it would still look on. Now we use that
state correctly

- **Fixes Automatic Boulder Retrieval by the BRM not actually being
automatic**
You must have noticed that once you do "Right click" and wait for all
the boulders it can teleport (determined by `boulder_processing_max`) to
be teleported it stops permanently after that. Even if more boulders get
generated it won't do anything, You have to again "Right click" &
retoggle automatic boulder retrieval on again, thus forcing someone to
stand there & monitor the BRM

Now once you set Automatic Boulder Retrieval on you can leave & forget.
It will teleport boulders as & when available thus enabling automation
properly.

- **Fixes boulders ejected from refineries via right click from getting
teleported back into the machines loc**
Fixes
tgstation#78524 (comment).
The problem is refinery machines & the BRM keep track of all the
boulders that entered into it via the `boulders_contained` list.

Now we directly check `contents` for boulders so we don't have to
maintain 2 seperate lists to keep track of boulders. It also now uses
`processed_by` var of boulders to ensure refinerries don't retake in the
same boulder it just processed. Not sure where exactly the problem got
fixed but implementing these 2 measures fixed it regardless.

- **Fixes boulders with 0 durability[a.k.a steps] from getting ejected
out**
Fixes
tgstation#78524 (comment).
So inside `process()` we constantly decrease the durability of the
boulder till it becomes 0.

https://github.com/tgstation/tgstation/blob/0a496f180c627b9de26d3982d775cbf323fbc459/code/modules/mining/boulder_processing/_boulder_processing.dm#L159

  When it reaches 0 it calls `breakdown_boulder()`

https://github.com/tgstation/tgstation/blob/0a496f180c627b9de26d3982d775cbf323fbc459/code/modules/mining/boulder_processing/_boulder_processing.dm#L164-L165

This proc has a chance to reject the boulder if it could not process any
materials

https://github.com/tgstation/tgstation/blob/0a496f180c627b9de26d3982d775cbf323fbc459/code/modules/mining/boulder_processing/_boulder_processing.dm#L219-L222
  
  **"Without resetting its durability"** over here

https://github.com/tgstation/tgstation/blob/0a496f180c627b9de26d3982d775cbf323fbc459/code/modules/mining/boulder_processing/_boulder_processing.dm#L241

So it ends up rejecting a "0" or worse -1 durability boulder. Now we set
the durability in `remove_boulder()` so regardless of what circumstances
the boulder is ejected it always gets a positive durability

- **Fixes BRM & Refinery from rapidly spitting out boulders in their loc
which causes lag in the long terms**
Fixes tgstation#81404. Basically even if there is 1 boulder sitting at a BRM's
loc or an refineries loc. Operations are haulted i.e. the BRM will not
teleport any more boulders & the refinery will keep their already
processed boulders inside till their locs are cleared from boulders.
This prevents large number of boulders from pilling up in long rounds

- **[Priority : High] Fixes refineries incorrectly removing materials
from processed boulders**
Fixes tgstation#81109. This bug is quite serious because it can't literarily
affect any random item with custom materials in game. This one line of
code over here can break the entire material economy as we know it

https://github.com/tgstation/tgstation/blob/0a496f180c627b9de26d3982d775cbf323fbc459/code/modules/mining/boulder_processing/_boulder_processing.dm#L217
  
**"DONT DO THIS"**. The `custom_materials` list is a **"read only"**
list & if you ever want to change it call the `set_custom_materials()`
proc with your new values but do not edit this list manually as it is
done here.
  
All lists related to materials are cached by the `SSmaterials`
subsystem. List values are cached & shared across multiple objects so
when you edit those values like here, you might end up effecting an
item/multiple items in some random corner of the map that shares this
list.

This also causes boulders with empty list of materials to get spawned at
random so yeah again plzz don't do this

**4. Refactors**
- Repathes `obj/machinery/boulder_processing/brm` -> just
`obj/machinery/brm`.
Even though semantically it looks nice that the brm is a subtype of
`obj/machinery/boulder_processing` from a code & operation perspective
they have 0 similarities.

1) The BRM does not accept boulders feed into it from a conveyer belt
unlike a refinery but instead picks boulders from `SSore` subsystem &
put it on the conveyer belt. This means procs for accepting boulders
such `CanAllowThrough()`, `breakdown_boulder()`, `accept_boulder()` etc
have no use in the BRM. Their just code clutter at this point
2) The BRM overrides `process()` & does not call its parent proc making
that code wasted
3) It has no use for silo materials & mining points making those vars go
to waste

With so much wasted code its better to just let go off all of it & just
make it a basic instance of `obj/machinery` making maintainence easy

- BRM now teleports boulders in a batch (batch size determined by
`boulders_processing_max` max value from upgraded parts is 7) with a
boulder appearing every 1.5 seconds rather than spawning all at once.
After a batch is processed it has a cooldown of 3 seconds before
repeating the process if automatic boulder retrieval is on. This stops
the conveyer belt from getting crowded with boulders and makes the
refining process more efficient.

With this BRM wires are removed because only it had only 1 wire
responsible for toggling boulder retrieval but now since this process is
automatic, we have true control over the timing of boulders spawned &
don't want to leave it in the hands of players

## Changelog
:cl:
qol: adds examines & screentips for crowbar, screwdriver acts to BRM &
refinery machines
qol: adds examines about the number of boulders stored & processed to
BRM & refinery machines
qol: BRM now has its lights turn on/off depending on wether automatic
boulder retrieval is on/off for visual clarity along with examines
qol: refinery machines now display ballon alerts & plays sounds more
frequently when processing boulders for better feedback
fix: vents now spawn boulders of all sizes & not just small ones
fix: expanded gulag boulders now have correct materials in them.
fix: manual tapping of vents now has a cooldown applied as intended.
fix: BRM has its light turned off when area power goes off
fix: boulders ejected from refineries by hand no longer teleport all
over the place occasionally.
fix: refineries no longer eject boulders with 0 durability
fix: Boulders & refineries no longer pile up on top of BRM's &
refineries in long rounds. Their locs have to be clear of boulders
before they spit out more boulders to prevent a large pile of boulders
from causing lag
fix: sheets ejected from lathes no longer get rejected when inserted
back which could happen at random, no more boulders with empty materials
code: splits boulder types into its own file along with other items
code: merges & autodocs procs, vars related to boulders
refactor: repaths BRM to a simpler subtype
refactor: BRM now spawns boulders in batches(batch size can be increased
with upgraded parts) with a boulder appearing every second. After a
batch is processed a 3 second cooldown is applied to stop the conveyer
belt from clogging up, With this BRM wires are removed as there is no
need for timers to be attached to wires which intefers without our batch
processing timings.
/:cl:

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
  • Loading branch information
2 people authored and larentoun committed Mar 1, 2024
1 parent 2a460a1 commit 7db6103
Show file tree
Hide file tree
Showing 18 changed files with 726 additions and 612 deletions.
2 changes: 1 addition & 1 deletion _maps/map_files/Birdshot/birdshot.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -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" = (
Expand Down
2 changes: 1 addition & 1 deletion _maps/map_files/IceBoxStation/IceBoxStation.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -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" = (
Expand Down
2 changes: 1 addition & 1 deletion _maps/map_files/MetaStation/MetaStation.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -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" = (
Expand Down
2 changes: 1 addition & 1 deletion _maps/map_files/NorthStar/north_star.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion _maps/map_files/tramstation/tramstation.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
15 changes: 7 additions & 8 deletions code/controllers/subsystem/ore_generation.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ 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.
* Each key value is the number of vents that will have this ore as a unique possible choice.
* 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,
Expand Down Expand Up @@ -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
Expand All @@ -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()
14 changes: 0 additions & 14 deletions code/datums/wires/brm.dm

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
63 changes: 29 additions & 34 deletions code/game/objects/structures/lavaland/ore_vent.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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.
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
. = ..()
Expand All @@ -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.
Expand Down Expand Up @@ -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"
Expand All @@ -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)
. = ..()
Expand Down Expand Up @@ -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
Expand All @@ -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."
Expand Down Expand Up @@ -536,3 +530,4 @@
#undef MINERAL_TYPE_OPTIONS_RANDOM
#undef OVERLAY_OFFSET_START
#undef OVERLAY_OFFSET_EACH
#undef MINERALS_PER_BOULDER

0 comments on commit 7db6103

Please sign in to comment.