fix(wait): fysisk optagede Wait-punkter springes over; feat(udkørsel): fodring — med 'Lager til' køres ved >= 10.000 l i kilden (v1.18.3.0)

This commit is contained in:
2026-09-24 12:51:12 +02:00
parent 889689cfce
commit 925163758a
9 changed files with 88 additions and 7 deletions
+2
View File
@@ -306,7 +306,9 @@ function ADOutbound.buildPlanInput(adEnv, run, vehicle)
product.store = findStoreMarker(adEnv, vehicle, product, capacity, sources, nil, run)
end
end
local feedMode = ADRunsController ~= nil and ADRunsController.getStoreMarkers ~= nil and #ADRunsController.getStoreMarkers(adEnv, run) > 0
local input = {
feedMode = feedMode,
capacity = capacity,
hasAutoload = hasAutoload,
sellAtPercent = run.sellAtPercent,
+5 -1
View File
@@ -44,6 +44,10 @@ local function sumSources(product)
return total, percent, pallets
end
-- Fodring: flowet har "Lager til" (et bestemt anlæg der bruger varen, fx gylle til en biogas-fermentor).
-- Så køres der så snart kilden har så meget — at vente på fuldt læs/80 % sulter anlægget.
ADOutboundPlanner.FEED_MIN_LITERS = 10000
function ADOutboundPlanner.evaluate(product, input)
local available, storagePercent, palletCount = sumSources(product)
local percent = product.quote ~= nil and product.quote.percent or nil
@@ -119,7 +123,7 @@ local function collectCandidates(input)
if wantsSell(product.policy) and e.priceOk and product.quote ~= nil and canSellWithoutReserve(e, input) then
table.insert(sell, {product = product, e = e, kind = "sell", targetWayPointId = product.quote.wayPointId, targetName = product.quote.stationName, percent = e.percent})
added = true
elseif wantsStore(product.policy) and (e.fullLoad or e.storageHigh) and product.store ~= nil then
elseif wantsStore(product.policy) and (e.fullLoad or e.storageHigh or (input.feedMode and e.available >= ADOutboundPlanner.FEED_MIN_LITERS)) and product.store ~= nil then
table.insert(store, {product = product, e = e, kind = "store", targetWayPointId = product.store.wayPointId, targetName = product.store.name})
added = true
end
+21 -2
View File
@@ -135,11 +135,30 @@ end
-- ledigt (eller allerede reserveret af dette køretøj) og som isReachable(candidate)
-- godkender (valgfri; AutoDrive slukker sig selv, hvis den sendes mod et punkt uden rute).
-- nil hvis intet punkt duer. Nåelighed tjekkes kun for de punkter der er i spil, nærmeste først.
function ADSupplyPlanner.pickNearestFreeWaitPoint(candidates, claims, x, z, vehicle, isReachable)
-- Wait-punkter hvor et ANDET køretøj fysisk holder (positions = {{x, z}}): hvert køretøj optager
-- højst ét punkt — det nærmeste inden for radius — så et nabopunkt 6 m væk ikke blokeres ved en fejl.
function ADSupplyPlanner.markOccupiedWaitPoints(candidates, positions, radius)
local occupied = {}
local limit = (radius or 6) * (radius or 6)
for _, position in ipairs(positions or {}) do
local best, bestDistance = nil, limit
for _, candidate in ipairs(candidates or {}) do
local dx, dz = candidate.x - position.x, candidate.z - position.z
local distance = dx * dx + dz * dz
if distance <= bestDistance then best, bestDistance = candidate, distance end
end
if best ~= nil then occupied[best.marker.id] = true end
end
return occupied
end
-- occupied (valgfri) = {[markerId] = true} fysisk optaget af andre; springes over medmindre man selv har reservationen.
function ADSupplyPlanner.pickNearestFreeWaitPoint(candidates, claims, x, z, vehicle, isReachable, occupied)
local free = {}
for _, candidate in ipairs(candidates) do
local owner = claims[candidate.marker.id]
if owner == nil or owner == vehicle then
local isTaken = occupied ~= nil and occupied[candidate.marker.id] == true and owner ~= vehicle
if (owner == nil or owner == vehicle) and not isTaken then
local dx, dz = candidate.x - x, candidate.z - z
table.insert(free, {candidate = candidate, distance = dx * dx + dz * dz})
end
+25 -1
View File
@@ -53,12 +53,36 @@ end
-- Nærmeste ledige (eller eget reserverede) Wait-punkt fra vognens position; isReachable(candidate)
-- valgfri. nil uden position eller uden brugbart punkt. Reserverer IKKE selv.
ADWaitPool.OCCUPIED_RADIUS = 6
-- Positioner for ANDRE motoriserede køretøjer (ikke vognen selv eller dens redskaber) — til at se om et
-- Wait-punkt fysisk er optaget, også uden reservation (fx lige efter en omplanlægning).
local function otherVehiclePositions(vehicle)
local positions = {}
local system = g_currentMission ~= nil and g_currentMission.vehicleSystem or nil
local own = {}
if vehicle.getChildVehicles ~= nil then
local ok, children = pcall(vehicle.getChildVehicles, vehicle)
for _, child in pairs(ok and children or {}) do own[child] = true end
end
own[vehicle] = true
for _, other in pairs(system ~= nil and system.vehicles or {}) do
if not own[other] and other.spec_motorized ~= nil and other.rootNode ~= nil then
local ok, x, _, z = pcall(getWorldTranslation, other.rootNode)
if ok and x ~= nil then table.insert(positions, {x = x, z = z}) end
end
end
return positions
end
function ADWaitPool.pickFree(adEnv, vehicle, poolGroup, isReachable)
local x, z = getVehiclePosition(vehicle)
if x == nil then
return nil
end
return ADSupplyPlanner.pickNearestFreeWaitPoint(ADWaitPool.getCandidates(adEnv, poolGroup), ADWaitPool.claims, x, z, vehicle, isReachable)
local candidates = ADWaitPool.getCandidates(adEnv, poolGroup)
local occupied = ADSupplyPlanner.markOccupiedWaitPoints(candidates, otherVehiclePositions(vehicle), ADWaitPool.OCCUPIED_RADIUS)
return ADSupplyPlanner.pickNearestFreeWaitPoint(candidates, ADWaitPool.claims, x, z, vehicle, isReachable, occupied)
end
-- Ender ruten i målet? (AutoDrive returnerer tom/afkortet liste når der ingen vej er.)
+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.18.2.0</version>
<version>1.18.3.0</version>
<title>
<en>AD Smart Pickup</en>
</title>