feat(marker): smalle standardmaskiner — vender/river i egen bredde, læssevogn følger rivens kursus; Riv også til ensilage (v1.23.0.0)

Brugerspørgsmål 25/9: få standardredskaber har 40,8 m. Vender og river kører hele marken i deres egen
bredde; efter riv ligger skåret midt i banen, så læssevognen kopierer rivens kursus uden breddekrav.
Uden riv kræver læssevognen stadig slåbredden (nu med hint 'sæt Riv til').
This commit is contained in:
2026-09-25 23:31:46 +02:00
parent 4c88118e56
commit ba88eb5f99
11 changed files with 105 additions and 42 deletions
+30 -15
View File
@@ -14,8 +14,8 @@ 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. -- 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.MAX_MOW_PASSES = 2
ADFieldJobs.state = {fields = {}, fleet = {}, assignments = {}} ADFieldJobs.state = {fields = {}, fleet = {}, assignments = {}}
-- mark-id -> kopi af slåmaskinens Courseplay-kursus (kun i hukommelsen; efter genindlæsning hentes det -- mark-id -> {mower = kursus, rake = kursus}: kopier af slåmaskinens/rivens Courseplay-kursus (kun i
-- igen fra slåmaskinen, som CP selv gemmer kurset på) -- hukommelsen; efter genindlæsning hentes de fra maskinen, som CP selv gemmer kurset på)
ADFieldJobs.courses = {} ADFieldJobs.courses = {}
ADFieldJobs.timer = 0 ADFieldJobs.timer = 0
ADFieldJobs.now = 0 ADFieldJobs.now = 0
@@ -246,7 +246,7 @@ end
local function dispatch(adEnv, field, info, role) local function dispatch(adEnv, field, info, role)
local candidates = ADFieldJobs.getRigs(adEnv) local candidates = ADFieldJobs.getRigs(adEnv)
local rig, reason, args = ADFieldFleet.pick(candidates, role, info.x, info.z, field.mowWidth) local rig, reason, args = ADFieldFleet.pick(candidates, role, info.x, info.z, ADFieldModel.requiredWidth(field, role))
if rig == nil then if rig == nil then
note(field.id, {reason = {key = "spu_field_reason_" .. reason, role = role, args = args}}) note(field.id, {reason = {key = "spu_field_reason_" .. reason, role = role, args = args}})
return return
@@ -258,18 +258,32 @@ local function dispatch(adEnv, field, info, role)
note(field.id, {reason = false}) note(field.id, {reason = false})
end end
-- Slåkurset for marken: gemt kopi, ellers slåmaskinens nuværende kursus (efter genindlæsning). -- Kurset som et trin skal genbruge ("mower"/"rake"): gemt kopi, ellers maskinens nuværende kursus
local function mowCourse(adEnv, field) -- (efter genindlæsning).
if ADFieldJobs.courses[field.id] ~= nil then return ADFieldJobs.courses[field.id] end local function sourceCourse(adEnv, field, source)
if field.mowVehicleId == nil then return nil end local saved = ADFieldJobs.courses[field.id]
if saved ~= nil and saved[source] ~= nil then return saved[source] end
local vehicleId = source == "rake" and field.rakeVehicleId or field.mowVehicleId
if vehicleId == nil then return nil end
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
if ADRunsController.getVehicleId(vehicle) == field.mowVehicleId then if ADRunsController.getVehicleId(vehicle) == vehicleId then
return ADCpBridge.getCourse(vehicle) return ADCpBridge.getCourse(vehicle)
end end
end end
return nil return nil
end end
local function rememberCourse(field, source, vehicle, vehicleId)
local course = ADCpBridge.getCourse(vehicle)
local ok, copy = false, nil
if course ~= nil and course.copy ~= nil then ok, copy = pcall(course.copy, course) end
ADFieldJobs.courses[field.id] = ADFieldJobs.courses[field.id] or {}
ADFieldJobs.courses[field.id][source] = ok and copy or course
if source == "rake" then
note(field.id, {rakeVehicleId = vehicleId})
end
end
local function beginWork(adEnv, field, info, assignment) local function beginWork(adEnv, field, info, assignment)
local vehicle = assignment.vehicle local vehicle = assignment.vehicle
if assignment.role == "collector" then if assignment.role == "collector" then
@@ -298,9 +312,10 @@ local function beginWork(adEnv, field, info, assignment)
local point = info.points[1] or {x = info.x, z = info.z} local point = info.points[1] or {x = info.x, z = info.z}
assignment.phase = "starting" assignment.phase = "starting"
assignment.since = ADFieldJobs.now assignment.since = ADFieldJobs.now
local course = assignment.role ~= "mower" and mowCourse(adEnv, field) or nil local source = ADFieldModel.courseSource(field, assignment.role)
if assignment.role ~= "mower" and course == nil then local course = source ~= nil and sourceCourse(adEnv, field, source) or nil
log(field.id, "intet slåkursus kendt — Courseplay laver et nyt kursus til %s", assignment.role) if source ~= nil and course == nil then
log(field.id, "intet %s-kursus kendt — Courseplay laver et nyt kursus til %s", source, assignment.role)
end end
local handle, err = ADCpBridge.start(vehicle, point.x, point.z, function(ok, reason) local handle, err = ADCpBridge.start(vehicle, point.x, point.z, function(ok, reason)
if ok then if ok then
@@ -308,11 +323,11 @@ local function beginWork(adEnv, field, info, assignment)
assignment.since = ADFieldJobs.now assignment.since = ADFieldJobs.now
if assignment.role == "mower" then if assignment.role == "mower" then
note(field.id, {mowWidth = assignment.width, mowVehicleId = assignment.vehicleId}) note(field.id, {mowWidth = assignment.width, mowVehicleId = assignment.vehicleId})
local mowed = ADCpBridge.getCourse(vehicle) rememberCourse(field, "mower", vehicle, assignment.vehicleId)
local copied = mowed ~= nil and mowed.copy ~= nil and select(2, pcall(mowed.copy, mowed)) or mowed elseif assignment.role == "rake" then
ADFieldJobs.courses[field.id] = type(copied) == "table" and copied or mowed rememberCourse(field, "rake", vehicle, assignment.vehicleId)
end end
log(field.id, "Courseplay startet (%s%s)", assignment.role, reason == "copied" and ", slåkursus kopieret" or "") log(field.id, "Courseplay startet (%s%s)", assignment.role, reason == "copied" and (", " .. tostring(source) .. "-kursus kopieret") or "")
else else
release(assignment) release(assignment)
note(field.id, {retryAt = ADFieldJobs.now + ADFieldModel.RETRY_MS, reason = {text = tostring(reason)}}) note(field.id, {retryAt = ADFieldJobs.now + ADFieldModel.RETRY_MS, reason = {text = tostring(reason)}})
+24 -5
View File
@@ -38,14 +38,30 @@ function ADFieldModel.newField(id)
} }
end end
-- Hø vendes; Riv kan vælges til både hø og ensilage (samler skårene midt i rivens baner, så også
-- smalle standard-læssevogne kan tage dem).
function ADFieldModel.workStages(plan) function ADFieldModel.workStages(plan)
if plan.product == "hay" then local stages = {"mowing"}
if plan.rake then if plan.product == "hay" then table.insert(stages, "tedding") end
return {"mowing", "tedding", "raking", "collecting"} if plan.rake then table.insert(stages, "raking") end
table.insert(stages, "collecting")
return stages
end end
return {"mowing", "tedding", "collecting"}
-- Krævet bredde for et sæt: kun læssevognen uden riv skal dække slåmaskinens baner. Vender og river kører
-- hele marken i deres egen bredde; efter riv ligger skåret midt i banen, så vognens bredde er ligegyldig.
function ADFieldModel.requiredWidth(field, role)
if role == "collector" and not field.plan.rake then
return field.mowWidth
end end
return {"mowing", "collecting"} return nil
end
-- Hvilket tidligere kursus sættet skal køre: læssevognen følger skårene (rivens kursus, ellers
-- slåmaskinens); de andre laver deres eget i deres egen bredde.
function ADFieldModel.courseSource(field, role)
if role ~= "collector" then return nil end
return field.plan.rake and "rake" or "mower"
end end
function ADFieldModel.roleFor(stage) function ADFieldModel.roleFor(stage)
@@ -93,6 +109,7 @@ function ADFieldModel.start(field)
copy.reason = nil copy.reason = nil
copy.mowWidth = nil copy.mowWidth = nil
copy.mowVehicleId = nil copy.mowVehicleId = nil
copy.rakeVehicleId = nil
return copy return copy
end end
@@ -158,6 +175,7 @@ function ADFieldModel.toRecord(field)
rake = field.plan.rake and 1 or 0, store = table.concat(field.plan.storeBuildingIds, " "), rake = field.plan.rake and 1 or 0, store = table.concat(field.plan.storeBuildingIds, " "),
mowWidth = field.mowWidth or 0, mowWidth = field.mowWidth or 0,
mowVehicle = field.mowVehicleId or "", mowVehicle = field.mowVehicleId or "",
rakeVehicle = field.rakeVehicleId or "",
} }
end end
@@ -170,5 +188,6 @@ function ADFieldModel.fromRecord(record)
for id in string.gmatch(record.store or "", "%S+") do table.insert(field.plan.storeBuildingIds, id) end 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.mowWidth = (record.mowWidth or 0) > 0 and record.mowWidth or nil
field.mowVehicleId = record.mowVehicle ~= nil and record.mowVehicle ~= "" and record.mowVehicle or nil field.mowVehicleId = record.mowVehicle ~= nil and record.mowVehicle ~= "" and record.mowVehicle or nil
field.rakeVehicleId = record.rakeVehicle ~= nil and record.rakeVehicle ~= "" and record.rakeVehicle or nil
return field return field
end end
+2
View File
@@ -29,6 +29,7 @@ function ADFieldStorage.save(state)
xmlFile:setString(key .. "#store", record.store) xmlFile:setString(key .. "#store", record.store)
xmlFile:setFloat(key .. "#mowWidth", record.mowWidth) xmlFile:setFloat(key .. "#mowWidth", record.mowWidth)
xmlFile:setString(key .. "#mowVehicle", record.mowVehicle) xmlFile:setString(key .. "#mowVehicle", record.mowVehicle)
xmlFile:setString(key .. "#rakeVehicle", record.rakeVehicle)
index = index + 1 index = index + 1
end end
local vehicleIndex = 0 local vehicleIndex = 0
@@ -53,6 +54,7 @@ function ADFieldStorage.load()
mode = xmlFile:getString(key .. "#mode"), product = xmlFile:getString(key .. "#product"), mode = xmlFile:getString(key .. "#mode"), product = xmlFile:getString(key .. "#product"),
rake = xmlFile:getInt(key .. "#rake"), store = xmlFile:getString(key .. "#store"), rake = xmlFile:getInt(key .. "#rake"), store = xmlFile:getString(key .. "#store"),
mowWidth = xmlFile:getFloat(key .. "#mowWidth"), mowVehicle = xmlFile:getString(key .. "#mowVehicle"), mowWidth = xmlFile:getFloat(key .. "#mowWidth"), mowVehicle = xmlFile:getString(key .. "#mowVehicle"),
rakeVehicle = xmlFile:getString(key .. "#rakeVehicle"),
}) })
if field.id ~= nil then result.fields[field.id] = field end if field.id ~= nil then result.fields[field.id] = field end
end) end)
@@ -36,7 +36,7 @@ end
function SmartPickupFrame:fieldPlanText(field) function SmartPickupFrame:fieldPlanText(field)
local text = self.i18n:getText(field.plan.product == "hay" and "spu_field_plan_hay" or "spu_field_plan_silage") local text = self.i18n:getText(field.plan.product == "hay" and "spu_field_plan_hay" or "spu_field_plan_silage")
if field.plan.product == "hay" and field.plan.rake then if field.plan.rake then
text = text .. " + " .. self.i18n:getText("spu_field_plan_rake") text = text .. " + " .. self.i18n:getText("spu_field_plan_rake")
end end
return text return text
@@ -102,9 +102,7 @@ function SmartPickupFrame:fillFieldDetail(adEnv, info)
local isHay = field.plan.product == "hay" local isHay = field.plan.product == "hay"
self:addToggleRow("fieldProduct", i18n:getText("spu_field_plan"), {i18n:getText("spu_field_plan_silage"), i18n:getText("spu_field_plan_hay")}, isHay) self:addToggleRow("fieldProduct", i18n:getText("spu_field_plan"), {i18n:getText("spu_field_plan_silage"), i18n:getText("spu_field_plan_hay")}, isHay)
self:addToggleRow("fieldMode", i18n:getText("spu_field_mode"), {i18n:getText("spu_field_mode_manual"), i18n:getText("spu_field_mode_auto")}, field.plan.mode == "auto") self:addToggleRow("fieldMode", i18n:getText("spu_field_mode"), {i18n:getText("spu_field_mode_manual"), i18n:getText("spu_field_mode_auto")}, field.plan.mode == "auto")
if isHay then
self:addToggleRow("fieldRake", i18n:getText("spu_field_rake"), {i18n:getText("ui_no"), i18n:getText("ui_yes")}, field.plan.rake == true) self:addToggleRow("fieldRake", i18n:getText("spu_field_rake"), {i18n:getText("ui_no"), i18n:getText("ui_yes")}, field.plan.rake == true)
end
if info.markerId ~= nil then if info.markerId ~= nil then
self:addTextRow(string.format(i18n:getText("spu_field_marker"), tostring(info.markerName), info.markerDistance or 0)) self:addTextRow(string.format(i18n:getText("spu_field_marker"), tostring(info.markerName), info.markerDistance or 0))
else else
+2 -2
View File
@@ -53,7 +53,7 @@
<text name="spu_field_reason_noRig" text="ingen %s med flueben i markflåden"/> <text name="spu_field_reason_noRig" text="ingen %s med flueben i markflåden"/>
<text name="spu_field_reason_allBusy" text="venter på ledig %s"/> <text name="spu_field_reason_allBusy" text="venter på ledig %s"/>
<text name="spu_field_reason_tooWide" text="%s for bred: %.1f m &gt; %.0f m (Courseplay)"/> <text name="spu_field_reason_tooWide" text="%s for bred: %.1f m &gt; %.0f m (Courseplay)"/>
<text name="spu_field_reason_tooNarrow" text="%s for smal: %.1f m &lt; slåbredde %.1f m"/> <text name="spu_field_reason_tooNarrow" text="%s for smal: %.1f m &lt; slåbredde %.1f m — sæt Riv til eller brug en bredere"/>
<text name="spu_field_role_mower" text="slåmaskine"/> <text name="spu_field_role_mower" text="slåmaskine"/>
<text name="spu_field_role_tedder" text="vender"/> <text name="spu_field_role_tedder" text="vender"/>
<text name="spu_field_role_rake" text="river"/> <text name="spu_field_role_rake" text="river"/>
@@ -74,7 +74,7 @@
<text name="spu_field_section" text="— Mark F%d: %s —"/> <text name="spu_field_section" text="— Mark F%d: %s —"/>
<text name="spu_field_plan" text="Plan"/> <text name="spu_field_plan" text="Plan"/>
<text name="spu_field_mode" text="Kørsel"/> <text name="spu_field_mode" text="Kørsel"/>
<text name="spu_field_rake" text="Riv høet sammen før opsamling"/> <text name="spu_field_rake" text="Riv skårene sammen før opsamling (gør smalle læssevogne brugbare)"/>
<text name="spu_field_marker" text=" Markør %s, %.0f m fra marken"/> <text name="spu_field_marker" text=" Markør %s, %.0f m fra marken"/>
<text name="spu_field_mowWidth" text=" Slået med %.1f m — opsamling skal være mindst lige så bred"/> <text name="spu_field_mowWidth" text=" Slået med %.1f m — opsamling skal være mindst lige så bred"/>
<text name="spu_field_section_store" text="— Tving lager (ellers nærmeste silo med plads) —"/> <text name="spu_field_section_store" text="— Tving lager (ellers nærmeste silo med plads) —"/>
+2 -2
View File
@@ -53,7 +53,7 @@
<text name="spu_field_reason_noRig" text="no %s ticked in the field fleet"/> <text name="spu_field_reason_noRig" text="no %s ticked in the field fleet"/>
<text name="spu_field_reason_allBusy" text="waiting for a free %s"/> <text name="spu_field_reason_allBusy" text="waiting for a free %s"/>
<text name="spu_field_reason_tooWide" text="%s too wide: %.1f m &gt; %.0f m (Courseplay)"/> <text name="spu_field_reason_tooWide" text="%s too wide: %.1f m &gt; %.0f m (Courseplay)"/>
<text name="spu_field_reason_tooNarrow" text="%s too narrow: %.1f m &lt; mowing width %.1f m"/> <text name="spu_field_reason_tooNarrow" text="%s too narrow: %.1f m &lt; mowing width %.1f m — turn on Rake or use a wider one"/>
<text name="spu_field_role_mower" text="mower"/> <text name="spu_field_role_mower" text="mower"/>
<text name="spu_field_role_tedder" text="tedder"/> <text name="spu_field_role_tedder" text="tedder"/>
<text name="spu_field_role_rake" text="rake"/> <text name="spu_field_role_rake" text="rake"/>
@@ -74,7 +74,7 @@
<text name="spu_field_section" text="— Field F%d: %s —"/> <text name="spu_field_section" text="— Field F%d: %s —"/>
<text name="spu_field_plan" text="Plan"/> <text name="spu_field_plan" text="Plan"/>
<text name="spu_field_mode" text="Mode"/> <text name="spu_field_mode" text="Mode"/>
<text name="spu_field_rake" text="Rake the hay before collecting"/> <text name="spu_field_rake" text="Rake the swaths before collecting (lets narrow loading wagons collect)"/>
<text name="spu_field_marker" text=" Marker %s, %.0f m from the field"/> <text name="spu_field_marker" text=" Marker %s, %.0f m from the field"/>
<text name="spu_field_mowWidth" text=" Mowed at %.1f m — collecting must be at least as wide"/> <text name="spu_field_mowWidth" text=" Mowed at %.1f m — collecting must be at least as wide"/>
<text name="spu_field_section_store" text="— Force storage (else nearest silo with room) —"/> <text name="spu_field_section_store" text="— Force storage (else nearest silo with room) —"/>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107"> <modDesc descVersion="107">
<author>masterdraco</author> <author>masterdraco</author>
<version>1.22.0.0</version> <version>1.23.0.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
+9 -6
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — brugermanual # AD Smart Pickup — brugermanual
Version 1.22.0 · Farming Simulator 25 · tillæg til AutoDrive Version 1.23.0 · Farming Simulator 25 · tillæg til AutoDrive
*English version: [USER_MANUAL.md](USER_MANUAL.md)* *English version: [USER_MANUAL.md](USER_MANUAL.md)*
@@ -531,7 +531,7 @@ hvilket trin og hvilken maskine. Kræver **Courseplay** ud over AutoDrive.
| Plan | Trin | | Plan | Trin |
|---|---| |---|---|
| **Ensilage** | Slås → Samles op → silo | | **Ensilage** | Slås → (Rives) → Samles op → silo |
| **Hø** | Slås → Vendes → (Rives) → Samles op → silo | | **Hø** | Slås → Vendes → (Rives) → Samles op → silo |
### Opsætning ### Opsætning
@@ -551,9 +551,12 @@ hvilket trin og hvilken maskine. Kræver **Courseplay** ud over AutoDrive.
- Courseplay kan højst køre **50 m** bredt. Et sæt over 50 m sendes ikke ud (`!! over 50 m` i - Courseplay kan højst køre **50 m** bredt. Et sæt over 50 m sendes ikke ud (`!! over 50 m` i
markflåden). markflåden).
- Moden husker, hvor bredt marken blev **slået**, og **slåmaskinens Courseplay-kursus**. Vender, river og - **Vender og river** kører hele marken i deres egen bredde med deres eget kursus. De må gerne være
læssevogn kører præcis samme kursus (kopieret), så de rammer skårene. De skal være **mindst lige så smallere end slåmaskinen.
brede** som slåmaskinen. Med Unrealistic Pack: sæt slåmaskinen og - **Læssevognen** skal ramme skårene og kører derfor et kopieret kursus:
- **uden Riv:** slåmaskinens kursus, og vognen skal være **mindst lige så bred som slåbredden**.
- **med Riv:** rivens kursus. Skåret ligger midt i hver rivebane, så vognens bredde er ligegyldig.
- Har du kun smalle standardvogne, så slå **Riv** til på marken (også ved ensilage). Med Unrealistic Pack: sæt slåmaskinen og
læssevognene til samme bredde, fx 40,8 m. læssevognene til samme bredde, fx 40,8 m.
### En mark ### En mark
@@ -564,7 +567,7 @@ Klik på en mark i tabellen for at vælge den. Under tabellen står:
|---|---| |---|---|
| **Plan** | Ensilage eller Hø | | **Plan** | Ensilage eller Hø |
| **Kørsel** | *Manuel*: marken venter på **Start nu**. *Auto*: marken starter selv, når den er klar | | **Kørsel** | *Manuel*: marken venter på **Start nu**. *Auto*: marken starter selv, når den er klar |
| **Riv** | Kun ved hø: riv høet sammen før opsamling. Standard fra, fordi brede læssevogne samler spredt hø | | **Riv** | Riv skårene sammen før opsamling (hø og ensilage). Standard fra. Slå til ved smalle læssevogne |
| **Tving lager** | Vælg siloer. Uden valg bruges nærmeste silo med plads, der tager varen | | **Tving lager** | Vælg siloer. Uden valg bruges nærmeste silo med plads, der tager varen |
En mark er **klar**, når mindst 90 % af den står i høstvinduet. Status viser andelen, fx `Venter 72 %`. En mark er **klar**, når mindst 90 % af den står i høstvinduet. Status viser andelen, fx `Venter 72 %`.
+10 -6
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — user manual # AD Smart Pickup — user manual
Version 1.22.0 · Farming Simulator 25 · add-on for AutoDrive Version 1.23.0 · Farming Simulator 25 · add-on for AutoDrive
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)* *Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
@@ -537,7 +537,7 @@ which step and which machine. Requires **Courseplay** in addition to AutoDrive.
| Plan | Steps | | Plan | Steps |
|---|---| |---|---|
| **Silage** | Mow → Collect → silo | | **Silage** | Mow → (Rake) → Collect → silo |
| **Hay** | Mow → Ted → (Rake) → Collect → silo | | **Hay** | Mow → Ted → (Rake) → Collect → silo |
### Setup ### Setup
@@ -557,9 +557,13 @@ which step and which machine. Requires **Courseplay** in addition to AutoDrive.
- Courseplay can work at most **50 m** wide. A rig over 50 m is not sent out (`!! over 50 m` in the - Courseplay can work at most **50 m** wide. A rig over 50 m is not sent out (`!! over 50 m` in the
fleet). fleet).
- The mod remembers how wide the field was **mowed**, and the **mower's Courseplay course**. Tedder, - **Tedder and rake** work the whole field at their own width with their own course. They may be
rake and loading wagon drive exactly that course (copied), so they hit the swaths. They must be **at narrower than the mower.
least as wide** as the mower. With Unrealistic Pack: set the mower and the - **The loading wagon** must hit the swaths, so it drives a copied course:
- **without Rake:** the mower's course, and the wagon must be **at least as wide as the mowing width**.
- **with Rake:** the rake's course. The swath lies in the middle of each rake lane, so the wagon's width
does not matter.
- If you only have narrow standard wagons, turn **Rake** on for the field (also for silage). With Unrealistic Pack: set the mower and the
loading wagons to the same width, such as 40.8 m. loading wagons to the same width, such as 40.8 m.
### A field ### A field
@@ -570,7 +574,7 @@ Click a field in the table to select it. Below the table:
|---|---| |---|---|
| **Plan** | Silage or Hay | | **Plan** | Silage or Hay |
| **Mode** | *Manual*: the field waits for **Start now**. *Auto*: the field starts by itself when ready | | **Mode** | *Manual*: the field waits for **Start now**. *Auto*: the field starts by itself when ready |
| **Rake** | Hay only: rake before collecting. Off by default, because wide loading wagons collect spread hay | | **Rake** | Rake the swaths before collecting (hay and silage). Off by default. Turn on for narrow loading wagons |
| **Force storage** | Pick silos. Without a choice the nearest silo with room that takes the goods is used | | **Force storage** | Pick silos. Without a choice the nearest silo with room that takes the goods is used |
A field is **ready** when at least 90 % of it is in the harvest window. The status shows the share, A field is **ready** when at least 90 % of it is in the harvest window. The status shows the share,
@@ -44,6 +44,10 @@ Ikke med i etape 1: mejetærskerafgrøder (etape 2), roer (etape 3), jordbehandl
kursus** (`vehicle:cpCopyCourse`). Kurset gemmes pr. mark; efter genindlæsning hentes det fra kursus** (`vehicle:cpCopyCourse`). Kurset gemmes pr. mark; efter genindlæsning hentes det fra
slåmaskinen (id gemt som `mowVehicle`), som Courseplay selv gemmer kurset på. Uden kendt slåkursus slåmaskinen (id gemt som `mowVehicle`), som Courseplay selv gemmer kurset på. Uden kendt slåkursus
laves et nyt som reserve (logges). laves et nyt som reserve (logges).
**Revideret igen 25/9 (smalle standardmaskiner):** vender og river kører hele marken i egen bredde med
eget kursus (intet breddekrav). Læssevognen følger skårene: uden riv slåmaskinens kursus og bredde ≥
slåbredde; med riv rivens kursus (skåret ligger midt i banen) og intet breddekrav. Riv kan vælges til
både hø og ensilage.
7. **Silovalg** genbruger Smart Pickups motor (`ADLoadSwap`): nærmeste silo med plads, der tager varen, 7. **Silovalg** genbruger Smart Pickups motor (`ADLoadSwap`): nærmeste silo med plads, der tager varen,
med vej fra `F`-markøren. *Tving lager* pr. mark (som "Lager til" i flows). Fabrikker er ikke mål. med vej fra `F`-markøren. *Tving lager* pr. mark (som "Lager til" i flows). Fabrikker er ikke mål.
8. **Marksilo.** En silo, hvis afstand til markens polygon er ≤ 150 m, er et mellemlager. Den må gerne 8. **Marksilo.** En silo, hvis afstand til markens polygon er ≤ 150 m, er et mellemlager. Den må gerne
+18
View File
@@ -28,6 +28,7 @@ check("M3 lidt under 90 % forbliver klar", M.onReadiness(ready, 0.8).stage, "rea
-- M4: trin pr. plan -- M4: trin pr. plan
check("M4 ensilage", table.concat(M.workStages({product = "silage"}), ","), "mowing,collecting") check("M4 ensilage", table.concat(M.workStages({product = "silage"}), ","), "mowing,collecting")
check("M4 ensilage m. riv", table.concat(M.workStages({product = "silage", rake = true}), ","), "mowing,raking,collecting")
check("M4 hø", table.concat(M.workStages({product = "hay", rake = false}), ","), "mowing,tedding,collecting") check("M4 hø", table.concat(M.workStages({product = "hay", rake = false}), ","), "mowing,tedding,collecting")
check("M4 hø m. riv", table.concat(M.workStages({product = "hay", rake = true}), ","), "mowing,tedding,raking,collecting") check("M4 hø m. riv", table.concat(M.workStages({product = "hay", rake = true}), ","), "mowing,tedding,raking,collecting")
@@ -103,5 +104,22 @@ check("M9 trin bevaret", noted.stage, "mowing"); check("M9 original urørt", bas
check("M10 venter -> klar", M.forceReady(M.newField(2)).stage, "ready") check("M10 venter -> klar", M.forceReady(M.newField(2)).stage, "ready")
check("M10 arbejdende uændret", M.forceReady(base).stage, "mowing") check("M10 arbejdende uændret", M.forceReady(base).stage, "mowing")
-- M11: krævet bredde og kursus-kilde pr. rolle (smalle standardmaskiner, 25/9)
local cut = M.with(M.newField(3), {mowWidth = 40.8})
check("M11 vender kræver ingen bredde", M.requiredWidth(cut, "tedder"), nil)
check("M11 river kræver ingen bredde", M.requiredWidth(cut, "rake"), nil)
check("M11 læssevogn uden riv = slåbredde", M.requiredWidth(cut, "collector"), 40.8)
local raked = M.with(cut, {plan = {rake = true}})
check("M11 læssevogn efter riv = ingen krav", M.requiredWidth(raked, "collector"), nil)
check("M11 vender eget kursus", M.courseSource(cut, "tedder"), nil)
check("M11 river eget kursus", M.courseSource(raked, "rake"), nil)
check("M11 læssevogn uden riv -> slåkursus", M.courseSource(cut, "collector"), "mower")
check("M11 læssevogn efter riv -> rivekursus", M.courseSource(raked, "collector"), "rake")
check("M11 slåmaskine eget kursus", M.courseSource(cut, "mower"), nil)
-- gem/indlæs rivemaskine
local withRake = M.with(raked, {rakeVehicleId = "vehicleRake"})
check("M11 rivemaskine gemt", M.fromRecord(M.toRecord(withRake)).rakeVehicleId, "vehicleRake")
check("M11 start glemmer rivemaskine", M.start(M.with(M.onReadiness(M.newField(9), 1), {rakeVehicleId = "x"})).rakeVehicleId, nil)
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1) os.exit(failures == 0 and 0 or 1)