fix: en fabriks inputs stjæles aldrig som kilde; stalde læses via getHusbandry* (v1.6.1.0)

In-game 2026-09-22: fire Fastrac'er med halm+TMR til to kostalde kørte med
'Rotér mål: kun aflæsning' og fast pålæsning ved 'TMR Load' -> AutoDrive læssede
halm (fabrikkens input) dér uden at modden var i spil. Med modden i spil ville
'mindst fyldte først' have valgt samme lager.

- ADSupplyPlanner.isProductionInput: vare der er input (og ikke output) i en
  fabriks produktioner udelukkes som kilde i findBestSource (mappe + behov).
- Stald som mål: niveau/kapacitet/understøttelse fra placeable:getHusbandry*
  (stationen selv siger nej til halm) -> halm rangeres og hentes.
- README: to stalde = kun pålæsnings-rotation (AD vælger pickup FØR deliver roteres).
This commit is contained in:
2026-09-22 20:45:43 +02:00
parent 795c03663c
commit 2ff0b641b0
6 changed files with 156 additions and 11 deletions
+62
View File
@@ -355,6 +355,68 @@ fallbackPp.getIsProductionEnabled = nil
fallbackPp.activeProductions = {fallbackPp.productions[1]}
check("F6 activeProductions som fallback", manager:getNextPickup(fallbackDriver, false), 4)
-- ==== En fabriks inputs stjæles aldrig (halm+TMR til kostald; TMR-fabrikken har halm som input) ====
local STRAW, TMR = 41, 42
FILL_TYPE_NAMES[STRAW], FILL_TYPE_NAMES[TMR] = "STRAW", "FORAGE"
local cowLevels
local function buildCowWorld()
resetWorld()
local tmrFactory = {
getName = function() return "TMR-fabrik" end,
spec_productionPoint = {productionPoint = {productions = {
{id = "tmr", cyclesPerMinute = 1, inputs = {{type = STRAW, amount = 10}, {type = SILAGE, amount = 100}}, outputs = {{type = TMR, amount = 50}}},
}}},
}
-- fabrikkens læssestation har BÅDE halm (input, mindst fyldt) og TMR (output)
addMarker(20, "TMR Load", "Fabrication", 0, 0)
table.insert(stations, makeStation(120, 0, 15, {[STRAW] = 5000, [TMR] = 30000}))
stations[#stations].owningPlaceable = tmrFactory
addMarker(21, "Halmlade", "Lader", 500, 0)
table.insert(stations, makeStation(121, 500, 15, {[STRAW] = 50000}))
addMarker(30, "Cow 1 Food", "Cow Food", 5000, 0)
cowLevels = {[STRAW] = 0, [TMR] = 40000}
table.insert(unloadStations, makeUnloadStation(130, 5000, 10, cowLevels, {[STRAW] = 100000, [TMR] = 100000}, {name = "kostald"}))
local driver = makeSupplyDriver(markerByIndex(21), markerByIndex(30), {TMR, STRAW})
driver.carriable = {TMR, STRAW}
return driver
end
-- P1: halm mangler mest -> hentes fra halmladen, IKKE fra fabrikken (selv om den er mindst fyldt)
local cowDriver = buildCowWorld()
check("P1 halm hentes fra siloen, ikke fabrikkens input", manager:getNextPickup(cowDriver, false), 21)
-- P2: halm fuld -> TMR hentes gerne fra fabrikken (det er dens output)
cowLevels[STRAW] = 99500
check("P2 fabrikkens output må hentes", manager:getNextPickup(cowDriver, false), 20)
-- P3: mappe-logik (én vare) beskytter også fabrikkens input
cowDriver = buildCowWorld()
addMarker(22, "Halmlade 2", "Fabrication", 1000, 0)
table.insert(stations, makeStation(122, 1000, 15, {[STRAW] = 60000}))
local strawDriver = makeDriver(markerByIndex(20), {STRAW})
check("P3 mappe-logik springer fabrikkens input over", manager:getNextPickup(strawDriver, false), 22)
-- P4: stald som mål — niveau/kapacitet læses fra stalden selv (getHusbandry*), ikke fra
-- stationens lagre; stationen selv "understøtter" kun foder, men stalden tager også halm
cowDriver = buildCowWorld()
local barnLevels = {[STRAW] = 45000, [TMR] = 10000}
local barnCapacity = {[STRAW] = 50000, [TMR] = 100000}
local barn = {
getName = function() return "Kostald" end,
getHusbandryFillLevel = function(_, fillType) return barnLevels[fillType] or 0 end,
getHusbandryCapacity = function(_, fillType) return barnCapacity[fillType] or 0 end,
getHusbandryFreeCapacity = function(_, fillType) return (barnCapacity[fillType] or 0) - (barnLevels[fillType] or 0) end,
getHusbandryIsFillTypeSupported = function(_, fillType) return barnCapacity[fillType] ~= nil end,
}
local barnStation = unloadStations[1]
barnStation.targetStorages = nil
barnStation.owningPlaceable = barn
barnStation.getIsFillTypeSupported = function(_, fillType) return fillType == TMR end
barnStation.getFreeCapacity = function(_, fillType) return 999999 end
check("P4 stald: TMR (90 % tom) hentes før halm (10 % tom)", manager:getNextPickup(cowDriver, false), 20)
barnLevels[TMR] = 95000
check("P4 stald: halm hentes når TMR er fuld", manager:getNextPickup(cowDriver, false), 21)
-- L1: moden valgte siloen -> AutoDrive skal stå og læsse (rotation skjules under opgaven)
resetWorld()
local loadLevels = {[SUGARBEET] = 5000}
+14
View File
@@ -108,5 +108,19 @@ check("fuldt mål springes over trods forbrug", #ADSupplyPlanner.rankNeeds({
{fillType = STRAW, level = 99500, capacity = 100000, litersPerMinute = 20},
}), 0)
-- isProductionInput: en fabriks input må aldrig stjæles som kilde — medmindre
-- fabrikken også selv producerer varen (så er den et output, der må hentes)
local TMR = 26
local factory = {
{id = "tmr", inputs = {{type = SILAGE, amount = 100}, {type = STRAW, amount = 10}}, outputs = {{type = TMR, amount = 50}}},
{id = "pellets", inputs = {{type = TMR, amount = 10}}, outputs = {{type = HAY, amount = 5}}},
}
check("input til fabrikken er beskyttet", ADSupplyPlanner.isProductionInput(factory, STRAW), true)
check("output må hentes", ADSupplyPlanner.isProductionInput(factory, HAY), false)
check("både input og output (kæde) -> må hentes", ADSupplyPlanner.isProductionInput(factory, TMR), false)
check("vare fabrikken ikke kender -> ikke beskyttet", ADSupplyPlanner.isProductionInput(factory, WATER), false)
check("ingen produktioner -> ikke beskyttet", ADSupplyPlanner.isProductionInput({}, STRAW), false)
check("produktion uden inputs/outputs tåles", ADSupplyPlanner.isProductionInput({{id = "x"}}, STRAW), false)
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1)