LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

AIVehicle

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

actionEventToggleAIState

Description
Definition
actionEventToggleAIState()
Code
1069function AIVehicle.actionEventToggleAIState(self, actionName, inputValue, callbackState, isAnalog)
1070 if g_currentMission:getHasPlayerPermission("hireAssistant") then
1071 if self:getIsAIActive() then
1072 self:stopAIVehicle(AIVehicle.STOP_REASON_USER)
1073 else
1074 if self:getCanStartAIVehicle() then
1075 self:startAIVehicle(nil, false, g_currentMission.player.farmId)
1076 end
1077 end
1078 end
1079end

addAIDebugLine

Description
Definition
addAIDebugLine()
Code
956function AIVehicle:addAIDebugLine(s, e, c)
957 local spec = self.spec_aiVehicle
958 table.insert(spec.debugLines, {s=s, e=e, c=c})
959end

addAIDebugText

Description
Definition
addAIDebugText()
Code
943function AIVehicle:addAIDebugText(text)
944 local spec = self.spec_aiVehicle
945 table.insert(spec.debugTexts, text)
946end

aiBlock

Description
Definition
aiBlock()
Code
901function AIVehicle:aiBlock()
902 self:raiseAIEvent("onAIBlock", "onAIImplementBlock")
903
904 if self.isClient then
905 if g_currentMission.player.farmId == self.spec_aiVehicle.startedFarmId then
906 local helperName = self:getCurrentHelper().name
907 local text = string.format(g_i18n:getText(AIVehicle.REASON_TEXT_MAPPING[AIVehicle.STOP_REASON_BLOCKED_BY_OBJECT]), helperName)
908 g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_CRITICAL, text)
909 end
910 end
911end

aiContinue

Description
Definition
aiContinue()
Code
915function AIVehicle:aiContinue()
916 self:raiseAIEvent("onAIContinue", "onAIImplementContinue")
917end

aiEndTurn

Description
Definition
aiEndTurn()
Code
893function AIVehicle:aiEndTurn(left)
894 local spec = self.spec_aiVehicle
895 spec.isTurning = false
896 self:raiseAIEvent("onAIEndTurn", "onAIImplementEndTurn", left)
897end

aiStartTurn

Description
Definition
aiStartTurn()
Code
879function AIVehicle:aiStartTurn(left)
880 local spec = self.spec_aiVehicle
881 spec.isTurning = true
882 self:raiseAIEvent("onAIStartTurn", "onAIImplementStartTurn", left)
883end

aiTurnProgress

Description
Definition
aiTurnProgress()
Code
887function AIVehicle:aiTurnProgress(progress, left)
888 self:raiseAIEvent("onAITurnProgress", "onAIImplementTurnProgress", progress, left)
889end

clearAIDebugLines

Description
Definition
clearAIDebugLines()
Code
950function AIVehicle:clearAIDebugLines()
951 self.spec_aiVehicle.debugLines = {}
952end

clearAIDebugTexts

Description
Definition
clearAIDebugTexts()
Code
937function AIVehicle:clearAIDebugTexts()
938 self.spec_aiVehicle.debugTexts = {}
939end

getActiveFarm

Description
Definition
getActiveFarm()
Code
1007function AIVehicle:getActiveFarm(superFunc)
1008 local starter = self.spec_aiVehicle.startedFarmId
1009 if starter ~= nil then
1010 return starter
1011 else
1012 return superFunc(self)
1013 end
1014end

getAICollisionTriggers

Description
Definition
getAICollisionTriggers()
Code
728function AIVehicle:getAICollisionTriggers(collisionTriggers)
729end

getAIDidNotMoveTimeout

Description
Definition
getAIDidNotMoveTimeout()
Code
786function AIVehicle:getAIDidNotMoveTimeout()
787 return self.spec_aiVehicle.didNotMoveTimeout
788end

getAIIsTurning

Description
Definition
getAIIsTurning()
Code
867function AIVehicle:getAIIsTurning()
868 return self.spec_aiVehicle.isTurning
869end

getAILastAllowedToDrive

Description
Definition
getAILastAllowedToDrive()
Code
873function AIVehicle:getAILastAllowedToDrive()
874 return self.spec_aiVehicle.lastAllowedToDrive
875end

getAINeedsTrafficCollisionBox

Description
Returns if the ai vehicle needs a traffic collision box
Definition
getAINeedsTrafficCollisionBox()
Return Values
booleanisNeededcollision box is needed
Code
765function AIVehicle:getAINeedsTrafficCollisionBox()
766 return true
767end

getAISteeringSpeed

Description
Definition
getAISteeringSpeed()
Code
751function AIVehicle:getAISteeringSpeed()
752 return self.spec_aiVehicle.aiSteeringSpeed
753end

getAIVehicleDirectionNode

Description
Definition
getAIVehicleDirectionNode()
Code
733function AIVehicle:getAIVehicleDirectionNode()
734 return self.components[1].node
735end

getAIVehicleReverserNode

Description
Definition
getAIVehicleReverserNode()
Code
745function AIVehicle:getAIVehicleReverserNode()
746 return self.spec_aiVehicle.reverserNode
747end

getAIVehicleSteeringNode

