diff --git a/FS25_ADSmartPickup/adLoadSwap.lua b/FS25_ADSmartPickup/adLoadSwap.lua index ec65758..9e5aa33 100644 --- a/FS25_ADSmartPickup/adLoadSwap.lua +++ b/FS25_ADSmartPickup/adLoadSwap.lua @@ -87,13 +87,14 @@ function ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReac end wait.swapTimerMs = 0 local vehicle = task.vehicle + -- Tager målet slet ikke varen (forkert last), skal den af uanset hvad der ellers mangler. local missing = ADLoadSwap.findMissingIngredient(adEnv, vehicle, wait.fillType) - if missing == nil then + if missing == nil and not wait.isRejected then return false end local marker = ADLoadSwap.findDumpMarker(adEnv, vehicle, wait.fillType, wait.rest, wait.homeDestinationID, isReachable) local restName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(wait.fillType) or tostring(wait.fillType) - local missingName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(missing.fillType) or tostring(missing.fillType) + local missingName = missing ~= nil and (g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(missing.fillType) or tostring(missing.fillType)) or "-" if marker == nil then if not warnedNoSilo[vehicle] then warnedNoSilo[vehicle] = true @@ -104,7 +105,8 @@ function ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReac warnedNoSilo[vehicle] = nil release(vehicle) redirect(task, marker.id) - Logging.info(ADLoadSwap.LOG_PREFIX .. "'%s' bytter læs: %.0f l %s tilbage i %s (markør %s), målet mangler %s", tostring(vehicle:getName()), wait.rest, tostring(restName), tostring(marker.name), tostring(marker.markerIndex or marker.id), tostring(missingName)) + local why = missing ~= nil and ("målet mangler " .. tostring(missingName)) or "målet tager ikke varen" + Logging.info(ADLoadSwap.LOG_PREFIX .. "'%s' bytter læs: %.0f l %s tilbage i %s (markør %s), %s", tostring(vehicle:getName()), wait.rest, tostring(restName), tostring(marker.name), tostring(marker.markerIndex or marker.id), why) return true end diff --git a/FS25_ADSmartPickup/adSmartPickup.lua b/FS25_ADSmartPickup/adSmartPickup.lua index 74d31db..d5d12c2 100644 --- a/FS25_ADSmartPickup/adSmartPickup.lua +++ b/FS25_ADSmartPickup/adSmartPickup.lua @@ -516,7 +516,8 @@ end -- Fri plads + kapacitet for varen i køretøjets aflæsningsmål (Wait-punkt-logikken); -- nil hvis målet ikke kendes eller ikke tager varen. -function ADSmartPickup.getTargetFreeCapacity(adEnv, driver, fillType) +-- askAccepted=true: returnerer i stedet true/false for "tager målet varen?" (nil = mål ukendt). +function ADSmartPickup.getTargetFreeCapacity(adEnv, driver, fillType, askAccepted) local secondMarker = driver.ad.stateModule:getSecondMarker() local farmId = getFarmId(driver) if secondMarker == nil or farmId == nil then @@ -528,6 +529,9 @@ function ADSmartPickup.getTargetFreeCapacity(adEnv, driver, fillType) return nil end local level, capacity = getTargetLevelAndCapacity(target, fillType, farmId) + if askAccepted then + return level ~= nil + end if level == nil then return nil end @@ -723,7 +727,37 @@ local function installLoadWaitHook(adEnv) return pickup.stalledMs > ADSmartPickup.MAX_WAIT_WITHOUT_LOADING_MS end + -- Vognen kan kun læsse oven i SAMME vare. Er der en anden vare på vognen (rest fra et + -- tidligere run), afsluttes pålæsningen med det samme, så AD kører til aflæsning med + -- det den har — dér tager Wait-/bytte-logikken over, hvis målet ikke tager varen. + local function hasWrongCargo(loadTask) + if loadTask.spuCargoChecked or ADUnloadWait == nil or ADUnloadWait.getRestLoad == nil then + return false + end + loadTask.spuCargoChecked = true + local pickup = activePickups[loadTask.vehicle] + if pickup == nil or pickup.fillType == nil then + return false + end + local fillType, liters = ADUnloadWait.getRestLoad(adEnv, loadTask.vehicle) + if fillType == nil or liters < 100 or fillType == pickup.fillType then + return false + end + local cargoName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType) + local wantedName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(pickup.fillType) or tostring(pickup.fillType) + Logging.info(ADSmartPickup.LOG_PREFIX .. "'%s' har %.0f l %s på vognen og skulle hente %s — leverer først det den har", tostring(loadTask.vehicle:getName()), liters, tostring(cargoName), tostring(wantedName)) + return true + end + task.update = function(self, dt) + local wrongOk, isWrong = pcall(hasWrongCargo, self) + if wrongOk and isWrong then + activePickups[self.vehicle] = nil + if self.finished ~= nil then + self:finished() + return + end + end local ok, shouldWait = pcall(ADSmartPickup.shouldWaitForLoading, self.vehicle) shouldWait = ok and shouldWait if shouldWait then diff --git a/FS25_ADSmartPickup/adUnloadWait.lua b/FS25_ADSmartPickup/adUnloadWait.lua index 545b1c4..eb09109 100644 --- a/FS25_ADSmartPickup/adUnloadWait.lua +++ b/FS25_ADSmartPickup/adUnloadWait.lua @@ -127,7 +127,12 @@ local function startWaiting(adEnv, task) if fillType == nil or rest < ADUnloadWait.MIN_REST_LITERS then return end - local free = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType) + local free, capacity = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType) + -- nil = målet tager slet ikke varen (forkert last fra et tidligere run): som "fuldt" + local isRejected = free == nil and ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType, true) == false + if isRejected then + free = 0 + end if free == nil or free >= ADUnloadWait.MIN_FREE_TO_UNLOAD then return end @@ -169,6 +174,11 @@ local function updateWaiting(adEnv, task, wait, dt) -- Friske tal til evt. bytte og til tilbage-loggen — ikke dem fra da ventningen startede. wait.fillType, wait.rest = fillType, rest local free, capacity = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType) + local isRejected = free == nil and ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType, true) == false + if isRejected then + free = 0 + end + wait.isRejected = isRejected -- run'ets "kør hjem under X %" (fri ≥ (100-X) % af kapaciteten), ellers standardreglen local run = ADRunsController ~= nil and ADRunsController.getRunForVehicle(vehicle) or nil local freeFraction = run ~= nil and run.returnBelowPercent ~= nil and (1 - run.returnBelowPercent / 100) or nil diff --git a/FS25_ADSmartPickup/modDesc.xml b/FS25_ADSmartPickup/modDesc.xml index 0eba7f3..6ead6fc 100644 --- a/FS25_ADSmartPickup/modDesc.xml +++ b/FS25_ADSmartPickup/modDesc.xml @@ -1,7 +1,7 @@ masterdraco - 1.11.6.0 + 1.11.7.0 <en>AD Smart Pickup</en> diff --git a/tests/test_adSmartPickup.lua b/tests/test_adSmartPickup.lua index ee5d497..6012d6e 100644 --- a/tests/test_adSmartPickup.lua +++ b/tests/test_adSmartPickup.lua @@ -923,6 +923,41 @@ check("I6 næste tur: halm til stald 2", manager:getNextPickup(i6, false), 21) check("I6 mål skiftet til stald 2", i6.ad.stateModule.secondMarkerId, 31) ADRunsController.store = ADRuns.newStore() +-- ==== V: forkert last på vognen ==== +-- V1: pålæsning starter med anden vare på vognen -> opgaven afsluttes straks (AD leverer det den har) +buildCowWorld() +cowLevels[STRAW], cowLevels[TMR] = 90000, 0 -- TMR mangler +local wv = makeSupplyDriver(markerByIndex(21), markerByIndex(30), {TMR, STRAW}) +wv.carriable = {TMR, STRAW}; wv.trailers = {level = 8000, capacity = 8000} +wv.units = {{object = {getFillUnitFillLevel = function() return 8000 end, getFillUnitFillType = function() return STRAW end}, fillUnitIndex = 1}} +withDrivePath(wv); wv.targetReached = false +check("V1 TMR vælges som behov", manager:getNextPickup(wv, false), 20) +local loadTask = {vehicle = wv, trailers = wv.trailers, finished = function(self) self.isFinished = true end} +FS25_AutoDrive.LoadAtDestinationTask.update(loadTask, 16) +check("V1 pålæsningsopgave afsluttet pga. halm på vognen", loadTask.isFinished, true) +check("V1 logget", countLogsSince(1, "leverer først") >= 1, true) +-- samme vare på vognen som den der hentes -> opgaven kører normalt +wv.units[1].object.getFillUnitFillType = function() return TMR end +local loadTask2 = {vehicle = wv, trailers = wv.trailers, finished = function(self) self.isFinished = true end} +manager:getNextPickup(wv, false) +FS25_AutoDrive.LoadAtDestinationTask.update(loadTask2, 16) +check("V1 samme vare -> ikke afsluttet", loadTask2.isFinished, nil) + +-- V2: ved målet med en vare målet ikke tager -> Wait; ved Wait -> silo uanset "manglende" vare +buildWaitWorld() +table.insert(unloadStations, stations[2]) -- halmladen tager halm +stations[2].unloadTriggers = {{exactFillRootNode = 121}} +stations[2].getIsFillTypeSupported = function(_, fillType) return fillType == STRAW end +stations[2].getFreeCapacity = function() return 100000 end +stations[2].owningPlaceable = {spec_silo = {storages = {{getFillLevel = function() return 0 end}}}} +waitBarnCapacity[STRAW] = nil -- stalden tager IKKE halm +local vw, tw = makeUnloadingVehicle("Fastrac Forkert", 561, 5000, 35000) +UnloadTask.update(tw, 16) +check("V2 målet tager ikke varen -> Wait", tw.destinationID, 40) +UnloadTask.update(tw, ADLoadSwap.CHECK_INTERVAL_MS + 1) +check("V2 fra Wait til silo selv uden manglende vare", tw.destinationID, 21) +waitBarnCapacity[STRAW] = 50000 + -- ==== E: eksponerede opslag (bruges af runs-controller og læs-bytte) ==== local eDriver = buildCowWorld() check("E1 aflæsningsstation ved waypoint", ADSmartPickup.getUnloadStationAtWayPointId(FS25_AutoDrive, 30, 1), unloadStations[1])