LUADOC - Farming Simulator 22

AIVehicleUtil

Description
Util class for various ai vehicle functions
Functions

driveAlongCurvature

Description
Definition
driveAlongCurvature()
Code
101function AIVehicleUtil.driveAlongCurvature(self, dt, curvature, maxSpeed, acceleration)
102 local targetRotTime = self:getSteeringRotTimeByCurvature(curvature)
103
104-- if targetRotTime > self.rotatedTime then
105-- self.rotatedTime = math.min(self.rotatedTime + dt*self:getAISteeringSpeed(), targetRotTime)
106-- else
107-- self.rotatedTime = math.max(self.rotatedTime - dt*self:getAISteeringSpeed(), targetRotTime)
108-- end
109
110 self.rotatedTime = -targetRotTime
111
112 if self.finishedFirstUpdate then
113 local acc = acceleration
114 if maxSpeed ~= nil and maxSpeed > 0 then
115 self:getMotor():setSpeedLimit(maxSpeed)
116
117 if self:getCruiseControlState() ~= Drivable.CRUISECONTROL_STATE_ACTIVE then
118 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_ACTIVE)
119 end
120 else
121 acc = 0
122 end
123
124 WheelsUtil.updateWheelsPhysics(self, dt, self.lastSpeedReal*self.movingDirection, acc, maxSpeed > 0, true)
125 end
126end

driveInDirection

Description
Drive in given direction
Definition
driveInDirection(table self, float dt, float steeringAngleLimit, float acceleration, float slowAcceleration, float slowAngleLimit, boolean allowedToDrive, boolean moveForwards, float lx, float lz, float maxSpeed, float slowDownFactor)
Arguments
tableselfobject of vehicle
floatdttime since last call in ms
floatsteeringAngleLimitlimit for steering angle
floataccelerationacceleration
floatslowAccelerationslow acceleration
floatslowAngleLimitlimit of slow angle
booleanallowedToDriveallow to drive
booleanmoveForwardsmove forwards
floatlxx direction
floatlzz direction
floatmaxSpeedmax speed
floatslowDownFactorslow down factor
Code
143function AIVehicleUtil.driveInDirection(self, dt, steeringAngleLimit, acceleration, slowAcceleration, slowAngleLimit, allowedToDrive, moveForwards, lx, lz, maxSpeed, slowDownFactor)
144
145 local angle = 0
146 if lx ~= nil and lz ~= nil then
147 local dot = lz
148 angle = math.deg(math.acos(dot))
149 if angle < 0 then
150 angle = angle+180
151 end
152
153 local turnLeft = lx > 0.00001
154 if not moveForwards then
155 turnLeft = not turnLeft
156 end
157
158 local targetRotTime
159 if turnLeft then
160 --rotate to the left
161 targetRotTime = self.maxRotTime*math.min(angle/steeringAngleLimit, 1)
162 else
163 --rotate to the right
164 targetRotTime = self.minRotTime*math.min(angle/steeringAngleLimit, 1)
165 end
166
167 if targetRotTime > self.rotatedTime then
168 self.rotatedTime = math.min(self.rotatedTime + dt*self:getAISteeringSpeed(), targetRotTime)
169 else
170 self.rotatedTime = math.max(self.rotatedTime - dt*self:getAISteeringSpeed(), targetRotTime)
171 end
172 end
173
174
175 if self.finishedFirstUpdate then
176 local acc = acceleration
177 if maxSpeed ~= nil and maxSpeed ~= 0 then
178 if math.abs(angle) >= slowAngleLimit then
179 maxSpeed = maxSpeed * slowDownFactor
180 end
181 self.motor:setSpeedLimit(maxSpeed)
182
183 if self.cruiseControl.state ~= Drivable.CRUISECONTROL_STATE_ACTIVE then
184 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_ACTIVE)
185 end
186 else
187 if math.abs(angle) >= slowAngleLimit then
188 acc = slowAcceleration
189 end
190 end
191 if not allowedToDrive then
192 acc = 0
193 end
194 if not moveForwards then
195 acc = -acc
196 end
197 WheelsUtil.updateWheelsPhysics(self, dt, self.lastSpeedReal*self.movingDirection, acc, not allowedToDrive, true)
198 end
199end

