feat: v1.12.1.0 — prisregel via sæsonkurven, reserve til gårdens eget forbrug, paller til palleskur, fanen Lagre (idéer fra Distribution Redux)
This commit is contained in:
@@ -317,6 +317,281 @@ function ADSources.getSellMarkers(adEnv, farmId)
|
||||
return result
|
||||
end
|
||||
|
||||
-- ---- paller til lager: objektlager (palleskur) som mål ----
|
||||
|
||||
function ADSources.objectStorageAccepts(placeable, fillType)
|
||||
local spec = placeable ~= nil and placeable.spec_objectStorage or nil
|
||||
if spec == nil or spec.supportsPallets == false then
|
||||
return false
|
||||
end
|
||||
if placeable.getObjectStorageSupportsFillType ~= nil then
|
||||
local ok, value = pcall(placeable.getObjectStorageSupportsFillType, placeable, fillType)
|
||||
return ok and value == true
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Ledige pladser (objekter); uendeligt når lageret ingen kapacitet opgiver.
|
||||
function ADSources.objectStorageFreeSlots(placeable)
|
||||
local spec = placeable ~= nil and placeable.spec_objectStorage or nil
|
||||
if spec == nil then
|
||||
return 0
|
||||
end
|
||||
local capacity = spec.capacity or 0
|
||||
if capacity <= 0 then
|
||||
return math.huge
|
||||
end
|
||||
local stored = spec.storedObjects ~= nil and #spec.storedObjects or (spec.numStoredObjects or 0)
|
||||
return math.max(0, capacity - stored)
|
||||
end
|
||||
|
||||
-- Nærmeste markør ved et objektlager der tager varen og har plads, med rute fra traktoren;
|
||||
-- kilderne selv udelukkes. {wayPointId, name, free = pladser} eller nil.
|
||||
function ADSources.findPalletStore(adEnv, vehicle, fillType, excludedPlaceables, isReachable, farmId)
|
||||
local x, z = getNodePosition(vehicle.rootNode)
|
||||
if x == nil then
|
||||
return nil
|
||||
end
|
||||
local candidates = {}
|
||||
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
|
||||
local source = ADSources.identify(adEnv, marker.id, farmId)
|
||||
if source ~= nil and source.kind == "objectStorage" and not (excludedPlaceables ~= nil and excludedPlaceables[source.placeable])
|
||||
and ADSources.objectStorageAccepts(source.placeable, fillType) and ADSources.objectStorageFreeSlots(source.placeable) >= 1 then
|
||||
local wayPoint = adEnv.ADGraphManager:getWayPointById(marker.id)
|
||||
table.insert(candidates, {marker = marker, source = source, distance = distance2(x, z, wayPoint.x, wayPoint.z)})
|
||||
end
|
||||
end
|
||||
table.sort(candidates, function(a, b) return a.distance < b.distance end)
|
||||
for _, candidate in ipairs(candidates) do
|
||||
if isReachable == nil or isReachable(candidate.marker.id) then
|
||||
return {wayPointId = candidate.marker.id, name = tostring(candidate.marker.name), free = ADSources.objectStorageFreeSlots(candidate.source.placeable)}
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- ---- reserve: hvad gårdens egne fabrikker og stalde skal bruge det næste døgn ----
|
||||
|
||||
ADSources.RESERVE_HOURS = 24
|
||||
|
||||
local function isOwnedBy(placeable, farmId)
|
||||
if placeable.getOwnerFarmId ~= nil then
|
||||
local ok, owner = pcall(placeable.getOwnerFarmId, placeable)
|
||||
return ok and owner == farmId
|
||||
end
|
||||
return placeable.ownerFarmId == farmId
|
||||
end
|
||||
|
||||
local function isProductionWanted(productionPoint, production)
|
||||
local isEnabled = false
|
||||
if productionPoint.getIsProductionEnabled ~= nil then
|
||||
isEnabled = productionPoint:getIsProductionEnabled(production.id) == true
|
||||
else
|
||||
for _, active in ipairs(productionPoint.activeProductions or {}) do
|
||||
if active == production then isEnabled = true end
|
||||
end
|
||||
end
|
||||
local missingInputs = ProductionPoint ~= nil and ProductionPoint.PROD_STATUS ~= nil and ProductionPoint.PROD_STATUS.MISSING_INPUTS or nil
|
||||
return isEnabled or (missingInputs ~= nil and production.status == missingInputs)
|
||||
end
|
||||
|
||||
-- Fabrik: døgnforbrug af varen i ønskede produktioner minus det den har, højst fri plads.
|
||||
local function getProductionReserve(placeable, fillType)
|
||||
local productionPoint = getProductionPoint(placeable)
|
||||
if productionPoint == nil or productionPoint.storage == nil then
|
||||
return 0
|
||||
end
|
||||
local perMinute = 0
|
||||
for _, production in ipairs(productionPoint.productions or {}) do
|
||||
if isProductionWanted(productionPoint, production) then
|
||||
for _, input in ipairs(production.inputs or {}) do
|
||||
if input.type == fillType then
|
||||
local cyclesPerMinute = production.cyclesPerMinute or ((production.cyclesPerHour or 0) / 60)
|
||||
perMinute = perMinute + (input.amount or 0) * cyclesPerMinute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if perMinute <= 0 then
|
||||
return 0
|
||||
end
|
||||
local storage = productionPoint.storage
|
||||
local level = storage.getFillLevel ~= nil and (storage:getFillLevel(fillType) or 0) or ((storage.fillLevels or {})[fillType] or 0)
|
||||
local free = storage.getFreeCapacity ~= nil and storage:getFreeCapacity(fillType) or nil
|
||||
if free == nil then
|
||||
local capacity = storage.getCapacity ~= nil and (storage:getCapacity(fillType) or 0) or 0
|
||||
free = math.max(0, capacity - level)
|
||||
end
|
||||
local need = perMinute * 60 * ADSources.RESERVE_HOURS - level
|
||||
return math.max(0, math.min(need, free))
|
||||
end
|
||||
|
||||
-- Stald: foder/halm/vand-rate × timer minus beholdning, højst fri plads (spec-felter som
|
||||
-- Distribution Redux læser dem); automatisk vandforsyning = intet behov.
|
||||
local function getHusbandryReserve(placeable, fillType)
|
||||
if placeable.getHusbandryIsFillTypeSupported == nil or placeable.getHusbandryFillLevel == nil then
|
||||
return 0
|
||||
end
|
||||
local okSupported, supported = pcall(placeable.getHusbandryIsFillTypeSupported, placeable, fillType)
|
||||
if not okSupported or supported ~= true then
|
||||
return 0
|
||||
end
|
||||
local name = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or ""
|
||||
local rate, level = 0, placeable:getHusbandryFillLevel(fillType) or 0
|
||||
local food, straw, water = placeable.spec_husbandryFood, placeable.spec_husbandryStraw, placeable.spec_husbandryWater
|
||||
if name == "WATER" then
|
||||
if water == nil or water.automaticWaterSupply then return 0 end
|
||||
rate = water.litersPerHour or 0
|
||||
elseif name == "STRAW" and straw ~= nil then
|
||||
rate = straw.inputLitersPerHour or 0
|
||||
elseif food ~= nil then
|
||||
rate = food.litersPerHour or 0
|
||||
level = 0
|
||||
for _, value in pairs(food.fillLevels or {}) do level = level + (value or 0) end
|
||||
end
|
||||
if rate <= 0 then
|
||||
return 0
|
||||
end
|
||||
local free = placeable.getHusbandryFreeCapacity ~= nil and (placeable:getHusbandryFreeCapacity(fillType) or 0) or math.huge
|
||||
return math.max(0, math.min(rate * ADSources.RESERVE_HOURS - level, free))
|
||||
end
|
||||
|
||||
-- {liters, consumers = {navne}} — gårdens samlede behov for varen; udelukkede placeables (kilderne) tæller ikke.
|
||||
function ADSources.getFarmDemand(adEnv, fillType, farmId, excludedPlaceables)
|
||||
local placeables = g_currentMission ~= nil and g_currentMission.placeableSystem ~= nil and g_currentMission.placeableSystem.placeables or {}
|
||||
local total, consumers = 0, {}
|
||||
for _, placeable in pairs(placeables) do
|
||||
if isOwnedBy(placeable, farmId) and not (excludedPlaceables ~= nil and excludedPlaceables[placeable]) then
|
||||
local reserve = getProductionReserve(placeable, fillType) + getHusbandryReserve(placeable, fillType)
|
||||
if reserve > 0 then
|
||||
total = total + reserve
|
||||
table.insert(consumers, getPlaceableName(placeable, "?"))
|
||||
end
|
||||
end
|
||||
end
|
||||
return {liters = total, consumers = consumers}
|
||||
end
|
||||
|
||||
-- ---- inventar: alt gården har liggende, pr. bygning ----
|
||||
|
||||
local function addEntry(entries, fillType, level, capacity, extra)
|
||||
local entry = newProduct(fillType, level, level, capacity, false)
|
||||
entry.isOutput = extra ~= nil and extra.isOutput or false
|
||||
entry.count = extra ~= nil and extra.count or nil
|
||||
table.insert(entries, entry)
|
||||
end
|
||||
|
||||
local function factoryEntries(placeable)
|
||||
local productionPoint = getProductionPoint(placeable)
|
||||
local storage = productionPoint ~= nil and productionPoint.storage or nil
|
||||
local entries = {}
|
||||
if storage == nil then return entries end
|
||||
local outputs = {}
|
||||
for _, production in ipairs(productionPoint.productions or {}) do
|
||||
for _, output in ipairs(production.outputs or {}) do outputs[output.type] = true end
|
||||
end
|
||||
for fillType, level in pairs(storage.fillLevels or {}) do
|
||||
if (level or 0) > 0 then
|
||||
local capacity = storage.getCapacity ~= nil and (storage:getCapacity(fillType) or 0) or 0
|
||||
addEntry(entries, fillType, level, capacity, {isOutput = outputs[fillType] == true})
|
||||
end
|
||||
end
|
||||
return entries
|
||||
end
|
||||
|
||||
local function siloEntries(placeable)
|
||||
local entries, levels, capacities = {}, {}, {}
|
||||
for _, storage in pairs(placeable.spec_silo.storages or {}) do
|
||||
for fillType, level in pairs(storage.fillLevels or {}) do
|
||||
if (level or 0) > 0 then
|
||||
levels[fillType] = (levels[fillType] or 0) + level
|
||||
capacities[fillType] = (capacities[fillType] or 0) + (storage.getCapacity ~= nil and (storage:getCapacity(fillType) or 0) or 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
for fillType, level in pairs(levels) do addEntry(entries, fillType, level, capacities[fillType] or 0) end
|
||||
return entries
|
||||
end
|
||||
|
||||
local function objectStorageEntries(placeable)
|
||||
local entries = {}
|
||||
local spec = placeable.spec_objectStorage
|
||||
for _, objectInfo in ipairs(spec.objectInfos or {}) do
|
||||
local fillType, perObject = getObjectInfoContent(objectInfo)
|
||||
local count = objectInfo.numObjects or 0
|
||||
if fillType ~= nil and count > 0 then
|
||||
addEntry(entries, fillType, count * perObject, spec.capacity or 0, {count = count})
|
||||
end
|
||||
end
|
||||
return entries
|
||||
end
|
||||
|
||||
local function husbandryEntries(placeable)
|
||||
local entries, seen = {}, {}
|
||||
local food = placeable.spec_husbandryFood
|
||||
if food ~= nil then
|
||||
local total = 0
|
||||
for _, level in pairs(food.fillLevels or {}) do total = total + (level or 0) end
|
||||
for fillType, level in pairs(food.fillLevels or {}) do
|
||||
if (level or 0) > 0 then
|
||||
seen[fillType] = true
|
||||
addEntry(entries, fillType, level, level + math.max(0, (food.capacity or 0) - total))
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, name in ipairs({"STRAW", "WATER", "MILK", "LIQUIDMANURE", "MANURE"}) do
|
||||
local fillType = g_fillTypeManager ~= nil and g_fillTypeManager.getFillTypeIndexByName ~= nil and g_fillTypeManager:getFillTypeIndexByName(name) or nil
|
||||
if fillType == nil and g_fillTypeManager ~= nil then
|
||||
-- test-fakes uden getFillTypeIndexByName: slå navnet op baglæns
|
||||
for index = 1, 64 do
|
||||
if g_fillTypeManager:getFillTypeNameByIndex(index) == name then fillType = index break end
|
||||
end
|
||||
end
|
||||
if fillType ~= nil and not seen[fillType] and placeable.getHusbandryIsFillTypeSupported ~= nil and placeable:getHusbandryIsFillTypeSupported(fillType) then
|
||||
local level = placeable.getHusbandryFillLevel ~= nil and (placeable:getHusbandryFillLevel(fillType) or 0) or 0
|
||||
if level > 0 then
|
||||
local free = placeable.getHusbandryFreeCapacity ~= nil and (placeable:getHusbandryFreeCapacity(fillType) or 0) or 0
|
||||
addEntry(entries, fillType, level, level + free)
|
||||
end
|
||||
end
|
||||
end
|
||||
return entries
|
||||
end
|
||||
|
||||
-- { {name, kind = "factory"|"silo"|"objectStorage"|"husbandry", entries = {{fillType, name, title, level, capacity, isOutput, count}}} }
|
||||
-- kun gårdens bygninger med indhold; sorteret på slags, dernæst navn.
|
||||
function ADSources.getFarmInventory(adEnv, farmId)
|
||||
local placeables = g_currentMission ~= nil and g_currentMission.placeableSystem ~= nil and g_currentMission.placeableSystem.placeables or {}
|
||||
local result = {}
|
||||
for _, placeable in pairs(placeables) do
|
||||
if isOwnedBy(placeable, farmId) then
|
||||
local kind, entries = nil, nil
|
||||
if getProductionPoint(placeable) ~= nil then
|
||||
kind, entries = "factory", factoryEntries(placeable)
|
||||
elseif placeable.spec_silo ~= nil then
|
||||
kind, entries = "silo", siloEntries(placeable)
|
||||
elseif placeable.spec_objectStorage ~= nil then
|
||||
kind, entries = "objectStorage", objectStorageEntries(placeable)
|
||||
elseif placeable.getHusbandryFillLevel ~= nil then
|
||||
kind, entries = "husbandry", husbandryEntries(placeable)
|
||||
end
|
||||
if entries ~= nil and #entries > 0 then
|
||||
table.sort(entries, function(a, b)
|
||||
if a.isOutput ~= b.isOutput then return a.isOutput end
|
||||
return tostring(a.title) < tostring(b.title)
|
||||
end)
|
||||
table.insert(result, {name = getPlaceableName(placeable, "?"), kind = kind, entries = entries, placeable = placeable})
|
||||
end
|
||||
end
|
||||
end
|
||||
local order = {factory = 1, husbandry = 2, objectStorage = 3, silo = 4}
|
||||
table.sort(result, function(a, b)
|
||||
if order[a.kind] ~= order[b.kind] then return order[a.kind] < order[b.kind] end
|
||||
return a.name < b.name
|
||||
end)
|
||||
return result
|
||||
end
|
||||
|
||||
function ADSources.getSourcePlaceables(sources)
|
||||
local set = {}
|
||||
for _, source in ipairs(sources or {}) do
|
||||
|
||||
Reference in New Issue
Block a user