mirror of
https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git
synced 2024-12-04 09:43:00 +02:00
First empty commit for V2.
This commit is contained in:
parent
5bc032dfb3
commit
7b2b26a330
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
||||
config.lua
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Oarcinae
|
||||
Copyright (c) 2024 Oarcinae
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
19
README.md
19
README.md
@ -1,22 +1,25 @@
|
||||
# FactorioScenarioMultiplayerSpawn
|
||||
A custom scenario for allowing separate spawn locations in multiplayer. Designed for Co-op and PvE.
|
||||
|
||||
## WORK IN PROGRESS
|
||||
This is the currently in development branch for Factorio V2.0. It is not yet complete. If you want a stable version, please use the latest release.
|
||||
|
||||
## Read the WIKI
|
||||
The github wiki page will have the most up to date information. If you have questions, go there first, otherwise just ask.
|
||||
|
||||
## Versions
|
||||
Check releases for stable versions. 0.17 and 0.16 have final stable versions that will no longer be maintained.
|
||||
The latest master is for 1.0.0+
|
||||
Check releases for stable versions.
|
||||
2.0.X WILL BE the currently in work version that will support Factorio V2.0 with and without the Space Age expansion.
|
||||
1.1.X is the latest stable version for V1.0 that I plan to do minimal maintaince on.
|
||||
0.17 and 0.16 have final stable versions that will no longer be maintained.
|
||||
|
||||
## Status
|
||||
At this time I have no more planned features and will only be in support and maintenance mode.
|
||||
Currently working on adding support for V2.0 Factorio.
|
||||
Will be removing many of the soft-mod features and other feature creep things for the first version.
|
||||
|
||||
## Credit
|
||||
Several other portions of the code (tags, frontier style rocket silo) have also been adapted from other scenario code.
|
||||
|
||||
Credit to 3Ra for help as well: https://github.com/3RaGaming
|
||||
|
||||
Praise be to Mylon
|
||||
Thanks to https://github.com/vfinn (JustGoFly) and many others for their assistance!
|
||||
https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn/graphs/contributors
|
||||
|
||||
## Random Notes
|
||||
Feel free to submit bugs/fixes/requests/pulls/forks whatever you want.
|
||||
|
@ -1,14 +0,0 @@
|
||||
Compat = Compat or {}
|
||||
|
||||
|
||||
function Compat.handle_factoriomaps()
|
||||
if remote.interfaces.factoriomaps then
|
||||
script.on_event(remote.call("factoriomaps", "get_start_capture_event_id"), function()
|
||||
|
||||
print("Starting factoriomaps-oarc integration script")
|
||||
|
||||
remote.call("factoriomaps", "surface_set_default", "oarc")
|
||||
|
||||
end)
|
||||
end
|
||||
end
|
451
control.lua
451
control.lua
@ -1,451 +0,0 @@
|
||||
-- control.lua
|
||||
-- Mar 2019
|
||||
|
||||
-- Oarc's Separated Spawn Scenario
|
||||
--
|
||||
-- I wanted to create a scenario that allows you to spawn in separate locations
|
||||
-- From there, I ended up adding a bunch of other minor/major features
|
||||
--
|
||||
-- Credit:
|
||||
-- Tags - Taken from WOGs scenario
|
||||
-- Rocket Silo - Taken from Frontier as an idea
|
||||
--
|
||||
-- Feel free to re-use anything you want. It would be nice to give me credit
|
||||
-- if you can.
|
||||
|
||||
|
||||
|
||||
-- To keep the scenario more manageable (for myself) I have done the following:
|
||||
-- 1. Keep all event calls in control.lua (here)
|
||||
-- 2. Put all config options in config.lua and provided an example-config.lua file too.
|
||||
-- 3. Put other stuff into their own files where possible.
|
||||
-- 4. Put all other files into lib folder
|
||||
-- 5. Provided an examples folder for example/recommended map gen settings
|
||||
|
||||
-- Generic Utility Includes
|
||||
require("lib/oarc_utils")
|
||||
|
||||
-- Other soft-mod type features.
|
||||
require("lib/frontier_silo")
|
||||
require("lib/tag")
|
||||
require("lib/game_opts")
|
||||
require("lib/player_list")
|
||||
require("lib/rocket_launch")
|
||||
require("lib/admin_commands")
|
||||
require("lib/regrowth_map")
|
||||
require("lib/shared_chests")
|
||||
require("lib/notepad")
|
||||
require("lib/map_features")
|
||||
require("lib/oarc_buy")
|
||||
require("lib/auto_decon_miners")
|
||||
|
||||
-- For Philip. I currently do not use this and need to add proper support for
|
||||
-- commands like this in the future.
|
||||
-- require("lib/rgcommand")
|
||||
-- require("lib/helper_commands")
|
||||
|
||||
-- Main Configuration File
|
||||
require("config")
|
||||
|
||||
-- Save all config settings to global table.
|
||||
require("lib/oarc_global_cfg.lua")
|
||||
|
||||
-- Scenario Specific Includes
|
||||
require("lib/separate_spawns")
|
||||
require("lib/separate_spawns_guis")
|
||||
require("lib/oarc_enemies")
|
||||
require("lib/oarc_gui_tabs")
|
||||
|
||||
-- compatibility with mods
|
||||
require("compat/factoriomaps")
|
||||
|
||||
-- Create a new surface so we can modify map settings at the start.
|
||||
GAME_SURFACE_NAME="oarc"
|
||||
|
||||
commands.add_command("trigger-map-cleanup",
|
||||
"Force immediate removal of all expired chunks (unused chunk removal mod)",
|
||||
RegrowthForceRemoveChunksCmd)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- ALL EVENT HANLDERS ARE HERE IN ONE PLACE!
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
----------------------------------------
|
||||
-- On Init - only runs once the first
|
||||
-- time the game starts
|
||||
----------------------------------------
|
||||
script.on_init(function(event)
|
||||
|
||||
-- FIRST
|
||||
InitOarcConfig()
|
||||
|
||||
-- Regrowth (always init so we can enable during play.)
|
||||
RegrowthInit()
|
||||
|
||||
-- Create new game surface
|
||||
CreateGameSurface()
|
||||
|
||||
-- MUST be before other stuff, but after surface creation.
|
||||
InitSpawnGlobalsAndForces()
|
||||
|
||||
-- Frontier Silo Area Generation
|
||||
if (global.ocfg.frontier_rocket_silo and not global.ocfg.enable_magic_factories) then
|
||||
SpawnSilosAndGenerateSiloAreas()
|
||||
end
|
||||
|
||||
-- Everyone do the shuffle. Helps avoid always starting at the same location.
|
||||
-- Needs to be done after the silo spawning.
|
||||
if (global.ocfg.enable_vanilla_spawns) then
|
||||
global.vanillaSpawns = FYShuffle(global.vanillaSpawns)
|
||||
log("Vanilla spawns:")
|
||||
log(serpent.block(global.vanillaSpawns))
|
||||
end
|
||||
|
||||
Compat.handle_factoriomaps()
|
||||
|
||||
if (global.ocfg.enable_coin_shop and global.ocfg.enable_chest_sharing) then
|
||||
SharedChestInitItems()
|
||||
end
|
||||
|
||||
if (global.ocfg.enable_coin_shop and global.ocfg.enable_magic_factories) then
|
||||
MagicFactoriesInit()
|
||||
end
|
||||
|
||||
OarcMapFeatureInitGlobalCounters()
|
||||
OarcAutoDeconOnInit()
|
||||
|
||||
-- Display starting point text as a display of dominance.
|
||||
RenderPermanentGroundText(game.surfaces[GAME_SURFACE_NAME], {x=-29,y=-30}, 40, "OARC", {0.9, 0.7, 0.3, 0.8})
|
||||
end)
|
||||
|
||||
script.on_load(function()
|
||||
Compat.handle_factoriomaps()
|
||||
end)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- Rocket launch event
|
||||
-- Used for end game win conditions / unlocking late game stuff
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_rocket_launched, function(event)
|
||||
RocketLaunchEvent(event)
|
||||
end)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- Chunk Generation
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_chunk_generated, function(event)
|
||||
|
||||
if (event.surface.name ~= GAME_SURFACE_NAME) then return end
|
||||
|
||||
if global.ocfg.enable_regrowth then
|
||||
RegrowthChunkGenerate(event)
|
||||
end
|
||||
|
||||
if global.ocfg.enable_undecorator then
|
||||
UndecorateOnChunkGenerate(event)
|
||||
end
|
||||
|
||||
SeparateSpawnsGenerateChunk(event)
|
||||
|
||||
CreateHoldingPen(event.surface, event.area)
|
||||
end)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- Gui Click
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_gui_click, function(event)
|
||||
|
||||
-- Don't interfere with other mod related stuff.
|
||||
if (event.element.get_mod() ~= nil) then return end
|
||||
|
||||
if global.ocfg.enable_tags then
|
||||
TagGuiClick(event)
|
||||
end
|
||||
|
||||
WelcomeTextGuiClick(event)
|
||||
SpawnOptsGuiClick(event)
|
||||
SpawnCtrlGuiClick(event)
|
||||
SharedSpwnOptsGuiClick(event)
|
||||
BuddySpawnOptsGuiClick(event)
|
||||
BuddySpawnWaitMenuClick(event)
|
||||
BuddySpawnRequestMenuClick(event)
|
||||
SharedSpawnJoinWaitMenuClick(event)
|
||||
|
||||
ClickOarcGuiButton(event)
|
||||
|
||||
if global.ocfg.enable_coin_shop then
|
||||
ClickOarcStoreButton(event)
|
||||
end
|
||||
|
||||
GameOptionsGuiClick(event)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_gui_checked_state_changed, function (event)
|
||||
SpawnOptsRadioSelect(event)
|
||||
SpawnCtrlGuiOptionsSelect(event)
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_gui_selected_tab_changed, function (event)
|
||||
TabChangeOarcGui(event)
|
||||
|
||||
if global.ocfg.enable_coin_shop then
|
||||
TabChangeOarcStore(event)
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- Player Events
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_player_joined_game, function(event)
|
||||
PlayerJoinedMessages(event)
|
||||
ServerWriteFile("player_events", game.players[event.player_index].name .. " joined the game." .. "\n")
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_player_created, function(event)
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
-- Move the player to the game surface immediately.
|
||||
player.teleport({x=0,y=0}, GAME_SURFACE_NAME)
|
||||
|
||||
if global.ocfg.enable_long_reach then
|
||||
GivePlayerLongReach(player)
|
||||
end
|
||||
|
||||
SeparateSpawnsPlayerCreated(event.player_index, true)
|
||||
|
||||
InitOarcGuiTabs(player)
|
||||
|
||||
if global.ocfg.enable_coin_shop then
|
||||
InitOarcStoreGuiTabs(player)
|
||||
end
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_player_respawned, function(event)
|
||||
SeparateSpawnsPlayerRespawned(event)
|
||||
|
||||
PlayerRespawnItems(event)
|
||||
|
||||
if global.ocfg.enable_long_reach then
|
||||
GivePlayerLongReach(game.players[event.player_index])
|
||||
end
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_player_left_game, function(event)
|
||||
ServerWriteFile("player_events", game.players[event.player_index].name .. " left the game." .. "\n")
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
-- If players leave early, say goodbye.
|
||||
if (player and (player.online_time < (global.ocfg.minimum_online_time * TICKS_PER_MINUTE))) then
|
||||
log("Player left early: " .. player.name)
|
||||
SendBroadcastMsg(player.name .. "'s base was marked for immediate clean up because they left within "..global.ocfg.minimum_online_time.." minutes of joining.")
|
||||
RemoveOrResetPlayer(player, true, true, true, true)
|
||||
end
|
||||
end)
|
||||
|
||||
-- script.on_event(defines.events.on_player_removed, function(event)
|
||||
-- Player is already deleted when this is called.
|
||||
-- end)
|
||||
|
||||
----------------------------------------
|
||||
-- On tick events. Stuff that needs to happen at regular intervals.
|
||||
-- Delayed events, delayed spawns, ...
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_tick, function(event)
|
||||
if global.ocfg.enable_regrowth then
|
||||
RegrowthOnTick()
|
||||
RegrowthForceRemovalOnTick()
|
||||
end
|
||||
|
||||
DelayedSpawnOnTick()
|
||||
|
||||
if global.ocfg.enable_chest_sharing then
|
||||
SharedChestsOnTick()
|
||||
end
|
||||
|
||||
if (global.ocfg.enable_chest_sharing and global.ocfg.enable_magic_factories) then
|
||||
MagicFactoriesOnTick()
|
||||
end
|
||||
|
||||
TimeoutSpeechBubblesOnTick()
|
||||
FadeoutRenderOnTick()
|
||||
|
||||
if global.ocfg.enable_miner_decon then
|
||||
OarcAutoDeconOnTick()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
script.on_event(defines.events.on_sector_scanned, function (event)
|
||||
if global.ocfg.enable_regrowth then
|
||||
RegrowthSectorScan(event)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- Various on "built" events
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_built_entity, function(event)
|
||||
if global.ocfg.enable_autofill then
|
||||
Autofill(event)
|
||||
end
|
||||
|
||||
if global.ocfg.enable_regrowth then
|
||||
if (event.created_entity.surface.name ~= GAME_SURFACE_NAME) then return end
|
||||
RegrowthMarkAreaSafeGivenTilePos(event.created_entity.position, 2, false)
|
||||
end
|
||||
|
||||
if global.ocfg.enable_anti_grief then
|
||||
SetItemBlueprintTimeToLive(event)
|
||||
end
|
||||
|
||||
if global.ocfg.frontier_rocket_silo then
|
||||
BuildSiloAttempt(event)
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_robot_built_entity, function (event)
|
||||
if global.ocfg.enable_regrowth then
|
||||
if (event.created_entity.surface.name ~= GAME_SURFACE_NAME) then return end
|
||||
RegrowthMarkAreaSafeGivenTilePos(event.created_entity.position, 2, false)
|
||||
end
|
||||
if global.ocfg.frontier_rocket_silo then
|
||||
BuildSiloAttempt(event)
|
||||
end
|
||||
end)
|
||||
|
||||
script.on_event(defines.events.on_player_built_tile, function (event)
|
||||
if global.ocfg.enable_regrowth then
|
||||
if (game.surfaces[event.surface_index].name ~= GAME_SURFACE_NAME) then return end
|
||||
|
||||
for k,v in pairs(event.tiles) do
|
||||
RegrowthMarkAreaSafeGivenTilePos(v.position, 2, false)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- On script_raised_built. This should help catch mods that
|
||||
-- place items that don't count as player_built and robot_built.
|
||||
-- Specifically FARL.
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.script_raised_built, function(event)
|
||||
if global.ocfg.enable_regrowth then
|
||||
if (event.entity.surface.name ~= GAME_SURFACE_NAME) then return end
|
||||
RegrowthMarkAreaSafeGivenTilePos(event.entity.position, 2, false)
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- Shared chat, so you don't have to type /s
|
||||
-- But you do lose your player colors across forces.
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_console_chat, function(event)
|
||||
if (event.player_index) then
|
||||
ServerWriteFile("server_chat", game.players[event.player_index].name .. ": " .. event.message .. "\n")
|
||||
end
|
||||
if (global.ocfg.enable_shared_chat) then
|
||||
if (event.player_index ~= nil) then
|
||||
ShareChatBetweenForces(game.players[event.player_index], event.message)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- On Research Finished
|
||||
-- This is where you can permanently remove researched techs
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_research_finished, function(event)
|
||||
|
||||
-- Never allows players to build rocket-silos in "frontier" mode.
|
||||
if global.ocfg.frontier_rocket_silo and not global.ocfg.frontier_allow_build then
|
||||
RemoveRecipe(event.research.force, "rocket-silo")
|
||||
end
|
||||
|
||||
if global.ocfg.lock_goodies_rocket_launch and
|
||||
(not global.ocore.satellite_sent or not global.ocore.satellite_sent[event.research.force.name]) then
|
||||
for _,v in ipairs(LOCKED_RECIPES) do
|
||||
RemoveRecipe(event.research.force, v.r)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- On Entity Spawned and On Biter Base Built
|
||||
-- This is where I modify biter spawning based on location and other factors.
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_entity_spawned, function(event)
|
||||
if (global.ocfg.modified_enemy_spawning) then
|
||||
ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
end
|
||||
end)
|
||||
script.on_event(defines.events.on_biter_base_built, function(event)
|
||||
if (global.ocfg.modified_enemy_spawning) then
|
||||
ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- On unit group finished gathering
|
||||
-- This is where I remove biter waves on offline players
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_unit_group_finished_gathering, function(event)
|
||||
if (global.ocfg.enable_offline_protect) then
|
||||
OarcModifyEnemyGroup(event.group)
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- On Corpse Timed Out
|
||||
-- Save player's stuff so they don't lose it if they can't get to the corpse fast enough.
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_character_corpse_expired, function(event)
|
||||
DropGravestoneChestFromCorpse(event.corpse)
|
||||
end)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- On Gui Text Change
|
||||
-- For capturing text entry.
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_gui_text_changed, function(event)
|
||||
NotepadOnGuiTextChange(event)
|
||||
end)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- On Gui Closed
|
||||
-- For capturing player escaping custom GUI so we can close it using ESC key.
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_gui_closed, function(event)
|
||||
OarcGuiOnGuiClosedEvent(event)
|
||||
if global.ocfg.enable_coin_shop then
|
||||
OarcStoreOnGuiClosedEvent(event)
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------------------------
|
||||
-- On enemies killed
|
||||
-- For coin generation and stuff
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_post_entity_died, function(event)
|
||||
if (game.surfaces[event.surface_index].name ~= GAME_SURFACE_NAME) then return end
|
||||
if global.ocfg.enable_coin_shop then
|
||||
CoinsFromEnemiesOnPostEntityDied(event)
|
||||
end
|
||||
end,
|
||||
{{filter="type", type = "unit"}, {filter="type", type = "unit-spawner"}, {filter="type", type = "turret"}})
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- Scripted auto decon for miners...
|
||||
----------------------------------------
|
||||
script.on_event(defines.events.on_resource_depleted, function(event)
|
||||
if global.ocfg.enable_miner_decon then
|
||||
OarcAutoDeconOnResourceDepleted(event)
|
||||
end
|
||||
end)
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"order": "a",
|
||||
"multiplayer-compatible": true
|
||||
}
|
@ -1,473 +0,0 @@
|
||||
-- example-config.lua (Rename this file to config.lua to use it)
|
||||
-- May 26 2020 (updated on)
|
||||
-- Configuration Options
|
||||
--
|
||||
-- You should be safe to leave most of the settings here as defaults if you want.
|
||||
-- The only thing you definitely want to change are the welcome messages.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Messages
|
||||
-- You will want to change some of these to be your own.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- This stuff is shown in the welcome GUI and Info panel. Make sure it's valid.
|
||||
WELCOME_MSG_TITLE = "[INSERT SERVER OWNER MSG HERE test title!]"
|
||||
WELCOME_MSG = "[INSERT SERVER OWNER MSG HERE test msg!]" -- Printed to player on join as well.
|
||||
SERVER_MSG = "Rules: Be polite. Ask before changing other players's stuff. Have fun!\n"..
|
||||
"This server is running a custom scenario that allows individual starting areas on the map."
|
||||
|
||||
SCENARIO_INFO_MSG = "Latest updates in this scenario version:\n"..
|
||||
"Item & energy sharing system! No attacks on your base while you are offline!\n"..
|
||||
"This scenario gives you and/or your friends your own starting area.\n"..
|
||||
"You can be on the main team or your own. All teams are friendly.\n"..
|
||||
"If you leave in the first 15 minutes, your base and character will be deleted!"
|
||||
|
||||
CONTACT_MSG = "Contact: SteamID:Oarc | oarcinae@gmail.com | Discord:Oarc#8695"
|
||||
DISCORD_INV = "discord.gg/trnpcen"
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Module Enables
|
||||
-- Each of the following things enable special features. These can't be changed once the game starts.
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This allows 2 players to spawn next to each other in the wilderness, each with their own starting point. It adds more
|
||||
-- GUI selection options.
|
||||
ENABLE_BUDDY_SPAWN = true
|
||||
|
||||
-- Frontier style rocket silo mode. This means you can't build silos, but some spawn out in the wild for you to use.
|
||||
-- if ENABLE_MAGIC_FACTORIES=false, you will find a few special areas to launch rockets from.
|
||||
-- If ENABLE_MAGIC_FACTORIES=true, you must buy a silo at one of the special chunks.
|
||||
FRONTIER_ROCKET_SILO_MODE = true
|
||||
|
||||
-- Enable Undecorator. Removes decorative items to reduce save file size.
|
||||
ENABLE_UNDECORATOR = true
|
||||
|
||||
-- Enable Tags (Players can add a name-tag to explain what type of role they are doing if they want.)
|
||||
ENABLE_TAGS = true
|
||||
|
||||
-- Enable Long Reach
|
||||
ENABLE_LONGREACH = true
|
||||
|
||||
-- Enable Autofill (My autofill is very simplistic, if you are using a similar mod disable this!)
|
||||
ENABLE_AUTOFILL = true
|
||||
|
||||
-- Enable auto decon of miners (My miner decon is very simplistic, if you are using a similar mod disable this!)
|
||||
ENABLE_MINER_AUTODECON = true
|
||||
|
||||
-- Enable Playerlist
|
||||
ENABLE_PLAYER_LIST = true
|
||||
PLAYER_LIST_OFFLINE_PLAYERS = true -- List offline players as well.
|
||||
|
||||
-- Enable shared vision between teams (all teams are COOP regardless)
|
||||
ENABLE_SHARED_TEAM_VISION = true
|
||||
|
||||
-- Cleans up unused chunks periodically. Helps keep map size down.
|
||||
ENABLE_REGROWTH = true
|
||||
-- This removes player bases when they leave shortly after joining. Only works if you have regrowth enabled!
|
||||
ENABLE_ABANDONED_BASE_REMOVAL = true
|
||||
|
||||
-- Enable the research queue by default for all forces.
|
||||
ENABLE_RESEARCH_QUEUE = true
|
||||
|
||||
-- This enables coin drops from enemies and a shop (GUI) to buy stuff from.
|
||||
ENABLE_COIN_SHOP = false
|
||||
|
||||
-- Enable item & energy sharing system.
|
||||
ENABLE_ITEM_AND_ENERGY_SHARING = false -- REQUIRES ENABLE_COIN_SHOP=true!
|
||||
|
||||
-- Enable magic chunks around the map that let you buy powerful factories that smelt/assemble/process very very quickly.
|
||||
ENABLE_MAGIC_FACTORIES = false -- REQUIRES ENABLE_COIN_SHOP=true!
|
||||
|
||||
-- This inhibits enemy attacks on bases where all players are offline.
|
||||
-- Not 100% guaranteed.
|
||||
ENABLE_OFFLINE_PROTECTION = true
|
||||
|
||||
-- This allows you to set the tech price multiplier for the game, but
|
||||
-- have it only affect the main force. We just pad all non-main forces lab prod bonus.
|
||||
-- This has no effect unless the tech multiplier is more than 1!
|
||||
ENABLE_FORCE_LAB_PROD_BONUS = true
|
||||
|
||||
-- Lock various recipes and technologies behind a rocket launch.
|
||||
-- Each team/force must launch their own rocket to unlock this!
|
||||
LOCK_GOODIES_UNTIL_ROCKET_LAUNCH = true
|
||||
LOCKED_TECHNOLOGIES = {
|
||||
{t="atomic-bomb"},{t="power-armor-mk2"},{t="artillery"},{t="spidertron"}
|
||||
}
|
||||
LOCKED_RECIPES = {
|
||||
{r="productivity-module-3"},{r="speed-module-3"}
|
||||
}
|
||||
|
||||
-- Give cheaty items on start.
|
||||
ENABLE_POWER_ARMOR_QUICK_START = false
|
||||
ENABLE_MODULAR_ARMOR_QUICK_START = false
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- MAP CONFIGURATION OPTIONS
|
||||
-- In past versions I had a way to config map settings here to be used for cmd
|
||||
-- line launching, but now you should just be using --map-gen-settings and
|
||||
-- --map-settings option since it works with --start-server-load-scenario
|
||||
-- Read the README.md file for instructions.
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This scales resources so that even if you spawn "far away" from the center
|
||||
-- of the map, resources near to your spawn point scale so you aren't
|
||||
-- surrounded by 100M patches or something. This is useful depending on what
|
||||
-- map gen settings you pick.
|
||||
SCALE_RESOURCES_AROUND_SPAWNS = true
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Alien Options
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- Adjust enemy spawning based on distance to spawns. All it does it make things
|
||||
-- more balanced based on your distance and makes the game a little easier.
|
||||
-- No behemoth worms everywhere just because you spawned far away.
|
||||
-- If you're trying out the vanilla spawning, you might want to disable this.
|
||||
OARC_MODIFIED_ENEMY_SPAWNING = true
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Starting Items
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Items provided to the player the first time they join
|
||||
PLAYER_SPAWN_START_ITEMS = {
|
||||
["pistol"]=1,
|
||||
["firearm-magazine"]=200,
|
||||
["iron-plate"]=100,
|
||||
["burner-mining-drill"] = 4,
|
||||
["stone-furnace"] = 4,
|
||||
["coal"] = 50,
|
||||
["stone"] = 50,
|
||||
|
||||
["coin"] = 2500, -- Don't give coins unless you have shared chests enabled.
|
||||
}
|
||||
|
||||
-- Items provided after EVERY respawn (disabled by default)
|
||||
PLAYER_RESPAWN_START_ITEMS = {
|
||||
-- ["pistol"]=1,
|
||||
-- ["firearm-magazine"]=100,
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Distance Options
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This is the radius, in chunks, that a spawn area is from any other generated
|
||||
-- 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!).
|
||||
CHECK_SPAWN_UNGENERATED_CHUNKS_RADIUS = 10
|
||||
|
||||
-- Near Distance in chunks
|
||||
-- When a player selects "near" spawn, they will be in or as close to this range as possible.
|
||||
NEAR_MIN_DIST = 50
|
||||
NEAR_MAX_DIST = 100
|
||||
|
||||
-- Far Distance in chunks
|
||||
-- When a player selects "far" spawn, they will be at least this distance away.
|
||||
FAR_MIN_DIST = 200
|
||||
FAR_MAX_DIST = 300
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Resource & Spawn Circle Options
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This is where you can modify what resources spawn, how much, where, etc.
|
||||
-- Once you have a config you like, it's a good idea to save it for later use
|
||||
-- so you don't lost it if you update the scenario.
|
||||
OARC_CFG = {
|
||||
|
||||
-- Misc spawn related config.
|
||||
gen_settings = {
|
||||
|
||||
-- THIS IS WHAT SETS THE SPAWN CIRCLE SIZE!
|
||||
-- Create a circle of land area for the spawn
|
||||
-- If you make this much bigger than a few chunks, good luck.
|
||||
land_area_tiles = CHUNK_SIZE*2,
|
||||
|
||||
-- Allow players to choose to spawn with a moat
|
||||
moat_choice_enabled = true,
|
||||
-- If there is a moat, this attempts to connect to land to avoid "turtling"
|
||||
moat_bridging = true,
|
||||
|
||||
-- If you change the spawn area size, you might have to adjust this as well
|
||||
moat_size_modifier = 1,
|
||||
|
||||
-- Start resource shape. true = circle, false = square.
|
||||
resources_circle_shape = true,
|
||||
|
||||
-- Force the land area circle at the spawn to be fully grass
|
||||
force_grass = true,
|
||||
|
||||
-- Spawn a circle/octagon of trees around the base outline.
|
||||
tree_circle = true,
|
||||
tree_octagon = false,
|
||||
|
||||
-- Add a crashed ship like a vanilla game (create_crash_site)
|
||||
-- Resources go in the ship itself. (5 slots)
|
||||
-- Wreakage is distributed in small pieces. (I recommend only 1 item type.)
|
||||
crashed_ship = true,
|
||||
crashed_ship_resources = {
|
||||
["electronic-circuit"] = 200,
|
||||
["iron-gear-wheel"] = 100,
|
||||
["copper-cable"] = 200,
|
||||
-- ["spidertron"] = 1,
|
||||
["steel-plate"] = 100
|
||||
},
|
||||
crashed_ship_wreakage = {
|
||||
["iron-plate"] = 100
|
||||
},
|
||||
},
|
||||
|
||||
-- Safe Spawn Area Options
|
||||
-- The default settings here are balanced for my recommended map gen settings (close to train world).
|
||||
safe_area =
|
||||
{
|
||||
-- Safe area has no aliens
|
||||
-- This is the radius in tiles of safe area.
|
||||
safe_radius = CHUNK_SIZE*6,
|
||||
|
||||
-- Warning area has significantly reduced aliens
|
||||
-- This is the radius in tiles of warning area.
|
||||
warn_radius = CHUNK_SIZE*12,
|
||||
|
||||
-- 1 : X (spawners alive : spawners destroyed) in this area
|
||||
warn_reduction = 20,
|
||||
|
||||
-- Danger area has slightly reduce aliens
|
||||
-- This is the radius in tiles of danger area.
|
||||
danger_radius = CHUNK_SIZE*32,
|
||||
|
||||
-- 1 : X (spawners alive : spawners destroyed) in this area
|
||||
danger_reduction = 5,
|
||||
},
|
||||
|
||||
-- Location of water strip (horizontal)
|
||||
water = {
|
||||
x_offset = -4,
|
||||
y_offset = -48,
|
||||
length = 8
|
||||
},
|
||||
|
||||
-- Handle placement of starting resources
|
||||
resource_rand_pos_settings =
|
||||
{
|
||||
-- Autoplace resources (randomly in circle)
|
||||
-- This will ignore the fixed x_offset/y_offset values in resource_tiles.
|
||||
-- Only works for resource_tiles at the moment, not oil patches/water.
|
||||
enabled = true,
|
||||
-- Distance from center of spawn that resources are placed.
|
||||
radius = 45,
|
||||
-- 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.
|
||||
-- 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.
|
||||
},
|
||||
|
||||
-- Resource tiles
|
||||
-- If you are running with mods like bobs/angels, you'll want to customize this.
|
||||
resource_tiles =
|
||||
{
|
||||
["iron-ore"] =
|
||||
{
|
||||
amount = 1500,
|
||||
size = 18,
|
||||
x_offset = -29,
|
||||
y_offset = 16
|
||||
},
|
||||
["copper-ore"] =
|
||||
{
|
||||
amount = 1200,
|
||||
size = 18,
|
||||
x_offset = -28,
|
||||
y_offset = -3
|
||||
},
|
||||
["stone"] =
|
||||
{
|
||||
amount = 1200,
|
||||
size = 16,
|
||||
x_offset = -27,
|
||||
y_offset = -34
|
||||
},
|
||||
["coal"] =
|
||||
{
|
||||
amount = 1200,
|
||||
size = 16,
|
||||
x_offset = -27,
|
||||
y_offset = -20
|
||||
}--,
|
||||
-- ["uranium-ore"] =
|
||||
-- {
|
||||
-- amount = 0,
|
||||
-- size = 0,
|
||||
-- x_offset = 17,
|
||||
-- y_offset = -34
|
||||
-- }
|
||||
|
||||
-- ####### Bobs + Angels #######
|
||||
-- DISABLE STARTING OIL PATCHES!
|
||||
-- Coal = coal
|
||||
-- Saphirite = angels-ore1
|
||||
-- Stiratite = angels-ore3
|
||||
-- Rubyte = angels-ore5
|
||||
-- Bobmonium = angels-ore6
|
||||
|
||||
-- ########## Bobs Ore ##########
|
||||
-- Iron = iron-ore
|
||||
-- Copper = copper-ore
|
||||
-- Coal = coal
|
||||
-- Stone = stone
|
||||
-- Tin = tin-ore
|
||||
-- Lead (Galena) = lead-ore
|
||||
|
||||
-- See https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn/issues/11#issuecomment-479724909
|
||||
-- for full examples.
|
||||
},
|
||||
|
||||
-- Special resource patches like oil
|
||||
resource_patches =
|
||||
{
|
||||
["crude-oil"] =
|
||||
{
|
||||
num_patches = 2,
|
||||
amount = 900000,
|
||||
x_offset_start = -3,
|
||||
y_offset_start = 48,
|
||||
x_offset_next = 6,
|
||||
y_offset_next = 0
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
---------------------------------------
|
||||
-- Other Forces/Teams Options
|
||||
---------------------------------------
|
||||
|
||||
-- Separate teams
|
||||
-- This allows you to join your own force/team. Everyone is still COOP/PvE, all
|
||||
-- teams are friendly and cease-fire.
|
||||
ENABLE_SEPARATE_TEAMS = true
|
||||
|
||||
-- Main force is what default players join
|
||||
MAIN_FORCE = "Main Force"
|
||||
|
||||
-- Enable if players can allow others to join their base.
|
||||
-- And specify how many including the host are allowed.
|
||||
ENABLE_SHARED_SPAWNS = true
|
||||
MAX_PLAYERS_AT_SHARED_SPAWN = 3
|
||||
|
||||
-- Share local team chat with all teams
|
||||
-- This makes it so you don't have to use /s
|
||||
-- But it also means you can't talk privately with your own team.
|
||||
ENABLE_SHARED_TEAM_CHAT = true
|
||||
|
||||
---------------------------------------
|
||||
-- Special Action Cooldowns
|
||||
---------------------------------------
|
||||
RESPAWN_COOLDOWN_IN_MINUTES = 15
|
||||
|
||||
-- Require playes to be online for at least X minutes
|
||||
-- Else their character is removed and their spawn point is freed up for use
|
||||
MIN_ONLINE_TIME_IN_MINUTES = 15
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Frontier Rocket Silo Options
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Number of silos found in the wild.
|
||||
-- These will spawn in a circle at given distance from the center of the map
|
||||
-- If you set this number too high, you'll have a lot of delay at the start of the game.
|
||||
SILO_NUM_SPAWNS = 5
|
||||
|
||||
-- How many chunks away from the center of the map should the silo be spawned
|
||||
SILO_CHUNK_DISTANCE = 200
|
||||
|
||||
-- If this is enabled, you get silos at the positions specified below.
|
||||
-- (The other settings above are ignored in this case.)
|
||||
SILO_FIXED_POSITION = false
|
||||
|
||||
-- If you want to set fixed spawn locations for some silos.
|
||||
SILO_POSITIONS = {{x = -1000, y = -1000},
|
||||
{x = -1000, y = 1000},
|
||||
{x = 1000, y = -1000},
|
||||
{x = 1000, y = 1000}}
|
||||
|
||||
-- Set this to false so that you have to search for the silo's.
|
||||
ENABLE_SILO_VISION = true
|
||||
|
||||
-- Add beacons around the silo (Philip's mod)
|
||||
ENABLE_SILO_BEACONS = false
|
||||
ENABLE_SILO_RADAR = false
|
||||
|
||||
-- Allow silos to be built by the player, but forces them to build in
|
||||
-- the fixed locations. If this is false, silos are built and assigned
|
||||
-- only to the main force. This can cause a problem for non main forces
|
||||
-- when playing with LOCK_GOODIES_UNTIL_ROCKET_LAUNCH enabled.
|
||||
ENABLE_SILO_PLAYER_BUILD = true
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Long Reach Options
|
||||
--------------------------------------------------------------------------------
|
||||
BUILD_DIST_BONUS = 64
|
||||
REACH_DIST_BONUS = BUILD_DIST_BONUS
|
||||
RESOURCE_DIST_BONUS = 2
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Autofill Options
|
||||
--------------------------------------------------------------------------------
|
||||
AUTOFILL_TURRET_AMMO_QUANTITY = 10
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- ANTI-Griefing stuff ( I don't personally maintain this as I don't care for it.)
|
||||
-- These things were added from other people's requests/changes and are disabled by default.
|
||||
--------------------------------------------------------------------------------
|
||||
-- Enable this to disable deconstructing from map view, and setting a time limit
|
||||
-- on ghost placements.
|
||||
ENABLE_ANTI_GRIEFING = false
|
||||
|
||||
-- Makes blueprint ghosts dissapear if they have been placed longer than this
|
||||
-- ONLY has an effect if ENABLE_ANTI_GRIEFING is true!
|
||||
GHOST_TIME_TO_LIVE = 10 * TICKS_PER_MINUTE
|
||||
|
||||
-- I like keeping this off... set to true if you want to shoot your own chests
|
||||
-- and stuff.
|
||||
ENABLE_FRIENDLY_FIRE = false
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- EXPERIMENTAL FEATURES
|
||||
-- The following things are not recommended unless you really know what you are doing and are okay with crashes and
|
||||
-- editing lua code.
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This turns on writing chat and certain events to specific files so that I can use that for discord integration. I
|
||||
-- suggest you leave this off unless you know what you are doing.
|
||||
ENABLE_SERVER_WRITE_FILES = false
|
||||
|
||||
-- Enable this to have a vanilla style starting spawn. This changes the experience pretty drastically. If you enable
|
||||
-- this, you will NOT get the option to spawn using the "pre-fab" fixed layout spawns. This is because the spawn types
|
||||
-- just don't balance well with each other.
|
||||
ENABLE_VANILLA_SPAWNS = false
|
||||
|
||||
-- Vanilla spawn point options (only applicable if ENABLE_VANILLA_SPAWNS is enabled.)
|
||||
|
||||
-- Num total spawns pre-assigned (minimum number)
|
||||
-- Points are in an even grid layout.
|
||||
VANILLA_SPAWN_COUNT = 60
|
||||
|
||||
-- Num tiles between each spawn. (I recommend at least 1000)
|
||||
VANILLA_SPAWN_SPACING = 2000
|
||||
|
||||
-- Silo Islands
|
||||
-- This options is only valid when used with ENABLE_VANILLA_SPAWNS and FRONTIER_ROCKET_SILO_MODE!
|
||||
-- This spreads out rocket silos on every OTHER island/vanilla spawn
|
||||
SILO_ISLANDS_MODE = false
|
||||
|
||||
-- This is part of regrowth, and if both are enabled, any chunks which aren't active and have no entities will
|
||||
-- eventually be deleted over time. DO NOT USE THIS WITH MODS!
|
||||
ENABLE_WORLD_EATER = false
|
@ -1,72 +0,0 @@
|
||||
{
|
||||
"_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": 0,
|
||||
"height": 0,
|
||||
|
||||
"_starting_area_comment": "Multiplier for 'biter free zone radius'",
|
||||
"starting_area": 1,
|
||||
|
||||
"peaceful_mode": false,
|
||||
|
||||
"autoplace_controls":
|
||||
{
|
||||
"coal" : {"frequency" : 0.20, "richness" : 10.00, "size" : 0.20},
|
||||
"iron-ore" : {"frequency" : 0.20, "richness" : 10.00, "size" : 0.20},
|
||||
"copper-ore" : {"frequency" : 0.20, "richness" : 10.00, "size" : 0.20},
|
||||
"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}
|
||||
},
|
||||
|
||||
"cliff_settings":
|
||||
{
|
||||
"_name_comment": "Name of the cliff prototype",
|
||||
"name": "cliff",
|
||||
|
||||
"_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,
|
||||
|
||||
"_richness_comment": "Multiplier for cliff continuity; 0 will result in no cliffs, 10 will make all cliff rows completely solid",
|
||||
"richness": 1
|
||||
},
|
||||
|
||||
"_property_expression_names_comment":
|
||||
[
|
||||
"Overrides for property value generators",
|
||||
"Elevation influences water and cliff placement.",
|
||||
"Leave it blank to get 'normal' terrain.",
|
||||
"Use '0_16-elevation' to reproduce terrain from 0.16.",
|
||||
"Use '0_17-island' to get an island.",
|
||||
"elevation'': ''0_17-island"
|
||||
],
|
||||
"property_expression_names":
|
||||
{
|
||||
"control-setting:aux:bias": "0.00",
|
||||
"control-setting:aux:frequency:multiplier": "1.00",
|
||||
"control-setting:moisture:bias": "0.00",
|
||||
"control-setting:moisture:frequency:multiplier": "1.00"
|
||||
},
|
||||
|
||||
"starting_points":
|
||||
[
|
||||
{"x": 0, "y": 0}
|
||||
],
|
||||
|
||||
"_seed_comment": "Use null for a random seed, number for a specific seed.",
|
||||
"seed": null
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
{
|
||||
"difficulty_settings":
|
||||
{
|
||||
"recipe_difficulty": 0,
|
||||
"technology_difficulty": 0,
|
||||
"technology_price_multiplier": 3,
|
||||
"research_queue_setting": "always"
|
||||
},
|
||||
"pollution":
|
||||
{
|
||||
"enabled": true,
|
||||
"_comment_min_to_diffuse_1": "these are values for 60 ticks (1 simulated second)",
|
||||
"_comment_min_to_diffuse_2": "amount that is diffused to neighboring chunk",
|
||||
"diffusion_ratio": 0.02,
|
||||
"min_to_diffuse": 15,
|
||||
"ageing": 1,
|
||||
"expected_max_per_chunk": 150,
|
||||
"min_to_show_per_chunk": 50,
|
||||
"min_pollution_to_damage_trees": 60,
|
||||
"pollution_with_max_forest_damage": 150,
|
||||
"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_evolution":
|
||||
{
|
||||
"enabled": true,
|
||||
"time_factor": 0.000000,
|
||||
"destroy_factor": 0.002,
|
||||
"pollution_factor": 0.0000002
|
||||
},
|
||||
"enemy_expansion":
|
||||
{
|
||||
"enabled": true,
|
||||
"min_base_spacing": 3,
|
||||
"max_expansion_distance": 10,
|
||||
"friendly_base_influence_radius": 2,
|
||||
"enemy_building_influence_radius": 2,
|
||||
"building_coefficient": 0.1,
|
||||
"other_base_coefficient": 2.0,
|
||||
"neighbouring_chunk_coefficient": 0.5,
|
||||
"neighbouring_base_chunk_coefficient": 0.4,
|
||||
"max_colliding_tiles_coefficient": 0.9,
|
||||
"settler_group_min_size": 5,
|
||||
"settler_group_max_size": 20,
|
||||
"min_expansion_cooldown": 14400,
|
||||
"max_expansion_cooldown": 108000
|
||||
},
|
||||
"unit_group":
|
||||
{
|
||||
"min_group_gathering_time": 3600,
|
||||
"max_group_gathering_time": 36000,
|
||||
"max_wait_time_for_late_members": 7200,
|
||||
"max_group_radius": 30.0,
|
||||
"min_group_radius": 5.0,
|
||||
"max_member_speedup_when_behind": 1.4,
|
||||
"max_member_slowdown_when_ahead": 0.6,
|
||||
"max_group_slowdown_factor": 0.3,
|
||||
"max_group_member_fallback_factor": 3,
|
||||
"member_disown_distance": 10,
|
||||
"tick_tolerance_when_member_arrives": 60,
|
||||
"max_gathering_unit_groups": 30,
|
||||
"max_unit_group_size": 200
|
||||
},
|
||||
"steering":
|
||||
{
|
||||
"default":
|
||||
{
|
||||
"radius": 1.2,
|
||||
"separation_force": 0.005,
|
||||
"separation_factor": 1.2,
|
||||
"force_unit_fuzzy_goto_behavior": false
|
||||
},
|
||||
"moving":
|
||||
{
|
||||
"radius": 3,
|
||||
"separation_force": 0.01,
|
||||
"separation_factor": 3,
|
||||
"force_unit_fuzzy_goto_behavior": false
|
||||
}
|
||||
},
|
||||
"path_finder":
|
||||
{
|
||||
"fwd2bwd_ratio": 5,
|
||||
"goal_pressure_ratio": 2,
|
||||
"max_steps_worked_per_tick": 100,
|
||||
"max_work_done_per_tick": 8000,
|
||||
"use_path_cache": true,
|
||||
"short_cache_size": 5,
|
||||
"long_cache_size": 25,
|
||||
"short_cache_min_cacheable_distance": 10,
|
||||
"short_cache_min_algo_steps_to_cache": 50,
|
||||
"long_cache_min_cacheable_distance": 30,
|
||||
"cache_max_connect_to_cache_steps_multiplier": 100,
|
||||
"cache_accept_path_start_distance_ratio": 0.2,
|
||||
"cache_accept_path_end_distance_ratio": 0.15,
|
||||
"negative_cache_accept_path_start_distance_ratio": 0.3,
|
||||
"negative_cache_accept_path_end_distance_ratio": 0.3,
|
||||
"cache_path_start_distance_rating_multiplier": 10,
|
||||
"cache_path_end_distance_rating_multiplier": 20,
|
||||
"stale_enemy_with_same_destination_collision_penalty": 30,
|
||||
"ignore_moving_enemy_collision_distance": 5,
|
||||
"enemy_with_different_destination_collision_penalty": 30,
|
||||
"general_entity_collision_penalty": 10,
|
||||
"general_entity_subsequent_collision_penalty": 3,
|
||||
"extended_collision_penalty": 3,
|
||||
"max_clients_to_accept_any_new_request": 10,
|
||||
"max_clients_to_accept_short_new_request": 100,
|
||||
"direct_distance_to_consider_short_request": 100,
|
||||
"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,
|
||||
"overload_levels": [0, 100, 500],
|
||||
"overload_multipliers": [2, 3, 4]
|
||||
},
|
||||
"max_failed_behavior_count": 3
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
-- admin_commands.lua
|
||||
-- May 2019
|
||||
--
|
||||
-- Yay, admin commands!
|
||||
|
||||
require("lib/oarc_utils")
|
||||
|
||||
-- name :: string: Name of the command.
|
||||
-- tick :: uint: Tick the command was used.
|
||||
-- player_index :: uint (optional): The player who used the command. It will be missing if run from the server console.
|
||||
-- parameter :: string (optional): The parameter passed after the command, separated from the command by 1 space.
|
||||
|
||||
-- Give yourself or another player, power armor
|
||||
commands.add_command("give-power-armor-kit", "give a start kit", function(command)
|
||||
|
||||
local player = game.players[command.player_index]
|
||||
local target = player
|
||||
|
||||
if player ~= nil and player.admin then
|
||||
if (command.parameter ~= nil) then
|
||||
if game.players[command.parameter] ~= nil then
|
||||
target = game.players[command.parameter]
|
||||
else
|
||||
target.print("Invalid player target. Double check the player name?")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
GiveQuickStartPowerArmor(target)
|
||||
player.print("Gave a powerstart kit to " .. target.name)
|
||||
target.print("You have been given a power armor starting kit!")
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
commands.add_command("give-test-kit", "give a start kit", function(command)
|
||||
|
||||
local player = game.players[command.player_index]
|
||||
local target = player
|
||||
|
||||
if player ~= nil and player.admin then
|
||||
if (command.parameter ~= nil) then
|
||||
if game.players[command.parameter] ~= nil then
|
||||
target = game.players[command.parameter]
|
||||
else
|
||||
target.print("Invalid player target. Double check the player name?")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
GiveTestKit(target)
|
||||
player.print("Gave a test kit to " .. target.name)
|
||||
target.print("You have been given a test kit!")
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
commands.add_command("load-quickbar", "Pre-load quickbar shortcuts", function(command)
|
||||
|
||||
local p = game.players[command.player_index]
|
||||
|
||||
-- 1st Row
|
||||
p.set_quick_bar_slot(1, "transport-belt");
|
||||
p.set_quick_bar_slot(2, "small-electric-pole");
|
||||
p.set_quick_bar_slot(3, "inserter");
|
||||
p.set_quick_bar_slot(4, "underground-belt");
|
||||
p.set_quick_bar_slot(5, "splitter");
|
||||
|
||||
p.set_quick_bar_slot(6, "coal");
|
||||
p.set_quick_bar_slot(7, "repair-pack");
|
||||
p.set_quick_bar_slot(8, "gun-turret");
|
||||
p.set_quick_bar_slot(9, "stone-wall");
|
||||
p.set_quick_bar_slot(10, "radar");
|
||||
|
||||
-- 2nd Row
|
||||
p.set_quick_bar_slot(11, "stone-furnace");
|
||||
p.set_quick_bar_slot(12, "wooden-chest");
|
||||
p.set_quick_bar_slot(13, "steel-chest");
|
||||
p.set_quick_bar_slot(14, "assembling-machine-1");
|
||||
p.set_quick_bar_slot(15, "assembling-machine-2");
|
||||
|
||||
p.set_quick_bar_slot(16, nil);
|
||||
p.set_quick_bar_slot(17, nil);
|
||||
p.set_quick_bar_slot(18, nil);
|
||||
p.set_quick_bar_slot(19, nil);
|
||||
p.set_quick_bar_slot(20, nil);
|
||||
|
||||
-- 3rd Row
|
||||
p.set_quick_bar_slot(21, "electric-mining-drill");
|
||||
p.set_quick_bar_slot(22, "fast-inserter");
|
||||
p.set_quick_bar_slot(23, "long-handed-inserter");
|
||||
p.set_quick_bar_slot(24, "medium-electric-pole");
|
||||
p.set_quick_bar_slot(25, "big-electric-pole");
|
||||
|
||||
p.set_quick_bar_slot(26, "stack-inserter");
|
||||
p.set_quick_bar_slot(27, nil);
|
||||
p.set_quick_bar_slot(28, nil);
|
||||
p.set_quick_bar_slot(29, nil);
|
||||
p.set_quick_bar_slot(30, nil);
|
||||
|
||||
-- 4th Row
|
||||
p.set_quick_bar_slot(31, "fast-transport-belt");
|
||||
p.set_quick_bar_slot(32, "medium-electric-pole");
|
||||
p.set_quick_bar_slot(33, "fast-inserter");
|
||||
p.set_quick_bar_slot(34, "fast-underground-belt");
|
||||
p.set_quick_bar_slot(35, "fast-splitter");
|
||||
|
||||
p.set_quick_bar_slot(36, "stone-wall");
|
||||
p.set_quick_bar_slot(37, "repair-pack");
|
||||
p.set_quick_bar_slot(38, "gun-turret");
|
||||
p.set_quick_bar_slot(39, "laser-turret");
|
||||
p.set_quick_bar_slot(40, "radar");
|
||||
|
||||
-- 5th Row
|
||||
p.set_quick_bar_slot(41, "train-stop");
|
||||
p.set_quick_bar_slot(42, "rail-signal");
|
||||
p.set_quick_bar_slot(43, "rail-chain-signal");
|
||||
p.set_quick_bar_slot(44, "rail");
|
||||
p.set_quick_bar_slot(45, "big-electric-pole");
|
||||
|
||||
p.set_quick_bar_slot(46, "locomotive");
|
||||
p.set_quick_bar_slot(47, "cargo-wagon");
|
||||
p.set_quick_bar_slot(48, "fluid-wagon");
|
||||
p.set_quick_bar_slot(49, "pump");
|
||||
p.set_quick_bar_slot(50, "storage-tank");
|
||||
|
||||
-- 6th Row
|
||||
p.set_quick_bar_slot(51, "oil-refinery");
|
||||
p.set_quick_bar_slot(52, "chemical-plant");
|
||||
p.set_quick_bar_slot(53, "storage-tank");
|
||||
p.set_quick_bar_slot(54, "pump");
|
||||
p.set_quick_bar_slot(55, nil);
|
||||
|
||||
p.set_quick_bar_slot(56, "pipe");
|
||||
p.set_quick_bar_slot(57, "pipe-to-ground");
|
||||
p.set_quick_bar_slot(58, "assembling-machine-2");
|
||||
p.set_quick_bar_slot(59, "pump");
|
||||
p.set_quick_bar_slot(60, nil);
|
||||
|
||||
-- 7th Row
|
||||
p.set_quick_bar_slot(61, "roboport");
|
||||
p.set_quick_bar_slot(62, "logistic-chest-storage");
|
||||
p.set_quick_bar_slot(63, "logistic-chest-passive-provider");
|
||||
p.set_quick_bar_slot(64, "logistic-chest-requester");
|
||||
p.set_quick_bar_slot(65, "logistic-chest-buffer");
|
||||
|
||||
p.set_quick_bar_slot(66, "logistic-chest-active-provider");
|
||||
p.set_quick_bar_slot(67, "logistic-robot");
|
||||
p.set_quick_bar_slot(68, "construction-robot");
|
||||
p.set_quick_bar_slot(69, nil);
|
||||
p.set_quick_bar_slot(70, nil);
|
||||
|
||||
end)
|
@ -1,43 +0,0 @@
|
||||
-- auto_decon_miners.lua
|
||||
-- May 2020
|
||||
-- My shitty softmod version which is buggy
|
||||
|
||||
function OarcAutoDeconOnInit(event)
|
||||
if (not global.oarc_decon_miners) then
|
||||
global.oarc_decon_miners = {}
|
||||
end
|
||||
end
|
||||
|
||||
function OarcAutoDeconOnTick()
|
||||
if (global.oarc_decon_miners and (#global.oarc_decon_miners > 0)) then
|
||||
for i,miner in pairs(global.oarc_decon_miners) do
|
||||
if ((not miner) or (not miner.valid)) then
|
||||
table.remove(global.oarc_decon_miners, i)
|
||||
|
||||
else
|
||||
if (#miner.surface.find_entities_filtered{area = {{miner.position.x-3, miner.position.y-3},
|
||||
{miner.position.x+3, miner.position.y+3}},
|
||||
type = "resource", limit = 1} == 0) then
|
||||
miner.order_deconstruction(miner.force)
|
||||
end
|
||||
table.remove(global.oarc_decon_miners, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function OarcAutoDeconOnResourceDepleted(event)
|
||||
if (not global.oarc_decon_miners) then
|
||||
global.oarc_decon_miners = {}
|
||||
end
|
||||
if (event.entity and event.entity.position and event.entity.surface) then
|
||||
|
||||
local nearby_miners = event.entity.surface.find_entities_filtered{area = {{event.entity.position.x-1, event.entity.position.y-1},
|
||||
{event.entity.position.x+1, event.entity.position.y+1}},
|
||||
name = {"burner-mining-drill", "electric-mining-drill"}}
|
||||
|
||||
for i,v in pairs(nearby_miners) do
|
||||
table.insert(global.oarc_decon_miners, v)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,401 +0,0 @@
|
||||
-- frontier_silo.lua
|
||||
-- Jan 2018
|
||||
-- My take on frontier silos for my Oarc scenario
|
||||
|
||||
require("config")
|
||||
require("lib/oarc_utils")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Frontier style rocket silo stuff
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function SpawnSilosAndGenerateSiloAreas()
|
||||
|
||||
-- Special silo islands mode "boogaloo"
|
||||
if (global.ocfg.silo_islands) then
|
||||
|
||||
local num_spawns = #global.vanillaSpawns
|
||||
local new_spawn_list = {}
|
||||
|
||||
-- Pick out every OTHER vanilla spawn for the rocket silos.
|
||||
for k,v in pairs(global.vanillaSpawns) do
|
||||
if ((k <= num_spawns/2) and (k%2==1)) then
|
||||
SetFixedSiloPosition({x=v.x,y=v.y})
|
||||
elseif ((k > num_spawns/2) and (k%2==0)) then
|
||||
SetFixedSiloPosition({x=v.x,y=v.y})
|
||||
else
|
||||
table.insert(new_spawn_list, v)
|
||||
end
|
||||
end
|
||||
global.vanillaSpawns = new_spawn_list
|
||||
|
||||
-- A set of fixed silo positions
|
||||
elseif (global.ocfg.frontier_fixed_pos) then
|
||||
for k,v in pairs(global.ocfg.frontier_pos_table) do
|
||||
SetFixedSiloPosition(v)
|
||||
end
|
||||
|
||||
-- Random locations on a circle.
|
||||
else
|
||||
SetRandomSiloPosition(global.ocfg.frontier_silo_count)
|
||||
|
||||
end
|
||||
|
||||
-- Freezes the game at the start to generate all the chunks.
|
||||
GenerateRocketSiloAreas(game.surfaces[GAME_SURFACE_NAME])
|
||||
end
|
||||
|
||||
-- This creates a random silo position, stored to global.siloPosition
|
||||
-- It uses the config setting global.ocfg.frontier_silo_distance and spawns the
|
||||
-- silo somewhere on a circle edge with radius using that distance.
|
||||
function SetRandomSiloPosition(num_silos)
|
||||
if (global.siloPosition == nil) then
|
||||
global.siloPosition = {}
|
||||
end
|
||||
|
||||
local random_angle_offset = math.random(0, math.pi * 2)
|
||||
|
||||
for i=1,num_silos do
|
||||
local theta = ((math.pi * 2) / num_silos);
|
||||
local angle = (theta * i) + random_angle_offset;
|
||||
|
||||
local tx = (global.ocfg.frontier_silo_distance*CHUNK_SIZE * math.cos(angle))
|
||||
local ty = (global.ocfg.frontier_silo_distance*CHUNK_SIZE * math.sin(angle))
|
||||
|
||||
-- Ensure it's centered around a chunk
|
||||
local tx = (tx - (tx % CHUNK_SIZE)) + CHUNK_SIZE/2
|
||||
local ty = (ty - (ty % CHUNK_SIZE)) + CHUNK_SIZE/2
|
||||
|
||||
table.insert(global.siloPosition, {x=math.floor(tx), y=math.floor(ty)})
|
||||
|
||||
log("Silo position: " .. tx .. ", " .. ty .. ", " .. angle)
|
||||
end
|
||||
end
|
||||
|
||||
-- Sets the global.siloPosition var to the set in the config file
|
||||
function SetFixedSiloPosition(pos)
|
||||
table.insert(global.siloPosition, pos)
|
||||
end
|
||||
|
||||
-- Create a rocket silo at the specified positionmmmm
|
||||
-- Also makes sure tiles and entities are cleared if required.
|
||||
local function CreateRocketSilo(surface, siloPosition, force)
|
||||
|
||||
-- Delete any entities beneath the silo?
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = {{siloPosition.x-5,
|
||||
siloPosition.y-6},
|
||||
{siloPosition.x+6,
|
||||
siloPosition.y+6}}}) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
-- Remove nearby enemies again
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = {{siloPosition.x-(CHUNK_SIZE*4),
|
||||
siloPosition.y-(CHUNK_SIZE*4)},
|
||||
{siloPosition.x+(CHUNK_SIZE*4),
|
||||
siloPosition.y+(CHUNK_SIZE*4)}}, force = "enemy"}) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
-- Set tiles below the silo
|
||||
tiles = {}
|
||||
for dx = -6,5 do
|
||||
for dy = -6,5 do
|
||||
if (game.active_mods["oarc-restricted-build"]) then
|
||||
table.insert(tiles, {name = global.ocfg.locked_build_area_tile,
|
||||
position = {siloPosition.x+dx, siloPosition.y+dy}})
|
||||
else
|
||||
if ((dx % 2 == 0) or (dx % 2 == 0)) then
|
||||
table.insert(tiles, {name = "concrete",
|
||||
position = {siloPosition.x+dx, siloPosition.y+dy}})
|
||||
else
|
||||
table.insert(tiles, {name = "hazard-concrete-left",
|
||||
position = {siloPosition.x+dx, siloPosition.y+dy}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles, true)
|
||||
|
||||
-- Create indestructible silo and assign to a force
|
||||
if not global.ocfg.frontier_allow_build then
|
||||
local silo = surface.create_entity{name = "rocket-silo", position = {siloPosition.x+0.5, siloPosition.y}, force = force}
|
||||
silo.destructible = false
|
||||
silo.minable = false
|
||||
end
|
||||
|
||||
-- TAG it on the main force at least.
|
||||
game.forces[global.ocfg.main_force].add_chart_tag(game.surfaces[GAME_SURFACE_NAME],
|
||||
{position=siloPosition, text="Rocket Silo",
|
||||
icon={type="item",name="rocket-silo"}})
|
||||
|
||||
-- Make silo safe from being removed.
|
||||
if global.ocfg.enable_regrowth then
|
||||
RegrowthMarkAreaSafeGivenTilePos(siloPosition, 5, true)
|
||||
end
|
||||
|
||||
if ENABLE_SILO_BEACONS then
|
||||
PhilipsBeacons(surface, siloPosition, game.forces[global.ocfg.main_force])
|
||||
end
|
||||
if ENABLE_SILO_RADAR then
|
||||
PhilipsRadar(surface, siloPosition, game.forces[global.ocfg.main_force])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Generates all rocket silos, should be called after the areas are generated
|
||||
-- Includes a crop circle
|
||||
function GenerateAllSilos()
|
||||
|
||||
-- Create each silo in the list
|
||||
for idx,siloPos in pairs(global.siloPosition) do
|
||||
CreateRocketSilo(game.surfaces[GAME_SURFACE_NAME], siloPos, global.ocfg.main_force)
|
||||
end
|
||||
end
|
||||
|
||||
-- Validates any attempt to build a silo.
|
||||
-- Should be call in on_built_entity and on_robot_built_entity
|
||||
function BuildSiloAttempt(event)
|
||||
|
||||
-- Validation
|
||||
if (event.created_entity == nil) then return end
|
||||
|
||||
local e_name = event.created_entity.name
|
||||
if (event.created_entity.name == "entity-ghost") then
|
||||
e_name =event.created_entity.ghost_name
|
||||
end
|
||||
|
||||
if (e_name ~= "rocket-silo") then return end
|
||||
|
||||
-- Check if it's in the right area.
|
||||
local epos = event.created_entity.position
|
||||
|
||||
for k,v in pairs(global.siloPosition) do
|
||||
if (getDistance(epos, v) <= 1) then
|
||||
if (event.created_entity.name ~= "entity-ghost") then
|
||||
SendBroadcastMsg("Rocket silo has been built!")
|
||||
end
|
||||
return -- THIS MEANS WE SUCCESFULLY BUILT THE SILO (ghost or actual building.)
|
||||
end
|
||||
end
|
||||
|
||||
-- If we get here, means it wasn't in a valid position. Need to remove it.
|
||||
if (event.created_entity.last_user ~= nil) then
|
||||
FlyingText("Can't build silo here! Check the map!", epos, my_color_red, event.created_entity.surface)
|
||||
if (event.created_entity.name == "entity-ghost") then
|
||||
event.created_entity.destroy()
|
||||
else
|
||||
event.created_entity.last_user.mine_entity(event.created_entity, true)
|
||||
end
|
||||
else
|
||||
log("ERROR! Rocket-silo had no valid last user?!?!")
|
||||
end
|
||||
end
|
||||
|
||||
-- Generate clean land and trees around silo area
|
||||
function GenerateRocketSiloChunks()
|
||||
|
||||
-- Silo generation can take awhile depending on the number of silos.
|
||||
-- if (game.tick < #global.siloPosition*10*TICKS_PER_SECOND) then
|
||||
local surface = game.surfaces[GAME_SURFACE_NAME]
|
||||
-- local chunkArea = event.area
|
||||
|
||||
-- local chunkAreaCenter = {x=chunkArea.left_top.x+(CHUNK_SIZE/2),
|
||||
-- y=chunkArea.left_top.y+(CHUNK_SIZE/2)}
|
||||
|
||||
for _,siloPos in pairs(global.siloPosition) do
|
||||
local siloArea = {left_top=
|
||||
{x=siloPos.x-(CHUNK_SIZE*2),
|
||||
y=siloPos.y-(CHUNK_SIZE*2)},
|
||||
right_bottom=
|
||||
{x=siloPos.x+(CHUNK_SIZE*2),
|
||||
y=siloPos.y+(CHUNK_SIZE*2)}}
|
||||
|
||||
|
||||
-- Clear enemies directly next to the rocket
|
||||
-- if CheckIfInArea(chunkAreaCenter,siloArea) then
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = siloArea, force = "enemy"}) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
-- Remove trees/resources inside the spawn area
|
||||
RemoveInCircle(surface, siloArea, "tree", siloPos, (CHUNK_SIZE*1.5)+5)
|
||||
RemoveInCircle(surface, siloArea, "resource", siloPos, (CHUNK_SIZE*1.5)+5)
|
||||
RemoveInCircle(surface, siloArea, "cliff", siloPos, (CHUNK_SIZE*1.5)+5)
|
||||
RemoveDecorationsArea(surface, siloArea)
|
||||
|
||||
-- Create rocket silo
|
||||
CreateCropOctagon(surface, siloPos, siloArea, (CHUNK_SIZE*1.5)+4, "landfill")
|
||||
-- end
|
||||
end
|
||||
-- end
|
||||
end
|
||||
|
||||
-- Generate chunks where we plan to place the rocket silos.
|
||||
function GenerateRocketSiloAreas(surface)
|
||||
for idx,siloPos in pairs(global.siloPosition) do
|
||||
surface.request_to_generate_chunks({siloPos.x, siloPos.y}, 1)
|
||||
end
|
||||
if (global.ocfg.frontier_silo_vision) then
|
||||
ChartRocketSiloAreas(surface, game.forces[global.ocfg.main_force])
|
||||
end
|
||||
|
||||
game.surfaces[GAME_SURFACE_NAME].force_generate_chunk_requests() -- Block and generate all to be sure.
|
||||
|
||||
GenerateRocketSiloChunks()
|
||||
GenerateAllSilos()
|
||||
end
|
||||
|
||||
-- Chart chunks where we plan to place the rocket silos.
|
||||
function ChartRocketSiloAreas(surface, force)
|
||||
for idx,siloPos in pairs(global.siloPosition) do
|
||||
force.chart(surface, {{siloPos.x-(CHUNK_SIZE*1),
|
||||
siloPos.y-(CHUNK_SIZE*1)},
|
||||
{siloPos.x+(CHUNK_SIZE*1),
|
||||
siloPos.y+(CHUNK_SIZE*1)}})
|
||||
end
|
||||
end
|
||||
|
||||
function PhilipsBeacons(surface, siloPos, force)
|
||||
|
||||
-- Add Beacons
|
||||
-- x = right, left; y = up, down
|
||||
-- top 1 left 1
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y-8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-5, siloPos.y-8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-2, siloPos.y-8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+2, siloPos.y-8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 5
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+5, siloPos.y-8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- top 6 right 1
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y-8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y-5}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y-2}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y+2}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 5
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y+5}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 6 bottom 1
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-8, siloPos.y+8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- left 7 bottom 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x-5, siloPos.y+8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 2
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y-5}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y-2}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y+2}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 5
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y+5}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 6 bottom 3
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+5, siloPos.y+8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- right 7 bottom 4
|
||||
local beacon = surface.create_entity{name = "beacon", position = {siloPos.x+8, siloPos.y+8}, force = force}
|
||||
beacon.destructible = false
|
||||
beacon.minable = false
|
||||
-- substations
|
||||
-- top left
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x-5, siloPos.y-5}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
-- top right
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x+6, siloPos.y-5}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
-- bottom left
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x-5, siloPos.y+6}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
-- bottom right
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x+6, siloPos.y+6}, force = force}
|
||||
substation.destructible = false
|
||||
substation.minable = false
|
||||
|
||||
-- end adding beacons
|
||||
end
|
||||
|
||||
function PhilipsRadar(surface, siloPos, force)
|
||||
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-43, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-43, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-40, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-37, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-34, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-34, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-34, siloPos.y}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-34, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-43, siloPos.y-6}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-40, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "solar-panel", position = {siloPos.x-37, siloPos.y+3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "radar", position = {siloPos.x-43, siloPos.y}, force = force}
|
||||
radar.destructible = false
|
||||
local substation = surface.create_entity{name = "substation", position = {siloPos.x-38, siloPos.y-1}, force = force}
|
||||
substation.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-40, siloPos.y-1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-40, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-40, siloPos.y+1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-38, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-38, siloPos.y+1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-36, siloPos.y-1}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-36, siloPos.y-3}, force = force}
|
||||
radar.destructible = false
|
||||
local radar = surface.create_entity{name = "accumulator", position = {siloPos.x-36, siloPos.y+1}, force = force}
|
||||
radar.destructible = false
|
||||
end
|
@ -1,160 +0,0 @@
|
||||
-- game_opts.lua
|
||||
-- Jan 2018
|
||||
-- Display current game options, maybe have some admin controls here
|
||||
|
||||
-- Main Configuration File
|
||||
require("config")
|
||||
require("lib/oarc_utils")
|
||||
require("lib/separate_spawns")
|
||||
|
||||
function GameOptionsGuiClick(event)
|
||||
if not (event and event.element and event.element.valid) then return end
|
||||
local player = game.players[event.player_index]
|
||||
local name = event.element.name
|
||||
|
||||
if (name == "ban_player") then
|
||||
local pIndex = event.element.parent.ban_players_dropdown.selected_index
|
||||
|
||||
if (pIndex ~= 0) then
|
||||
local banPlayer = event.element.parent.ban_players_dropdown.get_item(pIndex)
|
||||
if (game.players[banPlayer]) then
|
||||
game.ban_player(banPlayer, "Banned from admin panel.")
|
||||
log("Banning " .. banPlayer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (name == "restart_player") then
|
||||
local pIndex = event.element.parent.ban_players_dropdown.selected_index
|
||||
|
||||
if (pIndex ~= 0) then
|
||||
local resetPlayer = event.element.parent.ban_players_dropdown.get_item(pIndex)
|
||||
if (game.players[resetPlayer]) then
|
||||
RemoveOrResetPlayer(player, false, true, true, true)
|
||||
SeparateSpawnsPlayerCreated(resetPlayer, true)
|
||||
log("Resetting " .. resetPlayer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Used by AddOarcGuiTab
|
||||
function CreateGameOptionsTab(tab_container, player)
|
||||
|
||||
if global.oarc_announcements ~= nil then
|
||||
AddLabel(tab_container, "announcement_info_label", "Server announcements:", my_label_header_style)
|
||||
AddLabel(tab_container, "announcement_info_txt", global.oarc_announcements, my_longer_label_style)
|
||||
AddSpacerLine(tab_container)
|
||||
end
|
||||
|
||||
-- General Server Info:
|
||||
AddLabel(tab_container, "info_1", global.ocfg.welcome_msg, my_longer_label_style)
|
||||
AddLabel(tab_container, "info_2", global.ocfg.server_rules, my_longer_label_style)
|
||||
AddLabel(tab_container, "info_3", global.ocfg.server_contact, my_longer_label_style)
|
||||
tab_container.add{type="textfield",
|
||||
tooltip="Come join the discord (copy this invite)!",
|
||||
text=DISCORD_INV}
|
||||
AddSpacerLine(tab_container)
|
||||
|
||||
-- Enemy Settings:
|
||||
local enemy_expansion_txt = "disabled"
|
||||
if game.map_settings.enemy_expansion.enabled then enemy_expansion_txt = "enabled" end
|
||||
|
||||
local enemy_text="Server Run Time: " .. formattime_hours_mins(game.tick) .. "\n" ..
|
||||
"Current Evolution: " .. string.format("%.4f", game.forces["enemy"].evolution_factor) .. "\n" ..
|
||||
"Enemy evolution time/pollution/destroy factors: " .. game.map_settings.enemy_evolution.time_factor .. "/" ..
|
||||
game.map_settings.enemy_evolution.pollution_factor .. "/" ..
|
||||
game.map_settings.enemy_evolution.destroy_factor .. "\n" ..
|
||||
"Enemy expansion is " .. enemy_expansion_txt
|
||||
|
||||
AddLabel(tab_container, "enemy_info", enemy_text, my_longer_label_style)
|
||||
AddSpacerLine(tab_container)
|
||||
|
||||
-- Soft Mods:
|
||||
local soft_mods_string = "Oarc Core"
|
||||
if (global.ocfg.enable_undecorator) then
|
||||
soft_mods_string = soft_mods_string .. ", Undecorator"
|
||||
end
|
||||
if (global.ocfg.enable_tags) then
|
||||
soft_mods_string = soft_mods_string .. ", Tags"
|
||||
end
|
||||
if (global.ocfg.enable_long_reach) then
|
||||
soft_mods_string = soft_mods_string .. ", Long Reach"
|
||||
end
|
||||
if (global.ocfg.enable_autofill) then
|
||||
soft_mods_string = soft_mods_string .. ", Auto Fill"
|
||||
end
|
||||
if (global.ocfg.enable_player_list) then
|
||||
soft_mods_string = soft_mods_string .. ", Player List"
|
||||
end
|
||||
if (global.ocfg.enable_regrowth) then
|
||||
soft_mods_string = soft_mods_string .. ", Regrowth"
|
||||
end
|
||||
if (global.ocfg.enable_chest_sharing) then
|
||||
soft_mods_string = soft_mods_string .. ", Item & Energy Sharing"
|
||||
end
|
||||
if (global.ocfg.enable_magic_factories) then
|
||||
soft_mods_string = soft_mods_string .. ", Special Map Chunks"
|
||||
end
|
||||
if (global.ocfg.enable_offline_protect) then
|
||||
soft_mods_string = soft_mods_string .. ", Offline Attack Inhibitor"
|
||||
end
|
||||
|
||||
local game_info_str = "Soft Mods: " .. soft_mods_string
|
||||
|
||||
-- Spawn options:
|
||||
if (global.ocfg.enable_separate_teams) then
|
||||
game_info_str = game_info_str.."\n".."You are allowed to spawn on your own team (have your own research tree). All teams are friendly!"
|
||||
end
|
||||
if (global.ocfg.enable_vanilla_spawns) then
|
||||
game_info_str = game_info_str.."\n".."You are spawned in a default style starting area."
|
||||
else
|
||||
game_info_str = game_info_str.."\n".."You are spawned with a fix set of starting resources."
|
||||
if (global.ocfg.enable_buddy_spawn) then
|
||||
game_info_str = game_info_str.."\n".."You can chose to spawn alongside a buddy if you spawn together at the same time."
|
||||
end
|
||||
end
|
||||
if (global.ocfg.enable_shared_spawns) then
|
||||
game_info_str = game_info_str.."\n".."Spawn hosts may choose to share their spawn and allow other players to join them."
|
||||
end
|
||||
if (global.ocfg.enable_separate_teams and global.ocfg.enable_shared_team_vision) then
|
||||
game_info_str = game_info_str.."\n".."Everyone (all teams) have shared vision."
|
||||
end
|
||||
if (global.ocfg.frontier_rocket_silo) then
|
||||
game_info_str = game_info_str.."\n".."Silos are only placeable in certain areas on the map!"
|
||||
end
|
||||
if (global.ocfg.enable_regrowth) then
|
||||
game_info_str = game_info_str.."\n".."Old parts of the map will slowly be deleted over time (chunks without any player buildings)."
|
||||
end
|
||||
if (global.ocfg.enable_power_armor_start or global.ocfg.enable_modular_armor_start) then
|
||||
game_info_str = game_info_str.."\n".."Quicker start enabled."
|
||||
end
|
||||
if (global.ocfg.lock_goodies_rocket_launch) then
|
||||
game_info_str = game_info_str.."\n".."Some technologies and recipes are locked until you launch a rocket!"
|
||||
end
|
||||
|
||||
|
||||
|
||||
AddLabel(tab_container, "game_info_label", game_info_str, my_longer_label_style)
|
||||
|
||||
if (global.ocfg.enable_abandoned_base_removal) then
|
||||
AddLabel(tab_container, "leave_warning_msg", "If you leave within " .. global.ocfg.minimum_online_time .. " minutes of joining, your base and character will be deleted.", my_longer_label_style)
|
||||
tab_container.leave_warning_msg.style.font_color=my_color_red
|
||||
end
|
||||
|
||||
-- Ending Spacer
|
||||
AddSpacerLine(tab_container)
|
||||
|
||||
-- ADMIN CONTROLS
|
||||
if (player.admin) then
|
||||
player_list = {}
|
||||
for _,player in pairs(game.connected_players) do
|
||||
table.insert(player_list, player.name)
|
||||
end
|
||||
tab_container.add{name = "ban_players_dropdown",
|
||||
type = "drop-down",
|
||||
items = player_list}
|
||||
tab_container.add{name="ban_player", type="button", caption="Ban Player"}
|
||||
tab_container.add{name="restart_player", type="button", caption="Restart Player"}
|
||||
end
|
||||
end
|
@ -1,67 +0,0 @@
|
||||
-- helper_commands.lua
|
||||
-- Jan 2018
|
||||
-- None of this is my code.
|
||||
|
||||
require("lib/oarc_utils")
|
||||
|
||||
commands.add_command("run", "change player speed bonus", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "fast" then
|
||||
player.character_running_speed_modifier = 1
|
||||
elseif command.parameter == "slow" then
|
||||
player.character_running_speed_modifier = 0
|
||||
else
|
||||
player.print("run fast | slow");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command("handcraft", "change player speed bonus", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "fast" then
|
||||
player.character_crafting_speed_modifier = 5
|
||||
elseif command.parameter == "slow" then
|
||||
player.character_crafting_speed_modifier = 0
|
||||
else
|
||||
player.print("handcraft fast | slow");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command("mine", "change player speed bonus", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "fast" then
|
||||
player.character_mining_speed_modifier = 2
|
||||
elseif command.parameter == "slow" then
|
||||
player.character_mining_speed_modifier = 0
|
||||
else
|
||||
player.print("mine fast | slow");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command("kit", "give a start kit", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil and player.admin then
|
||||
local target = player
|
||||
if (command.parameter ~= nil) then
|
||||
target = game.players[command.parameter]
|
||||
end
|
||||
if target ~= nil then
|
||||
GivePlayerStarterItems(target);
|
||||
player.print("gave a kit to " .. target.name);
|
||||
target.print("you have been given a start kit");
|
||||
else
|
||||
player.print("no player " .. command.parameter);
|
||||
end
|
||||
end
|
||||
end)
|
@ -1,970 +0,0 @@
|
||||
-- map_features.lua
|
||||
-- April 2020
|
||||
-- Oarc's clone of whistlestop factories maybe?
|
||||
|
||||
-- Generic Utility Includes
|
||||
require("lib/oarc_utils")
|
||||
|
||||
|
||||
-- Used to generate placement of buildings.
|
||||
MAGIC_BUILDING_MIN_DISTANCE = 40
|
||||
MAGIC_BUILDING_MAX_DISTANCE = FAR_MAX_DIST + 50
|
||||
MAGIC_BUILDING_CHUNK_SPREAD = 41
|
||||
|
||||
|
||||
POWER_USAGE_SCALING_FACTOR = 2
|
||||
|
||||
-- This is a table indexed by the single INPUT item!
|
||||
FURNACE_ENERGY_PER_CRAFT_SECOND = (180000 / 2) * POWER_USAGE_SCALING_FACTOR
|
||||
FURNACE_RECIPES = {
|
||||
["iron-ore"] = {recipe_name = "iron-plate",
|
||||
recipe_energy = 3.2*FURNACE_ENERGY_PER_CRAFT_SECOND,
|
||||
recipe_pollution = 0.053},
|
||||
["copper-ore"] = {recipe_name = "copper-plate",
|
||||
recipe_energy = 3.2*FURNACE_ENERGY_PER_CRAFT_SECOND,
|
||||
recipe_pollution = 0.053},
|
||||
["iron-plate"] = {recipe_name = "steel-plate",
|
||||
recipe_energy = 16*FURNACE_ENERGY_PER_CRAFT_SECOND,
|
||||
recipe_pollution = 0.267},
|
||||
["stone"] = {recipe_name = "stone-brick",
|
||||
recipe_energy = 3.2*FURNACE_ENERGY_PER_CRAFT_SECOND,
|
||||
recipe_pollution = 0.053},
|
||||
}
|
||||
|
||||
-- The chemplants/refineries/assemblers lookup their own recipes since they can be set by the player.
|
||||
CHEMPLANT_ENERGY_PER_CRAFT_SECOND = 210000 * POWER_USAGE_SCALING_FACTOR
|
||||
REFINERY_ENERGY_PER_CRAFT_SECOND = 420000 * POWER_USAGE_SCALING_FACTOR
|
||||
ASSEMBLER3_ENERGY_PER_CRAFT_SECOND = (375000 / 1.25) * POWER_USAGE_SCALING_FACTOR
|
||||
CENTRIFUGE_ENERGY_PER_CRAFT_SECOND = 350000 * POWER_USAGE_SCALING_FACTOR
|
||||
|
||||
CHEMPLANT_POLLUTION_PER_CRAFT_SECOND = 4/60
|
||||
REFINERY_POLLUTION_PER_CRAFT_SECOND = 6/60
|
||||
ASSEMBLER3_POLLUTION_PER_CRAFT_SECOND = 2/60
|
||||
CENTRIFUGE_POLLUTION_PER_CRAFT_SECOND = 4/60
|
||||
|
||||
|
||||
ENEMY_WORM_TURRETS =
|
||||
{
|
||||
[0] = "small-worm-turret",
|
||||
[1] = "medium-worm-turret",
|
||||
[2] = "big-worm-turret"
|
||||
}
|
||||
|
||||
NEUTRAL_FORCE_RECIPES =
|
||||
{
|
||||
-- Science packs
|
||||
["automation-science-pack"] = true,
|
||||
["chemical-science-pack"] = true,
|
||||
["logistic-science-pack"] = true,
|
||||
["military-science-pack"] = true,
|
||||
["production-science-pack"] = true,
|
||||
["utility-science-pack"] = true,
|
||||
|
||||
-- Oil Stuff
|
||||
["advanced-oil-processing"] = true,
|
||||
["basic-oil-processing"] = true,
|
||||
-- ["coal-liquefaction"] = true, -- Too difficult/costly to implement
|
||||
|
||||
["heavy-oil-cracking"] = true,
|
||||
["light-oil-cracking"] = true,
|
||||
|
||||
["solid-fuel-from-heavy-oil"] = true,
|
||||
["solid-fuel-from-light-oil"] = true,
|
||||
["solid-fuel-from-petroleum-gas"] = true,
|
||||
|
||||
["lubricant"] = true,
|
||||
["plastic-bar"] = true,
|
||||
["sulfur"] = true,
|
||||
["sulfuric-acid"] = true,
|
||||
|
||||
-- ["oil-refinery"] = true,
|
||||
-- ["explosives"] = true,
|
||||
|
||||
-- Modules
|
||||
["effectivity-module"] = true,
|
||||
["effectivity-module-2"] = true,
|
||||
["effectivity-module-3"] = true,
|
||||
["productivity-module"] = true,
|
||||
["productivity-module-2"] = true,
|
||||
["productivity-module-3"] = true,
|
||||
["speed-module"] = true,
|
||||
["speed-module-2"] = true,
|
||||
["speed-module-3"] = true,
|
||||
|
||||
-- Intermediates
|
||||
["advanced-circuit"] = true,
|
||||
["battery"] = true,
|
||||
["copper-cable"] = true,
|
||||
["copper-plate"] = true,
|
||||
["electric-engine-unit"] = true,
|
||||
["electronic-circuit"] = true,
|
||||
["engine-unit"] = true,
|
||||
["flying-robot-frame"] = true,
|
||||
["iron-gear-wheel"] = true,
|
||||
["iron-plate"] = true,
|
||||
["iron-stick"] = true,
|
||||
["low-density-structure"] = true,
|
||||
["processing-unit"] = true,
|
||||
["rocket-control-unit"] = true,
|
||||
["rocket-fuel"] = true,
|
||||
["steel-plate"] = true,
|
||||
["stone-brick"] = true,
|
||||
|
||||
-- Misc
|
||||
["concrete"] = true,
|
||||
["landfill"] = true,
|
||||
["rail"] = true,
|
||||
["solar-panel"] = true,
|
||||
["stone-wall"] = true,
|
||||
["empty-barrel"] = true,
|
||||
|
||||
-- Nuclear
|
||||
["uranium-processing"] = true,
|
||||
-- ["kovarex-enrichment-process"] = true,
|
||||
-- ["nuclear-fuel-reprocessing"] = true,
|
||||
|
||||
-- ["pipe"] = true,
|
||||
-- ["pipe-to-ground"] = true,
|
||||
}
|
||||
|
||||
function SetNeutralForceAllowedRecipes()
|
||||
|
||||
-- Neutral force requires recipes so that furnaces can smelt steel for example.
|
||||
-- game.forces["neutral"].enable_all_recipes()
|
||||
|
||||
-- Disable ALL recipes
|
||||
for i,v in pairs(game.forces["neutral"].recipes) do
|
||||
game.forces["neutral"].recipes[i].enabled = false;
|
||||
end
|
||||
|
||||
-- Enable only the ones we want
|
||||
for i,v in pairs(NEUTRAL_FORCE_RECIPES) do
|
||||
game.forces["neutral"].recipes[i].enabled = true;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function MagicFactoriesInit()
|
||||
|
||||
SetNeutralForceAllowedRecipes()
|
||||
|
||||
global.omagic = {}
|
||||
global.omagic.building_total_count = 0
|
||||
global.omagic.factory_positions = {}
|
||||
global.omagic.furnaces = {}
|
||||
global.omagic.chemplants = {}
|
||||
global.omagic.refineries = {}
|
||||
global.omagic.assemblers = {}
|
||||
global.omagic.centrifuges = {}
|
||||
|
||||
MagicFactoryChunkGenerator()
|
||||
|
||||
game.surfaces[GAME_SURFACE_NAME].force_generate_chunk_requests() -- Block and generate all to be sure.
|
||||
MagicalFactorySpawnAll()
|
||||
end
|
||||
|
||||
function MagicFactoryChunkGenerator()
|
||||
|
||||
-- This generates several circles of randomized chunk positions.
|
||||
for r=MAGIC_BUILDING_MIN_DISTANCE,MAGIC_BUILDING_MAX_DISTANCE,MAGIC_BUILDING_CHUNK_SPREAD do
|
||||
local random_angle_offset = math.random(0, math.pi * 2)
|
||||
local num_positions_for_circle = math.ceil((r/8)) -- This makes it so each circle has more dots, roughly spreads things out equally.
|
||||
|
||||
for i=1,num_positions_for_circle do
|
||||
local theta = ((math.pi * 2) / num_positions_for_circle);
|
||||
local angle = (theta * i) + random_angle_offset;
|
||||
|
||||
local chunk_x = MathRound((r * math.cos(angle)) + math.random(-2, 2))
|
||||
local chunk_y = MathRound((r * math.sin(angle)) + math.random(-2, 2))
|
||||
|
||||
if (not game.surfaces[GAME_SURFACE_NAME].is_chunk_generated({chunk_x,chunk_y})) then
|
||||
|
||||
table.insert(global.omagic.factory_positions, {x=chunk_x, y=chunk_y})
|
||||
game.surfaces[GAME_SURFACE_NAME].request_to_generate_chunks(GetCenterTilePosFromChunkPos({x=chunk_x, y=chunk_y}), 0)
|
||||
log("Magic furnace position: " .. chunk_x .. ", " .. chunk_y .. ", " .. angle)
|
||||
else
|
||||
log("Magic furnace collided with silo location?" .. chunk_x .. ", " .. chunk_y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SendBroadcastMsg("Number magic chunks: " .. #global.omagic.factory_positions)
|
||||
end
|
||||
|
||||
function FindClosestMagicChunk(player)
|
||||
if (not player or not player.character) then return end
|
||||
return GetClosestPosFromTable(GetChunkPosFromTilePos(player.character.position), global.omagic.factory_positions)
|
||||
end
|
||||
|
||||
function IndicateClosestMagicChunk(player)
|
||||
local target_pos = GetCenterTilePosFromChunkPos(FindClosestMagicChunk(player))
|
||||
rendering.draw_line{color={r=0.5,g=0.5,b=0.5,a=0.5},
|
||||
width=2,
|
||||
from=player.character,
|
||||
to=target_pos,
|
||||
surface=player.character.surface,
|
||||
players={player},
|
||||
draw_on_ground=true,
|
||||
time_to_live=60*5}
|
||||
end
|
||||
|
||||
function MagicalFactorySpawnAll()
|
||||
for _,chunk_pos in pairs(global.omagic.factory_positions) do
|
||||
|
||||
local pos = GetCenterTilePosFromChunkPos(chunk_pos)
|
||||
local c_area = GetAreaFromChunkPos(chunk_pos)
|
||||
|
||||
-- Remove any entities in the chunk area.
|
||||
for _, entity in pairs(game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area=c_area}) do
|
||||
entity.destroy()
|
||||
end
|
||||
|
||||
-- Place landfill underneath
|
||||
local dirtTiles = {}
|
||||
for i=c_area.left_top.x,c_area.right_bottom.x,1 do
|
||||
for j=c_area.left_top.y,c_area.right_bottom.y,1 do
|
||||
table.insert(dirtTiles, {name = "landfill", position ={i,j}})
|
||||
end
|
||||
end
|
||||
game.surfaces[GAME_SURFACE_NAME].set_tiles(dirtTiles)
|
||||
|
||||
-- Yay colored tiles
|
||||
CreateFixedColorTileArea(game.surfaces[GAME_SURFACE_NAME],
|
||||
{left_top = {x=c_area.left_top.x+2, y=c_area.left_top.y+2},
|
||||
right_bottom = {x=c_area.right_bottom.x-2, y=c_area.right_bottom.y-2}},
|
||||
"black")
|
||||
|
||||
-- Make it safe from regrowth
|
||||
if global.ocfg.enable_regrowth then
|
||||
RegrowthMarkAreaSafeGivenTilePos(pos, 0, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SpawnEnemyTurret(pos)
|
||||
|
||||
local turret = game.surfaces[GAME_SURFACE_NAME].create_entity{name="gun-turret", position=pos, force="enemy"}
|
||||
local turret_inv = turret.get_inventory(defines.inventory.turret_ammo)
|
||||
turret_inv.insert({name="uranium-rounds-magazine", count=200})
|
||||
|
||||
end
|
||||
|
||||
function RequestSpawnSpecialChunk(player, spawn_function, feature_name)
|
||||
local closest_chunk = FindClosestMagicChunk(player)
|
||||
local player_chunk = GetChunkPosFromTilePos(player.character.position)
|
||||
if ((closest_chunk.x == player_chunk.x) and (closest_chunk.y == player_chunk.y)) then
|
||||
local chunk_area = GetAreaFromChunkPos(closest_chunk)
|
||||
|
||||
local entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{
|
||||
area={left_top = {chunk_area.left_top.x+1, chunk_area.left_top.y+1},
|
||||
right_bottom = {chunk_area.right_bottom.x-1, chunk_area.right_bottom.y-1}},
|
||||
force={"enemy"},
|
||||
invert=true}
|
||||
|
||||
-- Either there are no entities in the chunk (player is just on the boundary), or the only entity is the player.
|
||||
if ((#entities == 1) and (entities[1].player) and (entities[1].player == player)) or (#entities == 0) then
|
||||
spawn_function(closest_chunk)
|
||||
-- Teleport to center of chunk to be safe.
|
||||
SafeTeleport(player, game.surfaces[GAME_SURFACE_NAME], GetCenterTilePosFromChunkPos(closest_chunk))
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chunks", feature_name, 1)
|
||||
return true
|
||||
else
|
||||
player.print("Looks like this chunk already has something in it other than just you the player?! " .. entities[1].name)
|
||||
return false
|
||||
end
|
||||
|
||||
else
|
||||
player.print("You need to be standing inside the special chunk!")
|
||||
return false
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function SpecialChunkHelperText(pos)
|
||||
RenderPermanentGroundText(game.surfaces[GAME_SURFACE_NAME].index,
|
||||
{x=pos.x-3.5,y=pos.y+1},
|
||||
1,
|
||||
"Supply energy to this interface!",
|
||||
{0.7,0.4,0.3,0.8})
|
||||
RenderPermanentGroundText(game.surfaces[GAME_SURFACE_NAME].index,
|
||||
{x=pos.x-4.5,y=pos.y+2},
|
||||
1,
|
||||
"Modules/beacons DO NOT have any effect!",
|
||||
{0.7,0.4,0.3,0.8})
|
||||
end
|
||||
|
||||
function spawnSpecialChunkInputElec(center_pos)
|
||||
local inputElec = game.surfaces[GAME_SURFACE_NAME].create_entity{name="electric-energy-interface", position=center_pos, force="neutral"}
|
||||
inputElec.destructible = false
|
||||
inputElec.minable = false
|
||||
inputElec.operable = false
|
||||
inputElec.electric_buffer_size = 1000000000
|
||||
inputElec.power_production = 0
|
||||
inputElec.power_usage = 0
|
||||
inputElec.energy = 0
|
||||
return inputElec
|
||||
end
|
||||
|
||||
function SpawnFurnaceChunk(chunk_pos)
|
||||
|
||||
center_pos = GetCenterTilePosFromChunkPos(chunk_pos)
|
||||
local furnace_chunk = {["energy_input"] = spawnSpecialChunkInputElec(center_pos),
|
||||
["entities"] = {}}
|
||||
|
||||
-- 4x furnaces
|
||||
table.insert(furnace_chunk.entities, SpawnMagicBuilding("electric-furnace", {x=center_pos.x-12,y=center_pos.y-12}))
|
||||
table.insert(furnace_chunk.entities, SpawnMagicBuilding("electric-furnace", {x=center_pos.x+11,y=center_pos.y-12}))
|
||||
table.insert(furnace_chunk.entities, SpawnMagicBuilding("electric-furnace", {x=center_pos.x-12,y=center_pos.y+11}))
|
||||
table.insert(furnace_chunk.entities, SpawnMagicBuilding("electric-furnace", {x=center_pos.x+11,y=center_pos.y+11}))
|
||||
|
||||
table.insert(global.omagic.furnaces, furnace_chunk)
|
||||
SpecialChunkHelperText(center_pos)
|
||||
end
|
||||
|
||||
function SpawnOilRefineryChunk(chunk_pos)
|
||||
|
||||
center_pos = GetCenterTilePosFromChunkPos(chunk_pos)
|
||||
|
||||
local oil_chunk = {["energy_input"] = spawnSpecialChunkInputElec(center_pos),
|
||||
["chemplants"] = {},
|
||||
["refineries"] = {}}
|
||||
|
||||
-- 2x Refineries
|
||||
table.insert(oil_chunk.refineries, SpawnMagicBuilding("oil-refinery", {x=center_pos.x-5,y=center_pos.y-8}))
|
||||
table.insert(oil_chunk.refineries, SpawnMagicBuilding("oil-refinery", {x=center_pos.x+5,y=center_pos.y-8}))
|
||||
|
||||
-- 6x Chem Plants
|
||||
table.insert(oil_chunk.chemplants, SpawnMagicBuilding("chemical-plant", {x=center_pos.x-10,y=center_pos.y+8}))
|
||||
table.insert(oil_chunk.chemplants, SpawnMagicBuilding("chemical-plant", {x=center_pos.x-6,y=center_pos.y+8}))
|
||||
table.insert(oil_chunk.chemplants, SpawnMagicBuilding("chemical-plant", {x=center_pos.x-2,y=center_pos.y+8}))
|
||||
table.insert(oil_chunk.chemplants, SpawnMagicBuilding("chemical-plant", {x=center_pos.x+2,y=center_pos.y+8}))
|
||||
table.insert(oil_chunk.chemplants, SpawnMagicBuilding("chemical-plant", {x=center_pos.x+6,y=center_pos.y+8}))
|
||||
table.insert(oil_chunk.chemplants, SpawnMagicBuilding("chemical-plant", {x=center_pos.x+10,y=center_pos.y+8}))
|
||||
|
||||
table.insert(global.omagic.refineries, oil_chunk)
|
||||
table.insert(global.omagic.chemplants, oil_chunk)
|
||||
SpecialChunkHelperText(center_pos)
|
||||
end
|
||||
|
||||
function SpawnAssemblyChunk(chunk_pos)
|
||||
|
||||
center_pos = GetCenterTilePosFromChunkPos(chunk_pos)
|
||||
local assembler_chunk = {["energy_input"] = spawnSpecialChunkInputElec(center_pos),
|
||||
["entities"] = {}}
|
||||
|
||||
-- 6x Assemblers
|
||||
table.insert(assembler_chunk.entities, SpawnMagicBuilding("assembling-machine-3", {x=center_pos.x-12,y=center_pos.y-12}))
|
||||
table.insert(assembler_chunk.entities, SpawnMagicBuilding("assembling-machine-3", {x=center_pos.x,y=center_pos.y-12}))
|
||||
table.insert(assembler_chunk.entities, SpawnMagicBuilding("assembling-machine-3", {x=center_pos.x+11,y=center_pos.y-12}))
|
||||
table.insert(assembler_chunk.entities, SpawnMagicBuilding("assembling-machine-3", {x=center_pos.x-12,y=center_pos.y+11}))
|
||||
table.insert(assembler_chunk.entities, SpawnMagicBuilding("assembling-machine-3", {x=center_pos.x-1,y=center_pos.y+11}))
|
||||
table.insert(assembler_chunk.entities, SpawnMagicBuilding("assembling-machine-3", {x=center_pos.x+11,y=center_pos.y+11}))
|
||||
|
||||
table.insert(global.omagic.assemblers, assembler_chunk)
|
||||
SpecialChunkHelperText(center_pos)
|
||||
end
|
||||
|
||||
function SpawnCentrifugeChunk(chunk_pos)
|
||||
|
||||
center_pos = GetCenterTilePosFromChunkPos(chunk_pos)
|
||||
local centrifuge_chunk = {["energy_input"] = spawnSpecialChunkInputElec(center_pos),
|
||||
["entities"] = {}}
|
||||
|
||||
-- 1 Centrifuge (MORE THAN ENOUGH!)
|
||||
table.insert(centrifuge_chunk.entities, SpawnMagicBuilding("centrifuge", {x=center_pos.x,y=center_pos.y-10}))
|
||||
|
||||
table.insert(global.omagic.centrifuges, centrifuge_chunk)
|
||||
SpecialChunkHelperText(center_pos)
|
||||
end
|
||||
|
||||
function SpawnSiloChunk(chunk_pos)
|
||||
|
||||
center_pos = GetCenterTilePosFromChunkPos(chunk_pos)
|
||||
|
||||
table.insert(global.siloPosition, center_pos)
|
||||
|
||||
RenderPermanentGroundText(game.surfaces[GAME_SURFACE_NAME].index,
|
||||
{x=center_pos.x-3.25,y=center_pos.y+6},
|
||||
1,
|
||||
"You can build a silo here!",
|
||||
{0.7,0.4,0.3,0.8})
|
||||
|
||||
-- Set tiles below the silo
|
||||
tiles = {}
|
||||
for dx = -6,5 do
|
||||
for dy = -6,5 do
|
||||
if (game.active_mods["oarc-restricted-build"]) then
|
||||
table.insert(tiles, {name = global.ocfg.locked_build_area_tile,
|
||||
position = {center_pos.x+dx, center_pos.y+dy}})
|
||||
else
|
||||
if ((dx % 2 == 0) or (dx % 2 == 0)) then
|
||||
table.insert(tiles, {name = "concrete",
|
||||
position = {center_pos.x+dx, center_pos.y+dy}})
|
||||
else
|
||||
table.insert(tiles, {name = "hazard-concrete-left",
|
||||
position = {center_pos.x+dx, center_pos.y+dy}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
game.surfaces[GAME_SURFACE_NAME].set_tiles(tiles, true)
|
||||
end
|
||||
|
||||
function SpawnMagicBuilding(entity_name, position)
|
||||
local direction = defines.direction.north
|
||||
if (entity_name == "oil-refinery") then
|
||||
direction = defines.direction.south
|
||||
end
|
||||
local magic_building = game.surfaces[GAME_SURFACE_NAME].create_entity{name=entity_name, position=position, force="neutral", direction=direction}
|
||||
magic_building.destructible = false
|
||||
magic_building.minable = false
|
||||
magic_building.operable = true
|
||||
magic_building.active = false
|
||||
|
||||
global.omagic.building_total_count = global.omagic.building_total_count + 1
|
||||
|
||||
return magic_building
|
||||
end
|
||||
|
||||
function MagicFactoriesOnTick()
|
||||
MagicFurnaceOnTick()
|
||||
MagicChemplantOnTick()
|
||||
MagicRefineryOnTick()
|
||||
MagicAssemblerOnTick()
|
||||
MagicCentrifugeOnTick()
|
||||
end
|
||||
|
||||
-- Some helpful math:
|
||||
-- 94 per tick (max stack of ore in a smelter) (More like 2 or 3 ore per tick.)
|
||||
-- blue belt = 45 / sec
|
||||
-- 6 INPUT blue belts = 4.5 ore/tick (45 * 6 / 60) with productivity is an extra 0.9 maybe.
|
||||
function MagicFurnaceOnTick()
|
||||
if not global.omagic.furnaces then return end
|
||||
|
||||
for entry_idx,entry in pairs(global.omagic.furnaces) do
|
||||
|
||||
-- Validate the entry.
|
||||
if (entry == nil) or (entry.entities == nil) or (entry.energy_input == nil) or (not entry.energy_input.valid) then
|
||||
global.omagic.furnaces[entry_idx] = nil
|
||||
log("MagicFurnaceOnTick - Magic furnace entry removed?")
|
||||
goto next_furnace_entry
|
||||
end
|
||||
|
||||
local energy_share = entry.energy_input.energy/#entry.entities
|
||||
|
||||
for idx,furnace in pairs(entry.entities) do
|
||||
|
||||
if (furnace == nil) or (not furnace.valid) then
|
||||
global.omagic.furnaces[entry_idx] = nil
|
||||
log("MagicFurnaceOnTick - Magic furnace removed?")
|
||||
goto next_furnace_entry
|
||||
end
|
||||
|
||||
local input_inv = furnace.get_inventory(defines.inventory.furnace_source)
|
||||
local input_items = input_inv.get_contents()
|
||||
|
||||
-- We have something inside?
|
||||
local input_item_name = next(input_items)
|
||||
if not input_item_name then
|
||||
goto next_furnace
|
||||
end
|
||||
|
||||
-- Does the input item have a recipe?
|
||||
if not FURNACE_RECIPES[input_item_name] then
|
||||
log("MagicFurnaceOnTick - Missing FURNACE_RECIPES?")
|
||||
goto next_furnace
|
||||
end
|
||||
local recipe = game.forces["neutral"].recipes[FURNACE_RECIPES[input_item_name].recipe_name]
|
||||
if not recipe then
|
||||
log("MagicFurnaceOnTick - Missing neutral force recipes?")
|
||||
goto next_furnace
|
||||
end
|
||||
|
||||
-- Verify 1 ingredient type and 1 product type (for furnaces)
|
||||
if (#recipe.products ~= 1) or (#recipe.ingredients ~= 1) then
|
||||
log("MagicFurnaceOnTick - Recipe product/ingredient more than 1?")
|
||||
goto next_furnace
|
||||
end
|
||||
local recipe_ingredient = recipe.ingredients[next(recipe.ingredients)]
|
||||
local recipe_product = recipe.products[next(recipe.products)]
|
||||
|
||||
local output_inv = furnace.get_inventory(defines.inventory.furnace_result)
|
||||
|
||||
-- Can we insert at least 1 of the recipe result?
|
||||
-- if not output_inv.can_insert({name=recipe_product.name}) then goto next_furnace end
|
||||
local output_space = output_inv.get_insertable_count(recipe_product.name)
|
||||
|
||||
-- Calculate how many times we can make the recipe.
|
||||
local ingredient_limit = math.floor(input_items[input_item_name]/recipe_ingredient.amount)
|
||||
local output_limit = math.floor(output_space/recipe_product.amount)
|
||||
|
||||
-- Use shared energy pool
|
||||
local energy_limit = math.floor(energy_share/FURNACE_RECIPES[input_item_name].recipe_energy)
|
||||
local recipe_count = math.min(ingredient_limit, output_limit, energy_limit)
|
||||
|
||||
-- Hit a limit somewhere?
|
||||
if (recipe_count <= 0) then goto next_furnace end
|
||||
|
||||
-- Track energy usage
|
||||
entry.energy_input.energy = entry.energy_input.energy - (FURNACE_RECIPES[input_item_name].recipe_energy*recipe_count)
|
||||
furnace.surface.pollute(furnace.position, FURNACE_RECIPES[input_item_name].recipe_pollution*recipe_count)
|
||||
|
||||
-- Check if it has a last_user
|
||||
if (not furnace.last_user) then
|
||||
local player_entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{
|
||||
position=furnace.position,
|
||||
radius=10,
|
||||
force={"enemy", "neutral"},
|
||||
limit=1,
|
||||
invert=true}
|
||||
if (player_entities and player_entities[1] and player_entities[1].last_user) then
|
||||
furnace.last_user = player_entities[1].last_user
|
||||
end
|
||||
end
|
||||
|
||||
-- Subtract recipe count from input and Add recipe count to output
|
||||
input_inv.remove({name=recipe_ingredient.name, count=recipe_count*recipe_ingredient.amount})
|
||||
output_inv.insert({name=recipe_product.name, count=recipe_count*recipe_product.amount})
|
||||
furnace.products_finished = furnace.products_finished + recipe_count
|
||||
|
||||
-- If we have a user, do the stats
|
||||
if (furnace.last_user) then
|
||||
furnace.last_user.force.item_production_statistics.on_flow(recipe_ingredient.name, -recipe_count*recipe_ingredient.amount)
|
||||
furnace.last_user.force.item_production_statistics.on_flow(recipe_product.name, recipe_count*recipe_product.amount)
|
||||
end
|
||||
|
||||
::next_furnace::
|
||||
end
|
||||
|
||||
::next_furnace_entry::
|
||||
end
|
||||
end
|
||||
|
||||
function MagicChemplantOnTick()
|
||||
if not global.omagic.chemplants then return end
|
||||
|
||||
for entry_idx,entry in pairs(global.omagic.chemplants) do
|
||||
|
||||
-- Validate the entry.
|
||||
if (entry == nil) or (entry.chemplants == nil) or (entry.energy_input == nil) or (not entry.energy_input.valid) then
|
||||
global.omagic.chemplants[entry_idx] = nil
|
||||
log("MagicChemplantOnTick - Magic assembler entry removed?")
|
||||
goto next_chemplant_entry
|
||||
end
|
||||
|
||||
local energy_share = entry.energy_input.energy/(#entry.chemplants + #entry.refineries)
|
||||
|
||||
for idx,chemplant in pairs(entry.chemplants) do
|
||||
|
||||
if (chemplant == nil) or (not chemplant.valid) then
|
||||
global.omagic.chemplants[idx] = nil
|
||||
log("Magic chemplant removed?")
|
||||
goto next_chemplant_entry
|
||||
end
|
||||
|
||||
recipe = chemplant.get_recipe()
|
||||
|
||||
if (not recipe) then
|
||||
goto next_chemplant -- No recipe means do nothing.
|
||||
end
|
||||
|
||||
local energy_cost = recipe.energy * CHEMPLANT_ENERGY_PER_CRAFT_SECOND
|
||||
if (energy_share < energy_cost) then goto next_chemplant end -- Not enough energy!
|
||||
|
||||
local input_inv = chemplant.get_inventory(defines.inventory.assembling_machine_input)
|
||||
local input_items = input_inv.get_contents()
|
||||
local input_fluids = chemplant.get_fluid_contents()
|
||||
|
||||
for _,v in ipairs(recipe.ingredients) do
|
||||
if (not input_items[v.name] or (input_items[v.name] < v.amount)) then
|
||||
if (not input_fluids[v.name] or (input_fluids[v.name] < v.amount)) then
|
||||
goto next_chemplant -- Not enough ingredients
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local recipe_product = recipe.products[next(recipe.products)] -- Assume only 1 product.
|
||||
|
||||
if recipe_product.type == "fluid" then
|
||||
|
||||
if ((chemplant.get_fluid_count(recipe_product.name) + recipe_product.amount) > 100) then
|
||||
goto next_chemplant -- Not enough space for ouput
|
||||
end
|
||||
|
||||
chemplant.insert_fluid({name=recipe_product.name, amount=recipe_product.amount})
|
||||
if (chemplant.last_user) then
|
||||
chemplant.last_user.force.fluid_production_statistics.on_flow(recipe_product.name, recipe_product.amount)
|
||||
end
|
||||
|
||||
-- Otherwise it must be an item type
|
||||
else
|
||||
|
||||
local output_inv = chemplant.get_inventory(defines.inventory.assembling_machine_output)
|
||||
|
||||
-- Can we insert at least 1 of the recipe result?
|
||||
if not output_inv.can_insert({name=recipe_product.name, amount=recipe_product.amount}) then goto next_chemplant end
|
||||
|
||||
-- Add recipe count to output
|
||||
output_inv.insert({name=recipe_product.name, count=recipe_product.amount})
|
||||
if (chemplant.last_user) then
|
||||
chemplant.last_user.force.item_production_statistics.on_flow(recipe_product.name, recipe_product.amount)
|
||||
end
|
||||
end
|
||||
|
||||
-- Subtract ingredients from input
|
||||
for _,v in ipairs(recipe.ingredients) do
|
||||
if (input_items[v.name]) then
|
||||
input_inv.remove({name=v.name, count=v.amount})
|
||||
if (chemplant.last_user) then
|
||||
chemplant.last_user.force.item_production_statistics.on_flow(v.name, -v.amount)
|
||||
end
|
||||
elseif (input_fluids[v.name]) then
|
||||
chemplant.remove_fluid{name=v.name, amount=v.amount}
|
||||
if (chemplant.last_user) then
|
||||
chemplant.last_user.force.fluid_production_statistics.on_flow(v.name, -v.amount)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
chemplant.products_finished = chemplant.products_finished + 1
|
||||
|
||||
-- Track energy usage
|
||||
entry.energy_input.energy = entry.energy_input.energy - energy_cost
|
||||
chemplant.surface.pollute(chemplant.position, recipe.energy*CHEMPLANT_POLLUTION_PER_CRAFT_SECOND)
|
||||
|
||||
|
||||
::next_chemplant::
|
||||
end
|
||||
|
||||
::next_chemplant_entry::
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function MagicRefineryOnTick()
|
||||
if not global.omagic.refineries then return end
|
||||
|
||||
for entry_idx,entry in pairs(global.omagic.refineries) do
|
||||
|
||||
-- Validate the entry.
|
||||
if (entry == nil) or (entry.refineries == nil) or (entry.energy_input == nil) or (not entry.energy_input.valid) then
|
||||
global.omagic.refineries[entry_idx] = nil
|
||||
log("MagicRefineryOnTick - Magic assembler entry removed?")
|
||||
goto next_refinery_entry
|
||||
end
|
||||
|
||||
local energy_share = entry.energy_input.energy/(#entry.chemplants + #entry.refineries)
|
||||
|
||||
for idx,refinery in pairs(entry.refineries) do
|
||||
|
||||
if (refinery == nil) or (not refinery.valid) then
|
||||
global.omagic.refineries[idx] = nil
|
||||
log("Magic refinery removed?")
|
||||
goto next_refinery_entry
|
||||
end
|
||||
|
||||
recipe = refinery.get_recipe()
|
||||
|
||||
if (not recipe) then
|
||||
goto next_refinery -- No recipe means do nothing.
|
||||
end
|
||||
|
||||
local energy_cost = recipe.energy * REFINERY_ENERGY_PER_CRAFT_SECOND
|
||||
if (energy_share < energy_cost) then goto next_refinery end -- Not enough energy!
|
||||
|
||||
local fluidbox_copy = refinery.fluidbox
|
||||
|
||||
-- If recipe is COAL LIQUEFACTION: heavy(1), steam(2), heavy(3), light(4), petro(5)
|
||||
-- if (recipe.name == "coal-liquefaction") then
|
||||
|
||||
|
||||
-- If recipe is Advanced OIL: water(1), crude(2), heavy(3), light(4), petro(5)
|
||||
if (recipe.name == "advanced-oil-processing") then
|
||||
|
||||
if ((not refinery.fluidbox[1]) or (refinery.fluidbox[1].amount < 50)) then goto next_refinery end -- Not enough water
|
||||
if ((not refinery.fluidbox[2]) or (refinery.fluidbox[2].amount < 100)) then goto next_refinery end -- Not enough crude
|
||||
if ((refinery.fluidbox[3]) and (refinery.fluidbox[3].amount > 25)) then goto next_refinery end -- Not enough space for heavy
|
||||
if ((refinery.fluidbox[4]) and (refinery.fluidbox[4].amount > 45)) then goto next_refinery end -- Not enough space for light
|
||||
if ((refinery.fluidbox[5]) and (refinery.fluidbox[5].amount > 55)) then goto next_refinery end -- Not enough space for petro
|
||||
|
||||
refinery.remove_fluid{name="water", amount=50}
|
||||
refinery.remove_fluid{name="crude-oil", amount=100}
|
||||
refinery.insert_fluid({name="heavy-oil", amount=25})
|
||||
refinery.insert_fluid({name="light-oil", amount=45})
|
||||
refinery.insert_fluid({name="petroleum-gas", amount=55})
|
||||
|
||||
if (refinery.last_user) then
|
||||
refinery.last_user.force.fluid_production_statistics.on_flow("water", -50)
|
||||
refinery.last_user.force.fluid_production_statistics.on_flow("crude-oil", -100)
|
||||
refinery.last_user.force.fluid_production_statistics.on_flow("heavy-oil", 25)
|
||||
refinery.last_user.force.fluid_production_statistics.on_flow("light-oil", 45)
|
||||
refinery.last_user.force.fluid_production_statistics.on_flow("petroleum-gas", 55)
|
||||
end
|
||||
|
||||
-- If recipe is Basic OIL: crude(1), petro(2)
|
||||
elseif (recipe.name == "basic-oil-processing") then
|
||||
|
||||
if ((not refinery.fluidbox[1]) or (refinery.fluidbox[1].amount < 100)) then goto next_refinery end -- Not enough crude
|
||||
if ((refinery.fluidbox[2]) and (refinery.fluidbox[2].amount > 45)) then goto next_refinery end -- Not enough space for petro
|
||||
|
||||
refinery.remove_fluid{name="crude-oil", amount=100}
|
||||
refinery.insert_fluid({name="petroleum-gas", amount=45})
|
||||
|
||||
if (refinery.last_user) then
|
||||
refinery.last_user.force.fluid_production_statistics.on_flow("crude-oil", -100)
|
||||
refinery.last_user.force.fluid_production_statistics.on_flow("petroleum-gas", 45)
|
||||
end
|
||||
|
||||
else
|
||||
goto next_refinery -- Shouldn't hit this...
|
||||
end
|
||||
|
||||
refinery.products_finished = refinery.products_finished + 1
|
||||
|
||||
-- Track energy usage
|
||||
entry.energy_input.energy = entry.energy_input.energy - energy_cost
|
||||
refinery.surface.pollute(refinery.position, recipe.energy*REFINERY_POLLUTION_PER_CRAFT_SECOND)
|
||||
|
||||
::next_refinery::
|
||||
end
|
||||
|
||||
::next_refinery_entry::
|
||||
end
|
||||
end
|
||||
|
||||
function MagicAssemblerOnTick()
|
||||
if not global.omagic.assemblers then return end
|
||||
|
||||
for entry_idx,entry in pairs(global.omagic.assemblers) do
|
||||
|
||||
-- Validate the entry.
|
||||
if (entry == nil) or (entry.entities == nil) or (entry.energy_input == nil) or (not entry.energy_input.valid) then
|
||||
global.omagic.assemblers[entry_idx] = nil
|
||||
log("MagicAssemblerOnTick - Magic assembler entry removed?")
|
||||
goto next_assembler_entry
|
||||
end
|
||||
|
||||
local energy_share = entry.energy_input.energy/#entry.entities
|
||||
|
||||
for idx,assembler in pairs(entry.entities) do
|
||||
|
||||
if (assembler == nil) or (not assembler.valid) then
|
||||
global.omagic.assemblers[entry_idx] = nil
|
||||
log("MagicAssemblerOnTick - Magic assembler removed?")
|
||||
goto next_assembler_entry
|
||||
end
|
||||
|
||||
recipe = assembler.get_recipe()
|
||||
|
||||
if (not recipe) then
|
||||
goto next_assembler -- No recipe means do nothing.
|
||||
end
|
||||
|
||||
local energy_cost = recipe.energy * ASSEMBLER3_ENERGY_PER_CRAFT_SECOND
|
||||
if (energy_share < energy_cost) then goto next_assembler end -- Not enough energy!
|
||||
|
||||
-- Assume only 1 product and that it's an item!
|
||||
local recipe_product = recipe.products[next(recipe.products)]
|
||||
if recipe_product.type ~= "item" then goto next_assembler end
|
||||
|
||||
local input_inv = assembler.get_inventory(defines.inventory.assembling_machine_input)
|
||||
local input_items = input_inv.get_contents()
|
||||
local input_fluids = assembler.get_fluid_contents()
|
||||
|
||||
for _,v in ipairs(recipe.ingredients) do
|
||||
if (not input_items[v.name] or (input_items[v.name] < v.amount)) then
|
||||
if (not input_fluids[v.name] or (input_fluids[v.name] < v.amount)) then
|
||||
goto next_assembler -- Not enough ingredients
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local output_inv = assembler.get_inventory(defines.inventory.assembling_machine_output)
|
||||
if not output_inv.can_insert({name=recipe_product.name, amount=recipe_product.amount}) then
|
||||
goto next_assembler -- Can we insert the result?
|
||||
end
|
||||
|
||||
-- Add recipe count to output
|
||||
output_inv.insert({name=recipe_product.name, count=recipe_product.amount})
|
||||
if (assembler.last_user) then
|
||||
assembler.last_user.force.item_production_statistics.on_flow(recipe_product.name, recipe_product.amount)
|
||||
end
|
||||
|
||||
-- Subtract ingredients from input
|
||||
for _,v in ipairs(recipe.ingredients) do
|
||||
if (input_items[v.name]) then
|
||||
input_inv.remove({name=v.name, count=v.amount})
|
||||
if (assembler.last_user) then
|
||||
assembler.last_user.force.item_production_statistics.on_flow(v.name, -v.amount)
|
||||
end
|
||||
elseif (input_fluids[v.name]) then
|
||||
assembler.remove_fluid{name=v.name, amount=v.amount}
|
||||
if (assembler.last_user) then
|
||||
assembler.last_user.force.fluid_production_statistics.on_flow(v.name, -v.amount)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Track energy usage
|
||||
entry.energy_input.energy = entry.energy_input.energy - energy_cost
|
||||
assembler.surface.pollute(assembler.position, recipe.energy*ASSEMBLER3_POLLUTION_PER_CRAFT_SECOND)
|
||||
|
||||
assembler.products_finished = assembler.products_finished + 1
|
||||
|
||||
::next_assembler::
|
||||
end
|
||||
|
||||
::next_assembler_entry::
|
||||
end
|
||||
end
|
||||
|
||||
function MagicCentrifugeOnTick()
|
||||
if not global.omagic.centrifuges then return end
|
||||
|
||||
for entry_idx,entry in pairs(global.omagic.centrifuges) do
|
||||
|
||||
-- Validate the entry.
|
||||
if (entry == nil) or (entry.entities == nil) or (entry.energy_input == nil) or (not entry.energy_input.valid) then
|
||||
global.omagic.centrifuges[entry_idx] = nil
|
||||
log("MagicCentrifugeOnTick - Magic centrifuge entry removed?")
|
||||
goto next_centrifuge_entry
|
||||
end
|
||||
|
||||
local energy_share = entry.energy_input.energy/#entry.entities
|
||||
|
||||
for idx,centrifuge in pairs(entry.entities) do
|
||||
|
||||
if (centrifuge == nil) or (not centrifuge.valid) then
|
||||
global.omagic.centrifuges[entry_idx] = nil
|
||||
log("MagicCentrifugeOnTick - Magic centrifuge removed?")
|
||||
goto next_centrifuge_entry
|
||||
end
|
||||
|
||||
recipe = centrifuge.get_recipe()
|
||||
|
||||
if (not recipe) then
|
||||
goto next_centrifuge -- No recipe means do nothing.
|
||||
end
|
||||
|
||||
local energy_cost = recipe.energy * CENTRIFUGE_ENERGY_PER_CRAFT_SECOND
|
||||
if (energy_share < energy_cost) then goto next_centrifuge end -- Not enough energy!
|
||||
|
||||
local input_inv = centrifuge.get_inventory(defines.inventory.assembling_machine_input)
|
||||
local input_items = input_inv.get_contents()
|
||||
|
||||
for _,v in ipairs(recipe.ingredients) do
|
||||
if (not input_items[v.name] or (input_items[v.name] < v.amount)) then
|
||||
goto next_centrifuge -- Not enough ingredients
|
||||
end
|
||||
end
|
||||
|
||||
local output_inv = centrifuge.get_inventory(defines.inventory.assembling_machine_output)
|
||||
|
||||
local output_item, output_count
|
||||
|
||||
-- 10 uranium ore IN
|
||||
-- .993 uranium-238 and .007 uranium-235 OUT
|
||||
if (recipe.name == "uranium-processing") then
|
||||
|
||||
local rand_chance = math.random()
|
||||
|
||||
output_count = 1
|
||||
if (rand_chance <= .007) then
|
||||
output_item = "uranium-235"
|
||||
else
|
||||
output_item = "uranium-238"
|
||||
end
|
||||
|
||||
-- Check if we can insert at least 1 of BOTH.
|
||||
if not output_inv.can_insert({name="uranium-235", amount=output_count}) then
|
||||
goto next_centrifuge
|
||||
end
|
||||
if not output_inv.can_insert({name= "uranium-238", amount=output_count}) then
|
||||
goto next_centrifuge
|
||||
end
|
||||
|
||||
output_inv.insert({name=output_item, count=output_count})
|
||||
if (centrifuge.last_user) then
|
||||
centrifuge.last_user.force.item_production_statistics.on_flow(output_item, output_count)
|
||||
end
|
||||
|
||||
for _,v in ipairs(recipe.ingredients) do
|
||||
if (input_items[v.name]) then
|
||||
input_inv.remove({name=v.name, count=v.amount})
|
||||
if (centrifuge.last_user) then
|
||||
centrifuge.last_user.force.item_production_statistics.on_flow(v.name, -v.amount)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
goto next_centrifuge -- Unsupported!
|
||||
end
|
||||
|
||||
centrifuge.products_finished = centrifuge.products_finished + 1
|
||||
|
||||
-- Track energy usage
|
||||
entry.energy_input.energy = entry.energy_input.energy - energy_cost
|
||||
centrifuge.surface.pollute(centrifuge.position, recipe.energy*CENTRIFUGE_POLLUTION_PER_CRAFT_SECOND)
|
||||
|
||||
::next_centrifuge::
|
||||
end
|
||||
|
||||
::next_centrifuge_entry::
|
||||
end
|
||||
end
|
||||
|
||||
COIN_MULTIPLIER = 2
|
||||
|
||||
COIN_GENERATION_CHANCES = {
|
||||
["small-biter"] = 0.01,
|
||||
["medium-biter"] = 0.02,
|
||||
["big-biter"] = 0.05,
|
||||
["behemoth-biter"] = 1,
|
||||
|
||||
["small-spitter"] = 0.01,
|
||||
["medium-spitter"] = 0.02,
|
||||
["big-spitter"] = 0.05,
|
||||
["behemoth-spitter"] = 1,
|
||||
|
||||
["small-worm-turret"] = 5,
|
||||
["medium-worm-turret"] = 10,
|
||||
["big-worm-turret"] = 15,
|
||||
["behemoth-worm-turret"] = 25,
|
||||
|
||||
["biter-spawner"] = 20,
|
||||
["spitter-spawner"] = 20,
|
||||
}
|
||||
|
||||
function CoinsFromEnemiesOnPostEntityDied(event)
|
||||
if (not event.prototype or not event.prototype.name) then return end
|
||||
|
||||
local coin_chance = nil
|
||||
if (COIN_GENERATION_CHANCES[event.prototype.name]) then
|
||||
coin_chance = COIN_GENERATION_CHANCES[event.prototype.name]
|
||||
end
|
||||
|
||||
if (coin_chance) then
|
||||
DropCoins(event.position, coin_chance, event.force)
|
||||
end
|
||||
end
|
||||
|
||||
-- Drop coins, force is optional, decon is applied if force is not nil.
|
||||
function DropCoins(pos, count, force)
|
||||
|
||||
local drop_amount = 0
|
||||
|
||||
-- If count is less than 1, it represents a probability to drop a single coin
|
||||
if (count < 1) then
|
||||
if (math.random() < count) then
|
||||
drop_amount = 1
|
||||
end
|
||||
|
||||
-- If count is 1 or more, it represents a probability to drop at least that amount and up to 3x
|
||||
elseif (count >= 1) then
|
||||
drop_amount = math.random(count,count*COIN_MULTIPLIER)
|
||||
end
|
||||
|
||||
if drop_amount == 0 then return end
|
||||
game.surfaces[GAME_SURFACE_NAME].spill_item_stack(pos, {name="coin", count=math.floor(drop_amount)}, true, force, false) -- Set nil to force to auto decon.
|
||||
end
|
@ -1,35 +0,0 @@
|
||||
-- notepad.lua
|
||||
-- Oarc's simple notepad cause I keep forgetting what I want to do next.
|
||||
|
||||
|
||||
function CreateNotepadGuiTab(tab_container, player)
|
||||
|
||||
if global.oarc_notepad == nil then
|
||||
global.oarc_notepad = {}
|
||||
end
|
||||
|
||||
if global.oarc_notepad[player.name] == nil then
|
||||
global.oarc_notepad[player.name] = "Write something here...!"
|
||||
end
|
||||
|
||||
AddLabel(tab_container, "notepad_info", "Use this to take notes:", my_longer_label_style)
|
||||
|
||||
local txt_box = tab_container.add{type="text-box", name="oarc_notepad_textbox", text=global.oarc_notepad[player.name]}
|
||||
ApplyStyle(txt_box, my_notepad_fixed_width_style)
|
||||
|
||||
txt_box.focus()
|
||||
end
|
||||
|
||||
|
||||
function NotepadOnGuiTextChange(event)
|
||||
|
||||
if (event.element.name ~= "oarc_notepad_textbox") then return end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
if global.oarc_notepad == nil then
|
||||
global.oarc_notepad = {}
|
||||
end
|
||||
|
||||
global.oarc_notepad[player.name] = event.element.text
|
||||
end
|
283
lib/oarc_buy.lua
283
lib/oarc_buy.lua
@ -1,283 +0,0 @@
|
||||
-- oarc_buy.lua
|
||||
-- May 2020
|
||||
-- Adding microtransactions.
|
||||
|
||||
require("lib/oarc_store_player_items")
|
||||
require("lib/oarc_store_map_features")
|
||||
local mod_gui = require("mod-gui")
|
||||
|
||||
-- NAME of the top level element (outer frame)
|
||||
OARC_STORE_GUI = "oarc_store_gui"
|
||||
|
||||
OARC_PLAYER_STORE_GUI_TAB_NAME = "Item Store"
|
||||
OARC_MAP_FEATURE_GUI_TAB_NAME = "Special Store"
|
||||
|
||||
local OARC_STORE_TAB_CONTENT_FUNCTIONS = {}
|
||||
OARC_STORE_TAB_CONTENT_FUNCTIONS[OARC_PLAYER_STORE_GUI_TAB_NAME] = CreatePlayerStoreTab
|
||||
OARC_STORE_TAB_CONTENT_FUNCTIONS[OARC_MAP_FEATURE_GUI_TAB_NAME] = CreateMapFeatureStoreTab
|
||||
|
||||
function InitOarcStoreGuiTabs(player)
|
||||
CreateOarcStoreButton(player)
|
||||
CreateOarcStoreTabsPane(player)
|
||||
|
||||
-- Store for personal items
|
||||
AddOarcStoreTab(player, OARC_PLAYER_STORE_GUI_TAB_NAME)
|
||||
SetOarcStoreTabEnabled(player, OARC_PLAYER_STORE_GUI_TAB_NAME, true)
|
||||
|
||||
-- Store for map feature stuff
|
||||
AddOarcStoreTab(player, OARC_MAP_FEATURE_GUI_TAB_NAME)
|
||||
SetOarcStoreTabEnabled(player, OARC_MAP_FEATURE_GUI_TAB_NAME, true)
|
||||
|
||||
HideOarcStore(player)
|
||||
end
|
||||
|
||||
function CreateOarcStoreButton(player)
|
||||
if (mod_gui.get_button_flow(player).oarc_store == nil) then
|
||||
local b = mod_gui.get_button_flow(player).add{name="oarc_store",
|
||||
type="sprite-button",
|
||||
sprite="item/coin",
|
||||
style=mod_gui.button_style}
|
||||
b.style.padding=2
|
||||
end
|
||||
end
|
||||
|
||||
function DoesOarcStoreExist(player)
|
||||
return (mod_gui.get_frame_flow(player)[OARC_STORE_GUI] ~= nil)
|
||||
end
|
||||
|
||||
function IsOarcStoreVisible(player)
|
||||
local of = mod_gui.get_frame_flow(player)[OARC_STORE_GUI]
|
||||
return (of.visible)
|
||||
end
|
||||
|
||||
function ShowOarcStore(player)
|
||||
local of = mod_gui.get_frame_flow(player)[OARC_STORE_GUI]
|
||||
if (of == nil) then return end
|
||||
of.visible = true
|
||||
player.opened = of
|
||||
end
|
||||
|
||||
function HideOarcStore(player)
|
||||
local of = mod_gui.get_frame_flow(player)[OARC_STORE_GUI]
|
||||
if (of == nil) then return end
|
||||
of.visible = false
|
||||
player.opened = nil
|
||||
end
|
||||
|
||||
function GetOarcStoreTabsPane(player)
|
||||
if (mod_gui.get_frame_flow(player)[OARC_STORE_GUI] == nil) then
|
||||
return nil
|
||||
else
|
||||
return mod_gui.get_frame_flow(player)[OARC_STORE_GUI].store_if.store_tabs
|
||||
end
|
||||
end
|
||||
|
||||
function ClickOarcStoreButton(event)
|
||||
if not (event and event.element and event.element.valid) then return end
|
||||
local button = event.element
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
-- Don't allow any clicks on the store while player is dead!
|
||||
if (not player or player.ticks_to_respawn) then
|
||||
if (DoesOarcStoreExist(player)) then
|
||||
HideOarcStore(player)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if (button.name == "oarc_store") then
|
||||
if (not DoesOarcStoreExist(player)) then
|
||||
CreateOarcStoreTabsPane(player)
|
||||
else
|
||||
if (IsOarcStoreVisible(player)) then
|
||||
HideOarcStore(player)
|
||||
else
|
||||
ShowOarcStore(player)
|
||||
FakeTabChangeEventOarcStore(player)
|
||||
end
|
||||
end
|
||||
elseif ((button.parent ~= nil) and (button.parent.parent ~= nil)) then
|
||||
if (button.parent.parent.name == OARC_PLAYER_STORE_GUI_TAB_NAME.."_if") then
|
||||
OarcPlayerStoreButton(event)
|
||||
elseif (button.parent.parent.name == OARC_MAP_FEATURE_GUI_TAB_NAME.."_if") then
|
||||
OarcMapFeatureStoreButton(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TabChangeOarcStore(event)
|
||||
if (event.element.name ~= "store_tabs") then return end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
local otabs = event.element
|
||||
local selected_tab_name = otabs.tabs[otabs.selected_tab_index].tab.name
|
||||
|
||||
-- Clear all tab contents
|
||||
for i,t in pairs(otabs.tabs) do
|
||||
t.content.clear()
|
||||
end
|
||||
|
||||
SetOarcStoreTabContent(player, selected_tab_name)
|
||||
end
|
||||
|
||||
function FakeTabChangeEventOarcStore(player)
|
||||
local event = {}
|
||||
event.element = GetOarcStoreTabsPane(player)
|
||||
event.player_index = player.index
|
||||
TabChangeOarcStore(event)
|
||||
end
|
||||
|
||||
function CreateOarcStoreTabsPane(player)
|
||||
if (mod_gui.get_frame_flow(player)[OARC_STORE_GUI] == nil) then
|
||||
|
||||
-- OUTER FRAME (TOP GUI ELEMENT)
|
||||
local frame = mod_gui.get_frame_flow(player).add{
|
||||
type = 'frame',
|
||||
name = OARC_STORE_GUI,
|
||||
direction = "vertical"}
|
||||
frame.style.padding = 5
|
||||
|
||||
-- INNER FRAME
|
||||
local inside_frame = frame.add{
|
||||
type = "frame",
|
||||
name = "store_if",
|
||||
style = "inside_deep_frame",
|
||||
direction = "vertical"
|
||||
}
|
||||
|
||||
-- SUB HEADING w/ LABEL
|
||||
local subhead = inside_frame.add{
|
||||
type="frame",
|
||||
name="sub_header",
|
||||
style = "changelog_subheader_frame",
|
||||
direction = "vertical"}
|
||||
AddLabel(subhead, "store_info", "OARC Microtransactions and DLC", "subheader_caption_label")
|
||||
|
||||
-- TABBED PANE
|
||||
local store_tabs = inside_frame.add{
|
||||
name="store_tabs",
|
||||
type="tabbed-pane",
|
||||
style="tabbed_pane"}
|
||||
store_tabs.style.top_padding = 8
|
||||
end
|
||||
end
|
||||
|
||||
function AddOarcStoreTab(player, tab_name)
|
||||
-- if (not DoesOarcStoreExist(player)) then
|
||||
-- CreateOarcStoreTabsPane(player)
|
||||
-- end
|
||||
|
||||
-- Get the tabbed pane
|
||||
local otabs = GetOarcStoreTabsPane(player)
|
||||
|
||||
-- Create new tab
|
||||
local new_tab = otabs.add{
|
||||
type="tab",
|
||||
name=tab_name,
|
||||
caption=tab_name}
|
||||
|
||||
-- Create inside frame for content
|
||||
local tab_inside_frame = otabs.add{
|
||||
type="frame",
|
||||
name=tab_name.."_if",
|
||||
style = "inside_deep_frame",
|
||||
direction="vertical"}
|
||||
tab_inside_frame.style.left_margin = 10
|
||||
tab_inside_frame.style.right_margin = 10
|
||||
tab_inside_frame.style.top_margin = 4
|
||||
tab_inside_frame.style.bottom_margin = 4
|
||||
tab_inside_frame.style.padding = 5
|
||||
tab_inside_frame.style.horizontally_stretchable = true
|
||||
-- tab_inside_frame.style.vertically_stretchable = true
|
||||
-- tab_inside_frame.style.horizontally_squashable = true
|
||||
-- tab_inside_frame.style.vertically_squashable = true
|
||||
|
||||
-- Add the whole thing to the tab now.
|
||||
otabs.add_tab(new_tab, tab_inside_frame)
|
||||
|
||||
-- Disable all new tabs by default
|
||||
new_tab.enabled = false
|
||||
|
||||
-- If no other tabs are selected, select the first one.
|
||||
if (otabs.selected_tab_index == nil) then
|
||||
otabs.selected_tab_index = 1
|
||||
end
|
||||
end
|
||||
|
||||
function SetOarcStoreTabContent(player, tab_name)
|
||||
if (not DoesOarcStoreExist(player)) then return end
|
||||
|
||||
local otabs = GetOarcStoreTabsPane(player)
|
||||
|
||||
for _,t in ipairs(otabs.tabs) do
|
||||
if (t.tab.name == tab_name) then
|
||||
t.content.clear()
|
||||
OARC_STORE_TAB_CONTENT_FUNCTIONS[tab_name](t.content, player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SetOarcStoreTabEnabled(player, tab_name, enable)
|
||||
if (not DoesOarcStoreExist(player)) then return end
|
||||
|
||||
local otabs = GetOarcStoreTabsPane(player)
|
||||
|
||||
for _,t in ipairs(otabs.tabs) do
|
||||
if (t.tab.name == tab_name) then
|
||||
t.tab.enabled = enable
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function OarcStoreOnGuiClosedEvent(event)
|
||||
if (event.element and (event.element.name == OARC_STORE_GUI)) then
|
||||
HideOarcStore(game.players[event.player_index])
|
||||
end
|
||||
end
|
||||
|
||||
commands.add_command("donate-coins", "Toss a Coin to Your Witcher", function(command)
|
||||
|
||||
local player = game.players[command.player_index]
|
||||
|
||||
if (command.parameter == nil) then
|
||||
player.print("Invalid parameters? /donate-coins [username] [amount]")
|
||||
return
|
||||
end
|
||||
|
||||
local target, amount
|
||||
local count = 1
|
||||
for i in string.gmatch(command.parameter, "%S+") do
|
||||
if (count == 1) then
|
||||
target = i
|
||||
end
|
||||
if (count == 2) then
|
||||
amount = i
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
if (count ~= 3) then
|
||||
player.print("Invalid parameters (count = " ..count..")? /donate-coins [username] [amount]")
|
||||
return
|
||||
end
|
||||
|
||||
-- Validate all the things...
|
||||
if (game.players[target] and
|
||||
not game.players[target].ticks_to_respawn and
|
||||
amount and
|
||||
player and
|
||||
player.get_main_inventory()) then
|
||||
local target_player = game.players[target]
|
||||
local amount_number = tonumber(amount)
|
||||
if ((amount_number > 0) and (player.get_main_inventory().get_item_count("coin") >= amount_number)) then
|
||||
local transfer = target_player.get_main_inventory().insert({name="coin", count=amount_number})
|
||||
player.get_main_inventory().remove({name="coin", count=transfer})
|
||||
player.print("You transfered " .. transfer .. " coins to " .. target .. ".")
|
||||
target_player.print("You received " .. transfer .. " coins from " .. player.name .. ".")
|
||||
else
|
||||
player.print("You can't transfer what you don't have... (Not enough coins!)")
|
||||
end
|
||||
end
|
||||
end)
|
@ -1,163 +0,0 @@
|
||||
-- oarc_enemies.lua
|
||||
-- Feb 2020
|
||||
|
||||
-- This is my second attempt at modifying the normal enemy experience. The
|
||||
-- first attempt ended up in a wave attack system which wasn't well received.
|
||||
-- This attempt will try to intercept normal vanilla enemy groups and modify
|
||||
-- them based on player activity.
|
||||
|
||||
-- Basic logic:
|
||||
-- on_unit_group_finished_gathering we check what command is given.
|
||||
-- find destination position
|
||||
-- check for closest "player" using find_nearest_enemy function
|
||||
-- if a player is found, check if player is part of a shared spawn
|
||||
-- Remove the enemy group if no player in the shared spawn is online.
|
||||
|
||||
-- TODO:
|
||||
-- Add options for modifying the default waves or spawning additional special waves.
|
||||
-- Add option to disable attacks completely for a given spawn.
|
||||
|
||||
-- Generic Utility Includes
|
||||
require("lib/oarc_utils")
|
||||
|
||||
function OarcModifyEnemyGroup(group)
|
||||
|
||||
-- Check validity
|
||||
if ((group == nil) or (group.command == nil) or (group.force.name ~= "enemy")) then
|
||||
log("OarcModifyEnemyGroup ignoring INVALID group/command")
|
||||
return
|
||||
end
|
||||
|
||||
-- Make sure the attack is of a TYPE that we care about.
|
||||
if ((group.command.type == defines.command.attack) or
|
||||
(group.command.type == defines.command.attack_area) or
|
||||
(group.command.type == defines.command.build_base)) then
|
||||
log("OarcModifyEnemyGroup MODIFYING command TYPE=" .. group.command.type)
|
||||
else
|
||||
log("OarcModifyEnemyGroup ignoring command TYPE=" .. group.command.type)
|
||||
return
|
||||
end
|
||||
|
||||
-- defines.command.attack --> target --> target.position
|
||||
if (group.command.type == defines.command.attack) then
|
||||
log("OarcModifyEnemyGroup defines.command.attack NOT IMPLEMENTED YET!")
|
||||
return
|
||||
|
||||
-- defines.command.attack_area --> destination --> closest enemy (within 3 chunk radius?)
|
||||
-- defines.command.build_base --> destination --> closest enemy (expansion chunk distance?)
|
||||
else
|
||||
local destination = group.command.destination
|
||||
|
||||
local distance = CHUNK_SIZE*3
|
||||
if (group.command.type == defines.command.build_base) then
|
||||
distance = CHUNK_SIZE*(game.map_settings.enemy_expansion.max_expansion_distance)
|
||||
end
|
||||
|
||||
-- Find some enemies near the attack point.
|
||||
local target_entities = group.surface.find_entities_filtered{
|
||||
position=destination,
|
||||
radius=distance,
|
||||
force={"enemy", "neutral"},
|
||||
limit=50,
|
||||
invert=true}
|
||||
|
||||
-- Search through them all to find anything with a last_user.
|
||||
local target_entity = nil
|
||||
for _,target in ipairs(target_entities) do
|
||||
if (target.last_user ~= nil) then
|
||||
target_entity = target
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- No enemies nearby?
|
||||
if (target_entity == nil) then
|
||||
if (group.command.type == defines.command.attack_area) then
|
||||
if (global.enable_oe_debug) then
|
||||
SendBroadcastMsg("OarcModifyEnemyGroup find_nearest_enemy attack_area FAILED!?!? " .. GetGPStext(group.position) .. " Target: " .. GetGPStext(destination))
|
||||
end
|
||||
log("OarcModifyEnemyGroup UNEXPECTED find_nearest_enemy did not find anything!")
|
||||
for _,member in pairs(group.members) do
|
||||
member.destroy()
|
||||
end
|
||||
else
|
||||
log("OarcModifyEnemyGroup find_nearest_enemy did not find anything!")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Probably don't need this I hope?
|
||||
if (target_entity.force == "neutral") then
|
||||
log("OarcModifyEnemyGroup UNEXPECTED find_nearest_enemy found neutral target?")
|
||||
for _,member in pairs(group.members) do
|
||||
member.destroy()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Most common target will be a built entity with a "last_user"
|
||||
local target_player = target_entity.last_user
|
||||
|
||||
-- Target could also be a player character (more rare)
|
||||
if (target_player == nil) and (target_entity.type == "character") then
|
||||
target_player = target_entity.player
|
||||
end
|
||||
|
||||
-- I don't think this should happen...
|
||||
if ((target_player == nil) or (not target_player.valid)) then
|
||||
if (global.enable_oe_debug) then
|
||||
SendBroadcastMsg("ERROR?? target_player nil/invalid " .. GetGPStext(group.position) .. " Target: " .. GetGPStext(target_entity.position))
|
||||
end
|
||||
log("OarcModifyEnemyGroup ERROR?? target_player nil/invalid")
|
||||
for _,member in pairs(group.members) do
|
||||
member.destroy()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Is the target player online? Then the attack can go through.
|
||||
if (target_player.connected) then
|
||||
if (global.enable_oe_debug) then
|
||||
SendBroadcastMsg("Enemy group released (player): " .. GetGPStext(group.position) .. " Target: " .. GetGPStext(target_entity.position) .. " " .. target_player.name)
|
||||
end
|
||||
log("OarcModifyEnemyGroup RELEASING enemy group since player is ONLINE")
|
||||
return
|
||||
end
|
||||
|
||||
-- Find the shared spawn that the player is part of.
|
||||
-- This could be the own player's spawn (quite likely)
|
||||
local sharedSpawnOwnerName = FindPlayerSharedSpawn(target_player.name)
|
||||
|
||||
-- Is someone in the shared spawn online?
|
||||
if (sharedSpawnOwnerName ~= nil) then
|
||||
if (GetOnlinePlayersAtSharedSpawn(sharedSpawnOwnerName) > 0) then
|
||||
if (global.enable_oe_debug) then
|
||||
SendBroadcastMsg("Enemy group released (shared): " .. GetGPStext(group.position) .. " Target: " .. GetGPStext(target_entity.position) .. " " .. target_player.name)
|
||||
end
|
||||
log("OarcModifyEnemyGroup RELEASING enemy group since someone in the group is ONLINE")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Is there a buddy spawn and is the buddy online?
|
||||
local buddyName = global.ocore.buddyPairs[sharedSpawnOwnerName]
|
||||
if (buddyName ~= nil) and (game.players[buddyName] ~= nil) then
|
||||
if (game.players[buddyName].connected or (GetOnlinePlayersAtSharedSpawn(buddyName) > 0)) then
|
||||
if (global.enable_oe_debug) then
|
||||
SendBroadcastMsg("Enemy group released (buddy): " .. GetGPStext(group.position) .. " Target: " .. GetGPStext(target_entity.position) .. " " .. target_player.name)
|
||||
end
|
||||
log("OarcModifyEnemyGroup RELEASING enemy group since someone in the BUDDY PAIR is ONLINE")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Otherwise, we delete the group.
|
||||
if (global.enable_oe_debug) then
|
||||
SendBroadcastMsg("Enemy group deleted: " .. GetGPStext(group.position) .. " Target: " .. GetGPStext(target_entity.position) .. " " .. target_player.name)
|
||||
end
|
||||
for _,member in pairs(group.members) do
|
||||
member.destroy()
|
||||
end
|
||||
log("OarcModifyEnemyGroup REMOVED enemy group since nobody was online?")
|
||||
end
|
||||
end
|
@ -1,102 +0,0 @@
|
||||
-- oarc_global_cfg.lua
|
||||
-- April 2019
|
||||
--
|
||||
-- Here is where we store/init config values to the global table.
|
||||
-- Allows runtime modification of game settings if we want it.
|
||||
-- Also allows supporting both MOD and SCENARIO versions.
|
||||
|
||||
-- DON'T JUDGE ME
|
||||
|
||||
|
||||
-- That's a LOT of settings.
|
||||
function InitOarcConfig()
|
||||
|
||||
global.ocfg = {}
|
||||
|
||||
if (game.active_mods["clean-tutorial-grid"]) then
|
||||
global.ocfg.locked_build_area_tile = "clean-tutorial-grid"
|
||||
else
|
||||
global.ocfg.locked_build_area_tile = "tutorial-grid"
|
||||
end
|
||||
|
||||
-- SCENARIO VERSION (ONLY - no more mod version.)
|
||||
global.ocfg.welcome_title = WELCOME_MSG_TITLE
|
||||
global.ocfg.welcome_msg = WELCOME_MSG
|
||||
global.ocfg.server_rules = SERVER_MSG
|
||||
global.ocfg.minimum_online_time = MIN_ONLINE_TIME_IN_MINUTES
|
||||
global.ocfg.server_contact = CONTACT_MSG
|
||||
global.ocfg.enable_vanilla_spawns = ENABLE_VANILLA_SPAWNS
|
||||
global.ocfg.enable_buddy_spawn = ENABLE_BUDDY_SPAWN
|
||||
global.ocfg.frontier_rocket_silo = FRONTIER_ROCKET_SILO_MODE
|
||||
global.ocfg.silo_islands = SILO_ISLANDS_MODE
|
||||
global.ocfg.enable_undecorator = ENABLE_UNDECORATOR
|
||||
global.ocfg.enable_tags = ENABLE_TAGS
|
||||
global.ocfg.enable_long_reach = ENABLE_LONGREACH
|
||||
global.ocfg.enable_autofill = ENABLE_AUTOFILL
|
||||
global.ocfg.enable_miner_decon = ENABLE_MINER_AUTODECON
|
||||
global.ocfg.enable_player_list = ENABLE_PLAYER_LIST
|
||||
global.ocfg.list_offline_players = PLAYER_LIST_OFFLINE_PLAYERS
|
||||
global.ocfg.enable_shared_team_vision = ENABLE_SHARED_TEAM_VISION
|
||||
global.ocfg.enable_regrowth = ENABLE_REGROWTH
|
||||
global.ocfg.enable_abandoned_base_removal = ENABLE_ABANDONED_BASE_REMOVAL
|
||||
global.ocfg.enable_research_queue = ENABLE_RESEARCH_QUEUE
|
||||
global.ocfg.enable_coin_shop = ENABLE_COIN_SHOP
|
||||
global.ocfg.enable_chest_sharing = ENABLE_ITEM_AND_ENERGY_SHARING
|
||||
global.ocfg.enable_magic_factories = ENABLE_MAGIC_FACTORIES
|
||||
global.ocfg.enable_offline_protect = ENABLE_OFFLINE_PROTECTION
|
||||
global.ocfg.enable_power_armor_start = ENABLE_POWER_ARMOR_QUICK_START
|
||||
global.ocfg.enable_modular_armor_start = ENABLE_MODULAR_ARMOR_QUICK_START
|
||||
global.ocfg.lock_goodies_rocket_launch = LOCK_GOODIES_UNTIL_ROCKET_LAUNCH
|
||||
global.ocfg.scale_resources_around_spawns = SCALE_RESOURCES_AROUND_SPAWNS
|
||||
|
||||
global.ocfg.modified_enemy_spawning = OARC_MODIFIED_ENEMY_SPAWNING
|
||||
global.ocfg.near_dist_start = NEAR_MIN_DIST
|
||||
global.ocfg.near_dist_end = NEAR_MAX_DIST
|
||||
global.ocfg.far_dist_start = FAR_MIN_DIST
|
||||
global.ocfg.far_dist_end = FAR_MAX_DIST
|
||||
global.ocfg.vanilla_spawn_count = VANILLA_SPAWN_COUNT
|
||||
global.ocfg.vanilla_spawn_spacing = VANILLA_SPAWN_SPACING
|
||||
|
||||
global.ocfg.spawn_config = OARC_CFG
|
||||
|
||||
global.ocfg.enable_separate_teams = ENABLE_SEPARATE_TEAMS
|
||||
global.ocfg.main_force = MAIN_FORCE
|
||||
global.ocfg.enable_shared_spawns = ENABLE_SHARED_SPAWNS
|
||||
global.ocfg.max_players_shared_spawn = MAX_PLAYERS_AT_SHARED_SPAWN
|
||||
global.ocfg.enable_shared_chat = ENABLE_SHARED_TEAM_CHAT
|
||||
global.ocfg.respawn_cooldown_min = RESPAWN_COOLDOWN_IN_MINUTES
|
||||
global.ocfg.frontier_silo_count = SILO_NUM_SPAWNS
|
||||
global.ocfg.frontier_silo_distance = SILO_CHUNK_DISTANCE
|
||||
global.ocfg.frontier_fixed_pos = SILO_FIXED_POSITION
|
||||
global.ocfg.frontier_pos_table = SILO_POSITIONS
|
||||
global.ocfg.frontier_silo_vision = ENABLE_SILO_VISION
|
||||
global.ocfg.frontier_allow_build = ENABLE_SILO_PLAYER_BUILD
|
||||
|
||||
global.ocfg.enable_anti_grief = ENABLE_ANTI_GRIEFING
|
||||
global.ocfg.ghost_ttl = GHOST_TIME_TO_LIVE
|
||||
global.ocfg.enable_friendly_fire = ENABLE_FRIENDLY_FIRE
|
||||
|
||||
global.ocfg.enable_server_write_files = ENABLE_SERVER_WRITE_FILES
|
||||
|
||||
|
||||
-----------------------
|
||||
-- VALIDATION CHECKS --
|
||||
-----------------------
|
||||
|
||||
if (not global.ocfg.frontier_rocket_silo or not global.ocfg.enable_vanilla_spawns) then
|
||||
global.ocfg.silo_islands = false
|
||||
end
|
||||
|
||||
if (global.ocfg.enable_vanilla_spawns) then
|
||||
global.ocfg.enable_buddy_spawn = false
|
||||
end
|
||||
|
||||
if (not global.ocfg.enable_coin_shop) then
|
||||
global.ocfg.enable_chest_sharing = false
|
||||
end
|
||||
|
||||
if (not global.ocfg.enable_chest_sharing) then
|
||||
global.ocfg.enable_magic_factories = false
|
||||
end
|
||||
|
||||
end
|
@ -1,284 +0,0 @@
|
||||
-- oarc_gui_tabs.lua
|
||||
|
||||
local mod_gui = require("mod-gui")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- GUI Tab Handler
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- NAME of the top level element (outer frame)
|
||||
OARC_GUI = "oarc_gui"
|
||||
|
||||
-- LIST of all implemented tabs and their content Functions
|
||||
OARC_GAME_OPTS_GUI_TAB_NAME = "Server Info"
|
||||
OARC_SPAWN_CTRL_GUI_NAME = "Spawn Controls"
|
||||
OARC_PLAYER_LIST_GUI_TAB_NAME = "Players"
|
||||
OARC_TAGS_GUI_TAB_NAME = "Name Tags"
|
||||
OARC_ROCKETS_GUI_TAB_NAME = "Rockets"
|
||||
OARC_SHARED_ITEMS_GUI_TAB_NAME = "Shared Items"
|
||||
OARC_NOTEPAD_GUI_TAB_NAME = "Notepad"
|
||||
|
||||
local OARC_GUI_TAB_CONTENT_FUNCTIONS = {}
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS["Server Info"] = CreateGameOptionsTab
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS["Spawn Controls"] = CreateSpawnCtrlGuiTab
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS["Players"] = CreatePlayerListGuiTab
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS["Name Tags"] = CreateTagGuiTab
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS["Rockets"] = CreateRocketGuiTab
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS["Shared Items"] = CreateSharedItemsGuiTab
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS["Notepad"] = CreateNotepadGuiTab
|
||||
|
||||
function InitOarcGuiTabs(player)
|
||||
CreateOarcGuiButton(player)
|
||||
|
||||
-- Add general info tab
|
||||
AddOarcGuiTab(player, OARC_GAME_OPTS_GUI_TAB_NAME)
|
||||
SetOarcGuiTabEnabled(player, OARC_GAME_OPTS_GUI_TAB_NAME, true)
|
||||
|
||||
-- Spawn control tab, disabled by default
|
||||
AddOarcGuiTab(player, OARC_SPAWN_CTRL_GUI_NAME)
|
||||
|
||||
-- If player list is enabled, create that
|
||||
if global.ocfg.enable_player_list then
|
||||
AddOarcGuiTab(player, OARC_PLAYER_LIST_GUI_TAB_NAME)
|
||||
SetOarcGuiTabEnabled(player, OARC_PLAYER_LIST_GUI_TAB_NAME, true)
|
||||
end
|
||||
|
||||
-- Player tags
|
||||
if global.ocfg.enable_tags then
|
||||
AddOarcGuiTab(player, OARC_TAGS_GUI_TAB_NAME)
|
||||
SetOarcGuiTabEnabled(player, OARC_TAGS_GUI_TAB_NAME, true)
|
||||
end
|
||||
|
||||
-- Rockets tab, only enable if one has been launched already
|
||||
AddOarcGuiTab(player, OARC_ROCKETS_GUI_TAB_NAME)
|
||||
if (global.ocore.satellite_sent) then
|
||||
SetOarcGuiTabEnabled(player, OARC_ROCKETS_GUI_TAB_NAME, true)
|
||||
end
|
||||
|
||||
if global.ocfg.enable_chest_sharing then
|
||||
AddOarcGuiTab(player, OARC_SHARED_ITEMS_GUI_TAB_NAME)
|
||||
SetOarcGuiTabEnabled(player, OARC_SHARED_ITEMS_GUI_TAB_NAME, true)
|
||||
end
|
||||
|
||||
AddOarcGuiTab(player, OARC_NOTEPAD_GUI_TAB_NAME)
|
||||
SetOarcGuiTabEnabled(player, OARC_NOTEPAD_GUI_TAB_NAME, true)
|
||||
|
||||
HideOarcGui(player)
|
||||
end
|
||||
|
||||
function CreateOarcGuiButton(player)
|
||||
if (mod_gui.get_button_flow(player).oarc_button == nil) then
|
||||
local b = mod_gui.get_button_flow(player).add{name="oarc_button",
|
||||
caption="CLICK ME FOR MORE INFO",
|
||||
type="sprite-button",
|
||||
-- sprite="utility/expand_dots",
|
||||
style=mod_gui.button_style}
|
||||
b.style.padding=2
|
||||
-- b.style.width=20
|
||||
end
|
||||
end
|
||||
|
||||
function DoesOarcGuiExist(player)
|
||||
return (mod_gui.get_frame_flow(player)[OARC_GUI] ~= nil)
|
||||
end
|
||||
|
||||
function IsOarcGuiVisible(player)
|
||||
local of = mod_gui.get_frame_flow(player)[OARC_GUI]
|
||||
return (of.visible)
|
||||
end
|
||||
|
||||
function ShowOarcGui(player)
|
||||
local of = mod_gui.get_frame_flow(player)[OARC_GUI]
|
||||
if (of == nil) then return end
|
||||
of.visible = true
|
||||
player.opened = of
|
||||
end
|
||||
|
||||
function HideOarcGui(player)
|
||||
local of = mod_gui.get_frame_flow(player)[OARC_GUI]
|
||||
if (of == nil) then return end
|
||||
of.visible = false
|
||||
player.opened = nil
|
||||
end
|
||||
|
||||
function GetOarcGuiTabsPane(player)
|
||||
if (mod_gui.get_frame_flow(player)[OARC_GUI] == nil) then
|
||||
return nil
|
||||
else
|
||||
return mod_gui.get_frame_flow(player)[OARC_GUI].oarc_if.oarc_tabs
|
||||
end
|
||||
end
|
||||
|
||||
function ClickOarcGuiButton(event)
|
||||
if not (event and event.element and event.element.valid) then return end
|
||||
local player = game.players[event.player_index]
|
||||
local name = event.element.name
|
||||
|
||||
if (name ~= "oarc_button") then return end
|
||||
|
||||
if (event.element.caption ~= "") then
|
||||
event.element.caption = ""
|
||||
event.element.style.width = 20
|
||||
event.element.sprite="utility/expand_dots"
|
||||
end
|
||||
|
||||
if (not DoesOarcGuiExist(player)) then
|
||||
CreateOarcGuiTabsPane(player)
|
||||
else
|
||||
if (IsOarcGuiVisible(player)) then
|
||||
HideOarcGui(player)
|
||||
else
|
||||
ShowOarcGui(player)
|
||||
FakeTabChangeEventOarcGui(player)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TabChangeOarcGui(event)
|
||||
if (event.element.name ~= "oarc_tabs") then return end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
local otabs = event.element
|
||||
local selected_tab_name = otabs.tabs[otabs.selected_tab_index].tab.name
|
||||
|
||||
-- Clear all tab contents
|
||||
for i,t in pairs(otabs.tabs) do
|
||||
t.content.clear()
|
||||
end
|
||||
|
||||
SetOarGuiTabContent(player, selected_tab_name)
|
||||
end
|
||||
|
||||
function FakeTabChangeEventOarcGui(player)
|
||||
local event = {}
|
||||
event.element = GetOarcGuiTabsPane(player)
|
||||
event.player_index = player.index
|
||||
TabChangeOarcGui(event)
|
||||
end
|
||||
|
||||
function CreateOarcGuiTabsPane(player)
|
||||
|
||||
if (mod_gui.get_frame_flow(player)[OARC_GUI] == nil) then
|
||||
|
||||
-- OUTER FRAME (TOP GUI ELEMENT)
|
||||
local frame = mod_gui.get_frame_flow(player).add{
|
||||
type = 'frame',
|
||||
name = OARC_GUI,
|
||||
direction = "vertical"}
|
||||
frame.style.padding = 5
|
||||
|
||||
-- INNER FRAME
|
||||
local inside_frame = frame.add{
|
||||
type = "frame",
|
||||
name = "oarc_if",
|
||||
style = "inside_deep_frame",
|
||||
direction = "vertical"
|
||||
}
|
||||
|
||||
-- SUB HEADING w/ LABEL
|
||||
local subhead = inside_frame.add{
|
||||
type="frame",
|
||||
name="sub_header",
|
||||
style = "changelog_subheader_frame"}
|
||||
AddLabel(subhead, "scen_info", "Scenario Info and Controls", "subheader_caption_label")
|
||||
|
||||
-- TABBED PANE
|
||||
local oarc_tabs = inside_frame.add{
|
||||
name="oarc_tabs",
|
||||
type="tabbed-pane",
|
||||
style="tabbed_pane"}
|
||||
oarc_tabs.style.top_padding = 8
|
||||
end
|
||||
end
|
||||
|
||||
-- Function creates a new tab.
|
||||
-- It adds whatever it wants to the provided scroll-pane.
|
||||
function AddOarcGuiTab(player, tab_name)
|
||||
if (not DoesOarcGuiExist(player)) then
|
||||
CreateOarcGuiTabsPane(player)
|
||||
end
|
||||
|
||||
-- Get the tabbed pane
|
||||
local otabs = GetOarcGuiTabsPane(player)
|
||||
|
||||
-- Create new tab
|
||||
local new_tab = otabs.add{
|
||||
type="tab",
|
||||
name=tab_name,
|
||||
caption=tab_name}
|
||||
|
||||
-- Create inside frame for content
|
||||
local tab_inside_frame = otabs.add{
|
||||
type="frame",
|
||||
name=tab_name.."_if",
|
||||
style = "inside_deep_frame",
|
||||
direction="vertical"}
|
||||
tab_inside_frame.style.left_margin = 10
|
||||
tab_inside_frame.style.right_margin = 10
|
||||
tab_inside_frame.style.top_margin = 4
|
||||
tab_inside_frame.style.bottom_margin = 4
|
||||
tab_inside_frame.style.padding = 5
|
||||
tab_inside_frame.style.horizontally_stretchable = true
|
||||
-- tab_inside_frame.style.vertically_stretchable = true
|
||||
-- tab_inside_frame.style.horizontally_squashable = true
|
||||
-- tab_inside_frame.style.vertically_squashable = true
|
||||
|
||||
-- Add the whole thing to the tab now.
|
||||
otabs.add_tab(new_tab, tab_inside_frame)
|
||||
|
||||
-- Disable all new tabs by default
|
||||
new_tab.enabled = false
|
||||
|
||||
-- If no other tabs are selected, select the first one.
|
||||
if (otabs.selected_tab_index == nil) then
|
||||
otabs.selected_tab_index = 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function SetOarGuiTabContent(player, tab_name)
|
||||
if (not DoesOarcGuiExist(player)) then return end
|
||||
|
||||
local otabs = GetOarcGuiTabsPane(player)
|
||||
|
||||
for _,t in ipairs(otabs.tabs) do
|
||||
if (t.tab.name == tab_name) then
|
||||
t.content.clear()
|
||||
OARC_GUI_TAB_CONTENT_FUNCTIONS[tab_name](t.content, player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SetOarcGuiTabEnabled(player, tab_name, enable)
|
||||
if (not DoesOarcGuiExist(player)) then return end
|
||||
|
||||
local otabs = GetOarcGuiTabsPane(player)
|
||||
|
||||
for _,t in ipairs(otabs.tabs) do
|
||||
if (t.tab.name == tab_name) then
|
||||
t.tab.enabled = enable
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SwitchOarcGuiTab(player, tab_name)
|
||||
if (not DoesOarcGuiExist(player)) then return end
|
||||
|
||||
local otabs = GetOarcGuiTabsPane(player)
|
||||
|
||||
for i,t in pairs(otabs.tabs) do
|
||||
if (t.tab.name == tab_name) then
|
||||
otabs.selected_tab_index = i
|
||||
FakeTabChangeEventOarcGui(player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function OarcGuiOnGuiClosedEvent(event)
|
||||
if (event.element and (event.element.name == "oarc_gui")) then
|
||||
HideOarcGui(game.players[event.player_index])
|
||||
end
|
||||
end
|
@ -1,152 +0,0 @@
|
||||
-- oarc_gui_utils.lua
|
||||
-- Mar 2019
|
||||
|
||||
-- Generic GUI stuff goes here.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- GUI Styles
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
my_fixed_width_style = {
|
||||
minimal_width = 450,
|
||||
maximal_width = 450
|
||||
}
|
||||
my_label_style = {
|
||||
-- minimal_width = 450,
|
||||
-- maximal_width = 50,
|
||||
single_line = false,
|
||||
font_color = {r=1,g=1,b=1},
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_label_header_style = {
|
||||
single_line = false,
|
||||
font = "heading-1",
|
||||
font_color = {r=1,g=1,b=1},
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_label_header_grey_style = {
|
||||
single_line = false,
|
||||
font = "heading-1",
|
||||
font_color = {r=0.6,g=0.6,b=0.6},
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_note_style = {
|
||||
-- minimal_width = 450,
|
||||
single_line = false,
|
||||
font = "default-small-semibold",
|
||||
font_color = {r=1,g=0.5,b=0.5},
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_warning_style = {
|
||||
-- minimal_width = 450,
|
||||
-- maximal_width = 450,
|
||||
single_line = false,
|
||||
font_color = {r=1,g=0.1,b=0.1},
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_spacer_style = {
|
||||
minimal_height = 10,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_small_button_style = {
|
||||
font = "default-small-semibold"
|
||||
}
|
||||
my_player_list_fixed_width_style = {
|
||||
minimal_width = 200,
|
||||
maximal_width = 400,
|
||||
maximal_height = 200
|
||||
}
|
||||
my_shared_item_list_fixed_width_style = {
|
||||
minimal_width = 200,
|
||||
maximal_width = 600,
|
||||
maximal_height = 600
|
||||
}
|
||||
my_player_list_admin_style = {
|
||||
font = "default-semibold",
|
||||
font_color = {r=1,g=0.5,b=0.5},
|
||||
minimal_width = 200,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0,
|
||||
single_line = false,
|
||||
}
|
||||
my_player_list_style = {
|
||||
font = "default-semibold",
|
||||
minimal_width = 200,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0,
|
||||
single_line = false,
|
||||
}
|
||||
my_player_list_offline_style = {
|
||||
-- font = "default-semibold",
|
||||
font_color = {r=0.5,g=0.5,b=0.5},
|
||||
minimal_width = 200,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0,
|
||||
single_line = false,
|
||||
}
|
||||
my_player_list_style_spacer = {
|
||||
minimal_height = 20,
|
||||
}
|
||||
my_color_red = {r=1,g=0.1,b=0.1}
|
||||
|
||||
my_longer_label_style = {
|
||||
maximal_width = 600,
|
||||
single_line = false,
|
||||
font_color = {r=1,g=1,b=1},
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_longer_warning_style = {
|
||||
maximal_width = 600,
|
||||
single_line = false,
|
||||
font_color = {r=1,g=0.1,b=0.1},
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
my_notepad_fixed_width_style = {
|
||||
minimal_width = 600,
|
||||
maximal_width = 600,
|
||||
minimal_height = 300,
|
||||
maximal_height = 300,
|
||||
font = "default-small-semibold",
|
||||
font_color = {r=0.2,g=0.3,b=0.4},
|
||||
top_margin = 5,
|
||||
bottom_margin = 5
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- GUI Functions
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Apply a style option to a GUI
|
||||
function ApplyStyle (guiIn, styleIn)
|
||||
for k,v in pairs(styleIn) do
|
||||
guiIn.style[k]=v
|
||||
end
|
||||
end
|
||||
|
||||
-- Shorter way to add a label with a style
|
||||
function AddLabel(guiIn, name, message, style)
|
||||
local g = guiIn.add{name = name, type = "label",
|
||||
caption=message}
|
||||
if (type(style) == "table") then
|
||||
ApplyStyle(g, style)
|
||||
else
|
||||
g.style = style
|
||||
end
|
||||
end
|
||||
|
||||
-- Shorter way to add a spacer
|
||||
function AddSpacer(guiIn)
|
||||
ApplyStyle(guiIn.add{type = "label", caption=" "}, my_spacer_style)
|
||||
end
|
||||
|
||||
function AddSpacerLine(guiIn)
|
||||
ApplyStyle(guiIn.add{type = "line", direction="horizontal"}, my_spacer_style)
|
||||
end
|
@ -1,337 +0,0 @@
|
||||
-- oarc_store_map_features.lua
|
||||
-- May 2020
|
||||
-- Adding microtransactions.
|
||||
|
||||
require("lib/shared_chests")
|
||||
require("lib/map_features")
|
||||
local mod_gui = require("mod-gui")
|
||||
|
||||
OARC_STORE_MAP_TEXT =
|
||||
{
|
||||
special_chests = "Special buildings for sharing or monitoring items and energy. This will convert the closest wooden chest (to you) within 16 tiles into a special building of your choice. Make sure to leave enough space! The combinators and accumulators can take up several tiles around them.",
|
||||
special_chunks = "Map features that can be built on the special empty chunks found on the map. You must be standing inside an empty special chunk to be able to build these. Each player can only build one of each type. [color=red]THESE FEATURES ARE PERMANENT AND CAN NOT BE REMOVED![/color]",
|
||||
special_buttons = "Special buttons like teleporting home and placing waterfill.",
|
||||
reset_buttons = "Reset your player and base. [color=red]Choose carefully! Can't be undone.[/color] If you don't own a base and your own force, some options may not be available to you."
|
||||
}
|
||||
|
||||
-- N = number already purchased
|
||||
-- Cost = initial + (additional * ( N^multiplier ))
|
||||
OARC_STORE_MAP_FEATURES =
|
||||
{
|
||||
special_chests = {
|
||||
["logistic-chest-storage"] = {
|
||||
initial_cost = 200,
|
||||
additional_cost = 20,
|
||||
multiplier_cost = 2,
|
||||
max_cost = 2000,
|
||||
-- limit = 100,
|
||||
text="Input chest for storing shared items."},
|
||||
["logistic-chest-requester"] = {
|
||||
initial_cost = 200,
|
||||
additional_cost = 50,
|
||||
multiplier_cost = 2,
|
||||
max_cost = 4000,
|
||||
-- limit = 100,
|
||||
text="Output chest for requesting shared items."},
|
||||
["constant-combinator"] = {
|
||||
initial_cost = 50,
|
||||
text="Combinator setup to monitor shared items."},
|
||||
["accumulator"] = {
|
||||
initial_cost = 200,
|
||||
additional_cost = 50,
|
||||
multiplier_cost = 2,
|
||||
max_cost = 2000,
|
||||
-- limit = 100,
|
||||
text="INPUT for shared energy system. [color=red]Only starts to share once it is charged to 50%.[/color]"},
|
||||
["electric-energy-interface"] = {
|
||||
initial_cost = 200,
|
||||
additional_cost = 100,
|
||||
multiplier_cost = 2,
|
||||
max_cost = 4000,
|
||||
-- limit = 100,
|
||||
text="OUTPUT for shared energy system. [color=red]Will NOT power other special eletric interfaces! You especially can't power special chunks with this![/color]"},
|
||||
["deconstruction-planner"] = {
|
||||
initial_cost = 0,
|
||||
text="Removes the closest special building within range. NO REFUNDS!"},
|
||||
},
|
||||
|
||||
special_chunks = {
|
||||
["electric-furnace"] = {
|
||||
initial_cost = 1000,
|
||||
additional_cost = 1000,
|
||||
multiplier_cost = 2,
|
||||
-- limit = 3,
|
||||
text="Build a special furnace chunk here. Contains 4 furnaces that run at very high speeds. [color=red]Requires energy from the shared storage. Modules have no effect![/color]"},
|
||||
["oil-refinery"] = {
|
||||
initial_cost = 1000,
|
||||
additional_cost = 1000,
|
||||
multiplier_cost = 2,
|
||||
-- limit = 3,
|
||||
text="Build a special oil refinery chunk here. Contains 2 refineries and some chemical plants that run at very high speeds. [color=red]Requires energy from the shared storage. Modules have no effect![/color]"},
|
||||
["assembling-machine-3"] = {
|
||||
initial_cost = 1000,
|
||||
additional_cost = 1000,
|
||||
multiplier_cost = 2,
|
||||
-- limit = 3,
|
||||
text="Build a special assembly machine chunk here. Contains 6 assembling machines that run at very high speeds. [color=red]Requires energy from the shared storage. Modules have no effect![/color]"},
|
||||
["centrifuge"] = {
|
||||
initial_cost = 1000,
|
||||
additional_cost = 1000,
|
||||
multiplier_cost = 2,
|
||||
-- limit = 1,
|
||||
text="Build a special centrifuge chunk here. Contains 1 centrifuge that runs at very high speeds. [color=red]Requires energy from the shared storage. Modules have no effect![/color]"},
|
||||
["rocket-silo"] = {
|
||||
initial_cost = 1000,
|
||||
additional_cost = 0,
|
||||
multiplier_cost = 2,
|
||||
max_cost = 10000,
|
||||
-- limit = 2,
|
||||
text="Convert this special chunk into a rocket launch pad. This allows you to build a rocket silo here!"},
|
||||
},
|
||||
|
||||
-- special_chunks_upgrades = {
|
||||
-- ["big-electric-pole"] = {
|
||||
-- cost = 0,
|
||||
-- text = "Upgrade your special chunk so that it pulls power from the cloud! Refills the accumulator from the cloud automatically if it falls below 50%."
|
||||
-- }
|
||||
|
||||
-- }
|
||||
|
||||
special_buttons = {
|
||||
["assembling-machine-1"] = {
|
||||
initial_cost = 10,
|
||||
text="Teleport home."},
|
||||
["offshore-pump"] = {
|
||||
initial_cost = 50,
|
||||
text="Converts the closest empty wooden chest into a water tile!"
|
||||
}
|
||||
},
|
||||
|
||||
reset_buttons = {
|
||||
["electronic-circuit"] = {
|
||||
initial_cost = 5000,
|
||||
solo_force = true,
|
||||
text="DESTROY your base and restart. This allows you to choose a new spawn and will completely destroy all your buildings and your force. All technology progress will be reset. You get to keep your current items and armor! [color=red]THERE IS NO CONFIRMATION PROMPT! THIS CAN NOT BE UNDONE![/color]"
|
||||
},
|
||||
["advanced-circuit"] = {
|
||||
initial_cost = 5000,
|
||||
solo_force = true,
|
||||
text="ABANDON your base and restart. This allows you to choose a new spawn and will move all your buildings to a neutral force. They will still be on the map and can be interacted with, but will not be owned by any player or player force. All radars will be destroyed to help trim map size. You get to keep your current items and armor! [color=red]THERE IS NO CONFIRMATION PROMPT! THIS CAN NOT BE UNDONE![/color]"
|
||||
},
|
||||
["processing-unit"] = {
|
||||
initial_cost = 5000,
|
||||
text="Restart your game. This will reset your player, your force and your base. [color=red]THERE IS NO CONFIRMATION PROMPT! THIS CAN NOT BE UNDONE![/color]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function CreateMapFeatureStoreTab(tab_container, player)
|
||||
|
||||
local player_inv = player.get_main_inventory()
|
||||
if (player_inv == nil) then return end
|
||||
|
||||
local wallet = player_inv.get_item_count("coin")
|
||||
AddLabel(tab_container,
|
||||
"map_feature_store_wallet_lbl",
|
||||
"Coins Available: " .. wallet .. " [item=coin]",
|
||||
{top_margin=5, bottom_margin=5})
|
||||
AddLabel(tab_container, "coin_info", "Players start with some coins. Earn more coins by killing enemies.", my_note_style)
|
||||
|
||||
local line = tab_container.add{type="line", direction="horizontal"}
|
||||
line.style.top_margin = 5
|
||||
line.style.bottom_margin = 5
|
||||
|
||||
for category,section in pairs(OARC_STORE_MAP_FEATURES) do
|
||||
|
||||
if (not global.ocfg.enable_chest_sharing and (category == "special_chests")) then
|
||||
goto SKIP_CATEGORY
|
||||
end
|
||||
|
||||
if (not global.ocfg.enable_magic_factories and (category == "special_chunks")) then
|
||||
goto SKIP_CATEGORY
|
||||
end
|
||||
|
||||
AddLabel(tab_container,
|
||||
nil,
|
||||
OARC_STORE_MAP_TEXT[category],
|
||||
{bottom_margin=5, maximal_width = 400, single_line = false})
|
||||
local flow = tab_container.add{name = category, type="flow", direction="horizontal"}
|
||||
for item_name,item in pairs(section) do
|
||||
|
||||
local blocked = false
|
||||
if (item.solo_force and ((player.force.name == global.ocfg.main_force) or
|
||||
(not global.ocore.playerSpawns[player.name]))) then
|
||||
blocked = true
|
||||
end
|
||||
|
||||
local count = OarcMapFeaturePlayerCountGet(player, category, item_name)
|
||||
local cost = OarcMapFeatureCostScaling(player, category, item_name)
|
||||
local color = "[color=green]"
|
||||
if ((cost > wallet) or (cost < 0) or blocked) then
|
||||
color = "[color=red]"
|
||||
end
|
||||
local btn = flow.add{name=item_name,
|
||||
type="sprite-button",
|
||||
-- number=item.count,
|
||||
sprite="item/"..item_name,
|
||||
-- tooltip=item.text.." Cost: "..color..cost.."[/color] [item=coin]",
|
||||
style=mod_gui.button_style}
|
||||
if (cost < 0) then
|
||||
btn.enabled = false
|
||||
btn.tooltip = item.text .. "\n "..color..
|
||||
"Limit: ("..count.."/"..item.limit..") [/color]"
|
||||
elseif (blocked) then
|
||||
btn.enabled = false
|
||||
btn.tooltip = item.text .. " (This is only allowed for players on their own force that own the spawn. If you have other players on your force, they must reset first before you can use this.)" .." Cost: "..color..cost.."[/color] [item=coin]"
|
||||
elseif (item.limit) then
|
||||
btn.tooltip = item.text .. "\nCost: "..color..cost.."[/color] [item=coin] "..
|
||||
"Limit: ("..count.."/"..item.limit..")"
|
||||
else
|
||||
btn.tooltip = item.text.." Cost: "..color..cost.."[/color] [item=coin]"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Spacer
|
||||
local line2 = tab_container.add{type="line", direction="horizontal"}
|
||||
line2.style.top_margin = 5
|
||||
line2.style.bottom_margin = 5
|
||||
|
||||
::SKIP_CATEGORY::
|
||||
end
|
||||
end
|
||||
|
||||
function OarcMapFeatureInitGlobalCounters()
|
||||
global.oarc_store = {}
|
||||
global.oarc_store.pmf_counts = {}
|
||||
end
|
||||
|
||||
function OarcMapFeaturePlayerCreatedEvent(player)
|
||||
global.oarc_store.pmf_counts[player.name] = {}
|
||||
end
|
||||
|
||||
function OarcMapFeaturePlayerCountGet(player, category_name, feature_name)
|
||||
if (not global.oarc_store.pmf_counts[player.name][feature_name]) then
|
||||
global.oarc_store.pmf_counts[player.name][feature_name] = 0
|
||||
return 0
|
||||
end
|
||||
|
||||
return global.oarc_store.pmf_counts[player.name][feature_name]
|
||||
end
|
||||
|
||||
function OarcMapFeaturePlayerCountChange(player, category_name, feature_name, change)
|
||||
|
||||
if (not global.oarc_store.pmf_counts[player.name][feature_name]) then
|
||||
if (change < 0) then
|
||||
log("ERROR - OarcMapFeaturePlayerCountChange - Removing when count is not set??")
|
||||
end
|
||||
global.oarc_store.pmf_counts[player.name][feature_name] = change
|
||||
return
|
||||
end
|
||||
|
||||
-- Update count
|
||||
global.oarc_store.pmf_counts[player.name][feature_name] = global.oarc_store.pmf_counts[player.name][feature_name] + change
|
||||
|
||||
-- Make sure we don't go below 0.
|
||||
if (global.oarc_store.pmf_counts[player.name][feature_name] < 0) then
|
||||
global.oarc_store.pmf_counts[player.name][feature_name] = 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Return cost (0 or more) or return -1 if disabled.
|
||||
function OarcMapFeatureCostScaling(player, category_name, feature_name)
|
||||
|
||||
local map_feature = OARC_STORE_MAP_FEATURES[category_name][feature_name]
|
||||
|
||||
-- Check limit first.
|
||||
local count = OarcMapFeaturePlayerCountGet(player, category_name, feature_name)
|
||||
if (map_feature.limit and (count >= map_feature.limit)) then
|
||||
return -1
|
||||
end
|
||||
|
||||
if (map_feature.initial_cost and map_feature.additional_cost and map_feature.multiplier_cost) then
|
||||
local calc_cost = (map_feature.initial_cost + (map_feature.additional_cost*(count^map_feature.multiplier_cost)))
|
||||
if (map_feature.max_cost) then
|
||||
return math.min(map_feature.max_cost, calc_cost)
|
||||
else
|
||||
return calc_cost
|
||||
end
|
||||
else
|
||||
return map_feature.initial_cost
|
||||
end
|
||||
end
|
||||
|
||||
function OarcMapFeatureStoreButton(event)
|
||||
local button = event.element
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
local player_inv = player.get_inventory(defines.inventory.character_main)
|
||||
if (player_inv == nil) then return end
|
||||
local wallet = player_inv.get_item_count("coin")
|
||||
|
||||
local map_feature = OARC_STORE_MAP_FEATURES[button.parent.name][button.name]
|
||||
|
||||
-- Calculate cost based on how many player has purchased?
|
||||
local cost = OarcMapFeatureCostScaling(player, button.parent.name, button.name)
|
||||
|
||||
-- Check if we have enough money
|
||||
if (wallet < cost) then
|
||||
player.print("You're broke! Go kill some enemies or beg for change...")
|
||||
return
|
||||
end
|
||||
|
||||
if (player.vehicle) then
|
||||
player.print("Sir, please step out of the vehicle before you try to make any purchases...")
|
||||
return
|
||||
end
|
||||
|
||||
-- Each button has a special function
|
||||
local result = false
|
||||
if (button.name == "logistic-chest-storage") then
|
||||
result = ConvertWoodenChestToSharedChestInput(player)
|
||||
elseif (button.name == "logistic-chest-requester") then
|
||||
result = ConvertWoodenChestToSharedChestOutput(player)
|
||||
elseif (button.name == "constant-combinator") then
|
||||
result = ConvertWoodenChestToSharedChestCombinators(player)
|
||||
elseif (button.name == "accumulator") then
|
||||
result = ConvertWoodenChestToShareEnergyInput(player)
|
||||
elseif (button.name == "electric-energy-interface") then
|
||||
result = ConvertWoodenChestToShareEnergyOutput(player)
|
||||
elseif (button.name == "deconstruction-planner") then
|
||||
result = DestroyClosestSharedChestEntity(player)
|
||||
elseif (button.name == "electric-furnace") then
|
||||
result = RequestSpawnSpecialChunk(player, SpawnFurnaceChunk, button.name)
|
||||
elseif (button.name == "oil-refinery") then
|
||||
result = RequestSpawnSpecialChunk(player, SpawnOilRefineryChunk, button.name)
|
||||
elseif (button.name == "assembling-machine-3") then
|
||||
result = RequestSpawnSpecialChunk(player, SpawnAssemblyChunk, button.name)
|
||||
elseif (button.name == "centrifuge") then
|
||||
result = RequestSpawnSpecialChunk(player, SpawnCentrifugeChunk, button.name)
|
||||
elseif (button.name == "rocket-silo") then
|
||||
result = RequestSpawnSpecialChunk(player, SpawnSiloChunk, button.name)
|
||||
elseif (button.name == "assembling-machine-1") then
|
||||
SendPlayerToSpawn(player)
|
||||
result = true
|
||||
elseif (button.name == "offshore-pump") then
|
||||
result = ConvertWoodenChestToWaterFill(player)
|
||||
elseif (button.name == "electronic-circuit") then
|
||||
ResetPlayerAndDestroyForce(player)
|
||||
result = true
|
||||
elseif (button.name == "advanced-circuit") then
|
||||
ResetPlayerAndAbandonForce(player)
|
||||
result = true
|
||||
elseif (button.name == "processing-unit") then
|
||||
ResetPlayerAndMergeForceToNeutral(player)
|
||||
result = true
|
||||
end
|
||||
|
||||
-- On success, we deduct money
|
||||
if (result) then
|
||||
player_inv.remove({name = "coin", count = cost})
|
||||
end
|
||||
|
||||
-- Refresh GUI:
|
||||
FakeTabChangeEventOarcStore(player)
|
||||
end
|
@ -1,160 +0,0 @@
|
||||
-- oarc_store_player_items.lua
|
||||
-- May 2020
|
||||
-- Adding microtransactions.
|
||||
|
||||
local mod_gui = require("mod-gui")
|
||||
|
||||
OARC_STORE_PLAYER_ITEMS =
|
||||
{
|
||||
["Guns"] = {
|
||||
["pistol"] = {cost = 1, count = 1, play_time_locked=false},
|
||||
["shotgun"] = {cost = 5, count = 1, play_time_locked=false},
|
||||
["submachine-gun"] = {cost = 10, count = 1, play_time_locked=false},
|
||||
["flamethrower"] = {cost = 50, count = 1, play_time_locked=true},
|
||||
["rocket-launcher"] = {cost = 50, count = 1, play_time_locked=true},
|
||||
-- ["railgun"] = {cost = 250, count = 1, play_time_locked=true}, -- SAD
|
||||
},
|
||||
|
||||
["Turrets"] = {
|
||||
["gun-turret"] = {cost = 25, count = 1, play_time_locked=false},
|
||||
["flamethrower-turret"] = {cost = 50, count = 1, play_time_locked=false},
|
||||
["laser-turret"] = {cost = 75, count = 1, play_time_locked=false},
|
||||
["artillery-turret"] = {cost = 500, count = 1, play_time_locked=true},
|
||||
},
|
||||
|
||||
["Ammo"] = {
|
||||
["firearm-magazine"] = {cost = 10, count = 10, play_time_locked=false},
|
||||
["piercing-rounds-magazine"] = {cost = 30, count = 10, play_time_locked=false},
|
||||
["shotgun-shell"] = {cost = 10, count = 10, play_time_locked=false},
|
||||
["flamethrower-ammo"] = {cost = 50, count = 10, play_time_locked=true},
|
||||
["rocket"] = {cost = 100, count = 10, play_time_locked=true},
|
||||
-- ["railgun-dart"] = {cost = 250, count = 10, play_time_locked=true}, -- SAD
|
||||
["atomic-bomb"] = {cost = 1000, count = 1, play_time_locked=true},
|
||||
["artillery-shell"] = {cost = 50, count = 1, play_time_locked=true},
|
||||
|
||||
},
|
||||
|
||||
["Special"] = {
|
||||
["repair-pack"] = {cost = 1, count = 1, play_time_locked=false},
|
||||
["raw-fish"] = {cost = 1, count = 1, play_time_locked=false},
|
||||
["grenade"] = {cost = 20, count = 10, play_time_locked=true},
|
||||
["cliff-explosives"] = {cost = 20, count = 10, play_time_locked=true},
|
||||
["artillery-targeting-remote"] = {cost = 500, count = 1, play_time_locked=true},
|
||||
},
|
||||
|
||||
["Capsules/Mines"] = {
|
||||
["land-mine"] = {cost = 20, count = 10, play_time_locked=false},
|
||||
["defender-capsule"] = {cost = 20, count = 10, play_time_locked=false},
|
||||
["distractor-capsule"] = {cost = 40, count = 10, play_time_locked=false},
|
||||
["destroyer-capsule"] = {cost = 60, count = 10, play_time_locked=false},
|
||||
["poison-capsule"] = {cost = 50, count = 10, play_time_locked=false},
|
||||
["slowdown-capsule"] = {cost = 25, count = 10, play_time_locked=false},
|
||||
},
|
||||
|
||||
["Armor"] = {
|
||||
["light-armor"] = {cost = 10, count = 1, play_time_locked=false},
|
||||
["heavy-armor"] = {cost = 20, count = 1, play_time_locked=false},
|
||||
["modular-armor"] = {cost = 200, count = 1, play_time_locked=false},
|
||||
["power-armor"] = {cost = 1000, count = 1, play_time_locked=false},
|
||||
["power-armor-mk2"] = {cost = 5000, count = 1, play_time_locked=false},
|
||||
},
|
||||
|
||||
["Power Equipment"] = {
|
||||
["fusion-reactor-equipment"] = {cost = 1000, count = 1, play_time_locked=false},
|
||||
["battery-equipment"] = {cost = 100, count = 1, play_time_locked=false},
|
||||
["battery-mk2-equipment"] = {cost = 1000, count = 1, play_time_locked=false},
|
||||
["solar-panel-equipment"] = {cost = 10, count = 1, play_time_locked=false},
|
||||
},
|
||||
|
||||
["Bot Equipment"] = {
|
||||
["personal-roboport-equipment"] = {cost = 100, count = 1, play_time_locked=false},
|
||||
["personal-roboport-mk2-equipment"] = {cost = 500, count = 1, play_time_locked=false},
|
||||
["construction-robot"] = {cost = 100, count = 10, play_time_locked=false},
|
||||
["roboport"] = {cost = 1000, count = 1, play_time_locked=false},
|
||||
["logistic-chest-storage"] = {cost = 100, count = 1, play_time_locked=false},
|
||||
},
|
||||
|
||||
["Misc Equipment"] = {
|
||||
["belt-immunity-equipment"] = {cost = 10, count = 1, play_time_locked=false},
|
||||
["exoskeleton-equipment"] = {cost = 100, count = 1, play_time_locked=false},
|
||||
["night-vision-equipment"] = {cost = 50, count = 1, play_time_locked=false},
|
||||
|
||||
["personal-laser-defense-equipment"] = {cost = 100, count = 1, play_time_locked=false},
|
||||
-- ["discharge-defense-equipment"] = {cost = 1, count = 1, play_time_locked=false},
|
||||
["energy-shield-equipment"] = {cost = 50, count = 1, play_time_locked=false},
|
||||
["energy-shield-mk2-equipment"] = {cost = 500, count = 1, play_time_locked=false},
|
||||
},
|
||||
|
||||
["Spidertron"] = {
|
||||
["spidertron"] = {cost = 5000, count = 1, play_time_locked=false},
|
||||
["spidertron-remote"] = {cost = 500, count = 1, play_time_locked=false},
|
||||
},
|
||||
}
|
||||
|
||||
function CreatePlayerStoreTab(tab_container, player)
|
||||
|
||||
local player_inv = player.get_main_inventory()
|
||||
if (player_inv == nil) then return end
|
||||
|
||||
local wallet = player_inv.get_item_count("coin")
|
||||
AddLabel(tab_container,
|
||||
"player_store_wallet_lbl",
|
||||
"Coins Available: " .. wallet .. " [item=coin]",
|
||||
{top_margin=5, bottom_margin=5})
|
||||
AddLabel(tab_container, "coin_info", "Players start with some coins. Earn more coins by killing enemies.", my_note_style)
|
||||
AddLabel(tab_container,
|
||||
"player_store_note_lbl",
|
||||
"Locked items become available after playing for awhile...",
|
||||
my_note_style)
|
||||
|
||||
local line = tab_container.add{type="line", direction="horizontal"}
|
||||
line.style.top_margin = 5
|
||||
line.style.bottom_margin = 5
|
||||
|
||||
for category,section in pairs(OARC_STORE_PLAYER_ITEMS) do
|
||||
local flow = tab_container.add{name = category, type="flow", direction="horizontal"}
|
||||
for item_name,item in pairs(section) do
|
||||
local color = "[color=green]"
|
||||
if (item.cost > wallet) then
|
||||
color = "[color=red]"
|
||||
end
|
||||
local btn = flow.add{name=item_name,
|
||||
type="sprite-button",
|
||||
number=item.count,
|
||||
sprite="item/"..item_name,
|
||||
tooltip=item_name .. " Cost: "..color..item.cost.."[/color] [item=coin]",
|
||||
style=mod_gui.button_style}
|
||||
if (item.play_time_locked and (player.online_time < TICKS_PER_MINUTE*15)) then
|
||||
btn.enabled = false
|
||||
end
|
||||
end
|
||||
local line2 = tab_container.add{type="line", direction="horizontal"}
|
||||
line2.style.top_margin = 5
|
||||
line2.style.bottom_margin = 5
|
||||
end
|
||||
end
|
||||
|
||||
function OarcPlayerStoreButton(event)
|
||||
local button = event.element
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
local player_inv = player.get_inventory(defines.inventory.character_main)
|
||||
if (player_inv == nil) then return end
|
||||
|
||||
local category = button.parent.name
|
||||
|
||||
local item = OARC_STORE_PLAYER_ITEMS[category][button.name]
|
||||
|
||||
if (player_inv.get_item_count("coin") >= item.cost) then
|
||||
player_inv.insert({name = button.name, count = item.count})
|
||||
player_inv.remove({name = "coin", count = item.cost})
|
||||
|
||||
if (button.parent and button.parent.parent and button.parent.parent.player_store_wallet_lbl) then
|
||||
local wallet = player_inv.get_item_count("coin")
|
||||
button.parent.parent.player_store_wallet_lbl.caption = "Coins Available: " .. wallet .. " [item=coin]"
|
||||
end
|
||||
|
||||
else
|
||||
player.print("You're broke! Go kill some enemies or beg for change...")
|
||||
end
|
||||
end
|
1362
lib/oarc_utils.lua
1362
lib/oarc_utils.lua
File diff suppressed because it is too large
Load Diff
@ -1,36 +0,0 @@
|
||||
-- oarc_player_list.lua
|
||||
-- Mar 2019
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Player List GUI - My own version
|
||||
--------------------------------------------------------------------------------
|
||||
function CreatePlayerListGuiTab(tab_container, player)
|
||||
local scrollFrame = tab_container.add{type="scroll-pane",
|
||||
name="playerList-panel",
|
||||
direction = "vertical"}
|
||||
ApplyStyle(scrollFrame, my_player_list_fixed_width_style)
|
||||
scrollFrame.horizontal_scroll_policy = "never"
|
||||
|
||||
AddLabel(scrollFrame, "online_title_msg", "Online Players:", my_label_header_style)
|
||||
for _,player in pairs(game.connected_players) do
|
||||
local caption_str = player.name.." ["..player.force.name.."]".." ("..formattime_hours_mins(player.online_time)..")"
|
||||
if (player.admin) then
|
||||
AddLabel(scrollFrame, player.name.."_plist", caption_str, my_player_list_admin_style)
|
||||
else
|
||||
AddLabel(scrollFrame, player.name.."_plist", caption_str, my_player_list_style)
|
||||
end
|
||||
end
|
||||
|
||||
-- List offline players
|
||||
if (global.ocfg.list_offline_players) then
|
||||
AddSpacerLine(scrollFrame)
|
||||
AddLabel(scrollFrame, "offline_title_msg", "Offline Players:", my_label_header_grey_style)
|
||||
for _,player in pairs(game.players) do
|
||||
if (not player.connected) then
|
||||
local caption_str = player.name.." ["..player.force.name.."]".." ("..formattime_hours_mins(player.online_time)..")"
|
||||
local text = scrollFrame.add{type="label", caption=caption_str, name=player.name.."_plist"}
|
||||
ApplyStyle(text, my_player_list_offline_style)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,385 +0,0 @@
|
||||
-- regrowth_map.lua
|
||||
-- Sep 2019
|
||||
-- REVERTED BACK TO SOFT MOD
|
||||
|
||||
-- Code tracks all chunks generated and allows for deleting of inactive chunks.
|
||||
--
|
||||
-- Basic rules of regrowth:
|
||||
-- 1. Area around player is safe for quite a large distance.
|
||||
-- 2. Chunks with pollution won't be deleted.
|
||||
-- 3. Chunks with any player buildings won't be deleted.
|
||||
-- 4. Anything within radar range won't be deleted, but radar MUST be active.
|
||||
-- -- This works by refreshing all chunk timers within radar range using
|
||||
-- the on_sector_scanned event.
|
||||
-- 5. Chunks timeout after 1 hour-ish, configurable
|
||||
|
||||
require("lib/oarc_utils")
|
||||
require("config")
|
||||
|
||||
REGROWTH_TIMEOUT_TICKS = TICKS_PER_HOUR -- TICKS_PER_HOUR TICKS_PER_MINUTE
|
||||
|
||||
-- Init globals and set player join area to be off limits.
|
||||
function RegrowthInit()
|
||||
global.rg = {}
|
||||
global.rg.player_refresh_index = nil
|
||||
global.rg.force_removal_flag = -2000
|
||||
global.rg.map = {}
|
||||
global.rg.removal_list = {}
|
||||
global.rg.chunk_iter = nil
|
||||
global.rg.world_eater_iter = nil
|
||||
global.rg.timeout_ticks = REGROWTH_TIMEOUT_TICKS
|
||||
end
|
||||
|
||||
function TriggerCleanup()
|
||||
global.rg.force_removal_flag = game.tick
|
||||
end
|
||||
|
||||
function RegrowthForceRemoveChunksCmd(cmd_table)
|
||||
if (game.players[cmd_table.player_index].admin) then
|
||||
TriggerCleanup()
|
||||
end
|
||||
end
|
||||
|
||||
-- Get the next player index available
|
||||
function GetNextPlayerIndex(player_index)
|
||||
if (not global.rg.player_refresh_index or not game.players[global.rg.player_refresh_index]) then
|
||||
global.rg.player_refresh_index = 1
|
||||
else
|
||||
global.rg.player_refresh_index = global.rg.player_refresh_index + 1
|
||||
end
|
||||
|
||||
if (global.rg.player_refresh_index > #game.players) then
|
||||
global.rg.player_refresh_index = 1
|
||||
end
|
||||
|
||||
return global.rg.player_refresh_index
|
||||
end
|
||||
|
||||
-- Adds new chunks to the global table to track them.
|
||||
-- This should always be called first in the chunk generate sequence
|
||||
-- (Compared to other RSO & Oarc related functions...)
|
||||
function RegrowthChunkGenerate(event)
|
||||
local c_pos = GetChunkPosFromTilePos(event.area.left_top)
|
||||
|
||||
-- Surface must be "added" first.
|
||||
if (global.rg == nil) then return end
|
||||
|
||||
-- If this is the first chunk in that row:
|
||||
if (global.rg.map[c_pos.x] == nil) then
|
||||
global.rg.map[c_pos.x] = {}
|
||||
end
|
||||
|
||||
-- Only update it if it isn't already set!
|
||||
if (global.rg.map[c_pos.x][c_pos.y] == nil) then
|
||||
global.rg.map[c_pos.x][c_pos.y] = game.tick
|
||||
end
|
||||
end
|
||||
|
||||
-- Mark an area for "immediate" forced removal
|
||||
function RegrowthMarkAreaForRemoval(pos, chunk_radius)
|
||||
local c_pos = GetChunkPosFromTilePos(pos)
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.rg.map[x] ~= nil) then
|
||||
global.rg.map[x][y] = nil
|
||||
end
|
||||
table.insert(global.rg.removal_list, {pos={x=x,y=y},force=true})
|
||||
end
|
||||
if (table_size(global.rg.map[x]) == 0) then
|
||||
global.rg.map[x] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Downgrades permanent flag to semi-permanent.
|
||||
function RegrowthMarkAreaNotPermanentOVERWRITE(pos, chunk_radius)
|
||||
local c_pos = GetChunkPosFromTilePos(pos)
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.rg.map[x] and global.rg.map[x][y] and (global.rg.map[x][y] == -2)) then
|
||||
global.rg.map[x][y] = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Marks a chunk containing a position to be relatively permanent.
|
||||
function MarkChunkSafe(c_pos, permanent)
|
||||
if (global.rg.map[c_pos.x] == nil) then
|
||||
global.rg.map[c_pos.x] = {}
|
||||
end
|
||||
|
||||
if (permanent) then
|
||||
global.rg.map[c_pos.x][c_pos.y] = -2
|
||||
|
||||
-- Make sure we don't overwrite...
|
||||
elseif (global.rg.map[c_pos.x][c_pos.y] and (global.rg.map[c_pos.x][c_pos.y] ~= -2)) then
|
||||
global.rg.map[c_pos.x][c_pos.y] = -1
|
||||
end
|
||||
end
|
||||
|
||||
-- Marks a safe area around a CHUNK position to be relatively permanent.
|
||||
function RegrowthMarkAreaSafeGivenChunkPos(c_pos, chunk_radius, permanent)
|
||||
if (global.rg == nil) then return end
|
||||
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
for j=-chunk_radius,chunk_radius do
|
||||
MarkChunkSafe({x=c_pos.x+i,y=c_pos.y+j}, permanent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Marks a safe area around a TILE position to be relatively permanent.
|
||||
function RegrowthMarkAreaSafeGivenTilePos(pos, chunk_radius, permanent)
|
||||
if (global.rg == nil) then return end
|
||||
|
||||
local c_pos = GetChunkPosFromTilePos(pos)
|
||||
RegrowthMarkAreaSafeGivenChunkPos(c_pos, chunk_radius, permanent)
|
||||
end
|
||||
|
||||
-- Refreshes timers on a chunk containing position
|
||||
function RefreshChunkTimer(pos, bonus_time)
|
||||
local c_pos = GetChunkPosFromTilePos(pos)
|
||||
|
||||
if (global.rg.map[c_pos.x] == nil) then
|
||||
global.rg.map[c_pos.x] = {}
|
||||
end
|
||||
if (global.rg.map[c_pos.x][c_pos.y] >= 0) then
|
||||
global.rg.map[c_pos.x][c_pos.y] = game.tick + bonus_time
|
||||
end
|
||||
end
|
||||
|
||||
-- Refreshes timers on all chunks around a certain area
|
||||
function RefreshArea(pos, chunk_radius, bonus_time)
|
||||
local c_pos = GetChunkPosFromTilePos(pos)
|
||||
|
||||
for i=-chunk_radius,chunk_radius do
|
||||
local x = c_pos.x+i
|
||||
for k=-chunk_radius,chunk_radius do
|
||||
local y = c_pos.y+k
|
||||
|
||||
if (global.rg.map[x] == nil) then
|
||||
global.rg.map[x] = {}
|
||||
end
|
||||
if ((global.rg.map[x][y] == nil) or (global.rg.map[x][y] >= 0)) then
|
||||
global.rg.map[x][y] = game.tick + bonus_time
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Refreshes timers on all chunks near an ACTIVE radar
|
||||
function RegrowthSectorScan(event)
|
||||
if (event.radar.surface.name ~= GAME_SURFACE_NAME) then return end
|
||||
|
||||
RefreshArea(event.radar.position, 14, 0)
|
||||
end
|
||||
|
||||
-- Refresh all chunks near a single player. Cyles through all connected players.
|
||||
function RefreshPlayerArea()
|
||||
player_index = GetNextPlayerIndex()
|
||||
if (player_index and game.connected_players[player_index]) then
|
||||
local player = game.connected_players[player_index]
|
||||
|
||||
if (not player.character) then return end
|
||||
if (player.character.surface.name ~= GAME_SURFACE_NAME) then return end
|
||||
|
||||
RefreshArea(player.position, 4, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Gets the next chunk the array map and checks to see if it has timed out.
|
||||
-- Adds it to the removal list if it has.
|
||||
function RegrowthSingleStepArray()
|
||||
|
||||
-- Make sure we have a valid iterator!
|
||||
if (not global.rg.chunk_iter or not global.rg.chunk_iter.valid) then
|
||||
global.rg.chunk_iter = game.surfaces[GAME_SURFACE_NAME].get_chunks()
|
||||
end
|
||||
|
||||
local next_chunk = global.rg.chunk_iter()
|
||||
|
||||
-- Check if we reached the end
|
||||
if (not next_chunk) then
|
||||
global.rg.chunk_iter = game.surfaces[GAME_SURFACE_NAME].get_chunks()
|
||||
next_chunk = global.rg.chunk_iter()
|
||||
end
|
||||
|
||||
-- Do we have it in our map?
|
||||
if (not global.rg.map[next_chunk.x] or not global.rg.map[next_chunk.x][next_chunk.y]) then
|
||||
return -- Chunk isn't in our map so we don't care?
|
||||
end
|
||||
|
||||
-- If the chunk has timed out, add it to the removal list
|
||||
local c_timer = global.rg.map[next_chunk.x][next_chunk.y]
|
||||
if ((c_timer ~= nil) and (c_timer >= 0) and ((c_timer + global.rg.timeout_ticks) < game.tick)) then
|
||||
|
||||
-- Check chunk actually exists
|
||||
if (game.surfaces[GAME_SURFACE_NAME].is_chunk_generated({x=next_chunk.x, y=next_chunk.y})) then
|
||||
table.insert(global.rg.removal_list, {pos={x=next_chunk.x, y=next_chunk.y}, force=false})
|
||||
global.rg.map[next_chunk.x][next_chunk.y] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove all chunks at same time to reduce impact to FPS/UPS
|
||||
function OarcRegrowthRemoveAllChunks()
|
||||
for key,c_remove in pairs(global.rg.removal_list) do
|
||||
local c_pos = c_remove.pos
|
||||
|
||||
-- Confirm chunk is still expired
|
||||
if (not global.rg.map[c_pos.x] or not global.rg.map[c_pos.x][c_pos.y]) then
|
||||
|
||||
-- If it is FORCE removal, then remove it regardless of pollution.
|
||||
if (c_remove.force) then
|
||||
game.surfaces[GAME_SURFACE_NAME].delete_chunk(c_pos)
|
||||
|
||||
-- If it is a normal timeout removal, don't do it if there is pollution in the chunk.
|
||||
elseif (game.surfaces[GAME_SURFACE_NAME].get_pollution({c_pos.x*32,c_pos.y*32}) > 0) then
|
||||
global.rg.map[c_pos.x][c_pos.y] = game.tick
|
||||
|
||||
-- Else delete the chunk
|
||||
else
|
||||
game.surfaces[GAME_SURFACE_NAME].delete_chunk(c_pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove entry
|
||||
global.rg.removal_list[key] = nil
|
||||
end
|
||||
|
||||
-- MUST GET A NEW CHUNK ITERATOR ON DELETE CHUNK!
|
||||
global.rg.chunk_iter = nil
|
||||
global.rg.world_eater_iter = nil
|
||||
end
|
||||
|
||||
-- This is the main work function, it checks a single chunk in the list
|
||||
-- per tick. It works according to the rules listed in the header of this
|
||||
-- file.
|
||||
function RegrowthOnTick()
|
||||
|
||||
-- Every half a second, refresh all chunks near a single player
|
||||
-- Cyles through all players. Tick is offset by 2
|
||||
if ((game.tick % (30)) == 2) then
|
||||
RefreshPlayerArea()
|
||||
end
|
||||
|
||||
-- Every tick, check a few points in the 2d array of the only active surface According to /measured-command this
|
||||
-- shouldn't take more than 0.1ms on average
|
||||
for i=1,20 do
|
||||
RegrowthSingleStepArray()
|
||||
end
|
||||
|
||||
if (not global.world_eater_disable) then
|
||||
WorldEaterSingleStep()
|
||||
end
|
||||
|
||||
-- Allow enable/disable of auto cleanup, can change during runtime.
|
||||
local interval_ticks = global.rg.timeout_ticks
|
||||
-- Send a broadcast warning before it happens.
|
||||
if ((game.tick % interval_ticks) == interval_ticks-(60*30 + 1)) then
|
||||
if (#global.rg.removal_list > 100) then
|
||||
SendBroadcastMsg("Map cleanup in 30 seconds... Unused and old map chunks will be deleted!")
|
||||
end
|
||||
end
|
||||
|
||||
-- Delete all listed chunks across all active surfaces
|
||||
if ((game.tick % interval_ticks) == interval_ticks-1) then
|
||||
if (#global.rg.removal_list > 100) then
|
||||
OarcRegrowthRemoveAllChunks()
|
||||
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function removes any chunks flagged but on demand.
|
||||
-- Controlled by the global.rg.force_removal_flag
|
||||
-- This function may be used outside of the normal regrowth modse.
|
||||
function RegrowthForceRemovalOnTick()
|
||||
-- Catch force remove flag
|
||||
if (game.tick == global.rg.force_removal_flag+60) then
|
||||
SendBroadcastMsg("Map cleanup (forced) in 30 seconds... Unused and old map chunks will be deleted!")
|
||||
end
|
||||
|
||||
if (game.tick == global.rg.force_removal_flag+(60*30 + 60)) then
|
||||
OarcRegrowthRemoveAllChunks()
|
||||
SendBroadcastMsg("Map cleanup done, sorry for your loss.")
|
||||
end
|
||||
end
|
||||
|
||||
function WorldEaterSingleStep()
|
||||
|
||||
-- Make sure we have a valid iterator!
|
||||
if (not global.rg.world_eater_iter or not global.rg.world_eater_iter.valid) then
|
||||
global.rg.world_eater_iter = game.surfaces[GAME_SURFACE_NAME].get_chunks()
|
||||
end
|
||||
|
||||
local next_chunk = global.rg.world_eater_iter()
|
||||
|
||||
-- Check if we reached the end
|
||||
if (not next_chunk) then
|
||||
global.rg.world_eater_iter = game.surfaces[GAME_SURFACE_NAME].get_chunks()
|
||||
next_chunk = global.rg.world_eater_iter()
|
||||
end
|
||||
|
||||
-- Do we have it in our map?
|
||||
if (not global.rg.map[next_chunk.x] or not global.rg.map[next_chunk.x][next_chunk.y]) then
|
||||
return -- Chunk isn't in our map so we don't care?
|
||||
end
|
||||
|
||||
-- Search for any abandoned radars and destroy them?
|
||||
local entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area=next_chunk.area,
|
||||
force={global.ocore.abandoned_force},
|
||||
name="radar"}
|
||||
for k,v in pairs(entities) do
|
||||
v.die(nil)
|
||||
end
|
||||
|
||||
-- Search for any entities with _DESTROYED_ force and kill them.
|
||||
entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area=next_chunk.area,
|
||||
force={global.ocore.destroyed_force}}
|
||||
for k,v in pairs(entities) do
|
||||
v.die(nil)
|
||||
end
|
||||
|
||||
-- If the chunk isn't marked permament, then check if we can remove it
|
||||
local c_timer = global.rg.map[next_chunk.x][next_chunk.y]
|
||||
if (c_timer == -1) then
|
||||
|
||||
local area = {left_top = {next_chunk.area.left_top.x-8, next_chunk.area.left_top.y-8},
|
||||
right_bottom = {next_chunk.area.right_bottom.x+8, next_chunk.area.right_bottom.y+8}}
|
||||
|
||||
local entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area=area, force={"enemy", "neutral"}, invert=true}
|
||||
local total_count = #entities
|
||||
local has_last_user_set = false
|
||||
|
||||
if (total_count > 0) then
|
||||
for k,v in pairs(entities) do
|
||||
if (v.last_user or (v.type == "character") or string.contains(v.type, "robot")) then
|
||||
has_last_user_set = true
|
||||
return -- This means we're done checking this chunk.
|
||||
end
|
||||
end
|
||||
|
||||
-- If all entities found have no last user, then KILL all entities!
|
||||
if (not has_last_user_set) then
|
||||
for k,v in pairs(entities) do
|
||||
if (v and v.valid) then
|
||||
v.die(nil)
|
||||
end
|
||||
end
|
||||
-- SendBroadcastMsg(next_chunk.x .. "," .. next_chunk.y .. " WorldEaterSingleStep - ENTITIES FOUND")
|
||||
global.rg.map[next_chunk.x][next_chunk.y] = game.tick -- Set the timer on it.
|
||||
end
|
||||
else
|
||||
-- SendBroadcastMsg(next_chunk.x .. "," .. next_chunk.y .. " WorldEaterSingleStep - NO ENTITIES FOUND")
|
||||
global.rg.map[next_chunk.x][next_chunk.y] = game.tick -- Set the timer on it.
|
||||
end
|
||||
end
|
||||
end
|
@ -1,49 +0,0 @@
|
||||
|
||||
local function RemoveTileGhosts()
|
||||
local surface = game.player.surface
|
||||
for c in surface.get_chunks() do
|
||||
for key, entity in pairs(surface.find_entities_filtered({area={{c.x * 32, c.y * 32}, {c.x * 32 + 32, c.y * 32 + 32}}, name= "tile-ghost"})) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function RemoveBlueprintedModulesGhosts()
|
||||
local surface = game.player.surface
|
||||
for c in surface.get_chunks() do
|
||||
for key, entity in pairs(surface.find_entities_filtered({area={{c.x * 32, c.y * 32}, {c.x * 32 + 32, c.y * 32 + 32}}, name= "item-request-proxy"})) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function RemoveGhostEntities()
|
||||
local surface = game.player.surface
|
||||
for c in surface.get_chunks() do
|
||||
for key, entity in pairs(surface.find_entities_filtered({area={{c.x * 32, c.y * 32}, {c.x * 32 + 32, c.y * 32 + 32}}, name= "entity-ghost"})) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
commands.add_command("rg", "remove ghosts", function(command)
|
||||
local player = game.players[command.player_index];
|
||||
if player ~= nil and player.admin then
|
||||
if (command.parameter ~= nil) then
|
||||
if command.parameter == "all" then
|
||||
RemoveTileGhosts()
|
||||
RemoveBlueprintedModulesGhosts()
|
||||
RemoveGhostEntities()
|
||||
elseif command.parameter == "tiles" then
|
||||
RemoveTileGhosts()
|
||||
elseif command.parameter == "modules" then
|
||||
RemoveBlueprintedModulesGhosts()
|
||||
elseif command.parameter == "entities" then
|
||||
RemoveGhostEntities()
|
||||
else
|
||||
player.print("remove all ghostes | tiles | modules | entities");
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
@ -1,78 +0,0 @@
|
||||
-- rocket_launch.lua
|
||||
-- May 2019
|
||||
|
||||
-- This is meant to extract out any rocket launch related logic to support my oarc scenario designs.
|
||||
|
||||
require("lib/oarc_utils")
|
||||
require("config")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Rocket Launch Event Code
|
||||
-- Controls the "win condition"
|
||||
--------------------------------------------------------------------------------
|
||||
function RocketLaunchEvent(event)
|
||||
local force = event.rocket.force
|
||||
|
||||
-- Notify players on force if rocket was launched without sat.
|
||||
if event.rocket.get_item_count("satellite") == 0 then
|
||||
for index, player in pairs(force.players) do
|
||||
player.print("You launched the rocket, but you didn't put a satellite inside.")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- First ever sat launch
|
||||
if not global.ocore.satellite_sent then
|
||||
global.ocore.satellite_sent = {}
|
||||
SendBroadcastMsg("Team " .. force.name .. " was the first to launch a rocket!")
|
||||
ServerWriteFile("rocket_events", "Team " .. force.name .. " was the first to launch a rocket!" .. "\n")
|
||||
|
||||
for name,player in pairs(game.players) do
|
||||
SetOarcGuiTabEnabled(player, OARC_ROCKETS_GUI_TAB_NAME, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Track additional satellites launched by this force
|
||||
if global.ocore.satellite_sent[force.name] then
|
||||
global.ocore.satellite_sent[force.name] = global.ocore.satellite_sent[force.name] + 1
|
||||
SendBroadcastMsg("Team " .. force.name .. " launched another rocket. Total " .. global.ocore.satellite_sent[force.name])
|
||||
ServerWriteFile("rocket_events", "Team " .. force.name .. " launched another rocket. Total " .. global.ocore.satellite_sent[force.name] .. "\n")
|
||||
|
||||
-- First sat launch for this force.
|
||||
else
|
||||
-- game.set_game_state{game_finished=true, player_won=true, can_continue=true}
|
||||
global.ocore.satellite_sent[force.name] = 1
|
||||
SendBroadcastMsg("Team " .. force.name .. " launched their first rocket!")
|
||||
ServerWriteFile("rocket_events", "Team " .. force.name .. " launched their first rocket!" .. "\n")
|
||||
|
||||
-- Unlock research and recipes
|
||||
if global.ocfg.lock_goodies_rocket_launch then
|
||||
for _,v in ipairs(LOCKED_TECHNOLOGIES) do
|
||||
EnableTech(force, v.t)
|
||||
end
|
||||
for _,v in ipairs(LOCKED_RECIPES) do
|
||||
if (force.technologies[v.r].researched) then
|
||||
AddRecipe(force, v.r)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CreateRocketGuiTab(tab_container, player)
|
||||
-- local frame = tab_container.add{type="frame", name="rocket-panel", caption="Satellites Launched:", direction = "vertical"}
|
||||
|
||||
AddLabel(tab_container, nil, "Satellites Launched:", my_label_header_style)
|
||||
|
||||
if (global.ocore.satellite_sent == nil) then
|
||||
AddLabel(tab_container, nil, "No launches yet.", my_label_style)
|
||||
else
|
||||
for force_name,sat_count in pairs(global.ocore.satellite_sent) do
|
||||
AddLabel(tab_container,
|
||||
"rc_"..force_name,
|
||||
"Team " .. force_name .. ": " .. tostring(sat_count),
|
||||
my_label_style)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,689 +0,0 @@
|
||||
-- shared_chests.lua
|
||||
-- Feb 2020
|
||||
-- Oarc's silly idea for a scripted item sharing solution.
|
||||
|
||||
-- Buffer size is the limit of joules/tick so multiply by 60 to get /sec.
|
||||
SHARED_ELEC_OUTPUT_BUFFER_SIZE = 1000000000
|
||||
SHARED_ELEC_INPUT_BUFFER_SIZE = 1000000001
|
||||
|
||||
SHARED_ENERGY_STARTING_VALUE = 0 -- 100GJ
|
||||
|
||||
function SharedChestInitItems()
|
||||
|
||||
global.oshared = {}
|
||||
|
||||
global.oshared.chests = {}
|
||||
global.oshared.requests = {}
|
||||
global.oshared.requests_totals = {}
|
||||
|
||||
global.oshared.electricity_inputs = {}
|
||||
global.oshared.electricity_outputs = {}
|
||||
|
||||
global.oshared.chests_combinators = {}
|
||||
global.oshared.items = {}
|
||||
|
||||
global.oshared.items['red-wire'] = 10000
|
||||
global.oshared.items['green-wire'] = 10000
|
||||
global.oshared.items['raw-fish'] = 10000
|
||||
|
||||
global.oshared.energy_stored = SHARED_ENERGY_STARTING_VALUE
|
||||
global.oshared.energy_stored_history = {start=SHARED_ENERGY_STARTING_VALUE, after_input=SHARED_ENERGY_STARTING_VALUE, after_output=SHARED_ENERGY_STARTING_VALUE}
|
||||
end
|
||||
|
||||
function SharedEnergySpawnInput(player, pos)
|
||||
|
||||
local inputElec = game.surfaces[GAME_SURFACE_NAME].create_entity{name="electric-energy-interface", position=pos, force="neutral"}
|
||||
inputElec.destructible = false
|
||||
inputElec.minable = false
|
||||
inputElec.operable = false
|
||||
inputElec.last_user = player
|
||||
|
||||
inputElec.electric_buffer_size = SHARED_ELEC_INPUT_BUFFER_SIZE
|
||||
inputElec.power_production = 0
|
||||
inputElec.power_usage = 0
|
||||
inputElec.energy = 0
|
||||
|
||||
local inputElecCombi = game.surfaces[GAME_SURFACE_NAME].create_entity{name="constant-combinator", position={x=pos.x+1, y=pos.y}, force="neutral"}
|
||||
inputElecCombi.destructible = false
|
||||
inputElecCombi.minable = false
|
||||
inputElecCombi.operable = true -- Input combi can be set by the player!
|
||||
inputElecCombi.last_user = player
|
||||
|
||||
-- Default share is 1MW
|
||||
inputElecCombi.get_or_create_control_behavior().set_signal(1,
|
||||
{signal={type="virtual", name="signal-M"},
|
||||
count=1})
|
||||
|
||||
TemporaryHelperText("Connect to electric network to contribute shared energy.", {pos.x+1.5, pos.y-1}, TICKS_PER_MINUTE*2)
|
||||
TemporaryHelperText("Use combinator to limit number of MW shared.", {pos.x+2.5, pos.y}, TICKS_PER_MINUTE*2)
|
||||
|
||||
table.insert(global.oshared.electricity_inputs, {eei=inputElec, combi=inputElecCombi})
|
||||
end
|
||||
|
||||
function SharedEnergySpawnOutput(player, pos)
|
||||
|
||||
local outputElec = game.surfaces[GAME_SURFACE_NAME].create_entity{name="electric-energy-interface", position=pos, force="neutral"}
|
||||
outputElec.destructible = false
|
||||
outputElec.minable = false
|
||||
outputElec.operable = false
|
||||
outputElec.last_user = player
|
||||
|
||||
outputElec.electric_buffer_size = SHARED_ELEC_OUTPUT_BUFFER_SIZE
|
||||
outputElec.power_production = 0
|
||||
outputElec.power_usage = 0
|
||||
outputElec.energy = 0
|
||||
|
||||
local outputElecCombi = game.surfaces[GAME_SURFACE_NAME].create_entity{name="constant-combinator", position={x=pos.x+1, y=pos.y}, force="neutral"}
|
||||
outputElecCombi.destructible = false
|
||||
outputElecCombi.minable = false
|
||||
outputElecCombi.operable = false -- Output combi is set my script!
|
||||
outputElec.last_user = player
|
||||
|
||||
TemporaryHelperText("Connect to electric network to consume shared energy.", {pos.x+1.5, pos.y-1}, TICKS_PER_MINUTE*2)
|
||||
TemporaryHelperText("Combinator outputs number of MJ currently stored.", {pos.x+2.5, pos.y}, TICKS_PER_MINUTE*2)
|
||||
|
||||
table.insert(global.oshared.electricity_outputs, {eei=outputElec, combi=outputElecCombi})
|
||||
end
|
||||
|
||||
function SharedEnergyStoreInputOnTick()
|
||||
global.oshared.energy_stored_history.start = global.oshared.energy_stored
|
||||
|
||||
for idx,input in pairs(global.oshared.electricity_inputs) do
|
||||
|
||||
-- Check for entity no longer valid:
|
||||
if (input.eei == nil) or (not input.eei.valid) or (input.combi == nil) or (not input.combi.valid) then
|
||||
global.oshared.electricity_inputs[idx] = nil
|
||||
|
||||
-- Is input at least half full, then we can start to store energy.
|
||||
elseif (input.eei.energy > (SHARED_ELEC_INPUT_BUFFER_SIZE/2)) then
|
||||
|
||||
-- Calculate the max we can share
|
||||
local max_input_allowed = input.eei.energy - (SHARED_ELEC_INPUT_BUFFER_SIZE/2)
|
||||
|
||||
-- Get the combinator limit
|
||||
local limit = 0
|
||||
local sig = input.combi.get_or_create_control_behavior().get_signal(1)
|
||||
if ((sig ~= nil) and (sig.signal ~= nil) and (sig.signal.name == "signal-M")) then
|
||||
limit = sig.count
|
||||
end
|
||||
|
||||
-- Get the minimum
|
||||
input.eei.power_usage = math.min(max_input_allowed, math.floor(limit*1000000/60))
|
||||
|
||||
global.oshared.energy_stored = global.oshared.energy_stored + input.eei.power_usage
|
||||
|
||||
-- Switch off contribution if not at least half full.
|
||||
else
|
||||
input.eei.power_usage = 0
|
||||
end
|
||||
end
|
||||
|
||||
global.oshared.energy_stored_history.after_input = global.oshared.energy_stored
|
||||
end
|
||||
|
||||
-- If there is room to distribute energy, we take shared amount split by players.
|
||||
function SharedEnergyDistributeOutputOnTick()
|
||||
|
||||
-- Share limit is total amount stored divided by outputs
|
||||
local energyShareCap = math.floor(global.oshared.energy_stored / (#global.oshared.electricity_outputs))
|
||||
|
||||
-- Iterate through and fill up outputs if they are under 50%
|
||||
for idx,output in pairs(global.oshared.electricity_outputs) do
|
||||
|
||||
-- Check for entity no longer valid:
|
||||
if (output.eei == nil) or (not output.eei.valid) or (output.combi == nil) or (not output.combi.valid) then
|
||||
global.oshared.electricity_outputs[idx] = nil
|
||||
|
||||
|
||||
else
|
||||
-- If it's not full, set production to fill (or as much as is allowed.)
|
||||
if (output.eei.energy < (SHARED_ELEC_OUTPUT_BUFFER_SIZE/2)) then
|
||||
local outBufferSpace = ((SHARED_ELEC_OUTPUT_BUFFER_SIZE/2) - output.eei.energy)
|
||||
output.eei.power_production = math.min(outBufferSpace, energyShareCap)
|
||||
global.oshared.energy_stored = global.oshared.energy_stored - math.min(outBufferSpace, energyShareCap)
|
||||
|
||||
-- Switch off if we're more than half full.
|
||||
else
|
||||
output.eei.power_production = 0
|
||||
end
|
||||
|
||||
-- Update output combinator
|
||||
output.combi.get_or_create_control_behavior().set_signal(1,
|
||||
{signal={type="virtual", name="signal-M"},
|
||||
count=clampInt32(math.floor(global.oshared.energy_stored/1000000))})
|
||||
end
|
||||
end
|
||||
|
||||
global.oshared.energy_stored_history.after_output = global.oshared.energy_stored
|
||||
end
|
||||
|
||||
-- Returns NIL or position of destroyed chest.
|
||||
function FindClosestWoodenChestAndDestroy(player)
|
||||
local target_chest = FindClosestPlayerOwnedEntity(player, "wooden-chest", 16)
|
||||
if (not target_chest) then
|
||||
player.print("Failed to find wooden-chest?")
|
||||
return nil
|
||||
end
|
||||
|
||||
if (not target_chest.get_inventory(defines.inventory.chest).is_empty()) then
|
||||
player.print("Chest is NOT empty! Please empty it and try again.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local pos = target_chest.position
|
||||
if (not target_chest.destroy()) then
|
||||
player.print("ERROR - Can't remove wooden chest??")
|
||||
return nil
|
||||
end
|
||||
|
||||
return {x=math.floor(pos.x),y=math.floor(pos.y)}
|
||||
end
|
||||
|
||||
function ConvertWoodenChestToSharedChestInput(player)
|
||||
local pos = FindClosestWoodenChestAndDestroy(player)
|
||||
if (pos) then
|
||||
SharedChestsSpawnInput(player, pos)
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "logistic-chest-storage", 1)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ConvertWoodenChestToSharedChestOutput(player)
|
||||
local pos = FindClosestWoodenChestAndDestroy(player)
|
||||
if (pos) then
|
||||
SharedChestsSpawnOutput(player, pos)
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "logistic-chest-requester", 1)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ConvertWoodenChestToSharedChestCombinators(player)
|
||||
local pos = FindClosestWoodenChestAndDestroy(player)
|
||||
if (pos) then
|
||||
if (player.surface.can_place_entity{name="constant-combinator", position={pos.x,pos.y-1}}) and
|
||||
(player.surface.can_place_entity{name="constant-combinator", position={pos.x,pos.y+1}}) then
|
||||
SharedChestsSpawnCombinators(player, {x=pos.x,y=pos.y-1}, {x=pos.x,y=pos.y+1})
|
||||
return true
|
||||
else
|
||||
player.print("Failed to place the special combinators. Please check there is enough space in the surrounding tiles!")
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ConvertWoodenChestToShareEnergyInput(player)
|
||||
local pos = FindClosestWoodenChestAndDestroy(player)
|
||||
if (pos) then
|
||||
if (player.surface.can_place_entity{name="electric-energy-interface", position=pos}) and
|
||||
(player.surface.can_place_entity{name="constant-combinator", position={x=pos.x+1, y=pos.y}}) then
|
||||
SharedEnergySpawnInput(player, pos)
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "accumulator", 1)
|
||||
return true
|
||||
else
|
||||
player.print("Failed to place the shared energy input. Please check there is enough space in the surrounding tiles!")
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ConvertWoodenChestToShareEnergyOutput(player)
|
||||
local pos = FindClosestWoodenChestAndDestroy(player)
|
||||
if (pos) then
|
||||
if (player.surface.can_place_entity{name="electric-energy-interface", position=pos}) and
|
||||
(player.surface.can_place_entity{name="constant-combinator", position={x=pos.x+1, y=pos.y}}) then
|
||||
SharedEnergySpawnOutput(player, pos)
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "electric-energy-interface", 1)
|
||||
return true
|
||||
else
|
||||
player.print("Failed to place the shared energy input. Please check there is enough space in the surrounding tiles!")
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function ConvertWoodenChestToWaterFill(player)
|
||||
local pos = FindClosestWoodenChestAndDestroy(player)
|
||||
if (pos) then
|
||||
if (getDistance(pos, player.position) > 2) then
|
||||
player.surface.set_tiles({[1]={name = "water", position=pos}})
|
||||
return true
|
||||
else
|
||||
player.print("Failed to place waterfill. Don't stand so close FOOL!")
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function DestroyClosestSharedChestEntity(player)
|
||||
local special_entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{
|
||||
name={"electric-energy-interface", "constant-combinator", "logistic-chest-storage", "logistic-chest-requester"},
|
||||
position=player.position,
|
||||
radius=16,
|
||||
force={"neutral"}}
|
||||
|
||||
if (#special_entities == 0) then
|
||||
player.print("Special entity not found? Are you close enough?")
|
||||
return
|
||||
end
|
||||
|
||||
local closest = game.surfaces[GAME_SURFACE_NAME].get_closest(player.position, special_entities)
|
||||
|
||||
if (closest) then
|
||||
if (closest.last_user and (closest.last_user ~= player)) then
|
||||
player.print("You can't remove other players chests!")
|
||||
else
|
||||
-- Subtract from feature counter...
|
||||
local name = closest.name
|
||||
if (name == "electric-energy-interface") then
|
||||
if (closest.electric_buffer_size == SHARED_ELEC_INPUT_BUFFER_SIZE) then
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "accumulator", -1)
|
||||
else
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "electric-energy-interface", -1)
|
||||
end
|
||||
elseif (name == "logistic-chest-storage") then
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "logistic-chest-storage", -1)
|
||||
elseif (name == "logistic-chest-requester") then
|
||||
OarcMapFeaturePlayerCountChange(player, "special_chests", "logistic-chest-requester", -1)
|
||||
end
|
||||
|
||||
closest.destroy()
|
||||
player.print("Special entity removed!")
|
||||
end
|
||||
else
|
||||
player.print("Special entity not found? Are you close enough? -- ERROR")
|
||||
end
|
||||
end
|
||||
|
||||
function SharedChestsSpawnInput(player, pos)
|
||||
|
||||
local inputChest = game.surfaces[GAME_SURFACE_NAME].create_entity{name="logistic-chest-storage", position={pos.x, pos.y}, force="neutral"}
|
||||
inputChest.destructible = false
|
||||
inputChest.minable = false
|
||||
inputChest.last_user = player
|
||||
|
||||
if global.oshared.chests == nil then
|
||||
global.oshared.chests = {}
|
||||
end
|
||||
|
||||
local chestInfoIn = {player=player.name,type="INPUT",entity=inputChest}
|
||||
table.insert(global.oshared.chests, chestInfoIn)
|
||||
|
||||
TemporaryHelperText("Place items in to share.", {pos.x+1.5, pos.y}, TICKS_PER_MINUTE*2)
|
||||
end
|
||||
|
||||
function SharedChestsSpawnOutput(player, pos, enable_example)
|
||||
|
||||
local outputChest = game.surfaces[GAME_SURFACE_NAME].create_entity{name="logistic-chest-requester", position={pos.x, pos.y}, force="neutral"}
|
||||
outputChest.destructible = false
|
||||
outputChest.minable = false
|
||||
outputChest.last_user = player
|
||||
|
||||
if (enable_example) then
|
||||
outputChest.set_request_slot({name="raw-fish", count=1}, 1)
|
||||
end
|
||||
|
||||
if global.oshared.chests == nil then
|
||||
global.oshared.chests = {}
|
||||
end
|
||||
|
||||
local chestInfoOut = {player=player.name,type="OUTPUT",entity=outputChest}
|
||||
table.insert(global.oshared.chests, chestInfoOut)
|
||||
|
||||
TemporaryHelperText("Set filters to request items.", {pos.x+1.5, pos.y}, TICKS_PER_MINUTE*2)
|
||||
end
|
||||
|
||||
|
||||
function SharedChestsSpawnCombinators(player, posCtrl, posStatus)
|
||||
|
||||
local combiCtrl = game.surfaces[GAME_SURFACE_NAME].create_entity{name="constant-combinator", position=posCtrl, force="neutral"}
|
||||
combiCtrl.destructible = false
|
||||
combiCtrl.minable = false
|
||||
combiCtrl.last_user = player
|
||||
|
||||
-- Fish as an example.
|
||||
combiCtrl.get_or_create_control_behavior().set_signal(1, {signal={type="item", name="raw-fish"}, count=1})
|
||||
|
||||
local combiStat = game.surfaces[GAME_SURFACE_NAME].create_entity{name="constant-combinator", position=posStatus, force="neutral"}
|
||||
combiStat.destructible = false
|
||||
combiStat.minable = false
|
||||
combiStat.operable = false
|
||||
combiStat.last_user = player
|
||||
|
||||
if global.oshared.chests_combinators == nil then
|
||||
global.oshared.chests_combinators = {}
|
||||
end
|
||||
|
||||
local combiPair = {player=player.name,ctrl=combiCtrl,status=combiStat}
|
||||
table.insert(global.oshared.chests_combinators, combiPair)
|
||||
|
||||
TemporaryHelperText("Set signals here to monitor item counts.", {posCtrl.x+1.5, posCtrl.y}, TICKS_PER_MINUTE*2)
|
||||
TemporaryHelperText("Receive signals here to see available items.", {posStatus.x+1.5, posStatus.y}, TICKS_PER_MINUTE*2)
|
||||
end
|
||||
|
||||
function SharedChestsUpdateCombinators()
|
||||
|
||||
if global.oshared.chests_combinators == nil then
|
||||
global.oshared.chests_combinators = {}
|
||||
end
|
||||
|
||||
for idx,combiPair in pairs(global.oshared.chests_combinators) do
|
||||
|
||||
-- Check if combinators still exist
|
||||
if (combiPair.ctrl == nil) or (combiPair.status == nil) or
|
||||
(not combiPair.ctrl.valid) or (not combiPair.status.valid) then
|
||||
global.oshared.chests_combinators[idx] = nil
|
||||
else
|
||||
|
||||
local combiCtrlBehav = combiPair.ctrl.get_or_create_control_behavior()
|
||||
local ctrlSignals = {}
|
||||
|
||||
-- Get signals on the ctrl combi:
|
||||
for i=1,combiCtrlBehav.signals_count do
|
||||
local sig = combiCtrlBehav.get_signal(i)
|
||||
if ((sig ~= nil) and (sig.signal ~= nil) and (sig.signal.type == "item")) then
|
||||
table.insert(ctrlSignals, sig.signal.name)
|
||||
end
|
||||
end
|
||||
|
||||
local combiStatBehav = combiPair.status.get_or_create_control_behavior()
|
||||
|
||||
-- Set signals on the status combi:
|
||||
for i=1,combiCtrlBehav.signals_count do
|
||||
if (ctrlSignals[i] ~= nil) then
|
||||
local availAmnt = global.oshared.items[ctrlSignals[i]]
|
||||
if availAmnt == nil then availAmnt = 0 end
|
||||
|
||||
combiStatBehav.set_signal(i, {signal={type="item", name=ctrlSignals[i]}, count=clampInt32(availAmnt)})
|
||||
else
|
||||
combiStatBehav.set_signal(i, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SharedChestUploadItem(item_name, count)
|
||||
if (not game.item_prototypes[item_name].has_flag("hidden")) then
|
||||
if (global.oshared.items[item_name] == nil) then
|
||||
global.oshared.items[item_name] = count
|
||||
else
|
||||
global.oshared.items[item_name] = global.oshared.items[item_name] + count
|
||||
end
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function SharedChestEmptyEquipment(item_stack)
|
||||
if (item_stack == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
if (item_stack.grid == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
local contents = item_stack.grid.get_contents()
|
||||
for item_name,count in pairs(contents) do
|
||||
SharedChestUploadItem(item_name, count)
|
||||
end
|
||||
end
|
||||
|
||||
function SharedChestUploadChest(entity)
|
||||
|
||||
local chest_inv = entity.get_inventory(defines.inventory.chest)
|
||||
if (chest_inv == nil) then return end
|
||||
if (chest_inv.is_empty()) then return end
|
||||
|
||||
local contents = chest_inv.get_contents()
|
||||
for item_name,count in pairs(contents) do
|
||||
if (game.item_prototypes[item_name].equipment_grid ~= nil) then
|
||||
local item_stack = chest_inv.find_item_stack(item_name)
|
||||
while (item_stack ~= nil) do
|
||||
SharedChestEmptyEquipment(item_stack)
|
||||
item_stack.clear()
|
||||
item_stack = chest_inv.find_item_stack(item_name)
|
||||
end
|
||||
end
|
||||
|
||||
if (SharedChestUploadItem(item_name, count)) then
|
||||
chest_inv.remove({name=item_name, count=count})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Pull all items in the deposit chests
|
||||
function SharedChestsDepositAll()
|
||||
|
||||
if global.oshared.items == nil then
|
||||
global.oshared.items = {}
|
||||
end
|
||||
|
||||
for idx,chest_info in pairs(global.oshared.chests) do
|
||||
|
||||
local chest_entity = chest_info.entity
|
||||
|
||||
-- Delete any chest that is no longer valid.
|
||||
if ((chest_entity == nil) or (not chest_entity.valid)) then
|
||||
global.oshared.chests[idx] = nil
|
||||
|
||||
-- Take inputs and store.
|
||||
elseif (chest_info.type == "INPUT") then
|
||||
SharedChestUploadChest(chest_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Tally up requests by item.
|
||||
function SharedChestsTallyRequests()
|
||||
|
||||
-- Clear existing requests. Also serves as an init
|
||||
global.oshared.requests = {}
|
||||
global.oshared.requests_totals = {}
|
||||
|
||||
-- For each output chest.
|
||||
for idx,chestInfo in pairs(global.oshared.chests) do
|
||||
|
||||
local chestEntity = chestInfo.entity
|
||||
|
||||
-- Delete any chest that is no longer valid.
|
||||
if ((chestEntity == nil) or (not chestEntity.valid)) then
|
||||
global.oshared.chests[idx] = nil
|
||||
|
||||
elseif (chestInfo.type == "OUTPUT") then
|
||||
|
||||
-- For each request slot
|
||||
for i = 1, chestEntity.request_slot_count, 1 do
|
||||
local req = chestEntity.get_request_slot(i)
|
||||
|
||||
-- If there is a request, add the request count to our request table.
|
||||
if (req ~= nil) then
|
||||
|
||||
if global.oshared.requests[req.name] == nil then
|
||||
global.oshared.requests[req.name] = {}
|
||||
end
|
||||
|
||||
if global.oshared.requests[req.name][chestInfo.player] == nil then
|
||||
global.oshared.requests[req.name][chestInfo.player] = 0
|
||||
end
|
||||
|
||||
if global.oshared.requests_totals[req.name] == nil then
|
||||
global.oshared.requests_totals[req.name] = 0
|
||||
end
|
||||
|
||||
-- Calculate actual request to fill remainder
|
||||
local existingAmount = chestEntity.get_inventory(defines.inventory.chest).get_item_count(req.name)
|
||||
local requestAmount = math.max(req.count-existingAmount, 0)
|
||||
|
||||
-- Add the request counts
|
||||
global.oshared.requests[req.name][chestInfo.player] = global.oshared.requests[req.name][chestInfo.player] + requestAmount
|
||||
global.oshared.requests_totals[req.name] = global.oshared.requests_totals[req.name] + requestAmount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- If demand is more than supply, limit each player's total item request to shared amount
|
||||
for reqName,reqTally in pairs(global.oshared.requests) do
|
||||
|
||||
local cap = 0
|
||||
local mustCap = false
|
||||
|
||||
-- No shared items means nothing to supply.
|
||||
if (global.oshared.items[reqName] == nil) or (global.oshared.items[reqName] == 0) then
|
||||
mustCap = true
|
||||
cap = 0
|
||||
|
||||
-- Otherwise, limit by dividing by players.
|
||||
elseif (global.oshared.requests_totals[reqName] > global.oshared.items[reqName]) then
|
||||
mustCap = true
|
||||
cap = math.floor(global.oshared.items[reqName] / TableLength(global.oshared.requests[reqName]))
|
||||
|
||||
-- In the case where we are rounding down to 0, let's bump the minimum distribution to 1.
|
||||
if (cap == 0) then
|
||||
cap = 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Limit each request to the cap.
|
||||
if mustCap then
|
||||
for player,reqCount in pairs(global.oshared.requests[reqName]) do
|
||||
if (reqCount > cap) then
|
||||
global.oshared.requests[reqName][player] = cap
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Distribute requests based on demand
|
||||
function SharedChestsDistributeRequests()
|
||||
|
||||
-- For each output chest.
|
||||
for idx,chestInfo in pairs(global.oshared.chests) do
|
||||
if (chestInfo.type == "OUTPUT") then
|
||||
|
||||
local chestEntity = chestInfo.entity
|
||||
|
||||
-- Delete any chest that is no longer valid.
|
||||
if ((chestEntity == nil) or (not chestEntity.valid)) then
|
||||
global.oshared.chests[idx] = nil
|
||||
|
||||
-- For each request slot
|
||||
else
|
||||
for i = 1, chestEntity.request_slot_count, 1 do
|
||||
local req = chestEntity.get_request_slot(i)
|
||||
|
||||
-- If there is a request, distribute items
|
||||
if (req ~= nil) then
|
||||
|
||||
-- Make sure requests have been created.
|
||||
-- Make sure shared items exist.
|
||||
if (global.oshared.requests_totals[req.name] ~= nil) and
|
||||
(global.oshared.items[req.name] ~= nil) and
|
||||
(global.oshared.requests[req.name][chestInfo.player] ~= nil) then
|
||||
|
||||
if (global.oshared.requests[req.name][chestInfo.player] > 0)and (global.oshared.items[req.name] > 0) then
|
||||
|
||||
-- How much is already in the chest?
|
||||
local existingAmount = chestEntity.get_inventory(defines.inventory.chest).get_item_count(req.name)
|
||||
-- How much is required to fill the remainder request?
|
||||
local requestAmount = math.max(req.count-existingAmount, 0)
|
||||
-- How much is allowed based on the player's current request amount?
|
||||
local allowedAmount = math.min(requestAmount, global.oshared.requests[req.name][chestInfo.player])
|
||||
|
||||
if (allowedAmount > 0) then
|
||||
local chestInv = chestEntity.get_inventory(defines.inventory.chest)
|
||||
if chestInv.can_insert({name=req.name}) then
|
||||
|
||||
local amnt = chestInv.insert({name=req.name, count=math.min(allowedAmount, global.oshared.items[req.name])})
|
||||
global.oshared.items[req.name] = global.oshared.items[req.name] - amnt
|
||||
global.oshared.requests[req.name][chestInfo.player] = global.oshared.requests[req.name][chestInfo.player] - amnt
|
||||
global.oshared.requests_totals[req.name] = global.oshared.requests_totals[req.name] - amnt
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SharedChestsOnTick()
|
||||
|
||||
-- Every tick we share power
|
||||
SharedEnergyStoreInputOnTick()
|
||||
SharedEnergyDistributeOutputOnTick()
|
||||
|
||||
-- Every second, we check the input chests and deposit stuff.
|
||||
if ((game.tick % (60)) == 37) then
|
||||
SharedChestsDepositAll()
|
||||
end
|
||||
|
||||
-- Every second, we check the output chests for requests
|
||||
if ((game.tick % (60)) == 38) then
|
||||
SharedChestsTallyRequests()
|
||||
end
|
||||
|
||||
-- Every second, we distribute to the output chests.
|
||||
if ((game.tick % (60)) == 39) then
|
||||
SharedChestsDistributeRequests()
|
||||
end
|
||||
|
||||
-- Every second, we update our combinator status info.
|
||||
if ((game.tick % (60)) == 40) then
|
||||
SharedChestsUpdateCombinators()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function CreateSharedItemsGuiTab(tab_container, player)
|
||||
local scrollFrame = tab_container.add{type="scroll-pane",
|
||||
name="sharedItems-panel",
|
||||
direction = "vertical"}
|
||||
ApplyStyle(scrollFrame, my_shared_item_list_fixed_width_style)
|
||||
scrollFrame.horizontal_scroll_policy = "never"
|
||||
|
||||
AddLabel(scrollFrame, "share_items_info", "Place items into the [color=yellow]yellow storage chests to share[/color].\nRequest items from the [color=blue]blue requestor chests to pull out items[/color].\nTo refresh this view, click the tab again.\nShared items are accessible by [color=red]EVERYONE and all teams[/color].\nThe combinator pair allows you to 'set' item types to watch for. Set items in the top one, and connect the bottom one to a circuit network to view the current available inventory. Items with 0 amount do not generate any signal.\nThe special accumulators share energy. The top one acts as an input, the bottom is the output.", my_longer_label_style)
|
||||
|
||||
AddSpacerLine(scrollFrame)
|
||||
|
||||
-- MW charging/discharging rate. (delta change * sample rate per second)
|
||||
local energy_change_add = (global.oshared.energy_stored_history.after_input - global.oshared.energy_stored_history.start)*60/1000000
|
||||
local energy_change_sub = (((global.oshared.energy_stored_history.after_input - global.oshared.energy_stored_history.after_output)*60))/1000000
|
||||
local energy_add_str = string.format("+%.3fMW", energy_change_add)
|
||||
local energy_sub_str = string.format("-%.3fMW", energy_change_sub)
|
||||
local rate_color = "green"
|
||||
if (energy_change_add <= energy_change_sub) then
|
||||
rate_color = "red"
|
||||
elseif (energy_change_add < (energy_change_sub+10)) then
|
||||
rate_color = "orange"
|
||||
end
|
||||
|
||||
AddLabel(scrollFrame, "elec_avail_info", "[color=acid]Current electricity available: " .. string.format("%.3f", global.oshared.energy_stored/1000000) .. "MJ[/color] [color=" .. rate_color .. "](" .. energy_add_str .. " " .. energy_sub_str ..")[/color]", my_longer_label_style)
|
||||
|
||||
AddSpacerLine(scrollFrame)
|
||||
AddLabel(scrollFrame, "share_items_title_msg", "Shared Items:", my_label_header_style)
|
||||
|
||||
local sorted_items = {}
|
||||
for k in pairs(global.oshared.items) do table.insert(sorted_items, k) end
|
||||
table.sort(sorted_items)
|
||||
|
||||
for idx,itemName in pairs(sorted_items) do
|
||||
if (global.oshared.items[itemName] > 0) then
|
||||
local caption_str = "[item="..itemName.."] " .. itemName..": "..global.oshared.items[itemName]
|
||||
AddLabel(scrollFrame, itemName.."_itemlist", caption_str, my_player_list_style)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
52
lib/tag.lua
52
lib/tag.lua
@ -1,52 +0,0 @@
|
||||
-- tag.lua
|
||||
-- Apr 2017
|
||||
-- Allows adding play tags
|
||||
|
||||
-- Tag list
|
||||
local roles = {
|
||||
{display_name = "[Solo]"},
|
||||
{display_name = "[Mining]"},
|
||||
{display_name = "[Power]"},
|
||||
{display_name = "[Oil]"},
|
||||
{display_name = "[Smelt]"},
|
||||
{display_name = "[Rail]"},
|
||||
{display_name = "[Defense]"},
|
||||
{display_name = "[Circuits]"},
|
||||
{display_name = "[Science!]"},
|
||||
{display_name = "[Logistics]"},
|
||||
{display_name = "[Misc]"},
|
||||
{display_name = "[Aliens]"},
|
||||
{display_name = "[Rocket]"},
|
||||
{display_name = "[AFK]"}}
|
||||
|
||||
function CreateTagGuiTab(tab_container, player)
|
||||
for i,role in ipairs(roles) do
|
||||
tab_container.add{type="button", caption=role.display_name, name=role.display_name}
|
||||
end
|
||||
if (player.admin) then
|
||||
tab_container.add{type="button", caption="[Admin]", name="admin"}
|
||||
tab_container.add{type="button", caption="[Moderator]", name="moderator"}
|
||||
end
|
||||
tab_container.add{type="button", caption="Clear", name="clear_btn"}
|
||||
end
|
||||
|
||||
function TagGuiClick(event)
|
||||
if not (event and event.element and event.element.valid) then return end
|
||||
local player = game.players[event.player_index]
|
||||
local name = event.element.name
|
||||
|
||||
if (name == "clear_btn") then
|
||||
player.tag = ""
|
||||
return
|
||||
end
|
||||
|
||||
for i,role in ipairs(roles) do
|
||||
if (name == role.display_name) then
|
||||
player.tag = role.display_name
|
||||
elseif (name == "admin") then
|
||||
player.tag = "[Admin]"
|
||||
elseif (name == "moderator") then
|
||||
player.tag = "[Moderator]"
|
||||
end
|
||||
end
|
||||
end
|
@ -1,122 +0,0 @@
|
||||
oarc-spawn-time-warning-msg=Aufgrund der Funktionsweise dieses Szenarios kann es einige Zeit dauern, bis das Land um deinen neuen Spawn herum generiert wurde. Bitte warte 10-20 Sekunden, nachdem du deinen Spawn ausgewählt hast.
|
||||
|
||||
oarc-i-understand=Ich verstehe
|
||||
oarc-spawn-options=Spawn Optionen
|
||||
|
||||
oarc-click-info-btn-help=Klick oben links auf die Schaltfläche INFO, um mehr über dieses Szenario zu erfahren! Dies ist deine einzige Chance, eine Spawn-Option zu wählen. Wähle sorgfältig...
|
||||
|
||||
oarc-vanilla-spawn=Vanilla Spawn
|
||||
oarc-default-spawn-behavior=Dies ist das standardmäßige Spawn-Verhalten eines Vanilla-Spiels. Du trittst dem Standardteam in der Mitte der Karte bei.
|
||||
|
||||
oarc-join-main-team-radio=Dem Standardteam beitreten (gemeinsame Forschung)
|
||||
oarc-create-own-team-radio=Erstelle dein eigenes Team (eigene Forschung)
|
||||
|
||||
oarc-moat-option=Umgib deinen Spawn mit einem Graben.
|
||||
|
||||
oarc-solo-spawn-near=Allein spawnen (nah)
|
||||
oarc-solo-spawn-far=Allein spawnen (fern)
|
||||
|
||||
oarc-starting-area-vanilla=Du spawnst in deinem eigenen Startbereich (wie im Vanilla-Spiel).
|
||||
oarc-vanilla-spawns-available=Es steht __1__ Vanilla-Spawn zur Verfügung.
|
||||
|
||||
oarc-starting-area-normal=Du spawnst in einem neuen Gebiet mit voreingestellten Startressourcen.
|
||||
oarc-join-someone-avail=Jemandem beitreten (__1__ verfügbar)
|
||||
oarc-join-someone-info=Du wirst in der Basis von jemand anderem spawnen. Dies erfordert, dass mindestens eine Person Zugang zu seiner Basis gewährt hat. Diese Wahl ist endgültig und du wirst später nicht mehr in der Lage sein, deinen eigenen Spawn zu erstellen.
|
||||
|
||||
oarc-no-shared-avail=Es gibt derzeit keine freigegebenen Basen, in denen man spawnen kann.
|
||||
oarc-join-check-again=Erneut prüfen
|
||||
oarc-shared-spawn-disabled=Gemeinsame Spawns sind in diesem Modus deaktiviert.
|
||||
|
||||
oarc-buddy-spawn=Buddy Spawn
|
||||
oarc-buddy-spawn-info=Das Buddy-System erfordert 2 Spieler in diesem Menü gleichzeitig, sie spawnen nebeneinander, jeder mit seinen eigenen Ressourcen.
|
||||
|
||||
oarc-max-players-shared-spawn=Wenn du deinen eigenen Spawn-Punkt erstellst, kann bis zu __1__ anderer Online-Spieler teilnehmen.
|
||||
oarc-spawn-dist-notes=Der nahe Spawn liegt zwischen __1__-__2__ Chunks von der Mitte der Karte entfernt.\nDer ferne Spawn liegt zwischen __3__-__4__ Chunks von der Mitte der Karte entfernt.\nAlleine Spawnen ist gefährlich! Du wirst kämpfen müssen, um andere Spieler erreichen zu können.
|
||||
|
||||
oarc-player-is-joining-main-force=__1__ tritt dem Standardteam bei!
|
||||
oarc-player-is-joining-near=__1__ nimmt aus naher Entfernung am Spiel teil!
|
||||
oarc-player-is-joining-far=__1__ nimmt aus großer Entfernung am Spiel teil!
|
||||
|
||||
oarc-please-wait=BITTE WARTE, BIS DEIN SPAWN-PUNKT GENERIERT WURDE!
|
||||
|
||||
oarc-looking-for-buddy=__1__ sucht nach einem Buddy.
|
||||
|
||||
oarc-avail-bases-join=Verfügbare Basen zum Beitreten:
|
||||
oarc-spawn-spots-remaining=__1__ (__2__ verbleibende Plätze)
|
||||
oarc-cancel-return-to-previous=Abbrechen (zurück zu den vorherigen Optionen)
|
||||
oarc-player-requesting-join-you=__1__ bittet darum, deiner Basis beizutreten!
|
||||
oarc-waiting-for-spawn-owner=Warte auf die Antwort des Spawn-Besitzers...
|
||||
|
||||
oarc-you-will-spawn-once-host=Du wirst spawnen, sobald der Host ja gewählt hat...
|
||||
oarc-player-cancel-join-request=__1__ hat die Anfrage zum Beitritt zu deinem Spawn abgebrochen.
|
||||
|
||||
oarc-spawn-ctrl=Spawn-Einst.
|
||||
oarc-spawn-controls=Spawn Einstellungen:
|
||||
oarc-spawn-allow-joiners=Erlaube anderen, deiner Basis beizutreten.
|
||||
|
||||
oarc-set-respawn-loc=Setze neuen Spawn-Punkt (1 Stunde Abklingzeit)
|
||||
oarc-set-respawn-loc-cooldown=Set Respawn Cooldown Remaining: __1__
|
||||
oarc-set-respawn-note=Das setzt deinen Spawn-Punkt an deine aktuelle Position.
|
||||
|
||||
oarc-select-player-join-queue=Wähle einen Spieler aus der Beitrittswarteschlange aus:
|
||||
|
||||
oarc-accept=Akzeptieren
|
||||
oarc-reject=Ablehnen
|
||||
|
||||
oarc-no-player-join-reqs=Du hast keine Anfragen von Spielern, deiner Base beizutreten.
|
||||
|
||||
oarc-start-shared-base=Neue Spieler können nun __1__'s Base beitreten!
|
||||
oarc-stop-shared-base=Neue Spieler können nicht länger der Base von __1__ beitreten!
|
||||
|
||||
oarc-spawn-point-updated=Re-Spawn Punkt aktualisiert!
|
||||
oarc-selected-player-not-wait=Der ausgewählte Spieler wartet nicht mehr auf den Beitritt!
|
||||
oarc-reject-joiner=Du lehnst __1__'s Anfrage, deiner Base beizutreten, ab.
|
||||
oarc-your-request-rejected=Deine Anfrage zum Beitritt wurde abgelehnt.
|
||||
|
||||
oarc-player-joining-base=__1__ trat der Base von __2__ bei!
|
||||
|
||||
oarc-player-left-while-joining=__1__ verließ das Spiel. Was für ein Arsch.
|
||||
|
||||
oarc-buddy-spawn-options=Buddy Spawn Optionen
|
||||
oarc-buddy-spawn-instructions=Um dies zu nutzen, vergewissere dich, dass du und dein Buddy zur gleichen Zeit in diesem Menü sind. Nur einer von euch muss die Anfrage senden. Wähle deinen Buddy aus der Liste aus (aktualisiere, wenn der Name deines Buddys nicht sichtbar ist) und wähle deine Spawn-Optionen. Klicke auf eine der Schaltflächen für die Anforderung, um die Anforderung zu senden. Der andere Buddy kann dann die Anfrage annehmen (oder ablehnen). Dies ermöglicht es euch beiden, nebeneinander zu spawnen, jeder mit seinem eigenen Spawn-Bereich. Sobald ein Buddy eine Spawn-Anfrage annimmt, ist sie endgültig!
|
||||
|
||||
oarc-buddy-select-info=Wähle zunächst einen Buddy aus der Warteliste aus. Wähle dann die Spawn-Optionen aus und sende deine Anfrage:
|
||||
|
||||
oarc-buddy-refresh=Buddy-Liste aktualisieren
|
||||
oarc-create-buddy-team=Erstelle dein eigenes Team (geteilte Entwicklung)
|
||||
|
||||
oarc-buddy-spawn-near=Erfrage Buddy-Spawn (nah)
|
||||
oarc-buddy-spawn-far=Erfrage Buddy-Spawn (fern)
|
||||
|
||||
oarc-invalid-buddy=Du hast keinen gültigen Buddy ausgewählt, versuche es noch mal.
|
||||
oarc-buddy-not-avail=Der ausgewählte Buddy ist nicht länger vefügbar, bitte versuche es erneut.
|
||||
|
||||
oarc-waiting-for-buddy=Warte auf die Antwort vom Buddy...
|
||||
oarc-wait-buddy-select-yes=Du wirst spawnen, sobald dein Buddy ja gewählt hat...
|
||||
|
||||
oarc-buddy-cancel-request=__1__ brach die Buddy-Anfrage ab!
|
||||
|
||||
oarc-buddy-requesting-from-you=__1__ fordert einen Buddy Spawn von dir an!
|
||||
|
||||
oarc-buddy-txt-main-team=Das Standardteam
|
||||
oarc-buddy-txt-new-teams=in getrennten Teams
|
||||
oarc-buddy-txt-buddy-team=ein Buddy Team
|
||||
oarc-buddy-txt-moat= umgeben von einem Graben
|
||||
oarc-buddy-txt-near=in der Nähe der Mitte der Karte!
|
||||
oarc-buddy-txt-far=weit weg von der Mitte der Karte!
|
||||
oarc-buddy-txt-would-like= möchte teilnehmen
|
||||
oarc-buddy-txt-next-to-you= neben dir
|
||||
|
||||
oarc-buddy-declined=__1__ hat deine Buddy-Anfrage abgelehnt!
|
||||
|
||||
oarc-spawn-wait=Bitte warte!
|
||||
oarc-wait-text=Dein Spawn wird gerade erstellt. Du wirst in __1__ Sekunden dorthin teleportiert!\nHalte dich bereit...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,117 +0,0 @@
|
||||
scenario-name=Oarc's Multiplayer Spawning Scenario
|
||||
|
||||
description=This scenario allows every player to create their own spawn point when they join the game. There are a lot of helpful features to ensure that new players can join at anytime in the game or even join other players. This is a multiplayer only scenario.\n[color=red][font=default-bold]You must first create a config.lua file if one does not yet exist![/font][/color]\nIn the scenario folder, copy "example-config.lua" and name it "config.lua". Edit the file with any text editor. This is the only way to configure your scenario options and it MUST be done before starting a new game.\n[color=yellow][font=default-bold]Always start a new game when changing the config or updating the scenario![/font][/color]\nPlease visit https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn for the scenario source code, Wiki, and if you want to file any bugs. The wiki has instructions on how to best start games on dedicated/headless servers!\n[color=yellow][font=default-bold]If you got this scenario from the mod portal or by joining a server, make sure you remove any blueprint.zip files in the scenario folder![/font][/color]
|
||||
|
||||
oarc-spawn-time-warning-msg=Due to the way this scenario works, it may take some time for the land around your new spawn area to generate... Please wait for 10-20 seconds when you select your first spawn.
|
||||
|
||||
oarc-i-understand=I Understand
|
||||
oarc-spawn-options=Spawn Options
|
||||
|
||||
oarc-click-info-btn-help=Click the INFO button in the top left to learn more about this scenario! This is your ONLY chance to choose a spawn option. Choose carefully...
|
||||
|
||||
oarc-vanilla-spawn=Vanilla Spawn
|
||||
oarc-default-spawn-behavior=This is the default spawn behavior of a vanilla game. You join the default team in the center of the map.
|
||||
|
||||
oarc-join-main-team-radio=Join Main Team (shared research)
|
||||
oarc-create-own-team-radio=Create Your Own Team (own research tree)
|
||||
|
||||
oarc-moat-option=Surround your spawn with a moat
|
||||
|
||||
oarc-solo-spawn-near=Solo Spawn (Near)
|
||||
oarc-solo-spawn-far=Solo Spawn (Far)
|
||||
|
||||
oarc-starting-area-vanilla=You are spawned in your own starting area (vanilla style).
|
||||
oarc-vanilla-spawns-available=There are __1__ vanilla spawns available.
|
||||
|
||||
oarc-starting-area-normal=You are spawned in a new area, with pre-set starting resources.
|
||||
oarc-join-someone-avail=Join Someone (__1__ available)
|
||||
oarc-join-someone-info=You are spawned in someone else's base. This requires at least 1 person to have allowed access to their base. This choice is final and you will not be able to create your own spawn later.
|
||||
|
||||
oarc-no-shared-avail=There are currently no shared bases availble to spawn at.
|
||||
oarc-join-check-again=Check Again
|
||||
oarc-shared-spawn-disabled=Shared spawns are disabled in this mode.
|
||||
|
||||
oarc-buddy-spawn=Buddy Spawn
|
||||
oarc-buddy-spawn-info=The buddy system requires 2 players in this menu at the same time, you spawn beside each other, each with your own resources.
|
||||
|
||||
oarc-max-players-shared-spawn=If you create your own spawn point you can allow up to __1__ other online players to join.
|
||||
oarc-spawn-dist-notes=Near spawn is between __1__-__2__ chunks away from the center of the map.\nFar spawn is between __3__-__4__ chunks away from the center of the map.\nSolo spawns are dangerous! Expect a fight to reach other players.
|
||||
|
||||
oarc-player-is-joining-main-force=__1__ is joining the main force!
|
||||
oarc-player-is-joining-near=__1__ is joining the game from a distance!
|
||||
oarc-player-is-joining-far=__1__ is joining the game from a great distance!
|
||||
|
||||
oarc-please-wait=PLEASE WAIT WHILE YOUR SPAWN POINT IS GENERATED!
|
||||
|
||||
oarc-looking-for-buddy=__1__ is looking for a buddy.
|
||||
|
||||
oarc-avail-bases-join=Available Bases to Join:
|
||||
oarc-spawn-spots-remaining=__1__ (__2__ spots remaining)
|
||||
oarc-cancel-return-to-previous=Cancel (Return to Previous Options)
|
||||
oarc-player-requesting-join-you=__1__ is requesting to join your base!
|
||||
oarc-waiting-for-spawn-owner=Waiting for spawn owner to respond...
|
||||
|
||||
oarc-you-will-spawn-once-host=You will spawn once the host selects yes...
|
||||
oarc-player-cancel-join-request=__1__ cancelled their request to join your spawn.
|
||||
|
||||
oarc-spawn-ctrl=Spawn Ctrl
|
||||
oarc-spawn-controls=Spawn Controls:
|
||||
oarc-spawn-allow-joiners=Allow others to join your base.
|
||||
|
||||
oarc-set-respawn-loc=Set New Respawn Location (has a cooldown)
|
||||
oarc-set-respawn-loc-cooldown=Set Respawn Cooldown Remaining: __1__
|
||||
oarc-set-respawn-note=This will set your respawn point to your current location.
|
||||
|
||||
oarc-select-player-join-queue=Select a player from the join queue:
|
||||
|
||||
oarc-accept=Accept
|
||||
oarc-reject=Reject
|
||||
|
||||
oarc-no-player-join-reqs=You have no players requesting to join you at this time.
|
||||
|
||||
oarc-start-shared-base=New players can now join __1__'s base!
|
||||
oarc-stop-shared-base=New players can no longer join __1__'s base!
|
||||
|
||||
oarc-spawn-point-updated=Re-spawn point updated!
|
||||
oarc-selected-player-not-wait=Selected player is no longer waiting to join!
|
||||
oarc-reject-joiner=You rejected __1__'s request to join your base.
|
||||
oarc-your-request-rejected=Your request to join was rejected.
|
||||
|
||||
oarc-player-joining-base=__1__ is joining __2__'s base!
|
||||
|
||||
oarc-player-left-while-joining=__1__ left the game. What an ass.
|
||||
|
||||
oarc-buddy-spawn-options=Buddy Spawn Options
|
||||
oarc-buddy-spawn-instructions=To use this, make sure you and your buddy are in this menu at the same time. Only one of you must send the request. Select your buddy from the list (refresh if your buddy's name is not visible) and select your spawn options. Click one of the request buttons to send the request. The other buddy can then accept (or deny) the request. This will allow you both to spawn next to each other, each with your own spawn area. Once a buddy accepts a spawn request, it is final!
|
||||
|
||||
oarc-buddy-select-info=First, select a buddy from the waiting list. Then choose the spawn options and send your request:
|
||||
|
||||
oarc-buddy-refresh=Refresh Buddy List
|
||||
oarc-create-buddy-team=Create Your Own Buddy Team (buddy and you share research)
|
||||
|
||||
oarc-buddy-spawn-near=Request Buddy Spawn (Near)
|
||||
oarc-buddy-spawn-far=Request Buddy Spawn (Far)
|
||||
|
||||
oarc-invalid-buddy=You have not selected a valid buddy! Please try again.
|
||||
oarc-buddy-not-avail=Selected buddy is no longer available! Please try again.
|
||||
|
||||
oarc-waiting-for-buddy=Waiting for buddy to respond...
|
||||
oarc-wait-buddy-select-yes=You will spawn once your buddy selects yes...
|
||||
|
||||
oarc-buddy-cancel-request=__1__ cancelled their buddy request!
|
||||
|
||||
oarc-buddy-requesting-from-you=__1__ is requesting a buddy spawn from you!
|
||||
|
||||
oarc-buddy-txt-main-team=the main team
|
||||
oarc-buddy-txt-new-teams=on separate teams
|
||||
oarc-buddy-txt-buddy-team=a buddy team
|
||||
oarc-buddy-txt-moat= surrounded by a moat
|
||||
oarc-buddy-txt-near=near to the center of the map!
|
||||
oarc-buddy-txt-far=far from the center of the map!
|
||||
oarc-buddy-txt-would-like= would like to join
|
||||
oarc-buddy-txt-next-to-you= next to you
|
||||
|
||||
oarc-buddy-declined=__1__ declined your buddy request!
|
||||
|
||||
oarc-spawn-wait=Please wait!
|
||||
oarc-wait-text=Your spawn is being created now.\nYou will be teleported there in __1__ seconds!\nPlease standby...
|
@ -1,113 +0,0 @@
|
||||
oarc-spawn-time-warning-msg=En raison de la manière de fonctionnement de ce scénario, la génération de votre base peut prendre un certain temps ... Veuillez patienter 10 à 20 secondes lorsque vous apparaissez.
|
||||
|
||||
oarc-i-understand=Je comprends
|
||||
oarc-spawn-options=Options d'apparition
|
||||
|
||||
oarc-click-info-btn-help=Cliquez sur le bouton INFO en haut à gauche pour en savoir plus sur ce scénario! Ceci est votre SEULE chance de choisir une option de spawn. Choisissez soigneusement...
|
||||
|
||||
oarc-vanilla-spawn=Spawn vanillia
|
||||
oarc-default-spawn-behavior=C’est le comportement par défaut du spawn d’un jeu vanillia. Vous rejoignez l'équipe par défaut au centre de la carte.
|
||||
|
||||
oarc-join-main-team-radio=Rejoindre l'équipe principale (recherche partagée)
|
||||
oarc-create-own-team-radio=Créez votre propre équipe (propre arbre de recherche)
|
||||
|
||||
oarc-moat-option=Entourez votre base d'eau (fossé)
|
||||
|
||||
oarc-solo-spawn-near=Spawn solo (proche)
|
||||
oarc-solo-spawn-far=Spawn solo (Loin)
|
||||
|
||||
oarc-starting-area-vanilla=Vous êtes apparu dans votre propre base (style vanilla).
|
||||
oarc-vanilla-spawns-available=Il y a __1__ une base vanilla disponible.
|
||||
|
||||
oarc-starting-area-normal=Vous êtes apparu dans une nouvelle base, avec des ressources de départ prédéfinies.
|
||||
oarc-join-someone-avail=Rejoindre quelqu'un (__1__ disponible)
|
||||
oarc-join-someone-info=Vous rejoindrez la base de quelqu'un d'autre. Cela nécessite que au moins 1 personne autorise l'accès à leur base. Ce choix est définitif et vous ne pourrez pas créer votre propre zone plus tard.
|
||||
|
||||
oarc-no-shared-avail=Il n’existe actuellement aucune base partagée disponible.
|
||||
oarc-join-check-again=Vérifier à nouveau
|
||||
oarc-shared-spawn-disabled=Les spawns partagés sont désactivés dans ce mode.
|
||||
|
||||
oarc-buddy-spawn=Spawn avec un ami
|
||||
oarc-buddy-spawn-info=Se système d'amis nécessite 2 joueurs dans ce menu en même temps, vous apparaissez côte à côte, chacun avec vos propres ressources.
|
||||
|
||||
oarc-max-players-shared-spawn=Si vous créez votre propre point d'apparition, vous pouvez autoriser jusqu'à __1__ autres joueurs en ligne à rejoindre.
|
||||
oarc-spawn-dist-notes=Le point d’apparition (proche) se situe entre __1__-__2__ morceaux du centre de la carte. \nLe point d’apparition (loin) se situe entre __3__-__4__ morceaux du centre de la carte. \nLes apparitions solo sont dangereuses! Attendez-vous à un combat pour atteindre d'autres joueurs.
|
||||
|
||||
oarc-player-is-joining-main-force=__1__ rejoint l'équipe principale'!
|
||||
oarc-player-is-joining-near=__1__ rejoint le jeu à distance!
|
||||
oarc-player-is-joining-far=__1__ rejoint le jeu avec une grande distance!
|
||||
|
||||
oarc-please-wait=VEUILLEZ ATTENDRE QUE VOTRE POINT D'APPARITION SOIT GÉNÉRÉ!
|
||||
|
||||
oarc-looking-for-buddy=__1__ est à la recherche d'un copain.
|
||||
|
||||
oarc-avail-bases-join=Bases disponibles à rejoindre:
|
||||
oarc-spawn-spots-remaining=__1__ (__2__ places restantes)
|
||||
oarc-cancel-return-to-previous=Annuler (retourner aux options précédentes)
|
||||
oarc-player-requesting-join-you=__1__ demande à rejoindre votre base!
|
||||
oarc-waiting-for-spawn-owner=Attendez que le propriétaire de la base réponde ...
|
||||
|
||||
oarc-you-will-spawn-once-host=Vous apparaîtrez une fois que l'hôte aura choisi oui ...
|
||||
oarc-player-cancel-join-request=__1__ a annulé sa demande pour rejoindre votre base.
|
||||
|
||||
oarc-spawn-ctrl=Spawn Ctrl
|
||||
oarc-spawn-controls=Contrôle d'apparition':
|
||||
oarc-spawn-allow-joiners=Autoriser les autres à rejoindre votre base.
|
||||
|
||||
oarc-set-respawn-loc=Définir le nouvel emplacement de réapparition (il y a une heure d'attente pour réutiliser ce boutton)
|
||||
oarc-set-respawn-loc-cooldown=Définir le temps d'attente pour réapparaître restant: __1__
|
||||
oarc-set-respawn-note=Cela va définir votre point de réapparition à votre position actuelle.
|
||||
|
||||
oarc-select-player-join-queue=Sélectionnez un joueur dans la file d'attente:
|
||||
|
||||
oarc-accept=Accepter
|
||||
oarc-reject=Rejeter
|
||||
|
||||
oarc-no-player-join-reqs=Vous n'avez aucun joueur demandant à vous rejoindre pour le moment.
|
||||
|
||||
oarc-start-shared-base=Les nouveaux joueurs peuvent maintenant rejoindre la base de __1__!
|
||||
oarc-stop-shared-base=Les nouveaux joueurs ne peuvent plus rejoindre la base de __1__!
|
||||
|
||||
oarc-spawn-point-updated=Point de réapparition mis à jour!
|
||||
oarc-selected-player-not-wait=Le joueur sélectionné n'attend plus de rejoindre!
|
||||
oarc-reject-joiner=Vous avez rejeté la demande de __1__ pour rejoindre votre base.
|
||||
oarc-your-request-rejected=Votre demande d'adhésion a été rejetée.
|
||||
|
||||
oarc-player-joining-base=__1__ à rejoint la base de __2__!
|
||||
|
||||
oarc-player-left-while-joining=__1__ a quitté le match. Quel âne.
|
||||
|
||||
oarc-buddy-spawn-options=Options d'apparition du menu (Spawn avec un ami)
|
||||
oarc-buddy-spawn-instructions=Pour utiliser ceci, assurez-vous que votre ami et vous êtes dans ce menu en même temps. Un seul d'entre vous doit envoyer la demande. Sélectionnez votre ami dans la liste (actualisez-la si son nom n'est pas visible) et sélectionnez vos options d'apparition. Cliquez sur l'un des boutons de requête pour envoyer la requête. L'autre copain peut alors accepter (ou refuser) la demande. Cela vous permettra à tous les deux d'apparaître côte à côte, chacun avec votre propre base. Une fois que votre copain aura accepté une demande de spawn, c'est définitif!
|
||||
|
||||
oarc-buddy-select-info=D'abord, sélectionnez un ami dans la liste d'attente. Puis choisissez les options de spawn et envoyez votre demande:
|
||||
|
||||
oarc-buddy-refresh=Actualiser la liste d'amis
|
||||
oarc-create-buddy-team=Créez votre propre équipe d'amis (vous et votre ami partagez la recherche)
|
||||
|
||||
oarc-buddy-spawn-near=Demander la création de la base (proche)
|
||||
oarc-buddy-spawn-far=Demander la création de la base (loin)
|
||||
|
||||
oarc-invalid-buddy=Vous n'avez pas sélectionné de partenaire valide! Veuillez réessayer.
|
||||
oarc-buddy-not-avail=Le copain sélectionné n'est plus disponible! Veuillez réessayer.
|
||||
|
||||
oarc-waiting-for-buddy=Attendez que votre ami réponde ...
|
||||
oarc-wait-buddy-select-yes=Vous apparaîtrez une fois que votre ami aura choisi oui ...
|
||||
|
||||
oarc-buddy-cancel-request=__1__ a annulé sa demande!
|
||||
|
||||
oarc-buddy-requesting-from-you=__1__ vous demande a appraître avec lui!
|
||||
|
||||
oarc-buddy-txt-main-team=l'équipe principale
|
||||
oarc-buddy-txt-new-teams=sur des équipes séparées
|
||||
oarc-buddy-txt-buddy-team=une équipe de amis
|
||||
oarc-buddy-txt-moat=entouré d'eau (fossé)
|
||||
oarc-buddy-txt-near=proche du centre de la carte!
|
||||
oarc-buddy-txt-far=loin du centre de la carte!
|
||||
oarc-buddy-txt-would-like=aimerait rejoindre
|
||||
oarc-buddy-txt-next-to-you=à côté de toi
|
||||
|
||||
oarc-buddy-declined=__1__ a refusé votre demande d'ami!
|
||||
|
||||
oarc-spawn-wait=Patienter s'il vous plaît!
|
||||
oarc-wait-text=Votre spawn est en cours de création. \nVous serez téléporté dans __1__ secondes! \nVeuillez patienter ...
|
@ -1,117 +0,0 @@
|
||||
scenario-name=Oarc多人游戏场景。
|
||||
|
||||
description=该场景允许每个玩家在加入游戏时创建自己的生成点。这里有许多便利功能,确保新玩家可以随时加入游戏或加入其他玩家的队伍。这是一个仅限多人游戏的场景。\n[color=red][font=default-bold]首先您必须创建一个config.lua文件,如果还没有的话![/font][/color]\n在场景文件夹内,复制"example-config.lua"并将其命名为"config.lua"。用任何文本编辑器编辑该文件。这是唯一配置场景选项的方法,必须在开始新游戏之前完成。\n[color=yellow][font=default-bold]更改配置或更新场景时,请始终开始新游戏![/font][/color]\n请访问https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn获取场景源代码、Wiki以及提交任何错误报告。Wiki上有关于如何在专用/无头服务器上最佳开始游戏的说明。\n[color=yellow][font=default-bold]如果你是从模组门户或通过加入服务器得到这个场景的,确保在场景文件夹中删除任何blueprint.zip文件![/font][/color]
|
||||
|
||||
oarc-spawn-time-warning-msg=由于这个场景的运作方式,你新出生点周围的土地可能需要一些时间来生成...当你选择你的第一个生成点时,请等待10-20秒。
|
||||
|
||||
oarc-i-understand=我明白了
|
||||
oarc-spawn-options=生成选项
|
||||
|
||||
oarc-click-info-btn-help=点击左上角的信息按钮以了解更多关于这个场景的信息!这是你唯一选择生成选项的机会,请慎重选择...
|
||||
|
||||
oarc-vanilla-spawn=原版生成
|
||||
oarc-default-spawn-behavior=这是原版游戏的默认生成行为。你将加入地图中心的默认队伍。
|
||||
|
||||
oarc-join-main-team-radio=加入主队(共享科技)
|
||||
oarc-create-own-team-radio=创建你自己的队伍(独立科技树)
|
||||
|
||||
oarc-moat-option=用护城河包围你的出生点
|
||||
|
||||
oarc-solo-spawn-near=单人出生点(近)
|
||||
oarc-solo-spawn-far=单人出生点(远)
|
||||
|
||||
oarc-starting-area-vanilla=你将在自己的起始区域生成(原版风格)。
|
||||
oarc-vanilla-spawns-available=目前有 __1__ 个原版生成点可用。
|
||||
|
||||
oarc-starting-area-normal=你将在一个新出生点出生。
|
||||
oarc-join-someone-avail=加入他人(有 __1__ 个可用)
|
||||
oarc-join-someone-info=你将在别人的基地出生。这需要至少有1个人开放了他们的基地。这个选择是最终的,你将无法再次创建自己的基地。
|
||||
|
||||
oarc-no-shared-avail=当前没有可用的共享基地。
|
||||
oarc-join-check-again=再次检查
|
||||
oarc-shared-spawn-disabled=本模式中禁用了共享生成。
|
||||
|
||||
oarc-buddy-spawn=和好友一起出生
|
||||
oarc-buddy-spawn-info=好友系统需要两个玩家同时在这个菜单中,你们将彼此并肩生成,各自拥有自己的资源。
|
||||
|
||||
oarc-max-players-shared-spawn=如果你创建自己的出生基地,则最多可以允许多达 __1__ 名其他在线玩家加入。
|
||||
oarc-spawn-dist-notes=近距离生成距离地图中心 __1__-__2__ 块。\n远距离生成距离地图中心 __3__-__4__ 块。\n单人出生有危险!要开荒到达其他玩家的地方,请做好准备。
|
||||
|
||||
oarc-player-is-joining-main-force=__ 1__正在加入主要团队!
|
||||
oarc-player-is-joining-near=__1__ 从远处加入了游戏!
|
||||
oarc-player-is-joining-far=___1__ 从很远的地方加入游戏!
|
||||
|
||||
oarc-please-wait=请稍候,正在生成您的出生点!
|
||||
|
||||
oarc-looking-for-buddy=__1__正在寻找队友。
|
||||
|
||||
oarc-avail-bases-join=可加入的基地:
|
||||
oarc-spawn-spots-remaining=__1__(还剩 __2__ 个名额)
|
||||
oarc-cancel-return-to-previous=取消(返回到之前的选项)
|
||||
oarc-player-requesting-join-you=__1__ 请求加入你的基地!
|
||||
oarc-waiting-for-spawn-owner=等待基地拥有者的回应...
|
||||
|
||||
oarc-you-will-spawn-once-host=一旦对方大佬选择是,你便会加入...
|
||||
oarc-player-cancel-join-request=__1__ 取消了他加入你基地的请求。
|
||||
|
||||
oarc-spawn-ctrl=生成控制
|
||||
oarc-spawn-controls=生成控制选项:
|
||||
oarc-spawn-allow-joiners=允许其他人加入你的基地。
|
||||
|
||||
oarc-set-respawn-loc=设置新的重生点(有冷却时间)
|
||||
oarc-set-respawn-loc-cooldown=重生点冷却剩余时间:__1__
|
||||
oarc-set-respawn-note=这将把你的重生点设置为你当前的位置。
|
||||
|
||||
oarc-select-player-join-queue=从申请队列中选择一个玩家:
|
||||
|
||||
oarc-accept=欣然接受
|
||||
oarc-reject=残忍拒绝
|
||||
|
||||
oarc-no-player-join-reqs=目前没有玩家请求加入你的基地。
|
||||
|
||||
oarc-start-shared-base=新玩家现在可以加入 __1__的基地!
|
||||
oarc-stop-shared-base=新玩家不能再加入 __1__ 的基地!
|
||||
|
||||
oarc-spawn-point-updated=重生点已更新!
|
||||
oarc-selected-player-not-wait=选中的玩家不再等待加入。
|
||||
oarc-reject-joiner=您已拒绝 __1__ 加入您的基地的请求。
|
||||
oarc-your-request-rejected=您的加入请求被拒绝了。
|
||||
|
||||
oarc-player-joining-base=__1__ 正在加入 __2__ 的基地!
|
||||
|
||||
oarc-player-left-while-joining=__1__ 退出了游戏,真是无情。
|
||||
|
||||
oarc-buddy-spawn-options=好友生成选项
|
||||
oarc-buddy-spawn-instructions=要使用此功能,请确保您和您的好友同时处于此菜单中。只需其中一人发送请求即可。从列表中选择你的好友(如果看不到好友的名字,请刷新),然后选择您的出生选项。单击请求按钮发送请求。然后,另一个伙伴可以接受(或拒绝)该请求。这将使你们俩都能在彼此旁边生成,每人都有自己的出生点。一旦伙伴接受了生成请求,便不可更改!
|
||||
|
||||
oarc-buddy-select-info=首先,从待选列表中选择一个好友。然后选择生成选项并发送您的请求:
|
||||
|
||||
oarc-buddy-refresh=刷新好友列表
|
||||
oarc-create-buddy-team=创建你自己的好友团队 (好友和你共享研究)
|
||||
|
||||
oarc-buddy-spawn-near=请求和好友出生 (近)
|
||||
oarc-buddy-spawn-far=请求和好友出生 (远)
|
||||
|
||||
oarc-invalid-buddy=你尚未选择有效的好友!请再试一遍。
|
||||
oarc-buddy-not-avail=已选择的好友不再可用!请再试一遍。
|
||||
|
||||
oarc-waiting-for-buddy=正在等待好友响应...
|
||||
oarc-wait-buddy-select-yes=一旦您的好友选择是,您将会出生…
|
||||
|
||||
oarc-buddy-cancel-request=__1__ 取消了其好友请求!
|
||||
|
||||
oarc-buddy-requesting-from-you=__1__ 正在向你请求好友生成!
|
||||
|
||||
oarc-buddy-txt-main-team=默认团队
|
||||
oarc-buddy-txt-new-teams=独立团队
|
||||
oarc-buddy-txt-buddy-team=好友团队
|
||||
oarc-buddy-txt-moat=被护城河环绕
|
||||
oarc-buddy-txt-near=靠近地图中心!
|
||||
oarc-buddy-txt-far=远离地图中心!
|
||||
oarc-buddy-txt-would-like=希望加入
|
||||
oarc-buddy-txt-next-to-you=在您旁边
|
||||
|
||||
oarc-buddy-declined=__1__ 拒绝了你的好友请求!
|
||||
|
||||
oarc-spawn-wait=请稍候!
|
||||
oarc-wait-text=您的出生点正在创建中。\n您将在 __1__ 秒内被传送到那里!\n请稍候…
|
Loading…
Reference in New Issue
Block a user