driveToPoint

Description
Drive vehicle to given point
Definition
driveToPoint(table self, float dt, float acceleration, boolean allowedToDrive, boolean moveForwards, float tX, float tY, float maxSpeed, boolean doNotSteer)
Arguments
tableselfobject of vehicle to move
floatdttime since last call in ms
floataccelerationacceleration
booleanallowedToDriveallowed to drive
booleanmoveForwardsmove forwards
floattXlocal space x position
floattYlocal space y position
floatmaxSpeedspeed limit
booleandoNotSteerdo not steer
Code
26function AIVehicleUtil.driveToPoint(self, dt, acceleration, allowedToDrive, moveForwards, tX, tZ, maxSpeed, doNotSteer)
27 if self.finishedFirstUpdate then
28
29 if allowedToDrive then
30
31 local tX_2 = tX * 0.5
32 local tZ_2 = tZ * 0.5
33
34 local d1X, d1Z = tZ_2, -tX_2
35 if tX > 0 then
36 d1X, d1Z = -tZ_2, tX_2
37 end
38
39 local hit,_,f2 = MathUtil.getLineLineIntersection2D(tX_2,tZ_2, d1X,d1Z, 0,0, tX, 0)
40
41 if doNotSteer == nil or not doNotSteer then
42 local rotTime = 0
43 if hit and math.abs(f2) < 100000 then
44 local radius = tX * f2
45 rotTime = self:getSteeringRotTimeByCurvature(1 / radius)
46
47 if self:getReverserDirection() < 0 then
48 rotTime = -rotTime
49 end
50
51 --rotTime = self.wheelSteeringDuration * ( math.atan(1/radius) / math.atan(1/self.maxTurningRadius) )
52 end
53
54 local targetRotTime
55 if rotTime >= 0 then
56 targetRotTime = math.min(rotTime, self.maxRotTime)
57 else
58 targetRotTime = math.max(rotTime, self.minRotTime)
59 end
60
61 if targetRotTime > self.rotatedTime then
62 self.rotatedTime = math.min(self.rotatedTime + dt*self:getAISteeringSpeed(), targetRotTime)
63 else
64 self.rotatedTime = math.max(self.rotatedTime - dt*self:getAISteeringSpeed(), targetRotTime)
65 end
66
67 -- adjust maxSpeed
68 local steerDiff = targetRotTime - self.rotatedTime
69 local fac = math.abs(steerDiff) / math.max(self.maxRotTime, -self.minRotTime)
70 local speedReduction = 1.0 - math.pow(fac, 0.25)
71
72 -- if the speed is decreased to less than 1 km/h we do not accelrate anymore
73 if maxSpeed * speedReduction < 1 then
74 acceleration = 0
75 speedReduction = 1 / maxSpeed
76 end
77
78 maxSpeed = maxSpeed * speedReduction
79 end
80 end
81
82 self:getMotor():setSpeedLimit(math.min(maxSpeed, self:getCruiseControlSpeed()))
83 if self:getCruiseControlState() ~= Drivable.CRUISECONTROL_STATE_ACTIVE then
84 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_ACTIVE)
85 end
86
87 if not allowedToDrive then
88 acceleration = 0
89 end
90 if not moveForwards then
91 acceleration = -acceleration
92 end
93
94 WheelsUtil.updateWheelsPhysics(self, dt, self.lastSpeedReal*self.movingDirection, acceleration, not allowedToDrive, true)
95
96 end
97end

getAIAreaOfVehicle

