Skip to content

Commit

Permalink
[MIRROR] Fixes ore vents spawning without ores on icebox, sets up map…
Browse files Browse the repository at this point in the history
… specific ore configurations (#805)

* Fixes ore vents spawning without ores on icebox, sets up map specific ore configurations (#81103)

## About The Pull Request

In short, we used a static list previously within the ore_generation
subsystem that held the amount of each ore that we expected a single map
to uniformly need. We held this number constant, since we were spawning
15 vents per map.

**Pros:** This worked flawlessly for Lavaland since 15 vents on a single
Z level makes it pretty densely packed map with a good amount of
map-based ore spawns, and it worked consistently.

**Cons:** 15 vents did not work well on Icebox however, even when split
so that the majority of the ores were spawning on the lower levels,
players did not feel like icebox spawned nearly enough ores and reported
the map spawning empty.

**Result:** As a result, we adjusted the ratio, so that we spawned
vastly more ores on the lower levels, now up to 4 vents on the upper
level, and 21 vents on the lower level. However, as we were still using
the ore distribution list based on lavaland, icebox vents were quickly
running out of ores to distribute between them, resulting in empty vents
-> which produced empty boulders -> which not only don't really let you
process them properly, but also just result in a metric ton of runtimes.

Icebox now has it's own list of ore distributions. These distributions
are now moved to a set of global lists as opposed to being saved on the
subsystem as a static list, which will make going and setting up new ore
distribution lists very very easy. Additionally, we've moved the setting
and getting of those ore_distributions over to the seedRuins proc, so
that we're actually setting the list of ores right before we actually
place them to make sure that the order that it's set is roughly as it's
needed, while still setting the list at the same time the
map-appropriate ruin placements are dropped in.

**Plus some misc cleanup fixes:**
`var/list/ore_vent_sizes` in SSore_generation wasn't being treated as a
similar budget list as `ore_vent_minerals`, since it `pick()`s off it's
own static size list. Which is honestly fine for this five seconds, I
can handle that later while we make sure the rest of the code code is
stable. In the meantime, I've just tweak it so that it's easy to see at
a glance how many of each random vent has spawned into the map.

Tweaked the description to not include anything about chemical
processing, as I'm planning on hitting on that in a part 2 PR that I'll
be picking back up after the freeze.

## Why It's Good For The Game

Cleans up the code a bit, but primarily fixes ores not spawning on
icebox as they should.
Should fix #81058.
Improves description to not mention mechanics that aren't in game.
Also, cleans up a piece of code that currently isn't serving much of a
purpose.

## Changelog

:cl:
fix: Icebox should have it's ore distribution and it's ore vents fixed,
so that vents should now produce ore.
spellcheck: Boulder processing machines now don't mention things they
don't do.
/:cl:

* Fixes ore vents spawning without ores on icebox, sets up map specific ore configurations

---------

Co-authored-by: ArcaneMusic <[email protected]>
  • Loading branch information
2 people authored and FFMirrorBot committed Feb 9, 2024
1 parent 107a5d8 commit 8f98972
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 64 deletions.
4 changes: 3 additions & 1 deletion code/__DEFINES/mining.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,6 @@
/// The multiplier that gets applied for automatically generated mining points.
#define MINING_POINT_MACHINE_MULTIPLIER 0.8


//String defines to use with CaveGenerator presets for what ore breakdown to use.
#define OREGEN_PRESET_LAVALAND "lavaland"
#define OREGEN_PRESET_TRIPLE_Z "triple_z"
35 changes: 35 additions & 0 deletions code/_globalvars/lists/ores_spawned.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Sets of global lists breaking down the base spawning distributions for various maps and stations.
*
* Currently used for ore vents on roundstart when the map is generated. (See ore_vent.dm, seedRuins() and ore_generation.dm)
* Ore vent lists here are copied to ore_vent_minerals on ruin seeding,
* in order to dynamically adjust the spawn rates as materials are picked and set a global ore distribution from vents.
*
* By default vents pull 4 unique materials each, but this can vary with subtypes.
*/

GLOBAL_LIST_INIT(ore_vent_minerals_lavaland, list(
/datum/material/iron = 13,
/datum/material/glass = 12,
/datum/material/plasma = 9,
/datum/material/titanium = 6,
/datum/material/silver = 5,
/datum/material/gold = 5,
/datum/material/diamond = 3,
/datum/material/uranium = 3,
/datum/material/bluespace = 3,
/datum/material/plastic = 1,
))

GLOBAL_LIST_INIT(ore_vent_minerals_triple_z, list(
/datum/material/iron = 24,
/datum/material/glass = 23,
/datum/material/plasma = 16,
/datum/material/titanium = 10,
/datum/material/silver = 8,
/datum/material/gold = 7,
/datum/material/diamond = 4,
/datum/material/uranium = 4,
/datum/material/bluespace = 3,
/datum/material/plastic = 1,
))
4 changes: 2 additions & 2 deletions code/controllers/subsystem/mapping.dm
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,12 @@ SUBSYSTEM_DEF(mapping)
// Generate mining ruins
var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS)
if (lava_ruins.len)
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), list(/area/lavaland/surface/outdoors/unexplored), themed_ruins[ZTRAIT_LAVA_RUINS], clear_below = TRUE)
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), list(/area/lavaland/surface/outdoors/unexplored), themed_ruins[ZTRAIT_LAVA_RUINS], clear_below = TRUE, mineral_budget = 15, mineral_budget_update = OREGEN_PRESET_LAVALAND)

