fix(markarbejde): slåmarker regnes først klar i fuld højde; afbrudt slåning venter på genvækst i stedet for at klippe græs i mellemhøjde (F90) (v1.34.1.0)

This commit is contained in:
2026-09-27 08:57:32 +02:00
parent 50301b61b9
commit 307676004e
7 changed files with 67 additions and 8 deletions
+12 -3
View File
@@ -28,6 +28,9 @@ ADFieldJobs.loaded = false
ADFieldJobs.ACTIVE_PHASES = {driving = true, starting = true, waitingCourse = true, working = true}
-- Andel græs i mellemhøjde (høstbart, men halv ydelse) der får en afbrudt slåning til at vente.
ADFieldJobs.REGROW_RATIO = 0.1
-- ---- ren beslutning ----
-- Er afgrøden taget (trin med afgrøde)? Slåning: under 50 % står. Høst: marken er bar eller under 50 %.
@@ -89,6 +92,11 @@ function ADFieldJobs.decide(field, info, assignments, now, env)
local maxPasses = ADFieldJobs.MAX_PASSES * ADFieldModel.maxRigs(field.stage, field.plan)
if not isCropStage or finished >= maxPasses then return {action = "advance"} end
end
-- slåning uden maskine på en halvt slået mark: vent til genvæksten er fuldt udvokset igen
-- (et hjørne Courseplay efterlod i samme omgang, finished > 0, slås straks)
if field.stage == "mowing" and finished == 0 and info ~= nil and (info.immatureRatio or 0) > ADFieldJobs.REGROW_RATIO then
return {action = "wait", reason = "regrowing"}
end
if not hasMarker then return {action = "wait"} end
if (field.retryAt or 0) > now then return {action = "none"} end
if raining and ADFieldModel.isWeatherSensitive(field.stage, field.plan, kind) then
@@ -262,9 +270,10 @@ local function stepField(adEnv, info, env)
ADFieldJobs.notify(string.format("F%d %s", info.id, g_i18n ~= nil and g_i18n:getText("spu_field_notice_done") or "done"), false)
end
ADFieldJobs.save()
elseif decision.action == "wait" and decision.reason == "rain" then
if field.reason == nil or field.reason.key ~= "spu_field_reason_rain" then
ADFieldJobs.note(info.id, {reason = {key = "spu_field_reason_rain"}})
elseif decision.action == "wait" and decision.reason ~= nil then
local key = "spu_field_reason_" .. decision.reason
if field.reason == nil or field.reason.key ~= key then
ADFieldJobs.note(info.id, {reason = {key = key}})
end
elseif decision.action == "dispatch" then
ADFieldWork.dispatch(adEnv, field, info, decision)
+34 -4
View File
@@ -59,6 +59,24 @@ function ADFields.growthPhase(state, fruit)
return "cut"
end
-- Fuldt udvokset stadie for en slåafgrøde: græs er "høstbart" allerede i mellemhøjde (halv ydelse,
-- Dakota-græs: greenMiddle 3 < harvestReady 4 < harvestReady2 5), så slåning venter til stadiet efter
-- det første høstbare, når afgrøden har flere. nil = ukendte grænser (ingen ekstra krav).
function ADFields.primeState(fruit)
if fruit == nil then return nil end
local minReady = fruit.minHarvestingGrowthState or fruit.minHarvestGrowthState
if minReady == nil then return nil end
local maxReady = fruit.maxHarvestingGrowthState or fruit.maxHarvestGrowthState or minReady
if maxReady > minReady then return minReady + 1 end
return minReady
end
-- Tæller punktets klar-pixels? Kun når stadiet (4. værdi fra getFruitArea) er fuldt udvokset.
function ADFields.isPrime(growthState, prime)
if prime == nil or type(growthState) ~= "number" or growthState <= 0 then return true end
return growthState >= prime
end
-- Vokser marken? Fasen vinder; ukendt fase -> der er voksende afgrøde (getFruitArea) og den er ikke klar.
function ADFields.isGrowing(phase, anyPixels, readyRatio)
if phase ~= nil then return phase == "growing" end
@@ -290,7 +308,7 @@ end
local function newScan(adEnv, entry)
local field, fieldId = entry.field, entry.id
local scan = {id = fieldId, queue = {}, head = 1, tail = 0, points = {}, fruitVotes = {},
anySum = 0, readySum = 0, soil = {fert = {0, 0}, lime = {0, 0}, plowLevel = {0, 0}, weed = {0, 0}}}
anySum = 0, readySum = 0, immatureSum = 0, soil = {fert = {0, 0}, lime = {0, 0}, plowLevel = {0, 0}, weed = {0, 0}}}
local info = {id = fieldId, field = field, points = scan.points, verts = {}, mowable = false, readyRatio = 0}
scan.info = info
-- 1) polygon og kandidatpunkter (centroid + halvvejs mod op til 8 hjørner)
@@ -348,14 +366,25 @@ function ADFields.scanPerFruit(scan)
local fruitIndex = info.fruitIndex
local settings = missionSettings()
scan.settings = settings
-- slåafgrøder: genvækst i mellemhøjde tæller ikke som klar (in-game 27/9: halvt slået F90 blev
-- klippet igen i mellemhøjde)
local prime = nil
if fruitIndex ~= nil and ADFields.getMowable()[fruitIndex] ~= nil then
prime = ADFields.primeState(g_fruitTypeManager:getFruitTypeByIndex(fruitIndex))
end
for _, point in ipairs(scan.points) do
push(scan, function()
local x, z = point.x, point.z
if fruitIndex ~= nil then
local okA, _, anyPixels = pcall(FSDensityMapUtil.getFruitArea, fruitIndex, x - 2, z - 2, x + 2, z, x, z + 2, true, true)
if okA and anyPixels then scan.anySum = scan.anySum + anyPixels end
local okA, _, anyPixels, _, pointState = pcall(FSDensityMapUtil.getFruitArea, fruitIndex, x - 2, z - 2, x + 2, z, x, z + 2, true, true)
if okA and anyPixels then
scan.anySum = scan.anySum + anyPixels
if not ADFields.isPrime(pointState, prime) then scan.immatureSum = scan.immatureSum + anyPixels end
end
local okR, _, readyPixels = pcall(FSDensityMapUtil.getFruitArea, fruitIndex, x - 2, z - 2, x + 2, z, x, z + 2, false, false)
if okR and readyPixels then scan.readySum = scan.readySum + readyPixels end
if okR and readyPixels and ADFields.isPrime(okA and pointState or nil, prime) then
scan.readySum = scan.readySum + readyPixels
end
end
end)
push(scan, function()
@@ -387,6 +416,7 @@ local function finishScan(adEnv, scan)
local fruit = nil
if info.fruitIndex ~= nil then
info.readyRatio = scan.anySum > 0 and scan.readySum / scan.anySum or 0
info.immatureRatio = scan.anySum > 0 and scan.immatureSum / scan.anySum or 0
info.anyPixels = scan.anySum
fruit = g_fruitTypeManager:getFruitTypeByIndex(info.fruitIndex)
info.fruitName = fruit ~= nil and fruit.name or nil
+2
View File
@@ -60,6 +60,7 @@
<text name="spu_field_reasonShort_noSowFruit" text="vælg afgrøde"/>
<text name="spu_field_reasonShort_notEnough" text="for få ledige"/>
<text name="spu_field_reasonShort_notPlantable" text="ikke såtid nu"/>
<text name="spu_field_reasonShort_regrowing" text="venter på genvækst"/>
<text name="spu_field_reasonShort_rain" text="venter på tørvejr"/>
<text name="spu_field_reasonShort_text" text="se detaljer"/>
<text name="spu_field_reason_allBusy" text="venter på ledig %s"/>
@@ -173,6 +174,7 @@
<text name="spu_field_unloaders" text="Aflæsningsvogne under høst"/>
<text name="spu_field_weed" text="Bekæmp ukrudt"/>
<text name="spu_field_notice_done" text="er færdig"/>
<text name="spu_field_reason_regrowing" text="venter på at græsset vokser helt ud igen"/>
<text name="spu_field_reason_rain" text="venter på tørvejr"/>
<text name="spu_field_target" text="Afgrøde på marken (moden passer resten)"/>
<text name="spu_field_target_none" text="Ingen — planlæg selv"/>
+2
View File
@@ -60,6 +60,7 @@
<text name="spu_field_reasonShort_noSowFruit" text="choose crop"/>
<text name="spu_field_reasonShort_notEnough" text="too few free"/>
<text name="spu_field_reasonShort_notPlantable" text="not sowing time"/>
<text name="spu_field_reasonShort_regrowing" text="waiting for regrowth"/>
<text name="spu_field_reasonShort_rain" text="waiting for dry weather"/>
<text name="spu_field_reasonShort_text" text="see details"/>
<text name="spu_field_reason_allBusy" text="waiting for a free %s"/>
@@ -173,6 +174,7 @@
<text name="spu_field_unloaders" text="Unloading trailers during harvest"/>
<text name="spu_field_weed" text="Control weeds"/>
<text name="spu_field_notice_done" text="is done"/>
<text name="spu_field_reason_regrowing" text="waiting for the regrowth to reach full height"/>
<text name="spu_field_reason_rain" text="waiting for dry weather"/>
<text name="spu_field_target" text="Crop on the field (the mod handles the rest)"/>
<text name="spu_field_target_none" text="None — plan it yourself"/>
+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.34.0.0</version>
<version>1.34.1.0</version>
<title>
<en>AD Smart Pickup</en>
</title>