Description
Returns amount of fruit to work for ai vehicle is in given area
Definition
getAIAreaOfVehicle(table vehicle, float startWorldX, float startWorldZ, float widthWorldX, float widthWorldZ, float heightWorldX, float heightWorldZ)
Arguments
tablevehiclevehicle
floatstartWorldXstart world x
floatstartWorldZstart world z
floatwidthWorldXwidth world x
floatwidthWorldZwidth world z
floatheightWorldXheight world x
floatheightWorldZheight world z
Return Values
floatareaarea found
floattotalAreatotal area checked
Code
634function AIVehicleUtil.getAIAreaOfVehicle(vehicle, startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ)
635 local useDensityHeightMap = #vehicle:getAIDensityHeightTypeRequirements() > 0
636
637 if not useDensityHeightMap then
638 local query, isValid = vehicle:getFieldCropsQuery()
639 if isValid then
640 return AIVehicleUtil.getAIFruitArea(startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ, query)
641 else
642 return 0, 0
643 end
644 else
645 local densityHeightTypeRequirements = vehicle:getAIDensityHeightTypeRequirements()
646 return AIVehicleUtil.getAIDensityHeightArea(startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ, densityHeightTypeRequirements)
647 end
648end

getAIDensityHeightArea

Description
Returns amount of density height to work is in given area
Definition
getAIDensityHeightArea(float startWorldX, float startWorldZ, float widthWorldX, float widthWorldZ, float heightWorldX, float heightWorldZ, table fruitRequirements, boolean useWindrowed)
Arguments
floatstartWorldXstart world x
floatstartWorldZstart world z
floatwidthWorldXwidth world x
floatwidthWorldZwidth world z
floatheightWorldXheight world x
floatheightWorldZheight world z
tablefruitRequirementstable with all required fruit types
booleanuseWindroweduse windrow
Return Values
floatareaarea found
floattotalAreatotal area checked
Code
678function AIVehicleUtil.getAIDensityHeightArea(startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ, densityHeightTypeRequirements)
679 -- first check if we are on a field
680 local _, detailArea, _ = FSDensityMapUtil.getFieldDensity(startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ)
681 if detailArea == 0 then
682 return 0, 0
683 end
684
685 local retArea, retTotalArea = 0, 0
686 for _, densityHeightTypeRequirement in pairs(densityHeightTypeRequirements) do
687 if densityHeightTypeRequirement.fillType ~= FillType.UNKNOWN then
688 local _, area, totalArea = DensityMapHeightUtil.getFillLevelAtArea(densityHeightTypeRequirement.fillType, startWorldX,startWorldZ, widthWorldX,widthWorldZ, heightWorldX,heightWorldZ)
689 retArea, retTotalArea = retArea+area, totalArea
690 end
691 end
692
693 return retArea, retTotalArea
694end

getAIFruitArea

Description
Returns amount of fruit to work is in given area
Definition
getAIFruitArea(float startWorldX, float startWorldZ, float widthWorldX, float widthWorldZ, float heightWorldX, float heightWorldZ, table query)
Arguments
floatstartWorldXstart world x
floatstartWorldZstart world z
floatwidthWorldXwidth world x
floatwidthWorldZwidth world z
floatheightWorldXheight world x
floatheightWorldZheight world z
tablequeryfield crops query of vehicle
Return Values
floatareaarea found
floattotalAreatotal area checked
Code
661function AIVehicleUtil.getAIFruitArea(startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ, query)
662 local x,z, widthX,widthZ, heightX,heightZ = MathUtil.getXZWidthAndHeight(startWorldX, startWorldZ, widthWorldX, widthWorldZ, heightWorldX, heightWorldZ)
663 return query:getParallelogram(x,z, widthX,widthZ, heightX,heightZ, false)
664end

getAIToolReverserDirectionNode

Description
Returns reverser direction node of attached ai tool
Definition
getAIToolReverserDirectionNode(table vehicle)
Arguments
tablevehiclevehicle to check
Return Values
integeraiToolReverserDirectionNodereverser direction node of ai tool
Code
335function AIVehicleUtil.getAIToolReverserDirectionNode(vehicle)
336 for _, implement in pairs(vehicle:getAttachedImplements()) do
337 if implement.object ~= nil and implement.object.getAIToolReverserDirectionNode ~= nil then
338 local reverserNode = implement.object:getAIToolReverserDirectionNode()
339
340 local attachedReverserNode = AIVehicleUtil.getAIToolReverserDirectionNode(implement.object)
341 reverserNode = reverserNode or attachedReverserNode
342
343 if reverserNode ~= nil then
344 return reverserNode
345 end
346 end
347 end
348end

