LUADOC - Farming Simulator 22

AIJobLoadAndDeliver

Description
AIJobDeliver
Parent
AIJob
Functions

applyCurrentState

Description
Definition
applyCurrentState()
Code
217function AIJobLoadAndDeliver:applyCurrentState(vehicle, mission, farmId, isDirectStart)
218 AIJobLoadAndDeliver:superClass().applyCurrentState(self, vehicle, mission, farmId, isDirectStart)
219
220 self.vehicleParameter:setVehicle(vehicle)
221 self.loopingParameter:setIsLooping(true)
222
223 if vehicle.getLastJob ~= nil then
224 local lastJob = vehicle:getLastJob()
225 if lastJob ~= nil and lastJob:isa(AIJobLoadAndDeliver) then
226 self.unloadingStationParameter:setUnloadingStation(lastJob.unloadingStationParameter:getUnloadingStation())
227 self.loadingStationParameter:setLoadingStation(lastJob.loadingStationParameter:getLoadingStation())
228 self.loopingParameter:setIsLooping(lastJob.loopingParameter:getIsLooping())
229 end
230 end
231
232 local unloadingStations = {}
233 for _, unloadingStation in pairs(g_currentMission.storageSystem:getUnloadingStations()) do
234 if g_currentMission.accessHandler:canPlayerAccess(unloadingStation) and unloadingStation:isa(UnloadingStation) then
235 local fillTypes = unloadingStation:getAISupportedFillTypes()
236 if next(fillTypes) ~= nil then
237 table.insert(unloadingStations, unloadingStation)
238 end
239 end
240 end
241 self.unloadingStationParameter:setValidUnloadingStations(unloadingStations)
242
243 local loadingStations = {}
244 for _, loadingStation in pairs(g_currentMission.storageSystem:getLoadingStations()) do
245 if g_currentMission.accessHandler:canPlayerAccess(loadingStation) then
246 local fillTypes = loadingStation:getAISupportedFillTypes()
247 if next(fillTypes) ~= nil then
248 table.insert(loadingStations, loadingStation)
249 end
250 end
251 end
252 self.loadingStationParameter:setValidLoadingStations(loadingStations)
253
254 local loadingStation = self.loadingStationParameter:getLoadingStation()
255 self:updateFillTypes(loadingStation)
256end

canContinueWork

Description
Definition
canContinueWork()
Code
375function AIJobLoadAndDeliver:canContinueWork()
376 local vehicle = self.vehicleParameter:getVehicle()
377 if vehicle == nil then
378 return false, AIMessageErrorVehicleDeleted.new()
379 end
380
381 local loadingStation = self.loadingStationParameter:getLoadingStation()
382 if loadingStation == nil then
383 return false, AIMessageErrorLoadingStationDeleted.new()
384 end
385
386 local unloadingStation = self.unloadingStationParameter:getUnloadingStation()
387 if unloadingStation == nil then
388 return false, AIMessageErrorUnloadingStationDeleted.new()
389 end
390
391 local fillTypeIndex = self.fillTypeParameter:getFillTypeIndex()
392 if unloadingStation:getFreeCapacity(fillTypeIndex, self.startedFarmId) <= 0 then
393 return false, AIMessageErrorUnloadingStationFull.new()
394 end
395
396 if self.currentTaskIndex == self.loadingTask.taskIndex then
397 if loadingStation:getFillLevel(fillTypeIndex, self.startedFarmId) <= 0 then
398 local isEmpty = true
399 for _, loadingNodeInfo in ipairs(self.loadingNodeInfos) do
400 local loadingVehicle = loadingNodeInfo.vehicle
401 local fillUnitIndex = loadingNodeInfo.fillUnitIndex
402 if loadingVehicle:getFillUnitFillLevel(fillUnitIndex) > 0 and loadingVehicle:getFillUnitFillType(fillUnitIndex) == fillTypeIndex then
403 isEmpty = false
404 break
405 end
406 end
407
408 if isEmpty then
409 return false, AIMessageSuccessSiloEmpty.new()
410 end
411 end
412 end
413
414 return true, nil
415end

getDescription

