1
0
mirror of https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git synced 2024-12-04 09:43:00 +02:00

Saving my work. The game loads and most of the basics are working but not properly tested yet.

This commit is contained in:
Oarcinae 2024-10-21 13:48:42 -04:00
parent 6d75811639
commit 0d5ec9210e
23 changed files with 198 additions and 133 deletions

View File

@ -17,7 +17,7 @@
-- Check if the OARC mod is loaded. Other than that, it's an empty scenario!
script.on_init(function(event)
if not game.active_mods["oarc-mod"] then
if not script.active_mods["oarc-mod"] then
error("OARC mod not found! This scenario is intended to be run with the OARC mod!")
end
end)

View File

@ -167,7 +167,10 @@ end)
----------------------------------------
-- This is not called when the default surface "nauvis" is created as it will always exist!
script.on_event(defines.events.on_surface_created, function(event)
log("Surface created: " .. game.surfaces[event.surface_index].name)
local surface = game.surfaces[event.surface_index]
log("Surface created: " .. surface.name)
if (surface.platform) then return end -- WE IGNORE PLATFORMS!
SeparateSpawnsSurfaceCreated(event)
RegrowthSurfaceCreated(event)
end)
@ -183,7 +186,7 @@ end)
----------------------------------------
script.on_event(defines.events.on_built_entity, function(event)
if storage.ocfg.regrowth.enable_regrowth then
RegrowthMarkAreaSafeGivenTilePos(event.created_entity.surface.name, event.created_entity.position, 2, false)
RegrowthMarkAreaSafeGivenTilePos(event.entity.surface.name, event.entity.position, 2, false)
end
-- For tracking spidertrons...
@ -192,7 +195,7 @@ end)
script.on_event(defines.events.on_robot_built_entity, function (event)
if storage.ocfg.regrowth.enable_regrowth then
RegrowthMarkAreaSafeGivenTilePos(event.created_entity.surface.name, event.created_entity.position, 2, false)
RegrowthMarkAreaSafeGivenTilePos(event.entity.surface.name, event.entity.position, 2, false)
end
end)

View File