getAreaDimensions

Description
Definition
getAreaDimensions()
Code
588function AIVehicleUtil.getAreaDimensions(directionX, directionZ, leftNode, rightNode, xOffset, zOffset, areaSize, invertXOffset)
589 local xOffsetLeft, xOffsetRight = xOffset, xOffset
590 if invertXOffset == nil or invertXOffset then
591 xOffsetLeft = -xOffsetLeft
592 end
593 local lX, _, lZ = localToWorld(leftNode, xOffsetLeft, 0, zOffset)
594 local rX, _, rZ = localToWorld(rightNode, xOffsetRight, 0, zOffset)
595
596 local sX = lX - (0.5 * directionX)
597 local sZ = lZ - (0.5 * directionZ)
598 local wX = rX - (0.5 * directionX)
599 local wZ = rZ - (0.5 * directionZ)
600 local hX = lX + (areaSize * directionX)
601 local hZ = lZ + (areaSize * directionZ)
602
603 return sX, sZ, wX, wZ, hX, hZ
604end

getAttachedImplementsAllowTurnBackward

Description
Returns if trailer or trailer low is attached
Definition
getAttachedImplementsAllowTurnBackward(table vehicle)
Arguments
tablevehiclevehicle to check
Return Values
booleanisAttachedis attached
Code
247function AIVehicleUtil.getAttachedImplementsAllowTurnBackward(vehicle)
248 if vehicle.getAIAllowTurnBackward ~= nil then
249 if not vehicle:getAIAllowTurnBackward() then
250 return false
251 end
252 end
253
254 if vehicle.getAttachedImplements ~= nil then
255 for _, implement in pairs(vehicle:getAttachedImplements()) do
256 local object = implement.object
257 if object ~= nil then
258 if object.getAIAllowTurnBackward ~= nil then
259 if not object:getAIAllowTurnBackward() then
260 return false
261 end
262 end
263
264 if not AIVehicleUtil.getAttachedImplementsAllowTurnBackward(object) then
265 return false
266 end
267 end
268 end
269 end
270
271 return true
272end

getAttachedImplementsBlockTurnBackward

Description
Returns if one of the attached implements blocks reverse driving
Definition
getAttachedImplementsBlockTurnBackward(table vehicle)
Arguments
tablevehiclevehicle to check
Return Values
booleandoesBlockimplement does block
Code
278function AIVehicleUtil.getAttachedImplementsBlockTurnBackward(vehicle)
279 if vehicle.getAIBlockTurnBackward ~= nil then
280 if vehicle:getAIBlockTurnBackward() then
281 return true
282 end
283 end
284
285 if vehicle.getAttachedImplements ~= nil then
286 for _, implement in pairs(vehicle:getAttachedImplements()) do
287 local object = implement.object
288 if object ~= nil then
289 if object.getAIBlockTurnBackward ~= nil then
290 if object:getAIBlockTurnBackward() then
291 return true
292 end
293 end
294
295 if AIVehicleUtil.getAttachedImplementsBlockTurnBackward(object) then
296 return true
297 end
298 end
299 end
300 end
301
302 return false
303end

getAttachedImplementsMaxTurnRadius

Description
Definition
getAttachedImplementsMaxTurnRadius()
Code
307function AIVehicleUtil.getAttachedImplementsMaxTurnRadius(vehicle)
308 local maxRadius = -1
309 if vehicle.getAttachedImplements ~= nil then
310 for _, implement in pairs(vehicle:getAttachedImplements()) do
311 local object = implement.object
312 if object ~= nil then
313 if object.getAITurnRadiusLimitation ~= nil then
314 local radius = object:getAITurnRadiusLimitation()
315 if radius ~= nil and radius > maxRadius then
316 maxRadius = radius
317 end
318 end
319
320 local radius = AIVehicleUtil.getAttachedImplementsMaxTurnRadius(object)
321 if radius > maxRadius then
322 maxRadius = radius
323 end
324 end
325 end
326 end
327
328 return maxRadius
329end

