Bio_Industries_2/Bio_Industries_2/control_arboretum.lua
Simon Brodtmann 3051414d98 Cleanup
2025-07-05 22:31:21 +02:00

261 lines
11 KiB
Lua

BioInd.writeDebug("Entered control_arboretum.lua")
---Arboretum Stuff
local Event = require('__kry_stdlib__/stdlib/event/event').set_protected_mode(false)
-- If a recipe with NORMAL FERTILIZER is used, don't fertilize tiles set have "true"
-- set! (Fertile tiles set to true in this table can't be made more fertile with
-- normal fertilizer, and nothing should grow on the other tiles.)
local Terrain_Check_1 = {
["grass-1"] = true, -- Fertility: 100%
["grass-3"] = true, -- Fertility: 85%
["vegetation-green-grass-1"] = true, -- Fertility: 100%
["vegetation-green-grass-3"] = true, -- Fertility: 85%
}
-- If a recipe with ADVANCED FERTILIZER is used, don't fertilize tiles set have "true" set!
-- (Fertile tiles in this table can't be made more fertile, and nothing should grow on the
-- the others tiles!)
local Terrain_Check_2 = {
["grass-1"] = true, -- Fertility: 100%
["vegetation-green-grass-1"] = true, -- Fertility: 100%
}
local plant_radius = 75
-- Different tiles are used if AlienBiomes is active
local AB, terrain_name_g1, terrain_name_g3
-- OmniFluid replaces all fluids with items, so the arboretum won't have a fluidbox!
local function get_new_position(pos)
pos = BioInd.normalize_position(pos) or BioInd.arg_err("nil", position)
local xxx = math.random(-plant_radius, plant_radius)
local yyy = math.random(-plant_radius, plant_radius)
return {x = pos.x + xxx, y = pos.y + yyy}
end
-- Check that all ingredients are available!
local function check_ingredients(arboretum)
local recipe = arboretum.get_recipe()
local need = recipe and storage.bi_arboretum_recipe_table[recipe.name]
local function check(need, have)
for name, amount in pairs(need or {}) do
if not (have and have[name]) or (have[name] < amount) then
BioInd.writeDebug("Missing ingredient %s (have %s of %s)", {name, have[name] or 0, amount})
return false
end
end
return true
end
local inventory = arboretum.get_inventory(defines.inventory.assembling_machine_input)
return need and
check(need.items, inventory and inventory.get_contents()) and
check(need.fluids, arboretum.get_fluid_contents()) and
{ingredients = need, name = recipe.name} or nil
end
local function consume_ingredients(arboretum, need)
local inventory = arboretum.get_inventory(defines.inventory.assembling_machine_input)
for item, i in pairs(need.items or {}) do
inventory.remove({name = item, count = i})
BioInd.writeDebug("Removed %s (%s)", {item, i})
end
BioInd.show("Inventory", inventory.get_contents() or "nil")
for fluid, f in pairs(need.fluids or {}) do
arboretum.remove_fluid({name = fluid, amount = f})
BioInd.writeDebug("Removed %s (%s)", {fluid, f})
end
BioInd.show("Fluid contents", arboretum.get_fluid_contents() or "nil")
end
local function set_tile(current, target, surface, position)
if current ~= target then
surface.set_tiles(
{{name = target, position = position}},
true, -- correct_tiles
true, -- remove_colliding_entities
true, -- remove_colliding_decoratives
true -- raise_event
)
end
end
function Get_Arboretum_Recipe(ArboretumTable, event)
BioInd.writeDebug("Entered function Get_Arboretum_Recipe(%s, %s)", {ArboretumTable, event})
if not ArboretumTable then
BioInd.writeDebug("%s is not a valid ArboretumTable. Leaving immediately!")
return
end
local arboretum = ArboretumTable.base
local new_position, currentTilename
local pos, surface, Inventory, stack
-- '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!
AB = storage.compatible.AlienBiomes
terrain_name_g1 = terrain_name_g1 or (AB and "vegetation-green-grass-1" or "grass-1")
terrain_name_g3 = terrain_name_g3 or (AB and "vegetation-green-grass-3" or "grass-3")
local check = check_ingredients(arboretum)
local ingredients, recipe_name
if check then
ingredients, recipe_name = check.ingredients, check.name
end
if ingredients then
local create_seedling, new_plant
pos = BioInd.normalize_position(arboretum.position) or
BioInd.arg_err("nil", "position")
surface = arboretum.surface
-- Just plant a tree and hope the ground is fertile!
if recipe_name == "bi-arboretum-r1" then
BioInd.writeDebug(tostring(recipe_name) .. ": Just plant a tree")
--- 10 attempts to find a random spot to plant a tree and/or change terrain
for k = 1, 10 do
new_position = get_new_position(pos)
new_plant = {
name= "seedling",
position = new_position,
force = "neutral"
}
if surface.can_place_entity(new_plant) then
consume_ingredients(arboretum, ingredients)
create_seedling = surface.create_entity(new_plant)
seed_planted_arboretum(event, create_seedling)
--- After sucessfully planting a tree, break out of the loop.
break
else
BioInd.writeDebug("Can't plant here (attempt %s)", k)
end
end
-- Fertilize the ground with normal fertilizer. Ignore tiles listed in Terrain_Check_1!
elseif recipe_name == "bi-arboretum-r2" then
BioInd.writeDebug(tostring(recipe_name) .. ": Just change terrain to grass-3 (basic)")
for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain
new_position = get_new_position(pos)
currentTilename = surface.get_tile(new_position.x, new_position.y).name
-- We need to fertilize the ground!
if Bi_Industries.fertility[currentTilename] and not Terrain_Check_1[currentTilename] then
consume_ingredients(arboretum, ingredients)
BioInd.writeDebug("%s: Changing terrain from %s to %s (%s)",
{k, currentTilename or "unknown tile",
terrain_name_g3, serpent.line(new_position)})
set_tile(currentTilename, terrain_name_g3, surface, new_position)
--- After sucessfully changing the terrain, break out of the loop.
break
else
BioInd.writeDebug("%s: Can't change terrain (%s)",
{k, currentTilename or "unknown tile"})
end
end
-- Fertilize the ground with advanced fertilizer. Ignore tiles listed in Terrain_Check_2!
elseif recipe_name == "bi-arboretum-r3" then
BioInd.writeDebug(tostring(recipe_name) .. ": Just change terrain to grass-1 (advanced)")
for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain
new_position = get_new_position(pos)
currentTilename = surface.get_tile(new_position.x, new_position.y).name
if Bi_Industries.fertility[currentTilename] and currentTilename ~= terrain_name_g1 then
consume_ingredients(arboretum, ingredients)
BioInd.writeDebug("%s: Changing terrain from %s to %s (%s)",
{k, currentTilename or "unknown tile",
terrain_name_g1, serpent.line(new_position)})
set_tile(currentTilename, terrain_name_g1, surface, new_position)
--- After sucessfully changing the terrain, break out of the loop.
break
else
BioInd.writeDebug("%s: Can't change terrain (%s)",
{k, currentTilename or "unknown tile"})
end
end
-- Fertilize the ground with normal fertilizer. Ignore tiles listed in Terrain_Check_1!
-- Also plant a tree.
elseif recipe_name == "bi-arboretum-r4" then
BioInd.writeDebug(tostring(recipe_name) .. ": Plant Tree AND change the terrain to grass-3 (basic)")
for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain
new_position = get_new_position(pos)
currentTilename = surface.get_tile(new_position.x, new_position.y).name
new_plant = {
name= "seedling",
position = new_position,
force = "neutral"
}
-- Test to see if we can plant
if surface.can_place_entity(new_plant) and Bi_Industries.fertility[currentTilename] then
consume_ingredients(arboretum, ingredients)
-- Refund fertilizer -- no need to waste it on fertile ground!
if Terrain_Check_1[currentTilename] then
arboretum.insert({name = "fertilizer", count = ingredients.items.fertilizer})
BioInd.writeDebug("Refunded fertilizer!")
end
set_tile(currentTilename, terrain_name_g3, surface, new_position)
create_seedling = surface.create_entity(new_plant)
seed_planted_arboretum(event, create_seedling)
--- After sucessfully planting a tree or changing the terrain, break out of the loop.
break
else
BioInd.writeDebug("%s: Can't change terrain and plant a tree (%s)",
{k, currentTilename or "unknown tile"})
end
end
-- Fertilize the ground with advanced fertilizer. Ignore tiles listed in Terrain_Check_2!
-- Also plant a tree.
elseif recipe_name == "bi-arboretum-r5" then
BioInd.writeDebug(tostring(recipe_name) .. ": Plant Tree and change the terrain to grass-1 (advanced)")
for k = 1, 10 do --- 10 attempts to find a random spot to plant a tree and / or change terrain
new_position = get_new_position(pos)
currentTilename = surface.get_tile(new_position.x, new_position.y).name
new_plant = {
name= "seedling",
position = new_position,
force = "neutral"
}
if surface.can_place_entity(new_plant) and Bi_Industries.fertility[currentTilename] then
consume_ingredients(arboretum, ingredients)
-- Refund fertilizer -- no need to waste it on fertile ground!
if Terrain_Check_2[currentTilename] then
arboretum.insert({
name = "bi-adv-fertilizer", count = ingredients.items["bi-adv-fertilizer"]
})
BioInd.writeDebug("Refunded advanced fertilizer!")
end
set_tile(currentTilename, terrain_name_g1, surface, new_position)
create_seedling = surface.create_entity(new_plant)
seed_planted_arboretum (event, create_seedling)
--- After sucessfully planting a tree or changing the terrain, break out of the loop.
break
else
BioInd.writeDebug("%s: Can't change terrain and plant a tree (%s)",
{k, currentTilename or "unknown tile"})
end
end
else
BioInd.writeDebug("Terraformer has no recipe!")
end
end
end