Description
Definition
getDescription()
Code
543function AIJobLoadAndDeliver:getDescription()
544 local desc = AIJobLoadAndDeliver:superClass().getDescription(self)
545
546 local nextTask = self:getTaskByIndex(self.currentTaskIndex)
547 if nextTask == self.driveToLoadingTask then
548 desc = desc .. " - " .. g_i18n:getText("ai_taskDescriptionDriveToLoadingStation")
549 elseif nextTask == self.loadingTask then
550 desc = desc .. " - " .. g_i18n:getText("ai_taskDescriptionLoading")
551 elseif nextTask == self.driveToUnloadingTask then
552 desc = desc .. " - " .. g_i18n:getText("ai_taskDescriptionDriveToUnloadingStation")
553 elseif nextTask == self.dischargeTask then
554 desc = desc .. " - " .. g_i18n:getText("ai_taskDescriptionUnloading")
555 end
556
557 return desc
558end

getIsAvailableForVehicle

Description
Definition
getIsAvailableForVehicle()
Code
462function AIJobLoadAndDeliver:getIsAvailableForVehicle(vehicle)
463 if vehicle.createAgent == nil or vehicle.setAITarget == nil or not vehicle:getCanStartAIVehicle() then
464 return false
465 end
466
467 local vehicles = vehicle:getChildVehicles()
468 for _, childVehicle in ipairs(vehicles) do
469 if childVehicle.getAIDischargeNodes ~= nil then
470 local nodes = childVehicle:getAIDischargeNodes()
471 if next(nodes) ~= nil then
472 return true
473 end
474 end
475 end
476
477 local foundDischargeNodes = false
478 if vehicle.getAIDischargeNodes ~= nil then
479 local nodes = vehicle:getAIDischargeNodes()
480 if next(nodes) ~= nil then
481 foundDischargeNodes = true
482 end
483 end
484
485 if not foundDischargeNodes then
486 vehicles = vehicle:getChildVehicles()
487 for _, childVehicle in ipairs(vehicles) do
488 if childVehicle.getAIDischargeNodes ~= nil then
489 local nodes = childVehicle:getAIDischargeNodes()
490 if next(nodes) ~= nil then
491 foundDischargeNodes = true
492 break
493 end
494 end
495 end
496 end
497
498 if not foundDischargeNodes then
499 return false
500 end
501
502 local foundLoadingNodes = false
503 if vehicle.getAIFillUnits ~= nil then
504 local fillUnits = vehicle:getAIFillUnits()
505 if next(fillUnits) ~= nil then
506 foundLoadingNodes = true
507 end
508 end
509
510 if not foundLoadingNodes then
511 vehicles = vehicle:getChildVehicles()
512 for _, childVehicle in ipairs(vehicles) do
513 if childVehicle.getAIFillUnits ~= nil then
514 local fillUnits = childVehicle:getAIFillUnits()
515 if next(fillUnits) ~= nil then
516 foundLoadingNodes = true
517 break
518 end
519 end
520 end
521 end
522
523 if not foundLoadingNodes then
524 return false
525 end
526
527 return true
528end

getIsLooping

Description
Definition
getIsLooping()
Code
562function AIJobLoadAndDeliver:getIsLooping()
563 return self.loopingParameter:getIsLooping()
564end

getIsStartable

Description
Definition
getIsStartable()
Code
568function AIJobLoadAndDeliver:getIsStartable(connection)
569 if g_currentMission.aiSystem:getAILimitedReached() then
570 return false, AIJobLoadAndDeliver.START_ERROR_LIMIT_REACHED
571 end
572
573 local vehicle = self.vehicleParameter:getVehicle()
574 if vehicle == nil then
575 return false, AIJobLoadAndDeliver.START_ERROR_VEHICLE_DELETED
576 end
577
578 if not g_currentMission:getHasPlayerPermission("hireAssistant", connection, vehicle:getOwnerFarmId()) then
579 return false, AIJobLoadAndDeliver.START_ERROR_NO_PERMISSION
580 end
581
582 if vehicle:getIsInUse(connection) then
583 return false, AIJobLoadAndDeliver.START_ERROR_VEHICLE_IN_USE
584 end
585
586 return true, AIJob.START_SUCCESS
587end