var/list/ice_ruins = levels_by_trait(ZTRAIT_ICE_RUINS)
if (ice_ruins.len)
// needs to be whitelisted for underground too so place_below ruins work
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), themed_ruins[ZTRAIT_ICE_RUINS], clear_below = TRUE, mineral_budget = 4)
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), themed_ruins[ZTRAIT_ICE_RUINS], clear_below = TRUE, mineral_budget = 4, mineral_budget_update = OREGEN_PRESET_TRIPLE_Z)

var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND)
if (ice_ruins_underground.len)
Expand Down
40 changes: 18 additions & 22 deletions code/controllers/subsystem/ore_generation.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,18 @@ SUBSYSTEM_DEF(ore_generation)
var/list/available_boulders = list()
/// All the ore vents that are currently in the game, not just the ones that are producing boulders.
var/list/possible_vents = list()
/// A list of all the minerals that are being mined by ore vents. We reset this list every time cave generation is done.
var/list/ore_vent_minerals = list()
/**
* Associated list of minerals to be associated with our ore vents.
* 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/static/list/ore_vent_minerals_default = list(
/datum/material/iron = 13,
/datum/material/glass = 12,
/datum/material/plasma = 9,
/datum/material/titanium = 6,
/datum/material/silver = 5,
/datum/material/gold = 5,
/datum/material/diamond = 3,
/datum/material/uranium = 3,
/datum/material/bluespace = 3,
/datum/material/plastic = 1,
)
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 = 3,
MEDIUM_VENT_TYPE = 5,
SMALL_VENT_TYPE = 7,
LARGE_VENT_TYPE = 0,
MEDIUM_VENT_TYPE = 0,
SMALL_VENT_TYPE = 0,
)
/// Ores spawned by proximity to an ore vent. Useful for logging purposes.
var/list/post_ore_random = list(
Expand All @@ -54,13 +43,20 @@ SUBSYSTEM_DEF(ore_generation)

/datum/controller/subsystem/ore_generation/Initialize()
//Basically, we're going to round robin through the list of ore vents and assign a mineral to them until complete.
while(ore_vent_minerals.len > 0)
while(length(ore_vent_minerals) > 0) //Keep looping if there's more to assign
var/stallbreaker = 0
for(var/obj/structure/ore_vent/vent as anything in possible_vents)
if(length(ore_vent_minerals) <= 0) //But break early if there's none left.
break
if(vent.unique_vent)
continue //Ya'll already got your minerals.
if(ore_vent_minerals.len <= 0)
break
vent.generate_mineral_breakdown(max_minerals = 1, map_loading = TRUE)
if(length(difflist(first = ore_vent_minerals, second = vent.mineral_breakdown, skiprep = 1)))
vent.generate_mineral_breakdown(new_minerals = 1, map_loading = TRUE)
else
stallbreaker++
if(stallbreaker >= length(possible_vents))
return SS_INIT_SUCCESS //We've done all we can here.
continue
return SS_INIT_SUCCESS

/datum/controller/subsystem/ore_generation/fire(resumed)
Expand Down
1 change: 0 additions & 1 deletion code/datums/mapgen/CaveGenerator.dm
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@
var/megas_allowed = (generate_in.area_flags & MEGAFAUNA_SPAWN_ALLOWED) && length(megafauna_spawn_list)

var/start_time = REALTIMEOFDAY
SSore_generation.ore_vent_minerals = (SSore_generation.ore_vent_minerals_default).Copy() //reset the ore vent minerals to the default

for(var/turf/target_turf as anything in turfs)
if(!(target_turf.type in open_turf_types)) //only put stuff on open turfs we generated, so closed walls and rivers and stuff are skipped
Expand Down
7 changes: 7 additions & 0 deletions code/datums/mapgen/Cavegens/IcemoonCaves.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@
birth_limit = 5
death_limit = 4
smoothing_iterations = 10
weighted_feature_spawn_list = list(
/obj/structure/geyser/hollowwater = 10,
/obj/structure/geyser/plasma_oxide = 10,
/obj/structure/geyser/protozine = 10,
/obj/structure/geyser/random = 2,
/obj/structure/geyser/wittel = 10,
)

/// Surface snow generator variant for forested station trait, WITH FORESTSSSS
/datum/map_generator/cave_generator/icemoon/surface/forested
Expand Down
55 changes: 30 additions & 25 deletions code/game/objects/structures/lavaland/ore_vent.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
var/tapped = FALSE
/// Has this vent been scanned by a mining scanner? Cannot be scanned again. Adds ores to the vent's description.
var/discovered = FALSE
/// Is this type of vent exempt from the 15 vent limit? Think the free iron/glass vent or boss vents. This also causes it to not roll for random mineral breakdown.
/// Is this type of vent exempt from the map's vent budget/limit? Think the free iron/glass vent or boss vents. This also causes it to not roll for random mineral breakdown.
var/unique_vent = FALSE
/// What icon_state do we use when the ore vent has been tapped?
var/icon_state_tapped = "ore_vent_active"
Expand Down Expand Up @@ -74,7 +74,8 @@
if(mapload)
generate_description()
register_context()
SSore_generation.possible_vents += src
if(!unique_vent)
SSore_generation.possible_vents += src
boulder_icon_state = pick(list(
"boulder",
"rock",
Expand Down Expand Up @@ -168,33 +169,37 @@
/**
* 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.
* As a result, minerals use a weighted list as seen by ore_vent_minerals_default, which is then copied to ore_vent_minerals.
* As a result, minerals use a weighted list as seen by ore_vent_minerals_lavaland, which is then copied to ore_vent_minerals.
* Once a material is picked from the weighted list, it's removed from ore_vent_minerals, so that it can't be picked again and provided it's own internal weight used when assigning minerals to boulders spawned by this vent.
* May also be called after the fact, as seen in SSore_generation's initialize, to add more minerals to an existing vent.
*
* The above applies only when spawning in at mapload, otherwise we pick randomly from ore_vent_minerals_default.
* The above applies only when spawning in at mapload, otherwise we pick randomly from ore_vent_minerals_lavaland.
*
* @params max_minerals How many minerals should be added to this vent? Defaults to MINERAL_TYPE_OPTIONS_RANDOM, which is 4.
* @params map_loading Is this vent being spawned in at mapload? If so, we use the ore_generation subsystem's ore_vent_minerals list to pick minerals. Otherwise, we pick randomly from ore_vent_minerals_default.
* @params new_minerals How many minerals should be added to this vent? Defaults to MINERAL_TYPE_OPTIONS_RANDOM, which is 4.
* @params map_loading Is this vent being spawned in at mapload? If so, we use the ore_generation subsystem's ore_vent_minerals list to pick minerals. Otherwise, we pick randomly from ore_vent_minerals_lavaland.
*/
/obj/structure/ore_vent/proc/generate_mineral_breakdown(max_minerals = MINERAL_TYPE_OPTIONS_RANDOM, map_loading = FALSE)
if(max_minerals < 1)
CRASH("generate_mineral_breakdown called with max_minerals < 1.")
for(var/iterator in 1 to max_minerals)
if(!SSore_generation.ore_vent_minerals.len && map_loading)
CRASH("No minerals left to pick from! We may have spawned too many ore vents in init, or added too many ores to the existing vents.")
var/datum/material/material
/obj/structure/ore_vent/proc/generate_mineral_breakdown(new_minerals = MINERAL_TYPE_OPTIONS_RANDOM, map_loading = FALSE)
if(new_minerals < 1)
CRASH("generate_mineral_breakdown called with new_minerals < 1.")
var/list/available_mats = difflist(first = SSore_generation.ore_vent_minerals, second = mineral_breakdown, skiprep = 1)
for(var/i in 1 to new_minerals)
if(!length(SSore_generation.ore_vent_minerals) && map_loading)
// We should prevent this from happening in SSore_generation, but if not then we crash here
CRASH("No minerals left to pick from! We may have spawned too many ore vents in init, or the map config in seedRuins may not have enough resources for the mineral budget.")
var/datum/material/new_material
if(map_loading)
material = pick_weight(SSore_generation.ore_vent_minerals)
if(is_type_in_list(mineral_breakdown, material))
continue
if(map_loading)
SSore_generation.ore_vent_minerals[material] -= 1 //We remove 1 from the ore vent's mineral breakdown weight, so that it can't be picked again.
if(SSore_generation.ore_vent_minerals[material] <= 0)
SSore_generation.ore_vent_minerals -= material
if(length(available_mats))
new_material = pick(GLOB.ore_vent_minerals_lavaland)
var/datum/material/surrogate_mat = pick(SSore_generation.ore_vent_minerals)
available_mats -= surrogate_mat
SSore_generation.ore_vent_minerals -= surrogate_mat
else
new_material = pick(available_mats)
available_mats -= new_material
SSore_generation.ore_vent_minerals -= new_material
else
material = pick_weight(SSore_generation.ore_vent_minerals_default)
mineral_breakdown[material] = rand(1, 4)
new_material = pick(GLOB.ore_vent_minerals_lavaland)
mineral_breakdown[new_material] = rand(1, 4)


