From 10cbe349679ce3711f4fee081795f7b41e0e3534 Mon Sep 17 00:00:00 2001 From: Peter Vaiko Date: Sat, 29 Jul 2023 02:23:00 -0400 Subject: [PATCH] fix: self unload trailer search Use the actual field polygon to find trailers on or near the field, instead of the CpFieldUtil functions as they go indirectly through the farmland ID to find the field ID which may give false positives if the farmland is significantly bigger than the field. #2663 --- scripts/ai/SelfUnloadHelper.lua | 19 ++++++++++++------- scripts/field/CpFieldUtil.lua | 9 ++++++--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/scripts/ai/SelfUnloadHelper.lua b/scripts/ai/SelfUnloadHelper.lua index f2b195e0e..dbc661688 100644 --- a/scripts/ai/SelfUnloadHelper.lua +++ b/scripts/ai/SelfUnloadHelper.lua @@ -23,6 +23,8 @@ SelfUnloadHelper = {} SelfUnloadHelper.debugChannel = CpDebug.DBG_FIELDWORK -- keep the helper nodes we create in this table for each vehicle so no nodes need to be created/destroyed SelfUnloadHelper.bestFillNodes = {} +-- search for trailers within this distance from the field +SelfUnloadHelper.maxDistanceFromField = 20 ------ Find a trailer we can use for self unloading function SelfUnloadHelper:findBestTrailer(fieldPolygon, myVehicle, fillType, pipeOffsetX) @@ -36,20 +38,23 @@ function SelfUnloadHelper:findBestTrailer(fieldPolygon, myVehicle, fillType, pip if SpecializationUtil.hasSpecialization(Attachable, otherVehicle.specializations) then attacherVehicle = otherVehicle.spec_attachable:getAttacherVehicle() end - local fieldNum = CpFieldUtil.getFieldNumUnderVehicle(otherVehicle) - local myFieldNum = CpFieldUtil.getFieldNumUnderVehicle(myVehicle) local x, _, z = getWorldTranslation(otherVehicle.rootNode) local closestDistance = CpMathUtil.getClosestDistanceToPolygonEdge(fieldPolygon, x, z) + -- if the trailer is within 20 m of the field perimeter, we are good + local isOnField = closestDistance <= SelfUnloadHelper.maxDistanceFromField + if not isOnField then + -- not within 20 m, but could still be on the field + isOnField = CpMathUtil.isPointInPolygon(fieldPolygon, x, z) + end local lastSpeed = rootVehicle:getLastSpeed() local isCpActive = rootVehicle.getIsCpActive and rootVehicle:getIsCpActive() CpUtil.debugVehicle(self.debugChannel, myVehicle, - '%s is a trailer on field %d, closest distance to %d is %.1f, attached to %s, root vehicle is %s, last speed %.1f, CP active %s', - otherVehicle:getName(), fieldNum, myFieldNum, closestDistance, attacherVehicle and attacherVehicle:getName() or 'none', + '%s is a trailer %s on my field, closest distance to %d is %.1f, attached to %s, root vehicle is %s, last speed %.1f, CP active %s', + otherVehicle:getName(), isOnField and '' or 'NOT', closestDistance, attacherVehicle and attacherVehicle:getName() or 'none', rootVehicle:getName(), lastSpeed, isCpActive) -- consider only trailer on my field or close to my field, not driven by CP and stopped - if rootVehicle ~= myVehicle and not isCpActive and lastSpeed < 0.1 and - (fieldNum == myFieldNum or myFieldNum == 0 or closestDistance < 20) - and not self:isInvalidAutoDriveTarget(myVehicle, rootVehicle) then + if rootVehicle ~= myVehicle and not isCpActive and lastSpeed < 0.1 and isOnField and + not self:isInvalidAutoDriveTarget(myVehicle, rootVehicle) then local d = calcDistanceFrom(myVehicle:getAIDirectionNode(), otherVehicle.rootNode or otherVehicle.nodeId) local canLoad, freeCapacity, fillUnitIndex = FillLevelManager.canLoadTrailer(otherVehicle, fillType) if d < minDistance and canLoad then diff --git a/scripts/field/CpFieldUtil.lua b/scripts/field/CpFieldUtil.lua index 888685f9a..b1c4f5af8 100644 --- a/scripts/field/CpFieldUtil.lua +++ b/scripts/field/CpFieldUtil.lua @@ -51,7 +51,7 @@ end --- Which field this node is on. ---@param node table Giants engine node ----@return number 0 if not on any field, otherwise the number of field, see note on getFieldItAtWorldPosition() +---@return number 0 if not on any field, otherwise the number of field, see note on getFieldIdAtWorldPosition() function CpFieldUtil.getFieldNumUnderNode(node) local x, _, z = getWorldTranslation(node) return CpFieldUtil.getFieldIdAtWorldPosition(x, z) @@ -62,8 +62,11 @@ function CpFieldUtil.getFieldNumUnderVehicle(vehicle) return CpFieldUtil.getFieldNumUnderNode(vehicle.rootNode) end ---- Returns the field ID (actually, land ID) for a position. The land is what you can buy in the game, ---- including the area around an actual field. +--- Returns a field ID for a position. This really is the ID of the first field which is +--- on the same farmland where the given position is. The farmland is what you can buy in the game, +--- including the area around an actual field, and may extend well beyond the actual field. +--- So do not use this the determine the field ID of a given position, as this does not guarantee +--- that the position is actually on a field. function CpFieldUtil.getFieldIdAtWorldPosition(posX, posZ) local farmland = g_farmlandManager:getFarmlandAtWorldPosition(posX, posZ) if farmland ~= nil then