fix: stå og læs ved den valgte silo — AutoDrive kørte tom videre (v1.2.0.0)

Med rotateTargets + mapper afslutter AutoDrives LoadAtDestinationTask pålæsningen
i det øjeblik markøren nås; traktoren kørte derfor lige igennem silo-markøren og
tom til aflæsning. Når moden har valgt siloen, ses rotationen som slået fra for
netop det køretøj under opgavens update, så AutoDrive står og læsser. Grebet
slippes når kilden er tom eller AD stopper.

Desuden: samme valg logges kun én gang, og loggen viser eget/nabo-lager.
This commit is contained in:
2026-09-21 15:55:07 +02:00
parent 95615253b0
commit bcc245863e
4 changed files with 150 additions and 5 deletions
+78 -4
View File
@@ -24,6 +24,10 @@ local isHooked = false
-- køretøj -> {ingredients, narrowedTo}. AutoDrive roterer selv vare ved triggeren
-- når flere er valgt, så valget indsnævres til én pr. tur; listen huskes her.
local supplyState = setmetatable({}, {__mode = "k"})
-- køretøj -> {station, fillTypes}: siloen moden sendte køretøjet til på denne tur.
local activePickups = setmetatable({}, {__mode = "k"})
-- køretøj -> senest loggede valg (AutoDrive spørger flere gange pr. start).
local lastLogged = setmetatable({}, {__mode = "k"})
-- Cross-mod adgang: FS25-mods er sandboxede; AutoDrives globals ligger
-- i den globale tabel FS25_AutoDrive (zip-navnet).
@@ -155,7 +159,7 @@ local function findLeastFilled(markerStations, fillTypes, farmId)
for _, entry in ipairs(markerStations) do
local level, isOwn = getStationFillLevel(entry.station, fillTypes, farmId)
if level >= ADSmartPickup.MIN_USEFUL_LITERS and level < best[isOwn].level then
best[isOwn] = {level = level, marker = entry.marker}
best[isOwn] = {level = level, marker = entry.marker, station = entry.station, isOwn = isOwn}
end
end
@@ -168,6 +172,9 @@ local function findLeastFilled(markerStations, fillTypes, farmId)
markerName = choice.marker.name,
group = choice.marker.group,
level = choice.level,
station = choice.station,
isOwn = choice.isOwn,
fillTypes = fillTypes,
}
end
@@ -243,6 +250,9 @@ function ADSmartPickup.findSupplyPickup(adEnv, driver, ingredients)
markerName = choice.markerName,
group = choice.group,
level = choice.level,
station = choice.station,
isOwn = choice.isOwn,
fillTypes = choice.fillTypes,
fillType = need.fillType,
need = need,
}
@@ -277,11 +287,63 @@ function ADSmartPickup.choosePickup(adEnv, driver)
end
local function describeChoice(choice)
local source = choice.isOwn and "eget lager" or "nabo-lager"
if choice.fillType == nil then
return string.format("%.0f l", choice.level)
return string.format("%.0f l, %s", choice.level, source)
end
local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(choice.fillType) or tostring(choice.fillType)
return string.format("%s: kilde %.0f l, målet har %.0f/%.0f l", tostring(fillTypeName), choice.level, choice.need.level, choice.need.capacity)
return string.format("%s: kilde %.0f l, %s, målet har %.0f/%.0f l", tostring(fillTypeName), choice.level, source, choice.need.level, choice.need.capacity)
end
local function logChoiceOnce(driver, choice)
local message = string.format("'%s' -> %s (%s)", tostring(driver:getName()), tostring(choice.markerName), describeChoice(choice))
if lastLogged[driver] ~= message then
lastLogged[driver] = message
Logging.info(ADSmartPickup.LOG_PREFIX .. "%s", message)
end
end
-- Sendte moden køretøjet til en silo der stadig har varen? Så skal AutoDrive
-- stå og læsse dér; løber kilden tør, slippes grebet og turen fortsætter.
function ADSmartPickup.shouldWaitForLoading(vehicle)
local pickup = activePickups[vehicle]
if pickup == nil then
return false
end
local level = getStationFillLevel(pickup.station, pickup.fillTypes, getFarmId(vehicle))
return level >= ADSmartPickup.MIN_USEFUL_LITERS
end
-- Med "Rotér mål" + mapper afslutter AutoDrive pålæsningen i det øjeblik markøren
-- nås (LoadAtDestinationTask: rotation = "prøv næste silo", aldrig vente). Moden
-- har valgt en silo der HAR varen, så under opgavens update ser AutoDrive
-- rotationen som slået fra for netop det køretøj -> den står og læsser som normalt.
local function installLoadWaitHook(adEnv)
local task, autoDrive = adEnv.LoadAtDestinationTask, adEnv.AutoDrive
if task == nil or task.update == nil or autoDrive == nil or autoDrive.getSetting == nil then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "kunne ikke koble på pålæsningsopgaven; traktoren venter ikke ved siloen")
return
end
local originalGetSetting, originalUpdate = autoDrive.getSetting, task.update
local waitingVehicle = nil
autoDrive.getSetting = function(settingName, vehicle)
if waitingVehicle ~= nil and vehicle == waitingVehicle and settingName == "rotateTargets" then
return autoDrive.RT_NONE
end
return originalGetSetting(settingName, vehicle)
end
task.update = function(self, dt)
local ok, shouldWait = pcall(ADSmartPickup.shouldWaitForLoading, self.vehicle)
waitingVehicle = ok and shouldWait and self.vehicle or nil
local updateOk, err = pcall(originalUpdate, self, dt)
waitingVehicle = nil
if not updateOk then
error(err, 0)
end
end
end
local function installHook(adEnv)
@@ -292,27 +354,39 @@ local function installHook(adEnv)
local ok, choice = pcall(ADSmartPickup.choosePickup, adEnv, driver)
if not ok then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "fejl i silo-opslag, bruger AutoDrives rotation: %s", tostring(choice))
activePickups[driver] = nil
return originalGetNextPickup(self, driver, forcedSkip)
end
if choice == nil then
activePickups[driver] = nil
return originalGetNextPickup(self, driver, forcedSkip)
end
activePickups[driver] = {station = choice.station, fillTypes = choice.fillTypes}
-- hold AutoDrives egen rotations-tilstand konsistent med vores valg
self.pickups[choice.group] = self.pickups[choice.group] or {}
self.pickups[choice.group].lastTarget = choice.markerIndex
self.pickups[choice.group].lastVehicle = driver
Logging.info(ADSmartPickup.LOG_PREFIX .. "'%s' -> %s (%s)", tostring(driver:getName()), tostring(choice.markerName), describeChoice(choice))
logChoiceOnce(driver, choice)
return choice.markerIndex
end
installLoadWaitHook(adEnv)
Logging.info(ADSmartPickup.LOG_PREFIX .. "aktiv (mindst fyldte silo med varen; flere valgte varer = behovsstyret forsyning)")
end
-- Når AutoDrive stopper, får køretøjet hele ingredienslisten tilbage i varevalget
-- (AutoDrive gemmer valget i savegame, så listen overlever også en genindlæsning).
local function restoreStoppedVehicles()
-- en standset traktor må ikke tage "stå og læs"-grebet med over i næste opgave
for vehicle in pairs(activePickups) do
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
if stateModule == nil or stateModule.isActive == nil or not stateModule:isActive() then
activePickups[vehicle] = nil
end
end
for vehicle, state in pairs(supplyState) do
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
if stateModule == nil or not stateModule:isActive() then
+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.1.0.0</version>
<version>1.2.0.0</version>
<title>
<en>AD Smart Pickup</en>
</title>