@ -6,14 +6,12 @@ oarc_linked_chest.type="linked-container"
oarc_linked_chest.name="oarc-linked-chest"
oarc_linked_chest.inventory_type="with_filters_and_bar"
oarc_linked_chest.inventory_size=settings.startup["oarc-mod-linked-chest-size"].value --[[@as integer]]
oarc_linked_chest.picture.layers[1].filename = "__oarc-mod__/graphics/oarc-linked-chest.png"
oarc_linked_chest.picture.layers[1].hr_version.filename = "__oarc-mod__/graphics/hr-oarc-linked-chest.png"
oarc_linked_chest.picture.layers[1].filename = "__oarc-mod__/graphics/hr-oarc-linked-chest.png"
local oarc_linked_power=table.deepcopy(data.raw["electric-pole"]["small-electric-pole"])
oarc_linked_power.name="oarc-linked-power"
oarc_linked_power.pictures.layers[1].filename = "__oarc-mod__/graphics/oarc-electric-pole.png"
oarc_linked_power.pictures.layers[1].hr_version.filename = "__oarc-mod__/graphics/hr-oarc-electric-pole.png"
oarc_linked_power.pictures.layers[1].filename = "__oarc-mod__/graphics/hr-oarc-electric-pole.png"
data:extend({
{
@ -27,4 +25,4 @@ data:extend({
})
-- Make coins not hidden
data.raw["item"]["coin"].flags = {}
data.raw["item"]["coin"].hidden = false

View File

@ -78,6 +78,7 @@ Added LuaForce::copy_from() and copy_chart() methods.
------------------------------------------------------------------------------------------------------------------------
Other Ideas, Not Committed:
- Look into checking if a force has a chunk visible (for regrowth)
- Add option to spawn on existing chunks (look for chunks with any entities in them, or use regrowth logic)
- Add option for spawn pen to be on a specified surface (not sure this serves any real purpose)
- Change "search for ungenerated spawn point" to be a "roll" button that the player can re-roll? Maybe it shows on the map in an icon where they might go first?

View File

@ -1,25 +1,13 @@
{
"_terrain_segmentation_comment": "Inverse of map scale",
"terrain_segmentation": 1,
"_water_comment":
[
"Multiplier for water 'coverage' - higher increases the water level.",
"Water level = 10 * log2(this value)"
],
"water": 1,
"_comment_width+height": "Width and height of map, in tiles; 0 means infinite",
"width": 1,
"height": 1,
"width": 0,
"height": 0,
"_starting_area_comment": "Multiplier for 'biter free zone radius'",
"starting_area": 1,
"peaceful_mode": false,
"default_enable_all_autoplace_controls": true,
"autoplace_controls":
{
"coal" : {"frequency" : 0.20, "richness" : 10.00, "size" : 0.20},
@ -28,8 +16,9 @@
"stone" : {"frequency" : 0.20, "richness" : 10.00, "size" : 0.20},
"uranium-ore" : {"frequency" : 0.20, "richness" : 10.00, "size" : 0.20},
"crude-oil" : {"frequency" : 0.20, "richness" : 10.00, "size" : 0.20},
"trees" : {"frequency" : 0.30, "richness" : 1.50, "size" : 1.00},
"enemy-base" : {"frequency" : 0.40, "richness" : 0.50, "size" : 0.50}
"water" : {"frequency": 1, "size": 1},
"trees" : {"frequency": 1, "size": 1},
"enemy-base" : {"frequency": 0.4, "size": 0.5}
},
"cliff_settings":
@ -40,10 +29,14 @@
"_cliff_elevation_0_comment": "Elevation of first row of cliffs",
"cliff_elevation_0": 10,
"_cliff_elevation_interval_comment": "Elevation difference between successive rows of cliffs",
"cliff_elevation_interval": 10,
"_cliff_elevation_interval_comment":
[
"Elevation difference between successive rows of cliffs.",
"This is inversely proportional to 'frequency' in the map generation GUI. Specifically, when set from the GUI the value is 40 / frequency."
],
"cliff_elevation_interval": 40,
"_richness_comment": "Multiplier for cliff continuity; 0 will result in no cliffs, 10 will make all cliff rows completely solid",
"_richness_comment": "Called 'cliff continuity' in the map generator GUI. 0 will result in no cliffs, 10 will make all cliff rows completely solid",
"richness": 1
},

View File

@ -1,10 +1,8 @@
{
"difficulty_settings":
{
"recipe_difficulty": 0,
"technology_difficulty": 0,
"technology_price_multiplier": 1,
"research_queue_setting": "always"
"spoil_time_modifier" : 1
},
"pollution":
{
@ -21,20 +19,19 @@
"pollution_per_tree_damage": 50,
"pollution_restored_per_tree_damage": 10,
"max_pollution_to_restore_trees": 20,
"enemy_attack_pollution_consumption_modifier": 0.5
"enemy_attack_pollution_consumption_modifier": 1
},
"enemy_evolution":
{
"enabled": true,
"time_factor": 0.000000,
"time_factor": 0.000004,
"destroy_factor": 0.002,
"pollution_factor": 0.0000002
"pollution_factor": 0.0000009
},
"enemy_expansion":
{
"enabled": true,
"min_base_spacing": 3,
"max_expansion_distance": 10,
"max_expansion_distance": 7,
"friendly_base_influence_radius": 2,
"enemy_building_influence_radius": 2,
"building_coefficient": 0.1,
@ -45,7 +42,7 @@
"settler_group_min_size": 5,
"settler_group_max_size": 20,
"min_expansion_cooldown": 14400,
"max_expansion_cooldown": 108000
"max_expansion_cooldown": 216000
},
"unit_group":
{
@ -84,7 +81,7 @@
{
"fwd2bwd_ratio": 5,
"goal_pressure_ratio": 2,
"max_steps_worked_per_tick": 100,
"max_steps_worked_per_tick": 1000,
"max_work_done_per_tick": 8000,
"use_path_cache": true,
"short_cache_size": 5,
@ -111,10 +108,15 @@
"short_request_max_steps": 1000,
"short_request_ratio": 0.5,
"min_steps_to_check_path_find_termination": 2000,
"start_to_goal_cost_multiplier_to_terminate_path_find": 500.0,
"start_to_goal_cost_multiplier_to_terminate_path_find": 2000.0,
"overload_levels": [0, 100, 500],
"overload_multipliers": [2, 3, 4],
"negative_path_cache_delay_interval": 20
},
"asteroids":
{
"spawning_rate" : 1,
"max_ray_portals_expanded_per_tick" : 100
},
"max_failed_behavior_count": 3
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -521,6 +521,8 @@ OCFG = {
-- (Ignore these surfaces completely for spawning and regrowth!)
---@type table<integer, string>
surfaces_blacklist_match = {
-- Space Age
"platform-",
-- Factorissimo Mod Surfaces
"factory-power",
"factory-floor",

View File

@ -126,7 +126,7 @@ function ValidateAndLoadConfig()
if (entry.mod_key ~= "") then
local mod_key = entry.mod_key
local oarc_key = entry.ocfg_keys
local mod_value = game.mod_setting_prototypes[mod_key].default_value
local mod_value = prototypes.mod_setting[mod_key].default_value
local oarc_value = GetGlobalOarcConfigUsingKeyTable(oarc_key)
if (mod_value ~= oarc_value) then
error("OCFG value does not match mod setting: " .. mod_key .. " = " .. tostring(mod_value) .. " -> " .. serpent.block(oarc_key) .. " = " .. tostring(oarc_value))

View File

@ -6,8 +6,16 @@
---@return nil
function CreateItemShopTab(tab_container, player)
local player_inv = player.get_main_inventory()
if (player_inv == nil) then return end
if (player.character == nil) then
AddLabel(tab_container, nil, "Player character not available right now.", my_warning_style)
return
end
local player_inv = player.character.get_main_inventory()
if (player_inv == nil) then
AddLabel(tab_container, nil, "Player main inventory not available right now.", my_warning_style)
return
end
local wallet = player_inv.get_item_count("coin")
AddLabel(tab_container,
@ -29,7 +37,7 @@ function CreateItemShopTab(tab_container, player)
for item_name,item in pairs(section) do
-- Validate if item exists
if (not game.item_prototypes[item_name]) then
if (not prototypes.item[item_name]) then
log("ERROR: Item not found in storage.ocfg.shop_items: " .. item_name)
goto continue
end
@ -134,8 +142,24 @@ function DropCoins(surface_index, pos, count, force)
if drop_amount == 0 then return end
if storage.ocfg.coin_generation.auto_decon_coins then
game.surfaces[surface_index].spill_item_stack(pos, {name="coin", count=math.floor(drop_amount)}, true, force, false)
game.surfaces[surface_index].spill_item_stack{
position=pos,
stack={name="coin", count=math.floor(drop_amount)},
enable_looted=true,
force=force,
-- allow_belts?=false,
-- max_radius?=…,
-- use_start_position_on_failure?=false
}
else
game.surfaces[surface_index].spill_item_stack(pos, {name="coin", count=math.floor(drop_amount)}, true, nil, false)
game.surfaces[surface_index].spill_item_stack{
position=pos,
stack={name="coin", count=math.floor(drop_amount)},
enable_looted=true,
force=nil,
-- allow_belts?=false,
-- max_radius?=…,
-- use_start_position_on_failure?=false
}
end
end

View File

@ -123,6 +123,6 @@ function PlayerListTabGuiClick(event)
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!
player.set_controller{type = defines.controllers.remote, position = target_player.character.position, surface = target_player.character.surface}
end
end

View File

@ -217,7 +217,7 @@ function SettingsControlsTabGuiTextconfirmed(event)
elseif (entry.type == "integer") then
local safe_value = GetSafeIntValueForModSetting(value, entry.mod_key)
if not pcall(function() settings.global[entry.mod_key] = { value = safe_value } end) then
settings.global[entry.mod_key] = { value = game.mod_setting_prototypes[entry.mod_key].default_value }
settings.global[entry.mod_key] = { value = prototypes.mod_setting[entry.mod_key].default_value }
log("Error setting value for " .. entry.mod_key .. " to " .. safe_value)
end
gui_elem.text = tostring(settings.global[entry.mod_key].value)
@ -229,7 +229,7 @@ function SettingsControlsTabGuiTextconfirmed(event)
elseif (entry.type == "double") then
local safe_value = GetSafeDoubleValueForModSetting(value, entry.mod_key)
if not pcall(function() settings.global[entry.mod_key] = { value = safe_value } end) then
settings.global[entry.mod_key] = { value = game.mod_setting_prototypes[entry.mod_key].default_value }
settings.global[entry.mod_key] = { value = prototypes.mod_setting[entry.mod_key].default_value }
log("Error setting value for " .. entry.mod_key .. " to " .. safe_value)
end
gui_elem.text = string.format("%.2f", settings.global[entry.mod_key].value)
@ -272,10 +272,10 @@ end
function GetSafeIntValueForModSetting(input, mod_key)
local value_num = tonumber(input)
if not value_num then
value_num = tonumber(game.mod_setting_prototypes[mod_key].default_value)
value_num = tonumber(prototypes.mod_setting[mod_key].default_value)
else
local minimum = game.mod_setting_prototypes[mod_key].minimum_value
local maximum = game.mod_setting_prototypes[mod_key].maximum_value
local minimum = prototypes.mod_setting[mod_key].minimum_value
local maximum = prototypes.mod_setting[mod_key].maximum_value
if minimum ~= nil then
value_num = math.max(value_num, minimum)
end
@ -294,10 +294,10 @@ end
function GetSafeDoubleValueForModSetting(input, mod_key)
local value_num = tonumber(input)
if not value_num then
value_num = tonumber(game.mod_setting_prototypes[mod_key].default_value)
value_num = tonumber(prototypes.mod_setting[mod_key].default_value)
else
local minimum = game.mod_setting_prototypes[mod_key].minimum_value
local maximum = game.mod_setting_prototypes[mod_key].maximum_value
local minimum = prototypes.mod_setting[mod_key].minimum_value
local maximum = prototypes.mod_setting[mod_key].maximum_value
if minimum ~= nil then
value_num = math.max(value_num, minimum)
end
@ -399,8 +399,8 @@ function AddIntegerSetting(tab_container, index, entry, enabled)
local slider = horizontal_flow.add {
name = "slider",
type = "slider",
minimum_value = game.mod_setting_prototypes[entry.mod_key].minimum_value,
maximum_value = game.mod_setting_prototypes[entry.mod_key].maximum_value,
minimum_value = prototypes.mod_setting[entry.mod_key].minimum_value,
maximum_value = prototypes.mod_setting[entry.mod_key].maximum_value,
value = GetGlobalOarcConfigUsingKeyTable(entry.ocfg_keys),
enabled = enabled,
tooltip = { "mod-setting-description."..entry.mod_key },
@ -447,8 +447,8 @@ function AddDoubleSetting(tab_container, index, entry, enabled)
local slider = horizontal_flow.add {
name = "slider",
type = "slider",
minimum_value = game.mod_setting_prototypes[entry.mod_key].minimum_value,
maximum_value = game.mod_setting_prototypes[entry.mod_key].maximum_value,
minimum_value = prototypes.mod_setting[entry.mod_key].minimum_value,
maximum_value = prototypes.mod_setting[entry.mod_key].maximum_value,
value = GetGlobalOarcConfigUsingKeyTable(entry.ocfg_keys),
enabled = enabled,
tooltip = { "mod-setting-description."..entry.mod_key },
@ -493,7 +493,7 @@ function AddStringListDropdownSetting(tab_container, index, entry, enabled)
}
dragger.style.horizontally_stretchable = true
local allowed_values = game.mod_setting_prototypes[entry.mod_key].allowed_values --[[@as string[] ]]
local allowed_values = prototypes.mod_setting[entry.mod_key].allowed_values --[[@as string[] ]]
local selected_index = 1
for i,v in pairs(allowed_values) do

View File

@ -301,8 +301,9 @@ function SpawnCtrlTabGuiClick(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) -- TODO: Update this for spage age!
player.print({"", { "oarc-spawn-gps-location" }, GetGPStext(surface_name, position)})
player.set_controller{type = defines.controllers.remote, position = position, surface = surface_name}
-- player.print({"", { "oarc-spawn-gps-location" }, GetGPStext(surface_name, position)})
-- Accept or reject pending player join requests to a shared base
elseif ((tags.setting == "accept_player_request") or (tags.setting == "reject_player_request")) then

View File

@ -870,7 +870,7 @@ function SurfaceConfigTabGuiElemChanged(event)
return
end
if (game.entity_prototypes[new_resource_name].resource_category ~= "basic-solid") then
if (prototypes.entity[new_resource_name].resource_category ~= "basic-solid") then
player.print("Resource must be a solid resource! " .. new_resource_name)
event.element.elem_value = nil
return
@ -918,7 +918,7 @@ function SurfaceConfigTabGuiElemChanged(event)
return
end
if (game.entity_prototypes[new_resource_name].resource_category ~= "basic-fluid") then
if (prototypes.entity[new_resource_name].resource_category ~= "basic-fluid") then
player.print("Resource must be a fluid resource! " .. new_resource_name)
event.element.elem_value = nil
return

View File

@ -12,8 +12,8 @@ function CreateHoldingPenSurface()
---@type MapGenSettings
---@diagnostic disable-next-line: missing-fields
local map_settings = {}
map_settings.terrain_segmentation = "none"
map_settings.water = "none"
-- map_settings.terrain_segmentation = "none"
-- map_settings.water = "none"
map_settings.starting_area = "none"
map_settings.peaceful_mode = true
map_settings.width = 64
@ -25,6 +25,7 @@ function CreateHoldingPenSurface()
holding_pen_surface.always_day = true
holding_pen_surface.show_clouds = false
holding_pen_surface.generate_with_lab_tiles = true
holding_pen_surface.localised_name = {"oarc-holding-pen-surface"}
RenderPermanentGroundText(holding_pen_surface, {x=9,y=-7}, 5, "O", {0.9, 0.7, 0.3, 0.5}, "center")
RenderPermanentGroundText(holding_pen_surface, {x=9,y=-4}, 5, "A", {0.9, 0.7, 0.3, 0.5}, "center")
@ -93,6 +94,11 @@ function CreateHoldingPenChunks(event)
amount = 90000,
position = { 0, 9 }
})
-- Create special power pole if sharing is enabled (it will be created later when first requested otherwise)
if (storage.ocfg.gameplay.enable_shared_power) then
InitSharingPowerPoles()
end
end
end

View File

@ -238,8 +238,20 @@ function CreateOarcGuiTabsPane(player)
local subhead = inside_frame.add{
type="frame",
name="sub_header",
style = "changelog_subheader_frame"
style = "subheader_frame"
}
subhead.style.horizontally_stretchable = true
-- changelog_subheader_frame =
-- {
-- type = "frame_style",
-- parent = "subheader_frame",
-- left_padding = 12,
-- right_padding = 12,
-- top_padding = 4,
-- horizontally_stretchable = "on"
-- }
AddLabel(subhead, nil, {"oarc-gui-tab-header-label"}, "subheader_caption_label")
-- TABBED PANE

View File

@ -88,7 +88,7 @@ end
---@param alignment TextAlign?
---@return nil
function TemporaryHelperText(text, surface, position, ttl, alignment)
local rid = rendering.draw_text { text = text,
local render_object = rendering.draw_text { text = text,
surface = surface,
target = position,
color = { 0.7, 0.7, 0.7, 0.7 },
@ -97,6 +97,7 @@ function TemporaryHelperText(text, surface, position, ttl, alignment)
time_to_live = ttl,
alignment = alignment,
draw_on_ground = false }
local rid = render_object.id
table.insert(storage.oarc_renders_fadeout, rid)
end
@ -121,12 +122,13 @@ end
function FadeoutRenderOnTick()
if (storage.oarc_renders_fadeout and (#storage.oarc_renders_fadeout > 0)) then
for k, rid in pairs(storage.oarc_renders_fadeout) do
if (rendering.is_valid(rid)) then
local ttl = rendering.get_time_to_live(rid)
local render_object = rendering.get_object_by_id(rid)
if (render_object and render_object.valid) then
local ttl = render_object.time_to_live
if ((ttl > 0) and (ttl < 200)) then
local color = rendering.get_color(rid)
local color = render_object.color
if (color.a > 0.005) then
rendering.set_color(rid, { r = color.r, g = color.g, b = color.b, a = color.a - 0.005 })
render_object.color = { r = color.r, g = color.g, b = color.b, a = color.a - 0.005 }
end
end
else
@ -372,7 +374,7 @@ end
---@return nil
function OarcsSaferInsert(entity, item_dict)
if not (entity and entity.valid and item_dict) then return end
local items = game.item_prototypes
local items = prototypes.item
local insert = entity.insert
for name, count in pairs(item_dict) do
if items[name] and count > 0 then
@ -389,7 +391,7 @@ end
---@return nil
function OarcsSaferRemove(entity, item_dict)
if not (entity and entity.valid and item_dict) then return end
local items = game.item_prototypes
local items = prototypes.item
local remove = entity.remove_item
for name, count in pairs(item_dict) do
if items[name] and count > 0 then
@ -1374,7 +1376,7 @@ function CreateCropCircle(surface, centerPos, chunkArea, tileRadius, fillTile, m
-- Fill in all unexpected water (or force grass)
if (distSqr <= tile_radius_sqr) then
if (surface.get_tile(i, j).collides_with("water-tile") or
if (surface.get_tile(i, j).collides_with("water_tile") or
storage.ocfg.spawn_general.force_grass) then
table.insert(dirtTiles, { name = fillTile, position = { i, j } })
end
@ -1442,7 +1444,7 @@ function CreateCropOctagon(surface, centerPos, chunkArea, tileRadius, fillTile,
-- Fill in all unexpected water (or force grass)
if (distVar <= tileRadius) then
if (surface.get_tile(i, j).collides_with("water-tile") or
if (surface.get_tile(i, j).collides_with("water_tile") or
storage.ocfg.spawn_general.force_grass) then
table.insert(dirtTiles, { name = fillTile, position = { i, j } })
end
@ -1511,7 +1513,7 @@ function CreateCropSquare(surface, centerPos, chunkArea, tileRadius, fillTile, m
-- Fill in all unexpected water (or force grass)
if (max_distance <= tileRadius) then
if (surface.get_tile(i, j).collides_with("water-tile") or
if (surface.get_tile(i, j).collides_with("water_tile") or
storage.ocfg.spawn_general.force_grass) then
table.insert(dirtTiles, { name = fillTile, position = { i, j } })
end

View File

@ -371,7 +371,7 @@ function RegrowthSectorScan(event)
if (storage.rg[surface_name] == nil) then return end
---@type integer
local radar_range = event.radar.prototype.max_distance_of_nearby_sector_revealed --TODO: Space age quality might affect this?
local radar_range = event.radar.prototype.get_max_distance_of_nearby_sector_revealed(event.radar.quality) --TODO: Space age quality might affect this?
RefreshAreaChunkPosition(surface_name, event.chunk_position, radar_range, 0)
end
@ -694,7 +694,7 @@ function RegrowthOnBuiltEntity(event)
log("Added spidertron to regrowth tracking")
if storage.rg.spidertron_chunk_radius == nil then
storage.rg.spidertron_chunk_radius = game.entity_prototypes["spidertron"].chunk_exploration_radius
storage.rg.spidertron_chunk_radius = prototypes.entity["spidertron"].chunk_exploration_radius
end
end
end

View File

@ -236,6 +236,9 @@ end
---@param event EventData.on_player_changed_surface
---@return nil
function SeparateSpawnsPlayerChangedSurface(event)
log("SeparateSpawnsPlayerChangedSurface - " .. event.surface_index)
if (not storage.ocfg.gameplay.enable_secondary_spawns) then return end
local player = game.players[event.player_index]
@ -453,7 +456,7 @@ function SendPlayerToNewSpawnAndCreateIt(delayed_spawn)
}
-- Create shared power poles
if (ocfg.gameplay.enable_shared_power) then
if (ocfg.gameplay.enable_shared_power and delayed_spawn.primary) then
local power_pole_position = {
x = sharing_ref_pos.x + spawn_config.shared_power_pole_position.x_offset,
y = sharing_ref_pos.y + spawn_config.shared_power_pole_position.y_offset }
@ -461,7 +464,7 @@ function SendPlayerToNewSpawnAndCreateIt(delayed_spawn)
end
-- Create shared chest
if (ocfg.gameplay.enable_shared_chest) then
if (ocfg.gameplay.enable_shared_chest and delayed_spawn.primary) then
local chest_position = {
x = sharing_ref_pos.x + spawn_config.shared_chest_position.x_offset,
y = sharing_ref_pos.y + spawn_config.shared_chest_position.y_offset }
@ -501,7 +504,7 @@ function DisplayWelcomeGroundTextAtSpawn(player, surface, position)
-- Render some welcoming text...
local tcolor = { 0.9, 0.7, 0.3, 0.8 }
local ttl = 2000
local rid1 = rendering.draw_text { text = "Welcome",
local render_object_1 = rendering.draw_text { text = "Welcome",
surface = surface,
target = { x = position.x - 21, y = position.y - 15 },
color = tcolor,
@ -514,7 +517,7 @@ function DisplayWelcomeGroundTextAtSpawn(player, surface, position)
-- alignment=center,
scale_with_zoom = false,
only_in_alt_mode = false }
local rid2 = rendering.draw_text { text = "Home",
local render_object_2 = rendering.draw_text { text = "Home",
surface = surface,
target = { x = position.x - 14, y = position.y - 5 },
color = tcolor,
@ -527,6 +530,8 @@ function DisplayWelcomeGroundTextAtSpawn(player, surface, position)
-- alignment=center,
scale_with_zoom = false,
only_in_alt_mode = false }
local rid1 = render_object_1.id
local rid2 = render_object_2.id
table.insert(storage.oarc_renders_fadeout, rid1)
table.insert(storage.oarc_renders_fadeout, rid2)
@ -1241,15 +1246,16 @@ function QueuePlayerForDelayedSpawn(player_name, surface, spawn_position, moat_e
final_chunk.y = final_chunk.y + spawn_chunk_radius
---@type OarcDelayedSpawn
local delayedSpawn = {}
delayedSpawn.playerName = player_name
delayedSpawn.surface = surface
delayedSpawn.position = spawn_position
delayedSpawn.moat = moat_enabled
delayedSpawn.delayedTick = game.tick + delay_spawn_seconds * TICKS_PER_SECOND
delayedSpawn.final_chunk_generated = final_chunk
local delayed_spawn = {}
delayed_spawn.playerName = player_name
delayed_spawn.surface = surface
delayed_spawn.position = spawn_position
delayed_spawn.moat = moat_enabled
delayed_spawn.delayedTick = game.tick + delay_spawn_seconds * TICKS_PER_SECOND
delayed_spawn.final_chunk_generated = final_chunk
delayed_spawn.primary = primary
table.insert(storage.delayed_spawns, delayedSpawn)
table.insert(storage.delayed_spawns, delayed_spawn)
HideOarcGui(game.players[player_name])
DisplayPleaseWaitForSpawnDialog(game.players[player_name], delay_spawn_seconds, game.surfaces[surface], spawn_position)
@ -1259,7 +1265,7 @@ function QueuePlayerForDelayedSpawn(player_name, surface, spawn_position, moat_e
-- Chart the area to be able to display the minimap while the player waits.
ChartArea(game.players[player_name].force,
delayedSpawn.position,
delayed_spawn.position,
spawn_chunk_radius,
surface
)
@ -1434,7 +1440,6 @@ function CreatePlayerForce(force_name)
new_force = game.create_force(force_name)
new_force.share_chart = storage.ocfg.gameplay.enable_shared_team_vision
new_force.friendly_fire = storage.ocfg.gameplay.enable_friendly_fire
new_force.research_queue_enabled = true
-- SetCeaseFireBetweenAllPlayerForces()
-- SetFriendlyBetweenAllPlayerForces()
ConfigurePlayerForceRelationships(true, true)
@ -1508,7 +1513,15 @@ SPAWN_TEAM_CHOICE = {
---@alias OarcPlayerCooldownsTable table<string, OarcPlayerCooldown>
---Temporary data used when spawning a player. Player needs to wait while the area is prepared.
---@alias OarcDelayedSpawn { surface: string, playerName: string, position: MapPosition, moat: boolean, delayedTick: number, final_chunk_generated: ChunkPosition }
---Temporary data used when spawning a player. Player needs to wait while the area is prepared.
---@class OarcDelayedSpawn
---@field surface string The surface on which the player will spawn.
---@field playerName string The name of the player.
---@field position MapPosition The position where the player will spawn.
---@field moat boolean Whether the spawn has a moat or not.
---@field delayedTick number The game tick when the spawn will be ready.
---@field final_chunk_generated ChunkPosition The final chunk position that needs to be generated.
---@field primary boolean Whether this is the primary spawn point for a player, this is the first surface they spawn on. All other spawns are secondary.
---Table of [OarcDelayedSpawn](lua://OarcDelayedSpawn) indexed by player name.
---@alias OarcDelayedSpawnsTable table<string, OarcDelayedSpawn>

View File

@ -58,8 +58,9 @@ function DisplayWelcomeTextGui(player)
local dragger = button_flow.add {
type = "empty-widget",
style = "draggable_space_with_no_left_margin",
style = "draggable_space",
}
dragger.style.left_margin = 0
dragger.style.horizontally_stretchable = true
dragger.style.height = 30
@ -117,9 +118,19 @@ function CreateSpawnMenuGuiFrame(player)
local subhead = inside_frame.add{
type="frame",
name="sub_header",
style = "changelog_subheader_frame"
style = "subheader_frame"
}
subhead.style.height = 46
subhead.style.horizontally_stretchable = true
-- changelog_subheader_frame =
-- {
-- type = "frame_style",
-- parent = "subheader_frame",
-- left_padding = 12,
-- right_padding = 12,
-- top_padding = 4,
-- horizontally_stretchable = "on"
-- }
AddLabel(subhead, "warning_lbl1", { "oarc-click-info-btn-help" }, my_note_style)
return inside_frame
@ -956,7 +967,8 @@ function DisplaySharedSpawnJoinWaitMenu(player)
style = "back_button"
}
local dragger = button_flow.add{type="empty-widget", style="draggable_space_with_no_right_margin"}
local dragger = button_flow.add{type="empty-widget", style="draggable_space"}
dragger.style.right_margin = 0
dragger.style.horizontally_stretchable = true
dragger.style.height = 30
end
@ -1009,7 +1021,8 @@ function DisplayBuddySpawnWaitMenu(player)
tooltip = { "oarc-return-to-previous-tooltip" },
}
local dragger = button_flow.add{type="empty-widget", style="draggable_space_with_no_right_margin"}
local dragger = button_flow.add{type="empty-widget", style="draggable_space"}
dragger.style.right_margin = 0
dragger.style.horizontally_stretchable = true
dragger.style.height = 30
end

View File

@ -1,9 +1,22 @@
-- This handles the shared power logic for the Oarc scenario.
-- Won't work too hard on this since 2.0 might change things...
-- Lets players share electricity via a special power pole and cross surface connections.
-- Also lets players share items via a linked-chest.
X_OFFSET_SHARING_POLE = 10
Y_OFFSET_SHARING_POLE = 0
STARTING_X_OFFSET_SHARING_POLE = -5
Y_OFFSET_SHARING_POLE = 20
function InitSharingPowerPoles()
if storage.shared_power_poles == nil then
---@type LuaEntity[]
storage.shared_power_poles = {}
end
if storage.shared_power_link == nil then
local link_position = { x = X_OFFSET_SHARING_POLE, y = Y_OFFSET_SHARING_POLE }
local link_pole = CreateSpecialPole(game.surfaces[HOLDING_PEN_SURFACE_NAME], link_position)
storage.shared_power_link = link_pole
end
end
---Create and connect a pair of power poles for a new base given surface and position.
---@param surface LuaSurface
@ -16,17 +29,10 @@ function CreateSharedPowerPolePair(surface, position)
storage.shared_power_poles = {}
end
--Get an open sharing pole from the holding pen surface if one exists, otherwise create a new one.
local hidden_pole = FindSharedPowerPole()
if not hidden_pole then
local poles_count = table_size(storage.shared_power_poles)
local new_position = { x = poles_count + STARTING_X_OFFSET_SHARING_POLE, y = Y_OFFSET_SHARING_POLE }
hidden_pole = CreateSpecialPole(game.surfaces[HOLDING_PEN_SURFACE_NAME], new_position)
if not hidden_pole then
log("ERROR - Failed to create shared power poles!? " .. serpent.block(position) .. " on " .. surface.name)
return
end
table.insert(storage.shared_power_poles, hidden_pole)
if storage.shared_power_link == nil then
local link_position = { x = X_OFFSET_SHARING_POLE, y = Y_OFFSET_SHARING_POLE }
local link_pole = CreateSpecialPole(game.surfaces[HOLDING_PEN_SURFACE_NAME], link_position)
storage.shared_power_link = link_pole
end
--Create the base pole on the new spawn area surface and connect it to the hidden pole.
@ -35,7 +41,9 @@ function CreateSharedPowerPolePair(surface, position)
log("ERROR - Failed to create shared power poles!? " .. serpent.block(position) .. " on " .. surface.name)
return
end
base_pole.connect_neighbour(hidden_pole)
local base_connector = base_pole.get_wire_connector(defines.wire_connector_id.pole_copper, true)
local hidden_connector = storage.shared_power_link.get_wire_connector(defines.wire_connector_id.pole_copper, true)
base_connector.connect_to(hidden_connector, false, defines.wire_origin.script)
TemporaryHelperText(
{ "oarc-shared-power-pole-helper-txt" },
@ -46,21 +54,6 @@ function CreateSharedPowerPolePair(surface, position)
)
end
---Find the first shared power pole that doesn't exceed the max number of connections.
---@return LuaEntity?
function FindSharedPowerPole()
if storage.shared_power_poles == nil then return nil end
for _,pole in pairs(storage.shared_power_poles) do
-- 5 is the hard coded engine limit and we need to leave one open for the connection to the next hidden pole.
if pole.neighbours["copper"] and table_size(pole.neighbours["copper"]) < 4 then
return pole
end
end
return nil
end
---Creates a special pole on the surface at the given position on the neutral force.
---@param surface LuaSurface
---@param position MapPosition

View File

@ -1,5 +1,7 @@
scenario-name=OARC
oarc-holding-pen-surface=[img=oarc-mod-sprite-40] New Player Holding Area
description=This mod provides a scenario that overhauls multiplayer spawning.\n[color=red][font=default-bold]Please check out the github page and discord for more information and support.[/font][/color]
oarc-scenario-info-warn-msg=This scenario allows players to create their own spawn points far from the center of the map. For more information, click the OARC button in the top left corner.