feat(stald): æg/uld-paller fra staldens egne pallespawnere (hønsehus) som udkørselskilde; brændstoftanke er ikke lager-kilder (v1.18.8.0)

This commit is contained in:
2026-09-24 19:24:36 +02:00
parent 6d25478783
commit b3d49c4857
7 changed files with 129 additions and 11 deletions
+30 -1
View File
@@ -104,6 +104,19 @@ local function collectNodes(placeable, loadStations, unloadStations)
end end
if #nodes > 0 then table.insert(loadGroups, nodes) end if #nodes > 0 then table.insert(loadGroups, nodes) end
end end
-- stald med egne pallespawnere (hønsehus: æg, fårestald: uld) — én læssegruppe pr. spawner
local husbandryPallets = placeable.spec_husbandryPallets
local seenSpawners = {}
for _, palletSpawner in pairs(husbandryPallets ~= nil and husbandryPallets.fillTypeIndexToPalletSpawner or {}) do
if not seenSpawners[palletSpawner] then
seenSpawners[palletSpawner] = true
local nodes = {}
for _, place in ipairs(palletSpawner.spawnPlaces or {}) do
if place.startNode ~= nil then table.insert(nodes, place.startNode) end
end
if #nodes > 0 then table.insert(loadGroups, nodes) end
end
end
if placeable.spec_objectStorage ~= nil and placeable.rootNode ~= nil then if placeable.spec_objectStorage ~= nil and placeable.rootNode ~= nil then
table.insert(loadGroups, {placeable.rootNode}) table.insert(loadGroups, {placeable.rootNode})
table.insert(unloadNodes, placeable.rootNode) table.insert(unloadNodes, placeable.rootNode)
@@ -249,9 +262,25 @@ local function isSellPlaceable(placeable, unloadStations)
return false return false
end end
-- Brændstof er ikke en vare der køres rundt (gårdens tankanlæg har en læssestation til diesel).
local FUEL_FILL_TYPES = {DIESEL = true, DEF = true, ELECTRICCHARGE = true, METHANE = true}
local function isFuelOnly(station)
local supported = station.supportedFillTypes
if supported == nil or next(supported) == nil or g_fillTypeManager == nil then
return false
end
for fillType, isSupported in pairs(supported) do
if isSupported and not FUEL_FILL_TYPES[tostring(g_fillTypeManager:getFillTypeNameByIndex(fillType))] then
return false
end
end
return true
end
local function hasOwnLoadingStation(placeable, loadStations) local function hasOwnLoadingStation(placeable, loadStations)
for _, station in pairs(loadStations) do for _, station in pairs(loadStations) do
if station.owningPlaceable == placeable then return true end if station.owningPlaceable == placeable and not isFuelOnly(station) then return true end
end end
return false return false
end end
+46 -5
View File
@@ -11,6 +11,17 @@ ADSources.MAX_DISTANCE = 40
-- Paller der står inden for denne afstand af fabrikkens pallespawner tæller som fabrikkens output. -- Paller der står inden for denne afstand af fabrikkens pallespawner tæller som fabrikkens output.
ADSources.PALLET_RADIUS = 25 ADSources.PALLET_RADIUS = 25
-- Staldens egne pallespawnere (hønsehus: æg, fårestald: uld): {[fillType] = spawner}.
local function getHusbandryPalletSpawners(placeable)
local spec = placeable ~= nil and placeable.spec_husbandryPallets or nil
return spec ~= nil and spec.fillTypeIndexToPalletSpawner or nil
end
local function firstSpawnerNode(spawner)
return spawner ~= nil and spawner.spawnPlaces ~= nil and spawner.spawnPlaces[1] ~= nil and spawner.spawnPlaces[1].startNode or nil
end
local function distance2(ax, az, bx, bz) local function distance2(ax, az, bx, bz)
local dx, dz = ax - bx, az - bz local dx, dz = ax - bx, az - bz
return dx * dx + dz * dz return dx * dx + dz * dz
@@ -63,7 +74,10 @@ end
-- Palle eller bulk ved DENNE kilde: silo = bulk; objektlager = palle; fabrik = bulk hvis -- Palle eller bulk ved DENNE kilde: silo = bulk; objektlager = palle; fabrik = bulk hvis
-- markørens læssestation udleverer varen, ellers palle hvis varen er en palletype. -- markørens læssestation udleverer varen, ellers palle hvis varen er en palletype.
function ADSources.isPalletAt(source, fillType) function ADSources.isPalletAt(source, fillType)
if source.kind == "silo" or source.kind == "husbandry" then if source.kind == "husbandry" then
local spawners = getHusbandryPalletSpawners(source.placeable)
return spawners ~= nil and spawners[fillType] ~= nil
elseif source.kind == "silo" then
return false return false
elseif source.kind == "objectStorage" then elseif source.kind == "objectStorage" then
return true return true
@@ -76,11 +90,14 @@ function ADSources.isPalletAt(source, fillType)
return ADSources.isPalletFillType(fillType) return ADSources.isPalletFillType(fillType)
end end
-- Placeable'ns "nærmeste punkt" for kildegenkendelse: pallespawnerens første plads (fabrik) -- Placeable'ns "nærmeste punkt" for kildegenkendelse: pallespawnerens første plads (fabrik,
-- eller rodnoden. -- stald med paller) eller rodnoden.
local function getPlaceableAnchor(placeable) local function getPlaceableAnchor(placeable)
local productionPoint = getProductionPoint(placeable) local productionPoint = getProductionPoint(placeable)
local spawner = productionPoint ~= nil and productionPoint.palletSpawner or nil local spawner = productionPoint ~= nil and productionPoint.palletSpawner or nil
if spawner == nil then
for _, husbandrySpawner in pairs(getHusbandryPalletSpawners(placeable) or {}) do spawner = husbandrySpawner break end
end
local place = spawner ~= nil and spawner.spawnPlaces ~= nil and spawner.spawnPlaces[1] or nil local place = spawner ~= nil and spawner.spawnPlaces ~= nil and spawner.spawnPlaces[1] or nil
local node = place ~= nil and place.startNode or placeable.rootNode local node = place ~= nil and place.startNode or placeable.rootNode
local x, z = getNodePosition(node) local x, z = getNodePosition(node)
@@ -158,6 +175,11 @@ function ADSources.identify(adEnv, wayPointId, farmId)
end end
end end
end end
-- stald med egne pallespawnere (hønsehus: æg) — markøren står ved spawneren, ingen læssestation
local palletBarn = findPlaceableNear(wayPoint, farmId, function(placeable) return placeable.getHusbandryFillLevel ~= nil and getHusbandryPalletSpawners(placeable) ~= nil end)
if palletBarn ~= nil then
return {kind = "husbandry", placeable = palletBarn, station = nil, wayPointId = wayPointId, name = getPlaceableName(palletBarn, markerName)}
end
-- Rene pallefabrikker (halmvarer, bageri ...) har ingen læssestation: find dem på afstand -- Rene pallefabrikker (halmvarer, bageri ...) har ingen læssestation: find dem på afstand
-- til pallespawneren; dernæst objektlagre. -- til pallespawneren; dernæst objektlagre.
local factory = findPlaceableNear(wayPoint, farmId, isProductionPoint) local factory = findPlaceableNear(wayPoint, farmId, isProductionPoint)
@@ -221,10 +243,10 @@ end
-- Liter af varen på paller der står ved fabrikkens spawner (pallespawneren tømmer lageret -- Liter af varen på paller der står ved fabrikkens spawner (pallespawneren tømmer lageret
-- ud på jorden løbende, så det er dér varen fysisk er). -- ud på jorden løbende, så det er dér varen fysisk er).
local function getPalletsNearSpawner(placeable, fillType, farmId) local function getPalletsNearSpawner(placeable, fillType, farmId, spawnerNode)
local productionPoint = getProductionPoint(placeable) local productionPoint = getProductionPoint(placeable)
local spawner = productionPoint ~= nil and productionPoint.palletSpawner or nil local spawner = productionPoint ~= nil and productionPoint.palletSpawner or nil
local node = spawner ~= nil and spawner.spawnPlaces ~= nil and spawner.spawnPlaces[1] ~= nil and spawner.spawnPlaces[1].startNode or placeable.rootNode local node = spawnerNode or (spawner ~= nil and spawner.spawnPlaces ~= nil and spawner.spawnPlaces[1] ~= nil and spawner.spawnPlaces[1].startNode) or placeable.rootNode
local sx, sz = getNodePosition(node) local sx, sz = getNodePosition(node)
if sx == nil then if sx == nil then
return 0 return 0
@@ -369,8 +391,27 @@ local function getNearestTriggerFillTypes(adEnv, source)
return #list > 0 and list or nil return #list > 0 and list or nil
end end
local function getHusbandryPalletProducts(source, farmId)
local products = {}
local spec = source.placeable.spec_husbandryPallets
for fillType, spawner in pairs(getHusbandryPalletSpawners(source.placeable) or {}) do
local liters, count = getPalletsNearSpawner(source.placeable, fillType, farmId, firstSpawnerNode(spawner))
local capacity = spec ~= nil and spec.capacities ~= nil and spec.capacities[fillType] or 0
local product = newProduct(fillType, liters, liters, math.max(capacity or 0, liters), true)
product.palletLiters, product.palletCount = liters, count
table.insert(products, product)
end
table.sort(products, function(a, b) return a.fillType < b.fillType end)
return products
end
local function getHusbandryProducts(adEnv, source) local function getHusbandryProducts(adEnv, source)
local placeable, station = source.placeable, source.station local placeable, station = source.placeable, source.station
local farmId = g_currentMission ~= nil and g_currentMission.getFarmId ~= nil and g_currentMission:getFarmId() or 1
if station == nil then
-- kilde via staldens pallespawner (hønsehus: æg): kun pallevarerne
return getHusbandryPalletProducts(source, farmId)
end
local fillTypes = getNearestTriggerFillTypes(adEnv, source) or {} local fillTypes = getNearestTriggerFillTypes(adEnv, source) or {}
if #fillTypes == 0 then if #fillTypes == 0 then
for fillType, supported in pairs(station ~= nil and station.supportedFillTypes or {}) do for fillType, supported in pairs(station ~= nil and station.supportedFillTypes or {}) do
+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.18.7.0</version> <version>1.18.8.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
+2 -2
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — brugermanual # AD Smart Pickup — brugermanual
Version 1.18.7 · Farming Simulator 25 · tillæg til AutoDrive Version 1.18.8 · Farming Simulator 25 · tillæg til AutoDrive
*English version: [USER_MANUAL.md](USER_MANUAL.md)* *English version: [USER_MANUAL.md](USER_MANUAL.md)*
@@ -285,7 +285,7 @@ Under **Fra** kan du vælge:
|---|---| |---|---|
| **Fabrik** | Fabrikkens outputs, både bulk og paller fra pallespawneren | | **Fabrik** | Fabrikkens outputs, både bulk og paller fra pallespawneren |
| **Silo** | Siloens indhold | | **Silo** | Siloens indhold |
| **Stald** | Mælk, gylle og gødning fra staldens læssepunkter, inklusive tilknyttede udvidelsestanke som Milk Tank Extension | | **Stald** | Mælk, gylle og gødning fra staldens læssepunkter, inklusive tilknyttede udvidelsestanke som Milk Tank Extension. Æg og uld hentes som paller ved staldens pallespawner, fx i hønsehuset. Sæt en markør ved spawneren |
| **Objektlager** | Paller og baller. De tages ud én ad gangen | | **Objektlager** | Paller og baller. De tages ud én ad gangen |
| **Lager** | Andre bygninger med en læssestation, fx Pumps & Hoses' separatorhal med digestat. Varerne læses fra læssestationen | | **Lager** | Andre bygninger med en læssestation, fx Pumps & Hoses' separatorhal med digestat. Varerne læses fra læssestationen |
+2 -2
View File
@@ -1,6 +1,6 @@
# AD Smart Pickup — user manual # AD Smart Pickup — user manual
Version 1.18.7 · Farming Simulator 25 · add-on for AutoDrive Version 1.18.8 · Farming Simulator 25 · add-on for AutoDrive
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)* *Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
@@ -288,7 +288,7 @@ Under **From** you can pick:
|---|---| |---|---|
| **Factory** | The factory's outputs, both bulk and pallets from the pallet spawner | | **Factory** | The factory's outputs, both bulk and pallets from the pallet spawner |
| **Silo** | The silo's contents | | **Silo** | The silo's contents |
| **Barn** | Milk, slurry and manure from the barn's loading points, including attached extension tanks such as Milk Tank Extension | | **Barn** | Milk, slurry and manure from the barn's loading points, including attached extension tanks such as Milk Tank Extension. Eggs and wool are collected as pallets at the barn's pallet spawner, such as the chicken coop's. Place a marker at the spawner |
| **Object storage** | Pallets and bales. They are taken out one at a time | | **Object storage** | Pallets and bales. They are taken out one at a time |
| **Storage** | Other buildings with a loading station, such as the Pumps & Hoses separator hall with digestate. The goods are read from the loading station | | **Storage** | Other buildings with a loading station, such as the Pumps & Hoses separator hall with digestate. The goods are read from the loading station |
+27
View File
@@ -186,5 +186,32 @@ do
check("B-DROP silo beholder sin egen markør (ikke nabosiloens)", byC.silo1.unloadMarker.id, 6) check("B-DROP silo beholder sin egen markør (ikke nabosiloens)", byC.silo1.unloadMarker.id, 6)
end end
-- B-COOP: hønsehus — foder aflæsses i den ene ende, æg-paller spawnes i den anden (ingen læssestation)
do
local coop = placeable("coop1", "Chicken Coop", 10000, 0, {getHusbandryFillLevel = function() return 0 end,
spec_husbandryPallets = {fillTypeIndexToPalletSpawner = {[99] = {spawnPlaces = {{startNode = {x = 10030, z = 0}}}}}}})
table.insert(unloadStations, {owningPlaceable = coop, unloadTriggers = {{exactFillRootNode = {x = 9970, z = 0}}}})
addMarker(61, "Chicken Food", "Chicken", 9965, 0)
addMarker(62, "Egg Pickup", "Chicken", 10035, 0)
ADBuildings.invalidate()
local byCoop = {}
for _, b in ipairs(ADBuildings.list(adEnv, 1)) do byCoop[b.id] = b end
check("B-COOP læssemarkør ved æggene", byCoop.coop1.loadMarker and byCoop.coop1.loadMarker.id, 62)
check("B-COOP aflæsningsmarkør ved foderet", byCoop.coop1.unloadMarker and byCoop.coop1.unloadMarker.id, 61)
end
-- B-FUEL: brændstoftank (læssestation kun med DIESEL) er ikke et lager/en kilde
do
local fmBefore = g_fillTypeManager
g_fillTypeManager = {getFillTypeNameByIndex = function(_, index) return index == 900 and "DIESEL" or "X" end}
local tank = placeable("fuel1", "Small Petrol Tank", 11000, 0, {})
table.insert(loadStations, {owningPlaceable = tank, supportedFillTypes = {[900] = true}, loadTriggers = {{triggerNode = {x = 11000, z = 3}}}})
ADBuildings.invalidate()
local byFuel = {}
for _, b in ipairs(ADBuildings.list(adEnv, 1)) do byFuel[b.id] = b end
check("B-FUEL brændstoftank udeladt", byFuel.fuel1, nil)
g_fillTypeManager = fmBefore
end
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)
+21
View File
@@ -389,6 +389,27 @@ local sepProducts = sepSource and ADSources.getProducts(adEnv, sepSource, 1) or
check("S14d digestat fra stationen", sepProducts[1] and sepProducts[1].fillType, DIGESTATE) check("S14d digestat fra stationen", sepProducts[1] and sepProducts[1].fillType, DIGESTATE)
check("S14d mængde", sepProducts[1] and sepProducts[1].level, 42000) check("S14d mængde", sepProducts[1] and sepProducts[1].level, 42000)
-- S14e: hønsehus — æg kommer som PALLER fra staldens egen pallespawner (spec_husbandryPallets), ingen
-- læssestation ved æggene: markøren ved spawneren er en staldkilde, æggene er pallevarer
local EGGS = 31
DESC[EGGS] = {index = EGGS, name = "EGG", title = "Æg", isPallet = true}
local coopSpawner = {spawnPlaces = {{startNode = {x = 8000, z = 0}}}}
local coop = {rootNode = {x = 8040, z = 0}, ownerFarmId = 1, getOwnerFarmId = function() return 1 end, getName = function() return "Chicken Coop" end,
getHusbandryFillLevel = function() return 0 end,
spec_husbandryPallets = {fillTypeIndexToPalletSpawner = {[EGGS] = coopSpawner}, activeFillTypes = {EGGS}, fillLevels = {[EGGS] = 0}, capacities = {[EGGS] = 5000}}}
table.insert(g_currentMission.placeableSystem.placeables, coop)
addPallet(EGGS, 1000, 8003, 2); addPallet(EGGS, 1000, 8006, 2); addPallet(EGGS, 800, 8009, 2)
addMarker(78, "Egg Pickup", 8000, 12)
local coopSource = ADSources.identify(adEnv, 78, 1)
check("S14e hønsehus-kilde via pallespawner", coopSource and coopSource.kind, "husbandry")
local coopProducts = coopSource and ADSources.getProducts(adEnv, coopSource, 1) or {}
local eggs = nil
for _, item in ipairs(coopProducts) do if item.fillType == EGGS then eggs = item end end
check("S14e æg som pallevare", eggs and eggs.isPallet, true)
check("S14e æg på paller ved spawneren", eggs and eggs.available, 2800)
check("S14e tre paller", eggs and eggs.palletCount, 3)
check("S14e isPalletAt æg", coopSource and ADSources.isPalletAt(coopSource, EGGS), true)
-- S15: forklaring af en markør til advarslen (hvad opslaget ser) -- S15: forklaring af en markør til advarslen (hvad opslaget ser)
check("S15 forklaring stald", ADSources.explainMarker(adEnv, 10, 1), "læssestation ved markøren hører til 'Kostald' (stald)") check("S15 forklaring stald", ADSources.explainMarker(adEnv, 10, 1), "læssestation ved markøren hører til 'Kostald' (stald)")
check("S15 forklaring ingen station", ADSources.explainMarker(adEnv, 4, 1), "ingen læssestation ved markøren, og ingen fabrik/objektlager inden for 40 m") check("S15 forklaring ingen station", ADSources.explainMarker(adEnv, 4, 1), "ingen læssestation ved markøren, og ingen fabrik/objektlager inden for 40 m")