1
0
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:
Oarcinae 2024-08-10 10:07:30 -04:00
parent 5bc032dfb3
commit 7b2b26a330
37 changed files with 12 additions and 9946 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
config.lua

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -1,4 +0,0 @@
{
"order": "a",
"multiplayer-compatible": true
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

BIN
image.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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...

View File

@ -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...

View File

@ -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 ...

View File

@ -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请稍候…