1022 lines
37 KiB
Lua
1022 lines
37 KiB
Lua
BioInd = require("__" .. script.mod_name .. "__.common")(script.mod_name)
|
|
local settings_changed = require("settings_changed")
|
|
|
|
if BioInd.get_startup_setting("BI_Enable_gvv_support") then
|
|
BioInd.writeDebug("Activating support for gvv!")
|
|
require("__gvv__/gvv")()
|
|
end
|
|
|
|
|
|
-- We can't just check if Alien Biomes is active, because we need to know if
|
|
-- the tiles we need from it exist in the game! To check this, we must call
|
|
-- game.get_tile_prototypes(), but this will crash in script.on_load(). So,
|
|
-- let's just declare the variable here and fill it later.
|
|
local AlienBiomes
|
|
|
|
local Event = require('__kry_stdlib__/stdlib/event/event').set_protected_mode(false)
|
|
require ("util")
|
|
require ("libs/util_ext")
|
|
require ("control_tree")
|
|
require ("control_arboretum")
|
|
|
|
|
|
---************** Used for Testing -----
|
|
--require ("Test_Spawn")
|
|
---*************
|
|
|
|
|
|
local function Create_dummy_force()
|
|
-- Create dummy force for musk floor if electric grid overlay should NOT be shown in map view
|
|
local f = game.create_force(BioInd.MuskForceName)
|
|
-- Set new force as neutral to every other force
|
|
for name, force in pairs(game.forces) do
|
|
if name ~= BioInd.MuskForceName then
|
|
f.set_friend(force, false)
|
|
f.set_cease_fire(force, true)
|
|
end
|
|
end
|
|
-- New force won't share chart data with any other force
|
|
f.share_chart = false
|
|
|
|
BioInd.writeDebug("Created force: %s", {game.forces[BioInd.MuskForceName].name})
|
|
end
|
|
|
|
|
|
-- Generate a look-up table with the names of our trees
|
|
local function get_bi_trees()
|
|
local list = {}
|
|
|
|
local trees = prototypes.get_entity_filtered({{filter = "type", type = "tree"}})
|
|
for tree_name, tree in pairs(trees) do
|
|
if tree_name:match("^bio%-tree%-.+%-%d$") then
|
|
BioInd.show("Found matching tree", tree_name)
|
|
list[tree_name] = true
|
|
end
|
|
end
|
|
|
|
return list
|
|
end
|
|
|
|
|
|
-- Generate a look-up table with the names of tiles that can't be changed by fertilizer
|
|
local tile_patterns = {
|
|
".*concrete.*",
|
|
".*stone%-path.*",
|
|
"^bi%-solar%-mat$",
|
|
"^bi%-wood%-floor$",
|
|
}
|
|
local function get_fixed_tiles()
|
|
local list = {}
|
|
|
|
for tile_name, tile in pairs(prototypes.tile) do
|
|
for p, pattern in ipairs(tile_patterns) do
|
|
if tile_name:match(pattern) then
|
|
BioInd.show("Found matching tile", tile_name)
|
|
-- If a tile is minable and fertilizer is used on it, we must deduct the mined
|
|
-- tiles from the player/robot again!
|
|
list[tile_name] = tile.mineable_properties.products or true
|
|
end
|
|
end
|
|
end
|
|
BioInd.show("Forbidden tiles", list)
|
|
return list
|
|
end
|
|
|
|
|
|
-- Generate a look-up table with recipe ingredients, as other mods may have changed them
|
|
local function get_arboretum_recipes()
|
|
local list = {}
|
|
|
|
local recipes = prototypes.recipe
|
|
local name
|
|
|
|
for i = 1, 5 do
|
|
name = "bi-arboretum-r" .. i
|
|
list[name] = {}
|
|
list[name].items = {}
|
|
list[name].fluids = {}
|
|
|
|
for i, ingredient in pairs(recipes[name].ingredients) do
|
|
if ingredient.type == "item" then
|
|
list[name].items[ingredient.name] = ingredient.amount
|
|
else
|
|
list[name].fluids[ingredient.name] = ingredient.amount
|
|
end
|
|
end
|
|
end
|
|
|
|
BioInd.show("Terraformer recipes", list)
|
|
return list
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
local function init()
|
|
BioInd.writeDebug("Entered init!")
|
|
if BioInd.is_debug then
|
|
game.check_prototype_translations()
|
|
end
|
|
|
|
storage = storage or {}
|
|
|
|
--------------------------------------------------------------------
|
|
-- Settings
|
|
--------------------------------------------------------------------
|
|
-- Global table for storing the last state of certain mod settings
|
|
storage.mod_settings = storage.mod_settings or {}
|
|
if BioInd.get_startup_setting("BI_Easy_Bio_Gardens") then
|
|
storage.mod_settings.garden_pole_connectors = BioInd.get_garden_pole_connectors()
|
|
else
|
|
storage.mod_settings.garden_pole_connectors = nil
|
|
end
|
|
|
|
-- Global table for storing the data of compound entities. They may change between
|
|
-- saves (e.g. Bio gardens only need hidden poles when the "Easy gardens" setting
|
|
-- is active).
|
|
storage.compound_entities = BioInd.rebuild_compound_entity_list()
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- Tree stuff!
|
|
--------------------------------------------------------------------
|
|
storage.bi = storage.bi or {}
|
|
storage.bi.tree_growing = storage.bi.tree_growing or {}
|
|
for i = 1, 4 do
|
|
storage.bi["tree_growing_stage_" .. i] = storage.bi["tree_growing_stage_" .. i] or {}
|
|
end
|
|
|
|
-- List of tree prototypes created by BI
|
|
storage.bi.trees = get_bi_trees()
|
|
|
|
-- List of tile prototypes that can't be fertilized
|
|
storage.bi.barren_tiles = get_fixed_tiles()
|
|
|
|
--------------------------------------------------------------------
|
|
-- Compound entities
|
|
--------------------------------------------------------------------
|
|
-- Check what global tables we need for compound entities
|
|
local compound_entity_tables = {}
|
|
for compound, compound_data in pairs(storage.compound_entities) do
|
|
-- BioInd.compound_entities contains entries that point to the same table
|
|
-- (e.g. straight/curved rails, or overlay entities), so we just overwrite
|
|
-- them to remove duplicates
|
|
compound_entity_tables[compound_data.tab] = compound
|
|
end
|
|
BioInd.show("Need to check these tables in global", compound_entity_tables)
|
|
|
|
-- Prepare global tables storing data of compound entities
|
|
local result
|
|
for compound_tab, compound_name in pairs(compound_entity_tables) do
|
|
-- Init table
|
|
storage[compound_tab] = storage[compound_tab] or {}
|
|
BioInd.writeDebug("Initialized storage[%s] (%s entities stored)",
|
|
{compound_name, table_size(storage[compound_tab])})
|
|
-- If this compound entity requires additional tables in global, initialize
|
|
-- them now!
|
|
local related_tables = storage.compound_entities[compound_name].add_global_tables
|
|
if related_tables then
|
|
for t, tab in ipairs(related_tables or {}) do
|
|
storage[tab] = storage[tab] or {}
|
|
BioInd.writeDebug("Initialized storage[%s] (%s values)", {tab, table_size(storage[tab])})
|
|
end
|
|
end
|
|
-- If this compound entity requires additional values in global, initialize
|
|
-- them now!
|
|
local related_vars = storage.compound_entities[compound_name].add_global_values
|
|
if related_vars then
|
|
for var_name, value in pairs(related_vars or {}) do
|
|
storage[var_name] = storage[var_name] or value
|
|
BioInd.writeDebug("Set storage[%s] to %s", {var_name, storage[var_name]})
|
|
end
|
|
end
|
|
|
|
-- Clean up global tables (We can skip this for empty tables!)
|
|
if next(storage[compound_tab]) then
|
|
-- Remove invalid entities
|
|
result = BioInd.clean_global_compounds_table(compound_name)
|
|
BioInd.writeDebug("Removed %s invalid entries from storage[%s]!",
|
|
{result, compound_tab})
|
|
-- Restore missing hidden entities
|
|
result = BioInd.restore_missing_entities(compound_name)
|
|
BioInd.writeDebug("Checked %s compound entities and restored %s missing hidden entries for storage[\"%s\"]!",
|
|
{result.checked, result.restored, compound_tab})
|
|
end
|
|
end
|
|
-- Search all surfaces for unregistered compound entities
|
|
result = BioInd.find_unregistered_entities()
|
|
BioInd.writeDebug("Registered %s forgotten entities!", {result})
|
|
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- Musk floor
|
|
--------------------------------------------------------------------
|
|
storage.bi_musk_floor_table = storage.bi_musk_floor_table or {}
|
|
storage.bi_musk_floor_table.tiles = storage.bi_musk_floor_table.tiles or {}
|
|
storage.bi_musk_floor_table.forces = storage.bi_musk_floor_table.forces or {}
|
|
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- Arboretum
|
|
--------------------------------------------------------------------
|
|
-- Global table for arboretum radars
|
|
storage.bi_arboretum_radar_table = storage.bi_arboretum_radar_table or {}
|
|
|
|
-- Global table of ingredients for terraformer recipes
|
|
storage.bi_arboretum_recipe_table = get_arboretum_recipes()
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- Compatibility with other mods
|
|
--------------------------------------------------------------------
|
|
storage.compatible = storage.compatible or {}
|
|
storage.compatible.AlienBiomes = BioInd.AB_tiles()
|
|
|
|
|
|
-- enable researched recipes
|
|
for i, force in pairs(game.forces) do
|
|
BioInd.writeDebug("Reset technology effects for force %s.", {force.name})
|
|
force.reset_technology_effects()
|
|
end
|
|
|
|
-- Create dummy force for musk floor if electric grid overlay should NOT be shown in map view
|
|
if BioInd.UseMuskForce and not game.forces[BioInd.MuskForceName] then
|
|
Create_dummy_force()
|
|
end
|
|
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
local function On_Load()
|
|
log("Entered On_Load!")
|
|
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
local function On_Config_Change(ConfigurationChangedData)
|
|
BioInd.writeDebug("On Configuration changed: %s", {ConfigurationChangedData})
|
|
|
|
|
|
-- Re-initialize global tables etc.
|
|
init()
|
|
|
|
-- Has setting BI_Show_musk_floor_in_mapview changed?
|
|
if ConfigurationChangedData.mod_startup_settings_changed then
|
|
settings_changed.musk_floor()
|
|
-- Has this been obsoleted by the new init process? Turn it off for now!
|
|
end
|
|
|
|
-- We've made a list of the tree prototypes that are currently available. Now we
|
|
-- need to make sure that the lists of growing trees don't contain removed tree
|
|
-- prototypes! (This fix is needed when "Alien Biomes" has been removed; it should
|
|
-- work with all other mods that create trees as well.)
|
|
local trees = storage.bi.trees
|
|
local tab
|
|
-- Growing stages
|
|
for i = 1, 4 do
|
|
tab = storage.bi["tree_growing_stage_" .. i]
|
|
BioInd.writeDebug("Number of trees in growing stage %s: %s", {i, table_size(tab)})
|
|
for t = #tab, 1, -1 do
|
|
if not trees[tab[t].tree_name] then
|
|
BioInd.writeDebug("Removing invalid tree %s (%s)", {t, tab[t].tree_name})
|
|
table.remove(tab, t)
|
|
end
|
|
end
|
|
|
|
-- Removing trees will create gaps in the table, but we need it as a continuous
|
|
-- list. (Trees need to be sorted by growing time, and we always look at the
|
|
-- tree with index 1 when checking if a tree has completed the growing stage, so
|
|
-- lets sort the table after all invalid trees have been removed!)
|
|
table.sort(tab, function(a, b) return a.time < b.time end)
|
|
BioInd.show("Number of trees in final list", #tab)
|
|
end
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
--- Used for some compatibility with Angels Mods
|
|
Event.register(defines.events.on_player_joined_game, function(event)
|
|
local player = game.players[event.player_index]
|
|
local force = player.force
|
|
local techs = force.technologies
|
|
|
|
if BioInd.get_startup_setting("angels-use-angels-barreling") then
|
|
techs['fluid-handling'].researched = false
|
|
techs['bi-tech-fertilizer'].reload()
|
|
local _t = techs['angels-fluid-barreling'].researched
|
|
techs['angels-fluid-barreling'].researched = false
|
|
techs['angels-fluid-barreling'].researched = _t
|
|
end
|
|
end)
|
|
|
|
|
|
---------------------------------------------
|
|
Event.register(defines.events.on_trigger_created_entity, function(event)
|
|
--- Used for Seed-bomb
|
|
local ent = event.entity
|
|
local surface = ent.surface
|
|
local position = ent.position
|
|
|
|
-- 'AlienBiomes' is a bool value -- we don't want to read it again if it's false,
|
|
-- but only if it hasn't been set yet!
|
|
AlienBiomes = AlienBiomes ~= nil and AlienBiomes or BioInd.AB_tiles()
|
|
|
|
-- Basic
|
|
if ent.name == "seedling" then
|
|
BioInd.writeDebug("Seed Bomb Activated - Basic")
|
|
seed_planted_trigger(event)
|
|
|
|
-- Standard
|
|
elseif ent.name == "seedling-2" then
|
|
BioInd.writeDebug("Seed Bomb Activated - Standard")
|
|
local currTile = surface.get_tile(position).name
|
|
if storage.bi.barren_tiles[currTile] then
|
|
BioInd.writeDebug("Can't fertilize %s!", {currTile})
|
|
else
|
|
BioInd.writeDebug("Using fertilizer!")
|
|
local terrain_name_s = AlienBiomes and "vegetation-green-grass-3" or "grass-3"
|
|
surface.set_tiles{{name = terrain_name_s, position = position}}
|
|
end
|
|
seed_planted_trigger(event)
|
|
|
|
-- Advanced
|
|
elseif ent.name == "seedling-3" then
|
|
BioInd.writeDebug("Seed Bomb Activated - Advanced")
|
|
local currTile = surface.get_tile(position).name
|
|
if storage.bi.barren_tiles[currTile] then
|
|
BioInd.writeDebug("Can't fertilize %s!", {currTile})
|
|
else
|
|
BioInd.writeDebug("Using fertilizer!")
|
|
local terrain_name_a = AlienBiomes and "vegetation-green-grass-1" or "grass-1"
|
|
surface.set_tiles{{name = terrain_name_a, position = position}}
|
|
end
|
|
seed_planted_trigger(event)
|
|
end
|
|
end)
|
|
|
|
--------------------------------------------------------------------
|
|
local function On_Built(event)
|
|
BioInd.writeDebug("Entered function On_Built with these data: " .. serpent.block(event))
|
|
local entity = event.created_entity or event.entity
|
|
if not (entity and entity.valid) then
|
|
BioInd.arg_err(entity or "nil", "entity")
|
|
end
|
|
|
|
local surface = BioInd.is_surface(entity.surface) or
|
|
BioInd.arg_err(entity.surface or "nil", "surface")
|
|
local position = BioInd.normalize_position(entity.position) or
|
|
BioInd.arg_err(entity.position or "nil", "position")
|
|
local force = entity.force
|
|
|
|
|
|
-- We can ignore ghosts -- if ghosts are revived, there will be
|
|
-- another event that triggers where actual entities are placed!
|
|
if entity.name == "entity-ghost" then
|
|
BioInd.writeDebug("Built ghost of %s -- return!", {entity.ghost_name})
|
|
return
|
|
end
|
|
|
|
BioInd.show("Built entity", BioInd.print_name_id(entity))
|
|
|
|
local base_entry = storage.compound_entities[entity.name]
|
|
local base = base_entry and entity
|
|
|
|
-- We've found a compound entity!
|
|
if base then
|
|
-- Make sure we work with a copy of the original table! We don't want to
|
|
-- remove anything from it for real.
|
|
local hidden_entities = util.table.deepcopy(base_entry.hidden)
|
|
|
|
BioInd.writeDebug("%s (%s) is a compound entity. Need to create %s", {base.name, base.unit_number, hidden_entities})
|
|
BioInd.show("hidden_entities", hidden_entities)
|
|
local new_base
|
|
local new_base_name = base_entry.new_base_name
|
|
-- If the base entity is only an overlay, we'll replace it with the real base
|
|
-- entity and raise an event. The hidden entities will be created in the second
|
|
-- pass (triggered by building the final entity).
|
|
BioInd.show("base_entry.new_base_name", base_entry.new_base_name)
|
|
BioInd.show("base_entry.new_base_name == base.name", base_entry.new_base_name == base.name)
|
|
BioInd.show("base_entry.optional", base_entry.optional)
|
|
if new_base_name and new_base_name ~= base.name then
|
|
new_base = surface.create_entity({
|
|
name = new_base_name,
|
|
position = base.position,
|
|
direction = base.direction,
|
|
force = base.force,
|
|
raise_built = true
|
|
})
|
|
new_base.health = base.health
|
|
BioInd.show("Created final base entity", BioInd.print_name_id(new_base))
|
|
|
|
base.destroy({raise_destroy = true})
|
|
base = new_base
|
|
BioInd.writeDebug("Destroyed old base entity!")
|
|
|
|
-- Second pass: We've placed the final base entity now, so we can create the
|
|
-- the hidden entities!
|
|
else
|
|
BioInd.writeDebug("Second pass -- creating hidden entities!")
|
|
BioInd.show("base_entry", base_entry)
|
|
|
|
BioInd.writeDebug("storage[%s]: %s", {base_entry.tab, storage[base_entry.tab]})
|
|
BioInd.show("base.name", base.name)
|
|
BioInd.show("base.unit_number", base.unit_number)
|
|
BioInd.show("hidden_entities", hidden_entities)
|
|
|
|
-- We must call create_entities even if there are no hidden entities (e.g. if
|
|
-- the "Easy Gardens" setting is disabled and no hidden poles are required)
|
|
-- because the compound entity gets registered there!
|
|
BioInd.create_entities(storage[base_entry.tab], base, hidden_entities)
|
|
BioInd.writeDebug("Stored %s in table: %s",
|
|
{BioInd.print_name_id(base), storage[base_entry.tab][base.unit_number]})
|
|
end
|
|
|
|
-- The built entity isn't one of our compound entities.
|
|
else
|
|
BioInd.writeDebug("%s is not a compound entity!", {BioInd.print_name_id(entity)})
|
|
|
|
-- If one of our hidden entities has been built, we'll have raised this event
|
|
-- ourselves and have passed on the base entity.
|
|
base = event.base_entity
|
|
|
|
local entities = BioInd.compound_entities
|
|
BioInd.show("Base entity", BioInd.print_name_id(base))
|
|
|
|
-- The hidden entities are listed with a common handle ("pole", "panel" etc.). We
|
|
-- can get it from the reverse-lookup list via the entity type!
|
|
local h_key = BioInd.HE_map_reverse[entity.type]
|
|
BioInd.show("h_key", h_key or "nil")
|
|
|
|
-- Arboretum radar -- we need to add it to the table!
|
|
if entity.type == "radar" and
|
|
entity.name == entities["bi-arboretum-area"].hidden[h_key].name and base then
|
|
storage.bi_arboretum_radar_table[entity.unit_number] = base.unit_number
|
|
entity.backer_name = ""
|
|
BioInd.writeDebug("Added %s to storage.bi_arboretum_radar_table", {BioInd.print_name_id(entity)})
|
|
|
|
-- Electric poles -- we need to take care that they don't hook up to hidden poles!
|
|
elseif entity.type == "electric-pole" then
|
|
local pole = entity
|
|
-- Make sure hidden poles of the Bio gardens are connected correctly!
|
|
if pole.name == entities["bi-bio-garden"].hidden[h_key].name and base then
|
|
BioInd.writeDebug("Bio garden!")
|
|
BioInd.connect_garden_pole(base, pole)
|
|
BioInd.writeDebug("Connected %s (%s)", {pole.name, pole.unit_number or "nil"})
|
|
end
|
|
|
|
-- A seedling has been planted
|
|
elseif entity.name == "seedling" then
|
|
seed_planted(event)
|
|
BioInd.writeDebug("Planted seedling!")
|
|
|
|
-- Something else has been built
|
|
else
|
|
BioInd.writeDebug("Nothing to do for %s!", {entity.name})
|
|
end
|
|
end
|
|
BioInd.writeDebug("End of function On_Built")
|
|
end
|
|
|
|
|
|
local function remove_plants(entity_position, tabl)
|
|
BioInd.writeDebug("Entered function remove_plants(%s, %s)", {entity_position or "nil", tabl or "nil"})
|
|
local e = BioInd.normalize_position(entity_position)
|
|
if not e then
|
|
BioInd.arg_err(entity_position or "nil", "position")
|
|
end
|
|
BioInd.check_args(tabl, "table")
|
|
|
|
local pos
|
|
|
|
for k, v in pairs(tabl or {}) do
|
|
pos = BioInd.normalize_position(v.position)
|
|
if pos and pos.x == e.x and pos.y == e.y then
|
|
BioInd.writeDebug("Removing entry %s from table: %s", {k, v})
|
|
table.remove(tabl, k)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
local function On_Pre_Remove(event)
|
|
BioInd.writeDebug("Entered function On_Pre_Remove(%s)", {event})
|
|
local entity = event.entity
|
|
|
|
if not (entity and entity.valid) then
|
|
BioInd.writeDebug("No valid entity -- nothing to do!")
|
|
return
|
|
end
|
|
|
|
local compound_entity = storage.compound_entities[entity.name]
|
|
local base_entry = compound_entity and storage[compound_entity.tab][entity.unit_number]
|
|
BioInd.show("entity.name", entity.name)
|
|
BioInd.show("entity.unit_number", entity.unit_number)
|
|
|
|
BioInd.show("compound_entity", compound_entity)
|
|
BioInd.show("base_entry", base_entry)
|
|
BioInd.show("compound_entity.tab", compound_entity and compound_entity.tab or "nil")
|
|
BioInd.writeDebug("storage[%s]: %s", {compound_entity and compound_entity.tab or "nil", compound_entity and storage[compound_entity.tab] or "nil"})
|
|
|
|
-- Found a compound entity from our list!
|
|
if base_entry then
|
|
BioInd.writeDebug("Found compound entity %s",
|
|
{base_entry.base and BioInd.print_name_id(base_entry.base)})
|
|
|
|
-- Arboretum: Need to separately remove the entry from the radar table
|
|
if entity.name == "bi-arboretum" and base_entry.radar and base_entry.radar.valid then
|
|
storage.bi_arboretum_radar_table[base_entry.radar.unit_number] = nil
|
|
BioInd.show("Removed arboretum radar! Table", storage.bi_arboretum_radar_table)
|
|
end
|
|
|
|
-- Power rails: Connections must be explicitely removed, otherwise the poles
|
|
-- from the remaining rails will automatically connect and bridge the gap in
|
|
-- the power supply!
|
|
if entity.name:match("bi%-%a+%-rail%-power") and base_entry.pole and base_entry.pole.valid then
|
|
BioInd.writeDebug("Before")
|
|
BioInd.writeDebug("Disconnecting %s!", {BioInd.print_name_id(base_entry.pole)})
|
|
base_entry.pole.disconnect_neighbour()
|
|
BioInd.writeDebug("After")
|
|
end
|
|
|
|
-- Default: Remove all hidden entities!
|
|
for hidden, h_name in pairs(compound_entity.hidden or {}) do
|
|
BioInd.show("hidden", hidden)
|
|
|
|
BioInd.writeDebug("Removing hidden entity %s", {BioInd.print_name_id(base_entry[hidden])})
|
|
BioInd.remove_entity(base_entry[hidden])
|
|
base_entry[hidden] = nil
|
|
end
|
|
storage[compound_entity.tab][entity.unit_number] = nil
|
|
|
|
-- Rail-to-power: Connections must be explicitely removed, otherwise the poles
|
|
-- from the different rail tracks hooked up to this connector will automatically
|
|
-- keep the separate power networks connected!
|
|
elseif entity.name == "bi-power-to-rail-pole" then
|
|
BioInd.writeDebug("Rail-to-power connector has been removed")
|
|
entity.disconnect_neighbour()
|
|
BioInd.writeDebug("Removed copper wires from %s (%g)", {entity.name, entity.unit_number})
|
|
|
|
-- Removed seedling
|
|
elseif entity.name == "seedling" then
|
|
BioInd.writeDebug("Seedling has been removed")
|
|
remove_plants(entity.position, storage.bi.tree_growing)
|
|
|
|
-- Removed tree
|
|
elseif entity.type == "tree" and storage.bi.trees[entity.name] then
|
|
BioInd.show("Removed tree", entity.name)
|
|
|
|
local tree_stage = entity.name:match('^.+%-(%d)$')
|
|
BioInd.writeDebug("Removed tree %s (grow stage: %s)", {entity.name, tree_stage or nil})
|
|
if tree_stage then
|
|
remove_plants(entity.position, storage.bi["tree_growing_stage_" .. tree_stage])
|
|
else
|
|
error(string.format("Tree %s does not have a valid tree_stage: %s", entity.name, tree_stage or "nil"))
|
|
end
|
|
|
|
-- Removed something else
|
|
else
|
|
BioInd.writeDebug("%s has been removed -- nothing to do!", {entity.name})
|
|
end
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
local function On_Damage(event)
|
|
local f_name = "On_Damage"
|
|
BioInd.writeDebug("Entered function %s(%s)", {f_name, event})
|
|
local entity = event.entity
|
|
local final_health = event.final_health
|
|
|
|
local arb = "bi-arboretum"
|
|
local associated
|
|
|
|
-- Base was damaged: Find the radar associated with it!
|
|
if entity.name == arb then
|
|
associated = storage.bi_arboretum_table[entity.unit_number].radar
|
|
-- Radar was damaged: Find the base entity!
|
|
elseif entity.name == storage.compound_entities[arb].hidden.radar.name then
|
|
local base_id = storage.bi_arboretum_radar_table[entity.unit_number]
|
|
associated = storage.bi_arboretum_table[base_id].base
|
|
end
|
|
|
|
if associated and associated.valid then
|
|
associated.health = final_health
|
|
BioInd.writeDebug("%s was damaged (%s). Reducing health of %s to %s!", {
|
|
BioInd.print_name_id(entity),
|
|
event.final_damage_amount,
|
|
entity.name == arb and "associated radar" or "base",
|
|
associated.health
|
|
})
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function On_Death(event)
|
|
local f_name = "On_Death"
|
|
BioInd.writeDebug("Entered function %s(%s)", {f_name, event})
|
|
|
|
local entity = event.entity
|
|
if not entity then
|
|
error("Something went wrong -- no entity data!")
|
|
end
|
|
|
|
if
|
|
-- Table checks
|
|
storage.compound_entities[entity.name] or
|
|
storage.bi.trees[entity.name] or
|
|
-- Entity checks
|
|
entity.name == storage.compound_entities["bi-arboretum"].hidden.radar.name or
|
|
entity.name == "bi-power-to-rail-pole" or
|
|
entity.name == "seedling" then
|
|
|
|
BioInd.writeDebug("Divert to On_Pre_Remove!")
|
|
On_Pre_Remove(event)
|
|
else
|
|
BioInd.writeDebug("Nothing to do!")
|
|
end
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- Radar stuff
|
|
--------------------------------------------------------------------
|
|
|
|
-- Radar completed a sector scan
|
|
local function On_Sector_Scanned(event)
|
|
local f_name = "On_Sector_Scanned"
|
|
BioInd.writeDebug("Entered function %s(%s)", {f_name, event})
|
|
|
|
---- Each time a Arboretum-Radar scans a sector ----
|
|
local arboretum = storage.bi_arboretum_radar_table[event.radar.unit_number]
|
|
if arboretum then
|
|
Get_Arboretum_Recipe(storage.bi_arboretum_table[arboretum], event)
|
|
end
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- Solar Mat stuff
|
|
--------------------------------------------------------------------
|
|
|
|
--------------------------------------------------------------------
|
|
-- Solar mat was removed
|
|
local function solar_mat_removed(event)
|
|
BioInd.writeDebug("Entered solar_mat_removed (\"%s\")", {event})
|
|
|
|
local surface = game.surfaces[event.surface_index]
|
|
local tiles = event.tiles
|
|
|
|
local pos, x, y
|
|
-- tiles contains an array of the old tiles and their position
|
|
for t, tile in pairs(tiles) do
|
|
if tile.old_tile and tile.old_tile.name == "bi-solar-mat" then
|
|
pos = BioInd.normalize_position(tile.position)
|
|
x, y = pos.x, pos.y
|
|
|
|
BioInd.writeDebug("Looking for hidden entities to remove")
|
|
for _, o in pairs(surface.find_entities_filtered{
|
|
name = {'bi-musk-mat-hidden-pole', 'bi-musk-mat-hidden-panel'},
|
|
position = {x + 0.5, y + 0.5}
|
|
} or {}) do
|
|
BioInd.show("Removing", o.name)
|
|
o.destroy()
|
|
end
|
|
|
|
-- Remove tile from global tables
|
|
local force_name = storage.bi_musk_floor_table.tiles and
|
|
storage.bi_musk_floor_table.tiles[x] and
|
|
storage.bi_musk_floor_table.tiles[x][y]
|
|
if force_name then
|
|
BioInd.writeDebug("Removing Musk floor tile from tables!")
|
|
storage.bi_musk_floor_table.tiles[x][y] = nil
|
|
if not next(storage.bi_musk_floor_table.tiles[x]) then
|
|
storage.bi_musk_floor_table.tiles[x] = nil
|
|
end
|
|
|
|
if storage.bi_musk_floor_table.forces[force_name] and
|
|
storage.bi_musk_floor_table.forces[force_name][x] then
|
|
storage.bi_musk_floor_table.forces[force_name][x][y] = nil
|
|
if not next(storage.bi_musk_floor_table.forces[force_name][x]) then
|
|
storage.bi_musk_floor_table.forces[force_name][x] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
BioInd.writeDebug("bi-solar-mat: removed %g tiles", {table_size(tiles)})
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- A solar mat must be placed
|
|
local function place_musk_floor(force, position, surface)
|
|
BioInd.check_args(force, "string")
|
|
position = BioInd.normalize_position(position) or BioInd.arg_err(position, "position")
|
|
surface = BioInd.is_surface(surface) or BioInd.arg_err(surface, "surface")
|
|
|
|
local x, y = position.x, position.y
|
|
local created
|
|
for n, name in ipairs({"bi-musk-mat-hidden-pole", "bi-musk-mat-hidden-panel"}) do
|
|
created = surface.create_entity({name = name, position = {x + 0.5, y + 0.5}, force = force})
|
|
created.minable = false
|
|
created.destructible = false
|
|
BioInd.writeDebug("Created %s: %s", {name, created.unit_number})
|
|
end
|
|
|
|
-- Add to global tables!
|
|
storage.bi_musk_floor_table.tiles[x] = storage.bi_musk_floor_table.tiles[x] or {}
|
|
storage.bi_musk_floor_table.tiles[x][y] = force
|
|
|
|
storage.bi_musk_floor_table.forces[force] = storage.bi_musk_floor_table.forces[force] or {}
|
|
storage.bi_musk_floor_table.forces[force][x] = storage.bi_musk_floor_table.forces[force][x] or {}
|
|
storage.bi_musk_floor_table.forces[force][x][y] = true
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- Solar mat was built
|
|
local function solar_mat_built(event)
|
|
BioInd.show("Entered function \"solar_mat_built\"", event)
|
|
-- Called from player, bot and script-raised events, so event may
|
|
-- contain "robot" or "player_index"
|
|
|
|
local tile = event.tile
|
|
local surface = game.surfaces[event.surface_index]
|
|
local player = event.player_index and game.players[event.player_index]
|
|
local robot = event.robot
|
|
local force = (BioInd.UseMuskForce and BioInd.MuskForceName) or
|
|
(event.player_index and game.players[event.player_index].force.name) or
|
|
(event.robot and event.robot.force.name) or
|
|
event.force.name
|
|
BioInd.show("Force.name", force)
|
|
|
|
-- Item that was used to place the tile
|
|
local item = event.item
|
|
local old_tiles = event.tiles
|
|
|
|
|
|
local position --, x, y
|
|
|
|
|
|
-- Musk floor has been built -- create hidden entities!
|
|
if tile.name == "bi-solar-mat" then
|
|
BioInd.writeDebug("Solar Mat has been built -- must create hidden entities!")
|
|
BioInd.show("Tile data", tile )
|
|
|
|
for index, t in pairs(old_tiles or {tile}) do
|
|
BioInd.show("Read old_tile inside loop", t)
|
|
-- event.tiles will also contain landscape tiles like "grass-1", and it will always
|
|
-- contain at least one tile
|
|
position = BioInd.normalize_position(t.position)
|
|
-- If we got here by a call from script_raised_built, force may be stored
|
|
-- with the tile
|
|
force = force or t.force
|
|
BioInd.show("Got force from tile data", t.force or "false")
|
|
BioInd.writeDebug("Building solar mat for force %s at position %s",
|
|
{tostring(type(force) == "table" and force.name or force), position})
|
|
|
|
place_musk_floor(force, position, surface)
|
|
end
|
|
|
|
-- Fertilizer/Advanced fertilizer has been used. Check if the tile was valid
|
|
-- (no Musk floor, no wooden floor, no concrete etc.)
|
|
elseif item and (item.name == "fertilizer" or item.name == "bi-adv-fertilizer") then
|
|
|
|
local restore_tiles = {}
|
|
local products, remove_this
|
|
|
|
for index, t in pairs(old_tiles or {tile}) do
|
|
BioInd.show("index", index)
|
|
BioInd.show("t.old_tile.name", t.old_tile.name)
|
|
|
|
-- We want to restore removed tiles if nothing is supposed to grow on them!
|
|
if storage.bi.barren_tiles[t.old_tile.name] then
|
|
BioInd.writeDebug("%s was used on forbidden ground (%s)!", {item.name, t.old_tile.name})
|
|
restore_tiles[#restore_tiles + 1] = {name = t.old_tile.name, position = t.position}
|
|
|
|
-- Is that tile minable?
|
|
products = storage.bi.barren_tiles[t.old_tile.name]
|
|
if type(products) == "table" then
|
|
for p, product in ipairs(products) do
|
|
remove_this = {name = product.name, count = product.amount}
|
|
if player then
|
|
BioInd.writeDebug("Removing %s (%s) from player %s",
|
|
{product.name, product.amount, player.name})
|
|
player.remove_item(remove_this)
|
|
elseif robot then
|
|
BioInd.writeDebug("Removing %s (%s) from robot %s",
|
|
{product.name, product.amount, robot.unit_number})
|
|
robot.remove_item(remove_this)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
BioInd.show("restore_tiles", restore_tiles)
|
|
if restore_tiles then
|
|
surface.set_tiles(
|
|
restore_tiles,
|
|
true, -- correct_tiles
|
|
true, -- remove_colliding_entities
|
|
true, -- remove_colliding_decoratives
|
|
true -- raise_event
|
|
)
|
|
end
|
|
|
|
-- Some other tile has been built -- check if it replaced musk floor!
|
|
else
|
|
local test
|
|
local removed_tiles = {}
|
|
for index, t in pairs(old_tiles or {tile}) do
|
|
position = BioInd.normalize_position(t.position)
|
|
test = storage.bi_musk_floor_table and
|
|
storage.bi_musk_floor_table.tiles and
|
|
storage.bi_musk_floor_table.tiles[position.x] and
|
|
storage.bi_musk_floor_table.tiles[position.x][position.y]
|
|
if test then
|
|
removed_tiles[#removed_tiles + 1] = {
|
|
old_tile = {name = "bi-solar-mat"},
|
|
position = position
|
|
}
|
|
end
|
|
end
|
|
if next(removed_tiles) then
|
|
solar_mat_removed({surface_index = event.surface_index, tiles = removed_tiles})
|
|
else
|
|
BioInd.writeDebug("%s has been built -- nothing to do!", {tile.name})
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
-- A tille has been changed
|
|
local function Tile_Changed(event)
|
|
local f_name = "Tile_Changed"
|
|
BioInd.writeDebug("Entered function %s(%s)", {f_name, event})
|
|
|
|
-- The event gives us only a list of the new tiles that have been placed.
|
|
-- So let's check if any Musk floor has been built!
|
|
local new_musk_floor_tiles = {}
|
|
local old_musk_floor_tiles = {}
|
|
local remove_musk_floor_tiles = {}
|
|
local pos, old_tile, force
|
|
|
|
local tile_force
|
|
|
|
for t, tile in ipairs(event.tiles) do
|
|
BioInd.show("t", t)
|
|
pos = BioInd.normalize_position(tile.position)
|
|
tile_force = storage.bi_musk_floor_table.tiles[pos.x] and
|
|
storage.bi_musk_floor_table.tiles[pos.x][pos.y]
|
|
BioInd.show("Placed tile", tile.name)
|
|
|
|
-- Musk floor was placed
|
|
if tile.name == "bi-solar-mat" then
|
|
BioInd.writeDebug("Musk floor tile was placed!")
|
|
new_musk_floor_tiles[#new_musk_floor_tiles + 1] = {
|
|
old_tile = { name = tile.name },
|
|
position = pos,
|
|
force = tile_force or
|
|
BioInd.UseMuskForce and BioInd.MuskForceName or
|
|
"neutral"
|
|
}
|
|
-- Other tile was placed -- by one of our fertilizers?
|
|
elseif tile.name:match("^vegetation%-green%-grass%-[13]$") or
|
|
tile.name:match("^green%-grass%-[13]$") then
|
|
BioInd.writeDebug("Fertilizer was used!")
|
|
|
|
-- Fertilizer was used on a Musk floor tile -- restore the tile!
|
|
BioInd.show("Musk floor tile in position", tile_force)
|
|
if tile_force then
|
|
old_musk_floor_tiles[#old_musk_floor_tiles + 1] = {
|
|
old_tile = { name = "bi-solar-mat" },
|
|
position = pos,
|
|
force = tile_force
|
|
}
|
|
end
|
|
-- Other tile was placed on a Musk floor tile -- remove Musk floor from lists!
|
|
elseif tile_force then
|
|
remove_musk_floor_tiles[#remove_musk_floor_tiles + 1] = {
|
|
old_tile = { name = "bi-solar-mat" },
|
|
position = pos,
|
|
}
|
|
end
|
|
end
|
|
BioInd.show("new_musk_floor_tiles", new_musk_floor_tiles)
|
|
BioInd.show("old_musk_floor_tiles", old_musk_floor_tiles)
|
|
BioInd.show("remove_musk_floor_tiles", remove_musk_floor_tiles)
|
|
|
|
if next(new_musk_floor_tiles) then
|
|
solar_mat_built({
|
|
surface_index = event.surface_index,
|
|
tile = {name = "bi-solar-mat"},
|
|
force = BioInd.MuskForceName,
|
|
tiles = new_musk_floor_tiles
|
|
})
|
|
end
|
|
if next(old_musk_floor_tiles) then
|
|
solar_mat_built({
|
|
surface_index = event.surface_index,
|
|
tile = {name = "bi-solar-mat"},
|
|
tiles = old_musk_floor_tiles
|
|
})
|
|
end
|
|
if next(remove_musk_floor_tiles) then
|
|
solar_mat_removed({surface_index = event.surface_index, tiles = remove_musk_floor_tiles})
|
|
end
|
|
BioInd.show("End of function", f_name)
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
|
|
Event.register(Event.core_events.configuration_changed, On_Config_Change)
|
|
Event.register(Event.core_events.init, init)
|
|
Event.register(Event.core_events.load, On_Load)
|
|
|
|
|
|
Event.build_events = {
|
|
defines.events.on_built_entity,
|
|
defines.events.on_robot_built_entity,
|
|
defines.events.script_raised_built,
|
|
defines.events.script_raised_revive
|
|
}
|
|
Event.pre_remove_events = {
|
|
defines.events.on_pre_player_mined_item,
|
|
defines.events.on_robot_pre_mined,
|
|
defines.events.on_player_mined_entity,
|
|
defines.events.on_robot_mined_entity,
|
|
}
|
|
Event.death_events = {
|
|
defines.events.on_entity_died,
|
|
defines.events.script_raised_destroy
|
|
}
|
|
Event.tile_build_events = {
|
|
defines.events.on_player_built_tile,
|
|
defines.events.on_robot_built_tile
|
|
}
|
|
Event.tile_remove_events = {
|
|
defines.events.on_player_mined_tile,
|
|
defines.events.on_robot_mined_tile
|
|
}
|
|
Event.tile_script_action = {
|
|
defines.events.script_raised_set_tiles
|
|
}
|
|
|
|
Event.register(Event.build_events, On_Built)
|
|
Event.register(Event.pre_remove_events, On_Pre_Remove)
|
|
Event.register(Event.death_events, On_Death)
|
|
Event.register(Event.tile_build_events, solar_mat_built)
|
|
Event.register(Event.tile_remove_events, solar_mat_removed)
|
|
|
|
|
|
Event.register(defines.events.on_entity_damaged, On_Damage, function(event)
|
|
-- A function is needed for event filtering with stdlib!
|
|
local entity = event.entity
|
|
|
|
-- Ignore damage without effect (invulnerable/resistant entities)
|
|
if event.final_damage_amount ~= 0 and
|
|
-- Terraformer/Terraformer radar was damaged
|
|
(storage.bi_arboretum_table[entity.unit_number] or
|
|
storage.bi_arboretum_radar_table[entity.unit_number]) then
|
|
return true
|
|
end
|
|
end)
|
|
|
|
-- Radar scan
|
|
Event.register(defines.events.on_sector_scanned, On_Sector_Scanned, function(event)
|
|
-- A function is needed for event filtering with stdlib!
|
|
if event.radar.name == BioInd.compound_entities["bi-arboretum"].hidden.radar.name then
|
|
return true
|
|
end
|
|
end)
|
|
|
|
-- Tile changed
|
|
Event.register(Event.tile_script_action, Tile_Changed)
|
|
|
|
|
|
------------------------------------------------------------------------------------
|
|
-- FIND LOCAL VARIABLES THAT ARE USED GLOBALLY --
|
|
-- (Thanks to eradicator!) --
|
|
------------------------------------------------------------------------------------
|
|
setmetatable(_ENV, {
|
|
__newindex = function (self, key, value) --locked_global_write
|
|
error('\n\n[ER Global Lock] Forbidden global *write*:\n'
|
|
.. serpent.line{key = key or '<nil>', value = value or '<nil>'} .. '\n')
|
|
end,
|
|
__index = function (self, key) --locked_global_read
|
|
if not (key == "game" or key == "mods" or key == "storage") then
|
|
error('\n\n[ER Global Lock] Forbidden global *read*:\n'
|
|
.. serpent.line{key = key or '<nil>'} .. '\n')
|
|
end
|
|
end
|
|
})
|