|
|
@@ -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
|
|
|
|
total = total + level
|
|
|
|
if own <= radius2 then
|
|
|
|
count = count + 1
|
|
|
|
if isNearestSpawner(rivals, placeable, own, x, z) then
|
|
|
|
|
|
|
|
total = total + level
|
|
|
|
|
|
|
|
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
|
|
|
|