getIsStartErrorText

Description
Definition
getIsStartErrorText()
Code
591function AIJobLoadAndDeliver.getIsStartErrorText(state)
592 if state == AIJobLoadAndDeliver.START_ERROR_LIMIT_REACHED then
593 return g_i18n:getText("ai_startStateLimitReached")
594 elseif state == AIJobLoadAndDeliver.START_ERROR_VEHICLE_DELETED then
595 return g_i18n:getText("ai_startStateVehicleDeleted")
596 elseif state == AIJobLoadAndDeliver.START_ERROR_NO_PERMISSION then
597 return g_i18n:getText("ai_startStateNoPermission")
598 elseif state == AIJobLoadAndDeliver.START_ERROR_VEHICLE_IN_USE then
599 return g_i18n:getText("ai_startStateVehicleInUse")
600 end
601
602 return g_i18n:getText("ai_startStateSuccess")
603end

getNextTaskIndex

Description
Definition
getNextTaskIndex()
Code
419function AIJobLoadAndDeliver:getNextTaskIndex(isSkipTask)
420 if self.currentTaskIndex == self.driveToLoadingTask.taskIndex or self.currentTaskIndex == self.loadingTask.taskIndex then
421 -- check if there are more loadingNodes that need loading
422 for _, loadingNodeInfo in ipairs(self.loadingNodeInfos) do
423 if loadingNodeInfo.isDirty then
424 local vehicle = loadingNodeInfo.vehicle
425 local fillUnitIndex = loadingNodeInfo.fillUnitIndex
426 if vehicle:getFillUnitFillLevel(fillUnitIndex) == 0 then
427 self.loadingTask:setFillUnit(vehicle, fillUnitIndex, loadingNodeInfo.offsetZ)
428 loadingNodeInfo.isDirty = false
429--#debug log("drive to loading next fillunit")
430 return self.loadingTask.taskIndex
431 end
432
433 loadingNodeInfo.isDirty = false
434 end
435 end
436
437 elseif self.currentTaskIndex == self.driveToUnloadingTask.taskIndex or self.currentTaskIndex == self.dischargeTask.taskIndex then
438 local fillTypeIndex = self.fillTypeParameter:getFillTypeIndex()
439 for _, dischargeNodeInfo in ipairs(self.dischargeNodeInfos) do
440 if dischargeNodeInfo.isDirty then
441 local vehicle = dischargeNodeInfo.vehicle
442 local fillUnitIndex = dischargeNodeInfo.dischargeNode.fillUnitIndex
443 if vehicle:getFillUnitFillLevel(fillUnitIndex) > 1 and vehicle:getFillUnitFillType(fillUnitIndex) == fillTypeIndex then
444 self.dischargeTask:setDischargeNode(vehicle, dischargeNodeInfo.dischargeNode, dischargeNodeInfo.offsetZ)
445 dischargeNodeInfo.isDirty = false
446--#debug log("drive to discharge next trailer")
447 return self.dischargeTask.taskIndex
448 end
449
450 dischargeNodeInfo.isDirty = false
451 end
452 end
453 end
454
455 local nextTaskIndex = AIJobDeliver:superClass().getNextTaskIndex(self, isSkipTask)
456--#debug log("AIJobLoadAndDeliver:getNextTaskIndex(): ", self.currentTaskIndex, "->", nextTaskIndex)
457 return nextTaskIndex
458end

getStartTaskIndex

Description
Definition
getStartTaskIndex()
Code
330function AIJobLoadAndDeliver:getStartTaskIndex()
331 local hasOneEmptyFillUnit = false
332 for _, loadingNodeInfo in ipairs(self.loadingNodeInfos) do
333 local vehicle = loadingNodeInfo.vehicle
334 local fillUnitIndex = loadingNodeInfo.fillUnitIndex
335 if vehicle:getFillUnitFillLevel(fillUnitIndex) == 0 then
336 hasOneEmptyFillUnit = true
337 break
338 end
339 end
340
341 if not hasOneEmptyFillUnit then
342 return self.driveToUnloadingTask.taskIndex
343 end
344
345 return self.driveToLoadingTask.taskIndex
346end

