Script v1_7_1_0
- AI
- Animals
- Collections
- Contracts
- Debug
- Economy
- Elements
- EnvironmentalScore
- Errors
- Events
- GUI
- Handtools
- Hud
- I3d
- Input
- Jobs
- Maps
- Materials
- Misc
- Objects
- Parameters
- Placeables
- Placement
- Player
- Shop
- Sounds
- Specialization
- Specializations
- AIConveyorBelt
- AIDrivable
- AIFieldWorker
- AIImplement
- AIJobVehicle
- AIVehicle
- AIVehicleObstacle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- AutoLoader
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BigBag
- BunkerSiloCompacter
- BunkerSiloInteractor
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- CropSensor
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- ExtendedAIVehicle
- ExtendedCombine
- ExtendedMotorized
- ExtendedMower
- ExtendedSowingMachine
- ExtendedSprayer
- ExtendedWearable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- HeadlandAnimation
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- InlineWrapper
- JigglingParts
- Leveler
- LicensePlates
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- ManureSensor
- MixerWagon
- Motorized
- Mountable
- Mower
- Mulcher
- MultipleItemPurchase
- Pallet
- Pickup
- Pipe
- PlaceableAI
- PlaceableAnimatedObjects
- PlaceableBeehive
- PlaceableBeehivePalletSpa...
- PlaceableBunkerSilo
- PlaceableBuyingStation
- PlaceableCartridgePlayer
- PlaceableChargingStation
- PlaceableClearAreas
- PlaceableColorable
- PlaceableDeletedNodes
- PlaceableDoghouse
- PlaceableDynamicallyLoade...
- PlaceableFarmhouse
- PlaceableFence
- PlaceableFoliageAreas
- PlaceableGreenhouse
- PlaceableHighPressureWash...
- PlaceableHotspots
- PlaceableHusbandry
- PlaceableHusbandryAnimals
- PlaceableHusbandryFeeding...
- PlaceableHusbandryFence
- PlaceableHusbandryFood
- PlaceableHusbandryLiquidM...
- PlaceableHusbandryMilk
- PlaceableHusbandryPallets
- PlaceableHusbandryStraw
- PlaceableHusbandryWater
- PlaceableIncomePerHour
- PlaceableIndoorAreas
- PlaceableInfoTrigger
- PlaceableLeveling
- PlaceableLights
- PlaceableManureHeap
- PlaceablePlacement
- PlaceableProductionPoint
- PlaceableSellingStation
- PlaceableSilo
- PlaceableSiloExtension
- PlaceableSolarPanels
- PlaceableTipOcclusionArea...
- PlaceableTrainSystem
- PlaceableTriggerMarkers
- PlaceableVine
- PlaceableWardrobe
- PlaceableWeatherStation
- PlaceableWeighingStation
- PlaceableWindTurbine
- PlaceableWorkshop
- Plow
- PlowPacker
- PowerConsumer
- PowerTakeOffs
- PrecisionFarmingStatistic
- PushHandTool
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- RTKStation
- SaltSpreader
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SoilSampler
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StonePicker
- StrawBlower
- StumpCutter
- SupportVehicle
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TestAreas
- TipOccluder
- Trailer
- TreePlanter
- TreeSaplingPallet
- TreeSaw
- TurnOnVehicle
- VariableWorkWidth
- VehicleSettings
- VineCutter
- VineDetector
- VinePrepruner
- Washable
- WaterTrailer
- Wearable
- Weeder
- WeedSpotSpray
- Wheels
- WindBending
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- StateMachine
- Statistics
- Tasks
- Triggers
- Utils
- Vehicles
Engine v1_7_1_0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- general
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- NoteNode
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- VoiceChat
- XML
Foundation Reference
AIFieldWorker
DescriptionSpecialization for extending vehicles to by used by AI helpersFunctions
- aiContinue
- onReadStream
- onWriteStream
- prerequisitesPresent
- saveToXMLFile
- updateAIFieldWorker
- updateAIFieldWorkerDriveStrategies
- updateAIFieldWorkerLowFrequency
aiContinue
DescriptionDefinitionaiContinue()Code
682 | function 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 |
689 | end |
onReadStream
DescriptionCalled on client side on joinDefinition
onReadStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
193 | function AIFieldWorker:onReadStream(streamId, connection) |
194 | if streamReadBool(streamId) then |
195 | self:startFieldWorker() |
196 | end |
197 | end |
onWriteStream
DescriptionCalled on server side on joinDefinition
onWriteStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
203 | function AIFieldWorker:onWriteStream(streamId, connection) |
204 | local spec = self.spec_aiFieldWorker |
205 | streamWriteBool(streamId, spec.isActive) |
206 | end |
prerequisitesPresent
DescriptionChecks if all prerequisite specializations are loadedDefinition
prerequisitesPresent(table specializations)Arguments
table | specializations | specializations |
boolean | hasPrerequisite | true if all prerequisite specializations are loaded |
55 | function AIFieldWorker.prerequisitesPresent(specializations) |
56 | return SpecializationUtil.hasSpecialization(AIJobVehicle, specializations) |
57 | and SpecializationUtil.hasSpecialization(Drivable, specializations) |
58 | end |
saveToXMLFile
DescriptionDefinitionsaveToXMLFile()Code
184 | function AIFieldWorker:saveToXMLFile(xmlFile, key, usedModNames) |
185 | local spec = self.spec_aiFieldWorker |
186 | xmlFile:setValue(key.."#lastTurnDirection", spec.lastTurnDirection) |
187 | end |
updateAIFieldWorker
DescriptionUpdates the AI logic that is needed to be called at a regular frequency (by default every 2 frames) Primarly this is wheel turning / motor logicDefinition
updateAIFieldWorker(float dt)Arguments
float | dt | time since last call in ms |
288 | function 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 |
313 | end |
updateAIFieldWorkerDriveStrategies
DescriptionSet drive strategies depending on the vehicleDefinition
updateAIFieldWorkerDriveStrategies()Code
486 | function 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 |
543 | end |
updateAIFieldWorkerLowFrequency
DescriptionUpdates 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
float | dt | time since last call in ms |
549 | function 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 |
630 | end |