Description
Definition
getAIVehicleSteeringNode()
Code
739function AIVehicle:getAIVehicleSteeringNode()
740 return self.spec_aiVehicle.steeringNode or self:getAIVehicleDirectionNode()
741end

getAllowTireTracks

Description
Definition
getAllowTireTracks()
Code
1001function AIVehicle:getAllowTireTracks(superFunc)
1002 return superFunc(self) and not self:getIsAIActive()
1003end

getAttachedAIImplements

Description
Definition
getAttachedAIImplements()
Code
780function AIVehicle:getAttachedAIImplements()
781 return self.spec_aiVehicle.aiImplementList
782end

getCanAIVehicleContinueWork

Description
Returns true if ai can contiue
Definition
getCanAIVehicleContinueWork()
Return Values
booleancanContiuecan contiue ai
Code
502function AIVehicle:getCanAIVehicleContinueWork()
503 for _, implement in ipairs(self:getAttachedAIImplements()) do
504 if not implement.object:getCanAIImplementContinueWork() then
505 return false
506 end
507 end
508
509 if SpecializationUtil.hasSpecialization(AIImplement, self.specializations) then
510 if not self:getCanAIImplementContinueWork() then
511 return false
512 end
513 end
514
515 return true
516end

getCanStartAIVehicle

Description
Returns true if ai can start
Definition
getCanStartAIVehicle()
Return Values
booleancanStartcan start ai
Code
477function AIVehicle:getCanStartAIVehicle()
478 local spec = self.spec_aiVehicle
479
480 if self:getAIVehicleDirectionNode() == nil then
481 return false
482 end
483
484 if g_currentMission.disableAIVehicle then
485 return false
486 end
487
488 if AIVehicle.numHirablesHired >= g_currentMission.maxNumHirables then
489 return false
490 end
491
492 if #spec.aiImplementList == 0 then
493 return false
494 end
495
496 return true
497end

getCurrentHelper

Description
Definition
getCurrentHelper()
Code
722function AIVehicle:getCurrentHelper()
723 return self.spec_aiVehicle.currentHelper
724end

getDeactivateOnLeave

Description
Get deactivate on leaving
Definition
getDeactivateOnLeave()
Return Values
booleandeactivateOnLeavedeactivate on leaving
Code
977function AIVehicle:getDeactivateOnLeave(superFunc)
978 return superFunc(self) and not self:getIsAIActive()
979end

getDirectionSnapAngle

Description
Get direction shape angle
Definition
getDirectionSnapAngle()
Return Values
floatdirectionshape angle
Code
758function AIVehicle:getDirectionSnapAngle()
759 return 0
760end

getDisableVehicleCharacterOnLeave

Description
Definition
getDisableVehicleCharacterOnLeave()
Code
995function AIVehicle:getDisableVehicleCharacterOnLeave(superFunc)
996 return superFunc(self) and not self:getIsAIActive()
997end

getIsActive

Description
Definition
getIsActive()
Code
1028function AIVehicle:getIsActive(superFunc)
1029 if self:getIsAIActive() then
1030 return true
1031 end
1032
1033 return superFunc(self)
1034end

getIsAIActive

Description
Definition
getIsAIActive()
Code
716function AIVehicle:getIsAIActive(superFunc)
717 return superFunc(self) or self.spec_aiVehicle.isActive
718end

getIsInUse

Description
Definition
getIsInUse()
Code
1018function AIVehicle:getIsInUse(superFunc, connection)
1019 if self:getIsAIActive() then
1020 return true
1021 end
1022
1023 return superFunc(self, connection)
1024end

getIsVehicleControlledByPlayer

Description
Definition
getIsVehicleControlledByPlayer()
Code
983function AIVehicle:getIsVehicleControlledByPlayer(superFunc)
984 return superFunc(self) and not self:getIsAIActive()
985end

getStopMotorOnLeave

Description
Definition
getStopMotorOnLeave()
Code
989function AIVehicle:getStopMotorOnLeave(superFunc)
990 return superFunc(self) and not self:getIsAIActive()
991end

initSpecialization

Description
Definition
initSpecialization()
Code
73function AIVehicle.initSpecialization()
74 Vehicle.registerStateChange("AI_START_LINE")
75 Vehicle.registerStateChange("AI_END_LINE")
76end

onEnterVehicle

Description
Called on enter vehicle
Definition
onEnterVehicle(boolean isControlling)
Arguments
booleanisControllingis player controlling the vehicle
Code
964function AIVehicle:onEnterVehicle(isControlling)
965 self:setAIMapHotspotVisibility(false)
966end

onLeaveVehicle

