From 305786da579a492cd115544a9c47f1c5577cd19e Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Tue, 29 Oct 2024 09:44:20 -0400 Subject: [PATCH] Have the basics of a Fulgora spawn working. Looks like shit, but best I can do for now. --- changelog.txt | 7 ++ info.json | 2 +- lib/config.lua | 157 ++-------------------------- lib/holding_pen.lua | 4 +- lib/oarc_tests.lua | 91 +++++++++++++++++ lib/oarc_utils.lua | 98 ++++++++++++++++-- lib/planet_configs/fulgora.lua | 34 +++++++ lib/planet_configs/nauvis.lua | 180 +++++++++++++++++++++++++++++++++ lib/separate_spawns.lua | 89 +++++++++++----- 9 files changed, 479 insertions(+), 183 deletions(-) create mode 100644 lib/planet_configs/fulgora.lua create mode 100644 lib/planet_configs/nauvis.lua diff --git a/changelog.txt b/changelog.txt index a67ffcf..818c7d5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,11 @@ --------------------------------------------------------------------------------------------------- +Version: 2.1.10 +Date: ???? + Major Features: + - Adding support for secondary spawns on Fulgora. + Bugfixes: + - Fixed a crash if surface only had 1 basic-solid resource to place. +--------------------------------------------------------------------------------------------------- Version: 2.1.9 Date: 2024-11-06 Bugfixes: diff --git a/info.json b/info.json index 5475ce9..706cad6 100644 --- a/info.json +++ b/info.json @@ -1,6 +1,6 @@ { "name": "oarc-mod", - "version": "2.1.9", + "version": "2.1.10", "factorio_version": "2.0", "title": "Oarc Multiplayer Spawn", "author": "Oarcinae", diff --git a/lib/config.lua b/lib/config.lua index f415383..9c2465e 100644 --- a/lib/config.lua +++ b/lib/config.lua @@ -15,6 +15,8 @@ ]] +require("lib/planet_configs/nauvis") +require("lib/planet_configs/fulgora") ---@alias SpawnShapeChoice "circle" | "octagon" | "square" SPAWN_SHAPE_CHOICE_CIRCLE = "circle" @@ -28,148 +30,6 @@ RESOURCES_SHAPE_CHOICE_SQUARE = "square" MAX_CRASHED_SHIP_RESOURCES_ITEMS = 5 MAX_CRASHED_SHIP_WRECKAGE_ITEMS = 1 --- THIS is used as the default starting items on all surfaces if no other settings are provided! ----@type OarcConfigStartingItems -NAUVIS_STARTER_ITEMS = -{ - player_start_items = { - ["iron-plate"] = 8, - ["wood"] = 1, - ["pistol"] = 1, - ["firearm-magazine"] = 10, - ["burner-mining-drill"] = 1, - ["stone-furnace"] = 1 - }, - player_respawn_items = { - ["pistol"] = 1, - ["firearm-magazine"] = 10 - }, - - crashed_ship = true, - crashed_ship_resources = { - ["firearm-magazine"] = 8 -- Max of 5 inventory slots! - }, - crashed_ship_wreakage = { - ["iron-plate"] = 8 -- I don't recommend more than 1 item type here! - }, -} - --- THIS is used as the default spawn config on all surfaces if no other settings are provided! ----@type OarcConfigSpawn -NAUVIS_SPAWN_CONFIG = -{ - -- Safe Spawn Area Options - -- The default settings here are balanced for my recommended map gen settings (close to train world). - safe_area = - { - -- Safe area has no aliens - -- This is the radius in chunks of safe area. - safe_radius = 6, - - -- Warning area has significantly reduced aliens - -- This is the radius in chunks of warning area. - warn_radius = 12, - - -- 1 : X (spawners alive : spawners destroyed) in this area - warn_reduction = 20, - - -- Danger area has slightly reduced aliens - -- This is the radius in chunks of danger area. - danger_radius = 32, - - -- 1 : X (spawners alive : spawners destroyed) in this area - danger_reduction = 5, - }, - - -- Location of water strip within the spawn area (2 horizontal rows) - -- The offset is from the TOP (NORTH) of the spawn area. - water = { - x_offset = -4, - y_offset = 10, - length = 8, - }, - - -- Location of shared power pole within the spawn area (if enabled) - -- The offset is from the RIGHT (WEST) of the spawn area. - shared_power_pole_position = { - x_offset=-10, - y_offset=0 - }, - - -- Location of shared chest within the spawn area (if enabled) - -- The offset is from the RIGHT (WEST) of the spawn area. - shared_chest_position = { - x_offset=-10, - y_offset=1 - }, - - -- Solid resource tiles - -- If you are running with mods that add or change resources, you'll want to customize this. - -- Offsets only are applicable if auto placement is disabled. Offsets are from CENTER of spawn area. - solid_resources = { - ["iron-ore"] = { - amount = 1500, - size = 21, - - -- These are only used if not using automatic placing. - x_offset = -29, - y_offset = 16 - }, - ["copper-ore"] = { - amount = 1200, - size = 21, - - -- These are only used if not using automatic placing. - x_offset = -28, - y_offset = -3 - }, - ["stone"] = { - amount = 1200, - size = 21, - - -- These are only used if not using automatic placing. - x_offset = -27, - y_offset = -34 - }, - ["coal"] = { - amount = 1200, - size = 21, - - -- These are only used if not using automatic placing. - x_offset = -27, - y_offset = -20 - } - }, - - -- Fluid resource patches like oil - -- If you are running with mods that add or change resources, you'll want to customize this. - -- The offset is from the BOTTOM (SOUTH) of the spawn area. - fluid_resources = - { - ["crude-oil"] = - { - num_patches = 2, - amount = 900000, - spacing = 6, -- Spacing between each patch, only used for automatic placing. - - -- These are only used if not using automatic placing. - -- Starting position offset (relative to bottom/south of spawn area) - x_offset_start = -3, - y_offset_start = -10, - -- Additional position offsets for each new oil patch (relative to previous oil patch) - x_offset_next = 6, - y_offset_next = 0 - } - }, -} - ----@type OarcConfigSurface -NAUVIS_SURFACE_CONFIG = -{ - starting_items = NAUVIS_STARTER_ITEMS, - spawn_config = NAUVIS_SPAWN_CONFIG -} - ---This only matters if you have the coin shop enabled. ---@type OarcStoreList OARC_SHOP_ITEMS = @@ -507,10 +367,10 @@ OCFG = { -- starting_items = NAUVIS_STARTER_ITEMS, -- spawn_config = NAUVIS_SPAWN_CONFIG -- }, - -- ["fulgora"] = { - -- starting_items = NAUVIS_STARTER_ITEMS, - -- spawn_config = NAUVIS_SPAWN_CONFIG - -- }, + ["fulgora"] = { + starting_items = FULGORA_STARTER_ITEMS, + spawn_config = FULGORA_SPAWN_CONFIG + }, -- ["gleba"] = { -- starting_items = NAUVIS_STARTER_ITEMS, -- spawn_config = NAUVIS_SPAWN_CONFIG @@ -641,6 +501,11 @@ OCFG = { ---@field player_respawn_items table Items provided after EVERY respawn (disabled by default) ---@class OarcConfigSpawn +---@field fill_tile string Fill tile for the spawn area (grass on Nauvis) +---@field liquid_tile string Moat and liquid strip for the spawn area (water on Nauvis) +---@field tree_entity string Tree ring entity for the spawn area (tree-02 on Nauvis) +---@field random_entities table Random entities to place around the spawn area (like rocks on nauvis, ruins on fulgora) +---@field radius_modifier number Radius modifier for the spawn area (1.0 is default) ---@field safe_area OarcConfigSpawnSafeArea How safe is the spawn area? ---@field water OarcConfigSpawnWater Water strip settings ---@field shared_power_pole_position OarcOffsetPosition Location of shared power pole relative to spawn center (if enabled) diff --git a/lib/holding_pen.lua b/lib/holding_pen.lua index b438b22..846bfc1 100644 --- a/lib/holding_pen.lua +++ b/lib/holding_pen.lua @@ -86,8 +86,8 @@ function CreateHoldingPenChunks(event) PlaceResourcesInSemiCircleHoldingPen(surface, {x=0,y=0}, 0.2, 0.1) - CreateWaterStrip(surface, {x=-2,y=-11}, 4) - CreateWaterStrip(surface, {x=-2,y=-10}, 4) + CreateTileStrip(surface, {x=-2,y=-11}, 4, "water") + CreateTileStrip(surface, {x=-2,y=-10}, 4, "water") surface.create_entity({ name = "crude-oil", diff --git a/lib/oarc_tests.lua b/lib/oarc_tests.lua index db87e20..7f054b7 100644 --- a/lib/oarc_tests.lua +++ b/lib/oarc_tests.lua @@ -232,3 +232,94 @@ function DudeWheresMyCargoPod(player) player.print({ "oarc-teleport-success" }) end end + + + +---Allow players to reroll their spawn point, dangerous because this doesn't do a lot of checks. +---@param player LuaPlayer +---@return nil +function RerollSpawn(player) + + -- Make sure character is valid + if not player.character then + log("ERROR - RerollSpawn - No valid character for player: " .. player.name) + return + end + + -- Ensure we still have their previous spawn choices + local spawn_choices = storage.spawn_choices[player.name] + if (spawn_choices == nil) then + log("ERROR - RerollSpawn - No spawn choices for player: " .. player.name) + return + end + + local surface = player.character.surface + + -- Confirm there is AN existing spawn point for this player on this surface + if (storage.unique_spawns[surface.name] == nil or storage.unique_spawns[surface.name][player.name] == nil) then + log("ERROR - RerollSpawn - Can't reroll? No existing spawn for " .. player.name) + return + end + + -- Save a copy of the previous spawn point + local old_spawn_point = table.deepcopy(storage.unique_spawns[surface.name][player.name]) + + -- Find a new spawn point + local spawn_position = FindUngeneratedCoordinates(surface, spawn_choices.distance, 3) + -- If that fails, just throw a warning and don't spawn them. They can try again. + if ((spawn_position.x == 0) and (spawn_position.y == 0)) then + player.print({ "oarc-no-ungenerated-land-error" }) + return + end + + -- Remove the old spawn point + if (storage.ocfg.regrowth.enable_abandoned_base_cleanup) then + log("Removing base: " .. spawn_position.x .. "," .. spawn_position.y .. " on surface: " .. old_spawn_point.surface_name) + + -- Clear an area around the spawn that SHOULD not include any other bases. + local clear_radius = storage.ocfg.gameplay.minimum_distance_to_existing_chunks - 2 -- Bring in a bit for safety. + RegrowthMarkAreaForRemoval(old_spawn_point.surface_name, old_spawn_point.position, clear_radius) + TriggerCleanup() + -- Trigger event + script.raise_event("oarc-mod-on-spawn-remove-request", {spawn_data = old_spawn_point}) + end + + -- Add new spawn point for the new surface + SetPlayerRespawn(player.name, surface.name, spawn_position, false) -- Do not reset cooldown + QueuePlayerForDelayedSpawn(player.name, surface.name, spawn_position, spawn_choices.moat, old_spawn_point.primary, nil) + + -- Send them to the holding pen + SafeTeleport(player, game.surfaces[HOLDING_PEN_SURFACE_NAME], {x=0,y=0}) + + -- Announce + SendBroadcastMsg({"", { "oarc-player-new-secondary", player.name, surface.name }, " ", GetGPStext(surface.name, spawn_position)}) +end + + + +---Test out placing fulgoran stuff +-- fulgurite-small +-- fulgurite +-- fulgoran-ruin-attractor +-- fulgoran-ruin-small +-- fulgoran-ruin-medium +-- fulgoran-ruin-colossal +-- fulgoran-ruin-stonehenge +-- fulgoran-ruin-vault + +-- if (tree_entity == nil) then return end +-- --Create trees (needs to be done after setting tiles!) +-- for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do +-- for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do +-- local distSqr = math.floor((centerPos.x - i) ^ 2 + (centerPos.y - j) ^ 2) +-- if ((distSqr < tree_radius_sqr_outer) and (distSqr > tree_radius_sqr_inner)) then + +-- local random_tree_index = math.random(1, #tree_entity) +-- local pos = surface.find_non_colliding_position(tree_entity[random_tree_index], { i, j }, 2, 0.5) +-- if (pos ~= nil) then +-- surface.create_entity({ name = tree_entity[random_tree_index], amount = 1, position = pos }) +-- end +-- -- surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } }) +-- end +-- end +-- end diff --git a/lib/oarc_utils.lua b/lib/oarc_utils.lua index 23d9567..183950d 100644 --- a/lib/oarc_utils.lua +++ b/lib/oarc_utils.lua @@ -295,6 +295,18 @@ function TableRemoveOneUsingPairs(t, val) end end +---Gets a random point within a circle of a given radius and center point. +---@param radius number +---@param center MapPosition +---@return MapPosition +function GetRandomPointWithinCircle(radius, center) + local angle = math.random() * 2 * math.pi + local distance = math.random() * radius + local x = center.x + distance * math.cos(angle) + local y = center.y + distance * math.sin(angle) + return {x=x, y=y} +end + -- -- Get a random KEY from a table. -- function GetRandomKeyFromTable(t) -- local keyset = {} @@ -1355,6 +1367,11 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius, fillTile, m local tree_radius_sqr_inner = ((tileRadius - 1 - tree_width) ^ 2) -- 1 less to make sure trees are inside the spawn area local tree_radius_sqr_outer = ((tileRadius - 1) ^ 2) + + local surface_config = storage.ocfg.surfaces_config[surface.name] + local liquid_tile = surface_config.spawn_config.liquid_tile + local fish_enabled = (liquid_tile == "water") + local dirtTiles = {} for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do @@ -1382,10 +1399,10 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius, fillTile, m -- This will leave the tiles "as is" on the left and right of the spawn which has the effect of creating -- land connections if the spawn is on or near land. elseif ((distSqr < moat_radius_sqr) and (distSqr > tile_radius_sqr)) then - table.insert(dirtTiles, { name = "water", position = { i, j } }) + table.insert(dirtTiles, { name = liquid_tile, position = { i, j } }) --5% chance of fish in water - if (math.random(1,20) == 1) then + if fish_enabled and (math.random(1,20) == 1) then surface.create_entity({name="fish", position={i + 0.5, j + 0.5}}) end end @@ -1396,11 +1413,18 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius, fillTile, m surface.set_tiles(dirtTiles) --Create trees (needs to be done after setting tiles!) + local tree_entity = surface_config.spawn_config.tree_entity + if (tree_entity == nil) then return end + for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do local distSqr = math.floor((centerPos.x - i) ^ 2 + (centerPos.y - j) ^ 2) if ((distSqr < tree_radius_sqr_outer) and (distSqr > tree_radius_sqr_inner)) then - surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } }) + local pos = surface.find_non_colliding_position(tree_entity, { i, j }, 2, 0.5) + if (pos ~= nil) then + surface.create_entity({ name = tree_entity, amount = 1, position = pos }) + end + -- surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } }) end end end @@ -1462,6 +1486,7 @@ function CreateCropOctagon(surface, centerPos, chunkArea, tileRadius, fillTile, end surface.set_tiles(dirtTiles) + if (tree_entity == nil) then return end --Create trees (needs to be done after setting tiles!) for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do @@ -1532,6 +1557,7 @@ function CreateCropSquare(surface, centerPos, chunkArea, tileRadius, fillTile, m surface.set_tiles(dirtTiles) + if (tree_entity == nil) then return end --Create trees (needs to be done after setting tiles!) for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do @@ -1578,14 +1604,16 @@ function CreateMoat(surface, centerPos, chunkArea, tileRadius, moatTile, bridge, surface.set_tiles(tiles) end --- Create a horizontal line of water +-- Create a horizontal line of tiles (typically used for water) ---@param surface LuaSurface ---@param leftPos TilePosition ---@param length integer -function CreateWaterStrip(surface, leftPos, length) +---@param tile_name string +---@return nil +function CreateTileStrip(surface, leftPos, length, tile_name) local waterTiles = {} for i = 0, length-1, 1 do - table.insert(waterTiles, { name = "water", position = { leftPos.x + i, leftPos.y } }) + table.insert(waterTiles, { name = tile_name, position = { leftPos.x + i, leftPos.y } }) end surface.set_tiles(waterTiles) end @@ -1620,6 +1648,64 @@ function GenerateResourcePatch(surface, resourceName, diameter, position, amount end end +--- Function to generate a resource patch, of a certain size/amount at a pos. +---@param surface LuaSurface +---@param position MapPosition +---@return nil +function PlaceRandomEntities(surface, position) + local spawn_config = storage.ocfg.surfaces_config[surface.name].spawn_config + local random_entities = spawn_config.random_entities + if (random_entities == nil) then return end + + local tree_width = storage.ocfg.spawn_general.tree_width_tiles + local radius = storage.ocfg.spawn_general.spawn_radius_tiles * spawn_config.radius_modifier - tree_width + + --Iterate through the random entities and place them + for _, entry in pairs(random_entities) do + local entity_name = entry.name + + for i = 1, entry.count do + + local random_pos = GetRandomPointWithinCircle(radius, position) + local open_pos = surface.find_non_colliding_position(entity_name, random_pos, tree_width, 0.5) + + if (open_pos ~= nil) then + surface.create_entity({ + name = entity_name, + position = open_pos + }) + end + end + end +end + +--- Randomly place lightning attractors specific for Fulgora. This should space them out so they don't overlap too much. +---@param surface LuaSurface +---@param position MapPosition +---@return nil +function PlaceFulgoranLightningAttractors(surface, position, count) + local spawn_config = storage.ocfg.surfaces_config[surface.name].spawn_config + local radius = storage.ocfg.spawn_general.spawn_radius_tiles * spawn_config.radius_modifier + + -- HARDCODED FOR NOW + local ATTRACTOR_NAME = "fulgoran-ruin-attractor" + local ATTRACTOR_RADIUS = 20 + + --Iterate through and place them and use the largest available entity + for i = 1, count do + + local random_pos = GetRandomPointWithinCircle(radius, position) + local open_pos = surface.find_non_colliding_position("crash-site-spaceship", random_pos, 1, 0.5) + + if (open_pos ~= nil) then + surface.create_entity({ + name = ATTRACTOR_NAME, + position = open_pos + }) + end + end +end + -- -------------------------------------------------------------------------------- -- -- Holding pen for new players joining the map -- -------------------------------------------------------------------------------- diff --git a/lib/planet_configs/fulgora.lua b/lib/planet_configs/fulgora.lua new file mode 100644 index 0000000..51b0033 --- /dev/null +++ b/lib/planet_configs/fulgora.lua @@ -0,0 +1,34 @@ +-- THIS is used as the default starting items on all surfaces if no other settings are provided! +---@type OarcConfigStartingItems +FULGORA_STARTER_ITEMS = table.deepcopy(NO_STARTER_ITEMS) + +---@type OarcConfigSpawn +FULGORA_SPAWN_CONFIG = table.deepcopy(NAUVIS_SPAWN_CONFIG) +FULGORA_SPAWN_CONFIG.fill_tile = "fulgoran-paving" +FULGORA_SPAWN_CONFIG.liquid_tile = "oil-ocean-deep" +FULGORA_SPAWN_CONFIG.tree_entity = nil +FULGORA_SPAWN_CONFIG.random_entities = { + {name = "fulgoran-ruin-vault", count = 2}, + {name = "fulgoran-ruin-stonehenge", count = 5}, + {name = "fulgoran-ruin-colossal", count = 5}, + {name = "fulgoran-ruin-medium", count = 20}, + {name = "fulgoran-ruin-small", count = 30}, + {name = "fulgurite", count = 20}, + {name = "fulgurite-small", count = 30}, +} +-- I think Fulgora should be smaller in general. +FULGORA_SPAWN_CONFIG.radius_modifier = 0.7 + +FULGORA_SPAWN_CONFIG.solid_resources = +{ + ["scrap"] = { + amount = 10000, + size = 25, + + -- These are only used if not using automatic placing. + x_offset = -29, + y_offset = 16 + } +} + +FULGORA_SPAWN_CONFIG.fluid_resources = { } \ No newline at end of file diff --git a/lib/planet_configs/nauvis.lua b/lib/planet_configs/nauvis.lua new file mode 100644 index 0000000..eb7f055 --- /dev/null +++ b/lib/planet_configs/nauvis.lua @@ -0,0 +1,180 @@ +-- THIS is used as the default starting items on all surfaces if no other settings are provided! +---@type OarcConfigStartingItems +NAUVIS_STARTER_ITEMS = +{ + player_start_items = { + ["iron-plate"] = 8, + ["wood"] = 1, + ["pistol"] = 1, + ["firearm-magazine"] = 10, + ["burner-mining-drill"] = 1, + ["stone-furnace"] = 1 + }, + player_respawn_items = { + ["pistol"] = 1, + ["firearm-magazine"] = 10 + }, + + crashed_ship = true, + crashed_ship_resources = { + ["firearm-magazine"] = 8 -- Max of 5 inventory slots! + }, + crashed_ship_wreakage = { + ["iron-plate"] = 8 -- I don't recommend more than 1 item type here! + }, +} + +-- THIS is used when disabling starter items on a surface? +---@type OarcConfigStartingItems +NO_STARTER_ITEMS = +{ + player_start_items = { }, + player_respawn_items = { + ["pistol"] = 1, + ["firearm-magazine"] = 10 + }, + + crashed_ship = false, + crashed_ship_resources = { + -- ["firearm-magazine"] = 8 -- Max of 5 inventory slots! + }, + crashed_ship_wreakage = { + -- ["iron-plate"] = 8 -- I don't recommend more than 1 item type here! + }, +} + +-- THIS is used as the default spawn config on all surfaces if no other settings are provided! +---@type OarcConfigSpawn +NAUVIS_SPAWN_CONFIG = +{ + -- Used to fill in area that collides with water layer, IF force grass is enabled. + fill_tile = "grass-1", + + -- Used to fill in the moat and the liquid strip at the top of the circle if no moat. + liquid_tile = "water", + + -- Used to circle the base. Set to nil to disable. + tree_entity = "tree-02", + + -- Random entities to place around the base. + random_entities = { + {name = "big-rock", count = 5}, + {name = "huge-rock", count = 5}, + {name = "dead-grey-trunk", count = 5}, + {name = "big-sand-rock", count = 5}, + }, + + -- Used to modify the size of the base. + radius_modifier = 1, + + -- Safe Spawn Area Options + -- The default settings here are balanced for my recommended map gen settings (close to train world). + safe_area = + { + -- Safe area has no aliens + -- This is the radius in chunks of safe area. + safe_radius = 6, + + -- Warning area has significantly reduced aliens + -- This is the radius in chunks of warning area. + warn_radius = 12, + + -- 1 : X (spawners alive : spawners destroyed) in this area + warn_reduction = 20, + + -- Danger area has slightly reduced aliens + -- This is the radius in chunks of danger area. + danger_radius = 32, + + -- 1 : X (spawners alive : spawners destroyed) in this area + danger_reduction = 5, + }, + + -- Location of water strip within the spawn area (2 horizontal rows) + -- The offset is from the TOP (NORTH) of the spawn area. + water = { + x_offset = -4, + y_offset = 10, + length = 8, + }, + + -- Location of shared power pole within the spawn area (if enabled) + -- The offset is from the RIGHT (WEST) of the spawn area. + shared_power_pole_position = { + x_offset=-10, + y_offset=0 + }, + + -- Location of shared chest within the spawn area (if enabled) + -- The offset is from the RIGHT (WEST) of the spawn area. + shared_chest_position = { + x_offset=-10, + y_offset=1 + }, + + -- Solid resource tiles + -- If you are running with mods that add or change resources, you'll want to customize this. + -- Offsets only are applicable if auto placement is disabled. Offsets are from CENTER of spawn area. + solid_resources = { + ["iron-ore"] = { + amount = 1500, + size = 21, + + -- These are only used if not using automatic placing. + x_offset = -29, + y_offset = 16 + }, + ["copper-ore"] = { + amount = 1200, + size = 21, + + -- These are only used if not using automatic placing. + x_offset = -28, + y_offset = -3 + }, + ["stone"] = { + amount = 1200, + size = 21, + + -- These are only used if not using automatic placing. + x_offset = -27, + y_offset = -34 + }, + ["coal"] = { + amount = 1200, + size = 21, + + -- These are only used if not using automatic placing. + x_offset = -27, + y_offset = -20 + } + }, + + -- Fluid resource patches like oil + -- If you are running with mods that add or change resources, you'll want to customize this. + -- The offset is from the BOTTOM (SOUTH) of the spawn area. + fluid_resources = + { + ["crude-oil"] = + { + num_patches = 2, + amount = 900000, + spacing = 6, -- Spacing between each patch, only used for automatic placing. + + -- These are only used if not using automatic placing. + -- Starting position offset (relative to bottom/south of spawn area) + x_offset_start = -3, + y_offset_start = -10, + -- Additional position offsets for each new oil patch (relative to previous oil patch) + x_offset_next = 6, + y_offset_next = 0 + } + }, +} + +---@type OarcConfigSurface +NAUVIS_SURFACE_CONFIG = +{ + starting_items = NAUVIS_STARTER_ITEMS, + spawn_config = NAUVIS_SPAWN_CONFIG +} \ No newline at end of file diff --git a/lib/separate_spawns.lua b/lib/separate_spawns.lua index e514f27..df4b217 100644 --- a/lib/separate_spawns.lua +++ b/lib/separate_spawns.lua @@ -367,7 +367,7 @@ function GenerateStartingResources(surface, position) for i = 1, r_data.num_patches do surface.create_entity({ - name = "crude-oil", + name = r_name, amount = r_data.amount, position = { oil_patch_x, oil_patch_y } }) @@ -416,25 +416,41 @@ function PlaceResourcesInSemiCircle(surface, position, size_mod, amount_mod) local shuffled_list = FYShuffle(r_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 theta = ((angle_final_radians - angle_offset_radians) / (num_resources-1)); - local count = 0 + local radius = storage.ocfg.spawn_general.spawn_radius_tiles * surface_config.spawn_config.radius_modifier - storage.ocfg.resource_placement.distance_to_edge - local radius = storage.ocfg.spawn_general.spawn_radius_tiles - storage.ocfg.resource_placement.distance_to_edge - - for _, r_name in pairs(shuffled_list) do - local angle = (theta * count) + angle_offset_radians; + -- Special case for only one resource, place it in the middle of the semi-circle. + if (num_resources == 1) then + local r_name = shuffled_list[1] + local angle = ((angle_final_radians - angle_offset_radians) / 2) + angle_offset_radians; local tx = (radius * math.cos(angle)) + position.x local ty = (radius * math.sin(angle)) + position.y local pos = { x = math.floor(tx), y = math.floor(ty) } - local resourceConfig = storage.ocfg.surfaces_config[surface.name].spawn_config.solid_resources[r_name] + local resourceConfig = surface_config.spawn_config.solid_resources[r_name] GenerateResourcePatch(surface, r_name, resourceConfig.size * size_mod, pos, resourceConfig.amount * amount_mod) - count = count + 1 + else + local theta = ((angle_final_radians - angle_offset_radians) / (num_resources-1)); + local count = 0 + + + for _, r_name in pairs(shuffled_list) do + local angle = (theta * count) + angle_offset_radians; + + local tx = (radius * math.cos(angle)) + position.x + local ty = (radius * math.sin(angle)) + position.y + + 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) + count = count + 1 + end end end @@ -493,12 +509,14 @@ function SendPlayerToNewSpawnAndCreateIt(delayed_spawn) x = delayed_spawn.position.x, y = delayed_spawn.position.y - storage.ocfg.spawn_general.spawn_radius_tiles } - CreateWaterStrip(game.surfaces[delayed_spawn.surface], + CreateTileStrip(game.surfaces[delayed_spawn.surface], { x = reference_pos.x + water_data.x_offset, y = reference_pos.y + water_data.y_offset }, - water_data.length) - CreateWaterStrip(game.surfaces[delayed_spawn.surface], + water_data.length, + spawn_config.liquid_tile) + CreateTileStrip(game.surfaces[delayed_spawn.surface], { x = reference_pos.x + water_data.x_offset, y = reference_pos.y + water_data.y_offset + 1 }, - water_data.length) + water_data.length, + spawn_config.liquid_tile) end -- Create the spawn resources here @@ -526,10 +544,29 @@ function SendPlayerToNewSpawnAndCreateIt(delayed_spawn) CreateSharedChest(game.surfaces[delayed_spawn.surface], chest_position) end + -- Place randomized entities + if (delayed_spawn.surface == "fulgora") then + PlaceFulgoranLightningAttractors(game.surfaces[delayed_spawn.surface], delayed_spawn.position, 10) + end + + PlaceRandomEntities(game.surfaces[delayed_spawn.surface], delayed_spawn.position) + -- Send the player to that position local player = game.players[delayed_spawn.playerName] SendPlayerToSpawn(delayed_spawn.surface, player, delayed_spawn.primary) - GivePlayerStarterItems(player) + + -- Only primary spawns get starter items and a crashed ship. + if delayed_spawn.primary then + GivePlayerStarterItems(player) + + -- Create crash site if configured + if (ocfg.surfaces_config[delayed_spawn.surface].starting_items.crashed_ship) then + crash_site.create_crash_site(game.surfaces[delayed_spawn.surface], + { x = delayed_spawn.position.x + 15, y = delayed_spawn.position.y - 25 }, + ocfg.surfaces_config[delayed_spawn.surface].starting_items.crashed_ship_resources, + ocfg.surfaces_config[delayed_spawn.surface].starting_items.crashed_ship_wreakage) + end + end -- Render some welcoming text... DisplayWelcomeGroundTextAtSpawn(player, delayed_spawn.surface, delayed_spawn.position) @@ -543,19 +580,13 @@ function SendPlayerToNewSpawnAndCreateIt(delayed_spawn) player.gui.screen.wait_for_spawn_dialog.destroy() end - -- Create crash site if configured - if (ocfg.surfaces_config[delayed_spawn.surface].starting_items.crashed_ship) then - crash_site.create_crash_site(game.surfaces[delayed_spawn.surface], - { x = delayed_spawn.position.x + 15, y = delayed_spawn.position.y - 25 }, - ocfg.surfaces_config[delayed_spawn.surface].starting_items.crashed_ship_resources, - ocfg.surfaces_config[delayed_spawn.surface].starting_items.crashed_ship_wreakage) - end - -- Trigger the event that the spawn was created. script.raise_event("oarc-mod-on-spawn-created", {spawn_data = storage.unique_spawns[delayed_spawn.surface][delayed_spawn.playerName]}) -- Trigger the event that player was spawned too. - script.raise_event("oarc-mod-on-player-spawned", {player_index = player.index}) + if delayed_spawn.primary then + script.raise_event("oarc-mod-on-player-spawned", {player_index = player.index}) + end end ---Displays some welcoming text at the spawn point on the ground. Fades out over time. @@ -623,6 +654,8 @@ function SetupAndClearSpawnAreas(surface, chunkArea) --[[@type OarcConfigSpawnGeneral]] local general_spawn_config = storage.ocfg.spawn_general + local surface_config = storage.ocfg.surfaces_config[surface.name] + local chunkAreaCenter = { x = chunkArea.left_top.x + (CHUNK_SIZE / 2), y = chunkArea.left_top.y + (CHUNK_SIZE / 2) @@ -645,15 +678,15 @@ 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"}, spawn.position, general_spawn_config.spawn_radius_tiles + 5) + RemoveInCircle(surface, chunkArea, {"resource", "cliff", "tree", "lightning-attractor", "simple-entity"}, spawn.position, general_spawn_config.spawn_radius_tiles + 5) elseif (general_spawn_config.shape == SPAWN_SHAPE_CHOICE_SQUARE) then - RemoveInSquare(surface, chunkArea, {"resource", "cliff", "tree"}, spawn.position, general_spawn_config.spawn_radius_tiles + 5) + RemoveInSquare(surface, chunkArea, {"resource", "cliff", "tree", "lightning-attractor", "simple-entity"}, spawn.position, general_spawn_config.spawn_radius_tiles + 5) end -- Fill in the spawn area with landfill and create a circle of trees around it. local fill_tile = "landfill" if general_spawn_config.force_grass then - fill_tile = "grass-1" + fill_tile = surface_config.spawn_config.fill_tile end if (general_spawn_config.shape == SPAWN_SHAPE_CHOICE_CIRCLE) then @@ -661,7 +694,7 @@ function SetupAndClearSpawnAreas(surface, chunkArea) surface, spawn.position, chunkArea, - general_spawn_config.spawn_radius_tiles, + general_spawn_config.spawn_radius_tiles * surface_config.spawn_config.radius_modifier, fill_tile, spawn.moat, storage.ocfg.gameplay.enable_moat_bridging @@ -736,7 +769,7 @@ function DowngradeResourcesDistanceBasedOnChunkGenerate(surface, chunkArea) if (new_amount < 1) then entity.destroy() else - if (entity.name ~= "crude-oil") then + if (entity.prototype.resource_category ~= "basic-fluid") then entity.amount = math.min(new_amount, ore_per_tile_cap) else entity.amount = new_amount