1
0
mirror of https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git synced 2024-12-14 10:23:17 +02:00
FactorioScenarioMultiplayer.../separate_spawns_guis.lua

583 lines
25 KiB
Lua
Executable File

-- separate_spawns_guis.lua
-- Nov 2016
-- I made a separate file for all the GUI related functions
require("separate_spawns")
local SPAWN_GUI_MAX_WIDTH = 450
local SPAWN_GUI_MAX_HEIGHT = 750
-- Use this for testing shared spawns...
-- local sharedSpawnExample1 = {openAccess=true,
-- position={x=50,y=50},
-- players={"ABC", "DEF"}}
-- local sharedSpawnExample2 = {openAccess=false,
-- position={x=200,y=200},
-- players={"ABC", "DEF"}}
-- local sharedSpawnExample3 = {openAccess=true,
-- owner="testName1",
-- players={"A", "B", "C", "D"}}
-- global.sharedSpawns = {testName1=sharedSpawnExample1,
-- testName2=sharedSpawnExample2,
-- testName3=sharedSpawnExample3}
-- A display gui message
-- Meant to be display the first time a player joins.
function DisplayWelcomeTextGui(player)
player.gui.center.add{name = "welcome_msg",
type = "frame",
direction = "vertical",
caption=global.welcome_msg_title}
local wGui = player.gui.center.welcome_msg
wGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH
wGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT
wGui.add{name = "welcome_msg_lbl1", type = "label",
caption=WELCOME_MSG1}
wGui.add{name = "welcome_msg_lbl2", type = "label",
caption=WELCOME_MSG2}
wGui.add{name = "welcome_msg_spacer1", type = "label",
caption=" "}
ApplyStyle(wGui.welcome_msg_lbl1, my_label_style)
ApplyStyle(wGui.welcome_msg_lbl2, my_label_style)
ApplyStyle(wGui.welcome_msg_spacer1, my_spacer_style)
wGui.add{name = "other_msg_lbl1", type = "label",
caption=OTHER_MSG1}
wGui.add{name = "other_msg_lbl2", type = "label",
caption=OTHER_MSG2}
wGui.add{name = "other_msg_spacer1", type = "label",
caption=" "}
ApplyStyle(wGui.other_msg_lbl1, my_label_style)
ApplyStyle(wGui.other_msg_lbl2, my_label_style)
ApplyStyle(wGui.other_msg_spacer1, my_spacer_style)
wGui.add{name = "welcome_msg_lbl3", type = "label",
caption=WELCOME_MSG3}
wGui.add{name = "welcome_msg_lbl4", type = "label",
caption=WELCOME_MSG4}
wGui.add{name = "welcome_msg_lbl5", type = "label",
caption=WELCOME_MSG5}
wGui.add{name = "welcome_msg_lbl6", type = "label",
caption=WELCOME_MSG6}
wGui.add{name = "welcome_msg_spacer2", type = "label",
caption=" "}
ApplyStyle(wGui.welcome_msg_lbl3, my_warning_style)
ApplyStyle(wGui.welcome_msg_lbl4, my_warning_style)
ApplyStyle(wGui.welcome_msg_lbl5, my_warning_style)
ApplyStyle(wGui.welcome_msg_lbl6, my_label_style)
ApplyStyle(wGui.welcome_msg_spacer2, my_spacer_style)
wGui.add{name = "welcome_okay_btn",
type = "button",
caption="I Understand"}
end
-- Handle the gui click of the welcome msg
function WelcomeTextGuiClick(event)
if not (event and event.element and event.element.valid) then return end
local player = game.players[event.player_index]
local buttonClicked = event.element.name
if (buttonClicked == "welcome_okay_btn") then
if (player.gui.center.welcome_msg ~= nil) then
player.gui.center.welcome_msg.destroy()
end
DisplaySpawnOptions(player)
end
end
-- Display the spawn options and explanation
function DisplaySpawnOptions(player)
player.gui.center.add{name = "spawn_opts",
type = "frame",
direction = "vertical",
caption="Spawn Options"}
local sGui = player.gui.center.spawn_opts
sGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH
sGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT
-- Warnings and explanations...
sGui.add{name = "warning_lbl1", type = "label",
caption="This is your ONLY chance to choose a spawn option. Choose carefully..."}
sGui.add{name = "warning_spacer", type = "label",
caption=" "}
ApplyStyle(sGui.warning_lbl1, my_warning_style)
ApplyStyle(sGui.warning_spacer, my_spacer_style)
sGui.add{name = "spawn_msg_lbl1", type = "label",
caption=SPAWN_MSG1}
sGui.add{name = "spawn_msg_lbl2", type = "label",
caption=SPAWN_MSG2}
sGui.add{name = "spawn_msg_lbl3", type = "label",
caption=SPAWN_MSG3}
sGui.add{name = "spawn_msg_spacer", type = "label",
caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"}
ApplyStyle(sGui.spawn_msg_lbl1, my_label_style)
ApplyStyle(sGui.spawn_msg_lbl2, my_label_style)
ApplyStyle(sGui.spawn_msg_lbl3, my_label_style)
ApplyStyle(sGui.spawn_msg_spacer, my_spacer_style)
if ENABLE_DEFAULT_SPAWN then
sGui.add{name = "default_spawn_btn",
type = "button",
caption="Default Spawn"}
sGui.add{name = "normal_spawn_lbl1", type = "label",
caption="This is the default spawn behavior of a vanilla game."}
sGui.add{name = "normal_spawn_lbl2", type = "label",
caption="You join the default team in the center of the map."}
sGui.add{name = "normal_spawn_lbl3", type = "label",
caption="(Back by popular request...)"}
ApplyStyle(sGui.normal_spawn_lbl1, my_label_style)
ApplyStyle(sGui.normal_spawn_lbl2, my_label_style)
ApplyStyle(sGui.normal_spawn_lbl3, my_label_style)
else
sGui.add{name = "normal_spawn_lbl1", type = "label",
caption="Default spawn is disabled in this mode."}
ApplyStyle(sGui.normal_spawn_lbl1, my_warning_style)
end
sGui.add{name = "normal_spawn_spacer", type = "label",
caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"}
ApplyStyle(sGui.normal_spawn_spacer, my_spacer_style)
-- 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 = "flow",
direction="vertical"}
if (ENABLE_SEPARATE_TEAMS) then
soloSpawnFlow.add{name = "isolated_spawn_main_team_radio",
type = "radiobutton",
caption="Join Main Team (shared research)",
state=true}
soloSpawnFlow.add{name = "isolated_spawn_new_team_radio",
type = "radiobutton",
caption="Create Your Own Team (own research tree)",
state=false}
soloSpawnFlow.add{name = "team_chat_warning_lbl1", type = "label",
caption="You must type '/s' before your msg to chat with other teams!!!"}
ApplyStyle(soloSpawnFlow.team_chat_warning_lbl1, my_warning_style)
soloSpawnFlow.add{name = "team_chat_warning_spacer", type = "label",
caption=" "}
ApplyStyle(soloSpawnFlow.team_chat_warning_spacer, my_spacer_style)
end
soloSpawnFlow.add{name = "isolated_spawn_near",
type = "button",
caption="Solo Spawn (Near)"}
soloSpawnFlow.add{name = "isolated_spawn_far",
type = "button",
caption="Solo Spawn (Far)"}
soloSpawnFlow.add{name = "isolated_spawn_lbl1", type = "label",
caption="You are spawned in a new area, with some starting resources."}
ApplyStyle(soloSpawnFlow.isolated_spawn_lbl1, my_label_style)
sGui.add{name = "isolated_spawn_spacer", type = "label",
caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"}
ApplyStyle(sGui.isolated_spawn_spacer, my_spacer_style)
-- Spawn options to join another player's base.
if ENABLE_SHARED_SPAWNS then
local numAvailSpawns = GetNumberOfAvailableSharedSpawns()
if (numAvailSpawns > 0) then
sGui.add{name = "join_other_spawn",
type = "button",
caption="Join Someone (" .. numAvailSpawns .. " available)"}
sGui.add{name = "join_other_spawn_lbl1", type = "label",
caption="You are spawned in someone else's base."}
sGui.add{name = "join_other_spawn_lbl2", type = "label",
caption="This requires at least 1 person to have allowed access to their base."}
sGui.add{name = "join_other_spawn_lbl3", type = "label",
caption="This choice is final and you will not be able to create your own spawn later."}
sGui.add{name = "join_other_spawn_spacer", type = "label",
caption=" "}
ApplyStyle(sGui.join_other_spawn_lbl1, my_label_style)
ApplyStyle(sGui.join_other_spawn_lbl2, my_label_style)
ApplyStyle(sGui.join_other_spawn_lbl3, my_label_style)
ApplyStyle(sGui.join_other_spawn_spacer, my_spacer_style)
else
sGui.add{name = "join_other_spawn_lbl1", type = "label",
caption="There are currently no shared bases availble to spawn at."}
sGui.add{name = "join_other_spawn_spacer", type = "label",
caption=" "}
ApplyStyle(sGui.join_other_spawn_lbl1, my_warning_style)
ApplyStyle(sGui.join_other_spawn_spacer, my_spacer_style)
sGui.add{name = "join_other_spawn_check",
type = "button",
caption="Check Again"}
end
else
sGui.add{name = "join_other_spawn_lbl1", type = "label",
caption="Shared spawns are disabled in this mode."}
ApplyStyle(sGui.join_other_spawn_lbl1, my_warning_style)
end
-- Some final notes
sGui.add{name = "note_spacer1", type = "label",
caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"}
sGui.add{name = "note_spacer2", type = "label",
caption=" "}
if MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN then
sGui.add{name = "shared_spawn_note1", type = "label",
caption="If you create your own spawn point you can allow up to " .. MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN-1 .. " other online players to join." }
ApplyStyle(sGui.shared_spawn_note1, my_note_style)
end
sGui.add{name = "note_lbl1", type = "label",
caption="Near spawn is between " .. NEAR_MIN_DIST*CHUNK_SIZE .. "-" .. NEAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."}
sGui.add{name = "note_lbl2", type = "label",
caption="Far spawn is between " .. FAR_MIN_DIST*CHUNK_SIZE .. "-" .. FAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."}
sGui.add{name = "note_lbl3", type = "label",
caption="Solo spawns are dangerous! Expect a fight to reach other players."}
sGui.add{name = "note_spacer3", type = "label",
caption=" "}
ApplyStyle(sGui.note_lbl1, my_note_style)
ApplyStyle(sGui.note_lbl2, my_note_style)
ApplyStyle(sGui.note_lbl3, my_note_style)
ApplyStyle(sGui.note_spacer1, my_spacer_style)
ApplyStyle(sGui.note_spacer2, my_spacer_style)
ApplyStyle(sGui.note_spacer3, my_spacer_style)
end
-- Handle the gui click of the spawn options
function SpawnOptsGuiClick(event)
if not (event and event.element and event.element.valid) then return end
local player = game.players[event.player_index]
local elemName = event.element.name
if (player.gui.center.spawn_opts == nil) then
return -- Gui event unrelated to this gui.
end
local joinMainTeamRadio, joinOwnTeamRadio = false
-- Check if a valid button on the gui was pressed
-- and delete the GUI
if ((elemName == "default_spawn_btn") or
(elemName == "isolated_spawn_near") or
(elemName == "isolated_spawn_far") or
(elemName == "join_other_spawn") or
(elemName == "join_other_spawn_check")) then
if (ENABLE_SEPARATE_TEAMS) then
joinMainTeamRadio =
player.gui.center.spawn_opts.spawn_solo_flow.isolated_spawn_main_team_radio.state
joinOwnTeamRadio =
player.gui.center.spawn_opts.spawn_solo_flow.isolated_spawn_new_team_radio.state
end
player.gui.center.spawn_opts.destroy()
-- This just updates the radio buttons.
elseif ((elemName == "isolated_spawn_main_team_radio") or
(elemName == "isolated_spawn_new_team_radio")) then
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
end
else
return -- Do nothing, no valid element item was clicked.
end
if (elemName == "default_spawn_btn") then
CreateSpawnCtrlGui(player)
GivePlayerStarterItems(player)
ChangePlayerSpawn(player, player.force.get_spawn_position(GAME_SURFACE_NAME))
SendBroadcastMsg(player.name .. " joined the main force!")
ChartArea(player.force, player.position, 4, player.surface)
elseif ((elemName == "isolated_spawn_near") or (elemName == "isolated_spawn_far")) then
CreateSpawnCtrlGui(player)
-- Create a new spawn point
local newSpawn = {x=0,y=0}
-- Create a new force for player if they choose that radio button
if ENABLE_SEPARATE_TEAMS and joinOwnTeamRadio then
local newForce = CreatePlayerCustomForce(player)
if (FRONTIER_ROCKET_SILO_MODE and (newForce ~= nil)) then
ChartRocketSiloArea(newForce, game.surfaces[GAME_SURFACE_NAME])
end
end
-- Re-used abandoned spawns...
if (#global.unusedSpawns >= 1) then
newSpawn = table.remove(global.unusedSpawns)
global.uniqueSpawns[player.name] = newSpawn
player.print("Sorry! You have been assigned to an abandoned base! This is done to keep map size small.")
ChangePlayerSpawn(player, newSpawn)
SendPlayerToSpawn(player)
GivePlayerStarterItems(player)
SendBroadcastMsg(player.name .. " joined an abandoned base!")
else
-- Find coordinates of a good place to spawn
if (elemName == "isolated_spawn_far") then
newSpawn = FindUngeneratedCoordinates(FAR_MIN_DIST,FAR_MAX_DIST, player.surface)
elseif (elemName == "isolated_spawn_near") then
newSpawn = FindUngeneratedCoordinates(NEAR_MIN_DIST,NEAR_MAX_DIST, player.surface)
end
-- If that fails, find a random map edge in a rand direction.
if ((newSpawn.x == 0) and (newSpawn.x == 0)) then
newSpawn = FindMapEdge(GetRandomVector(), player.surface)
DebugPrint("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y)
end
-- Create that spawn in the global vars
ChangePlayerSpawn(player, newSpawn)
-- Send the player there
SendPlayerToNewSpawnAndCreateIt(player, newSpawn)
if (elemName == "isolated_spawn_near") then
SendBroadcastMsg(player.name .. " joined the game from a distance!")
elseif (elemName == "isolated_spawn_far") then
SendBroadcastMsg(player.name .. " joined the game from a great distance!")
end
player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!")
player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!")
player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!")
end
elseif (elemName == "join_other_spawn") then
DisplaySharedSpawnOptions(player)
-- Provide a way to refresh the gui to check if people have shared their
-- bases.
elseif (elemName == "join_other_spawn_check") then
DisplaySpawnOptions(player)
end
end
-- Display the spawn options and explanation
function DisplaySharedSpawnOptions(player)
player.gui.center.add{name = "shared_spawn_opts",
type = "frame",
direction = "vertical",
caption="Available Bases to Join:"}
local shGuiFrame = player.gui.center.shared_spawn_opts
local shGui = shGuiFrame.add{type="scroll-pane", name="spawns_scroll_pane", caption=""}
ApplyStyle(shGui, my_fixed_width_style)
shGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH
shGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT
shGui.horizontal_scroll_policy = "never"
for spawnName,sharedSpawn in pairs(global.sharedSpawns) do
if sharedSpawn.openAccess then
local spotsRemaining = MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN - GetOnlinePlayersAtSharedSpawn(spawnName)
if (spotsRemaining > 0) then
shGui.add{type="button", caption=spawnName .. " (" .. spotsRemaining .. " spots remaining)", name=spawnName}
shGui.add{name = spawnName .. "spacer_lbl", type = "label", caption=" "}
ApplyStyle(shGui[spawnName], my_small_button_style)
ApplyStyle(shGui[spawnName .. "spacer_lbl"], my_spacer_style)
end
end
end
shGui.add{name = "shared_spawn_cancel",
type = "button",
caption="Cancel (Return to Previous Options)"}
end
-- Handle the gui click of the shared spawn options
function SharedSpwnOptsGuiClick(event)
if not (event and event.element and event.element.valid) then return end
local player = game.players[event.player_index]
local buttonClicked = event.element.name
if (event.element.parent) then
if (event.element.parent.name ~= "spawns_scroll_pane") then
return
end
end
-- Check for cancel button, return to spawn options
if (buttonClicked == "shared_spawn_cancel") then
DisplaySpawnOptions(player)
if (player.gui.center.shared_spawn_opts ~= nil) then
player.gui.center.shared_spawn_opts.destroy()
end
-- Else check for which spawn was selected
-- If a spawn is removed during this time, the button will not do anything
else
for spawnName,sharedSpawn in pairs(global.sharedSpawns) do
if (buttonClicked == spawnName) then
CreateSpawnCtrlGui(player)
ChangePlayerSpawn(player,sharedSpawn.position)
SendPlayerToSpawn(player)
GivePlayerStarterItems(player)
table.insert(sharedSpawn.players, player.name)
SendBroadcastMsg(player.name .. " joined " .. spawnName .. "'s base!")
player.force = game.players[spawnName].force
if (player.gui.center.shared_spawn_opts ~= nil) then
player.gui.center.shared_spawn_opts.destroy()
end
break
end
end
end
end
function CreateSpawnCtrlGui(player)
if player.gui.top.spwn_ctrls == nil then
player.gui.top.add{name="spwn_ctrls", type="button", caption="Spawn Ctrl"}
end
end
local function IsSharedSpawnActive(player)
if ((global.sharedSpawns[player.name] == nil) or
(global.sharedSpawns[player.name].openAccess == false)) then
return false
else
return true
end
end
-- Get a random warp point to go to
function GetRandomSpawnPoint()
local numSpawnPoints = TableLength(global.sharedSpawns)
if (numSpawnPoints > 0) then
local randSpawnNum = math.random(1,numSpawnPoints)
local counter = 1
for _,sharedSpawn in pairs(global.sharedSpawns) do
if (randSpawnNum == counter) then
return sharedSpawn.position
end
counter = counter + 1
end
end
return {x=0,y=0}
end
-- This is a toggle function, it either shows or hides the spawn controls
function ExpandSpawnCtrlGui(player, tick)
local spwnCtrlPanel = player.gui.left["spwn_ctrl_panel"]
if (spwnCtrlPanel) then
spwnCtrlPanel.destroy()
else
local spwnCtrlPanel = player.gui.left.add{type="frame",
name="spwn_ctrl_panel", caption="Spawn Controls:"}
local spwnCtrls = spwnCtrlPanel.add{type="scroll-pane",
name="spwn_ctrl_panel", caption=""}
ApplyStyle(spwnCtrls, my_fixed_width_style)
spwnCtrls.style.maximal_height = SPAWN_GUI_MAX_HEIGHT
spwnCtrls.horizontal_scroll_policy = "never"
if ENABLE_SHARED_SPAWNS then
if (global.uniqueSpawns[player.name] ~= nil) then
-- This checkbox allows people to join your base when they first
-- start the game.
spwnCtrls.add{type="checkbox", name="accessToggle",
caption="Allow others to join your base.",
state=IsSharedSpawnActive(player)}
spwnCtrls["accessToggle"].style.top_padding = 10
spwnCtrls["accessToggle"].style.bottom_padding = 10
ApplyStyle(spwnCtrls["accessToggle"], my_fixed_width_style)
end
end
-- Sets the player's custom spawn point to their current location
if ((tick - global.playerCooldowns[player.name].setRespawn) > RESPAWN_COOLDOWN_TICKS) then
spwnCtrls.add{type="button", name="setRespawnLocation", caption="Set New Respawn Location (1 hour cooldown)"}
spwnCtrls["setRespawnLocation"].style.font = "default-small-semibold"
spwnCtrls.add{name = "respawn_cooldown_note2", type = "label",
caption="This will set your respawn point to your current location."}
spwnCtrls.add{name = "respawn_cooldown_spacer1", type = "label",
caption=" "}
ApplyStyle(spwnCtrls.respawn_cooldown_note2, my_note_style)
ApplyStyle(spwnCtrls.respawn_cooldown_spacer1, my_spacer_style)
else
spwnCtrls.add{name = "respawn_cooldown_note1", type = "label",
caption="Set Respawn Cooldown Remaining: " .. formattime(RESPAWN_COOLDOWN_TICKS-(tick - global.playerCooldowns[player.name].setRespawn))}
spwnCtrls.add{name = "respawn_cooldown_note2", type = "label",
caption="This will set your respawn point to your current location."}
spwnCtrls.add{name = "respawn_cooldown_spacer1", type = "label",
caption=" "}
ApplyStyle(spwnCtrls.respawn_cooldown_note1, my_note_style)
ApplyStyle(spwnCtrls.respawn_cooldown_note2, my_note_style)
ApplyStyle(spwnCtrls.respawn_cooldown_spacer1, my_spacer_style)
end
end
end
function SpawnCtrlGuiClick(event)
if not (event and event.element and event.element.valid) then return end
local player = game.players[event.element.player_index]
local name = event.element.name
if (name == "spwn_ctrls") then
ExpandSpawnCtrlGui(player, event.tick)
end
if (event.element.parent) then
if (event.element.parent.name ~= "spwn_ctrl_panel") then
return
end
end
if (name == "accessToggle") then
if event.element.state then
if DoesPlayerHaveCustomSpawn(player) then
if (global.sharedSpawns[player.name] == nil) then
CreateNewSharedSpawn(player)
else
global.sharedSpawns[player.name].openAccess = true
end
SendBroadcastMsg("New players can now join " .. player.name .. "'s base!")
end
else
if (global.sharedSpawns[player.name] ~= nil) then
global.sharedSpawns[player.name].openAccess = false
SendBroadcastMsg("New players can no longer join " .. player.name .. "'s base!")
end
end
end
-- Sets a new respawn point and resets the cooldown.
if (name == "setRespawnLocation") then
if DoesPlayerHaveCustomSpawn(player) then
ChangePlayerSpawn(player, player.position)
ExpandSpawnCtrlGui(player, event.tick)
player.print("Re-spawn point updated!")
end
end
end