Description
Called on leaving the vehicle
Definition
onLeaveVehicle()
Code
970function AIVehicle:onLeaveVehicle()
971 self:setAIMapHotspotVisibility(true)
972end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
175function AIVehicle:onLoad(savegame)
176 local spec = self.spec_aiVehicle
177
178 spec.aiSteeringSpeed = Utils.getNoNil(getXMLFloat(spec.xmlFile, "vehicle.ai.steeringSpeed"), 1)*0.001
179
180 spec.isActive = false
181
182 spec.aiImplementList = {}
183 spec.aiImplementDataDirtyFlag = true
184
185 spec.aiDriveParams = { valid=false }
186 spec.aiUpdateLowFrequencyDt = 0
187 spec.aiUpdateDt = 0
188
189 spec.taskList = {}
190
191 spec.driveStrategies = {}
192
193 spec.didNotMoveTimeout = Utils.getNoNil( getXMLFloat(spec.xmlFile, "vehicle.ai.didNotMoveTimeout#value"), 5000)
194 if getXMLBool(spec.xmlFile, "vehicle.ai.didNotMoveTimeout#deactivated") then
195 spec.didNotMoveTimeout = math.huge
196 end
197
198 spec.didNotMoveTimer = spec.didNotMoveTimeout
199
200 spec.debugTexts = {}
201 spec.debugLines = {}
202
203 spec.aiTrafficCollision = nil
204 spec.aiTrafficCollisionTranslation = {0, 0, 20}
205
206 spec.pricePerMS = Utils.getNoNil(getXMLFloat(spec.xmlFile, "vehicle.ai.pricePerHour"), 2000)/60/60/1000
207
208 spec.steeringNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.ai.steeringNode#node"), self.i3dMappings)
209 spec.reverserNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.ai.reverserNode#node"), self.i3dMappings)
210end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
225function AIVehicle:onReadStream(streamId, connection)
226 if streamReadBool(streamId) then
227 local helperIndex = streamReadUInt8(streamId)
228 local farmId = streamReadUIntN(streamId, FarmManager.FARM_ID_SEND_NUM_BITS)
229 self:startAIVehicle(helperIndex, true, farmId)
230 end
231end

onRegisterActionEvents

Description
Definition
onRegisterActionEvents()
Code
1047function AIVehicle:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
1048 if self.isClient then
1049 local spec = self.spec_aiVehicle
1050 self:clearActionEventsTable(spec.actionEvents)
1051
1052 if self:getIsActiveForInput(true, true) and not g_isPresentationVersionAIDeactivated then
1053 local _, eventId = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_AI, self, AIVehicle.actionEventToggleAIState, false, true, false, true, nil)
1054 g_inputBinding:setActionEventTextPriority(eventId, GS_PRIO_HIGH)
1055 end
1056 end
1057end

onSetBroken

Description
Definition
onSetBroken()
Code
1061function AIVehicle:onSetBroken()
1062 if self:getIsAIActive() then
1063 self:stopAIVehicle(AIVehicle.STOP_REASON_UNKOWN)
1064 end
1065end

onStateChange

Description
Definition
onStateChange()
Code
1038function AIVehicle:onStateChange(state, data)
1039 if state == Vehicle.STATE_CHANGE_ATTACH or state == Vehicle.STATE_CHANGE_DETACH then
1040 local spec = self.spec_aiVehicle
1041 spec.aiImplementDataDirtyFlag = true
1042 end
1043end

onUpdate

Description
Called on update
Definition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
250function AIVehicle:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
251 local spec = self.spec_aiVehicle
252
253 if VehicleDebug.state == VehicleDebug.DEBUG_AI and self:getIsActiveForInput(true, true) then
254 if #spec.debugTexts > 0 then
255 for i, text in pairs(spec.debugTexts) do
256 renderText(0.7, 0.92-(0.02*i), 0.02, text)
257 end
258 end
259 if #spec.debugLines > 0 then
260 for _, l in pairs(spec.debugLines) do
261 drawDebugLine(l.s[1],l.s[2],l.s[3], l.c[1],l.c[2],l.c[3], l.e[1],l.e[2],l.e[3], l.c[1],l.c[2],l.c[3])
262 end
263 end
264 end
265
266 if spec.aiImplementDataDirtyFlag then
267 spec.aiImplementDataDirtyFlag = false
268 self:updateAIImplementData()
269 end
270
271 if self.isServer then
272 if self:getIsAIActive() then
273 if spec.driveStrategies ~= nil then
274 for i=1,#spec.driveStrategies do
275 local driveStrategy = spec.driveStrategies[i]
276 driveStrategy:update(dt)
277 end
278 end
279
280 -- Find our index in the hiredHirables list (this is not deterministic, but stays constant as long as the array is not changed)
281 local hirableIndex = 0
282 for hirable in pairs(AIVehicle.hiredHirables) do
283 if self == hirable then
284 break
285 end
286 hirableIndex = hirableIndex + 1
287 end
288 spec.aiUpdateLowFrequencyDt = spec.aiUpdateLowFrequencyDt + dt
289 if (g_updateLoopIndex + hirableIndex) % AIVehicle.aiUpdateLowFrequencyDelay == 0 then
290 self:updateAILowFrequency(spec.aiUpdateLowFrequencyDt)
291 spec.aiUpdateLowFrequencyDt = 0
292 end
293 spec.aiUpdateDt = spec.aiUpdateDt + dt
294 local aiUpdateDelay = dt > 25 and AIVehicle.aiUpdateDelayLowFps or AIVehicle.aiUpdateDelay
295 if (g_updateLoopIndex + hirableIndex) % aiUpdateDelay == 0 then
296 self:updateAI(spec.aiUpdateDt)
297 spec.aiUpdateDt = 0
298 end
299 end
300 end
301
302 if self:getIsAIActive() then
303 if spec.aiTrafficCollision ~= nil and not self:getAIIsTurning() then
304 local x, y, z = localToWorld(self.components[1].node, unpack(spec.aiTrafficCollisionTranslation))
305
306 setTranslation(spec.aiTrafficCollision, x, y, z)
307 setRotation(spec.aiTrafficCollision, localRotationToWorld(self.components[1].node, 0, 0, 0))
308 end
309
310 -- as long as the ai is turned on we raise active (e.g. if the vehicle stops due a collision the vehicle collision may sleep and stop raising active)
311 self:raiseActive()
312 end
313end

