LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

AIFieldWorker

Description
Specialization for extending vehicles to by used by AI helpers
Functions

aiContinue

Description
Definition
aiContinue()
Code
682function AIFieldWorker:aiContinue(superFunc)
683 superFunc(self)
684
685 local spec = self.spec_aiFieldWorker
686 if spec.isActive and not spec.isTurning then
687 self:raiseAIEvent("onAIFieldWorkerContinue", "onAIImplementContinue")
688 end
689end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
193function AIFieldWorker:onReadStream(streamId, connection)
194 if streamReadBool(streamId) then
195 self:startFieldWorker()
196 end
197end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
203function AIFieldWorker:onWriteStream(streamId, connection)
204 local spec = self.spec_aiFieldWorker
205 streamWriteBool(streamId, spec.isActive)
206end

prerequisitesPresent

Description
Checks if all prerequisite specializations are loaded
Definition
prerequisitesPresent(table specializations)
Arguments
tablespecializationsspecializations
Return Values
booleanhasPrerequisitetrue if all prerequisite specializations are loaded
Code
55function AIFieldWorker.prerequisitesPresent(specializations)
56 return SpecializationUtil.hasSpecialization(AIJobVehicle, specializations)
57 and SpecializationUtil.hasSpecialization(Drivable, specializations)
58end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
184function AIFieldWorker:saveToXMLFile(xmlFile, key, usedModNames)
185 local spec = self.spec_aiFieldWorker
186 xmlFile:setValue(key.."#lastTurnDirection", spec.lastTurnDirection)
187end

updateAIFieldWorker

Description
Updates the AI logic that is needed to be called at a regular frequency (by default every 2 frames) Primarly this is wheel turning / motor logic
Definition
updateAIFieldWorker(float dt)
Arguments
floatdttime since last call in ms
Code
288function AIFieldWorker:updateAIFieldWorker(dt)
289 local spec = self.spec_aiFieldWorker
290 if spec.aiDriveParams.valid then
291 local moveForwards = spec.aiDriveParams.moveForwards
292 local tX = spec.aiDriveParams.tX
293 local tY = spec.aiDriveParams.tY
294 local tZ = spec.aiDriveParams.tZ
295 local maxSpeed = spec.aiDriveParams.maxSpeed
296
297 local pX, _, pZ = worldToLocal(self:getAISteeringNode(), tX,tY,tZ)
298 if not moveForwards and self.spec_articulatedAxis ~= nil then
299 if self.spec_articulatedAxis.aiRevereserNode ~= nil then
300 pX, _, pZ = worldToLocal(self.spec_articulatedAxis.aiRevereserNode, tX,tY,tZ)
301 end
302 end
303
304 if not moveForwards and self:getAIReverserNode() ~= nil then
305 pX, _, pZ = worldToLocal(self:getAIReverserNode(), tX,tY,tZ)
306 end
307
308 local acceleration = 1.0
309 local isAllowedToDrive = maxSpeed ~= 0
310
311 AIVehicleUtil.driveToPoint(self, dt, acceleration, isAllowedToDrive, moveForwards, pX, pZ, maxSpeed)
312 end
313end

updateAIFieldWorkerDriveStrategies

Description
Set drive strategies depending on the vehicle
Definition
updateAIFieldWorkerDriveStrategies()
Code
486function AIFieldWorker:updateAIFieldWorkerDriveStrategies()
487 local spec = self.spec_aiFieldWorker
488
489 if #spec.aiImplementList > 0 then
490 if spec.driveStrategies ~= nil and #spec.driveStrategies > 0 then
491 for i=#spec.driveStrategies,1,-1 do
492 spec.driveStrategies[i]:delete()
493 table.remove(spec.driveStrategies, i)
494 end
495 spec.driveStrategies = {}
496 end
497
498 local foundCombine = false
499 local foundBaler = false
500 local foundStonePicker = false
501 for _, childVehicle in pairs(self.rootVehicle.childVehicles) do -- using all vehicles since the combine can also be standalone without cutter - so no ai implement
502 if SpecializationUtil.hasSpecialization(Combine, childVehicle.specializations) then
503 foundCombine = true
504 end
505 if SpecializationUtil.hasSpecialization(Baler, childVehicle.specializations) then
506 foundBaler = true
507 end
508 if SpecializationUtil.hasSpecialization(StonePicker, childVehicle.specializations) then
509 foundStonePicker = true
510 end
511 end
512
513 foundCombine = foundCombine or SpecializationUtil.hasSpecialization(Combine, spec.specializations)
514 if foundCombine then
515 local driveStrategyCombine = AIDriveStrategyCombine.new()
516 driveStrategyCombine:setAIVehicle(self)
517 table.insert(spec.driveStrategies, driveStrategyCombine)
518 end
519
520 foundBaler = foundBaler or SpecializationUtil.hasSpecialization(Baler, spec.specializations)
521 if foundBaler then
522 local driveStrategyBaler = AIDriveStrategyBaler.new()
523 driveStrategyBaler:setAIVehicle(self)
524 table.insert(spec.driveStrategies, driveStrategyBaler)
525 end
526
527 foundStonePicker = foundStonePicker or SpecializationUtil.hasSpecialization(StonePicker, spec.specializations)
528 if foundStonePicker then
529 local driveStrategyStonePicker = AIDriveStrategyStonePicker.new()
530 driveStrategyStonePicker:setAIVehicle(self)
531 table.insert(spec.driveStrategies, driveStrategyStonePicker)
532 end
533
534 local driveStrategyStraight = AIDriveStrategyStraight.new()
535 local driveStrategyCollision = AIDriveStrategyCollision.new(driveStrategyStraight)
536
537 driveStrategyCollision:setAIVehicle(self)
538 driveStrategyStraight:setAIVehicle(self)
539
540 table.insert(spec.driveStrategies, driveStrategyCollision)
541 table.insert(spec.driveStrategies, driveStrategyStraight)
542 end
543end

