feat(ui): 'Lager til' viser kun bygninger der kan tage flowets lagervarer (paller -> palleskure der tager varen); valgt palleskur bruges til palleture (v1.19.2.0)

This commit is contained in:
2026-09-24 19:40:35 +02:00
parent a2444661a0
commit 2ed79cf461
7 changed files with 113 additions and 9 deletions
+17
View File
@@ -185,6 +185,23 @@ local function findStoreMarker(adEnv, vehicle, product, capacity, sources, liter
end
-- paller lagres i et palleskur (objektlager) — UAL læsser af dér
if product.isPallet then
-- "Lager til" med palleskure: første valgte der tager varen, har plads og kan nås
local forcedSheds = run ~= nil and ADRunsController ~= nil and ADRunsController.getStoreBuildings ~= nil and ADRunsController.getStoreBuildings(adEnv, run) or {}
local hasForcedShed = false
for _, building in ipairs(forcedSheds) do
if building.kind == "objectStorage" then
hasForcedShed = true
local marker = building.unloadMarker or building.loadMarker
if marker ~= nil and ADSources.objectStorageAccepts(building.placeable, product.fillType)
and ADSources.objectStorageFreeSlots(building.placeable) >= 1 and isReachable(marker.id) then
return {wayPointId = marker.id, name = tostring(building.name), free = ADSources.objectStorageFreeSlots(building.placeable)}
end
end
end
if hasForcedShed then
warnOnce(adEnv, vehicle, "forcedShed:" .. tostring(product.name), string.format("'%s': %s kan ikke sættes på lager — intet af de valgte palleskure tager varen, har plads og kan nås", tostring(ADRuns.vehicleLabel(vehicle)), tostring(product.name)))
return nil
end
if ADSources.findPalletStore == nil then
return nil
end
+58
View File
@@ -147,6 +147,64 @@ function ADRunsController.getPickupMarkers()
return result
end
-- Varer flowet kører til lager (politik Lager / Salg, ellers lager): {{fillType, isPallet}}.
-- Er ingen vare sat til lager endnu, alle kildernes varer (så listen ikke er tom mens man opsætter).
function ADRunsController.getStoreGoods(adEnv, run)
local products = ADRunsController.getRunProducts(adEnv, run)
local goods = {}
for _, product in ipairs(products) do
if product.policy == "store" or product.policy == "sellElseStore" then
table.insert(goods, {fillType = product.fillType, isPallet = product.isPallet == true})
end
end
if #goods == 0 then
for _, product in ipairs(products) do
table.insert(goods, {fillType = product.fillType, isPallet = product.isPallet == true})
end
end
return goods
end
-- Kan bygningen tage mindst én af varerne som lager? Palleskur: pallevarer det tager. Silo/egen fabrik:
-- bulkvarer dens aflæsningsstation tager (samme regel som lagerturene: ADLoadSwap.isStoreTarget).
function ADRunsController.canStoreAt(adEnv, building, goods)
if building.kind == "objectStorage" then
for _, good in ipairs(goods or {}) do
if good.isPallet and ADSources ~= nil and ADSources.objectStorageAccepts ~= nil and ADSources.objectStorageAccepts(building.placeable, good.fillType) then
return true
end
end
return false
end
if building.unloadMarker == nil or ADLoadSwap == nil or ADLoadSwap.isStoreTarget == nil then
return false
end
local farmId = g_currentMission ~= nil and g_currentMission.getFarmId ~= nil and g_currentMission:getFarmId() or 1
local station = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, building.unloadMarker.id, farmId)
if station == nil then
return false
end
for _, good in ipairs(goods or {}) do
if not good.isPallet and ADLoadSwap.isStoreTarget(station, good.fillType, nil, true)
and (station.getIsFillTypeSupported == nil or station:getIsFillTypeSupported(good.fillType)) then
return true
end
end
return false
end
-- "Lager til"-bygningerne selv (i valgt rækkefølge) — til palleture der skal til et bestemt palleskur.
function ADRunsController.getStoreBuildings(adEnv, run)
local result = {}
if ADBuildings == nil or run == nil then return result end
local farmId = g_currentMission ~= nil and g_currentMission.getFarmId ~= nil and g_currentMission:getFarmId() or 1
for _, buildingId in ipairs(run.storeBuildingIds or {}) do
local building = ADBuildings.find(adEnv, farmId, buildingId)
if building ~= nil then table.insert(result, building) end
end
return result
end
-- "Lager til": aflæsningsmarkører for flowets valgte lagerbygninger, i valgt rækkefølge (tom = ingen tvang).
function ADRunsController.getStoreMarkers(adEnv, run)
local result = {}
@@ -119,10 +119,12 @@ function SmartPickupFrame:fillBuildingRows(adEnv, run, role)
local count = 0
-- kandidater -> valgte først, så med markør; uden markør kun med "Vis alle bygninger"
local candidates = {}
-- "Lager til": kun bygninger der kan tage flowets lagervarer (æg-paller -> palleskure der tager æg)
local storeGoods = role == "store" and ADRunsController.getStoreGoods(adEnv, run) or nil
for _, building in ipairs(ADBuildings.list(adEnv, g_currentMission:getFarmId())) do
-- "Lager til": siloer og gårdens fabrikker (fx BGA) — markøren er bygningens aflæsningsmarkør
local isStoreKind = building.kind == "silo" or building.kind == "factory" or building.kind == "objectStorage"
local fits = (role == "load" and building.canBeSource) or (role == "unload" and building.canBeTarget)
or (role == "store" and (building.kind == "silo" or building.kind == "factory"))
or (role == "store" and isStoreKind and (chosen[building.id] or ADRunsController.canStoreAt(adEnv, building, storeGoods)))
if fits then
local markers = ADBuildings.getMarkers ~= nil and ADBuildings.getMarkers(building, role == "store" and "unload" or role) or {}
table.insert(candidates, {id = building.id, name = building.name, hasMarker = markers[1] ~= nil, building = building})
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107">
<author>masterdraco</author>
<version>1.19.1.0</version>
<version>1.19.2.0</version>
<title>
<en>AD Smart Pickup</en>
</title>
+7 -3
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — brugermanual
Version 1.19.1 · Farming Simulator 25 · tillæg til AutoDrive
Version 1.19.2 · Farming Simulator 25 · tillæg til AutoDrive
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
@@ -325,12 +325,16 @@ Bulkvarer kræver en tipvogn eller tank. Pallevarer kræver en vogn med Universa
### Lager til: tvunget aflæsningssted
Under reglerne står afsnittet **Lager til** med gårdens siloer og egne fabrikker. Vælger du én eller
Under reglerne står afsnittet **Lager til**. Det viser kun de siloer, egne fabrikker og palleskure, der
kan tage mindst én af flowets lagervarer. Æggepaller viser altså kun palleskure, der tager æg, og
ingen siloer. Er ingen vare sat til Lager endnu, tæller alle kildernes varer. Valgte bygninger vises
altid. Vælger du én eller
flere, kører lagerture kun dertil. Den første i listen, der tager varen, har plads og kan nås, får
læsset. Et eksempel er gylle, der kun må til biogasanlægget og aldrig til AIO-fabrikken. Kan ingen af
de valgte tage læsset, venter traktoren ved Wait, og loggen skriver hvorfor, fx *valgt lager: BGA500kw:
fuld*. Vælger du ingen, finder moden selv den nærmeste silo eller egne fabrik, der bruger varen.
Paller følger stadig reglen om nærmeste palleskur.
Pallevarer går til det første valgte palleskur, der tager varen, har plads og kan nås. Er intet
palleskur valgt, går de til det nærmeste.
Med **Lager til** valgt regnes flowet som **fodring**: traktoren kører, så snart kilden har mindst
10.000 l af varen. Den venter ikke på fuldt læs eller *Kør til lager over*, for et anlæg som en
+7 -3
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — user manual
Version 1.19.1 · Farming Simulator 25 · add-on for AutoDrive
Version 1.19.2 · Farming Simulator 25 · add-on for AutoDrive
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
@@ -329,12 +329,16 @@ Bulk goods need a tipper or tank. Pallet goods need a trailer with Universal Aut
### Store to: forced drop-off
Below the rules there is a **Store to** section listing the farm's silos and own factories. If you
Below the rules there is a **Store to** section. It only lists the silos, own factories and pallet
sheds that can take at least one of the flow's storage goods. Egg pallets therefore only show pallet
sheds that take eggs, and no silos. If no good is set to Store yet, all goods at the sources count.
Chosen buildings are always shown. If you
pick one or more, storage trips only go there. The first one in the list that accepts the good, has
room and can be reached gets the load. An example is slurry that must only go to the biogas plant and
never to the AIO factory. If none of the chosen buildings can take the load, the tractor waits at
Wait, and the log says why, such as *valgt lager: BGA500kw: fuld*. If you pick none, the mod finds the
nearest silo or own factory that uses the good by itself. Pallets still follow the nearest pallet shed rule.
nearest silo or own factory that uses the good by itself. Pallet goods go to the first chosen pallet shed that accepts the good, has room and can be reached.
If no pallet shed is chosen, they go to the nearest one.
With **Store to** chosen, the flow counts as **feeding**: the tractor drives as soon as the source has
at least 10,000 l of the good. It does not wait for a full load or *Drive to storage above*, because a
+19
View File
@@ -721,6 +721,25 @@ do
ADRunsController.updateRun(sbRun.id, {storeBuildingIds = {}})
check("SB tom = ingen tvang", #ADRunsController.getStoreMarkers(adEnv, ADRuns.getRun(ADRunsController.store, sbRun.id)), 0)
end
-- CS: "Lager til" viser kun bygninger der kan tage flowets lagervarer (æg-paller: kun palleskure der tager æg)
do
local EGG, SILAGE = 501, 502
local shed = {id = "shed1", kind = "objectStorage", placeable = {takesEggs = true}}
local shedNo = {id = "shed2", kind = "objectStorage", placeable = {takesEggs = false}}
local silo = {id = "silo9", kind = "silo", placeable = {}, unloadMarker = {id = 901}}
unloadAt[901] = {accepts = {[SILAGE] = 100000}, getIsFillTypeSupported = function(_, ft) return ft == SILAGE end}
local accBefore, storeBefore = ADSources.objectStorageAccepts, ADLoadSwap and ADLoadSwap.isStoreTarget
ADSources.objectStorageAccepts = function(placeable, ft) return ft == EGG and placeable.takesEggs end
ADLoadSwap = ADLoadSwap or {}
ADLoadSwap.isStoreTarget = function(station, ft) return station.getIsFillTypeSupported(station, ft) end
local eggs = {{fillType = EGG, isPallet = true}}
check("CS palleskur der tager æg", ADRunsController.canStoreAt(adEnv, shed, eggs), true)
check("CS palleskur der ikke tager æg", ADRunsController.canStoreAt(adEnv, shedNo, eggs), false)
check("CS silo kan ikke tage æg-paller", ADRunsController.canStoreAt(adEnv, silo, eggs), false)
check("CS silo tager ensilage", ADRunsController.canStoreAt(adEnv, silo, {{fillType = SILAGE, isPallet = false}}), true)
ADSources.objectStorageAccepts = accBefore
ADLoadSwap.isStoreTarget = storeBefore
end
ADBuildings = nil; ADSources = nil; ADOutbound = nil
-- RC-navne: køretøjer får AD-førernavn efter forløbet; ude af forløb -> modelnavnet igen