onUpdateTick

Description
Called on update tick
Definition
onUpdateTick(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
320function AIVehicle:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
321 local spec = self.spec_aiVehicle
322
323 if self.isClient then
324 local actionEvent = spec.actionEvents[InputAction.TOGGLE_AI]
325 if actionEvent ~= nil then
326 local showAction = false
327
328 if self:getIsActiveForInput(true, true) then
329 -- if ai is active we always display the dismiss helper action
330 showAction = self:getCanStartAIVehicle() or self:getIsAIActive()
331
332 if showAction then
333 if self:getIsAIActive() then
334 g_inputBinding:setActionEventText(actionEvent.actionEventId, g_i18n:getText("action_dismissEmployee"))
335 else
336 g_inputBinding:setActionEventText(actionEvent.actionEventId, g_i18n:getText("action_hireEmployee"))
337 end
338 end
339 end
340
341 g_inputBinding:setActionEventActive(actionEvent.actionEventId, showAction)
342 end
343 end
344end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
237function AIVehicle:onWriteStream(streamId, connection)
238 local spec = self.spec_aiVehicle
239 if streamWriteBool(streamId, self:getIsAIActive()) then
240 streamWriteUInt8(streamId, spec.currentHelper.index)
241 streamWriteUIntN(streamId, spec.startedFarmId, FarmManager.FARM_ID_SEND_NUM_BITS)
242 end
243end

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
67function AIVehicle.prerequisitesPresent(specializations)
68 return SpecializationUtil.hasSpecialization(Drivable, specializations)
69end

raiseAIEvent

Description
Definition
raiseAIEvent()
Code
921function AIVehicle:raiseAIEvent(eventName, implementName, ...)
922 for _, implement in ipairs(self:getAttachedAIImplements()) do
923 if implement.object ~= self then
924 SpecializationUtil.raiseEvent(implement.object, implementName, ...)
925 end
926 end
927
928 if SpecializationUtil.hasSpecialization(AIImplement, self.specializations) then
929 SpecializationUtil.raiseEvent(self, implementName, ...)
930 end
931
932 SpecializationUtil.raiseEvent(self, eventName, ...)
933end

registerAITask

Description
Definition
registerAITask()
Code
520function AIVehicle:registerAITask(setObject, setFunc, setParams)
521 local spec = self.spec_aiVehicle
522
523 if setObject[setFunc] == nil then
524 return false
525 end
526
527 table.insert(spec.taskList, {setObject=setObject, setFunc=setFunc, setParams=setParams})
528
529 return false
530end

registerEventListeners

Description
Definition
registerEventListeners()
Code
158function AIVehicle.registerEventListeners(vehicleType)
159 SpecializationUtil.registerEventListener(vehicleType, "onLoad", AIVehicle)
160 SpecializationUtil.registerEventListener(vehicleType, "onDelete", AIVehicle)
161 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", AIVehicle)
162 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", AIVehicle)
163 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", AIVehicle)
164 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", AIVehicle)
165 SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", AIVehicle)
166 SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", AIVehicle)
167 SpecializationUtil.registerEventListener(vehicleType, "onStateChange", AIVehicle)
168 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", AIVehicle)
169 SpecializationUtil.registerEventListener(vehicleType, "onSetBroken", AIVehicle)
170end

registerEvents

Description
Definition
registerEvents()
Code
80function AIVehicle.registerEvents(vehicleType)
81 SpecializationUtil.registerEvent(vehicleType, "onAIStart")
82 SpecializationUtil.registerEvent(vehicleType, "onAIActive")
83 SpecializationUtil.registerEvent(vehicleType, "onAIEnd")
84
85 SpecializationUtil.registerEvent(vehicleType, "onAIStartTurn")
86 SpecializationUtil.registerEvent(vehicleType, "onAITurnProgress")
87 SpecializationUtil.registerEvent(vehicleType, "onAIEndTurn")
88
89 SpecializationUtil.registerEvent(vehicleType, "onAIBlock")
90 SpecializationUtil.registerEvent(vehicleType, "onAIContinue")
91end

registerFunctions

Description
Definition
registerFunctions()
Code
95function AIVehicle.registerFunctions(vehicleType)
96 SpecializationUtil.registerFunction(vehicleType, "getCanStartAIVehicle", AIVehicle.getCanStartAIVehicle)
97 SpecializationUtil.registerFunction(vehicleType, "getCanAIVehicleContinueWork", AIVehicle.getCanAIVehicleContinueWork)
98 SpecializationUtil.registerFunction(vehicleType, "registerAITask", AIVehicle.registerAITask)
99 SpecializationUtil.registerFunction(vehicleType, "registerSecureAITask", AIVehicle.registerSecureAITask)
100 SpecializationUtil.registerFunction(vehicleType, "startAIVehicle", AIVehicle.startAIVehicle)
101 SpecializationUtil.registerFunction(vehicleType, "stopAIVehicle", AIVehicle.stopAIVehicle)
102 SpecializationUtil.registerFunction(vehicleType, "getCurrentHelper", AIVehicle.getCurrentHelper)
103
104 SpecializationUtil.registerFunction(vehicleType, "updateAI", AIVehicle.updateAI)
105 SpecializationUtil.registerFunction(vehicleType, "updateAILowFrequency", AIVehicle.updateAILowFrequency)
106
107 SpecializationUtil.registerFunction(vehicleType, "getAICollisionTriggers", AIVehicle.getAICollisionTriggers)
108 SpecializationUtil.registerFunction(vehicleType, "getAIVehicleDirectionNode", AIVehicle.getAIVehicleDirectionNode)
109 SpecializationUtil.registerFunction(vehicleType, "getAIVehicleSteeringNode", AIVehicle.getAIVehicleSteeringNode)
110 SpecializationUtil.registerFunction(vehicleType, "getAIVehicleReverserNode", AIVehicle.getAIVehicleReverserNode)
111 SpecializationUtil.registerFunction(vehicleType, "getAISteeringSpeed", AIVehicle.getAISteeringSpeed)
112 SpecializationUtil.registerFunction(vehicleType, "getDirectionSnapAngle", AIVehicle.getDirectionSnapAngle)
113 SpecializationUtil.registerFunction(vehicleType, "getAINeedsTrafficCollisionBox", AIVehicle.getAINeedsTrafficCollisionBox)
114
115 SpecializationUtil.registerFunction(vehicleType, "updateAIImplementData", AIVehicle.updateAIImplementData)
116 SpecializationUtil.registerFunction(vehicleType, "getAttachedAIImplements", AIVehicle.getAttachedAIImplements)
117
118 SpecializationUtil.registerFunction(vehicleType, "getAIDidNotMoveTimeout", AIVehicle.getAIDidNotMoveTimeout)
119
120 SpecializationUtil.registerFunction(vehicleType, "updateAIDriveStrategies", AIVehicle.updateAIDriveStrategies)
121 SpecializationUtil.registerFunction(vehicleType, "setAIMapHotspotVisibility", AIVehicle.setAIMapHotspotVisibility)
122 SpecializationUtil.registerFunction(vehicleType, "setAIMapHotspotBlinking", AIVehicle.setAIMapHotspotBlinking)
123
124 SpecializationUtil.registerFunction(vehicleType, "getAIIsTurning", AIVehicle.getAIIsTurning)
125 SpecializationUtil.registerFunction(vehicleType, "getAILastAllowedToDrive", AIVehicle.getAILastAllowedToDrive)
126
127 SpecializationUtil.registerFunction(vehicleType, "aiStartTurn", AIVehicle.aiStartTurn)
128 SpecializationUtil.registerFunction(vehicleType, "aiTurnProgress", AIVehicle.aiTurnProgress)
129 SpecializationUtil.registerFunction(vehicleType, "aiEndTurn", AIVehicle.aiEndTurn)
130
131 SpecializationUtil.registerFunction(vehicleType, "aiBlock", AIVehicle.aiBlock)
132 SpecializationUtil.registerFunction(vehicleType, "aiContinue", AIVehicle.aiContinue)
133
134 SpecializationUtil.registerFunction(vehicleType, "raiseAIEvent", AIVehicle.raiseAIEvent)
135
136 SpecializationUtil.registerFunction(vehicleType, "clearAIDebugTexts", AIVehicle.clearAIDebugTexts)
137 SpecializationUtil.registerFunction(vehicleType, "addAIDebugText", AIVehicle.addAIDebugText)
138 SpecializationUtil.registerFunction(vehicleType, "clearAIDebugLines", AIVehicle.clearAIDebugLines)
139 SpecializationUtil.registerFunction(vehicleType, "addAIDebugLine", AIVehicle.addAIDebugLine)
140end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
144function AIVehicle.registerOverwrittenFunctions(vehicleType)
145 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsAIActive", AIVehicle.getIsAIActive)
146 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDeactivateOnLeave", AIVehicle.getDeactivateOnLeave)
147 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsVehicleControlledByPlayer", AIVehicle.getIsVehicleControlledByPlayer)
148 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getStopMotorOnLeave", AIVehicle.getStopMotorOnLeave)
149 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDisableVehicleCharacterOnLeave", AIVehicle.getDisableVehicleCharacterOnLeave)
150 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAllowTireTracks", AIVehicle.getAllowTireTracks)
151 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getActiveFarm", AIVehicle.getActiveFarm)
152 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsInUse", AIVehicle.getIsInUse)
153 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsActive", AIVehicle.getIsActive)
154end

registerSecureAITask

Description
Definition
registerSecureAITask()
Code
534function AIVehicle:registerSecureAITask(getObject, getFunc, getParams, setObject, setFunc, setParams)
535 local spec = self.spec_aiVehicle
536
537 if getObject[getFunc] == nil then
538 return false
539 end
540
541 if setObject[setFunc] == nil then
542 return false
543 end
544
545 table.insert(spec.taskList, {getObject=getObject, getFunc=getFunc, getParams=getParams, setObject=setObject, setFunc=setFunc, setParams=setParams})
546
547 return false
548end

saveStatsToXMLFile

Description
Returns string with states for game stats xml file
Definition
saveStatsToXMLFile()
Return Values
stringattributesstats attributes
Code
861function AIVehicle:saveStatsToXMLFile(xmlFile, key)
862 setXMLBool(xmlFile, key.."#isAIActive", self:getIsAIActive())
863end

setAIMapHotspotBlinking

Description
Definition
setAIMapHotspotBlinking()
Code
851function AIVehicle:setAIMapHotspotBlinking(isBlinking)
852 local spec = self.spec_aiVehicle
853 if spec.mapAIHotspot ~= nil then
854 spec.mapAIHotspot:setBlinking(isBlinking)
855 end
856end

setAIMapHotspotVisibility

Description
Definition
setAIMapHotspotVisibility()
Code
842function AIVehicle:setAIMapHotspotVisibility(visibility)
843 local spec = self.spec_aiVehicle
844 if spec.mapAIHotspot ~= nil then
845 spec.mapAIHotspot.enabled = visibility
846 end
847end

startAIVehicle

Description
Starts ai vehicle
Definition
startAIVehicle(integer helperIndex, boolean noEventSend)
Arguments
integerhelperIndexindex of hired helper
booleannoEventSendno event send
Code
554function AIVehicle:startAIVehicle(helperIndex, noEventSend, startedFarmId)
555 local spec = self.spec_aiVehicle
556
557 if not self:getIsAIActive() then
558 if helperIndex ~= nil then
559 spec.currentHelper = g_helperManager:getHelperByIndex(helperIndex)
560 else
561 spec.currentHelper = g_helperManager:getRandomHelper()
562 end
563
564 g_helperManager:useHelper(spec.currentHelper)
565
566 spec.startedFarmId = startedFarmId
567
568 if self.isServer then
569 g_farmManager:updateFarmStats(startedFarmId, "workersHired", 1)
570 end
571
572 if noEventSend == nil or noEventSend == false then
573 local event = AIVehicleSetStartedEvent:new(self, nil, true, spec.currentHelper, startedFarmId)
574 if g_server ~= nil then
575 g_server:broadcastEvent(event, nil, nil, self)
576 else
577 g_client:getServerConnection():sendEvent(event)
578 end
579 end
580
581 AIVehicle.numHirablesHired = AIVehicle.numHirablesHired + 1
582 AIVehicle.hiredHirables[self] = self
583
584 if self.setRandomVehicleCharacter ~= nil then
585 self:setRandomVehicleCharacter()
586 end
587
588 local hotspotX, _, hotspotZ = getWorldTranslation(spec.rootNode)
589
590 local _, textSize = getNormalizedScreenValues(0, 9)
591 local _, textOffsetY = getNormalizedScreenValues(0, 18)
592 local width, height = getNormalizedScreenValues(24, 24)
593 spec.mapAIHotspot = MapHotspot:new("helper", MapHotspot.CATEGORY_AI)
594 spec.mapAIHotspot:setSize(width, height)
595 spec.mapAIHotspot:setLinkedNode(spec.components[1].node)
596 spec.mapAIHotspot:setText(spec.currentHelper.name)
597 spec.mapAIHotspot:setImage(nil, getNormalizedUVs(MapHotspot.UV.HELPER), {0.052, 0.1248, 0.672, 1})
598 spec.mapAIHotspot:setBackgroundImage(nil, getNormalizedUVs(MapHotspot.UV.HELPER))
599 spec.mapAIHotspot:setIconScale(0.7)
600 spec.mapAIHotspot:setTextOptions(textSize, nil, textOffsetY, {1, 1, 1, 1}, Overlay.ALIGN_VERTICAL_MIDDLE)
601 spec.mapAIHotspot:setHasDetails(false)
602 g_currentMission:addMapHotspot(spec.mapAIHotspot)
603
604 spec.isActive = true
605
606 if self.isServer then
607 self:updateAIImplementData()
608 self:updateAIDriveStrategies()
609 end
610
611 self:raiseAIEvent("onAIStart", "onAIImplementStart")
612 self:requestActionEventUpdate()
613
614 if self:getAINeedsTrafficCollisionBox() then
615 local collisionRoot = g_i3DManager:loadSharedI3DFile(AIVehicle.TRAFFIC_COLLISION_BOX_FILENAME, g_currentMission.baseDirectory, false, true, false)
616 if collisionRoot ~= nil and collisionRoot ~= 0 then
617 local collision = getChildAt(collisionRoot, 0)
618
619 link(getRootNode(), collision)
620 spec.aiTrafficCollision = collision
621
622 delete(collisionRoot)
623 end
624 end
625 end
626end

stopAIVehicle

Description
Stops ai vehicle
Definition
stopAIVehicle(integer reason, boolean noEventSend)
Arguments
integerreasonreason
booleannoEventSendno event send
Code
632function AIVehicle:stopAIVehicle(reason, noEventSend)
633 local spec = self.spec_aiVehicle
634
635 if self:getIsAIActive() then
636 if noEventSend == nil or noEventSend == false then
637 local event = AIVehicleSetStartedEvent:new(self, reason, false, nil, spec.startedFarmId)
638
639 if g_server ~= nil then
640 g_server:broadcastEvent(event, nil, nil, self)
641 else
642 g_client:getServerConnection():sendEvent(event)
643 end
644 end
645 spec.aiDriveParams.valid = false
646
647 if self.isClient then
648 if g_currentMission.player ~= nil then
649 if g_currentMission.player.farmId == spec.startedFarmId then
650 if reason ~= nil and reason ~= AIVehicle.STOP_REASON_USER then
651 local notificationType = FSBaseMission.INGAME_NOTIFICATION_CRITICAL
652 if reason == AIVehicle.STOP_REASON_REGULAR then
653 notificationType = FSBaseMission.INGAME_NOTIFICATION_OK
654 end
655
656 if g_currentMission.accessHandler:canPlayerAccess(self) then
657 g_currentMission:addIngameNotification(notificationType, string.format(g_i18n:getText(AIVehicle.REASON_TEXT_MAPPING[reason]), spec.currentHelper.name))
658 end
659 end
660 end
661 end
662 end
663
664 g_helperManager:releaseHelper(spec.currentHelper)
665 spec.currentHelper = nil
666
667 if self.isServer then
668 g_farmManager:updateFarmStats(spec.startedFarmId, "workersHired", -1)
669 end
670
671 AIVehicle.numHirablesHired = math.max(AIVehicle.numHirablesHired - 1, 0)
672 AIVehicle.hiredHirables[self] = nil
673
674 if self.restoreVehicleCharacter ~= nil then
675 self:restoreVehicleCharacter()
676 end
677
678 if spec.mapAIHotspot ~= nil then
679 g_currentMission:removeMapHotspot(spec.mapAIHotspot)
680 spec.mapAIHotspot:delete()
681 spec.mapAIHotspot = nil
682 end
683
684 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF, true)
685 if self.isServer then
686 WheelsUtil.updateWheelsPhysics(self, 0, spec.lastSpeedReal*spec.movingDirection, 0, true, true)
687
688 if spec.driveStrategies ~= nil and #spec.driveStrategies > 0 then
689 for i=#spec.driveStrategies,1,-1 do
690 spec.driveStrategies[i]:delete()
691 table.remove(spec.driveStrategies, i)
692 end
693 spec.driveStrategies = {}
694 end
695 end
696
697 spec.isActive = false
698 spec.isTurning = false
699
700 -- move the collision far under the ground
701 if self:getAINeedsTrafficCollisionBox() then
702 setTranslation(spec.aiTrafficCollision, 0, -1000, 0)
703 end
704
705 if self.brake ~= nil then
706 self:brake(1)
707 end
708
709 self:raiseAIEvent("onAIEnd", "onAIImplementEnd")
710 self:requestActionEventUpdate()
711 end
712end