getAverageDriveDirection

Description
Returns average drive direction between 2 given vectors
Definition
getAverageDriveDirection(integer refNode, float x, float y, float z, float x2, float y2, float z2)
Arguments
integerrefNodeid of ref node
floatxworld x 1
floatyworld y 1
floatzworld z 1
floatx2world x 2
floaty2world y 2
floatz2world z 2
Return Values
floatlxaverage x direction
floatlzaverage z direction
Code
232function AIVehicleUtil.getAverageDriveDirection(refNode, x, y, z, x2, y2, z2)
233 local lx, _, lz = worldToLocal(refNode, (x+x2)*0.5, (y+y2)*0.5, (z+z2)*0.5)
234
235 local length = MathUtil.vector2Length(lx, lz)
236 if length > 0.00001 then
237 lx = lx/length
238 lz = lz/length
239 end
240 return lx, lz, length
241end

getDriveDirection

Description
Returns drive direction
Definition
getDriveDirection(integer refNode, float x, float y, float z)
Arguments
integerrefNodeid of ref node
floatxworld x
floatyworld y
floatzworld z
Return Values
floatlxx direction
floatlzz direction
Code
209function AIVehicleUtil.getDriveDirection(refNode, x, y, z)
210 local lx, _, lz = worldToLocal(refNode, x, y, z)
211
212 local length = MathUtil.vector2Length(lx, lz)
213 if length > 0.00001 then
214 length = 1/length
215 lx = lx*length
216 lz = lz*length
217 end
218 return lx, lz
219end

getIsAreaOwned

Description
Definition
getIsAreaOwned()
Code
608function AIVehicleUtil.getIsAreaOwned(vehicle, sX, sZ, wX, wZ, hX, hZ)
609 local farmId = vehicle:getAIJobFarmId()
610 local centerX, centerZ = (sX + wX)*0.5, (sZ + wZ)*0.5
611 if g_farmlandManager:getIsOwnedByFarmAtWorldPosition(farmId, centerX, centerZ) then
612 return true
613 end
614
615 if g_missionManager:getIsMissionWorkAllowed(farmId, centerX, centerZ, nil) then
616 return true
617 end
618
619 return false
620end

getMaxToolRadius

Description
Returns max tool turn radius
Definition
getMaxToolRadius(table implement)
Arguments
tableimplementimplement to check
Return Values
floatmaxTurnRadiusmax turn radius
Code
354function AIVehicleUtil.getMaxToolRadius(implement)
355 local radius = 0
356
357 local _, rotationNode, wheels, rotLimitFactor = implement.object:getAITurnRadiusLimitation()
358
359 -- collect the max manual defined turn radius of all vehicles, not only valid ai implements
360 local rootVehicle = implement.object.rootVehicle
361 local retRadius = AIVehicleUtil.getAttachedImplementsMaxTurnRadius(rootVehicle)
362
363 if retRadius ~= -1 then
364 radius = retRadius
365 end
366
367 if rotationNode then
368 local activeInputAttacherJoint = implement.object:getActiveInputAttacherJoint()
369 local refNode = rotationNode
370
371 -- If the refNode is any attacher joint, we always use the currently used attacher joint
372 for _, inputAttacherJoint in pairs(implement.object:getInputAttacherJoints()) do
373 if refNode == inputAttacherJoint.node then
374 refNode = activeInputAttacherJoint.node
375 break
376 end
377 end
378
379 local rx,_,rz = localToLocal(refNode, implement.object.components[1].node, 0,0,0)
380
381 for _, wheel in pairs(wheels) do
382 local nx,_,nz = localToLocal(wheel.repr, implement.object.components[1].node, 0,0,0)
383
384 local x,z = nx-rx, nz-rz
385 local cx,cz = 0,0
386
387 -- get max rotation
388 local rotMax
389 if refNode == activeInputAttacherJoint.node then
390 local attacherVehicle = implement.object:getAttacherVehicle()
391 local jointDesc = attacherVehicle:getAttacherJointDescFromObject(implement.object)
392 rotMax = math.max(jointDesc.upperRotLimit[2], jointDesc.lowerRotLimit[2]) * activeInputAttacherJoint.lowerRotLimitScale[2]
393 else
394 for _,compJoint in pairs(implement.object.componentJoints) do
395 if refNode == compJoint.jointNode then
396 rotMax = compJoint.rotLimit[2]
397 break
398 end
399 end
400 end
401
402 rotMax = rotMax * rotLimitFactor
403
404 -- calc turning radius
405 local x1 = x*math.cos(rotMax) - z*math.sin(rotMax)
406 local z1 = x*math.sin(rotMax) + z*math.cos(rotMax)
407
408 local dx = -z1
409 local dz = x1
410 if wheel.steeringAxleScale ~= 0 and wheel.steeringAxleRotMax ~= 0 then
411 local tmpx, tmpz = dx, dz
412 dx = tmpx*math.cos(wheel.steeringAxleRotMax) - tmpz*math.sin(wheel.steeringAxleRotMax)
413 dz = tmpx*math.sin(wheel.steeringAxleRotMax) + tmpz*math.cos(wheel.steeringAxleRotMax)
414 end
415
416 local hit,f1,_ = MathUtil.getLineLineIntersection2D(cx,cz, 1,0, x1,z1, dx,dz)
417 if hit then
418 radius = math.max(radius, math.abs(f1))
419 end
420 end
421 end
422
423 return radius
424end

