-- AD Unload Wait -- Holder en traktor med rest-læs ved en fuld stald AutoDrive i dag stille ved -- aflæsningspunktet "til den er tømt på en eller anden måde" — og spærrer for -- de næste i køen. Her omdirigeres den i stedet til nærmeste ledige Wait-punkt -- (markør i en mappe med ordet "Wait" i navnet, fx "Cow Wait"), og når målet igen -- har plads til HELE resten, sendes den tilbage og læsser af. -- -- Kun den aktuelle aflæsningsopgaves destination ændres; AutoDrives mål, -- rotation og loop-tæller røres ikke. ADUnloadWait = {} -- Under dette regnes vognen som tom (AutoDrive selv bruger 0,1 l). ADUnloadWait.MIN_REST_LITERS = 100 -- Kan målet tage mindre end dette, regnes det som fuldt (aflæsning starter ikke). ADUnloadWait.MIN_FREE_TO_UNLOAD = 100 ADUnloadWait.LOG_PREFIX = "ADSmartPickup: " -- køretøj -> {task, homeDestinationID, waitMarker, fillType, rest} local waits = setmetatable({}, {__mode = "k"}) local warnedNoWaitPoint = setmetatable({}, {__mode = "k"}) local isInstalled = false -- Den vare og mængde der er tilbage på vognen (største fyldte aflæsselige enhed). local function getRestLoad(adEnv, vehicle) local bestFillType, bestLevel = nil, 0 for _, unit in ipairs(adEnv.AutoDrive.getAllDischargeableUnits(vehicle) or {}) do local object = unit.object if object ~= nil and object.getFillUnitFillLevel ~= nil then local level = object:getFillUnitFillLevel(unit.fillUnitIndex) or 0 if level > bestLevel then bestLevel = level bestFillType = object.getFillUnitFillType ~= nil and object:getFillUnitFillType(unit.fillUnitIndex) or nil end end end return bestFillType, bestLevel end local function getWaitPoolGroup(vehicle) local run = ADRunsController ~= nil and ADRunsController.getRunForVehicle(vehicle) or nil return run ~= nil and run.waitPoolGroup or nil end -- Rutetjek, reservationer og omdirigering deles med udkørsels-modulet (adWaitPool). -- Kun "til punktet" ved silo-aflæsning: næste tur er AD's egen rute fra siloen. local function hasRouteTo(adEnv, vehicle, wayPointId) return ADWaitPool.hasRouteTo(adEnv, vehicle, wayPointId) end local function hasRouteBothWays(adEnv, vehicle, waitWayPointId, homeWayPointId) return ADWaitPool.hasRouteBothWays(adEnv, vehicle, waitWayPointId, homeWayPointId) end local function redirect(task, destinationID) ADWaitPool.redirect(task, destinationID) end -- køretøj -> AD's oprindelige 2. markør (waypoint-id) mens der læsses af i en silo local pendingTargetRestore = setmetatable({}, {__mode = "k"}) -- Aflæsning ved en ANDEN destination end AD's mål: AD tipper kun når vognen er tæt på -- AD's egen 2. markør (getDistanceToUnloadPosition), så den skiftes midlertidigt til -- siloen og gendannes når opgaven er færdig. local function redirectForUnload(task, destinationID) local vehicle = task.vehicle local stateModule = vehicle.ad.stateModule local current = stateModule.getSecondMarker ~= nil and stateModule:getSecondMarker() or nil if current ~= nil and current.id ~= destinationID and stateModule.setSecondMarkerByWayPointId ~= nil then pendingTargetRestore[vehicle] = pendingTargetRestore[vehicle] or current.id stateModule:setSecondMarkerByWayPointId(destinationID) end redirect(task, destinationID) end local function restoreTarget(vehicle) local homeId = pendingTargetRestore[vehicle] if homeId == nil then return end pendingTargetRestore[vehicle] = nil local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil if stateModule ~= nil and stateModule.setSecondMarkerByWayPointId ~= nil then stateModule:setSecondMarkerByWayPointId(homeId) end end local function release(vehicle) if waits[vehicle] ~= nil then ADWaitPool.releaseVehicle(vehicle) end waits[vehicle] = nil if ADLoadSwap ~= nil then ADLoadSwap.clearWarning(vehicle) end end -- "Fremme ved målet": AD stopper vognen så snart den står i aflæsningstriggeren — ofte -- 5–10 m FØR markøren, så isTargetReached() bliver aldrig sand (set ved sukkerfabrikken). -- Derfor tæller også AD's eget mål for tipning (afstand til aflæsningsstedet inden for -- AD's trigger-afstand) og at AD er i gang med at tippe. local function isAtUnloadTarget(adEnv, vehicle) if vehicle.ad.drivePathModule:isTargetReached() then return true end local trailerModule = vehicle.ad.trailerModule if trailerModule ~= nil and trailerModule.isUnloading then return true end local autoDrive = adEnv.AutoDrive if autoDrive.getDistanceToUnloadPosition ~= nil and autoDrive.getMaxTriggerDistance ~= nil then local ok, distance = pcall(autoDrive.getDistanceToUnloadPosition, vehicle) local okMax, maxDistance = pcall(autoDrive.getMaxTriggerDistance, vehicle) if ok and okMax and type(distance) == "number" and type(maxDistance) == "number" then return distance <= maxDistance end end return false end -- Står køretøjet ved målet med rest-læs, som målet ikke kan tage? Så find et Wait-punkt. ADUnloadWait.MIN_FREE_FOR_OTHER_TARGET = 1000 -- Det af run'ets ANDRE mål der tager varen og har mest fri plads (≥ MIN_FREE_FOR_OTHER_TARGET) og vej. local function findOtherTargetForRest(adEnv, vehicle, fillType, currentId) local run = ADRunsController ~= nil and ADRunsController.getRunForVehicle ~= nil and ADRunsController.getRunForVehicle(vehicle) or nil if run == nil or (run.kind or "supply") ~= "supply" or vehicle.ad.stateModule.setSecondMarkerByWayPointId == nil then return nil end local best, bestFree = nil, ADUnloadWait.MIN_FREE_FOR_OTHER_TARGET - 1 for _, targetId in ipairs(ADRunsController.getRunTargets(run)) do if targetId ~= currentId then local free = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType, false, targetId) if free ~= nil and free > bestFree and hasRouteTo(adEnv, vehicle, targetId) then local marker = adEnv.ADGraphManager.getMapMarkerByWayPointId ~= nil and adEnv.ADGraphManager:getMapMarkerByWayPointId(targetId) or nil best, bestFree = {id = targetId, name = marker ~= nil and marker.name or tostring(targetId)}, free end end end return best, bestFree end local function startWaiting(adEnv, task) local vehicle = task.vehicle -- Kun "fremme ved målet". At AD stadig regner vognen som aflæssende (isActiveAtTrigger) -- tæller IKKE med: ved et fuldt fodertrug bliver isUnloading stående for evigt, selv om -- intet løber — og så blokerede traktoren stalden i stedet for at køre til Wait. if not isAtUnloadTarget(adEnv, vehicle) then return end -- Efter et bytte er opgavens mål en silo, ikke AD's rigtige aflæsningsmål (anden markør); -- der skal AD bare læsse af som normalt, uden Wait-logik. local target = vehicle.ad.stateModule.getSecondMarker ~= nil and vehicle.ad.stateModule:getSecondMarker() or nil if target == nil or task.destinationID ~= target.id then return end local fillType, rest = getRestLoad(adEnv, vehicle) if fillType == nil then return end if rest < ADUnloadWait.MIN_REST_LITERS then -- En lille rest som målet ikke kan tage: AutoDrive venter ellers for evigt i triggeren -- ("til den er tømt") og spærrer for de næste. Regn vognen som tom og kør videre. local smallFree = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType) if rest > 0 and (smallFree == nil or smallFree < rest) and task.finished ~= nil then Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s': %.0f l %s rest kan ikke komme af — regnes som tom, kører videre", tostring(ADRuns.vehicleLabel(vehicle)), rest, g_fillTypeManager ~= nil and tostring(g_fillTypeManager:getFillTypeNameByIndex(fillType)) or tostring(fillType)) task:finished() end return end 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 -- Run med flere mål: resten køres til det af run'ets andre mål der har mest plads til varen, -- før der ventes (en 2,4M l-vogn kan ellers aldrig komme af med resten ved én svinesti) local other, otherFree = findOtherTargetForRest(adEnv, vehicle, fillType, target.id) if other ~= nil then vehicle.ad.stateModule:setSecondMarkerByWayPointId(other.id) redirect(task, other.id) Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s': %s er fuld — resten (%.0f l %s) køres til %s (%.0f l fri)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(target.name), rest, g_fillTypeManager ~= nil and tostring(g_fillTypeManager:getFillTypeNameByIndex(fillType)) or tostring(fillType), tostring(other.name), otherFree) return end local isReachable = function(candidate) return hasRouteBothWays(adEnv, vehicle, candidate.marker.id, task.destinationID) end local pool = getWaitPoolGroup(vehicle) local candidate = ADWaitPool.pickFree(adEnv, vehicle, pool, isReachable) if candidate == nil then if not warnedNoWaitPoint[vehicle] then warnedNoWaitPoint[vehicle] = true local poolText = pool ~= nil and pool ~= "" and (" i puljen '" .. pool .. "'") or "" Logging.warning(ADUnloadWait.LOG_PREFIX .. "'%s' har %.0f l rest, og målet er fuldt — intet ledigt Wait-punkt%s med vejnet til OG fra målet (markør i en mappe med 'Wait' i navnet), så AutoDrive venter ved målet", tostring(ADRuns.vehicleLabel(vehicle)), rest, poolText) end return end warnedNoWaitPoint[vehicle] = nil ADWaitPool.claim(candidate.marker.id, vehicle) waits[vehicle] = {task = task, homeDestinationID = task.destinationID, waitMarker = candidate.marker, fillType = fillType, rest = rest} -- AD tipper (og holder vognen stille) så længe den står nær sit EGET mål — også i små -- portioner, når målet forbruger løbende. Derfor peger AD's mål på Wait-punktet imens. redirectForUnload(task, candidate.marker.id) local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType) Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' venter ved %s (markør %s): %.0f l %s rest, målet har kun %.0f l fri", tostring(ADRuns.vehicleLabel(vehicle)), tostring(candidate.marker.name), tostring(candidate.marker.markerIndex or candidate.marker.id), rest, tostring(fillTypeName), free) end -- Ventende køretøj: er der nu plads til hele resten, køres tilbage til målet. local function updateWaiting(adEnv, task, wait, dt) local vehicle = task.vehicle if wait.task ~= task then release(vehicle) return end local fillType, rest = getRestLoad(adEnv, vehicle) if fillType == nil or rest < ADUnloadWait.MIN_REST_LITERS then release(vehicle) return end -- Friske tal til evt. bytte og til tilbage-loggen — ikke dem fra da ventningen startede. wait.fillType, wait.rest = fillType, rest local home = wait.homeDestinationID local free, capacity = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType, nil, home) local isRejected = free == nil and ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType, true, home) == 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 if free == nil or not ADSupplyPlanner.canUnloadRest(free, rest, capacity, freeFraction) then if ADLoadSwap ~= nil then local isReachable = function(markerId) return hasRouteTo(adEnv, vehicle, markerId) end ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirectForUnload, release, isReachable) end return end release(vehicle) restoreTarget(vehicle) redirect(task, home) Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' kører tilbage fra %s og læsser %.0f l af (målet har %.0f l fri)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(wait.waitMarker.name), rest, free) end -- Diagnose (midlertidig): mens en traktor holder ved sit mål med last, logges hvert 15. s hvad -- AD ser — vognens indhold, målets fri plads, AD's aflæsningstilstand og vognens dischargeState. ADUnloadWait.DEBUG_INTERVAL_MS = 15000 local debugTimers = setmetatable({}, {__mode = "k"}) local debugStuck = setmetatable({}, {__mode = "k"}) -- vehicle -> {level, since}: læsset uændret siden ADUnloadWait.STUCK_WITH_ROOM_MS = 30000 local function debugAtTarget(adEnv, task, dt) local vehicle = task.vehicle local targetReached = vehicle.ad.drivePathModule:isTargetReached() debugTimers[vehicle] = (debugTimers[vehicle] or ADUnloadWait.DEBUG_INTERVAL_MS) + (dt or 0) if debugTimers[vehicle] < ADUnloadWait.DEBUG_INTERVAL_MS then return end debugTimers[vehicle] = 0 local fillType, rest = getRestLoad(adEnv, vehicle) if fillType == nil or rest < ADUnloadWait.MIN_REST_LITERS then return end local free, capacity = ADSmartPickup.getTargetFreeCapacity(adEnv, vehicle, fillType) -- ved målet MED plads, men læsset falder ikke (in-game 29/9: EDK 650 ved TMR Unload/Biogas Drop) — også det -- vil vi se. Ellers kun: målet fuldt/afvist, og traktoren venter ikke ved et Wait-punkt. local stuck = debugStuck[vehicle] if stuck == nil or rest < stuck.level - 1 then stuck = {level = rest, since = g_time or 0} debugStuck[vehicle] = stuck end local stuckWithRoom = targetReached and (g_time or 0) - stuck.since >= ADUnloadWait.STUCK_WITH_ROOM_MS if waits[vehicle] ~= nil or (free ~= nil and free >= ADUnloadWait.MIN_FREE_TO_UNLOAD and not stuckWithRoom) then return end local trailerModule = vehicle.ad.trailerModule local states = {} for _, unit in ipairs(adEnv.AutoDrive.getAllDischargeableUnits(vehicle) or {}) do local object = unit.object local state = object ~= nil and object.getDischargeState ~= nil and object:getDischargeState() or "?" local canDischarge = "?" if object ~= nil and object.getCanDischargeToObject ~= nil and object.getCurrentDischargeNode ~= nil then local ok, value = pcall(function() return object:getCanDischargeToObject(object:getCurrentDischargeNode()) end) canDischarge = ok and tostring(value) or "err" end table.insert(states, string.format("dischargeState=%s canDischargeToObject=%s", tostring(state), canDischarge)) end local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType) local distance = adEnv.AutoDrive.getDistanceToUnloadPosition ~= nil and adEnv.AutoDrive.getDistanceToUnloadPosition(vehicle) or -1 local secondMarker = vehicle.ad.stateModule.getSecondMarker ~= nil and vehicle.ad.stateModule:getSecondMarker() or nil Logging.info(ADUnloadWait.LOG_PREFIX .. "DEBUG '%s': targetReached=%s taskDest=%s adMål=%s; %.0f l %s på vognen; målet fri=%s/kap=%s; AD isUnloading=%s isLoading=%s afstandTilAflæsning=%.1f; venter=%s; %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(targetReached), tostring(task.destinationID), tostring(secondMarker ~= nil and secondMarker.id or nil), rest, tostring(fillTypeName), tostring(free), tostring(capacity), tostring(trailerModule ~= nil and trailerModule.isUnloading), tostring(trailerModule ~= nil and trailerModule.isLoading), tonumber(distance) or -1, tostring(waits[vehicle] ~= nil), table.concat(states, " | ")) end 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 -- Tømning efter stop (ADFlowWagons): ingen Wait-pulje eller læs-bytte — den skal tømme og hjem -- (in-game 29/9: Goat Food blev sendt til Cow Wait efter Stop alt) if ADFlowWagons ~= nil and ADFlowWagons.isEmptying ~= nil and ADFlowWagons.isEmptying(task.vehicle) then if waits[task.vehicle] ~= nil then release(task.vehicle) end return end pcall(debugAtTarget, adEnv, task, dt) local wait = waits[task.vehicle] if wait ~= nil then updateWaiting(adEnv, task, wait, dt) else startWaiting(adEnv, task) end end -- Efter en genindlæsning er ventetilstanden (kun i hukommelsen) væk, men AutoDrives gemte mål -- peger stadig på Wait-punktet, og traktoren står der med rest-læs — uden dette ville den blive -- stående for evigt. Her genoptages ventningen for aktive traktorer i et forsynings-run hvis -- aflæsningsopgave peger på en Wait-markør: hjem = run'ets mål, og reservationen sættes igen. -- Kaldes fra ADSmartPickup:update (throttlet). ADUnloadWait.ADOPT_INTERVAL_MS = 5300 local adoptTimerMs = ADUnloadWait.ADOPT_INTERVAL_MS function ADUnloadWait.adoptOrphans(adEnv) if ADRunsController == nil or ADRunsController.getFarmVehicles == nil then return end for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil local isActive = stateModule ~= nil and stateModule.isActive ~= nil and stateModule:isActive() local run = isActive and waits[vehicle] == nil and ADRunsController.getRunForVehicle(vehicle) or nil if run ~= nil and (run.kind or "supply") == "supply" and stateModule.getSecondMarker ~= nil then local marker = stateModule:getSecondMarker() local task = vehicle.ad.taskModule ~= nil and vehicle.ad.taskModule.getActiveTask ~= nil and vehicle.ad.taskModule:getActiveTask() or nil if marker ~= nil and marker.id ~= nil and ADSupplyPlanner.isWaitMarker(marker) and task ~= nil and task.destinationID == marker.id and task.trailers ~= nil then local fillType, rest = getRestLoad(adEnv, vehicle) local homeId = ADRunsController.chooseTarget ~= nil and ADRunsController.chooseTarget(adEnv, run, vehicle) or run.targetWayPointId if fillType ~= nil and rest >= ADUnloadWait.MIN_REST_LITERS and homeId ~= nil then ADWaitPool.claim(marker.id, vehicle) pendingTargetRestore[vehicle] = homeId waits[vehicle] = {task = task, homeDestinationID = homeId, waitMarker = marker, fillType = fillType, rest = rest} local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType) Logging.info(ADUnloadWait.LOG_PREFIX .. "'%s' genoptager ventning ved %s efter genindlæsning: %.0f l %s rest, hjem = markør %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(marker.name), rest, tostring(fillTypeName), tostring(homeId)) end end end end end function ADUnloadWait.adoptOrphansThrottled(adEnv, dt) adoptTimerMs = adoptTimerMs + (dt or 0) if adoptTimerMs < ADUnloadWait.ADOPT_INTERVAL_MS then return end adoptTimerMs = 0 local ok, err = pcall(ADUnloadWait.adoptOrphans, adEnv) if not ok then Logging.warning(ADUnloadWait.LOG_PREFIX .. "kunne ikke genoptage ventende traktorer: %s", tostring(err)) end end -- Kaldes fra ADSmartPickup:update — standsede køretøjer slipper deres Wait-punkt. function ADUnloadWait.releaseInactive() for vehicle in pairs(waits) do local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil if stateModule == nil or stateModule.isActive == nil or not stateModule:isActive() then release(vehicle) end end for vehicle in pairs(pendingTargetRestore) do local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil if stateModule == nil or stateModule.isActive == nil or not stateModule:isActive() then restoreTarget(vehicle) end end end function ADUnloadWait.getPendingTargetRestore(vehicle) return pendingTargetRestore[vehicle] end -- Ved Start med forkert last: AD's mål peger på siloen indtil aflæsningen er færdig; -- det oprindelige mål gendannes af finished-hook'en. function ADUnloadWait.setDumpTarget(vehicle, dumpWayPointId) local stateModule = vehicle.ad.stateModule local current = stateModule.getSecondMarker ~= nil and stateModule:getSecondMarker() or nil if current ~= nil and current.id ~= dumpWayPointId then pendingTargetRestore[vehicle] = pendingTargetRestore[vehicle] or current.id end if stateModule.setSecondMarkerByWayPointId ~= nil then stateModule:setSecondMarkerByWayPointId(dumpWayPointId) end end -- Hvem holder hvor (GUI'ets Wait-puljer-visning). Sorteret på mappe, dernæst markør-id. -- Vognens indhold (største enhed) og evt. Wait-tilstand — til overblikket i fanen. function ADUnloadWait.hasRouteBothWays(adEnv, vehicle, toWayPointId, homeWayPointId) return hasRouteBothWays(adEnv, vehicle, toWayPointId, homeWayPointId) end function ADUnloadWait.hasRouteTo(adEnv, vehicle, wayPointId) return hasRouteTo(adEnv, vehicle, wayPointId) end function ADUnloadWait.getRestLoad(adEnv, vehicle) return getRestLoad(adEnv, vehicle) end function ADUnloadWait.getWaitFor(vehicle) local wait = waits[vehicle] if wait == nil then return nil end return {markerName = wait.waitMarker ~= nil and wait.waitMarker.name or nil, fillType = wait.fillType, rest = wait.rest} end -- Alle reservationer i puljen (også udkørsels-traktorer der holder). function ADUnloadWait.getClaims(adEnv) return ADWaitPool.getClaims(adEnv) end ADUnloadWait.TIP_CHECK_MS = 2000 local tipChecked = setmetatable({}, {__mode = "k"}) function ADUnloadWait.install(adEnv) local task, autoDrive = adEnv.UnloadAtDestinationTask, adEnv.AutoDrive if isInstalled or task == nil or task.update == nil or autoDrive == nil or autoDrive.getSetting == nil then return end isInstalled = true ADUnloadWait.STATE_DRIVING = task.STATE_DRIVING or 2 ADWaitPool.STATE_DRIVING = ADUnloadWait.STATE_DRIVING local originalUpdate, originalFinished, originalGetSetting = task.update, task.finished, autoDrive.getSetting task.update = function(self, dt) -- alle aflæsningsture (også udkørsel og tømning): tipvognen på en side AD må aflæsse fra (EDK 650, 29/9) if ADTipSide ~= nil and self.vehicle ~= nil then local now = g_time or 0 if (tipChecked[self.vehicle] or -math.huge) + ADUnloadWait.TIP_CHECK_MS <= now then tipChecked[self.vehicle] = now local okTip, errTip = pcall(ADTipSide.ensure, self.vehicle) if not okTip then Logging.warning(ADUnloadWait.LOG_PREFIX .. "tip-side: %s", tostring(errTip)) end end end local ok, err = pcall(ADUnloadWait.beforeUpdate, adEnv, self, dt) if not ok then Logging.warning(ADUnloadWait.LOG_PREFIX .. "fejl i Wait-punkt-logik, AutoDrive fortsætter selv: %s", tostring(err)) release(self.vehicle) end return originalUpdate(self, dt) end if originalFinished ~= nil then task.finished = function(self) release(self.vehicle) restoreTarget(self.vehicle) -- læsset er afleveret: tæller ikke længere som "på vej" for de andre traktorer if ADSmartPickup ~= nil and ADSmartPickup.clearEnRoute ~= nil then ADSmartPickup.clearEnRoute(self.vehicle) end return originalFinished(self) end end -- Ved "rotér aflæsning" kører AutoDrive straks videre fra et mål den ikke kan læsse -- af ved — også fra Wait-punktet. Ventende køretøjer ser derfor rotationen som slået fra. autoDrive.getSetting = function(settingName, vehicle) if settingName == "rotateTargets" and vehicle ~= nil and waits[vehicle] ~= nil then return autoDrive.RT_NONE end return originalGetSetting(settingName, vehicle) end end