updateAI

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
updateAI(float dt)
Arguments
floatdttime since last call in ms
Code
447function AIVehicle:updateAI(dt)
448 local spec = self.spec_aiVehicle
449 if spec.aiDriveParams.valid then
450 local moveForwards = spec.aiDriveParams.moveForwards
451 local tX = spec.aiDriveParams.tX
452 local tY = spec.aiDriveParams.tY
453 local tZ = spec.aiDriveParams.tZ
454 local maxSpeed = spec.aiDriveParams.maxSpeed
455
456 local pX, _, pZ = worldToLocal(self:getAIVehicleSteeringNode(), tX,tY,tZ)
457 if not moveForwards and self.spec_articulatedAxis ~= nil then
458 if self.spec_articulatedAxis.aiRevereserNode ~= nil then
459 pX, _, pZ = worldToLocal(self.spec_articulatedAxis.aiRevereserNode, tX,tY,tZ)
460 end
461 end
462
463 if not moveForwards and self:getAIVehicleReverserNode() ~= nil then
464 pX, _, pZ = worldToLocal(self:getAIVehicleReverserNode(), tX,tY,tZ)
465 end
466
467 local acceleration = 1.0
468 local isAllowedToDrive = maxSpeed ~= 0
469
470 AIVehicleUtil.driveToPoint(self, dt, acceleration, isAllowedToDrive, moveForwards, pX, pZ, maxSpeed)
471 end
472end

