1
0
mirror of https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git synced 2024-12-12 10:13:58 +02:00

Merge pull request #47 from Oarcinae/dev_0.16

Dev 0.16 going stable.
This commit is contained in:
Oarcinae 2018-03-30 16:15:18 -04:00 committed by GitHub
commit 717004cfe5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 4038 additions and 2640 deletions

View File

@ -1,8 +1,7 @@
# FactorioScenarioMultiplayerSpawn
A custom scenario for allowing separate spawn locations in multiplayer. Designed for Co-op and PvE.
Only supports 0.15.x at this time!
Go to the dev branch for a mostly working 0.16 version: https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn/tree/dev_0.16
0.16 is now stable and well supported!
## Instructions
@ -26,8 +25,21 @@ Rename the "FactorioScenarioMultiplayerSpawn" folder to something shorter and mo
### STEP 3
#### OPTION 1 (Client Hosted)
Start a multiplayer game on your client like normal.
#### OPTION 2 (Headless)
Generate a new map, use that save file to host if you want to.
#### OPTION 3 (Headless)
Place the scenario code in the game's scenario folder, typically something like "..\Factorio\scenarios\FactorioScenarioMultiplayerSpawn\\.."
Start a new game (generates a random map based on the config in config.lua) from the command line:
./factorio --start-server-load-scenario FactorioScenarioMultiplayerSpawn --server-settings my-server-settings.json
If you want to RESUME from this method, use something like this:
./factorio --start-server-load-latest --server-settings my-server-settings.json
## Configuration

View File