/**
Expand Down Expand Up @@ -416,15 +421,15 @@
if(LARGE_VENT_TYPE)
boulder_size = BOULDER_SIZE_LARGE
if(mapload)
SSore_generation.ore_vent_sizes["large"] -= 1
SSore_generation.ore_vent_sizes["large"] += 1
if(MEDIUM_VENT_TYPE)
boulder_size = BOULDER_SIZE_MEDIUM
if(mapload)
SSore_generation.ore_vent_sizes["medium"] -= 1
SSore_generation.ore_vent_sizes["medium"] += 1
if(SMALL_VENT_TYPE)
boulder_size = BOULDER_SIZE_SMALL
if(mapload)
SSore_generation.ore_vent_sizes["small"] -= 1
SSore_generation.ore_vent_sizes["small"] += 1
else
boulder_size = BOULDER_SIZE_SMALL //Might as well set a default value
name = initial(name)
Expand Down
2 changes: 0 additions & 2 deletions code/game/turfs/closed/minerals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@

var/distance = 128 // Max distance for a get_dist is 127
for(var/obj/structure/ore_vent/vent as anything in SSore_generation.possible_vents)
if(vent.unique_vent)
continue
if(vent.z != src.z)
continue //Silly
var/temp_distance = get_dist(src, vent)
Expand Down
9 changes: 8 additions & 1 deletion code/modules/mapping/ruins.dm
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@
* @param potentialRuins A list of ruins to choose from.
* @param clear_below Whether to clear the area below the ruin. Used for multiz ruins.
* @param mineral_budget The budget to spend on ruins that spawn ore vents. Map templates with vents have that defined by mineral_cost.
* @param mineral_budget_update What type of ore distribution should spawn from ruins picked by this cave generator? This list is copied from ores_spawned.dm into SSore_generation.ore_vent_minerals.
*/
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = list(/area/space), list/potentialRuins, clear_below = FALSE, mineral_budget = 15)
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = list(/area/space), list/potentialRuins, clear_below = FALSE, mineral_budget = 15, mineral_budget_update)
if(!z_levels || !z_levels.len)
WARNING("No Z levels provided - Not generating ruins")
return
Expand All @@ -92,6 +93,12 @@
if(PERFORM_ALL_TESTS(log_mapping))
log_mapping("All ruins being loaded for map testing.")

