fix: æg-markør genkendes som hønsehus når det er nærmere end en løs læssestation (Pickup 1+2 blev Pigsty); palletildeling måler til hele spawn-området (alle rækker, start-slut) (v1.28.2.0)

This commit is contained in:
2026-09-26 11:52:22 +02:00
parent cb68c81a3f
commit 725ad7b459
4 changed files with 116 additions and 33 deletions
+1 -1
View File
@@ -257,7 +257,7 @@ function ADSmartPickup.getLoadStationNearWayPointId(adEnv, wayPointId, farmId, m
end end
end end
end end
return best return best, best ~= nil and bestDistance or nil
end end
-- Siloens EGET indhold. Udvidelses-siloer (isExtension) deler lager med naboer -- Siloens EGET indhold. Udvidelses-siloer (isExtension) deler lager med naboer
+74 -29
View File
@@ -24,10 +24,6 @@ local function getHusbandryPalletSpawners(placeable)
return spec ~= nil and spec.fillTypeIndexToPalletSpawner or nil return spec ~= nil and spec.fillTypeIndexToPalletSpawner or nil
end 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
@@ -130,7 +126,8 @@ local function findPlaceableNear(wayPoint, farmId, predicate)
end end
end end
end end
return best -- (afstand i meter som 2. værdi)
return best, best ~= nil and math.sqrt(bestDistance) or nil
end end
local function isObjectStorage(placeable) local function isObjectStorage(placeable)
@@ -177,9 +174,15 @@ function ADSources.identifyUncached(adEnv, wayPointId, farmId)
end end
-- Det strenge opslag (trigger bag næsen) passer til silorækker; en mælketank eller fabrik ligger -- Det strenge opslag (trigger bag næsen) passer til silorækker; en mælketank eller fabrik ligger
-- ofte ved siden af markøren. Løst opslag inden for 40 m — men aldrig for siloer. -- ofte ved siden af markøren. Løst opslag inden for 40 m — men aldrig for siloer.
-- stald med egne pallespawnere (hønsehus: æg) — markøren står ved spawneren, ingen læssestation
local palletBarn, palletBarnDistance = findPlaceableNear(wayPoint, farmId, function(placeable) return placeable.getHusbandryFillLevel ~= nil and getHusbandryPalletSpawners(placeable) ~= nil end)
if placeable == nil and ADSmartPickup.getLoadStationNearWayPointId ~= nil then if placeable == nil and ADSmartPickup.getLoadStationNearWayPointId ~= nil then
local loose = ADSmartPickup.getLoadStationNearWayPointId(adEnv, wayPointId, farmId, ADSources.MAX_DISTANCE) local loose, looseDistance = ADSmartPickup.getLoadStationNearWayPointId(adEnv, wayPointId, farmId, ADSources.MAX_DISTANCE)
local loosePlaceable = loose ~= nil and loose.owningPlaceable or nil local loosePlaceable = loose ~= nil and loose.owningPlaceable or nil
-- et nærmere hønsehus vinder over en fjernere læssestation (gyllestation 23 m fra "Æg Pickup 1")
if palletBarn ~= nil and looseDistance ~= nil and palletBarnDistance ~= nil and palletBarnDistance < looseDistance then
loosePlaceable = nil
end
if loosePlaceable ~= nil and loosePlaceable.spec_silo == nil then if loosePlaceable ~= nil and loosePlaceable.spec_silo == nil then
if getProductionPoint(loosePlaceable) ~= nil then if getProductionPoint(loosePlaceable) ~= nil then
return {kind = "factory", placeable = loosePlaceable, station = loose, wayPointId = wayPointId, name = getPlaceableName(loosePlaceable, markerName)} return {kind = "factory", placeable = loosePlaceable, station = loose, wayPointId = wayPointId, name = getPlaceableName(loosePlaceable, markerName)}
@@ -188,8 +191,6 @@ function ADSources.identifyUncached(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 if palletBarn ~= nil then
return {kind = "husbandry", placeable = palletBarn, station = nil, wayPointId = wayPointId, name = getPlaceableName(palletBarn, markerName)} return {kind = "husbandry", placeable = palletBarn, station = nil, wayPointId = wayPointId, name = getPlaceableName(palletBarn, markerName)}
end end
@@ -254,55 +255,99 @@ local function getPalletContent(vehicle)
return nil, 0 return nil, 0
end end
-- Liter af varen på paller der står ved fabrikkens spawner (pallespawneren tømmer lageret -- Spawnerens område som segmenter {ax, az, bx, bz}: hver spawnPlace fra start til slut (startNode/endNode,
-- ud på jorden løbende, så det er dér varen fysisk er). -- eller PlacementUtil-felterne startX/startZ + dirX/dirZ*width). Et hønsehus har to rækker; måles kun
-- Alle andre pallespawnere der kan lave varen (stalde med spawner for fillType, fabrikkers -- til første række, ligger den anden række tættere på naboens start end husets egen.
-- pallespawner): {{x, z}, ...}. Står bygningerne tættere end PALLET_RADIUS (hønsehuse på række), local function spawnerSegments(spawner)
-- tilhører en palle den nærmeste spawner — ellers tæller et tomt hus naboernes paller med. local segments = {}
for _, place in ipairs(spawner ~= nil and spawner.spawnPlaces or {}) do
local ax, az = getNodePosition(place.startNode)
local bx, bz = getNodePosition(place.endNode)
if ax == nil and place.startX ~= nil and place.startZ ~= nil then
ax, az = place.startX, place.startZ
if place.dirX ~= nil and place.dirZ ~= nil and place.width ~= nil then
bx, bz = ax + place.dirX * place.width, az + place.dirZ * place.width
end
end
if ax ~= nil then table.insert(segments, {ax, az, bx or ax, bz or az}) end
end
return segments
end
-- Kvadreret afstand fra (x, z) til nærmeste punkt på et af segmenterne.
local function segmentsDistance2(segments, x, z)
local best = math.huge
for _, s in ipairs(segments) do
local ax, az, bx, bz = s[1], s[2], s[3], s[4]
local dx, dz = bx - ax, bz - az
local len2 = dx * dx + dz * dz
local t = len2 > 0 and math.max(0, math.min(1, ((x - ax) * dx + (z - az) * dz) / len2)) or 0
local d = distance2(x, z, ax + dx * t, az + dz * t)
if d < best then best = d end
end
return best
end
-- Alle pallespawnere der kan lave varen (stalde med spawner for fillType, fabrikkers pallespawner) som
-- {placeable, segments}. Står bygningerne tættere end PALLET_RADIUS (hønsehuse på række), tilhører en
-- palle den spawner hvis område er nærmest — ellers tæller et tomt hus naboernes paller med.
local function findRivalSpawners(fillType) local function findRivalSpawners(fillType)
local rivals = {} local rivals = {}
local placeables = g_currentMission ~= nil and g_currentMission.placeableSystem ~= nil and g_currentMission.placeableSystem.placeables or {} local placeables = g_currentMission ~= nil and g_currentMission.placeableSystem ~= nil and g_currentMission.placeableSystem.placeables or {}
for _, placeable in pairs(placeables) do for _, placeable in pairs(placeables) do
local husbandrySpawners = getHusbandryPalletSpawners(placeable) local husbandrySpawners = getHusbandryPalletSpawners(placeable)
local productionPoint = getProductionPoint(placeable) local productionPoint = getProductionPoint(placeable)
local node = firstSpawnerNode(husbandrySpawners ~= nil and husbandrySpawners[fillType] or nil) local spawner = husbandrySpawners ~= nil and husbandrySpawners[fillType] or (productionPoint ~= nil and productionPoint.palletSpawner or nil)
or firstSpawnerNode(productionPoint ~= nil and productionPoint.palletSpawner or nil) local segments = spawnerSegments(spawner)
local x, z = getNodePosition(node) if #segments > 0 then table.insert(rivals, {placeable = placeable, segments = segments}) end
if x ~= nil then table.insert(rivals, {x = x, z = z}) end
end end
return rivals return rivals
end end
local function isNearestSpawner(rivals, sx, sz, x, z) local function isNearestSpawner(rivals, placeable, own, x, z)
local own = distance2(sx, sz, x, z)
for _, rival in ipairs(rivals) do for _, rival in ipairs(rivals) do
if distance2(rival.x, rival.z, x, z) < own then return false end if rival.placeable ~= placeable and segmentsDistance2(rival.segments, x, z) < own then return false end
end end
return true return true
end end
local function getPalletsNearSpawner(placeable, fillType, farmId, spawnerNode) ADSources.lastPalletNote = {}
-- Liter af varen på paller ved spawneren (pallespawneren tømmer lageret ud på jorden løbende, så
-- det er dér varen fysisk er). spawner = staldens spawner for varen; nil = fabrikkens pallespawner.
local function getPalletsNearSpawner(placeable, fillType, farmId, spawner)
local productionPoint = getProductionPoint(placeable) local productionPoint = getProductionPoint(placeable)
local spawner = productionPoint ~= nil and productionPoint.palletSpawner or nil local segments = spawnerSegments(spawner or (productionPoint ~= nil and productionPoint.palletSpawner or nil))
local node = spawnerNode or (spawner ~= nil and spawner.spawnPlaces ~= nil and spawner.spawnPlaces[1] ~= nil and spawner.spawnPlaces[1].startNode) or placeable.rootNode if #segments == 0 then
local sx, sz = getNodePosition(node) local rx, rz = getNodePosition(placeable.rootNode)
if sx == nil then if rx == nil then return 0, 0 end
return 0 segments = {{rx, rz, rx, rz}}
end end
local rivals = cacheGet("palletSpawners", fillType, 10000, function() return findRivalSpawners(fillType) end) local rivals = cacheGet("palletSpawners", fillType, 10000, function() return findRivalSpawners(fillType) end)
local vehicles = g_currentMission ~= nil and g_currentMission.vehicleSystem ~= nil and g_currentMission.vehicleSystem.vehicles or {} local vehicles = g_currentMission ~= nil and g_currentMission.vehicleSystem ~= nil and g_currentMission.vehicleSystem.vehicles or {}
local total, count = 0, 0 local total, count, lost = 0, 0, 0
local radius2 = ADSources.PALLET_RADIUS * ADSources.PALLET_RADIUS local radius2 = ADSources.PALLET_RADIUS * ADSources.PALLET_RADIUS
for _, vehicle in pairs(vehicles) do for _, vehicle in pairs(vehicles) do
if isPalletVehicle(vehicle) and (vehicle.getOwnerFarmId == nil or vehicle:getOwnerFarmId() == farmId) then if isPalletVehicle(vehicle) and (vehicle.getOwnerFarmId == nil or vehicle:getOwnerFarmId() == farmId) then
local palletFillType, level = getPalletContent(vehicle) local palletFillType, level = getPalletContent(vehicle)
local x, z = getNodePosition(vehicle.rootNode) local x, z = getNodePosition(vehicle.rootNode)
if palletFillType == fillType and x ~= nil and distance2(sx, sz, x, z) <= radius2 and isNearestSpawner(rivals, sx, sz, x, z) then local own = (palletFillType == fillType and x ~= nil) and segmentsDistance2(segments, x, z) or math.huge
if own <= radius2 then
if isNearestSpawner(rivals, placeable, own, x, z) then
total = total + level total = total + level
count = count + 1 count = count + 1
else
lost = lost + 1
end end
end end
end end
end
-- diagnose: paller inden for rækkevidde, men alle tildelt en nabo (højst én gang pr. minut pr. bygning)
local now = g_currentMission ~= nil and g_currentMission.time or nil
if count == 0 and lost > 0 and now ~= nil and (ADSources.lastPalletNote[placeable] or -math.huge) + 60000 < now then
ADSources.lastPalletNote[placeable] = now
Logging.info(ADSources.LOG_PREFIX .. "%s: %d paller inden for %d m tilhører nabo-spawnere (0 egne)", getPlaceableName(placeable, "?"), lost, ADSources.PALLET_RADIUS)
end
return total, count return total, count
end end
@@ -434,7 +479,7 @@ local function getHusbandryPalletProducts(source, farmId)
local products = {} local products = {}
local spec = source.placeable.spec_husbandryPallets local spec = source.placeable.spec_husbandryPallets
for fillType, spawner in pairs(getHusbandryPalletSpawners(source.placeable) or {}) do for fillType, spawner in pairs(getHusbandryPalletSpawners(source.placeable) or {}) do
local liters, count = getPalletsNearSpawner(source.placeable, fillType, farmId, firstSpawnerNode(spawner)) local liters, count = getPalletsNearSpawner(source.placeable, fillType, farmId, spawner)
local capacity = spec ~= nil and spec.capacities ~= nil and spec.capacities[fillType] or 0 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) local product = newProduct(fillType, liters, liters, math.max(capacity or 0, liters), true)
product.palletLiters, product.palletCount = liters, count product.palletLiters, product.palletCount = liters, count
+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.28.1.0</version> <version>1.28.2.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
+38
View File
@@ -438,6 +438,31 @@ check("S14f tomt hus 0 paller", eggsAt(emptyCoop).palletCount, 0)
table.remove(g_currentMission.placeableSystem.placeables) table.remove(g_currentMission.placeableSystem.placeables)
table.remove(g_currentMission.placeableSystem.placeables) table.remove(g_currentMission.placeableSystem.placeables)
-- S14g: spawnerens område er ALLE rækker fra start til slut — ikke kun første rækkes start. Hus A's
-- række 2 slutter tæt på hus B's start; en palle for enden af A's række 2 er stadig A's.
local rowA = {spawnPlaces = {{startNode = {x = 9000, z = 0}, endNode = {x = 9008, z = 0}}, {startNode = {x = 9000, z = 3}, endNode = {x = 9008, z = 3}}}}
local rowB = {spawnPlaces = {{startNode = {x = 9014, z = 3}, endNode = {x = 9022, z = 3}}}}
local function rowCoop(spawner, x)
return {rootNode = {x = x, z = -10}, ownerFarmId = 1, getOwnerFarmId = function() return 1 end, getName = function() return "Chicken Coop" end,
getHusbandryFillLevel = function() return 0 end,
spec_husbandryPallets = {fillTypeIndexToPalletSpawner = {[EGGS] = spawner}, activeFillTypes = {EGGS}, fillLevels = {[EGGS] = 0}, capacities = {[EGGS] = 5000}}}
end
local coopA, coopB = rowCoop(rowA, 9004), rowCoop(rowB, 9018)
table.insert(g_currentMission.placeableSystem.placeables, coopA)
table.insert(g_currentMission.placeableSystem.placeables, coopB)
addPallet(EGGS, 1000, 9008, 3) -- enden af A's række 2: 6 m til B's start, 8 m til A's første start
check("S14g palle for enden af egen række 2 er husets egen", eggsAt(coopA).available, 1000)
check("S14g naboen får den ikke", eggsAt(coopB).available, 0)
-- PlacementUtil-form (startX/startZ + dirX/dirZ*width) i stedet for noder
local placeC = {spawnPlaces = {{startX = 9000, startZ = 50, dirX = 1, dirZ = 0, width = 8}}}
local coopC = rowCoop(placeC, 9004)
table.insert(g_currentMission.placeableSystem.placeables, coopC)
addPallet(EGGS, 700, 9007, 51)
check("S14g PlacementUtil-plads tæller", eggsAt(coopC).available, 700)
table.remove(g_currentMission.placeableSystem.placeables)
table.remove(g_currentMission.placeableSystem.placeables)
table.remove(g_currentMission.placeableSystem.placeables)
-- 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")
@@ -457,6 +482,19 @@ looseAt[13] = siloStation
check("S16 silo aldrig via løst opslag", ADSources.identify(adEnv, 13, 1), nil) check("S16 silo aldrig via løst opslag", ADSources.identify(adEnv, 13, 1), nil)
check("S16 forklaring nævner den løse station", ADSources.explainMarker(adEnv, 13, 1):find("silo", 1, true) ~= nil, true) check("S16 forklaring nævner den løse station", ADSources.explainMarker(adEnv, 13, 1):find("silo", 1, true) ~= nil, true)
-- S16b: "Æg Pickup 1" står 12 m fra hønsehusets palleområde og 23 m fra svinestaldens gyllestation;
-- det nærmeste vinder (in-game 26/9: Pickup 1+2 blev genkendt som Pigsty og æggene aldrig hentet)
local looseDistance = {}
ADSmartPickup.getLoadStationNearWayPointId = function(_, id, farmId, maxDistance) return looseAt[id], looseDistance[id] end
local pigStation = {owningPlaceable = cowBarn}
addMarker(14, "Æg Pickup 1", 8000, 12)
looseAt[14], looseDistance[14] = pigStation, 23
local eggSource = ADSources.identify(adEnv, 14, 1)
check("S16b hønsehuset vinder over fjernere gyllestation", eggSource and eggSource.placeable, coop)
addMarker(15, "Slurry ved hønsehus", 8000, 30)
looseAt[15], looseDistance[15] = pigStation, 5
check("S16b nærmere gyllestation vinder stadig", ADSources.identify(adEnv, 15, 1).placeable, cowBarn)
-- S17: stald med ÉN station og TO læssepunkter (mælk i den ene ende, gylle i den anden): hver markør -- S17: stald med ÉN station og TO læssepunkter (mælk i den ene ende, gylle i den anden): hver markør
-- giver kun de varer dens nærmeste læssepunkt udleverer (in-game 24/9, LargerAnimalBarns cowBarnBig) -- giver kun de varer dens nærmeste læssepunkt udleverer (in-game 24/9, LargerAnimalBarns cowBarnBig)
local SLURRY = 13 local SLURRY = 13