From 177cf9bf7e99efe9ad11ba0f968fd476e5cb8619 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Wed, 29 Nov 2017 14:39:09 -0500 Subject: [PATCH 01/58] Adjusting alien params, adding shared radar, buffing shared vision, setting map gen settings for non RSO. --- config.lua | 16 +++++++++------- control.lua | 22 +++++++++++++++------- locale/oarc_utils.lua | 28 ++++++++++++++++++++++++++++ separate_spawns.lua | 39 ++++++++++++++++++++++++++++++--------- 4 files changed, 82 insertions(+), 23 deletions(-) diff --git a/config.lua b/config.lua index 74040c8..23954a2 100644 --- a/config.lua +++ b/config.lua @@ -48,7 +48,7 @@ WELCOME_MSG_TITLE_OARC = "Welcome to Oarc's Server!" -------------------------------------------------------------------------------- -- Frontier style rocket silo mode -FRONTIER_ROCKET_SILO_MODE = true +FRONTIER_ROCKET_SILO_MODE = false -- Separate spawns -- This is the core of the mod. Probably not a good idea to disable it. @@ -56,20 +56,20 @@ ENABLE_SEPARATE_SPAWNS = true -- Enable Scenario version of RSO -- You can reconfigure the RSO resource settings in the RSO files if you want to -ENABLE_RSO = true +ENABLE_RSO = false -- Enable Undecorator -- Removes decorative items to reduce save file size. ENABLE_UNDECORATOR = true -- Enable Tags -ENABLE_TAGS = true +ENABLE_TAGS = false -- Enable Long Reach -ENABLE_LONGREACH = true +ENABLE_LONGREACH = false -- Enable Autofill -ENABLE_AUTOFILL = true +ENABLE_AUTOFILL = false -- Enable Playerlist ENABLE_PLAYER_LIST = true @@ -87,6 +87,7 @@ ENABLE_POWER_ARMOR_QUICK_START = false -- Enable shared vision between teams (all teams are still COOP) ENABLE_SHARED_TEAM_VISION = true +ENABLE_SHARED_TEAM_RADAR = true -- Enable map regrowth, see regrowth_map.lua for more info. ENABLE_REGROWTH = false @@ -224,7 +225,7 @@ SAFE_AREA_TILE_DIST = CHUNK_SIZE*12 -- Warning area has reduced aliens -- +/- this in x and y direction -WARNING_AREA_TILE_DIST = CHUNK_SIZE*20 +WARNING_AREA_TILE_DIST = CHUNK_SIZE*25 -- 1 : X (spawners alive : spawners destroyed) in this area WARN_AREA_REDUCTION_RATIO = 15 @@ -271,13 +272,14 @@ MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES -------------------------------------------------------------------------------- -- Enable/Disable enemy expansion (Applies to RSO as well!) -ENEMY_EXPANSION = false +ENEMY_EXPANSION = true -- Divide the alien factors by this number to reduce it (or multiply if < 1) ENEMY_POLLUTION_FACTOR_DIVISOR = 10 ENEMY_DESTROY_FACTOR_DIVISOR = 10 + -------------------------------------------------------------------------------- -- Frontier Rocket Silo Options -------------------------------------------------------------------------------- diff --git a/control.lua b/control.lua index 7aaa742..e64436d 100644 --- a/control.lua +++ b/control.lua @@ -86,6 +86,10 @@ 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! @@ -115,10 +119,6 @@ script.on_init(function(event) ChartRocketSiloArea(game.forces[MAIN_FORCE], 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 @@ -294,15 +294,23 @@ script.on_event(defines.events.on_tick, function(event) end) + +script.on_event(defines.events.on_sector_scanned, function (event) + if ENABLE_REGROWTH then + OarcRegrowthSectorScan(event) + end + + if ENABLE_SHARED_TEAM_RADAR then + ShareRadarBetweenForces(event) + end +end) + ---------------------------------------- -- Refreshes regrowth timers around an active timer -- Refresh areas where stuff is built, and mark any chunks with player -- 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) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 9d5f606..dbe31a9 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -487,7 +487,20 @@ 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 + game.map_settings.enemy_expansion.enabled = ENEMY_EXPANSION + + game.map_settings.enemy_expansion.min_base_spacing = 10 + game.map_settings.enemy_expansion.max_expansion_distance = 10 + + game.map_settings.enemy_expansion.settler_group_min_size = 5 + game.map_settings.enemy_expansion.settler_group_max_size = 20 + + -- game.map_settings.enemy_expansion.friendly_base_influence_radius = 4 + -- game.map_settings.enemy_expansion.enemy_building_influence_radius = 4 + + game.map_settings.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*30 + game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*120 end -- Add Long Reach to Character @@ -1007,6 +1020,21 @@ function CreateGameSurface(mode) ["crude-oil"]={ size="none" }, ["enemy-base"]={ size="none" } } + else + mapSettings.terrain_segmentation="normal" + mapSettings.water="normal" + mapSettings.starting_area="normal" + mapSettings.peaceful_mode=false + mapSettings.seed=math.random(999999999); + mapSettings.autoplace_controls = { + ["coal"]={frequency="very-low", size= "normal", richness= "very-high"}, + ["copper-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["crude-oil"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["enemy-base"]={frequency= "very-low", size= "very-low", richness= "very-low"}, + ["iron-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["stone"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["uranium-ore"]={frequency= "very-low", size= "normal", richness= "very-high"} + } end local surface = game.create_surface(GAME_SURFACE_NAME,mapSettings) diff --git a/separate_spawns.lua b/separate_spawns.lua index 4e18f5b..0833d54 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -293,7 +293,7 @@ end -- we'll have to figure out how to change it. function ShareVisionBetweenPlayers() - if ((game.tick % (TICKS_PER_SECOND*5)) == 0) then + if ((game.tick % 10) == 0) then for _,force in pairs(game.forces) do if (force ~= nil) then @@ -303,17 +303,38 @@ function ShareVisionBetweenPlayers() 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}}) + {{player.position.x-(2*CHUNK_SIZE), + player.position.y-(2*CHUNK_SIZE)}, + {player.position.x+(2*CHUNK_SIZE), + player.position.y+(2*CHUNK_SIZE)}}) end end end end - - global.tick_counter = 0 - else - global.tick_counter = global.tick_counter + 1 end end + + +-- For each force, if it's a valid force, chart the chunk that was just scanned +-- for all forces. +-- I have no idea how compute intensive this function is. If it starts to lag the game +-- we'll have to figure out how to change it. +function ShareRadarBetweenForces(event) + + for _,force in pairs(game.forces) do + if (force ~= nil) then + if ((force.name ~= enemy) and + (force.name ~= neutral) and + (force.name ~= player)) then + + for _,player in pairs(game.connected_players) do + force.chart(GAME_SURFACE_NAME, + {{event.position.x, + event.position.y}, + {event.position.x, + event.position.y}}) + end + end + end + end +end \ No newline at end of file From 44bca5e81f829018c1649048140fa6666b74c1f7 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Wed, 29 Nov 2017 14:44:29 -0500 Subject: [PATCH 02/58] fix radar position bug --- separate_spawns.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index 0833d54..2cb59cf 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -329,10 +329,11 @@ function ShareRadarBetweenForces(event) for _,player in pairs(game.connected_players) do force.chart(GAME_SURFACE_NAME, - {{event.position.x, - event.position.y}, - {event.position.x, - event.position.y}}) + {{event.chunk_position.x, + event.chunk_position.y}, + {event.chunk_position.x, + event.chunk_position.y}}) + DebugPrint("X="..event.chunk_position.x..",Y="..event.chunk_position.y) end end end From db26029af7643b98f0894d721ea634f7287e91e1 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Wed, 29 Nov 2017 15:56:03 -0500 Subject: [PATCH 03/58] bumping oil and uranium to low instead of very-low --- locale/oarc_utils.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index dbe31a9..17e26dc 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -1029,11 +1029,11 @@ function CreateGameSurface(mode) mapSettings.autoplace_controls = { ["coal"]={frequency="very-low", size= "normal", richness= "very-high"}, ["copper-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, - ["crude-oil"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["crude-oil"]={frequency= "low", size= "normal", richness= "very-high"}, ["enemy-base"]={frequency= "very-low", size= "very-low", richness= "very-low"}, ["iron-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, ["stone"]={frequency= "very-low", size= "normal", richness= "very-high"}, - ["uranium-ore"]={frequency= "very-low", size= "normal", richness= "very-high"} + ["uranium-ore"]={frequency= "low", size= "normal", richness= "very-high"} } end From 6d4a1378f5231d4d55c71f060813e1c39ff4544b Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Wed, 29 Nov 2017 16:41:28 -0500 Subject: [PATCH 04/58] fixing radar shared distance calc --- separate_spawns.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index 2cb59cf..4a0c401 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -329,11 +329,10 @@ function ShareRadarBetweenForces(event) for _,player in pairs(game.connected_players) do force.chart(GAME_SURFACE_NAME, - {{event.chunk_position.x, - event.chunk_position.y}, - {event.chunk_position.x, - event.chunk_position.y}}) - DebugPrint("X="..event.chunk_position.x..",Y="..event.chunk_position.y) + {{event.chunk_position.x*CHUNK_SIZE, + event.chunk_position.y*CHUNK_SIZE}, + {event.chunk_position.x*CHUNK_SIZE, + event.chunk_position.y*CHUNK_SIZE}}) end end end From e0a4903885f42449bed9132a6e285ccbc11ed0f7 Mon Sep 17 00:00:00 2001 From: oarcinae Date: Wed, 29 Nov 2017 19:14:31 -0500 Subject: [PATCH 05/58] Re-enablig long reach --- config.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.lua b/config.lua index 23954a2..35ed16d 100644 --- a/config.lua +++ b/config.lua @@ -66,7 +66,7 @@ ENABLE_UNDECORATOR = true ENABLE_TAGS = false -- Enable Long Reach -ENABLE_LONGREACH = false +ENABLE_LONGREACH = true -- Enable Autofill ENABLE_AUTOFILL = false @@ -263,7 +263,7 @@ RESPAWN_COOLDOWN_TICKS = TICKS_PER_MINUTE * RESPAWN_COOLDOWN_IN_MINUTES -- Require playes to be online for at least 5 minutes -- Else their character is removed and their spawn point is freed up for use -MIN_ONLINE_TIME_IN_MINUTES = 15 +MIN_ONLINE_TIME_IN_MINUTES = 10 MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES @@ -298,7 +298,7 @@ ENABLE_RANDOM_SILO_POSITION = true -- Long Reach Options -------------------------------------------------------------------------------- -BUILD_DIST_BONUS = 20 +BUILD_DIST_BONUS = 100 REACH_DIST_BONUS = BUILD_DIST_BONUS RESOURCE_DIST_BONUS = 2 From fcf17831b14b56fbd05ceb396fc14ae3bd3013f9 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 15 Dec 2017 14:45:01 -0500 Subject: [PATCH 06/58] First mostly working version for 0.16. --- config.lua | 87 +- control.lua | 49 +- locale/frontier_silo.lua | 10 +- locale/oarc_utils.lua | 167 ++-- locale/rso/drand.lua | 269 ------ locale/rso/metaball.lua | 104 -- locale/rso/rso_config.lua | 55 -- locale/rso/rso_control.lua | 1406 ---------------------------- locale/rso/rso_resource_config.lua | 171 ---- separate_spawns.lua | 1 + separate_spawns_guis.lua | 122 ++- 11 files changed, 208 insertions(+), 2233 deletions(-) delete mode 100644 locale/rso/drand.lua delete mode 100644 locale/rso/metaball.lua delete mode 100644 locale/rso/rso_config.lua delete mode 100644 locale/rso/rso_control.lua delete mode 100644 locale/rso/rso_resource_config.lua diff --git a/config.lua b/config.lua index 35ed16d..b7606d7 100644 --- a/config.lua +++ b/config.lua @@ -17,8 +17,8 @@ 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." -OTHER_MSG1 = "Latest updates in this scenario version (0.5.5):" -OTHER_MSG2 = "Regrowth fixes (disabled). Abandoned base removal." +OTHER_MSG1 = "Latest updates in this scenario version:" +OTHER_MSG2 = "0.16 experimental release." -- 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." @@ -36,40 +36,38 @@ 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. +SERVER_OWNER_IS_OARC = false -- 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!" -------------------------------------------------------------------------------- -- 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 = false - -- 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 -ENABLE_RSO = false +-- RSO OPTION HAS BEEN REMOVED FOR NOW. USE THE 0.16 MOD. + +-- Frontier style rocket silo mode +FRONTIER_ROCKET_SILO_MODE = false -- Enable Undecorator -- Removes decorative items to reduce save file size. -ENABLE_UNDECORATOR = true +ENABLE_UNDECORATOR = false -- Enable Tags -ENABLE_TAGS = false +ENABLE_TAGS = true -- Enable Long Reach ENABLE_LONGREACH = true -- Enable Autofill -ENABLE_AUTOFILL = false +ENABLE_AUTOFILL = true -- Enable Playerlist ENABLE_PLAYER_LIST = true @@ -87,7 +85,7 @@ ENABLE_POWER_ARMOR_QUICK_START = false -- Enable shared vision between teams (all teams are still COOP) ENABLE_SHARED_TEAM_VISION = true -ENABLE_SHARED_TEAM_RADAR = true +ENABLE_SHARED_TEAM_RADAR = true -- This shares charted chunks. Not active vision. -- Enable map regrowth, see regrowth_map.lua for more info. ENABLE_REGROWTH = false @@ -152,6 +150,11 @@ FAR_MAX_DIST = 300 --125 -- 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 @@ -221,7 +224,7 @@ 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*10 -- Warning area has reduced aliens -- +/- this in x and y direction @@ -271,14 +274,14 @@ MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES -- Alien Options -------------------------------------------------------------------------------- --- Enable/Disable enemy expansion (Applies to RSO as well!) +-- Enable/Disable enemy expansion ENEMY_EXPANSION = true --- Divide the alien factors by this number to reduce it (or multiply if < 1) -ENEMY_POLLUTION_FACTOR_DIVISOR = 10 -ENEMY_DESTROY_FACTOR_DIVISOR = 10 - - +-- 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 = 1 +ENEMY_POLLUTION_FACTOR_DIVISOR = 1 +ENEMY_DESTROY_FACTOR_DIVISOR = 1 -------------------------------------------------------------------------------- -- Frontier Rocket Silo Options @@ -309,19 +312,43 @@ RESOURCE_DIST_BONUS = 2 AUTOFILL_TURRET_AMMO_QUANTITY = 10 -------------------------------------------------------------------------------- --- Use rso_config and rso_resource_config for RSO config settings +-- MAP CONFIGURATION OPTIONS +-- Configure these if you are running headless since there is no way to set +-- resources otherwise. -------------------------------------------------------------------------------- --- Don't touch unless you know what you're doing... --- When using RSO, all resources MUST BE SET TO SIZE=NONE! --------------------------------------------------------------------------------- -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. + +-- 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="normal" +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 = { + ["coal"]={frequency="very-low", size= "normal", richness= "very-high"}, + ["copper-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["crude-oil"]={frequency= "low", size= "normal", richness= "very-high"}, + ["enemy-base"]={frequency= "low", size= "normal", richness= "normal"}, + ["iron-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["stone"]={frequency= "very-low", size= "normal", richness= "very-high"}, + ["uranium-ore"]={frequency= "low", size= "normal", richness= "very-high"}, + ["desert"]={frequency= "normal", size= "normal", richness= "normal"}, + ["dirt"]={frequency= "normal", size= "normal", richness= "normal"}, + ["grass"]={frequency= "normal", size= "normal", richness= "normal"}, + ["sand"]={frequency= "normal", size= "normal", richness= "normal"}, + ["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=100, cliff_elevation_interval=100, name="cliff"} ------------------------------------------------------------------------------- -- DEBUG -------------------------------------------------------------------------------- -- DEBUG prints for me -global.oarcDebugEnabled = false +global.oarcDebugEnabled = true diff --git a/control.lua b/control.lua index e64436d..2e4f546 100644 --- a/control.lua +++ b/control.lua @@ -24,7 +24,6 @@ -- Generic Utility Includes require("locale/oarc_utils") -require("locale/rso/rso_control") require("locale/frontier_silo") require("locale/tag") @@ -93,17 +92,7 @@ script.on_init(function(event) -- 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 - CreateGameSurface(VANILLA_MODE) - end + CreateGameSurface() if ENABLE_SEPARATE_SPAWNS then InitSpawnGlobalsAndForces() @@ -125,16 +114,6 @@ script.on_init(function(event) 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) @@ -161,20 +140,17 @@ script.on_event(defines.events.on_chunk_generated, function(event) UndecorateOnChunkGenerate(event) end - if ENABLE_RSO then - RSO_ChunkGenerated(event) - end - if FRONTIER_ROCKET_SILO_MODE then 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) @@ -199,6 +175,13 @@ script.on_event(defines.events.on_gui_click, function(event) end) +script.on_event(defines.events.on_gui_checked_state_changed, function (event) + if ENABLE_SEPARATE_SPAWNS then + SpawnOptsGuiOptionsSelect(event) + SpawnCtrlGuiOptionsSelect(event) + end +end) + ---------------------------------------- -- Player Events @@ -207,13 +190,13 @@ script.on_event(defines.events.on_player_joined_game, function(event) PlayerJoinedMessages(event) - if ENABLE_TAGS then - CreateTagGui(event) - end - if ENABLE_PLAYER_LIST then CreatePlayerListGui(event) end + + if ENABLE_TAGS then + CreateTagGui(event) + end end) script.on_event(defines.events.on_player_created, function(event) diff --git a/locale/frontier_silo.lua b/locale/frontier_silo.lua index e214cac..1336edf 100644 --- a/locale/frontier_silo.lua +++ b/locale/frontier_silo.lua @@ -18,7 +18,7 @@ local function CreateRocketSilo(surface, chunkArea, force) 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}} + tiles[i] = {name = "grass-1", position = {global.siloPosition.x+dx, global.siloPosition.y+dy}} i=i+1 end end @@ -68,9 +68,15 @@ function GenerateRocketSiloChunk(event) end end + -- Remove trees/resources inside the spawn area + RemoveInCircle(surface, chunkArea, "tree", global.siloPosition, ENFORCE_LAND_AREA_TILE_DIST+5) + RemoveInCircle(surface, chunkArea, "resource", global.siloPosition, ENFORCE_LAND_AREA_TILE_DIST+5) + RemoveInCircle(surface, chunkArea, "cliff", global.siloPosition, ENFORCE_LAND_AREA_TILE_DIST+5) + RemoveDecorationsArea(surface, chunkArea) + -- Create rocket silo CreateRocketSilo(surface, chunkArea, MAIN_FORCE) - CreateCropCircle(surface, global.siloPosition, chunkArea, 40) + CreateCropOctagon(surface, global.siloPosition, chunkArea, 40) end diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 17e26dc..b7e142a 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -441,7 +441,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 +451,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,23 +488,32 @@ end -- Adjust alien params function ConfigureAlienStartingParams() - game.map_settings.enemy_evolution.time_factor=0 + + -- 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 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 game.map_settings.enemy_expansion.enabled = ENEMY_EXPANSION - game.map_settings.enemy_expansion.min_base_spacing = 10 - game.map_settings.enemy_expansion.max_expansion_distance = 10 + -- game.map_settings.enemy_expansion.min_base_spacing = 10 + -- game.map_settings.enemy_expansion.max_expansion_distance = 10 - game.map_settings.enemy_expansion.settler_group_min_size = 5 - game.map_settings.enemy_expansion.settler_group_max_size = 20 + -- game.map_settings.enemy_expansion.settler_group_min_size = 5 + -- game.map_settings.enemy_expansion.settler_group_max_size = 20 -- game.map_settings.enemy_expansion.friendly_base_influence_radius = 4 -- game.map_settings.enemy_expansion.enemy_building_influence_radius = 4 - game.map_settings.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*30 - game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*120 + -- game.map_settings.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*30 + -- game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*120 end -- Add Long Reach to Character @@ -532,7 +545,7 @@ local function ExpandPlayerListGui(player) name="playerList-panel", direction = "vertical"} ApplyStyle(scrollFrame, my_player_list_fixed_width_style) - scrollFrame.horizontal_scroll_policy = "never" + scrollFrame.can_scroll_horizontally = false 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"} @@ -726,7 +739,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 @@ -760,7 +773,7 @@ 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 @@ -791,7 +804,7 @@ function CreateCropOctagon(surface, centerPos, chunkArea, tileRadius) -- 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 @@ -828,7 +841,7 @@ function CreateMoat(surface, centerPos, chunkArea, tileRadius) -- a clean transition if ((distVar < tileRadSqr-500) and (distVar > tileRadSqr-1000)) then - table.insert(waterTiles, {name = "grass", position ={i,j}}) + table.insert(waterTiles, {name = "grass-1", position ={i,j}}) end end end @@ -941,6 +954,8 @@ function CreateSpawnAreas(surface, chunkArea, spawnPointTable) -- Remove trees/resources inside the spawn area RemoveInCircle(surface, chunkArea, "tree", spawn.pos, ENFORCE_LAND_AREA_TILE_DIST+5) 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) @@ -970,73 +985,20 @@ 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) +function CreateGameSurface() local mapSettings = game.surfaces["nauvis"].map_gen_settings - 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" } - } - else - mapSettings.terrain_segmentation="normal" - mapSettings.water="normal" - mapSettings.starting_area="normal" - mapSettings.peaceful_mode=false - mapSettings.seed=math.random(999999999); - mapSettings.autoplace_controls = { - ["coal"]={frequency="very-low", size= "normal", richness= "very-high"}, - ["copper-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, - ["crude-oil"]={frequency= "low", size= "normal", richness= "very-high"}, - ["enemy-base"]={frequency= "very-low", size= "very-low", richness= "very-low"}, - ["iron-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, - ["stone"]={frequency= "very-low", size= "normal", richness= "very-high"}, - ["uranium-ore"]={frequency= "low", size= "normal", richness= "very-high"} - } + + 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 + local surface = game.create_surface(GAME_SURFACE_NAME,mapSettings) surface.set_tiles({{name = "out-of-map",position = {1,1}}}) end @@ -1053,7 +1015,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 @@ -1061,6 +1023,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 = {} @@ -1068,26 +1031,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) @@ -1095,10 +1066,6 @@ function CreateHoldingPen(surface, chunkArea) end end -function CreateHoldingPenGenerateChunk(event) - CreateHoldingPen(event.surface, event.area) -end - -------------------------------------------------------------------------------- -- EVENT SPECIFIC FUNCTIONS -------------------------------------------------------------------------------- diff --git a/locale/rso/drand.lua b/locale/rso/drand.lua deleted file mode 100644 index 60db0ad..0000000 --- a/locale/rso/drand.lua +++ /dev/null @@ -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 \ No newline at end of file diff --git a/locale/rso/metaball.lua b/locale/rso/metaball.lua deleted file mode 100644 index 09b207c..0000000 --- a/locale/rso/metaball.lua +++ /dev/null @@ -1,104 +0,0 @@ ---[[-- -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 \ No newline at end of file diff --git a/locale/rso/rso_config.lua b/locale/rso/rso_config.lua deleted file mode 100644 index b61e4b0..0000000 --- a/locale/rso/rso_config.lua +++ /dev/null @@ -1,55 +0,0 @@ -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 diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua deleted file mode 100644 index 4daa04a..0000000 --- a/locale/rso/rso_control.lua +++ /dev/null @@ -1,1406 +0,0 @@ -require("locale/rso/rso_config") -require("util") -require("locale/rso/rso_resource_config") -require("locale/oarc_utils") -require("config") - -local MB=require("locale/rso/metaball") -local drand = require("locale/rso/drand") -local rng = drand.mwvc -if not deterministic then rng = drand.sys_rand end - --- math shortcuts -local floor = math.floor -local abs = math.abs -local cos = math.cos -local sin = math.sin -local pi = math.pi -local max = math.max - -local function round(value) - return math.floor(value + 0.5) -end - -local function debug(str) - if debug_enabled then - game.players[1].print(str) - end -end - --- constants -local CHUNK_SIZE = 32 -local REGION_TILE_SIZE = CHUNK_SIZE*region_size -local MIN_BALL_DISTANCE = CHUNK_SIZE/6 -local P_BALL_SIZE_FACTOR = 0.7 -local N_BALL_SIZE_FACTOR = 0.95 -local NEGATIVE_MODIFICATOR = 123456 - -local meta_shapes = nil - -if use_donut_shapes then - meta_shapes = {MB.MetaEllipse, MB.MetaSquare, MB.MetaDonut} -else - meta_shapes = {MB.MetaEllipse, MB.MetaSquare} -end - --- local globals -local index_is_built = false -local max_allotment = 0 -local rgen = nil -local distance = util.distance -local spawner_probability_edge = 0 -- below this value a biter spawner, above/equal this value a spitter spawner -local invalidResources = {} -local config = nil -local configIndexed = nil - --- map gen settings mapping - -local startingAreaMultiplier = -{ - none = 0, - ["very-low"] = 0.25, - low = 0.5, - normal = 1, - high = 1.5, - ["very-high"] = 2, -} - -local frequencyAllotmentMultiplier = -{ - ["very-low"] = 0.5, - low = 0.75, - normal = 1, - high = 1.5, - ["very-high"] = 2, -} - -local sizeMultiplier = -{ - none = 0, - ["very-low"] = 0.5, - low = 0.75, - normal = 1, - high = 1.25, - ["very-high"] = 1.5, -} - -local richnessMultiplier = -{ - ["very-low"] = 0.125, - low = 0.25, - normal = 1, - high = 2, - ["very-high"] = 4, -} - -local entityFrequencyMultiplier = -{ - ["very-low"] = 0.25, - low = 0.5, - normal = 1, - high = 2, - ["very-high"] = 4, -} - -local entitySizeMultiplier = -{ - none = 0, - ["very-low"] = 0.5, - low = 0.75, - normal = 1, - high = 2, - ["very-high"] = 4, -} - ---[[ HELPER METHODS ]]-- - -local function normalize(n) --keep numbers at (positive) 32 bits - return floor(n) % 0x80000000 -end - -local function bearing(origin, dest) - -- finds relative angle - local xd = dest.x - origin.x - local yd = dest.y - origin.y - return math.atan2(xd, yd); -end - -local function str2num(s) - local num = 0 - for i=1,s:len() do - num=num + (s:byte(i) - 33)*i - end - return num -end - -local function mult_for_pos(pos) - local num = 0 - local x = pos.x - local y = pos.y - - if x == 0 then x = 0.5 end - if y == 0 then y = 0.5 end - if x < 0 then - x = abs(x) + NEGATIVE_MODIFICATOR - end - if y < 0 then - y = abs(y) + NEGATIVE_MODIFICATOR - end - - return drand.lcg(y, 'mvc'):random(0)*drand.lcg(x, 'nr'):random(0) -end - -local function rng_for_reg_pos(pos) - local rgen = rng(normalize(global.seed*mult_for_pos(pos))) - rgen:random() - rgen:random() - rgen:random() - return rgen -end - -local function rng_restricted_angle(restrictions) - local rng = rgen:random() - local x_scale, y_scale - local deformX = rgen:random() * 2 - 1 - local deformY = rgen:random() * 2 - 1 - - if restrictions=='xy' then - y_scale=1.0 + deformY*0.5 - x_scale=1.0 + deformX*0.5 - angle = rng*pi*2 - elseif restrictions=='x' then - y_scale=1.0 + deformY*0.6 - x_scale=1.0 + deformX*0.6 - angle = rng*pi/2 - pi/4 - elseif restrictions=='y' then - y_scale=1.0 + deformY*0.6 - x_scale=1.0 + deformX*0.6 - angle = rng*pi/2 + pi/2 - else - y_scale=1.0 + deformY*0.3 - x_scale=1.0 + deformX*0.3 - angle = rng*pi*2 - end - - return angle, x_scale, y_scale -end - -local function vary_by_percentage(x, p) - return x + (0.5 - rgen:random())*2*x*p -end - - -local function remove_trees(surface, x, y, x_size, y_size ) - local bb={{x - x_size, y - y_size}, {x + x_size, y + y_size}} - for _, entity in pairs(surface.find_entities_filtered{area = bb, type="tree"}) do - if entity.valid then - entity.destroy() - end - end -end - -local function removeDecorations(surface, x, y, width, height ) - local bb={{x, y}, {x + width, y + height}} - for _, entity in pairs(surface.find_entities_filtered{area = bb, type="decorative"}) do - if entity.valid then - entity.destroy() - end - end -end - -local function find_intersection(surface, x, y) - -- try to get position in between of valid chunks by probing map - -- this may breaks determinism of generation, but so far it returned on first if - local gt = surface.get_tile - local restriction = '' - if gt(x + CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid then - restriction = 'xy' - elseif gt(x + CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y).valid and gt(x, y + CHUNK_SIZE*2).valid then - x=x + CHUNK_SIZE/2 - y=y + CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x + CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y).valid and gt(x, y - CHUNK_SIZE*2).valid then - x=x + CHUNK_SIZE/2 - y=y - CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x - CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y).valid and gt(x, y + CHUNK_SIZE*2).valid then - x=x - CHUNK_SIZE/2 - y=y + CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x - CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y).valid and gt(x, y - CHUNK_SIZE*2).valid then - x=x - CHUNK_SIZE/2 - y=y - CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x + CHUNK_SIZE*2, y).valid then - x=x + CHUNK_SIZE/2 - restriction = 'x' - elseif gt(x - CHUNK_SIZE*2, y).valid then - x=x - CHUNK_SIZE/2 - restriction = 'x' - elseif gt(x, y + CHUNK_SIZE*2).valid then - y=y + CHUNK_SIZE/2 - restriction = 'y' - elseif gt(x, y - CHUNK_SIZE*2).valid then - y=y - CHUNK_SIZE/2 - restriction = 'y' - end - return x, y, restriction -end - -local function find_random_chunk(r_x, r_y) - local offset_x=rgen:random(region_size)-1 - local offset_y=rgen:random(region_size)-1 - local c_x=r_x*REGION_TILE_SIZE + offset_x*CHUNK_SIZE - local c_y=r_y*REGION_TILE_SIZE + offset_y*CHUNK_SIZE - return c_x, c_y -end - -local function is_same_region(c_x1, c_y1, c_x2, c_y2) - if not floor(c_x1/REGION_TILE_SIZE) == floor(c_x2/REGION_TILE_SIZE) then - return false - end - if not floor(c_y1/REGION_TILE_SIZE) == floor(c_y2/REGION_TILE_SIZE) then - return false - end - return true -end - -local function find_random_neighbour_chunk(ocx, ocy) - -- somewhat bruteforce and unoptimized - local x_dir = rgen:random(-1,1) - local y_dir = rgen:random(-1,1) - local ncx = ocx + x_dir*CHUNK_SIZE - local ncy = ocy + y_dir*CHUNK_SIZE - if is_same_region(ncx, ncy, ocx, ocy) then - return ncx, ncy - end - - ncx = ocx - x_dir*CHUNK_SIZE - ncy = ocy - y_dir*CHUNK_SIZE - if is_same_region(ncx, ncy, ocx, ocy) then - return ncx, ncy - end - - ncx = ocx - x_dir*CHUNK_SIZE - if is_same_region(ncx, ocy, ocx, ocy) then - return ncx, ocy - end - - ncy = ocy - y_dir*CHUNK_SIZE - if is_same_region(ocx, ncy, ocx, ocy) then - return ocx, ncy - end - - return ocx, ocy -end - -local function isInStartingArea( regionX, regionY ) - - for idx, pos in pairs( global.startingAreas ) do - - local adjustedX = regionX - pos.x / REGION_TILE_SIZE - local adjustedY = regionY - pos.y / REGION_TILE_SIZE - if ((adjustedX * adjustedX + adjustedY * adjustedY) <= starting_area_size * starting_area_size) then - return true - end - end - - return false -end - --- OARC SPECIFIC FUNCTION -- --- Checks if a point is near a spawn area -local function isNearOarcSpawn(pointPos) - - if (global.uniqueSpawns) and (ENFORCE_LAND_AREA_TILE_DIST) then - for name,spawn in pairs(global.uniqueSpawns) do - local clearArea = GetAreaFromPointAndDistance(spawn.pos, - (ENFORCE_LAND_AREA_TILE_DIST+2*CHUNK_SIZE)) - if (CheckIfInArea(pointPos,clearArea)) then - return true - end - end - end - - return false -end - --- modifies the resource size - only used in endless_resource_mode -local function modify_resource_size(resourceName, resourceSize, startingArea) - - if not startingArea then - resourceSize = math.ceil(resourceSize * global_size_mult) - end - - resourceEntity = game.entity_prototypes[resourceName] - if resourceEntity and resourceEntity.infinite_resource then - - newResourceSize = resourceSize * endless_resource_mode_sizeModifier - - -- make sure it's still an integer - newResourceSize = math.ceil(newResourceSize) - -- make sure it's not 0 - if newResourceSize == 0 then newResourceSize = 1 end - return newResourceSize - else - return resourceSize - end -end - ---[[ SPAWN METHODS ]]-- - -local locationOrder = -{ - { x = 0, y = 0 }, - { x = -1, y = 0 }, - { x = 1, y = 0 }, - { x = 0, y = -1 }, - { x = 0, y = 1 }, - { x = -1, y = -1 }, - { x = 1, y = -1 }, - { x = -1, y = 1 }, - { x = 1, y = 1 } -} - ---[[ entity-field ]]-- -local function spawn_resource_ore(surface, rname, pos, size, richness, startingArea, restrictions) - -- blob generator, centered at pos, size controls blob diameter - restrictions = restrictions or '' - debug("Entering spawn_resource_ore "..rname.." at:"..pos.x..","..pos.y.." size:"..size.." richness:"..richness.." isStart:"..tostring(startingArea).." restrictions:"..restrictions) - - size = modify_resource_size(rname, size, startingArea) - local radius = size / 2 -- to radius - - local p_balls={} - local n_balls={} - local MIN_BALL_DISTANCE = math.min(MIN_BALL_DISTANCE, radius/2) - - local maxPradius = 0 - local outside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } - local inside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } - - local function adjustRadius(radius, scaleX, scaleY, up) - return radius - end - - local function updateRect(rect, x, y, radius) - rect.xmin = math.min(rect.xmin, x - radius) - rect.xmax = math.max(rect.xmax, x + radius) - rect.ymin = math.min(rect.ymin, y - radius) - rect.ymax = math.max(rect.ymax, y + radius) - end - - local function updateRects(x, y, radius, scaleX, scaleY) - local adjustedRadius = adjustRadius(radius, scaleX, scaleY, true) - local radiusMax = adjustedRadius * 3 -- arbitrary multiplier - needs to be big enough to not cut any metaballs - updateRect(outside, x, y, radiusMax) - updateRect(inside, x, y, adjustedRadius) - end - - local function generate_p_ball() - local angle, x_scale, y_scale, x, y, b_radius, shape - angle, x_scale, y_scale=rng_restricted_angle(restrictions) - local dev = radius / 2 + rgen:random() * radius / 4--math.min(CHUNK_SIZE/3, radius*1.5) - local dev_x, dev_y = pos.x, pos.y - x = rgen:random(-dev, dev)+dev_x - y = rgen:random(-dev, dev)+dev_y - if p_balls[#p_balls] and distance(p_balls[#p_balls], {x=x, y=y}) < MIN_BALL_DISTANCE then - local new_angle = bearing(p_balls[#p_balls], {x=x, y=y}) - debug("Move ball old xy @ "..x..","..y) - x=(cos(new_angle)*MIN_BALL_DISTANCE) + x - y=(sin(new_angle)*MIN_BALL_DISTANCE) + y - debug("Move ball new xy @ "..x..","..y) - end - - if #p_balls == 0 then - b_radius = ( 3 * radius / 4 + rgen:random() * radius / 4) -- * (P_BALL_SIZE_FACTOR^#p_balls) - else - b_radius = ( radius / 4 + rgen:random() * radius / 2) -- * (P_BALL_SIZE_FACTOR^#p_balls) - end - - - if #p_balls > 0 then - local tempRect = table.deepcopy(inside) - updateRect(tempRect, x, y, adjustRadius(b_radius, x_scale, y_scale)) - local rectSize = math.max(tempRect.xmax - tempRect.xmin, tempRect.ymax - tempRect.ymin) - local targetSize = size * 1.25 - debug("Rect size "..rectSize.." targetSize "..targetSize) - if rectSize > targetSize then - local widthLeft = (targetSize - (inside.xmax - inside.xmin)) - local heightLeft = (targetSize - (inside.ymax - inside.ymin)) - local widthMod = math.min(x - inside.xmin, inside.xmax - x) - local heightMod = math.min(y - inside.ymin, inside.ymax - y) - local radiusBackup = b_radius - b_radius = math.min(widthLeft + widthMod, heightLeft + heightMod) - b_radius = adjustRadius(b_radius, x_scale, y_scale, false) - debug("Reduced ball radius from "..radiusBackup.." to "..b_radius.." widthLeft:"..widthLeft.." heightLeft:"..heightLeft.." widthMod:"..widthMod.." heightMod:"..heightMod) - end - end - - if b_radius < 2 and #p_balls == 0 then - b_radius = 2 - end - - if b_radius > 0 then - - maxPradius = math.max(maxPradius, b_radius) - shape = meta_shapes[rgen:random(1,#meta_shapes)] - local radiusText = "" - if shape.type == "MetaDonut" then - local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() - radiusText = " inRadius:"..inRadius - p_balls[#p_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.1) - else - p_balls[#p_balls+1] = shape:new(x, y, b_radius, angle, x_scale, y_scale, 1.1) - end - updateRects(x, y, b_radius, x_scale, y_scale) - - debug("P+Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) - end - end - - local function generate_n_ball(i) - local angle, x_scale, y_scale, x, y, b_radius, shape - angle, x_scale, y_scale=rng_restricted_angle('xy') - if p_balls[i] then - local new_angle = p_balls[i].angle + pi*rgen:random(0,1) + (rgen:random()-0.5)*pi/2 - local dist = p_balls[i].radius - x=(cos(new_angle)*dist) + p_balls[i].x - y=(sin(new_angle)*dist) + p_balls[i].y - angle = p_balls[i].angle + pi/2 + (rgen:random()-0.5)*pi*2/3 - else - x = rgen:random(-radius, radius)+pos.x - y = rgen:random(-radius, radius)+pos.y - end - - if p_balls[i] then - b_radius = (p_balls[i].radius / 4 + rgen:random() * p_balls[i].radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) - else - b_radius = (radius / 4 + rgen:random() * radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) - end - - if b_radius < 1 then - b_radius = 1 - end - - shape = meta_shapes[rgen:random(1,#meta_shapes)] - local radiusText = "" - if shape.type == "MetaDonut" then - local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() - radiusText = " inRadius:"..inRadius - n_balls[#n_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.15) - else - n_balls[#n_balls+1] = shape:new(x, y, b_radius, angle, x_scale, y_scale, 1.15) - end - -- updateRects(x, y, b_radius, x_scale, y_scale) -- should not be needed here - only positive ball can generate ore - debug("N-Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) - end - - local function calculate_force(x,y) - local p_force = 0 - local n_force = 0 - for _,ball in ipairs(p_balls) do - p_force = p_force + ball:force(x,y) - end - for _,ball in ipairs(n_balls) do - n_force = n_force + ball:force(x,y) - end - local totalForce = 0 - if p_force > n_force then - totalForce = 1 - 1/(p_force - n_force) - end - --debug("Force at "..x..","..y.." p:"..p_force.." n:"..n_force.." result:"..totalForce) - --return (1 - 1/p_force) - n_force - return totalForce - end - - local max_p_balls = 2 - local min_amount = config[rname].min_amount or min_amount - if restrictions == 'xy' then - max_p_balls = 3 - end - - radius = math.min(radius, 2*CHUNK_SIZE) - - local force - -- generate blobs - for i=1,max_p_balls do - generate_p_ball() - end - - for i=1,rgen:random(1, #p_balls) do - generate_n_ball(i) - end - - - local _total = 0 - local oreLocations = {} - local forceTotal = 0 - - -- fill the map - for y=outside.ymin, outside.ymax do - - for x=outside.xmin, outside.xmax do - force = calculate_force(x, y) - if force > 0 then - oreLocations[#oreLocations + 1] = {x = x, y = y, force = force, valid = false} - forceTotal = forceTotal + force - end - end - end - - local validCount, resOffsetX, resOffsetY, ratio - - for _,locationOffset in ipairs(locationOrder) do - validCount = 0 - resOffsetX = locationOffset.x * CHUNK_SIZE - resOffsetY = locationOffset.y * CHUNK_SIZE - - for _, location in ipairs(oreLocations) do - - local newX = location.x + resOffsetX - local newY = location.y + resOffsetY - location.valid = false - if surface.can_place_entity{name = rname, position = {x = newX,y = newY}} then - location.valid = true - validCount = validCount + 1 - end - end - - ratio = 0 - - if validCount > 0 then - ratio = validCount / #oreLocations - end - - debug("Valid ratio ".. ratio) - - if not useResourceCollisionDetection then - break - end - - if ratio > resourceCollisionDetectionRatio then - break - elseif resourceCollisionFieldSkip then -- in case no valid ratio was found we skip the field completely - validCount = 0 - end - end - - if validCount > 0 then - local rectSize = ((inside.xmax - inside.xmin) + (inside.ymax - inside.ymin)) / 2 - - local sizeMultiplier = rectSize ^ 0.6 - local minSize = richness * 5 * sizeMultiplier - local maxSize = richness * 10 * sizeMultiplier - local approxDepositSize = rgen:random(minSize, maxSize) - - approxDepositSize = approxDepositSize - validCount * min_amount - - if approxDepositSize < 0 then - approxDepositSize = 100 * validCount - end - - local forceFactor = approxDepositSize / forceTotal - - -- don't create very dense resources in starting area - another field will be generated - if startingArea and forceFactor > 4000 then - forceFactor = rgen:random(3000, 4000) - end - - debug( "Force total:"..forceTotal.." sizeMin:"..minSize.." sizeMax:"..maxSize.." factor:"..forceFactor.." location#:"..validCount.." rectSize:"..rectSize.." sizeMultiplier:"..sizeMultiplier) - local richnessMultiplier = global_richness_mult - - if startingArea then - richnessMultiplier = starting_richness_mult - end - - -- infinite ore handling for Angels Ores mod - local infiniteOrePresent = false - local infiniteOreName = "infinite-"..rname - local minimumInfiniteOreAmount = nil - local spawnName = rname - - if game.entity_prototypes[infiniteOreName] then - infiniteOrePresent = true - minimumInfiniteOreAmount = game.entity_prototypes[infiniteOreName].minimum_resource_amount - end - - if startingArea and not infiniteResourceInStartArea then - infiniteOrePresent = false - end - - for _,location in ipairs(oreLocations) do - if location.valid then - - local amount = floor(( forceFactor * location.force + min_amount ) * richnessMultiplier) - - if amount > 1e9 then - amount = 1e9 - end - - _total = _total + amount - - spawnName = rname - if infiniteOrePresent and location.force > infiniteResourceSpawnThreshold then - spawnName = infiniteOreName - if minimumInfiniteOreAmount and amount < minimumInfiniteOreAmount then - amount = minimumInfiniteOreAmount - end - end - - if amount > 0 then - surface.create_entity{name = spawnName, - position = {location.x + resOffsetX,location.y + resOffsetY}, - force = game.forces.neutral, - amount = amount} - end - end - end - - end - - if debug_enabled then - debug("Total amount: ".._total) - debug("Leaving spawn_resource_ore") - end - return _total -end - ---[[ entity-liquid ]]-- -local function spawn_resource_liquid(surface, rname, pos, size, richness, startingArea, restrictions) - restrictions = restrictions or '' - debug("Entering spawn_resource_liquid "..rname.." "..pos.x..","..pos.y.." "..size.." "..richness.." "..tostring(startingArea).." "..restrictions) - local _total = 0 - local max_radius = rgen:random()*CHUNK_SIZE/2 + CHUNK_SIZE - - richness = ( 0.75 + rgen:random() / 2 ) * richness * size - - resourceEntity = game.entity_prototypes[rname] - - - local total_share = 0 - local avg_share = 1/size - local angle = rgen:random()*pi*2 - local saved = 0 - while total_share < 1 do - local new_share = vary_by_percentage(avg_share, 0.25) - if new_share + total_share > 1 then - new_share = 1 - total_share - end - total_share = new_share + total_share - if new_share < avg_share/10 then - -- too small - break - end - local amount = floor(richness*new_share) + saved - - local richnessMultiplier = global_richness_mult - - if startingArea then - richnessMultiplier = starting_richness_mult - end - - --if amount >= game.entity_prototypes[rname].minimum then - if amount >= config[rname].minimum_amount then - saved = 0 - for try=1,5 do - local dist = rgen:random()*(max_radius - max_radius*0.1) - angle = angle + pi/4 + rgen:random()*pi/2 - local x, y = pos.x + cos(angle)*dist, pos.y + sin(angle)*dist - if surface.can_place_entity{name = rname, position = {x,y}} then - debug("@ "..x..","..y.." amount: "..amount.." new_share: "..new_share.." try: "..try) - amount = floor(amount * richnessMultiplier) - - if amount > 1e9 then - amount = 1e9 - end - - _total = _total + amount - - if amount > 0 then - surface.create_entity{name = rname, - position = {x,y}, - force = game.forces.neutral, - amount = amount, - direction = rgen:random(4)} - end - break - elseif not startingArea then -- we don't want to make ultra rich nodes in starting area - failing to make them will add second spawn in different location - entities = surface.find_entities_filtered{area = {{x-2.75, y-2.75}, {x+2.75, y+2.75}}, name=rname} - if entities and #entities > 0 then - _total = _total + amount - for k, ent in pairs(entities) do - ent.amount = ent.amount + floor(amount/#entities) - end - break - end - end - end - else - saved = amount - end - end - debug("Total amount: ".._total) - debug("Leaving spawn_resource_liquid") - return _total -end - -local spawnerTable = nil - -local function initSpawnerTable() - if spawnerTable == nil then - spawnerTable = {} - spawnerTable["biter-spawner"] = game.entity_prototypes["biter-spawner"] ~= nil - spawnerTable["bob-biter-spawner"] = game.entity_prototypes["bob-biter-spawner"] ~= nil - spawnerTable["spitter-spawner"] = game.entity_prototypes["spitter-spawner"] ~= nil - spawnerTable["bob-spitter-spawner"] = game.entity_prototypes["bob-spitter-spawner"] ~= nil - end -end - -local function spawn_entity(surface, ent, r_config, x, y) - if not use_RSO_biter_spawning then return end - local size=rgen:random(r_config.size.min, r_config.size.max) - - local _total = 0 - local r_distance = distance({x=0,y=0},{x=x/REGION_TILE_SIZE,y=y/REGION_TILE_SIZE}) - - local distanceMultiplier = math.min(r_distance^r_config.size_per_region_factor, 5) - if r_config.size_per_region_factor then - size = size*distanceMultiplier - end - - size = size * enemy_base_size_multiplier - - debug("Entering spawn_entity "..ent.." "..x..","..y.." "..size) - - local maxAttemptCount = 5 - local distancePerAttempt = 0.2 - - initSpawnerTable() - - for i=1,size do - for attempt = 1, maxAttemptCount do - local richness=r_config.richness*(r_distance^richness_distance_factor) - local max_d = floor(CHUNK_SIZE*(0.5 + distancePerAttempt*attempt)) - local s_x = x + rgen:random(0, floor(max_d - r_config.clear_range[1])) - max_d/2 + r_config.clear_range[1] - local s_y = y + rgen:random(0, floor(max_d - r_config.clear_range[2])) - max_d/2 + r_config.clear_range[2] - - if surface.get_tile(s_x, s_y).valid then - - remove_trees(surface, s_x, s_y, r_config.clear_range[1], r_config.clear_range[2]) - - local spawnerName = nil - - if spawner_probability_edge > 0 then - - bigSpawnerChance = rgen:random() - - if rgen:random() < spawner_probability_edge then - if ( useBobEntity and bigSpawnerChance > 0.75 ) then - spawnerName = "bob-biter-spawner" - else - spawnerName = "biter-spawner" - end - else - if ( useBobEntity and bigSpawnerChance > 0.75 ) then - spawnerName = "bob-spitter-spawner" - else - spawnerName = "spitter-spawner" - end - end - end - - if spawnerName and spawnerTable[spawnerName] then - if surface.can_place_entity{name=spawnerName, position={s_x, s_y}} then - _total = _total + richness - debug(spawnerName.." @ "..s_x..","..s_y.." placed on "..attempt.." attempt") - - surface.create_entity{name=spawnerName, position={s_x, s_y}, force=game.forces[r_config.force], amount=floor(richness)}--, direction=rgen:random(4) - -- else - -- debug("Entity "..spawnerName.." spawn failed") - break; - else - if attempt == maxAttemptCount then - debug(spawnerName.." @ "..s_x..","..s_y.." failed to spawn") - end - end - else - debug("Entity "..spawnerName.." doesn't exist") - end - end - end - - if r_config.sub_spawn_probability then - local sub_spawn_prob = r_config.sub_spawn_probability*math.min(r_config.sub_spawn_max_distance_factor, r_config.sub_spawn_distance_factor^r_distance) - if rgen:random() < sub_spawn_prob then - for i=1,(rgen:random(r_config.sub_spawn_size.min, r_config.sub_spawn_size.max)*distanceMultiplier) do - local allotment_max = 0 - -- build table - for k,v in pairs(r_config.sub_spawns) do - if not v.min_distance or r_distance > v.min_distance then - local allotment = v.allotment - if v.allotment_distance_factor then - allotment = allotment * (v.allotment_distance_factor^r_distance) - end - v.allotment_range ={min = allotment_max, max = allotment_max + allotment} - allotment_max = allotment_max + allotment - else - v.allotment_range = nil - end - end - local sub_type = rgen:random(0, allotment_max) - for sub_spawn,v in pairs(r_config.sub_spawns) do - if v.allotment_range and sub_type >= v.allotment_range.min and sub_type <= v.allotment_range.max then - for attempt = 1, maxAttemptCount do - local max_d = floor(CHUNK_SIZE*distancePerAttempt*attempt) - s_x = x + rgen:random(max_d) - max_d/2 - s_y = y + rgen:random(max_d) - max_d/2 - remove_trees(surface, s_x, s_y, v.clear_range[1], v.clear_range[2]) - if surface.can_place_entity{name=sub_spawn, position={s_x, s_y}} then - surface.create_entity{name=sub_spawn, position={s_x, s_y}, force=game.forces[r_config.force]}--, direction=rgen:random(4) - debug("Rolled subspawn "..sub_spawn.." @ "..s_x..","..s_x.." after "..attempt.." attempts") - break; - else - if attempt == maxAttemptCount then - debug("Rolling subspawn "..sub_spawn.." @ "..s_x..","..s_x.." failed") - end - end - end - break - end - end - end - end - end - end - debug("Total amount: ".._total) - debug("Leaving spawn_entity") -end - ---[[ EVENT/INIT METHODS ]]-- - -local function spawn_starting_resources( surface, index ) - - if global.startingAreas[index].spawned then return end - if surface.map_gen_settings.starting_area == "none" and not ignoreMapGenSettings then return end -- starting area disabled by map gen - if starting_area_size < 0.1 then return end -- skip spawning if starting area is to small - - local position = global.startingAreas[index] - - rgen = rng_for_reg_pos( position ) - local status = true - for index,v in ipairs(configIndexed) do - if v.starting then - local prob = rgen:random() -- probability that this resource is spawned - debug("starting resource probability rolled "..prob) - if v.starting.probability > 0 and prob <= v.starting.probability then - local total = 0 - local radius = 25 - local min_threshold = 0 - - if v.type == "resource-ore" then - min_threshold = v.starting.richness * rgen:random(5, 10) -- lets make sure that there is at least 10-15 times starting richness ore at start - elseif v.type == "resource-liquid" then - min_threshold = v.starting.richness * 0.5 * v.starting.size - end - - while (radius < 200) and (total < min_threshold) do - local angle = rgen:random() * pi * 2 - local dist = rgen:random() * 30 + radius * 2 - local pos = { x = floor(cos(angle) * dist) + position.x, y = floor(sin(angle) * dist) + position.y } - if v.type == "resource-ore" then - total = total + spawn_resource_ore(surface, v.name, pos, v.starting.size, v.starting.richness, true) - elseif v.type == "resource-liquid" then - total = total + spawn_resource_liquid(surface, v.name, pos, v.starting.size, v.starting.richness, true) - end - radius = radius + 10 - end - if total < min_threshold then - status = false - end - end - end - end - - global.startingAreas[index].spawned = true -end - -local function modifyMinMax(value, mod) - value.min = round( value.min * mod ) - value.max = round( value.max * mod ) -end - -local function prebuild_config_data(surface) - if index_is_built then return false end - - local mapGenSettings = nil - - if not ignoreMapGenSettings then - mapGenSettings = surface.map_gen_settings - end - local autoPlaceSettings = nil - if mapGenSettings then - autoPlaceSettings = mapGenSettings.autoplace_controls - end - - configIndexed = {} - -- build additional indexed array to the associative array - for res_name, res_conf in pairs(config) do - if res_conf.valid then -- only add valid resources - res_conf.name = res_name - - local settingsForResource = nil - local isEntity = (res_conf.type == "entity") - local addResource = true - - local autoplaceName = res_name - - if res_conf.autoplace_name then - autoplaceName = res_conf.autoplace_name - end - - if autoPlaceSettings then - settingsForResource = autoPlaceSettings[autoplaceName] - end - - if settingsForResource then - local allotmentMod = nil - local sizeMod = nil - if isEntity then - allotmentMod = entityFrequencyMultiplier[settingsForResource.frequency] - sizeMod = entitySizeMultiplier[settingsForResource.size] - else - allotmentMod =frequencyAllotmentMultiplier[settingsForResource.frequency] - sizeMod = sizeMultiplier[settingsForResource.size] - end - - local richnessMod = richnessMultiplier[settingsForResource.richness] - - - debug(res_name .. " allotment mod " .. allotmentMod .. " size mod " .. sizeMod .. " richness mod " .. richnessMod ) - - - if allotmentMod then - if isEntity then - res_conf.absolute_probability = res_conf.absolute_probability * allotmentMod - debug("Entity chance modified to "..res_conf.absolute_probability) - else - res_conf.allotment = round( res_conf.allotment * allotmentMod ) - end - end - - if sizeMod ~= nil and sizeMod == 0 then - addResource = false - end - - if sizeMod then - modifyMinMax(res_conf.size, sizeMod) - - if res_conf.starting then - res_conf.starting.size = round( res_conf.starting.size * sizeMod ) - end - - if isEntity then - if res_conf.sub_spawn_size then - modifyMinMax(res_conf.sub_spawn_size, sizeMod) - end - modifyMinMax(res_conf.spawns_per_region, sizeMod) - end - end - - if richnessMod then - if type == "resource-ore" then - res_conf.richness = round( res_conf.richness * richnessMod ) - elseif type == "resource-liquid" then - modifyMinMax(res_conf.richness, richnessMod) - end - - if res_conf.starting then - res_conf.starting.richness = round( res_conf.starting.richness * richnessMod ) - end - end - end - - if addResource then - configIndexed[#configIndexed + 1] = res_conf - if res_conf.multi_resource and multi_resource_active then - local new_list = {} - for sub_res_name, allotment in pairs(res_conf.multi_resource) do - if config[sub_res_name] and config[sub_res_name].valid then - new_list[#new_list+1] = {name = sub_res_name, allotment = allotment} - end - end - table.sort(new_list, function(a, b) return a.name < b.name end) - res_conf.multi_resource = new_list - else - res_conf.multi_resource_chance = nil - end - end - end - end - - table.sort(configIndexed, function(a, b) return a.name < b.name end) - - local pr=0 - for index,v in pairs(config) do - if v.along_resource_probability then - v.along_resource_probability_range={min=pr, max=pr+v.along_resource_probability} - pr=pr+v.along_resource_probability - end - if v.allotment and v.allotment > 0 then - v.allotment_range={min=max_allotment, max=max_allotment+v.allotment} - max_allotment=max_allotment+v.allotment - end - end - - if mapGenSettings and mapGenSettings.starting_area then - local multiplier = startingAreaMultiplier[mapGenSettings.starting_area] - if multiplier ~= nil then - starting_area_size = starting_area_size * multiplier - debug("Starting area "..starting_area_size) - end - end - - index_is_built = true -end - --- set up the probabilty segments from which to roll between for biter and spitter spawners -local function calculate_spawner_ratio() - if (biter_ratio_segment ~= 0 and spitter_ratio_segment ~= 0) and biter_ratio_segment >= 0 and spitter_ratio_segment >= 0 then - spawner_probability_edge=biter_ratio_segment/(biter_ratio_segment+spitter_ratio_segment) -- normalize to between 0 and 1 - end -end - -local function checkConfigForInvalidResources() - --make sure that every resource in the config is actually available. - --call this function, before the auxiliary config is prebuilt! - if index_is_built then return end - - local prototypes = game.entity_prototypes - - for resourceName, resourceConfig in pairs(config) do - if prototypes[resourceName] or resourceConfig.type == "entity" then - resourceConfig.valid = true - else - -- resource was in config, but it doesn't exist in game files anymore - mark it invalid - resourceConfig.valid = false - - table.insert(invalidResources, "Resource not available: " .. resourceName) - debug("Resource not available: " .. resourceName) - end - - if resourceConfig.valid and resourceConfig.type ~= "entity" then - if prototypes[resourceName].autoplace_specification == nil then - resourceConfig.valid = false - debug("Resource "..resourceName.." invalidated - autoplace not present") - end - end - end -end - -local function roll_region(c_x, c_y) - --in what region is this chunk? - local r_x=floor(c_x/REGION_TILE_SIZE) - local r_y=floor(c_y/REGION_TILE_SIZE) - local r_data = nil - - --don't spawn stuff in starting area - if isInStartingArea( c_x/REGION_TILE_SIZE, c_y/REGION_TILE_SIZE ) then - return false - end - - -- Reroll regions every region_size^2 chunk generation calls. - local regrow_rso = false - if (ENABLE_REGROWTH) then - if (global.chunk_regrow.rso_region_roll_counter > (region_size*region_size/2)) then - regrow_rso = true - global.chunk_regrow.rso_region_roll_counter = 0 - else - global.chunk_regrow.rso_region_roll_counter = global.chunk_regrow.rso_region_roll_counter + 1 - end - end - - --if this chunk is the first in its region to be generated - -- or we're hitting a lucky regrowth reroll... - if (not (global.regions[r_x] and global.regions[r_x][r_y]) or regrow_rso) then - - if not global.regions[r_x] then global.regions[r_x] = {} end - global.regions[r_x][r_y]={} - r_data = global.regions[r_x][r_y] - rgen = rng_for_reg_pos{x=r_x,y=r_y} - - local rollCount = math.ceil(#configIndexed / 10) - 1 -- 0 based counter is more convenient here - rollCount = math.min(rollCount, 3) - - for rollNumber = 0,rollCount do - - local resourceChance = absolute_resource_chance - rollNumber * 0.1 - --absolute chance to spawn resource - local abct = rgen:random() - debug("Rolling resource "..abct.." against "..resourceChance.." roll "..rollNumber) - if abct <= resourceChance then - local res_type=rgen:random(1, max_allotment) - for index,v in ipairs(configIndexed) do - if v.allotment_range and ((res_type >= v.allotment_range.min) and (res_type <= v.allotment_range.max)) then - debug("Rolled primary resource "..v.name.." with res_type="..res_type.." @ "..r_x..","..r_y) - local num_spawns=rgen:random(v.spawns_per_region.min, v.spawns_per_region.max) - local last_spawn_coords = {} - local along_ - for i=1,num_spawns do - local c_x, c_y = find_random_chunk(r_x, r_y) - if not r_data[c_x] then r_data[c_x] = {} end - if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end - local c_data = r_data[c_x][c_y] - c_data[#c_data+1]={v.name, rollNumber} - last_spawn_coords[#last_spawn_coords+1] = {c_x, c_y} - debug("Rolled primary chunk "..v.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) - -- Along resource spawn, only once - if i == 1 then - local am_roll = rgen:random() - for index,vv in ipairs(configIndexed) do - if vv.along_resource_probability_range and am_roll >= vv.along_resource_probability_range.min and am_roll <= vv.along_resource_probability_range.max then - c_data = r_data[c_x][c_y] - c_data[#c_data+1]={vv.name, rollNumber} - debug("Rolled along "..vv.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) - end - end - end - end - -- roll multiple resources in same region - local deep=0 - while v.multi_resource_chance and rgen:random() <= v.multi_resource_chance*(multi_resource_chance_diminish^deep) do - deep = deep + 1 - local max_allotment = 0 - for index,sub_res in pairs(v.multi_resource) do max_allotment=max_allotment+sub_res.allotment end - - local res_type=rgen:random(1, max_allotment) - local min=0 - for _, sub_res in pairs(v.multi_resource) do - if (res_type >= min) and (res_type <= sub_res.allotment + min) then - local last_coords = last_spawn_coords[rgen:random(1, #last_spawn_coords)] - local c_x, c_y = find_random_neighbour_chunk(last_coords[1], last_coords[2]) -- in same as primary resource chunk - if not r_data[c_x] then r_data[c_x] = {} end - if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end - local c_data = r_data[c_x][c_y] - c_data[#c_data+1]={sub_res.name, deep} - debug("Rolled multiple "..sub_res.name..":"..deep.." with res_type="..res_type.." @ "..c_x.."."..c_y.." reg: "..r_x.."."..r_y) - break - else - min = min + sub_res.allotment - end - end - end - break - end - end - - end - end - -- roll for absolute_probability - this rolls the enemies - - for index,v in ipairs(configIndexed) do - if v.absolute_probability then - local prob_factor = 1 - if v.probability_distance_factor then - prob_factor = math.min(v.max_probability_distance_factor, v.probability_distance_factor^distance({x=0,y=0},{x=r_x,y=r_y})) - end - local abs_roll = rgen:random() - if abs_roll 10 then - global.startingAreas[1].spawned = true - end - end - - calculate_spawner_ratio() - spawn_starting_resources(surface, 1 ) - - initDone = true - - if surface.map_gen_settings.autoplace_controls["iron-ore"].size ~= "none" then - game.players[1].print("RSO WARNING - VANILLA iron-ore GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["copper-ore"].size ~= "none" then - game.players[1].print("RSO WARNING - VANILLA copper-ore GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["uranium-ore"].size ~= "none" then - game.players[1].print("RSO WARNING - VANILLA uranium-ore GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["crude-oil"].size ~= "none" then - game.players[1].print("RSO WARNING - VANILLA crude-oil GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["enemy-base"].size ~= "none" then - game.players[1].print("RSO WARNING - VANILLA enemy-base GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["stone"].size ~= "none" then - game.players[1].print("RSO WARNING - VANILLA stone GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["coal"].size ~= "none" then - game.players[1].print("RSO WARNING - VANILLA coal GEN IS NOT DISABLED!") - end - end - -end - -function RSO_ChunkGenerated(event) - local c_x = event.area.left_top.x - local c_y = event.area.left_top.y - - RSO_init() - - roll_region(c_x, c_y) - roll_chunk(event.surface, c_x, c_y) -end \ No newline at end of file diff --git a/locale/rso/rso_resource_config.lua b/locale/rso/rso_resource_config.lua deleted file mode 100644 index d465415..0000000 --- a/locale/rso/rso_resource_config.lua +++ /dev/null @@ -1,171 +0,0 @@ - -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 -end \ No newline at end of file diff --git a/separate_spawns.lua b/separate_spawns.lua index 4a0c401..b92732d 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -221,6 +221,7 @@ function ChangePlayerSpawn(player, pos) end function SendPlayerToNewSpawnAndCreateIt(player, spawn, moatEnabled) + -- Send the player to that position player.teleport(spawn, GAME_SURFACE_NAME) GivePlayerStarterItems(player) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index feb420a..a000ea3 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -155,11 +155,8 @@ function DisplaySpawnOptions(player) caption="This is the default spawn behavior of a vanilla game."} sGui.add{name = "normal_spawn_lbl2", type = "label", caption="You join the default team in the center of the map."} - sGui.add{name = "normal_spawn_lbl3", type = "label", - caption="(Back by popular request...)"} ApplyStyle(sGui.normal_spawn_lbl1, my_label_style) ApplyStyle(sGui.normal_spawn_lbl2, my_label_style) - ApplyStyle(sGui.normal_spawn_lbl3, my_label_style) else sGui.add{name = "normal_spawn_lbl1", type = "label", caption="Default spawn is disabled in this mode."} @@ -279,12 +276,26 @@ function DisplaySpawnOptions(player) end +function SpawnOptsGuiOptionsSelect(event) + if not (event and event.element and event.element.valid) then return end + local elemName = event.element.name + + -- This just updates the radio buttons. + if (elemName == "isolated_spawn_main_team_radio") then + event.element.parent.isolated_spawn_new_team_radio.state=false + elseif (elemName == "isolated_spawn_new_team_radio") then + event.element.parent.isolated_spawn_main_team_radio.state=false + end +end + + -- Handle the gui click of the spawn options function SpawnOptsGuiClick(event) if not (event and event.element and event.element.valid) then return end local player = game.players[event.player_index] local elemName = event.element.name + if (player.gui.center.spawn_opts == nil) then return -- Gui event unrelated to this gui. end @@ -311,14 +322,6 @@ function SpawnOptsGuiClick(event) end player.gui.center.spawn_opts.destroy() - -- This just updates the radio buttons. - elseif ((elemName == "isolated_spawn_main_team_radio") or - (elemName == "isolated_spawn_new_team_radio")) then - if (elemName == "isolated_spawn_main_team_radio") then - event.element.parent.isolated_spawn_new_team_radio.state=false - elseif (elemName == "isolated_spawn_new_team_radio") then - event.element.parent.isolated_spawn_main_team_radio.state=false - end else return -- Do nothing, no valid element item was clicked. @@ -329,9 +332,7 @@ function SpawnOptsGuiClick(event) GivePlayerStarterItems(player) ChangePlayerSpawn(player, player.force.get_spawn_position(GAME_SURFACE_NAME)) SendBroadcastMsg(player.name .. " joined the main force!") - ChartArea(player.force, player.position, 4, player.surface) - - + ChartArea(player.force, player.position, 4, player.surface) elseif ((elemName == "isolated_spawn_near") or (elemName == "isolated_spawn_far")) then CreateSpawnCtrlGui(player) @@ -348,45 +349,33 @@ function SpawnOptsGuiClick(event) end end - -- Re-used abandoned spawns... - -- if (#global.unusedSpawns >= 1) then - -- oldSpawn = table.remove(global.unusedSpawns) - -- global.uniqueSpawns[player.name] = oldSpawn - -- player.print("Sorry! You have been assigned to an abandoned base! This is done to keep map size small.") - -- ChangePlayerSpawn(player, oldSpawn.pos) - -- SendPlayerToSpawn(player) - -- GivePlayerStarterItems(player) - -- SendBroadcastMsg(player.name .. " joined an abandoned base!") - -- else + -- Find coordinates of a good place to spawn + if (elemName == "isolated_spawn_far") then + newSpawn = FindUngeneratedCoordinates(FAR_MIN_DIST,FAR_MAX_DIST, player.surface) + elseif (elemName == "isolated_spawn_near") then + newSpawn = FindUngeneratedCoordinates(NEAR_MIN_DIST,NEAR_MAX_DIST, player.surface) + end - -- Find coordinates of a good place to spawn - if (elemName == "isolated_spawn_far") then - newSpawn = FindUngeneratedCoordinates(FAR_MIN_DIST,FAR_MAX_DIST, player.surface) - elseif (elemName == "isolated_spawn_near") then - newSpawn = FindUngeneratedCoordinates(NEAR_MIN_DIST,NEAR_MAX_DIST, player.surface) - end + -- If that fails, find a random map edge in a rand direction. + if ((newSpawn.x == 0) and (newSpawn.x == 0)) then + newSpawn = FindMapEdge(GetRandomVector(), player.surface) + DebugPrint("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y) + end - -- If that fails, find a random map edge in a rand direction. - if ((newSpawn.x == 0) and (newSpawn.x == 0)) then - newSpawn = FindMapEdge(GetRandomVector(), player.surface) - DebugPrint("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y) - end + -- Create that spawn in the global vars + ChangePlayerSpawn(player, newSpawn) + + -- Send the player there + SendPlayerToNewSpawnAndCreateIt(player, newSpawn, moatChoice) + if (elemName == "isolated_spawn_near") then + SendBroadcastMsg(player.name .. " joined the game from a distance!") + elseif (elemName == "isolated_spawn_far") then + SendBroadcastMsg(player.name .. " joined the game from a great distance!") + end - -- Create that spawn in the global vars - ChangePlayerSpawn(player, newSpawn) - - -- Send the player there - SendPlayerToNewSpawnAndCreateIt(player, newSpawn, moatChoice) - if (elemName == "isolated_spawn_near") then - SendBroadcastMsg(player.name .. " joined the game from a distance!") - elseif (elemName == "isolated_spawn_far") then - SendBroadcastMsg(player.name .. " joined the game from a great distance!") - end - - player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") - player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") - player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") - -- end + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") elseif (elemName == "join_other_spawn") then DisplaySharedSpawnOptions(player) @@ -411,7 +400,7 @@ function DisplaySharedSpawnOptions(player) ApplyStyle(shGui, my_fixed_width_style) shGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH shGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT - shGui.horizontal_scroll_policy = "never" + shGui.can_scroll_horizontally = false for spawnName,sharedSpawn in pairs(global.sharedSpawns) do @@ -520,7 +509,7 @@ function ExpandSpawnCtrlGui(player, tick) name="spwn_ctrl_panel", caption=""} ApplyStyle(spwnCtrls, my_fixed_width_style) spwnCtrls.style.maximal_height = SPAWN_GUI_MAX_HEIGHT - spwnCtrls.horizontal_scroll_policy = "never" + spwnCtrls.can_scroll_horizontally = false if ENABLE_SHARED_SPAWNS then if (global.uniqueSpawns[player.name] ~= nil) then @@ -561,22 +550,12 @@ function ExpandSpawnCtrlGui(player, tick) end -function SpawnCtrlGuiClick(event) +function SpawnCtrlGuiOptionsSelect(event) if not (event and event.element and event.element.valid) then return end local player = game.players[event.element.player_index] local name = event.element.name - if (name == "spwn_ctrls") then - ExpandSpawnCtrlGui(player, event.tick) - end - - if (event.element.parent) then - if (event.element.parent.name ~= "spwn_ctrl_panel") then - return - end - end - if (name == "accessToggle") then if event.element.state then if DoesPlayerHaveCustomSpawn(player) then @@ -595,6 +574,23 @@ function SpawnCtrlGuiClick(event) end end end +end + +function SpawnCtrlGuiClick(event) + if not (event and event.element and event.element.valid) then return end + + local player = game.players[event.element.player_index] + local name = event.element.name + + if (name == "spwn_ctrls") then + ExpandSpawnCtrlGui(player, event.tick) + end + + if (event.element.parent) then + if (event.element.parent.name ~= "spwn_ctrl_panel") then + return + end + end -- Sets a new respawn point and resets the cooldown. if (name == "setRespawnLocation") then From c81f3f9cb7f81e44f9d621a5e2ea228afb86f8af Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 15 Dec 2017 14:48:39 -0500 Subject: [PATCH 07/58] Adding note in readme about 0.16 and RSO --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 27c569b..897072a 100644 --- a/README.md +++ b/README.md @@ -1,7 +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! +0.16 is EXPERIMENTAL RIGHT NOW. It likely has bugs and it does NOT include RSO at this time. ## Instructions From 193ecba3cc9d460f687333de3fc0762e9e91ce6a Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 15 Dec 2017 15:43:03 -0500 Subject: [PATCH 08/58] buddy system dev --- config.lua | 1 + separate_spawns.lua | 3 ++ separate_spawns_guis.lua | 72 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/config.lua b/config.lua index b7606d7..13e8045 100644 --- a/config.lua +++ b/config.lua @@ -352,3 +352,4 @@ global.clMapGen.cliff_settings={cliff_elevation_0=100, cliff_elevation_interval= -- DEBUG prints for me global.oarcDebugEnabled = true +BUDDY_SPAWN = false diff --git a/separate_spawns.lua b/separate_spawns.lua index b92732d..9c02ac5 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -197,6 +197,9 @@ function InitSpawnGlobalsAndForces() if (global.playerCooldowns == nil) then global.playerCooldowns = {} end + if (global.waitingBuddies == nil) then + global.waitingBuddies = {} + 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) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index a000ea3..69903ff 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -248,6 +248,15 @@ function DisplaySpawnOptions(player) ApplyStyle(sGui.join_other_spawn_lbl1, my_warning_style) end + -- Hack for a 2 player twin spawn. + if BUDDY_SPAWN then + sGui.add{name = "buddy_spawn", + type = "button", + caption="Buddy Spawn"} + sGui.add{name = "buddy_spawn_lbl1", type = "label", + caption="You spawn with a buddy. You must both click this together."} + end + -- Some final notes sGui.add{name = "note_spacer1", type = "label", caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} @@ -308,6 +317,7 @@ function SpawnOptsGuiClick(event) (elemName == "isolated_spawn_near") or (elemName == "isolated_spawn_far") or (elemName == "join_other_spawn") or + (elemName == "buddy_spawn") or (elemName == "join_other_spawn_check")) then if (ENABLE_SEPARATE_TEAMS) then @@ -320,10 +330,8 @@ function SpawnOptsGuiClick(event) player.gui.center.spawn_opts.spawn_solo_flow.isolated_spawn_moat_option_checkbox.state end end - player.gui.center.spawn_opts.destroy() - - - else + player.gui.center.spawn_opts.destroy() + else return -- Do nothing, no valid element item was clicked. end @@ -379,11 +387,65 @@ function SpawnOptsGuiClick(event) elseif (elemName == "join_other_spawn") then DisplaySharedSpawnOptions(player) - + -- Provide a way to refresh the gui to check if people have shared their -- bases. elseif (elemName == "join_other_spawn_check") then DisplaySpawnOptions(player) + + -- Hacky buddy spawn system + elseif (elemName == "buddy_spawn") then + + if (TableLength(global.waitingBuddies) == 0) then + table.insert(global.waitingBuddies, player.name) + SendBroadcastMsg(player.name .. " is waiting for a buddy.") + + else + buddy_name = table.remove(global.waitingBuddies) + + CreateSpawnCtrlGui(player) + CreateSpawnCtrlGui(game.players[buddy_name]) + + -- Create a new spawn point + local newSpawn = {x=0,y=0} + + -- Create a new force for player if they choose that radio button + if ENABLE_SEPARATE_TEAMS and joinOwnTeamRadio then + local newForce = CreatePlayerCustomForce(player) + local buddyForce = CreatePlayerCustomForce(game.players[buddy_name]) + + if (FRONTIER_ROCKET_SILO_MODE and newForce and buddyForce) then + ChartRocketSiloArea(newForce, game.surfaces[GAME_SURFACE_NAME]) + ChartRocketSiloArea(buddyForce, game.surfaces[GAME_SURFACE_NAME]) + end + end + + -- Find coordinates of a good place to spawn + newSpawn = FindUngeneratedCoordinates(NEAR_MIN_DIST,NEAR_MAX_DIST, player.surface) + + -- If that fails, find a random map edge in a rand direction. + if ((newSpawn.x == 0) and (newSpawn.x == 0)) then + newSpawn = FindMapEdge(GetRandomVector(), player.surface) + DebugPrint("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y) + end + + -- Create that spawn in the global vars + buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*5), y=newSpawn.y} + ChangePlayerSpawn(player, newSpawn) + ChangePlayerSpawn(game.players[buddy_name], buddySpawn) + + -- Send the player there + SendPlayerToNewSpawnAndCreateIt(player, newSpawn, moatChoice) + SendPlayerToNewSpawnAndCreateIt(game.players[buddy_name], buddySpawn, moatChoice) + SendBroadcastMsg(player.name .. " and " .. buddy_name .. " joined the game from a distance!") + + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") + game.players[buddy_name].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") + game.players[buddy_name].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") + game.players[buddy_name].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") + end end end From e23e8504636d7cd15382b7ac0de362abc43d75cb Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 15 Dec 2017 16:39:10 -0500 Subject: [PATCH 09/58] tweaking live. --- config.lua | 28 ++++++++++++++-------------- locale/oarc_utils.lua | 3 +++ separate_spawns_guis.lua | 4 ++-- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/config.lua b/config.lua index 13e8045..f5856e8 100644 --- a/config.lua +++ b/config.lua @@ -139,8 +139,8 @@ 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 --50 +NEAR_MAX_DIST = 50 --125 -- -- Far Distance in chunks FAR_MIN_DIST = 200 --50 @@ -224,14 +224,14 @@ SPAWN_TREE_OCTAGON_ENABLED = true -- Safe area has no aliens -- +/- this in x and y direction -SAFE_AREA_TILE_DIST = CHUNK_SIZE*10 +SAFE_AREA_TILE_DIST = CHUNK_SIZE*5 -- Warning area has reduced aliens -- +/- this in x and y direction -WARNING_AREA_TILE_DIST = CHUNK_SIZE*25 +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 = 5`y --------------------------------------- @@ -325,18 +325,18 @@ CMD_LINE_MAP_GEN = true global.clMapGen = {} global.clMapGen.terrain_segmentation="normal" global.clMapGen.water="normal" -global.clMapGen.starting_area="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 = { - ["coal"]={frequency="very-low", size= "normal", richness= "very-high"}, - ["copper-ore"]={frequency= "very-low", size= "normal", richness= "very-high"}, - ["crude-oil"]={frequency= "low", size= "normal", richness= "very-high"}, + ["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= "normal", richness= "very-high"}, - ["stone"]={frequency= "very-low", size= "normal", richness= "very-high"}, - ["uranium-ore"]={frequency= "low", size= "normal", richness= "very-high"}, + ["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= "normal", size= "normal", richness= "normal"}, ["dirt"]={frequency= "normal", size= "normal", richness= "normal"}, ["grass"]={frequency= "normal", size= "normal", richness= "normal"}, @@ -344,7 +344,7 @@ global.clMapGen.autoplace_controls = { ["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=100, cliff_elevation_interval=100, name="cliff"} +global.clMapGen.cliff_settings={cliff_elevation_0=10, cliff_elevation_interval=10, name="cliff"} ------------------------------------------------------------------------------- -- DEBUG @@ -352,4 +352,4 @@ global.clMapGen.cliff_settings={cliff_elevation_0=100, cliff_elevation_interval= -- DEBUG prints for me global.oarcDebugEnabled = true -BUDDY_SPAWN = false +BUDDY_SPAWN = true diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index b7e142a..a607929 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -977,6 +977,9 @@ function CreateSpawnAreas(surface, chunkArea, spawnPointTable) 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 diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 69903ff..61fb702 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -407,7 +407,7 @@ function SpawnOptsGuiClick(event) CreateSpawnCtrlGui(game.players[buddy_name]) -- Create a new spawn point - local newSpawn = {x=0,y=0} + local newSpawn = {x=-(CHUNK_SIZE*2),y=0} -- Create a new force for player if they choose that radio button if ENABLE_SEPARATE_TEAMS and joinOwnTeamRadio then @@ -430,7 +430,7 @@ function SpawnOptsGuiClick(event) end -- Create that spawn in the global vars - buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*5), y=newSpawn.y} + buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*3), y=newSpawn.y} ChangePlayerSpawn(player, newSpawn) ChangePlayerSpawn(game.players[buddy_name], buddySpawn) From 22a691e0c826b604bcbc2a2f31a78f04b43e5896 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 15 Dec 2017 16:40:38 -0500 Subject: [PATCH 10/58] typo --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index f5856e8..8247a71 100644 --- a/config.lua +++ b/config.lua @@ -231,7 +231,7 @@ SAFE_AREA_TILE_DIST = CHUNK_SIZE*5 WARNING_AREA_TILE_DIST = CHUNK_SIZE*10 -- 1 : X (spawners alive : spawners destroyed) in this area -WARN_AREA_REDUCTION_RATIO = 5`y +WARN_AREA_REDUCTION_RATIO = 5 --------------------------------------- From 4200c4a96c0df46dba4635d87bfcc60256b5466d Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 16 Dec 2017 08:46:06 -0500 Subject: [PATCH 11/58] Trying to update RSO with latest 3.5.0 version. --- config.lua | 1 + control.lua | 11 +- locale/oarc_utils.lua | 16 +- locale/rso/drand.lua | 269 ++++++ locale/rso/metaball.lua | 104 ++ locale/rso/rso_config.lua | 55 ++ locale/rso/rso_control.lua | 1408 ++++++++++++++++++++++++++++ locale/rso/rso_resource_config.lua | 171 ++++ 8 files changed, 2033 insertions(+), 2 deletions(-) create mode 100644 locale/rso/drand.lua create mode 100644 locale/rso/metaball.lua create mode 100644 locale/rso/rso_config.lua create mode 100644 locale/rso/rso_control.lua create mode 100644 locale/rso/rso_resource_config.lua diff --git a/config.lua b/config.lua index 8247a71..626f435 100644 --- a/config.lua +++ b/config.lua @@ -52,6 +52,7 @@ WELCOME_MSG_TITLE_OARC = "Welcome to Oarc's Server!" ENABLE_SEPARATE_SPAWNS = true -- RSO OPTION HAS BEEN REMOVED FOR NOW. USE THE 0.16 MOD. +ENABLE_RSO = true -- Frontier style rocket silo mode FRONTIER_ROCKET_SILO_MODE = false diff --git a/control.lua b/control.lua index 2e4f546..bc4dde2 100644 --- a/control.lua +++ b/control.lua @@ -24,6 +24,7 @@ -- Generic Utility Includes require("locale/oarc_utils") +require("locale/rso/rso_control") require("locale/frontier_silo") require("locale/tag") @@ -92,7 +93,11 @@ script.on_init(function(event) -- 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! - CreateGameSurface() + if ENABLE_RSO then + CreateGameSurface(RSO_MODE) + else + CreateGameSurface(VANILLA_MODE) + end if ENABLE_SEPARATE_SPAWNS then InitSpawnGlobalsAndForces() @@ -140,6 +145,10 @@ script.on_event(defines.events.on_chunk_generated, function(event) UndecorateOnChunkGenerate(event) end + if ENABLE_RSO then + RSO_ChunkGenerated(event) + end + if FRONTIER_ROCKET_SILO_MODE then GenerateRocketSiloChunk(event) end diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index a607929..06f0e8c 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -988,7 +988,11 @@ end -------------------------------------------------------------------------------- -- Surface Generation Functions -------------------------------------------------------------------------------- -function CreateGameSurface() + +RSO_MODE = 1 +VANILLA_MODE = 2 + +function CreateGameSurface(mode) local mapSettings = game.surfaces["nauvis"].map_gen_settings if CMD_LINE_MAP_GEN then @@ -1001,6 +1005,16 @@ function CreateGameSurface() 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.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) surface.set_tiles({{name = "out-of-map",position = {1,1}}}) diff --git a/locale/rso/drand.lua b/locale/rso/drand.lua new file mode 100644 index 0000000..d907c57 --- /dev/null +++ b/locale/rso/drand.lua @@ -0,0 +1,269 @@ +--[[------------------------------------ +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 \ No newline at end of file diff --git a/locale/rso/metaball.lua b/locale/rso/metaball.lua new file mode 100644 index 0000000..407111b --- /dev/null +++ b/locale/rso/metaball.lua @@ -0,0 +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 + +return _M \ No newline at end of file diff --git a/locale/rso/rso_config.lua b/locale/rso/rso_config.lua new file mode 100644 index 0000000..d0852e9 --- /dev/null +++ b/locale/rso/rso_config.lua @@ -0,0 +1,55 @@ +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 diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua new file mode 100644 index 0000000..54df649 --- /dev/null +++ b/locale/rso/rso_control.lua @@ -0,0 +1,1408 @@ +require("config") +require("util") + +require("locale/rso/rso_config") +require("locale/rso/rso_resource_config") +require("locale/oarc_utils") + +local MB=require("locale/rso/metaball") + +local drand = require("locale/rso/drand") +local rng = drand.mwvc +if not deterministic then rng = drand.sys_rand end + +-- math shortcuts +local floor = math.floor +local abs = math.abs +local cos = math.cos +local sin = math.sin +local pi = math.pi +local max = math.max + +local function round(value) + return math.floor(value + 0.5) +end + +local function debug(str) + if debug_enabled then + game.players[1].print(str) + end +end + +-- constants +local CHUNK_SIZE = 32 +local REGION_TILE_SIZE = CHUNK_SIZE*region_size +local MIN_BALL_DISTANCE = CHUNK_SIZE/6 +local P_BALL_SIZE_FACTOR = 0.7 +local N_BALL_SIZE_FACTOR = 0.95 +local NEGATIVE_MODIFICATOR = 123456 + +local meta_shapes = nil + +if use_donut_shapes then + meta_shapes = {MB.MetaEllipse, MB.MetaSquare, MB.MetaDonut} +else + meta_shapes = {MB.MetaEllipse, MB.MetaSquare} +end + +-- local globals +local index_is_built = false +local max_allotment = 0 +local rgen = nil +local distance = util.distance +local spawner_probability_edge = 0 -- below this value a biter spawner, above/equal this value a spitter spawner +local invalidResources = {} +local config = nil +local configIndexed = nil + +-- map gen settings mapping + +local startingAreaMultiplier = +{ + none = 0, + ["very-low"] = 0.25, + low = 0.5, + normal = 1, + high = 1.5, + ["very-high"] = 2, +} + +local frequencyAllotmentMultiplier = +{ + ["very-low"] = 0.5, + low = 0.75, + normal = 1, + high = 1.5, + ["very-high"] = 2, +} + +local sizeMultiplier = +{ + none = 0, + ["very-low"] = 0.5, + low = 0.75, + normal = 1, + high = 1.25, + ["very-high"] = 1.5, +} + +local richnessMultiplier = +{ + ["very-low"] = 0.125, + low = 0.25, + normal = 1, + high = 2, + ["very-high"] = 4, +} + +local entityFrequencyMultiplier = +{ + ["very-low"] = 0.25, + low = 0.5, + normal = 1, + high = 2, + ["very-high"] = 4, +} + +local entitySizeMultiplier = +{ + none = 0, + ["very-low"] = 0.5, + low = 0.75, + normal = 1, + high = 2, + ["very-high"] = 4, +} + +--[[ HELPER METHODS ]]-- + +local function normalize(n) --keep numbers at (positive) 32 bits + return floor(n) % 0x80000000 +end + +local function bearing(origin, dest) + -- finds relative angle + local xd = dest.x - origin.x + local yd = dest.y - origin.y + return math.atan2(xd, yd); +end + +local function str2num(s) + local num = 0 + for i=1,s:len() do + num=num + (s:byte(i) - 33)*i + end + return num +end + +local function mult_for_pos(pos) + local num = 0 + local x = pos.x + local y = pos.y + + if x == 0 then x = 0.5 end + if y == 0 then y = 0.5 end + if x < 0 then + x = abs(x) + NEGATIVE_MODIFICATOR + end + if y < 0 then + y = abs(y) + NEGATIVE_MODIFICATOR + end + + return drand.lcg(y, 'mvc'):random(0)*drand.lcg(x, 'nr'):random(0) +end + +local function rng_for_reg_pos(pos) + local rgen = rng(normalize(global.seed*mult_for_pos(pos))) + rgen:random() + rgen:random() + rgen:random() + return rgen +end + +local function rng_restricted_angle(restrictions) + local rng = rgen:random() + local x_scale, y_scale + local deformX = rgen:random() * 2 - 1 + local deformY = rgen:random() * 2 - 1 + + if restrictions=='xy' then + y_scale=1.0 + deformY*0.5 + x_scale=1.0 + deformX*0.5 + angle = rng*pi*2 + elseif restrictions=='x' then + y_scale=1.0 + deformY*0.6 + x_scale=1.0 + deformX*0.6 + angle = rng*pi/2 - pi/4 + elseif restrictions=='y' then + y_scale=1.0 + deformY*0.6 + x_scale=1.0 + deformX*0.6 + angle = rng*pi/2 + pi/2 + else + y_scale=1.0 + deformY*0.3 + x_scale=1.0 + deformX*0.3 + angle = rng*pi*2 + end + + return angle, x_scale, y_scale +end + +local function vary_by_percentage(x, p) + return x + (0.5 - rgen:random())*2*x*p +end + + +local function remove_trees(surface, x, y, x_size, y_size ) + local bb={{x - x_size, y - y_size}, {x + x_size, y + y_size}} + for _, entity in pairs(surface.find_entities_filtered{area = bb, type="tree"}) do + if entity.valid then + entity.destroy() + end + end +end + +local function removeDecorations(surface, x, y, width, height ) + local bb={{x, y}, {x + width, y + height}} + for _, entity in pairs(surface.find_entities_filtered{area = bb, type="decorative"}) do + if entity.valid then + entity.destroy() + end + end +end + +local function find_intersection(surface, x, y) + -- try to get position in between of valid chunks by probing map + -- this may breaks determinism of generation, but so far it returned on first if + local gt = surface.get_tile + local restriction = '' + if gt(x + CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid then + restriction = 'xy' + elseif gt(x + CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y).valid and gt(x, y + CHUNK_SIZE*2).valid then + x=x + CHUNK_SIZE/2 + y=y + CHUNK_SIZE/2 + restriction = 'xy' + elseif gt(x + CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y).valid and gt(x, y - CHUNK_SIZE*2).valid then + x=x + CHUNK_SIZE/2 + y=y - CHUNK_SIZE/2 + restriction = 'xy' + elseif gt(x - CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y).valid and gt(x, y + CHUNK_SIZE*2).valid then + x=x - CHUNK_SIZE/2 + y=y + CHUNK_SIZE/2 + restriction = 'xy' + elseif gt(x - CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y).valid and gt(x, y - CHUNK_SIZE*2).valid then + x=x - CHUNK_SIZE/2 + y=y - CHUNK_SIZE/2 + restriction = 'xy' + elseif gt(x + CHUNK_SIZE*2, y).valid then + x=x + CHUNK_SIZE/2 + restriction = 'x' + elseif gt(x - CHUNK_SIZE*2, y).valid then + x=x - CHUNK_SIZE/2 + restriction = 'x' + elseif gt(x, y + CHUNK_SIZE*2).valid then + y=y + CHUNK_SIZE/2 + restriction = 'y' + elseif gt(x, y - CHUNK_SIZE*2).valid then + y=y - CHUNK_SIZE/2 + restriction = 'y' + end + return x, y, restriction +end + +local function find_random_chunk(r_x, r_y) + local offset_x=rgen:random(region_size)-1 + local offset_y=rgen:random(region_size)-1 + local c_x=r_x*REGION_TILE_SIZE + offset_x*CHUNK_SIZE + local c_y=r_y*REGION_TILE_SIZE + offset_y*CHUNK_SIZE + return c_x, c_y +end + +local function is_same_region(c_x1, c_y1, c_x2, c_y2) + if not floor(c_x1/REGION_TILE_SIZE) == floor(c_x2/REGION_TILE_SIZE) then + return false + end + if not floor(c_y1/REGION_TILE_SIZE) == floor(c_y2/REGION_TILE_SIZE) then + return false + end + return true +end + +local function find_random_neighbour_chunk(ocx, ocy) + -- somewhat bruteforce and unoptimized + local x_dir = rgen:random(-1,1) + local y_dir = rgen:random(-1,1) + local ncx = ocx + x_dir*CHUNK_SIZE + local ncy = ocy + y_dir*CHUNK_SIZE + if is_same_region(ncx, ncy, ocx, ocy) then + return ncx, ncy + end + + ncx = ocx - x_dir*CHUNK_SIZE + ncy = ocy - y_dir*CHUNK_SIZE + if is_same_region(ncx, ncy, ocx, ocy) then + return ncx, ncy + end + + ncx = ocx - x_dir*CHUNK_SIZE + if is_same_region(ncx, ocy, ocx, ocy) then + return ncx, ocy + end + + ncy = ocy - y_dir*CHUNK_SIZE + if is_same_region(ocx, ncy, ocx, ocy) then + return ocx, ncy + end + + return ocx, ocy +end + +local function isInStartingArea( regionX, regionY ) + + for idx, pos in pairs( global.startingAreas ) do + + local adjustedX = regionX - pos.x / REGION_TILE_SIZE + local adjustedY = regionY - pos.y / REGION_TILE_SIZE + if ((adjustedX * adjustedX + adjustedY * adjustedY) <= starting_area_size * starting_area_size) then + return true + end + end + + return false +end + +-- OARC SPECIFIC FUNCTION -- +-- Checks if a point is near a spawn area +local function isNearOarcSpawn(pointPos) + + if (global.uniqueSpawns) and (ENFORCE_LAND_AREA_TILE_DIST) then + for name,spawn in pairs(global.uniqueSpawns) do + local clearArea = GetAreaFromPointAndDistance(spawn.pos, + (ENFORCE_LAND_AREA_TILE_DIST+2*CHUNK_SIZE)) + if (CheckIfInArea(pointPos,clearArea)) then + return true + end + end + end + + return false +end + +-- modifies the resource size - only used in endless_resource_mode +local function modify_resource_size(resourceName, resourceSize, startingArea) + + if not startingArea then + resourceSize = math.ceil(resourceSize * global_size_mult) + end + + resourceEntity = game.entity_prototypes[resourceName] + if resourceEntity and resourceEntity.infinite_resource then + + newResourceSize = resourceSize * endless_resource_mode_sizeModifier + + -- make sure it's still an integer + newResourceSize = math.ceil(newResourceSize) + -- make sure it's not 0 + if newResourceSize == 0 then newResourceSize = 1 end + return newResourceSize + else + return resourceSize + end +end + +--[[ SPAWN METHODS ]]-- + +local locationOrder = +{ + { x = 0, y = 0 }, + { x = -1, y = 0 }, + { x = 1, y = 0 }, + { x = 0, y = -1 }, + { x = 0, y = 1 }, + { x = -1, y = -1 }, + { x = 1, y = -1 }, + { x = -1, y = 1 }, + { x = 1, y = 1 } +} + +--[[ entity-field ]]-- +local function spawn_resource_ore(surface, rname, pos, size, richness, startingArea, restrictions) + -- blob generator, centered at pos, size controls blob diameter + restrictions = restrictions or '' + debug("Entering spawn_resource_ore "..rname.." at:"..pos.x..","..pos.y.." size:"..size.." richness:"..richness.." isStart:"..tostring(startingArea).." restrictions:"..restrictions) + + size = modify_resource_size(rname, size, startingArea) + local radius = size / 2 -- to radius + + local p_balls={} + local n_balls={} + local MIN_BALL_DISTANCE = math.min(MIN_BALL_DISTANCE, radius/2) + + local maxPradius = 0 + local outside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } + local inside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } + + local function adjustRadius(radius, scaleX, scaleY, up) + return radius + end + + local function updateRect(rect, x, y, radius) + rect.xmin = math.min(rect.xmin, x - radius) + rect.xmax = math.max(rect.xmax, x + radius) + rect.ymin = math.min(rect.ymin, y - radius) + rect.ymax = math.max(rect.ymax, y + radius) + end + + local function updateRects(x, y, radius, scaleX, scaleY) + local adjustedRadius = adjustRadius(radius, scaleX, scaleY, true) + local radiusMax = adjustedRadius * 3 -- arbitrary multiplier - needs to be big enough to not cut any metaballs + updateRect(outside, x, y, radiusMax) + updateRect(inside, x, y, adjustedRadius) + end + + local function generate_p_ball() + local angle, x_scale, y_scale, x, y, b_radius, shape + angle, x_scale, y_scale=rng_restricted_angle(restrictions) + local dev = radius / 2 + rgen:random() * radius / 4--math.min(CHUNK_SIZE/3, radius*1.5) + local dev_x, dev_y = pos.x, pos.y + x = rgen:random(-dev, dev)+dev_x + y = rgen:random(-dev, dev)+dev_y + if p_balls[#p_balls] and distance(p_balls[#p_balls], {x=x, y=y}) < MIN_BALL_DISTANCE then + local new_angle = bearing(p_balls[#p_balls], {x=x, y=y}) + debug("Move ball old xy @ "..x..","..y) + x=(cos(new_angle)*MIN_BALL_DISTANCE) + x + y=(sin(new_angle)*MIN_BALL_DISTANCE) + y + debug("Move ball new xy @ "..x..","..y) + end + + if #p_balls == 0 then + b_radius = ( 3 * radius / 4 + rgen:random() * radius / 4) -- * (P_BALL_SIZE_FACTOR^#p_balls) + else + b_radius = ( radius / 4 + rgen:random() * radius / 2) -- * (P_BALL_SIZE_FACTOR^#p_balls) + end + + + if #p_balls > 0 then + local tempRect = table.deepcopy(inside) + updateRect(tempRect, x, y, adjustRadius(b_radius, x_scale, y_scale)) + local rectSize = math.max(tempRect.xmax - tempRect.xmin, tempRect.ymax - tempRect.ymin) + local targetSize = size * 1.25 + debug("Rect size "..rectSize.." targetSize "..targetSize) + if rectSize > targetSize then + local widthLeft = (targetSize - (inside.xmax - inside.xmin)) + local heightLeft = (targetSize - (inside.ymax - inside.ymin)) + local widthMod = math.min(x - inside.xmin, inside.xmax - x) + local heightMod = math.min(y - inside.ymin, inside.ymax - y) + local radiusBackup = b_radius + b_radius = math.min(widthLeft + widthMod, heightLeft + heightMod) + b_radius = adjustRadius(b_radius, x_scale, y_scale, false) + debug("Reduced ball radius from "..radiusBackup.." to "..b_radius.." widthLeft:"..widthLeft.." heightLeft:"..heightLeft.." widthMod:"..widthMod.." heightMod:"..heightMod) + end + end + + if b_radius < 2 and #p_balls == 0 then + b_radius = 2 + end + + if b_radius > 0 then + + maxPradius = math.max(maxPradius, b_radius) + shape = meta_shapes[rgen:random(1,#meta_shapes)] + local radiusText = "" + if shape.type == "MetaDonut" then + local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() + radiusText = " inRadius:"..inRadius + p_balls[#p_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.1) + else + p_balls[#p_balls+1] = shape:new(x, y, b_radius, angle, x_scale, y_scale, 1.1) + end + updateRects(x, y, b_radius, x_scale, y_scale) + + debug("P+Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) + end + end + + local function generate_n_ball(i) + local angle, x_scale, y_scale, x, y, b_radius, shape + angle, x_scale, y_scale=rng_restricted_angle('xy') + if p_balls[i] then + local new_angle = p_balls[i].angle + pi*rgen:random(0,1) + (rgen:random()-0.5)*pi/2 + local dist = p_balls[i].radius + x=(cos(new_angle)*dist) + p_balls[i].x + y=(sin(new_angle)*dist) + p_balls[i].y + angle = p_balls[i].angle + pi/2 + (rgen:random()-0.5)*pi*2/3 + else + x = rgen:random(-radius, radius)+pos.x + y = rgen:random(-radius, radius)+pos.y + end + + if p_balls[i] then + b_radius = (p_balls[i].radius / 4 + rgen:random() * p_balls[i].radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) + else + b_radius = (radius / 4 + rgen:random() * radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) + end + + if b_radius < 1 then + b_radius = 1 + end + + shape = meta_shapes[rgen:random(1,#meta_shapes)] + local radiusText = "" + if shape.type == "MetaDonut" then + local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() + radiusText = " inRadius:"..inRadius + n_balls[#n_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.15) + else + n_balls[#n_balls+1] = shape:new(x, y, b_radius, angle, x_scale, y_scale, 1.15) + end + -- updateRects(x, y, b_radius, x_scale, y_scale) -- should not be needed here - only positive ball can generate ore + debug("N-Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) + end + + local function calculate_force(x,y) + local p_force = 0 + local n_force = 0 + for _,ball in ipairs(p_balls) do + p_force = p_force + ball:force(x,y) + end + for _,ball in ipairs(n_balls) do + n_force = n_force + ball:force(x,y) + end + local totalForce = 0 + if p_force > n_force then + totalForce = 1 - 1/(p_force - n_force) + end + --debug("Force at "..x..","..y.." p:"..p_force.." n:"..n_force.." result:"..totalForce) + --return (1 - 1/p_force) - n_force + return totalForce + end + + local max_p_balls = 2 + local min_amount = config[rname].min_amount or min_amount + if restrictions == 'xy' then + max_p_balls = 3 + end + + radius = math.min(radius, 2*CHUNK_SIZE) + + local force + -- generate blobs + for i=1,max_p_balls do + generate_p_ball() + end + + for i=1,rgen:random(1, #p_balls) do + generate_n_ball(i) + end + + + local _total = 0 + local oreLocations = {} + local forceTotal = 0 + + -- fill the map + for y=outside.ymin, outside.ymax do + + for x=outside.xmin, outside.xmax do + force = calculate_force(x, y) + if force > 0 then + oreLocations[#oreLocations + 1] = {x = x, y = y, force = force, valid = false} + forceTotal = forceTotal + force + end + end + end + + local validCount, resOffsetX, resOffsetY, ratio + + for _,locationOffset in ipairs(locationOrder) do + validCount = 0 + resOffsetX = locationOffset.x * CHUNK_SIZE + resOffsetY = locationOffset.y * CHUNK_SIZE + + for _, location in ipairs(oreLocations) do + + local newX = location.x + resOffsetX + local newY = location.y + resOffsetY + location.valid = false + if surface.can_place_entity{name = rname, position = {x = newX,y = newY}} then + location.valid = true + validCount = validCount + 1 + end + end + + ratio = 0 + + if validCount > 0 then + ratio = validCount / #oreLocations + end + + debug("Valid ratio ".. ratio) + + if not useResourceCollisionDetection then + break + end + + if ratio > resourceCollisionDetectionRatio then + break + elseif resourceCollisionFieldSkip then -- in case no valid ratio was found we skip the field completely + validCount = 0 + end + end + + if validCount > 0 then + local rectSize = ((inside.xmax - inside.xmin) + (inside.ymax - inside.ymin)) / 2 + + local sizeMultiplier = rectSize ^ 0.6 + local minSize = richness * 5 * sizeMultiplier + local maxSize = richness * 10 * sizeMultiplier + local approxDepositSize = rgen:random(minSize, maxSize) + + approxDepositSize = approxDepositSize - validCount * min_amount + + if approxDepositSize < 0 then + approxDepositSize = 100 * validCount + end + + local forceFactor = approxDepositSize / forceTotal + + -- don't create very dense resources in starting area - another field will be generated + if startingArea and forceFactor > 4000 then + forceFactor = rgen:random(3000, 4000) + end + + debug( "Force total:"..forceTotal.." sizeMin:"..minSize.." sizeMax:"..maxSize.." factor:"..forceFactor.." location#:"..validCount.." rectSize:"..rectSize.." sizeMultiplier:"..sizeMultiplier) + local richnessMultiplier = global_richness_mult + + if startingArea then + richnessMultiplier = starting_richness_mult + end + + -- infinite ore handling for Angels Ores mod + local infiniteOrePresent = false + local infiniteOreName = "infinite-"..rname + local minimumInfiniteOreAmount = nil + local spawnName = rname + + if game.entity_prototypes[infiniteOreName] then + infiniteOrePresent = true + minimumInfiniteOreAmount = game.entity_prototypes[infiniteOreName].minimum_resource_amount + end + + if startingArea and not infiniteResourceInStartArea then + infiniteOrePresent = false + end + + for _,location in ipairs(oreLocations) do + if location.valid then + + local amount = floor(( forceFactor * location.force + min_amount ) * richnessMultiplier) + + if amount > 1e9 then + amount = 1e9 + end + + _total = _total + amount + + spawnName = rname + if infiniteOrePresent and location.force > infiniteResourceSpawnThreshold then + spawnName = infiniteOreName + if minimumInfiniteOreAmount and amount < minimumInfiniteOreAmount then + amount = minimumInfiniteOreAmount + end + end + + if amount > 0 then + surface.create_entity{name = spawnName, + position = {location.x + resOffsetX,location.y + resOffsetY}, + force = game.forces.neutral, + amount = amount} + end + end + end + + end + + if debug_enabled then + debug("Total amount: ".._total) + debug("Leaving spawn_resource_ore") + end + return _total +end + +--[[ entity-liquid ]]-- +local function spawn_resource_liquid(surface, rname, pos, size, richness, startingArea, restrictions) + restrictions = restrictions or '' + debug("Entering spawn_resource_liquid "..rname.." "..pos.x..","..pos.y.." "..size.." "..richness.." "..tostring(startingArea).." "..restrictions) + local _total = 0 + local max_radius = rgen:random()*CHUNK_SIZE/2 + CHUNK_SIZE + + richness = ( 0.75 + rgen:random() / 2 ) * richness * size + + resourceEntity = game.entity_prototypes[rname] + + + local total_share = 0 + local avg_share = 1/size + local angle = rgen:random()*pi*2 + local saved = 0 + while total_share < 1 do + local new_share = vary_by_percentage(avg_share, 0.25) + if new_share + total_share > 1 then + new_share = 1 - total_share + end + total_share = new_share + total_share + if new_share < avg_share/10 then + -- too small + break + end + local amount = floor(richness*new_share) + saved + + local richnessMultiplier = global_richness_mult + + if startingArea then + richnessMultiplier = starting_richness_mult + end + + --if amount >= game.entity_prototypes[rname].minimum then + if amount >= config[rname].minimum_amount then + saved = 0 + for try=1,5 do + local dist = rgen:random()*(max_radius - max_radius*0.1) + angle = angle + pi/4 + rgen:random()*pi/2 + local x, y = pos.x + cos(angle)*dist, pos.y + sin(angle)*dist + if surface.can_place_entity{name = rname, position = {x,y}} then + debug("@ "..x..","..y.." amount: "..amount.." new_share: "..new_share.." try: "..try) + amount = floor(amount * richnessMultiplier) + + if amount > 1e9 then + amount = 1e9 + end + + _total = _total + amount + + if amount > 0 then + surface.create_entity{name = rname, + position = {x,y}, + force = game.forces.neutral, + amount = amount, + direction = rgen:random(4)} + end + break + elseif not startingArea then -- we don't want to make ultra rich nodes in starting area - failing to make them will add second spawn in different location + entities = surface.find_entities_filtered{area = {{x-2.75, y-2.75}, {x+2.75, y+2.75}}, name=rname} + if entities and #entities > 0 then + _total = _total + amount + for k, ent in pairs(entities) do + ent.amount = ent.amount + floor(amount/#entities) + end + break + end + end + end + else + saved = amount + end + end + debug("Total amount: ".._total) + debug("Leaving spawn_resource_liquid") + return _total +end + +local spawnerTable = nil + +local function initSpawnerTable() + if spawnerTable == nil then + spawnerTable = {} + spawnerTable["biter-spawner"] = game.entity_prototypes["biter-spawner"] ~= nil + spawnerTable["bob-biter-spawner"] = game.entity_prototypes["bob-biter-spawner"] ~= nil + spawnerTable["spitter-spawner"] = game.entity_prototypes["spitter-spawner"] ~= nil + spawnerTable["bob-spitter-spawner"] = game.entity_prototypes["bob-spitter-spawner"] ~= nil + end +end + +local function spawn_entity(surface, ent, r_config, x, y) + if not use_RSO_biter_spawning then return end + local size=rgen:random(r_config.size.min, r_config.size.max) + + local _total = 0 + local r_distance = distance({x=0,y=0},{x=x/REGION_TILE_SIZE,y=y/REGION_TILE_SIZE}) + + local distanceMultiplier = math.min(r_distance^r_config.size_per_region_factor, 5) + if r_config.size_per_region_factor then + size = size*distanceMultiplier + end + + size = size * enemy_base_size_multiplier + + debug("Entering spawn_entity "..ent.." "..x..","..y.." "..size) + + local maxAttemptCount = 5 + local distancePerAttempt = 0.2 + + initSpawnerTable() + + for i=1,size do + for attempt = 1, maxAttemptCount do + local richness=r_config.richness*(r_distance^richness_distance_factor) + local max_d = floor(CHUNK_SIZE*(0.5 + distancePerAttempt*attempt)) + local s_x = x + rgen:random(0, floor(max_d - r_config.clear_range[1])) - max_d/2 + r_config.clear_range[1] + local s_y = y + rgen:random(0, floor(max_d - r_config.clear_range[2])) - max_d/2 + r_config.clear_range[2] + + if surface.get_tile(s_x, s_y).valid then + + remove_trees(surface, s_x, s_y, r_config.clear_range[1], r_config.clear_range[2]) + + local spawnerName = nil + + if spawner_probability_edge > 0 then + + bigSpawnerChance = rgen:random() + + if rgen:random() < spawner_probability_edge then + if ( useBobEntity and bigSpawnerChance > 0.75 ) then + spawnerName = "bob-biter-spawner" + else + spawnerName = "biter-spawner" + end + else + if ( useBobEntity and bigSpawnerChance > 0.75 ) then + spawnerName = "bob-spitter-spawner" + else + spawnerName = "spitter-spawner" + end + end + end + + if spawnerName and spawnerTable[spawnerName] then + if surface.can_place_entity{name=spawnerName, position={s_x, s_y}} then + _total = _total + richness + debug(spawnerName.." @ "..s_x..","..s_y.." placed on "..attempt.." attempt") + + surface.create_entity{name=spawnerName, position={s_x, s_y}, force=game.forces[r_config.force], amount=floor(richness)}--, direction=rgen:random(4) + -- else + -- debug("Entity "..spawnerName.." spawn failed") + break; + else + if attempt == maxAttemptCount then + debug(spawnerName.." @ "..s_x..","..s_y.." failed to spawn") + end + end + else + debug("Entity "..spawnerName.." doesn't exist") + end + end + end + + if r_config.sub_spawn_probability then + local sub_spawn_prob = r_config.sub_spawn_probability*math.min(r_config.sub_spawn_max_distance_factor, r_config.sub_spawn_distance_factor^r_distance) + if rgen:random() < sub_spawn_prob then + for i=1,(rgen:random(r_config.sub_spawn_size.min, r_config.sub_spawn_size.max)*distanceMultiplier) do + local allotment_max = 0 + -- build table + for k,v in pairs(r_config.sub_spawns) do + if not v.min_distance or r_distance > v.min_distance then + local allotment = v.allotment + if v.allotment_distance_factor then + allotment = allotment * (v.allotment_distance_factor^r_distance) + end + v.allotment_range ={min = allotment_max, max = allotment_max + allotment} + allotment_max = allotment_max + allotment + else + v.allotment_range = nil + end + end + local sub_type = rgen:random(0, allotment_max) + for sub_spawn,v in pairs(r_config.sub_spawns) do + if v.allotment_range and sub_type >= v.allotment_range.min and sub_type <= v.allotment_range.max then + for attempt = 1, maxAttemptCount do + local max_d = floor(CHUNK_SIZE*distancePerAttempt*attempt) + s_x = x + rgen:random(max_d) - max_d/2 + s_y = y + rgen:random(max_d) - max_d/2 + remove_trees(surface, s_x, s_y, v.clear_range[1], v.clear_range[2]) + if surface.can_place_entity{name=sub_spawn, position={s_x, s_y}} then + surface.create_entity{name=sub_spawn, position={s_x, s_y}, force=game.forces[r_config.force]}--, direction=rgen:random(4) + debug("Rolled subspawn "..sub_spawn.." @ "..s_x..","..s_x.." after "..attempt.." attempts") + break; + else + if attempt == maxAttemptCount then + debug("Rolling subspawn "..sub_spawn.." @ "..s_x..","..s_x.." failed") + end + end + end + break + end + end + end + end + end + end + debug("Total amount: ".._total) + debug("Leaving spawn_entity") +end + +--[[ EVENT/INIT METHODS ]]-- + +local function spawn_starting_resources( surface, index ) + + if global.startingAreas[index].spawned then return end + if surface.map_gen_settings.starting_area == "none" and not ignoreMapGenSettings then return end -- starting area disabled by map gen + if starting_area_size < 0.1 then return end -- skip spawning if starting area is to small + + local position = global.startingAreas[index] + + rgen = rng_for_reg_pos( position ) + local status = true + for index,v in ipairs(configIndexed) do + if v.starting then + local prob = rgen:random() -- probability that this resource is spawned + debug("starting resource probability rolled "..prob) + if v.starting.probability > 0 and prob <= v.starting.probability then + local total = 0 + local radius = 25 + local min_threshold = 0 + + if v.type == "resource-ore" then + min_threshold = v.starting.richness * rgen:random(5, 10) -- lets make sure that there is at least 10-15 times starting richness ore at start + elseif v.type == "resource-liquid" then + min_threshold = v.starting.richness * 0.5 * v.starting.size + end + + while (radius < 200) and (total < min_threshold) do + local angle = rgen:random() * pi * 2 + local dist = rgen:random() * 30 + radius * 2 + local pos = { x = floor(cos(angle) * dist) + position.x, y = floor(sin(angle) * dist) + position.y } + if v.type == "resource-ore" then + total = total + spawn_resource_ore(surface, v.name, pos, v.starting.size, v.starting.richness, true) + elseif v.type == "resource-liquid" then + total = total + spawn_resource_liquid(surface, v.name, pos, v.starting.size, v.starting.richness, true) + end + radius = radius + 10 + end + if total < min_threshold then + status = false + end + end + end + end + + global.startingAreas[index].spawned = true +end + +local function modifyMinMax(value, mod) + value.min = round( value.min * mod ) + value.max = round( value.max * mod ) +end + +local function prebuild_config_data(surface) + if index_is_built then return false end + + local mapGenSettings = nil + + if not ignoreMapGenSettings then + mapGenSettings = surface.map_gen_settings + end + local autoPlaceSettings = nil + if mapGenSettings then + autoPlaceSettings = mapGenSettings.autoplace_controls + end + + configIndexed = {} + -- build additional indexed array to the associative array + for res_name, res_conf in pairs(config) do + if res_conf.valid then -- only add valid resources + res_conf.name = res_name + + local settingsForResource = nil + local isEntity = (res_conf.type == "entity") + local addResource = true + + local autoplaceName = res_name + + if res_conf.autoplace_name then + autoplaceName = res_conf.autoplace_name + end + + if autoPlaceSettings then + settingsForResource = autoPlaceSettings[autoplaceName] + end + + if settingsForResource then + local allotmentMod = nil + local sizeMod = nil + if isEntity then + allotmentMod = entityFrequencyMultiplier[settingsForResource.frequency] + sizeMod = entitySizeMultiplier[settingsForResource.size] + else + allotmentMod =frequencyAllotmentMultiplier[settingsForResource.frequency] + sizeMod = sizeMultiplier[settingsForResource.size] + end + + local richnessMod = richnessMultiplier[settingsForResource.richness] + + + debug(res_name .. " allotment mod " .. allotmentMod .. " size mod " .. sizeMod .. " richness mod " .. richnessMod ) + + + if allotmentMod then + if isEntity then + res_conf.absolute_probability = res_conf.absolute_probability * allotmentMod + debug("Entity chance modified to "..res_conf.absolute_probability) + else + res_conf.allotment = round( res_conf.allotment * allotmentMod ) + end + end + + if sizeMod ~= nil and sizeMod == 0 then + addResource = false + end + + if sizeMod then + modifyMinMax(res_conf.size, sizeMod) + + if res_conf.starting then + res_conf.starting.size = round( res_conf.starting.size * sizeMod ) + end + + if isEntity then + if res_conf.sub_spawn_size then + modifyMinMax(res_conf.sub_spawn_size, sizeMod) + end + modifyMinMax(res_conf.spawns_per_region, sizeMod) + end + end + + if richnessMod then + if type == "resource-ore" then + res_conf.richness = round( res_conf.richness * richnessMod ) + elseif type == "resource-liquid" then + modifyMinMax(res_conf.richness, richnessMod) + end + + if res_conf.starting then + res_conf.starting.richness = round( res_conf.starting.richness * richnessMod ) + end + end + end + + if addResource then + configIndexed[#configIndexed + 1] = res_conf + if res_conf.multi_resource and multi_resource_active then + local new_list = {} + for sub_res_name, allotment in pairs(res_conf.multi_resource) do + if config[sub_res_name] and config[sub_res_name].valid then + new_list[#new_list+1] = {name = sub_res_name, allotment = allotment} + end + end + table.sort(new_list, function(a, b) return a.name < b.name end) + res_conf.multi_resource = new_list + else + res_conf.multi_resource_chance = nil + end + end + end + end + + table.sort(configIndexed, function(a, b) return a.name < b.name end) + + local pr=0 + for index,v in pairs(config) do + if v.along_resource_probability then + v.along_resource_probability_range={min=pr, max=pr+v.along_resource_probability} + pr=pr+v.along_resource_probability + end + if v.allotment and v.allotment > 0 then + v.allotment_range={min=max_allotment, max=max_allotment+v.allotment} + max_allotment=max_allotment+v.allotment + end + end + + if mapGenSettings and mapGenSettings.starting_area then + local multiplier = startingAreaMultiplier[mapGenSettings.starting_area] + if multiplier ~= nil then + starting_area_size = starting_area_size * multiplier + debug("Starting area "..starting_area_size) + end + end + + index_is_built = true +end + +-- set up the probabilty segments from which to roll between for biter and spitter spawners +local function calculate_spawner_ratio() + if (biter_ratio_segment ~= 0 and spitter_ratio_segment ~= 0) and biter_ratio_segment >= 0 and spitter_ratio_segment >= 0 then + spawner_probability_edge=biter_ratio_segment/(biter_ratio_segment+spitter_ratio_segment) -- normalize to between 0 and 1 + end +end + +local function checkConfigForInvalidResources() + --make sure that every resource in the config is actually available. + --call this function, before the auxiliary config is prebuilt! + if index_is_built then return end + + local prototypes = game.entity_prototypes + + for resourceName, resourceConfig in pairs(config) do + if prototypes[resourceName] or resourceConfig.type == "entity" then + resourceConfig.valid = true + else + -- resource was in config, but it doesn't exist in game files anymore - mark it invalid + resourceConfig.valid = false + + table.insert(invalidResources, "Resource not available: " .. resourceName) + debug("Resource not available: " .. resourceName) + end + + if resourceConfig.valid and resourceConfig.type ~= "entity" then + if prototypes[resourceName].autoplace_specification == nil then + resourceConfig.valid = false + debug("Resource "..resourceName.." invalidated - autoplace not present") + end + end + end +end + +local function roll_region(c_x, c_y) + --in what region is this chunk? + local r_x=floor(c_x/REGION_TILE_SIZE) + local r_y=floor(c_y/REGION_TILE_SIZE) + local r_data = nil + + --don't spawn stuff in starting area + if isInStartingArea( c_x/REGION_TILE_SIZE, c_y/REGION_TILE_SIZE ) then + return false + end + + -- Reroll regions every region_size^2 chunk generation calls. + local regrow_rso = false + if (ENABLE_REGROWTH) then + if (global.chunk_regrow.rso_region_roll_counter > (region_size*region_size/2)) then + regrow_rso = true + global.chunk_regrow.rso_region_roll_counter = 0 + else + global.chunk_regrow.rso_region_roll_counter = global.chunk_regrow.rso_region_roll_counter + 1 + end + end + + --if this chunk is the first in its region to be generated + -- or we're hitting a lucky regrowth reroll... + if (not (global.regions[r_x] and global.regions[r_x][r_y]) or regrow_rso) then + + if not global.regions[r_x] then global.regions[r_x] = {} end + global.regions[r_x][r_y]={} + r_data = global.regions[r_x][r_y] + rgen = rng_for_reg_pos{x=r_x,y=r_y} + + local rollCount = math.ceil(#configIndexed / 10) - 1 -- 0 based counter is more convenient here + rollCount = math.min(rollCount, 3) + + for rollNumber = 0,rollCount do + + local resourceChance = absolute_resource_chance - rollNumber * 0.1 + --absolute chance to spawn resource + local abct = rgen:random() + debug("Rolling resource "..abct.." against "..resourceChance.." roll "..rollNumber) + if abct <= resourceChance then + local res_type=rgen:random(1, max_allotment) + for index,v in ipairs(configIndexed) do + if v.allotment_range and ((res_type >= v.allotment_range.min) and (res_type <= v.allotment_range.max)) then + debug("Rolled primary resource "..v.name.." with res_type="..res_type.." @ "..r_x..","..r_y) + local num_spawns=rgen:random(v.spawns_per_region.min, v.spawns_per_region.max) + local last_spawn_coords = {} + local along_ + for i=1,num_spawns do + local c_x, c_y = find_random_chunk(r_x, r_y) + if not r_data[c_x] then r_data[c_x] = {} end + if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end + local c_data = r_data[c_x][c_y] + c_data[#c_data+1]={v.name, rollNumber} + last_spawn_coords[#last_spawn_coords+1] = {c_x, c_y} + debug("Rolled primary chunk "..v.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) + -- Along resource spawn, only once + if i == 1 then + local am_roll = rgen:random() + for index,vv in ipairs(configIndexed) do + if vv.along_resource_probability_range and am_roll >= vv.along_resource_probability_range.min and am_roll <= vv.along_resource_probability_range.max then + c_data = r_data[c_x][c_y] + c_data[#c_data+1]={vv.name, rollNumber} + debug("Rolled along "..vv.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) + end + end + end + end + -- roll multiple resources in same region + local deep=0 + while v.multi_resource_chance and rgen:random() <= v.multi_resource_chance*(multi_resource_chance_diminish^deep) do + deep = deep + 1 + local max_allotment = 0 + for index,sub_res in pairs(v.multi_resource) do max_allotment=max_allotment+sub_res.allotment end + + local res_type=rgen:random(1, max_allotment) + local min=0 + for _, sub_res in pairs(v.multi_resource) do + if (res_type >= min) and (res_type <= sub_res.allotment + min) then + local last_coords = last_spawn_coords[rgen:random(1, #last_spawn_coords)] + local c_x, c_y = find_random_neighbour_chunk(last_coords[1], last_coords[2]) -- in same as primary resource chunk + if not r_data[c_x] then r_data[c_x] = {} end + if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end + local c_data = r_data[c_x][c_y] + c_data[#c_data+1]={sub_res.name, deep} + debug("Rolled multiple "..sub_res.name..":"..deep.." with res_type="..res_type.." @ "..c_x.."."..c_y.." reg: "..r_x.."."..r_y) + break + else + min = min + sub_res.allotment + end + end + end + break + end + end + + end + end + -- roll for absolute_probability - this rolls the enemies + + for index,v in ipairs(configIndexed) do + if v.absolute_probability then + local prob_factor = 1 + if v.probability_distance_factor then + prob_factor = math.min(v.max_probability_distance_factor, v.probability_distance_factor^distance({x=0,y=0},{x=r_x,y=r_y})) + end + local abs_roll = rgen:random() + if abs_roll 10 then + global.startingAreas[1].spawned = true + end + end + + calculate_spawner_ratio() + spawn_starting_resources(surface, 1 ) + + initDone = true + + if surface.map_gen_settings.autoplace_controls["iron-ore"].size ~= "none" then + game.players[1].print("RSO WARNING - VANILLA iron-ore GEN IS NOT DISABLED!") + end + if surface.map_gen_settings.autoplace_controls["copper-ore"].size ~= "none" then + game.players[1].print("RSO WARNING - VANILLA copper-ore GEN IS NOT DISABLED!") + end + if surface.map_gen_settings.autoplace_controls["uranium-ore"].size ~= "none" then + game.players[1].print("RSO WARNING - VANILLA uranium-ore GEN IS NOT DISABLED!") + end + if surface.map_gen_settings.autoplace_controls["crude-oil"].size ~= "none" then + game.players[1].print("RSO WARNING - VANILLA crude-oil GEN IS NOT DISABLED!") + end + if surface.map_gen_settings.autoplace_controls["enemy-base"].size ~= "none" then + game.players[1].print("RSO WARNING - VANILLA enemy-base GEN IS NOT DISABLED!") + end + if surface.map_gen_settings.autoplace_controls["stone"].size ~= "none" then + game.players[1].print("RSO WARNING - VANILLA stone GEN IS NOT DISABLED!") + end + if surface.map_gen_settings.autoplace_controls["coal"].size ~= "none" then + game.players[1].print("RSO WARNING - VANILLA coal GEN IS NOT DISABLED!") + end + end + +end + +function RSO_ChunkGenerated(event) + local c_x = event.area.left_top.x + local c_y = event.area.left_top.y + + RSO_init() + + roll_region(c_x, c_y) + roll_chunk(event.surface, c_x, c_y) +end \ No newline at end of file diff --git a/locale/rso/rso_resource_config.lua b/locale/rso/rso_resource_config.lua new file mode 100644 index 0000000..1b4d9fd --- /dev/null +++ b/locale/rso/rso_resource_config.lua @@ -0,0 +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 +end \ No newline at end of file From 6bd4f31cb6bce1215f02865924e93d7531830c90 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 16 Dec 2017 15:21:58 -0500 Subject: [PATCH 12/58] I have a working rso soft mod again! --- config.lua | 10 +- locale/rso/prototype_utils.lua | 49 ++ locale/rso/rso_config.lua | 12 +- locale/rso/rso_control.lua | 862 +++++++++++++++++------------ locale/rso/rso_resource_config.lua | 18 +- 5 files changed, 577 insertions(+), 374 deletions(-) create mode 100644 locale/rso/prototype_utils.lua diff --git a/config.lua b/config.lua index 626f435..288e182 100644 --- a/config.lua +++ b/config.lua @@ -325,7 +325,7 @@ CMD_LINE_MAP_GEN = true -- "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.water="none" global.clMapGen.starting_area="low" global.clMapGen.peaceful_mode=false global.clMapGen.seed=nil; @@ -338,11 +338,11 @@ global.clMapGen.autoplace_controls = { ["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= "normal", size= "normal", richness= "normal"}, - ["dirt"]={frequency= "normal", size= "normal", richness= "normal"}, + ["desert"]={frequency= "normal", size= "none", richness= "normal"}, + ["dirt"]={frequency= "normal", size= "none", richness= "normal"}, ["grass"]={frequency= "normal", size= "normal", richness= "normal"}, - ["sand"]={frequency= "normal", size= "normal", richness= "normal"}, - ["trees"]={frequency= "normal", size= "normal", richness= "normal"} + ["sand"]={frequency= "normal", size= "none", richness= "normal"}, + ["trees"]={frequency= "normal", size= "none", 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"} diff --git a/locale/rso/prototype_utils.lua b/locale/rso/prototype_utils.lua new file mode 100644 index 0000000..e4566a2 --- /dev/null +++ b/locale/rso/prototype_utils.lua @@ -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 diff --git a/locale/rso/rso_config.lua b/locale/rso/rso_config.lua index d0852e9..fa03e41 100644 --- a/locale/rso/rso_config.lua +++ b/locale/rso/rso_config.lua @@ -1,6 +1,6 @@ -debug_enabled = false +debug_enabled = true -region_size = 10 -- alternative mean to control how further away resources would be, default - 256 tiles or 8 chunks +region_size = 8 -- 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 @@ -37,7 +37,7 @@ endless_resource_mode_sizeModifier = 0.80 -- 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_RSO_biter_spawning = false -- 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 @@ -51,5 +51,9 @@ ignoreMapGenSettings = true -- stops the default behaviour of reading map gen se 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 +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 diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua index 54df649..54c5a78 100644 --- a/locale/rso/rso_control.lua +++ b/locale/rso/rso_control.lua @@ -7,10 +7,6 @@ require("locale/oarc_utils") local MB=require("locale/rso/metaball") -local drand = require("locale/rso/drand") -local rng = drand.mwvc -if not deterministic then rng = drand.sys_rand end - -- math shortcuts local floor = math.floor local abs = math.abs @@ -29,13 +25,16 @@ local function debug(str) end end +-- cached setting value +-- local region_size = settings.global["rso-region-size"].value + -- constants local CHUNK_SIZE = 32 local REGION_TILE_SIZE = CHUNK_SIZE*region_size local MIN_BALL_DISTANCE = CHUNK_SIZE/6 local P_BALL_SIZE_FACTOR = 0.7 local N_BALL_SIZE_FACTOR = 0.95 -local NEGATIVE_MODIFICATOR = 123456 +local NEGATIVE_MODIFICATOR = 32771 local meta_shapes = nil @@ -46,14 +45,8 @@ else end -- local globals -local index_is_built = false -local max_allotment = 0 -local rgen = nil local distance = util.distance -local spawner_probability_edge = 0 -- below this value a biter spawner, above/equal this value a spitter spawner local invalidResources = {} -local config = nil -local configIndexed = nil -- map gen settings mapping @@ -116,8 +109,8 @@ local entitySizeMultiplier = --[[ HELPER METHODS ]]-- -local function normalize(n) --keep numbers at (positive) 32 bits - return floor(n) % 0x80000000 +local function normalize(n) -- keep numbers at 32 bits + return floor(n) % 0xffffffff end local function bearing(origin, dest) @@ -135,75 +128,72 @@ local function str2num(s) return num end -local function mult_for_pos(pos) - local num = 0 +local function rng_for_reg_pos(pos) local x = pos.x local y = pos.y - if x == 0 then x = 0.5 end - if y == 0 then y = 0.5 end + local rng = game.create_random_generator() + if x < 0 then - x = abs(x) + NEGATIVE_MODIFICATOR + x = abs(x) * 111 end if y < 0 then - y = abs(y) + NEGATIVE_MODIFICATOR + y = abs(y) * 111 end + + rng.re_seed(normalize(x * 65536)) + local valX = rng(65536) + rng.re_seed(normalize(y * 32768)) + local valY = rng(65536) - return drand.lcg(y, 'mvc'):random(0)*drand.lcg(x, 'nr'):random(0) + local seed = normalize( valX * valY * global.seed ) + rng.re_seed( seed ) + + -- debug("Generator for " .. pos.x .. "," .. pos.y .. " created with seed " .. seed .. " x:" .. valX .. " y:" .. valY) + + return rng end -local function rng_for_reg_pos(pos) - local rgen = rng(normalize(global.seed*mult_for_pos(pos))) - rgen:random() - rgen:random() - rgen:random() - return rgen -end - -local function rng_restricted_angle(restrictions) - local rng = rgen:random() +local function rng_restricted_angle(restrictions, rng) + local value = rng() local x_scale, y_scale - local deformX = rgen:random() * 2 - 1 - local deformY = rgen:random() * 2 - 1 + local deformX = rng() * 2 - 1 + local deformY = rng() * 2 - 1 if restrictions=='xy' then y_scale=1.0 + deformY*0.5 x_scale=1.0 + deformX*0.5 - angle = rng*pi*2 + angle = value*pi*2 elseif restrictions=='x' then y_scale=1.0 + deformY*0.6 x_scale=1.0 + deformX*0.6 - angle = rng*pi/2 - pi/4 + angle = value*pi/2 - pi/4 elseif restrictions=='y' then y_scale=1.0 + deformY*0.6 x_scale=1.0 + deformX*0.6 - angle = rng*pi/2 + pi/2 + angle = value*pi/2 + pi/2 else y_scale=1.0 + deformY*0.3 x_scale=1.0 + deformX*0.3 - angle = rng*pi*2 + angle = value*pi*2 end return angle, x_scale, y_scale end -local function vary_by_percentage(x, p) - return x + (0.5 - rgen:random())*2*x*p +local function vary_by_percentage(x, p, rng) + return x + (0.5 - rng())*2*x*p end local function remove_trees(surface, x, y, x_size, y_size ) - local bb={{x - x_size, y - y_size}, {x + x_size, y + y_size}} + local bb = {{x - x_size, y - y_size}, {x + x_size, y + y_size}} for _, entity in pairs(surface.find_entities_filtered{area = bb, type="tree"}) do if entity.valid then entity.destroy() end end -end - -local function removeDecorations(surface, x, y, width, height ) - local bb={{x, y}, {x + width, y + height}} - for _, entity in pairs(surface.find_entities_filtered{area = bb, type="decorative"}) do + for _, entity in pairs(surface.find_entities_filtered{area = bb, type="simple-entity"}) do if entity.valid then entity.destroy() end @@ -249,64 +239,67 @@ local function find_intersection(surface, x, y) return x, y, restriction end -local function find_random_chunk(r_x, r_y) - local offset_x=rgen:random(region_size)-1 - local offset_y=rgen:random(region_size)-1 +local function find_random_chunk(r_x, r_y, rng) + local offset_x=rng(region_size) - 1 + local offset_y=rng(region_size) - 1 local c_x=r_x*REGION_TILE_SIZE + offset_x*CHUNK_SIZE local c_y=r_y*REGION_TILE_SIZE + offset_y*CHUNK_SIZE +-- log("Random chunk "..r_x..","..r_y.." coords "..c_x..","..c_y.." offset "..offset_x..","..offset_y) return c_x, c_y end local function is_same_region(c_x1, c_y1, c_x2, c_y2) - if not floor(c_x1/REGION_TILE_SIZE) == floor(c_x2/REGION_TILE_SIZE) then + if not (floor(c_x1/REGION_TILE_SIZE) == floor(c_x2/REGION_TILE_SIZE)) then return false end - if not floor(c_y1/REGION_TILE_SIZE) == floor(c_y2/REGION_TILE_SIZE) then + if not (floor(c_y1/REGION_TILE_SIZE) == floor(c_y2/REGION_TILE_SIZE)) then return false end return true end -local function find_random_neighbour_chunk(ocx, ocy) +local function find_random_neighbour_chunk(ocx, ocy, rng) -- somewhat bruteforce and unoptimized - local x_dir = rgen:random(-1,1) - local y_dir = rgen:random(-1,1) - local ncx = ocx + x_dir*CHUNK_SIZE - local ncy = ocy + y_dir*CHUNK_SIZE + local x_dir = rng(-2,2) + local y_dir = rng(-2,2) + + local ncx = ocx + x_dir * CHUNK_SIZE + local ncy = ocy + y_dir * CHUNK_SIZE if is_same_region(ncx, ncy, ocx, ocy) then return ncx, ncy end - ncx = ocx - x_dir*CHUNK_SIZE - ncy = ocy - y_dir*CHUNK_SIZE + ncx = ocx - x_dir * CHUNK_SIZE + ncy = ocy - y_dir * CHUNK_SIZE if is_same_region(ncx, ncy, ocx, ocy) then return ncx, ncy end - ncx = ocx - x_dir*CHUNK_SIZE - if is_same_region(ncx, ocy, ocx, ocy) then - return ncx, ocy + ncx = ocx - x_dir * CHUNK_SIZE + ncy = ocy + y_dir * CHUNK_SIZE + if is_same_region(ncx, ncy, ocx, ocy) then + return ncx, ncy end - ncy = ocy - y_dir*CHUNK_SIZE - if is_same_region(ocx, ncy, ocx, ocy) then - return ocx, ncy + ncx = ocx + x_dir * CHUNK_SIZE + ncy = ocy - y_dir * CHUNK_SIZE + if is_same_region(ncx, ncy, ocx, ocy) then + return ncx, ncy end return ocx, ocy end -local function isInStartingArea( regionX, regionY ) +local function isInStartingArea( tileX, tileY ) for idx, pos in pairs( global.startingAreas ) do - local adjustedX = regionX - pos.x / REGION_TILE_SIZE - local adjustedY = regionY - pos.y / REGION_TILE_SIZE - if ((adjustedX * adjustedX + adjustedY * adjustedY) <= starting_area_size * starting_area_size) then + local adjustedX = ( tileX - pos.x ) / REGION_TILE_SIZE + local adjustedY = ( tileY - pos.y ) / REGION_TILE_SIZE + if ((adjustedX * adjustedX + adjustedY * adjustedY) <= global.starting_area_size * global.starting_area_size) then return true end end - return false end @@ -365,10 +358,10 @@ local locationOrder = } --[[ entity-field ]]-- -local function spawn_resource_ore(surface, rname, pos, size, richness, startingArea, restrictions) +local function spawn_resource_ore(surface, rname, pos, size, richness, startingArea, restrictions, rng) -- blob generator, centered at pos, size controls blob diameter restrictions = restrictions or '' - debug("Entering spawn_resource_ore "..rname.." at:"..pos.x..","..pos.y.." size:"..size.." richness:"..richness.." isStart:"..tostring(startingArea).." restrictions:"..restrictions) + -- debug("Entering spawn_resource_ore "..rname.." at:"..pos.x..","..pos.y.." size:"..size.." richness:"..richness.." isStart:"..tostring(startingArea).." restrictions:"..restrictions) size = modify_resource_size(rname, size, startingArea) local radius = size / 2 -- to radius @@ -377,14 +370,10 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA local n_balls={} local MIN_BALL_DISTANCE = math.min(MIN_BALL_DISTANCE, radius/2) - local maxPradius = 0 + local maxPradius = 0 local outside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } local inside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } - local function adjustRadius(radius, scaleX, scaleY, up) - return radius - end - local function updateRect(rect, x, y, radius) rect.xmin = math.min(rect.xmin, x - radius) rect.xmax = math.max(rect.xmax, x + radius) @@ -393,40 +382,46 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA end local function updateRects(x, y, radius, scaleX, scaleY) - local adjustedRadius = adjustRadius(radius, scaleX, scaleY, true) - local radiusMax = adjustedRadius * 3 -- arbitrary multiplier - needs to be big enough to not cut any metaballs + local radiusMax = radius * 3 -- arbitrary multiplier - needs to be big enough to not cut any metaballs updateRect(outside, x, y, radiusMax) - updateRect(inside, x, y, adjustedRadius) + updateRect(inside, x, y, radius) end - local function generate_p_ball() + local function roundRect( rect ) + rect.xmin = round( rect.xmin ) + rect.xmax = round( rect.xmax ) + rect.ymin = round( rect.ymin ) + rect.ymax = round( rect.ymax ) + end + + local function generate_p_ball(rng) local angle, x_scale, y_scale, x, y, b_radius, shape - angle, x_scale, y_scale=rng_restricted_angle(restrictions) - local dev = radius / 2 + rgen:random() * radius / 4--math.min(CHUNK_SIZE/3, radius*1.5) + angle, x_scale, y_scale=rng_restricted_angle(restrictions, rng) + local dev = radius / 2 + rng() * radius / 4--math.min(CHUNK_SIZE/3, radius*1.5) local dev_x, dev_y = pos.x, pos.y - x = rgen:random(-dev, dev)+dev_x - y = rgen:random(-dev, dev)+dev_y + x = rng(-dev, dev)+dev_x + y = rng(-dev, dev)+dev_y if p_balls[#p_balls] and distance(p_balls[#p_balls], {x=x, y=y}) < MIN_BALL_DISTANCE then local new_angle = bearing(p_balls[#p_balls], {x=x, y=y}) - debug("Move ball old xy @ "..x..","..y) + -- debug("Move ball old xy @ "..x..","..y) x=(cos(new_angle)*MIN_BALL_DISTANCE) + x y=(sin(new_angle)*MIN_BALL_DISTANCE) + y - debug("Move ball new xy @ "..x..","..y) + -- debug("Move ball new xy @ "..x..","..y) end if #p_balls == 0 then - b_radius = ( 3 * radius / 4 + rgen:random() * radius / 4) -- * (P_BALL_SIZE_FACTOR^#p_balls) + b_radius = ( 3 * radius / 4 + rng() * radius / 4) -- * (P_BALL_SIZE_FACTOR^#p_balls) else - b_radius = ( radius / 4 + rgen:random() * radius / 2) -- * (P_BALL_SIZE_FACTOR^#p_balls) + b_radius = ( radius / 4 + rng() * radius / 2) -- * (P_BALL_SIZE_FACTOR^#p_balls) end if #p_balls > 0 then local tempRect = table.deepcopy(inside) - updateRect(tempRect, x, y, adjustRadius(b_radius, x_scale, y_scale)) + updateRect(tempRect, x, y, b_radius, x_scale, y_scale) local rectSize = math.max(tempRect.xmax - tempRect.xmin, tempRect.ymax - tempRect.ymin) local targetSize = size * 1.25 - debug("Rect size "..rectSize.." targetSize "..targetSize) + -- debug("Rect size "..rectSize.." targetSize "..targetSize) if rectSize > targetSize then local widthLeft = (targetSize - (inside.xmax - inside.xmin)) local heightLeft = (targetSize - (inside.ymax - inside.ymin)) @@ -434,8 +429,7 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA local heightMod = math.min(y - inside.ymin, inside.ymax - y) local radiusBackup = b_radius b_radius = math.min(widthLeft + widthMod, heightLeft + heightMod) - b_radius = adjustRadius(b_radius, x_scale, y_scale, false) - debug("Reduced ball radius from "..radiusBackup.." to "..b_radius.." widthLeft:"..widthLeft.." heightLeft:"..heightLeft.." widthMod:"..widthMod.." heightMod:"..heightMod) + -- debug("Reduced ball radius from "..radiusBackup.." to "..b_radius.." widthLeft:"..widthLeft.." heightLeft:"..heightLeft.." widthMod:"..widthMod.." heightMod:"..heightMod) end end @@ -446,10 +440,11 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA if b_radius > 0 then maxPradius = math.max(maxPradius, b_radius) - shape = meta_shapes[rgen:random(1,#meta_shapes)] + shape = meta_shapes[rng(1,#meta_shapes)] local radiusText = "" +-- log("Index rolled "..index.." shapes amount "..#meta_shapes) if shape.type == "MetaDonut" then - local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() + local inRadius = b_radius / 4 + b_radius / 2 * rng() radiusText = " inRadius:"..inRadius p_balls[#p_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.1) else @@ -457,54 +452,55 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA end updateRects(x, y, b_radius, x_scale, y_scale) - debug("P+Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) + -- debug("P+Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) end end - local function generate_n_ball(i) + local function generate_n_ball(i, rng) local angle, x_scale, y_scale, x, y, b_radius, shape - angle, x_scale, y_scale=rng_restricted_angle('xy') + angle, x_scale, y_scale=rng_restricted_angle('xy', rng) if p_balls[i] then - local new_angle = p_balls[i].angle + pi*rgen:random(0,1) + (rgen:random()-0.5)*pi/2 + local new_angle = p_balls[i].angle + pi*rng(0,2) + (rng()-0.5)*pi/2 local dist = p_balls[i].radius x=(cos(new_angle)*dist) + p_balls[i].x y=(sin(new_angle)*dist) + p_balls[i].y - angle = p_balls[i].angle + pi/2 + (rgen:random()-0.5)*pi*2/3 + angle = p_balls[i].angle + pi/2 + (rng()-0.5)*pi*2/3 else - x = rgen:random(-radius, radius)+pos.x - y = rgen:random(-radius, radius)+pos.y + x = rng(-radius, radius)+pos.x + y = rng(-radius, radius)+pos.y end if p_balls[i] then - b_radius = (p_balls[i].radius / 4 + rgen:random() * p_balls[i].radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) + b_radius = (p_balls[i].radius / 4 + rng() * p_balls[i].radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) else - b_radius = (radius / 4 + rgen:random() * radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) + b_radius = (radius / 4 + rng() * radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) end if b_radius < 1 then b_radius = 1 end - shape = meta_shapes[rgen:random(1,#meta_shapes)] + shape = meta_shapes[rng(1,#meta_shapes)] +-- log("Index rolled "..index.." shapes amount "..#meta_shapes) local radiusText = "" if shape.type == "MetaDonut" then - local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() + local inRadius = b_radius / 4 + b_radius / 2 * rng() radiusText = " inRadius:"..inRadius n_balls[#n_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.15) else n_balls[#n_balls+1] = shape:new(x, y, b_radius, angle, x_scale, y_scale, 1.15) end -- updateRects(x, y, b_radius, x_scale, y_scale) -- should not be needed here - only positive ball can generate ore - debug("N-Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) + -- debug("N-Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) end local function calculate_force(x,y) local p_force = 0 local n_force = 0 - for _,ball in ipairs(p_balls) do + for _,ball in pairs(p_balls) do p_force = p_force + ball:force(x,y) end - for _,ball in ipairs(n_balls) do + for _,ball in pairs(n_balls) do n_force = n_force + ball:force(x,y) end local totalForce = 0 @@ -517,8 +513,12 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA end local max_p_balls = 2 - local min_amount = config[rname].min_amount or min_amount + local min_amount = global.config[rname].min_amount or min_amount if restrictions == 'xy' then + -- we have full 4 chunks + --radius = radius * 1.5 + --richness = richness * 2 / 3 + --min_amount = min_amount / 3 max_p_balls = 3 end @@ -527,45 +527,81 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA local force -- generate blobs for i=1,max_p_balls do - generate_p_ball() + generate_p_ball(rng) end - for i=1,rgen:random(1, #p_balls) do - generate_n_ball(i) + for i=1,rng(1, #p_balls) do + generate_n_ball(i, rng) end - +--* local _a = {} local _total = 0 local oreLocations = {} local forceTotal = 0 + roundRect( outside ) -- fill the map +-- for y=pos.y-CHUNK_SIZE*2, pos.y+CHUNK_SIZE*2-1 do for y=outside.ymin, outside.ymax do - +--* local _b = {} +--* _a[#_a+1] = _b +-- for x=pos.x-CHUNK_SIZE*2, pos.x+CHUNK_SIZE*2-1 do for x=outside.xmin, outside.xmax do +-- if surface.get_tile(x,y).valid then force = calculate_force(x, y) if force > 0 then + --debug("@ "..x..","..y.." force: "..force.." amount: "..amount) + -- if not surface.get_tile(x,y).collides_with("water-tile") and surface.can_place_entity{name = rname, position = {x,y}} then +--* _b[#_b+1] = '#' oreLocations[#oreLocations + 1] = {x = x, y = y, force = force, valid = false} forceTotal = forceTotal + force +-- elseif not startingArea then -- we don't want to make ultra rich nodes in starting area - failing to make them will add second spawn in different location +-- entities = game.find_entities_filtered{area = {{x-2.75, y-2.75}, {x+2.75, y+2.75}}, name=rname} +-- if entities and #entities > 0 then +--* _b[#_b+1] = 'O' +-- _total = _total + amount +-- for k, ent in pairs(entities) do +-- ent.amount = ent.amount + floor(amount/#entities) +-- end +-- else +-- _b[#_b+1] = '.' +-- end + -- else + -- _b[#_b+1] = 'c' + -- end +--* else +--* _b[#_b+1] = '<' end +--* else +--* _b[#_b+1] = 'x' +-- end end end local validCount, resOffsetX, resOffsetY, ratio - for _,locationOffset in ipairs(locationOrder) do + local bestRatio = 0 + local bestRatioIndex = -1 + local checkedLocations = {} + local needRecheck = false + + for index, locationOffset in pairs(locationOrder) do validCount = 0 resOffsetX = locationOffset.x * CHUNK_SIZE resOffsetY = locationOffset.y * CHUNK_SIZE - for _, location in ipairs(oreLocations) do + for _, location in pairs(oreLocations) do local newX = location.x + resOffsetX local newY = location.y + resOffsetY location.valid = false +-- debug("Checking ".. newX .. "," .. newY .."("..location.x..","..location.y..")") if surface.can_place_entity{name = rname, position = {x = newX,y = newY}} then location.valid = true validCount = validCount + 1 +-- debug("Passed") + else +-- debug("Failed ".. newX .. "," .. newY .."("..location.x..","..location.y..")") end end @@ -575,26 +611,50 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA ratio = validCount / #oreLocations end - debug("Valid ratio ".. ratio) + debug("Valid ratio "..ratio.." for index "..index.." offsets "..resOffsetX..","..resOffsetY ) if not useResourceCollisionDetection then break end + if ratio > bestRatio then + bestRatio = ratio + bestRatioIndex = index + end if ratio > resourceCollisionDetectionRatio then break - elseif resourceCollisionFieldSkip then -- in case no valid ratio was found we skip the field completely - validCount = 0 end end + if bestRatioIndex ~= index then + needRecheck = true + end + + if resourceCollisionFieldSkip and bestRatio < resourceCollisionDetectionRatioFallback then + validCount = 0 + -- debug("Cancelled with best ratio "..bestRatio.." for index "..bestRatioIndex ) + else + resOffsetX = locationOrder[bestRatioIndex].x * CHUNK_SIZE + resOffsetY = locationOrder[bestRatioIndex].y * CHUNK_SIZE + validCount = floor( bestRatio * #oreLocations ) + -- debug("Selected ratio "..bestRatio.." for index "..bestRatioIndex.." offsets "..resOffsetX..","..resOffsetY ) + end + if validCount > 0 then + local removeTrees = remove_trees + local revealResources = reveal_spawn_resources + local revealChunks = {} + revealChunks.minX = 1e9 + revealChunks.minY = 1e9 + revealChunks.maxX = -1e9 + revealChunks.maxY = -1e9 + local rectSize = ((inside.xmax - inside.xmin) + (inside.ymax - inside.ymin)) / 2 local sizeMultiplier = rectSize ^ 0.6 local minSize = richness * 5 * sizeMultiplier local maxSize = richness * 10 * sizeMultiplier - local approxDepositSize = rgen:random(minSize, maxSize) + local approxDepositSize = rng(minSize, maxSize) approxDepositSize = approxDepositSize - validCount * min_amount @@ -606,32 +666,25 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA -- don't create very dense resources in starting area - another field will be generated if startingArea and forceFactor > 4000 then - forceFactor = rgen:random(3000, 4000) + forceFactor = rng(3000, 4000) end +-- elseif forceFactor > 25000 then -- limit size of one resource pile +-- forceFactor = rgen:random(20000, 25000) +-- end - debug( "Force total:"..forceTotal.." sizeMin:"..minSize.." sizeMax:"..maxSize.." factor:"..forceFactor.." location#:"..validCount.." rectSize:"..rectSize.." sizeMultiplier:"..sizeMultiplier) + -- debug( "Force total:"..forceTotal.." sizeMin:"..minSize.." sizeMax:"..maxSize.." factor:"..forceFactor.." location#:"..validCount.." rectSize:"..rectSize.." sizeMultiplier:"..sizeMultiplier) local richnessMultiplier = global_richness_mult if startingArea then richnessMultiplier = starting_richness_mult end +-- if game.players[1] then +-- game.players[1].print("Spawning "..rname.." total amount "..(approxDepositSize + validCount * min_amount)*richnessMultiplier) +-- end - -- infinite ore handling for Angels Ores mod - local infiniteOrePresent = false - local infiniteOreName = "infinite-"..rname - local minimumInfiniteOreAmount = nil local spawnName = rname - if game.entity_prototypes[infiniteOreName] then - infiniteOrePresent = true - minimumInfiniteOreAmount = game.entity_prototypes[infiniteOreName].minimum_resource_amount - end - - if startingArea and not infiniteResourceInStartArea then - infiniteOrePresent = false - end - - for _,location in ipairs(oreLocations) do + for _,location in pairs(oreLocations) do if location.valid then local amount = floor(( forceFactor * location.force + min_amount ) * richnessMultiplier) @@ -643,49 +696,78 @@ local function spawn_resource_ore(surface, rname, pos, size, richness, startingA _total = _total + amount spawnName = rname - if infiniteOrePresent and location.force > infiniteResourceSpawnThreshold then - spawnName = infiniteOreName - if minimumInfiniteOreAmount and amount < minimumInfiniteOreAmount then - amount = minimumInfiniteOreAmount - end - end if amount > 0 then - surface.create_entity{name = spawnName, - position = {location.x + resOffsetX,location.y + resOffsetY}, - force = game.forces.neutral, - amount = amount} + local spawnX = location.x + resOffsetX + local spawnY = location.y + resOffsetY + + if not needRecheck or surface.can_place_entity{name = spawnName, position = {spawnX,spawnY}} then + surface.create_entity{name = spawnName, + position = {spawnX, spawnY}, + force = game.forces.neutral, + amount = amount} + end + + if removeTrees then + remove_trees(surface, spawnX, spawnY, 1, 1) + end + + revealChunks.minX = math.min( revealChunks.minX, spawnX ) + revealChunks.minY = math.min( revealChunks.minY, spawnY ) + revealChunks.maxX = math.max( revealChunks.maxX, spawnX ) + revealChunks.maxY = math.max( revealChunks.maxY, spawnY ) end end end - + + if revealResources then + for _,force in pairs( game.forces )do + force.chart( surface, {{x = revealChunks.minX, y = revealChunks.minY}, {x = revealChunks.maxX, y = revealChunks.maxY}}) + end + end end if debug_enabled then debug("Total amount: ".._total) - debug("Leaving spawn_resource_ore") + -- debug("Leaving spawn_resource_ore") end return _total end --[[ entity-liquid ]]-- -local function spawn_resource_liquid(surface, rname, pos, size, richness, startingArea, restrictions) +local function spawn_resource_liquid(surface, rname, pos, size, richness, startingArea, restrictions, rng) restrictions = restrictions or '' - debug("Entering spawn_resource_liquid "..rname.." "..pos.x..","..pos.y.." "..size.." "..richness.." "..tostring(startingArea).." "..restrictions) + -- debug("Entering spawn_resource_liquid "..rname.." "..pos.x..","..pos.y.." "..size.." "..richness.." "..tostring(startingArea).." "..restrictions) local _total = 0 - local max_radius = rgen:random()*CHUNK_SIZE/2 + CHUNK_SIZE + local max_radius = rng() * CHUNK_SIZE / 2 + CHUNK_SIZE + --[[ + if restrictions == 'xy' then + -- we have full 4 chunks + max_radius = floor(max_radius*1.5) + size = floor(size*1.2) + end + ]]-- + -- don't reduce amount of liquids - they are already infinite + -- size = modify_resource_size(size) - richness = ( 0.75 + rgen:random() / 2 ) * richness * size + richness = ( 0.75 + rng() / 2 ) * richness * size resourceEntity = game.entity_prototypes[rname] - local total_share = 0 local avg_share = 1/size - local angle = rgen:random()*pi*2 + local angle = rng()*pi*2 local saved = 0 + local removeTrees = remove_trees + local richnessMultiplier = global_richness_mult + local spawnCount = 0 + + if startingArea then + richnessMultiplier = starting_richness_mult + end + while total_share < 1 do - local new_share = vary_by_percentage(avg_share, 0.25) + local new_share = vary_by_percentage(avg_share, 0.25, rng) if new_share + total_share > 1 then new_share = 1 - total_share end @@ -696,21 +778,20 @@ local function spawn_resource_liquid(surface, rname, pos, size, richness, starti end local amount = floor(richness*new_share) + saved - local richnessMultiplier = global_richness_mult - - if startingArea then - richnessMultiplier = starting_richness_mult - end - --if amount >= game.entity_prototypes[rname].minimum then - if amount >= config[rname].minimum_amount then + if amount >= global.config[rname].minimum_amount then saved = 0 - for try=1,5 do - local dist = rgen:random()*(max_radius - max_radius*0.1) - angle = angle + pi/4 + rgen:random()*pi/2 - local x, y = pos.x + cos(angle)*dist, pos.y + sin(angle)*dist + + local spawned = false + local x, y + + for try=1,15 do + local dist = rng()*(max_radius - max_radius*0.1) * try / 15 + angle = angle + pi/4 + rng()*pi/2 + x = pos.x + cos(angle)*dist + y = pos.y + sin(angle)*dist if surface.can_place_entity{name = rname, position = {x,y}} then - debug("@ "..x..","..y.." amount: "..amount.." new_share: "..new_share.." try: "..try) + -- debug("@ "..x..","..y.." amount: "..amount.." new_share: "..new_share.." try: "..try) amount = floor(amount * richnessMultiplier) if amount > 1e9 then @@ -724,26 +805,40 @@ local function spawn_resource_liquid(surface, rname, pos, size, richness, starti position = {x,y}, force = game.forces.neutral, amount = amount, - direction = rgen:random(4)} + direction = rng(4)} + if removeTrees then + remove_trees(surface, x, y, 4, 4) + end + end + + if spawnCount == 0 then + debug("Switched center location to "..x..","..y) + pos.x = x + pos.y = y + end + + spawnCount = spawnCount + 1 + spawned = true + break + end + end + + if not startingArea and not spawned then -- we don't want to make ultra rich nodes in starting area - failing to make them will add second spawn in different location + entities = surface.find_entities_filtered{area = {{x - 5, y - 5}, {x + 5, y + 5}}, name=rname} + if entities and #entities > 0 then + _total = _total + amount + for k, ent in pairs(entities) do + ent.amount = ent.amount + floor(amount/#entities) end break - elseif not startingArea then -- we don't want to make ultra rich nodes in starting area - failing to make them will add second spawn in different location - entities = surface.find_entities_filtered{area = {{x-2.75, y-2.75}, {x+2.75, y+2.75}}, name=rname} - if entities and #entities > 0 then - _total = _total + amount - for k, ent in pairs(entities) do - ent.amount = ent.amount + floor(amount/#entities) - end - break - end end end else saved = amount end end - debug("Total amount: ".._total) - debug("Leaving spawn_resource_liquid") + -- debug("Total amount: ".._total.." in "..spawnCount.." fields") + -- debug("Leaving spawn_resource_liquid") return _total end @@ -761,7 +856,7 @@ end local function spawn_entity(surface, ent, r_config, x, y) if not use_RSO_biter_spawning then return end - local size=rgen:random(r_config.size.min, r_config.size.max) + local size = rng(r_config.size.min, r_config.size.max) local _total = 0 local r_distance = distance({x=0,y=0},{x=x/REGION_TILE_SIZE,y=y/REGION_TILE_SIZE}) @@ -773,31 +868,32 @@ local function spawn_entity(surface, ent, r_config, x, y) size = size * enemy_base_size_multiplier - debug("Entering spawn_entity "..ent.." "..x..","..y.." "..size) + -- debug("Entering spawn_entity "..ent.." "..x..","..y.." "..size) - local maxAttemptCount = 5 - local distancePerAttempt = 0.2 + local maxAttemptCount = 20 + local distancePerBatch = 0.5 initSpawnerTable() - + + local useBobEntity = global.useBobEntity + local spawner_probability_edge = global.spawner_probability_edge + local spawnerName = nil + for i=1,size do for attempt = 1, maxAttemptCount do - local richness=r_config.richness*(r_distance^richness_distance_factor) - local max_d = floor(CHUNK_SIZE*(0.5 + distancePerAttempt*attempt)) - local s_x = x + rgen:random(0, floor(max_d - r_config.clear_range[1])) - max_d/2 + r_config.clear_range[1] - local s_y = y + rgen:random(0, floor(max_d - r_config.clear_range[2])) - max_d/2 + r_config.clear_range[2] + local max_d = floor(CHUNK_SIZE * (0.5 + (attempt/5) * distancePerBatch)) + local s_x = x + rng(0, floor(max_d - r_config.clear_range[1])) - max_d/2 + r_config.clear_range[1] + local s_y = y + rng(0, floor(max_d - r_config.clear_range[2])) - max_d/2 + r_config.clear_range[2] if surface.get_tile(s_x, s_y).valid then remove_trees(surface, s_x, s_y, r_config.clear_range[1], r_config.clear_range[2]) - local spawnerName = nil - if spawner_probability_edge > 0 then - bigSpawnerChance = rgen:random() + bigSpawnerChance = rng() - if rgen:random() < spawner_probability_edge then + if rng() < spawner_probability_edge then if ( useBobEntity and bigSpawnerChance > 0.75 ) then spawnerName = "bob-biter-spawner" else @@ -814,35 +910,35 @@ local function spawn_entity(surface, ent, r_config, x, y) if spawnerName and spawnerTable[spawnerName] then if surface.can_place_entity{name=spawnerName, position={s_x, s_y}} then - _total = _total + richness - debug(spawnerName.." @ "..s_x..","..s_y.." placed on "..attempt.." attempt") + _total = _total + 1 + -- debug(spawnerName.." @ "..s_x..","..s_y.." placed on "..attempt.." attempt") - surface.create_entity{name=spawnerName, position={s_x, s_y}, force=game.forces[r_config.force], amount=floor(richness)}--, direction=rgen:random(4) - -- else - -- debug("Entity "..spawnerName.." spawn failed") + surface.create_entity{name=spawnerName, position={s_x, s_y}, force=game.forces[r_config.force]}--, amount=floor(richness), direction=rgen:random(4) + -- else + -- game.players[1].print("Entity "..spawnerName.." spawn failed") break; else if attempt == maxAttemptCount then - debug(spawnerName.." @ "..s_x..","..s_y.." failed to spawn") + -- debug(spawnerName.." @ "..s_x..","..s_y.." `spawn") end end else - debug("Entity "..spawnerName.." doesn't exist") + game.players[1].print("Entity "..spawnerName.." doesn't exist") end end end if r_config.sub_spawn_probability then local sub_spawn_prob = r_config.sub_spawn_probability*math.min(r_config.sub_spawn_max_distance_factor, r_config.sub_spawn_distance_factor^r_distance) - if rgen:random() < sub_spawn_prob then - for i=1,(rgen:random(r_config.sub_spawn_size.min, r_config.sub_spawn_size.max)*distanceMultiplier) do + if rng() < sub_spawn_prob then + for i=1,(rng(r_config.sub_spawn_size.min, r_config.sub_spawn_size.max)*distanceMultiplier) do local allotment_max = 0 -- build table for k,v in pairs(r_config.sub_spawns) do if not v.min_distance or r_distance > v.min_distance then local allotment = v.allotment if v.allotment_distance_factor then - allotment = allotment * (v.allotment_distance_factor^r_distance) + allotment = allotment * (r_distance^v.allotment_distance_factor) end v.allotment_range ={min = allotment_max, max = allotment_max + allotment} allotment_max = allotment_max + allotment @@ -850,21 +946,22 @@ local function spawn_entity(surface, ent, r_config, x, y) v.allotment_range = nil end end - local sub_type = rgen:random(0, allotment_max) + + local sub_type = rng(0, allotment_max) for sub_spawn,v in pairs(r_config.sub_spawns) do if v.allotment_range and sub_type >= v.allotment_range.min and sub_type <= v.allotment_range.max then for attempt = 1, maxAttemptCount do - local max_d = floor(CHUNK_SIZE*distancePerAttempt*attempt) - s_x = x + rgen:random(max_d) - max_d/2 - s_y = y + rgen:random(max_d) - max_d/2 + local max_d = floor((attempt/5) * CHUNK_SIZE * distancePerBatch) + s_x = x + rng(max_d) - max_d/2 + s_y = y + rng(max_d) - max_d/2 remove_trees(surface, s_x, s_y, v.clear_range[1], v.clear_range[2]) if surface.can_place_entity{name=sub_spawn, position={s_x, s_y}} then surface.create_entity{name=sub_spawn, position={s_x, s_y}, force=game.forces[r_config.force]}--, direction=rgen:random(4) - debug("Rolled subspawn "..sub_spawn.." @ "..s_x..","..s_x.." after "..attempt.." attempts") + -- debug("Rolled subspawn "..sub_spawn.." @ "..s_x..","..s_x.." after "..attempt.." attempts") break; else if attempt == maxAttemptCount then - debug("Rolling subspawn "..sub_spawn.." @ "..s_x..","..s_x.." failed") + -- debug("Rolling subspawn "..sub_spawn.." @ "..s_x..","..s_x.." failed") end end end @@ -875,47 +972,49 @@ local function spawn_entity(surface, ent, r_config, x, y) end end end - debug("Total amount: ".._total) - debug("Leaving spawn_entity") + -- debug("Total amount: ".._total) + -- debug("Leaving spawn_entity") end --[[ EVENT/INIT METHODS ]]-- local function spawn_starting_resources( surface, index ) + if global.disableStartingArea then return end if global.startingAreas[index].spawned then return end if surface.map_gen_settings.starting_area == "none" and not ignoreMapGenSettings then return end -- starting area disabled by map gen - if starting_area_size < 0.1 then return end -- skip spawning if starting area is to small + if global.starting_area_size < 0.1 then return end -- skip spawning if starting area is to small local position = global.startingAreas[index] + local configIndexed = global.configIndexed - rgen = rng_for_reg_pos( position ) + rng = rng_for_reg_pos( position ) local status = true - for index,v in ipairs(configIndexed) do + for _,v in pairs(configIndexed) do if v.starting then - local prob = rgen:random() -- probability that this resource is spawned + local prob = rng() -- probability that this resource is spawned debug("starting resource probability rolled "..prob) if v.starting.probability > 0 and prob <= v.starting.probability then local total = 0 - local radius = 25 + local radius = 20 local min_threshold = 0 if v.type == "resource-ore" then - min_threshold = v.starting.richness * rgen:random(5, 10) -- lets make sure that there is at least 10-15 times starting richness ore at start + min_threshold = v.starting.richness * rng(5, 10) -- lets make sure that there is at least 5-10 times starting richness ore at start elseif v.type == "resource-liquid" then min_threshold = v.starting.richness * 0.5 * v.starting.size end while (radius < 200) and (total < min_threshold) do - local angle = rgen:random() * pi * 2 - local dist = rgen:random() * 30 + radius * 2 + local angle = rng() * pi * 2 + local dist = rng(20) + radius * 2 local pos = { x = floor(cos(angle) * dist) + position.x, y = floor(sin(angle) * dist) + position.y } if v.type == "resource-ore" then - total = total + spawn_resource_ore(surface, v.name, pos, v.starting.size, v.starting.richness, true) + total = total + spawn_resource_ore(surface, v.name, pos, v.starting.size, v.starting.richness, true, null, rng) elseif v.type == "resource-liquid" then - total = total + spawn_resource_liquid(surface, v.name, pos, v.starting.size, v.starting.richness, true) + total = total + spawn_resource_liquid(surface, v.name, pos, v.starting.size, v.starting.richness, true, null, rng) end - radius = radius + 10 + radius = radius + 20 end if total < min_threshold then status = false @@ -925,6 +1024,7 @@ local function spawn_starting_resources( surface, index ) end global.startingAreas[index].spawned = true + --l:dump('logs/start_'..global.seed..'.log') end local function modifyMinMax(value, mod) @@ -932,9 +1032,7 @@ local function modifyMinMax(value, mod) value.max = round( value.max * mod ) end -local function prebuild_config_data(surface) - if index_is_built then return false end - +local function build_config_data(surface) local mapGenSettings = nil if not ignoreMapGenSettings then @@ -945,10 +1043,13 @@ local function prebuild_config_data(surface) autoPlaceSettings = mapGenSettings.autoplace_controls end - configIndexed = {} + local configIndexed = {} + local config = global.config + -- build additional indexed array to the associative array - for res_name, res_conf in pairs(config) do - if res_conf.valid then -- only add valid resources + for res_name, resConf in pairs(config) do + if resConf.valid then -- only add valid resources + res_conf = table.deepcopy(resConf) res_conf.name = res_name local settingsForResource = nil @@ -978,10 +1079,6 @@ local function prebuild_config_data(surface) local richnessMod = richnessMultiplier[settingsForResource.richness] - - debug(res_name .. " allotment mod " .. allotmentMod .. " size mod " .. sizeMod .. " richness mod " .. richnessMod ) - - if allotmentMod then if isEntity then res_conf.absolute_probability = res_conf.absolute_probability * allotmentMod @@ -989,10 +1086,13 @@ local function prebuild_config_data(surface) else res_conf.allotment = round( res_conf.allotment * allotmentMod ) end + else + -- log("Null allotment mod for "..res_name.." value "..settingsForResource.frequency) end if sizeMod ~= nil and sizeMod == 0 then addResource = false + -- log("Null size mod for "..res_name.." value "..settingsForResource.size) end if sizeMod then @@ -1020,11 +1120,15 @@ local function prebuild_config_data(surface) if res_conf.starting then res_conf.starting.richness = round( res_conf.starting.richness * richnessMod ) end + else + -- log("Null richness mod for "..res_name.." value "..settingsForResource.richness) + end + if allotmentMod and richnessMod and sizeMod then + debug(res_name .. " allotment mod " .. allotmentMod .. " size mod " .. sizeMod .. " richness mod " .. richnessMod ) end end if addResource then - configIndexed[#configIndexed + 1] = res_conf if res_conf.multi_resource and multi_resource_active then local new_list = {} for sub_res_name, allotment in pairs(res_conf.multi_resource) do @@ -1037,6 +1141,7 @@ local function prebuild_config_data(surface) else res_conf.multi_resource_chance = nil end + configIndexed[#configIndexed + 1] = res_conf end end end @@ -1044,55 +1149,61 @@ local function prebuild_config_data(surface) table.sort(configIndexed, function(a, b) return a.name < b.name end) local pr=0 - for index,v in pairs(config) do + local maxAllotment = 0 + for index,v in pairs(configIndexed) do if v.along_resource_probability then v.along_resource_probability_range={min=pr, max=pr+v.along_resource_probability} - pr=pr+v.along_resource_probability + pr = pr + v.along_resource_probability end if v.allotment and v.allotment > 0 then - v.allotment_range={min=max_allotment, max=max_allotment+v.allotment} - max_allotment=max_allotment+v.allotment + v.allotment_range={min = maxAllotment, max = maxAllotment + v.allotment} + maxAllotment = maxAllotment + v.allotment end end + global.maxAllotment = maxAllotment + global.starting_area_size = starting_area_size + if mapGenSettings and mapGenSettings.starting_area then local multiplier = startingAreaMultiplier[mapGenSettings.starting_area] if multiplier ~= nil then - starting_area_size = starting_area_size * multiplier - debug("Starting area "..starting_area_size) + global.starting_area_size = starting_area_size * multiplier + debug("Starting area "..global.starting_area_size) end end - index_is_built = true + global.configIndexed = configIndexed end -- set up the probabilty segments from which to roll between for biter and spitter spawners local function calculate_spawner_ratio() if (biter_ratio_segment ~= 0 and spitter_ratio_segment ~= 0) and biter_ratio_segment >= 0 and spitter_ratio_segment >= 0 then - spawner_probability_edge=biter_ratio_segment/(biter_ratio_segment+spitter_ratio_segment) -- normalize to between 0 and 1 + global.spawner_probability_edge = biter_ratio_segment/(biter_ratio_segment+spitter_ratio_segment) -- normalize to between 0 and 1 end end local function checkConfigForInvalidResources() --make sure that every resource in the config is actually available. --call this function, before the auxiliary config is prebuilt! - if index_is_built then return end local prototypes = game.entity_prototypes + local config = global.config for resourceName, resourceConfig in pairs(config) do if prototypes[resourceName] or resourceConfig.type == "entity" then resourceConfig.valid = true else - -- resource was in config, but it doesn't exist in game files anymore - mark it invalid - resourceConfig.valid = false - - table.insert(invalidResources, "Resource not available: " .. resourceName) - debug("Resource not available: " .. resourceName) + if prototypes[resourceName] and prototypes[resourceName].autoplace ~= nil then + -- resource was in config, but it doesn't exist in game files anymore - mark it invalid + resourceConfig.valid = false + + table.insert(invalidResources, "Resource not available: " .. resourceName) + debug("Resource not available: " .. resourceName) + end end if resourceConfig.valid and resourceConfig.type ~= "entity" then - if prototypes[resourceName].autoplace_specification == nil then + if prototypes[resourceName].autoplace_specification == nil then resourceConfig.valid = false debug("Resource "..resourceName.." invalidated - autoplace not present") end @@ -1107,10 +1218,12 @@ local function roll_region(c_x, c_y) local r_data = nil --don't spawn stuff in starting area - if isInStartingArea( c_x/REGION_TILE_SIZE, c_y/REGION_TILE_SIZE ) then + if isInStartingArea( c_x, c_y ) then return false end + local configIndexed = global.configIndexed + -- Reroll regions every region_size^2 chunk generation calls. local regrow_rso = false if (ENABLE_REGROWTH) then @@ -1124,71 +1237,101 @@ local function roll_region(c_x, c_y) --if this chunk is the first in its region to be generated -- or we're hitting a lucky regrowth reroll... + if global.regions[r_x] and global.regions[r_x][r_y] then + r_data = global.regions[r_x][r_y] + end + if (not (global.regions[r_x] and global.regions[r_x][r_y]) or regrow_rso) then - + + + --if this chunk is the first in its region to be generated if not global.regions[r_x] then global.regions[r_x] = {} end global.regions[r_x][r_y]={} r_data = global.regions[r_x][r_y] - rgen = rng_for_reg_pos{x=r_x,y=r_y} + rng = rng_for_reg_pos{x=r_x,y=r_y} local rollCount = math.ceil(#configIndexed / 10) - 1 -- 0 based counter is more convenient here rollCount = math.min(rollCount, 3) + local resourceSetting = absolute_resource_chance + + local maxAllotment = global.maxAllotment + + -- if in some way there are no valid ores present just bail or it will die on rng + if maxAllotment == 0 then + return false + end + + for rollNumber = 0,rollCount do - local resourceChance = absolute_resource_chance - rollNumber * 0.1 + local resourceChance = resourceSetting - rollNumber * 0.1 --absolute chance to spawn resource - local abct = rgen:random() - debug("Rolling resource "..abct.." against "..resourceChance.." roll "..rollNumber) + local abct = rng() + -- debug("Rolling resource "..abct.." against "..resourceChance.." roll "..rollNumber) if abct <= resourceChance then - local res_type=rgen:random(1, max_allotment) - for index,v in ipairs(configIndexed) do + local res_type=rng(1, maxAllotment) + for index,v in pairs(configIndexed) do if v.allotment_range and ((res_type >= v.allotment_range.min) and (res_type <= v.allotment_range.max)) then - debug("Rolled primary resource "..v.name.." with res_type="..res_type.." @ "..r_x..","..r_y) - local num_spawns=rgen:random(v.spawns_per_region.min, v.spawns_per_region.max) + -- debug("Rolled primary resource "..v.name.." with roll="..res_type.." @ "..r_x..","..r_y) + local num_spawns = 0 + if v.spawns_per_region.min == v.spawns_per_region.max then + num_spawns = v.spawns_per_region.min + else + num_spawns = rng(v.spawns_per_region.min, v.spawns_per_region.max) + end local last_spawn_coords = {} local along_ for i=1,num_spawns do - local c_x, c_y = find_random_chunk(r_x, r_y) - if not r_data[c_x] then r_data[c_x] = {} end - if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end - local c_data = r_data[c_x][c_y] - c_data[#c_data+1]={v.name, rollNumber} - last_spawn_coords[#last_spawn_coords+1] = {c_x, c_y} - debug("Rolled primary chunk "..v.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) - -- Along resource spawn, only once - if i == 1 then - local am_roll = rgen:random() - for index,vv in ipairs(configIndexed) do - if vv.along_resource_probability_range and am_roll >= vv.along_resource_probability_range.min and am_roll <= vv.along_resource_probability_range.max then - c_data = r_data[c_x][c_y] - c_data[#c_data+1]={vv.name, rollNumber} - debug("Rolled along "..vv.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) + local c_x, c_y = find_random_chunk(r_x, r_y, rng) + + -- even if initial chunk is outside region might overlap with starting area - need to recheck here if rolled coords are outside + if not isInStartingArea( c_x, c_y ) then + if not r_data[c_x] then r_data[c_x] = {} end + if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end + local c_data = r_data[c_x][c_y] + c_data[#c_data+1]={v.name, rollNumber} + last_spawn_coords[#last_spawn_coords+1] = {c_x, c_y} + debug("Rolled primary chunk "..v.name.." @ "..c_x..","..c_y.." reg: "..r_x..","..r_y) + -- Along resource spawn, only once + if i == 1 then + local am_roll = rng() + for index,vv in pairs(configIndexed) do + if vv.along_resource_probability_range and am_roll >= vv.along_resource_probability_range.min and am_roll <= vv.along_resource_probability_range.max then + c_data = r_data[c_x][c_y] + c_data[#c_data+1]={vv.name, rollNumber} + debug("Rolled along "..vv.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) + end end end end end -- roll multiple resources in same region local deep=0 - while v.multi_resource_chance and rgen:random() <= v.multi_resource_chance*(multi_resource_chance_diminish^deep) do - deep = deep + 1 - local max_allotment = 0 - for index,sub_res in pairs(v.multi_resource) do max_allotment=max_allotment+sub_res.allotment end - - local res_type=rgen:random(1, max_allotment) - local min=0 - for _, sub_res in pairs(v.multi_resource) do - if (res_type >= min) and (res_type <= sub_res.allotment + min) then - local last_coords = last_spawn_coords[rgen:random(1, #last_spawn_coords)] - local c_x, c_y = find_random_neighbour_chunk(last_coords[1], last_coords[2]) -- in same as primary resource chunk - if not r_data[c_x] then r_data[c_x] = {} end - if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end - local c_data = r_data[c_x][c_y] - c_data[#c_data+1]={sub_res.name, deep} - debug("Rolled multiple "..sub_res.name..":"..deep.." with res_type="..res_type.." @ "..c_x.."."..c_y.." reg: "..r_x.."."..r_y) - break - else - min = min + sub_res.allotment + if #last_spawn_coords > 0 then + while v.multi_resource_chance and rng() <= v.multi_resource_chance*(multi_resource_chance_diminish^deep) do + deep = deep + 1 + local multiAllotmentMax = 0 + for index,sub_res in pairs(v.multi_resource) do multiAllotmentMax = multiAllotmentMax + sub_res.allotment end + + local res_type = 1 -- with allotment of 1 we don't need to roll rng and rng will complain when it's range is 0 + if multiAllotmentMax > 1 then + res_type = rng(1, multiAllotmentMax) + end + local min=0 + for _, sub_res in pairs(v.multi_resource) do + if (res_type >= min) and (res_type <= sub_res.allotment + min) then + local last_coords = last_spawn_coords[rng(1, #last_spawn_coords)] + local c_x, c_y = find_random_neighbour_chunk(last_coords[1], last_coords[2], rng) -- in same region as primary resource chunk + if not r_data[c_x] then r_data[c_x] = {} end + if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end + local c_data = r_data[c_x][c_y] + c_data[#c_data+1]={sub_res.name, deep} + debug("Rolled multiple "..sub_res.name..":"..deep.." with res_type="..res_type.." @ "..c_x.."."..c_y.." reg: "..r_x.."."..r_y) + break + else + min = min + sub_res.allotment + end end end end @@ -1200,22 +1343,24 @@ local function roll_region(c_x, c_y) end -- roll for absolute_probability - this rolls the enemies - for index,v in ipairs(configIndexed) do + for index,v in pairs(configIndexed) do if v.absolute_probability then local prob_factor = 1 if v.probability_distance_factor then prob_factor = math.min(v.max_probability_distance_factor, v.probability_distance_factor^distance({x=0,y=0},{x=r_x,y=r_y})) end - local abs_roll = rgen:random() + local abs_roll = rng() if abs_roll 10 then + global.startingAreas[1].spawned = true end end - player.print("SanityCheck Allotment: "..string.format("%.1f", sanityCheckAllotment)) - debug("SanityCheck Allotment: "..string.format("%.1f", sanityCheckAllotment)) + global.seed = surface.map_gen_settings.seed + + global.config = loadResourceConfig() + checkConfigForInvalidResources() + build_config_data(surface) + + -- checkForBobEnemies() + calculate_spawner_ratio() + end function RSO_init() @@ -1346,29 +1516,9 @@ function RSO_init() local surface = game.surfaces[GAME_SURFACE_NAME] - if not global.regions then - global.regions = {} - end - - if not config then - config = loadResourceConfig() - checkConfigForInvalidResources() - prebuild_config_data(surface) - end - - global.seed = surface.map_gen_settings.seed + updateConfig() - if not global.startingAreas then - global.startingAreas = {} - table.insert( global.startingAreas, { x = 0, y = 0, spawned = false } ) - - if global.start_resources_spawned or game.tick > 10 then - global.startingAreas[1].spawned = true - end - end - - calculate_spawner_ratio() - spawn_starting_resources(surface, 1 ) + spawn_starting_resources(global.mainSurface, 1 ) initDone = true diff --git a/locale/rso/rso_resource_config.lua b/locale/rso/rso_resource_config.lua index 1b4d9fd..2a6dbac 100644 --- a/locale/rso/rso_resource_config.lua +++ b/locale/rso/rso_resource_config.lua @@ -5,9 +5,9 @@ local function fillVanillaConfig() type="resource-ore", -- general spawn params - allotment=100, -- how common resource is + allotment=90, -- 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 + 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, @@ -29,9 +29,9 @@ local function fillVanillaConfig() config["copper-ore"] = { type="resource-ore", - allotment=90, + allotment=80, spawns_per_region={min=1, max=1}, - richness=10000, + richness=20000, size={min=15, max=25}, min_amount=350, @@ -53,7 +53,7 @@ local function fillVanillaConfig() spawns_per_region={min=1, max=1}, size={min=15, max=25}, - richness=8000, + richness=16000, min_amount=350, starting={richness=6000, size=20, probability=1}, @@ -71,7 +71,7 @@ local function fillVanillaConfig() allotment=60, spawns_per_region={min=1, max=1}, - richness=6000, + richness=12000, size={min=15, max=20}, min_amount=250, @@ -99,13 +99,13 @@ local function fillVanillaConfig() config["crude-oil"] = { type="resource-liquid", - minimum_amount=10000, + minimum_amount=20000, allotment=70, spawns_per_region={min=1, max=2}, - richness={min=100000, max=200000}, -- richness per resource spawn + richness={min=400000, max=700000}, -- richness per resource spawn size={min=3, max=7}, - starting={richness=200000, size=2, probability=1}, + starting={richness=400000, size=2, probability=1}, multi_resource_chance=0.20, multi_resource={ From 06e7f9dca31fecce9bc600d8fadaa24ddd264b91 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 16 Dec 2017 16:02:35 -0500 Subject: [PATCH 13/58] Tweaked RSO to my liking. Should be challenging. Resources not too abundant. --- config.lua | 11 ++++++++++- locale/rso/rso_config.lua | 8 +++----- locale/rso/rso_control.lua | 12 +++++++----- locale/rso/rso_resource_config.lua | 6 +++--- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/config.lua b/config.lua index 288e182..29cf0a9 100644 --- a/config.lua +++ b/config.lua @@ -51,7 +51,7 @@ WELCOME_MSG_TITLE_OARC = "Welcome to Oarc's Server!" -- This is the core of the mod. Probably not a good idea to disable it. ENABLE_SEPARATE_SPAWNS = true --- RSO OPTION HAS BEEN REMOVED FOR NOW. USE THE 0.16 MOD. +-- RSO soft-mod (included in the scenario) ENABLE_RSO = true -- Frontier style rocket silo mode @@ -312,6 +312,15 @@ RESOURCE_DIST_BONUS = 2 AUTOFILL_TURRET_AMMO_QUANTITY = 10 +-------------------------------------------------------------------------------- +-- RSO Soft-Mod Configurations +-- Configure these to tweak the RSO values. +-------------------------------------------------------------------------------- +-- CONFIGURE STUFF INSIDE rso_config.lua +-- RSO resources can be very lucky/unlucky... +-- don't complain if you can't find a resource. + + -------------------------------------------------------------------------------- -- MAP CONFIGURATION OPTIONS -- Configure these if you are running headless since there is no way to set diff --git a/locale/rso/rso_config.lua b/locale/rso/rso_config.lua index fa03e41..0896880 100644 --- a/locale/rso/rso_config.lua +++ b/locale/rso/rso_config.lua @@ -1,4 +1,4 @@ -debug_enabled = true +debug_enabled = false region_size = 8 -- alternative mean to control how further away resources would be, default - 256 tiles or 8 chunks -- each region is region_size*region_size chunks @@ -23,7 +23,7 @@ multi_resource_chance_diminish = 0.6 -- diminishing effect factor on multi_resou min_amount=250 -- default value for minimum amount of resource in single pile -richness_distance_factor= 1 -- exponent for richness distance factor calculation +richness_distance_factor= 0.5 -- 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 @@ -37,7 +37,7 @@ endless_resource_mode_sizeModifier = 0.80 -- 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 = false -- enables spawning of biters controlled by RSO mod - less enemies around with more space between bases +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 @@ -47,8 +47,6 @@ useEnemiesInPeaceMod = false -- additional override for peace mod detection - wh -- 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.999 -- threshold to exit placement early diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua index 54c5a78..7aff2f0 100644 --- a/locale/rso/rso_control.lua +++ b/locale/rso/rso_control.lua @@ -1237,13 +1237,15 @@ local function roll_region(c_x, c_y) --if this chunk is the first in its region to be generated -- or we're hitting a lucky regrowth reroll... + -- if global.regions[r_x] and global.regions[r_x][r_y] then + -- r_data = global.regions[r_x][r_y] + -- end + + -- if (not (global.regions[r_x] and global.regions[r_x][r_y]) or regrow_rso) then + if global.regions[r_x] and global.regions[r_x][r_y] then r_data = global.regions[r_x][r_y] - end - - if (not (global.regions[r_x] and global.regions[r_x][r_y]) or regrow_rso) then - - + else --if this chunk is the first in its region to be generated if not global.regions[r_x] then global.regions[r_x] = {} end global.regions[r_x][r_y]={} diff --git a/locale/rso/rso_resource_config.lua b/locale/rso/rso_resource_config.lua index 2a6dbac..653b6b4 100644 --- a/locale/rso/rso_resource_config.lua +++ b/locale/rso/rso_resource_config.lua @@ -99,10 +99,10 @@ local function fillVanillaConfig() config["crude-oil"] = { type="resource-liquid", - minimum_amount=20000, + minimum_amount=10000, allotment=70, - spawns_per_region={min=1, max=2}, - richness={min=400000, max=700000}, -- richness per resource spawn + 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}, From a8121d3a98ebf7ac49a583c9b9d1d5e15b9cace7 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 16 Dec 2017 22:00:51 -0500 Subject: [PATCH 14/58] Using native shared vision option thanks to dev help. Restoring some config settings like water and other map biomes. Moving buddy spawn 1 chunk over. --- config.lua | 16 ++++---- control.lua | 9 ----- regrowth_map.lua | 2 +- separate_spawns.lua | 80 ++++++++++++++++++++++------------------ separate_spawns_guis.lua | 6 +-- 5 files changed, 57 insertions(+), 56 deletions(-) diff --git a/config.lua b/config.lua index 29cf0a9..0192ac5 100644 --- a/config.lua +++ b/config.lua @@ -84,9 +84,8 @@ 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_SHARED_TEAM_RADAR = true -- This shares charted chunks. Not active vision. -- Enable map regrowth, see regrowth_map.lua for more info. ENABLE_REGROWTH = false @@ -334,12 +333,14 @@ CMD_LINE_MAP_GEN = true -- "Sizes can be specified as none, very-low, low, normal, high, very-high" global.clMapGen = {} global.clMapGen.terrain_segmentation="normal" -global.clMapGen.water="none" +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"}, @@ -347,11 +348,12 @@ global.clMapGen.autoplace_controls = { ["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= "normal", size= "none", richness= "normal"}, - ["dirt"]={frequency= "normal", size= "none", richness= "normal"}, + + ["desert"]={frequency= "normal", size= "normal", richness= "normal"}, + ["dirt"]={frequency= "normal", size= "normal", richness= "normal"}, ["grass"]={frequency= "normal", size= "normal", richness= "normal"}, - ["sand"]={frequency= "normal", size= "none", richness= "normal"}, - ["trees"]={frequency= "normal", size= "none", richness= "normal"} + ["sand"]={frequency= "normal", size= "normal", richness= "normal"}, + ["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"} diff --git a/control.lua b/control.lua index bc4dde2..8447dce 100644 --- a/control.lua +++ b/control.lua @@ -271,11 +271,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 @@ -291,10 +286,6 @@ script.on_event(defines.events.on_sector_scanned, function (event) if ENABLE_REGROWTH then OarcRegrowthSectorScan(event) end - - if ENABLE_SHARED_TEAM_RADAR then - ShareRadarBetweenForces(event) - end end) ---------------------------------------- diff --git a/regrowth_map.lua b/regrowth_map.lua index 785f350..4372215 100644 --- a/regrowth_map.lua +++ b/regrowth_map.lua @@ -48,7 +48,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 diff --git a/separate_spawns.lua b/separate_spawns.lua index 9c02ac5..2af1cc1 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -203,6 +203,11 @@ function InitSpawnGlobalsAndForces() 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]) @@ -279,6 +284,9 @@ 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 player.force = newForce SetCeaseFireBetweenAllForces() SetFriendlyBetweenAllForces() @@ -295,50 +303,50 @@ end -- 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() +-- function ShareVisionBetweenPlayers() - if ((game.tick % 10) == 0) then +-- if ((game.tick % 10) == 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 _,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-(2*CHUNK_SIZE), - player.position.y-(2*CHUNK_SIZE)}, - {player.position.x+(2*CHUNK_SIZE), - player.position.y+(2*CHUNK_SIZE)}}) - end - end - end - end - end -end +-- for _,player in pairs(game.connected_players) do +-- force.chart(GAME_SURFACE_NAME, +-- {{player.position.x-(2*CHUNK_SIZE), +-- player.position.y-(2*CHUNK_SIZE)}, +-- {player.position.x+(2*CHUNK_SIZE), +-- player.position.y+(2*CHUNK_SIZE)}}) +-- end +-- end +-- end +-- end +-- end +-- end -- For each force, if it's a valid force, chart the chunk that was just scanned -- for all forces. -- I have no idea how compute intensive this function is. If it starts to lag the game -- we'll have to figure out how to change it. -function ShareRadarBetweenForces(event) +-- function ShareRadarBetweenForces(event) - for _,force in pairs(game.forces) do - if (force ~= nil) then - if ((force.name ~= enemy) and - (force.name ~= neutral) and - (force.name ~= player)) then +-- for _,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, - {{event.chunk_position.x*CHUNK_SIZE, - event.chunk_position.y*CHUNK_SIZE}, - {event.chunk_position.x*CHUNK_SIZE, - event.chunk_position.y*CHUNK_SIZE}}) - end - end - end - end -end \ No newline at end of file +-- for _,player in pairs(game.connected_players) do +-- force.chart(GAME_SURFACE_NAME, +-- {{event.chunk_position.x*CHUNK_SIZE, +-- event.chunk_position.y*CHUNK_SIZE}, +-- {event.chunk_position.x*CHUNK_SIZE, +-- event.chunk_position.y*CHUNK_SIZE}}) +-- end +-- end +-- end +-- end +-- end \ No newline at end of file diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 61fb702..10a09de 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -398,7 +398,7 @@ function SpawnOptsGuiClick(event) if (TableLength(global.waitingBuddies) == 0) then table.insert(global.waitingBuddies, player.name) - SendBroadcastMsg(player.name .. " is waiting for a buddy.") + SendBroadcastMsg(player.name .. " is waiting for a fuddy.") else buddy_name = table.remove(global.waitingBuddies) @@ -407,7 +407,7 @@ function SpawnOptsGuiClick(event) CreateSpawnCtrlGui(game.players[buddy_name]) -- Create a new spawn point - local newSpawn = {x=-(CHUNK_SIZE*2),y=0} + local newSpawn = {x=0,y=0} -- Create a new force for player if they choose that radio button if ENABLE_SEPARATE_TEAMS and joinOwnTeamRadio then @@ -430,7 +430,7 @@ function SpawnOptsGuiClick(event) end -- Create that spawn in the global vars - buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*3), y=newSpawn.y} + buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*4), y=newSpawn.y} ChangePlayerSpawn(player, newSpawn) ChangePlayerSpawn(game.players[buddy_name], buddySpawn) From 18b719f02d02c394146c85f6a7d7565f7d44b4ae Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sun, 17 Dec 2017 09:41:04 -0500 Subject: [PATCH 15/58] Updating readme with note about how to host the game headless with 0.16 --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 897072a..0e80b78 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ A custom scenario for allowing separate spawn locations in multiplayer. Designed 0.16 is EXPERIMENTAL RIGHT NOW. It likely has bugs and it does NOT include RSO at this time. +# NOTE +It appears as though the method of saving a zip file on one computer and then using that to host on another headless server may causes crashes / GUI issues. Please try launching the game from the command line instead. See STEP 3 - Option 3. + ## Instructions ### STEP 1 @@ -25,7 +28,20 @@ Rename the "FactorioScenarioMultiplayerSpawn" folder to something shorter and mo ### STEP 3 -Generate a new map, use that save file to host if you want to. +#### OPTION 1 (Client Hosted) +Start a multiplayer game on your client like normal. + +#### OPTION 2 (Headless) +(Bugged in 0.16) 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 From 69c75dd3fc5b81c7606a3944163d9e1f60d540fd Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sun, 17 Dec 2017 13:08:07 -0500 Subject: [PATCH 16/58] Fix typo and correct readme since RSO is now included. --- README.md | 2 +- separate_spawns_guis.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e80b78..04870b9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # FactorioScenarioMultiplayerSpawn A custom scenario for allowing separate spawn locations in multiplayer. Designed for Co-op and PvE. -0.16 is EXPERIMENTAL RIGHT NOW. It likely has bugs and it does NOT include RSO at this time. +0.16 is EXPERIMENTAL RIGHT NOW... Both the game and the scenario. # NOTE It appears as though the method of saving a zip file on one computer and then using that to host on another headless server may causes crashes / GUI issues. Please try launching the game from the command line instead. See STEP 3 - Option 3. diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 10a09de..14767e5 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -398,7 +398,7 @@ function SpawnOptsGuiClick(event) if (TableLength(global.waitingBuddies) == 0) then table.insert(global.waitingBuddies, player.name) - SendBroadcastMsg(player.name .. " is waiting for a fuddy.") + SendBroadcastMsg(player.name .. " is waiting for a buddy.") else buddy_name = table.remove(global.waitingBuddies) From 8d015812aa59970b3a4146aca807b33ddb9d4159 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sun, 17 Dec 2017 14:46:14 -0500 Subject: [PATCH 17/58] Tentative fix for GUI related crash reported by Noa3. Not sure how this function is getting hit with an invalid player. Wonder if it's buddy spawn related. --- separate_spawns_guis.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 14767e5..3ea0d74 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -525,7 +525,7 @@ end function CreateSpawnCtrlGui(player) - if player.gui.top.spwn_ctrls == nil then + if player and (player.gui.top.spwn_ctrls == nil) then player.gui.top.add{name="spwn_ctrls", type="button", caption="Spawn Ctrl"} end end From 5f1281ec9ccac8d406950a149a9321ac899a3e00 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sun, 17 Dec 2017 14:54:06 -0500 Subject: [PATCH 18/58] More tentative fixes by pushing the creation of the spawn control gui to after all the other setup. Maybe the player's setting of force and stuff makes the player "nil" when this function gets called or something. --- separate_spawns_guis.lua | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 3ea0d74..0c635a5 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -336,14 +336,14 @@ function SpawnOptsGuiClick(event) end if (elemName == "default_spawn_btn") then - CreateSpawnCtrlGui(player) GivePlayerStarterItems(player) ChangePlayerSpawn(player, player.force.get_spawn_position(GAME_SURFACE_NAME)) SendBroadcastMsg(player.name .. " joined the main force!") - ChartArea(player.force, player.position, 4, player.surface) + ChartArea(player.force, player.position, 4, player.surface) + -- Create the button at the top left for setting respawn point and sharing base. + CreateSpawnCtrlGui(player) elseif ((elemName == "isolated_spawn_near") or (elemName == "isolated_spawn_far")) then - CreateSpawnCtrlGui(player) -- Create a new spawn point local newSpawn = {x=0,y=0} @@ -381,6 +381,9 @@ function SpawnOptsGuiClick(event) SendBroadcastMsg(player.name .. " joined the game from a great distance!") end + -- Create the button at the top left for setting respawn point and sharing base. + CreateSpawnCtrlGui(player) + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") @@ -402,9 +405,6 @@ function SpawnOptsGuiClick(event) else buddy_name = table.remove(global.waitingBuddies) - - CreateSpawnCtrlGui(player) - CreateSpawnCtrlGui(game.players[buddy_name]) -- Create a new spawn point local newSpawn = {x=0,y=0} @@ -438,6 +438,10 @@ function SpawnOptsGuiClick(event) SendPlayerToNewSpawnAndCreateIt(player, newSpawn, moatChoice) SendPlayerToNewSpawnAndCreateIt(game.players[buddy_name], buddySpawn, moatChoice) SendBroadcastMsg(player.name .. " and " .. buddy_name .. " joined the game from a distance!") + + -- Create the button at the top left for setting respawn point and sharing base. + CreateSpawnCtrlGui(player) + CreateSpawnCtrlGui(game.players[buddy_name]) player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") @@ -507,7 +511,6 @@ function SharedSpwnOptsGuiClick(event) else for spawnName,sharedSpawn in pairs(global.sharedSpawns) do if ((buttonClicked == spawnName) and (game.players[spawnName] ~= nil)) then - CreateSpawnCtrlGui(player) ChangePlayerSpawn(player,sharedSpawn.position) SendPlayerToSpawn(player) GivePlayerStarterItems(player) @@ -517,6 +520,8 @@ function SharedSpwnOptsGuiClick(event) if (player.gui.center.shared_spawn_opts ~= nil) then player.gui.center.shared_spawn_opts.destroy() end + -- Create the button at the top left for setting respawn point and sharing base. + CreateSpawnCtrlGui(player) break end end From bf2cb79137896656ec0c192704f0c0b38f5446da Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Mon, 18 Dec 2017 12:36:58 -0500 Subject: [PATCH 19/58] Another tentative patch for catching this weird issue where gui clicks don't have a valid player.... --- separate_spawns_guis.lua | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 0c635a5..c7fb546 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -105,6 +105,11 @@ function WelcomeTextGuiClick(event) local player = game.players[event.player_index] local buttonClicked = event.element.name + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + if (buttonClicked == "welcome_okay_btn") then if (player.gui.center.welcome_msg ~= nil) then player.gui.center.welcome_msg.destroy() @@ -304,6 +309,10 @@ function SpawnOptsGuiClick(event) local player = game.players[event.player_index] local elemName = event.element.name + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end if (player.gui.center.spawn_opts == nil) then return -- Gui event unrelated to this gui. @@ -493,6 +502,11 @@ function SharedSpwnOptsGuiClick(event) local player = game.players[event.player_index] local buttonClicked = event.element.name + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + if (event.element.parent) then if (event.element.parent.name ~= "spawns_scroll_pane") then return @@ -623,6 +637,11 @@ function SpawnCtrlGuiOptionsSelect(event) local player = game.players[event.element.player_index] local name = event.element.name + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + if (name == "accessToggle") then if event.element.state then if DoesPlayerHaveCustomSpawn(player) then @@ -649,6 +668,11 @@ function SpawnCtrlGuiClick(event) local player = game.players[event.element.player_index] local name = event.element.name + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + if (name == "spwn_ctrls") then ExpandSpawnCtrlGui(player, event.tick) end From 49e2a79bab40ef19404f1d224329d3f4aa33a8ee Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 23 Dec 2017 15:34:39 -0500 Subject: [PATCH 20/58] Seems like the last dev push reverted this change. Wtf are the devs doing. --- locale/oarc_utils.lua | 2 +- separate_spawns_guis.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 06f0e8c..0c79fa7 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -545,7 +545,7 @@ local function ExpandPlayerListGui(player) name="playerList-panel", direction = "vertical"} ApplyStyle(scrollFrame, my_player_list_fixed_width_style) - scrollFrame.can_scroll_horizontally = false + 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"} diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index c7fb546..1001aef 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -475,7 +475,7 @@ function DisplaySharedSpawnOptions(player) ApplyStyle(shGui, my_fixed_width_style) shGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH shGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT - shGui.can_scroll_horizontally = false + shGui.horizontal_scroll_policy = "never" for spawnName,sharedSpawn in pairs(global.sharedSpawns) do @@ -590,7 +590,7 @@ function ExpandSpawnCtrlGui(player, tick) name="spwn_ctrl_panel", caption=""} ApplyStyle(spwnCtrls, my_fixed_width_style) spwnCtrls.style.maximal_height = SPAWN_GUI_MAX_HEIGHT - spwnCtrls.can_scroll_horizontally = false + spwnCtrls.horizontal_scroll_policy = "never" if ENABLE_SHARED_SPAWNS then if (global.uniqueSpawns[player.name] ~= nil) then From e427724066a5ac69c23097123c3bb4c198ddb0f5 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 6 Jan 2018 11:36:15 -0500 Subject: [PATCH 21/58] Adding options for disabling time and pollution evolution factors. Tweaking long reach to match the mod default distance 125 I think. --- config.lua | 5 +++-- locale/oarc_utils.lua | 11 ++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/config.lua b/config.lua index 0192ac5..146ef83 100644 --- a/config.lua +++ b/config.lua @@ -278,8 +278,9 @@ MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES ENEMY_EXPANSION = true -- 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_DISABLE = true -- Set this to true to disable time based evolution completely. ENEMY_TIME_FACTOR_DIVISOR = 1 +ENEMY_POLLUTION_FACTOR_DISABLE = true -- Set this to true to disable pollution based evolution completely. ENEMY_POLLUTION_FACTOR_DIVISOR = 1 ENEMY_DESTROY_FACTOR_DIVISOR = 1 @@ -301,7 +302,7 @@ ENABLE_RANDOM_SILO_POSITION = true -- Long Reach Options -------------------------------------------------------------------------------- -BUILD_DIST_BONUS = 100 +BUILD_DIST_BONUS = 125 REACH_DIST_BONUS = BUILD_DIST_BONUS RESOURCE_DIST_BONUS = 2 diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 0c79fa7..0c008ff 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -494,13 +494,18 @@ function ConfigureAlienStartingParams() -- "destroy_factor": 0.002, -- "pollution_factor": 0.000015 if ENEMY_TIME_FACTOR_DISABLE then - game.map_settings.enemy_evolution.time_factor=0 + 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 + 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 - game.map_settings.enemy_expansion.enabled = ENEMY_EXPANSION -- game.map_settings.enemy_expansion.min_base_spacing = 10 From cd2956f4655d444b5c6221065e5109bd652256c2 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 25 Jan 2018 00:04:07 -0500 Subject: [PATCH 22/58] Cleaned up buddy spawn system. Tested the basics and it works pretty well. --- config.lua | 9 +- control.lua | 9 +- locale/oarc_utils.lua | 47 ++-- separate_spawns.lua | 78 +++++- separate_spawns_guis.lua | 580 +++++++++++++++++++++++++++++++++++---- 5 files changed, 628 insertions(+), 95 deletions(-) diff --git a/config.lua b/config.lua index 146ef83..ae1643d 100644 --- a/config.lua +++ b/config.lua @@ -18,7 +18,7 @@ WELCOME_MSG1 = "Rules: Be polite. Ask before changing other players's stuff. Hav WELCOME_MSG2 = "This server is running a custom scenario that changes spawn locations." OTHER_MSG1 = "Latest updates in this scenario version:" -OTHER_MSG2 = "0.16 experimental release." +OTHER_MSG2 = "0.16 experimental release. Now with BUDDY SPAWN system." -- 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." @@ -51,6 +51,10 @@ WELCOME_MSG_TITLE_OARC = "Welcome to Oarc's Server!" -- This is the core of the mod. Probably not a good idea to disable it. ENABLE_SEPARATE_SPAWNS = true +-- 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 @@ -364,5 +368,4 @@ global.clMapGen.cliff_settings={cliff_elevation_0=10, cliff_elevation_interval=1 -------------------------------------------------------------------------------- -- DEBUG prints for me -global.oarcDebugEnabled = true -BUDDY_SPAWN = true +global.oarcDebugEnabled = false diff --git a/control.lua b/control.lua index 8447dce..c1944f1 100644 --- a/control.lua +++ b/control.lua @@ -180,13 +180,16 @@ script.on_event(defines.events.on_gui_click, function(event) SpawnOptsGuiClick(event) SpawnCtrlGuiClick(event) SharedSpwnOptsGuiClick(event) + BuddySpawnOptsGuiClick(event) + BuddySpawnWaitMenuClick(event) + BuddySpawnRequestMenuClick(event) end end) script.on_event(defines.events.on_gui_checked_state_changed, function (event) if ENABLE_SEPARATE_SPAWNS then - SpawnOptsGuiOptionsSelect(event) + SpawnOptsRadioSelect(event) SpawnCtrlGuiOptionsSelect(event) end end) @@ -279,6 +282,10 @@ script.on_event(defines.events.on_tick, function(event) OarcRegrowthForceRemovalOnTick() end + if ENABLE_SEPARATE_SPAWNS then + DelayedSpawnOnTick() + end + end) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 0c008ff..4cd620b 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -150,6 +150,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, @@ -320,15 +329,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 @@ -926,12 +935,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 @@ -957,7 +966,7 @@ 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) @@ -978,15 +987,15 @@ 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) - 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 + -- 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 diff --git a/separate_spawns.lua b/separate_spawns.lua index 2af1cc1..4eb617a 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -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 @@ -68,9 +68,19 @@ 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 + + -- Check if it was near someone else's base. + nearOtherSpawn = false + for _,otherSpawnPos in pairs(global.uniqueSpawns) do + if (getDistance(spawnPos, otherSpawnPos) < (CHUNK_SIZE*10)) then + nearOtherSpawn = true + end + end + + if (ENABLE_ABANDONED_BASE_REMOVAL and not nearOtherSpawn) then local spawnPos = global.uniqueSpawns[player.name].pos 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 @@ -200,6 +210,12 @@ function InitSpawnGlobalsAndForces() 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) @@ -228,21 +244,59 @@ function ChangePlayerSpawn(player, pos) global.playerCooldowns[player.name] = {setRespawn=game.tick} end +function QueuePlayerForDelayedSpawn(player, 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} + + player.print("Generating your spawn now, please wait 10 seconds...") + player.surface.request_to_generate_chunks(spawn, 4) + delayedTick = game.tick + 10*TICKS_PER_SECOND + table.insert(global.delayedSpawns, {player=player, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick}) + + else + DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!") + SendBroadcastMsg("ERROR!! Failed to create spawn point for: " .. player.name) + 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 + SendPlayerToNewSpawnAndCreateIt(delayedSpawn.player, delayedSpawn.spawn, delayedSpawn.moatEnabled) + table.remove(global.delayedSpawns, i) + end + end + end + end +end + function SendPlayerToNewSpawnAndCreateIt(player, 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 player.teleport(spawn, GAME_SURFACE_NAME) GivePlayerStarterItems(player) - ChartArea(player.force, player.position, 4, player.surface) - - -- 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) - else - DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!") - SendBroadcastMsg("Failed to create spawn point for: " .. player.name) - end end function SendPlayerToSpawn(player) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 1001aef..7635a9e 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -121,6 +121,10 @@ end -- Display the spawn options and explanation function DisplaySpawnOptions(player) + if (player.gui.center.spawn_opts ~= nil) then + DebugPrint("Tried to display spawn options when it was already displayed!") + return + end player.gui.center.add{name = "spawn_opts", type = "frame", direction = "vertical", @@ -253,13 +257,13 @@ function DisplaySpawnOptions(player) ApplyStyle(sGui.join_other_spawn_lbl1, my_warning_style) end - -- Hack for a 2 player twin spawn. - if BUDDY_SPAWN then + -- New awesome buddy spawning system + if ENABLE_SHARED_SPAWNS and ENABLE_BUDDY_SPAWN then sGui.add{name = "buddy_spawn", type = "button", caption="Buddy Spawn"} sGui.add{name = "buddy_spawn_lbl1", type = "label", - caption="You spawn with a buddy. You must both click this together."} + caption="You spawn next to a buddy of your choosing."} end -- Some final notes @@ -290,7 +294,7 @@ function DisplaySpawnOptions(player) end -function SpawnOptsGuiOptionsSelect(event) +function SpawnOptsRadioSelect(event) if not (event and event.element and event.element.valid) then return end local elemName = event.element.name @@ -300,6 +304,18 @@ function SpawnOptsGuiOptionsSelect(event) elseif (elemName == "isolated_spawn_new_team_radio") then event.element.parent.isolated_spawn_main_team_radio.state=false end + + if (elemName == "buddy_spawn_main_team_radio") then + event.element.parent.buddy_spawn_new_team_radio.state=false + event.element.parent.buddy_spawn_buddy_team_radio.state=false + elseif (elemName == "buddy_spawn_new_team_radio") then + event.element.parent.buddy_spawn_main_team_radio.state=false + event.element.parent.buddy_spawn_buddy_team_radio.state=false + elseif (elemName == "buddy_spawn_buddy_team_radio") then + event.element.parent.buddy_spawn_main_team_radio.state=false + event.element.parent.buddy_spawn_new_team_radio.state=false + end + end @@ -347,7 +363,7 @@ function SpawnOptsGuiClick(event) if (elemName == "default_spawn_btn") then GivePlayerStarterItems(player) ChangePlayerSpawn(player, player.force.get_spawn_position(GAME_SURFACE_NAME)) - SendBroadcastMsg(player.name .. " joined the main force!") + SendBroadcastMsg(player.name .. " is joining the main force!") ChartArea(player.force, player.position, 4, player.surface) -- Create the button at the top left for setting respawn point and sharing base. CreateSpawnCtrlGui(player) @@ -383,11 +399,11 @@ function SpawnOptsGuiClick(event) ChangePlayerSpawn(player, newSpawn) -- Send the player there - SendPlayerToNewSpawnAndCreateIt(player, newSpawn, moatChoice) + QueuePlayerForDelayedSpawn(player, newSpawn, moatChoice) if (elemName == "isolated_spawn_near") then - SendBroadcastMsg(player.name .. " joined the game from a distance!") + SendBroadcastMsg(player.name .. " is joining the game from a distance!") elseif (elemName == "isolated_spawn_far") then - SendBroadcastMsg(player.name .. " joined the game from a great distance!") + SendBroadcastMsg(player.name .. " is joining the game from a great distance!") end -- Create the button at the top left for setting respawn point and sharing base. @@ -407,58 +423,10 @@ function SpawnOptsGuiClick(event) -- Hacky buddy spawn system elseif (elemName == "buddy_spawn") then + table.insert(global.waitingBuddies, player.name) + SendBroadcastMsg(player.name .. " is looking for a buddy.") - if (TableLength(global.waitingBuddies) == 0) then - table.insert(global.waitingBuddies, player.name) - SendBroadcastMsg(player.name .. " is waiting for a buddy.") - - else - buddy_name = table.remove(global.waitingBuddies) - - -- Create a new spawn point - local newSpawn = {x=0,y=0} - - -- Create a new force for player if they choose that radio button - if ENABLE_SEPARATE_TEAMS and joinOwnTeamRadio then - local newForce = CreatePlayerCustomForce(player) - local buddyForce = CreatePlayerCustomForce(game.players[buddy_name]) - - if (FRONTIER_ROCKET_SILO_MODE and newForce and buddyForce) then - ChartRocketSiloArea(newForce, game.surfaces[GAME_SURFACE_NAME]) - ChartRocketSiloArea(buddyForce, game.surfaces[GAME_SURFACE_NAME]) - end - end - - -- Find coordinates of a good place to spawn - newSpawn = FindUngeneratedCoordinates(NEAR_MIN_DIST,NEAR_MAX_DIST, player.surface) - - -- If that fails, find a random map edge in a rand direction. - if ((newSpawn.x == 0) and (newSpawn.x == 0)) then - newSpawn = FindMapEdge(GetRandomVector(), player.surface) - DebugPrint("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y) - end - - -- Create that spawn in the global vars - buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*4), y=newSpawn.y} - ChangePlayerSpawn(player, newSpawn) - ChangePlayerSpawn(game.players[buddy_name], buddySpawn) - - -- Send the player there - SendPlayerToNewSpawnAndCreateIt(player, newSpawn, moatChoice) - SendPlayerToNewSpawnAndCreateIt(game.players[buddy_name], buddySpawn, moatChoice) - SendBroadcastMsg(player.name .. " and " .. buddy_name .. " joined the game from a distance!") - - -- Create the button at the top left for setting respawn point and sharing base. - CreateSpawnCtrlGui(player) - CreateSpawnCtrlGui(game.players[buddy_name]) - - player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") - player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") - player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") - game.players[buddy_name].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") - game.players[buddy_name].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") - game.players[buddy_name].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") - end + DisplayBuddySpawnOptions(player) end end @@ -529,7 +497,7 @@ function SharedSpwnOptsGuiClick(event) SendPlayerToSpawn(player) GivePlayerStarterItems(player) table.insert(sharedSpawn.players, player.name) - SendBroadcastMsg(player.name .. " joined " .. spawnName .. "'s base!") + SendBroadcastMsg(player.name .. " is joining " .. spawnName .. "'s base!") player.force = game.players[spawnName].force if (player.gui.center.shared_spawn_opts ~= nil) then player.gui.center.shared_spawn_opts.destroy() @@ -692,3 +660,495 @@ function SpawnCtrlGuiClick(event) end end end + +-- Display the buddy spawn menu +function DisplayBuddySpawnOptions(player) + player.gui.center.add{name = "buddy_spawn_opts", + type = "frame", + direction = "vertical", + caption="Buddy Spawn Options"} + local buddyGui = player.gui.center.buddy_spawn_opts + buddyGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH + buddyGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT + + + -- Warnings and explanations... + buddyGui.add{name = "warning_lbl1", type = "label", + caption="Once a buddy accepts a spawn request, it is final!"} + buddyGui.add{name = "warning_spacer", type = "label", + caption=" "} + ApplyStyle(buddyGui.warning_lbl1, my_warning_style) + ApplyStyle(buddyGui.warning_spacer, my_spacer_style) + + buddyGui.add{name = "spawn_msg_lbl1", type = "label", + caption=SPAWN_MSG1} + buddyGui.add{name = "spawn_msg_lbl2", type = "label", + caption=SPAWN_MSG2} + buddyGui.add{name = "spawn_msg_lbl3", type = "label", + caption=SPAWN_MSG3} + buddyGui.add{name = "spawn_msg_spacer", type = "label", + caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} + ApplyStyle(buddyGui.spawn_msg_lbl1, my_label_style) + ApplyStyle(buddyGui.spawn_msg_lbl2, my_label_style) + ApplyStyle(buddyGui.spawn_msg_lbl3, my_label_style) + ApplyStyle(buddyGui.spawn_msg_spacer, my_spacer_style) + + buddyList = {} + for _,buddyName in pairs(global.waitingBuddies) do + if (buddyName ~= player.name) then + table.insert(buddyList, buddyName) + end + end + + buddyGui.add{name = "waiting_buddies_dropdown", + type = "drop-down", + caption="Waiting Buddies:", + items = buddyList} + + + buddyGui.add{name = "waiting_buddies_spacer", type = "label", + caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} + ApplyStyle(buddyGui.waiting_buddies_spacer, my_spacer_style) + + + -- The buddy spawning options. + local buddySpawnFlow = buddyGui.add{name = "spawn_buddy_flow", + type = "flow", + direction="vertical"} + + + buddySpawnFlow.add{name = "buddy_spawn_main_team_radio", + type = "radiobutton", + caption="Join Main Team (shared research)", + state=true} + buddySpawnFlow.add{name = "buddy_spawn_new_team_radio", + type = "radiobutton", + caption="Create Your Own Team (own research tree)", + state=false} + buddySpawnFlow.add{name = "buddy_spawn_buddy_team_radio", + type = "radiobutton", + caption="Create Your Own Buddy Team (buddy and you share research)", + state=false} + if (SPAWN_MOAT_CHOICE_ENABLED) then + buddySpawnFlow.add{name = "buddy_spawn_moat_option_checkbox", + type = "checkbox", + caption="Surround your spawn with a moat", + state=false} + end + + buddySpawnFlow.add{name = "buddy_options_spacer", type = "label", + caption=" "} + ApplyStyle(buddySpawnFlow.buddy_options_spacer, my_spacer_style) + + + buddySpawnFlow.add{name = "buddy_spawn_request_near", + type = "button", + caption="Request Buddy Spawn (Near)"} + buddySpawnFlow.add{name = "buddy_spawn_request_far", + type = "button", + caption="Request Buddy Spawn (Far)"} + + buddySpawnFlow.add{name = "buddy_spawn_lbl1", type = "label", + caption="You are spawned in a new area, with some starting resources."} + ApplyStyle(buddySpawnFlow.buddy_spawn_lbl1, my_label_style) + + buddyGui.add{name = "buddy_spawn_spacer", type = "label", + caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} + ApplyStyle(buddyGui.buddy_spawn_spacer, my_spacer_style) + + + buddyGui.add{name = "refresh_buddy_list", + type = "button", + caption="Refresh Buddy List"} + buddyGui.add{name = "buddy_spawn_cancel", + type = "button", + caption="Cancel (Return to Previous Options)"} + + -- Some final notes + buddyGui.add{name = "note_spacer1", type = "label", + caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} + buddyGui.add{name = "note_spacer2", type = "label", + caption=" "} + + if MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN then + buddyGui.add{name = "shared_spawn_note1", type = "label", + caption="If you create your own spawn point you can allow up to " .. MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN-1 .. " other online players to join." } + ApplyStyle(buddyGui.shared_spawn_note1, my_note_style) + end + buddyGui.add{name = "note_lbl1", type = "label", + caption="Near spawn is between " .. NEAR_MIN_DIST*CHUNK_SIZE .. "-" .. NEAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."} + buddyGui.add{name = "note_lbl2", type = "label", + caption="Far spawn is between " .. FAR_MIN_DIST*CHUNK_SIZE .. "-" .. FAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."} + buddyGui.add{name = "note_lbl3", type = "label", + caption="Buddy spawns are only 1 chunk apart."} + buddyGui.add{name = "note_spacer3", type = "label", + caption=" "} + ApplyStyle(buddyGui.note_lbl1, my_note_style) + ApplyStyle(buddyGui.note_lbl2, my_note_style) + ApplyStyle(buddyGui.note_lbl3, my_note_style) + ApplyStyle(buddyGui.note_spacer1, my_spacer_style) + ApplyStyle(buddyGui.note_spacer2, my_spacer_style) + ApplyStyle(buddyGui.note_spacer3, my_spacer_style) +end + + + +-- Handle the gui click of the spawn options +function BuddySpawnOptsGuiClick(event) + if not (event and event.element and event.element.valid) then return end + local player = game.players[event.player_index] + local elemName = event.element.name + + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + + if (player.gui.center.buddy_spawn_opts == nil) then + return -- Gui event unrelated to this gui. + end + + -- Just refresh the buddy list dropdown values only. + if (elemName == "refresh_buddy_list") then + player.gui.center.buddy_spawn_opts.waiting_buddies_dropdown.clear_items() + + for _,buddyName in pairs(global.waitingBuddies) do + if (player.name ~= buddyName) then + player.gui.center.buddy_spawn_opts.waiting_buddies_dropdown.add_item(buddyName) + end + end + return + end + + -- Handle the cancel button to exit this menu + if (elemName == "buddy_spawn_cancel") then + player.gui.center.buddy_spawn_opts.destroy() + DisplaySpawnOptions(player) + + -- Remove them from the buddy list when they cancel + for i=#global.waitingBuddies,1,-1 do + name = global.waitingBuddies[i] + if (name == player.name) then + table.remove(global.waitingBuddies, i) + end + end + end + + local joinMainTeamRadio, joinOwnTeamRadio, joinBuddyTeamRadio, moatChoice = false + local buddyChoice = nil + + -- Handle the spawn request button clicks + if ((elemName == "buddy_spawn_request_near") or + (elemName == "buddy_spawn_request_far")) then + + buddySpawnGui = player.gui.center.buddy_spawn_opts + + dropDownIndex = buddySpawnGui.waiting_buddies_dropdown.selected_index + if (dropDownIndex > 0) then + buddyChoice = buddySpawnGui.waiting_buddies_dropdown.get_item(dropDownIndex) + else + player.print("You have not selected a valid buddy! Please try again.") + return + end + + buddyIsStillWaiting = false + for _,buddyName in pairs(global.waitingBuddies) do + if (buddyChoice == buddyName) then + buddyIsStillWaiting = true + break + end + end + if (not buddyIsStillWaiting) then + player.print("Selected buddy is no longer available! Please try again.") + player.gui.center.buddy_spawn_opts.destroy() + DisplayBuddySpawnOptions(player) + return + end + + joinMainTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_main_team_radio.state + joinOwnTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_new_team_radio.state + joinBuddyTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_buddy_team_radio.state + if (SPAWN_MOAT_CHOICE_ENABLED) then + moatChoice = buddySpawnGui.spawn_buddy_flow.buddy_spawn_moat_option_checkbox.state + end + + -- Save the chosen spawn options somewhere for later use. + global.buddySpawnOptions[player.name] = {joinMainTeamRadio=joinMainTeamRadio, + joinOwnTeamRadio=joinOwnTeamRadio, + joinBuddyTeamRadio=joinBuddyTeamRadio, + moatChoice=moatChoice, + buddyChoice=buddyChoice, + distChoice=elemName} + + player.gui.center.buddy_spawn_opts.destroy() + + -- Display prompts to the players + DisplayBuddySpawnWaitMenu(player) + DisplayBuddySpawnRequestMenu(game.players[buddyChoice], player.name) + if (game.players[buddyChoice].gui.center.buddy_spawn_opts ~= nil) then + game.players[buddyChoice].gui.center.buddy_spawn_opts.destroy() + end + + -- Remove them from the buddy list while they make up their minds. + for i=#global.waitingBuddies,1,-1 do + name = global.waitingBuddies[i] + if ((name == player.name) or (name == buddyChoice)) then + table.remove(global.waitingBuddies, i) + end + end + + else + return -- Do nothing, no valid element item was clicked. + end +end + + +function DisplayBuddySpawnWaitMenu(player) + + player.gui.center.add{name = "buddy_wait_menu", + type = "frame", + direction = "vertical", + caption="Waiting for buddy to respond..."} + local sGui = player.gui.center.buddy_wait_menu + sGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH + sGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT + + + -- Warnings and explanations... + sGui.add{name = "warning_lbl1", type = "label", + caption="You will spawn once your buddy selects yes..."} + sGui.add{name = "warning_spacer", type = "label", + caption=" "} + ApplyStyle(sGui.warning_lbl1, my_warning_style) + ApplyStyle(sGui.warning_spacer, my_spacer_style) + + sGui.add{name = "cancel_buddy_wait_menu", + type = "button", + caption="Cancel (Return to starting spawn options)"} +end + +-- Handle the gui click of the buddy wait menu +function BuddySpawnWaitMenuClick(event) + if not (event and event.element and event.element.valid) then return end + local player = game.players[event.player_index] + local elemName = event.element.name + + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + + if (player.gui.center.buddy_wait_menu == nil) then + return -- Gui event unrelated to this gui. + end + + -- Check if player is cancelling the request. + if (elemName == "cancel_buddy_wait_menu") then + player.gui.center.buddy_wait_menu.destroy() + DisplaySpawnOptions(player) + + buddy = game.players[global.buddySpawnOptions[player.name].buddyChoice] + + if (buddy.gui.center.buddy_request_menu ~= nil) then + buddy.gui.center.buddy_request_menu.destroy() + end + if (buddy.gui.center.buddy_spawn ~= nil) then + buddy.gui.center.buddy_spawn_opts.destroy() + end + DisplaySpawnOptions(buddy) + + buddy.print(player.name .. " cancelled their buddy request!") + end +end + +function DisplayBuddySpawnRequestMenu(player, requestingBuddyName) + + player.gui.center.add{name = "buddy_request_menu", + type = "frame", + direction = "vertical", + caption="Buddy Request!"} + local sGui = player.gui.center.buddy_request_menu + sGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH + sGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT + + + -- Warnings and explanations... + sGui.add{name = "warning_lbl1", type = "label", + caption=requestingBuddyName .. " is requesting a buddy spawn from you!"} + sGui.add{name = "warning_spacer", type = "label", + caption=" "} + ApplyStyle(sGui.warning_lbl1, my_warning_style) + ApplyStyle(sGui.warning_spacer, my_spacer_style) + + + teamText = "error!" + if (global.buddySpawnOptions[requestingBuddyName].joinMainTeamRadio) then + teamText = "the main team" + elseif (global.buddySpawnOptions[requestingBuddyName].joinOwnTeamRadio) then + teamText = "on separate teams" + elseif (global.buddySpawnOptions[requestingBuddyName].joinBuddyTeamRadio) then + teamText = "a buddy team" + end + + moatText = " " + if (global.buddySpawnOptions[requestingBuddyName].moatChoice) then + moatText = " surrounded by a moat " + end + + distText = "error!" + if (global.buddySpawnOptions[requestingBuddyName].distChoice == "buddy_spawn_request_near") then + distText = "near to the center of the map!" + elseif (global.buddySpawnOptions[requestingBuddyName].distChoice == "buddy_spawn_request_far") then + distText = "far from the center of the map!" + end + + + requestText = requestingBuddyName .. " would like to join " .. teamText .. " next to you" .. moatText .. distText + + + sGui.add{name = "note_lbl1", type = "label", + caption=requestText} + sGui.add{name = "note_spacer1", type = "label", + caption=" "} + ApplyStyle(sGui.note_lbl1, my_note_style) + ApplyStyle(sGui.note_spacer1, my_spacer_style) + + sGui.add{name = "accept_buddy_request", + type = "button", + caption="Accept"} + sGui.add{name = "decline_buddy_request", + type = "button", + caption="Decline"} +end + +-- Handle the gui click of the buddy request menu +function BuddySpawnRequestMenuClick(event) + if not (event and event.element and event.element.valid) then return end + local player = game.players[event.player_index] + local elemName = event.element.name + + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + + if (player.gui.center.buddy_request_menu == nil) then + return -- Gui event unrelated to this gui. + end + + -- Check if it's a button press and lookup the matching buddy info + if ((elemName == "accept_buddy_request") or (elemName == "decline_buddy_request")) then + + requesterName = nil + requesterOptions = {} + for name,opts in pairs(global.buddySpawnOptions) do + if (opts.buddyChoice == player.name) then + requesterName = name + requesterOptions = opts + end + end + + if (requesterName == nil) then + player.print("Error! Invalid buddy info...") + DebugPrint("Error! Invalid buddy info...") + + player.gui.center.buddy_request_menu.destroy() + DisplaySpawnOptions(player) + end + else + return -- Not a button click + end + + + -- Check if player is cancelling the request. + if (elemName == "accept_buddy_request") then + + if (game.players[requesterName].gui.center.buddy_wait_menu ~= nil) then + game.players[requesterName].gui.center.buddy_wait_menu.destroy() + end + if (player.gui.center.buddy_request_menu ~= nil) then + player.gui.center.buddy_request_menu.destroy() + end + + -- Create a new spawn point + local newSpawn = {x=0,y=0} + + -- Create a new force for each player if they chose that option + if requesterOptions.joinOwnTeamRadio then + local newForce = CreatePlayerCustomForce(player) + local buddyForce = CreatePlayerCustomForce(game.players[requesterName]) + + if (FRONTIER_ROCKET_SILO_MODE and newForce and buddyForce) then + ChartRocketSiloArea(newForce, game.surfaces[GAME_SURFACE_NAME]) + ChartRocketSiloArea(buddyForce, game.surfaces[GAME_SURFACE_NAME]) + end + + -- Create a new force for the combined players if they chose that option + elseif requesterOptions.joinBuddyTeamRadio then + local buddyForce = CreatePlayerCustomForce(game.players[requesterName]) + player.force = buddyForce + + if (FRONTIER_ROCKET_SILO_MODE and newForce and buddyForce) then + ChartRocketSiloArea(buddyForce, game.surfaces[GAME_SURFACE_NAME]) + end + end + + -- Find coordinates of a good place to spawn + if (requesterOptions.distChoice == "buddy_spawn_request_far") then + newSpawn = FindUngeneratedCoordinates(FAR_MIN_DIST,FAR_MAX_DIST, player.surface) + elseif (requesterOptions.distChoice == "buddy_spawn_request_near") then + newSpawn = FindUngeneratedCoordinates(NEAR_MIN_DIST,NEAR_MAX_DIST, player.surface) + end + + -- If that fails, find a random map edge in a rand direction. + if ((newSpawn.x == 0) and (newSpawn.x == 0)) then + newSpawn = FindMapEdge(GetRandomVector(), player.surface) + DebugPrint("Resorting to find map edge! x=" .. newSpawn.x .. ",y=" .. newSpawn.y) + end + + -- Create that spawn in the global vars + if (requesterOptions.moatChoice) then + buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*4), y=newSpawn.y} + else + buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*3), y=newSpawn.y} + end + ChangePlayerSpawn(player, newSpawn) + ChangePlayerSpawn(game.players[requesterName], buddySpawn) + + -- Send the player there + QueuePlayerForDelayedSpawn(player, newSpawn, requesterOptions.moatChoice) + QueuePlayerForDelayedSpawn(game.players[requesterName], buddySpawn, requesterOptions.moatChoice) + SendBroadcastMsg(requesterName .. " and " .. player.name .. " are joining the game together!") + + -- Create the button at the top left for setting respawn point and sharing base. + CreateSpawnCtrlGui(player) + CreateSpawnCtrlGui(game.players[requesterName]) + + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") + player.print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") + game.players[requesterName].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!") + game.players[requesterName].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!") + game.players[requesterName].print("PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!!!") + + + end + + + if (elemName == "decline_buddy_request") then + player.gui.center.buddy_request_menu.destroy() + DisplaySpawnOptions(player) + + requesterBuddy = game.players[requesterName] + + if (requesterBuddy.gui.center.buddy_wait_menu ~= nil) then + requesterBuddy.gui.center.buddy_wait_menu.destroy() + end + if (requesterBuddy.gui.center.buddy_spawn ~= nil) then + requesterBuddy.gui.center.buddy_spawn_opts.destroy() + end + DisplaySpawnOptions(requesterBuddy) + + requesterBuddy.print(player.name .. " declined your buddy request!") + end +end From f600dfeeea046a094cc9fa85b65d306fb95071f2 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 25 Jan 2018 12:39:15 -0500 Subject: [PATCH 23/58] Trying to add in some method to allow/deny people into a shared base selectively. We'll see how it goes. Likely has some bugs. --- config.lua | 2 +- control.lua | 1 + locale/oarc_utils.lua | 18 ++++ separate_spawns_guis.lua | 212 ++++++++++++++++++++++++++++++++++----- 4 files changed, 209 insertions(+), 24 deletions(-) diff --git a/config.lua b/config.lua index ae1643d..4611892 100644 --- a/config.lua +++ b/config.lua @@ -265,7 +265,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 diff --git a/control.lua b/control.lua index c1944f1..eb3fc31 100644 --- a/control.lua +++ b/control.lua @@ -183,6 +183,7 @@ script.on_event(defines.events.on_gui_click, function(event) BuddySpawnOptsGuiClick(event) BuddySpawnWaitMenuClick(event) BuddySpawnRequestMenuClick(event) + SharedSpawnJoinWaitMenuClick(event) end end) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 4cd620b..fd849a4 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -114,6 +114,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() @@ -274,6 +281,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) + 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) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 7635a9e..9faca09 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -6,7 +6,7 @@ require("separate_spawns") local SPAWN_GUI_MAX_WIDTH = 550 -local SPAWN_GUI_MAX_HEIGHT = 750 +local SPAWN_GUI_MAX_HEIGHT = 800 -- Use this for testing shared spawns... -- local sharedSpawnExample1 = {openAccess=true, @@ -16,11 +16,11 @@ local SPAWN_GUI_MAX_HEIGHT = 750 -- position={x=200,y=200}, -- players={"ABC", "DEF"}} -- local sharedSpawnExample3 = {openAccess=true, --- owner="testName1", +-- position={x=400,y=400}, -- players={"A", "B", "C", "D"}} -- global.sharedSpawns = {testName1=sharedSpawnExample1, -- testName2=sharedSpawnExample2, --- testName3=sharedSpawnExample3} +-- Oarc=sharedSpawnExample3} -- A display gui message @@ -447,7 +447,9 @@ function DisplaySharedSpawnOptions(player) for spawnName,sharedSpawn in pairs(global.sharedSpawns) do - if sharedSpawn.openAccess then + if (sharedSpawn.openAccess and + (game.players[spawnName] ~= nil) and + game.players[spawnName].connected) then local spotsRemaining = MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN - GetOnlinePlayersAtSharedSpawn(spawnName) if (spotsRemaining > 0) then shGui.add{type="button", caption=spawnName .. " (" .. spotsRemaining .. " spots remaining)", name=spawnName} @@ -492,24 +494,94 @@ function SharedSpwnOptsGuiClick(event) -- If a spawn is removed during this time, the button will not do anything else for spawnName,sharedSpawn in pairs(global.sharedSpawns) do - if ((buttonClicked == spawnName) and (game.players[spawnName] ~= nil)) then - ChangePlayerSpawn(player,sharedSpawn.position) - SendPlayerToSpawn(player) - GivePlayerStarterItems(player) - table.insert(sharedSpawn.players, player.name) - SendBroadcastMsg(player.name .. " is joining " .. spawnName .. "'s base!") - player.force = game.players[spawnName].force + if ((buttonClicked == spawnName) and + (game.players[spawnName] ~= nil) and + (game.players[spawnName].connected)) then + + -- Add the player to that shared spawns join queue. + if (global.sharedSpawns[spawnName].joinQueue == nil) then + global.sharedSpawns[spawnName].joinQueue = {} + end + table.insert(global.sharedSpawns[spawnName].joinQueue, player.name) + + -- Clear the shared spawn options gui. if (player.gui.center.shared_spawn_opts ~= nil) then player.gui.center.shared_spawn_opts.destroy() end - -- Create the button at the top left for setting respawn point and sharing base. - CreateSpawnCtrlGui(player) + + -- Display wait menu with cancel button. + DisplaySharedSpawnJoinWaitMenu(player) + + -- Tell other player they are requesting a response. + game.players[spawnName].print(player.name .. " is requesting to join your base!") break end end end end +function DisplaySharedSpawnJoinWaitMenu(player) + + player.gui.center.add{name = "join_shared_spawn_wait_menu", + type = "frame", + direction = "vertical", + caption="Waiting for spawn owner to respond..."} + local sGui = player.gui.center.join_shared_spawn_wait_menu + sGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH + sGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT + + + -- Warnings and explanations... + sGui.add{name = "warning_lbl1", type = "label", + caption="You will spawn once the host selects yes..."} + sGui.add{name = "warning_spacer", type = "label", + caption=" "} + ApplyStyle(sGui.warning_lbl1, my_warning_style) + ApplyStyle(sGui.warning_spacer, my_spacer_style) + + sGui.add{name = "cancel_shared_spawn_wait_menu", + type = "button", + caption="Cancel (Return to starting spawn options)"} +end + +-- Handle the gui click of the buddy wait menu +function SharedSpawnJoinWaitMenuClick(event) + if not (event and event.element and event.element.valid) then return end + local player = game.players[event.player_index] + local elemName = event.element.name + + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + + if (player.gui.center.join_shared_spawn_wait_menu == nil) then + return -- Gui event unrelated to this gui. + end + + -- Check if player is cancelling the request. + if (elemName == "cancel_shared_spawn_wait_menu") then + player.gui.center.join_shared_spawn_wait_menu.destroy() + DisplaySpawnOptions(player) + + -- Find and remove the player from the joinQueue they were in. + for spawnName,sharedSpawn in pairs(global.sharedSpawns) do + if (sharedSpawn.joinQueue ~= nil) then + for index,requestingPlayer in pairs(sharedSpawn.joinQueue) do + if (requestingPlayer == player.name) then + table.remove(global.sharedSpawns[spawnName].joinQueue, index) + game.players[spawnName].print(player.name .. " cancelled their request to join your spawn.") + return + end + end + end + end + + DebugPrint("ERROR! Failed to remove player from joinQueue!") + player.print("ERROR! Failed to remove player from joinQueue!") + end +end + function CreateSpawnCtrlGui(player) if player and (player.gui.top.spwn_ctrls == nil) then @@ -595,6 +667,34 @@ function ExpandSpawnCtrlGui(player, tick) ApplyStyle(spwnCtrls.respawn_cooldown_note2, my_note_style) ApplyStyle(spwnCtrls.respawn_cooldown_spacer1, my_spacer_style) end + + -- Display a list of people in the join queue for your base. + if (ENABLE_SHARED_SPAWNS and IsSharedSpawnActive(player)) then + if ((global.sharedSpawns[player.name].joinQueue ~= nil) and + (#global.sharedSpawns[player.name].joinQueue > 0)) then + + spwnCtrls.add{name = "drop_down_msg_lbl1", type = "label", + caption="Select a player from the join queue:"} + spwnCtrls.add{name = "join_queue_dropdown", + type = "drop-down", + items = global.sharedSpawns[player.name].joinQueue} + spwnCtrls.add{name = "accept_player_request", + type = "button", + caption="Accept"} + spwnCtrls.add{name = "reject_player_request", + type = "button", + caption="Reject"} + ApplyStyle(spwnCtrls.drop_down_msg_lbl1, my_label_style) + else + spwnCtrls.add{name = "empty_join_queue_note1", type = "label", + caption="You have no players requesting to join you at this time."} + + ApplyStyle(spwnCtrls.empty_join_queue_note1, my_note_style) + end + spwnCtrls.add{name = "join_queue_spacer", type = "label", + caption=" "} + ApplyStyle(spwnCtrls.join_queue_spacer, my_spacer_style) + end end end @@ -610,6 +710,7 @@ function SpawnCtrlGuiOptionsSelect(event) return end + -- Handle changes to spawn sharing. if (name == "accessToggle") then if event.element.state then if DoesPlayerHaveCustomSpawn(player) then @@ -634,15 +735,15 @@ function SpawnCtrlGuiClick(event) if not (event and event.element and event.element.valid) then return end local player = game.players[event.element.player_index] - local name = event.element.name + local elemName = event.element.name if not player then DebugPrint("Another gui click happened with no valid player...") return end - if (name == "spwn_ctrls") then - ExpandSpawnCtrlGui(player, event.tick) + if (elemName == "spwn_ctrls") then + ExpandSpawnCtrlGui(player, event.tick) end if (event.element.parent) then @@ -652,13 +753,78 @@ function SpawnCtrlGuiClick(event) end -- Sets a new respawn point and resets the cooldown. - if (name == "setRespawnLocation") then + if (elemName == "setRespawnLocation") then if DoesPlayerHaveCustomSpawn(player) then ChangePlayerSpawn(player, player.position) ExpandSpawnCtrlGui(player, event.tick) player.print("Re-spawn point updated!") end end + + -- Accept or reject pending player join requests to a shared base + if ((elemName == "accept_player_request") or (elemName == "reject_player_request")) then + + if ((event.element.parent.join_queue_dropdown == nil) or + (event.element.parent.join_queue_dropdown.selected_index == 0)) then + player.print("Selected player is no longer waiting to join!") + ExpandSpawnCtrlGui(player, event.tick) + return + end + + joinQueueIndex = event.element.parent.join_queue_dropdown.selected_index + joinQueuePlayerChoice = event.element.parent.join_queue_dropdown.get_item(joinQueueIndex) + + if ((game.players[joinQueuePlayerChoice] == nil) or + (not game.players[joinQueuePlayerChoice].connected)) then + player.print("Selected player is no longer waiting to join!") + ExpandSpawnCtrlGui(player, event.tick) + return + end + + if (elemName == "reject_player_request") then + player.print("You rejected " .. joinQueuePlayerChoice .. "'s request to join your base.") + SendMsg(joinQueuePlayerChoice, "Your request to join was rejected.") + + + game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu.destroy() + DisplaySpawnOptions(game.players[joinQueuePlayerChoice]) + + -- Find and remove the player from the joinQueue they were in. + for index,requestingPlayer in pairs(global.sharedSpawns[player.name].joinQueue) do + if (requestingPlayer == joinQueuePlayerChoice) then + table.remove(global.sharedSpawns[player.name].joinQueue, index) + return + end + end + + elseif (elemName == "accept_player_request") then + + -- Send an announcement + SendBroadcastMsg(joinQueuePlayerChoice .. " is joining " .. player.name .. "'s base!") + + -- Close the waiting players menu + game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu.destroy() + + -- Find and remove the player from the joinQueue they were in. + for index,requestingPlayer in pairs(global.sharedSpawns[player.name].joinQueue) do + if (requestingPlayer == joinQueuePlayerChoice) then + table.remove(global.sharedSpawns[player.name].joinQueue, index) + end + end + + -- Spawn the player + joiningPlayer = game.players[joinQueuePlayerChoice] + ChangePlayerSpawn(joiningPlayer, global.sharedSpawns[player.name].position) + SendPlayerToSpawn(joiningPlayer) + GivePlayerStarterItems(joiningPlayer) + table.insert(global.sharedSpawns[player.name].players, joiningPlayer.name) + joiningPlayer.force = game.players[player.name].force + + -- Create the button at the top left for setting respawn point and sharing base. + CreateSpawnCtrlGui(joiningPlayer) + ExpandSpawnCtrlGui(player, event.tick) + end + end end -- Display the buddy spawn menu @@ -700,14 +866,17 @@ function DisplayBuddySpawnOptions(player) end end + buddyGui.add{name = "drop_down_msg_lbl1", type = "label", + caption="Select a buddy from the waiting list:"} buddyGui.add{name = "waiting_buddies_dropdown", type = "drop-down", - caption="Waiting Buddies:", items = buddyList} - - + buddyGui.add{name = "refresh_buddy_list", + type = "button", + caption="Refresh Buddy List"} buddyGui.add{name = "waiting_buddies_spacer", type = "label", caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} + ApplyStyle(buddyGui.drop_down_msg_lbl1, my_label_style) ApplyStyle(buddyGui.waiting_buddies_spacer, my_spacer_style) @@ -757,9 +926,6 @@ function DisplayBuddySpawnOptions(player) ApplyStyle(buddyGui.buddy_spawn_spacer, my_spacer_style) - buddyGui.add{name = "refresh_buddy_list", - type = "button", - caption="Refresh Buddy List"} buddyGui.add{name = "buddy_spawn_cancel", type = "button", caption="Cancel (Return to Previous Options)"} From 0b83e24c355eb60f39fc8c9e0f3fb9f59634b605 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 25 Jan 2018 13:08:48 -0500 Subject: [PATCH 24/58] Fixed broken MergeForcesKeepResearch function. Forgot it hadn't been tested yet... --- locale/oarc_utils.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index fd849a4..edae6ef 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -283,7 +283,7 @@ end -- Merges force2 INTO force1 but keeps all research between both forces. function MergeForcesKeepResearch(force1, force2) - for techName,luaTech in pairs(force2.technologies) + for techName,luaTech in pairs(force2.technologies) do if (luaTech.researched) then force1.technologies[techName].researched = true force1.technologies[techName].level = luaTech.level From b5d09f63ba4a9ea73f04a6ea3e83fb5e973ab0b0 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 25 Jan 2018 16:28:09 -0500 Subject: [PATCH 25/58] Removed unused RSO file... Fixed regrowth so that resources come back at random positions. --- locale/rso/drand.lua | 269 ------------------------------------- locale/rso/rso_control.lua | 7 +- 2 files changed, 5 insertions(+), 271 deletions(-) delete mode 100644 locale/rso/drand.lua diff --git a/locale/rso/drand.lua b/locale/rso/drand.lua deleted file mode 100644 index d907c57..0000000 --- a/locale/rso/drand.lua +++ /dev/null @@ -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 \ No newline at end of file diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua index 7aff2f0..b47d4d5 100644 --- a/locale/rso/rso_control.lua +++ b/locale/rso/rso_control.lua @@ -149,7 +149,7 @@ local function rng_for_reg_pos(pos) local seed = normalize( valX * valY * global.seed ) rng.re_seed( seed ) - -- debug("Generator for " .. pos.x .. "," .. pos.y .. " created with seed " .. seed .. " x:" .. valX .. " y:" .. valY) + debug("Generator for " .. pos.x .. "," .. pos.y .. " created with seed " .. seed .. " x:" .. valX .. " y:" .. valY) return rng end @@ -1243,13 +1243,16 @@ local function roll_region(c_x, c_y) -- if (not (global.regions[r_x] and global.regions[r_x][r_y]) or regrow_rso) then - if global.regions[r_x] and global.regions[r_x][r_y] then + if (global.regions[r_x] and global.regions[r_x][r_y] and not regrow_rso) then r_data = global.regions[r_x][r_y] else --if this chunk is the first in its region to be generated if not global.regions[r_x] then global.regions[r_x] = {} end global.regions[r_x][r_y]={} r_data = global.regions[r_x][r_y] + if (regrow_rso and not deterministic) then + global.seed = math.random(0,4294967295) + end rng = rng_for_reg_pos{x=r_x,y=r_y} local rollCount = math.ceil(#configIndexed / 10) - 1 -- 0 based counter is more convenient here From 99a3e1a4c4fb77627b299c843db5e4b696e84bae Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 26 Jan 2018 20:41:02 -0500 Subject: [PATCH 26/58] Fixing a crash on player exit. --- config.lua | 4 ++-- separate_spawns.lua | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config.lua b/config.lua index 4611892..af601a9 100644 --- a/config.lua +++ b/config.lua @@ -36,7 +36,7 @@ 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 = false -- This should be false for you, it's just a convenience for me. +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!" @@ -59,7 +59,7 @@ ENABLE_BUDDY_SPAWN = true ENABLE_RSO = true -- Frontier style rocket silo mode -FRONTIER_ROCKET_SILO_MODE = false +FRONTIER_ROCKET_SILO_MODE = true -- Enable Undecorator -- Removes decorative items to reduce save file size. diff --git a/separate_spawns.lua b/separate_spawns.lua index 4eb617a..626ab0e 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -69,6 +69,8 @@ function FindUnusedSpawns(event) -- If a uniqueSpawn was created for the player, mark it as unused. if (global.uniqueSpawns[player.name] ~= nil) then + local spawnPos = global.uniqueSpawns[player.name].pos + -- Check if it was near someone else's base. nearOtherSpawn = false for _,otherSpawnPos in pairs(global.uniqueSpawns) do @@ -78,7 +80,6 @@ function FindUnusedSpawns(event) end if (ENABLE_ABANDONED_BASE_REMOVAL and not nearOtherSpawn) then - local spawnPos = global.uniqueSpawns[player.name].pos 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.") From c4278c51cb1ba1a61a7a92a781cc4d10cfd50794 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 26 Jan 2018 20:42:17 -0500 Subject: [PATCH 27/58] Returning some config settings to their old defaults. --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index af601a9..6ff149b 100644 --- a/config.lua +++ b/config.lua @@ -63,7 +63,7 @@ FRONTIER_ROCKET_SILO_MODE = true -- Enable Undecorator -- Removes decorative items to reduce save file size. -ENABLE_UNDECORATOR = false +ENABLE_UNDECORATOR = true -- Enable Tags ENABLE_TAGS = true From 4052c85731713a1857d8ccf3e86c6c56e2da431e Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 26 Jan 2018 20:43:24 -0500 Subject: [PATCH 28/58] Add extra crash warning in welcome msg lol. --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index 6ff149b..2e9e631 100644 --- a/config.lua +++ b/config.lua @@ -18,7 +18,7 @@ WELCOME_MSG1 = "Rules: Be polite. Ask before changing other players's stuff. Hav WELCOME_MSG2 = "This server is running a custom scenario that changes spawn locations." OTHER_MSG1 = "Latest updates in this scenario version:" -OTHER_MSG2 = "0.16 experimental release. Now with BUDDY SPAWN system." +OTHER_MSG2 = "0.16 experimental release. Now with BUDDY SPAWN system. MAY BE BUGGY AND CRASH!" -- 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." From 3b538183f3bf34b3c21757dc30e900a78f268e28 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 26 Jan 2018 20:47:10 -0500 Subject: [PATCH 29/58] Previous change didn't fix the player leaving crash. This should. --- separate_spawns.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index 626ab0e..d26fdfb 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -74,7 +74,7 @@ function FindUnusedSpawns(event) -- Check if it was near someone else's base. nearOtherSpawn = false for _,otherSpawnPos in pairs(global.uniqueSpawns) do - if (getDistance(spawnPos, otherSpawnPos) < (CHUNK_SIZE*10)) then + if (getDistance(spawnPos, otherSpawnPos.pos) < (CHUNK_SIZE*10)) then nearOtherSpawn = true end end From 5b87f9e369ca28ee91c83233482592cb78fe0350 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 10:02:45 -0500 Subject: [PATCH 30/58] Fixing another issue on player's leaving too quickly before they finish spawning. --- separate_spawns.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index d26fdfb..a4e6570 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -70,7 +70,7 @@ function FindUnusedSpawns(event) if (global.uniqueSpawns[player.name] ~= nil) then local spawnPos = global.uniqueSpawns[player.name].pos - + -- Check if it was near someone else's base. nearOtherSpawn = false for _,otherSpawnPos in pairs(global.uniqueSpawns) do @@ -273,7 +273,9 @@ function DelayedSpawnOnTick() delayedSpawn = global.delayedSpawns[i] if (delayedSpawn.delayedTick < game.tick) then - SendPlayerToNewSpawnAndCreateIt(delayedSpawn.player, delayedSpawn.spawn, delayedSpawn.moatEnabled) + if ((delayedSpawn.player ~= nil) and (delayedSpawn.player.connected)) then + SendPlayerToNewSpawnAndCreateIt(delayedSpawn.player, delayedSpawn.spawn, delayedSpawn.moatEnabled) + end table.remove(global.delayedSpawns, i) end end From 0771360b848ebe02bb9c669553ac14ca7b0eb1c8 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 10:09:03 -0500 Subject: [PATCH 31/58] Still trying to fix player leaving too early. --- separate_spawns.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index a4e6570..33b7635 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -273,7 +273,7 @@ function DelayedSpawnOnTick() delayedSpawn = global.delayedSpawns[i] if (delayedSpawn.delayedTick < game.tick) then - if ((delayedSpawn.player ~= nil) and (delayedSpawn.player.connected)) then + if (delayedSpawn.player ~= nil) then SendPlayerToNewSpawnAndCreateIt(delayedSpawn.player, delayedSpawn.spawn, delayedSpawn.moatEnabled) end table.remove(global.delayedSpawns, i) From db737a2d8f531a15064bc652a6a2277956eed910 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 10:24:38 -0500 Subject: [PATCH 32/58] Should probably pass around the player name instead of the LuaPlayer object. --- separate_spawns.lua | 14 +++++++------- separate_spawns_guis.lua | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index 33b7635..cb63e26 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -245,7 +245,7 @@ function ChangePlayerSpawn(player, pos) global.playerCooldowns[player.name] = {setRespawn=game.tick} end -function QueuePlayerForDelayedSpawn(player, spawn, moatEnabled) +function QueuePlayerForDelayedSpawn(playerName, spawn, moatEnabled) -- If we get a valid spawn point, setup the area if ((spawn.x ~= 0) and (spawn.y ~= 0)) then @@ -254,7 +254,7 @@ function QueuePlayerForDelayedSpawn(player, spawn, moatEnabled) player.print("Generating your spawn now, please wait 10 seconds...") player.surface.request_to_generate_chunks(spawn, 4) delayedTick = game.tick + 10*TICKS_PER_SECOND - table.insert(global.delayedSpawns, {player=player, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick}) + table.insert(global.delayedSpawns, {playerName=playerName, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick}) else DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!") @@ -273,8 +273,8 @@ function DelayedSpawnOnTick() delayedSpawn = global.delayedSpawns[i] if (delayedSpawn.delayedTick < game.tick) then - if (delayedSpawn.player ~= nil) then - SendPlayerToNewSpawnAndCreateIt(delayedSpawn.player, delayedSpawn.spawn, delayedSpawn.moatEnabled) + if (game.players[delayedSpawn.playerName] ~= nil) then + SendPlayerToNewSpawnAndCreateIt(delayedSpawn.playerName, delayedSpawn.spawn, delayedSpawn.moatEnabled) end table.remove(global.delayedSpawns, i) end @@ -283,7 +283,7 @@ function DelayedSpawnOnTick() end end -function SendPlayerToNewSpawnAndCreateIt(player, spawn, moatEnabled) +function SendPlayerToNewSpawnAndCreateIt(playerName, spawn, moatEnabled) -- Make sure the area is super safe. ClearNearbyEnemies(spawn, SAFE_AREA_TILE_DIST, game.surfaces[GAME_SURFACE_NAME]) @@ -298,8 +298,8 @@ function SendPlayerToNewSpawnAndCreateIt(player, spawn, moatEnabled) GenerateStartingResources(surface, spawn) -- Send the player to that position - player.teleport(spawn, GAME_SURFACE_NAME) - GivePlayerStarterItems(player) + game.players[playerName].teleport(spawn, GAME_SURFACE_NAME) + GivePlayerStarterItems(game.players[playerName]) end function SendPlayerToSpawn(player) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 9faca09..90dfc46 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -399,7 +399,7 @@ function SpawnOptsGuiClick(event) ChangePlayerSpawn(player, newSpawn) -- Send the player there - QueuePlayerForDelayedSpawn(player, newSpawn, moatChoice) + QueuePlayerForDelayedSpawn(player.name, newSpawn, moatChoice) if (elemName == "isolated_spawn_near") then SendBroadcastMsg(player.name .. " is joining the game from a distance!") elseif (elemName == "isolated_spawn_far") then @@ -1282,8 +1282,8 @@ function BuddySpawnRequestMenuClick(event) ChangePlayerSpawn(game.players[requesterName], buddySpawn) -- Send the player there - QueuePlayerForDelayedSpawn(player, newSpawn, requesterOptions.moatChoice) - QueuePlayerForDelayedSpawn(game.players[requesterName], buddySpawn, requesterOptions.moatChoice) + QueuePlayerForDelayedSpawn(player.name, newSpawn, requesterOptions.moatChoice) + QueuePlayerForDelayedSpawn(requesterName, buddySpawn, requesterOptions.moatChoice) SendBroadcastMsg(requesterName .. " and " .. player.name .. " are joining the game together!") -- Create the button at the top left for setting respawn point and sharing base. From eb76918838d1ec249f34da843fe0cc2d66add99d Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 10:29:06 -0500 Subject: [PATCH 33/58] Had to fix some other player references that should be player names as well. --- separate_spawns.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index cb63e26..93d3cb6 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -249,16 +249,16 @@ 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} + global.uniqueSpawns[playerName] = {pos=spawn,moat=moatEnabled} - player.print("Generating your spawn now, please wait 10 seconds...") - player.surface.request_to_generate_chunks(spawn, 4) + game.players[playerName].print("Generating your spawn now, please wait 10 seconds...") + game.players[playerName].surface.request_to_generate_chunks(spawn, 4) delayedTick = game.tick + 10*TICKS_PER_SECOND table.insert(global.delayedSpawns, {playerName=playerName, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick}) else DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!") - SendBroadcastMsg("ERROR!! Failed to create spawn point for: " .. player.name) + SendBroadcastMsg("ERROR!! Failed to create spawn point for: " .. playerName) end end From bd65e3ddb2b671eb4db8094cd8c903202a41430e Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 10:41:47 -0500 Subject: [PATCH 34/58] Testing player exit and cleanup of a delayed spawn. Debugging now, haven't fixed yet. --- config.lua | 2 +- separate_spawns.lua | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/config.lua b/config.lua index 2e9e631..77597ac 100644 --- a/config.lua +++ b/config.lua @@ -368,4 +368,4 @@ global.clMapGen.cliff_settings={cliff_elevation_0=10, cliff_elevation_interval=1 -------------------------------------------------------------------------------- -- DEBUG prints for me -global.oarcDebugEnabled = false +global.oarcDebugEnabled = true diff --git a/separate_spawns.lua b/separate_spawns.lua index 93d3cb6..3d952e2 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -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 @@ -75,6 +85,7 @@ function FindUnusedSpawns(event) nearOtherSpawn = false for _,otherSpawnPos in pairs(global.uniqueSpawns) do if (getDistance(spawnPos, otherSpawnPos.pos) < (CHUNK_SIZE*10)) then + DebugPrint("Won't remove base as it's close to another spawn.") nearOtherSpawn = true end end From 993fa6ee1bcf9bcb26e9aca6cfaca8bab96e4741 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 10:49:15 -0500 Subject: [PATCH 35/58] Trying to debug base cleanup. --- separate_spawns.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index 3d952e2..eb1e155 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -83,11 +83,12 @@ function FindUnusedSpawns(event) -- Check if it was near someone else's base. nearOtherSpawn = false - for _,otherSpawnPos in pairs(global.uniqueSpawns) do + for spawnPlayerName,otherSpawnPos in pairs(global.uniqueSpawns) do if (getDistance(spawnPos, otherSpawnPos.pos) < (CHUNK_SIZE*10)) then DebugPrint("Won't remove base as it's close to another spawn.") nearOtherSpawn = true end + DebugPrint("Checking distance to spawn: " .. spawnPlayerName) end if (ENABLE_ABANDONED_BASE_REMOVAL and not nearOtherSpawn) then From 295c746e927f966a2795b9096cc190e471be954c Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 10:53:27 -0500 Subject: [PATCH 36/58] I think I found the issue with the base cleanup, it was checking distance to the nearest spawn and always matching the same player who was leaving. --- separate_spawns.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index eb1e155..6d1cf6a 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -84,7 +84,7 @@ function FindUnusedSpawns(event) -- Check if it was near someone else's base. nearOtherSpawn = false for spawnPlayerName,otherSpawnPos in pairs(global.uniqueSpawns) do - if (getDistance(spawnPos, otherSpawnPos.pos) < (CHUNK_SIZE*10)) then + if ((spawnPlayerName ~= player.name) and (getDistance(spawnPos, otherSpawnPos.pos) < (CHUNK_SIZE*10))) then DebugPrint("Won't remove base as it's close to another spawn.") nearOtherSpawn = true end From 7179e44a1ed3d8d577f42ac49d399fd7d37ebe5e Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 11:07:27 -0500 Subject: [PATCH 37/58] Fix some of the config welcome messages. --- config.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.lua b/config.lua index 77597ac..b9cc8bf 100644 --- a/config.lua +++ b/config.lua @@ -18,10 +18,10 @@ WELCOME_MSG1 = "Rules: Be polite. Ask before changing other players's stuff. Hav WELCOME_MSG2 = "This server is running a custom scenario that changes spawn locations." OTHER_MSG1 = "Latest updates in this scenario version:" -OTHER_MSG2 = "0.16 experimental release. Now with BUDDY SPAWN system. MAY BE BUGGY AND CRASH!" +OTHER_MSG2 = "0.16 experimental release. New spawning permissions and buddy spawns." -- 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_MSG3 = "This scenario gives you or your friends your own starting area." +OTHER_MSG4 = "You can be on the main team or your own. All teams are friendly." OTHER_MSG5 = "If you leave in the first 15 minutes, your base and character will be deleted!" From 4c89f759087cf7f5aada02f5691a4bf011866ddc Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 27 Jan 2018 11:07:54 -0500 Subject: [PATCH 38/58] Add a dialog to tell players to wait while their spawn is created. --- separate_spawns.lua | 9 +++++++-- separate_spawns_guis.lua | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index 6d1cf6a..d5c262a 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -85,10 +85,9 @@ function FindUnusedSpawns(event) nearOtherSpawn = false for spawnPlayerName,otherSpawnPos in pairs(global.uniqueSpawns) do if ((spawnPlayerName ~= player.name) and (getDistance(spawnPos, otherSpawnPos.pos) < (CHUNK_SIZE*10))) then - DebugPrint("Won't remove base as it's close to another spawn.") + DebugPrint("Won't remove base as it's close to another spawn: " .. spawnPlayerName) nearOtherSpawn = true end - DebugPrint("Checking distance to spawn: " .. spawnPlayerName) end if (ENABLE_ABANDONED_BASE_REMOVAL and not nearOtherSpawn) then @@ -268,6 +267,8 @@ function QueuePlayerForDelayedSpawn(playerName, spawn, moatEnabled) delayedTick = game.tick + 10*TICKS_PER_SECOND table.insert(global.delayedSpawns, {playerName=playerName, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick}) + DisplayPleaseWaitForSpawnDialog(game.players[playerName]) + else DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!") SendBroadcastMsg("ERROR!! Failed to create spawn point for: " .. playerName) @@ -312,6 +313,10 @@ function SendPlayerToNewSpawnAndCreateIt(playerName, spawn, moatEnabled) -- Send the player to that position game.players[playerName].teleport(spawn, GAME_SURFACE_NAME) GivePlayerStarterItems(game.players[playerName]) + + if (game.players[playerName].gui.center.wait_for_spawn_dialog ~= nil) then + game.players[playerName].gui.center.wait_for_spawn_dialog.destroy() + end end function SendPlayerToSpawn(player) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 90dfc46..eeb5d7e 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -1318,3 +1318,31 @@ function BuddySpawnRequestMenuClick(event) requesterBuddy.print(player.name .. " declined your buddy request!") end end + + +function DisplayPleaseWaitForSpawnDialog(player) + + player.gui.center.add{name = "wait_for_spawn_dialog", + type = "frame", + direction = "vertical", + caption="Please wait!"} + local pleaseWaitGui = player.gui.center.wait_for_spawn_dialog + pleaseWaitGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH + pleaseWaitGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT + + + -- Warnings and explanations... + pleaseWaitGui.add{name = "warning_lbl1", type = "label", + caption="Your spawn is being created now."} + pleaseWaitGui.add{name = "warning_lbl2", type = "label", + caption="You will be teleported there in about 10 seconds!"} + pleaseWaitGui.add{name = "warning_lbl3", type = "label", + caption="Please standby..."} + pleaseWaitGui.add{name = "warning_spacer", type = "label", + caption=" "} + ApplyStyle(pleaseWaitGui.warning_lbl1, my_warning_style) + ApplyStyle(pleaseWaitGui.warning_lbl2, my_warning_style) + ApplyStyle(pleaseWaitGui.warning_lbl3, my_warning_style) + ApplyStyle(pleaseWaitGui.warning_spacer, my_spacer_style) + +end \ No newline at end of file From 5ee691072630b53da2ea1d49079d0718369cd69a Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Wed, 31 Jan 2018 23:31:33 -0500 Subject: [PATCH 39/58] Feedback from Philip and his mods added in where possible. Added an Info button with an admin ban button hidden inside. Added option for more silos. Cleanedup separate teams options and disabling of radio buttons. --- config.lua | 78 +++++--- control.lua | 22 ++- locale/frontier_silo.lua | 352 ++++++++++++++++++++++++++++++------- locale/game_opts.lua | 194 ++++++++++++++++++++ locale/oarc_utils.lua | 63 ++++--- locale/tag.lua | 3 +- locale/temp/rgcommand.lua | 49 ++++++ locale/temp/runcommand.lua | 44 +++++ separate_spawns.lua | 82 +++------ separate_spawns_guis.lua | 91 ++++++---- 10 files changed, 752 insertions(+), 226 deletions(-) create mode 100644 locale/game_opts.lua create mode 100644 locale/temp/rgcommand.lua create mode 100644 locale/temp/runcommand.lua diff --git a/config.lua b/config.lua index b9cc8bf..eb7fc25 100644 --- a/config.lua +++ b/config.lua @@ -80,9 +80,9 @@ ENABLE_PLAYER_LIST = true -- 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 @@ -105,7 +105,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}, @@ -143,12 +143,12 @@ PLAYER_RESPAWN_START_ITEMS = { CHECK_SPAWN_UNGENERATED_CHUNKS_RADIUS = 5 -- Near Distance in chunks -NEAR_MIN_DIST = 0 --50 -NEAR_MAX_DIST = 50 --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 @@ -207,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 @@ -255,7 +259,7 @@ ENABLE_DEFAULT_SPAWN = false -- 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 @@ -270,7 +274,7 @@ RESPAWN_COOLDOWN_TICKS = TICKS_PER_MINUTE * RESPAWN_COOLDOWN_IN_MINUTES -- Require playes to be online for at least 5 minutes -- Else their character is removed and their spawn point is freed up for use -MIN_ONLINE_TIME_IN_MINUTES = 10 +MIN_ONLINE_TIME_IN_MINUTES = 15 MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES @@ -279,28 +283,38 @@ MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES -------------------------------------------------------------------------------- -- Enable/Disable enemy expansion -ENEMY_EXPANSION = true +ENEMY_EXPANSION = false -- Divide the alien evolution factors by this number to reduce it (or multiply if < 1) -ENEMY_TIME_FACTOR_DISABLE = true -- Set this to true to disable time based evolution completely. -ENEMY_TIME_FACTOR_DIVISOR = 1 -ENEMY_POLLUTION_FACTOR_DISABLE = true -- Set this to true to disable pollution based evolution completely. -ENEMY_POLLUTION_FACTOR_DIVISOR = 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 = 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 +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 = 100 --- 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 @@ -363,9 +377,19 @@ global.clMapGen.autoplace_controls = { -- 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 = 3 * TICKS_PER_MINUTE -- set to 0 for infinite ghost life + ------------------------------------------------------------------------------- -- DEBUG -------------------------------------------------------------------------------- -- DEBUG prints for me -global.oarcDebugEnabled = true +global.oarcDebugEnabled = false diff --git a/control.lua b/control.lua index eb3fc31..0552e19 100644 --- a/control.lua +++ b/control.lua @@ -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/runcommand") -- Main Configuration File require("config") @@ -103,14 +109,14 @@ 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 SetServerWelcomeMessages() @@ -186,6 +192,8 @@ script.on_event(defines.events.on_gui_click, function(event) SharedSpawnJoinWaitMenuClick(event) end + GameOptionsGuiClick(event) + end) script.on_event(defines.events.on_gui_checked_state_changed, function (event) @@ -210,6 +218,8 @@ script.on_event(defines.events.on_player_joined_game, function(event) if ENABLE_TAGS then CreateTagGui(event) end + + CreateGameOptionsGui(event) end) script.on_event(defines.events.on_player_created, function(event) @@ -287,6 +297,10 @@ script.on_event(defines.events.on_tick, function(event) DelayedSpawnOnTick() end + if FRONTIER_ROCKET_SILO_MODE then + DelayedSiloCreationOnTick() + end + end) diff --git a/locale/frontier_silo.lua b/locale/frontier_silo.lua index 1336edf..e4d1d75 100644 --- a/locale/frontier_silo.lua +++ b/locale/frontier_silo.lua @@ -1,85 +1,303 @@ -- 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-1", 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 + + -- 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 - - -- Remove trees/resources inside the spawn area - RemoveInCircle(surface, chunkArea, "tree", global.siloPosition, ENFORCE_LAND_AREA_TILE_DIST+5) - RemoveInCircle(surface, chunkArea, "resource", global.siloPosition, ENFORCE_LAND_AREA_TILE_DIST+5) - RemoveInCircle(surface, chunkArea, "cliff", global.siloPosition, ENFORCE_LAND_AREA_TILE_DIST+5) - RemoveDecorationsArea(surface, chunkArea) - - -- Create rocket silo - CreateRocketSilo(surface, chunkArea, MAIN_FORCE) - CreateCropOctagon(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) + + -- All silo chunk generate events should be done within the first minute. + if (game.tick < 1*TICKS_PER_MINUTE) 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-150, + y=siloPos.y-150}, + right_bottom= + {x=siloPos.x+150, + y=siloPos.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 + 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, 40) + 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 + game.forces[MAIN_FORCE].chart(surface, {{siloPos.x-(CHUNK_SIZE*2), + siloPos.y-(CHUNK_SIZE*2)}, + {siloPos.x+(CHUNK_SIZE*2), + siloPos.y+(CHUNK_SIZE*2)}}) + end + surface.request_to_generate_chunks({siloPos.x, siloPos.y}, 3) + 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 >= 30*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 \ No newline at end of file diff --git a/locale/game_opts.lua b/locale/game_opts.lua new file mode 100644 index 0000000..f097216 --- /dev/null +++ b/locale/game_opts.lua @@ -0,0 +1,194 @@ +-- 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: + frame.add{name = "info_1", type = "label", + caption=WELCOME_MSG_OARC} + frame.add{name = "info_2", type = "label", + caption=WELCOME_MSG1} + frame.add{name = "info_3", type = "label", + caption=WELCOME_MSG2} + frame.add{name = "info_4", type = "label", + caption=WELCOME_MSG6} + frame.add{name = "info_spacer", type = "label", + caption=" "} + ApplyStyle(frame.info_1, my_longer_label_style) + ApplyStyle(frame.info_2, my_longer_label_style) + ApplyStyle(frame.info_3, my_longer_label_style) + ApplyStyle(frame.info_4, my_longer_label_style) + ApplyStyle(frame.info_spacer, my_spacer_style) + + + -- Enemy Settings: + frame.add{name = "server_time", type = "label", + caption="Server Run Time: " .. formattime_hours_mins(game.tick)} + frame.add{name = "evo_now", type = "label", + caption="Current Evolution: " .. game.forces["enemy"].evolution_factor} + frame.add{name = "evo_factor_time", type = "label", + caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.time_factor} + frame.add{name = "evo_factor_pollution", type = "label", + caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.pollution_factor} + frame.add{name = "evo_factor_destroy", type = "label", + caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.destroy_factor} + if game.map_settings.enemy_expansion.enabled then + enemy_expansion_txt = "enabled" + else + enemy_expansion_txt = "disabled" + end + frame.add{name = "enemy_expansion", type = "label", + caption="Enemy expansion is " .. enemy_expansion_txt} + frame.add{name = "enemy_spacer", type = "label", + caption=" "} + ApplyStyle(frame.server_time, my_longer_label_style) + ApplyStyle(frame.evo_now, my_longer_label_style) + ApplyStyle(frame.evo_factor_time, my_longer_label_style) + ApplyStyle(frame.evo_factor_pollution, my_longer_label_style) + ApplyStyle(frame.evo_factor_destroy, my_longer_label_style) + ApplyStyle(frame.enemy_expansion, my_longer_label_style) + ApplyStyle(frame.enemy_spacer, my_spacer_style) + + + -- Game Mode: + frame.add{name = "core_mod_en", type = "label", + caption="Core game mode (separate spawns) is enabled."} + ApplyStyle(frame.core_mod_en, 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.font_color=my_color_red + end + + -- Soft Mods: + if (ENABLE_SEPARATE_SPAWNS) then + soft_mods_string = "Oarc Core" + else + 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 + frame.add{name = "soft_mods", type = "label", + caption="Soft Mods Enabled: " .. soft_mods_string} + ApplyStyle(frame.soft_mods, my_longer_label_style) + + -- Spawn options: + if (ENABLE_SEPARATE_TEAMS) then + frame.add{name = "separate_teams_mod", type = "label", + caption="You are allowed to spawn on your own team (have your own research tree). All teams are COOP."} + ApplyStyle(frame.separate_teams_mod, my_longer_label_style) + end + if (ENABLE_BUDDY_SPAWN) then + frame.add{name = "buddy_spawn_mod", type = "label", + caption="You can chose to spawn alongside a buddy if you spawn together at the same time."} + ApplyStyle(frame.buddy_spawn_mod, my_longer_label_style) + end + if (ENABLE_SEPARATE_TEAMS and ENABLE_SHARED_TEAM_VISION) then + frame.add{name = "shared_team_vision_mod", type = "label", + caption="Everyone (all teams) have shared vision."} + ApplyStyle(frame.shared_team_vision_mod, my_longer_label_style) + end + + -- Silo: + if (FRONTIER_ROCKET_SILO_MODE) then + frame.add{name = "silo_mod", type = "label", + caption="Silos are NOT craftable. There is at least one already located on the map."} + ApplyStyle(frame.silo_mod, my_longer_label_style) + end + + -- Regrowth: + if (ENABLE_REGROWTH) then + frame.add{name = "regrowth_mod", type = "label", + caption="Old parts of the map will slowly be deleted over time (chunks without any player buildings)."} + ApplyStyle(frame.regrowth_mod, my_longer_label_style) + end + + -- Minimum Play Time: + if (ENABLE_ABANDONED_BASE_REMOVAL) then + frame.add{name = "base_removal", type = "label", + caption="If you leave within " .. MIN_ONLINE_TIME_IN_MINUTES .. " minutes of joining, your base and character will be deleted."} + ApplyStyle(frame.base_removal, my_longer_warning_style) + end + + -- Quick Start: + if (ENABLE_POWER_ARMOR_QUICK_START) then + frame.add{name = "power_armor_quick_start", type = "label", + caption="Power armor quick start enabled."} + ApplyStyle(frame.power_armor_quick_start, my_longer_label_style) + end + + -- Ending Spacer + frame.add{name = "end_spacer", type = "label", + caption=" "} + ApplyStyle(frame.end_spacer, my_spacer_style) + + -- 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 diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index edae6ef..5c42f60 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -85,6 +85,20 @@ my_player_list_style_spacer = { } my_color_red = {r=1,g=0.1,b=0.1} +my_longer_label_style = { + maximal_width = 600, + maximal_height = 10, + font_color = {r=1,g=1,b=1}, + top_padding = 0, + bottom_padding = 0 +} +my_longer_warning_style = { + maximal_width = 600, + maximal_height = 10, + font_color = {r=1,g=0.1,b=0.1}, + top_padding = 0, + bottom_padding = 0 +} -------------------------------------------------------------------------------- -- General Helper Functions @@ -608,6 +622,13 @@ 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 -------------------------------------------------------------------------------- @@ -680,34 +701,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 -------------------------------------------------------------------------------- @@ -929,11 +922,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) diff --git a/locale/tag.lua b/locale/tag.lua index 204c2a2..b47c53a 100644 --- a/locale/tag.lua +++ b/locale/tag.lua @@ -1,5 +1,6 @@ --- control.lua +-- tag.lua -- Apr 2017 +-- Allows adding play tags function CreateTagGui(event) local player = game.players[event.player_index] diff --git a/locale/temp/rgcommand.lua b/locale/temp/rgcommand.lua new file mode 100644 index 0000000..bf3ac39 --- /dev/null +++ b/locale/temp/rgcommand.lua @@ -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) diff --git a/locale/temp/runcommand.lua b/locale/temp/runcommand.lua new file mode 100644 index 0000000..7fe6719 --- /dev/null +++ b/locale/temp/runcommand.lua @@ -0,0 +1,44 @@ +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) \ No newline at end of file diff --git a/separate_spawns.lua b/separate_spawns.lua index d5c262a..f913985 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -188,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 @@ -238,7 +241,9 @@ function InitSpawnGlobalsAndForces() SetCeaseFireBetweenAllForces() SetFriendlyBetweenAllForces() - -- AntiGriefing(game.forces[MAIN_FORCE]) + if (ENABLE_ANTI_GRIEFING) then + AntiGriefing(game.forces[MAIN_FORCE]) + end end @@ -262,9 +267,9 @@ function QueuePlayerForDelayedSpawn(playerName, spawn, moatEnabled) if ((spawn.x ~= 0) and (spawn.y ~= 0)) then global.uniqueSpawns[playerName] = {pos=spawn,moat=moatEnabled} - game.players[playerName].print("Generating your spawn now, please wait 10 seconds...") + game.players[playerName].print("Generating your spawn now, please wait a few seconds...") game.players[playerName].surface.request_to_generate_chunks(spawn, 4) - delayedTick = game.tick + 10*TICKS_PER_SECOND + delayedTick = game.tick + 3*TICKS_PER_SECOND table.insert(global.delayedSpawns, {playerName=playerName, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick}) DisplayPleaseWaitForSpawnDialog(game.players[playerName]) @@ -363,64 +368,25 @@ function CreatePlayerCustomForce(player) 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 player.print("Sorry, no new teams can be created. You were assigned to the default team instead.") end + -- Chart silo areas if necessary + if ENABLE_SILO_VISION then + for idx,siloPos in pairs(global.siloPosition) do + newForce.chart(surface, {{siloPos.x-(CHUNK_SIZE*2), + siloPos.y-(CHUNK_SIZE*2)}, + {siloPos.x+(CHUNK_SIZE*2), + siloPos.y+(CHUNK_SIZE*2)}}) + end + end + 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 % 10) == 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-(2*CHUNK_SIZE), --- player.position.y-(2*CHUNK_SIZE)}, --- {player.position.x+(2*CHUNK_SIZE), --- player.position.y+(2*CHUNK_SIZE)}}) --- end --- end --- end --- end --- end --- end - - --- For each force, if it's a valid force, chart the chunk that was just scanned --- for all forces. --- I have no idea how compute intensive this function is. If it starts to lag the game --- we'll have to figure out how to change it. --- function ShareRadarBetweenForces(event) - --- for _,force in pairs(game.forces) do --- if (force ~= nil) then --- if ((force.name ~= enemy) and --- (force.name ~= neutral) and --- (force.name ~= player)) then - --- for _,player in pairs(game.connected_players) do --- force.chart(GAME_SURFACE_NAME, --- {{event.chunk_position.x*CHUNK_SIZE, --- event.chunk_position.y*CHUNK_SIZE}, --- {event.chunk_position.x*CHUNK_SIZE, --- event.chunk_position.y*CHUNK_SIZE}}) --- end --- end --- end --- end --- end \ No newline at end of file diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index eeb5d7e..00a10fb 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -182,29 +182,31 @@ function DisplaySpawnOptions(player) type = "flow", direction="vertical"} + + -- Radio buttons to pick your team. if (ENABLE_SEPARATE_TEAMS) then soloSpawnFlow.add{name = "isolated_spawn_main_team_radio", type = "radiobutton", caption="Join Main Team (shared research)", - state=true} + state=false} soloSpawnFlow.add{name = "isolated_spawn_new_team_radio", type = "radiobutton", caption="Create Your Own Team (own research tree)", state=false} - if (SPAWN_MOAT_CHOICE_ENABLED) then - soloSpawnFlow.add{name = "isolated_spawn_moat_option_checkbox", - type = "checkbox", - caption="Surround your spawn with a moat", - state=false} - end - -- soloSpawnFlow.add{name = "team_chat_warning_lbl1", type = "label", - -- caption="You must type '/s' before your msg to chat with other teams!!!"} - -- ApplyStyle(soloSpawnFlow.team_chat_warning_lbl1, my_warning_style) - soloSpawnFlow.add{name = "team_chat_warning_spacer", type = "label", - caption=" "} - ApplyStyle(soloSpawnFlow.team_chat_warning_spacer, my_spacer_style) end + -- Allow players to spawn with a moat around their area. + if (SPAWN_MOAT_CHOICE_ENABLED) then + soloSpawnFlow.add{name = "isolated_spawn_moat_option_checkbox", + type = "checkbox", + caption="Surround your spawn with a moat", + state=false} + end + + soloSpawnFlow.add{name = "team_chat_warning_spacer", type = "label", + caption=" "} + ApplyStyle(soloSpawnFlow.team_chat_warning_spacer, my_spacer_style) + soloSpawnFlow.add{name = "isolated_spawn_near", type = "button", caption="Solo Spawn (Near)"} @@ -272,7 +274,7 @@ function DisplaySpawnOptions(player) sGui.add{name = "note_spacer2", type = "label", caption=" "} - if MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN then + if (MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN > 0) then sGui.add{name = "shared_spawn_note1", type = "label", caption="If you create your own spawn point you can allow up to " .. MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN-1 .. " other online players to join." } ApplyStyle(sGui.shared_spawn_note1, my_note_style) @@ -294,11 +296,12 @@ function DisplaySpawnOptions(player) end +-- This just updates the radio buttons when players click them. function SpawnOptsRadioSelect(event) if not (event and event.element and event.element.valid) then return end local elemName = event.element.name - -- This just updates the radio buttons. + if (elemName == "isolated_spawn_main_team_radio") then event.element.parent.isolated_spawn_new_team_radio.state=false elseif (elemName == "isolated_spawn_new_team_radio") then @@ -350,10 +353,13 @@ function SpawnOptsGuiClick(event) player.gui.center.spawn_opts.spawn_solo_flow.isolated_spawn_main_team_radio.state joinOwnTeamRadio = player.gui.center.spawn_opts.spawn_solo_flow.isolated_spawn_new_team_radio.state - if (SPAWN_MOAT_CHOICE_ENABLED) then - moatChoice = - player.gui.center.spawn_opts.spawn_solo_flow.isolated_spawn_moat_option_checkbox.state - end + else + joinMainTeamRadio = true + joinOwnTeamRadio = false + end + if (SPAWN_MOAT_CHOICE_ENABLED) then + moatChoice = + player.gui.center.spawn_opts.spawn_solo_flow.isolated_spawn_moat_option_checkbox.state end player.gui.center.spawn_opts.destroy() else @@ -451,8 +457,12 @@ function DisplaySharedSpawnOptions(player) (game.players[spawnName] ~= nil) and game.players[spawnName].connected) then local spotsRemaining = MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN - GetOnlinePlayersAtSharedSpawn(spawnName) - if (spotsRemaining > 0) then + if (MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN == 0) then + shGui.add{type="button", caption=spawnName, name=spawnName} + elseif (spotsRemaining > 0) then shGui.add{type="button", caption=spawnName .. " (" .. spotsRemaining .. " spots remaining)", name=spawnName} + end + if (shGui.spawnName ~= nil) then shGui.add{name = spawnName .. "spacer_lbl", type = "label", caption=" "} ApplyStyle(shGui[spawnName], my_small_button_style) ApplyStyle(shGui[spawnName .. "spacer_lbl"], my_spacer_style) @@ -886,18 +896,21 @@ function DisplayBuddySpawnOptions(player) direction="vertical"} - buddySpawnFlow.add{name = "buddy_spawn_main_team_radio", - type = "radiobutton", - caption="Join Main Team (shared research)", - state=true} - buddySpawnFlow.add{name = "buddy_spawn_new_team_radio", - type = "radiobutton", - caption="Create Your Own Team (own research tree)", - state=false} - buddySpawnFlow.add{name = "buddy_spawn_buddy_team_radio", - type = "radiobutton", - caption="Create Your Own Buddy Team (buddy and you share research)", - state=false} + -- Allow picking of teams + if (ENABLE_SEPARATE_TEAMS) then + buddySpawnFlow.add{name = "buddy_spawn_main_team_radio", + type = "radiobutton", + caption="Join Main Team (shared research)", + state=true} + buddySpawnFlow.add{name = "buddy_spawn_new_team_radio", + type = "radiobutton", + caption="Create Your Own Team (own research tree)", + state=false} + buddySpawnFlow.add{name = "buddy_spawn_buddy_team_radio", + type = "radiobutton", + caption="Create Your Own Buddy Team (buddy and you share research)", + state=false} + end if (SPAWN_MOAT_CHOICE_ENABLED) then buddySpawnFlow.add{name = "buddy_spawn_moat_option_checkbox", type = "checkbox", @@ -1031,9 +1044,15 @@ function BuddySpawnOptsGuiClick(event) return end - joinMainTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_main_team_radio.state - joinOwnTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_new_team_radio.state - joinBuddyTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_buddy_team_radio.state + if (ENABLE_SEPARATE_TEAMS) then + joinMainTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_main_team_radio.state + joinOwnTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_new_team_radio.state + joinBuddyTeamRadio = buddySpawnGui.spawn_buddy_flow.buddy_spawn_buddy_team_radio.state + else + joinMainTeamRadio = true + joinOwnTeamRadio = false + joinBuddyTeamRadio = false + end if (SPAWN_MOAT_CHOICE_ENABLED) then moatChoice = buddySpawnGui.spawn_buddy_flow.buddy_spawn_moat_option_checkbox.state end @@ -1335,7 +1354,7 @@ function DisplayPleaseWaitForSpawnDialog(player) pleaseWaitGui.add{name = "warning_lbl1", type = "label", caption="Your spawn is being created now."} pleaseWaitGui.add{name = "warning_lbl2", type = "label", - caption="You will be teleported there in about 10 seconds!"} + caption="You will be teleported there in a few seconds!"} pleaseWaitGui.add{name = "warning_lbl3", type = "label", caption="Please standby..."} pleaseWaitGui.add{name = "warning_spacer", type = "label", From 21df6e264e204549cc622a98c5c1c5b573adba05 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Wed, 31 Jan 2018 23:44:13 -0500 Subject: [PATCH 40/58] Fix a bug with other team spawn and silo charting. Add more info to info button. --- control.lua | 3 ++- locale/game_opts.lua | 5 +++++ separate_spawns.lua | 2 +- separate_spawns_guis.lua | 4 ---- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/control.lua b/control.lua index 0552e19..4e5293b 100644 --- a/control.lua +++ b/control.lua @@ -209,6 +209,8 @@ end) ---------------------------------------- script.on_event(defines.events.on_player_joined_game, function(event) + CreateGameOptionsGui(event) + PlayerJoinedMessages(event) if ENABLE_PLAYER_LIST then @@ -219,7 +221,6 @@ script.on_event(defines.events.on_player_joined_game, function(event) CreateTagGui(event) end - CreateGameOptionsGui(event) end) script.on_event(defines.events.on_player_created, function(event) diff --git a/locale/game_opts.lua b/locale/game_opts.lua index f097216..67df502 100644 --- a/locale/game_opts.lua +++ b/locale/game_opts.lua @@ -118,6 +118,11 @@ local function ExpandGameOptionsGui(player) caption="You can chose to spawn alongside a buddy if you spawn together at the same time."} ApplyStyle(frame.buddy_spawn_mod, my_longer_label_style) end + if (ENABLE_SHARED_SPAWNS) then + frame.add{name = "share_spawn_mod", type = "label", + caption="Spawn hosts may choose to share their spawn and allow other players to join them."} + ApplyStyle(frame.share_spawn_mod, my_longer_label_style) + end if (ENABLE_SEPARATE_TEAMS and ENABLE_SHARED_TEAM_VISION) then frame.add{name = "shared_team_vision_mod", type = "label", caption="Everyone (all teams) have shared vision."} diff --git a/separate_spawns.lua b/separate_spawns.lua index f913985..8980d18 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -379,7 +379,7 @@ function CreatePlayerCustomForce(player) end -- Chart silo areas if necessary - if ENABLE_SILO_VISION then + if FRONTIER_ROCKET_SILO_MODE and ENABLE_SILO_VISION then for idx,siloPos in pairs(global.siloPosition) do newForce.chart(surface, {{siloPos.x-(CHUNK_SIZE*2), siloPos.y-(CHUNK_SIZE*2)}, diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 00a10fb..1ac9d41 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -382,10 +382,6 @@ function SpawnOptsGuiClick(event) -- Create a new force for player if they choose that radio button if ENABLE_SEPARATE_TEAMS and joinOwnTeamRadio then local newForce = CreatePlayerCustomForce(player) - - if (FRONTIER_ROCKET_SILO_MODE and (newForce ~= nil)) then - ChartRocketSiloArea(newForce, game.surfaces[GAME_SURFACE_NAME]) - end end -- Find coordinates of a good place to spawn From 1f098086cde963f65ca0c96e730164628061c5b7 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 00:06:29 -0500 Subject: [PATCH 41/58] Tweaking the frontier silo generation, still have enemies spawning nearby and ore.... Might need to fix that later. --- config.lua | 1 + locale/frontier_silo.lua | 40 ++++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/config.lua b/config.lua index eb7fc25..29d7d1e 100644 --- a/config.lua +++ b/config.lua @@ -298,6 +298,7 @@ ENEMY_DESTROY_FACTOR_DIVISOR = 1 -- 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 -- How many chunks away from the center of the map should the silo be spawned diff --git a/locale/frontier_silo.lua b/locale/frontier_silo.lua index e4d1d75..f69b051 100644 --- a/locale/frontier_silo.lua +++ b/locale/frontier_silo.lua @@ -53,6 +53,14 @@ local function CreateRocketSilo(surface, siloPosition, force) 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 @@ -97,8 +105,8 @@ end -- Generate clean land and trees around silo area on chunk generate event function GenerateRocketSiloChunk(event) - -- All silo chunk generate events should be done within the first minute. - if (game.tick < 1*TICKS_PER_MINUTE) then + -- 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 @@ -107,11 +115,11 @@ function GenerateRocketSiloChunk(event) for idx,siloPos in pairs(global.siloPosition) do local safeArea = {left_top= - {x=siloPos.x-150, - y=siloPos.y-150}, + {x=siloPos.x-(CHUNK_SIZE*4), + y=siloPos.y-(CHUNK_SIZE*4)}, right_bottom= - {x=siloPos.x+150, - y=siloPos.y+150}} + {x=siloPos.x+(CHUNK_SIZE*4), + y=siloPos.y+(CHUNK_SIZE*4)}} -- Clear enemies directly next to the rocket @@ -119,16 +127,16 @@ function GenerateRocketSiloChunk(event) 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, 40) 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, 40) end end end @@ -150,7 +158,7 @@ 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 >= 30*TICKS_PER_SECOND)) then + 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]) From f9d75030ad05b11cd66edd26684917ce6961415b Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 12:14:48 -0500 Subject: [PATCH 42/58] Make the evo status a nicer number. --- locale/game_opts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/game_opts.lua b/locale/game_opts.lua index 67df502..539c0b4 100644 --- a/locale/game_opts.lua +++ b/locale/game_opts.lua @@ -45,7 +45,7 @@ local function ExpandGameOptionsGui(player) frame.add{name = "server_time", type = "label", caption="Server Run Time: " .. formattime_hours_mins(game.tick)} frame.add{name = "evo_now", type = "label", - caption="Current Evolution: " .. game.forces["enemy"].evolution_factor} + caption="Current Evolution: " .. string.format("%.4f", game.forces["enemy"].evolution_factor)} frame.add{name = "evo_factor_time", type = "label", caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.time_factor} frame.add{name = "evo_factor_pollution", type = "label", From d8ecfbfcdc3c36239f2238b99e7a586598829787 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 12:37:38 -0500 Subject: [PATCH 43/58] Fix the ghost/blueprint time to live. I didn't realize how it was supposed to work. --- control.lua | 6 +++++- locale/oarc_utils.lua | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/control.lua b/control.lua index 4e5293b..2e5b2c0 100644 --- a/control.lua +++ b/control.lua @@ -210,7 +210,7 @@ end) script.on_event(defines.events.on_player_joined_game, function(event) CreateGameOptionsGui(event) - + PlayerJoinedMessages(event) if ENABLE_PLAYER_LIST then @@ -279,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) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 5c42f60..0ff9d76 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -631,6 +631,15 @@ function SetForceGhostTimeToLive(force) end end +function SetItemBlueprintTimeToLive(event) + local type = event.created_entity.type + if type == "entity-ghost" or type == "tile-ghost" or type == "item-request-proxy" then + if GHOST_TIME_TO_LIVE ~= 0 then + event.created_entity.time_to_live = GHOST_TIME_TO_LIVE + end + end +end + -------------------------------------------------------------------------------- -- Gravestone soft mod. With my own modifications/improvements. -------------------------------------------------------------------------------- From cda98958363d57e507d3a9236ec423c6959a21a8 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 12:41:36 -0500 Subject: [PATCH 44/58] Removing or type == "item-request-proxy" from the ghost time to live stuff. --- locale/oarc_utils.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 0ff9d76..ef5af3f 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -633,7 +633,7 @@ end function SetItemBlueprintTimeToLive(event) local type = event.created_entity.type - if type == "entity-ghost" or type == "tile-ghost" or type == "item-request-proxy" then + 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 From b9c5000bab4632654ae3ec335257ce5175b5b406 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 13:03:11 -0500 Subject: [PATCH 45/58] Trying to fix desyncs that I think are related to my regrowth and RSO changes. --- config.lua | 2 +- locale/rso/rso_control.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.lua b/config.lua index 29d7d1e..74a5b9a 100644 --- a/config.lua +++ b/config.lua @@ -92,7 +92,7 @@ ENABLE_POWER_ARMOR_QUICK_START = false ENABLE_SHARED_TEAM_VISION = true -- Enable map regrowth, see regrowth_map.lua for more info. -ENABLE_REGROWTH = false +ENABLE_REGROWTH = true -- 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. diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua index b47d4d5..bc12c44 100644 --- a/locale/rso/rso_control.lua +++ b/locale/rso/rso_control.lua @@ -1251,7 +1251,7 @@ local function roll_region(c_x, c_y) global.regions[r_x][r_y]={} r_data = global.regions[r_x][r_y] if (regrow_rso and not deterministic) then - global.seed = math.random(0,4294967295) + global.seed = global.seed + 1 end rng = rng_for_reg_pos{x=r_x,y=r_y} From 2347577b492b87eefd0018f0a525ce403d1b7e65 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 13:17:09 -0500 Subject: [PATCH 46/58] Still trying to fix regrowth-rso desyncs. --- locale/rso/rso_control.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua index bc12c44..758c999 100644 --- a/locale/rso/rso_control.lua +++ b/locale/rso/rso_control.lua @@ -1225,10 +1225,10 @@ local function roll_region(c_x, c_y) local configIndexed = global.configIndexed -- Reroll regions every region_size^2 chunk generation calls. - local regrow_rso = false + global.regrow_rso = false if (ENABLE_REGROWTH) then if (global.chunk_regrow.rso_region_roll_counter > (region_size*region_size/2)) then - regrow_rso = true + global.regrow_rso = true global.chunk_regrow.rso_region_roll_counter = 0 else global.chunk_regrow.rso_region_roll_counter = global.chunk_regrow.rso_region_roll_counter + 1 @@ -1243,17 +1243,19 @@ local function roll_region(c_x, c_y) -- if (not (global.regions[r_x] and global.regions[r_x][r_y]) or regrow_rso) then - if (global.regions[r_x] and global.regions[r_x][r_y] and not regrow_rso) then + if (global.regions[r_x] and global.regions[r_x][r_y] and not global.regrow_rso) then r_data = global.regions[r_x][r_y] else --if this chunk is the first in its region to be generated if not global.regions[r_x] then global.regions[r_x] = {} end global.regions[r_x][r_y]={} r_data = global.regions[r_x][r_y] - if (regrow_rso and not deterministic) then - global.seed = global.seed + 1 + if (global.regrow_rso and not deterministic) then + rng = rng_for_reg_pos{x=r_x*math.random(-1,1),y=r_y*math.random(-1,1)} + else + rng = rng_for_reg_pos{x=r_x,y=r_y} end - rng = rng_for_reg_pos{x=r_x,y=r_y} + local rollCount = math.ceil(#configIndexed / 10) - 1 -- 0 based counter is more convenient here rollCount = math.min(rollCount, 3) From 4b789b196fea380391bc497aa1e570f314d97f94 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 13:37:34 -0500 Subject: [PATCH 47/58] Adding a kit command and belt immunity. --- control.lua | 2 +- locale/oarc_utils.lua | 1 + .../{runcommand.lua => helper_commands.lua} | 23 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) rename locale/temp/{runcommand.lua => helper_commands.lua} (69%) diff --git a/control.lua b/control.lua index 2e5b2c0..b243c20 100644 --- a/control.lua +++ b/control.lua @@ -32,7 +32,7 @@ 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/runcommand") +require("locale/temp/helper_commands") -- Main Configuration File require("config") diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index ef5af3f..7b4f29f 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -231,6 +231,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 diff --git a/locale/temp/runcommand.lua b/locale/temp/helper_commands.lua similarity index 69% rename from locale/temp/runcommand.lua rename to locale/temp/helper_commands.lua index 7fe6719..fcfad06 100644 --- a/locale/temp/runcommand.lua +++ b/locale/temp/helper_commands.lua @@ -1,3 +1,9 @@ +-- 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 @@ -41,4 +47,21 @@ commands.add_command("mine", "change player speed bonus", function(command) 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) \ No newline at end of file From cee32721e07e2b57f500d825c8d78ef611a7b978 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 14:35:27 -0500 Subject: [PATCH 48/58] MMorwen found a typo in the info panel. --- locale/game_opts.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locale/game_opts.lua b/locale/game_opts.lua index 539c0b4..be7792a 100644 --- a/locale/game_opts.lua +++ b/locale/game_opts.lua @@ -49,9 +49,9 @@ local function ExpandGameOptionsGui(player) frame.add{name = "evo_factor_time", type = "label", caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.time_factor} frame.add{name = "evo_factor_pollution", type = "label", - caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.pollution_factor} + caption="Enemy evolution pollution factor: " .. game.map_settings.enemy_evolution.pollution_factor} frame.add{name = "evo_factor_destroy", type = "label", - caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.destroy_factor} + caption="Enemy evolution destroy factor: " .. game.map_settings.enemy_evolution.destroy_factor} if game.map_settings.enemy_expansion.enabled then enemy_expansion_txt = "enabled" else From 5098a2b904b544a7a08d914f5cc11f6ea6f1cadf Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 1 Feb 2018 17:06:06 -0500 Subject: [PATCH 49/58] Regrowth still causing desyncs. --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index 74a5b9a..69c63d0 100644 --- a/config.lua +++ b/config.lua @@ -92,7 +92,7 @@ ENABLE_POWER_ARMOR_QUICK_START = false ENABLE_SHARED_TEAM_VISION = true -- Enable map regrowth, see regrowth_map.lua for more info. -ENABLE_REGROWTH = true +ENABLE_REGROWTH = false -- THIS STILL CAUSES DESYNCS -- 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. From f67cd30778fc76d5b8b6ae3482a676a3ff7088b7 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 2 Feb 2018 17:22:45 -0500 Subject: [PATCH 50/58] Tweaking alien params for fun. --- locale/oarc_utils.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 7b4f29f..966e950 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -551,16 +551,16 @@ function ConfigureAlienStartingParams() game.map_settings.enemy_expansion.enabled = ENEMY_EXPANSION -- game.map_settings.enemy_expansion.min_base_spacing = 10 - -- game.map_settings.enemy_expansion.max_expansion_distance = 10 + game.map_settings.enemy_expansion.max_expansion_distance = 20 - -- game.map_settings.enemy_expansion.settler_group_min_size = 5 - -- game.map_settings.enemy_expansion.settler_group_max_size = 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.friendly_base_influence_radius = 4 -- game.map_settings.enemy_expansion.enemy_building_influence_radius = 4 - -- game.map_settings.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*30 - -- game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*120 + game.map_settings.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*2 + game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*20 end -- Add Long Reach to Character From 920617a8af5289981dadf4c94a472a0a1752404e Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 3 Feb 2018 12:10:55 -0500 Subject: [PATCH 51/58] Reducing the long reach by about half, seemed kind of OP. Added a custom flag for changing to my difficulty settings. Fixed silo charting for other forces. Removed attempts at trying to randomize regrowth of ores. --- config.lua | 8 +++++--- locale/frontier_silo.lua | 15 +++++++++++---- locale/oarc_utils.lua | 20 ++++++++++++-------- locale/rso/rso_config.lua | 2 +- locale/rso/rso_control.lua | 8 ++++---- separate_spawns.lua | 14 ++++---------- separate_spawns_guis.lua | 9 --------- 7 files changed, 37 insertions(+), 39 deletions(-) diff --git a/config.lua b/config.lua index 69c63d0..df20c5e 100644 --- a/config.lua +++ b/config.lua @@ -92,7 +92,7 @@ ENABLE_POWER_ARMOR_QUICK_START = false ENABLE_SHARED_TEAM_VISION = true -- Enable map regrowth, see regrowth_map.lua for more info. -ENABLE_REGROWTH = false -- THIS STILL CAUSES DESYNCS +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. @@ -321,7 +321,7 @@ ENABLE_SILO_RADAR = false -- Long Reach Options -------------------------------------------------------------------------------- -BUILD_DIST_BONUS = 125 +BUILD_DIST_BONUS = 64 REACH_DIST_BONUS = BUILD_DIST_BONUS RESOURCE_DIST_BONUS = 2 @@ -389,8 +389,10 @@ ENABLE_ANTI_GRIEFING = false GHOST_TIME_TO_LIVE = 3 * 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 diff --git a/locale/frontier_silo.lua b/locale/frontier_silo.lua index f69b051..f40d8a2 100644 --- a/locale/frontier_silo.lua +++ b/locale/frontier_silo.lua @@ -145,15 +145,22 @@ end function GenerateRocketSiloAreas(surface) for idx,siloPos in pairs(global.siloPosition) do if (ENABLE_SILO_VISION) then - game.forces[MAIN_FORCE].chart(surface, {{siloPos.x-(CHUNK_SIZE*2), - siloPos.y-(CHUNK_SIZE*2)}, - {siloPos.x+(CHUNK_SIZE*2), - siloPos.y+(CHUNK_SIZE*2)}}) + 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) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 966e950..7945c1a 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -550,17 +550,21 @@ function ConfigureAlienStartingParams() game.map_settings.enemy_evolution.destroy_factor = game.map_settings.enemy_evolution.destroy_factor / ENEMY_DESTROY_FACTOR_DIVISOR game.map_settings.enemy_expansion.enabled = ENEMY_EXPANSION - -- game.map_settings.enemy_expansion.min_base_spacing = 10 - game.map_settings.enemy_expansion.max_expansion_distance = 20 + if (OARC_DIFFICULTY_CUSTOM) then - 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_base_spacing = 10 + game.map_settings.enemy_expansion.max_expansion_distance = 20 - -- game.map_settings.enemy_expansion.friendly_base_influence_radius = 4 - -- game.map_settings.enemy_expansion.enemy_building_influence_radius = 4 + 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*2 - game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*20 + -- game.map_settings.enemy_expansion.friendly_base_influence_radius = 4 + -- game.map_settings.enemy_expansion.enemy_building_influence_radius = 4 + + game.map_settings.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*2 + game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*20 + + end end -- Add Long Reach to Character diff --git a/locale/rso/rso_config.lua b/locale/rso/rso_config.lua index 0896880..77ff59b 100644 --- a/locale/rso/rso_config.lua +++ b/locale/rso/rso_config.lua @@ -27,7 +27,7 @@ richness_distance_factor= 0.5 -- exponent for richness distance factor calculat 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 +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. diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua index 758c999..236be79 100644 --- a/locale/rso/rso_control.lua +++ b/locale/rso/rso_control.lua @@ -1250,11 +1250,11 @@ local function roll_region(c_x, c_y) if not global.regions[r_x] then global.regions[r_x] = {} end global.regions[r_x][r_y]={} r_data = global.regions[r_x][r_y] - if (global.regrow_rso and not deterministic) then - rng = rng_for_reg_pos{x=r_x*math.random(-1,1),y=r_y*math.random(-1,1)} - else + -- if (global.regrow_rso and not deterministic) then + -- rng = rng_for_reg_pos{x=r_x*math.random(-1,1),y=r_y*math.random(-1,1)} + -- else rng = rng_for_reg_pos{x=r_x,y=r_y} - end + -- end local rollCount = math.ceil(#configIndexed / 10) - 1 -- 0 based counter is more convenient here diff --git a/separate_spawns.lua b/separate_spawns.lua index 8980d18..ed88aa3 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -366,6 +366,10 @@ function CreatePlayerCustomForce(player) 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() @@ -378,15 +382,5 @@ function CreatePlayerCustomForce(player) player.print("Sorry, no new teams can be created. You were assigned to the default team instead.") end - -- Chart silo areas if necessary - if FRONTIER_ROCKET_SILO_MODE and ENABLE_SILO_VISION then - for idx,siloPos in pairs(global.siloPosition) do - newForce.chart(surface, {{siloPos.x-(CHUNK_SIZE*2), - siloPos.y-(CHUNK_SIZE*2)}, - {siloPos.x+(CHUNK_SIZE*2), - siloPos.y+(CHUNK_SIZE*2)}}) - end - end - return newForce end diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 1ac9d41..bd6c356 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -1259,19 +1259,10 @@ function BuddySpawnRequestMenuClick(event) local newForce = CreatePlayerCustomForce(player) local buddyForce = CreatePlayerCustomForce(game.players[requesterName]) - if (FRONTIER_ROCKET_SILO_MODE and newForce and buddyForce) then - ChartRocketSiloArea(newForce, game.surfaces[GAME_SURFACE_NAME]) - ChartRocketSiloArea(buddyForce, game.surfaces[GAME_SURFACE_NAME]) - end - -- Create a new force for the combined players if they chose that option elseif requesterOptions.joinBuddyTeamRadio then local buddyForce = CreatePlayerCustomForce(game.players[requesterName]) player.force = buddyForce - - if (FRONTIER_ROCKET_SILO_MODE and newForce and buddyForce) then - ChartRocketSiloArea(buddyForce, game.surfaces[GAME_SURFACE_NAME]) - end end -- Find coordinates of a good place to spawn From 1ec66c50725a3db77b99d0962fe3ac3106d1d374 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 3 Feb 2018 14:37:32 -0500 Subject: [PATCH 52/58] Exposing more custom enemy options for my custom difficulty. Added disable destroy factor for evolution. --- config.lua | 1 + locale/oarc_utils.lua | 120 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 115 insertions(+), 6 deletions(-) diff --git a/config.lua b/config.lua index df20c5e..88cccf4 100644 --- a/config.lua +++ b/config.lua @@ -290,6 +290,7 @@ ENEMY_TIME_FACTOR_DISABLE = false -- Set this to true to disable time based evol 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_DISABLE = false -- Set this to true to disable spawner destruction based evolution completely. ENEMY_DESTROY_FACTOR_DIVISOR = 1 -------------------------------------------------------------------------------- diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 7945c1a..e311142 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -535,6 +535,7 @@ function ConfigureAlienStartingParams() -- "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 @@ -547,22 +548,129 @@ function ConfigureAlienStartingParams() game.map_settings.enemy_evolution.pollution_factor = game.map_settings.enemy_evolution.pollution_factor / ENEMY_POLLUTION_FACTOR_DIVISOR end - game.map_settings.enemy_evolution.destroy_factor = game.map_settings.enemy_evolution.destroy_factor / ENEMY_DESTROY_FACTOR_DIVISOR + 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.enemy_expansion.min_base_spacing = 10 + game.map_settings.pollution.diffusion_ratio = 0.05 + game.map_settings.pollution.ageing = 1.2 + 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.friendly_base_influence_radius = 4 - -- game.map_settings.enemy_expansion.enemy_building_influence_radius = 4 + 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.enemy_expansion.min_expansion_cooldown = TICKS_PER_MINUTE*2 - game.map_settings.enemy_expansion.max_expansion_cooldown = TICKS_PER_MINUTE*20 + game.map_settings.unit_group.min_group_gathering_time = TICKS_PER_MINUTE + game.map_settings.unit_group.max_group_gathering_time = 6 * 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 = 50 + + -- 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 From 1264c6557dfc892a3c2da66818127ec15b8a28a1 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 3 Feb 2018 21:27:54 -0500 Subject: [PATCH 53/58] Increasing delay so that chunks are more likely to be generated... otherwise it can get bugged. --- separate_spawns.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/separate_spawns.lua b/separate_spawns.lua index ed88aa3..b2779d5 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -269,7 +269,7 @@ function QueuePlayerForDelayedSpawn(playerName, spawn, moatEnabled) game.players[playerName].print("Generating your spawn now, please wait a few seconds...") game.players[playerName].surface.request_to_generate_chunks(spawn, 4) - delayedTick = game.tick + 3*TICKS_PER_SECOND + delayedTick = game.tick + 10*TICKS_PER_SECOND table.insert(global.delayedSpawns, {playerName=playerName, spawn=spawn, moatEnabled=moatEnabled, delayedTick=delayedTick}) DisplayPleaseWaitForSpawnDialog(game.players[playerName]) From dcbd996bb3b3230dfca6f8134403458ec7731b78 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 3 Feb 2018 21:50:52 -0500 Subject: [PATCH 54/58] Add some comments in code, todo and explanation. --- regrowth_map.lua | 3 ++- separate_spawns.lua | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/regrowth_map.lua b/regrowth_map.lua index 4372215..f214144 100644 --- a/regrowth_map.lua +++ b/regrowth_map.lua @@ -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. diff --git a/separate_spawns.lua b/separate_spawns.lua index b2779d5..1087bec 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -291,6 +291,7 @@ function DelayedSpawnOnTick() 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 From 10814e30fa10c3a60a0f10eb14ae1830d94216c0 Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Sat, 3 Feb 2018 21:51:14 -0500 Subject: [PATCH 55/58] Tweaking enemies. --- locale/oarc_utils.lua | 8 ++++---- locale/rso/rso_resource_config.lua | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index e311142..038e25e 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -558,8 +558,8 @@ function ConfigureAlienStartingParams() if (OARC_DIFFICULTY_CUSTOM) then - game.map_settings.pollution.diffusion_ratio = 0.05 - game.map_settings.pollution.ageing = 1.2 + game.map_settings.pollution.diffusion_ratio = 0.08 + game.map_settings.pollution.ageing = 1 game.map_settings.enemy_expansion.max_expansion_distance = 20 @@ -570,9 +570,9 @@ function ConfigureAlienStartingParams() 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 = 6 * 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 = 50 + 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) diff --git a/locale/rso/rso_resource_config.lua b/locale/rso/rso_resource_config.lua index 653b6b4..196ee74 100644 --- a/locale/rso/rso_resource_config.lua +++ b/locale/rso/rso_resource_config.lua @@ -123,7 +123,7 @@ local function fillEnemies() spawns_per_region={min=2,max=4}, size={min=2,max=4}, - size_per_region_factor=1, + size_per_region_factor=0.3, richness=3, absolute_probability=absolute_enemy_chance, -- chance to spawn in region From 5ddb5b2deee55bdcb22a2045ffa7f3e2c5afefeb Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 22 Feb 2018 18:05:22 -0500 Subject: [PATCH 56/58] Trying to fix some issues with player being nil for certain GUI events. --- separate_spawns_guis.lua | 63 ++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index bd6c356..6704a08 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -121,6 +121,11 @@ end -- Display the spawn options and explanation function DisplaySpawnOptions(player) + if (player == nil) then + DebugPrint("DisplaySpawnOptions with no valid player...") + return + end + if (player.gui.center.spawn_opts ~= nil) then DebugPrint("Tried to display spawn options when it was already displayed!") return @@ -791,9 +796,11 @@ function SpawnCtrlGuiClick(event) player.print("You rejected " .. joinQueuePlayerChoice .. "'s request to join your base.") SendMsg(joinQueuePlayerChoice, "Your request to join was rejected.") - - game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu.destroy() - DisplaySpawnOptions(game.players[joinQueuePlayerChoice]) + -- Close the waiting players menu + if (game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu) then + game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu.destroy() + DisplaySpawnOptions(game.players[joinQueuePlayerChoice]) + end -- Find and remove the player from the joinQueue they were in. for index,requestingPlayer in pairs(global.sharedSpawns[player.name].joinQueue) do @@ -805,12 +812,6 @@ function SpawnCtrlGuiClick(event) elseif (elemName == "accept_player_request") then - -- Send an announcement - SendBroadcastMsg(joinQueuePlayerChoice .. " is joining " .. player.name .. "'s base!") - - -- Close the waiting players menu - game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu.destroy() - -- Find and remove the player from the joinQueue they were in. for index,requestingPlayer in pairs(global.sharedSpawns[player.name].joinQueue) do if (requestingPlayer == joinQueuePlayerChoice) then @@ -818,17 +819,30 @@ function SpawnCtrlGuiClick(event) end end - -- Spawn the player - joiningPlayer = game.players[joinQueuePlayerChoice] - ChangePlayerSpawn(joiningPlayer, global.sharedSpawns[player.name].position) - SendPlayerToSpawn(joiningPlayer) - GivePlayerStarterItems(joiningPlayer) - table.insert(global.sharedSpawns[player.name].players, joiningPlayer.name) - joiningPlayer.force = game.players[player.name].force + -- If player exists, then do stuff. + if (game.players[joinQueuePlayerChoice]) then + -- Send an announcement + SendBroadcastMsg(joinQueuePlayerChoice .. " is joining " .. player.name .. "'s base!") + + -- Close the waiting players menu + if (game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu) then + game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu.destroy() + end + + -- Spawn the player + joiningPlayer = game.players[joinQueuePlayerChoice] + ChangePlayerSpawn(joiningPlayer, global.sharedSpawns[player.name].position) + SendPlayerToSpawn(joiningPlayer) + GivePlayerStarterItems(joiningPlayer) + table.insert(global.sharedSpawns[player.name].players, joiningPlayer.name) + joiningPlayer.force = game.players[player.name].force - -- Create the button at the top left for setting respawn point and sharing base. - CreateSpawnCtrlGui(joiningPlayer) - ExpandSpawnCtrlGui(player, event.tick) + -- Create the button at the top left for setting respawn point and sharing base. + CreateSpawnCtrlGui(joiningPlayer) + ExpandSpawnCtrlGui(player, event.tick) + else + SendBroadcastMsg(joinQueuePlayerChoice .. " left the game. What an ass.") + end end end end @@ -1029,7 +1043,9 @@ function BuddySpawnOptsGuiClick(event) buddyIsStillWaiting = false for _,buddyName in pairs(global.waitingBuddies) do if (buddyChoice == buddyName) then - buddyIsStillWaiting = true + if (game.players[buddyChoice]) then + buddyIsStillWaiting = true + end break end end @@ -1143,7 +1159,12 @@ function BuddySpawnWaitMenuClick(event) end function DisplayBuddySpawnRequestMenu(player, requestingBuddyName) - + + if not player then + DebugPrint("Another gui click happened with no valid player...") + return + end + player.gui.center.add{name = "buddy_request_menu", type = "frame", direction = "vertical", From 8221e3928cf0894e812a9923ca81e6de0288245d Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Thu, 15 Mar 2018 18:00:46 -0400 Subject: [PATCH 57/58] Fix for text line issues. Better support for larger spawn size areas. Minor text changes. Tweaking of resources and difficulty. --- config.lua | 25 ++++++++++------- locale/frontier_silo.lua | 2 +- locale/oarc_utils.lua | 56 ++++++++++++++++++++++++++------------- locale/rso/rso_config.lua | 8 +++--- regrowth_map.lua | 8 +++--- separate_spawns.lua | 11 +++++--- separate_spawns_guis.lua | 22 ++++++++------- 7 files changed, 83 insertions(+), 49 deletions(-) diff --git a/config.lua b/config.lua index 88cccf4..c028616 100644 --- a/config.lua +++ b/config.lua @@ -18,7 +18,7 @@ WELCOME_MSG1 = "Rules: Be polite. Ask before changing other players's stuff. Hav WELCOME_MSG2 = "This server is running a custom scenario that changes spawn locations." OTHER_MSG1 = "Latest updates in this scenario version:" -OTHER_MSG2 = "0.16 experimental release. New spawning permissions and buddy spawns." +OTHER_MSG2 = "0.16 experimental release. Tweaks to fix spawn issues / text / difficulty." -- Optional other messages below: OTHER_MSG3 = "This scenario gives you or your friends your own starting area." OTHER_MSG4 = "You can be on the main team or your own. All teams are friendly." @@ -76,6 +76,7 @@ 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 @@ -92,7 +93,9 @@ ENABLE_POWER_ARMOR_QUICK_START = false 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. @@ -161,10 +164,12 @@ FAR_MAX_DIST = 300 -- 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 -- 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 @@ -224,6 +229,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 --------------------------------------- @@ -239,7 +245,7 @@ SAFE_AREA_TILE_DIST = CHUNK_SIZE*5 WARNING_AREA_TILE_DIST = CHUNK_SIZE*10 -- 1 : X (spawners alive : spawners destroyed) in this area -WARN_AREA_REDUCTION_RATIO = 5 +WARN_AREA_REDUCTION_RATIO = 10 --------------------------------------- @@ -283,7 +289,7 @@ MIN_ONLINE_TIME = TICKS_PER_MINUTE * MIN_ONLINE_TIME_IN_MINUTES -------------------------------------------------------------------------------- -- Enable/Disable enemy expansion -ENEMY_EXPANSION = false +ENEMY_EXPANSION = true -- 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. @@ -370,10 +376,10 @@ global.clMapGen.autoplace_controls = { ["stone"]={frequency= "very-low", size= "low", richness= "high"}, ["uranium-ore"]={frequency= "low", size= "low", richness= "high"}, - ["desert"]={frequency= "normal", size= "normal", richness= "normal"}, - ["dirt"]={frequency= "normal", size= "normal", richness= "normal"}, + ["desert"]={frequency= "low", size= "low", richness= "normal"}, + ["dirt"]={frequency= "low", size= "low", richness= "normal"}, ["grass"]={frequency= "normal", size= "normal", richness= "normal"}, - ["sand"]={frequency= "normal", size= "normal", richness= "normal"}, + ["sand"]={frequency= "low", size= "low", richness= "normal"}, ["trees"]={frequency= "normal", size= "normal", richness= "normal"} } -- Cliff defaults are 10 and 10, set both to 0 to turn cliffs off I think? @@ -387,12 +393,11 @@ global.clMapGen.cliff_settings={cliff_elevation_0=10, cliff_elevation_interval=1 ENABLE_ANTI_GRIEFING = false -- Makes blueprint ghosts dissapear if they have been placed longer than this -GHOST_TIME_TO_LIVE = 3 * TICKS_PER_MINUTE -- set to 0 for infinite ghost life +GHOST_TIME_TO_LIVE = 0 * TICKS_PER_MINUTE -- set to 0 for infinite ghost life ------------------------------------------------------------------------------- -- DEBUG / Custom stuff -------------------------------------------------------------------------------- - OARC_DIFFICULTY_CUSTOM = false -- DEBUG prints for me diff --git a/locale/frontier_silo.lua b/locale/frontier_silo.lua index f40d8a2..ccc12dc 100644 --- a/locale/frontier_silo.lua +++ b/locale/frontier_silo.lua @@ -135,7 +135,7 @@ function GenerateRocketSiloChunk(event) RemoveDecorationsArea(surface, chunkArea) -- Create rocket silo - CreateCropOctagon(surface, siloPos, chunkArea, 40) + CreateCropOctagon(surface, siloPos, chunkArea, CHUNK_SIZE*2) end end end diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index 038e25e..e4ed990 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -27,14 +27,14 @@ my_fixed_width_style = { my_label_style = { minimal_width = 450, maximal_width = 450, - maximal_height = 10, + -- maximal_height = 10, font_color = {r=1,g=1,b=1}, top_padding = 0, bottom_padding = 0 } my_note_style = { minimal_width = 450, - maximal_height = 10, + -- maximal_height = 10, font = "default-small-semibold", font_color = {r=1,g=0.5,b=0.5}, top_padding = 0, @@ -43,7 +43,7 @@ my_note_style = { my_warning_style = { minimal_width = 450, maximal_width = 450, - maximal_height = 10, + -- maximal_height = 10, font_color = {r=1,g=0.1,b=0.1}, top_padding = 0, bottom_padding = 0 @@ -52,7 +52,7 @@ my_spacer_style = { minimal_width = 450, maximal_width = 450, minimal_height = 20, - maximal_height = 20, + -- maximal_height = 20, font_color = {r=0,g=0,b=0}, top_padding = 0, bottom_padding = 0 @@ -71,30 +71,38 @@ my_player_list_admin_style = { minimal_width = 200, top_padding = 0, bottom_padding = 0, - maximal_height = 15 + -- maximal_height = 15 } my_player_list_style = { font = "default-semibold", minimal_width = 200, top_padding = 0, bottom_padding = 0, - maximal_height = 15 + -- maximal_height = 15 +} +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, + -- maximal_height = 15 } my_player_list_style_spacer = { - maximal_height = 15 + -- maximal_height = 15 } my_color_red = {r=1,g=0.1,b=0.1} my_longer_label_style = { maximal_width = 600, - maximal_height = 10, + -- maximal_height = 10, font_color = {r=1,g=1,b=1}, top_padding = 0, bottom_padding = 0 } my_longer_warning_style = { maximal_width = 600, - maximal_height = 10, + -- maximal_height = 10, font_color = {r=1,g=0.1,b=0.1}, top_padding = 0, bottom_padding = 0 @@ -714,6 +722,15 @@ local function ExpandPlayerListGui(player) ApplyStyle(text, my_player_list_style) end end + if (PLAYER_LIST_OFFLINE_PLAYERS) then + 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"} ApplyStyle(spacer, my_player_list_style_spacer) end @@ -788,7 +805,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 @@ -926,8 +943,8 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius) -- 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 @@ -946,7 +963,7 @@ 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 @@ -979,15 +996,15 @@ 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+(2000*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 + if ((distVar <= tileRadSqr) and + (distVar > tileRadSqr-10000)) then table.insert(waterTiles, {name = "grass-1", position ={i,j}}) end end @@ -1008,6 +1025,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 @@ -1116,7 +1136,7 @@ function SetupAndClearSpawnAreas(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 diff --git a/locale/rso/rso_config.lua b/locale/rso/rso_config.lua index 77ff59b..11291d4 100644 --- a/locale/rso/rso_config.lua +++ b/locale/rso/rso_config.lua @@ -1,6 +1,6 @@ debug_enabled = false -region_size = 8 -- alternative mean to control how further away resources would be, default - 256 tiles or 8 chunks +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 @@ -8,7 +8,7 @@ use_donut_shapes = false -- setting this to false will remove donuts from possi 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 +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 @@ -23,9 +23,9 @@ multi_resource_chance_diminish = 0.6 -- diminishing effect factor on multi_resou min_amount=250 -- default value for minimum amount of resource in single pile -richness_distance_factor= 0.5 -- exponent for richness distance factor calculation +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.15 -- exponent for size distance factor calculation +size_distance_factor=0.3 -- exponent for size distance factor calculation deterministic = true -- set to false to use system for all decisions math.random diff --git a/regrowth_map.lua b/regrowth_map.lua index f214144..4be72b7 100644 --- a/regrowth_map.lua +++ b/regrowth_map.lua @@ -321,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 @@ -329,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 @@ -340,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 \ No newline at end of file diff --git a/separate_spawns.lua b/separate_spawns.lua index 1087bec..30735ba 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -267,12 +267,14 @@ function QueuePlayerForDelayedSpawn(playerName, spawn, moatEnabled) if ((spawn.x ~= 0) and (spawn.y ~= 0)) then global.uniqueSpawns[playerName] = {pos=spawn,moat=moatEnabled} - game.players[playerName].print("Generating your spawn now, please wait a few seconds...") + 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 + 10*TICKS_PER_SECOND + 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]) + DisplayPleaseWaitForSpawnDialog(game.players[playerName], delay_spawn_seconds) else DebugPrint("THIS SHOULD NOT EVER HAPPEN! Spawn failed!") @@ -320,6 +322,9 @@ function SendPlayerToNewSpawnAndCreateIt(playerName, spawn, moatEnabled) 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 diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index 6704a08..cc93251 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -5,8 +5,8 @@ require("separate_spawns") -local SPAWN_GUI_MAX_WIDTH = 550 -local SPAWN_GUI_MAX_HEIGHT = 800 +local SPAWN_GUI_MAX_WIDTH = 1000 +local SPAWN_GUI_MAX_HEIGHT = 1000 -- Use this for testing shared spawns... -- local sharedSpawnExample1 = {openAccess=true, @@ -142,10 +142,10 @@ function DisplaySpawnOptions(player) -- Warnings and explanations... sGui.add{name = "warning_lbl1", type = "label", caption="This is your ONLY chance to choose a spawn option. Choose carefully..."} - sGui.add{name = "warning_spacer", type = "label", - caption=" "} + -- sGui.add{name = "warning_spacer", type = "label", + -- caption=" "} ApplyStyle(sGui.warning_lbl1, my_warning_style) - ApplyStyle(sGui.warning_spacer, my_spacer_style) + -- ApplyStyle(sGui.warning_spacer, my_spacer_style) sGui.add{name = "spawn_msg_lbl1", type = "label", caption=SPAWN_MSG1} @@ -266,11 +266,15 @@ function DisplaySpawnOptions(player) -- New awesome buddy spawning system if ENABLE_SHARED_SPAWNS and ENABLE_BUDDY_SPAWN then + sGui.add{name = "buddy_spawn_msg_spacer", type = "label", + caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} + ApplyStyle(sGui.buddy_spawn_msg_spacer, my_spacer_style) + sGui.add{name = "buddy_spawn", type = "button", caption="Buddy Spawn"} sGui.add{name = "buddy_spawn_lbl1", type = "label", - caption="You spawn next to a buddy of your choosing."} + caption="Buddy System requires 2 players in this menu at the same time, you spawn beside each other."} end -- Some final notes @@ -375,7 +379,7 @@ function SpawnOptsGuiClick(event) GivePlayerStarterItems(player) ChangePlayerSpawn(player, player.force.get_spawn_position(GAME_SURFACE_NAME)) SendBroadcastMsg(player.name .. " is joining the main force!") - ChartArea(player.force, player.position, 4, player.surface) + ChartArea(player.force, player.position, math.ceil(ENFORCE_LAND_AREA_TILE_DIST/CHUNK_SIZE), player.surface) -- Create the button at the top left for setting respawn point and sharing base. CreateSpawnCtrlGui(player) @@ -1347,7 +1351,7 @@ function BuddySpawnRequestMenuClick(event) end -function DisplayPleaseWaitForSpawnDialog(player) +function DisplayPleaseWaitForSpawnDialog(player, delay_seconds) player.gui.center.add{name = "wait_for_spawn_dialog", type = "frame", @@ -1362,7 +1366,7 @@ function DisplayPleaseWaitForSpawnDialog(player) pleaseWaitGui.add{name = "warning_lbl1", type = "label", caption="Your spawn is being created now."} pleaseWaitGui.add{name = "warning_lbl2", type = "label", - caption="You will be teleported there in a few seconds!"} + caption="You will be teleported there in "..delay_seconds.." seconds!"} pleaseWaitGui.add{name = "warning_lbl3", type = "label", caption="Please standby..."} pleaseWaitGui.add{name = "warning_spacer", type = "label", From 8a06581c7d4f97ce8cbbd1a99dae7342a9051e4d Mon Sep 17 00:00:00 2001 From: Oarcinae Date: Fri, 16 Mar 2018 19:32:49 -0400 Subject: [PATCH 58/58] Changed a LOT of text to use a few label/spacer utility functions. Changed a lot of text to be multi-line so I fix the absurd spacing issues I had previously. I added better support for changing spawn sizes. Fixed a bug with rejecting players requests to join. --- config.lua | 53 +++--- locale/game_opts.lua | 124 ++++--------- locale/oarc_utils.lua | 64 ++++--- locale/rso/rso_config.lua | 2 +- locale/rso/rso_control.lua | 2 +- separate_spawns.lua | 2 +- separate_spawns_guis.lua | 363 ++++++++----------------------------- 7 files changed, 187 insertions(+), 423 deletions(-) diff --git a/config.lua b/config.lua index c028616..3a65933 100644 --- a/config.lua +++ b/config.lua @@ -7,38 +7,32 @@ -------------------------------------------------------------------------------- -- 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:" -OTHER_MSG2 = "0.16 experimental release. Tweaks to fix spawn issues / text / difficulty." --- Optional other messages below: -OTHER_MSG3 = "This scenario gives you or your friends your own starting area." -OTHER_MSG4 = "You can be on the main team or your own. All teams are friendly." -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 -------------------------------------------------------------------------------- @@ -167,6 +161,7 @@ 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 -- If you make this much bigger than a few chunks, good luck. ENFORCE_LAND_AREA_TILE_DIST = CHUNK_SIZE*1.8 @@ -261,7 +256,8 @@ 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 @@ -309,7 +305,7 @@ ENEMY_DESTROY_FACTOR_DIVISOR = 1 SILO_NUM_SPAWNS = 3 -- How many chunks away from the center of the map should the silo be spawned -SILO_CHUNK_DISTANCE = 100 +SILO_CHUNK_DISTANCE = 200 -- If this is enabled, you get ONE silo at the location specified below. SILO_FIXED_POSITION = false @@ -376,10 +372,10 @@ global.clMapGen.autoplace_controls = { ["stone"]={frequency= "very-low", size= "low", richness= "high"}, ["uranium-ore"]={frequency= "low", size= "low", richness= "high"}, - ["desert"]={frequency= "low", size= "low", richness= "normal"}, - ["dirt"]={frequency= "low", size= "low", richness= "normal"}, + ["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= "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? @@ -402,3 +398,8 @@ 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!" diff --git a/locale/game_opts.lua b/locale/game_opts.lua index be7792a..05805ff 100644 --- a/locale/game_opts.lua +++ b/locale/game_opts.lua @@ -24,65 +24,34 @@ local function ExpandGameOptionsGui(player) direction="vertical"} -- General Server Info: - frame.add{name = "info_1", type = "label", - caption=WELCOME_MSG_OARC} - frame.add{name = "info_2", type = "label", - caption=WELCOME_MSG1} - frame.add{name = "info_3", type = "label", - caption=WELCOME_MSG2} - frame.add{name = "info_4", type = "label", - caption=WELCOME_MSG6} - frame.add{name = "info_spacer", type = "label", - caption=" "} - ApplyStyle(frame.info_1, my_longer_label_style) - ApplyStyle(frame.info_2, my_longer_label_style) - ApplyStyle(frame.info_3, my_longer_label_style) - ApplyStyle(frame.info_4, my_longer_label_style) - ApplyStyle(frame.info_spacer, my_spacer_style) - + 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: - frame.add{name = "server_time", type = "label", - caption="Server Run Time: " .. formattime_hours_mins(game.tick)} - frame.add{name = "evo_now", type = "label", - caption="Current Evolution: " .. string.format("%.4f", game.forces["enemy"].evolution_factor)} - frame.add{name = "evo_factor_time", type = "label", - caption="Enemy evolution time factor: " .. game.map_settings.enemy_evolution.time_factor} - frame.add{name = "evo_factor_pollution", type = "label", - caption="Enemy evolution pollution factor: " .. game.map_settings.enemy_evolution.pollution_factor} - frame.add{name = "evo_factor_destroy", type = "label", - caption="Enemy evolution destroy factor: " .. game.map_settings.enemy_evolution.destroy_factor} - if game.map_settings.enemy_expansion.enabled then - enemy_expansion_txt = "enabled" - else - enemy_expansion_txt = "disabled" - end - frame.add{name = "enemy_expansion", type = "label", - caption="Enemy expansion is " .. enemy_expansion_txt} - frame.add{name = "enemy_spacer", type = "label", - caption=" "} - ApplyStyle(frame.server_time, my_longer_label_style) - ApplyStyle(frame.evo_now, my_longer_label_style) - ApplyStyle(frame.evo_factor_time, my_longer_label_style) - ApplyStyle(frame.evo_factor_pollution, my_longer_label_style) - ApplyStyle(frame.evo_factor_destroy, my_longer_label_style) - ApplyStyle(frame.enemy_expansion, my_longer_label_style) - ApplyStyle(frame.enemy_spacer, my_spacer_style) + 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: - frame.add{name = "core_mod_en", type = "label", - caption="Core game mode (separate spawns) is enabled."} - ApplyStyle(frame.core_mod_en, my_longer_label_style) + 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.font_color=my_color_red + frame.core_mod_en.style.font_color=my_color_red end -- Soft Mods: - if (ENABLE_SEPARATE_SPAWNS) then - soft_mods_string = "Oarc Core" - else + local soft_mods_string = "Oarc Core" + if (not ENABLE_SEPARATE_SPAWNS) then soft_mods_string = "Oarc Core [DISABLED!]" end if (ENABLE_RSO) then @@ -103,64 +72,41 @@ local function ExpandGameOptionsGui(player) if (ENABLE_PLAYER_LIST) then soft_mods_string = soft_mods_string .. ", Player List" end - frame.add{name = "soft_mods", type = "label", - caption="Soft Mods Enabled: " .. soft_mods_string} - ApplyStyle(frame.soft_mods, my_longer_label_style) + + local game_info_str = "Soft Mods Enabled: " .. soft_mods_string -- Spawn options: if (ENABLE_SEPARATE_TEAMS) then - frame.add{name = "separate_teams_mod", type = "label", - caption="You are allowed to spawn on your own team (have your own research tree). All teams are COOP."} - ApplyStyle(frame.separate_teams_mod, my_longer_label_style) + 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 - frame.add{name = "buddy_spawn_mod", type = "label", - caption="You can chose to spawn alongside a buddy if you spawn together at the same time."} - ApplyStyle(frame.buddy_spawn_mod, my_longer_label_style) + 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 - frame.add{name = "share_spawn_mod", type = "label", - caption="Spawn hosts may choose to share their spawn and allow other players to join them."} - ApplyStyle(frame.share_spawn_mod, my_longer_label_style) + 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 - frame.add{name = "shared_team_vision_mod", type = "label", - caption="Everyone (all teams) have shared vision."} - ApplyStyle(frame.shared_team_vision_mod, my_longer_label_style) + game_info_str = game_info_str.."\n".."Everyone (all teams) have shared vision." end - - -- Silo: if (FRONTIER_ROCKET_SILO_MODE) then - frame.add{name = "silo_mod", type = "label", - caption="Silos are NOT craftable. There is at least one already located on the map."} - ApplyStyle(frame.silo_mod, my_longer_label_style) + game_info_str = game_info_str.."\n".."Silos are NOT craftable. There is at least one already located on the map." end - - -- Regrowth: if (ENABLE_REGROWTH) then - frame.add{name = "regrowth_mod", type = "label", - caption="Old parts of the map will slowly be deleted over time (chunks without any player buildings)."} - ApplyStyle(frame.regrowth_mod, my_longer_label_style) + game_info_str = game_info_str.."\n".."Old parts of the map will slowly be deleted over time (chunks without any player buildings)." end - - -- Minimum Play Time: - if (ENABLE_ABANDONED_BASE_REMOVAL) then - frame.add{name = "base_removal", type = "label", - caption="If you leave within " .. MIN_ONLINE_TIME_IN_MINUTES .. " minutes of joining, your base and character will be deleted."} - ApplyStyle(frame.base_removal, my_longer_warning_style) - end - - -- Quick Start: if (ENABLE_POWER_ARMOR_QUICK_START) then - frame.add{name = "power_armor_quick_start", type = "label", - caption="Power armor quick start enabled."} - ApplyStyle(frame.power_armor_quick_start, my_longer_label_style) + 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 - frame.add{name = "end_spacer", type = "label", - caption=" "} - ApplyStyle(frame.end_spacer, my_spacer_style) + AddSpacer(frame, "end_spacer") -- ADMIN CONTROLS if (player.admin) then diff --git a/locale/oarc_utils.lua b/locale/oarc_utils.lua index e4ed990..3907df1 100644 --- a/locale/oarc_utils.lua +++ b/locale/oarc_utils.lua @@ -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,14 +68,14 @@ 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", @@ -86,23 +83,23 @@ my_player_list_offline_style = { minimal_width = 200, top_padding = 0, bottom_padding = 0, - -- maximal_height = 15 + 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, - -- maximal_height = 10, + single_line = false, font_color = {r=1,g=1,b=1}, top_padding = 0, bottom_padding = 0 } my_longer_warning_style = { maximal_width = 600, - -- maximal_height = 10, + single_line = false, font_color = {r=1,g=0.1,b=0.1}, top_padding = 0, bottom_padding = 0 @@ -334,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 @@ -715,14 +733,16 @@ 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)..")" @@ -996,7 +1016,7 @@ 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+(2000*MOAT_SIZE_MODIFIER)) and + if ((distVar < tileRadSqr+(1500*MOAT_SIZE_MODIFIER)) and (distVar > tileRadSqr)) then table.insert(waterTiles, {name = "water", position ={i,j}}) end diff --git a/locale/rso/rso_config.lua b/locale/rso/rso_config.lua index 11291d4..f11a495 100644 --- a/locale/rso/rso_config.lua +++ b/locale/rso/rso_config.lua @@ -6,7 +6,7 @@ region_size = 10 -- alternative mean to control how further away resources wo 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 +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 diff --git a/locale/rso/rso_control.lua b/locale/rso/rso_control.lua index 236be79..5c9afc6 100644 --- a/locale/rso/rso_control.lua +++ b/locale/rso/rso_control.lua @@ -1525,7 +1525,7 @@ function RSO_init() updateConfig() - spawn_starting_resources(global.mainSurface, 1 ) + spawn_starting_resources(surface, 1 ) initDone = true diff --git a/separate_spawns.lua b/separate_spawns.lua index 30735ba..1e0448b 100644 --- a/separate_spawns.lua +++ b/separate_spawns.lua @@ -84,7 +84,7 @@ function FindUnusedSpawns(event) -- 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) < (CHUNK_SIZE*10))) then + 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 diff --git a/separate_spawns_guis.lua b/separate_spawns_guis.lua index cc93251..04b2dd6 100755 --- a/separate_spawns_guis.lua +++ b/separate_spawns_guis.lua @@ -5,7 +5,7 @@ require("separate_spawns") -local SPAWN_GUI_MAX_WIDTH = 1000 +local SPAWN_GUI_MAX_WIDTH = 500 local SPAWN_GUI_MAX_HEIGHT = 1000 -- Use this for testing shared spawns... @@ -35,64 +35,17 @@ function DisplayWelcomeTextGui(player) wGui.style.maximal_width = SPAWN_GUI_MAX_WIDTH wGui.style.maximal_height = SPAWN_GUI_MAX_HEIGHT + -- Start with server message. + AddLabel(wGui, "server_msg_lbl1", SERVER_MSG, my_label_style) + AddLabel(wGui, "contact_info_msg_lbl1", CONTACT_MSG, my_label_style) + AddSpacer(wGui, "server_msg_spacer1") + -- Informational message about the scenario + AddLabel(wGui, "scenario_info_msg_lbl1", SCENARIO_INFO_MSG, my_label_style) + AddSpacer(wGui, "scenario_info_msg_spacer1") - wGui.add{name = "welcome_msg_lbl1", type = "label", - caption=WELCOME_MSG1} - wGui.add{name = "welcome_msg_lbl2", type = "label", - caption=WELCOME_MSG2} - wGui.add{name = "welcome_msg_spacer1", type = "label", - caption=" "} - - ApplyStyle(wGui.welcome_msg_lbl1, my_label_style) - ApplyStyle(wGui.welcome_msg_lbl2, my_label_style) - ApplyStyle(wGui.welcome_msg_spacer1, my_spacer_style) - - wGui.add{name = "other_msg_lbl1", type = "label", - caption=OTHER_MSG1} - wGui.add{name = "other_msg_lbl2", type = "label", - caption=OTHER_MSG2} - if (OTHER_MSG3 ~= nil) then - wGui.add{name = "other_msg_lbl3", type = "label", - caption=OTHER_MSG3} - ApplyStyle(wGui.other_msg_lbl3, my_label_style) - end - if (OTHER_MSG4 ~= nil) then - wGui.add{name = "other_msg_lbl4", type = "label", - caption=OTHER_MSG4} - ApplyStyle(wGui.other_msg_lbl4, my_label_style) - end - if (OTHER_MSG5 ~= nil) then - wGui.add{name = "other_msg_lbl5", type = "label", - caption=OTHER_MSG5} - ApplyStyle(wGui.other_msg_lbl5, my_label_style) - end - wGui.add{name = "other_msg_spacer1", type = "label", - caption=" "} - - ApplyStyle(wGui.other_msg_lbl1, my_label_style) - ApplyStyle(wGui.other_msg_lbl2, my_label_style) - ApplyStyle(wGui.other_msg_spacer1, my_spacer_style) - - wGui.add{name = "welcome_msg_lbl3", type = "label", - caption=WELCOME_MSG3} - wGui.add{name = "welcome_msg_lbl4", type = "label", - caption=WELCOME_MSG4} - wGui.add{name = "welcome_msg_lbl5", type = "label", - caption=WELCOME_MSG5} - wGui.add{name = "welcome_msg_lbl6", type = "label", - caption=WELCOME_MSG6} - wGui.add{name = "welcome_msg_spacer2", type = "label", - caption=" "} - - ApplyStyle(wGui.welcome_msg_lbl3, my_warning_style) - ApplyStyle(wGui.welcome_msg_lbl4, my_warning_style) - ApplyStyle(wGui.welcome_msg_lbl5, my_warning_style) - ApplyStyle(wGui.welcome_msg_lbl6, my_label_style) - ApplyStyle(wGui.welcome_msg_spacer2, my_spacer_style) - - - + -- Warning about spawn creation time + AddLabel(wGui, "spawn_time_msg_lbl1", SPAWN_WARN_MSG, my_warning_style) wGui.add{name = "welcome_okay_btn", type = "button", caption="I Understand"} @@ -140,46 +93,19 @@ function DisplaySpawnOptions(player) -- Warnings and explanations... - sGui.add{name = "warning_lbl1", type = "label", - caption="This is your ONLY chance to choose a spawn option. Choose carefully..."} - -- sGui.add{name = "warning_spacer", type = "label", - -- caption=" "} - ApplyStyle(sGui.warning_lbl1, my_warning_style) - -- ApplyStyle(sGui.warning_spacer, my_spacer_style) - - sGui.add{name = "spawn_msg_lbl1", type = "label", - caption=SPAWN_MSG1} - sGui.add{name = "spawn_msg_lbl2", type = "label", - caption=SPAWN_MSG2} - sGui.add{name = "spawn_msg_lbl3", type = "label", - caption=SPAWN_MSG3} - sGui.add{name = "spawn_msg_spacer", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - ApplyStyle(sGui.spawn_msg_lbl1, my_label_style) - ApplyStyle(sGui.spawn_msg_lbl2, my_label_style) - ApplyStyle(sGui.spawn_msg_lbl3, my_label_style) - ApplyStyle(sGui.spawn_msg_spacer, my_spacer_style) - + local warn_msg = "Click the INFO button in the top left to learn more about this scenario! This is your ONLY chance to choose a spawn option. Choose carefully..." + AddLabel(sGui, "warning_lbl1", warn_msg, my_warning_style) + AddLabel(sGui, "spawn_msg_lbl1", SPAWN_MSG1, my_label_style) + -- Button and message about the regular vanilla spawn if ENABLE_DEFAULT_SPAWN then sGui.add{name = "default_spawn_btn", - type = "button", - caption="Default Spawn"} - sGui.add{name = "normal_spawn_lbl1", type = "label", - caption="This is the default spawn behavior of a vanilla game."} - sGui.add{name = "normal_spawn_lbl2", type = "label", - caption="You join the default team in the center of the map."} - ApplyStyle(sGui.normal_spawn_lbl1, my_label_style) - ApplyStyle(sGui.normal_spawn_lbl2, my_label_style) - else - sGui.add{name = "normal_spawn_lbl1", type = "label", - caption="Default spawn is disabled in this mode."} - ApplyStyle(sGui.normal_spawn_lbl1, my_warning_style) + type = "button", + caption="Vanilla Spawn"} + local normal_spawn_text = "This is the default spawn behavior of a vanilla game. You join the default team in the center of the map." + AddLabel(sGui, "normal_spawn_lbl1", normal_spawn_text, my_label_style) + AddSpacerLine(sGui, "normal_spawn_spacer") end - sGui.add{name = "normal_spawn_spacer", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - ApplyStyle(sGui.normal_spawn_spacer, my_spacer_style) - -- The main spawning options. Solo near and solo far. -- If enable, you can also choose to be on your own team. @@ -187,7 +113,6 @@ function DisplaySpawnOptions(player) type = "flow", direction="vertical"} - -- Radio buttons to pick your team. if (ENABLE_SEPARATE_TEAMS) then soloSpawnFlow.add{name = "isolated_spawn_main_team_radio", @@ -208,24 +133,19 @@ function DisplaySpawnOptions(player) state=false} end - soloSpawnFlow.add{name = "team_chat_warning_spacer", type = "label", - caption=" "} - ApplyStyle(soloSpawnFlow.team_chat_warning_spacer, my_spacer_style) - - soloSpawnFlow.add{name = "isolated_spawn_near", + -- Isolated spawn options. The core gameplay of this scenario. + local soloSpawnbuttons = soloSpawnFlow.add{name = "spawn_solo_flow", + type = "flow", + direction="horizontal"} + soloSpawnbuttons.add{name = "isolated_spawn_near", type = "button", caption="Solo Spawn (Near)"} - soloSpawnFlow.add{name = "isolated_spawn_far", + soloSpawnbuttons.add{name = "isolated_spawn_far", type = "button", caption="Solo Spawn (Far)"} - - soloSpawnFlow.add{name = "isolated_spawn_lbl1", type = "label", - caption="You are spawned in a new area, with some starting resources."} - ApplyStyle(soloSpawnFlow.isolated_spawn_lbl1, my_label_style) - - sGui.add{name = "isolated_spawn_spacer", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - ApplyStyle(sGui.isolated_spawn_spacer, my_spacer_style) + AddLabel(soloSpawnFlow, "isolated_spawn_lbl1", + "You are spawned in a new area, with some starting resources.", my_label_style) + AddSpacerLine(soloSpawnFlow, "isolated_spawn_spacer") -- Spawn options to join another player's base. @@ -235,73 +155,41 @@ function DisplaySpawnOptions(player) sGui.add{name = "join_other_spawn", type = "button", caption="Join Someone (" .. numAvailSpawns .. " available)"} - sGui.add{name = "join_other_spawn_lbl1", type = "label", - caption="You are spawned in someone else's base."} - sGui.add{name = "join_other_spawn_lbl2", type = "label", - caption="This requires at least 1 person to have allowed access to their base."} - sGui.add{name = "join_other_spawn_lbl3", type = "label", - caption="This choice is final and you will not be able to create your own spawn later."} - sGui.add{name = "join_other_spawn_spacer", type = "label", - caption=" "} - ApplyStyle(sGui.join_other_spawn_lbl1, my_label_style) - ApplyStyle(sGui.join_other_spawn_lbl2, my_label_style) - ApplyStyle(sGui.join_other_spawn_lbl3, my_label_style) - ApplyStyle(sGui.join_other_spawn_spacer, my_spacer_style) + local join_spawn_text = "You are spawned in someone else's base. This requires at least 1 person to have allowed access to their base. This choice is final and you will not be able to create your own spawn later." + AddLabel(sGui, "join_other_spawn_lbl1", join_spawn_text, my_label_style) else - sGui.add{name = "join_other_spawn_lbl1", type = "label", - caption="There are currently no shared bases availble to spawn at."} - sGui.add{name = "join_other_spawn_spacer", type = "label", - caption=" "} - ApplyStyle(sGui.join_other_spawn_lbl1, my_warning_style) - ApplyStyle(sGui.join_other_spawn_spacer, my_spacer_style) + AddLabel(sGui, "join_other_spawn_lbl1", "There are currently no shared bases availble to spawn at.", my_label_style) sGui.add{name = "join_other_spawn_check", type = "button", caption="Check Again"} end else - sGui.add{name = "join_other_spawn_lbl1", type = "label", - caption="Shared spawns are disabled in this mode."} - ApplyStyle(sGui.join_other_spawn_lbl1, my_warning_style) + AddLabel(soloSpawnFlow, "join_other_spawn_lbl1", + "Shared spawns are disabled in this mode.", my_warning_style) end -- New awesome buddy spawning system if ENABLE_SHARED_SPAWNS and ENABLE_BUDDY_SPAWN then - sGui.add{name = "buddy_spawn_msg_spacer", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - ApplyStyle(sGui.buddy_spawn_msg_spacer, my_spacer_style) - + AddSpacerLine(sGui, "buddy_spawn_msg_spacer") sGui.add{name = "buddy_spawn", type = "button", caption="Buddy Spawn"} - sGui.add{name = "buddy_spawn_lbl1", type = "label", - caption="Buddy System requires 2 players in this menu at the same time, you spawn beside each other."} + AddLabel(sGui, "buddy_spawn_lbl1", + "The buddy system requires 2 players in this menu at the same time, you spawn beside each other, each with your own resources.", my_label_style) end -- Some final notes - sGui.add{name = "note_spacer1", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - sGui.add{name = "note_spacer2", type = "label", - caption=" "} + AddSpacerLine(sGui, "note_spacer1") if (MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN > 0) then - sGui.add{name = "shared_spawn_note1", type = "label", - caption="If you create your own spawn point you can allow up to " .. MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN-1 .. " other online players to join." } - ApplyStyle(sGui.shared_spawn_note1, my_note_style) + AddLabel(sGui, "buddy_spawn_lbl1", + "If you create your own spawn point you can allow up to " .. MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN-1 .. " other online players to join.", + my_note_style) end - sGui.add{name = "note_lbl1", type = "label", - caption="Near spawn is between " .. NEAR_MIN_DIST*CHUNK_SIZE .. "-" .. NEAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."} - sGui.add{name = "note_lbl2", type = "label", - caption="Far spawn is between " .. FAR_MIN_DIST*CHUNK_SIZE .. "-" .. FAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."} - sGui.add{name = "note_lbl3", type = "label", - caption="Solo spawns are dangerous! Expect a fight to reach other players."} - sGui.add{name = "note_spacer3", type = "label", - caption=" "} - ApplyStyle(sGui.note_lbl1, my_note_style) - ApplyStyle(sGui.note_lbl2, my_note_style) - ApplyStyle(sGui.note_lbl3, my_note_style) - ApplyStyle(sGui.note_spacer1, my_spacer_style) - ApplyStyle(sGui.note_spacer2, my_spacer_style) - ApplyStyle(sGui.note_spacer3, my_spacer_style) + spawn_distance_notes="Near spawn is between " .. NEAR_MIN_DIST .. "-" .. NEAR_MAX_DIST .. " chunks away from the center of the map.\n".. + "Far spawn is between " .. FAR_MIN_DIST .. "-" .. FAR_MAX_DIST .. " chunks away from the center of the map.\n".. + "Solo spawns are dangerous! Expect a fight to reach other players." + AddLabel(sGui, "note_lbl1", spawn_distance_notes, my_note_style) end @@ -468,9 +356,8 @@ function DisplaySharedSpawnOptions(player) shGui.add{type="button", caption=spawnName .. " (" .. spotsRemaining .. " spots remaining)", name=spawnName} end if (shGui.spawnName ~= nil) then - shGui.add{name = spawnName .. "spacer_lbl", type = "label", caption=" "} + -- AddSpacer(buddyGui, spawnName .. "spacer_lbl") ApplyStyle(shGui[spawnName], my_small_button_style) - ApplyStyle(shGui[spawnName .. "spacer_lbl"], my_spacer_style) end end end @@ -547,13 +434,7 @@ function DisplaySharedSpawnJoinWaitMenu(player) -- Warnings and explanations... - sGui.add{name = "warning_lbl1", type = "label", - caption="You will spawn once the host selects yes..."} - sGui.add{name = "warning_spacer", type = "label", - caption=" "} - ApplyStyle(sGui.warning_lbl1, my_warning_style) - ApplyStyle(sGui.warning_spacer, my_spacer_style) - + AddLabel(sGui, "warning_lbl1", "You will spawn once the host selects yes...", my_warning_style) sGui.add{name = "cancel_shared_spawn_wait_menu", type = "button", caption="Cancel (Return to starting spawn options)"} @@ -665,31 +546,19 @@ function ExpandSpawnCtrlGui(player, tick) if ((tick - global.playerCooldowns[player.name].setRespawn) > RESPAWN_COOLDOWN_TICKS) then spwnCtrls.add{type="button", name="setRespawnLocation", caption="Set New Respawn Location (1 hour cooldown)"} spwnCtrls["setRespawnLocation"].style.font = "default-small-semibold" - spwnCtrls.add{name = "respawn_cooldown_note2", type = "label", - caption="This will set your respawn point to your current location."} - spwnCtrls.add{name = "respawn_cooldown_spacer1", type = "label", - caption=" "} - ApplyStyle(spwnCtrls.respawn_cooldown_note2, my_note_style) - ApplyStyle(spwnCtrls.respawn_cooldown_spacer1, my_spacer_style) + else - spwnCtrls.add{name = "respawn_cooldown_note1", type = "label", - caption="Set Respawn Cooldown Remaining: " .. formattime(RESPAWN_COOLDOWN_TICKS-(tick - global.playerCooldowns[player.name].setRespawn))} - spwnCtrls.add{name = "respawn_cooldown_note2", type = "label", - caption="This will set your respawn point to your current location."} - spwnCtrls.add{name = "respawn_cooldown_spacer1", type = "label", - caption=" "} - ApplyStyle(spwnCtrls.respawn_cooldown_note1, my_note_style) - ApplyStyle(spwnCtrls.respawn_cooldown_note2, my_note_style) - ApplyStyle(spwnCtrls.respawn_cooldown_spacer1, my_spacer_style) + AddLabel(spwnCtrls, "respawn_cooldown_note1", "Set Respawn Cooldown Remaining: " .. formattime(RESPAWN_COOLDOWN_TICKS-(tick - global.playerCooldowns[player.name].setRespawn)), my_note_style) end + AddLabel(spwnCtrls, "respawn_cooldown_note2", "This will set your respawn point to your current location.", my_note_style) -- Display a list of people in the join queue for your base. if (ENABLE_SHARED_SPAWNS and IsSharedSpawnActive(player)) then if ((global.sharedSpawns[player.name].joinQueue ~= nil) and (#global.sharedSpawns[player.name].joinQueue > 0)) then - spwnCtrls.add{name = "drop_down_msg_lbl1", type = "label", - caption="Select a player from the join queue:"} + + AddLabel(spwnCtrls, "drop_down_msg_lbl1", "Select a player from the join queue:", my_label_style) spwnCtrls.add{name = "join_queue_dropdown", type = "drop-down", items = global.sharedSpawns[player.name].joinQueue} @@ -699,16 +568,11 @@ function ExpandSpawnCtrlGui(player, tick) spwnCtrls.add{name = "reject_player_request", type = "button", caption="Reject"} - ApplyStyle(spwnCtrls.drop_down_msg_lbl1, my_label_style) else - spwnCtrls.add{name = "empty_join_queue_note1", type = "label", - caption="You have no players requesting to join you at this time."} - - ApplyStyle(spwnCtrls.empty_join_queue_note1, my_note_style) + AddLabel(spwnCtrls, "empty_join_queue_note1", "You have no players requesting to join you at this time.", my_note_style) end spwnCtrls.add{name = "join_queue_spacer", type = "label", caption=" "} - ApplyStyle(spwnCtrls.join_queue_spacer, my_spacer_style) end end end @@ -799,6 +663,7 @@ function SpawnCtrlGuiClick(event) if (elemName == "reject_player_request") then player.print("You rejected " .. joinQueuePlayerChoice .. "'s request to join your base.") SendMsg(joinQueuePlayerChoice, "Your request to join was rejected.") + ExpandSpawnCtrlGui(player, event.tick) -- Close the waiting players menu if (game.players[joinQueuePlayerChoice].gui.center.join_shared_spawn_wait_menu) then @@ -863,25 +728,9 @@ function DisplayBuddySpawnOptions(player) -- Warnings and explanations... - buddyGui.add{name = "warning_lbl1", type = "label", - caption="Once a buddy accepts a spawn request, it is final!"} - buddyGui.add{name = "warning_spacer", type = "label", - caption=" "} - ApplyStyle(buddyGui.warning_lbl1, my_warning_style) - ApplyStyle(buddyGui.warning_spacer, my_spacer_style) - - buddyGui.add{name = "spawn_msg_lbl1", type = "label", - caption=SPAWN_MSG1} - buddyGui.add{name = "spawn_msg_lbl2", type = "label", - caption=SPAWN_MSG2} - buddyGui.add{name = "spawn_msg_lbl3", type = "label", - caption=SPAWN_MSG3} - buddyGui.add{name = "spawn_msg_spacer", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - ApplyStyle(buddyGui.spawn_msg_lbl1, my_label_style) - ApplyStyle(buddyGui.spawn_msg_lbl2, my_label_style) - ApplyStyle(buddyGui.spawn_msg_lbl3, my_label_style) - ApplyStyle(buddyGui.spawn_msg_spacer, my_spacer_style) + buddy_info_msg="To use this, make sure you and your buddy are in this menu at the same time. Only one of you must send the request. Select your buddy from the list (refresh if your buddy's name is not visible) and select your spawn options. Click one of the request buttons to send the request. The other buddy can then accept (or deny) the request. This will allow you both to spawn next to each other, each with your own spawn area. Once a buddy accepts a spawn request, it is final!" + AddLabel(buddyGui, "buddy_info_msg", buddy_info_msg, my_label_style) + AddSpacerLine(buddyGui, "buddy_info_spacer") buddyList = {} for _,buddyName in pairs(global.waitingBuddies) do @@ -890,19 +739,14 @@ function DisplayBuddySpawnOptions(player) end end - buddyGui.add{name = "drop_down_msg_lbl1", type = "label", - caption="Select a buddy from the waiting list:"} + AddLabel(buddyGui, "drop_down_msg_lbl1", "First, select a buddy from the waiting list. Then choose the spawn options and send your request:", my_label_style) buddyGui.add{name = "waiting_buddies_dropdown", type = "drop-down", items = buddyList} buddyGui.add{name = "refresh_buddy_list", type = "button", caption="Refresh Buddy List"} - buddyGui.add{name = "waiting_buddies_spacer", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - ApplyStyle(buddyGui.drop_down_msg_lbl1, my_label_style) - ApplyStyle(buddyGui.waiting_buddies_spacer, my_spacer_style) - + -- AddSpacerLine(buddyGui, "waiting_buddies_spacer") -- The buddy spawning options. local buddySpawnFlow = buddyGui.add{name = "spawn_buddy_flow", @@ -932,25 +776,15 @@ function DisplayBuddySpawnOptions(player) state=false} end - buddySpawnFlow.add{name = "buddy_options_spacer", type = "label", - caption=" "} - ApplyStyle(buddySpawnFlow.buddy_options_spacer, my_spacer_style) - - + AddSpacer(buddyGui, "buddy_options_spacer") buddySpawnFlow.add{name = "buddy_spawn_request_near", type = "button", caption="Request Buddy Spawn (Near)"} buddySpawnFlow.add{name = "buddy_spawn_request_far", type = "button", caption="Request Buddy Spawn (Far)"} - - buddySpawnFlow.add{name = "buddy_spawn_lbl1", type = "label", - caption="You are spawned in a new area, with some starting resources."} - ApplyStyle(buddySpawnFlow.buddy_spawn_lbl1, my_label_style) + AddSpacerLine(buddyGui, "buddy_spawn_spacer") - buddyGui.add{name = "buddy_spawn_spacer", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - ApplyStyle(buddyGui.buddy_spawn_spacer, my_spacer_style) buddyGui.add{name = "buddy_spawn_cancel", @@ -958,30 +792,17 @@ function DisplayBuddySpawnOptions(player) caption="Cancel (Return to Previous Options)"} -- Some final notes - buddyGui.add{name = "note_spacer1", type = "label", - caption="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"} - buddyGui.add{name = "note_spacer2", type = "label", - caption=" "} + AddSpacerLine(buddyGui, "note_spacer1") - if MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN then - buddyGui.add{name = "shared_spawn_note1", type = "label", - caption="If you create your own spawn point you can allow up to " .. MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN-1 .. " other online players to join." } - ApplyStyle(buddyGui.shared_spawn_note1, my_note_style) + if (MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN > 0) then + AddLabel(buddyGui, "buddy_spawn_lbl1", + "You can allow up to " .. MAX_ONLINE_PLAYERS_AT_SHARED_SPAWN-1 .. " other online players to join.", + my_note_style) end - buddyGui.add{name = "note_lbl1", type = "label", - caption="Near spawn is between " .. NEAR_MIN_DIST*CHUNK_SIZE .. "-" .. NEAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."} - buddyGui.add{name = "note_lbl2", type = "label", - caption="Far spawn is between " .. FAR_MIN_DIST*CHUNK_SIZE .. "-" .. FAR_MAX_DIST*CHUNK_SIZE .. " tiles away from the center of the map."} - buddyGui.add{name = "note_lbl3", type = "label", - caption="Buddy spawns are only 1 chunk apart."} - buddyGui.add{name = "note_spacer3", type = "label", - caption=" "} - ApplyStyle(buddyGui.note_lbl1, my_note_style) - ApplyStyle(buddyGui.note_lbl2, my_note_style) - ApplyStyle(buddyGui.note_lbl3, my_note_style) - ApplyStyle(buddyGui.note_spacer1, my_spacer_style) - ApplyStyle(buddyGui.note_spacer2, my_spacer_style) - ApplyStyle(buddyGui.note_spacer3, my_spacer_style) + spawn_distance_notes="Near spawn is between " .. NEAR_MIN_DIST .. "-" .. NEAR_MAX_DIST .. " chunks away from the center of the map.\n".. + "Far spawn is between " .. FAR_MIN_DIST .. "-" .. FAR_MAX_DIST .. " chunks away from the center of the map.\n".. + "Solo spawns are dangerous! Expect a fight to reach other players." + AddLabel(buddyGui, "note_lbl1", spawn_distance_notes, my_note_style) end @@ -1116,13 +937,8 @@ function DisplayBuddySpawnWaitMenu(player) -- Warnings and explanations... - sGui.add{name = "warning_lbl1", type = "label", - caption="You will spawn once your buddy selects yes..."} - sGui.add{name = "warning_spacer", type = "label", - caption=" "} - ApplyStyle(sGui.warning_lbl1, my_warning_style) - ApplyStyle(sGui.warning_spacer, my_spacer_style) - + AddLabel(sGui, "warning_lbl1", "You will spawn once your buddy selects yes...", my_warning_style) + AddSpacer(sGui, "warning_spacer") sGui.add{name = "cancel_buddy_wait_menu", type = "button", caption="Cancel (Return to starting spawn options)"} @@ -1179,14 +995,8 @@ function DisplayBuddySpawnRequestMenu(player, requestingBuddyName) -- Warnings and explanations... - sGui.add{name = "warning_lbl1", type = "label", - caption=requestingBuddyName .. " is requesting a buddy spawn from you!"} - sGui.add{name = "warning_spacer", type = "label", - caption=" "} - ApplyStyle(sGui.warning_lbl1, my_warning_style) - ApplyStyle(sGui.warning_spacer, my_spacer_style) + AddLabel(sGui, "warning_lbl1", requestingBuddyName .. " is requesting a buddy spawn from you!", my_warning_style) - teamText = "error!" if (global.buddySpawnOptions[requestingBuddyName].joinMainTeamRadio) then teamText = "the main team" @@ -1210,15 +1020,10 @@ function DisplayBuddySpawnRequestMenu(player, requestingBuddyName) requestText = requestingBuddyName .. " would like to join " .. teamText .. " next to you" .. moatText .. distText + AddLabel(sGui, "note_lbl1", requestText, my_warning_style) + AddSpacer(sGui, "note_spacer1") - sGui.add{name = "note_lbl1", type = "label", - caption=requestText} - sGui.add{name = "note_spacer1", type = "label", - caption=" "} - ApplyStyle(sGui.note_lbl1, my_note_style) - ApplyStyle(sGui.note_spacer1, my_spacer_style) - sGui.add{name = "accept_buddy_request", type = "button", caption="Accept"} @@ -1305,9 +1110,9 @@ function BuddySpawnRequestMenuClick(event) -- Create that spawn in the global vars if (requesterOptions.moatChoice) then - buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*4), y=newSpawn.y} + buddySpawn = {x=newSpawn.x+(ENFORCE_LAND_AREA_TILE_DIST*2)+10, y=newSpawn.y} else - buddySpawn = {x=newSpawn.x+(CHUNK_SIZE*3), y=newSpawn.y} + buddySpawn = {x=newSpawn.x+(ENFORCE_LAND_AREA_TILE_DIST*2), y=newSpawn.y} end ChangePlayerSpawn(player, newSpawn) ChangePlayerSpawn(game.players[requesterName], buddySpawn) @@ -1363,17 +1168,9 @@ function DisplayPleaseWaitForSpawnDialog(player, delay_seconds) -- Warnings and explanations... - pleaseWaitGui.add{name = "warning_lbl1", type = "label", - caption="Your spawn is being created now."} - pleaseWaitGui.add{name = "warning_lbl2", type = "label", - caption="You will be teleported there in "..delay_seconds.." seconds!"} - pleaseWaitGui.add{name = "warning_lbl3", type = "label", - caption="Please standby..."} - pleaseWaitGui.add{name = "warning_spacer", type = "label", - caption=" "} - ApplyStyle(pleaseWaitGui.warning_lbl1, my_warning_style) - ApplyStyle(pleaseWaitGui.warning_lbl2, my_warning_style) - ApplyStyle(pleaseWaitGui.warning_lbl3, my_warning_style) - ApplyStyle(pleaseWaitGui.warning_spacer, my_spacer_style) + local wait_warning_text = "Your spawn is being created now.\n".. + "You will be teleported there in "..delay_seconds.." seconds!\n".. + "Please standby..." + AddLabel(pleaseWaitGui, "warning_lbl1", wait_warning_text, my_warning_style) end \ No newline at end of file