feat(marker): vender/river/læssevogn genbruger slåmaskinens Courseplay-kursus (v1.22.0.0)

In-game 25/9: læssevognens nye CP-kursus lå forskudt i forhold til skårene -> ikke samlet korrekt.
Slåkurset gemmes pr. mark (kopi) og kopieres til næste trin med vehicle:cpCopyCourse; efter
genindlæsning hentes det fra slåmaskinen (mowVehicle gemt i ADSmartPickup_fields.xml).
This commit is contained in:
2026-09-25 23:25:55 +02:00
parent 048f5e6547
commit 4c88118e56
9 changed files with 78 additions and 22 deletions
+28 -8
View File
@@ -74,7 +74,16 @@ function ADCpBridge.isWorking(vehicle)
return vehicle.getIsAIActive ~= nil and vehicle:getIsAIActive() or false
end
function ADCpBridge.start(vehicle, fieldX, fieldZ, onDone)
-- Køretøjets nuværende Courseplay-kursus (slåmaskinens kursus genbruges af de næste trin).
function ADCpBridge.getCourse(vehicle)
if vehicle == nil or vehicle.getFieldWorkCourse == nil then return nil end
local ok, course = pcall(vehicle.getFieldWorkCourse, vehicle)
return ok and course or nil
end
-- course (valgfri): et færdigt kursus (slåmaskinens) der kopieres til køretøjet i stedet for at lave et
-- nyt — så vender/river/læssevogn kører præcis slåmaskinens baner (in-game 25/9: nyt kursus lå forskudt).
function ADCpBridge.start(vehicle, fieldX, fieldZ, onDone, course)
if not ADCpBridge.isAvailable() then
return nil, "Courseplay (FIELDWORK_CP) findes ikke"
end
@@ -93,16 +102,27 @@ function ADCpBridge.start(vehicle, fieldX, fieldZ, onDone)
handle.finished = true
if not handle.cancelled then onDone(ok, reason) end
end
local function startWithCourse()
job:setValues()
local ok, err = job:validate(farmId)
if not ok then return finish(false, "Courseplay: " .. tostring(err)) end
g_currentMission.aiSystem:startJob(job, farmId)
finish(true, handle.copiedCourse and "copied" or nil)
end
local function generateAndStart()
if handle.cancelled then return end
job:onClickGenerateFieldWorkCourse(function(course)
if course ~= nil and vehicle.cpCopyCourse ~= nil then
local copied, copyError = pcall(vehicle.cpCopyCourse, vehicle, course)
if copied then
handle.copiedCourse = true
return startWithCourse()
end
Logging.warning("ADSmartPickup: kunne ikke kopiere slåkursus: %s — laver nyt", tostring(copyError))
end
job:onClickGenerateFieldWorkCourse(function(generated)
if handle.cancelled then return end
if not course then return finish(false, "Courseplay kunne ikke lave kursus") end
job:setValues()
local ok, err = job:validate(farmId)
if not ok then return finish(false, "Courseplay: " .. tostring(err)) end
g_currentMission.aiSystem:startJob(job, farmId)
finish(true)
if not generated then return finish(false, "Courseplay kunne ikke lave kursus") end
startWithCourse()
end)
end
handle.onBoundary = function(_, success, message)
+25 -3
View File
@@ -14,6 +14,9 @@ ADFieldJobs.PLAYER_DRIVING_KMH = 3
-- Courseplay kan efterlade hjørner på skæve marker: efter så mange færdige slå-ture går marken videre.
ADFieldJobs.MAX_MOW_PASSES = 2
ADFieldJobs.state = {fields = {}, fleet = {}, assignments = {}}
-- mark-id -> kopi af slåmaskinens Courseplay-kursus (kun i hukommelsen; efter genindlæsning hentes det
-- igen fra slåmaskinen, som CP selv gemmer kurset på)
ADFieldJobs.courses = {}
ADFieldJobs.timer = 0
ADFieldJobs.now = 0
ADFieldJobs.loaded = false
@@ -255,6 +258,18 @@ local function dispatch(adEnv, field, info, role)
note(field.id, {reason = false})
end
-- Slåkurset for marken: gemt kopi, ellers slåmaskinens nuværende kursus (efter genindlæsning).
local function mowCourse(adEnv, field)
if ADFieldJobs.courses[field.id] ~= nil then return ADFieldJobs.courses[field.id] end
if field.mowVehicleId == nil then return nil end
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
if ADRunsController.getVehicleId(vehicle) == field.mowVehicleId then
return ADCpBridge.getCourse(vehicle)
end
end
return nil
end
local function beginWork(adEnv, field, info, assignment)
local vehicle = assignment.vehicle
if assignment.role == "collector" then
@@ -283,20 +298,27 @@ local function beginWork(adEnv, field, info, assignment)
local point = info.points[1] or {x = info.x, z = info.z}
assignment.phase = "starting"
assignment.since = ADFieldJobs.now
local course = assignment.role ~= "mower" and mowCourse(adEnv, field) or nil
if assignment.role ~= "mower" and course == nil then
log(field.id, "intet slåkursus kendt — Courseplay laver et nyt kursus til %s", assignment.role)
end
local handle, err = ADCpBridge.start(vehicle, point.x, point.z, function(ok, reason)
if ok then
assignment.phase = "working"
assignment.since = ADFieldJobs.now
if assignment.role == "mower" then
note(field.id, {mowWidth = assignment.width})
note(field.id, {mowWidth = assignment.width, mowVehicleId = assignment.vehicleId})
local mowed = ADCpBridge.getCourse(vehicle)
local copied = mowed ~= nil and mowed.copy ~= nil and select(2, pcall(mowed.copy, mowed)) or mowed
ADFieldJobs.courses[field.id] = type(copied) == "table" and copied or mowed
end
log(field.id, "Courseplay startet (%s)", assignment.role)
log(field.id, "Courseplay startet (%s%s)", assignment.role, reason == "copied" and ", slåkursus kopieret" or "")
else
release(assignment)
note(field.id, {retryAt = ADFieldJobs.now + ADFieldModel.RETRY_MS, reason = {text = tostring(reason)}})
log(field.id, "Courseplay fejlede: %s", tostring(reason))
end
end)
end, course)
if handle == nil then
release(assignment)
log(field.id, "Courseplay kunne ikke startes: %s", tostring(err))
+3
View File
@@ -92,6 +92,7 @@ function ADFieldModel.start(field)
copy.retryAt = 0
copy.reason = nil
copy.mowWidth = nil
copy.mowVehicleId = nil
return copy
end
@@ -156,6 +157,7 @@ function ADFieldModel.toRecord(field)
id = field.id, stage = field.stage, mode = field.plan.mode, product = field.plan.product,
rake = field.plan.rake and 1 or 0, store = table.concat(field.plan.storeBuildingIds, " "),
mowWidth = field.mowWidth or 0,
mowVehicle = field.mowVehicleId or "",
}
end
@@ -167,5 +169,6 @@ function ADFieldModel.fromRecord(record)
field.plan.rake = record.rake == 1 or record.rake == true
for id in string.gmatch(record.store or "", "%S+") do table.insert(field.plan.storeBuildingIds, id) end
field.mowWidth = (record.mowWidth or 0) > 0 and record.mowWidth or nil
field.mowVehicleId = record.mowVehicle ~= nil and record.mowVehicle ~= "" and record.mowVehicle or nil
return field
end
+2 -1
View File
@@ -28,6 +28,7 @@ function ADFieldStorage.save(state)
xmlFile:setInt(key .. "#rake", record.rake)
xmlFile:setString(key .. "#store", record.store)
xmlFile:setFloat(key .. "#mowWidth", record.mowWidth)
xmlFile:setString(key .. "#mowVehicle", record.mowVehicle)
index = index + 1
end
local vehicleIndex = 0
@@ -51,7 +52,7 @@ function ADFieldStorage.load()
id = xmlFile:getInt(key .. "#id"), stage = xmlFile:getString(key .. "#stage"),
mode = xmlFile:getString(key .. "#mode"), product = xmlFile:getString(key .. "#product"),
rake = xmlFile:getInt(key .. "#rake"), store = xmlFile:getString(key .. "#store"),
mowWidth = xmlFile:getFloat(key .. "#mowWidth"),
mowWidth = xmlFile:getFloat(key .. "#mowWidth"), mowVehicle = xmlFile:getString(key .. "#mowVehicle"),
})
if field.id ~= nil then result.fields[field.id] = field end
end)
+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.21.6.0</version>
<version>1.22.0.0</version>
<title>
<en>AD Smart Pickup</en>
</title>