updateAIFieldWorkerLowFrequency

Description
Updates the AI logic that is possible to be run at a lower frequency (by default every 4 frames) Primarly this is the evaluation of the drive strategies (collsion, etc.)
Definition
updateAIFieldWorkerLowFrequency(float dt)
Arguments
floatdttime since last call in ms
Code
549function AIFieldWorker:updateAIFieldWorkerLowFrequency(dt)
550 local spec = self.spec_aiFieldWorker
551
552 self:clearAIDebugTexts()
553 self:clearAIDebugLines()
554
555 if self:getIsFieldWorkActive() then
556 if spec.driveStrategies ~= nil and #spec.driveStrategies > 0 then
557 local vX,vY,vZ = getWorldTranslation(self:getAISteeringNode())
558
559 local tX, tZ, moveForwards, maxSpeedStra, maxSpeed, distanceToStop
560 for i=1,#spec.driveStrategies do
561 local driveStrategy = spec.driveStrategies[i]
562 tX, tZ, moveForwards, maxSpeedStra, distanceToStop = driveStrategy:getDriveData(dt, vX,vY,vZ)
563 maxSpeed = math.min(maxSpeedStra or math.huge, maxSpeed or math.huge)
564 if tX ~= nil or not self:getIsFieldWorkActive() then
565 break
566 end
567 end
568
569 if tX == nil then
570 if self:getIsFieldWorkActive() then -- check if AI is still active, because it might have been kicked by a strategy
571 self:stopCurrentAIJob(AIMessageSuccessFinishedJob.new())
572 end
573 end
574
575 if not self:getIsFieldWorkActive() then
576 return
577 end
578
579 local minimumSpeed = 5
580 local lookAheadDistance = 5
581
582 -- use different settings while turning
583 -- so we are more pricise when stopping at end point in small turning segments
584 if self:getAIFieldWorkerIsTurning() then
585 minimumSpeed = 1.5
586 lookAheadDistance = 2
587 end
588
589 local distSpeed = math.max(minimumSpeed, maxSpeed * math.min(1, distanceToStop/lookAheadDistance))
590 local speedLimit, _ = self:getSpeedLimit(true)
591 maxSpeed = math.min(maxSpeed, distSpeed, speedLimit)
592 maxSpeed = math.min(maxSpeed, self:getCruiseControlMaxSpeed())
593
594 if VehicleDebug.state == VehicleDebug.DEBUG_AI then
595 self:addAIDebugText(string.format("===> maxSpeed = %.2f", maxSpeed))
596 end
597
598 local isAllowedToDrive = maxSpeed ~= 0
599
600 -- set drive values
601 spec.aiDriveParams.moveForwards = moveForwards
602 spec.aiDriveParams.tX = tX
603 spec.aiDriveParams.tY = vY
604 spec.aiDriveParams.tZ = tZ
605 spec.aiDriveParams.maxSpeed = maxSpeed
606 spec.aiDriveParams.valid = true
607
608 -- worst case check: did not move but should have moved
609 if isAllowedToDrive and self:getLastSpeed() < 0.5 then
610 spec.didNotMoveTimer = spec.didNotMoveTimer - dt
611 else
612 spec.didNotMoveTimer = spec.didNotMoveTimeout
613 end
614
615 if spec.didNotMoveTimer < 0 then
616 if self:getAIFieldWorkerIsTurning() then
617 if spec.lastTurnStrategy ~= nil then
618 spec.lastTurnStrategy:skipTurnSegment()
619 end
620 else
621 self:stopCurrentAIJob(AIMessageErrorBlockedByObject.new())
622 end
623
624 spec.didNotMoveTimer = spec.didNotMoveTimeout
625 end
626 end
627
628 self:raiseAIEvent("onAIFieldWorkerActive", "onAIImplementActive")
629 end
630end