Skip to content

Commit

Permalink
fix: self unload trailer search
Browse files Browse the repository at this point in the history
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
  • Loading branch information
pvaiko committed Jul 29, 2023
1 parent 86d2c48 commit 10cbe34
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 10 deletions.
19 changes: 12 additions & 7 deletions scripts/ai/SelfUnloadHelper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
9 changes: 6 additions & 3 deletions scripts/field/CpFieldUtil.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit 10cbe34

Please sign in to comment.