8 Commits

Author SHA1 Message Date
masterdraco 4f676135ac fix(flow-vogne): husk kun redskaber med lastrum som flow-vogn (v1.60.21.0)
Sell Slurry 2 havde ploven husket som gyllevogn. Manualerne: fast sæt/bundet
omfatter nu også flowets vogne.
2026-09-30 12:34:39 +02:00
masterdraco 2a36de0837 docs: engelsk README-afsnit med install-trin 3 og Development 2026-09-30 11:53:12 +02:00
masterdraco c415bdc7a4 fix(marker): vinhøster — lille CP-bredde erstattes af 3 m (v1.60.20.0) 2026-09-29 23:50:34 +02:00
masterdraco a6506fea4e fix(marker): vinhøster uden bredde får vinrækkens 3 m (v1.60.19.0) 2026-09-29 23:40:08 +02:00
masterdraco 8abcbcdcb8 fix(marker): vinhøsterens afgrøde fra inputFruitTypeIndex (FS25) (v1.60.18.0) 2026-09-29 23:34:38 +02:00
masterdraco 3c67591cb3 fix(marker): vinhøstere genkendes via spec_vineCutter (v1.60.17.0) 2026-09-29 23:26:31 +02:00
masterdraco 784144cd4e fix(aflæsning): tipvogn skiftes til en tip-side AD må aflæsse fra
EDK 650 Unrealistic har kun allowAIDischarge på bagudtip; på venstre/højre/
kornluge åbnede AD aflæsningen, men intet løb ud (Chicken Food 2 786.712 l
hvede ved Farma med plads; Disponibel Vogn 3 fuld af løg). CP-genstart logger
kun ved ændring (v1.60.16.0).
2026-09-29 23:23:20 +02:00
masterdraco 13e5dbf188 fix(marker): humle (HOPS) er vinafgrøde — aldrig slåafgrøde (v1.60.15.0) 2026-09-29 23:12:16 +02:00
11 changed files with 170 additions and 19 deletions
+10
View File
@@ -8,6 +8,16 @@ står i [docs/BRUGERMANUAL.md](docs/BRUGERMANUAL.md) (dansk) og [docs/USER_MANUA
## 1.60 — "Kræver handling" → flow, menuplacering, flow-vogne i guiden
- **1.60.21** Flow-vogne: kun et redskab med lastrum (ikke plov, kultivator eller såmaskine) huskes som flowets vogn. Før kunne en plov, der hang bag en flow-traktor, blive gemt som gyllevogn, og gyllen blev aldrig kørt.
- **1.60.20** Vinhøsterens bredde: også en lille bredde fra Courseplay (under 1,5 m) erstattes af vinrækkens 3 m.
- **1.60.19** Vinhøster uden kendt arbejdsbredde får vinrækkens 3 m (før "bredde ukendt", og marken blev ikke startet).
- **1.60.18** Vinhøsterens afgrøde læses fra `inputFruitTypeIndex` (feltnavnet i FS25).
- **1.60.17** Vinhøstere (fx Grégoire GL86) genkendes som høstere af den afgrøde, de er konfigureret til
(spec_vineCutter). Før fik vinmarker "ingen kan" (in-game: F22 hvide druer).
- **1.60.16** Tipvogne skiftes under AD-aflæsning til en tip-side, AutoDrive må aflæsse fra (`allowAIDischarge`).
Farmtech EDK 650 (Unrealistic) tillader kun bagudtip; stod den på venstre, højre eller kornluge, åbnede AD
aflæsningen, men intet løb ud, og vognen holdt med fuldt læs. CP-genstartslisten logges kun, når den ændrer sig.
- **1.60.15** Humle (HOPS, Dakota) behandles som vinafgrøde: aldrig slåafgrøde, og markmaskiner kører på rækkerne som ved druer.
- **1.60.14** Afkobling ved redskabets egen parkering godtager 8 m (før 5 m): lange redskaber som en valse står
med roden over 5 m inde i båsen, så afkoblingen fejlede med "stoppedAway".
- **1.60.13** CP-genstart efter indlæsning starter kun maskiner, hvis valgte CP-job er markarbejde. Moddets
+47 -4
View File
@@ -169,12 +169,43 @@ function ADCpBridge.getSpecs(vehicle)
return specs
end
-- Afgrøder høsteren kan tage (alle skærebord/optagere i kæden). nil = ikke en høster.
-- Vinhøster (fx Grégoire GL86): afgrøden vælges i konfigurationen og står i spec_vineCutter, ikke i spec_cutter
-- (in-game 29/9: F22 hvide druer "none can do it" — moddet så aldrig vinhøstere som høstere).
function ADCpBridge.vineFruitSet(spec)
local fruits = {}
if spec == nil then return fruits end
for _, key in ipairs({"inputFruitTypeIndex", "fruitTypeIndex", "fruitType"}) do
if type(spec[key]) == "number" then fruits[spec[key]] = true end
end
if type(spec.fruitTypes) == "table" then
for key, value in pairs(spec.fruitTypes) do
if type(value) == "number" then fruits[value] = true
elseif value == true and type(key) == "number" then fruits[key] = true end
end
end
return fruits
end
local vineLogged = setmetatable({}, {__mode = "k"})
-- Afgrøder høsteren kan tage (alle skærebord/optagere/vinhøstere i kæden). nil = ikke en høster.
function ADCpBridge.getHarvestFruits(vehicle)
if vehicle.spec_combine == nil then return nil end
local fruits = {}
for _, object in ipairs(collect(vehicle)) do
for fruit in pairs(ADCpBridge.harvestFruitSet(object.spec_cutter)) do fruits[fruit] = true end
if object.spec_vineCutter ~= nil then
local vine = ADCpBridge.vineFruitSet(object.spec_vineCutter)
for fruit in pairs(vine) do fruits[fruit] = true end
if next(vine) == nil and not vineLogged[object] then
-- ukendt feltnavn i denne spilversion: vis nøglerne, så reglen kan rettes
vineLogged[object] = true
local keys = {}
for key, value in pairs(object.spec_vineCutter) do table.insert(keys, tostring(key) .. "=" .. type(value)) end
table.sort(keys)
Logging.info("ADSmartPickup: vinhøster uden afgrøde fundet — spec_vineCutter: %s", table.concat(keys, ", "))
end
end
end
return fruits
end
@@ -360,9 +391,21 @@ local function courseplayWidth(vehicle)
return nil
end
-- Vinhøster uden AI-markører: bredden er vinrækken (3 m = Courseplays vin-gitter for druer).
ADCpBridge.VINE_ROW_WIDTH = 3
function ADCpBridge.widthOrVine(width, hasVineCutter)
-- under markarbejdets minimum (1,5 m) — også en lille bredde fra Courseplay (in-game 29/9: stadig widthUnknown)
if hasVineCutter and (width or 0) < 1.5 then return ADCpBridge.VINE_ROW_WIDTH end
return width
end
function ADCpBridge.getWorkWidth(vehicle)
local hasVine = false
for _, object in ipairs(collect(vehicle)) do
if object.spec_vineCutter ~= nil then hasVine = true end
end
local cpWidth = courseplayWidth(vehicle)
if cpWidth ~= nil then return cpWidth end
if cpWidth ~= nil then return ADCpBridge.widthOrVine(cpWidth, hasVine) end
local best = 0
for _, object in ipairs(collect(vehicle)) do
local variable = variableWidth(object)
@@ -374,7 +417,7 @@ function ADCpBridge.getWorkWidth(vehicle)
if ok and type(width) == "number" and width > best then best = width end
end
end
return best
return ADCpBridge.widthOrVine(best, hasVine)
end
-- AutoDrive kører også som AI-job i FS25: aktiv AD er ikke Courseplay (in-game 29/9: Milk Store ved Cow Wait
@@ -500,7 +543,7 @@ end
-- Vinmarker (druer/oliven): Courseplays kursus ligger som standard PÅ vinen — en sprøjte/spreder/harve kører
-- så ind i stolperne ("Blocked by an object", in-game 26/9 F22). Alt der arbejder i gangene køres til
-- venstre for vinen; høsteren kører hen over rækken. nil = ikke en vinmark (rør intet).
ADCpBridge.VINE_FRUITS = {GRAPE = true, GRAPEB = true, OLIVE = true, OLIVEB = true}
ADCpBridge.VINE_FRUITS = {GRAPE = true, GRAPEB = true, OLIVE = true, OLIVEB = true, HOPS = true}
function ADCpBridge.vineOffsetFor(fruitName, role)
if fruitName == nil or not ADCpBridge.VINE_FRUITS[string.upper(tostring(fruitName))] then return nil end
if role == "harvester" then return 0 end
+6 -1
View File
@@ -110,7 +110,12 @@ function ADCpResume.save(adEnv)
end
xmlFile:save()
xmlFile:delete()
Logging.info(ADCpResume.LOG_PREFIX .. "gemt: %d maskine(r) kører Courseplay", #ids)
-- gemmes ved hver runs-gem (flere gange i minuttet): log kun når listen ændrer sig
local signature = table.concat(ids, ",")
if signature ~= ADCpResume.lastLogged then
ADCpResume.lastLogged = signature
Logging.info(ADCpResume.LOG_PREFIX .. "gemt: %d maskine(r) kører Courseplay", #ids)
end
return true
end
+1 -1
View File
@@ -104,7 +104,7 @@ end
-- Vin og oliven høstes med egen høster — aldrig slåafgrøder, selv om et mod har sat dem på MOWER-listen
-- (in-game 29/9: F22 hvide druer fik "Silage + så" og en skårlægger). Samme liste som ADCpBridge.VINE_FRUITS.
ADFields.VINE_FRUITS = {GRAPE = true, GRAPEB = true, OLIVE = true, OLIVEB = true}
ADFields.VINE_FRUITS = {GRAPE = true, GRAPEB = true, OLIVE = true, OLIVEB = true, HOPS = true}
-- fruitName + indgangen fra getMowable() (nil = ikke på listen) -> slåbar?
function ADFields.isMowableFruit(fruitName, mowableEntry)
+13 -2
View File
@@ -23,6 +23,12 @@ function ADFlowWagons.remember(wagons, tractorId, wagonId)
return copy
end
-- Må redskabet bag traktoren huskes som flowets vogn? Kun noget der kan rumme last — ikke plov/kultivator (ingen
-- plads) og ikke såmaskine (frøtank). s = {capacity, isSowingMachine}. in-game 30/9: 'Sell Slurry 2' huskede ploven.
function ADFlowWagons.isRememberableWagon(s)
return (s.capacity or 0) > 0 and not s.isSowingMachine
end
-- s = {hasRear, wagonId, wagonExists, hasConnect, wagonAttached, wagonBusy} -> "start" | "fetch" | "wait"
function ADFlowWagons.startAction(s)
-- lånt ud af puljen (markarbejde, marksilo, på hjemtur): vent til den er fri
@@ -453,11 +459,16 @@ end
-- Husk vognen bag traktoren som flowets (også når flowet lige er stoppet — rememberAll ser kun kørende flows).
-- in-game 29/9: Milk Store's tanke blev sat af ved Stop alt uden at være husket -> 'noTrailer' ved næste start.
local function isCargoWagon(object)
local _, capacity = ADPool.cargoOf(object)
return ADFlowWagons.isRememberableWagon({capacity = capacity, isSowingMachine = object.spec_sowingMachine ~= nil})
end
local function rememberWagonOf(vehicle)
local run = ADRunsController.getRunForVehicle(vehicle)
local rear = run ~= nil and ADHitch.rearImplementsOf(vehicle) or {}
local tractorId = ADRunsController.getVehicleId(vehicle)
local wagonId = rear[1] ~= nil and ADRunsController.getVehicleId(rear[1].object) or nil
local wagonId = rear[1] ~= nil and isCargoWagon(rear[1].object) and ADRunsController.getVehicleId(rear[1].object) or nil
if wagonId == nil or tractorId == nil then return end
local updated = ADFlowWagons.remember(run.wagons, tractorId, wagonId)
if updated ~= run.wagons then
@@ -615,7 +626,7 @@ local function rememberAll(adEnv)
for _, vehicleId in ipairs(run.vehicleIds or {}) do
local vehicle = ADRunsController.findVehicleById(adEnv, vehicleId)
local rear = vehicle ~= nil and ADHitch.rearImplementsOf(vehicle) or {}
local wagonId = rear[1] ~= nil and ADRunsController.getVehicleId(rear[1].object) or nil
local wagonId = rear[1] ~= nil and isCargoWagon(rear[1].object) and ADRunsController.getVehicleId(rear[1].object) or nil
if wagonId ~= nil then
local updated = ADFlowWagons.remember(run.wagons, vehicleId, wagonId)
if updated ~= run.wagons then
+58
View File
@@ -0,0 +1,58 @@
-- AD Tip Side
-- Tipvogne med flere tip-sider (fx Farmtech EDK 650 Unrealistic: bag / kornluge / venstre / højre) tillader kun
-- AI-aflæsning (allowAIDischarge) på nogle af udløbene. Står vognen på en side uden, åbner AD aflæsningen ved
-- målet, men intet løber ud — vognen holder med fuldt læs (in-game 29/9: Chicken Food 2 med 786.712 l hvede på
-- højre side ved en Farma med 10 mio. l fri; Disponibel Vogn 3 fuld af løg). Når AD kører en vogn, skiftes den til
-- en side, AI må aflæsse fra.
ADTipSide = {}
ADTipSide.LOG_PREFIX = "ADSmartPickup: tip-side: "
-- ---- ren logik ----
-- sides = {{node = udløbsindeks}}, allowAI = {[udløbsindeks] = true}, current = nuværende side
-- -> sideindeks der skal vælges, eller nil (nuværende er fin / ingen side tilladt / ukendt)
function ADTipSide.choose(sides, allowAI, current)
local currentSide = (sides or {})[current]
if currentSide ~= nil and (allowAI or {})[currentSide.node] then return nil end
for index, side in ipairs(sides or {}) do
if (allowAI or {})[side.node] then return index end
end
return nil
end
-- ---- spil ----
local warned = setmetatable({}, {__mode = "k"})
local function sidesOf(object)
local spec = object.spec_trailer
local dis = object.spec_dischargeable
if spec == nil or dis == nil or spec.tipSides == nil or #spec.tipSides < 2 then return nil end
local sides, allowAI = {}, {}
for index, side in ipairs(spec.tipSides) do sides[index] = {node = side.dischargeNodeIndex} end
for index, node in ipairs(dis.dischargeNodes or {}) do
if node.allowAIDischarge then allowAI[index] = true end
end
return sides, allowAI, spec.preferedTipSideIndex
end
-- Alle tipvogne bag traktoren: skift til en AI-tilladt side (kun mens vognen ikke tipper).
function ADTipSide.ensure(vehicle)
local children = vehicle.getChildVehicles ~= nil and vehicle:getChildVehicles() or {}
for _, object in pairs(children) do
if object ~= vehicle and object.setPreferedTipSide ~= nil then
local sides, allowAI, current = sidesOf(object)
local tipping = Trailer ~= nil and object.getTipState ~= nil and object:getTipState() ~= Trailer.TIPSTATE_CLOSED
local index = sides ~= nil and not tipping and ADTipSide.choose(sides, allowAI, current) or nil
if index ~= nil then
object:setPreferedTipSide(index)
if not warned[object] then
warned[object] = true
Logging.info(ADTipSide.LOG_PREFIX .. "'%s': tip-side %s -> %d (AutoDrive må kun aflæse fra den side)",
tostring(object.getName ~= nil and object:getName() or "?"), tostring(current), index)
end
end
end
end
end
+12
View File
@@ -426,6 +426,9 @@ function ADUnloadWait.getClaims(adEnv)
return ADWaitPool.getClaims(adEnv)
end
ADUnloadWait.TIP_CHECK_MS = 2000
local tipChecked = setmetatable({}, {__mode = "k"})
function ADUnloadWait.install(adEnv)
local task, autoDrive = adEnv.UnloadAtDestinationTask, adEnv.AutoDrive
if isInstalled or task == nil or task.update == nil or autoDrive == nil or autoDrive.getSetting == nil then
@@ -438,6 +441,15 @@ function ADUnloadWait.install(adEnv)
local originalUpdate, originalFinished, originalGetSetting = task.update, task.finished, autoDrive.getSetting
task.update = function(self, dt)
-- alle aflæsningsture (også udkørsel og tømning): tipvognen på en side AD må aflæsse fra (EDK 650, 29/9)
if ADTipSide ~= nil and self.vehicle ~= nil then
local now = g_time or 0
if (tipChecked[self.vehicle] or -math.huge) + ADUnloadWait.TIP_CHECK_MS <= now then
tipChecked[self.vehicle] = now
local okTip, errTip = pcall(ADTipSide.ensure, self.vehicle)
if not okTip then Logging.warning(ADUnloadWait.LOG_PREFIX .. "tip-side: %s", tostring(errTip)) end
end
end
local ok, err = pcall(ADUnloadWait.beforeUpdate, adEnv, self, dt)
if not ok then
Logging.warning(ADUnloadWait.LOG_PREFIX .. "fejl i Wait-punkt-logik, AutoDrive fortsætter selv: %s", tostring(err))
+2 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107">
<author>masterdraco</author>
<version>1.60.14.0</version>
<version>1.60.21.0</version>
<title>
<en>AD Smart Pickup</en>
</title>
@@ -31,6 +31,7 @@
<sourceFile filename="adSources.lua"/>
<sourceFile filename="adBuildings.lua"/>
<sourceFile filename="adOutbound.lua"/>
<sourceFile filename="adTipSide.lua"/>
<sourceFile filename="adUnloadWait.lua"/>
<sourceFile filename="adFieldModel.lua"/>
<sourceFile filename="adFieldFleet.lua"/>
+5 -1
View File
@@ -80,7 +80,8 @@ is set up in the **Smart Pickup** menu in the ESC menu.
**Install:** download `FS25_ADSmartPickup.zip` from
[Releases](https://git.powerdata.dk/masterdraco/fs25-adsmartpickup/releases). Put the zip, not unpacked,
in `Documents/My Games/FarmingSimulator2025/mods/`.
in `Documents/My Games/FarmingSimulator2025/mods/`. Enable the mod together with AutoDrive when you pick
the savegame. The **Smart Pickup** menu is in the ESC menu, just above Settings.
**Requirements:** AutoDrive is required. Courseplay is needed for field work, and Universal Autoload is
needed for pallets.
@@ -90,3 +91,6 @@ needed for pallets.
**Feedback:** tell the developer (issues here need an account on git.powerdata.dk). Attach `log.txt`, or at least the lines starting with
`ADSmartPickup`.
**Development:** the mod code is in `FS25_ADSmartPickup/`. Build the zip with
`cd FS25_ADSmartPickup && zip -qr ../FS25_ADSmartPickup.zip .`
+7 -4
View File
@@ -93,8 +93,10 @@ til tom*: den vare, der slipper op først, hentes først.
**Reserve.** Det, gårdens egne stalde og fabrikker skal bruge det næste døgn. Reserven sælges aldrig.
**Sæt.** En traktor med redskab eller vogn koblet på, eller en selvkørende maskine. Et **fast sæt** er et
redskab, der ikke har en Connect-markør. Det bliver siddende og udlånes aldrig.
**Sæt.** En traktor med redskab eller vogn koblet på, eller en selvkørende maskine. Et redskab eller en
vogn er **bundet** og udlånes aldrig, når det hører til et flow (flowets traktorer og vogne, også når flowet
er stoppet), eller når det ikke har en Connect-markør (et **fast sæt**, fx en vintraktor med sit
vinredskab).
**Maskinpulje.** Frakoblede redskaber og vogne med parkering og Connect-markør samt ledige traktorer uden
redskab. Moden parrer dem selv, når der er brug for det.
@@ -149,7 +151,8 @@ En **Connect-markør** er stedet, hvor traktoren holder for at koble et redskab
- Kører du selv en traktor med AutoDrives "Kør til" til en Connect-markør, kobler moden også på.
- Omdøber du en parkering, skal Connect-markøren omdøbes med.
Et redskab eller en vogn **uden** Connect-markør er et fast sæt og bliver aldrig lånt ud.
Et redskab eller en vogn **uden** Connect-markør er et fast sæt og bliver aldrig lånt ud. Det samme
gælder et flows vogne, selv om de har en Connect-markør (se [Flow-vogne](#flow-vogne)).
### Afkobling: "Afkobl"
@@ -1139,7 +1142,7 @@ Moden testes løbende, og fejlrapporter er meget velkomne.
| **Connect-markør** | Markøren `Connect <parkeringsnavn>`, hvor en traktor kobler et redskab på |
| **Afkobl-markør** | Markør, hvor redskaber bag traktoren kobles af |
| **Solo-traktor** | Traktor uden vogn eller redskab bagpå |
| **Fast sæt** | Redskab uden Connect-markør. Det bliver siddende og udlånes aldrig |
| **Fast sæt** | Redskab uden Connect-markør. Det bliver siddende og udlånes aldrig. Et flows vogne udlånes heller aldrig |
| **Maskinpulje** | Frakoblede redskaber/vogne og ledige traktorer, som moden parrer efter behov |
| **Markflåde** | De maskiner, markarbejdet må bruge |
| **UAL** | Universal Autoload, mod der læsser paller automatisk |
+9 -5
View File
@@ -93,8 +93,10 @@ empty*: the good that runs out first is fetched first.
**Reserve.** What the farm's own barns and factories will use in the next day. The reserve is never sold.
**Set.** A tractor with an implement or trailer attached, or a self-propelled machine. A **fixed set** is
an implement that has no Connect marker. It stays attached and is never lent out.
**Set.** A tractor with an implement or trailer attached, or a self-propelled machine. An implement or
trailer is **bound** and never lent out when it belongs to a flow (the flow's tractors and trailers, also
while the flow is stopped), or when it has no Connect marker (a **fixed set**, e.g. a vineyard tractor with
its vineyard implement).
**Machine pool.** Detached implements and trailers with a parking spot and a Connect marker, plus free
tractors without an implement. The mod pairs them up when needed.
@@ -149,7 +151,8 @@ A **Connect marker** is where the tractor stops to hitch an implement or trailer
- If you drive a tractor with AutoDrive's "Drive to" to a Connect marker yourself, the mod hitches too.
- If you rename a parking spot, rename the Connect marker as well.
An implement or trailer **without** a Connect marker is a fixed set and is never lent out.
An implement or trailer **without** a Connect marker is a fixed set and is never lent out. The same goes
for a flow's trailers, even when they have a Connect marker (see [Flow trailers](#flow-trailers)).
### Detaching: "Afkobl"
@@ -603,7 +606,8 @@ and while the flow is running.
The machine pool is used by field work and field silos when no ready-made set is free.
- **Pool implement/trailer:** detached, owned by the farm, with an AutoDrive parking spot and a Connect
marker for that parking spot. Implements without a Connect marker are fixed sets and are never lent.
marker for that parking spot, and not bound to a flow. Implements without a Connect marker are fixed sets
and are never lent.
- **Pool tractor:** an ordinary tractor with nothing attached at the rear, with its own AutoDrive parking
spot, on AutoDrive's road network and not driven by you. Field implements are only hitched behind
tractors. Unloading trailers can also be pulled by other vehicles.
@@ -1169,7 +1173,7 @@ The mod is being tested continuously, and bug reports are very welcome.
| **Connect marker** | The marker `Connect <parking name>`, where a tractor hitches an implement |
| **Afkobl marker** | Marker where implements behind the tractor are detached |
| **Solo tractor** | Tractor with no trailer or implement attached at the rear |
| **Fixed set** | Implement without a Connect marker. It stays attached and is never lent out |
| **Fixed set** | Implement without a Connect marker. It stays attached and is never lent out. A flow's trailers are never lent out either |
| **Machine pool** | Detached implements/trailers and free tractors that the mod pairs up as needed |
| **Field fleet** | The machines field work is allowed to use |
| **UAL** | Universal Autoload, a mod that loads pallets automatically |