2016-11-30 21:41:04 -05:00
-- separate_spawns.lua
-- Nov 2016
--
2016-11-25 16:20:41 -08:00
-- Code that handles everything regarding giving each player a separate spawn
-- Includes the GUI stuff
2016-11-30 21:41:04 -05:00
--------------------------------------------------------------------------------
-- EVENT RELATED FUNCTIONS
--------------------------------------------------------------------------------
2016-11-25 16:20:41 -08:00
-- When a new player is created, present the spawn options
-- Assign them to the main force so they can communicate with the team
-- without shouting.
2016-11-30 21:41:04 -05:00
function SeparateSpawnsPlayerCreated ( event )
2016-11-25 16:20:41 -08:00
local player = game.players [ event.player_index ]
player.force = MAIN_FORCE
2016-11-30 21:41:04 -05:00
DisplayWelcomeTextGui ( player )
2016-11-25 16:20:41 -08:00
end
-- Check if the player has a different spawn point than the default one
-- Make sure to give the default starting items
2016-11-30 21:41:04 -05:00
function SeparateSpawnsPlayerRespawned ( event )
2016-11-25 16:20:41 -08:00
local player = game.players [ event.player_index ]
2016-12-02 16:26:49 -05:00
SendPlayerToSpawn ( player )
2016-11-25 16:20:41 -08:00
end
-- This is the main function that creates the spawn area
-- Provides resources, land and a safe zone
2016-11-30 21:41:04 -05:00
function SeparateSpawnsGenerateChunk ( event )
2016-11-25 16:20:41 -08:00
local surface = event.surface
local chunkArea = event.area
-- This handles chunk generation near player spawns
-- If it is near a player spawn, it does a few things like make the area
-- safe and provide a guaranteed area of land and water tiles.
2016-12-30 09:41:46 -08:00
CreateSpawnAreas ( surface , chunkArea , global.uniqueSpawns )
2016-11-25 16:20:41 -08:00
end
2016-11-30 21:41:04 -05:00
2016-12-02 16:26:49 -05:00
-- Call this if a player leaves the game
2017-07-25 20:20:35 -04:00
-- Still seems to have a bug.
2016-12-02 16:26:49 -05:00
function FindUnusedSpawns ( event )
local player = game.players [ event.player_index ]
if ( player.online_time < MIN_ONLINE_TIME ) then
2017-04-27 21:48:28 -04:00
DropGravestoneChests ( player )
2016-12-14 16:00:00 -05:00
2017-05-12 22:33:57 -04:00
-- Clear out global variables for that player
2016-12-02 16:26:49 -05:00
if ( global.playerSpawns [ player.name ] ~= nil ) then
global.playerSpawns [ player.name ] = nil
end
2017-05-11 19:42:23 -04:00
2017-05-12 22:33:57 -04:00
-- Transfer or remove a shared spawn if player is owner
2017-05-11 19:42:23 -04:00
if ( global.sharedSpawns [ player.name ] ~= nil ) then
2017-05-12 22:33:57 -04:00
local teamMates = global.sharedSpawns [ player.name ] . players
if ( # teamMates >= 1 ) then
local newOwnerName = table.remove ( teamMates )
TransferOwnershipOfSharedSpawn ( player.name , newOwnerName )
else
2017-05-11 19:42:23 -04:00
global.sharedSpawns [ player.name ] = nil
2017-05-12 22:33:57 -04:00
end
2017-05-11 19:42:23 -04:00
end
2016-12-02 16:26:49 -05:00
-- If a uniqueSpawn was created for the player, mark it as unused.
if ( global.uniqueSpawns [ player.name ] ~= nil ) then
2017-11-08 09:13:34 -05:00
if ENABLE_ABANDONED_BASE_REMOVAL then
2017-08-23 23:42:51 -07:00
local spawnPos = global.uniqueSpawns [ player.name ] . pos
global.uniqueSpawns [ player.name ] = nil
2017-11-08 09:13:34 -05:00
SendBroadcastMsg ( player.name .. " 's base was marked for immediate clean up because they left within " .. MIN_ONLINE_TIME_IN_MINUTES .. " minutes of joining. " )
2017-08-23 23:42:51 -07:00
OarcRegrowthMarkForRemoval ( spawnPos , 10 )
global.chunk_regrow . force_removal_flag = game.tick
else
table.insert ( global.unusedSpawns , global.uniqueSpawns [ player.name ] )
2017-11-08 09:13:34 -05:00
global.uniqueSpawns [ player.name ] = nil
SendBroadcastMsg ( player.name .. " base was freed up because they left within " .. MIN_ONLINE_TIME_IN_MINUTES .. " minutes of joining. " )
2017-08-23 23:42:51 -07:00
end
2016-12-02 16:26:49 -05:00
end
2016-12-13 18:46:48 -05:00
-- remove that player's cooldown setting
2016-12-02 16:26:49 -05:00
if ( global.playerCooldowns [ player.name ] ~= nil ) then
global.playerCooldowns [ player.name ] = nil
end
2016-11-30 21:41:04 -05:00
2016-12-14 16:00:00 -05:00
-- Remove from shared spawn player slots (need to search all)
for _ , sharedSpawn in pairs ( global.sharedSpawns ) do
for key , playerName in pairs ( sharedSpawn.players ) do
if ( player.name == playerName ) then
sharedSpawn.players [ key ] = nil ;
end
end
end
2017-04-30 09:22:45 -04:00
-- Remove a force if this player created it and they are the only one on it
2017-05-11 09:47:06 -04:00
if ( ( # player.force . players <= 1 ) and ( player.force . name ~= MAIN_FORCE ) ) then
2017-04-30 09:22:45 -04:00
game.merge_forces ( player.force , MAIN_FORCE )
end
2016-12-13 18:46:48 -05:00
-- Remove the character completely
2016-12-02 16:26:49 -05:00
game.remove_offline_players ( { player } )
end
end
2016-11-30 21:41:04 -05:00
2016-12-30 09:41:46 -08:00
--------------------------------------------------------------------------------
-- NON-EVENT RELATED FUNCTIONS
--------------------------------------------------------------------------------
-- Add a spawn to the shared spawn global
-- Used for tracking which players are assigned to it, where it is and if
-- it is open for new players to join
2016-12-13 18:46:48 -05:00
function CreateNewSharedSpawn ( player )
global.sharedSpawns [ player.name ] = { openAccess = true ,
position = global.playerSpawns [ player.name ] ,
players = { } }
end
2017-05-12 22:33:57 -04:00
function TransferOwnershipOfSharedSpawn ( prevOwnerName , newOwnerName )
2017-05-11 19:42:23 -04:00
-- Transfer the shared spawn global
2017-05-12 22:33:57 -04:00
global.sharedSpawns [ newOwnerName ] = global.sharedSpawns [ prevOwnerName ]
global.sharedSpawns [ newOwnerName ] . openAccess = false
global.sharedSpawns [ prevOwnerName ] = nil
2017-05-11 19:42:23 -04:00
-- Transfer the unique spawn global
2017-05-12 22:33:57 -04:00
global.uniqueSpawns [ newOwnerName ] = global.uniqueSpawns [ prevOwnerName ]
global.uniqueSpawns [ prevOwnerName ] = nil
game.players [ newOwnerName ] . print ( " You have been given ownership of this base! " )
2017-05-11 19:42:23 -04:00
end
2016-12-30 09:41:46 -08:00
-- Returns the number of players currently online at the shared spawn
2016-12-13 18:46:48 -05:00
function GetOnlinePlayersAtSharedSpawn ( ownerName )
if ( global.sharedSpawns [ ownerName ] ~= nil ) then
-- Does not count base owner
local count = 0
-- For each player in the shared spawn, check if online and add to count.
for _ , player in pairs ( game.connected_players ) do
if ( ownerName == player.name ) then
count = count + 1
end
for _ , playerName in pairs ( global.sharedSpawns [ ownerName ] . players ) do
if ( playerName == player.name ) then
count = count + 1
end
end
end
return count
else
return 0
end
end
-- Get the number of currently available shared spawns
-- This means the base owner has enabled access AND the number of online players
-- is below the threshold.
function GetNumberOfAvailableSharedSpawns ( )
local count = 0
for ownerName , sharedSpawn in pairs ( global.sharedSpawns ) do
if ( sharedSpawn.openAccess ) then
if ( GetOnlinePlayersAtSharedSpawn ( ownerName ) < MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN ) then
count = count + 1
end
end
end
return count
end
2016-11-30 21:41:04 -05:00
2016-12-30 09:41:46 -08:00
-- Initializes the globals used to track the special spawn and player
-- status information
2016-11-25 16:20:41 -08:00
function InitSpawnGlobalsAndForces ( )
-- Containes an array of all player spawns
-- A secondary array tracks whether the character will respawn there.
if ( global.playerSpawns == nil ) then
global.playerSpawns = { }
2016-12-02 16:26:49 -05:00
end
if ( global.uniqueSpawns == nil ) then
global.uniqueSpawns = { }
end
if ( global.sharedSpawns == nil ) then
global.sharedSpawns = { }
end
if ( global.unusedSpawns == nil ) then
global.unusedSpawns = { }
end
if ( global.playerCooldowns == nil ) then
global.playerCooldowns = { }
2016-11-25 16:20:41 -08:00
end
2017-12-15 15:43:03 -05:00
if ( global.waitingBuddies == nil ) then
global.waitingBuddies = { }
end
2016-11-25 16:20:41 -08:00
game.create_force ( MAIN_FORCE )
2017-04-26 20:59:48 -04:00
game.forces [ MAIN_FORCE ] . set_spawn_position ( game.forces [ " player " ] . get_spawn_position ( GAME_SURFACE_NAME ) , GAME_SURFACE_NAME )
2016-11-25 16:20:41 -08:00
SetCeaseFireBetweenAllForces ( )
2017-04-26 20:59:48 -04:00
SetFriendlyBetweenAllForces ( )
2017-05-11 19:42:23 -04:00
-- AntiGriefing(game.forces[MAIN_FORCE])
2016-11-25 16:20:41 -08:00
end
function DoesPlayerHaveCustomSpawn ( player )
for name , spawnPos in pairs ( global.playerSpawns ) do
if ( player.name == name ) then
return true
end
end
return false
end
2016-12-02 16:26:49 -05:00
function ChangePlayerSpawn ( player , pos )
global.playerSpawns [ player.name ] = pos
2017-04-27 21:48:28 -04:00
global.playerCooldowns [ player.name ] = { setRespawn = game.tick }
2016-11-25 16:20:41 -08:00
end
2017-07-25 20:20:35 -04:00
function SendPlayerToNewSpawnAndCreateIt ( player , spawn , moatEnabled )
2017-12-15 14:45:01 -05:00
2016-11-25 16:20:41 -08:00
-- Send the player to that position
2017-04-26 20:59:48 -04:00
player.teleport ( spawn , GAME_SURFACE_NAME )
2016-11-25 16:20:41 -08:00
GivePlayerStarterItems ( player )
2017-04-26 20:59:48 -04:00
ChartArea ( player.force , player.position , 4 , player.surface )
2016-11-25 16:20:41 -08:00
-- If we get a valid spawn point, setup the area
2016-12-02 16:26:49 -05:00
if ( ( spawn.x ~= 0 ) and ( spawn.y ~= 0 ) ) then
2017-07-25 20:20:35 -04:00
global.uniqueSpawns [ player.name ] = { pos = spawn , moat = moatEnabled }
2016-11-25 16:20:41 -08:00
ClearNearbyEnemies ( player , SAFE_AREA_TILE_DIST )
2016-12-02 16:26:49 -05:00
else
DebugPrint ( " THIS SHOULD NOT EVER HAPPEN! Spawn failed! " )
SendBroadcastMsg ( " Failed to create spawn point for: " .. player.name )
2016-11-25 16:20:41 -08:00
end
end
2016-12-02 16:26:49 -05:00
function SendPlayerToSpawn ( player )
if ( DoesPlayerHaveCustomSpawn ( player ) ) then
2017-04-26 20:59:48 -04:00
player.teleport ( global.playerSpawns [ player.name ] , GAME_SURFACE_NAME )
2016-11-25 16:20:41 -08:00
else
2017-04-26 20:59:48 -04:00
player.teleport ( game.forces [ MAIN_FORCE ] . get_spawn_position ( GAME_SURFACE_NAME ) , GAME_SURFACE_NAME )
2016-11-25 16:20:41 -08:00
end
end
function SendPlayerToRandomSpawn ( player )
2016-12-02 16:26:49 -05:00
local numSpawns = TableLength ( global.uniqueSpawns )
2016-11-25 16:20:41 -08:00
local rndSpawn = math.random ( 0 , numSpawns )
local counter = 0
if ( rndSpawn == 0 ) then
2017-04-26 20:59:48 -04:00
player.teleport ( game.forces [ MAIN_FORCE ] . get_spawn_position ( GAME_SURFACE_NAME ) , GAME_SURFACE_NAME )
2016-11-25 16:20:41 -08:00
else
counter = counter + 1
2017-07-25 20:20:35 -04:00
for name , spawn in pairs ( global.uniqueSpawns ) do
2016-11-25 16:20:41 -08:00
if ( counter == rndSpawn ) then
2017-07-25 20:20:35 -04:00
player.teleport ( spawn.pos )
2016-11-25 16:20:41 -08:00
break
end
counter = counter + 1
end
end
end
2017-04-30 09:22:45 -04:00
function CreatePlayerCustomForce ( player )
local newForce = nil
-- Check if force already exists
if ( game.forces [ player.name ] ~= nil ) then
DebugPrint ( " Force already exists! " )
player.force = game.forces [ player.name ]
return game.forces [ player.name ]
-- Create a new force using the player's name
elseif ( TableLength ( game.forces ) < MAX_FORCES ) then
newForce = game.create_force ( player.name )
player.force = newForce
SetCeaseFireBetweenAllForces ( )
SetFriendlyBetweenAllForces ( )
SendBroadcastMsg ( player.name .. " has started their own team! " )
else
player.force = MAIN_FORCE
player.print ( " Sorry, no new teams can be created. You were assigned to the default team instead. " )
end
2016-11-25 16:20:41 -08:00
2017-04-30 09:22:45 -04:00
return newForce
end
2016-11-30 21:41:04 -05:00
2017-04-30 09:22:45 -04:00
-- For each force, if it's a valid force, chart the chunk that all active players
-- are in.
-- I have no idea how compute intensive this function is. If it starts to lag the game
-- we'll have to figure out how to change it.
function ShareVisionBetweenPlayers ( )
2016-11-30 21:41:04 -05:00
2017-11-29 14:39:09 -05:00
if ( ( game.tick % 10 ) == 0 ) then
2017-05-21 15:33:52 -04:00
for _ , force in pairs ( game.forces ) do
if ( force ~= nil ) then
if ( ( force.name ~= enemy ) and
( force.name ~= neutral ) and
( force.name ~= player ) ) then
for _ , player in pairs ( game.connected_players ) do
force.chart ( GAME_SURFACE_NAME ,
2017-11-29 14:39:09 -05:00
{ { player.position . x - ( 2 * CHUNK_SIZE ) ,
player.position . y - ( 2 * CHUNK_SIZE ) } ,
{ player.position . x + ( 2 * CHUNK_SIZE ) ,
player.position . y + ( 2 * CHUNK_SIZE ) } } )
2017-05-21 15:33:52 -04:00
end
end
2017-04-30 09:22:45 -04:00
end
end
end
2017-05-11 09:47:06 -04:00
end
2017-11-29 14:39:09 -05:00
-- For each force, if it's a valid force, chart the chunk that was just scanned
-- for all forces.
-- I have no idea how compute intensive this function is. If it starts to lag the game
-- we'll have to figure out how to change it.
function ShareRadarBetweenForces ( event )
for _ , force in pairs ( game.forces ) do
if ( force ~= nil ) then
if ( ( force.name ~= enemy ) and
( force.name ~= neutral ) and
( force.name ~= player ) ) then
for _ , player in pairs ( game.connected_players ) do
force.chart ( GAME_SURFACE_NAME ,
2017-11-29 16:41:28 -05:00
{ { event.chunk_position . x * CHUNK_SIZE ,
event.chunk_position . y * CHUNK_SIZE } ,
{ event.chunk_position . x * CHUNK_SIZE ,
event.chunk_position . y * CHUNK_SIZE } } )
2017-11-29 14:39:09 -05:00
end
end
end
end
end