fix: spor-regel, vent kun ved målet, sikkerhedsventil (v1.4.0.0)

In-game-fund 2026-09-21:
- 'Dropof'-markøren vandt over 'Pickup' ved ensilage-tankene (samme tank, modsat
  side): triggeren skal nu ligge i trækkerens spor (<= 6 m til siden); nødløsning
  uden spor-træf kun inden for 12 m når retningen kendes.
- Rotationen blev skjult under hele pålæsningsopgaven, så traktoren ventede ved
  nabosiloens tomme trigger på vej til målet: skjules nu først når målet er nået.
- Sikkerhedsventil: 30 s ved markøren uden læsning -> grebet slippes.
Verificeret mod savegame: 40/40 silo-markører, 7 pickup koblet, 0 dropof.
This commit is contained in:
2026-09-21 16:15:55 +02:00
parent e414c99b58
commit e6412d78e4
4 changed files with 114 additions and 14 deletions
+48 -8
View File
@@ -16,8 +16,17 @@ ADSmartPickup.MAX_MARKER_TO_TRIGGER_DISTANCE = 40
-- I tætte silo-rækker ligger nabosiloens trigger FORAN næsen og er ofte nærmere
-- end markørens egen. Triggere mere end dette foran næsen hører til naboen.
ADSmartPickup.MAX_TRIGGER_AHEAD_OF_MARKER = 2
-- Vognen følger trækkerens spor: en trigger længere til siden end dette er en
-- anden bane (fx aflæsningssiden af samme tank), ikke markørens læsseplads.
ADSmartPickup.MAX_TRIGGER_LATERAL_OFFSET = 6
-- Kendes køreretningen, men ligger ingen trigger i sporet bag næsen (kurve ind til
-- markøren), accepteres kun en trigger helt tæt på.
ADSmartPickup.MAX_FALLBACK_TRIGGER_DISTANCE = 12
-- Under dette niveau regnes siloen som tom (undgår ture efter støv-rester).
ADSmartPickup.MIN_USEFUL_LITERS = 1
-- Sikkerhedsventil: står køretøjet ved markøren så længe uden at vognen fyldes
-- (forkert markør↔silo-kobling, røret når ikke vognen), slippes grebet.
ADSmartPickup.MAX_WAIT_WITHOUT_LOADING_MS = 30000
ADSmartPickup.LOG_PREFIX = "ADSmartPickup: "
local LOAD_TRIGGER_NODE_FIELDS = {"triggerNode"}
@@ -96,10 +105,13 @@ local function getDistancesToTriggers(triggers, nodeFields, wayPoint, direction)
local tx, _, tz = getWorldTranslation(node)
local distance = MathUtil.vector2Length(wayPoint.x - tx, wayPoint.z - tz)
closest = math.min(closest, distance)
-- > 0: triggeren ligger bag næsen set i køreretningen
local behind = direction ~= nil and ((wayPoint.x - tx) * direction.x + (wayPoint.z - tz) * direction.z) or nil
if behind ~= nil and behind >= -ADSmartPickup.MAX_TRIGGER_AHEAD_OF_MARKER then
closestBehind = math.min(closestBehind, distance)
if direction ~= nil then
-- behind > 0: bag næsen set i køreretningen; lateral: afstand fra sporet
local behind = (wayPoint.x - tx) * direction.x + (wayPoint.z - tz) * direction.z
local lateral = math.abs((wayPoint.x - tx) * direction.z - (wayPoint.z - tz) * direction.x)
if behind >= -ADSmartPickup.MAX_TRIGGER_AHEAD_OF_MARKER and lateral <= ADSmartPickup.MAX_TRIGGER_LATERAL_OFFSET then
closestBehind = math.min(closestBehind, distance)
end
end
end
end
@@ -107,11 +119,12 @@ local function getDistancesToTriggers(triggers, nodeFields, wayPoint, direction)
return closest, closestBehind
end
-- Markørens station: nærmeste trigger bag næsen; findes ingen (eller er
-- retningen ukendt), nærmeste trigger overhovedet.
-- Markørens station: nærmeste trigger i sporet bag næsen. Findes ingen, bruges
-- nærmeste trigger overhovedet — helt tæt på hvis retningen kendes, ellers som før.
local function getClosestStation(adEnv, candidateStations, triggersField, nodeFields, wayPoint, farmId)
local direction = getArrivalDirection(adEnv, wayPoint)
local best = {any = {distance = ADSmartPickup.MAX_MARKER_TO_TRIGGER_DISTANCE}, behind = {distance = ADSmartPickup.MAX_MARKER_TO_TRIGGER_DISTANCE}}
local maxFallbackDistance = direction ~= nil and ADSmartPickup.MAX_FALLBACK_TRIGGER_DISTANCE or ADSmartPickup.MAX_MARKER_TO_TRIGGER_DISTANCE
local best = {any = {distance = maxFallbackDistance}, behind = {distance = ADSmartPickup.MAX_MARKER_TO_TRIGGER_DISTANCE}}
for _, station in pairs(candidateStations) do
if g_currentMission.accessHandler:canFarmAccess(farmId, station) then
local closest, closestBehind = getDistancesToTriggers(station[triggersField], nodeFields, wayPoint, direction)
@@ -339,6 +352,12 @@ function ADSmartPickup.shouldWaitForLoading(vehicle)
if pickup == nil then
return false
end
-- kun FREMME ved markøren: undervejs ruller vognen gennem nabosiloers triggere,
-- og dér skal AutoDrives rotation gælde (kør videre ved tom trigger).
local drivePathModule = vehicle.ad ~= nil and vehicle.ad.drivePathModule or nil
if drivePathModule == nil or not drivePathModule:isTargetReached() then
return false
end
local level = getStationFillLevel(pickup.station, pickup.fillTypes, getFarmId(vehicle))
return level >= ADSmartPickup.MIN_USEFUL_LITERS
end
@@ -364,9 +383,30 @@ local function installLoadWaitHook(adEnv)
return originalGetSetting(settingName, vehicle)
end
-- true når vognen ikke er blevet fyldt i MAX_WAIT_WITHOUT_LOADING_MS ved markøren
local function hasLoadingStalled(loadTask, dt)
local pickup = activePickups[loadTask.vehicle]
local fillLevel = autoDrive.getAllFillLevels ~= nil and autoDrive.getAllFillLevels(loadTask.trailers) or 0
if pickup.lastFillLevel == nil or fillLevel > pickup.lastFillLevel then
pickup.lastFillLevel, pickup.stalledMs = fillLevel, 0
return false
end
pickup.stalledMs = pickup.stalledMs + dt
return pickup.stalledMs > ADSmartPickup.MAX_WAIT_WITHOUT_LOADING_MS
end
task.update = function(self, dt)
local ok, shouldWait = pcall(ADSmartPickup.shouldWaitForLoading, self.vehicle)
waitingVehicle = ok and shouldWait and self.vehicle or nil
shouldWait = ok and shouldWait
if shouldWait then
local stalledOk, isStalled = pcall(hasLoadingStalled, self, dt)
if not stalledOk or isStalled then
Logging.warning(ADSmartPickup.LOG_PREFIX .. "'%s' læsser ikke ved markøren; slipper grebet så AutoDrive kører videre", tostring(self.vehicle:getName()))
activePickups[self.vehicle] = nil
shouldWait = false
end
end
waitingVehicle = shouldWait and self.vehicle or nil
local updateOk, err = pcall(originalUpdate, self, dt)
waitingVehicle = nil
if not updateOk 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.3.0.0</version>
<version>1.4.0.0</version>
<title>
<en>AD Smart Pickup</en>
</title>