@ -7,57 +7,54 @@
--------------------------------------------------------------------------------
-- Messages
-- You will want to change some of these to be your own.
-- Make sure SERVER_OWNER_IS_OARC = false
--------------------------------------------------------------------------------
-- This stuff is printed in the console. It's probably ignored most of the time.
WELCOME_MSG = "[INSERT SERVER OWNER MSG HERE!]"
GAME_MODE_MSG = "In the current game mode, a satellite must be launched from an existing far away rocket silo to win!"
MODULES_ENABLED = "Mods Enabled: Separate Spawns, RSO, Long-Reach, Autofill, Undecorator, Player List"
-- This stuff is shown in the welcome GUI. Make sure it's valid.
WELCOME_MSG_TITLE = "[INSERT SERVER OWNER MSG HERE!]"
WELCOME_MSG1 = "Rules: Be polite. Ask before changing other players's stuff. Have fun!"
WELCOME_MSG2 = "This server is running a custom scenario that changes spawn locations."
SERVER_MSG = "Rules: Be polite. Ask before changing other players's stuff. Have fun!\n"..
"This server is running a custom scenario that changes spawn locations."
OTHER_MSG1 = "Latest updates in this scenario version (0.5.5):"
OTHER_MSG2 = "Regrowth fixes (disabled). Abandoned base removal."
-- Optional other messages below:
OTHER_MSG3 = "Standard multiplayer spawn allows spawning in far locations."
OTHER_MSG4 = "You can be on the main team or your own."
OTHER_MSG5 = "If you leave in the first 15 minutes, your base and character will be deleted!"
SCENARIO_INFO_MSG = "Latest updates in this scenario version:\n"..
"0.16 experimental release. Tweaks to fix spawn issues / text / difficulty.\n"..
"This scenario gives you and/or your friends your own starting area.\n"..
"You can be on the main team or your own. All teams are friendly.\n"..
"If you leave in the first 15 minutes, your base and character will be deleted!"
SPAWN_WARN_MSG = "Due to the way this scenario works, it may take some time for the land around your new spawn area to generate... Please wait for 10-20 seconds when you select your first spawn."
WELCOME_MSG3 = "Due to the way this scenario works, it may take some time for the land"
WELCOME_MSG4 = "around your new spawn area to generate..."
WELCOME_MSG5 = "Please wait for 10-20 seconds when you select your first spawn."
WELCOME_MSG6 = "Contact: SteamID:Oarc | oarcinae@gmail.com"
CONTACT_MSG = "Contact: SteamID:Oarc | oarcinae@gmail.com | discord.gg/TPYxRrS"
SPAWN_MSG1 = "Current Spawn Mode: WILDERNESS"
SPAWN_MSG2 = "In this mode, there is no default spawn. Everyone starts in the wild!"
SPAWN_MSG3 = "Resources are spread out far apart but are quite rich."
-- These are my specific welcome messages that get used only if I am the user
-- that creates the game.
SERVER_OWNER_IS_OARC = true -- This should be false for you, it's just a convenience for me.
WELCOME_MSG_OARC = "Welcome to Oarc's official server! Join the discord here: discord.gg/TPYxRrS"
WELCOME_MSG_TITLE_OARC = "Welcome to Oarc's Server!"
-- This should be false for you, it's just a convenience for me.
SERVER_OWNER_IS_OARC = false
--------------------------------------------------------------------------------
-- Module Enables
-- These enables are not fully tested! For example, disable separate spawns
-- These enables are not fully tested! For example, disabling separate spawns
-- will probably break the frontier rocket silo mode
--------------------------------------------------------------------------------
-- Frontier style rocket silo mode
FRONTIER_ROCKET_SILO_MODE = true
-- Separate spawns
-- This is the core of the mod. Probably not a good idea to disable it.
ENABLE_SEPARATE_SPAWNS = true
-- Enable Scenario version of RSO
-- You can reconfigure the RSO resource settings in the RSO files if you want to
-- This allows 2 players to spawn next to each other in the wilderness,
-- each with their own starting point. It adds more GUI selection options.
ENABLE_BUDDY_SPAWN = true
-- RSO soft-mod (included in the scenario)
ENABLE_RSO = true
-- Frontier style rocket silo mode
FRONTIER_ROCKET_SILO_MODE = true
-- Enable Undecorator
-- Removes decorative items to reduce save file size.
ENABLE_UNDECORATOR = true
@ -73,23 +70,26 @@ ENABLE_AUTOFILL = true
-- Enable Playerlist
ENABLE_PLAYER_LIST = true
PLAYER_LIST_OFFLINE_PLAYERS = true -- List offline players as well.
-- Enable Gravestone Chests
ENABLE_GRAVESTONE_ON_DEATH = false
-- Items dumped into chest when you leave.
-- Items dumped into chest when you leave.
ENABLE_GRAVESTONE_ON_LEAVING = false
-- If anyone leaves within first X minutes, items get dumped into chest.
-- If anyone leaves within first X minutes, items get dumped into chest.
ENABLE_GRAVESTONE_ON_LEAVING_TIME_MINS = 15
-- Enable quick start items
ENABLE_POWER_ARMOR_QUICK_START = false
-- Enable shared vision between teams (all teams are still COOP)
-- Enable shared vision between teams (all teams are COOP regardless)
ENABLE_SHARED_TEAM_VISION = true
-- Enable map regrowth, see regrowth_map.lua for more info.
-- I'm not a fan of this anymore, but it helps keep the map size down
ENABLE_REGROWTH = false
-- If you have regrowth enabled, this should also be enabled.
-- It removes bases for players that join and leave the game quickly.
-- This can also be used without enabling regrowth.
@ -102,7 +102,7 @@ ENABLE_ABANDONED_BASE_REMOVAL = true
---------------------------------------
-- Starting Items
---------------------------------------
-- Items provided to the player the first time they join ("quick start" commented out)
-- Items provided to the player the first time they join
PLAYER_SPAWN_START_ITEMS = {
{name="pistol", count=1},
{name="firearm-magazine", count=100},
@ -140,23 +140,31 @@ PLAYER_RESPAWN_START_ITEMS = {
CHECK_SPAWN_UNGENERATED_CHUNKS_RADIUS = 5
-- Near Distance in chunks
NEAR_MIN_DIST = 25 --50
NEAR_MAX_DIST = 100 --125
--
NEAR_MIN_DIST = 0
NEAR_MAX_DIST = 50
-- Far Distance in chunks
FAR_MIN_DIST = 200 --50
FAR_MAX_DIST = 300 --125
FAR_MIN_DIST = 200
FAR_MAX_DIST = 300
---------------------------------------
-- Resource & Spawn Circle Options
---------------------------------------
-- Enable this to have a vanilla style starting spawn for all new spawns.
-- This scenario normally gives you a fixed circle with resources.
-- USE_VANILLA_STARTING_SPAWN = true
-- TODO - Requires pre-allocating spawns...
-- Allow players to choose to spawn with a moat
SPAWN_MOAT_CHOICE_ENABLED = true
-- If you change the spawn area size, you might have to adjust this as well
MOAT_SIZE_MODIFIER = 1
-- THIS IS WHAT SETS THE SPAWN CIRCLE SIZE!
-- Create a circle of land area for the spawn
-- This is the radius (I think?) in TILES.
ENFORCE_LAND_AREA_TILE_DIST = 48
-- If you make this much bigger than a few chunks, good luck.
ENFORCE_LAND_AREA_TILE_DIST = CHUNK_SIZE*1.8
-- Location of water strip (horizontal)
WATER_SPAWN_OFFSET_X = -4
@ -199,10 +207,14 @@ START_RESOURCE_URANIUM_POS_Y = -34
START_RESOURCE_URANIUM_SIZE = 0 -- Disabled by default.
-- Specify 2 oil spot locations for starting oil.
START_RESOURCE_OIL_A_POS_X = -39
START_RESOURCE_OIL_A_POS_Y = -2
START_RESOURCE_OIL_B_POS_X = -39
START_RESOURCE_OIL_B_POS_Y = 2
START_RESOURCE_OIL_NUM_PATCHES = 2
-- The first patch
START_RESOURCE_OIL_POS_X = -39
START_RESOURCE_OIL_POS_Y = -2
-- How far each patch is offset from the others and in which direction
-- Default (x=0, y=-4) means that patches spawn in a vertical row downwards.
START_RESOURCE_OIL_X_OFFSET = 0
START_RESOURCE_OIL_Y_OFFSET = -4
-- Force the land area circle at the spawn to be fully grass
@ -212,6 +224,7 @@ ENABLE_SPAWN_FORCE_GRASS = true
SPAWN_TREE_CIRCLE_ENABLED = true
-- Set this to true for the spawn area to be surrounded by an octagon of trees
-- I don't recommend using this with moatsm
SPAWN_TREE_OCTAGON_ENABLED = true
---------------------------------------
@ -220,14 +233,14 @@ SPAWN_TREE_OCTAGON_ENABLED = true
-- Safe area has no aliens
-- +/- this in x and y direction
SAFE_AREA_TILE_DIST = CHUNK_SIZE*12
SAFE_AREA_TILE_DIST = CHUNK_SIZE*5
-- Warning area has reduced aliens
-- +/- this in x and y direction
WARNING_AREA_TILE_DIST = CHUNK_SIZE*20
WARNING_AREA_TILE_DIST = CHUNK_SIZE*10
-- 1 : X (spawners alive : spawners destroyed) in this area
WARN_AREA_REDUCTION_RATIO = 15
WARN_AREA_REDUCTION_RATIO = 10
---------------------------------------
@ -243,11 +256,12 @@ ENABLE_SEPARATE_TEAMS = true
MAIN_FORCE = "Main Force"
-- Enable if people can spawn at the main base
ENABLE_DEFAULT_SPAWN = false
-- THIS CURRENTLY IS BROKEN! YOU WILL NOT GET ANY RESOURCES IF YOU USE RSO!
ENABLE_DEFAULT_SPAWN = false -- DON'T USE THIS
-- Enable if people can allow others to join their base
ENABLE_SHARED_SPAWNS = true
MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN = 3
MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN = 0
-- Share local team chat with all teams
-- This makes it so you don't have to use /s
@ -257,7 +271,7 @@ ENABLE_SHARED_TEAM_CHAT = true
---------------------------------------
-- Special Action Cooldowns
---------------------------------------
RESPAWN_COOLDOWN_IN_MINUTES = 60
RESPAWN_COOLDOWN_IN_MINUTES = 15
RESPAWN_COOLDOWN_TICKS = TICKS_PER_MINUTE * RESPAWN_COOLDOWN_IN_MINUTES
-- Require playes to be online for at least 5 minutes
@ -270,33 +284,47 @@ MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES
-- Alien Options
--------------------------------------------------------------------------------
-- Enable/Disable enemy expansion (Applies to RSO as well!)
ENEMY_EXPANSION = false
-- Enable/Disable enemy expansion
ENEMY_EXPANSION = true
-- Divide the alien factors by this number to reduce it (or multiply if < 1)
-- 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.
ENEMY_TIME_FACTOR_DIVISOR = 10
ENEMY_POLLUTION_FACTOR_DISABLE = false -- Set this to true to disable pollution based evolution completely.
ENEMY_POLLUTION_FACTOR_DIVISOR = 10
ENEMY_DESTROY_FACTOR_DIVISOR = 10
ENEMY_DESTROY_FACTOR_DISABLE = false -- Set this to true to disable spawner destruction based evolution completely.
ENEMY_DESTROY_FACTOR_DIVISOR = 1
--------------------------------------------------------------------------------
-- Frontier Rocket Silo Options
--------------------------------------------------------------------------------
SILO_CHUNK_DISTANCE_X = 15
SILO_DISTANCE_X = SILO_CHUNK_DISTANCE_X*CHUNK_SIZE + CHUNK_SIZE/2
SILO_DISTANCE_Y = 16
-- Number of silos found in the wild.
-- These will spawn in a circle at given distance from the center of the map
-- If you set this number too high, you'll have a lot of delay at the start of the game.
SILO_NUM_SPAWNS = 3
-- Should be in the middle of a chunk
SILO_POSITION = {x = SILO_DISTANCE_X, y = SILO_DISTANCE_Y}
-- How many chunks away from the center of the map should the silo be spawned
SILO_CHUNK_DISTANCE = 200
-- If this is enabled, the static position is ignored.
ENABLE_RANDOM_SILO_POSITION = true
-- If this is enabled, you get ONE silo at the location specified below.
SILO_FIXED_POSITION = false
-- If you want to set a fixed spawn location for a single silo
SILO_POSITION = {x = 0, y = 100}
-- Set this to false so that you have to search for the silo's.
ENABLE_SILO_VISION = true
-- Add beacons around the silo (Philip's modm)
ENABLE_SILO_BEACONS = false
ENABLE_SILO_RADAR = false
--------------------------------------------------------------------------------
-- Long Reach Options
--------------------------------------------------------------------------------
BUILD_DIST_BONUS = 20
BUILD_DIST_BONUS = 64
REACH_DIST_BONUS = BUILD_DIST_BONUS
RESOURCE_DIST_BONUS = 2
@ -307,19 +335,71 @@ RESOURCE_DIST_BONUS = 2
AUTOFILL_TURRET_AMMO_QUANTITY = 10
--------------------------------------------------------------------------------
-- Use rso_config and rso_resource_config for RSO config settings
-- RSO Soft-Mod Configurations
-- Configure these to tweak the RSO values.
--------------------------------------------------------------------------------
-- Don't touch unless you know what you're doing...
-- When using RSO, all resources MUST BE SET TO SIZE=NONE!
-- CONFIGURE STUFF INSIDE rso_config.lua
-- RSO resources can be very lucky/unlucky...
-- don't complain if you can't find a resource.
--------------------------------------------------------------------------------
MAP_SETTINGS_RSO_TERRAIN_SEGMENTATION = "very-low" -- Frequency of water
MAP_SETTINGS_RSO_WATER = "high" -- Size of water patches
MAP_SETTINGS_RSO_PEACEFUL = false -- Peaceful mode for biters/aliens
MAP_SETTINGS_RSO_STARTING_AREA = "very-low" -- Does not affect Oarc spawn sizes.
-- MAP CONFIGURATION OPTIONS
-- Configure these if you are running headless since there is no way to set
-- resources otherwise.
--------------------------------------------------------------------------------
-- Set this to true if you are creating the scenario at the cmd line.
CMD_LINE_MAP_GEN = true
-- Adjust settings here to set your map stuff.
-- "Sizes can be specified as none, very-low, low, normal, high, very-high"
global.clMapGen = {}
global.clMapGen.terrain_segmentation="normal"
global.clMapGen.water="normal"
global.clMapGen.starting_area="low"
global.clMapGen.peaceful_mode=false
global.clMapGen.seed=nil;
-- These are my go to default vanilla settings, it's not RSO, but it's okay.
global.clMapGen.autoplace_controls = {
-- Resources and enemies only matter if you are NOT using RSO.
["coal"]={frequency="very-low", size= "low", richness= "high"},
["copper-ore"]={frequency= "very-low", size= "low", richness= "high"},
["crude-oil"]={frequency= "low", size= "low", richness= "high"},
["enemy-base"]={frequency= "low", size= "normal", richness= "normal"},
["iron-ore"]={frequency= "very-low", size= "low", richness= "high"},
["stone"]={frequency= "very-low", size= "low", richness= "high"},
["uranium-ore"]={frequency= "low", size= "low", richness= "high"},
["desert"]={frequency= "low", size= "low", richness= "low"},
["dirt"]={frequency= "low", size= "low", richness= "low"},
["grass"]={frequency= "normal", size= "normal", richness= "normal"},
["sand"]={frequency= "low", size= "low", richness= "low"},
["trees"]={frequency= "normal", size= "normal", richness= "normal"}
}
-- Cliff defaults are 10 and 10, set both to 0 to turn cliffs off I think?
global.clMapGen.cliff_settings={cliff_elevation_0=10, cliff_elevation_interval=10, name="cliff"}
--------------------------------------------------------------------------------
-- ANTI-Griefing stuff ( I don't personally maintain this as I don't care for it.)
-- These things were added from other people's requests/changes and are disabled by default.
--------------------------------------------------------------------------------
-- Enable this to disable some basic things like friendly fire, deconstructing from map view, etc.
ENABLE_ANTI_GRIEFING = false
-- Makes blueprint ghosts dissapear if they have been placed longer than this
GHOST_TIME_TO_LIVE = 0 * TICKS_PER_MINUTE -- set to 0 for infinite ghost life
-------------------------------------------------------------------------------
-- DEBUG
-- DEBUG / Custom stuff
--------------------------------------------------------------------------------
OARC_DIFFICULTY_CUSTOM = false
-- DEBUG prints for me
global.oarcDebugEnabled = false
-- These are my specific welcome messages that get used only if I am the user
-- that creates the game.
WELCOME_MSG_OARC = "Welcome to Oarc's official server! Join the discord here: discord.gg/TPYxRrS"
WELCOME_MSG_TITLE_OARC = "Welcome to Oarc's Server!"

View File

@ -27,6 +27,12 @@ require("locale/oarc_utils")
require("locale/rso/rso_control")
require("locale/frontier_silo")
require("locale/tag")
require("locale/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")
-- Main Configuration File
require("config")
@ -86,15 +92,13 @@ script.on_init(function(event)
-- CreateLobbySurface() -- Currently unused, but have plans for future.
-- Configures the map settings for enemies
-- This controls evolution growth factors and enemy expansion settings.
ConfigureAlienStartingParams()
-- Here I create the game surface. I do this so that I don't have to worry
-- about the game menu settings and I can now generate a map from the command
-- line more easily!
--
-- If you are using RSO, map settings are ignored and you MUST configure
-- the relevant map settings in config.lua
--
-- If you disable RSO, the map settings will be set from the ones that you
-- choose from the game GUI when you start a new scenario.
if ENABLE_RSO then
CreateGameSurface(RSO_MODE)
else
@ -105,36 +109,22 @@ script.on_init(function(event)
InitSpawnGlobalsAndForces()
end
if ENABLE_RANDOM_SILO_POSITION then
SetRandomSiloPosition()
if SILO_FIXED_POSITION then
SetFixedSiloPosition(SILO_POSITION)
else
SetFixedSiloPosition()
SetRandomSiloPosition(SILO_NUM_SPAWNS)
end
if FRONTIER_ROCKET_SILO_MODE then
ChartRocketSiloArea(game.forces[MAIN_FORCE], game.surfaces[GAME_SURFACE_NAME])
GenerateRocketSiloAreas(game.surfaces[GAME_SURFACE_NAME])
end
-- Configures the map settings for enemies
-- This controls evolution growth factors and enemy expansion settings.
ConfigureAlienStartingParams()
SetServerWelcomeMessages()
if ENABLE_REGROWTH or ENABLE_ABANDONED_BASE_REMOVAL then
OarcRegrowthInit()
end
--If any (not global.) globals are written to at this point, an error will be thrown.
--eg, x = 2 will throw an error because it's not global.x
-- setmetatable(_G, {
-- __newindex = function(_, n)
-- log("Attempt to write to undeclared var " .. n)
-- game.print("Attempt to write to undeclared var " .. n)
-- end
-- })
-- -- THIS REQUIRES A LOT OF CHANGES TO RSO SOFT MOD...
end)
@ -169,12 +159,13 @@ script.on_event(defines.events.on_chunk_generated, function(event)
GenerateRocketSiloChunk(event)
end
-- This MUST come after RSO generation!
if ENABLE_SEPARATE_SPAWNS then
if ENABLE_SEPARATE_SPAWNS and not USE_VANILLA_STARTING_SPAWN then
SeparateSpawnsGenerateChunk(event)
end
CreateHoldingPenGenerateChunk(event)
if not ENABLE_DEFAULT_SPAWN then
CreateHoldingPen(event.surface, event.area, 16, false)
end
end)
@ -195,8 +186,21 @@ script.on_event(defines.events.on_gui_click, function(event)
SpawnOptsGuiClick(event)
SpawnCtrlGuiClick(event)
SharedSpwnOptsGuiClick(event)
BuddySpawnOptsGuiClick(event)
BuddySpawnWaitMenuClick(event)
BuddySpawnRequestMenuClick(event)
SharedSpawnJoinWaitMenuClick(event)
end
GameOptionsGuiClick(event)
end)
script.on_event(defines.events.on_gui_checked_state_changed, function (event)
if ENABLE_SEPARATE_SPAWNS then
SpawnOptsRadioSelect(event)
SpawnCtrlGuiOptionsSelect(event)
end
end)
@ -205,15 +209,18 @@ end)
----------------------------------------
script.on_event(defines.events.on_player_joined_game, function(event)
CreateGameOptionsGui(event)
PlayerJoinedMessages(event)
if ENABLE_PLAYER_LIST then
CreatePlayerListGui(event)
end
if ENABLE_TAGS then
CreateTagGui(event)
end
if ENABLE_PLAYER_LIST then
CreatePlayerListGui(event)
end
end)
script.on_event(defines.events.on_player_created, function(event)
@ -272,6 +279,10 @@ script.on_event(defines.events.on_built_entity, function(event)
if ENABLE_REGROWTH then
OarcRegrowthOffLimitsChunk(event.created_entity.position)
end
if ENABLE_ANTI_GRIEFING then
SetItemBlueprintTimeToLive(event)
end
end)
@ -279,11 +290,6 @@ end)
-- Shared vision, charts a small area around other players
----------------------------------------
script.on_event(defines.events.on_tick, function(event)
-- Every few seconds, chart all players to "share vision"
if ENABLE_SHARED_TEAM_VISION then
ShareVisionBetweenPlayers()
end
if ENABLE_REGROWTH then
OarcRegrowthOnTick()
end
@ -292,6 +298,21 @@ script.on_event(defines.events.on_tick, function(event)
OarcRegrowthForceRemovalOnTick()
end
if ENABLE_SEPARATE_SPAWNS then
DelayedSpawnOnTick()
end
if FRONTIER_ROCKET_SILO_MODE then
DelayedSiloCreationOnTick()
end
end)
script.on_event(defines.events.on_sector_scanned, function (event)
if ENABLE_REGROWTH then
OarcRegrowthSectorScan(event)
end
end)
----------------------------------------
@ -300,9 +321,6 @@ end)
-- built stuff as permanent.
----------------------------------------
if ENABLE_REGROWTH then
script.on_event(defines.events.on_sector_scanned, function (event)
OarcRegrowthSectorScan(event)
end)
script.on_event(defines.events.on_robot_built_entity, function (event)
OarcRegrowthOffLimitsChunk(event.created_entity.position)

View File

@ -1,79 +1,318 @@
-- frontier_silo.lua
-- Nov 2016
-- Jan 2018
-- My take on frontier silos for my Oarc scenario
require("config")
require("locale/oarc_utils")
-- Create a rocket silo
local function CreateRocketSilo(surface, chunkArea, force)
if CheckIfInArea(global.siloPosition, chunkArea) then
--------------------------------------------------------------------------------
-- Frontier style rocket silo stuff
--------------------------------------------------------------------------------
-- Delete any entities beneat the silo?
for _, entity in pairs(surface.find_entities_filtered{area = {{global.siloPosition.x-5, global.siloPosition.y-6},{global.siloPosition.x+6, global.siloPosition.y+6}}}) do
entity.destroy()
end
-- 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
-- Set tiles below the silo
local tiles = {}
local i = 1
for dx = -6,6 do
for dy = -7,6 do
tiles[i] = {name = "grass", position = {global.siloPosition.x+dx, global.siloPosition.y+dy}}
i=i+1
end
end
surface.set_tiles(tiles, false)
tiles = {}
i = 1
for dx = -5,5 do
for dy = -6,5 do
tiles[i] = {name = "concrete", position = {global.siloPosition.x+dx, global.siloPosition.y+dy}}
i=i+1
end
end
surface.set_tiles(tiles, true)
global.siloPosition = {}
-- Create silo and assign to a force
local silo = surface.create_entity{name = "rocket-silo", position = {global.siloPosition.x+0.5, global.siloPosition.y}, force = force}
silo.destructible = false
silo.minable = false
random_angle_offset = math.random(0, math.pi * 2)
-- Make silo safe from being removed.
if ENABLE_REGROWTH then
OarcRegrowthOffLimits(global.siloPosition, 5)
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
-- Generates the rocket silo during chunk generation event
-- 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 GenerateRocketSiloChunk(event)
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)}
local safeArea = {left_top=
{x=global.siloPosition.x-150,
y=global.siloPosition.y-150},
right_bottom=
{x=global.siloPosition.x+150,
y=global.siloPosition.y+150}}
-- 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
function GenerateAllSilos(surface)
-- Create each silo in the list
for idx,siloPos in pairs(global.siloPosition) do
CreateRocketSilo(surface, siloPos, MAIN_FORCE)
end
-- Create rocket silo
CreateRocketSilo(surface, chunkArea, MAIN_FORCE)
CreateCropCircle(surface, global.siloPosition, chunkArea, 40)
end
function ChartRocketSiloArea(force, surface)
force.chart(surface, {{global.siloPosition.x-(CHUNK_SIZE*2), global.siloPosition.y-(CHUNK_SIZE*2)}, {global.siloPosition.x+(CHUNK_SIZE*2), global.siloPosition.y+(CHUNK_SIZE*2)}})
-- 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
locale/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("locale/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

View File

@ -25,34 +25,31 @@ my_fixed_width_style = {
maximal_width = 450
}
my_label_style = {
minimal_width = 450,
maximal_width = 450,
maximal_height = 10,
-- minimal_width = 450,
-- maximal_width = 50,
single_line = false,
font_color = {r=1,g=1,b=1},
top_padding = 0,
bottom_padding = 0
}
my_note_style = {
minimal_width = 450,
maximal_height = 10,
-- minimal_width = 450,
single_line = false,
font = "default-small-semibold",
font_color = {r=1,g=0.5,b=0.5},
top_padding = 0,
bottom_padding = 0
}
my_warning_style = {
minimal_width = 450,
maximal_width = 450,
maximal_height = 10,
-- minimal_width = 450,
-- maximal_width = 450,
single_line = false,
font_color = {r=1,g=0.1,b=0.1},
top_padding = 0,
bottom_padding = 0
}
my_spacer_style = {
minimal_width = 450,
maximal_width = 450,
minimal_height = 20,
maximal_height = 20,
minimal_height = 10,
font_color = {r=0,g=0,b=0},
top_padding = 0,
bottom_padding = 0
@ -71,20 +68,42 @@ my_player_list_admin_style = {
minimal_width = 200,
top_padding = 0,
bottom_padding = 0,
maximal_height = 15
single_line = false,
}
my_player_list_style = {
font = "default-semibold",
minimal_width = 200,
top_padding = 0,
bottom_padding = 0,
maximal_height = 15
single_line = false,
}
my_player_list_offline_style = {
-- font = "default-semibold",
font_color = {r=0.5,g=0.5,b=0.5},
minimal_width = 200,
top_padding = 0,
bottom_padding = 0,
single_line = false,
}
my_player_list_style_spacer = {
maximal_height = 15
minimal_height = 20,
}
my_color_red = {r=1,g=0.1,b=0.1}
my_longer_label_style = {
maximal_width = 600,
single_line = false,
font_color = {r=1,g=1,b=1},
top_padding = 0,
bottom_padding = 0
}
my_longer_warning_style = {
maximal_width = 600,
single_line = false,
font_color = {r=1,g=0.1,b=0.1},
top_padding = 0,
bottom_padding = 0
}
--------------------------------------------------------------------------------
-- General Helper Functions
@ -114,6 +133,13 @@ function SendBroadcastMsg(msg)
end
end
-- Send a message to a player, safely checks if they exist and are online.
function SendMsg(playerName, msg)
if ((game.players[playerName] ~= nil) and (game.players[playerName].connected)) then
game.players[playerName].print(msg)
end
end
-- Special case for ensuring that if I create the server, my messages are
-- used instead of the generic insert msg warning.
function SetServerWelcomeMessages()
@ -150,6 +176,15 @@ function TableLength(T)
return count
end
-- Simple function to get distance between two positions.
function getDistance(posA, posB)
-- Get the length for each of the components x and y
local xDist = posB.x - posA.x
local yDist = posB.y - posA.y
return math.sqrt( (xDist ^ 2) + (yDist ^ 2) )
end
-- Chart area for a force
function ChartArea(force, position, chunkDist, surface)
force.chart(surface,
@ -201,6 +236,7 @@ function GiveQuickStartPowerArmor(player)
p_armor.put({name = "solar-panel-equipment"})
end
player.insert{name="construction-robot", count = 100}
player.insert{name="belt-immunity-equipment", count = 1}
end
end
@ -265,6 +301,17 @@ function ShareChatBetweenForces(player, msg)
end
end
-- Merges force2 INTO force1 but keeps all research between both forces.
function MergeForcesKeepResearch(force1, force2)
for techName,luaTech in pairs(force2.technologies) do
if (luaTech.researched) then
force1.technologies[techName].researched = true
force1.technologies[techName].level = luaTech.level
end
end
game.merge_forces(force2, force1)
end
-- Undecorator
function RemoveDecorationsArea(surface, area)
surface.destroy_decoratives(area)
@ -284,6 +331,27 @@ function ApplyStyle (guiIn, styleIn)
end
end
-- Shorter way to add a label with a style
function AddLabel(guiIn, name, message, style)
guiIn.add{name = name, type = "label",
caption=message}
ApplyStyle(guiIn[name], style)
end
-- Shorter way to add a spacer
function AddSpacer(guiIn, name)
guiIn.add{name = name, type = "label",
caption=" "}
ApplyStyle(guiIn[name], my_spacer_style)
end
-- Shorter way to add a spacer with a decorative line
function AddSpacerLine(guiIn, name)
guiIn.add{name = name, type = "label",
caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"}
ApplyStyle(guiIn[name], my_spacer_style)
end
-- Get a random 1 or -1
function RandomNegPos()
if (math.random(0,1) == 1) then
@ -320,15 +388,15 @@ function IsChunkAreaUngenerated(chunkPos, chunkDist, surface)
end
-- Clear out enemies around an area with a certain distance
function ClearNearbyEnemies(player, safeDist)
function ClearNearbyEnemies(pos, safeDist, surface)
local safeArea = {left_top=
{x=player.position.x-safeDist,
y=player.position.y-safeDist},
{x=pos.x-safeDist,
y=pos.y-safeDist},
right_bottom=
{x=player.position.x+safeDist,
y=player.position.y+safeDist}}
{x=pos.x+safeDist,
y=pos.y+safeDist}}
for _, entity in pairs(player.surface.find_entities_filtered{area = safeArea, force = "enemy"}) do
for _, entity in pairs(surface.find_entities_filtered{area = safeArea, force = "enemy"}) do
entity.destroy()
end
end
@ -441,7 +509,9 @@ end
-- Removes the entity type from the area given
function RemoveInArea(surface, area, type)
for key, entity in pairs(surface.find_entities_filtered({area=area, type= type})) do
entity.destroy()
if entity.valid and entity and entity.position then
entity.destroy()
end
end
end
@ -449,8 +519,10 @@ end
-- Only if it is within given distance from given position.
function RemoveInCircle(surface, area, type, pos, dist)
for key, entity in pairs(surface.find_entities_filtered({area=area, type= type})) do
if ((pos.x - entity.position.x)^2 + (pos.y - entity.position.y)^2 < dist^2) then
entity.destroy()
if entity.valid and entity and entity.position then
if ((pos.x - entity.position.x)^2 + (pos.y - entity.position.y)^2 < dist^2) then
entity.destroy()
end
end
end
end
@ -484,10 +556,149 @@ end
-- Adjust alien params
function ConfigureAlienStartingParams()
game.map_settings.enemy_evolution.time_factor=0
game.map_settings.enemy_evolution.destroy_factor = game.map_settings.enemy_evolution.destroy_factor / ENEMY_DESTROY_FACTOR_DIVISOR
game.map_settings.enemy_evolution.pollution_factor = game.map_settings.enemy_evolution.pollution_factor / ENEMY_POLLUTION_FACTOR_DIVISOR
-- These are the default values for reference:
-- "time_factor": 0.000004,
-- "destroy_factor": 0.002,
-- "pollution_factor": 0.000015
if ENEMY_TIME_FACTOR_DISABLE then
game.map_settings.enemy_evolution.time_factor = 0
else
game.map_settings.enemy_evolution.time_factor=game.map_settings.enemy_evolution.time_factor / ENEMY_TIME_FACTOR_DIVISOR
end
if ENEMY_POLLUTION_FACTOR_DISABLE then
game.map_settings.enemy_evolution.pollution_factor = 0
else
game.map_settings.enemy_evolution.pollution_factor = game.map_settings.enemy_evolution.pollution_factor / ENEMY_POLLUTION_FACTOR_DIVISOR
end
if ENEMY_DESTROY_FACTOR_DISABLE then
game.map_settings.enemy_evolution.destroy_factor = 0
else
game.map_settings.enemy_evolution.destroy_factor = game.map_settings.enemy_evolution.destroy_factor / ENEMY_DESTROY_FACTOR_DIVISOR
end
game.map_settings.enemy_expansion.enabled = ENEMY_EXPANSION
if (OARC_DIFFICULTY_CUSTOM) then
game.map_settings.pollution.diffusion_ratio = 0.08
game.map_settings.pollution.ageing = 1
game.map_settings.enemy_expansion.max_expansion_distance = 20
game.map_settings.enemy_expansion.settler_group_min_size = 2
game.map_settings.enemy_expansion.settler_group_max_size = 10
game.map_settings.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*15
game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*60
game.map_settings.unit_group.min_group_gathering_time = TICKS_PER_MINUTE
game.map_settings.unit_group.max_group_gathering_time = 4 * TICKS_PER_MINUTE
game.map_settings.unit_group.max_wait_time_for_late_members = 1 * TICKS_PER_MINUTE
game.map_settings.unit_group.max_unit_group_size = 15
-- game.map_settings.pollution.enabled=true,
-- -- these are values for 60 ticks (1 simulated second)
-- --
-- -- amount that is diffused to neighboring chunk
-- -- (possibly repeated for other directions as well)
-- game.map_settings.pollution.diffusion_ratio=0.02,
-- -- this much PUs must be on the chunk to start diffusing
-- game.map_settings.pollution.min_to_diffuse=15,
-- -- constant modifier a percentage of 1 - the pollution eaten by a chunks tiles
-- game.map_settings.pollution.ageing=1,
-- -- anything bigger than this is visualised as this value
-- game.map_settings.pollution.expected_max_per_chunk=7000,
-- -- anything lower than this (but > 0) is visualised as this value
-- game.map_settings.pollution.min_to_show_per_chunk=700,
-- game.map_settings.pollution.min_pollution_to_damage_trees = 3500,
-- game.map_settings.pollution.pollution_with_max_forest_damage = 10000,
-- game.map_settings.pollution.pollution_per_tree_damage = 2000,
-- game.map_settings.pollution.pollution_restored_per_tree_damage = 500,
-- game.map_settings.pollution.max_pollution_to_restore_trees = 1000
-- game.map_settings.enemy_expansion.enabled = true,
-- -- Distance in chunks from the furthest base around.
-- -- This prevents expansions from reaching too far into the
-- -- player's territory
-- game.map_settings.enemy_expansion.max_expansion_distance = 7,
-- game.map_settings.enemy_expansion.friendly_base_influence_radius = 2,
-- game.map_settings.enemy_expansion.enemy_building_influence_radius = 2,
-- -- A candidate chunk's score is given as follows:
-- -- player = 0
-- -- for neighbour in all chunks within enemy_building_influence_radius from chunk:
-- -- player += number of player buildings on neighbour
-- -- * building_coefficient
-- -- * neighbouring_chunk_coefficient^distance(chunk, neighbour)
-- --
-- -- base = 0
-- -- for neighbour in all chunk within friendly_base_influence_radius from chunk:
-- -- base += num of enemy bases on neighbour
-- -- * other_base_coefficient
-- -- * neighbouring_base_chunk_coefficient^distance(chunk, neighbour)
-- --
-- -- score(chunk) = 1 / (1 + player + base)
-- --
-- -- The iteration is over a square region centered around the chunk for which the calculation is done,
-- -- and includes the central chunk as well. distance is the Manhattan distance, and ^ signifies exponentiation.
-- game.map_settings.enemy_expansion.building_coefficient = 0.1,
-- game.map_settings.enemy_expansion.other_base_coefficient = 2.0,
-- game.map_settings.enemy_expansion.neighbouring_chunk_coefficient = 0.5,
-- game.map_settings.enemy_expansion.neighbouring_base_chunk_coefficient = 0.4;
-- -- A chunk has to have at most this much percent unbuildable tiles for it to be considered a candidate.
-- -- This is to avoid chunks full of water to be marked as candidates.
-- game.map_settings.enemy_expansion.max_colliding_tiles_coefficient = 0.9,
-- -- Size of the group that goes to build new base (in game this is multiplied by the
-- -- evolution factor).
-- game.map_settings.enemy_expansion.settler_group_min_size = 5,
-- game.map_settings.enemy_expansion.settler_group_max_size = 20,
-- -- Ticks to expand to a single
-- -- position for a base is used.
-- --
-- -- cooldown is calculated as follows:
-- -- cooldown = lerp(max_expansion_cooldown, min_expansion_cooldown, -e^2 + 2 * e),
-- -- where lerp is the linear interpolation function, and e is the current evolution factor.
-- game.map_settings.enemy_expansion.min_expansion_cooldown = 4 * 3600,
-- game.map_settings.enemy_expansion.max_expansion_cooldown = 60 * 3600
-- -- pollution triggered group waiting time is a random time between min and max gathering time
-- game.map_settings.unit_group.min_group_gathering_time = 3600,
-- game.map_settings.unit_group.max_group_gathering_time = 10 * 3600,
-- -- after the gathering is finished the group can still wait for late members,
-- -- but it doesn't accept new ones anymore
-- game.map_settings.unit_group.max_wait_time_for_late_members = 2 * 3600,
-- -- limits for group radius (calculated by number of numbers)
-- game.map_settings.unit_group.max_group_radius = 30.0,
-- game.map_settings.unit_group.min_group_radius = 5.0,
-- -- when a member falls behind the group he can speedup up till this much of his regular speed
-- game.map_settings.unit_group.max_member_speedup_when_behind = 1.4,
-- -- When a member gets ahead of its group, it will slow down to at most this factor of its speed
-- game.map_settings.unit_group.max_member_slowdown_when_ahead = 0.6,
-- -- When members of a group are behind, the entire group will slow down to at most this factor of its max speed
-- game.map_settings.unit_group.max_group_slowdown_factor = 0.3,
-- -- If a member falls behind more than this times the group radius, the group will slow down to max_group_slowdown_factor
-- game.map_settings.unit_group.max_group_member_fallback_factor = 3,
-- -- If a member falls behind more than this time the group radius, it will be removed from the group.
-- game.map_settings.unit_group.member_disown_distance = 10,
-- game.map_settings.unit_group.tick_tolerance_when_member_arrives = 60,
-- -- Maximum number of automatically created unit groups gathering for attack at any time.
-- game.map_settings.unit_group.max_gathering_unit_groups = 30,
-- -- Maximum size of an attack unit group. This only affects automatically-created unit groups; manual groups
-- -- created through the API are unaffected.
-- game.map_settings.unit_group.max_unit_group_size = 200
end
end
-- Add Long Reach to Character
@ -522,11 +733,22 @@ local function ExpandPlayerListGui(player)
scrollFrame.horizontal_scroll_policy = "never"
for _,player in pairs(game.connected_players) do
local caption_str = player.name.." ["..player.force.name.."]".." ("..formattime_hours_mins(player.online_time)..")"
local text = scrollFrame.add{type="label", caption=caption_str, name=player.name.."_plist"}
if (player.admin) then
ApplyStyle(text, my_player_list_admin_style)
AddLabel(scrollFrame, player.name.."_plist", caption_str, my_player_list_admin_style)
else
ApplyStyle(text, my_player_list_style)
AddLabel(scrollFrame, player.name.."_plist", caption_str, my_player_list_style)
end
end
-- List offline players
if (PLAYER_LIST_OFFLINE_PLAYERS) then
AddLabel(scrollFrame, "offline_title_msg", "Offline Players:", my_label_style)
for _,player in pairs(game.players) do
if (not player.connected) then
local caption_str = player.name.." ["..player.force.name.."]".." ("..formattime_hours_mins(player.online_time)..")"
local text = scrollFrame.add{type="label", caption=caption_str, name=player.name.."_plist"}
ApplyStyle(text, my_player_list_offline_style)
end
end
end
local spacer = scrollFrame.add{type="label", caption=" ", name="plist_spacer_plist"}
@ -550,6 +772,22 @@ end
function AntiGriefing(force)
force.zoom_to_world_deconstruction_planner_enabled=false
force.friendly_fire=false
SetForceGhostTimeToLive(force)
end
function SetForceGhostTimeToLive(force)
if GHOST_TIME_TO_LIVE ~= 0 then
force.ghost_time_to_live = GHOST_TIME_TO_LIVE+1
end
end
function SetItemBlueprintTimeToLive(event)
local type = event.created_entity.type
if type == "entity-ghost" or type == "tile-ghost" then
if GHOST_TIME_TO_LIVE ~= 0 then
event.created_entity.time_to_live = GHOST_TIME_TO_LIVE
end
end
end
--------------------------------------------------------------------------------
@ -587,7 +825,7 @@ function DropGravestoneChests(player)
local inv = player.get_inventory(id)
if (not inv.is_empty()) then
if ((#inv > 0) and not inv.is_empty()) then
for j = 1, #inv do
if inv[j].valid_for_read then
@ -622,34 +860,6 @@ function DropGravestoneChests(player)
end
end
--------------------------------------------------------------------------------
-- 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()
if (global.siloPosition == nil) then
-- Get an X,Y on a circle far away.
local distX = math.random(0,SILO_CHUNK_DISTANCE_X)
local distY = RandomNegPos() * math.floor(math.sqrt(SILO_CHUNK_DISTANCE_X^2 - distX^2))
local distX = RandomNegPos() * distX
-- Set those values.
local siloX = distX*CHUNK_SIZE + CHUNK_SIZE/2
local siloY = distY*CHUNK_SIZE + CHUNK_SIZE/2
global.siloPosition = {x = siloX, y = siloY}
end
end
-- Sets the global.siloPosition var to the set in the config file
function SetFixedSiloPosition()
if (global.siloPosition == nil) then
global.siloPosition = SILO_POSITION
end
end
--------------------------------------------------------------------------------
-- Autofill Stuff
--------------------------------------------------------------------------------
@ -713,7 +923,7 @@ function AutoFillVehicle(player, vehicle)
-- Attempt to transfer some fuel
if ((vehicle.name == "car") or (vehicle.name == "tank") or (vehicle.name == "locomotive")) then
TransferItemMultipleTypes(mainInv, vehicle, {"rocket-fuel", "solid-fuel", "coal", "raw-wood"}, 50)
TransferItemMultipleTypes(mainInv, vehicle, {"nuclear-fuel", "rocket-fuel", "solid-fuel", "coal", "raw-wood"}, 50)
end
-- Attempt to transfer some ammo
@ -747,14 +957,14 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius)
-- Fill in all unexpected water in a circle
if (distVar < tileRadSqr) then
if (surface.get_tile(i,j).collides_with("water-tile") or ENABLE_SPAWN_FORCE_GRASS) then
table.insert(dirtTiles, {name = "grass", position ={i,j}})
table.insert(dirtTiles, {name = "grass-1", position ={i,j}})
end
end
-- Create a circle of trees around the spawn point.
if ((distVar < tileRadSqr-200) and
(distVar > tileRadSqr-300)) then
surface.create_entity({name="tree-01", amount=1, position={i, j}})
(distVar > tileRadSqr-400)) then
surface.create_entity({name="tree-02", amount=1, position={i, j}})
end
end
end
@ -773,12 +983,12 @@ function CreateCropOctagon(surface, centerPos, chunkArea, tileRadius)
local distVar1 = math.floor(math.max(math.abs(centerPos.x - i), math.abs(centerPos.y - j)))
local distVar2 = math.floor(math.abs(centerPos.x - i) + math.abs(centerPos.y - j))
local distVar = math.max(distVar1, distVar2 * 0.707);
local distVar = math.max(distVar1*1.1, distVar2 * 0.707*1.1);
-- Fill in all unexpected water in a circle
if (distVar < tileRadius+2) then
if (surface.get_tile(i,j).collides_with("water-tile") or ENABLE_SPAWN_FORCE_GRASS) then
table.insert(dirtTiles, {name = "grass", position ={i,j}})
table.insert(dirtTiles, {name = "grass-1", position ={i,j}})
end
end
@ -806,16 +1016,16 @@ function CreateMoat(surface, centerPos, chunkArea, tileRadius)
local distVar = math.floor((centerPos.x - i)^2 + (centerPos.y - j)^2)
-- Create a circle of water
if ((distVar < tileRadSqr+400) and
(distVar > tileRadSqr-500)) then
if ((distVar < tileRadSqr+(1500*MOAT_SIZE_MODIFIER)) and
(distVar > tileRadSqr)) then
table.insert(waterTiles, {name = "water", position ={i,j}})
end
-- Enforce land inside the edges of the circle to make sure it's
-- a clean transition
if ((distVar < tileRadSqr-500) and
(distVar > tileRadSqr-1000)) then
table.insert(waterTiles, {name = "grass", position ={i,j}})
if ((distVar <= tileRadSqr) and
(distVar > tileRadSqr-10000)) then
table.insert(waterTiles, {name = "grass-1", position ={i,j}})
end
end
end
@ -835,6 +1045,9 @@ end
-- Function to generate a resource patch, of a certain size/amount at a pos.
function GenerateResourcePatch(surface, resourceName, diameter, pos, amount)
local midPoint = math.floor(diameter/2)
if (diameter == 0) then
return
end
for y=0, diameter do
for x=0, diameter do
if (not ENABLE_RESOURCE_SHAPE_CIRCLE or ((x-midPoint)^2 + (y-midPoint)^2 < midPoint^2)) then
@ -871,11 +1084,15 @@ function GenerateStartingResources(surface, pos)
-- Tree generation is taken care of in chunk generation
-- Generate 2 oil patches
surface.create_entity({name="crude-oil", amount=START_OIL_AMOUNT,
position={pos.x+START_RESOURCE_OIL_A_POS_X, pos.y+START_RESOURCE_OIL_A_POS_Y}})
surface.create_entity({name="crude-oil", amount=START_OIL_AMOUNT,
position={pos.x+START_RESOURCE_OIL_B_POS_X, pos.y+START_RESOURCE_OIL_B_POS_Y}})
-- Generate oil patches
oil_patch_x=pos.x+START_RESOURCE_OIL_POS_X
oil_patch_y=pos.y+START_RESOURCE_OIL_POS_Y
for i=1,START_RESOURCE_OIL_NUM_PATCHES do
surface.create_entity({name="crude-oil", amount=START_OIL_AMOUNT,
position={oil_patch_x, oil_patch_y}})
oil_patch_x=oil_patch_x+START_RESOURCE_OIL_X_OFFSET
oil_patch_y=oil_patch_y+START_RESOURCE_OIL_Y_OFFSET
end
-- Generate Stone
GenerateResourcePatch(surface, "stone", START_RESOURCE_STONE_SIZE, stonePos, START_STONE_AMOUNT)
@ -895,12 +1112,12 @@ end
-- Create the spawn areas.
-- Clear the spawn areas.
-- This should be run inside the chunk generate event and be given a list of all
-- unique spawn points.
-- This clears enemies in the immediate area, creates a slightly safe area around it,
-- And spawns the basic resources as well
function CreateSpawnAreas(surface, chunkArea, spawnPointTable)
-- It no LONGER generates the resources though as that is now handled in a delayed event!
function SetupAndClearSpawnAreas(surface, chunkArea, spawnPointTable)
for name,spawn in pairs(spawnPointTable) do
-- Create a bunch of useful area and position variables
@ -926,8 +1143,10 @@ function CreateSpawnAreas(surface, chunkArea, spawnPointTable)
if CheckIfInArea(chunkAreaCenter,landArea) then
-- Remove trees/resources inside the spawn area
RemoveInCircle(surface, chunkArea, "tree", spawn.pos, ENFORCE_LAND_AREA_TILE_DIST+5)
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)
if (SPAWN_TREE_CIRCLE_ENABLED) then
CreateCropCircle(surface, spawn.pos, chunkArea, ENFORCE_LAND_AREA_TILE_DIST)
@ -937,7 +1156,7 @@ function CreateSpawnAreas(surface, chunkArea, spawnPointTable)
end
if (SPAWN_MOAT_CHOICE_ENABLED) then
if (spawn.moat) then
CreateMoat(surface, spawn.pos, chunkArea, ENFORCE_LAND_AREA_TILE_DIST+10)
CreateMoat(surface, spawn.pos, chunkArea, ENFORCE_LAND_AREA_TILE_DIST)
end
end
end
@ -945,68 +1164,47 @@ function CreateSpawnAreas(surface, chunkArea, spawnPointTable)
-- Provide starting resources
-- This is run on the bottom, right chunk of the spawn area which should be
-- generated last, so it should work everytime.
if CheckIfInArea(spawnPosOffset,chunkArea) then
CreateWaterStrip(surface,
{x=spawn.pos.x+WATER_SPAWN_OFFSET_X, y=spawn.pos.y+WATER_SPAWN_OFFSET_Y},
WATER_SPAWN_LENGTH)
GenerateStartingResources(surface, spawn.pos)
end
-- if CheckIfInArea(spawnPosOffset,chunkArea) then
-- CreateWaterStrip(surface,
-- {x=spawn.pos.x+WATER_SPAWN_OFFSET_X, y=spawn.pos.y+WATER_SPAWN_OFFSET_Y},
-- WATER_SPAWN_LENGTH)
-- CreateWaterStrip(surface,
-- {x=spawn.pos.x+WATER_SPAWN_OFFSET_X, y=spawn.pos.y+WATER_SPAWN_OFFSET_Y+1},
-- WATER_SPAWN_LENGTH)
-- GenerateStartingResources(surface, spawn.pos)
-- end
end
end
--------------------------------------------------------------------------------
-- Surface Generation Functions
--------------------------------------------------------------------------------
-- To use RSO resources, we have to disable vanilla ore generation
local surface_autoplace_none = {
["coal"]={
size="none"
},
["copper-ore"]={
size="none"
},
["iron-ore"]={
size="none"
},
["stone"]={
size="none"
},
["uranium-ore"]={
size="none"
},
["crude-oil"]={
size="none"
},
["enemy-base"]={
size="none"
}
}
RSO_MODE = 1
VANILLA_MODE = 2
function CreateLobbySurface()
local surface = game.create_surface("Lobby",{width = 1, height = 1})
surface.set_tiles({{name = "out-of-map",position = {1,1}}})
end
function CreateGameSurface(mode)
local mapSettings = game.surfaces["nauvis"].map_gen_settings
if CMD_LINE_MAP_GEN then
mapSettings.terrain_segmentation = global.clMapGen.terrain_segmentation
mapSettings.water = global.clMapGen.water
mapSettings.starting_area = global.clMapGen.starting_area
mapSettings.peaceful_mode = global.clMapGen.peaceful_mode
mapSettings.seed = global.clMapGen.seed
mapSettings.autoplace_controls = global.clMapGen.autoplace_controls
mapSettings.cliff_settings = global.clMapGen.cliff_settings
end
-- To use RSO resources, we have to disable vanilla ore generation
if (mode == RSO_MODE) then
mapSettings.terrain_segmentation=MAP_SETTINGS_RSO_TERRAIN_SEGMENTATION
mapSettings.water=MAP_SETTINGS_RSO_WATER
mapSettings.starting_area=MAP_SETTINGS_RSO_STARTING_AREA
mapSettings.peaceful_mode=MAP_SETTINGS_RSO_PEACEFUL
mapSettings.seed=math.random(999999999);
mapSettings.autoplace_controls = {
["coal"]={ size="none" },
["copper-ore"]={ size="none" },
["iron-ore"]={ size="none" },
["stone"]={ size="none" },
["uranium-ore"]={ size="none" },
["crude-oil"]={ size="none" },
["enemy-base"]={ size="none" }
}
mapSettings.autoplace_controls["coal"].size="none"
mapSettings.autoplace_controls["copper-ore"].size="none"
mapSettings.autoplace_controls["iron-ore"].size="none"
mapSettings.autoplace_controls["stone"].size="none"
mapSettings.autoplace_controls["uranium-ore"].size="none"
mapSettings.autoplace_controls["crude-oil"].size="none"
mapSettings.autoplace_controls["enemy-base"].size="none"
end
local surface = game.create_surface(GAME_SURFACE_NAME,mapSettings)
@ -1025,7 +1223,7 @@ function CreateWall(surface, pos)
end
end
function CreateHoldingPen(surface, chunkArea)
function CreateHoldingPen(surface, chunkArea, sizeTiles, walls)
if (((chunkArea.left_top.x == -32) or (chunkArea.left_top.x == 0)) and
((chunkArea.left_top.y == -32) or (chunkArea.left_top.y == 0))) then
@ -1033,6 +1231,7 @@ function CreateHoldingPen(surface, chunkArea)
RemoveAliensInArea(surface, chunkArea)
RemoveInArea(surface, chunkArea, "tree")
RemoveInArea(surface, chunkArea, "resource")
RemoveInArea(surface, chunkArea, "cliff")
-- This loop runs through each tile
local grassTiles = {}
@ -1040,26 +1239,34 @@ function CreateHoldingPen(surface, chunkArea)
for i=chunkArea.left_top.x,chunkArea.right_bottom.x,1 do
for j=chunkArea.left_top.y,chunkArea.right_bottom.y,1 do
-- Fill all area with grass only
table.insert(grassTiles, {name = "grass", position ={i,j}})
if ((i>-sizeTiles) and (i<(sizeTiles-1)) and (j>-sizeTiles) and (j<(sizeTiles-1))) then
-- Create the spawn box walls
if (j<15 and j>-16) then
-- Fill all area with grass only
table.insert(grassTiles, {name = "grass-1", position ={i,j}})
-- Create the spawn box walls
if (j<(sizeTiles-1) and j>-sizeTiles) then
-- Create horizontal sides of center spawn box
if (((j>-sizeTiles and j<-(sizeTiles-4)) or (j<(sizeTiles-1) and j>(sizeTiles-5))) and (i<(sizeTiles-1) and i>-sizeTiles)) then
if walls then
CreateWall(surface, {i,j})
else
table.insert(waterTiles, {name = "water", position ={i,j}})
end
end
-- Create vertical sides of center spawn box
if ((i>-sizeTiles and i<-(sizeTiles-4)) or (i<(sizeTiles-1) and i>(sizeTiles-5))) then
if walls then
CreateWall(surface, {i,j})
else
table.insert(waterTiles, {name = "water", position ={i,j}})
end
end
-- Create horizontal sides of center spawn box
if (((j>-16 and j<-12) or (j<15 and j>11)) and (i<15 and i>-16)) then
-- CreateWall(surface, {i,j})
table.insert(waterTiles, {name = "water", position ={i,j}})
end
-- Create vertical sides of center spawn box
if ((i>-16 and i<-12) or (i<15 and i>11)) then
-- CreateWall(surface, {i,j})
table.insert(waterTiles, {name = "water", position ={i,j}})
end
end
end
end
surface.set_tiles(grassTiles)
@ -1067,10 +1274,6 @@ function CreateHoldingPen(surface, chunkArea)
end
end
function CreateHoldingPenGenerateChunk(event)
CreateHoldingPen(event.surface, event.area)
end
--------------------------------------------------------------------------------
-- EVENT SPECIFIC FUNCTIONS
--------------------------------------------------------------------------------

View File

@ -1,269 +0,0 @@
--[[------------------------------------
RandomLua v0.3.1
Pure Lua Pseudo-Random Numbers Generator
Under the MIT license.
copyright(c) 2011 linux-man
--]]------------------------------------
local _M = {}
local mod = math.fmod
local floor = math.floor
local abs = math.abs
local function normalize(n) --keep numbers at (positive) 32 bits
return n % 0x80000000
end
local function bit_and(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if (a % 2 == 1) and (b % 2 == 1) then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function bit_or(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if (a % 2 == 1) or (b % 2 == 1) then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function bit_xor(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if a % 2 ~= b % 2 then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function seed()
--return normalize(tonumber(tostring(os.time()):reverse()))
return normalize(os.time())
end
--Mersenne twister
mersenne_twister = {}
mersenne_twister.__index = mersenne_twister
function mersenne_twister:randomseed(s)
if not s then s = seed() end
self.mt[0] = normalize(s)
for i = 1, 623 do
self.mt[i] = normalize(0x6c078965 * bit_xor(self.mt[i-1], floor(self.mt[i-1] / 0x40000000)) + i)
end
end
function mersenne_twister:random(a, b)
local y
if self.index == 0 then
for i = 0, 623 do
--y = bit_or(floor(self.mt[i] / 0x80000000) * 0x80000000, self.mt[(i + 1) % 624] % 0x80000000)
y = self.mt[(i + 1) % 624] % 0x80000000
self.mt[i] = bit_xor(self.mt[(i + 397) % 624], floor(y / 2))
if y % 2 ~= 0 then self.mt[i] = bit_xor(self.mt[i], 0x9908b0df) end
end
end
y = self.mt[self.index]
y = bit_xor(y, floor(y / 0x800))
y = bit_xor(y, bit_and(normalize(y * 0x80), 0x9d2c5680))
y = bit_xor(y, bit_and(normalize(y * 0x8000), 0xefc60000))
y = bit_xor(y, floor(y / 0x40000))
self.index = (self.index + 1) % 624
if not a then return y / 0x80000000
elseif not b then
if a == 0 then return y
else return 1 + (y % a)
end
else
return a + (y % (b - a + 1))
end
end
function _M.twister(s)
local temp = {}
setmetatable(temp, mersenne_twister)
temp.mt = {}
temp.index = 0
temp:randomseed(s)
return temp
end
--Linear Congruential Generator
linear_congruential_generator = {}
linear_congruential_generator.__index = linear_congruential_generator
function linear_congruential_generator:random(a, b)
local y = (self.a * self.x + self.c) % self.m
self.x = y
if not a then return y / 0x10000
elseif not b then
if a == 0 then return y
else return 1 + (y % a) end
else
return a + (y % (b - a + 1))
end
end
function linear_congruential_generator:randomseed(s)
if not s then s = seed() end
self.x = normalize(s)
end
function _M.lcg(s, r)
local temp = {}
setmetatable(temp, linear_congruential_generator)
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
if r then
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
end
temp:randomseed(s)
return temp
end
-- Multiply-with-carry
multiply_with_carry = {}
multiply_with_carry.__index = multiply_with_carry
function multiply_with_carry:random(a, b)
local m = self.m
local t = self.a * self.x + self.c
local y = t % m
self.x = y
self.c = floor(t / m)
if not a then return y / 0x10000
elseif not b then
if a == 0 then return y
else return 1 + (y % a) end
else
local diff = 0
if a == b then return a end
if a < 0 then
diff = abs(a)
a = a + diff
b = b + diff
end
return a + (y % (b - a + 1)) - diff
end
end
function multiply_with_carry:randomseed(s)
if not s then s = seed() end
self.c = self.ic
self.x = normalize(s)
end
function _M.mwc(s, r)
local temp = {}
setmetatable(temp, multiply_with_carry)
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
if r then
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
end
temp.ic = temp.c
temp:randomseed(s)
return temp
end
function _M.mwvc(s)
return _M.mwc(s, 'mvc')
end
local B = 0x10000
-- rough adaptation of Knuth float generator
function _M.krandom( seedobj, fVal1, fVal2 )
local ma = seedobj.ma
local seed = seedobj.seed
local mj, mk
if seed < 0 or not ma then
ma = {}
seedobj.ma = ma
mj = normalize( seed )
mj = mod( mj, B )
ma[55] = mj
mk = 1
for i = 1, 54 do
local ii = mod( 21 * i, 55 )
ma[ii] = mk
mk = mj - mk
if mk < 0 then mk = mk + B end
mj = ma[ii]
end
for k = 1, 4 do
for i = 1, 55 do
ma[i] = ma[i] - ma[ 1 + mod( i + 30, 55) ]
if ma[i] < 0 then ma[i] = ma[i] + B end
end
end
seedobj.inext = 0
seedobj.inextp = 31
seedobj.seed = 1
end -- if
local inext = seedobj.inext
local inextp = seedobj.inextp
inext = inext + 1
if inext == 56 then inext = 1 end
seedobj.inext = inext
inextp = inextp + 1
if inextp == 56 then inextp = 1 end
seedobj.inextp = inextp
mj = ma[ inext ] - ma[ inextp ]
if mj < 0 then mj = mj + B end
ma[ inext ] = mj
local temp_rand = mj / B
if fVal2 then
return floor( fVal1 + 0.5 + temp_rand * ( fVal2 - fVal1 ) )
elseif fVal1 then
return floor( temp_rand * fVal1 ) + 1
else
return temp_rand
end
end
-- Sys rand
sys_rand = {}
sys_rand.__index = sys_rand
function sys_rand:random(a, b)
local diff = 0
if a and b and a == b then math.random(); return a end
if a and b then
if a < 0 then
diff = abs(a)
a = a + diff
b = b + diff
end
return math.random(a, b) - diff
end
if a and a == 0 then return floor(math.random() * 0x10000) end
if a then return math.random(a) end
return math.random()
end
function sys_rand:randomseed(s)
-- ignore
return
end
function _M.sys_rand(s)
local temp = {}
setmetatable(temp, sys_rand)
return temp
end
return _M

View File

@ -1,104 +1,104 @@
--[[--
Metaball implementation for LUA by Dark
For bruteforce usage, nor efficient nor fast
Force scales to from inf to 1 at R
--]]--
local _M = {}
local sqrt = math.sqrt
local cos = math.cos
local sin = math.sin
local abs = math.abs
local zero_value = 0x80000000
--Classic ball
local MetaBall = {x=0, y=0, radius=0, goo=1, type="MetaBall"}
MetaBall.__index = MetaBall
_M.MetaBall=MetaBall
function MetaBall:new(x, y, radius, goo)
goo = goo or 1
return setmetatable({x=x, y=y, radius=radius, goo=goo}, MetaBall)
end
function MetaBall:force(x, y)
--Calculate force at point x y
local force = sqrt( (x - self.x)^2 + (y - self.y)^2 )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--Ellipse
local MetaEllipse = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaEllipse"}
MetaEllipse.__index = MetaEllipse
_M.MetaEllipse=MetaEllipse
function MetaEllipse:new(x, y, radius, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaEllipse)
end
function MetaEllipse:force(x, y)
--Calculate force at point x y
local force = sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--SquareBalls
local MetaSquare = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaSquare"}
MetaSquare.__index = MetaSquare
_M.MetaSquare=MetaSquare
function MetaSquare:new(x, y, radius, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaSquare)
end
function MetaSquare:force(x, y)
--Calculate force at point x y
local force = ( abs( (x - self.x)*self.cosa + (y - self.y)*self.sina )/self.x_scale +
abs( (y - self.y)*self.cosa - (x - self.x)*self.sina )/self.y_scale )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--Donuts
local MetaDonut = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaDonut"}
MetaDonut.__index = MetaDonut
_M.MetaDonut=MetaDonut
function MetaDonut:new(x, y, out_r, int_r, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
if int_r >= out_r then error("int_r >= out_r ("..int_r.." > "..out_r); return; end
local radius = out_r--(out_r - int_r)*0.5
local radius2 = int_r--(radius2 + radius)*0.5
return setmetatable({x=x, y=y, radius=radius, radius2=radius2, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaDonut)
end
function MetaDonut:force(x, y)
--Calculate force at point x y
local force = abs(self.radius - sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) ))
if force == 0 then return zero_value end
return (self.radius2 / force)^self.goo
end
--[[--
Metaball implementation for LUA by Dark
For bruteforce usage, nor efficient nor fast
Force scales to from inf to 1 at R
--]]--
local _M = {}
local sqrt = math.sqrt
local cos = math.cos
local sin = math.sin
local abs = math.abs
local zero_value = 0x80000000
--Classic ball
local MetaBall = {x=0, y=0, radius=0, goo=1, type="MetaBall"}
MetaBall.__index = MetaBall
_M.MetaBall=MetaBall
function MetaBall:new(x, y, radius, goo)
goo = goo or 1
return setmetatable({x=x, y=y, radius=radius, goo=goo}, MetaBall)
end
function MetaBall:force(x, y)
--Calculate force at point x y
local force = sqrt( (x - self.x)^2 + (y - self.y)^2 )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--Ellipse
local MetaEllipse = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaEllipse"}
MetaEllipse.__index = MetaEllipse
_M.MetaEllipse=MetaEllipse
function MetaEllipse:new(x, y, radius, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaEllipse)
end
function MetaEllipse:force(x, y)
--Calculate force at point x y
local force = sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--SquareBalls
local MetaSquare = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaSquare"}
MetaSquare.__index = MetaSquare
_M.MetaSquare=MetaSquare
function MetaSquare:new(x, y, radius, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaSquare)
end
function MetaSquare:force(x, y)
--Calculate force at point x y
local force = ( abs( (x - self.x)*self.cosa + (y - self.y)*self.sina )/self.x_scale +
abs( (y - self.y)*self.cosa - (x - self.x)*self.sina )/self.y_scale )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--Donuts
local MetaDonut = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaDonut"}
MetaDonut.__index = MetaDonut
_M.MetaDonut=MetaDonut
function MetaDonut:new(x, y, out_r, int_r, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
if int_r >= out_r then error("int_r >= out_r ("..int_r.." > "..out_r); return; end
local radius = out_r--(out_r - int_r)*0.5
local radius2 = int_r--(radius2 + radius)*0.5
return setmetatable({x=x, y=y, radius=radius, radius2=radius2, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaDonut)
end
function MetaDonut:force(x, y)
--Calculate force at point x y
local force = abs(self.radius - sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) ))
if force == 0 then return zero_value end
return (self.radius2 / force)^self.goo
end
return _M

View File

@ -0,0 +1,49 @@
require("locale/rso/rso_config")
function add_peak(ent, peak)
if ent and ent.autoplace then
ent.autoplace.peaks[#ent.autoplace.peaks+1] = peak
end
end
function change_ocataves(autoplace, octaves)
for k,v in pairs(autoplace.peaks) do
if v.noise_layer then
v.noise_octaves_difference = (v.noise_octaves_difference or 0) + octaves
end
end
end
function generate_basic_peaks(noise_layer)
return {
{
influence = 0.1
},
{
influence = 0.67,
noise_layer = noise_layer,
noise_octaves_difference = -2.7,
noise_persistence = 0.3
}
}
end
function resetRichness(ent)
if ent and ent.autoplace then
ent.autoplace.richness_multiplier = 0
ent.autoplace.richness_base = 0
end
end
function removeAutoplace(ent)
if ent then
ent.autoplace = nil
end
end
function removePeaks(ent)
if ent and ent.autoplace then
ent.autoplace.peaks = {}
end
end

View File

@ -1,55 +1,57 @@
debug_enabled = false
region_size = 10 -- alternative mean to control how further away resources would be, default - 256 tiles or 8 chunks
-- each region is region_size*region_size chunks
-- each chunk is 32*32 tiles
use_donut_shapes = false -- setting this to false will remove donuts from possible resource layouts
starting_area_size = 0 -- starting area in regions, safe from random nonsense
absolute_resource_chance = 0.50 -- chance to spawn an resource in a region
starting_richness_mult = 1 -- multiply starting area richness for resources
global_richness_mult = 1 -- multiply richness for all resources except starting area
global_size_mult = 1 -- multiply size for all ores, doesn't affect starting area
absolute_enemy_chance = 3 -- chance to spawn enemies per sector (can be more then one base if spawned)
enemy_base_size_multiplier = 1 -- all base sizes will be multiplied by this - larger number means bigger bases
multi_resource_active = false -- global switch for multi resource chances
multi_resource_richness_factor = 0.60 -- any additional resource is multiplied by this value times resources-1
multi_resource_size_factor = 0.90
multi_resource_chance_diminish = 0.6 -- diminishing effect factor on multi_resource_chance
min_amount=250 -- default value for minimum amount of resource in single pile
richness_distance_factor= 1 -- exponent for richness distance factor calculation
fluid_richness_distance_factor = 0.8 -- exponent for richness distance factor calculation for fluids
size_distance_factor=0.15 -- exponent for size distance factor calculation
deterministic = false -- set to false to use system for all decisions math.random
-- mode is no longer used by generation process - it autodetects endless resources
-- endless_resource_mode = false -- if true, the size of each resource is modified by the following modifier. Use with the endless resources mod.
endless_resource_mode_sizeModifier = 0.80
-- This setting isn't used anywhere in the soft mod version of RSO -- OARC
-- Just set it from Oarc's config.lua (look for ENEMY_EXPANSION)
-- disableEnemyExpansion = false -- allows for disabling of in-game biter base building
use_RSO_biter_spawning = true -- enables spawning of biters controlled by RSO mod - less enemies around with more space between bases
use_vanilla_biter_spawning = false -- enables using of vanilla spawning
biter_ratio_segment=3 --the ratio components determining how many biters to spitters will be spawned
spitter_ratio_segment=1 --eg. 1 and 1 -> equal number of biters and spitters, 10 and 1 -> 10 times as many biters to spitters
useEnemiesInPeaceMod = false -- additional override for peace mod detection - when set to true it will spawn enemies normally, needs to have enemies enabled in peace mod
-- Always leave this setting to true in this soft mod scenario version! -- OARC
ignoreMapGenSettings = true -- stops the default behaviour of reading map gen settings
fluidResourcesFactor = 20 -- temporary factor for calculation of resource %-ages for fluids
--
useResourceCollisionDetection = true -- enables avoidace calculations to reduce ores overlaping of each other
resourceCollisionDetectionRatio = 0.8 -- at least this much of ore field needs to be placable to spawn it
resourceCollisionFieldSkip = true -- determines if ore field should be skipped completely if placement based on ratio failed
debug_enabled = false
region_size = 10 -- alternative mean to control how further away resources would be, default - 256 tiles or 8 chunks
-- each region is region_size*region_size chunks
-- each chunk is 32*32 tiles
use_donut_shapes = false -- setting this to false will remove donuts from possible resource layouts
starting_area_size = 1 -- starting area in regions, safe from random nonsense
absolute_resource_chance = 0.40 -- chance to spawn an resource in a region
starting_richness_mult = 1 -- multiply starting area richness for resources
global_richness_mult = 1 -- multiply richness for all resources except starting area
global_size_mult = 1 -- multiply size for all ores, doesn't affect starting area
absolute_enemy_chance = 3 -- chance to spawn enemies per sector (can be more then one base if spawned)
enemy_base_size_multiplier = 1 -- all base sizes will be multiplied by this - larger number means bigger bases
multi_resource_active = false -- global switch for multi resource chances
multi_resource_richness_factor = 0.60 -- any additional resource is multiplied by this value times resources-1
multi_resource_size_factor = 0.90
multi_resource_chance_diminish = 0.6 -- diminishing effect factor on multi_resource_chance
min_amount=250 -- default value for minimum amount of resource in single pile
richness_distance_factor= 0.8 -- exponent for richness distance factor calculation
fluid_richness_distance_factor = 0.8 -- exponent for richness distance factor calculation for fluids
size_distance_factor=0.3 -- exponent for size distance factor calculation
deterministic = true -- set to false to use system for all decisions math.random
-- mode is no longer used by generation process - it autodetects endless resources
-- endless_resource_mode = false -- if true, the size of each resource is modified by the following modifier. Use with the endless resources mod.
endless_resource_mode_sizeModifier = 0.80
-- This setting isn't used anywhere in the soft mod version of RSO -- OARC
-- Just set it from Oarc's config.lua (look for ENEMY_EXPANSION)
-- disableEnemyExpansion = false -- allows for disabling of in-game biter base building
use_RSO_biter_spawning = true -- enables spawning of biters controlled by RSO mod - less enemies around with more space between bases
use_vanilla_biter_spawning = false -- enables using of vanilla spawning
biter_ratio_segment=3 --the ratio components determining how many biters to spitters will be spawned
spitter_ratio_segment=1 --eg. 1 and 1 -> equal number of biters and spitters, 10 and 1 -> 10 times as many biters to spitters
useEnemiesInPeaceMod = false -- additional override for peace mod detection - when set to true it will spawn enemies normally, needs to have enemies enabled in peace mod
-- Always leave this setting to true in this soft mod scenario version! -- OARC
ignoreMapGenSettings = true -- stops the default behaviour of reading map gen settings
--
useResourceCollisionDetection = true -- enables avoidace calculations to reduce ores overlaping of each other
resourceCollisionDetectionRatio = 0.999 -- threshold to exit placement early
resourceCollisionDetectionRatioFallback = 0.75 -- at least this much of ore field needs to be placable to spawn it
resourceCollisionFieldSkip = true -- determines if ore field should be skipped completely if placement based on ratio failed
remove_trees = false
reveal_spawn_resources = false

File diff suppressed because it is too large Load Diff

View File

@ -1,171 +1,171 @@
local function fillVanillaConfig()
config["iron-ore"] = {
type="resource-ore",
-- general spawn params
allotment=100, -- how common resource is
spawns_per_region={min=1, max=1}, --number of chunks
richness=10000, -- resource_ore has only one richness value - resource-liquid has min/max
size={min=15, max=25}, -- rough radius of area, too high value can produce square shaped areas
min_amount=350,
-- resource provided at starting location
-- probability: 1 = 100% chance to be in starting area
-- 0 = resource is not in starting area
starting={richness=8000, size=25, probability=1},
multi_resource_chance=0.20, -- absolute value
multi_resource={
["iron-ore"] = 2, -- ["resource_name"] = allotment
['copper-ore'] = 4,
["coal"] = 4,
["stone"] = 4,
}
}
config["copper-ore"] = {
type="resource-ore",
allotment=90,
spawns_per_region={min=1, max=1},
richness=10000,
size={min=15, max=25},
min_amount=350,
starting={richness=6000, size=25, probability=1},
multi_resource_chance=0.20,
multi_resource={
["iron-ore"] = 4,
['copper-ore'] = 2,
["coal"] = 4,
["stone"] = 4,
}
}
config["coal"] = {
type="resource-ore",
allotment=80,
spawns_per_region={min=1, max=1},
size={min=15, max=25},
richness=8000,
min_amount=350,
starting={richness=6000, size=20, probability=1},
multi_resource_chance=0.30,
multi_resource={
["crude-oil"] = 1,
["iron-ore"] = 3,
['copper-ore'] = 3,
}
}
config["stone"] = {
type="resource-ore",
allotment=60,
spawns_per_region={min=1, max=1},
richness=6000,
size={min=15, max=20},
min_amount=250,
starting={richness=5000, size=16, probability=1},
multi_resource_chance=0.30,
multi_resource={
["coal"] = 4,
["iron-ore"] = 3,
['copper-ore'] = 3,
}
}
config["uranium-ore"] = {
type="resource-ore",
allotment=50,
spawns_per_region={min=1, max=1},
richness=10000,
size={min=15, max=20},
min_amount=500,
starting={richness=2000, size=10, probability=1},
}
config["crude-oil"] = {
type="resource-liquid",
minimum_amount=10000,
allotment=70,
spawns_per_region={min=1, max=2},
richness={min=100000, max=200000}, -- richness per resource spawn
size={min=3, max=7},
starting={richness=200000, size=2, probability=1},
multi_resource_chance=0.20,
multi_resource={
["coal"] = 4,
}
}
end
local function fillEnemies()
config["enemy-base"] = {
type="entity",
force="enemy",
clear_range = {6, 6},
spawns_per_region={min=2,max=4},
size={min=2,max=4},
size_per_region_factor=1,
richness=3,
absolute_probability=absolute_enemy_chance, -- chance to spawn in region
probability_distance_factor=1.1, -- relative increase per region
max_probability_distance_factor=3, -- absolute value
along_resource_probability=0.20, -- chance to spawn in resource chunk anyway, absolute value. Can happen once per resource.
sub_spawn_probability=0.1, -- chance for this entity to spawn anything from sub_spawns table, absolute value
sub_spawn_size={min=1, max=2}, -- in same chunk
sub_spawn_distance_factor=1.01,
sub_spawn_max_distance_factor=1.5,
sub_spawns={
["small-worm-turret"]={
min_distance=0,
allotment=200,
allotment_distance_factor=0.99,
clear_range = {2, 2},
},
["medium-worm-turret"]={
min_distance=10,
allotment=100,
allotment_distance_factor=1.01,
clear_range = {2, 2},
},
["big-worm-turret"]={
min_distance=20,
allotment=100,
allotment_distance_factor=1.015,
clear_range = {2, 2},
}
}
}
end
function loadResourceConfig()
config={}
fillVanillaConfig()
fillEnemies()
return config
local function fillVanillaConfig()
config["iron-ore"] = {
type="resource-ore",
-- general spawn params
allotment=90, -- how common resource is
spawns_per_region={min=1, max=1}, --number of chunks
richness=20000, -- resource_ore has only one richness value - resource-liquid has min/max
size={min=15, max=25}, -- rough radius of area, too high value can produce square shaped areas
min_amount=350,
-- resource provided at starting location
-- probability: 1 = 100% chance to be in starting area
-- 0 = resource is not in starting area
starting={richness=8000, size=25, probability=1},
multi_resource_chance=0.20, -- absolute value
multi_resource={
["iron-ore"] = 2, -- ["resource_name"] = allotment
['copper-ore'] = 4,
["coal"] = 4,
["stone"] = 4,
}
}
config["copper-ore"] = {
type="resource-ore",
allotment=80,
spawns_per_region={min=1, max=1},
richness=20000,
size={min=15, max=25},
min_amount=350,
starting={richness=6000, size=25, probability=1},
multi_resource_chance=0.20,
multi_resource={
["iron-ore"] = 4,
['copper-ore'] = 2,
["coal"] = 4,
["stone"] = 4,
}
}
config["coal"] = {
type="resource-ore",
allotment=80,
spawns_per_region={min=1, max=1},
size={min=15, max=25},
richness=16000,
min_amount=350,
starting={richness=6000, size=20, probability=1},
multi_resource_chance=0.30,
multi_resource={
["crude-oil"] = 1,
["iron-ore"] = 3,
['copper-ore'] = 3,
}
}
config["stone"] = {
type="resource-ore",
allotment=60,
spawns_per_region={min=1, max=1},
richness=12000,
size={min=15, max=20},
min_amount=250,
starting={richness=5000, size=16, probability=1},
multi_resource_chance=0.30,
multi_resource={
["coal"] = 4,
["iron-ore"] = 3,
['copper-ore'] = 3,
}
}
config["uranium-ore"] = {
type="resource-ore",
allotment=50,
spawns_per_region={min=1, max=1},
richness=10000,
size={min=15, max=20},
min_amount=500,
starting={richness=2000, size=10, probability=1},
}
config["crude-oil"] = {
type="resource-liquid",
minimum_amount=10000,
allotment=70,
spawns_per_region={min=1, max=1},
richness={min=400000, max=1000000}, -- richness per resource spawn
size={min=3, max=7},
starting={richness=400000, size=2, probability=1},
multi_resource_chance=0.20,
multi_resource={
["coal"] = 4,
}
}
end
local function fillEnemies()
config["enemy-base"] = {
type="entity",
force="enemy",
clear_range = {6, 6},
spawns_per_region={min=2,max=4},
size={min=2,max=4},
size_per_region_factor=0.3,
richness=3,
absolute_probability=absolute_enemy_chance, -- chance to spawn in region
probability_distance_factor=1.1, -- relative increase per region
max_probability_distance_factor=3, -- absolute value
along_resource_probability=0.20, -- chance to spawn in resource chunk anyway, absolute value. Can happen once per resource.
sub_spawn_probability=0.1, -- chance for this entity to spawn anything from sub_spawns table, absolute value
sub_spawn_size={min=1, max=2}, -- in same chunk
sub_spawn_distance_factor=1.01,
sub_spawn_max_distance_factor=1.5,
sub_spawns={
["small-worm-turret"]={
min_distance=0,
allotment=200,
allotment_distance_factor=0.99,
clear_range = {2, 2},
},
["medium-worm-turret"]={
min_distance=10,
allotment=100,
allotment_distance_factor=1.01,
clear_range = {2, 2},
},
["big-worm-turret"]={
min_distance=20,
allotment=100,
allotment_distance_factor=1.015,
clear_range = {2, 2},
}
}
}
end
function loadResourceConfig()
config={}
fillVanillaConfig()
fillEnemies()
return config
end

View File

@ -1,5 +1,6 @@
-- control.lua
-- tag.lua
-- Apr 2017
-- Allows adding play tags
function CreateTagGui(event)
local player = game.players[event.player_index]

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)

49
locale/temp/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

@ -3,7 +3,8 @@
--
-- 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.
-- 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.
@ -48,7 +49,7 @@ function OarcRegrowthInit()
global.chunk_regrow.min_y = 0
global.chunk_regrow.max_y = 0
global.chunk_regrow.y_index = 0
global.chunk_regrow.force_removal_flag = 0
global.chunk_regrow.force_removal_flag = -1000
OarcRegrowthOffLimits({x=0,y=0}, 10)
end
@ -320,7 +321,7 @@ function OarcRegrowthOnTick()
-- 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...")
SendBroadcastMsg("Map cleanup in 10 seconds, if you don't want to lose what you found drop a powered radar on it!")
end
end
@ -328,7 +329,7 @@ function OarcRegrowthOnTick()
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...")
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
end
end
end
@ -339,10 +340,10 @@ end
function OarcRegrowthForceRemovalOnTick()
-- Catch force remove flag
if (game.tick == global.chunk_regrow.force_removal_flag+60) then
SendBroadcastMsg("Map cleanup in 10 seconds...")
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...")
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
end
end

View File

@ -36,7 +36,7 @@ function SeparateSpawnsGenerateChunk(event)
-- 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.
CreateSpawnAreas(surface, chunkArea, global.uniqueSpawns)
SetupAndClearSpawnAreas(surface, chunkArea, global.uniqueSpawns)
end
@ -53,6 +53,16 @@ function FindUnusedSpawns(event)
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
@ -68,9 +78,21 @@ function FindUnusedSpawns(event)
-- If a uniqueSpawn was created for the player, mark it as unused.
if (global.uniqueSpawns[player.name] ~= nil) then
if ENABLE_ABANDONED_BASE_REMOVAL then
local spawnPos = global.uniqueSpawns[player.name].pos
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
@ -166,8 +188,11 @@ function GetNumberOfAvailableSharedSpawns()
local count = 0
for ownerName,sharedSpawn in pairs(global.sharedSpawns) do
if (sharedSpawn.openAccess) then
if (GetOnlinePlayersAtSharedSpawn(ownerName) < MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN) then
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
@ -197,12 +222,28 @@ function InitSpawnGlobalsAndForces()
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()
-- AntiGriefing(game.forces[MAIN_FORCE])
if (ENABLE_ANTI_GRIEFING) then
AntiGriefing(game.forces[MAIN_FORCE])
end
end
@ -220,19 +261,72 @@ function ChangePlayerSpawn(player, pos)
global.playerCooldowns[player.name] = {setRespawn=game.tick}
end
function SendPlayerToNewSpawnAndCreateIt(player, spawn, moatEnabled)
-- Send the player to that position
player.teleport(spawn, GAME_SURFACE_NAME)
GivePlayerStarterItems(player)
ChartArea(player.force, player.position, 4, player.surface)
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[player.name] = {pos=spawn,moat=moatEnabled}
ClearNearbyEnemies(player, SAFE_AREA_TILE_DIST)
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("Failed to create spawn point for: " .. player.name)
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(surface, 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
@ -275,9 +369,19 @@ function CreatePlayerCustomForce(player)
-- 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()
SetFriendlyBetweenAllForces()
if (ENABLE_ANTI_GRIEFING) then
AntiGriefing(newForce)
end
SendBroadcastMsg(player.name.." has started their own team!")
else
player.force = MAIN_FORCE
@ -286,34 +390,3 @@ function CreatePlayerCustomForce(player)
return newForce
end
-- For each force, if it's a valid force, chart the chunk that all active players
-- are in.
-- I have no idea how compute intensive this function is. If it starts to lag the game
-- we'll have to figure out how to change it.
function ShareVisionBetweenPlayers()
if ((game.tick % (TICKS_PER_SECOND*5)) == 0) then
for _,force in pairs(game.forces) do
if (force ~= nil) then
if ((force.name ~= enemy) and
(force.name ~= neutral) and
(force.name ~= player)) then
for _,player in pairs(game.connected_players) do
force.chart(GAME_SURFACE_NAME,
{{player.position.x-CHUNK_SIZE,
player.position.y-CHUNK_SIZE},
{player.position.x+CHUNK_SIZE,
player.position.y+CHUNK_SIZE}})
end
end
end
end
global.tick_counter = 0
else
global.tick_counter = global.tick_counter + 1
end
end

File diff suppressed because it is too large Load Diff