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:
@@ -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,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>
|
||||
|
||||
Reference in New Issue
Block a user