switch(mineral_budget_update) //If we use more map configurations, add another case
if(OREGEN_PRESET_LAVALAND)
SSore_generation.ore_vent_minerals = expand_weights(GLOB.ore_vent_minerals_lavaland)
if(OREGEN_PRESET_TRIPLE_Z)
SSore_generation.ore_vent_minerals = expand_weights(GLOB.ore_vent_minerals_triple_z)

//Set up the starting ruin list
for(var/key in ruins)
var/datum/map_template/ruin/R = ruins[key]
Expand Down
12 changes: 2 additions & 10 deletions code/modules/mining/boulder_processing/refinery.dm
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
/**
* Your new favorite industrial waste magnet!
* Accepts boulders and produces sheets of non-metalic materials.
* Can be upgraded with stock parts or through chemical inputs.
* When upgraded, it can hold more boulders and process more at once.
*
* Chemical inputs can be used to boost the refinery's efficiency, but produces industrial waste, which eats through the station and is generally difficult to store.
*/

/obj/machinery/bouldertech/refinery
name = "boulder refinery"
desc = "BR for short. Accepts boulders and refines non-metallic ores into sheets using internal chemicals. Can be upgraded with stock parts or through chemical inputs."
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(
Expand Down Expand Up @@ -53,14 +49,11 @@
/**
* Your other new favorite industrial waste magnet!
* Accepts boulders and produces sheets of metalic materials.
* Can be upgraded with stock parts or through chemical inputs.
* When upgraded, it can hold more boulders and process more at once.
*
* Chemical inputs can be used to boost the refinery's efficiency, but produces industrial waste, which eats through the station and is generally difficult to store.
*/
/obj/machinery/bouldertech/refinery/smelter
name = "boulder smelter"
desc = "BS for short. Accept boulders and refines metallic ores into sheets. Can be upgraded with stock parts or through gas inputs."
desc = "BS for short. Accept boulders and refines metallic ores into sheets."
icon_state = "smelter"
processable_materials = list(
/datum/material/iron,
Expand Down Expand Up @@ -90,7 +83,6 @@
set_light_on(TRUE)
return TRUE


/obj/machinery/bouldertech/refinery/smelter/process()
. = ..()
if(. == PROCESS_KILL)
Expand Down
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@
#include "code\_globalvars\lists\mobs.dm"
#include "code\_globalvars\lists\names.dm"
#include "code\_globalvars\lists\objects.dm"
#include "code\_globalvars\lists\ores_spawned.dm"
#include "code\_globalvars\lists\plumbing.dm"
#include "code\_globalvars\lists\poll_ignore.dm"
#include "code\_globalvars\lists\quirks.dm"
Expand Down

0 comments on commit 8f98972

Please sign in to comment.