updateAIDriveStrategies

Description
Set drive strategies depending on the vehicle
Definition
updateAIDriveStrategies()
Code
792function AIVehicle:updateAIDriveStrategies()
793 local spec = self.spec_aiVehicle
794
795 if #spec.aiImplementList > 0 then
796 if spec.driveStrategies ~= nil and #spec.driveStrategies > 0 then
797 for i=#spec.driveStrategies,1,-1 do
798 spec.driveStrategies[i]:delete()
799 table.remove(spec.driveStrategies, i)
800 end
801 spec.driveStrategies = {}
802 end
803
804 local foundCombine = false
805 local foundBaler = false
806 for _,implement in pairs(spec.aiImplementList) do
807 if SpecializationUtil.hasSpecialization(Combine, implement.object.specializations) then
808 foundCombine = true
809 end
810 if SpecializationUtil.hasSpecialization(Baler, implement.object.specializations) then
811 foundBaler = true
812 end
813 end
814
815 foundCombine = foundCombine or SpecializationUtil.hasSpecialization(Combine, spec.specializations)
816 if foundCombine then
817 local driveStrategyCombine = AIDriveStrategyCombine:new()
818 driveStrategyCombine:setAIVehicle(self)
819 table.insert(spec.driveStrategies, driveStrategyCombine)
820 end
821
822 foundBaler = foundBaler or SpecializationUtil.hasSpecialization(Baler, spec.specializations)
823 if foundBaler then
824 local driveStrategyCombine = AIDriveStrategyBaler:new()
825 driveStrategyCombine:setAIVehicle(self)
826 table.insert(spec.driveStrategies, driveStrategyCombine)
827 end
828
829 local driveStrategyCollision = AIDriveStrategyCollision:new()
830 local driveStrategyStraight = AIDriveStrategyStraight:new()
831
832 driveStrategyCollision:setAIVehicle(self)
833 driveStrategyStraight:setAIVehicle(self)
834
835 table.insert(spec.driveStrategies, driveStrategyCollision)
836 table.insert(spec.driveStrategies, driveStrategyStraight)
837 end
838end