getTitle

Description
Definition
getTitle()
Code
532function AIJobLoadAndDeliver:getTitle()
533 local vehicle = self.vehicleParameter:getVehicle()
534 if vehicle ~= nil then
535 return vehicle:getName()
536 end
537
538 return ""
539end

new

Description
Definition
new()
Code
22function AIJobLoadAndDeliver.new(isServer, customMt)
23 local self = AIJob.new(isServer, customMt or AIJobLoadAndDeliver_mt)
24
25 self.dischargeNodeInfos = {}
26 self.loadingNodeInfos = {}
27
28 self.driveToLoadingTask = AITaskDriveTo.new(isServer, self)
29 self.loadingTask = AITaskLoading.new(isServer, self)
30 self.driveToUnloadingTask = AITaskDriveTo.new(isServer, self)
31 self.dischargeTask = AITaskDischarge.new(isServer, self)
32
33 self:addTask(self.driveToLoadingTask)
34 self:addTask(self.loadingTask)
35 self:addTask(self.driveToUnloadingTask)
36 self:addTask(self.dischargeTask)
37
38 self.vehicleParameter = AIParameterVehicle.new()
39 self.unloadingStationParameter = AIParameterUnloadingStation.new()
40 self.loadingStationParameter = AIParameterLoadingStation.new()
41 self.fillTypeParameter = AIParameterFillType.new()
42 self.loopingParameter = AIParameterLooping.new()
43
44 self:addNamedParameter("vehicle", self.vehicleParameter)
45 self:addNamedParameter("loadingStation", self.loadingStationParameter)
46 self:addNamedParameter("fillType", self.fillTypeParameter)
47 self:addNamedParameter("unloadingStation", self.unloadingStationParameter)
48 self:addNamedParameter("looping", self.loopingParameter)
49
50 local vehicleGroup = AIParameterGroup.new(g_i18n:getText("ai_parameterGroupTitleVehicle"))
51 vehicleGroup:addParameter(self.vehicleParameter)
52
53 local loadTargetGroup = AIParameterGroup.new(g_i18n:getText("ai_parameterGroupTitleLoadingStation"))
54 loadTargetGroup:addParameter(self.loadingStationParameter)
55 loadTargetGroup:addParameter(self.fillTypeParameter)
56
57 local unloadTargetGroup = AIParameterGroup.new(g_i18n:getText("ai_parameterGroupTitleUnloadingStation"))
58 unloadTargetGroup:addParameter(self.unloadingStationParameter)
59
60 local loopingGroup = AIParameterGroup.new(g_i18n:getText("ai_parameterGroupTitleLooping"))
61 loopingGroup:addParameter(self.loopingParameter)
62
63 table.insert(self.groupedParameters, vehicleGroup)
64 table.insert(self.groupedParameters, loadTargetGroup)
65 table.insert(self.groupedParameters, unloadTargetGroup)
66 table.insert(self.groupedParameters, loopingGroup)
67
68 return self
69end

onParameterValueChanged

Description
Definition
onParameterValueChanged()
Code
274function AIJobLoadAndDeliver:onParameterValueChanged(parameter)
275 if parameter == self.loadingStationParameter then
276 local loadingStation = self.loadingStationParameter:getLoadingStation()
277 self:updateFillTypes(loadingStation)
278 end
279end

setValues

