Files
fs25-adsmartpickup/FS25_ADSmartPickup/adCpBridge.lua
T
masterdraco 4c88118e56 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).
2026-09-25 23:25:55 +02:00

144 lines
6.2 KiB
Lua

-- AD Courseplay Bridge
-- Den eneste kode der rører Courseplay: start markarbejde på en mark (grænse -> kursus -> start, alt
-- async), og læs om et sæt arbejder. Opskriften er bevist i spillet i AI-Bonden (AIHelperGlue.startCP):
-- CP kalder grænse-callbacken to gange (først false ved fejl) — kun første kald tæller.
ADCpBridge = {}
ADCpBridge.SPECS = {"spec_mower", "spec_tedder", "spec_windrower", "spec_forageWagon"}
function ADCpBridge.isAvailable()
return AIJobType ~= nil and AIJobType.FIELDWORK_CP ~= nil
end
local function collect(vehicle, list)
list = list or {}
table.insert(list, vehicle)
if vehicle.getAttachedImplements ~= nil then
for _, implement in ipairs(vehicle:getAttachedImplements()) do
if implement.object ~= nil then collect(implement.object, list) end
end
end
return list
end
function ADCpBridge.getSpecs(vehicle)
local specs = {}
for _, object in ipairs(collect(vehicle)) do
for _, name in ipairs(ADCpBridge.SPECS) do
if object[name] ~= nil then specs[name] = true end
end
end
return specs
end
-- Variabel bredde (Unrealistic Pack m.fl.) først, som Courseplays WorkWidthUtil: AI-markørerne står på
-- grundbredden (læssevogn 2,4 m selv om den er sat til 40,8 m).
local function variableWidth(object)
if object.getVariableWorkWidth == nil then return nil end
local okLeft, left, _, leftValid = pcall(object.getVariableWorkWidth, object, true)
local okRight, right, _, rightValid = pcall(object.getVariableWorkWidth, object)
if okLeft and okRight and leftValid and rightValid and type(left) == "number" and type(right) == "number" then
return math.abs(left) + math.abs(right)
end
return nil
end
-- Courseplays egen bredde-indstilling (den i HUD'en) er den marken faktisk køres med.
local function courseplayWidth(vehicle)
if vehicle.getCourseGeneratorSettings == nil then return nil end
local ok, width = pcall(function() return vehicle:getCourseGeneratorSettings().workWidth:getValue() end)
if ok and type(width) == "number" and width > 0 then return width end
return nil
end
function ADCpBridge.getWorkWidth(vehicle)
local cpWidth = courseplayWidth(vehicle)
if cpWidth ~= nil then return cpWidth end
local best = 0
for _, object in ipairs(collect(vehicle)) do
local variable = variableWidth(object)
if variable ~= nil then
best = math.max(best, variable)
elseif object.getAIMarkers ~= nil then
pcall(function() if object.updateAIMarkerWidth ~= nil then object:updateAIMarkerWidth() end end)
local ok, _, _, _, _, width = pcall(object.getAIMarkers, object)
if ok and type(width) == "number" and width > best then best = width end
end
end
return best
end
function ADCpBridge.isWorking(vehicle)
if vehicle.getIsCpFieldWorkActive ~= nil and vehicle:getIsCpFieldWorkActive() then return true end
return vehicle.getIsAIActive ~= nil and vehicle:getIsAIActive() or false
end
-- 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
local farmId = vehicle:getOwnerFarmId()
local job = g_currentMission.aiJobTypeManager:createJob(AIJobType.FIELDWORK_CP)
if job == nil then return nil, "kunne ikke oprette Courseplay-job" end
job:applyCurrentState(vehicle, g_currentMission, farmId, false, false)
local vx, _, vz = getWorldTranslation(vehicle.rootNode)
local params = job.cpJobParameters
if params ~= nil and params.fieldPosition ~= nil then params.fieldPosition:setPosition(fieldX, fieldZ) end
if params ~= nil and params.startPosition ~= nil then params.startPosition:setPosition(vx, vz) end
job:setValues()
local handle = {cancelled = false, fired = false, finished = false}
local function finish(ok, reason)
if handle.finished then return end
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
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 generated then return finish(false, "Courseplay kunne ikke lave kursus") end
startWithCourse()
end)
end
handle.onBoundary = function(_, success, message)
if handle.fired then return end
handle.fired = true
if handle.cancelled then return end
if not success then return finish(false, "Courseplay fandt ikke markgrænsen: " .. tostring(message)) end
generateAndStart()
end
job:registerFieldBoundaryDetectionCallback(handle, handle.onBoundary)
local isValid, isRunning, message = job:detectFieldBoundary()
if isValid and not isRunning then
generateAndStart()
elseif not isRunning then
return nil, "Courseplay: " .. tostring(message)
end
return handle
end