getValidityOfTurnDirections

Description
Checks fruits on left and right side of vehicle to decide the turn direction
Definition
getValidityOfTurnDirections(table vehicle, float checkFrontDistance, table turnData)
Arguments
tablevehiclevehicle to check
floatcheckFrontDistancedistance to check in front of vehicle
tableturnDataproperties for turning
Return Values
floatleftAreaPercentageleft area percentage
floatrightAreaPercentageright area percentage
Code
451function AIVehicleUtil.getValidityOfTurnDirections(vehicle, turnData)
452 -- let's check the area at/around the marker which is farest behind of vehicle
453 local directionNode = vehicle:getAIDirectionNode()
454 local attachedAIImplements = vehicle:getAttachedAIImplements()
455 local checkFrontDistance = 5
456
457 local leftAreaPercentage = 0
458 local rightAreaPercentage = 0
459
460 local minZ = math.huge
461 local maxZ = -math.huge
462 for _,implement in pairs(attachedAIImplements) do
463 local leftMarker, rightMarker, backMarker = implement.object:getAIMarkers()
464
465 local _,_,zl = localToLocal(leftMarker, directionNode, 0,0,0)
466 local _,_,zr = localToLocal(rightMarker, directionNode, 0,0,0)
467 local _,_,zb = localToLocal(backMarker, directionNode, 0,0,0)
468
469 minZ = math.min(minZ, zl, zr, zb)
470 maxZ = math.max(maxZ, zl, zr, zb)
471 end
472
473 local sideDistance
474 if turnData == nil then
475 local minAreaWidth = math.huge
476 for _,implement in pairs(attachedAIImplements) do
477 local leftMarker, rightMarker, _ = implement.object:getAIMarkers()
478
479 local lx, _, _ = localToLocal(leftMarker, directionNode, 0,0,0)
480 local rx, _, _ = localToLocal(rightMarker, directionNode, 0,0,0)
481 minAreaWidth = math.min(minAreaWidth, math.abs(lx-rx))
482 end
483 sideDistance = minAreaWidth
484 else
485 sideDistance = math.abs(turnData.sideOffsetRight - turnData.sideOffsetLeft)
486 end
487
488 local dx, dz = vehicle.aiDriveDirection[1], vehicle.aiDriveDirection[2]
489 local sx, sz = -dz, dx
490
491 for _,implement in pairs(attachedAIImplements) do
492 local leftMarker, rightMarker, _ = implement.object:getAIMarkers()
493
494 local lx, ly, lz = localToLocal(leftMarker, directionNode, 0,0,0)
495 local rx, ry, rz = localToLocal(rightMarker, directionNode, 0,0,0)
496
497 local width = math.abs(lx-rx)
498 local length = checkFrontDistance + (maxZ - minZ) + math.max(sideDistance*1.3 + 2, checkFrontDistance) -- 1.3~tan(53) allows detecting back along a field side with angle 53 (and 2m extra compensates for some variances, or higher angles with small tools)
499
500 lx, _, lz = localToWorld(directionNode, lx,ly,maxZ + checkFrontDistance)
501 rx, _, rz = localToWorld(directionNode, rx,ry,maxZ + checkFrontDistance)
502
503 local lSX = lx
504 local lSZ = lz
505 local lWX = lSX - sx * width
506 local lWZ = lSZ - sz * width
507 local lHX = lSX - dx * length
508 local lHZ = lSZ - dz * length
509
510 local rSX = rx
511 local rSZ = rz
512 local rWX = rSX + sx * width
513 local rWZ = rSZ + sz * width
514 local rHX = rSX - dx * length
515 local rHZ = rSZ - dz * length
516
517 local lArea, lTotal = AIVehicleUtil.getAIAreaOfVehicle(implement.object, lSX,lSZ, lWX,lWZ, lHX,lHZ, false)
518 local rArea, rTotal = AIVehicleUtil.getAIAreaOfVehicle(implement.object, rSX,rSZ, rWX,rWZ, rHX,rHZ, false)
519
520 if lTotal > 0 then
521 leftAreaPercentage = leftAreaPercentage + (lArea / lTotal)
522 end
523 if rTotal > 0 then
524 rightAreaPercentage = rightAreaPercentage + (rArea / rTotal)
525 end
526
527 -- just visual debuging
528 if VehicleDebug.state == VehicleDebug.DEBUG_AI then
529 local lSY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, lSX,0,lSZ)+2
530 local lWY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, lWX,0,lWZ)+2
531 local lHY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, lHX,0,lHZ)+2
532 local rSY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, rSX,0,rSZ)+2
533 local rWY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, rWX,0,rWZ)+2
534 local rHY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, rHX,0,rHZ)+2
535
536 vehicle:addAIDebugLine({lSX,lSY,lSZ}, {lWX,lWY,lWZ}, {0.5, 0.5, 0.5})
537 vehicle:addAIDebugLine({lSX,lSY,lSZ}, {lHX,lHY,lHZ}, {0.5, 0.5, 0.5})
538 vehicle:addAIDebugLine({rSX,rSY,rSZ}, {rWX,rWY,rWZ}, {0.5, 0.5, 0.5})
539 vehicle:addAIDebugLine({rSX,rSY,rSZ}, {rHX,rHY,rHZ}, {0.5, 0.5, 0.5})
540 end
541 end
542
543 leftAreaPercentage = leftAreaPercentage / #attachedAIImplements
544 rightAreaPercentage = rightAreaPercentage / #attachedAIImplements
545
546 return leftAreaPercentage, rightAreaPercentage
547end

updateInvertLeftRightMarkers

Description
Update invertation of ai left and right markers on vehicle
Definition
updateInvertLeftRightMarkers(table rootAttacherVehicle, table vehicle)
Arguments
tablerootAttacherVehicleroot attacher vehicle
tablevehiclevehicle
Code
430function AIVehicleUtil.updateInvertLeftRightMarkers(rootAttacherVehicle, vehicle)
431 if vehicle.getAIMarkers ~= nil then
432 local leftMarker, rightMarker, _ = vehicle:getAIMarkers()
433 if leftMarker ~= nil and rightMarker ~= nil then
434 local lX, _, _ = localToLocal(leftMarker, rootAttacherVehicle:getAIDirectionNode(), 0,0,0)
435 local rX, _, _ = localToLocal(rightMarker, rootAttacherVehicle:getAIDirectionNode(), 0,0,0)
436
437 if rX > lX then
438 vehicle:setAIMarkersInverted()
439 end
440 end
441 end
442end