Description
Definition
setValues()
Code
73function AIJobLoadAndDeliver:setValues()
74 self:resetTasks()
75
76 local vehicle = self.vehicleParameter:getVehicle()
77 if vehicle == nil then
78 return
79 end
80 local loadingStation = self.loadingStationParameter:getLoadingStation()
81 if loadingStation == nil then
82 return
83 end
84 local unloadingStation = self.unloadingStationParameter:getUnloadingStation()
85 if unloadingStation == nil then
86 return
87 end
88 local fillTypeIndex = self.fillTypeParameter:getFillTypeIndex()
89
90 self.loadingTask:setVehicle(vehicle)
91 self.driveToUnloadingTask:setVehicle(vehicle)
92 self.driveToLoadingTask:setVehicle(vehicle)
93 self.dischargeTask:setVehicle(vehicle)
94
95 self.loadingNodeInfos = {}
96 self.dischargeNodeInfos = {}
97
98 if vehicle.getAIFillUnits ~= nil then
99 for _, fillUnit in ipairs(vehicle:getAIFillUnits()) do
100 local fillUnitIndex = fillUnit.fillUnitIndex
101 local _, _, z = vehicle:getAILoadingNodeZAlignedOffset(fillUnitIndex, vehicle)
102 table.insert(self.loadingNodeInfos, {vehicle=vehicle, fillUnitIndex=fillUnitIndex, offsetZ=z, isDirty=true})
103 end
104 end
105
106 if vehicle.getAIDischargeNodes ~= nil then
107 for _, dischargeNode in ipairs(vehicle:getAIDischargeNodes()) do
108 local _, _, z = vehicle:getAIDischargeNodeZAlignedOffset(dischargeNode, vehicle)
109 table.insert(self.dischargeNodeInfos, {vehicle=vehicle, dischargeNode=dischargeNode, offsetZ=z, isDirty=true})
110 end
111 end
112
113 local childVehicles = vehicle:getChildVehicles()
114 for _, childVehicle in ipairs(childVehicles) do
115 if childVehicle.getAIDischargeNodes ~= nil then
116 for _, dischargeNode in ipairs(childVehicle:getAIDischargeNodes()) do
117 local _, _, z = childVehicle:getAIDischargeNodeZAlignedOffset(dischargeNode, vehicle)
118 table.insert(self.dischargeNodeInfos, {vehicle=childVehicle, dischargeNode=dischargeNode, offsetZ=z, isDirty=true})
119 end
120 end
121
122 if childVehicle.getAIFillUnits ~= nil then
123 for _, fillUnit in ipairs(childVehicle:getAIFillUnits()) do
124 local fillUnitIndex = fillUnit.fillUnitIndex
125 local _, _, z = childVehicle:getAILoadingNodeZAlignedOffset(fillUnitIndex, vehicle)
126 table.insert(self.loadingNodeInfos, {vehicle=childVehicle, fillUnitIndex=fillUnitIndex, offsetZ=z, isDirty=true})
127 end
128 end
129 end
130
131 table.sort(self.dischargeNodeInfos, function(a, b)
132 return a.offsetZ > b.offsetZ
133 end)
134
135 table.sort(self.loadingNodeInfos, function(a, b)
136 return a.offsetZ > b.offsetZ
137 end)
138
139 local maxDischargeOffset = 0
140 if #self.dischargeNodeInfos > 0 then
141 maxDischargeOffset = self.dischargeNodeInfos[#self.dischargeNodeInfos].offsetZ
142 end
143 self.driveToUnloadingTask:setTargetOffset(-maxDischargeOffset)
144
145 local maxLoadingOffset = 0
146 if #self.loadingNodeInfos > 0 then
147 maxLoadingOffset = self.loadingNodeInfos[#self.loadingNodeInfos].offsetZ
148 end
149 self.driveToLoadingTask:setTargetOffset(-maxLoadingOffset)
150
151 if fillTypeIndex ~= nil then
152 if loadingStation ~= nil then
153 local x, z, dirX, dirZ, trigger = loadingStation:getAITargetPositionAndDirection(fillTypeIndex)
154 if trigger ~= nil then
155 self.driveToLoadingTask:setTargetPosition(x, z)
156 self.driveToLoadingTask:setTargetDirection(dirX, dirZ)
157 self.loadingTask:setLoadTrigger(trigger)
158 end
159 end
160 if unloadingStation ~= nil then
161 local x, z, dirX, dirZ, trigger = unloadingStation:getAITargetPositionAndDirection(fillTypeIndex)
162 if trigger ~= nil then
163 self.driveToUnloadingTask:setTargetPosition(x, z)
164 self.driveToUnloadingTask:setTargetDirection(dirX, dirZ)
165 self.dischargeTask:setUnloadTrigger(trigger)
166 end
167 end
168
169 self.loadingTask:setFillType(fillTypeIndex)
170 end
171end

start

Description
Definition
start()
Code
283function AIJobLoadAndDeliver:start(farmId)
284 -- Client start notification will be done by vehicle
285 AIJobLoadAndDeliver:superClass().start(self, farmId)
286
287 if self.isServer then
288 local vehicle = self.vehicleParameter:getVehicle()
289 vehicle:createAgent(self.helperIndex)
290 vehicle:aiJobStarted(self, self.helperIndex, farmId)
291 end
292end

startTask

Description
Definition
startTask()
Code
312function AIJobLoadAndDeliver:startTask(task)
313 if task == self.driveToLoadingTask then
314 -- mark all discharge infos as isDirty
315 for _, dischargeNodeInfo in ipairs(self.dischargeNodeInfos) do
316 dischargeNodeInfo.isDirty = true
317 end
318 elseif task == self.driveToUnloadingTask then
319 -- mark all fillunit infos as isDirty
320 for _, loadingNodeInfo in ipairs(self.loadingNodeInfos) do
321 loadingNodeInfo.isDirty = true
322 end
323 end
324
325 AIJobLoadAndDeliver:superClass().startTask(self, task)
326end

stop

Description
Definition
stop()
Code
296function AIJobLoadAndDeliver:stop(aiMessage)
297 -- Client stop notifcation will be done by vehicle
298 if self.isServer then
299 local vehicle = self.vehicleParameter:getVehicle()
300 vehicle:deleteAgent()
301 vehicle:aiJobFinished()
302 end
303
304 AIJobLoadAndDeliver:superClass().stop(self, aiMessage)
305
306 self.loadingNodeInfos = {}
307 self.dischargeNodeInfos = {}
308end

updateFillTypes

Description
Definition
updateFillTypes()
Code
260function AIJobLoadAndDeliver:updateFillTypes(loadingStation)
261 local fillTypes = {}
262
263 if loadingStation ~= nil then
264 for fillTypeIndex, _ in pairs(loadingStation:getAISupportedFillTypes()) do
265 fillTypes[fillTypeIndex] = loadingStation:getFillLevel(fillTypeIndex, g_currentMission.player.farmId)
266 end
267 end
268
269 self.fillTypeParameter:setValidFillTypes(fillTypes)
270end

validate

Description
Definition
validate()
Code
175function AIJobLoadAndDeliver:validate(farmId)
176 self:setParamterValid(true)
177
178 local isVehicleValid, vehicleErrorMessage = self.vehicleParameter:validate()
179 if isVehicleValid then
180 if #self.dischargeNodeInfos == 0 then
181 isVehicleValid = false
182 vehicleErrorMessage = g_i18n:getText("ai_validationErrorNoAIDischargeNodesFound")
183 elseif #self.loadingNodeInfos == 0 then
184 isVehicleValid = false
185 vehicleErrorMessage = g_i18n:getText("ai_validationErrorNoAILoadingNodesFound")
186 end
187 end
188 if not isVehicleValid then
189 self.vehicleParameter:setIsValid(false)
190 end
191
192 local isFillTypeValid, fillTypeErrorMessage = self.fillTypeParameter:validate()
193 if not isFillTypeValid then
194 self.fillTypeParameter:setIsValid(false)
195 end
196
197 local fillTypeIndex = self.fillTypeParameter:getFillTypeIndex()
198
199 local isLoadingStationValid, loadingStationErrorMessage = self.loadingStationParameter:validate(fillTypeIndex, farmId)
200 if not isLoadingStationValid then
201 self.loadingStationParameter:setIsValid(false)
202 end
203
204 local isUnloadingStationValid, unloadingStationErrorMessage = self.unloadingStationParameter:validate(fillTypeIndex, farmId)
205 if not isUnloadingStationValid then
206 self.unloadingStationParameter:setIsValid(false)
207 end
208
209 local isValid = isVehicleValid and isFillTypeValid and isLoadingStationValid and isUnloadingStationValid
210 local errorMessage = vehicleErrorMessage or fillTypeErrorMessage or loadingStationErrorMessage or unloadingStationErrorMessage
211
212 return isValid, errorMessage
213end