mirror of
https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git
synced 2024-12-04 09:43:00 +02:00
Merge pull request #157 from Oarcinae/dev
2.0.2 Minor Fixes and Features (+player list, +moat fish, +more GUI config)
This commit is contained in:
commit
54ab7c0a16
@ -1,4 +1,18 @@
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 2.0.2
|
||||
Date: 2024-10-08
|
||||
Major Features:
|
||||
- Added a new GUI config for all surface specific settings that can't be made available in the mod settings. This will let you easily configure all available settings via the in game custom GUI now. It is also possible to import and export settings as a serialized string. (You can still use a custom scenario to configure all settings as well using the template provided.)
|
||||
- Added a player list tab to the custom GUI so you can see all players on the server, and their locations.
|
||||
Bugfixes:
|
||||
- Fixed a minor issue with resource placement not calculating the angle correctly when placing solid resources.
|
||||
- Removed log spam related to offline enemy protection.
|
||||
- Fixed an issue with regrowth that was causing log spam about chunks not being tracked properly.
|
||||
Info:
|
||||
- Added fish to moats.
|
||||
- Doubled the default value for "minimum distance to existing chunks". There were some concerns bases might spawn too close together in some cases, this should help alleviate that.
|
||||
- Changed safe_area radii config to use chunks instead of tiles. Makes more sense for the setting and is easier to visualize distance in chunks. (Older configs should get migrated automatically, but you may want to double check your settings.)
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 2.0.1
|
||||
Date: 2024-09-25
|
||||
Bugfixes:
|
||||
|
52
control.lua
52
control.lua
@ -68,9 +68,14 @@ end)
|
||||
--------------------------------------------------------------------------------
|
||||
-- oarc_new_spawn_created = script.generate_event_name()
|
||||
|
||||
-- script.on_configuration_changed(function(data)
|
||||
-- -- Regenerate event ID:
|
||||
-- end)
|
||||
script.on_configuration_changed(function(data)
|
||||
-- Regenerate event ID:
|
||||
|
||||
-- Reset the players GUI
|
||||
for _,player in pairs(game.players) do
|
||||
RecreateOarcGui(player)
|
||||
end
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
|
||||
if (not StringStartsWith(event.setting, "oarc-mod")) then return end
|
||||
@ -96,6 +101,7 @@ script.on_event(defines.events.on_player_changed_surface, function(event)
|
||||
SeparateSpawnsPlayerChangedSurface(event)
|
||||
end)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- Shared chat, so you don't have to type /s
|
||||
-- But you do lose your player colors across forces.
|
||||
@ -248,30 +254,24 @@ end)
|
||||
-- Gui Events
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_gui_click, function(event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
if not event.element.valid then return end
|
||||
|
||||
SeparateSpawnsGuiClick(event)
|
||||
|
||||
ClickOarcGuiButton(event)
|
||||
ServerInfoGuiClick(event)
|
||||
SpawnCtrlGuiClick(event)
|
||||
SettingsControlsTabGuiClick(event)
|
||||
SettingsSurfaceControlsTabGuiClick(event)
|
||||
OarcGuiTabsClick(event)
|
||||
end)
|
||||
|
||||
--- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
|
||||
script.on_event(defines.events.on_gui_checked_state_changed, function (event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
if not event.element.valid then return end
|
||||
|
||||
SeparateSpawnsGuiCheckedStateChanged(event)
|
||||
|
||||
SpawnCtrlGuiOptionsSelect(event)
|
||||
OarcGuiTabsCheckedStateChanged(event)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_gui_selected_tab_changed, function (event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
if not event.element.valid then return end
|
||||
|
||||
OarcGuiSelectedTabChanged(event)
|
||||
OarcGuiTabsSelectedTabChanged(event)
|
||||
end)
|
||||
|
||||
-- For capturing player escaping custom GUI so we can close it using ESC key.
|
||||
@ -282,30 +282,36 @@ end)
|
||||
|
||||
--- For sliders and other value changing elements.
|
||||
script.on_event(defines.events.on_gui_value_changed, function(event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
if not event.element.valid then return end
|
||||
|
||||
SeparateSpawnsGuiValueChanged(event)
|
||||
SettingsControlsTabGuiValueChanged(event)
|
||||
OarcGuiTabsValueChanged(event)
|
||||
end)
|
||||
|
||||
--- For dropdowns and listboxes.
|
||||
script.on_event(defines.events.on_gui_selection_state_changed, function(event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
if not event.element.valid then return end
|
||||
|
||||
SeparateSpawnsGuiSelectionStateChanged(event)
|
||||
SettingsControlsTabGuiSelectionStateChanged(event)
|
||||
OarcGuiTabsSelectionStateChanged(event)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_gui_text_changed, function(event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
if not event.element.valid then return end
|
||||
|
||||
SettingsControlsTabGuiTextChanged(event)
|
||||
OarcGuiTabsTextChanged(event)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_gui_confirmed, function(event)
|
||||
if not event.element.valid then return end -- Should we ever react to invalid GUI elements?
|
||||
if not event.element.valid then return end
|
||||
|
||||
SettingsControlsTabGuiTextconfirmed(event)
|
||||
OarcGuiTabsConfirmed(event)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_gui_elem_changed, function(event)
|
||||
if not event.element.valid then return end
|
||||
|
||||
OarcGuiTabsElemChanged(event)
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
|
40
devplan.txt
40
devplan.txt
@ -35,6 +35,46 @@ Major:
|
||||
- Radar quality affects regrowth safe range?
|
||||
- Update electric pole connections for shared power if things change in V2.0
|
||||
|
||||
- Source: https://forums.factorio.com/115737
|
||||
- Specifics that I might need to investigate:
|
||||
Added LuaPlayer::land_on_planet() method.
|
||||
Added LuaPlayer::enter_space_platform() and leave_space_platform() method.
|
||||
Added cargo-landing-pad prototype.
|
||||
Added space-platform-starter-pack, space-location, planet and space-connection prototypes.
|
||||
Added surface-property and surface prototypes.
|
||||
Added new controller type (remote), which is to build space platforms, so it allows ghost building but not any physical manipulation.
|
||||
Added LuaPlayer::physical_surface, physical_surface_index, physical_vehicle and physical_position read.
|
||||
Electric pole created through LuaSurface::create_entity can be requested to not auto connect.
|
||||
Added LuaSurface::global_effect read/write.
|
||||
Added LuaSurface::localised_name read/write.
|
||||
LuaGameScript::print, LuaPlayer::print, LuaSurface::print and LuaForce::print no longer accept Color as a second parameter.
|
||||
Added LuaSurface::set_property() and get_property() methods.
|
||||
Added LuaSurface::execute_lightning() method.
|
||||
Added LuaSurface::create_global_electric_network() and destroy_global_electric_network() methods.
|
||||
Added LuaSurface::has_global_electric_network read.
|
||||
Added LuaSurface::platform read.
|
||||
Added LuaSurface::pollutant_type read.
|
||||
Added airborne-pollutant prototype and changed various pollution related properties to support multiple pollution types.
|
||||
Added LuaSurface::deletable read.
|
||||
Added LuaForce::set_surface_hidden() and get_surface_hidden() methods.
|
||||
Added cause argument to LuaSurface::create_entity.
|
||||
Added LuaSurfacePrototype::surface_properties read.
|
||||
Added on_player_controller_changed event.
|
||||
Removed LuaPlayer::open_map, zoom_to_world, and close_map. LuaPlayer::set_controller with type 'remote' replaces these.
|
||||
oved LuaGameScript::styles to LuaPrototypes::style.
|
||||
Removed LuaGameScript::active_mods. Use LuaBootstrap::active_mods instead.
|
||||
Renamed `global` into `storage`.
|
||||
Added LuaGameScript::technology_notifications_enabled (read/write).
|
||||
Added LuaGameScript::planets read.
|
||||
Added LuaGameScript::get_vehicles.
|
||||
Added LuaForce::platforms read.
|
||||
Added LuaGameScript::set_win_ending_info() and set_lose_ending_info() methods.
|
||||
Added LuaForce::unlock_space_location(), lock_space_location() and is_space_location_unlocked() methods.
|
||||
Added LuaForce::create_space_platform() method.
|
||||
Added LuaForce::unlock_space_platforms(), lock_space_platforms() and is_space_platforms_unlocked() methods.
|
||||
Changed LuaForce::evolution_factor, evolution_factor_by_pollution, evolution_factor_by_time and evolution_factor_by_killing_spawners to get_* and set_* methods.
|
||||
Added LuaForce::copy_from() and copy_chart() methods.
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Other Ideas, Not Committed:
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "oarc-mod",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"factorio_version": "1.1",
|
||||
"title": "Oarc Multiplayer Spawn",
|
||||
"author": "Oarcinae",
|
||||
@ -14,6 +14,7 @@
|
||||
"(?) space-exploration",
|
||||
"(?) alien-biomes",
|
||||
"(?) sonaxaton-research-queue",
|
||||
"(?) helmod"
|
||||
"(?) helmod",
|
||||
"(?) rso-mod"
|
||||
]
|
||||
}
|
@ -26,6 +26,10 @@ SPAWN_SHAPE_CHOICE_SQUARE = "square"
|
||||
RESOURCES_SHAPE_CHOICE_CIRCLE = "circle"
|
||||
RESOURCES_SHAPE_CHOICE_SQUARE = "square"
|
||||
|
||||
MAX_CRASHED_SHIP_RESOURCES_ITEMS = 5
|
||||
MAX_CRASHED_SHIP_WRECKAGE_ITEMS = 1
|
||||
|
||||
-- THIS is used as the default starting items on all surfaces if no other settings are provided!
|
||||
---@type OarcConfigStartingItems
|
||||
NAUVIS_STARTER_ITEMS =
|
||||
{
|
||||
@ -54,6 +58,7 @@ NAUVIS_STARTER_ITEMS =
|
||||
},
|
||||
}
|
||||
|
||||
-- THIS is used as the default spawn config on all surfaces if no other settings are provided!
|
||||
---@type OarcConfigSpawn
|
||||
NAUVIS_SPAWN_CONFIG =
|
||||
{
|
||||
@ -62,19 +67,19 @@ NAUVIS_SPAWN_CONFIG =
|
||||
safe_area =
|
||||
{
|
||||
-- Safe area has no aliens
|
||||
-- This is the radius in tiles of safe area.
|
||||
safe_radius = CHUNK_SIZE*6,
|
||||
-- This is the radius in chunks of safe area.
|
||||
safe_radius = 6,
|
||||
|
||||
-- Warning area has significantly reduced aliens
|
||||
-- This is the radius in tiles of warning area.
|
||||
warn_radius = CHUNK_SIZE*12,
|
||||
-- This is the radius in chunks of warning area.
|
||||
warn_radius = 12,
|
||||
|
||||
-- 1 : X (spawners alive : spawners destroyed) in this area
|
||||
warn_reduction = 20,
|
||||
|
||||
-- Danger area has slightly reduced aliens
|
||||
-- This is the radius in tiles of danger area.
|
||||
danger_radius = CHUNK_SIZE*32,
|
||||
-- This is the radius in chunks of danger area.
|
||||
danger_radius = 32,
|
||||
|
||||
-- 1 : X (spawners alive : spawners destroyed) in this area
|
||||
danger_reduction = 5,
|
||||
@ -109,24 +114,32 @@ NAUVIS_SPAWN_CONFIG =
|
||||
["iron-ore"] = {
|
||||
amount = 1500,
|
||||
size = 21,
|
||||
|
||||
-- These are only used if not using automatic placing.
|
||||
x_offset = -29,
|
||||
y_offset = 16
|
||||
},
|
||||
["copper-ore"] = {
|
||||
amount = 1200,
|
||||
size = 21,
|
||||
|
||||
-- These are only used if not using automatic placing.
|
||||
x_offset = -28,
|
||||
y_offset = -3
|
||||
},
|
||||
["stone"] = {
|
||||
amount = 1200,
|
||||
size = 21,
|
||||
|
||||
-- These are only used if not using automatic placing.
|
||||
x_offset = -27,
|
||||
y_offset = -34
|
||||
},
|
||||
["coal"] = {
|
||||
amount = 1200,
|
||||
size = 21,
|
||||
|
||||
-- These are only used if not using automatic placing.
|
||||
x_offset = -27,
|
||||
y_offset = -20
|
||||
}
|
||||
@ -141,6 +154,8 @@ NAUVIS_SPAWN_CONFIG =
|
||||
{
|
||||
num_patches = 2,
|
||||
amount = 900000,
|
||||
|
||||
-- These are only used if not using automatic placing.
|
||||
-- Starting position offset (relative to bottom/south of spawn area)
|
||||
x_offset_start = -3,
|
||||
y_offset_start = -10,
|
||||
@ -202,7 +217,7 @@ OCFG = {
|
||||
-- chunks. It ensures the spawn area isn't too near generated/explored/existing
|
||||
-- area. The larger you make this, the further away players will spawn from
|
||||
-- generated map area (even if it is not visible on the map!).
|
||||
minimum_distance_to_existing_chunks = 10,
|
||||
minimum_distance_to_existing_chunks = 20,
|
||||
|
||||
-- The range in which a player can select how close to the center of the map they want to spawn.
|
||||
near_spawn_distance = 100,
|
||||
@ -330,11 +345,11 @@ OCFG = {
|
||||
-- At what angle (in radians) do resources start.
|
||||
-- 0 means starts directly east.
|
||||
-- Resources are placed clockwise from there.
|
||||
angle_offset = 2.32, -- 2.32 is approx SSW.
|
||||
angle_offset = 2.09, -- Approx SSW.
|
||||
|
||||
-- At what andle do we place the last resource.
|
||||
-- angle_offset and angle_final determine spacing and placement.
|
||||
angle_final = 4.46, -- 4.46 is approx NNW.
|
||||
angle_final = 4.18, -- Approx NNW.
|
||||
|
||||
-- Vertical offset in tiles for the deposit resource placement. Starting from top-left corner.
|
||||
-- Only applicable for square spawns.
|
||||
@ -364,22 +379,22 @@ OCFG = {
|
||||
starting_items = NAUVIS_STARTER_ITEMS,
|
||||
spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
},
|
||||
["vulcanus"] = {
|
||||
starting_items = NAUVIS_STARTER_ITEMS,
|
||||
spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
},
|
||||
["fulgora"] = {
|
||||
starting_items = NAUVIS_STARTER_ITEMS,
|
||||
spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
},
|
||||
["gleba"] = {
|
||||
starting_items = NAUVIS_STARTER_ITEMS,
|
||||
spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
},
|
||||
["aquilo"] = {
|
||||
starting_items = NAUVIS_STARTER_ITEMS,
|
||||
spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
}
|
||||
-- ["vulcanus"] = {
|
||||
-- starting_items = NAUVIS_STARTER_ITEMS,
|
||||
-- spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
-- },
|
||||
-- ["fulgora"] = {
|
||||
-- starting_items = NAUVIS_STARTER_ITEMS,
|
||||
-- spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
-- },
|
||||
-- ["gleba"] = {
|
||||
-- starting_items = NAUVIS_STARTER_ITEMS,
|
||||
-- spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
-- },
|
||||
-- ["aquilo"] = {
|
||||
-- starting_items = NAUVIS_STARTER_ITEMS,
|
||||
-- spawn_config = NAUVIS_SPAWN_CONFIG
|
||||
-- }
|
||||
},
|
||||
|
||||
-- Surfaces blacklist (Ignore these surfaces completely for spawning and regrowth!)
|
||||
@ -490,10 +505,10 @@ OCFG = {
|
||||
---@field shape SpawnShapeChoice Spawn a circle/octagon/square of trees around this base outline.
|
||||
|
||||
---@class OarcConfigSpawnSafeArea
|
||||
---@field safe_radius number Safe area has no aliens This is the radius in tiles of safe area.
|
||||
---@field warn_radius number Warning area has significantly reduced aliens This is the radius in tiles of warning area.
|
||||
---@field safe_radius number Safe area has no aliens This is the radius in chunks of safe area.
|
||||
---@field warn_radius number Warning area has significantly reduced aliens This is the radius in chunks of warning area.
|
||||
---@field warn_reduction number 1 : X (spawners alive : spawners destroyed) in this area
|
||||
---@field danger_radius number Danger area has slightly reduce aliens This is the radius in tiles of danger area.
|
||||
---@field danger_radius number Danger area has slightly reduce aliens This is the radius in chunks of danger area.
|
||||
---@field danger_reduction number 1 : X (spawners alive : spawners destroyed) in this area
|
||||
|
||||
---@class OarcConfigSpawnWater
|
||||
|
@ -158,7 +158,7 @@ function ValidateAndLoadConfig()
|
||||
|
||||
-- Load the template config into the global table.
|
||||
---@class OarcConfig
|
||||
global.ocfg = OCFG
|
||||
global.ocfg = table.deepcopy(OCFG)
|
||||
|
||||
-- Check that each entry in OCFG matches the default value of the mod setting. This is just for my own sanity.
|
||||
-- Helps make sure mod default settings and my internal config are in sync.
|
||||
@ -178,11 +178,58 @@ function ValidateAndLoadConfig()
|
||||
|
||||
GetScenarioOverrideSettings() -- Get any scenario settings and overwrite both the mod settings and OARC_CFG.
|
||||
|
||||
SyncModSettingsToOCFG() -- Make sure mod settings are in sync with global.ocfg table.
|
||||
|
||||
ValidateSettings() -- These are validation checks that can't be done within the mod settings natively.
|
||||
end
|
||||
|
||||
---DO some basic validation checks on the config settings.
|
||||
---@return nil
|
||||
function ValidateSettings()
|
||||
|
||||
-- Verify the major sections exist. Not exhaustive but should catch missing sections.
|
||||
if (global.ocfg["server_info"] == nil) then
|
||||
log("ERROR - Missing server_info section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing server_info section in config! Loading defaults instead!")
|
||||
global.ocfg.server_info = table.deepcopy(OCFG.server_info)
|
||||
end
|
||||
if (global.ocfg["gameplay"] == nil) then
|
||||
log("ERROR - Missing gameplay section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing gameplay section in config! Loading defaults instead!")
|
||||
global.ocfg.gameplay = table.deepcopy(OCFG.gameplay)
|
||||
end
|
||||
if (global.ocfg["regrowth"] == nil) then
|
||||
log("ERROR - Missing regrowth section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing regrowth section in config! Loading defaults instead!")
|
||||
global.ocfg.regrowth = table.deepcopy(OCFG.regrowth)
|
||||
end
|
||||
if (global.ocfg["spawn_general"] == nil) then
|
||||
log("ERROR - Missing spawn_general section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing spawn_general section in config! Loading defaults instead!")
|
||||
global.ocfg.spawn_general = table.deepcopy(OCFG.spawn_general)
|
||||
end
|
||||
if (global.ocfg["resource_placement"] == nil) then
|
||||
log("ERROR - Missing resource_placement section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing resource_placement section in config! Loading defaults instead!")
|
||||
global.ocfg.resource_placement = table.deepcopy(OCFG.resource_placement)
|
||||
end
|
||||
if (global.ocfg["surfaces_config"] == nil) then
|
||||
log("ERROR - Missing surfaces_config section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing surfaces_config section in config! Loading defaults instead!")
|
||||
global.ocfg.surfaces_config = table.deepcopy(OCFG.surfaces_config)
|
||||
end
|
||||
if (global.ocfg["surfaces_blacklist"] == nil) then
|
||||
log("ERROR - Missing surfaces_blacklist section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing surfaces_blacklist section in config! Loading defaults instead!")
|
||||
global.ocfg.surfaces_blacklist = table.deepcopy(OCFG.surfaces_blacklist)
|
||||
end
|
||||
if (global.ocfg["surfaces_blacklist_match"] == nil) then
|
||||
log("ERROR - Missing surfaces_blacklist_match section in config! Loading defaults instead!")
|
||||
SendBroadcastMsg("ERROR - Missing surfaces_blacklist_match section in config! Loading defaults instead!")
|
||||
global.ocfg.surfaces_blacklist_match = table.deepcopy(OCFG.surfaces_blacklist_match)
|
||||
end
|
||||
|
||||
|
||||
-- Validate enable_main_team and enable_separate_teams.
|
||||
-- Force enable_main_team if both are disabled.
|
||||
if (not global.ocfg.gameplay.enable_main_team and not global.ocfg.gameplay.enable_separate_teams) then
|
||||
@ -221,6 +268,17 @@ function ValidateSettings()
|
||||
if (global.ocfg.surfaces_config["nauvis"] == nil) then
|
||||
error("nauvis surface config does not exist! Please check your mod settings or config!")
|
||||
end
|
||||
|
||||
-- Very for each surface config that the item counts are valid.
|
||||
for surface_name,surface_config in pairs(global.ocfg.surfaces_config) do
|
||||
if (table_size(surface_config.starting_items.crashed_ship_resources) > MAX_CRASHED_SHIP_RESOURCES_ITEMS) then
|
||||
error("Too many items in crashed_ship_resources for surface: " .. surface_name)
|
||||
end
|
||||
|
||||
if (table_size(surface_config.starting_items.crashed_ship_wreakage) > MAX_CRASHED_SHIP_WRECKAGE_ITEMS) then
|
||||
error("Too many items in crashed_ship_wreakage for surface: " .. surface_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Read in the mod settings and copy them to the OARC_CFG table, overwriting the defaults in config.lua.
|
||||
@ -241,6 +299,8 @@ function CacheModSettings()
|
||||
global.ocfg.gameplay.main_force_name = settings.startup["oarc-mod-main-force-name"].value --[[@as string]]
|
||||
end
|
||||
|
||||
---Get the scenario settings from the scenario if it exists.
|
||||
---@return nil
|
||||
function GetScenarioOverrideSettings()
|
||||
|
||||
if remote.interfaces["oarc_scenario"] then
|
||||
@ -250,27 +310,32 @@ function GetScenarioOverrideSettings()
|
||||
|
||||
-- Overwrite the non mod settings with the scenario settings.
|
||||
global.ocfg = scenario_settings
|
||||
|
||||
-- Override the mod settings with the scenario settings!
|
||||
for _,entry in pairs(OCFG_KEYS) do
|
||||
if (entry.type ~= "header") and (entry.type ~= "subheader") then
|
||||
local mod_key = entry.mod_key
|
||||
local oarc_key = entry.ocfg_keys
|
||||
local scenario_value = GetGlobalOarcConfigUsingKeyTable(oarc_key)
|
||||
if (scenario_value ~= nil) then
|
||||
local ok,result = pcall(function() settings.global[mod_key] = { value = scenario_value } end)
|
||||
if not ok then
|
||||
error("Error setting mod setting: " .. mod_key .. " = " .. tostring(scenario_value) .. "\n" .. "If you see this, you probably picked an invalid value for a setting override in the custom scenario.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
log("No scenario settings found.")
|
||||
end
|
||||
end
|
||||
|
||||
---Syncs all mod settings to the OARC config table.
|
||||
---@return nil
|
||||
function SyncModSettingsToOCFG()
|
||||
|
||||
-- Override the mod settings with the the global.ocfg settings.
|
||||
for _,entry in pairs(OCFG_KEYS) do
|
||||
if (entry.type ~= "header") and (entry.type ~= "subheader") then
|
||||
local mod_key = entry.mod_key
|
||||
local oarc_key = entry.ocfg_keys
|
||||
local scenario_value = GetGlobalOarcConfigUsingKeyTable(oarc_key)
|
||||
if (scenario_value ~= nil) then
|
||||
local ok,result = pcall(function() settings.global[mod_key] = { value = scenario_value } end)
|
||||
if not ok then
|
||||
error("Error setting mod setting: " .. mod_key .. " = " .. tostring(scenario_value) .. "\n" .. "If you see this, you probably picked an invalid value for a setting override in the custom scenario.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
---Handles the event when a mod setting is changed in the mod settings menu.
|
||||
---@param event EventData.on_runtime_mod_setting_changed
|
||||
---@return nil
|
||||
|
128
lib/gui_tabs/player_list.lua
Normal file
128
lib/gui_tabs/player_list.lua
Normal file
@ -0,0 +1,128 @@
|
||||
-- Contains the GUI for the player list tab.
|
||||
|
||||
---Used by AddOarcGuiTab
|
||||
---@param tab_container LuaGuiElement
|
||||
---@param player LuaPlayer
|
||||
---@return nil
|
||||
function CreatePlayerListTab(tab_container, player)
|
||||
|
||||
local scroll_pane = tab_container.add {
|
||||
type = "scroll-pane",
|
||||
direction = "vertical",
|
||||
vertical_scroll_policy = "always",
|
||||
}
|
||||
scroll_pane.style.maximal_height = 500
|
||||
|
||||
|
||||
-- Make a table: player name, force name, home surface, time played, gps button
|
||||
local player_table = scroll_pane.add {
|
||||
type = "table",
|
||||
column_count = 6,
|
||||
style = "bordered_table",
|
||||
}
|
||||
|
||||
--- Add the header rows
|
||||
AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-player"}, "caption_label")
|
||||
AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-force"}, "caption_label")
|
||||
AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-surface"}, "caption_label")
|
||||
AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-time-player"}, "caption_label")
|
||||
AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-location"}, "caption_label")
|
||||
AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-status"}, "caption_label")
|
||||
|
||||
-- List online players first
|
||||
for _,online_player in pairs(game.connected_players) do
|
||||
AddPlayerRow(player_table, online_player.name, true)
|
||||
end
|
||||
|
||||
-- List offline players later
|
||||
for _,player in pairs(game.players) do
|
||||
if (not player.connected) then
|
||||
AddPlayerRow(player_table, player.name, false)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
---Add a row to the table for a player
|
||||
---@param table LuaGuiElement
|
||||
---@param player_name string
|
||||
---@param online boolean
|
||||
---@return nil
|
||||
function AddPlayerRow(table, player_name, online)
|
||||
local player = game.players[player_name]
|
||||
if (player) then
|
||||
if player.admin then
|
||||
local label = AddLabel(table, nil, player.name, my_player_list_admin_style)
|
||||
label.tooltip = "Admin"
|
||||
else
|
||||
AddLabel(table, nil, player.name, my_label_style)
|
||||
end
|
||||
AddLabel(table, nil, player.force.name, my_label_style)
|
||||
|
||||
-- List home surface name or holding pen
|
||||
if (player.surface.name == HOLDING_PEN_SURFACE_NAME) then
|
||||
AddLabel(table, nil, {"oarc-player-waiting-to-spawn"}, my_label_style)
|
||||
else
|
||||
local spawn = FindPlayerHomeSpawn(player.name)
|
||||
if (spawn) then
|
||||
AddLabel(table, nil, spawn.surface_name, my_label_style)
|
||||
else
|
||||
AddLabel(table, nil, "Unknown?", my_label_style) -- Shouldn't happen
|
||||
end
|
||||
end
|
||||
|
||||
AddLabel(table, nil, FormatTimeHoursSecs(player.online_time), my_label_style)
|
||||
|
||||
CreatePlayerGPSButton(table, player.name)
|
||||
|
||||
if online then
|
||||
local label = AddLabel(table, nil, {"oarc-player-online"}, my_player_list_style)
|
||||
label.style.font_color = {r=0.1, g=1, b=0.1}
|
||||
else
|
||||
AddLabel(table, nil, {"oarc-player-offline"}, my_player_list_offline_style)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Display a GPS button for a specific location. (For the player list)
|
||||
---@param container LuaGuiElement
|
||||
---@param player_name string
|
||||
---@return nil
|
||||
function CreatePlayerGPSButton(container, player_name)
|
||||
local gps_button = container.add {
|
||||
type = "sprite-button",
|
||||
sprite = "utility/gps_map_icon",
|
||||
tags = {
|
||||
action = "oarc_player_list_tab",
|
||||
setting = "show_location",
|
||||
player_name = player_name,
|
||||
},
|
||||
style = "slot_button",
|
||||
tooltip = {"", {"oarc-player-list-tab-location-button-tooltip"}, " (", game.players[player_name].surface.name, ")"},
|
||||
}
|
||||
gps_button.style.width = 28
|
||||
gps_button.style.height = 28
|
||||
end
|
||||
|
||||
---Handle the gui click of the player list tab in the Oarc GUI.
|
||||
---@param event EventData.on_gui_click
|
||||
---@return nil
|
||||
function PlayerListTabGuiClick(event)
|
||||
if not event.element.valid then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
|
||||
if (tags.action ~= "oarc_player_list_tab") then
|
||||
return
|
||||
end
|
||||
|
||||
-- Shows the player's current location on the map
|
||||
if (tags.setting == "show_location") then
|
||||
local player_name = tags.player_name --[[@as string]]
|
||||
local target_player = game.players[player_name]
|
||||
|
||||
player.open_map(target_player.position, 0.05) -- TODO: Update this for spage age!
|
||||
end
|
||||
end
|
@ -92,7 +92,7 @@ end
|
||||
---Server info gui click event handler
|
||||
---@param event EventData.on_gui_click
|
||||
---@return nil
|
||||
function ServerInfoGuiClick(event)
|
||||
function ServerInfoTabGuiClick(event)
|
||||
if not event.element.valid then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
|
@ -36,7 +36,13 @@ function CreateSettingsControlsTab(tab_container, player)
|
||||
scroll_pane_right.style.maximal_height = GENERIC_GUI_MAX_HEIGHT
|
||||
scroll_pane_right.style.padding = 5
|
||||
scroll_pane_right.style.left_margin = 2
|
||||
|
||||
CreateSurfaceSettingsSection(scroll_pane_right, player)
|
||||
AddSpacerLine(scroll_pane_right)
|
||||
|
||||
if (player.admin) then
|
||||
CreateSettingsExportSection(scroll_pane_right, player)
|
||||
end
|
||||
end
|
||||
|
||||
---Create the content for the mod settings section
|
||||
@ -98,6 +104,53 @@ function CreateSurfaceSettingsSection(container, player)
|
||||
|
||||
end
|
||||
|
||||
---Create the content for the settings export section. Exports the entire global.ocfg table into a string.
|
||||
---@param container LuaGuiElement
|
||||
---@param player LuaPlayer
|
||||
---@return nil
|
||||
function CreateSettingsExportSection(container, player)
|
||||
AddLabel(container, nil, { "oarc-settings-tab-title-export" }, my_label_header2_style)
|
||||
|
||||
local horizontal_flow = container.add {
|
||||
type = "flow",
|
||||
direction = "horizontal",
|
||||
}
|
||||
|
||||
local export_button = horizontal_flow.add {
|
||||
type = "button",
|
||||
caption = { "oarc-settings-tab-export-button" },
|
||||
style = "green_button",
|
||||
tooltip = { "oarc-settings-tab-export-button-tooltip" },
|
||||
tags = {
|
||||
action = "oarc_settings_tab_right_pane",
|
||||
setting = "oarc_settings_export"
|
||||
},
|
||||
}
|
||||
|
||||
local import_button = horizontal_flow.add {
|
||||
type = "button",
|
||||
caption = { "oarc-settings-tab-import-button" },
|
||||
tooltip = { "oarc-settings-tab-import-button-tooltip" },
|
||||
style = "red_button",
|
||||
tags = {
|
||||
action = "oarc_settings_tab_right_pane",
|
||||
setting = "oarc_settings_import"
|
||||
},
|
||||
}
|
||||
|
||||
local export_textfield = container.add {
|
||||
type = "textfield",
|
||||
name = "export_textfield",
|
||||
text = " ",
|
||||
tags = {
|
||||
action = "oarc_settings_tab_right_pane",
|
||||
setting = "oarc_settings_textfield"
|
||||
},
|
||||
}
|
||||
export_textfield.style.horizontally_stretchable = true
|
||||
export_textfield.style.maximal_width = 500
|
||||
end
|
||||
|
||||
---Handles the click event for the tab used by AddOarcGuiTab
|
||||
---@param event EventData.on_gui_click
|
||||
---@return nil
|
||||
@ -105,7 +158,7 @@ function SettingsControlsTabGuiClick(event)
|
||||
if not (event.element.valid) then return end
|
||||
|
||||
local gui_elem = event.element
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab") then return end
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab_left_pane") then return end
|
||||
local index = gui_elem.tags.setting
|
||||
|
||||
local entry = OCFG_KEYS[index]
|
||||
@ -121,7 +174,7 @@ function SettingsControlsTabGuiTextChanged(event)
|
||||
if not (event.element.valid) then return end
|
||||
|
||||
local gui_elem = event.element
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab") then return end
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab_left_pane") then return end
|
||||
local index = gui_elem.tags.setting
|
||||
local value = gui_elem.text
|
||||
local entry = OCFG_KEYS[index]
|
||||
@ -141,7 +194,7 @@ function SettingsControlsTabGuiTextconfirmed(event)
|
||||
if not (event.element.valid) then return end
|
||||
|
||||
local gui_elem = event.element
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab") then return end
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab_left_pane") then return end
|
||||
local index = gui_elem.tags.setting
|
||||
local value = gui_elem.text
|
||||
local entry = OCFG_KEYS[index]
|
||||
@ -260,7 +313,7 @@ function AddCheckboxSetting(tab_container, index, entry, enabled)
|
||||
state = GetGlobalOarcConfigUsingKeyTable(entry.ocfg_keys),
|
||||
enabled = enabled,
|
||||
tooltip = { "mod-setting-description."..entry.mod_key },
|
||||
tags = { action = "oarc_settings_tab", setting = index },
|
||||
tags = { action = "oarc_settings_tab_left_pane", setting = index },
|
||||
}
|
||||
end
|
||||
|
||||
@ -293,7 +346,7 @@ function AddTextfieldSetting(tab_container, index, entry, enabled)
|
||||
text = GetGlobalOarcConfigUsingKeyTable(entry.ocfg_keys),
|
||||
enabled = enabled,
|
||||
tooltip = tooltip,
|
||||
tags = { action = "oarc_settings_tab", setting = index },
|
||||
tags = { action = "oarc_settings_tab_left_pane", setting = index },
|
||||
}
|
||||
end
|
||||
|
||||
@ -340,7 +393,7 @@ function AddIntegerSetting(tab_container, index, entry, enabled)
|
||||
text = GetGlobalOarcConfigUsingKeyTable(entry.ocfg_keys),
|
||||
enabled = enabled,
|
||||
tooltip = tooltip,
|
||||
tags = { action = "oarc_settings_tab", setting = index },
|
||||
tags = { action = "oarc_settings_tab_left_pane", setting = index },
|
||||
}
|
||||
textfield.style.width = 50
|
||||
end
|
||||
@ -389,7 +442,7 @@ function AddDoubleSetting(tab_container, index, entry, enabled)
|
||||
text = string.format("%.2f", GetGlobalOarcConfigUsingKeyTable(entry.ocfg_keys)),
|
||||
enabled = enabled,
|
||||
tooltip = tooltip,
|
||||
tags = { action = "oarc_settings_tab", setting = index },
|
||||
tags = { action = "oarc_settings_tab_left_pane", setting = index },
|
||||
}
|
||||
textfield.style.width = 50
|
||||
end
|
||||
@ -431,7 +484,7 @@ function AddStringListDropdownSetting(tab_container, index, entry, enabled)
|
||||
selected_index = selected_index,
|
||||
enabled = enabled,
|
||||
tooltip = { "mod-setting-description."..entry.mod_key },
|
||||
tags = { action = "oarc_settings_tab", setting = index },
|
||||
tags = { action = "oarc_settings_tab_left_pane", setting = index },
|
||||
}
|
||||
end
|
||||
|
||||
@ -448,7 +501,7 @@ function AddSurfaceCheckboxSetting(parent, surface_name, setting_name, state, ad
|
||||
name = surface_name.."_"..setting_name,
|
||||
type = "checkbox",
|
||||
state = state,
|
||||
tags = { action = "oarc_settings_tab_surfaces", setting = setting_name, surface = surface_name },
|
||||
tags = { action = "oarc_settings_tab_right_pane", setting = setting_name, surface = surface_name },
|
||||
enabled = admin,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
@ -461,11 +514,11 @@ function SettingsSurfaceControlsTabGuiClick(event)
|
||||
if not (event.element.valid) then return end
|
||||
|
||||
local gui_elem = event.element
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab_surfaces") then return end
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab_right_pane") then return end
|
||||
local setting_name = gui_elem.tags.setting
|
||||
local surface_name = gui_elem.tags.surface --[[@as string]]
|
||||
|
||||
if (setting_name == "spawn_enabled") then
|
||||
local surface_name = gui_elem.tags.surface --[[@as string]]
|
||||
global.oarc_surfaces[surface_name] = gui_elem.state
|
||||
|
||||
if (#GetAllowedSurfaces() == 0) then
|
||||
@ -473,7 +526,9 @@ function SettingsSurfaceControlsTabGuiClick(event)
|
||||
global.oarc_surfaces[global.ocfg.gameplay.default_surface] = true
|
||||
event.element.parent[global.ocfg.gameplay.default_surface.."_spawn_enabled"].state = true
|
||||
end
|
||||
|
||||
elseif (setting_name == "regrowth_enabled") then
|
||||
local surface_name = gui_elem.tags.surface --[[@as string]]
|
||||
|
||||
if (gui_elem.state) then
|
||||
if not IsRegrowthEnabledOnSurface(surface_name) then
|
||||
@ -484,7 +539,34 @@ function SettingsSurfaceControlsTabGuiClick(event)
|
||||
RegrowthDisableSurface(surface_name)
|
||||
end
|
||||
end
|
||||
|
||||
elseif (setting_name == "oarc_settings_textfield") then
|
||||
gui_elem.select_all() -- Select all text when clicked
|
||||
|
||||
elseif (setting_name == "oarc_settings_export") then
|
||||
|
||||
log("Exported settings!")
|
||||
local export_textfield = gui_elem.parent.parent["export_textfield"]
|
||||
export_textfield.text = serpent.line(global.ocfg, {compact = true, sparse = true})
|
||||
|
||||
elseif (setting_name == "oarc_settings_import") then
|
||||
local player = game.players[event.player_index]
|
||||
local export_textfield = gui_elem.parent.parent["export_textfield"]
|
||||
local import_text = export_textfield.text
|
||||
local ok, copy = serpent.load(import_text)
|
||||
if (not ok) or (type(copy) ~= "table") or (next(copy) == nil) then
|
||||
log("Error importing settings!")
|
||||
player.print("Error importing settings!")
|
||||
else
|
||||
global.ocfg = table.deepcopy(copy)
|
||||
ValidateSettings() -- Some basic validation, not 100% foolproof
|
||||
SyncModSettingsToOCFG() -- Sync the mod settings.
|
||||
log("Imported settings!")
|
||||
player.print("Imported settings!")
|
||||
OarcGuiRefreshContent(player)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -495,7 +577,7 @@ function SettingsControlsTabGuiSelectionStateChanged(event)
|
||||
if not (event.element.valid) then return end
|
||||
|
||||
local gui_elem = event.element
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab") then return end
|
||||
if (gui_elem.tags.action ~= "oarc_settings_tab_left_pane") then return end
|
||||
local index = gui_elem.tags.setting
|
||||
local entry = OCFG_KEYS[index]
|
||||
|
||||
|
@ -252,7 +252,7 @@ end
|
||||
---Handle the gui checkboxes & radio buttons of the spawn control tab in the Oarc GUI.
|
||||
---@param event EventData.on_gui_checked_state_changed
|
||||
---@return nil
|
||||
function SpawnCtrlGuiOptionsSelect(event)
|
||||
function SpawnCtrlGuiOptionsCheckedStateChanged(event)
|
||||
if not event.element.valid then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
@ -282,7 +282,7 @@ end
|
||||
---Handle the gui click of the spawn control tab in the Oarc GUI.
|
||||
---@param event EventData.on_gui_click
|
||||
---@return nil
|
||||
function SpawnCtrlGuiClick(event)
|
||||
function SpawnCtrlTabGuiClick(event)
|
||||
if not event.element.valid then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tags = event.element.tags
|
||||
@ -301,7 +301,7 @@ function SpawnCtrlGuiClick(event)
|
||||
elseif (tags.setting == "show_location") then
|
||||
local surface_name = tags.surface --[[@as string]]
|
||||
local position = tags.position --[[@as MapPosition]]
|
||||
player.open_map(position, 0.05)
|
||||
player.open_map(position, 0.05) -- TODO: Update this for spage age!
|
||||
player.print({"", { "oarc-spawn-gps-location" }, GetGPStext(surface_name, position)})
|
||||
|
||||
-- Accept or reject pending player join requests to a shared base
|
||||
|
1112
lib/gui_tabs/surface_config.lua
Normal file
1112
lib/gui_tabs/surface_config.lua
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,8 @@ require("lib/gui_tabs/server_info")
|
||||
require("lib/gui_tabs/spawn_controls")
|
||||
require("lib/gui_tabs/settings_controls")
|
||||
require("lib/gui_tabs/mod_info_faq")
|
||||
require("lib/gui_tabs/player_list")
|
||||
require("lib/gui_tabs/surface_config")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- GUI Tab Handler
|
||||
@ -18,17 +20,23 @@ OARC_SERVER_INFO_TAB_NAME = "server_info"
|
||||
OARC_SPAWN_CTRL_TAB_NAME = "spawn_controls"
|
||||
OARC_CONFIG_CTRL_TAB_NAME = "settings"
|
||||
OARC_MOD_INFO_CTRL_TAB_NAME = "mod_info"
|
||||
OARC_MOD_PLAYER_LIST_TAB_NAME = "player_list"
|
||||
OARC_SURFACE_CONFIG_TAB_NAME = "surface_config"
|
||||
|
||||
OARC_SERVER_INFO_TAB_LOCALIZED = {"oarc-server-info-tab-title"}
|
||||
OARC_SPAWN_CTRL_TAB_LOCALIZED = {"oarc-spawn-ctrls-tab-title"}
|
||||
OARC_CONFIG_CTRL_TAB_LOCALIZED = {"oarc-settings-tab-title"}
|
||||
OARC_MOD_INFO_CTRL_TAB_LOCALIZED = {"oarc-mod-info-tab-title"}
|
||||
OARC_PLAYER_LIST_TAB_LOCALIZED = {"oarc-player-list-tab-title"}
|
||||
OARC_SURFACE_CONFIG_TAB_LOCALIZED = {"oarc-surface-config-tab-title"}
|
||||
|
||||
local OARC_GUI_TAB_CONTENT_FUNCTIONS = {
|
||||
[OARC_SERVER_INFO_TAB_NAME] = CreateServerInfoTab,
|
||||
[OARC_SPAWN_CTRL_TAB_NAME] = CreateSpawnControlsTab,
|
||||
[OARC_MOD_INFO_CTRL_TAB_NAME] = CreateModInfoTab,
|
||||
[OARC_CONFIG_CTRL_TAB_NAME] = CreateSettingsControlsTab,
|
||||
[OARC_MOD_PLAYER_LIST_TAB_NAME] = CreatePlayerListTab,
|
||||
[OARC_SURFACE_CONFIG_TAB_NAME] = CreateSurfaceConfigTab,
|
||||
}
|
||||
|
||||
---@param player LuaPlayer
|
||||
@ -57,6 +65,16 @@ function InitOarcGuiTabs(player)
|
||||
AddOarcGuiTab(player, OARC_CONFIG_CTRL_TAB_NAME, OARC_CONFIG_CTRL_TAB_LOCALIZED)
|
||||
SetOarcGuiTabEnabled(player, OARC_CONFIG_CTRL_TAB_NAME, true)
|
||||
|
||||
-- Player list tab
|
||||
AddOarcGuiTab(player, OARC_MOD_PLAYER_LIST_TAB_NAME, OARC_PLAYER_LIST_TAB_LOCALIZED)
|
||||
SetOarcGuiTabEnabled(player, OARC_MOD_PLAYER_LIST_TAB_NAME, true)
|
||||
|
||||
-- Surface config tab
|
||||
if (player.admin) then
|
||||
AddOarcGuiTab(player, OARC_SURFACE_CONFIG_TAB_NAME, OARC_SURFACE_CONFIG_TAB_LOCALIZED)
|
||||
SetOarcGuiTabEnabled(player, OARC_SURFACE_CONFIG_TAB_NAME, true)
|
||||
end
|
||||
|
||||
HideOarcGui(player)
|
||||
end
|
||||
|
||||
@ -142,12 +160,7 @@ function ClickOarcGuiButton(event)
|
||||
end
|
||||
end
|
||||
|
||||
---@param event EventData.on_gui_selected_tab_changed
|
||||
---@return nil
|
||||
function OarcGuiSelectedTabChanged(event)
|
||||
if (event.element.name ~= "oarc_tabs") then return end
|
||||
OarcGuiCreateContentOfTab(game.players[event.player_index])
|
||||
end
|
||||
|
||||
|
||||
---Set tab content to currently selected tab, clears all other tab content and refreshes the selected tab content!
|
||||
---Safe to call just to refresh the current tab.
|
||||
@ -298,9 +311,107 @@ function SwitchOarcGuiTab(player, tab_name)
|
||||
end
|
||||
end
|
||||
|
||||
--@param event EventData.on_gui_closed
|
||||
---Completely destroys and recreates the OARC GUI for a player.
|
||||
---@param player LuaPlayer
|
||||
---@return nil
|
||||
function RecreateOarcGui(player)
|
||||
if (mod_gui.get_button_flow(player).oarc_button ~= nil) then
|
||||
mod_gui.get_button_flow(player).oarc_button.destroy()
|
||||
end
|
||||
|
||||
if (mod_gui.get_frame_flow(player)[OARC_GUI] ~= nil) then
|
||||
mod_gui.get_frame_flow(player)[OARC_GUI].destroy()
|
||||
end
|
||||
|
||||
InitOarcGuiTabs(player)
|
||||
end
|
||||
|
||||
--[[
|
||||
_____ _____ _ _ _____ _ _ _ _ _ ___ _ ___ ___ ___
|
||||
| __\ \ / / __| \| |_ _| | || | /_\ | \| | \| | | __| _ \/ __|
|
||||
| _| \ V /| _|| .` | | | | __ |/ _ \| .` | |) | |__| _|| /\__ \
|
||||
|___| \_/ |___|_|\_| |_| |_||_/_/ \_\_|\_|___/|____|___|_|_\|___/
|
||||
|
||||
]]
|
||||
|
||||
---Handles the closing of the OARC GUI.
|
||||
---@param event EventData.on_gui_closed
|
||||
---@return nil
|
||||
function OarcGuiClosed(event)
|
||||
if (event.element and (event.element.name == "oarc_gui")) then
|
||||
HideOarcGui(game.players[event.player_index])
|
||||
end
|
||||
end
|
||||
|
||||
---@param event EventData.on_gui_selected_tab_changed
|
||||
---@return nil
|
||||
function OarcGuiTabsSelectedTabChanged(event)
|
||||
if (event.element.name ~= "oarc_tabs") then return end
|
||||
OarcGuiCreateContentOfTab(game.players[event.player_index])
|
||||
end
|
||||
|
||||
---All gui tabs click event handler
|
||||
---@param event EventData.on_gui_click
|
||||
---@return nil
|
||||
function OarcGuiTabsClick(event)
|
||||
if not event.element.valid then return end
|
||||
ClickOarcGuiButton(event)
|
||||
ServerInfoTabGuiClick(event)
|
||||
SpawnCtrlTabGuiClick(event)
|
||||
SettingsControlsTabGuiClick(event)
|
||||
SettingsSurfaceControlsTabGuiClick(event)
|
||||
PlayerListTabGuiClick(event)
|
||||
SurfaceConfigTabGuiClick(event)
|
||||
end
|
||||
|
||||
---All gui tabs on_gui_checked_state_changed event handler
|
||||
---@param event EventData.on_gui_checked_state_changed
|
||||
---@return nil
|
||||
function OarcGuiTabsCheckedStateChanged(event)
|
||||
if not event.element.valid then return end
|
||||
SpawnCtrlGuiOptionsCheckedStateChanged(event)
|
||||
end
|
||||
|
||||
|
||||
---Handles the `on_gui_value_changed` event.
|
||||
---@param event EventData.on_gui_value_changed
|
||||
---@return nil
|
||||
function OarcGuiTabsValueChanged(event)
|
||||
if not event.element.valid then return end
|
||||
SettingsControlsTabGuiValueChanged(event)
|
||||
end
|
||||
|
||||
---Handles the `on_gui_selection_state_changed` event.
|
||||
---@param event EventData.on_gui_selection_state_changed
|
||||
---@return nil
|
||||
function OarcGuiTabsSelectionStateChanged(event)
|
||||
if not event.element.valid then return end
|
||||
SettingsControlsTabGuiSelectionStateChanged(event)
|
||||
SurfaceConfigTabGuiSelect(event)
|
||||
end
|
||||
|
||||
---Handles the `on_gui_text_changed` event.
|
||||
---@param event EventData.on_gui_text_changed
|
||||
---@return nil
|
||||
function OarcGuiTabsTextChanged(event)
|
||||
if not event.element.valid then return end
|
||||
SettingsControlsTabGuiTextChanged(event)
|
||||
SurfaceConfigTabGuiTextChanged(event)
|
||||
end
|
||||
|
||||
---Handles the `on_gui_confirmed` event.
|
||||
---@param event EventData.on_gui_confirmed
|
||||
---@return nil
|
||||
function OarcGuiTabsConfirmed(event)
|
||||
if not event.element.valid then return end
|
||||
SettingsControlsTabGuiTextconfirmed(event)
|
||||
SurfaceConfigTabGuiConfirmed(event)
|
||||
end
|
||||
|
||||
---Handles the `on_gui_elem_changed` event.
|
||||
---@param event EventData.on_gui_elem_changed
|
||||
---@return nil
|
||||
function OarcGuiTabsElemChanged(event)
|
||||
if not event.element.valid then return end
|
||||
SurfaceConfigTabGuiElemChanged(event)
|
||||
end
|
||||
|
@ -58,6 +58,7 @@ my_note_style = {
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
|
||||
---@type LuaStyle
|
||||
---@diagnostic disable-next-line: missing-fields
|
||||
my_warning_style = {
|
||||
@ -99,8 +100,8 @@ my_shared_item_list_fixed_width_style = {
|
||||
---@diagnostic disable-next-line: missing-fields
|
||||
my_player_list_admin_style = {
|
||||
font = "default-semibold",
|
||||
font_color = {r=1,g=0.5,b=0.5},
|
||||
minimal_width = 200,
|
||||
font_color = { r=0.9, g=0.7, b=0.3 },
|
||||
-- minimal_width = 200,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0,
|
||||
single_line = false,
|
||||
@ -109,7 +110,7 @@ my_player_list_admin_style = {
|
||||
---@diagnostic disable-next-line: missing-fields
|
||||
my_player_list_style = {
|
||||
font = "default-semibold",
|
||||
minimal_width = 200,
|
||||
-- minimal_width = 200,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0,
|
||||
single_line = false,
|
||||
@ -119,7 +120,7 @@ my_player_list_style = {
|
||||
my_player_list_offline_style = {
|
||||
-- font = "default-semibold",
|
||||
font_color = {r=0.5,g=0.5,b=0.5},
|
||||
minimal_width = 200,
|
||||
-- minimal_width = 200,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0,
|
||||
single_line = false,
|
||||
|
@ -162,18 +162,6 @@ function ClearTestButtons(player)
|
||||
end
|
||||
end
|
||||
|
||||
function RecreateOarcGui(player)
|
||||
if (mod_gui.get_button_flow(player).oarc_button ~= nil) then
|
||||
mod_gui.get_button_flow(player).oarc_button.destroy()
|
||||
end
|
||||
|
||||
if (mod_gui.get_frame_flow(player)[OARC_GUI] ~= nil) then
|
||||
mod_gui.get_frame_flow(player)[OARC_GUI].destroy()
|
||||
end
|
||||
|
||||
InitOarcGuiTabs(player)
|
||||
end
|
||||
|
||||
|
||||
function SetNauvisChunksGenerated()
|
||||
local nauvis = game.surfaces["nauvis"]
|
||||
|
@ -208,12 +208,13 @@ end
|
||||
---@return string
|
||||
function FormatTimeHoursSecs(ticks)
|
||||
local seconds = ticks / 60
|
||||
local minutes = math.floor((seconds)/60)
|
||||
local hours = math.floor((minutes)/60)
|
||||
local minutes = math.floor(minutes - 60*hours)
|
||||
local total_minutes = math.floor((seconds)/60)
|
||||
local hours = math.floor((total_minutes)/60)
|
||||
local minutes = math.floor(total_minutes - 60*hours)
|
||||
return string.format("%dh:%02dm", hours, minutes)
|
||||
end
|
||||
|
||||
|
||||
-- -- Simple math clamp
|
||||
-- function clamp(val, min, max)
|
||||
-- if (val > max) then
|
||||
@ -1345,10 +1346,10 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius, fillTile, m
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a tree ring
|
||||
if ((distSqr < tree_radius_sqr_outer) and (distSqr > tree_radius_sqr_inner)) then
|
||||
surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } })
|
||||
end
|
||||
-- -- Create a tree ring
|
||||
-- if ((distSqr < tree_radius_sqr_outer) and (distSqr > tree_radius_sqr_inner)) then
|
||||
-- surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } })
|
||||
-- end
|
||||
|
||||
-- Fill moat with water.
|
||||
if (moat) then
|
||||
@ -1357,12 +1358,27 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius, fillTile, m
|
||||
-- land connections if the spawn is on or near land.
|
||||
elseif ((distSqr < moat_radius_sqr) and (distSqr > tile_radius_sqr)) then
|
||||
table.insert(dirtTiles, { name = "water", position = { i, j } })
|
||||
|
||||
--5% chance of fish in water
|
||||
if (math.random(1,20) == 1) then
|
||||
surface.create_entity({name="fish", position={i + 0.5, j + 0.5}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(dirtTiles)
|
||||
|
||||
--Create trees (needs to be done after setting tiles!)
|
||||
for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do
|
||||
for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do
|
||||
local distSqr = math.floor((centerPos.x - i) ^ 2 + (centerPos.y - j) ^ 2)
|
||||
if ((distSqr < tree_radius_sqr_outer) and (distSqr > tree_radius_sqr_inner)) then
|
||||
surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---` spawn shape (handles land, trees and moat) (Curtesy of jvmguy)
|
||||
@ -1398,10 +1414,10 @@ function CreateCropOctagon(surface, centerPos, chunkArea, tileRadius, fillTile,
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a tree ring
|
||||
if ((distVar < tileRadius) and (distVar >= tree_distance_inner)) then
|
||||
surface.create_entity({ name = "tree-01", amount = 1, position = { i, j } })
|
||||
end
|
||||
-- -- Create a tree ring
|
||||
-- if ((distVar < tileRadius) and (distVar >= tree_distance_inner)) then
|
||||
-- surface.create_entity({ name = "tree-01", amount = 1, position = { i, j } })
|
||||
-- end
|
||||
|
||||
-- Fill moat with water
|
||||
if (moat) then
|
||||
@ -1410,11 +1426,29 @@ function CreateCropOctagon(surface, centerPos, chunkArea, tileRadius, fillTile,
|
||||
-- land connections if the spawn is on or near land.
|
||||
elseif ((distVar > tileRadius) and (distVar <= moat_width_outer)) then
|
||||
table.insert(dirtTiles, { name = "water", position = { i, j } })
|
||||
|
||||
--5% chance of fish in water
|
||||
if (math.random(1,20) == 1) then
|
||||
surface.create_entity({name="fish", position={i + 0.5, j + 0.5}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
surface.set_tiles(dirtTiles)
|
||||
|
||||
--Create trees (needs to be done after setting tiles!)
|
||||
for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do
|
||||
for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do
|
||||
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);
|
||||
|
||||
if ((distVar < tileRadius) and (distVar >= tree_distance_inner)) then
|
||||
surface.create_entity({ name = "tree-01", amount = 1, position = { i, j } })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Square spawn shape (handles land, trees and moat)
|
||||
@ -1449,10 +1483,10 @@ function CreateCropSquare(surface, centerPos, chunkArea, tileRadius, fillTile, m
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a tree ring
|
||||
if ((max_distance < tileRadius) and (max_distance >= tree_distance_inner)) then
|
||||
surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } })
|
||||
end
|
||||
-- -- Create a tree ring
|
||||
-- if ((max_distance < tileRadius) and (max_distance >= tree_distance_inner)) then
|
||||
-- surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } })
|
||||
-- end
|
||||
|
||||
-- Fill moat with water
|
||||
if (moat) then
|
||||
@ -1461,12 +1495,27 @@ function CreateCropSquare(surface, centerPos, chunkArea, tileRadius, fillTile, m
|
||||
-- land connections if the spawn is on or near land.
|
||||
elseif ((max_distance > tileRadius) and (max_distance <= moat_width_outer)) then
|
||||
table.insert(dirtTiles, { name = "water", position = { i, j } })
|
||||
|
||||
--5% chance of fish in water
|
||||
if (math.random(1,20) == 1) then
|
||||
surface.create_entity({name="fish", position={i + 0.5, j + 0.5}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(dirtTiles)
|
||||
|
||||
--Create trees (needs to be done after setting tiles!)
|
||||
for i = chunkArea.left_top.x, chunkArea.right_bottom.x, 1 do
|
||||
for j = chunkArea.left_top.y, chunkArea.right_bottom.y, 1 do
|
||||
local max_distance = math.max(math.abs(centerPos.x - i), math.abs(centerPos.y - j))
|
||||
if ((max_distance < tileRadius) and (max_distance >= tree_distance_inner)) then
|
||||
surface.create_entity({ name = "tree-02", amount = 1, position = { i, j } })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Add a circle of water
|
||||
|
@ -19,7 +19,7 @@ function OarcModifyEnemyGroup(event)
|
||||
|
||||
-- Check validity
|
||||
if ((group == nil) or (group.command == nil) or not TableContains(ENEMY_FORCES_NAMES, group.force.name)) then
|
||||
log("OarcModifyEnemyGroup ignoring INVALID group/command")
|
||||
log("WARN - OarcModifyEnemyGroup ignoring INVALID group/command " .. serpent.block(group))
|
||||
return
|
||||
end
|
||||
|
||||
@ -72,7 +72,7 @@ function OarcModifyEnemyGroup(event)
|
||||
-- This is unexpected, not sure under which conditions this would happen.
|
||||
if (group.command.type == defines.command.attack_area) then
|
||||
-- SendBroadcastMsg("OarcModifyEnemyGroup find_nearest_enemy attack_area FAILED!?!? " .. GetGPStext(group.surface.name, group.position) .. " Target: " .. GetGPStext(group.surface.name, group.command.destination))
|
||||
log("ERROR - OarcModifyEnemyGroup find_nearest_enemy attack_area FAILED!?!?")
|
||||
log("ERROR - OarcModifyEnemyGroup find_nearest_enemy attack_area FAILED!?!?" .. serpent.block(group))
|
||||
-- for _,member in pairs(group.members) do
|
||||
-- member.destroy()
|
||||
-- end
|
||||
@ -95,7 +95,7 @@ function OarcModifyEnemyGroup(event)
|
||||
-- I don't think this should happen ever...
|
||||
if ((target_player == nil) or (not target_player.valid)) then
|
||||
-- SendBroadcastMsg("ERROR?? target_player nil/invalid " .. GetGPStext(group.surface.name, group.position) .. " Target: " .. GetGPStext(group.surface.name, target_entity.position))
|
||||
log("ERROR - OarcModifyEnemyGroup target_player nil/invalid?")
|
||||
log("ERROR - OarcModifyEnemyGroup target_player nil/invalid?" .. serpent.block(group))
|
||||
-- for _,member in pairs(group.members) do
|
||||
-- member.destroy()
|
||||
-- end
|
||||
@ -125,6 +125,6 @@ function OarcModifyEnemyGroup(event)
|
||||
member.destroy()
|
||||
end
|
||||
-- SendBroadcastMsg("Enemy group deleted: " .. GetGPStext(group.surface.name, group.position) .. " Target: " .. GetGPStext(group.surface.name, target_entity.position) .. " " .. target_player.name)
|
||||
log("OarcModifyEnemyGroup REMOVED enemy group since nobody was online? " .. target_player.name)
|
||||
-- log("OarcModifyEnemyGroup REMOVED enemy group since nobody was online? " .. target_player.name)
|
||||
|
||||
end
|
@ -493,6 +493,7 @@ function OarcRegrowthRemoveAllChunks()
|
||||
-- If it is FORCE removal, then remove it regardless of pollution.
|
||||
if (c_remove.force) then
|
||||
game.surfaces[surface_name].delete_chunk(c_pos)
|
||||
global.rg[surface_name].map[c_pos.x][c_pos.y] = nil
|
||||
|
||||
elseif (global.rg[surface_name].map[c_pos.x][c_pos.y] == REGROWTH_FLAG_REMOVAL) then
|
||||
|
||||
@ -506,9 +507,12 @@ function OarcRegrowthRemoveAllChunks()
|
||||
global.rg[surface_name].map[c_pos.x][c_pos.y] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- If we hit here, the chunk was probably refreshed or something and so we don't want to delete it.
|
||||
-- We won't check it again since we clear the removal list after this. This should be correct.
|
||||
else
|
||||
-- This should never happen, TODO: check if it does?
|
||||
error("ERROR - OarcRegrowthRemoveAllChunks: Chunk not in map: " .. c_pos.x .. "," .. c_pos.y .. " on surface: " .. surface_name)
|
||||
log("WARN - OarcRegrowthRemoveAllChunks: Chunk not in map: " .. c_pos.x .. "," .. c_pos.y .. " on surface: " .. surface_name)
|
||||
end
|
||||
|
||||
-- Remove entry
|
||||
|
@ -132,11 +132,11 @@ function DowngradeAndReduceEnemiesOnChunkGenerate(event)
|
||||
}
|
||||
|
||||
-- Make chunks near a spawn safe by removing enemies
|
||||
if (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.safe_radius) then
|
||||
if (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.safe_radius * CHUNK_SIZE) then
|
||||
RemoveEnemiesInArea(surface, chunk_area)
|
||||
|
||||
-- Create a warning area with heavily reduced enemies
|
||||
elseif (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.warn_radius) then
|
||||
elseif (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.warn_radius * CHUNK_SIZE) then
|
||||
|
||||
-- TODO: Refactor this to reduce calls to find_entities_filtered!
|
||||
ReduceEnemiesInArea(surface, chunk_area, spawn_config.safe_area.warn_reduction)
|
||||
@ -144,7 +144,7 @@ function DowngradeAndReduceEnemiesOnChunkGenerate(event)
|
||||
ConvertEnemiesToOtherForceInArea(surface, chunk_area, ENEMY_FORCE_EASY)
|
||||
|
||||
-- Create a third area with moderately reduced enemies
|
||||
elseif (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.danger_radius) then
|
||||
elseif (util.distance(closest_spawn.position, chunkAreaCenter) < spawn_config.safe_area.danger_radius * CHUNK_SIZE) then
|
||||
|
||||
-- TODO: Refactor this to reduce calls to find_entities_filtered!
|
||||
ReduceEnemiesInArea(surface, chunk_area, spawn_config.safe_area.danger_reduction)
|
||||
@ -287,15 +287,15 @@ function ChangeEnemySpawnersToOtherForceOnBuilt(event)
|
||||
if (closest_spawn == nil) then return end
|
||||
|
||||
-- No enemies inside safe radius!
|
||||
if (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.safe_radius) then
|
||||
if (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.safe_radius * CHUNK_SIZE) then
|
||||
event.entity.destroy()
|
||||
|
||||
-- Warn distance should be EASY
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.warn_radius) then
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.warn_radius * CHUNK_SIZE) then
|
||||
event.entity.force = game.forces[ENEMY_FORCE_EASY]
|
||||
|
||||
-- Danger distance should be MEDIUM
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.danger_radius) then
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.danger_radius * CHUNK_SIZE) then
|
||||
event.entity.force = game.forces[ENEMY_FORCE_MEDIUM]
|
||||
|
||||
-- Otherwise make sure they are on the base enemy force (stops easy enemies from spreading out too far).
|
||||
@ -328,11 +328,11 @@ function ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
end
|
||||
|
||||
-- No enemies inside safe radius!
|
||||
if (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.safe_radius) then
|
||||
if (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.safe_radius * CHUNK_SIZE) then
|
||||
event.entity.destroy()
|
||||
|
||||
-- Warn distance is all SMALL only.
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.warn_radius) then
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.warn_radius * CHUNK_SIZE) then
|
||||
if ((enemy_name == "biter-spawner") or (enemy_name == "spitter-spawner")) then
|
||||
event.entity.force = game.forces["enemy-easy"]
|
||||
|
||||
@ -351,7 +351,7 @@ function ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
end
|
||||
|
||||
-- Danger distance is MEDIUM max.
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.danger_radius) then
|
||||
elseif (util.distance(enemy_pos, closest_spawn.position) < global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.danger_radius * CHUNK_SIZE) then
|
||||
if ((enemy_name == "big-biter") or (enemy_name == "behemoth-biter")) then
|
||||
event.entity.destroy()
|
||||
surface.create_entity { name = "medium-biter", position = enemy_pos, force = game.forces.enemy }
|
||||
|
@ -141,10 +141,10 @@ function SeparateSpawnsInitSurface(surface_name)
|
||||
global.oarc_surfaces[surface_name] = (surface_name == global.ocfg.gameplay.default_surface)
|
||||
end
|
||||
|
||||
-- Make sure it has a surface configuration entry
|
||||
if (global.oarc_surfaces[surface_name] and global.ocfg.surfaces_config[surface_name] == nil) then
|
||||
-- Make sure it has a surface configuration entry!
|
||||
if (global.ocfg.surfaces_config[surface_name] == nil) then
|
||||
log("Surface does NOT have a config entry, defaulting to nauvis entry for new surface: " .. surface_name)
|
||||
global.ocfg.surfaces_config[surface_name] = global.ocfg.surfaces_config["nauvis"]
|
||||
global.ocfg.surfaces_config[surface_name] = table.deepcopy(global.ocfg.surfaces_config["nauvis"])
|
||||
end
|
||||
end
|
||||
|
||||
@ -272,37 +272,62 @@ function GenerateStartingResources(surface, position)
|
||||
local amount_mod = global.ocfg.resource_placement.amount_multiplier
|
||||
|
||||
-- Generate all resource tile patches
|
||||
if (not global.ocfg.resource_placement.enabled) then
|
||||
for r_name, r_data in pairs(global.ocfg.surfaces_config[surface.name].spawn_config.solid_resources --[[@as table<string, OarcConfigSolidResource>]]) do
|
||||
local pos = { x = position.x + r_data.x_offset, y = position.y + r_data.y_offset }
|
||||
GenerateResourcePatch(surface, r_name, r_data.size * size_mod, pos, r_data.amount * amount_mod)
|
||||
end
|
||||
|
||||
-- Generate resources in random order around the spawn point. Tweak in config.lua
|
||||
else
|
||||
|
||||
-- Generate resources in random order around the spawn point.
|
||||
if global.ocfg.resource_placement.enabled then
|
||||
if (global.ocfg.spawn_general.shape == SPAWN_SHAPE_CHOICE_CIRCLE) or (global.ocfg.spawn_general.shape == SPAWN_SHAPE_CHOICE_OCTAGON) then
|
||||
PlaceResourcesInSemiCircle(surface, position, size_mod, amount_mod)
|
||||
elseif (global.ocfg.spawn_general.shape == SPAWN_SHAPE_CHOICE_SQUARE) then
|
||||
PlaceResourcesInSquare(surface, position, size_mod, amount_mod)
|
||||
end
|
||||
|
||||
-- Generate resources using specified offsets if auto placement is disabled.
|
||||
else
|
||||
for r_name, r_data in pairs(global.ocfg.surfaces_config[surface.name].spawn_config.solid_resources --[[@as table<string, OarcConfigSolidResource>]]) do
|
||||
local pos = { x = position.x + r_data.x_offset, y = position.y + r_data.y_offset }
|
||||
GenerateResourcePatch(surface, r_name, r_data.size * size_mod, pos, r_data.amount * amount_mod)
|
||||
end
|
||||
end
|
||||
|
||||
-- Generate special fluid resource patches (oil)
|
||||
-- Autoplace using spacing and vertical offset.
|
||||
-- Reference position is the bottom of the spawn area.
|
||||
local fluid_ref_pos = { x = position.x,
|
||||
y = position.y + global.ocfg.spawn_general.spawn_radius_tiles }
|
||||
for r_name, r_data in pairs(global.ocfg.surfaces_config[surface.name].spawn_config.fluid_resources --[[@as table<string, OarcConfigFluidResource>]]) do
|
||||
local oil_patch_x = fluid_ref_pos.x + r_data.x_offset_start
|
||||
local oil_patch_y = fluid_ref_pos.y + r_data.y_offset_start
|
||||
for i = 1, r_data.num_patches do
|
||||
surface.create_entity({
|
||||
name = r_name,
|
||||
amount = r_data.amount,
|
||||
position = { oil_patch_x, oil_patch_y }
|
||||
})
|
||||
oil_patch_x = oil_patch_x + r_data.x_offset_next
|
||||
oil_patch_y = oil_patch_y + r_data.y_offset_next
|
||||
if global.ocfg.resource_placement.enabled then
|
||||
local y_offset = global.ocfg.resource_placement.distance_to_edge
|
||||
local spacing = 4 -- HARDCODED FLUID PATCH SPACING SIZE!
|
||||
local fluid_ref_pos = { x = position.x, y = position.y + global.ocfg.spawn_general.spawn_radius_tiles - y_offset }
|
||||
|
||||
for r_name, r_data in pairs(global.ocfg.surfaces_config[surface.name].spawn_config.fluid_resources --[[@as table<string, OarcConfigFluidResource>]]) do
|
||||
|
||||
local oil_patch_x = fluid_ref_pos.x - (((r_data.num_patches-1) * spacing) / 2)
|
||||
local oil_patch_y = fluid_ref_pos.y
|
||||
|
||||
for i = 1, r_data.num_patches do
|
||||
surface.create_entity({
|
||||
name = "crude-oil",
|
||||
amount = r_data.amount,
|
||||
position = { oil_patch_x, oil_patch_y }
|
||||
})
|
||||
oil_patch_x = oil_patch_x + spacing
|
||||
end
|
||||
|
||||
fluid_ref_pos.y = fluid_ref_pos.y - spacing
|
||||
end
|
||||
|
||||
-- This places using specified offsets if auto placement is disabled.
|
||||
else
|
||||
local fluid_ref_pos = { x = position.x, y = position.y + global.ocfg.spawn_general.spawn_radius_tiles }
|
||||
for r_name, r_data in pairs(global.ocfg.surfaces_config[surface.name].spawn_config.fluid_resources --[[@as table<string, OarcConfigFluidResource>]]) do
|
||||
local oil_patch_x = fluid_ref_pos.x + r_data.x_offset_start
|
||||
local oil_patch_y = fluid_ref_pos.y + r_data.y_offset_start
|
||||
for i = 1, r_data.num_patches do
|
||||
surface.create_entity({
|
||||
name = r_name,
|
||||
amount = r_data.amount,
|
||||
position = { oil_patch_x, oil_patch_y }
|
||||
})
|
||||
oil_patch_x = oil_patch_x + r_data.x_offset_next
|
||||
oil_patch_y = oil_patch_y + r_data.y_offset_next
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -329,7 +354,7 @@ function PlaceResourcesInSemiCircle(surface, position, size_mod, amount_mod)
|
||||
-- This places resources in a semi-circle
|
||||
local angle_offset = global.ocfg.resource_placement.angle_offset
|
||||
local num_resources = table_size(global.ocfg.surfaces_config[surface.name].spawn_config.solid_resources)
|
||||
local theta = ((global.ocfg.resource_placement.angle_final - global.ocfg.resource_placement.angle_offset) / num_resources);
|
||||
local theta = ((global.ocfg.resource_placement.angle_final - global.ocfg.resource_placement.angle_offset) / (num_resources-1));
|
||||
local count = 0
|
||||
|
||||
local radius = global.ocfg.spawn_general.spawn_radius_tiles - global.ocfg.resource_placement.distance_to_edge
|
||||
@ -392,7 +417,7 @@ function SendPlayerToNewSpawnAndCreateIt(delayed_spawn)
|
||||
local spawn_config = ocfg.surfaces_config[delayed_spawn.surface].spawn_config
|
||||
|
||||
-- DOUBLE CHECK and make sure the area is super safe.
|
||||
ClearNearbyEnemies(delayed_spawn.position, spawn_config.safe_area.safe_radius,
|
||||
ClearNearbyEnemies(delayed_spawn.position, spawn_config.safe_area.safe_radius * CHUNK_SIZE,
|
||||
game.surfaces[delayed_spawn.surface])
|
||||
|
||||
-- Generate water strip only if we don't have a moat.
|
||||
@ -624,7 +649,7 @@ function DowngradeResourcesDistanceBasedOnChunkGenerate(surface, chunkArea)
|
||||
|
||||
local distance = util.distance(chunkArea.left_top, closestSpawn.position)
|
||||
-- Adjust multiplier to bring it in or out
|
||||
local modifier = (distance / (global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.danger_radius * 1)) ^ 3
|
||||
local modifier = (distance / (global.ocfg.surfaces_config[surface.name].spawn_config.safe_area.danger_radius * CHUNK_SIZE * 1)) ^ 3
|
||||
if modifier < 0.1 then modifier = 0.1 end
|
||||
if modifier > 1 then return end
|
||||
|
||||
@ -737,7 +762,7 @@ function RemoveOrResetPlayer(player, remove_player)
|
||||
end
|
||||
end
|
||||
|
||||
---Searches all unique spawns for the primary one for a player.
|
||||
---Searches all unique spawns for the primary one for a player. This will return null if they joined someeone else's spawn.
|
||||
---@param player_name string
|
||||
---@return OarcUniqueSpawn?
|
||||
function FindPrimaryUniqueSpawn(player_name)
|
||||
@ -748,6 +773,19 @@ function FindPrimaryUniqueSpawn(player_name)
|
||||
end
|
||||
end
|
||||
|
||||
---Find the primary home spawn of a player, if one exists. It could be they joined a shared spawn.
|
||||
---@param player_name string
|
||||
---@return OarcUniqueSpawn?
|
||||
function FindPlayerHomeSpawn(player_name)
|
||||
for _,spawns in pairs(global.unique_spawns) do
|
||||
for _,spawn in pairs(spawns) do
|
||||
if (spawn.primary) and ((spawn.host_name == player_name) or TableContains(spawn.joiners, player_name)) then
|
||||
return spawn
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Searches all unique spawns for a list of secondary ones for a player.
|
||||
---@param player_name string
|
||||
---@return table<string, OarcUniqueSpawn> -- Indexed by surface name!
|
||||
|
@ -181,6 +181,8 @@ oarc-server-info-tab-title=Server Info
|
||||
oarc-spawn-ctrls-tab-title=Spawn Controls
|
||||
oarc-settings-tab-title=Settings
|
||||
oarc-mod-info-tab-title=Mod Info
|
||||
oarc-player-list-tab-title=Player List
|
||||
oarc-surface-config-tab-title=Surface Config
|
||||
|
||||
oarc-server-info-tab-welcome-msg-title=Welcome Message
|
||||
oarc-server-info-tab-discord-invite=Discord Invite:
|
||||
@ -197,11 +199,24 @@ oarc-player-not-found=Player __1__ is not found?
|
||||
oarc-player-about-to-spawn=Player __1__ is about to spawn, try again later.
|
||||
oarc-player-none-selected=No player selected!
|
||||
|
||||
oarc-player-list-tab-column-header-player=Player
|
||||
oarc-player-list-tab-column-header-force=Team (Force)
|
||||
oarc-player-list-tab-column-header-surface=Home Surface
|
||||
oarc-player-list-tab-column-header-time-player=Time Played
|
||||
oarc-player-list-tab-column-header-location=Location
|
||||
oarc-player-list-tab-column-header-status=Status
|
||||
|
||||
oarc-player-online=Online
|
||||
oarc-player-offline=Offline
|
||||
oarc-player-waiting-to-spawn=Not Spawned Yet
|
||||
|
||||
oarc-player-list-tab-location-button-tooltip=Click to view map location.
|
||||
|
||||
|
||||
oarc-settings-tab-title-mod-settings=Mod Settings
|
||||
oarc-settings-tab-admin-warning=You are an admin. Changing these settings late in the game may cause issues!\nChanging settings will not modify existing spawns. BE CAREFUL!
|
||||
oarc-settings-tab-player-warning=You are not an admin. These settings are read-only for you.
|
||||
oarc-settings-tab-description=This tab contains the same mod settings in the mod settings menu AND some additional settings that can only be changed in game.
|
||||
oarc-settings-tab-description=This tab contains the same mod settings in the mod settings menu AND some additional settings that can only be changed in game. Check the Surface Config tab for surface-specific settings.
|
||||
oarc-settings-tab-text-field-enter-tooltip=[color=red]You must press ENTER after typing in a text field to save the value![/color]
|
||||
oarc-settings-tab-title-surface=Surface Settings
|
||||
oarc-settings-tab-surface-checkbox-tooltip=Enabling this will allow custom spawn areas (the main feature of this mod) on this surface. You need at least one of these enabled for the mod to work.
|
||||
@ -209,7 +224,11 @@ oarc-settings-tab-surface-regrowth-checkbox-tooltip=Enabling this will allow the
|
||||
oarc-settings-tab-surface-column-header=Surface
|
||||
oarc-settings-tab-surface-spawning-enabled=Custom Spawns
|
||||
oarc-settings-tab-surface-regrowth-enabled=Regrowth
|
||||
|
||||
oarc-settings-tab-title-export=Import/Export Settings
|
||||
oarc-settings-tab-export-button=Export
|
||||
oarc-settings-tab-export-button-tooltip=Exports all settings to a string that can be shared with other players or saved for later.
|
||||
oarc-settings-tab-import-button=Import
|
||||
oarc-settings-tab-import-button-tooltip=Imports settings from a string. This will overwrite all settings with the imported values!
|
||||
|
||||
oarc-settings-section-header-server-info=Server Info
|
||||
oarc-settings-section-header-gameplay=Gameplay
|
||||
|
16
migrations/oarc-mod_V2.0.2.lua
Normal file
16
migrations/oarc-mod_V2.0.2.lua
Normal file
@ -0,0 +1,16 @@
|
||||
-- Migrate safe_radius, warn_radius and danger_radius to be chunks instead of tiles.
|
||||
for surface_name, surface_config in pairs(global.ocfg.surfaces_config) do
|
||||
|
||||
-- If the safe_area is greater than 3 chunks, then it's likely in chunks...
|
||||
if surface_config.spawn_config.safe_area.safe_radius >= (3 * 32) then
|
||||
log("Oarc-mod: Migrating safe_radius, warn_radius and danger_radius to be chunks instead of tiles.")
|
||||
local safe_radius = surface_config.spawn_config.safe_area.safe_radius
|
||||
global.ocfg.surfaces_config[surface_name].spawn_config.safe_area.safe_radius = math.ceil(safe_radius / 32)
|
||||
|
||||
local warn_radius = surface_config.spawn_config.safe_area.warn_radius
|
||||
global.ocfg.surfaces_config[surface_name].spawn_config.safe_area.warn_radius = math.ceil(warn_radius / 32)
|
||||
|
||||
local danger_radius = surface_config.spawn_config.safe_area.danger_radius
|
||||
global.ocfg.surfaces_config[surface_name].spawn_config.safe_area.danger_radius = math.ceil(danger_radius / 32)
|
||||
end
|
||||
end
|
@ -80,9 +80,9 @@ data:extend({
|
||||
type = "int-setting",
|
||||
name = "oarc-mod-minimum-distance-to-existing-chunks",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 10,
|
||||
default_value = 20,
|
||||
minimum_value = 5,
|
||||
maximum_value = 25,
|
||||
maximum_value = 50,
|
||||
order = "c1"
|
||||
},
|
||||
{
|
||||
@ -341,7 +341,7 @@ data:extend({
|
||||
type = "double-setting",
|
||||
name = "oarc-mod-resource-placement-angle-offset",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 2.32,
|
||||
default_value = 2.09,
|
||||
minimum_value = 0,
|
||||
maximum_value = 6.28,
|
||||
order = "i3"
|
||||
@ -350,7 +350,7 @@ data:extend({
|
||||
type = "double-setting",
|
||||
name = "oarc-mod-resource-placement-angle-final",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 4.46,
|
||||
default_value = 4.18,
|
||||
minimum_value = 0,
|
||||
maximum_value = 6.28,
|
||||
order = "i4"
|
||||
|
Loading…
Reference in New Issue
Block a user