feat: udkørsel koblet på AutoDrive-hooks; Wait-logik springer udkørsels-traktorer over; v1.12.0.0

This commit is contained in:
2026-09-23 09:59:10 +02:00
parent de36abe1fa
commit cb115f9588
4 changed files with 85 additions and 3 deletions
+37 -1
View File
@@ -13,6 +13,8 @@ ADSmartPickup = {}
ADSmartPickup.dir = g_currentModDirectory ADSmartPickup.dir = g_currentModDirectory
if ADSmartPickup.dir ~= nil and source ~= nil then if ADSmartPickup.dir ~= nil and source ~= nil then
source(ADSmartPickup.dir .. "gui/SmartPickupFrame.lua") source(ADSmartPickup.dir .. "gui/SmartPickupFrame.lua")
source(ADSmartPickup.dir .. "gui/SmartPickupSupplyTab.lua")
source(ADSmartPickup.dir .. "gui/SmartPickupOutboundTab.lua")
end end
-- Markøren er dér hvor trækkerens næse stopper; læssetriggeren ligger et -- Markøren er dér hvor trækkerens næse stopper; læssetriggeren ligger et
@@ -607,6 +609,16 @@ function ADSmartPickup.getActivePickup(vehicle)
return {markerName = pickup.markerName, fillType = pickup.fillType} return {markerName = pickup.markerName, fillType = pickup.fillType}
end end
-- Udkørslens opsamlingsrunde skifter kilde midt i en tur: grebet ("stå og læs ved markøren")
-- følger med til den nye kilde. choice = {station, fillTypes, markerName, fillType} eller nil.
function ADSmartPickup.setActivePickup(vehicle, choice)
if choice == nil or choice.station == nil then
activePickups[vehicle] = nil
return
end
activePickups[vehicle] = {station = choice.station, fillTypes = choice.fillTypes or {}, markerName = choice.markerName, fillType = choice.fillType or (choice.fillTypes or {})[1]}
end
function ADSmartPickup.getIngredientsFor(adEnv, driver) function ADSmartPickup.getIngredientsFor(adEnv, driver)
local run = ADRunsController ~= nil and ADRunsController.getRunForVehicle(driver) or nil local run = ADRunsController ~= nil and ADRunsController.getRunForVehicle(driver) or nil
if run ~= nil then if run ~= nil then
@@ -790,6 +802,24 @@ local function installHook(adEnv)
local originalGetNextPickup = manager.getNextPickup local originalGetNextPickup = manager.getNextPickup
manager.getNextPickup = function(self, driver, forcedSkip) manager.getNextPickup = function(self, driver, forcedSkip)
-- Udkørsel: turvalg (kilde + mål + varer) eller Wait-punkt fra ADOutbound.
if ADOutbound ~= nil and ADOutbound.isOutboundVehicle(driver) then
local okOut, outChoice = pcall(ADOutbound.choosePickup, adEnv, driver)
if not okOut then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "fejl i udkørsel, bruger AutoDrives rotation: %s", tostring(outChoice))
activePickups[driver] = nil
return originalGetNextPickup(self, driver, forcedSkip)
end
if outChoice == nil then
activePickups[driver] = nil
return originalGetNextPickup(self, driver, forcedSkip)
end
ADSmartPickup.setActivePickup(driver, outChoice)
self.pickups[outChoice.group] = self.pickups[outChoice.group] or {}
self.pickups[outChoice.group].lastTarget = outChoice.markerIndex
self.pickups[outChoice.group].lastVehicle = driver
return outChoice.markerIndex
end
local ok, choice = pcall(ADSmartPickup.choosePickup, adEnv, driver) local ok, choice = pcall(ADSmartPickup.choosePickup, adEnv, driver)
if not ok then if not ok then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "fejl i silo-opslag, bruger AutoDrives rotation: %s", tostring(choice)) Logging.warning(ADSmartPickup.LOG_PREFIX .. "fejl i silo-opslag, bruger AutoDrives rotation: %s", tostring(choice))
@@ -815,8 +845,11 @@ local function installHook(adEnv)
if ADUnloadWait ~= nil then if ADUnloadWait ~= nil then
ADUnloadWait.install(adEnv) ADUnloadWait.install(adEnv)
end end
if ADOutbound ~= nil and ADOutbound.install ~= nil then
ADOutbound.install(adEnv)
end
Logging.info(ADSmartPickup.LOG_PREFIX .. "aktiv (mindst fyldte silo med varen; flere valgte varer = behovsstyret forsyning; Wait-punkter for rest-læs)") Logging.info(ADSmartPickup.LOG_PREFIX .. "aktiv (mindst fyldte silo med varen; flere valgte varer = behovsstyret forsyning; Wait-punkter for rest-læs; udkørsel til silo/salg)")
end end
-- Når AutoDrive stopper, får køretøjet hele ingredienslisten tilbage i varevalget -- Når AutoDrive stopper, får køretøjet hele ingredienslisten tilbage i varevalget
@@ -914,6 +947,9 @@ function ADSmartPickup:update(dt)
if ADUnloadWait ~= nil then if ADUnloadWait ~= nil then
pcall(ADUnloadWait.releaseInactive) pcall(ADUnloadWait.releaseInactive)
end end
if ADOutbound ~= nil and ADOutbound.releaseInactive ~= nil then
pcall(ADOutbound.releaseInactive)
end
local ok, err = pcall(restoreStoppedVehicles) local ok, err = pcall(restoreStoppedVehicles)
if not ok then if not ok then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "kunne ikke gendanne varevalg: %s", tostring(err)) Logging.warning(ADSmartPickup.LOG_PREFIX .. "kunne ikke gendanne varevalg: %s", tostring(err))
+4
View File
@@ -249,6 +249,10 @@ local function debugAtTarget(adEnv, task, dt)
end end
function ADUnloadWait.beforeUpdate(adEnv, task, dt) function ADUnloadWait.beforeUpdate(adEnv, task, dt)
-- Udkørsels-traktorer: plads i målet er tjekket før turen, og målet skiftes pr. tur — ingen Wait-logik.
if ADOutbound ~= nil and ADOutbound.isOutboundVehicle ~= nil and ADOutbound.isOutboundVehicle(task.vehicle) then
return
end
pcall(debugAtTarget, adEnv, task, dt) pcall(debugAtTarget, adEnv, task, dt)
local wait = waits[task.vehicle] local wait = waits[task.vehicle]
if wait ~= nil then if wait ~= nil then
+6 -2
View File
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107"> <modDesc descVersion="107">
<author>masterdraco</author> <author>masterdraco</author>
<version>1.11.13.0</version> <version>1.12.0.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
<description> <description>
<en><![CDATA[AutoDrive-tillæg: når pålæsningsmål roteres i en mappe, køres der direkte til den silo i mappen, der har den valgte vare (mindst fyldte først), i stedet for at prøve markørerne én efter én. Vælges FLERE varer i AutoDrive, ses de som ingredienser til aflæsningsmålet (fx en TMR-blander): én traktor henter pr. tur den vare målet mangler mest, fra en silo hvor som helst på kortet. Er målet en fabrik, følger listen automatisk fabrikkens tændte produktioner (tid-til-tom først). Rest-læs ved fuldt mål venter ved nærmeste ledige markør i en "Wait"-mappe til der er plads. Ny ESC-fane "Smart Pickup": definér runs (mål + varer + Wait-pulje + traktorer + ture) og start/stop dem samlet. Venter en traktor med en vare målet er fuldt af, mens målet mangler en anden vare på dens liste, afleveres resten i en silo og den manglende vare hentes. Kræver FS25_AutoDrive med "Brug mapper" + "Rotér mål: pålæsning".]]></en> <en><![CDATA[AutoDrive-tillæg: når pålæsningsmål roteres i en mappe, køres der direkte til den silo i mappen, der har den valgte vare (mindst fyldte først), i stedet for at prøve markørerne én efter én. Vælges FLERE varer i AutoDrive, ses de som ingredienser til aflæsningsmålet (fx en TMR-blander): én traktor henter pr. tur den vare målet mangler mest, fra en silo hvor som helst på kortet. Er målet en fabrik, følger listen automatisk fabrikkens tændte produktioner (tid-til-tom først). Rest-læs ved fuldt mål venter ved nærmeste ledige markør i en "Wait"-mappe til der er plads. Ny ESC-fane "Smart Pickup": definér runs (mål + varer + Wait-pulje + traktorer + ture) og start/stop dem samlet. Venter en traktor med en vare målet er fuldt af, mens målet mangler en anden vare på dens liste, afleveres resten i en silo og den manglende vare hentes. NYT (v1.12): runs med retning "Udkørsel" — traktorer henter fabrikkers output og lagervarer (bulk og paller, også fra objektlagre via Universal Autoload) og kører dem til en silo eller sælger dem, men kun når prisen er tæt på årets toppris (pristærskel pr. run), eller når lageret løber fuldt. Kræver FS25_AutoDrive med "Brug mapper" + "Rotér mål: pålæsning".]]></en>
</description> </description>
<iconFilename>icon.dds</iconFilename> <iconFilename>icon.dds</iconFilename>
<multiplayer supported="true"/> <multiplayer supported="true"/>
@@ -18,6 +18,10 @@
<sourceFile filename="adRunsController.lua"/> <sourceFile filename="adRunsController.lua"/>
<sourceFile filename="adLoadSwap.lua"/> <sourceFile filename="adLoadSwap.lua"/>
<sourceFile filename="adWaitPool.lua"/> <sourceFile filename="adWaitPool.lua"/>
<sourceFile filename="adPrices.lua"/>
<sourceFile filename="adOutboundPlanner.lua"/>
<sourceFile filename="adSources.lua"/>
<sourceFile filename="adOutbound.lua"/>
<sourceFile filename="adUnloadWait.lua"/> <sourceFile filename="adUnloadWait.lua"/>
<sourceFile filename="adSmartPickup.lua"/> <sourceFile filename="adSmartPickup.lua"/>
</extraSourceFiles> </extraSourceFiles>
+38
View File
@@ -1067,5 +1067,43 @@ manager:getNextPickup(chatty, false); manager:getNextPickup(chatty, false)
check("L6 gentaget valg logges én gang", #logLines, 1) check("L6 gentaget valg logges én gang", #logLines, 1)
check("L6 loggen viser eget lager", logLines[1]:find("eget lager", 1, true) ~= nil, true) check("L6 loggen viser eget lager", logLines[1]:find("eget lager", 1, true) ~= nil, true)
-- X: udkørsel koblet på getNextPickup-wrap'en og Wait-logikken
resetWorld()
addMarker(1, "Suger Load", "Pickup points", 0, 0); table.insert(stations, makeStation(101, 0, 15, {[WHEAT] = 1000}))
addMarker(2, "Wait 3", "General Wait", 100, 0)
local outboundDriver = makeDriver(markers[1], {WHEAT})
local outboundCalls, outboundChoice, outboundError = 0, nil, false
ADOutbound = {
isOutboundVehicle = function(vehicle) return vehicle == outboundDriver end,
choosePickup = function(adEnv, vehicle) outboundCalls = outboundCalls + 1; if outboundError then error("boom") end return outboundChoice end,
releaseInactive = function() end,
install = function() end,
}
outboundChoice = {markerIndex = markers[1].markerIndex, markerName = "Suger Load", group = "Pickup points", station = stations[1], fillTypes = {WHEAT}, fillType = WHEAT}
check("X1 udkørsel: kilden vælges af ADOutbound", manager:getNextPickup(outboundDriver, false), markers[1].markerIndex)
check("X1 ADOutbound spurgt", outboundCalls, 1)
check("X1 greb sat (station kendt)", ADSmartPickup.getActivePickup(outboundDriver) ~= nil, true)
outboundChoice = {markerIndex = markers[2].markerIndex, markerName = "Wait 3", group = "General Wait", station = nil, fillTypes = {}, fillType = nil}
check("X1 Wait-markør uden station", manager:getNextPickup(outboundDriver, false), markers[2].markerIndex)
check("X1 intet greb uden station", ADSmartPickup.getActivePickup(outboundDriver), nil)
outboundChoice = nil
check("X1 nil -> AutoDrives original", manager:getNextPickup(outboundDriver, false), "ORIGINAL")
outboundError = true
check("X1 fejl -> AutoDrives original", manager:getNextPickup(outboundDriver, false), "ORIGINAL")
outboundError = false
-- setActivePickup (bruges af opsamlingsrunden) opdaterer grebet direkte
ADSmartPickup.setActivePickup(outboundDriver, {station = stations[1], fillTypes = {WHEAT}, markerName = "Suger Load", fillType = WHEAT})
check("X2 setActivePickup", ADSmartPickup.getActivePickup(outboundDriver).markerName, "Suger Load")
ADSmartPickup.setActivePickup(outboundDriver, nil)
check("X2 setActivePickup nil rydder", ADSmartPickup.getActivePickup(outboundDriver), nil)
-- Wait-logikken springer udkørsels-traktorer over (rører ikke vognens indhold)
local originalUnits = FS25_AutoDrive.AutoDrive.getAllDischargeableUnits
FS25_AutoDrive.AutoDrive.getAllDischargeableUnits = function() error("må ikke kaldes for udkørsel") end
outboundDriver.ad.drivePathModule = {isTargetReached = function() return true end}
local okWait = pcall(ADUnloadWait.beforeUpdate, FS25_AutoDrive, {vehicle = outboundDriver, destinationID = 1}, 16)
check("X3 Wait-logik springer udkørsel over", okWait, true)
FS25_AutoDrive.AutoDrive.getAllDischargeableUnits = originalUnits
ADOutbound = nil
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1) os.exit(failures == 0 and 0 or 1)