updateAIImplementData

Description
Fills aiImplementList with vehicles to use by ai
Definition
updateAIImplementData()
Code
771function AIVehicle:updateAIImplementData()
772 local spec = self.spec_aiVehicle
773
774 spec.aiImplementList = {}
775 self:addVehicleToAIImplementList(spec.aiImplementList)
776end

updateAILowFrequency

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
updateAILowFrequency(float dt)
Arguments
floatdttime since last call in ms
Code
350function AIVehicle:updateAILowFrequency(dt)
351 local spec = self.spec_aiVehicle
352
353 self:clearAIDebugTexts()
354 self:clearAIDebugLines()
355
356 if self:getIsAIActive() then
357 local difficultyMultiplier = g_currentMission.missionInfo.buyPriceMultiplier;
358 local price = -dt * difficultyMultiplier * spec.pricePerMS
359
360 -- If field was not owned, it is a mission. Increase the price for balancing.
361 if self.getLastTouchedFarmlandFarmId ~= nil and self:getLastTouchedFarmlandFarmId() == 0 then
362 price = price * MissionManager.AI_PRICE_MULTIPLIER
363 end
364
365 g_currentMission:addMoney(price, spec.startedFarmId, MoneyType.AI, true)
366
367 if spec.driveStrategies ~= nil and #spec.driveStrategies > 0 then
368 local vX,vY,vZ = getWorldTranslation(self:getAIVehicleSteeringNode())
369
370 local tX, tZ, moveForwards, maxSpeedStra, maxSpeed, distanceToStop
371 for i=1,#spec.driveStrategies do
372 local driveStrategy = spec.driveStrategies[i]
373 tX, tZ, moveForwards, maxSpeedStra, distanceToStop = driveStrategy:getDriveData(dt, vX,vY,vZ)
374 maxSpeed = math.min(maxSpeedStra or math.huge, maxSpeed or math.huge)
375 if tX ~= nil or not self:getIsAIActive() then
376 break
377 end
378 end
379
380 if tX == nil then
381 if self:getIsAIActive() then -- check if AI is still active, because it might have been kicked by a strategy
382 self:stopAIVehicle(AIVehicle.STOP_REASON_REGULAR)
383 end
384 end
385
386 if not self:getIsAIActive() then
387 return
388 end
389
390 local minimumSpeed = 5
391 local lookAheadDistance = 5
392
393 local distSpeed = math.max(minimumSpeed, maxSpeed * math.min(1, distanceToStop/lookAheadDistance))
394 local speedLimit, _ = self:getSpeedLimit()
395 maxSpeed = math.min(maxSpeed, distSpeed, speedLimit)
396 maxSpeed = math.min(maxSpeed, self:getCruiseControlMaxSpeed())
397
398 local isAllowedToDrive = maxSpeed ~= 0
399
400 -- set drive values
401 spec.aiDriveParams.moveForwards = moveForwards
402 spec.aiDriveParams.tX = tX
403 spec.aiDriveParams.tY = vY
404 spec.aiDriveParams.tZ = tZ
405 spec.aiDriveParams.maxSpeed = maxSpeed
406 spec.aiDriveParams.valid = true
407
408 spec.lastAllowedToDrive = isAllowedToDrive
409
410 -- worst case check: did not move but should have moved
411 if isAllowedToDrive and self:getLastSpeed() < 0.5 then
412 spec.didNotMoveTimer = spec.didNotMoveTimer - dt
413 else
414 spec.didNotMoveTimer = spec.didNotMoveTimeout
415 end
416
417 if spec.didNotMoveTimer < 0 then
418 self:stopAIVehicle(AIVehicle.STOP_REASON_BLOCKED_BY_OBJECT)
419 end
420 end
421
422 if #spec.taskList > 0 then
423 for i, task in pairs(spec.taskList) do
424 if VehicleDebug.state == VehicleDebug.DEBUG_AI then
425 self:addAIDebugText(string.format("AI TASK: %d - %s", i, task.getFunc))
426 end
427 if task.getObject ~= nil then
428 if task.getObject[task.getFunc](task.getObject, unpack(task.getParams)) then
429 task.setObject[task.setFunc](task.setObject, unpack(task.setParams))
430 spec.taskList[i] = nil
431 end
432 else
433 task.setObject[task.setFunc](task.setObject, unpack(task.setParams))
434 spec.taskList[i] = nil
435 end
436 end
437 end
438
439 self:raiseAIEvent("onAIActive", "onAIImplementActive")
440 end
441end