mirror of
https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git
synced 2024-12-04 09:43:00 +02:00
Improving GUI internal logic and user experience (shared spawns now auto refresh)
This commit is contained in:
parent
42ad29a6f0
commit
60fba766a1
14
control.lua
14
control.lua
@ -262,6 +262,20 @@ script.on_event(defines.events.on_gui_closed, function(event)
|
||||
end)
|
||||
|
||||
|
||||
--- For sliders and other value changing elements.
|
||||
script.on_event(defines.events.on_gui_value_changed, function(event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
|
||||
SeparateSpawnsGuiValueChanged(event)
|
||||
end)
|
||||
|
||||
--- For dropdowns and listboxes.
|
||||
script.on_event(defines.events.on_gui_selection_state_changed, function(event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
|
||||
SeparateSpawnsGuiSelectionStateChanged(event)
|
||||
end)
|
||||
|
||||
--on_gui_checked_state_changed Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
|
||||
--on_gui_click Called when LuaGuiElement is clicked.
|
||||
--on_gui_closed Called when the player closes the GUI they have open. [...]
|
||||
|
11
devplan.txt
11
devplan.txt
@ -1,6 +1,9 @@
|
||||
|
||||
ACTIVE ITEM:
|
||||
11. Change Near/Far buttons to radio selection w/ text explanation and have a single Spawn button.
|
||||
ACTIVE ITEMS:
|
||||
22. Remove separate buddy spawn menu?
|
||||
23. Refresh the spawn controls GUI when player accepts/rejects
|
||||
24. Remove the shared spawn separate GUI window?
|
||||
|
||||
|
||||
10. Tooltips for GUI elements in spawn menu options!
|
||||
13. Add regrowth settings GUI tab? Not sure how the other settings fit in with a dedicated regrowth tab? Need to be able to enable/disable other surfaces during runtime?
|
||||
@ -11,6 +14,7 @@ ACTIVE ITEM:
|
||||
19. Support run time toggling of main_force_name
|
||||
20. Force enable_world_eater to require enable_regrowth
|
||||
|
||||
|
||||
Other Ideas, Not Committed:
|
||||
- Add option to spawn on existing chunks (look for chunks with any entities in them, or use regrowth logic)
|
||||
- Add option for spawn pen to be on a specified surface
|
||||
@ -37,3 +41,6 @@ Other Ideas, Not Committed:
|
||||
8. Check and update all functions using surfaces to clearly use either the LuaSurface obj OR a string name.
|
||||
9. Create server settings admin GUI tab
|
||||
15. Figure out how to define custom lua table/data structs to make syntax/linting work?
|
||||
23. Setup multiplayer testing using multiple instances and some batch files.
|
||||
11. Change Near/Far buttons to radio selection w/ text explanation and have a single Spawn button.
|
||||
21. Refactor the spawn menu GUI (don't destroy the menu unless we need to, refresh only the elements we need to, save data to a global using tags?)
|
@ -111,6 +111,11 @@ function SpawnCtrlGuiOptionsSelect(event)
|
||||
end
|
||||
end
|
||||
FakeTabChangeEventOarcGui(player)
|
||||
|
||||
-- Refresh the shared spawn spawn gui for all players
|
||||
for _,p in pairs(game.connected_players) do
|
||||
RefreshSharedSpawnFrameIfExist(p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,6 +98,11 @@ function InitSpawnGlobalsAndForces()
|
||||
global.ocore.delayedSpawns --[[@as OarcDelayedSpawnsTable]] = {}
|
||||
end
|
||||
|
||||
-- This temporarily stores the spawn choices that a player makes from the GUI interactions.
|
||||
if (global.ocore.spawnChoices == nil) then
|
||||
global.ocore.spawnChoices --[[@as OarcSpawnChoicesTable]] = {}
|
||||
end
|
||||
|
||||
-- This is what I use to communicate a buddy spawn request between the buddies.
|
||||
-- This contains information of who is asking, and what options were selected.
|
||||
if (global.ocore.buddySpawnOpts == nil) then
|
||||
@ -715,7 +720,7 @@ end
|
||||
---Cleans up a player's unique spawn point.
|
||||
---TODO: Move relevant stuff to regrowth?
|
||||
---@param playerName string
|
||||
---@param cleanup boolean
|
||||
---@param cleanup boolean Marks the chunks for cleanup by the regrowth mod.
|
||||
---@param immediate boolean Trrigger cleanup immediately.
|
||||
---@return nil
|
||||
function UniqueSpawnCleanupRemove(playerName, cleanup, immediate)
|
||||
@ -727,11 +732,12 @@ function UniqueSpawnCleanupRemove(playerName, cleanup, immediate)
|
||||
local spawnPos = spawn.position
|
||||
local spawn_radius_tiles = global.ocfg.surfaces_config[spawn.surface].spawn_config.general.spawn_radius_tiles
|
||||
|
||||
-- Check if it was near someone else's base. (Really just buddy base is possible I think.)
|
||||
-- Check if it was near someone else's base. (Really just buddy base is possible I think?)
|
||||
nearOtherSpawn = false
|
||||
for spawnPlayerName, otherSpawnPos in pairs(global.ocore.uniqueSpawns) do
|
||||
if ((spawnPlayerName ~= playerName) and
|
||||
(util.distance(spawnPos, otherSpawnPos.pos) < (spawn_radius_tiles * 3))) then
|
||||
for spawnPlayerName, otherSpawnPos in pairs(global.ocore.uniqueSpawns --[[@as OarcUniqueSpawnsTable]]) do
|
||||
if ((spawn.surface == otherSpawnPos.surface) and
|
||||
(spawnPlayerName ~= playerName) and
|
||||
(util.distance(spawnPos, otherSpawnPos.position) < (spawn_radius_tiles * 3))) then
|
||||
log("Won't remove base as it's close to another spawn: " .. spawnPlayerName)
|
||||
nearOtherSpawn = true
|
||||
end
|
||||
@ -1147,6 +1153,19 @@ function PlayerHasDelayedSpawn(player_name)
|
||||
return false
|
||||
end
|
||||
|
||||
---Get the list of surfaces that are allowed for spawning.
|
||||
---@return string[]
|
||||
function GetAllowedSurfaces()
|
||||
---@type string[]
|
||||
local surfaceList = {}
|
||||
for surfaceName,allowed in pairs(global.ocore.surfaces --[[@as table<string, boolean>]]) do
|
||||
if allowed then
|
||||
table.insert(surfaceList, surfaceName)
|
||||
end
|
||||
end
|
||||
return surfaceList
|
||||
end
|
||||
|
||||
--[[
|
||||
___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
|
||||
| __|/ _ \ | _ \ / __|| __| / __|| _ \| __|/ __||_ _|| __||_ _|/ __|
|
||||
@ -1349,8 +1368,8 @@ end
|
||||
You can ignore this unless you're making changes to the mod, in which case it might be helpful.
|
||||
]]
|
||||
|
||||
---@enum BuddySpawnChoice
|
||||
BUDDY_SPAWN_CHOICE = {
|
||||
---@enum SpawnTeamChoice
|
||||
SPAWN_TEAM_CHOICE = {
|
||||
join_main_team = 1,
|
||||
join_own_team = 2,
|
||||
join_buddy_team = 3,
|
||||
@ -1382,9 +1401,14 @@ BUDDY_SPAWN_CHOICE = {
|
||||
---@alias OarcDelayedSpawnsTable table<string, OarcDelayedSpawn>
|
||||
|
||||
---This contains information of who is being asked to buddy spawn, and what options were selected.
|
||||
---@alias OarcBuddySpawnOpts { surface: string, teamRadioSelection: BuddySpawnChoice, moatChoice: boolean, buddyChoice: string, distChoice: string }
|
||||
---@alias OarcBuddySpawnOpts { surface: string, teamRadioSelection: SpawnTeamChoice, moatChoice: boolean, buddyChoice: string, distChoice: string }
|
||||
---Table of [OarcBuddySpawnOpts](lua://OarcBuddySpawnOpts) indexed by player name.
|
||||
---@alias OarcBuddySpawnOptsTable table<string, OarcBuddySpawnOpts>
|
||||
|
||||
---This contains the spawn choices for a player in the spawn menu.
|
||||
---@alias OarcSpawnChoices { surface: string, team: SpawnTeamChoice, moat: boolean, buddy: string?, distance: integer }
|
||||
---Table of [OarcSpawnChoices](lua://OarcSpawnChoices) indexed by player name.
|
||||
---@alias OarcSpawnChoicesTable table<string, OarcSpawnChoices>
|
||||
|
||||
---Table of players in the "waiting room" for a buddy spawn.
|
||||
---@alias OarcWaitingBuddiesTable table<integer, string>
|
||||
|
@ -74,6 +74,212 @@ function WelcomeTextGuiClick(event)
|
||||
end
|
||||
end
|
||||
|
||||
---Creates the spawn options gui frame to hold all the spawn options.
|
||||
---@param player LuaPlayer
|
||||
---@return LuaGuiElement
|
||||
function CreateSpawnOptionsGuiFrame(player)
|
||||
local spawn_opts_gui = player.gui.screen.add {
|
||||
name = "spawn_opts",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
caption = { "oarc-spawn-options" }
|
||||
}
|
||||
spawn_opts_gui.style.maximal_width = SPAWN_GUI_MAX_WIDTH
|
||||
spawn_opts_gui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT
|
||||
spawn_opts_gui.auto_center = true
|
||||
return spawn_opts_gui
|
||||
end
|
||||
|
||||
---Show the surface select dropdown
|
||||
---@param parent_flow LuaGuiElement
|
||||
---@return nil
|
||||
function ShowSurfaceSelectDropdown(parent_flow)
|
||||
local surfacesHorizontalFlow = parent_flow.add {
|
||||
name = "surfaces_horizontal_flow",
|
||||
type = "flow",
|
||||
direction = "horizontal"
|
||||
}
|
||||
|
||||
local surface_list = GetAllowedSurfaces()
|
||||
|
||||
AddLabel(surfacesHorizontalFlow, "surfacesHorizontalFlowLabel", "Select Surface: ", my_label_style)
|
||||
surfacesHorizontalFlow.add {
|
||||
name = "surface_select_dropdown",
|
||||
tags = { action = "oarc_spawn_options", setting = "surface_select" },
|
||||
type = "drop-down",
|
||||
items = surface_list,
|
||||
selected_index = 1
|
||||
}
|
||||
end
|
||||
|
||||
---Display the team select radio buttons
|
||||
---@param parent_flow LuaGuiElement
|
||||
---@param enable_separate_teams boolean
|
||||
---@param enable_buddy_spawn boolean
|
||||
---@return nil
|
||||
function DisplayTeamSelectRadioButtons(parent_flow, enable_separate_teams, enable_buddy_spawn)
|
||||
|
||||
local main_team_radio = parent_flow.add {
|
||||
name = "isolated_spawn_main_team_radio",
|
||||
tags = { action = "oarc_spawn_options", setting = "team_select", value = SPAWN_TEAM_CHOICE.join_main_team },
|
||||
type = "radiobutton",
|
||||
caption = { "oarc-join-main-team-radio" },
|
||||
state = true
|
||||
}
|
||||
|
||||
if (enable_separate_teams) then
|
||||
parent_flow.add {
|
||||
name = "isolated_spawn_new_team_radio",
|
||||
tags = { action = "oarc_spawn_options", setting = "team_select", value = SPAWN_TEAM_CHOICE.join_own_team },
|
||||
type = "radiobutton",
|
||||
caption = { "oarc-create-own-team-radio" },
|
||||
state = false
|
||||
}
|
||||
if (enable_buddy_spawn) then
|
||||
parent_flow.add {
|
||||
name = "isolated_spawn_buddy_team_radio",
|
||||
tags = { action = "oarc_spawn_options", setting = "team_select", value = SPAWN_TEAM_CHOICE.join_buddy_team },
|
||||
type = "radiobutton",
|
||||
caption = { "oarc-create-buddy-team" },
|
||||
state = false
|
||||
}
|
||||
end
|
||||
else
|
||||
-- If separate teams are not enabled, default to joining the main team, and disable the radio buttons.
|
||||
main_team_radio.ignored_by_interaction = true
|
||||
end
|
||||
end
|
||||
|
||||
---Create a distance select slider
|
||||
---@param parent_flow LuaGuiElement
|
||||
---@param minimum_distance number
|
||||
---@param maximum_distance number
|
||||
---@return nil
|
||||
function CreateDistanceSelectSlider(parent_flow, minimum_distance, maximum_distance)
|
||||
local sliderFlow = parent_flow.add { name = "spawn_distance_slider_flow",
|
||||
type = "flow",
|
||||
direction = "horizontal",
|
||||
style = "player_input_horizontal_flow"
|
||||
}
|
||||
sliderFlow.style.horizontal_align = "center"
|
||||
sliderFlow.add { name = "spawn_distance_slider_label",
|
||||
type = "label",
|
||||
caption = "test" }
|
||||
sliderFlow.add { name = "spawn_distance_slider",
|
||||
type = "slider",
|
||||
tags = { action = "oarc_spawn_options", setting = "distance_select" },
|
||||
minimum_value = minimum_distance,
|
||||
maximum_value = maximum_distance,
|
||||
value = minimum_distance,
|
||||
discrete_slider = true,
|
||||
value_step = 1,
|
||||
}
|
||||
sliderFlow.add { name = "spawn_distance_slider_value",
|
||||
type = "textfield",
|
||||
ignored_by_interaction = true,
|
||||
caption = minimum_distance,
|
||||
style = "slider_value_textfield",
|
||||
text = tostring(minimum_distance)
|
||||
}
|
||||
end
|
||||
|
||||
---Create a confim button for player to request spawn creation
|
||||
---@param parent_flow LuaGuiElement
|
||||
---@return nil
|
||||
function CreateSpawnRequestButton(parent_flow)
|
||||
local spawnRequestFlow = parent_flow.add {
|
||||
name = "spawn_request_flow",
|
||||
type = "flow",
|
||||
direction = "horizontal"
|
||||
}
|
||||
spawnRequestFlow.style.horizontal_align = "right"
|
||||
spawnRequestFlow.style.horizontally_stretchable = true
|
||||
spawnRequestFlow.add {
|
||||
name = "spawn_request",
|
||||
tags = { action = "oarc_spawn_options", setting = "spawn_request" },
|
||||
type = "button",
|
||||
caption = { "oarc-solo-spawn-near" },
|
||||
style = "confirm_button"
|
||||
}
|
||||
end
|
||||
|
||||
---Creates the shared spawn frame for joining another player's base
|
||||
---@param parent_flow LuaGuiElement
|
||||
---@param enable_shared_spawns boolean
|
||||
---@return nil
|
||||
function CreateSharedSpawnFrame(parent_flow, enable_shared_spawns)
|
||||
|
||||
local sharedSpawnFrame = parent_flow.spawn_shared_flow
|
||||
if sharedSpawnFrame == nil then
|
||||
sharedSpawnFrame = parent_flow.add {
|
||||
name = "spawn_shared_flow",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "bordered_frame"
|
||||
}
|
||||
--- Let's us refresh the frame if it already exists
|
||||
else
|
||||
for _,child in pairs(sharedSpawnFrame.children) do
|
||||
child.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
if enable_shared_spawns then
|
||||
local numAvailSpawns = GetNumberOfAvailableSharedSpawns()
|
||||
if (numAvailSpawns > 0) then
|
||||
sharedSpawnFrame.add {
|
||||
name = "join_other_spawn",
|
||||
tags = { action = "oarc_spawn_options", setting = "join_other_spawn" },
|
||||
type = "button",
|
||||
caption = { "oarc-join-someone-avail", numAvailSpawns }
|
||||
}
|
||||
local join_spawn_text = { "oarc-join-someone-info" }
|
||||
AddLabel(sharedSpawnFrame, "join_other_spawn_lbl1", join_spawn_text, my_label_style)
|
||||
else
|
||||
AddLabel(sharedSpawnFrame, "join_other_spawn_lbl1", { "oarc-no-shared-avail" }, my_label_style)
|
||||
sharedSpawnFrame.add {
|
||||
name = "join_other_spawn_check",
|
||||
type = "button",
|
||||
caption = { "oarc-join-check-again" }
|
||||
}
|
||||
end
|
||||
else
|
||||
AddLabel(sharedSpawnFrame, "join_other_spawn_lbl1", { "oarc-shared-spawn-disabled" }, my_warning_style)
|
||||
end
|
||||
end
|
||||
|
||||
---Refresh the shared spawn frame if it exists
|
||||
---@param player LuaPlayer
|
||||
---@return nil
|
||||
function RefreshSharedSpawnFrameIfExist(player)
|
||||
local spawn_opts = player.gui.screen.spawn_opts
|
||||
if spawn_opts == nil then return end
|
||||
CreateSharedSpawnFrame(spawn_opts, global.ocfg.gameplay.enable_shared_spawns)
|
||||
end
|
||||
|
||||
---Creates the buddy spawn frame for spawning with a buddy
|
||||
---@param parent_flow LuaGuiElement
|
||||
---@return nil
|
||||
function CreateBuddySpawnFrame(parent_flow, enable_buddy_spawn)
|
||||
if enable_buddy_spawn then -- TODO: Confirm if this must also require enable_shared_spawns!!
|
||||
local buddySpawnFrame = parent_flow.add {
|
||||
name = "spawn_buddy_flow",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "bordered_frame"
|
||||
}
|
||||
|
||||
-- AddSpacerLine(buddySpawnFrame, "buddy_spawn_msg_spacer")
|
||||
buddySpawnFrame.add {
|
||||
name = "buddy_spawn",
|
||||
type = "button",
|
||||
caption = { "oarc-buddy-spawn" }
|
||||
}
|
||||
AddLabel(buddySpawnFrame, "buddy_spawn_lbl1", { "oarc-buddy-spawn-info" }, my_label_style)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Display the spawn options and explanation
|
||||
---@param player LuaPlayer
|
||||
---@return nil
|
||||
@ -88,88 +294,50 @@ function DisplaySpawnOptions(player)
|
||||
return
|
||||
end
|
||||
|
||||
-- Get gameplay settings from config
|
||||
local gameplay = global.ocfg.gameplay
|
||||
|
||||
player.gui.screen.add { name = "spawn_opts",
|
||||
-- Create the primary frame and a warning label
|
||||
local sGui = CreateSpawnOptionsGuiFrame(player)
|
||||
AddLabel(sGui, "warning_lbl1", { "oarc-click-info-btn-help" }, my_warning_style)
|
||||
|
||||
-- Create the default settings entry for the OarcSpawnChoices table
|
||||
---@type OarcSpawnChoices
|
||||
local spawn_choices_entry = {
|
||||
surface = global.ocfg.gameplay.default_surface,
|
||||
team = SPAWN_TEAM_CHOICE.join_main_team,
|
||||
moat = false,
|
||||
buddy = nil,
|
||||
distance = global.ocfg.gameplay.near_spawn_distance
|
||||
}
|
||||
global.ocore.spawnChoices[player.name] = spawn_choices_entry
|
||||
|
||||
-- Holds the main spawn options
|
||||
local soloSpawnFlow = sGui.add {
|
||||
name = "spawn_solo_flow",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
caption = { "oarc-spawn-options" } }
|
||||
local sGui = player.gui.screen.spawn_opts
|
||||
sGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH
|
||||
sGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT
|
||||
sGui.auto_center = true
|
||||
|
||||
-- Warnings and explanations...
|
||||
local warn_msg = { "oarc-click-info-btn-help" }
|
||||
AddLabel(sGui, "warning_lbl1", warn_msg, my_warning_style)
|
||||
|
||||
-- TODO: Not sure what this is for...? SPAWN_MSG1 is not defined anywhere.
|
||||
-- AddLabel(sGui, "spawn_msg_lbl1", SPAWN_MSG1, my_label_style)
|
||||
|
||||
-- Button and message about the regular vanilla spawn
|
||||
-- if ENABLE_DEFAULT_SPAWN then
|
||||
-- sGui.add{name = "default_spawn_btn",
|
||||
-- type = "button",
|
||||
-- caption={"oarc-vanilla-spawn"}}
|
||||
-- local normal_spawn_text = {"oarc-default-spawn-behavior"}
|
||||
-- AddLabel(sGui, "normal_spawn_lbl1", normal_spawn_text, my_label_style)
|
||||
-- -- AddSpacerLine(sGui, "normal_spawn_spacer")
|
||||
-- end
|
||||
|
||||
-- The main spawning options. Solo near and solo far.
|
||||
-- If enable, you can also choose to be on your own team.
|
||||
local soloSpawnFlow = sGui.add { name = "spawn_solo_flow",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "bordered_frame" }
|
||||
|
||||
style = "bordered_frame"
|
||||
}
|
||||
|
||||
-- Pick surface
|
||||
if (gameplay.enable_spawning_on_other_surfaces) then
|
||||
|
||||
local surfacesHorizontalFlow = soloSpawnFlow.add { name = "surfaces_horizontal_flow",
|
||||
type = "flow",
|
||||
direction = "horizontal" }
|
||||
|
||||
---@type string[]
|
||||
local surfaceList = {}
|
||||
for surfaceName,allowed in pairs(global.ocore.surfaces) do
|
||||
if allowed then
|
||||
table.insert(surfaceList, surfaceName)
|
||||
end
|
||||
end
|
||||
|
||||
AddLabel(surfacesHorizontalFlow, "surfacesHorizontalFlowLabel", "Select Surface: ", my_label_style)
|
||||
surfacesHorizontalFlow.add { name = "surface_select_dropdown",
|
||||
type = "drop-down",
|
||||
items = surfaceList,
|
||||
selected_index = 1}
|
||||
ShowSurfaceSelectDropdown(soloSpawnFlow)
|
||||
end
|
||||
|
||||
-- Radio buttons to pick your team.
|
||||
if (gameplay.enable_separate_teams) then
|
||||
soloSpawnFlow.add { name = "isolated_spawn_main_team_radio",
|
||||
type = "radiobutton",
|
||||
caption = { "oarc-join-main-team-radio" },
|
||||
state = true }
|
||||
soloSpawnFlow.add { name = "isolated_spawn_new_team_radio",
|
||||
type = "radiobutton",
|
||||
caption = { "oarc-create-own-team-radio" },
|
||||
state = false }
|
||||
end
|
||||
|
||||
-- OPTIONS frame
|
||||
-- AddLabel(soloSpawnFlow, "options_spawn_lbl1",
|
||||
-- "Additional spawn options can be selected here. Not all are compatible with each other.", my_label_style)
|
||||
DisplayTeamSelectRadioButtons(soloSpawnFlow, gameplay.enable_separate_teams, gameplay.enable_buddy_spawn)
|
||||
|
||||
-- Allow players to spawn with a moat around their area.
|
||||
--TODO: Vanilla spawn points are not implemented yet.
|
||||
-- and not global.ocfg.enable_vanilla_spawns
|
||||
if (gameplay.allow_moats_around_spawns) then
|
||||
soloSpawnFlow.add { name = "isolated_spawn_moat_option_checkbox",
|
||||
soloSpawnFlow.add {
|
||||
name = "isolated_spawn_moat_option_checkbox",
|
||||
type = "checkbox",
|
||||
caption = { "oarc-moat-option" },
|
||||
state = false }
|
||||
state = false
|
||||
}
|
||||
end
|
||||
-- if (global.ocfg.enable_vanilla_spawns and (TableLength(global.vanillaSpawns) > 0)) then
|
||||
-- soloSpawnFlow.add{name = "isolated_spawn_vanilla_option_checkbox",
|
||||
@ -178,44 +346,11 @@ function DisplaySpawnOptions(player)
|
||||
-- state=false}
|
||||
-- end
|
||||
|
||||
local sliderFlow = soloSpawnFlow.add { name = "spawn_distance_slider_flow",
|
||||
type = "flow",
|
||||
direction = "horizontal",
|
||||
style = "player_input_horizontal_flow"
|
||||
}
|
||||
sliderFlow.style.horizontal_align = "center"
|
||||
sliderFlow.add { name = "spawn_distance_slider_label",
|
||||
type = "label",
|
||||
caption = "test" }
|
||||
sliderFlow.add { name = "spawn_distance_slider",
|
||||
type = "slider",
|
||||
minimum_value = global.ocfg.gameplay.near_spawn_distance,
|
||||
maximum_value = global.ocfg.gameplay.far_spawn_distance,
|
||||
value = global.ocfg.gameplay.near_spawn_distance,
|
||||
discrete_slider = true,
|
||||
value_step = 1
|
||||
}
|
||||
sliderFlow.add { name = "spawn_distance_slider_value",
|
||||
type = "textfield",
|
||||
ignored_by_interaction = true,
|
||||
caption = global.ocfg.gameplay.near_spawn_distance,
|
||||
style = "slider_value_textfield"
|
||||
}
|
||||
CreateDistanceSelectSlider(soloSpawnFlow, gameplay.near_spawn_distance, gameplay.far_spawn_distance)
|
||||
|
||||
-- The confirm button to request a spawn
|
||||
CreateSpawnRequestButton(soloSpawnFlow)
|
||||
|
||||
-- Isolated spawn options. The core gameplay of this scenario.
|
||||
local soloSpawnbuttons = soloSpawnFlow.add { name = "spawn_solo_flow",
|
||||
type = "flow",
|
||||
direction = "horizontal" }
|
||||
soloSpawnbuttons.style.horizontal_align = "center"
|
||||
soloSpawnbuttons.style.horizontally_stretchable = true
|
||||
soloSpawnbuttons.add { name = "isolated_spawn_near",
|
||||
type = "button",
|
||||
caption = { "oarc-solo-spawn-near" },
|
||||
style = "confirm_button" }
|
||||
soloSpawnbuttons.add { name = "isolated_spawn_far",
|
||||
type = "button",
|
||||
caption = { "oarc-solo-spawn-far" },
|
||||
style = "confirm_button" }
|
||||
|
||||
-- if (global.ocfg.enable_vanilla_spawns) then
|
||||
-- AddLabel(soloSpawnFlow, "isolated_spawn_lbl1",
|
||||
@ -223,50 +358,16 @@ function DisplaySpawnOptions(player)
|
||||
-- AddLabel(soloSpawnFlow, "vanilla_spawn_lbl2",
|
||||
-- {"oarc-vanilla-spawns-available", TableLength(global.vanillaSpawns)}, my_label_style)
|
||||
-- else
|
||||
AddLabel(soloSpawnFlow, "isolated_spawn_lbl1",
|
||||
{ "oarc-starting-area-normal" }, my_label_style)
|
||||
AddLabel(soloSpawnFlow, "isolated_spawn_lbl1", { "oarc-starting-area-normal" }, my_label_style)
|
||||
-- end
|
||||
|
||||
-- Spawn options to join another player's base.
|
||||
local sharedSpawnFrame = sGui.add { name = "spawn_shared_flow",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "bordered_frame" }
|
||||
if gameplay.enable_shared_spawns then
|
||||
local numAvailSpawns = GetNumberOfAvailableSharedSpawns()
|
||||
if (numAvailSpawns > 0) then
|
||||
sharedSpawnFrame.add { name = "join_other_spawn",
|
||||
type = "button",
|
||||
caption = { "oarc-join-someone-avail", numAvailSpawns } }
|
||||
local join_spawn_text = { "oarc-join-someone-info" }
|
||||
AddLabel(sharedSpawnFrame, "join_other_spawn_lbl1", join_spawn_text, my_label_style)
|
||||
else
|
||||
AddLabel(sharedSpawnFrame, "join_other_spawn_lbl1", { "oarc-no-shared-avail" }, my_label_style)
|
||||
sharedSpawnFrame.add { name = "join_other_spawn_check",
|
||||
type = "button",
|
||||
caption = { "oarc-join-check-again" } }
|
||||
end
|
||||
else
|
||||
AddLabel(sharedSpawnFrame, "join_other_spawn_lbl1",
|
||||
{ "oarc-shared-spawn-disabled" }, my_warning_style)
|
||||
end
|
||||
CreateSharedSpawnFrame(sGui, gameplay.enable_shared_spawns)
|
||||
|
||||
-- Awesome buddy spawning system
|
||||
---TODO: Vanilla spawn points are not implemented yet.
|
||||
-- if (not global.ocfg.enable_vanilla_spawns) then
|
||||
if gameplay.enable_shared_spawns and gameplay.enable_buddy_spawn then
|
||||
local buddySpawnFrame = sGui.add { name = "spawn_buddy_flow",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "bordered_frame" }
|
||||
|
||||
-- AddSpacerLine(buddySpawnFrame, "buddy_spawn_msg_spacer")
|
||||
buddySpawnFrame.add { name = "buddy_spawn",
|
||||
type = "button",
|
||||
caption = { "oarc-buddy-spawn" } }
|
||||
AddLabel(buddySpawnFrame, "buddy_spawn_lbl1",
|
||||
{ "oarc-buddy-spawn-info" }, my_label_style)
|
||||
end
|
||||
CreateBuddySpawnFrame(sGui, gameplay.enable_buddy_spawn)
|
||||
-- end
|
||||
|
||||
-- Some final notes
|
||||
@ -280,28 +381,147 @@ function DisplaySpawnOptions(player)
|
||||
AddLabel(sGui, "note_lbl1", spawn_distance_notes, my_note_style)
|
||||
end
|
||||
|
||||
|
||||
---This just updates the radio buttons/checkboxes when players click them.
|
||||
---@param event EventData.on_gui_checked_state_changed
|
||||
---@return nil
|
||||
function SpawnOptsRadioSelect(event)
|
||||
if not event.element.valid then return end
|
||||
local elemName = event.element.name
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
|
||||
if (elemName == "isolated_spawn_main_team_radio") then
|
||||
event.element.parent.isolated_spawn_new_team_radio.state = false
|
||||
elseif (elemName == "isolated_spawn_new_team_radio") then
|
||||
event.element.parent.isolated_spawn_main_team_radio.state = false
|
||||
if (tags.action ~= "oarc_spawn_options") then
|
||||
return
|
||||
end
|
||||
|
||||
if (elemName == "buddy_spawn_main_team_radio") then
|
||||
event.element.parent.buddy_spawn_new_team_radio.state = false
|
||||
event.element.parent.buddy_spawn_buddy_team_radio.state = false
|
||||
elseif (elemName == "buddy_spawn_new_team_radio") then
|
||||
event.element.parent.buddy_spawn_main_team_radio.state = false
|
||||
event.element.parent.buddy_spawn_buddy_team_radio.state = false
|
||||
elseif (elemName == "buddy_spawn_buddy_team_radio") then
|
||||
event.element.parent.buddy_spawn_main_team_radio.state = false
|
||||
event.element.parent.buddy_spawn_new_team_radio.state = false
|
||||
if (tags.setting == "team_select") then
|
||||
global.ocore.spawnChoices[player.name].team = tags.value
|
||||
|
||||
-- Need to handle the radio button logic manually
|
||||
if (elemName == "isolated_spawn_main_team_radio") then
|
||||
if (event.element.parent.isolated_spawn_new_team_radio ~= nil) then
|
||||
event.element.parent.isolated_spawn_new_team_radio.state = false
|
||||
end
|
||||
if (event.element.parent.isolated_spawn_buddy_team_radio ~= nil) then
|
||||
event.element.parent.isolated_spawn_buddy_team_radio.state = false
|
||||
end
|
||||
elseif (elemName == "isolated_spawn_new_team_radio") then
|
||||
event.element.parent.isolated_spawn_main_team_radio.state = false
|
||||
if (event.element.parent.isolated_spawn_buddy_team_radio ~= nil) then
|
||||
event.element.parent.isolated_spawn_buddy_team_radio.state = false
|
||||
end
|
||||
elseif (elemName == "isolated_spawn_buddy_team_radio") then
|
||||
event.element.parent.isolated_spawn_main_team_radio.state = false
|
||||
event.element.parent.isolated_spawn_new_team_radio.state = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Handle the gui click of the spawn options
|
||||
---@param event EventData.on_gui_click
|
||||
---@return nil
|
||||
function SpawnChoicesGuiClickNew(event)
|
||||
if not event.element.valid then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
|
||||
if (tags.action ~= "oarc_spawn_options") then
|
||||
return
|
||||
end
|
||||
local setting_name = tags.setting
|
||||
|
||||
if (tags.setting == "spawn_request") then
|
||||
SpawnRequest(player)
|
||||
end
|
||||
end
|
||||
|
||||
---Handle slider value changes
|
||||
---@param event EventData.on_gui_value_changed
|
||||
---@return nil
|
||||
function SpawnOptsValueChanged(event)
|
||||
if not event.element.valid then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
|
||||
if (tags.action ~= "oarc_spawn_options") then
|
||||
return
|
||||
end
|
||||
|
||||
if (tags.setting == "distance_select") then
|
||||
local distance = event.element.slider_value
|
||||
global.ocore.spawnChoices[player.name].distance = distance
|
||||
event.element.parent.spawn_distance_slider_value.text = tostring(distance)
|
||||
-- log("GUI DEBUG Selected distance: " .. distance)
|
||||
end
|
||||
end
|
||||
|
||||
---Handle dropdown selection changes
|
||||
---@param event EventData.on_gui_selection_state_changed
|
||||
---@return nil
|
||||
function SpawnOptsSelectionChanged(event)
|
||||
if not event.element.valid then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
|
||||
if (tags.action ~= "oarc_spawn_options") then
|
||||
return
|
||||
end
|
||||
|
||||
if (tags.setting == "surface_select") then
|
||||
local index = event.element.selected_index
|
||||
local surfaceName = event.element.get_item(index) --[[@as string]]
|
||||
global.ocore.spawnChoices[player.name].surface = surfaceName
|
||||
log("GUI DEBUG Selected surface: " .. surfaceName)
|
||||
end
|
||||
end
|
||||
|
||||
---Requests the generation of a spawn point for the player
|
||||
---@param player LuaPlayer
|
||||
---@return nil
|
||||
function SpawnRequest(player)
|
||||
-- Get the player's spawn choices
|
||||
---@type OarcSpawnChoices
|
||||
local spawnChoices = global.ocore.spawnChoices[player.name]
|
||||
if (spawnChoices == nil) then error("ERROR! No spawn choices found for player!") return end
|
||||
|
||||
-- Cache some useful variables
|
||||
local gameplay = global.ocfg.gameplay
|
||||
local surface = game.surfaces[spawnChoices.surface]
|
||||
|
||||
-- Create a new force for player if they choose that radio button
|
||||
if spawnChoices.team ~= SPAWN_TEAM_CHOICE.join_main_team then
|
||||
CreatePlayerCustomForce(player)
|
||||
end
|
||||
|
||||
-- Find coordinates of a good place to spawn
|
||||
local newSpawn = { x = 0, y = 0 }
|
||||
newSpawn = FindUngeneratedCoordinates(gameplay.near_spawn_distance, gameplay.far_spawn_distance, surface)
|
||||
|
||||
-- If that fails, find a random map edge in a rand direction.
|
||||
if ((newSpawn.x == 0) and (newSpawn.y == 0)) then
|
||||
newSpawn = FindMapEdge(GetRandomVector(), surface)
|
||||
log("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y)
|
||||
end
|
||||
|
||||
-- Create that player's spawn in the global vars
|
||||
ChangePlayerSpawn(player, spawnChoices.surface, newSpawn)
|
||||
|
||||
-- Send the player there
|
||||
-- global.ocfg.enable_vanilla_spawns --TODO: Vanilla spawn points are not implemented yet.
|
||||
QueuePlayerForDelayedSpawn(player.name, spawnChoices.surface, newSpawn, spawnChoices.moat, false)
|
||||
SendBroadcastMsg({ "oarc-player-is-joining-far", player.name, spawnChoices.surface })
|
||||
|
||||
-- Unlock spawn control gui tab
|
||||
SetOarcGuiTabEnabled(player, OARC_SPAWN_CTRL_TAB_NAME, true)
|
||||
|
||||
player.print({ "oarc-please-wait" })
|
||||
player.print({ "", { "oarc-please-wait" }, "!" })
|
||||
player.print({ "", { "oarc-please-wait" }, "!!" })
|
||||
|
||||
-- Destroy the spawn options gui
|
||||
if (player.gui.screen.spawn_opts ~= nil) then
|
||||
player.gui.screen.spawn_opts.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
@ -327,7 +547,7 @@ function SpawnOptsGuiClick(event)
|
||||
local joinOwnTeamRadio, moatChoice = false, false
|
||||
local surfaceName = global.ocfg.gameplay.default_surface -- Default to default surface
|
||||
local surface = game.surfaces[surfaceName]
|
||||
|
||||
|
||||
-- Check if a valid button on the gui was pressed
|
||||
-- and delete the GUI
|
||||
if ((elemName == "default_spawn_btn") or
|
||||
@ -382,67 +602,9 @@ function SpawnOptsGuiClick(event)
|
||||
defaultSurface)
|
||||
-- Unlock spawn control gui tab
|
||||
SetOarcGuiTabEnabled(player, OARC_SPAWN_CTRL_TAB_NAME, true)
|
||||
|
||||
|
||||
elseif ((elemName == "isolated_spawn_near") or (elemName == "isolated_spawn_far")) then
|
||||
|
||||
local newSpawn = { x = 0, y = 0 }
|
||||
local gameplay = global.ocfg.gameplay
|
||||
|
||||
-- Create a new force for player if they choose that radio button
|
||||
if gameplay.enable_separate_teams and joinOwnTeamRadio then
|
||||
local newForce = CreatePlayerCustomForce(player)
|
||||
end
|
||||
|
||||
---TODO: Vanilla spawn points are not implemented yet.
|
||||
-- -- Find an unused vanilla spawn
|
||||
-- -- if (vanillaChoice) then
|
||||
-- if (global.ocfg.enable_vanilla_spawns) then
|
||||
-- if (elemName == "isolated_spawn_far") then
|
||||
-- newSpawn = FindUnusedVanillaSpawn(game.surfaces[GAME_SURFACE_NAME],
|
||||
-- global.ocfg.far_dist_end*CHUNK_SIZE)
|
||||
-- elseif (elemName == "isolated_spawn_near") then
|
||||
-- newSpawn = FindUnusedVanillaSpawn(game.surfaces[GAME_SURFACE_NAME],
|
||||
-- global.ocfg.near_dist_start*CHUNK_SIZE)
|
||||
-- end
|
||||
|
||||
|
||||
-- -- Default OARC-type pre-set layout spawn.
|
||||
-- else
|
||||
-- Find coordinates of a good place to spawn
|
||||
if (elemName == "isolated_spawn_far") then
|
||||
newSpawn = FindUngeneratedCoordinates(gameplay.near_spawn_distance, gameplay.far_spawn_distance, surface)
|
||||
elseif (elemName == "isolated_spawn_near") then
|
||||
newSpawn = FindUngeneratedCoordinates(gameplay.near_spawn_distance, gameplay.far_spawn_distance, surface)
|
||||
end
|
||||
-- end
|
||||
|
||||
-- If that fails, find a random map edge in a rand direction.
|
||||
if ((newSpawn.x == 0) and (newSpawn.y == 0)) then
|
||||
newSpawn = FindMapEdge(GetRandomVector(), surface)
|
||||
log("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y)
|
||||
end
|
||||
|
||||
-- Create that player's spawn in the global vars
|
||||
ChangePlayerSpawn(player, surfaceName, newSpawn)
|
||||
|
||||
-- Send the player there
|
||||
QueuePlayerForDelayedSpawn(player.name,
|
||||
surfaceName,
|
||||
newSpawn,
|
||||
moatChoice,
|
||||
false) -- global.ocfg.enable_vanilla_spawns --TODO: Vanilla spawn points are not implemented yet.
|
||||
if (elemName == "isolated_spawn_near") then
|
||||
SendBroadcastMsg({ "oarc-player-is-joining-near", player.name, surfaceName })
|
||||
elseif (elemName == "isolated_spawn_far") then
|
||||
SendBroadcastMsg({ "oarc-player-is-joining-far", player.name, surfaceName })
|
||||
end
|
||||
|
||||
-- Unlock spawn control gui tab
|
||||
SetOarcGuiTabEnabled(player, OARC_SPAWN_CTRL_TAB_NAME, true)
|
||||
|
||||
player.print({ "oarc-please-wait" })
|
||||
player.print({ "", { "oarc-please-wait" }, "!" })
|
||||
player.print({ "", { "oarc-please-wait" }, "!!" })
|
||||
--- MOVED
|
||||
elseif (elemName == "join_other_spawn") then
|
||||
DisplaySharedSpawnOptions(player)
|
||||
|
||||
@ -810,18 +972,18 @@ function BuddySpawnOptsGuiClick(event)
|
||||
surfaceName = buddySpawnGui.surfaces_horizontal_flow.surface_select_dropdown.get_item(surfaceDropdownIndex) --[[@as string]]
|
||||
end
|
||||
|
||||
---@type BuddySpawnChoice
|
||||
---@type SpawnTeamChoice
|
||||
local buddyTeamRadioSelection = nil
|
||||
if (global.ocfg.gameplay.enable_separate_teams) then
|
||||
if buddySpawnGui.buddy_spawn_main_team_radio.state then
|
||||
buddyTeamRadioSelection = BUDDY_SPAWN_CHOICE.join_main_team
|
||||
buddyTeamRadioSelection = SPAWN_TEAM_CHOICE.join_main_team
|
||||
elseif buddySpawnGui.buddy_spawn_new_team_radio.state then
|
||||
buddyTeamRadioSelection = BUDDY_SPAWN_CHOICE.join_own_team
|
||||
buddyTeamRadioSelection = SPAWN_TEAM_CHOICE.join_own_team
|
||||
elseif buddySpawnGui.buddy_spawn_buddy_team_radio.state then
|
||||
buddyTeamRadioSelection = BUDDY_SPAWN_CHOICE.join_buddy_team
|
||||
buddyTeamRadioSelection = SPAWN_TEAM_CHOICE.join_buddy_team
|
||||
end
|
||||
else
|
||||
buddyTeamRadioSelection = BUDDY_SPAWN_CHOICE.join_main_team
|
||||
buddyTeamRadioSelection = SPAWN_TEAM_CHOICE.join_main_team
|
||||
end
|
||||
|
||||
if (global.ocfg.gameplay.allow_moats_around_spawns) then
|
||||
@ -950,11 +1112,11 @@ function DisplayBuddySpawnRequestMenu(player, requestingBuddyName)
|
||||
|
||||
---@type LocalisedString
|
||||
local teamText = "error!"
|
||||
if (buddySpawnOpts.teamRadioSelection == BUDDY_SPAWN_CHOICE.join_main_team) then
|
||||
if (buddySpawnOpts.teamRadioSelection == SPAWN_TEAM_CHOICE.join_main_team) then
|
||||
teamText = { "oarc-buddy-txt-main-team" }
|
||||
elseif (buddySpawnOpts.teamRadioSelection == BUDDY_SPAWN_CHOICE.join_own_team) then
|
||||
elseif (buddySpawnOpts.teamRadioSelection == SPAWN_TEAM_CHOICE.join_own_team) then
|
||||
teamText = { "oarc-buddy-txt-new-teams" }
|
||||
elseif (buddySpawnOpts.teamRadioSelection == BUDDY_SPAWN_CHOICE.join_buddy_team) then
|
||||
elseif (buddySpawnOpts.teamRadioSelection == SPAWN_TEAM_CHOICE.join_buddy_team) then
|
||||
teamText = { "oarc-buddy-txt-buddy-team" }
|
||||
end
|
||||
|
||||
@ -1045,12 +1207,12 @@ function BuddySpawnRequestMenuClick(event)
|
||||
local newSpawn = { x = 0, y = 0 }
|
||||
|
||||
-- Create a new force for each player if they chose that option
|
||||
if requesterOptions.teamRadioSelection == BUDDY_SPAWN_CHOICE.join_own_team then
|
||||
if requesterOptions.teamRadioSelection == SPAWN_TEAM_CHOICE.join_own_team then
|
||||
CreatePlayerCustomForce(player)
|
||||
CreatePlayerCustomForce(game.players[requesterName])
|
||||
|
||||
-- Create a new force for the combined players if they chose that option
|
||||
elseif requesterOptions.teamRadioSelection == BUDDY_SPAWN_CHOICE.join_buddy_team then
|
||||
elseif requesterOptions.teamRadioSelection == SPAWN_TEAM_CHOICE.join_buddy_team then
|
||||
local buddyForce = CreatePlayerCustomForce(game.players[requesterName])
|
||||
player.force = buddyForce
|
||||
end
|
||||
@ -1166,6 +1328,9 @@ end
|
||||
---@return nil
|
||||
function SeparateSpawnsGuiClick(event)
|
||||
WelcomeTextGuiClick(event)
|
||||
|
||||
SpawnChoicesGuiClickNew(event)
|
||||
|
||||
SpawnOptsGuiClick(event)
|
||||
SharedSpwnOptsGuiClick(event)
|
||||
BuddySpawnOptsGuiClick(event)
|
||||
@ -1179,4 +1344,18 @@ end
|
||||
---@return nil
|
||||
function SeparateSpawnsGuiCheckedStateChanged(event)
|
||||
SpawnOptsRadioSelect(event)
|
||||
end
|
||||
|
||||
---Gui value changed event handlers
|
||||
---@param event EventData.on_gui_value_changed
|
||||
---@return nil
|
||||
function SeparateSpawnsGuiValueChanged(event)
|
||||
SpawnOptsValueChanged(event)
|
||||
end
|
||||
|
||||
---Gui selection state changed event handlers
|
||||
---@param event EventData.on_gui_selection_state_changed
|
||||
---@return nil
|
||||
function SeparateSpawnsGuiSelectionStateChanged(event)
|
||||
SpawnOptsSelectionChanged(event)
|
||||
end
|
Loading…
Reference in New Issue
Block a user