mirror of
https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git
synced 2024-12-04 09:43:00 +02:00
Saving initial Gleba work. Have a dumb but simple method for placing plants and iron-copper things. Needs refining and testing.
This commit is contained in:
parent
d06d6eadf3
commit
553389ce6e
@ -18,6 +18,7 @@
|
||||
require("lib/planet_configs/nauvis")
|
||||
require("lib/planet_configs/fulgora")
|
||||
require("lib/planet_configs/vulcanus")
|
||||
require("lib/planet_configs/gleba")
|
||||
|
||||
---@alias SpawnShapeChoice "circle" | "octagon" | "square"
|
||||
SPAWN_SHAPE_CHOICE_CIRCLE = "circle"
|
||||
@ -372,13 +373,13 @@ OCFG = {
|
||||
starting_items = FULGORA_STARTER_ITEMS,
|
||||
spawn_config = FULGORA_SPAWN_CONFIG
|
||||
},
|
||||
-- ["gleba"] = {
|
||||
-- starting_items = NAUVIS_STARTER_ITEMS,
|
||||
-- spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
-- },
|
||||
["gleba"] = {
|
||||
starting_items = GLEBA_STARTER_ITEMS,
|
||||
spawn_config = GLEBA_SPAWN_CONFIG
|
||||
},
|
||||
-- ["aquilo"] = {
|
||||
-- starting_items = NAUVIS_STARTER_ITEMS,
|
||||
-- spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
-- starting_items = AQUILO_STARTER_ITEMS,
|
||||
-- spawn_config = AQUILO_SPAWN_CONFIG
|
||||
-- }
|
||||
},
|
||||
|
||||
@ -512,6 +513,7 @@ OCFG = {
|
||||
---@field shared_chest_position OarcOffsetPosition Location of shared chest relative to spawn center (if enabled)
|
||||
---@field solid_resources table<string, OarcConfigSolidResource> Spawn area config for solid resource tiles
|
||||
---@field fluid_resources table<string, OarcConfigFluidResource> Spawn area config for fluid resource patches (like oil)
|
||||
---@field growth_resources table<string, OarcConfigGrowthResource> Spawn area config for growth resources (like gleba trees)
|
||||
|
||||
---@class OarcConfigSpawnGeneral
|
||||
---@field spawn_radius_tiles number THIS IS WHAT SETS THE SPAWN CIRCLE SIZE! Create a circle of land area for the spawn If you make this much bigger than a few chunks, good luck.
|
||||
@ -561,6 +563,11 @@ OCFG = {
|
||||
---@field x_offset_next integer
|
||||
---@field y_offset_next integer
|
||||
|
||||
---@class OarcConfigGrowthResource
|
||||
---@field tile string The tile to place
|
||||
---@field entity string The entity (tree that grows on this specific tile)
|
||||
---@field size integer
|
||||
|
||||
---@class OarcStoreItem
|
||||
---@field cost integer
|
||||
---@field count integer
|
||||
|
58
lib/planet_configs/gleba.lua
Normal file
58
lib/planet_configs/gleba.lua
Normal file
@ -0,0 +1,58 @@
|
||||
-- This config is used as the default config for the planet gleba.
|
||||
|
||||
---@type OarcConfigStartingItems
|
||||
GLEBA_STARTER_ITEMS = table.deepcopy(NO_STARTER_ITEMS)
|
||||
|
||||
---@type OarcConfigSpawn
|
||||
GLEBA_SPAWN_CONFIG = table.deepcopy(NAUVIS_SPAWN_CONFIG)
|
||||
GLEBA_SPAWN_CONFIG.fill_tile = "highland-dark-rock-2"
|
||||
GLEBA_SPAWN_CONFIG.liquid_tile = "gleba-deep-lake"
|
||||
GLEBA_SPAWN_CONFIG.tree_entity = nil
|
||||
GLEBA_SPAWN_CONFIG.random_entities = {
|
||||
{name = "boompuff", count = 10},
|
||||
{name = "sunnycomb", count = 10},
|
||||
{name = "stingfrond", count = 10},
|
||||
{name = "funneltrunk", count = 10},
|
||||
{name = "teflilly", count = 10},
|
||||
{name = "slipstack", count = 10},
|
||||
{name = "cuttlepop", count = 10},
|
||||
{name = "water-cane", count = 10},
|
||||
}
|
||||
|
||||
GLEBA_SPAWN_CONFIG.solid_resources =
|
||||
{
|
||||
["stone"] = {
|
||||
amount = 1000,
|
||||
size = 20,
|
||||
|
||||
-- These are only used if not using automatic placing.
|
||||
x_offset = -29,
|
||||
y_offset = 16
|
||||
}
|
||||
}
|
||||
|
||||
GLEBA_SPAWN_CONFIG.growth_resources =
|
||||
{
|
||||
["yumako"] = {
|
||||
tile = "natural-yumako-soil",
|
||||
entity = "yumako-tree",
|
||||
size = 20
|
||||
},
|
||||
["jellystem"] = {
|
||||
tile = "natural-jellynut-soil",
|
||||
entity = "jellystem",
|
||||
size = 20
|
||||
},
|
||||
["iron"] = {
|
||||
tile = "wetland-dead-skin",
|
||||
entity = "iron-stromatolite",
|
||||
size = 20
|
||||
},
|
||||
["copper"] = {
|
||||
tile = "wetland-dead-skin",
|
||||
entity = "copper-stromatolite",
|
||||
size = 20
|
||||
},
|
||||
}
|
||||
|
||||
GLEBA_SPAWN_CONFIG.fluid_resources = { }
|
@ -170,6 +170,8 @@ NAUVIS_SPAWN_CONFIG =
|
||||
y_offset_next = 0
|
||||
}
|
||||
},
|
||||
|
||||
growth_resources = {}
|
||||
}
|
||||
|
||||
---@type OarcConfigSurface
|
||||
|
@ -8,9 +8,14 @@
|
||||
ENEMY_FORCES_NAMES = { "enemy" }
|
||||
ENEMY_FORCES_NAMES_INCL_NEUTRAL = { "enemy", "neutral" }
|
||||
|
||||
ENEMY_BUILT_TYPES = { "biter-spawner", "spitter-spawner", "small-worm-turret", "medium-worm-turret", "big-worm-turret",
|
||||
"behemoth-worm-turret" }
|
||||
|
||||
-- gleba-spawner-small
|
||||
-- gleba-spawner
|
||||
|
||||
-- yumako-tree
|
||||
-- copper-stromatolite
|
||||
-- jellystem
|
||||
-- yumako-tree
|
||||
|
||||
---Downgrades worms based on distance from origin and near/far spawn distances.
|
||||
---This helps make sure worms aren't too overwhelming even at these further spawn distances.
|
||||
@ -47,12 +52,15 @@ function DowngradeAndReduceEnemiesOnChunkGenerate(event)
|
||||
y = chunk_area.left_top.y + (CHUNK_SIZE / 2)
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- TODO: Change this lookup to be done once during surface init.
|
||||
local nauvis_enemies = surface.map_gen_settings.autoplace_controls["enemy-base"] ~= nil
|
||||
local gleba_enemies = surface.map_gen_settings.autoplace_controls["gleba_enemy_base"] ~= nil
|
||||
-- local vulcanus_enemies = surface.map_gen_settings.territory_settings ~= nil
|
||||
|
||||
-- Make chunks near a spawn safe by removing enemies
|
||||
-- TODO: Refactor this to reduce calls to find_entities_filtered maybe?
|
||||
if (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.safe_radius * CHUNK_SIZE) then
|
||||
if nauvis_enemies or gleba_enemies then
|
||||
RemoveEnemiesInArea(surface, chunk_area)
|
||||
@ -60,17 +68,21 @@ function DowngradeAndReduceEnemiesOnChunkGenerate(event)
|
||||
|
||||
-- Create a warning area with heavily reduced enemies
|
||||
elseif (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.warn_radius * CHUNK_SIZE) then
|
||||
if nauvis_enemies then
|
||||
-- TODO: Refactor this to reduce calls to find_entities_filtered!
|
||||
if nauvis_enemies or gleba_enemies then
|
||||
ReduceEnemiesInArea(surface, chunk_area, spawn_config.safe_area.warn_reduction)
|
||||
end
|
||||
|
||||
if nauvis_enemies then
|
||||
RemoveWormsInArea(surface, chunk_area, false, true, true, true) -- remove all non-small worms.
|
||||
end
|
||||
|
||||
-- Create a third area with moderately reduced enemies
|
||||
elseif (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.danger_radius * CHUNK_SIZE) then
|
||||
if nauvis_enemies then
|
||||
-- TODO: Refactor this to reduce calls to find_entities_filtered!
|
||||
if nauvis_enemies or gleba_enemies then
|
||||
ReduceEnemiesInArea(surface, chunk_area, spawn_config.safe_area.danger_reduction)
|
||||
end
|
||||
|
||||
if nauvis_enemies then
|
||||
RemoveWormsInArea(surface, chunk_area, false, false, true, true) -- remove all huge/behemoth worms.
|
||||
end
|
||||
end
|
||||
@ -203,36 +215,54 @@ function ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
|
||||
-- Warn distance is all SMALL only.
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < storage.ocfg.surfaces_config[surface.name].spawn_config.safe_area.warn_radius * CHUNK_SIZE) then
|
||||
if ((enemy_name == "biter-spawner") or (enemy_name == "spitter-spawner")) then
|
||||
-- Do nothing.
|
||||
elseif ((enemy_name == "big-biter") or (enemy_name == "behemoth-biter") or (enemy_name == "medium-biter")) then
|
||||
|
||||
-- Nauvis enemies
|
||||
if ((enemy_name == "big-biter") or (enemy_name == "behemoth-biter") or (enemy_name == "medium-biter")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "small-biter", position = enemy_pos, force = game.forces.enemy }
|
||||
-- log("Downgraded biter close to spawn.")
|
||||
elseif ((enemy_name == "big-spitter") or (enemy_name == "behemoth-spitter") or (enemy_name == "medium-spitter")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "small-spitter", position = enemy_pos, force = game.forces.enemy }
|
||||
-- log("Downgraded spitter close to spawn.")
|
||||
elseif ((enemy_name == "big-worm-turret") or (enemy_name == "behemoth-worm-turret") or (enemy_name == "medium-worm-turret")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "small-worm-turret", position = enemy_pos, force = game.forces.enemy }
|
||||
-- log("Downgraded worm close to spawn.")
|
||||
|
||||
-- Gleba enemies
|
||||
elseif ((enemy_name == "big-wriggler-pentapod") or (enemy_name == "medium-wriggler-pentapod")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "small-wriggler-pentapod", position = enemy_pos, force = game.forces.enemy }
|
||||
elseif ((enemy_name == "big-stomper-pentapod") or (enemy_name == "medium-stomper-pentapod")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "small-stomper-pentapod", position = enemy_pos, force = game.forces.enemy }
|
||||
elseif ((enemy_name == "big-strafer-pentapod") or (enemy_name == "medium-strafer-pentapod")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "small-strafer-pentapod", position = enemy_pos, force = game.forces.enemy }
|
||||
end
|
||||
|
||||
-- Danger distance is MEDIUM max.
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < storage.ocfg.surfaces_config[surface.name].spawn_config.safe_area.danger_radius * CHUNK_SIZE) then
|
||||
|
||||
-- Nauvis enemies
|
||||
if ((enemy_name == "big-biter") or (enemy_name == "behemoth-biter")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "medium-biter", position = enemy_pos, force = game.forces.enemy }
|
||||
-- log("Downgraded biter further from spawn.")
|
||||
elseif ((enemy_name == "big-spitter") or (enemy_name == "behemoth-spitter")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "medium-spitter", position = enemy_pos, force = game.forces.enemy }
|
||||
-- log("Downgraded spitter further from spawn
|
||||
elseif ((enemy_name == "big-worm-turret") or (enemy_name == "behemoth-worm-turret")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "medium-worm-turret", position = enemy_pos, force = game.forces.enemy }
|
||||
-- log("Downgraded worm further from spawn.")
|
||||
|
||||
-- Gleba enemies
|
||||
elseif (enemy_name == "big-wriggler-pentapod") then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "medium-wriggler-pentapod", position = enemy_pos, force = game.forces.enemy }
|
||||
elseif (enemy_name == "big-stomper-pentapod") then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "medium-stomper-pentapod", position = enemy_pos, force = game.forces.enemy }
|
||||
elseif (enemy_name == "big-strafer-pentapod") then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "medium-strafer-pentapod", position = enemy_pos, force = game.forces.enemy }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -372,7 +372,7 @@ end
|
||||
---@param spawn_config OarcConfigSpawn
|
||||
---@param surface LuaSurface
|
||||
---@return nil
|
||||
function GenerateStartingLiquedStrip(delayed_spawn, spawn_config, surface)
|
||||
function GenerateStartingLiquidStrip(delayed_spawn, spawn_config, surface)
|
||||
|
||||
local water_data = spawn_config.water
|
||||
-- Reference position is the top of the spawn area.
|
||||
@ -398,6 +398,7 @@ end
|
||||
---@return nil
|
||||
function GenerateStartingResources(surface, position)
|
||||
|
||||
--TODO: This should come from map gen settings instead:
|
||||
local size_mod = storage.ocfg.resource_placement.size_multiplier
|
||||
local amount_mod = storage.ocfg.resource_placement.amount_multiplier
|
||||
|
||||
@ -478,19 +479,26 @@ function PlaceResourcesInSemiCircle(surface, position, size_mod, amount_mod)
|
||||
-- Create list of resource tiles
|
||||
---@type table<string>
|
||||
local r_list = {}
|
||||
for r_name, _ in pairs(storage.ocfg.surfaces_config[surface.name].spawn_config.solid_resources --[[@as table<string, OarcConfigSolidResource>]]) do
|
||||
for r_name, _ in pairs(storage.ocfg.surfaces_config[surface.name].spawn_config.solid_resources) do
|
||||
if (r_name ~= "") then
|
||||
table.insert(r_list, r_name)
|
||||
end
|
||||
end
|
||||
|
||||
for g_name,_ in pairs(storage.ocfg.surfaces_config[surface.name].spawn_config.growth_resources) do
|
||||
if (g_name ~= "") then
|
||||
table.insert(r_list, g_name)
|
||||
end
|
||||
end
|
||||
|
||||
---@type table<string>
|
||||
local shuffled_list = FYShuffle(r_list)
|
||||
local num_resources = table_size(shuffled_list)
|
||||
|
||||
-- This places resources in a semi-circle
|
||||
local surface_config = storage.ocfg.surfaces_config[surface.name]
|
||||
local angle_offset_radians = math.rad(storage.ocfg.resource_placement.angle_offset)
|
||||
local angle_final_radians = math.rad(storage.ocfg.resource_placement.angle_final)
|
||||
local num_resources = table_size(storage.ocfg.surfaces_config[surface.name].spawn_config.solid_resources)
|
||||
local radius = storage.ocfg.spawn_general.spawn_radius_tiles * surface_config.spawn_config.radius_modifier - storage.ocfg.resource_placement.distance_to_edge
|
||||
|
||||
-- Special case for only one resource, place it in the middle of the semi-circle.
|
||||
@ -504,7 +512,13 @@ function PlaceResourcesInSemiCircle(surface, position, size_mod, amount_mod)
|
||||
local pos = { x = math.floor(tx), y = math.floor(ty) }
|
||||
|
||||
local resourceConfig = surface_config.spawn_config.solid_resources[r_name]
|
||||
GenerateResourcePatch(surface, r_name, resourceConfig.size * size_mod, pos, resourceConfig.amount * amount_mod)
|
||||
if (resourceConfig ~= nil) then
|
||||
GenerateResourcePatch(surface, r_name, resourceConfig.size * size_mod, pos, resourceConfig.amount * amount_mod)
|
||||
else
|
||||
local gResourceConfig = surface_config.spawn_config.growth_resources[r_name]
|
||||
GenerateGrowthResourcePatch(surface, gResourceConfig.tile, gResourceConfig.entity, gResourceConfig.size * size_mod, pos)
|
||||
end
|
||||
|
||||
else
|
||||
local theta = ((angle_final_radians - angle_offset_radians) / (num_resources-1));
|
||||
local count = 0
|
||||
@ -518,8 +532,13 @@ function PlaceResourcesInSemiCircle(surface, position, size_mod, amount_mod)
|
||||
|
||||
local pos = { x = math.floor(tx), y = math.floor(ty) }
|
||||
|
||||
local resourceConfig = storage.ocfg.surfaces_config[surface.name].spawn_config.solid_resources[r_name]
|
||||
GenerateResourcePatch(surface, r_name, resourceConfig.size * size_mod, pos, resourceConfig.amount * amount_mod)
|
||||
local resourceConfig = surface_config.spawn_config.solid_resources[r_name]
|
||||
if (resourceConfig ~= nil) then
|
||||
GenerateResourcePatch(surface, r_name, resourceConfig.size * size_mod, pos, resourceConfig.amount * amount_mod)
|
||||
else
|
||||
local gResourceConfig = surface_config.spawn_config.growth_resources[r_name]
|
||||
GenerateGrowthResourcePatch(surface, gResourceConfig.tile, gResourceConfig.entity, gResourceConfig.size * size_mod, pos)
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
@ -580,7 +599,7 @@ function GenerateFinalSpawnPieces(delayed_spawn)
|
||||
|
||||
-- Generate water strip only if we don't have a moat.
|
||||
if (not delayed_spawn.moat or spawn_config.liquid_tile == "lava") then
|
||||
GenerateStartingLiquedStrip(delayed_spawn, spawn_config, surface)
|
||||
GenerateStartingLiquidStrip(delayed_spawn, spawn_config, surface)
|
||||
end
|
||||
|
||||
-- Create the spawn resources here
|
||||
@ -754,9 +773,9 @@ function SetupAndClearSpawnAreas(surface, chunkArea)
|
||||
|
||||
-- Remove trees/resources inside the spawn area
|
||||
if (general_spawn_config.shape == SPAWN_SHAPE_CHOICE_CIRCLE) or (general_spawn_config.shape == SPAWN_SHAPE_CHOICE_OCTAGON) then
|
||||
RemoveInCircle(surface, chunkArea, {"resource", "cliff", "tree", "lightning-attractor", "simple-entity"}, spawn.position, radius + 5)
|
||||
RemoveInCircle(surface, chunkArea, {"resource", "cliff", "tree", "plant", "lightning-attractor", "simple-entity"}, spawn.position, radius + 5)
|
||||
elseif (general_spawn_config.shape == SPAWN_SHAPE_CHOICE_SQUARE) then
|
||||
RemoveInSquare(surface, chunkArea, {"resource", "cliff", "tree", "lightning-attractor", "simple-entity"}, spawn.position, radius + 5)
|
||||
RemoveInSquare(surface, chunkArea, {"resource", "cliff", "tree", "plant", "lightning-attractor", "simple-entity"}, spawn.position, radius + 5)
|
||||
end
|
||||
|
||||
if (general_spawn_config.shape == SPAWN_SHAPE_CHOICE_CIRCLE) then
|
||||
|
@ -277,6 +277,7 @@ end
|
||||
---@param diameter integer
|
||||
---@param position TilePosition
|
||||
---@param amount integer
|
||||
---@return nil
|
||||
function GenerateResourcePatch(surface, resourceName, diameter, position, amount)
|
||||
local midPoint = math.floor(diameter / 2)
|
||||
if (diameter == 0) then
|
||||
@ -300,7 +301,55 @@ function GenerateResourcePatch(surface, resourceName, diameter, position, amount
|
||||
end
|
||||
end
|
||||
|
||||
--- Function to generate a resource patch, of a certain size/amount at a pos.
|
||||
--- Function to generate a growth resource patch, of a certain size at a pos.
|
||||
---@param surface LuaSurface
|
||||
---@param tile_name string
|
||||
---@param entity_name string
|
||||
---@param diameter integer
|
||||
---@param position TilePosition
|
||||
---@return nil
|
||||
function GenerateGrowthResourcePatch(surface, tile_name, entity_name, diameter, position)
|
||||
local midPoint = math.floor(diameter / 2)
|
||||
if (diameter == 0) then
|
||||
return
|
||||
end
|
||||
|
||||
-- Right now only 2 shapes are supported. Circle and Square.
|
||||
local square_shape = (storage.ocfg.spawn_general.resources_shape == RESOURCES_SHAPE_CHOICE_SQUARE)
|
||||
|
||||
local tiles = {}
|
||||
for y = -midPoint, midPoint do
|
||||
for x = -midPoint, midPoint do
|
||||
-- Either it's a square, or it's a circle so we check if it's inside the circle.
|
||||
if (square_shape or ((x) ^ 2 + (y) ^ 2 < midPoint ^ 2)) then
|
||||
table.insert(tiles, { name = tile_name, position = { position.x + x, position.y + y } })
|
||||
end
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles)
|
||||
|
||||
for y = -midPoint, midPoint do
|
||||
for x = -midPoint, midPoint do
|
||||
-- Either it's a square, or it's a circle so we check if it's inside the circle.
|
||||
if (square_shape or ((x) ^ 2 + (y) ^ 2 < midPoint ^ 2)) then
|
||||
|
||||
-- Reduce chances to spawn to make it more sparse.
|
||||
if (math.random(1, 20) == 1) then
|
||||
local pos = surface.find_non_colliding_position(entity_name, { position.x + x, position.y + y }, 2, 0.5)
|
||||
if (pos ~= nil) then
|
||||
local entity = surface.create_entity({ name = entity_name, position = pos })
|
||||
if (entity.type == "plant") then
|
||||
entity.tick_grown = game.tick
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Places random entities around the spawn area.
|
||||
---@param surface LuaSurface
|
||||
---@param position MapPosition
|
||||
---@return nil
|
||||
|
Loading…
Reference in New Issue
Block a user