diff --git a/FS25_ADSmartPickup/adFieldSiloPlanner.lua b/FS25_ADSmartPickup/adFieldSiloPlanner.lua
index 8825692..4000bec 100644
--- a/FS25_ADSmartPickup/adFieldSiloPlanner.lua
+++ b/FS25_ADSmartPickup/adFieldSiloPlanner.lua
@@ -39,6 +39,9 @@ local function chooseStore(stores, silo, fillType, liters, minLiters, reserved,
if mostFree == nil or free > mostFree then most, mostFree = store, free end
end
end
+ -- fabrikker kun med plads til hele læsset: en fabrik tager kun det den forbruger, så en vogn med resten
+ -- holder ved den i timevis (in-game 28/9: 252.000 l kartofler ved en fuld snackfabrik)
+ if production then return best end
return best or most
end
@@ -69,6 +72,27 @@ local function pickStore(input, farmIncoming, task, liters, minLiters, reserved)
or chooseStore(input.stores, task.silo, fillType, liters, minLiters, reserved, not wantProduction)
end
+-- Høsten først: for hvert behov {fillType, count} (høstere i arbejde, der mangler tømmevogne) holdes så mange
+-- vogne der kan bære afgrøden tilbage; resten må marksilo-flowet låne. Ny liste; input muteres ikke.
+function ADFieldSiloPlanner.withoutHarvestReserve(vehicles, needs)
+ local held = {}
+ for _, need in ipairs(needs or {}) do
+ local left = need.count or 0
+ for _, vehicle in ipairs(vehicles or {}) do
+ if left <= 0 then break end
+ if not held[vehicle.id] and canCarry(vehicle, need.fillType) then
+ held[vehicle.id] = true
+ left = left - 1
+ end
+ end
+ end
+ local free = {}
+ for _, vehicle in ipairs(vehicles or {}) do
+ if not held[vehicle.id] then table.insert(free, vehicle) end
+ end
+ return free
+end
+
function ADFieldSiloPlanner.plan(input)
local minLiters = input.minLiters or 10000
local storesById = {}
diff --git a/FS25_ADSmartPickup/adFieldSilos.lua b/FS25_ADSmartPickup/adFieldSilos.lua
index 4659ba4..bf604b0 100644
--- a/FS25_ADSmartPickup/adFieldSilos.lua
+++ b/FS25_ADSmartPickup/adFieldSilos.lua
@@ -251,7 +251,8 @@ function ADFieldSilos.collectVehicles(adEnv)
local vehicles, byId = {}, {}
-- hvorfor tømmevogne ikke kan lånes (til fanens statuslinje)
local why = {notEnabled = 0, busy = 0, controlled = 0, noPark = 0}
- for _, rig in ipairs(ADFieldWork.getRigs(adEnv)) do
+ local rigs = ADFieldWork.getRigs(adEnv)
+ for _, rig in ipairs(rigs) do
-- uden AD-parkeringspunkt bliver vognen holdende på lagerets markør og spærrer for de næste
local canPark = ADFieldWork.parkMarkerId == nil or ADFieldWork.parkMarkerId(adEnv, rig.vehicle) ~= nil
if rig.role == "unloader" then
@@ -266,11 +267,54 @@ function ADFieldSilos.collectVehicles(adEnv)
byId[rig.id] = rig.vehicle
end
end
+ local ok, needs = pcall(ADFieldSilos.harvestNeeds, adEnv, rigs)
+ if ok and #needs > 0 then
+ local before = #vehicles
+ vehicles = ADFieldSiloPlanner.withoutHarvestReserve(vehicles, needs)
+ why.harvest = before - #vehicles
+ elseif not ok then
+ Logging.warning(ADFieldSilos.LOG_PREFIX .. "høstreserve kunne ikke beregnes: %s", tostring(needs))
+ end
why.eligible = #vehicles
ADFieldSilos.lastVehicleReasons = why
return vehicles, byId
end
+-- Høsten først: pr. høster der arbejder (CP kører) holdes dens planlagte antal tømmevogne tilbage, minus dem
+-- markarbejdet allerede har sendt til marken. (in-game 28/9: marksilo-flowet havde lånt begge kartoffelvogne,
+-- og ingen kom til roeoptagerne.)
+function ADFieldSilos.harvestNeeds(adEnv, rigs)
+ local assignments = ADFieldJobs ~= nil and ADFieldJobs.state ~= nil and ADFieldJobs.state.assignments or {}
+ local sent = {}
+ for _, assignment in pairs(assignments) do
+ if assignment.role == "unloader" and assignment.fieldId ~= nil then sent[assignment.fieldId] = (sent[assignment.fieldId] or 0) + 1 end
+ end
+ local needs = {}
+ for _, rig in ipairs(rigs) do
+ if rig.role == "harvester" and ADCpBridge.isWorking(rig.vehicle) then
+ local assignment = assignments[rig.id]
+ local fieldId = assignment ~= nil and assignment.fieldId or nil
+ local field = fieldId ~= nil and ADFieldJobs.getField(fieldId) or nil
+ local info = fieldId ~= nil and ADFields.getInfo(fieldId) or nil
+ local count = field ~= nil and ADFieldModel.maxHelpers("harvesting", field.plan) or 1
+ count = count - (fieldId ~= nil and (sent[fieldId] or 0) or 0)
+ local fillTypes = {}
+ if info ~= nil and info.harvestFillType ~= nil then
+ fillTypes[info.harvestFillType] = true
+ else
+ for fruitIndex in pairs(rig.fruits or {}) do
+ local fruit = g_fruitTypeManager ~= nil and g_fruitTypeManager:getFruitTypeByIndex(fruitIndex) or nil
+ if fruit ~= nil and fruit.fillType ~= nil then fillTypes[fruit.fillType.index] = true end
+ end
+ end
+ for fillType in pairs(fillTypes) do
+ if count > 0 then table.insert(needs, {fillType = fillType, count = count}) end
+ end
+ end
+ end
+ return needs
+end
+
-- ---- lån ----
local function fillTypeName(fillType)
diff --git a/FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua b/FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua
index ca2f990..df14d25 100644
--- a/FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua
+++ b/FS25_ADSmartPickup/gui/SmartPickupFieldSiloTab.lua
@@ -61,6 +61,10 @@ function SmartPickupFrame:fillFieldSiloRows(adEnv)
self:addTextRow(string.format(i18n:getText("spu_fs_noVehicle"), why.noPark, why.busy, why.controlled, why.notEnabled))
end
+ if why ~= nil and (why.harvest or 0) > 0 then
+ self:addTextRow(string.format(i18n:getText("spu_fs_harvestHeld"), why.harvest))
+ end
+
self:addTextRow(i18n:getText("spu_fs_silosTitle"))
if plan == nil or #plan.status == 0 then
self:addTextRow(" " .. i18n:getText("spu_fs_nothing"))
diff --git a/FS25_ADSmartPickup/l10n/l10n_da.xml b/FS25_ADSmartPickup/l10n/l10n_da.xml
index 09a66a8..0a2d595 100644
--- a/FS25_ADSmartPickup/l10n/l10n_da.xml
+++ b/FS25_ADSmartPickup/l10n/l10n_da.xml
@@ -501,5 +501,6 @@
+
diff --git a/FS25_ADSmartPickup/l10n/l10n_en.xml b/FS25_ADSmartPickup/l10n/l10n_en.xml
index 30ccc00..2c5cc30 100644
--- a/FS25_ADSmartPickup/l10n/l10n_en.xml
+++ b/FS25_ADSmartPickup/l10n/l10n_en.xml
@@ -501,5 +501,6 @@
+
diff --git a/FS25_ADSmartPickup/modDesc.xml b/FS25_ADSmartPickup/modDesc.xml
index c55cec6..60ce81e 100644
--- a/FS25_ADSmartPickup/modDesc.xml
+++ b/FS25_ADSmartPickup/modDesc.xml
@@ -1,7 +1,7 @@
masterdraco
- 1.45.0.0
+ 1.45.1.0
AD Smart Pickup
diff --git a/tests/test_adFieldSiloPlanner.lua b/tests/test_adFieldSiloPlanner.lua
index 8a5effa..3e50742 100644
--- a/tests/test_adFieldSiloPlanner.lua
+++ b/tests/test_adFieldSiloPlanner.lua
@@ -111,5 +111,23 @@ check("P7 reserve mangler men ingen gård tager varen -> fabrik", r.dispatch[1].
check("P7 status ok (ikke noFarmStore)", r.status[1].state, "ok")
check("P7 status viser destination", r.status[1].toProduction, true)
+-- fabrik kun når hele læsset kan være der (in-game 28/9: vogn med 252.000 l ventede timevis ved en fuld fabrik)
+r = P.plan(base({stores = {store("farm", 5000, {[WHEAT] = 1000000}), factory("mill", 100, {[WHEAT] = 30000})}, silos = {silo("A", 500, {[WHEAT] = 90000})},
+ vehicles = {vehicle("v1", 400, 50000)}}))
+check("P8 fabrik uden plads til hele læsset -> gårdlager", r.dispatch[1].storeId, "farm")
+r = P.plan(base({stores = {store("farm", 5000, {[CANOLA] = 1000000}), factory("mill", 100, {[WHEAT] = 30000})}, silos = {silo("A", 500, {[WHEAT] = 90000})},
+ vehicles = {vehicle("v1", 400, 50000)}}))
+check("P9 kun fabrik uden plads til hele læsset -> ingen afsendelse", #r.dispatch, 0)
+
+-- høsten først: tømmevogne holdes tilbage til høstere der arbejder
+local vs = {vehicle("v1", 400, 50000), vehicle("v2", 400, 50000, {[CANOLA] = true}), vehicle("v3", 400, 50000)}
+local left = P.withoutHarvestReserve(vs, {{fillType = WHEAT, count = 1}})
+check("R1 én hvede-vogn holdt tilbage", #left, 2)
+check("R1 raps-vognen er fri", left[1].id == "v2" or left[2].id == "v2", true)
+left = P.withoutHarvestReserve(vs, {{fillType = WHEAT, count = 5}})
+check("R2 alle hvede-vogne holdt tilbage", #left, 1)
+check("R3 intet behov -> alle fri", #P.withoutHarvestReserve(vs, {}), 3)
+check("R4 input muteres ikke", #vs, 3)
+
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1)