1
0
mirror of https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git synced 2024-12-04 09:43:00 +02:00

Merge pull request #196 from Oarcinae/153-add-a-way-to-configure-primary-spawns-only-allowed-on-a-single-surface-and-secondary-spawns-on-other-surfaces

153 add a way to configure primary spawns only allowed on a single surface and secondary spawns on other surfaces
This commit is contained in:
Oarcinae 2024-10-18 22:27:07 -04:00 committed by GitHub
commit 8a9d7c0f23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 96 additions and 30 deletions

View File

@ -339,7 +339,7 @@ end)
local oarc_mod_interface =
{
get_mod_settings = function()
return OCFG
return global.ocfg
end
}

View File

@ -302,7 +302,7 @@ OCFG = {
-- Default setting for enabling spawning on other surfaces other than the default_surface.
-- This is a STARTUP setting, so it can't be changed in game!!
-- This is a STARTUP setting, so it can't be changed in game!!
default_allow_spawning_on_other_surfaces = true,
default_allow_spawning_on_other_surfaces = false,
-- The name of the main force.
-- This is a STARTUP setting, so it can't be changed in game!!

View File

@ -83,20 +83,24 @@ function CreateSurfaceSettingsSection(container, player)
local surface_table = container.add {
type = "table",
name = "surface_table",
column_count = 3,
column_count = 4,
style = "bordered_table",
}
--- Add the header row
AddLabel(surface_table, nil, {"oarc-settings-tab-surface-column-header"}, "caption_label")
AddLabel(surface_table, nil, {"oarc-settings-tab-surface-spawning-enabled"}, "caption_label")
AddLabel(surface_table, nil, {"oarc-settings-tab-surface-secondary-enabled"}, "caption_label")
AddLabel(surface_table, nil, {"oarc-settings-tab-surface-regrowth-enabled"}, "caption_label")
--- Add the rows
for name, allowed in pairs(global.oarc_surfaces --[[@as table<string, boolean>]]) do
for name, allowed in pairs(global.oarc_surfaces) do
AddLabel(surface_table, nil, name, my_label_style)
AddSurfaceCheckboxSetting(surface_table, name, "spawn_enabled", allowed, player.admin,
AddSurfaceCheckboxSetting(surface_table, name, "spawn_enabled", allowed.primary, player.admin,
{ "oarc-settings-tab-surface-checkbox-tooltip" })
AddSurfaceCheckboxSetting(surface_table, name, "secondary_enabled", allowed.secondary, player.admin,
{ "oarc-settings-tab-surface-secondary-checkbox-tooltip" })
local regrowth_enabled = TableContains(global.rg.active_surfaces, name)
AddSurfaceCheckboxSetting(surface_table, name, "regrowth_enabled", regrowth_enabled, player.admin,
{"oarc-settings-tab-surface-regrowth-checkbox-tooltip"})
@ -540,14 +544,19 @@ function SettingsSurfaceControlsTabGuiClick(event)
if (setting_name == "spawn_enabled") then
local surface_name = gui_elem.tags.surface --[[@as string]]
global.oarc_surfaces[surface_name] = gui_elem.state
global.oarc_surfaces[surface_name].primary = gui_elem.state
if (#GetAllowedSurfaces() == 0) then
log("Warning - GetAllowedSurfaces() - No surfaces found! Forcing default surface!")
global.oarc_surfaces[global.ocfg.gameplay.default_surface] = true
global.oarc_surfaces[global.ocfg.gameplay.default_surface].primary = true
event.element.parent[global.ocfg.gameplay.default_surface.."_spawn_enabled"].state = true
end
elseif (setting_name == "secondary_enabled") then
local surface_name = gui_elem.tags.surface --[[@as string]]
global.oarc_surfaces[surface_name].secondary = gui_elem.state
elseif (setting_name == "regrowth_enabled") then
local surface_name = gui_elem.tags.surface --[[@as string]]

View File

@ -20,7 +20,7 @@ ABANDONED_FORCE_NAME = "_ABANDONED_"
function InitSpawnGlobalsAndForces()
-- Contains a table of entries for each surface. This tracks which surfaces allow spawning?
--[[@type table<string, boolean>]]
--[[@type table<string, OarcSurfaceSpawnSetting>]]
global.oarc_surfaces = {}
for _, surface in pairs(game.surfaces) do
SeparateSpawnsInitSurface(surface.name)
@ -134,11 +134,14 @@ function SeparateSpawnsInitSurface(surface_name)
-- Add the surface to the list of surfaces that allow spawns with value from config.
if global.ocfg.gameplay.default_allow_spawning_on_other_surfaces then
global.oarc_surfaces[surface_name] = true
global.oarc_surfaces[surface_name] = { primary = true, secondary = true }
-- Otherwise only allow the default surface (by default)
else
global.oarc_surfaces[surface_name] = (surface_name == global.ocfg.gameplay.default_surface)
global.oarc_surfaces[surface_name] = {
primary = (surface_name == global.ocfg.gameplay.default_surface),
secondary = false
}
end
-- Make sure it has a surface configuration entry!
@ -213,7 +216,7 @@ function SeparateSpawnsPlayerRespawned(event)
if (player.surface.name == HOLDING_PEN_SURFACE_NAME) then return end
-- If the mod isn't active on this surface, then ignore it.
if (not global.oarc_surfaces[surface_name]) then return end
if (global.oarc_surfaces[surface_name] == nil) then return end
SendPlayerToSpawn(surface_name, player)
GivePlayerRespawnItems(player)
@ -239,16 +242,22 @@ function SeparateSpawnsPlayerChangedSurface(event)
if (not global.ocfg.gameplay.enable_secondary_spawns) then return end
local player = game.players[event.player_index]
local surface_name = player.surface.name
-- Check if player has been init'd yet. If not, then ignore it.
if (global.player_respawns[player.name] == nil) then return end
-- If the mod isn't active on this surface, then ignore it.
if (not global.oarc_surfaces[player.surface.name]) then return end
if (global.oarc_surfaces[surface_name] == nil) then return end
-- If this is their first time on the planet, create a secondary spawn point for them.
-- TODO: Check for buddy and shared spawn hosts?
if (global.unique_spawns[player.surface.name] == nil) or (global.unique_spawns[player.surface.name][player.name] == nil) then
-- If the mod is configured to not allow secondary spawns here, then ignore it.
if (not global.oarc_surfaces[surface_name].secondary) then return end
-- Check if there is already a spawn for them on this surface
-- Could be a buddy spawn, or a shared spawn, or a unique spawn.
local player_spawn = FindPlayerSpawnOnSurface(player.name, surface_name)
if (player_spawn == nil) then
log("WARNING - THIS IS NOT FULLY IMPLEMENTED YET!!")
SecondarySpawn(player, player.surface)
end
@ -793,6 +802,19 @@ function FindPlayerHomeSpawn(player_name)
end
end
---Find the spawn of a player, if one exists, on a specific surface.
---@param player_name string
---@param surface_name string
---@return OarcUniqueSpawn?
function FindPlayerSpawnOnSurface(player_name, surface_name)
if (global.unique_spawns[surface_name] == nil) then return nil end
for _,spawn in pairs(global.unique_spawns[surface_name]) do
if ((spawn.host_name == player_name) or TableContains(spawn.joiners, player_name)) then
return spawn
end
end
end
---Searches all unique spawns for a list of secondary ones for a player.
---@param player_name string
---@return table<string, OarcUniqueSpawn> -- Indexed by surface name!
@ -865,12 +887,10 @@ function CleanupPlayerGlobals(player_name)
for index, joiner in pairs(spawn.joiners) do
if (player_name == joiner) then
global.unique_spawns[surface_index][player_index].joiners[index] = nil
goto LOOP_BREAK -- Nest loop break. Assumes only one entry per player is possible.
end
end
end
end
::LOOP_BREAK::
-- Clear their personal spawn point info
if (global.player_respawns[player_name] ~= nil) then
@ -1274,11 +1294,32 @@ function SecondarySpawn(player, surface)
player.print({ "oarc-no-ungenerated-land-error" })
return
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, false, nil)
-- TODO: Temporary for space age, buddies get a single spawn point for secondary spawns.
if (spawn_choices.buddy) then
SetPlayerRespawn(spawn_choices.buddy, surface.name, spawn_position, false)
-- Add buddy to the shared spawn?
global.unique_spawns[surface.name][player.name].joiners = { spawn_choices.buddy }
log("Buddy secondary spawn NOT IMPLEMENTED YET!")
end
-- -- If it is a buddy spawn, we need to setup both areas TOGETHER
-- if spawn_choices.buddy then
-- -- The x_offset must be big enough to ensure the spawns DO NOT overlap!
-- local x_offset = (global.ocfg.spawn_general.spawn_radius_tiles * 2)
-- if (spawn_choices.moat) then
-- x_offset = x_offset + 10
-- end
-- local buddy_spawn_position = { x = spawn_position.x + x_offset, y = spawn_position.y }
-- SetPlayerRespawn(spawn_choices.buddy, spawn_choices.surface, buddy_spawn_position, true)
-- end
-- Send them to the holding pen
SafeTeleport(player, game.surfaces[HOLDING_PEN_SURFACE_NAME], {x=0,y=0})
@ -1350,7 +1391,7 @@ end
---@param player_name string
---@return boolean
function PlayerHasDelayedSpawn(player_name)
for _,delayedSpawn in pairs(global.delayed_spawns --[[@as OarcDelayedSpawnsTable]]) do
for _,delayedSpawn in pairs(global.delayed_spawns) do
if (delayedSpawn.playerName == player_name) then
return true
end
@ -1358,13 +1399,13 @@ function PlayerHasDelayedSpawn(player_name)
return false
end
---Get the list of surfaces that are allowed for spawning.
---Get the list of surfaces that are allowed for primary spawning.
---@return string[]
function GetAllowedSurfaces()
---@type string[]
local surfaceList = {}
for surfaceName,allowed in pairs(global.oarc_surfaces --[[@as table<string, boolean>]]) do
if allowed then
for surfaceName, allowed in pairs(global.oarc_surfaces) do
if allowed.primary then
table.insert(surfaceList, surfaceName)
end
end
@ -1475,7 +1516,18 @@ SPAWN_TEAM_CHOICE = {
---@alias OarcDelayedSpawnsTable table<string, OarcDelayedSpawn>
---This contains the spawn choices for a player in the spawn menu.
---@alias OarcSpawnChoices { surface: string, team: SpawnTeamChoice, moat: boolean, buddy: string?, distance: integer, host: string?, buddy_team: boolean }
---Class representing the spawn choices for a player in the spawn menu.
---@class OarcSpawnChoices
---@field surface string The surface on which the player wants to spawn.
---@field team SpawnTeamChoice The team choice for the player. Main team or own team.
---@field moat boolean Whether the player wants a moat around their spawn.
---@field buddy string? The buddy player name if the player wants to spawn with a buddy.
---@field distance integer The distance from the center of the map where the player wants to spawn.
---@field host string? The host player name if the player wants to join a shared spawn.
---@field buddy_team boolean Whether the player wants to join a buddy's team. This means both players will be on the same team.
---Table of [OarcSpawnChoices](lua://OarcSpawnChoices) indexed by player name.
---@alias OarcSpawnChoicesTable table<string, OarcSpawnChoices>
---Primary means a player can spawn for the first time on this surface, secondary they can land here and also receive a custom spawn area.
---@alias OarcSurfaceSpawnSetting { primary: boolean, secondary: boolean}

View File

@ -1122,7 +1122,10 @@ function AcceptBuddyRequest(player, requesting_buddy_name)
local requesting_buddy = game.players[requesting_buddy_name]
local surface = game.surfaces[spawn_choices.surface]
global.spawn_choices[player.name].host = nil -- N/A for buddy spawns so clear it.
-- Copy the buddy's spawn choices to the accepting player
spawn_choices.host = nil -- N/A for buddy spawns so clear it.
global.spawn_choices[player.name] = table.deepcopy(spawn_choices)
global.spawn_choices[player.name].buddy = requesting_buddy_name
-- Find coordinates of a good place to spawn
local spawn_position = FindUngeneratedCoordinates(surface, spawn_choices.distance, 3)
@ -1159,12 +1162,12 @@ function AcceptBuddyRequest(player, requesting_buddy_name)
x_offset = x_offset + 10
end
buddySpawn = { x = spawn_position.x + x_offset, y = spawn_position.y }
SetPlayerRespawn(player.name, spawn_choices.surface, spawn_position, true)
SetPlayerRespawn(requesting_buddy_name, spawn_choices.surface, buddySpawn, true)
SetPlayerRespawn(player.name, spawn_choices.surface, buddySpawn, true)
SetPlayerRespawn(requesting_buddy_name, spawn_choices.surface, spawn_position, true)
-- Send the player there
QueuePlayerForDelayedSpawn(player.name, spawn_choices.surface, spawn_position, spawn_choices.moat, true, requesting_buddy_name)
QueuePlayerForDelayedSpawn(requesting_buddy_name, spawn_choices.surface, buddySpawn, spawn_choices.moat, true, player.name)
QueuePlayerForDelayedSpawn(player.name, spawn_choices.surface, buddySpawn, spawn_choices.moat, true, requesting_buddy_name)
QueuePlayerForDelayedSpawn(requesting_buddy_name, spawn_choices.surface, spawn_position, spawn_choices.moat, true, player.name)
SendBroadcastMsg({"", {"oarc-buddies-are-joining", requesting_buddy_name, player.name, spawn_choices.surface}, " ", GetGPStext(spawn_choices.surface, spawn_position)})
-- Unlock spawn control gui tab

View File

@ -221,9 +221,11 @@ oarc-settings-tab-description=This tab contains the same mod settings in the mod
oarc-settings-tab-text-field-enter-tooltip=[color=red]You must press ENTER after typing in a text field to save the value![/color]
oarc-settings-tab-title-surface=Surface Settings
oarc-settings-tab-surface-checkbox-tooltip=Enabling this will allow custom spawn areas (the main feature of this mod) on this surface. You need at least one of these enabled for the mod to work.
oarc-settings-tab-surface-secondary-checkbox-tooltip=Enabling this will give players custom secondary spawns when they first travel to this surface. [color=red]This feature is currently a work in progress.[/color]
oarc-settings-tab-surface-regrowth-checkbox-tooltip=Enabling this will allow the regrowth and world eater features to work on this surface, if those are enabled.
oarc-settings-tab-surface-column-header=Surface
oarc-settings-tab-surface-spawning-enabled=Custom Spawns
oarc-settings-tab-surface-spawning-enabled=Home
oarc-settings-tab-surface-secondary-enabled=Secondary
oarc-settings-tab-surface-regrowth-enabled=Regrowth
oarc-settings-tab-title-export=Import/Export Settings
oarc-settings-tab-export-button=Export