mirror of
https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git
synced 2025-01-18 02:58:37 +02:00
Moving around stuff, about to test on headless.
This commit is contained in:
parent
07de8d1fe5
commit
e1839a8756
22
config.lua
22
config.lua
@ -287,7 +287,7 @@ MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Enable/Disable enemy expansion
|
||||
ENEMY_EXPANSION = true
|
||||
ENEMY_EXPANSION = false
|
||||
|
||||
-- Divide the alien evolution factors by this number to reduce it (or multiply if < 1)
|
||||
ENEMY_TIME_FACTOR_DISABLE = false -- Set this to true to disable time based evolution completely.
|
||||
@ -352,6 +352,8 @@ AUTOFILL_TURRET_AMMO_QUANTITY = 10
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Set this to true if you are creating the scenario at the cmd line.
|
||||
-- Set this to false if you want to configure the world settings using the in-game
|
||||
-- scenario settings.
|
||||
CMD_LINE_MAP_GEN = true
|
||||
|
||||
-- Adjust settings here to set your map stuff.
|
||||
@ -367,14 +369,14 @@ global.clMapGen.width = 2000000
|
||||
|
||||
-- These are my go to default vanilla settings, it's not RSO, but it's okay.
|
||||
global.clMapGen.autoplace_controls = {
|
||||
["coal"] = {frequency = 0.20, richness = 1.00, size = 1.50},
|
||||
["copper-ore"] = {frequency = 0.20, richness = 1.00, size = 1.50},
|
||||
["crude-oil"] = {frequency = 0.20, richness = 1.00, size = 1.50},
|
||||
["enemy-base"] = {frequency = 0.20, richness = 1.00, size = 0.50},
|
||||
["iron-ore"] = {frequency = 0.20, richness = 1.00, size = 1.50},
|
||||
["stone"] = {frequency = 0.20, richness = 1.00, size = 1.50},
|
||||
["trees"] = {frequency = 0.20, richness = 1.00, size = 1.50},
|
||||
["uranium-ore"] = {frequency = 0.20, richness = 1.00, size = 1.50}
|
||||
["coal"] = {frequency = 0.20, richness = 0.50, size = 1.50},
|
||||
["copper-ore"] = {frequency = 0.20, richness = 0.50, size = 1.50},
|
||||
["crude-oil"] = {frequency = 0.20, richness = 0.50, size = 1.50},
|
||||
["enemy-base"] = {frequency = 0.20, richness = 0.50, size = 0.50},
|
||||
["iron-ore"] = {frequency = 0.20, richness = 0.50, size = 1.50},
|
||||
["stone"] = {frequency = 0.20, richness = 0.50, size = 1.50},
|
||||
["trees"] = {frequency = 0.50, richness = 1.00, size = 1.50},
|
||||
["uranium-ore"] = {frequency = 0.20, richness = 0.50, size = 1.50}
|
||||
}
|
||||
|
||||
-- Cliff defaults are 10 and 10, set both to 0 to turn cliffs off I think?
|
||||
@ -390,7 +392,7 @@ global.clMapGen.property_expression_names = {
|
||||
["control-setting:aux:frequency:multiplier"] = "1.00",
|
||||
["control-setting:moisture:bias"] = "0.00",
|
||||
["control-setting:moisture:frequency:multiplier"] = "1.00",
|
||||
elevation = "0_17-islands+continents"
|
||||
-- elevation = "0_17-islands+continents"
|
||||
}
|
||||
|
||||
|
||||
|
30
control.lua
30
control.lua
@ -1,5 +1,5 @@
|
||||
-- control.lua
|
||||
-- Apr 2017
|
||||
-- Mar 2019
|
||||
|
||||
-- Oarc's Separated Spawn Scenario
|
||||
--
|
||||
@ -16,31 +16,31 @@
|
||||
|
||||
|
||||
|
||||
-- To keep the scenario more manageable I have done the following:
|
||||
-- To keep the scenario more manageable (for myself) I have done the following:
|
||||
-- 1. Keep all event calls in control.lua (here)
|
||||
-- 2. Put all config options in config.lua
|
||||
-- 3. Put mods into their own files where possible (RSO has multiple)
|
||||
-- 3. Put other stuff into their own files where possible.
|
||||
|
||||
|
||||
-- Generic Utility Includes
|
||||
require("oarc_utils")
|
||||
-- require("locale/rso/rso_control")
|
||||
-- require("locale/frontier_silo")
|
||||
-- require("locale/tag")
|
||||
-- require("locale/game_opts")
|
||||
require("lib/oarc_utils")
|
||||
-- require("lib/rso/rso_control")
|
||||
-- require("lib/frontier_silo")
|
||||
-- require("lib/tag")
|
||||
require("lib/game_opts")
|
||||
|
||||
-- For Philip. I currently do not use this and need to add proper support for
|
||||
-- commands like this in the future.
|
||||
-- require("locale/temp/rgcommand")
|
||||
-- require("locale/temp/helper_commands")
|
||||
-- require("lib/temp/rgcommand")
|
||||
-- require("lib/temp/helper_commands")
|
||||
|
||||
-- Main Configuration File
|
||||
require("config")
|
||||
|
||||
-- Scenario Specific Includes
|
||||
require("separate_spawns")
|
||||
require("separate_spawns_guis")
|
||||
require("regrowth_map")
|
||||
require("lib/separate_spawns")
|
||||
require("lib/separate_spawns_guis")
|
||||
-- require("regrowth_map")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Rocket Launch Event Code
|
||||
@ -188,7 +188,7 @@ script.on_event(defines.events.on_gui_click, function(event)
|
||||
SharedSpawnJoinWaitMenuClick(event)
|
||||
end
|
||||
|
||||
-- GameOptionsGuiClick(event)
|
||||
GameOptionsGuiClick(event)
|
||||
|
||||
end)
|
||||
|
||||
@ -205,7 +205,7 @@ end)
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_player_joined_game, function(event)
|
||||
|
||||
-- CreateGameOptionsGui(event)
|
||||
CreateGameOptionsGui(event)
|
||||
|
||||
PlayerJoinedMessages(event)
|
||||
|
||||
|
318
lib/frontier_silo.lua
Normal file
318
lib/frontier_silo.lua
Normal file
@ -0,0 +1,318 @@
|
||||
-- frontier_silo.lua
|
||||
-- Jan 2018
|
||||
-- My take on frontier silos for my Oarc scenario
|
||||
|
||||
require("config")
|
||||
require("locale/oarc_utils")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Frontier style rocket silo stuff
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- This creates a random silo position, stored to global.siloPosition
|
||||
-- It uses the config setting SILO_CHUNK_DISTANCE and spawns the silo somewhere
|
||||
-- on a circle edge with radius using that distance.
|
||||
function SetRandomSiloPosition(num_silos)
|
||||
if (global.siloPosition == nil) then
|
||||
|
||||
global.siloPosition = {}
|
||||
|
||||
random_angle_offset = math.random(0, math.pi * 2)
|
||||
|
||||
for i=1,num_silos do
|
||||
theta = ((math.pi * 2) / num_silos);
|
||||
angle = (theta * i) + random_angle_offset;
|
||||
|
||||
tx = (SILO_CHUNK_DISTANCE*CHUNK_SIZE * math.cos(angle))
|
||||
ty = (SILO_CHUNK_DISTANCE*CHUNK_SIZE * math.sin(angle))
|
||||
|
||||
table.insert(global.siloPosition, {x=math.floor(tx), y=math.floor(ty)})
|
||||
|
||||
log("Silo position: " .. tx .. ", " .. ty .. ", " .. angle)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sets the global.siloPosition var to the set in the config file
|
||||
function SetFixedSiloPosition(pos)
|
||||
if (global.siloPosition == nil) then
|
||||
global.siloPosition = {}
|
||||
table.insert(global.siloPosition, SILO_POSITION)
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a rocket silo at the specified positionmmmm
|
||||
-- Also makes sure tiles and entities are cleared if required.
|
||||
local function CreateRocketSilo(surface, siloPosition, force)
|
||||
|
||||
-- Delete any entities beneath the silo?
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = {{siloPosition.x-5,
|
||||
siloPosition.y-6},
|
||||
{siloPosition.x+6,
|
||||
siloPosition.y+6}}}) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
-- Remove nearby enemies again
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = {{siloPosition.x-(CHUNK_SIZE*4),
|
||||
siloPosition.y-(CHUNK_SIZE*4)},
|
||||
{siloPosition.x+(CHUNK_SIZE*4),
|
||||
siloPosition.y+(CHUNK_SIZE*4)}}, force = "enemy"}) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
-- Set tiles below the silo
|
||||
tiles = {}
|
||||
i = 1
|
||||
for dx = -5,5 do
|
||||
for dy = -6,5 do
|
||||
tiles[i] = {name = "concrete", position = {siloPosition.x+dx, siloPosition.y+dy}}
|
||||
i=i+1
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles, true)
|
||||
|
||||
-- Create indestructible silo and assign to a force
|
||||
local silo = surface.create_entity{name = "rocket-silo", position = {siloPosition.x+0.5, siloPosition.y}, force = force}
|
||||
silo.destructible = false
|
||||
silo.minable = false
|
||||
|
||||
-- Make silo safe from being removed by regrowth
|
||||
if ENABLE_REGROWTH then
|
||||
OarcRegrowthOffLimits(siloPosition, 5)
|
||||
end
|
||||
|
||||
|
||||
if ENABLE_SILO_BEACONS then
|
||||
PhilipsBeaconsAndShit(surface, siloPosition, game.forces[MAIN_FORCE])
|
||||
end
|
||||
if ENABLE_SILO_RADAR then
|
||||
PhilipsRadarAndShit(surface, siloPosition, game.forces[MAIN_FORCE])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Generates all rocket silos, should be called after the areas are generated
|
||||
-- Includes a crop circle
|
||||
function GenerateAllSilos(surface)
|
||||
|
||||
-- Create each silo in the list
|
||||
for idx,siloPos in pairs(global.siloPosition) do
|
||||
CreateRocketSilo(surface, siloPos, MAIN_FORCE)
|
||||
end
|
||||
end
|
||||
|
||||
-- Generate clean land and trees around silo area on chunk generate event
|
||||
function GenerateRocketSiloChunk(event)
|
||||
|
||||
-- Silo generation can take awhile depending on the number of silos.
|
||||
if (game.tick < SILO_NUM_SPAWNS*10*TICKS_PER_SECOND) then
|
||||
local surface = event.surface
|
||||
local chunkArea = event.area
|
||||
|
||||
local chunkAreaCenter = {x=chunkArea.left_top.x+(CHUNK_SIZE/2),
|
||||
y=chunkArea.left_top.y+(CHUNK_SIZE/2)}
|
||||
|
||||
for idx,siloPos in pairs(global.siloPosition) do
|
||||
local safeArea = {left_top=
|
||||
{x=siloPos.x-(CHUNK_SIZE*4),
|
||||
y=siloPos.y-(CHUNK_SIZE*4)},
|
||||
right_bottom=
|
||||
{x=siloPos.x+(CHUNK_SIZE*4),
|
||||
y=siloPos.y+(CHUNK_SIZE*4)}}
|
||||
|
||||
|
||||
-- Clear enemies directly next to the rocket
|
||||
if CheckIfInArea(chunkAreaCenter,safeArea) then
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = chunkArea, force = "enemy"}) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
-- Remove trees/resources inside the spawn area
|
||||
RemoveInCircle(surface, chunkArea, "tree", siloPos, ENFORCE_LAND_AREA_TILE_DIST+5)
|
||||
RemoveInCircle(surface, chunkArea, "resource", siloPos, ENFORCE_LAND_AREA_TILE_DIST+5)
|
||||
RemoveInCircle(surface, chunkArea, "cliff", siloPos, ENFORCE_LAND_AREA_TILE_DIST+5)
|
||||
RemoveDecorationsArea(surface, chunkArea)
|
||||
|
||||
-- Create rocket silo
|
||||
CreateCropOctagon(surface, siloPos, chunkArea, CHUNK_SIZE*2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Generate chunks where we plan to place the rocket silos.
|
||||
function GenerateRocketSiloAreas(surface)
|
||||
for idx,siloPos in pairs(global.siloPosition) do
|
||||
if (ENABLE_SILO_VISION) then
|
||||
ChartRocketSiloAreas(surface, game.forces[MAIN_FORCE])
|
||||
end
|
||||
surface.request_to_generate_chunks({siloPos.x, siloPos.y}, 3)
|
||||
end
|
||||
end
|
||||
|
||||
-- Chart chunks where we plan to place the rocket silos.
|
||||
function ChartRocketSiloAreas(surface, force)
|
||||
for idx,siloPos in pairs(global.siloPosition) do
|
||||
force.chart(surface, {{siloPos.x-(CHUNK_SIZE*2),
|
||||
siloPos.y-(CHUNK_SIZE*2)},
|
||||
{siloPos.x+(CHUNK_SIZE*2),
|
||||
siloPos.y+(CHUNK_SIZE*2)}})
|
||||
end
|
||||
end
|
||||
|
||||
global.oarc_silos_generated = false
|
||||
function DelayedSiloCreationOnTick(event)
|
||||
|
||||
-- Delay the creation of the silos so we place them on already generated lands.
|
||||
if (not global.oarc_silos_generated and (game.tick >= SILO_NUM_SPAWNS*10*TICKS_PER_SECOND)) then
|
||||
DebugPrint("Frontier silos generated!")
|
||||
global.oarc_silos_generated = true
|
||||
GenerateAllSilos(game.surfaces[GAME_SURFACE_NAME])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function PhilipsBeaconsAndShit(surface, siloPos, force)
|
||||
|
||||
-- Add Beacons
|
||||
-- x = right, left; y = up, down
|
||||
-- top 1 left 1
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y-9}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-5, siloPos.y-9}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-2, siloPos.y-9}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+2, siloPos.y-9}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 5
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+5, siloPos.y-9}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 6 right 1
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y-9}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-6, siloPos.y-6}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-6, siloPos.y-3}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-6, siloPos.y}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 5
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-6, siloPos.y+3}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 6 bottom 1
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y+6}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 7 bottom 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-5, siloPos.y+6}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+6, siloPos.y-6}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+6, siloPos.y-3}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+6, siloPos.y}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 5
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+6, siloPos.y+3}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 6 bottom 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+5, siloPos.y+6}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 7 bottom 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y+6}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- substations
|
||||
-- top left
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x-8, siloPos.y-6}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
-- top right
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x+9, siloPos.y-6}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
-- bottom left
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x-8, siloPos.y+4}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
-- bottom right
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x+9, siloPos.y+4}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
|
||||
-- end adding beacons
|
||||
end
|
||||
|
||||
function PhilipsRadarAndShit(surface, siloPos, force)
|
||||
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-33, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-33, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-30, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-27, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-24, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-24, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-24, siloPos.y}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-24, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-33, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-30, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-27, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "radar", position = {siloPos.x-33, siloPos.y}, force = force}
|
||||
radar.destructible = false
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x-28, siloPos.y-1}, force = force}
|
||||
substation.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-30, siloPos.y-1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-30, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-30, siloPos.y+1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-28, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-28, siloPos.y+1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-26, siloPos.y-1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-26, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-26, siloPos.y+1}, force = force}
|
||||
radar.destructible = false
|
||||
end
|
145
lib/game_opts.lua
Normal file
145
lib/game_opts.lua
Normal file
@ -0,0 +1,145 @@
|
||||
-- game_opts.lua
|
||||
-- Jan 2018
|
||||
-- Display current game options, maybe have some admin controls here
|
||||
|
||||
-- Main Configuration File
|
||||
require("config")
|
||||
require("lib/oarc_utils")
|
||||
|
||||
function CreateGameOptionsGui(event)
|
||||
local player = game.players[event.player_index]
|
||||
if player.gui.top.game_options == nil then
|
||||
player.gui.top.add{name="game_options", type="button", caption="Info"}
|
||||
end
|
||||
end
|
||||
|
||||
local function ExpandGameOptionsGui(player)
|
||||
local frame = player.gui.left["game_options_panel"]
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
else
|
||||
local frame = player.gui.left.add{type="frame",
|
||||
name="game_options_panel",
|
||||
caption="Server Info:",
|
||||
direction="vertical"}
|
||||
|
||||
-- General Server Info:
|
||||
AddLabel(frame, "info_1", global.welcome_msg, my_longer_label_style)
|
||||
AddLabel(frame, "info_2", SERVER_MSG, my_longer_label_style)
|
||||
AddSpacer(frame, "info_spacer1")
|
||||
|
||||
-- Enemy Settings:
|
||||
local enemy_expansion_txt = "disabled"
|
||||
if game.map_settings.enemy_expansion.enabled then enemy_expansion_txt = "enabled" end
|
||||
|
||||
local enemy_text="Server Run Time: " .. formattime_hours_mins(game.tick) .. "\n" ..
|
||||
"Current Evolution: " .. string.format("%.4f", game.forces["enemy"].evolution_factor) .. "\n" ..
|
||||
"Enemy evolution time factor: " .. game.map_settings.enemy_evolution.time_factor .. "\n" ..
|
||||
"Enemy evolution pollution factor: " .. game.map_settings.enemy_evolution.pollution_factor .. "\n" ..
|
||||
"Enemy evolution destroy factor: " .. game.map_settings.enemy_evolution.destroy_factor .. "\n" ..
|
||||
"Enemy expansion is " .. enemy_expansion_txt
|
||||
|
||||
AddLabel(frame, "enemy_info", enemy_text, my_longer_label_style)
|
||||
AddSpacer(frame, "enemy_info_spacer1")
|
||||
|
||||
-- Game Mode:
|
||||
AddLabel(frame, "core_mod_en", "Core game mode (separate spawns) is enabled.", my_longer_label_style)
|
||||
if (not ENABLE_SEPARATE_SPAWNS) then
|
||||
frame.core_mod_en.caption="Core game mode (separate spawns) is DISABLED."
|
||||
frame.core_mod_en.style.font_color=my_color_red
|
||||
end
|
||||
|
||||
-- Soft Mods:
|
||||
local soft_mods_string = "Oarc Core"
|
||||
if (not ENABLE_SEPARATE_SPAWNS) then
|
||||
soft_mods_string = "Oarc Core [DISABLED!]"
|
||||
end
|
||||
if (ENABLE_RSO) then
|
||||
soft_mods_string = soft_mods_string .. ", RSO"
|
||||
end
|
||||
if (ENABLE_UNDECORATOR) then
|
||||
soft_mods_string = soft_mods_string .. ", Undecorator"
|
||||
end
|
||||
if (ENABLE_TAGS) then
|
||||
soft_mods_string = soft_mods_string .. ", Tags"
|
||||
end
|
||||
if (ENABLE_LONGREACH) then
|
||||
soft_mods_string = soft_mods_string .. ", Long Reach"
|
||||
end
|
||||
if (ENABLE_AUTOFILL) then
|
||||
soft_mods_string = soft_mods_string .. ", Auto Fill"
|
||||
end
|
||||
if (ENABLE_PLAYER_LIST) then
|
||||
soft_mods_string = soft_mods_string .. ", Player List"
|
||||
end
|
||||
|
||||
local game_info_str = "Soft Mods Enabled: " .. soft_mods_string
|
||||
|
||||
-- Spawn options:
|
||||
if (ENABLE_SEPARATE_TEAMS) then
|
||||
game_info_str = game_info_str.."\n".."You are allowed to spawn on your own team (have your own research tree). All teams are friendly!"
|
||||
end
|
||||
if (ENABLE_BUDDY_SPAWN) then
|
||||
game_info_str = game_info_str.."\n".."You can chose to spawn alongside a buddy if you spawn together at the same time."
|
||||
end
|
||||
if (ENABLE_SHARED_SPAWNS) then
|
||||
game_info_str = game_info_str.."\n".."Spawn hosts may choose to share their spawn and allow other players to join them."
|
||||
end
|
||||
if (ENABLE_SEPARATE_TEAMS and ENABLE_SHARED_TEAM_VISION) then
|
||||
game_info_str = game_info_str.."\n".."Everyone (all teams) have shared vision."
|
||||
end
|
||||
if (FRONTIER_ROCKET_SILO_MODE) then
|
||||
game_info_str = game_info_str.."\n".."Silos are NOT craftable. There is at least one already located on the map."
|
||||
end
|
||||
if (ENABLE_REGROWTH) then
|
||||
game_info_str = game_info_str.."\n".."Old parts of the map will slowly be deleted over time (chunks without any player buildings)."
|
||||
end
|
||||
if (ENABLE_POWER_ARMOR_QUICK_START) then
|
||||
game_info_str = game_info_str.."\n".."Power armor quick start enabled."
|
||||
end
|
||||
|
||||
AddLabel(frame, "game_info_label", game_info_str, my_longer_label_style)
|
||||
|
||||
if (ENABLE_ABANDONED_BASE_REMOVAL) then
|
||||
AddLabel(frame, "leave_warning_msg", "If you leave within " .. MIN_ONLINE_TIME_IN_MINUTES .. " minutes of joining, your base and character will be deleted.", my_longer_label_style)
|
||||
frame.leave_warning_msg.style.font_color=my_color_red
|
||||
end
|
||||
|
||||
-- Ending Spacer
|
||||
AddSpacer(frame, "end_spacer")
|
||||
|
||||
-- ADMIN CONTROLS
|
||||
if (player.admin) then
|
||||
player_list = {}
|
||||
for _,player in pairs(game.connected_players) do
|
||||
table.insert(player_list, player.name)
|
||||
end
|
||||
frame.add{name = "ban_players_dropdown",
|
||||
type = "drop-down",
|
||||
items = player_list}
|
||||
frame.add{name="ban_player", type="button", caption="Ban Player"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GameOptionsGuiClick(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 == "game_options") then
|
||||
ExpandGameOptionsGui(player)
|
||||
end
|
||||
|
||||
if (name == "ban_player") then
|
||||
banIndex = event.element.parent.ban_players_dropdown.selected_index
|
||||
|
||||
if (banIndex ~= 0) then
|
||||
banPlayer = event.element.parent.ban_players_dropdown.get_item(banIndex)
|
||||
if (game.players[banPlayer]) then
|
||||
game.ban_player(banPlayer, "Banned for griefing - Banned from admin panel.")
|
||||
DebugPrint("Banning " .. banPlayer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
67
lib/helper_commands.lua
Normal file
67
lib/helper_commands.lua
Normal file
@ -0,0 +1,67 @@
|
||||
-- helper_commands.lua
|
||||
-- Jan 2018
|
||||
-- None of this is my code.
|
||||
|
||||
require("locale/oarc_utils")
|
||||
|
||||
commands.add_command("run", "change player speed bonus", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "fast" then
|
||||
player.character_running_speed_modifier = 1
|
||||
elseif command.parameter == "slow" then
|
||||
player.character_running_speed_modifier = 0
|
||||
else
|
||||
player.print("run fast | slow");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command("handcraft", "change player speed bonus", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "fast" then
|
||||
player.character_crafting_speed_modifier = 5
|
||||
elseif command.parameter == "slow" then
|
||||
player.character_crafting_speed_modifier = 0
|
||||
else
|
||||
player.print("handcraft fast | slow");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command("mine", "change player speed bonus", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "fast" then
|
||||
player.character_mining_speed_modifier = 2
|
||||
elseif command.parameter == "slow" then
|
||||
player.character_mining_speed_modifier = 0
|
||||
else
|
||||
player.print("mine fast | slow");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command("kit", "give a start kit", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil and player.admin then
|
||||
local target = player
|
||||
if (command.parameter ~= nil) then
|
||||
target = game.players[command.parameter]
|
||||
end
|
||||
if target ~= nil then
|
||||
GivePlayerStarterItems(target);
|
||||
player.print("gave a kit to " .. target.name);
|
||||
target.print("you have been given a start kit");
|
||||
else
|
||||
player.print("no player " .. command.parameter);
|
||||
end
|
||||
end
|
||||
end)
|
@ -1018,7 +1018,7 @@ function CreateMoat(surface, centerPos, chunkArea, tileRadius)
|
||||
-- Create a circle of water
|
||||
if ((distVar < tileRadSqr+(1500*MOAT_SIZE_MODIFIER)) and
|
||||
(distVar > tileRadSqr)) then
|
||||
table.insert(waterTiles, {name = "water-shallow", position ={i,j}})
|
||||
table.insert(waterTiles, {name = "water", position ={i,j}})
|
||||
end
|
||||
|
||||
-- Enforce land inside the edges of the circle to make sure it's
|
||||
@ -1146,7 +1146,7 @@ function SetupAndClearSpawnAreas(surface, chunkArea, spawnPointTable)
|
||||
RemoveInCircle(surface, chunkArea, "tree", spawn.pos, ENFORCE_LAND_AREA_TILE_DIST)
|
||||
RemoveInCircle(surface, chunkArea, "resource", spawn.pos, ENFORCE_LAND_AREA_TILE_DIST+5)
|
||||
RemoveInCircle(surface, chunkArea, "cliff", spawn.pos, ENFORCE_LAND_AREA_TILE_DIST+5)
|
||||
RemoveDecorationsArea(surface, chunkArea)
|
||||
-- RemoveDecorationsArea(surface, chunkArea)
|
||||
|
||||
if (SPAWN_TREE_CIRCLE_ENABLED) then
|
||||
CreateCropCircle(surface, spawn.pos, chunkArea, ENFORCE_LAND_AREA_TILE_DIST)
|
@ -1,349 +1,349 @@
|
||||
-- regrowth_map.lua
|
||||
-- July 2017
|
||||
--
|
||||
-- Code tracks all chunks generated and allows for deleting inactive chunks
|
||||
-- Relies on some changes to RSO to provide random resource locations the next
|
||||
-- time the land is regenerated. -- (THIS IS CURRENTLY NOT WORKING IN 0.16,
|
||||
-- resources always how up in the same spot!)
|
||||
--
|
||||
-- Basic rules of regrowth:
|
||||
-- 1. Area around player is safe for quite a large distance.
|
||||
-- 2. Rocket silo won't be deleted. - PERMANENT
|
||||
-- 3. Chunks with pollution won't be deleted.
|
||||
-- 4. Chunks with railways won't be deleted.
|
||||
-- 5. Anything within radar range won't be deleted, but radar MUST be active.
|
||||
-- -- This works by refreshing all chunk timers within radar range using
|
||||
-- the on_sector_scanned event.
|
||||
-- 6. Chunks timeout after 1 hour-ish, configurable
|
||||
-- 7. For now, oarc spawns are deletion safe as well, but only immediate area.
|
||||
|
||||
-- Generic Utility Includes
|
||||
require("oarc_utils")
|
||||
|
||||
|
||||
-- Default timeout of generated chunks
|
||||
REGROWTH_TIMEOUT_TICKS = TICKS_PER_HOUR
|
||||
|
||||
-- We can't delete chunks regularly without causing lag.
|
||||
-- So we should save them up to delete them.
|
||||
REGROWTH_CLEANING_INTERVAL_TICKS = REGROWTH_TIMEOUT_TICKS
|
||||
|
||||
-- Not used right now.
|
||||
-- It takes a radar 7 hours and 20 minutes to scan it's whole area completely
|
||||
-- So I will bump the refresh time of blocks up by 8 hours
|
||||
-- RADAR_COMPLETE_SCAN_TICKS = TICKS_PER_HOUR*8
|
||||
-- Additional bonus time for certain things:
|
||||
-- REFRESH_BONUS_RADAR = RADAR_COMPLETE_SCAN_TICKS
|
||||
|
||||
|
||||
-- Init globals and set player join area to be off limits.
|
||||
function OarcRegrowthInit()
|
||||
global.chunk_regrow = {}
|
||||
global.chunk_regrow.map = {}
|
||||
global.chunk_regrow.removal_list = {}
|
||||
global.chunk_regrow.rso_region_roll_counter = 0
|
||||
global.chunk_regrow.player_refresh_index = 1
|
||||
global.chunk_regrow.min_x = 0
|
||||
global.chunk_regrow.max_x = 0
|
||||
global.chunk_regrow.x_index = 0
|
||||
global.chunk_regrow.min_y = 0
|
||||
global.chunk_regrow.max_y = 0
|
||||
global.chunk_regrow.y_index = 0
|
||||
global.chunk_regrow.force_removal_flag = -1000
|
||||
|
||||
OarcRegrowthOffLimits({x=0,y=0}, 10)
|
||||
end
|
||||
|
||||
function GetChunkTopLeft(pos)
|
||||
return {x=pos.x-(pos.x % 32), y=pos.y-(pos.y % 32)}
|
||||
end
|
||||
|
||||
function GetChunkCoordsFromPos(pos)
|
||||
return {x=math.floor(pos.x/32), y=math.floor(pos.y/32)}
|
||||
end
|
||||
|
||||
-- This complicated function checks that if a chunk
|
||||
function CheckChunkEmpty(pos)
|
||||
chunkPos = GetChunkCoordsFromPos(pos)
|
||||
search_top_left = {x=chunkPos.x*32, y=chunkPos.y*32}
|
||||
search_area = {search_top_left, {x=search_top_left.x+32,y=search_top_left.y+32}}
|
||||
total = 0
|
||||
for f,_ in pairs(game.forces) do
|
||||
if f ~= "neutral" and f ~= "enemy" then
|
||||
entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area = search_area, force=f}
|
||||
total = total + #entities
|
||||
if (#entities > 0) then
|
||||
|
||||
for _,e in pairs(entities) do
|
||||
if ((e.type == "player") or
|
||||
(e.type == "car") or
|
||||
(e.type == "logistic-robot") or
|
||||
(e.type == "construction-robot")) then
|
||||
total = total - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- A destroyed entity is still found during the event check.
|
||||
return (total == 1)
|
||||
end
|
||||
|
||||
-- game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area = {game.player.position, {game.player.position.x+32, game.player.position-`32}}, type= "resource"}
|
||||
|
||||
-- If an entity is mined or destroyed, then check if the chunk
|
||||
-- is empty. If it's empty, reset the refresh timer.
|
||||
function OarcRegrowthCheckChunkEmpty(event)
|
||||
if ((event.entity.force ~= nil) and (event.entity.force ~= "neutral") and (event.entity.force ~= "enemy")) then
|
||||
if CheckChunkEmpty(event.entity.position) then
|
||||
DebugPrint("Resetting chunk timer."..event.entity.position.x.." "..event.entity.position.y)
|
||||
OarcRegrowthForceRefreshChunk(event.entity.position, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Adds new chunks to the global table to track them.
|
||||
-- This should always be called first in the chunk generate sequence
|
||||
-- (Compared to other RSO & Oarc related functions...)
|
||||
function OarcRegrowthChunkGenerate(pos)
|
||||
|
||||
c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
-- If this is the first chunk in that row:
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.x] = {}
|
||||
end
|
||||
|
||||
-- Confirm the chunk doesn't already have a value set:
|
||||
if (global.chunk_regrow.map[c_pos.x][c_pos.y] == nil) then
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick
|
||||
end
|
||||
|
||||
-- Store min/max values for x/y dimensions:
|
||||
if (c_pos.x < global.chunk_regrow.min_x) then
|
||||
global.chunk_regrow.min_x = c_pos.x
|
||||
end
|
||||
if (c_pos.x > global.chunk_regrow.max_x) then
|
||||
global.chunk_regrow.max_x = c_pos.x
|
||||
end
|
||||
if (c_pos.y < global.chunk_regrow.min_y) then
|
||||
global.chunk_regrow.min_y = c_pos.y
|
||||
end
|
||||
if (c_pos.y > global.chunk_regrow.max_y) then
|
||||
global.chunk_regrow.max_y = c_pos.y
|
||||
end
|
||||
end
|
||||
|
||||
-- Mark an area for immediate forced removal
|
||||
function OarcRegrowthMarkForRemoval(pos, chunk_radius)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.chunk_regrow.map[x] == nil) then
|
||||
global.chunk_regrow.map[x] = {}
|
||||
end
|
||||
global.chunk_regrow.map[x][y] = nil
|
||||
table.insert(global.chunk_regrow.removal_list, {x=x,y=y})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Marks a chunk a position that won't ever be deleted.
|
||||
function OarcRegrowthOffLimitsChunk(pos)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.y] = {}
|
||||
end
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = -1
|
||||
end
|
||||
|
||||
|
||||
-- Marks a safe area around a position that won't ever be deleted.
|
||||
function OarcRegrowthOffLimits(pos, chunk_radius)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.chunk_regrow.map[x] == nil) then
|
||||
global.chunk_regrow.map[x] = {}
|
||||
end
|
||||
global.chunk_regrow.map[x][y] = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Refreshes timers on a chunk containing position
|
||||
function OarcRegrowthRefreshChunk(pos, bonus_time)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.y] = {}
|
||||
end
|
||||
if (global.chunk_regrow.map[c_pos.x][c_pos.y] ~= -1) then
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick + bonus_time
|
||||
end
|
||||
end
|
||||
|
||||
-- Forcefully refreshes timers on a chunk containing position
|
||||
-- Will overwrite -1 flag.
|
||||
function OarcRegrowthForceRefreshChunk(pos, bonus_time)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.y] = {}
|
||||
end
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick + bonus_time
|
||||
end
|
||||
|
||||
-- Refreshes timers on all chunks around a certain area
|
||||
function OarcRegrowthRefreshArea(pos, chunk_radius, bonus_time)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.chunk_regrow.map[x] == nil) then
|
||||
global.chunk_regrow.map[x] = {}
|
||||
end
|
||||
if (global.chunk_regrow.map[x][y] ~= -1) then
|
||||
global.chunk_regrow.map[x][y] = game.tick + bonus_time
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Refreshes timers on all chunks near an ACTIVE radar
|
||||
function OarcRegrowthSectorScan(event)
|
||||
OarcRegrowthRefreshArea(event.radar.position, 14, 0)
|
||||
OarcRegrowthRefreshChunk(event.chunk_position, 0)
|
||||
end
|
||||
|
||||
-- Refresh all chunks near a single player. Cyles through all connected players.
|
||||
function OarcRegrowthRefreshPlayerArea()
|
||||
global.chunk_regrow.player_refresh_index = global.chunk_regrow.player_refresh_index + 1
|
||||
if (global.chunk_regrow.player_refresh_index > #game.connected_players) then
|
||||
global.chunk_regrow.player_refresh_index = 1
|
||||
end
|
||||
if (game.connected_players[global.chunk_regrow.player_refresh_index]) then
|
||||
OarcRegrowthRefreshArea(game.connected_players[global.chunk_regrow.player_refresh_index].position, 4, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Check each chunk in the 2d array for a timeout value
|
||||
function OarcRegrowthCheckArray()
|
||||
|
||||
-- Increment X
|
||||
if (global.chunk_regrow.x_index > global.chunk_regrow.max_x) then
|
||||
global.chunk_regrow.x_index = global.chunk_regrow.min_x
|
||||
|
||||
-- Increment Y
|
||||
if (global.chunk_regrow.y_index > global.chunk_regrow.max_y) then
|
||||
global.chunk_regrow.y_index = global.chunk_regrow.min_y
|
||||
DebugPrint("Finished checking regrowth array."..global.chunk_regrow.min_x.." "..global.chunk_regrow.max_x.." "..global.chunk_regrow.min_y.." "..global.chunk_regrow.max_y)
|
||||
else
|
||||
global.chunk_regrow.y_index = global.chunk_regrow.y_index + 1
|
||||
end
|
||||
else
|
||||
global.chunk_regrow.x_index = global.chunk_regrow.x_index + 1
|
||||
end
|
||||
|
||||
-- Check row exists, otherwise make one.
|
||||
if (global.chunk_regrow.map[global.chunk_regrow.x_index] == nil) then
|
||||
global.chunk_regrow.map[global.chunk_regrow.x_index] = {}
|
||||
end
|
||||
|
||||
-- If the chunk has timed out, add it to the removal list
|
||||
local c_timer = global.chunk_regrow.map[global.chunk_regrow.x_index][global.chunk_regrow.y_index]
|
||||
if ((c_timer ~= nil) and (c_timer ~= -1) and ((c_timer+REGROWTH_TIMEOUT_TICKS) < game.tick)) then
|
||||
|
||||
-- Check chunk actually exists
|
||||
if (game.surfaces[GAME_SURFACE_NAME].is_chunk_generated({x=(global.chunk_regrow.x_index),
|
||||
y=(global.chunk_regrow.y_index)})) then
|
||||
table.insert(global.chunk_regrow.removal_list, {x=global.chunk_regrow.x_index,
|
||||
y=global.chunk_regrow.y_index})
|
||||
global.chunk_regrow.map[global.chunk_regrow.x_index][global.chunk_regrow.y_index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove all chunks at same time to reduce impact to FPS/UPS
|
||||
function OarcRegrowthRemoveAllChunks()
|
||||
while (#global.chunk_regrow.removal_list > 0) do
|
||||
local c_pos = table.remove(global.chunk_regrow.removal_list)
|
||||
local c_timer = global.chunk_regrow.map[c_pos.x][c_pos.y]
|
||||
|
||||
-- Confirm chunk is still expired
|
||||
if (c_timer == nil) then
|
||||
|
||||
-- Check for pollution
|
||||
if (game.surfaces[GAME_SURFACE_NAME].get_pollution({c_pos.x*32,c_pos.y*32}) > 0) then
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick
|
||||
|
||||
-- Else delete the chunk
|
||||
else
|
||||
game.surfaces[GAME_SURFACE_NAME].delete_chunk(c_pos)
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = nil
|
||||
end
|
||||
else
|
||||
|
||||
-- DebugPrint("Chunk no longer expired?")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This is the main work function, it checks a single chunk in the list
|
||||
-- per tick. It works according to the rules listed in the header of this
|
||||
-- file.
|
||||
function OarcRegrowthOnTick()
|
||||
|
||||
-- Every half a second, refresh all chunks near a single player
|
||||
-- Cyles through all players. Tick is offset by 2
|
||||
if ((game.tick % (30)) == 2) then
|
||||
OarcRegrowthRefreshPlayerArea()
|
||||
end
|
||||
|
||||
-- Every tick, check a few points in the 2d array
|
||||
-- According to /measured-command this shouldn't take more
|
||||
-- than 0.1ms on average
|
||||
for i=1,20 do
|
||||
OarcRegrowthCheckArray()
|
||||
end
|
||||
|
||||
-- Send a broadcast warning before it happens.
|
||||
if ((game.tick % REGROWTH_CLEANING_INTERVAL_TICKS) == REGROWTH_CLEANING_INTERVAL_TICKS-601) then
|
||||
if (#global.chunk_regrow.removal_list > 100) then
|
||||
SendBroadcastMsg("Map cleanup in 10 seconds, if you don't want to lose what you found drop a powered radar on it!")
|
||||
end
|
||||
end
|
||||
|
||||
-- Delete all listed chunks
|
||||
if ((game.tick % REGROWTH_CLEANING_INTERVAL_TICKS) == REGROWTH_CLEANING_INTERVAL_TICKS-1) then
|
||||
if (#global.chunk_regrow.removal_list > 100) then
|
||||
OarcRegrowthRemoveAllChunks()
|
||||
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function removes any chunks flagged but on demand.
|
||||
-- Controlled by the global.chunk_regrow.force_removal_flag
|
||||
-- This function may be used outside of the normal regrowth modse.
|
||||
function OarcRegrowthForceRemovalOnTick()
|
||||
-- Catch force remove flag
|
||||
if (game.tick == global.chunk_regrow.force_removal_flag+60) then
|
||||
SendBroadcastMsg("Map cleanup in 10 seconds, if you don't want to lose what you found drop a powered radar on it!")
|
||||
end
|
||||
if (game.tick == global.chunk_regrow.force_removal_flag+660) then
|
||||
OarcRegrowthRemoveAllChunks()
|
||||
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
|
||||
end
|
||||
-- regrowth_map.lua
|
||||
-- July 2017
|
||||
--
|
||||
-- Code tracks all chunks generated and allows for deleting inactive chunks
|
||||
-- Relies on some changes to RSO to provide random resource locations the next
|
||||
-- time the land is regenerated. -- (THIS IS CURRENTLY NOT WORKING IN 0.16,
|
||||
-- resources always how up in the same spot!)
|
||||
--
|
||||
-- Basic rules of regrowth:
|
||||
-- 1. Area around player is safe for quite a large distance.
|
||||
-- 2. Rocket silo won't be deleted. - PERMANENT
|
||||
-- 3. Chunks with pollution won't be deleted.
|
||||
-- 4. Chunks with railways won't be deleted.
|
||||
-- 5. Anything within radar range won't be deleted, but radar MUST be active.
|
||||
-- -- This works by refreshing all chunk timers within radar range using
|
||||
-- the on_sector_scanned event.
|
||||
-- 6. Chunks timeout after 1 hour-ish, configurable
|
||||
-- 7. For now, oarc spawns are deletion safe as well, but only immediate area.
|
||||
|
||||
-- Generic Utility Includes
|
||||
require("lib/oarc_utils")
|
||||
|
||||
|
||||
-- Default timeout of generated chunks
|
||||
REGROWTH_TIMEOUT_TICKS = TICKS_PER_HOUR
|
||||
|
||||
-- We can't delete chunks regularly without causing lag.
|
||||
-- So we should save them up to delete them.
|
||||
REGROWTH_CLEANING_INTERVAL_TICKS = REGROWTH_TIMEOUT_TICKS
|
||||
|
||||
-- Not used right now.
|
||||
-- It takes a radar 7 hours and 20 minutes to scan it's whole area completely
|
||||
-- So I will bump the refresh time of blocks up by 8 hours
|
||||
-- RADAR_COMPLETE_SCAN_TICKS = TICKS_PER_HOUR*8
|
||||
-- Additional bonus time for certain things:
|
||||
-- REFRESH_BONUS_RADAR = RADAR_COMPLETE_SCAN_TICKS
|
||||
|
||||
|
||||
-- Init globals and set player join area to be off limits.
|
||||
function OarcRegrowthInit()
|
||||
global.chunk_regrow = {}
|
||||
global.chunk_regrow.map = {}
|
||||
global.chunk_regrow.removal_list = {}
|
||||
global.chunk_regrow.rso_region_roll_counter = 0
|
||||
global.chunk_regrow.player_refresh_index = 1
|
||||
global.chunk_regrow.min_x = 0
|
||||
global.chunk_regrow.max_x = 0
|
||||
global.chunk_regrow.x_index = 0
|
||||
global.chunk_regrow.min_y = 0
|
||||
global.chunk_regrow.max_y = 0
|
||||
global.chunk_regrow.y_index = 0
|
||||
global.chunk_regrow.force_removal_flag = -1000
|
||||
|
||||
OarcRegrowthOffLimits({x=0,y=0}, 10)
|
||||
end
|
||||
|
||||
function GetChunkTopLeft(pos)
|
||||
return {x=pos.x-(pos.x % 32), y=pos.y-(pos.y % 32)}
|
||||
end
|
||||
|
||||
function GetChunkCoordsFromPos(pos)
|
||||
return {x=math.floor(pos.x/32), y=math.floor(pos.y/32)}
|
||||
end
|
||||
|
||||
-- This complicated function checks that if a chunk
|
||||
function CheckChunkEmpty(pos)
|
||||
chunkPos = GetChunkCoordsFromPos(pos)
|
||||
search_top_left = {x=chunkPos.x*32, y=chunkPos.y*32}
|
||||
search_area = {search_top_left, {x=search_top_left.x+32,y=search_top_left.y+32}}
|
||||
total = 0
|
||||
for f,_ in pairs(game.forces) do
|
||||
if f ~= "neutral" and f ~= "enemy" then
|
||||
entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area = search_area, force=f}
|
||||
total = total + #entities
|
||||
if (#entities > 0) then
|
||||
|
||||
for _,e in pairs(entities) do
|
||||
if ((e.type == "player") or
|
||||
(e.type == "car") or
|
||||
(e.type == "logistic-robot") or
|
||||
(e.type == "construction-robot")) then
|
||||
total = total - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- A destroyed entity is still found during the event check.
|
||||
return (total == 1)
|
||||
end
|
||||
|
||||
-- game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area = {game.player.position, {game.player.position.x+32, game.player.position-`32}}, type= "resource"}
|
||||
|
||||
-- If an entity is mined or destroyed, then check if the chunk
|
||||
-- is empty. If it's empty, reset the refresh timer.
|
||||
function OarcRegrowthCheckChunkEmpty(event)
|
||||
if ((event.entity.force ~= nil) and (event.entity.force ~= "neutral") and (event.entity.force ~= "enemy")) then
|
||||
if CheckChunkEmpty(event.entity.position) then
|
||||
DebugPrint("Resetting chunk timer."..event.entity.position.x.." "..event.entity.position.y)
|
||||
OarcRegrowthForceRefreshChunk(event.entity.position, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Adds new chunks to the global table to track them.
|
||||
-- This should always be called first in the chunk generate sequence
|
||||
-- (Compared to other RSO & Oarc related functions...)
|
||||
function OarcRegrowthChunkGenerate(pos)
|
||||
|
||||
c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
-- If this is the first chunk in that row:
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.x] = {}
|
||||
end
|
||||
|
||||
-- Confirm the chunk doesn't already have a value set:
|
||||
if (global.chunk_regrow.map[c_pos.x][c_pos.y] == nil) then
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick
|
||||
end
|
||||
|
||||
-- Store min/max values for x/y dimensions:
|
||||
if (c_pos.x < global.chunk_regrow.min_x) then
|
||||
global.chunk_regrow.min_x = c_pos.x
|
||||
end
|
||||
if (c_pos.x > global.chunk_regrow.max_x) then
|
||||
global.chunk_regrow.max_x = c_pos.x
|
||||
end
|
||||
if (c_pos.y < global.chunk_regrow.min_y) then
|
||||
global.chunk_regrow.min_y = c_pos.y
|
||||
end
|
||||
if (c_pos.y > global.chunk_regrow.max_y) then
|
||||
global.chunk_regrow.max_y = c_pos.y
|
||||
end
|
||||
end
|
||||
|
||||
-- Mark an area for immediate forced removal
|
||||
function OarcRegrowthMarkForRemoval(pos, chunk_radius)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.chunk_regrow.map[x] == nil) then
|
||||
global.chunk_regrow.map[x] = {}
|
||||
end
|
||||
global.chunk_regrow.map[x][y] = nil
|
||||
table.insert(global.chunk_regrow.removal_list, {x=x,y=y})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Marks a chunk a position that won't ever be deleted.
|
||||
function OarcRegrowthOffLimitsChunk(pos)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.y] = {}
|
||||
end
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = -1
|
||||
end
|
||||
|
||||
|
||||
-- Marks a safe area around a position that won't ever be deleted.
|
||||
function OarcRegrowthOffLimits(pos, chunk_radius)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.chunk_regrow.map[x] == nil) then
|
||||
global.chunk_regrow.map[x] = {}
|
||||
end
|
||||
global.chunk_regrow.map[x][y] = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Refreshes timers on a chunk containing position
|
||||
function OarcRegrowthRefreshChunk(pos, bonus_time)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.y] = {}
|
||||
end
|
||||
if (global.chunk_regrow.map[c_pos.x][c_pos.y] ~= -1) then
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick + bonus_time
|
||||
end
|
||||
end
|
||||
|
||||
-- Forcefully refreshes timers on a chunk containing position
|
||||
-- Will overwrite -1 flag.
|
||||
function OarcRegrowthForceRefreshChunk(pos, bonus_time)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
if (global.chunk_regrow.map[c_pos.x] == nil) then
|
||||
global.chunk_regrow.map[c_pos.y] = {}
|
||||
end
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick + bonus_time
|
||||
end
|
||||
|
||||
-- Refreshes timers on all chunks around a certain area
|
||||
function OarcRegrowthRefreshArea(pos, chunk_radius, bonus_time)
|
||||
local c_pos = GetChunkCoordsFromPos(pos)
|
||||
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.chunk_regrow.map[x] == nil) then
|
||||
global.chunk_regrow.map[x] = {}
|
||||
end
|
||||
if (global.chunk_regrow.map[x][y] ~= -1) then
|
||||
global.chunk_regrow.map[x][y] = game.tick + bonus_time
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Refreshes timers on all chunks near an ACTIVE radar
|
||||
function OarcRegrowthSectorScan(event)
|
||||
OarcRegrowthRefreshArea(event.radar.position, 14, 0)
|
||||
OarcRegrowthRefreshChunk(event.chunk_position, 0)
|
||||
end
|
||||
|
||||
-- Refresh all chunks near a single player. Cyles through all connected players.
|
||||
function OarcRegrowthRefreshPlayerArea()
|
||||
global.chunk_regrow.player_refresh_index = global.chunk_regrow.player_refresh_index + 1
|
||||
if (global.chunk_regrow.player_refresh_index > #game.connected_players) then
|
||||
global.chunk_regrow.player_refresh_index = 1
|
||||
end
|
||||
if (game.connected_players[global.chunk_regrow.player_refresh_index]) then
|
||||
OarcRegrowthRefreshArea(game.connected_players[global.chunk_regrow.player_refresh_index].position, 4, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Check each chunk in the 2d array for a timeout value
|
||||
function OarcRegrowthCheckArray()
|
||||
|
||||
-- Increment X
|
||||
if (global.chunk_regrow.x_index > global.chunk_regrow.max_x) then
|
||||
global.chunk_regrow.x_index = global.chunk_regrow.min_x
|
||||
|
||||
-- Increment Y
|
||||
if (global.chunk_regrow.y_index > global.chunk_regrow.max_y) then
|
||||
global.chunk_regrow.y_index = global.chunk_regrow.min_y
|
||||
DebugPrint("Finished checking regrowth array."..global.chunk_regrow.min_x.." "..global.chunk_regrow.max_x.." "..global.chunk_regrow.min_y.." "..global.chunk_regrow.max_y)
|
||||
else
|
||||
global.chunk_regrow.y_index = global.chunk_regrow.y_index + 1
|
||||
end
|
||||
else
|
||||
global.chunk_regrow.x_index = global.chunk_regrow.x_index + 1
|
||||
end
|
||||
|
||||
-- Check row exists, otherwise make one.
|
||||
if (global.chunk_regrow.map[global.chunk_regrow.x_index] == nil) then
|
||||
global.chunk_regrow.map[global.chunk_regrow.x_index] = {}
|
||||
end
|
||||
|
||||
-- If the chunk has timed out, add it to the removal list
|
||||
local c_timer = global.chunk_regrow.map[global.chunk_regrow.x_index][global.chunk_regrow.y_index]
|
||||
if ((c_timer ~= nil) and (c_timer ~= -1) and ((c_timer+REGROWTH_TIMEOUT_TICKS) < game.tick)) then
|
||||
|
||||
-- Check chunk actually exists
|
||||
if (game.surfaces[GAME_SURFACE_NAME].is_chunk_generated({x=(global.chunk_regrow.x_index),
|
||||
y=(global.chunk_regrow.y_index)})) then
|
||||
table.insert(global.chunk_regrow.removal_list, {x=global.chunk_regrow.x_index,
|
||||
y=global.chunk_regrow.y_index})
|
||||
global.chunk_regrow.map[global.chunk_regrow.x_index][global.chunk_regrow.y_index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove all chunks at same time to reduce impact to FPS/UPS
|
||||
function OarcRegrowthRemoveAllChunks()
|
||||
while (#global.chunk_regrow.removal_list > 0) do
|
||||
local c_pos = table.remove(global.chunk_regrow.removal_list)
|
||||
local c_timer = global.chunk_regrow.map[c_pos.x][c_pos.y]
|
||||
|
||||
-- Confirm chunk is still expired
|
||||
if (c_timer == nil) then
|
||||
|
||||
-- Check for pollution
|
||||
if (game.surfaces[GAME_SURFACE_NAME].get_pollution({c_pos.x*32,c_pos.y*32}) > 0) then
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = game.tick
|
||||
|
||||
-- Else delete the chunk
|
||||
else
|
||||
game.surfaces[GAME_SURFACE_NAME].delete_chunk(c_pos)
|
||||
global.chunk_regrow.map[c_pos.x][c_pos.y] = nil
|
||||
end
|
||||
else
|
||||
|
||||
-- DebugPrint("Chunk no longer expired?")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This is the main work function, it checks a single chunk in the list
|
||||
-- per tick. It works according to the rules listed in the header of this
|
||||
-- file.
|
||||
function OarcRegrowthOnTick()
|
||||
|
||||
-- Every half a second, refresh all chunks near a single player
|
||||
-- Cyles through all players. Tick is offset by 2
|
||||
if ((game.tick % (30)) == 2) then
|
||||
OarcRegrowthRefreshPlayerArea()
|
||||
end
|
||||
|
||||
-- Every tick, check a few points in the 2d array
|
||||
-- According to /measured-command this shouldn't take more
|
||||
-- than 0.1ms on average
|
||||
for i=1,20 do
|
||||
OarcRegrowthCheckArray()
|
||||
end
|
||||
|
||||
-- Send a broadcast warning before it happens.
|
||||
if ((game.tick % REGROWTH_CLEANING_INTERVAL_TICKS) == REGROWTH_CLEANING_INTERVAL_TICKS-601) then
|
||||
if (#global.chunk_regrow.removal_list > 100) then
|
||||
SendBroadcastMsg("Map cleanup in 10 seconds, if you don't want to lose what you found drop a powered radar on it!")
|
||||
end
|
||||
end
|
||||
|
||||
-- Delete all listed chunks
|
||||
if ((game.tick % REGROWTH_CLEANING_INTERVAL_TICKS) == REGROWTH_CLEANING_INTERVAL_TICKS-1) then
|
||||
if (#global.chunk_regrow.removal_list > 100) then
|
||||
OarcRegrowthRemoveAllChunks()
|
||||
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function removes any chunks flagged but on demand.
|
||||
-- Controlled by the global.chunk_regrow.force_removal_flag
|
||||
-- This function may be used outside of the normal regrowth modse.
|
||||
function OarcRegrowthForceRemovalOnTick()
|
||||
-- Catch force remove flag
|
||||
if (game.tick == global.chunk_regrow.force_removal_flag+60) then
|
||||
SendBroadcastMsg("Map cleanup in 10 seconds, if you don't want to lose what you found drop a powered radar on it!")
|
||||
end
|
||||
if (game.tick == global.chunk_regrow.force_removal_flag+660) then
|
||||
OarcRegrowthRemoveAllChunks()
|
||||
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
|
||||
end
|
||||
end
|
49
lib/rgcommand.lua
Normal file
49
lib/rgcommand.lua
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
local function RemoveTileGhosts()
|
||||
local surface = game.player.surface
|
||||
for c in surface.get_chunks() do
|
||||
for key, entity in pairs(surface.find_entities_filtered({area={{c.x * 32, c.y * 32}, {c.x * 32 + 32, c.y * 32 + 32}}, name= "tile-ghost"})) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function RemoveBlueprintedModulesGhosts()
|
||||
local surface = game.player.surface
|
||||
for c in surface.get_chunks() do
|
||||
for key, entity in pairs(surface.find_entities_filtered({area={{c.x * 32, c.y * 32}, {c.x * 32 + 32, c.y * 32 + 32}}, name= "item-request-proxy"})) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function RemoveGhostEntities()
|
||||
local surface = game.player.surface
|
||||
for c in surface.get_chunks() do
|
||||
for key, entity in pairs(surface.find_entities_filtered({area={{c.x * 32, c.y * 32}, {c.x * 32 + 32, c.y * 32 + 32}}, name= "entity-ghost"})) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
commands.add_command("rg", "remove ghosts", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil and player.admin then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "all" then
|
||||
RemoveTileGhosts()
|
||||
RemoveBlueprintedModulesGhosts()
|
||||
RemoveGhostEntities()
|
||||
elseif command.parameter == "tiles" then
|
||||
RemoveTileGhosts()
|
||||
elseif command.parameter == "modules" then
|
||||
RemoveBlueprintedModulesGhosts()
|
||||
elseif command.parameter == "entities" then
|
||||
RemoveGhostEntities()
|
||||
else
|
||||
player.print("remove all ghostes | tiles | modules | entities");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
@ -1,392 +1,392 @@
|
||||
-- separate_spawns.lua
|
||||
-- Nov 2016
|
||||
--
|
||||
-- Code that handles everything regarding giving each player a separate spawn
|
||||
-- Includes the GUI stuff
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- EVENT RELATED FUNCTIONS
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 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.
|
||||
function SeparateSpawnsPlayerCreated(event)
|
||||
local player = game.players[event.player_index]
|
||||
player.force = MAIN_FORCE
|
||||
DisplayWelcomeTextGui(player)
|
||||
end
|
||||
|
||||
|
||||
-- Check if the player has a different spawn point than the default one
|
||||
-- Make sure to give the default starting items
|
||||
function SeparateSpawnsPlayerRespawned(event)
|
||||
local player = game.players[event.player_index]
|
||||
SendPlayerToSpawn(player)
|
||||
end
|
||||
|
||||
|
||||
-- This is the main function that creates the spawn area
|
||||
-- Provides resources, land and a safe zone
|
||||
function SeparateSpawnsGenerateChunk(event)
|
||||
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.
|
||||
SetupAndClearSpawnAreas(surface, chunkArea, global.uniqueSpawns)
|
||||
end
|
||||
|
||||
|
||||
-- Call this if a player leaves the game
|
||||
-- Still seems to have a bug.
|
||||
function FindUnusedSpawns(event)
|
||||
local player = game.players[event.player_index]
|
||||
if (player.online_time < MIN_ONLINE_TIME) then
|
||||
|
||||
DropGravestoneChests(player)
|
||||
|
||||
-- Clear out global variables for that player
|
||||
if (global.playerSpawns[player.name] ~= nil) then
|
||||
global.playerSpawns[player.name] = nil
|
||||
end
|
||||
|
||||
-- Remove them from the delayer spawn queue if they are in it
|
||||
for i=#global.delayedSpawns,1,-1 do
|
||||
delayedSpawn = global.delayedSpawns[i]
|
||||
|
||||
if (player.name == delayedSpawn.playerName) then
|
||||
table.remove(global.delayedSpawns, i)
|
||||
DebugPrint("Removing player from delayed spawn queue: " .. player.name)
|
||||
end
|
||||
end
|
||||
|
||||
-- Transfer or remove a shared spawn if player is owner
|
||||
if (global.sharedSpawns[player.name] ~= nil) then
|
||||
|
||||
local teamMates = global.sharedSpawns[player.name].players
|
||||
|
||||
if (#teamMates >= 1) then
|
||||
local newOwnerName = table.remove(teamMates)
|
||||
TransferOwnershipOfSharedSpawn(player.name, newOwnerName)
|
||||
else
|
||||
global.sharedSpawns[player.name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- If a uniqueSpawn was created for the player, mark it as unused.
|
||||
if (global.uniqueSpawns[player.name] ~= nil) then
|
||||
|
||||
local spawnPos = global.uniqueSpawns[player.name].pos
|
||||
|
||||
-- Check if it was near someone else's base.
|
||||
nearOtherSpawn = false
|
||||
for spawnPlayerName,otherSpawnPos in pairs(global.uniqueSpawns) do
|
||||
if ((spawnPlayerName ~= player.name) and (getDistance(spawnPos, otherSpawnPos.pos) < (ENFORCE_LAND_AREA_TILE_DIST*3))) then
|
||||
DebugPrint("Won't remove base as it's close to another spawn: " .. spawnPlayerName)
|
||||
nearOtherSpawn = true
|
||||
end
|
||||
end
|
||||
|
||||
if (ENABLE_ABANDONED_BASE_REMOVAL and not nearOtherSpawn) then
|
||||
global.uniqueSpawns[player.name] = nil
|
||||
|
||||
SendBroadcastMsg(player.name .. "'s base was marked for immediate clean up because they left within "..MIN_ONLINE_TIME_IN_MINUTES.." minutes of joining.")
|
||||
OarcRegrowthMarkForRemoval(spawnPos, 10)
|
||||
global.chunk_regrow.force_removal_flag = game.tick
|
||||
else
|
||||
table.insert(global.unusedSpawns, global.uniqueSpawns[player.name])
|
||||
global.uniqueSpawns[player.name] = nil
|
||||
SendBroadcastMsg(player.name .. " base was freed up because they left within "..MIN_ONLINE_TIME_IN_MINUTES.." minutes of joining.")
|
||||
end
|
||||
end
|
||||
|
||||
-- remove that player's cooldown setting
|
||||
if (global.playerCooldowns[player.name] ~= nil) then
|
||||
global.playerCooldowns[player.name] = nil
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
-- Remove a force if this player created it and they are the only one on it
|
||||
if ((#player.force.players <= 1) and (player.force.name ~= MAIN_FORCE)) then
|
||||
game.merge_forces(player.force, MAIN_FORCE)
|
||||
end
|
||||
|
||||
-- Remove the character completely
|
||||
game.remove_offline_players({player})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- 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
|
||||
function CreateNewSharedSpawn(player)
|
||||
global.sharedSpawns[player.name] = {openAccess=true,
|
||||
position=global.playerSpawns[player.name],
|
||||
players={}}
|
||||
end
|
||||
|
||||
function TransferOwnershipOfSharedSpawn(prevOwnerName, newOwnerName)
|
||||
-- Transfer the shared spawn global
|
||||
global.sharedSpawns[newOwnerName] = global.sharedSpawns[prevOwnerName]
|
||||
global.sharedSpawns[newOwnerName].openAccess = false
|
||||
global.sharedSpawns[prevOwnerName] = nil
|
||||
|
||||
-- Transfer the unique spawn global
|
||||
global.uniqueSpawns[newOwnerName] = global.uniqueSpawns[prevOwnerName]
|
||||
global.uniqueSpawns[prevOwnerName] = nil
|
||||
|
||||
game.players[newOwnerName].print("You have been given ownership of this base!")
|
||||
end
|
||||
|
||||
-- Returns the number of players currently online at the shared spawn
|
||||
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 and
|
||||
(game.players[ownerName] ~= nil) and
|
||||
game.players[ownerName].connected) then
|
||||
if ((MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN == 0) or
|
||||
(GetOnlinePlayersAtSharedSpawn(ownerName) < MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN)) then
|
||||
count = count+1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
|
||||
-- Initializes the globals used to track the special spawn and player
|
||||
-- status information
|
||||
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 = {}
|
||||
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 = {}
|
||||
end
|
||||
if (global.waitingBuddies == nil) then
|
||||
global.waitingBuddies = {}
|
||||
end
|
||||
if (global.delayedSpawns == nil) then
|
||||
global.delayedSpawns = {}
|
||||
end
|
||||
if (global.buddySpawnOptions == nil) then
|
||||
global.buddySpawnOptions = {}
|
||||
end
|
||||
|
||||
game.create_force(MAIN_FORCE)
|
||||
game.forces[MAIN_FORCE].set_spawn_position(game.forces["player"].get_spawn_position(GAME_SURFACE_NAME), GAME_SURFACE_NAME)
|
||||
|
||||
if ENABLE_SHARED_TEAM_VISION then
|
||||
game.forces[MAIN_FORCE].share_chart = true
|
||||
end
|
||||
|
||||
SetCeaseFireBetweenAllForces()
|
||||
SetFriendlyBetweenAllForces()
|
||||
if (ENABLE_ANTI_GRIEFING) then
|
||||
AntiGriefing(game.forces[MAIN_FORCE])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function DoesPlayerHaveCustomSpawn(player)
|
||||
for name,spawnPos in pairs(global.playerSpawns) do
|
||||
if (player.name == name) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ChangePlayerSpawn(player, pos)
|
||||
global.playerSpawns[player.name] = pos
|
||||
global.playerCooldowns[player.name] = {setRespawn=game.tick}
|
||||
end
|
||||
|
||||
function QueuePlayerForDelayedSpawn(playerName, spawn, moatEnabled)
|
||||
|
||||
-- If we get a valid spawn point, setup the area
|
||||
if ((spawn.x ~= 0) and (spawn.y ~= 0)) then
|
||||
global.uniqueSpawns[playerName] = {pos=spawn,moat=moatEnabled}
|
||||
|
||||
local delay_spawn_seconds = 5*(math.ceil(ENFORCE_LAND_AREA_TILE_DIST/CHUNK_SIZE))
|
||||
|
||||
game.players[playerName].print("Generating your spawn now, please wait a few for " .. delay_spawn_seconds .. " seconds...")
|
||||
game.players[playerName].surface.request_to_generate_chunks(spawn, 4)
|
||||
delayedTick = game.tick + delay_spawn_seconds*TICKS_PER_SECOND
|
||||
table.insert(global.delayedSpawns, {playerName=playerName, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick})
|
||||
|
||||
DisplayPleaseWaitForSpawnDialog(game.players[playerName], delay_spawn_seconds)
|
||||
|
||||
else
|
||||
DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!")
|
||||
SendBroadcastMsg("ERROR!! Failed to create spawn point for: " .. playerName)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Check a table to see if there are any players waiting to spawn
|
||||
-- Check if we are past the delayed tick count
|
||||
-- Spawn the players and remove them from the table.
|
||||
function DelayedSpawnOnTick()
|
||||
if ((game.tick % (30)) == 1) then
|
||||
if ((global.delayedSpawns ~= nil) and (#global.delayedSpawns > 0)) then
|
||||
for i=#global.delayedSpawns,1,-1 do
|
||||
delayedSpawn = global.delayedSpawns[i]
|
||||
|
||||
if (delayedSpawn.delayedTick < game.tick) then
|
||||
-- TODO, add check here for if chunks around spawn are generated surface.is_chunk_generated(chunkPos)
|
||||
if (game.players[delayedSpawn.playerName] ~= nil) then
|
||||
SendPlayerToNewSpawnAndCreateIt(delayedSpawn.playerName, delayedSpawn.spawn, delayedSpawn.moatEnabled)
|
||||
end
|
||||
table.remove(global.delayedSpawns, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SendPlayerToNewSpawnAndCreateIt(playerName, spawn, moatEnabled)
|
||||
|
||||
-- Make sure the area is super safe.
|
||||
ClearNearbyEnemies(spawn, SAFE_AREA_TILE_DIST, game.surfaces[GAME_SURFACE_NAME])
|
||||
|
||||
-- Create the spawn resources here
|
||||
CreateWaterStrip(game.surfaces[GAME_SURFACE_NAME],
|
||||
{x=spawn.x+WATER_SPAWN_OFFSET_X, y=spawn.y+WATER_SPAWN_OFFSET_Y},
|
||||
WATER_SPAWN_LENGTH)
|
||||
CreateWaterStrip(game.surfaces[GAME_SURFACE_NAME],
|
||||
{x=spawn.x+WATER_SPAWN_OFFSET_X, y=spawn.y+WATER_SPAWN_OFFSET_Y+1},
|
||||
WATER_SPAWN_LENGTH)
|
||||
GenerateStartingResources(game.surfaces[GAME_SURFACE_NAME], spawn)
|
||||
|
||||
-- Send the player to that position
|
||||
game.players[playerName].teleport(spawn, GAME_SURFACE_NAME)
|
||||
GivePlayerStarterItems(game.players[playerName])
|
||||
|
||||
-- Chart the area.
|
||||
ChartArea(game.players[playerName].force, game.players[playerName].position, math.ceil(ENFORCE_LAND_AREA_TILE_DIST/CHUNK_SIZE), game.players[playerName].surface)
|
||||
|
||||
if (game.players[playerName].gui.center.wait_for_spawn_dialog ~= nil) then
|
||||
game.players[playerName].gui.center.wait_for_spawn_dialog.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function SendPlayerToSpawn(player)
|
||||
if (DoesPlayerHaveCustomSpawn(player)) then
|
||||
player.teleport(global.playerSpawns[player.name], GAME_SURFACE_NAME)
|
||||
else
|
||||
player.teleport(game.forces[MAIN_FORCE].get_spawn_position(GAME_SURFACE_NAME), GAME_SURFACE_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
function SendPlayerToRandomSpawn(player)
|
||||
local numSpawns = TableLength(global.uniqueSpawns)
|
||||
local rndSpawn = math.random(0,numSpawns)
|
||||
local counter = 0
|
||||
|
||||
if (rndSpawn == 0) then
|
||||
player.teleport(game.forces[MAIN_FORCE].get_spawn_position(GAME_SURFACE_NAME), GAME_SURFACE_NAME)
|
||||
else
|
||||
counter = counter + 1
|
||||
for name,spawn in pairs(global.uniqueSpawns) do
|
||||
if (counter == rndSpawn) then
|
||||
player.teleport(spawn.pos)
|
||||
break
|
||||
end
|
||||
counter = counter + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
if ENABLE_SHARED_TEAM_VISION then
|
||||
newForce.share_chart = true
|
||||
end
|
||||
-- Chart silo areas if necessary
|
||||
if FRONTIER_ROCKET_SILO_MODE and ENABLE_SILO_VISION then
|
||||
ChartRocketSiloAreas(game.surfaces[GAME_SURFACE_NAME], newForce)
|
||||
end
|
||||
player.force = newForce
|
||||
SetCeaseFireBetweenAllForces()
|
||||
SetFriendlyBetweenAllForces()
|
||||
if (ENABLE_ANTI_GRIEFING) then
|
||||
AntiGriefing(newForce)
|
||||
end
|
||||
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
|
||||
|
||||
return newForce
|
||||
end
|
||||
-- separate_spawns.lua
|
||||
-- Nov 2016
|
||||
--
|
||||
-- Code that handles everything regarding giving each player a separate spawn
|
||||
-- Includes the GUI stuff
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- EVENT RELATED FUNCTIONS
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 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.
|
||||
function SeparateSpawnsPlayerCreated(event)
|
||||
local player = game.players[event.player_index]
|
||||
player.force = MAIN_FORCE
|
||||
DisplayWelcomeTextGui(player)
|
||||
end
|
||||
|
||||
|
||||
-- Check if the player has a different spawn point than the default one
|
||||
-- Make sure to give the default starting items
|
||||
function SeparateSpawnsPlayerRespawned(event)
|
||||
local player = game.players[event.player_index]
|
||||
SendPlayerToSpawn(player)
|
||||
end
|
||||
|
||||
|
||||
-- This is the main function that creates the spawn area
|
||||
-- Provides resources, land and a safe zone
|
||||
function SeparateSpawnsGenerateChunk(event)
|
||||
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.
|
||||
SetupAndClearSpawnAreas(surface, chunkArea, global.uniqueSpawns)
|
||||
end
|
||||
|
||||
|
||||
-- Call this if a player leaves the game
|
||||
-- Still seems to have a bug.
|
||||
function FindUnusedSpawns(event)
|
||||
local player = game.players[event.player_index]
|
||||
if (player.online_time < MIN_ONLINE_TIME) then
|
||||
|
||||
DropGravestoneChests(player)
|
||||
|
||||
-- Clear out global variables for that player
|
||||
if (global.playerSpawns[player.name] ~= nil) then
|
||||
global.playerSpawns[player.name] = nil
|
||||
end
|
||||
|
||||
-- Remove them from the delayer spawn queue if they are in it
|
||||
for i=#global.delayedSpawns,1,-1 do
|
||||
delayedSpawn = global.delayedSpawns[i]
|
||||
|
||||
if (player.name == delayedSpawn.playerName) then
|
||||
table.remove(global.delayedSpawns, i)
|
||||
DebugPrint("Removing player from delayed spawn queue: " .. player.name)
|
||||
end
|
||||
end
|
||||
|
||||
-- Transfer or remove a shared spawn if player is owner
|
||||
if (global.sharedSpawns[player.name] ~= nil) then
|
||||
|
||||
local teamMates = global.sharedSpawns[player.name].players
|
||||
|
||||
if (#teamMates >= 1) then
|
||||
local newOwnerName = table.remove(teamMates)
|
||||
TransferOwnershipOfSharedSpawn(player.name, newOwnerName)
|
||||
else
|
||||
global.sharedSpawns[player.name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- If a uniqueSpawn was created for the player, mark it as unused.
|
||||
if (global.uniqueSpawns[player.name] ~= nil) then
|
||||
|
||||
local spawnPos = global.uniqueSpawns[player.name].pos
|
||||
|
||||
-- Check if it was near someone else's base.
|
||||
nearOtherSpawn = false
|
||||
for spawnPlayerName,otherSpawnPos in pairs(global.uniqueSpawns) do
|
||||
if ((spawnPlayerName ~= player.name) and (getDistance(spawnPos, otherSpawnPos.pos) < (ENFORCE_LAND_AREA_TILE_DIST*3))) then
|
||||
DebugPrint("Won't remove base as it's close to another spawn: " .. spawnPlayerName)
|
||||
nearOtherSpawn = true
|
||||
end
|
||||
end
|
||||
|
||||
if (ENABLE_ABANDONED_BASE_REMOVAL and not nearOtherSpawn) then
|
||||
global.uniqueSpawns[player.name] = nil
|
||||
|
||||
SendBroadcastMsg(player.name .. "'s base was marked for immediate clean up because they left within "..MIN_ONLINE_TIME_IN_MINUTES.." minutes of joining.")
|
||||
OarcRegrowthMarkForRemoval(spawnPos, 10)
|
||||
global.chunk_regrow.force_removal_flag = game.tick
|
||||
else
|
||||
table.insert(global.unusedSpawns, global.uniqueSpawns[player.name])
|
||||
global.uniqueSpawns[player.name] = nil
|
||||
SendBroadcastMsg(player.name .. " base was freed up because they left within "..MIN_ONLINE_TIME_IN_MINUTES.." minutes of joining.")
|
||||
end
|
||||
end
|
||||
|
||||
-- remove that player's cooldown setting
|
||||
if (global.playerCooldowns[player.name] ~= nil) then
|
||||
global.playerCooldowns[player.name] = nil
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
-- Remove a force if this player created it and they are the only one on it
|
||||
if ((#player.force.players <= 1) and (player.force.name ~= MAIN_FORCE)) then
|
||||
game.merge_forces(player.force, MAIN_FORCE)
|
||||
end
|
||||
|
||||
-- Remove the character completely
|
||||
game.remove_offline_players({player})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- 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
|
||||
function CreateNewSharedSpawn(player)
|
||||
global.sharedSpawns[player.name] = {openAccess=true,
|
||||
position=global.playerSpawns[player.name],
|
||||
players={}}
|
||||
end
|
||||
|
||||
function TransferOwnershipOfSharedSpawn(prevOwnerName, newOwnerName)
|
||||
-- Transfer the shared spawn global
|
||||
global.sharedSpawns[newOwnerName] = global.sharedSpawns[prevOwnerName]
|
||||
global.sharedSpawns[newOwnerName].openAccess = false
|
||||
global.sharedSpawns[prevOwnerName] = nil
|
||||
|
||||
-- Transfer the unique spawn global
|
||||
global.uniqueSpawns[newOwnerName] = global.uniqueSpawns[prevOwnerName]
|
||||
global.uniqueSpawns[prevOwnerName] = nil
|
||||
|
||||
game.players[newOwnerName].print("You have been given ownership of this base!")
|
||||
end
|
||||
|
||||
-- Returns the number of players currently online at the shared spawn
|
||||
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 and
|
||||
(game.players[ownerName] ~= nil) and
|
||||
game.players[ownerName].connected) then
|
||||
if ((MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN == 0) or
|
||||
(GetOnlinePlayersAtSharedSpawn(ownerName) < MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN)) then
|
||||
count = count+1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
|
||||
-- Initializes the globals used to track the special spawn and player
|
||||
-- status information
|
||||
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 = {}
|
||||
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 = {}
|
||||
end
|
||||
if (global.waitingBuddies == nil) then
|
||||
global.waitingBuddies = {}
|
||||
end
|
||||
if (global.delayedSpawns == nil) then
|
||||
global.delayedSpawns = {}
|
||||
end
|
||||
if (global.buddySpawnOptions == nil) then
|
||||
global.buddySpawnOptions = {}
|
||||
end
|
||||
|
||||
game.create_force(MAIN_FORCE)
|
||||
game.forces[MAIN_FORCE].set_spawn_position(game.forces["player"].get_spawn_position(GAME_SURFACE_NAME), GAME_SURFACE_NAME)
|
||||
|
||||
if ENABLE_SHARED_TEAM_VISION then
|
||||
game.forces[MAIN_FORCE].share_chart = true
|
||||
end
|
||||
|
||||
SetCeaseFireBetweenAllForces()
|
||||
SetFriendlyBetweenAllForces()
|
||||
if (ENABLE_ANTI_GRIEFING) then
|
||||
AntiGriefing(game.forces[MAIN_FORCE])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function DoesPlayerHaveCustomSpawn(player)
|
||||
for name,spawnPos in pairs(global.playerSpawns) do
|
||||
if (player.name == name) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ChangePlayerSpawn(player, pos)
|
||||
global.playerSpawns[player.name] = pos
|
||||
global.playerCooldowns[player.name] = {setRespawn=game.tick}
|
||||
end
|
||||
|
||||
function QueuePlayerForDelayedSpawn(playerName, spawn, moatEnabled)
|
||||
|
||||
-- If we get a valid spawn point, setup the area
|
||||
if ((spawn.x ~= 0) and (spawn.y ~= 0)) then
|
||||
global.uniqueSpawns[playerName] = {pos=spawn,moat=moatEnabled}
|
||||
|
||||
local delay_spawn_seconds = 5*(math.ceil(ENFORCE_LAND_AREA_TILE_DIST/CHUNK_SIZE))
|
||||
|
||||
game.players[playerName].print("Generating your spawn now, please wait a few for " .. delay_spawn_seconds .. " seconds...")
|
||||
game.players[playerName].surface.request_to_generate_chunks(spawn, 4)
|
||||
delayedTick = game.tick + delay_spawn_seconds*TICKS_PER_SECOND
|
||||
table.insert(global.delayedSpawns, {playerName=playerName, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick})
|
||||
|
||||
DisplayPleaseWaitForSpawnDialog(game.players[playerName], delay_spawn_seconds)
|
||||
|
||||
else
|
||||
DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!")
|
||||
SendBroadcastMsg("ERROR!! Failed to create spawn point for: " .. playerName)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Check a table to see if there are any players waiting to spawn
|
||||
-- Check if we are past the delayed tick count
|
||||
-- Spawn the players and remove them from the table.
|
||||
function DelayedSpawnOnTick()
|
||||
if ((game.tick % (30)) == 1) then
|
||||
if ((global.delayedSpawns ~= nil) and (#global.delayedSpawns > 0)) then
|
||||
for i=#global.delayedSpawns,1,-1 do
|
||||
delayedSpawn = global.delayedSpawns[i]
|
||||
|
||||
if (delayedSpawn.delayedTick < game.tick) then
|
||||
-- TODO, add check here for if chunks around spawn are generated surface.is_chunk_generated(chunkPos)
|
||||
if (game.players[delayedSpawn.playerName] ~= nil) then
|
||||
SendPlayerToNewSpawnAndCreateIt(delayedSpawn.playerName, delayedSpawn.spawn, delayedSpawn.moatEnabled)
|
||||
end
|
||||
table.remove(global.delayedSpawns, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SendPlayerToNewSpawnAndCreateIt(playerName, spawn, moatEnabled)
|
||||
|
||||
-- Make sure the area is super safe.
|
||||
ClearNearbyEnemies(spawn, SAFE_AREA_TILE_DIST, game.surfaces[GAME_SURFACE_NAME])
|
||||
|
||||
-- Create the spawn resources here
|
||||
CreateWaterStrip(game.surfaces[GAME_SURFACE_NAME],
|
||||
{x=spawn.x+WATER_SPAWN_OFFSET_X, y=spawn.y+WATER_SPAWN_OFFSET_Y},
|
||||
WATER_SPAWN_LENGTH)
|
||||
CreateWaterStrip(game.surfaces[GAME_SURFACE_NAME],
|
||||
{x=spawn.x+WATER_SPAWN_OFFSET_X, y=spawn.y+WATER_SPAWN_OFFSET_Y+1},
|
||||
WATER_SPAWN_LENGTH)
|
||||
GenerateStartingResources(game.surfaces[GAME_SURFACE_NAME], spawn)
|
||||
|
||||
-- Send the player to that position
|
||||
game.players[playerName].teleport(spawn, GAME_SURFACE_NAME)
|
||||
GivePlayerStarterItems(game.players[playerName])
|
||||
|
||||
-- Chart the area.
|
||||
ChartArea(game.players[playerName].force, game.players[playerName].position, math.ceil(ENFORCE_LAND_AREA_TILE_DIST/CHUNK_SIZE), game.players[playerName].surface)
|
||||
|
||||
if (game.players[playerName].gui.center.wait_for_spawn_dialog ~= nil) then
|
||||
game.players[playerName].gui.center.wait_for_spawn_dialog.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function SendPlayerToSpawn(player)
|
||||
if (DoesPlayerHaveCustomSpawn(player)) then
|
||||
player.teleport(global.playerSpawns[player.name], GAME_SURFACE_NAME)
|
||||
else
|
||||
player.teleport(game.forces[MAIN_FORCE].get_spawn_position(GAME_SURFACE_NAME), GAME_SURFACE_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
function SendPlayerToRandomSpawn(player)
|
||||
local numSpawns = TableLength(global.uniqueSpawns)
|
||||
local rndSpawn = math.random(0,numSpawns)
|
||||
local counter = 0
|
||||
|
||||
if (rndSpawn == 0) then
|
||||
player.teleport(game.forces[MAIN_FORCE].get_spawn_position(GAME_SURFACE_NAME), GAME_SURFACE_NAME)
|
||||
else
|
||||
counter = counter + 1
|
||||
for name,spawn in pairs(global.uniqueSpawns) do
|
||||
if (counter == rndSpawn) then
|
||||
player.teleport(spawn.pos)
|
||||
break
|
||||
end
|
||||
counter = counter + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
if ENABLE_SHARED_TEAM_VISION then
|
||||
newForce.share_chart = true
|
||||
end
|
||||
-- Chart silo areas if necessary
|
||||
if FRONTIER_ROCKET_SILO_MODE and ENABLE_SILO_VISION then
|
||||
ChartRocketSiloAreas(game.surfaces[GAME_SURFACE_NAME], newForce)
|
||||
end
|
||||
player.force = newForce
|
||||
SetCeaseFireBetweenAllForces()
|
||||
SetFriendlyBetweenAllForces()
|
||||
if (ENABLE_ANTI_GRIEFING) then
|
||||
AntiGriefing(newForce)
|
||||
end
|
||||
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
|
||||
|
||||
return newForce
|
||||
end
|
2372
separate_spawns_guis.lua → lib/separate_spawns_guis.lua
Executable file → Normal file
2372
separate_spawns_guis.lua → lib/separate_spawns_guis.lua
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
61
lib/tag.lua
Normal file
61
lib/tag.lua
Normal file
@ -0,0 +1,61 @@
|
||||
-- tag.lua
|
||||
-- Apr 2017
|
||||
-- Allows adding play tags
|
||||
|
||||
function CreateTagGui(event)
|
||||
local player = game.players[event.player_index]
|
||||
if player.gui.top.tag == nil then
|
||||
player.gui.top.add{name="tag", type="button", caption="Tag"}
|
||||
end
|
||||
end
|
||||
|
||||
-- Tag list
|
||||
local roles = {
|
||||
{display_name = "[Solo]"},
|
||||
{display_name = "[Mining]"},
|
||||
{display_name = "[Power]"},
|
||||
{display_name = "[Oil]"},
|
||||
{display_name = "[Smelt]"},
|
||||
{display_name = "[Rail]"},
|
||||
{display_name = "[Defense]"},
|
||||
{display_name = "[Circuits]"},
|
||||
{display_name = "[Science!]"},
|
||||
{display_name = "[Logistics]"},
|
||||
{display_name = "[Misc]"},
|
||||
{display_name = "[Aliens]"},
|
||||
{display_name = "[Rocket]"},
|
||||
{display_name = "[AFK]"},
|
||||
{display_name = "Clear"}}
|
||||
|
||||
local function ExpandTagGui(player)
|
||||
local frame = player.gui.left["tag-panel"]
|
||||
if (frame) then
|
||||
frame.destroy()
|
||||
else
|
||||
local frame = player.gui.left.add{type="frame", name="tag-panel", caption="What are you doing:"}
|
||||
for _, role in pairs(roles) do
|
||||
frame.add{type="button", caption=role.display_name, name=role.display_name}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TagGuiClick(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 == "tag") then
|
||||
ExpandTagGui(player)
|
||||
end
|
||||
|
||||
if (name == "Clear") then
|
||||
player.tag = ""
|
||||
return
|
||||
end
|
||||
|
||||
for _, role in pairs(roles) do
|
||||
if (name == role.display_name) then
|
||||
player.tag = role.display_name
|
||||
end
|
||||
end
|
||||
end
|
1
lib/test_lib_file.lua
Normal file
1
lib/test_lib_file.lua
Normal file
@ -0,0 +1 @@
|
||||
-- test_lib_file.lua
|
Loading…
Reference in New Issue
Block a user