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
- 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
AIJob
DescriptionA job mainly runs on server only. Task starting, stopping and updating is server code only Client gets notified by targets. This avoids a lot of issues with async loading of vehicles e.g. if a vehicle is not available when job gets started or syncedFunctions
- addNamedParameter
- addTask
- applyCurrentState
- canContinueWork
- canStartWork
- delete
- getCanSkipTask
- getDescription
- getGroupedParameters
- getHelperName
- getIsAvailableForVehicle
- getIsLooping
- getIsStartable
- getNamedParameter
- getNamedParameters
- getNextTaskIndex
- getPricePerMs
- getStartTaskIndex
- getTaskByIndex
- getTitle
- loadFromXMLFile
- new
- onParameterValueChanged
- readStream
- resetTasks
- saveToXMLFile
- setId
- setParamterValid
- setValues
- showNotification
- skipCurrentTask
- start
- startTask
- stop
- stopTask
- update
- validate
- writeStream
addNamedParameter
DescriptionDefinitionaddNamedParameter()Code
344 | function AIJob:addNamedParameter(name, parameter) |
345 | table.insert(self.namedParameters, {name=name, parameter=parameter}) |
346 | end |
addTask
DescriptionDefinitionaddTask()Code
267 | function AIJob:addTask(task) |
268 | assert(task.taskIndex == nil, "Task already added") |
269 | table.insert(self.tasks, task) |
270 | task.taskIndex = #self.tasks |
271 | end |
applyCurrentState
DescriptionDefinitionapplyCurrentState()Code
387 | function AIJob:applyCurrentState(vehicle, mission, farmId, isDirectStart) |
388 | self.isDirectStart = isDirectStart |
389 | end |
canContinueWork
DescriptionDefinitioncanContinueWork()Code
166 | function AIJob:canContinueWork() |
167 | return true, nil |
168 | end |
canStartWork
DescriptionDefinitioncanStartWork()Code
172 | function AIJob:canStartWork() |
173 | return true, nil |
174 | end |
delete
DescriptionDefinitiondelete()Code
39 | function AIJob:delete() |
40 | for _, namedParameter in ipairs(self.namedParameters) do |
41 | namedParameter.parameter:delete() |
42 | end |
43 | for _, task in ipairs(self.tasks) do |
44 | task:delete() |
45 | end |
46 | end |
getCanSkipTask
DescriptionDefinitiongetCanSkipTask()Code
240 | function AIJob:getCanSkipTask() |
241 | return false |
242 | end |
getDescription
DescriptionDefinitiongetDescription()Code
296 | function AIJob:getDescription() |
297 | local jobType = g_currentMission.aiJobTypeManager:getJobTypeByIndex(self.jobTypeIndex) |
298 | return jobType.title |
299 | end |
getGroupedParameters
DescriptionDefinitiongetGroupedParameters()Code
381 | function AIJob:getGroupedParameters() |
382 | return self.groupedParameters |
383 | end |
getHelperName
DescriptionDefinitiongetHelperName()Code
303 | function AIJob:getHelperName() |
304 | local helper = g_helperManager:getHelperByIndex(self.helperIndex) |
305 | return helper.title |
306 | end |
getIsAvailableForVehicle
DescriptionDefinitiongetIsAvailableForVehicle()Code
393 | function AIJob:getIsAvailableForVehicle(vehicle) |
394 | return true |
395 | end |
getIsLooping
DescriptionDefinitiongetIsLooping()Code
196 | function AIJob:getIsLooping() |
197 | return false |
198 | end |
getIsStartable
DescriptionDefinitiongetIsStartable()Code
410 | function AIJob:getIsStartable(connection) |
411 | return true, AIJob.START_SUCCESS |
412 | end |
getNamedParameter
DescriptionDefinitiongetNamedParameter()Code
364 | function AIJob:getNamedParameter(name) |
365 | if name == nil then |
366 | return nil |
367 | end |
368 | |
369 | name = name:upper() |
370 | for _, data in ipairs(self.namedParameters) do |
371 | if data.name:upper() == name then |
372 | return data.parameter |
373 | end |
374 | end |
375 | |
376 | return nil |
377 | end |
getNamedParameters
DescriptionDefinitiongetNamedParameters()Code
358 | function AIJob:getNamedParameters() |
359 | return self.namedParameters |
360 | end |
getNextTaskIndex
DescriptionDefinitiongetNextTaskIndex()Code
184 | function AIJob:getNextTaskIndex() |
185 | return self.currentTaskIndex + 1 |
186 | end |
getPricePerMs
DescriptionDefinitiongetPricePerMs()Code
178 | function AIJob:getPricePerMs() |
179 | return 0.0004 |
180 | end |
getStartTaskIndex
DescriptionDefinitiongetStartTaskIndex()Code
338 | function AIJob:getStartTaskIndex() |
339 | return 1 |
340 | end |
getTaskByIndex
DescriptionDefinitiongetTaskByIndex()Code
283 | function AIJob:getTaskByIndex(taskIndex) |
284 | return self.tasks[taskIndex] |
285 | end |
getTitle
DescriptionDefinitiongetTitle()Code
289 | function AIJob:getTitle() |
290 | local helper = g_helperManager:getHelperByIndex(self.helperIndex) |
291 | return helper.title |
292 | end |
loadFromXMLFile
DescriptionDefinitionloadFromXMLFile()Code
67 | function AIJob:loadFromXMLFile(xmlFile, key) |
68 | xmlFile:iterate(key .. ".parameter", function(_, paramKey) |
69 | local name = xmlFile:getString(paramKey .. "#name") |
70 | if name ~= nil then |
71 | local parameter = self:getNamedParameter(name) |
72 | if parameter ~= nil and parameter.loadFromXMLFile ~= nil then |
73 | parameter:loadFromXMLFile(xmlFile, paramKey) |
74 | end |
75 | end |
76 | end) |
77 | end |
new
DescriptionDefinitionnew()Code
22 | function AIJob.new(isServer, customMt) |
23 | local self = setmetatable({}, customMt or AIJob_mt) |
24 | |
25 | self.isServer = isServer |
26 | self.tasks = {} |
27 | self.namedParameters = {} |
28 | self.groupedParameters = {} |
29 | self.currentTaskIndex = 0 |
30 | self.jobId = nil |
31 | self.startedFarmId = nil |
32 | self.isDirectStart = false |
33 | |
34 | return self |
35 | end |
onParameterValueChanged
DescriptionDefinitiononParameterValueChanged()Code
405 | function AIJob:onParameterValueChanged(parameter) |
406 | end |
readStream
DescriptionDefinitionreadStream()Code
81 | function AIJob:readStream(streamId, connection) |
82 | self.isDirectStart = streamReadBool(streamId) |
83 | |
84 | if streamReadBool(streamId) then |
85 | self.jobId = streamReadInt32(streamId) |
86 | end |
87 | |
88 | for _, namedParameter in ipairs(self.namedParameters) do |
89 | namedParameter.parameter:readStream(streamId, connection) |
90 | end |
91 | |
92 | self:setValues() |
93 | |
94 | self.currentTaskIndex = streamReadUInt8(streamId) |
95 | end |
resetTasks
DescriptionDefinitionresetTasks()Code
275 | function AIJob:resetTasks() |
276 | for _, task in ipairs(self.tasks) do |
277 | task:reset() |
278 | end |
279 | end |
saveToXMLFile
DescriptionDefinitionsaveToXMLFile()Code
50 | function AIJob:saveToXMLFile(xmlFile, key, usedModNames) |
51 | local index = 0 |
52 | for _, namedParameter in ipairs(self.namedParameters) do |
53 | local parameter = namedParameter.parameter |
54 | if parameter.saveToXMLFile ~= nil then |
55 | local paramKey = string.format("%s.parameter(%d)", key, index) |
56 | xmlFile:setString(paramKey .. "#name", namedParameter.name) |
57 | namedParameter.parameter:saveToXMLFile(xmlFile, paramKey, usedModNames) |
58 | index = index + 1 |
59 | end |
60 | end |
61 | |
62 | return true |
63 | end |
setId
DescriptionDefinitionsetId()Code
399 | function AIJob:setId(id) |
400 | self.jobId = id |
401 | end |
setParamterValid
DescriptionDefinitionsetParamterValid()Code
350 | function AIJob:setParamterValid(isValid) |
351 | for _, namedParameter in ipairs(self.namedParameters) do |
352 | namedParameter.parameter:setIsValid(isValid) |
353 | end |
354 | end |
setValues
DescriptionDefinitionsetValues()Code
202 | function AIJob:setValues() |
203 | end |
showNotification
DescriptionDefinitionshowNotification()Code
310 | function AIJob:showNotification(aiMessage) |
311 | local helper = g_helperManager:getHelperByIndex(self.helperIndex) |
312 | |
313 | -- helper can be nil on game quit |
314 | if helper ~= nil then |
315 | local playerFarmId |
316 | if g_currentMission ~= nil and g_currentMission.player ~= nil then |
317 | playerFarmId = g_currentMission.player.farmId |
318 | end |
319 | |
320 | if aiMessage ~= nil and self.startedFarmId == playerFarmId then |
321 | local text = aiMessage:getMessage() |
322 | local errorType = aiMessage:getType() |
323 | local notificationType = FSBaseMission.INGAME_NOTIFICATION_CRITICAL |
324 | |
325 | if errorType == AIMessageType.OK then |
326 | notificationType = FSBaseMission.INGAME_NOTIFICATION_OK |
327 | elseif errorType == AIMessageType.INFO then |
328 | notificationType = FSBaseMission.INGAME_NOTIFICATION_INFO |
329 | end |
330 | |
331 | g_currentMission:addIngameNotification(notificationType, string.format(text, helper.name, aiMessage:getMessageArguments())) |
332 | end |
333 | end |
334 | end |
skipCurrentTask
DescriptionDefinitionskipCurrentTask()Code
246 | function AIJob:skipCurrentTask() |
247 | end |
start
DescriptionDefinitionstart()Code
228 | function AIJob:start(farmId) |
229 | self.helperIndex = g_helperManager:getRandomIndex() |
230 | self.startedFarmId = farmId |
231 | self.isRunning = true |
232 | |
233 | if self.isServer then |
234 | self.currentTaskIndex = 0 |
235 | end |
236 | end |
startTask
DescriptionDefinitionstartTask()Code
207 | function AIJob:startTask(task) |
208 | self.currentTaskIndex = task.taskIndex |
209 | task:start() |
210 | |
211 | if self.isServer then |
212 | g_server:broadcastEvent(AITaskStartEvent.new(self, task)) |
213 | end |
214 | end |
stop
DescriptionDefinitionstop()Code
251 | function AIJob:stop(aiMessage) |
252 | self.isRunning = false |
253 | |
254 | if self.isServer and self.currentTaskIndex ~= 0 then |
255 | -- client will be notified in stopTask function |
256 | local task = self:getTaskByIndex(self.currentTaskIndex) |
257 | self:stopTask(task, true) |
258 | end |
259 | |
260 | self:showNotification(aiMessage) |
261 | |
262 | self:resetTasks() |
263 | end |
stopTask
DescriptionDefinitionstopTask()Code
218 | function AIJob:stopTask(task, wasJobStopped) |
219 | task:stop(wasJobStopped) |
220 | |
221 | if self.isServer then |
222 | g_server:broadcastEvent(AITaskStopEvent.new(self, task, wasJobStopped)) |
223 | end |
224 | end |
update
DescriptionDefinitionupdate()Code
115 | function AIJob:update(dt) |
116 | -- task update and handling is done on server side only |
117 | if self.isServer then |
118 | local currentTask |
119 | if self.currentTaskIndex == 0 then |
120 | local canStart, aiMessage = self:canStartWork() |
121 | if canStart then |
122 | local taskIndex = self:getStartTaskIndex() |
123 | local task = self:getTaskByIndex(taskIndex) |
124 | self:startTask(task) |
125 | else |
126 | g_currentMission.aiSystem:stopJob(self, aiMessage) |
127 | return |
128 | end |
129 | else |
130 | currentTask = self:getTaskByIndex(self.currentTaskIndex) |
131 | end |
132 | |
133 | if currentTask ~= nil then |
134 | currentTask:update(dt) |
135 | |
136 | if currentTask:getIsFinished() then |
137 | local canContinue, aiMessage = self:canContinueWork() |
138 | if not canContinue then |
139 | g_currentMission.aiSystem:stopJob(self, aiMessage) |
140 | return |
141 | end |
142 | |
143 | |
144 | local newTaskIndex = self:getNextTaskIndex() |
145 | |
146 | if newTaskIndex > #self.tasks then |
147 | if self:getIsLooping() then |
148 | newTaskIndex = 1 |
149 | else |
150 | g_currentMission.aiSystem:stopJob(self, AIMessageSuccessFinishedJob.new()) |
151 | return |
152 | end |
153 | end |
154 | |
155 | self:stopTask(currentTask, false) |
156 | |
157 | local nextTask = self:getTaskByIndex(newTaskIndex) |
158 | self:startTask(nextTask) |
159 | end |
160 | end |
161 | end |
162 | end |
validate
DescriptionDefinitionvalidate()Code
190 | function AIJob:validate(farmId) |
191 | return true, nil |
192 | end |
writeStream
DescriptionDefinitionwriteStream()Code
99 | function AIJob:writeStream(streamId, connection) |
100 | streamWriteBool(streamId, self.isDirectStart) |
101 | |
102 | if streamWriteBool(streamId, self.jobId ~= nil) then |
103 | streamWriteInt32(streamId, self.jobId) |
104 | end |
105 | |
106 | for _, namedParameter in ipairs(self.namedParameters) do |
107 | namedParameter.parameter:writeStream(streamId, connection) |
108 | end |
109 | |
110 | streamWriteUInt8(streamId, self.currentTaskIndex) |
111 | end |