1
0
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:
Oarcinae 2019-03-01 21:07:24 -05:00
parent 07de8d1fe5
commit e1839a8756
12 changed files with 2596 additions and 1953 deletions

View File

@ -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"
}

View File

@ -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
View 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
View 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
View 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)

View File

@ -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)

View File

@ -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
View 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)

View File

@ -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

File diff suppressed because it is too large Load Diff

61
lib/tag.lua Normal file
View 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
View File

@ -0,0 +1 @@
-- test_lib_file.lua