diff --git a/FS25_ADSmartPickup/adFieldView.lua b/FS25_ADSmartPickup/adFieldView.lua
index 6addb3c..650ee2a 100644
--- a/FS25_ADSmartPickup/adFieldView.lua
+++ b/FS25_ADSmartPickup/adFieldView.lua
@@ -37,3 +37,12 @@ function ADFieldView.soilParts(info)
if (info.weed or 0) >= ADFieldModel.WEED_MIN then table.insert(parts, "weed") end
return parts
end
+
+-- Afgrødekolonnen: høstet mark = "stub (Hvede)", bar mark = "bar jord", ellers afgrøden.
+function ADFieldView.cropText(info, getText)
+ if info.kind == "bare" and info.stubbleOf ~= nil then
+ return string.format(getText("spu_field_stubble"), tostring(info.stubbleOf))
+ end
+ if info.kind == "bare" then return getText("spu_field_bare") end
+ return tostring(info.cropTitle or "-")
+end
diff --git a/FS25_ADSmartPickup/adFields.lua b/FS25_ADSmartPickup/adFields.lua
index 96582d4..e64c57d 100644
--- a/FS25_ADSmartPickup/adFields.lua
+++ b/FS25_ADSmartPickup/adFields.lua
@@ -153,6 +153,15 @@ end
ADFields.SAMPLE_DIRECTIONS = 16
+-- field.fieldState (FS25, bekræftet i AI-Bonde via aifProbe): {fruitIndex|nil, growthState} eller nil
+-- når spillet ikke har tilstanden (så bruges punkt-afstemningen).
+function ADFields.readFieldState(field)
+ local state = field ~= nil and field.fieldState or nil
+ if type(state) ~= "table" or type(state.fruitTypeIndex) ~= "number" then return nil end
+ local fruitIndex = state.fruitTypeIndex > 0 and state.fruitTypeIndex or nil
+ return {fruitIndex = fruitIndex, growthState = fruitIndex ~= nil and state.growthState or nil}
+end
+
-- Markens omrids som {{x, z}, ...}. FS25: field:getDensityMapPolygon():getVerticesList() (flad liste
-- x1, z1, x2, z2 ... — som Courseplay); ældre: polygonPoints (noder). Tom liste hvis intet findes.
function ADFields.readPolygon(field)
@@ -243,7 +252,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 = {}, growthVotes = {},
+ 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}}}
local info = {id = fieldId, field = field, points = scan.points, verts = {}, mowable = false, readyRatio = 0}
scan.info = info
@@ -289,7 +298,15 @@ end
-- Når afgrøden kendes: klar-andel, vækststadie og jord pr. punkt (én opgave pr. punkt).
function ADFields.scanPerFruit(scan)
local info = scan.info
- info.fruitIndex = winner(scan.fruitVotes)
+ -- spillets egen marktilstand (som fields.xml) er sandheden; punkt-afstemningen er reserve.
+ -- (getFieldDataAtWorldPosition giver isOnField, densityBits, groundType — IKKE vækststadie)
+ local state = ADFields.readFieldState(info.field)
+ info.growthState = state ~= nil and state.growthState or nil
+ if state ~= nil then
+ info.fruitIndex = state.fruitIndex
+ else
+ info.fruitIndex = winner(scan.fruitVotes)
+ end
local fruitIndex = info.fruitIndex
local settings = missionSettings()
scan.settings = settings
@@ -301,11 +318,6 @@ function ADFields.scanPerFruit(scan)
if okA and anyPixels then scan.anySum = scan.anySum + anyPixels 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
- local okG, _, state = pcall(function()
- local y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 1, z)
- return FSDensityMapUtil.getFieldDataAtWorldPosition(x, y, z)
- end)
- if okG and type(state) == "number" then vote(scan.growthVotes, state) end
end
end)
push(scan, function()
@@ -345,11 +357,12 @@ local function finishScan(adEnv, scan)
info.cropTitle = fillType ~= nil and fillType.title or (fruit ~= nil and fruit.name) or "?"
end
info.kind = ADFields.classify(info.fruitIndex, info.mowable, info.readyRatio)
- info.phase = fruit ~= nil and ADFields.growthPhase(winner(scan.growthVotes), fruit) or nil
+ info.phase = fruit ~= nil and ADFields.growthPhase(info.growthState, fruit) or nil
info.growing = info.fruitIndex ~= nil and ADFields.isGrowing(info.phase, info.anyPixels, info.readyRatio)
-- høstet stub eller visnet afgrøde er i praksis en bar mark (klargøring/såning)
if info.kind == "harvest" and (info.phase == "cut" or info.phase == "withered" or info.phase == "none") then
info.kind = "bare"
+ info.stubbleOf = info.phase == "cut" and info.cropTitle or nil
end
local settings = scan.settings or missionSettings()
for key, sum in pairs(scan.soil) do
diff --git a/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua
index 2651aed..d0f5fe2 100644
--- a/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua
+++ b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua
@@ -109,7 +109,7 @@ function SmartPickupFrame:fieldCells(row)
table.insert(names, ADRuns.vehicleLabel(assignment.vehicle))
end
local name = string.format("%s%sF%d", info.id == self.selectedFieldId and "> " or "", info.markerId == nil and "! " or "", info.id)
- local crop = info.kind == "bare" and self.i18n:getText("spu_field_bare") or (info.cropTitle or "-")
+ local crop = ADFieldView.cropText(info, function(key) return self.i18n:getText(key) end)
return {
name, crop, self:fieldPlanText(field, info),
self.i18n:getText(field.plan.mode == "auto" and "spu_field_mode_auto" or "spu_field_mode_manual"),
@@ -190,7 +190,7 @@ function SmartPickupFrame:fillFieldDetail(adEnv, info)
local field = ADFieldJobs.getField(info.id)
local plan = field.plan
local yesNo = {i18n:getText("ui_no"), i18n:getText("ui_yes")}
- local crop = info.kind == "bare" and i18n:getText("spu_field_bare") or tostring(info.cropTitle or "-")
+ local crop = ADFieldView.cropText(info, function(key) return i18n:getText(key) end)
self:addTextRow(string.format(i18n:getText("spu_field_section"), info.id, crop))
local targetTexts, targetValues = self:sowFruitChoices("spu_field_target_none")
self:addChoiceRow("fieldTarget", i18n:getText("spu_field_target"), targetTexts, targetValues, plan.targetFruit or "")
diff --git a/FS25_ADSmartPickup/l10n/l10n_da.xml b/FS25_ADSmartPickup/l10n/l10n_da.xml
index 1067ef8..82f8a75 100644
--- a/FS25_ADSmartPickup/l10n/l10n_da.xml
+++ b/FS25_ADSmartPickup/l10n/l10n_da.xml
@@ -94,6 +94,7 @@
+
diff --git a/FS25_ADSmartPickup/l10n/l10n_en.xml b/FS25_ADSmartPickup/l10n/l10n_en.xml
index e916ab2..75c98da 100644
--- a/FS25_ADSmartPickup/l10n/l10n_en.xml
+++ b/FS25_ADSmartPickup/l10n/l10n_en.xml
@@ -94,6 +94,7 @@
+
diff --git a/FS25_ADSmartPickup/modDesc.xml b/FS25_ADSmartPickup/modDesc.xml
index 5194961..4125de9 100644
--- a/FS25_ADSmartPickup/modDesc.xml
+++ b/FS25_ADSmartPickup/modDesc.xml
@@ -1,7 +1,7 @@
masterdraco
- 1.28.6.0
+ 1.28.7.0
AD Smart Pickup
diff --git a/tests/test_adFieldView.lua b/tests/test_adFieldView.lua
index 518bd02..d677f26 100644
--- a/tests/test_adFieldView.lua
+++ b/tests/test_adFieldView.lua
@@ -38,5 +38,12 @@ local parts = V.soilParts({lime = 0.2, fert = 1, fertMax = 2, weed = 3, needs =
check("V5 dele", table.concat(parts, ","), "lime,plow,fert,weed")
check("V5 intet", #V.soilParts({lime = 2, fert = 2, fertMax = 2, weed = 0, needs = {}}), 0)
+-- cropText: høstet = stub (afgrøde), bar = bar jord, ellers afgrøden
+local texts = {spu_field_stubble = "stub (%s)", spu_field_bare = "bar jord"}
+local function T(key) return texts[key] end
+check("FVcrop stub", ADFieldView.cropText({kind = "bare", stubbleOf = "Hvede", cropTitle = "Hvede"}, T), "stub (Hvede)")
+check("FVcrop bar", ADFieldView.cropText({kind = "bare"}, T), "bar jord")
+check("FVcrop afgrøde", ADFieldView.cropText({kind = "harvest", cropTitle = "Majs"}, T), "Majs")
+
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1)
diff --git a/tests/test_adFieldsPolygon.lua b/tests/test_adFieldsPolygon.lua
index 41db33f..8e171d5 100644
--- a/tests/test_adFieldsPolygon.lua
+++ b/tests/test_adFieldsPolygon.lua
@@ -15,7 +15,7 @@ local MAIZE = 10
function getWorldTranslation() return 0, 0, 0 end
function getTerrainHeightAtWorldPos() return 0 end
-- markskiltet står i marken, men ved en stribe uden afgrøde (x > 1400)
-local function cropAt(x) return x <= 1400 and MAIZE or nil end
+function cropAt(x) return x <= 1400 and MAIZE or nil end
FSDensityMapUtil = {
getFieldDataAtWorldPosition = function() return 1, 2 end,
getFruitTypeIndexAtWorldPos = function(x, z) return cropAt(x) end,
@@ -56,5 +56,31 @@ check("PG3 majsen findes trods skiltet på bar stribe", info and info.fruitName,
check("PG4 ikke bar mark", info and info.kind, "harvest")
check("PG5 markør ved kanten findes (afstand til omridset)", info and info.markerId, 900)
check("PG6 afstand = til kanten", info and info.markerDistance, 5)
+
+-- PG7-9: field.fieldState er spillets sandhed (fields.xml: MAIZE growthState 2); jord-bits fra
+-- getFieldDataAtWorldPosition (2. værdi) er IKKE vækststadie. Høstet mark (cutState) = bar, vist som stub.
+
+field.fieldState = {fruitTypeIndex = MAIZE, growthState = 2}
+FSDensityMapUtil.getFieldDataAtWorldPosition = function() return true, 0 end -- jord-bits 0 lignede "ingen vækst"
+local function rescan()
+ ADFields.cache, ADFields.listCache, ADFields.activeScan, ADFields.lastScanStart = {}, nil, nil, nil
+ for _ = 1, 2000 do
+ if ADFields.getInfo(108) ~= nil then break end
+ ADFields.scanStep(adEnv, 1, now)
+ now = now + 16
+ end
+ return ADFields.getInfo(108)
+end
+info = rescan()
+check("PG7 majs i vækst (fieldState), ikke bar", info and info.kind, "harvest")
+check("PG7 fase vokser", info and info.phase, "growing")
+field.fieldState = {fruitTypeIndex = MAIZE, growthState = 9}
+info = rescan()
+check("PG8 høstet (cutState) = bar", info and info.kind, "bare")
+check("PG8 stub af majs", info and info.stubbleOf, "Majs")
+field.fieldState = {fruitTypeIndex = 0, growthState = 0}
+cropAt = function() return nil end
+info = rescan()
+check("PG9 ingen afgrøde = bar uden stub", info and info.kind .. "/" .. tostring(info.stubbleOf), "bare/nil")
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1)
diff --git a/tests/test_adFieldsScan.lua b/tests/test_adFieldsScan.lua
index febcd97..796f3b5 100644
--- a/tests/test_adFieldsScan.lua
+++ b/tests/test_adFieldsScan.lua
@@ -17,7 +17,7 @@ function getWorldTranslation(node) local p = nodes[node]; return p[1], 0, p[2] e
function getTerrainHeightAtWorldPos() return 0 end
local calls = 0
FSDensityMapUtil = {
- getFieldDataAtWorldPosition = function() calls = calls + 1; return 1, 6 end, -- på mark, vækststadie 6
+ getFieldDataAtWorldPosition = function() calls = calls + 1; return true, 170 end, -- på mark (2. værdi = jord-bits, IKKE vækst)
getFruitTypeIndexAtWorldPos = function() calls = calls + 1; return WHEAT end,
getFruitArea = function(_, _, _, _, _, _, _, any) calls = calls + 1; return 0, any and 10 or 10 end,
}
@@ -30,7 +30,9 @@ g_fruitTypeManager = {
}
g_fillTypeManager = {getConverterDataByName = function() return {} end, getFillTypeNameByIndex = function() return "X" end}
g_farmlandManager = {getFarmlandOwner = function() return 1 end}
-local field = {getId = function() return 7 end, farmland = {id = 70}, polygonPoints = {101, 102, 103, 104}, posX = 50, posZ = 50}
+-- spillets egen marktilstand (field.fieldState, som fields.xml): afgrøde + vækststadie
+local field = {getId = function() return 7 end, farmland = {id = 70}, polygonPoints = {101, 102, 103, 104}, posX = 50, posZ = 50,
+ fieldState = {fruitTypeIndex = WHEAT, growthState = 6}}
g_fieldManager = {getFields = function() return {field} end}
g_currentMission = {terrainRootNode = 1, missionInfo = {}, fieldGroundSystem = {
getDensityMapData = function() return 1, 0, 2 end, getMaxValue = function() return 2 end}}