LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

WorkMode

Description
Specialization for tools with switchable work modes by providing grouping of different animations and work areas
Functions

actionEventWorkModeChange

Description
Definition
actionEventWorkModeChange()
Code
965function WorkMode.actionEventWorkModeChange(self, actionName, inputValue, callbackState, isAnalog)
966 local spec = self.spec_workMode
967 local state = spec.state + 1
968 if state > spec.stateMax then
969 state = 1
970 end
971
972 if state ~= spec.state then
973 self:setWorkMode(state)
974 end
975end

actionEventWorkModeChangeDirect

Description
Definition
actionEventWorkModeChangeDirect()
Code
979function WorkMode.actionEventWorkModeChangeDirect(self, actionName, inputValue, callbackState, isAnalog)
980 local spec = self.spec_workMode
981
982 for state, mode in ipairs(spec.workModes) do
983 if mode.inputAction == InputAction[actionName] then
984 if state ~= spec.state then
985 self:setWorkMode(state)
986 end
987 end
988 end
989end

deactivateWindrowerEffects

Description
Called on deactivate
Definition
deactivateWindrowerEffects()
Code
579function WorkMode:deactivateWindrowerEffects()
580 if self.isClient then
581 local spec = self.spec_workMode
582 for _, mode in pairs(spec.workModes) do
583 if mode.windrowerEffects ~= nil then
584 g_effectManager:stopEffects(mode.windrowerEffects)
585 end
586 end
587 end
588end

getAllowsLowering

Description
Definition
getAllowsLowering()
Code
725function WorkMode:getAllowsLowering(superFunc)
726 local allowLowering, warning = superFunc(self)
727
728 local spec = self.spec_workMode
729 local hasLoweringAnimations = false
730 if #spec.workModes > 0 then
731 hasLoweringAnimations = #spec.workModes[spec.state].loweringAnimations > 0
732 end
733
734 return allowLowering or hasLoweringAnimations, warning
735end

getAreEffectsVisible

Description
Definition
getAreEffectsVisible()
Code
790function WorkMode:getAreEffectsVisible(superFunc)
791 if not superFunc(self) then
792 return false
793 end
794
795 local spec = self.spec_workMode
796 if spec.stateMax > 0 then
797 for i=1, #spec.workModes do
798 local workMode = spec.workModes[i]
799
800 for j=1, #workMode.animations do
801 if self:getIsAnimationPlaying(workMode.animations[j].animName) then
802 return false
803 end
804 end
805 end
806 end
807
808 return true
809end

getCanBeSelected

Description
Definition
getCanBeSelected()
Code
719function WorkMode:getCanBeSelected(superFunc)
720 return true
721end

getIsMovingToolActive

Description
Definition
getIsMovingToolActive()
Code
771function WorkMode:getIsMovingToolActive(superFunc, movingTool)
772 if not movingTool.allowWhileChangingWorkMode then
773 local spec = self.spec_workMode
774 for i=1, #spec.workModes do
775 local workMode = spec.workModes[i]
776
777 for j=1, #workMode.animations do
778 if self:getIsAnimationPlaying(workMode.animations[j].animName) then
779 return false
780 end
781 end
782 end
783 end
784
785 return superFunc(self, movingTool)
786end

getIsSprayTypeActive

Description
Definition
getIsSprayTypeActive()
Code
747function WorkMode:getIsSprayTypeActive(superFunc, sprayType)
748 if sprayType.workModeIndex ~= nil then
749 if self.spec_workMode.state ~= sprayType.workModeIndex then
750 return false
751 end
752 end
753
754 return superFunc(self, sprayType)
755end

getIsWorkAreaActive

Description
Definition
getIsWorkAreaActive()
Code
700function WorkMode:getIsWorkAreaActive(superFunc, workArea)
701 local spec = self.spec_workMode
702 if spec.stateMax == 0 then
703 return superFunc(self, workArea)
704 end
705
706 for _, workArea2 in pairs(spec.workModes[spec.state].workAreas) do
707 if workArea.index == workArea2.workAreaIndex then
708 if workArea2.dropAreaIndex == 0 then
709 return false
710 end
711 end
712 end
713
714 return superFunc(self, workArea)
715end

getIsWorkModeChangeAllowed

Description
Returns if work mode change is allowed
Definition
getIsWorkModeChangeAllowed()
Return Values
booleanisAllowedis allowed
Code
814function WorkMode:getIsWorkModeChangeAllowed()
815 local spec = self.spec_workMode
816
817 if self.getFoldAnimTime ~= nil then
818 if self:getFoldAnimTime() > spec.foldMaxLimit or self:getFoldAnimTime() < spec.foldMinLimit then
819 return false
820 end
821 end
822
823 if not spec.allowChangeOnLowered then
824 local attacherVehicle = self:getAttacherVehicle()
825 if attacherVehicle ~= nil then
826 local index = attacherVehicle:getAttacherJointIndexFromObject(self)
827 local attacherJoint = attacherVehicle:getAttacherJointByJointDescIndex(index)
828
829 if attacherJoint.moveDown then
830 return false
831 end
832 end
833 end
834
835 return true
836end

initSpecialization

Description
Called on specialization initializing
Definition
initSpecialization()
Code
28function WorkMode.initSpecialization()
29 g_configurationManager:addConfigurationType("workMode", g_i18n:getText("configuration_workMode"), "workModes", nil, nil, nil, ConfigurationUtil.SELECTOR_MULTIOPTION)
30
31 local schema = Vehicle.xmlSchema
32 schema:setXMLSpecializationType("WorkMode")
33
34 WorkMode.registerWorkModeXMLPaths(schema, "vehicle.workModes")
35 WorkMode.registerWorkModeXMLPaths(schema, "vehicle.workModes.workModeConfigurations.workModeConfiguration(?)")
36
37 ObjectChangeUtil.registerObjectChangeXMLPaths(schema, "vehicle.workModes.workModeConfigurations.workModeConfiguration(?)")
38
39 schema:setXMLSpecializationType()
40
41 local schemaSavegame = Vehicle.xmlSchemaSavegame
42 schemaSavegame:register(XMLValueType.INT, "vehicles.vehicle(?).workMode#state", "Current work mode", 1)
43end

loadMovingToolFromXML

Description
Definition
loadMovingToolFromXML()
Code
759function WorkMode:loadMovingToolFromXML(superFunc, xmlFile, key, entry)
760 if not superFunc(self, xmlFile, key, entry) then
761 return false
762 end
763
764 entry.allowWhileChangingWorkMode = self.xmlFile:getValue(key.. "#allowWhileChangingWorkMode", true)
765
766 return true
767end

loadSprayTypeFromXML

Description
Definition
loadSprayTypeFromXML()
Code
739function WorkMode:loadSprayTypeFromXML(superFunc, xmlFile, key, sprayType)
740 sprayType.workModeIndex = self.xmlFile:getValue(key.. "#workModeIndex")
741
742 return superFunc(self, xmlFile, key, sprayType)
743end

onDeactivate

Description
Called on deactivate
Definition
onDeactivate()
Code
573function WorkMode:onDeactivate()
574 WorkMode.deactivateWindrowerEffects(self)
575end

onDelete

Description
Definition
onDelete()
Code
329function WorkMode:onDelete()
330 local spec = self.spec_workMode
331 if spec.workModes ~= nil then
332 for _, mode in ipairs(spec.workModes) do
333 g_effectManager:deleteEffects(mode.windrowerEffects)
334 g_animationManager:deleteAnimations(mode.animationNodes)
335 end
336 end
337end

onDraw

Description
Called on draw
Definition
onDraw(boolean isActiveForInput, boolean isSelected)
Arguments
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
545function WorkMode:onDraw(isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
546 local spec = self.spec_workMode
547 if spec.stateMax == 0 then
548 return
549 else
550 local mode = spec.workModes[spec.state]
551 g_currentMission:addExtraPrintText(string.format(g_i18n:getText("action_workModeSelected"), mode.name))
552
553 local allowWorkModeChange = self:getIsWorkModeChangeAllowed()
554
555 local actionEvent = spec.actionEvents[InputAction.TOGGLE_WORKMODE]
556 if actionEvent ~= nil then
557 g_inputBinding:setActionEventActive(actionEvent.actionEventId, allowWorkModeChange)
558 end
559
560 for _, workMode in ipairs(spec.workModes) do
561 if workMode.inputAction ~= nil then
562 actionEvent = spec.actionEvents[workMode.inputAction]
563 if actionEvent ~= nil then
564 g_inputBinding:setActionEventActive(actionEvent.actionEventId, allowWorkModeChange)
565 end
566 end
567 end
568 end
569end

onFoldStateChanged

Description
Called on fold state change
Definition
onFoldStateChanged(integer direction)
Arguments
integerdirectiondirection of folding
Code
913function WorkMode:onFoldStateChanged(direction, moveToMiddle)
914 local spec = self.spec_workMode
915 if spec.stateMax == 0 then
916 return
917 end
918
919 if direction > 0 then
920 local mode = spec.workModes[spec.state]
921
922 for _, anim in pairs(mode.animations) do
923 if anim.repeatAfterUnfolding then
924 anim.repeated = false
925 end
926 end
927
928 -- if the tool is still lowered while folding we lift it
929 if self:getIsLowered() then
930 if self.getAttacherVehicle ~= nil then
931 local attacherVehicle = self:getAttacherVehicle()
932 if attacherVehicle ~= nil then
933 attacherVehicle:handleLowerImplementEvent()
934 end
935 end
936 end
937 end
938end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
129function WorkMode:onLoad(savegame)
130 local spec = self.spec_workMode
131
132 local baseKey = "vehicle.workModes"
133 local configurationId = Utils.getNoNil(self.configurations["workMode"], 1)
134 local configKey = string.format(baseKey .. ".workModeConfigurations.workModeConfiguration(%d)", configurationId -1)
135 ObjectChangeUtil.updateObjectChanges(self.xmlFile, baseKey .. ".workModeConfigurations.workModeConfiguration", configurationId , self.components, self)
136
137 if not self.xmlFile:hasProperty(configKey) then
138 configKey = baseKey
139 end
140
141 spec.state = 1
142 spec.stateMax = 0
143
144 spec.foldMaxLimit = self.xmlFile:getValue(configKey .. "#foldMaxLimit", 1)
145 spec.foldMinLimit = self.xmlFile:getValue(configKey .. "#foldMinLimit", 0)
146 spec.allowChangeOnLowered = self.xmlFile:getValue(configKey .. "#allowChangeOnLowered", true)
147 spec.allowChangeWhileTurnedOn = self.xmlFile:getValue(configKey .. "#allowChangeWhileTurnedOn", true)
148
149 spec.workModes = {}
150 local i = 0
151 while true do
152 local key = string.format("%s.workMode(%d)", configKey, i)
153 if not self.xmlFile:hasProperty(key) then
154 break
155 end
156
157 local entry = {}
158 entry.name = self.xmlFile:getValue(key .. "#name", nil, self.customEnvironment)
159 local inputBindingName = self.xmlFile:getValue(key .. "#inputBindingName")
160 if inputBindingName ~= nil then
161 if InputAction[inputBindingName] ~= nil then
162 entry.inputAction = InputAction[inputBindingName]
163 end
164 end
165
166 entry.turnedOnAnimations = {}
167 local j = 0
168 while true do
169 local key2 = string.format("%s.turnedOnAnimations.turnedOnAnimation(%d)", key, j)
170 if not self.xmlFile:hasProperty(key2) then
171 break
172 end
173
174 local turnedOnAnimation = {}
175 turnedOnAnimation.name = self.xmlFile:getValue(key2.."#name")
176 turnedOnAnimation.turnOnFadeTime = self.xmlFile:getValue(key2.."#turnOnFadeTime", 1) * 1000
177 turnedOnAnimation.turnOffFadeTime = self.xmlFile:getValue(key2.."#turnOffFadeTime", 1) * 1000
178 turnedOnAnimation.speedScale = self.xmlFile:getValue(key2.."#speedScale", 1)
179
180 turnedOnAnimation.speedDirection = 0
181 turnedOnAnimation.currentSpeed = 0
182
183 if self:getAnimationExists(turnedOnAnimation.name) then
184 table.insert(entry.turnedOnAnimations, turnedOnAnimation)
185 end
186
187 j = j + 1
188 end
189
190 entry.loweringAnimations = {}
191 j = 0
192 while true do
193 local key2 = string.format("%s.loweringAnimations.loweringAnimation(%d)", key, j)
194 if not self.xmlFile:hasProperty(key2) then
195 break
196 end
197
198 local loweringAnimation = {}
199 loweringAnimation.name = self.xmlFile:getValue(key2.."#name")
200 loweringAnimation.speed = self.xmlFile:getValue(key2.."#speed", 1)
201
202 if self:getAnimationExists(loweringAnimation.name) then
203 table.insert(entry.loweringAnimations, loweringAnimation)
204 end
205
206 j = j + 1
207 end
208
209 entry.workAreas = {}
210 j = 0
211 while true do
212 local key2 = string.format("%s.workAreas.workArea(%d)", key, j)
213 if not self.xmlFile:hasProperty(key2) then
214 break
215 end
216
217 local workArea = {}
218 workArea.workAreaIndex = self.xmlFile:getValue(key2.."#workAreaIndex", j+1)
219 workArea.dropAreaIndex = self.xmlFile:getValue(key2.."#dropAreaIndex", j+1)
220
221 table.insert(entry.workAreas, workArea)
222
223 j = j + 1
224 end
225
226 entry.animations = {}
227 j = 0
228 while true do
229 local animKey = string.format("%s.animation(%d)", key, j)
230 if not self.xmlFile:hasProperty(animKey) then
231 break
232 end
233
234 local animation = {}
235 animation.animName = self.xmlFile:getValue(animKey .. "#name")
236 animation.animSpeed = self.xmlFile:getValue(animKey .. "#speed", 1.0)
237 animation.stopTime = self.xmlFile:getValue(animKey .. "#stopTime")
238 animation.repeatAfterUnfolding = self.xmlFile:getValue(animKey .. "#repeatAfterUnfolding", false)
239 animation.repeatStartTime = self.xmlFile:getValue(animKey .. "#repeatStartTime")
240 animation.repeated = false
241
242 if self:getAnimationExists(animation.animName) then
243 table.insert(entry.animations, animation)
244 end
245
246 j = j + 1
247 end
248
249 local movingToolLimitNode = self.xmlFile:getValue(key .. ".movingToolLimit#node", nil, self.components, self.i3dMappings)
250 if movingToolLimitNode ~= nil then
251 entry.movingTool = self:getMovingToolByNode(movingToolLimitNode)
252 entry.movingToolMinRot = self.xmlFile:getValue(key .. ".movingToolLimit#minRot", 0)
253 entry.movingToolMaxRot = self.xmlFile:getValue(key .. ".movingToolLimit#maxRot", 0)
254 end
255
256 entry.windrowerEffects = g_effectManager:loadEffect(self.xmlFile, string.format("%s.windrowerEffect", key), self.components, self, self.i3dMappings)
257 entry.animationNodes = g_animationManager:loadAnimations(self.xmlFile, key..".animationNodes", self.components, self, self.i3dMappings)
258
259 table.insert(spec.workModes, entry)
260 i = i + 1
261 end
262
263 spec.stateMax = table.getn(spec.workModes)
264 if spec.stateMax > ((2^WorkMode.WORKMODE_SEND_NUM_BITS) - 1) then
265 print("Error: WorkMode only supports "..((2^WorkMode.WORKMODE_SEND_NUM_BITS) - 1).." modes!")
266 end
267
268 if spec.stateMax > 0 then
269 self:setWorkMode(1, true)
270 end
271
272 spec.accumulatedFruitType = FruitType.UNKNOWN
273 spec.dirtyFlag = self:getNextDirtyFlag()
274
275 if spec.stateMax == 0 then
276 SpecializationUtil.removeEventListener(self, "onReadStream", WorkMode)
277 SpecializationUtil.removeEventListener(self, "onWriteStream", WorkMode)
278 SpecializationUtil.removeEventListener(self, "onReadUpdateStream", WorkMode)
279 SpecializationUtil.removeEventListener(self, "onWriteUpdateStream", WorkMode)
280 SpecializationUtil.removeEventListener(self, "onUpdate", WorkMode)
281 SpecializationUtil.removeEventListener(self, "onUpdateTick", WorkMode)
282 SpecializationUtil.removeEventListener(self, "onDraw", WorkMode)
283 SpecializationUtil.removeEventListener(self, "onTurnedOn", WorkMode)
284 SpecializationUtil.removeEventListener(self, "onTurnedOff", WorkMode)
285 SpecializationUtil.removeEventListener(self, "onDeactivate", WorkMode)
286 SpecializationUtil.removeEventListener(self, "onSetLowered", WorkMode)
287 SpecializationUtil.removeEventListener(self, "onFoldStateChanged", WorkMode)
288 SpecializationUtil.removeEventListener(self, "onRegisterActionEvents", WorkMode)
289 end
290end

onPostLoad

Description
Definition
onPostLoad()
Code
294function WorkMode:onPostLoad(savegame)
295 if savegame ~= nil and not savegame.resetVehicles then
296 local spec = self.spec_workMode
297 if spec.stateMax > 0 then
298 if savegame.xmlFile:hasProperty(savegame.key..".workMode#state") then
299 local workMode = savegame.xmlFile:getValue(savegame.key..".workMode#state", 1)
300 workMode = MathUtil.clamp(workMode, 1, spec.stateMax)
301
302 self:setWorkMode(workMode, true)
303 AnimatedVehicle.updateAnimations(self, 99999999, true)
304
305 if self.getFoldAnimTime ~= nil then
306 if self.spec_foldable.foldMoveDirection == 0 then
307 if self:getFoldAnimTime() <= 0 then
308 self.spec_foldable.foldMoveDirection = -1
309 else
310 self.spec_foldable.foldMoveDirection = 1
311 end
312 end
313 end
314 end
315 end
316 end
317end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
343function WorkMode:onReadStream(streamId, connection)
344 local spec = self.spec_workMode
345 if spec.stateMax == 0 then
346 return
347 end
348
349 local state = streamReadUIntN(streamId, WorkMode.WORKMODE_SEND_NUM_BITS)
350 self:setWorkMode(state, true)
351end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
371function WorkMode:onReadUpdateStream(streamId, timestamp, connection)
372 if connection:getIsServer() then
373 if streamReadBool(streamId) then
374 local spec = self.spec_workMode
375
376 local mode = spec.workModes[spec.state]
377 for _, effect in ipairs(mode.windrowerEffects) do
378 if streamReadBool(streamId) then
379 effect.lastChargeTime = g_currentMission.time
380 end
381 end
382
383 spec.accumulatedFruitType = streamReadUIntN(streamId, FruitTypeManager.SEND_NUM_BITS)
384 end
385 end
386end

onRegisterActionEvents

Description
Definition
onRegisterActionEvents()
Code
942function WorkMode:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
943 if self.isClient then
944 local spec = self.spec_workMode
945 if spec.stateMax > 0 then
946 self:clearActionEventsTable(spec.actionEvents)
947
948 if isActiveForInputIgnoreSelection then
949 local _, actionEventId = self:addPoweredActionEvent(spec.actionEvents, InputAction.TOGGLE_WORKMODE, self, WorkMode.actionEventWorkModeChange, false, true, false, true, nil)
950 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL)
951
952 for _, mode in ipairs(spec.workModes) do
953 if mode.inputAction ~= nil then
954 _, actionEventId = self:addPoweredActionEvent(spec.actionEvents, mode.inputAction, self, WorkMode.actionEventWorkModeChangeDirect, false, true, false, true, nil)
955 g_inputBinding:setActionEventTextVisibility(actionEventId, false)
956 end
957 end
958 end
959 end
960 end
961end

onSetLowered

Description
Called on change lowering state
Definition
onSetLowered(boolean lowered)
Arguments
booleanloweredattachable is lowered
Code
881function WorkMode:onSetLowered(lowered)
882 local spec = self.spec_workMode
883 if spec.stateMax == 0 then
884 return
885 end
886
887 if self.getFoldAnimTime ~= nil then
888 local foldAnimTime = self:getFoldAnimTime()
889 if foldAnimTime ~= 1 and foldAnimTime ~= 0 and foldAnimTime ~= self.foldMiddleAnimTime then
890 spec.playDelayedLoweringAnimation = lowered
891 return
892 end
893 end
894
895 local mode = spec.workModes[spec.state]
896
897 for _, loweringAnimation in pairs(mode.loweringAnimations) do
898 if lowered then
899 if self:getAnimationTime(loweringAnimation.name) < 1 then
900 self:playAnimation(loweringAnimation.name, loweringAnimation.speed, nil, true)
901 end
902 else
903 if self:getAnimationTime(loweringAnimation.name) > 0 then
904 self:playAnimation(loweringAnimation.name, -loweringAnimation.speed, nil, true)
905 end
906 end
907 end
908end

onTurnedOff

Description
Called on turn off
Definition
onTurnedOff(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
841function WorkMode:onTurnedOff()
842 local spec = self.spec_workMode
843 if spec.stateMax == 0 then
844 return
845 end
846
847 if self.isClient then
848 WorkMode.deactivateWindrowerEffects(self)
849 local mode = spec.workModes[spec.state]
850
851 for _, turnedOnAnimation in pairs(mode.turnedOnAnimations) do
852 turnedOnAnimation.speedDirection = -1
853 end
854 g_animationManager:stopAnimations(mode.animationNodes)
855 end
856end

onTurnedOn

Description
Called on turn on
Definition
onTurnedOn(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
861function WorkMode:onTurnedOn()
862 local spec = self.spec_workMode
863 if spec.stateMax == 0 then
864 return
865 end
866
867 if self.isClient then
868 local mode = spec.workModes[spec.state]
869
870 for _, turnedOnAnimation in pairs(mode.turnedOnAnimations) do
871 turnedOnAnimation.speedDirection = 1
872 end
873
874 g_animationManager:startAnimations(mode.animationNodes)
875 end
876end

onUpdate

Description
Called on update
Definition
onUpdate(float dt)
Arguments
floatdttime since last call in ms
Code
411function WorkMode:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
412 local spec = self.spec_workMode
413 if spec.stateMax == 0 then
414 return
415 end
416
417 if self.isClient then
418 local mode = spec.workModes[spec.state]
419
420 for i=1, #spec.workModes do
421 for _, turnedOnAnimation in pairs(spec.workModes[i].turnedOnAnimations) do
422 if turnedOnAnimation.speedDirection ~= 0 then
423 local duration = turnedOnAnimation.turnOnFadeTime
424 if turnedOnAnimation.speedDirection == -1 then
425 duration = turnedOnAnimation.turnOffFadeTime
426 end
427 local min, max = 0, 1
428 if turnedOnAnimation.speedDirection == 1 then
429 min, max = -1, 1
430 end
431
432 turnedOnAnimation.currentSpeed = MathUtil.clamp(turnedOnAnimation.currentSpeed + turnedOnAnimation.speedDirection * dt/duration, min, max)
433
434 if not self:getIsAnimationPlaying(turnedOnAnimation.name) then
435 self:playAnimation(turnedOnAnimation.name, turnedOnAnimation.currentSpeed*turnedOnAnimation.speedScale, self:getAnimationTime(turnedOnAnimation.name), true)
436 else
437 self:setAnimationSpeed(turnedOnAnimation.name, turnedOnAnimation.currentSpeed*turnedOnAnimation.speedScale)
438 end
439
440 if turnedOnAnimation.speedDirection == -1 and turnedOnAnimation.currentSpeed == 0 then
441 self:stopAnimation(turnedOnAnimation.name, true)
442 end
443
444 if turnedOnAnimation.currentSpeed == 1 or turnedOnAnimation.currentSpeed == 0 then
445 turnedOnAnimation.speedDirection = 0
446 end
447 end
448 end
449 end
450
451 for _, effect in pairs(mode.windrowerEffects) do
452 if effect.lastChargeTime + 500 > g_currentMission.time then
453 local fillType = g_fruitTypeManager:getWindrowFillTypeIndexByFruitTypeIndex(spec.accumulatedFruitType)
454 if fillType ~= nil then
455 effect:setFillType(fillType)
456 if not effect:isRunning() then
457 g_effectManager:startEffect(effect)
458 end
459 end
460 else
461 if effect.turnOffRequiredEffect == 0 or (effect.turnOffRequiredEffect ~= 0 and not mode.windrowerEffects[effect.turnOffRequiredEffect]:isRunning()) then
462 g_effectManager:stopEffect(effect)
463 end
464 end
465 end
466 end
467
468 if self.isServer then
469 local mode = spec.workModes[spec.state]
470
471 local fruitType
472 local workAreaCharge
473 for _, area in ipairs(mode.workAreas) do
474 local workArea = self.spec_workArea.workAreas[area.workAreaIndex]
475 if workArea ~= nil then
476 if workArea.lastValidPickupFruitType ~= FruitType.UNKNOWN then
477 fruitType = workArea.lastValidPickupFruitType
478 end
479 workAreaCharge = workAreaCharge or workArea.lastPickupLiters ~= 0
480 end
481 end
482
483 if fruitType ~= nil then
484 if fruitType ~= spec.accumulatedFruitType then
485 spec.accumulatedFruitType = fruitType
486 self:raiseDirtyFlags(spec.dirtyFlag)
487 end
488 end
489
490 for _, effect in pairs(mode.windrowerEffects) do
491 if workAreaCharge then
492 effect.lastChargeTime = g_currentMission.time
493 self:raiseDirtyFlags(spec.dirtyFlag)
494 end
495 end
496 end
497end

onUpdateTick

Description
Definition
onUpdateTick()
Code
501function WorkMode:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
502 local spec = self.spec_workMode
503 if spec.stateMax == 0 then
504 return
505 end
506
507 if self.getFoldAnimTime ~= nil then
508 local foldAnimTime = self:getFoldAnimTime()
509 if foldAnimTime == 0 or foldAnimTime == self.spec_foldable.foldMiddleAnimTime then
510 local mode = spec.workModes[spec.state]
511 for _, anim in pairs(mode.animations) do
512 if anim.repeatAfterUnfolding then
513 if not anim.repeated then
514 local curTime = self:getAnimationTime(anim.animName)
515 if anim.stopTime ~= nil then
516 self:setAnimationStopTime(anim.animName, anim.stopTime)
517 local speed = math.abs(anim.animSpeed)
518 if curTime > anim.stopTime then
519 speed = -math.abs(anim.animSpeed)
520 end
521 self:playAnimation(anim.animName, speed, Utils.getNoNil(anim.repeatStartTime, curTime), true)
522 else
523 self:playAnimation(anim.animName, anim.animSpeed, Utils.getNoNil(anim.repeatStartTime, curTime), true)
524 end
525
526 anim.repeated = true
527 end
528 end
529 end
530 end
531
532 if spec.playDelayedLoweringAnimation ~= nil then
533 if foldAnimTime == 1 or foldAnimTime == 0 or foldAnimTime == self.spec_foldable.foldMiddleAnimTime then
534 WorkMode.onSetLowered(self, spec.playDelayedLoweringAnimation)
535 spec.playDelayedLoweringAnimation = nil
536 end
537 end
538 end
539end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
357function WorkMode:onWriteStream(streamId, connection)
358 local spec = self.spec_workMode
359 if spec.stateMax == 0 then
360 return
361 end
362
363 streamWriteUIntN(streamId, spec.state, WorkMode.WORKMODE_SEND_NUM_BITS)
364end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
393function WorkMode:onWriteUpdateStream(streamId, connection, dirtyMask)
394 if not connection:getIsServer() then
395 local spec = self.spec_workMode
396 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
397 local mode = spec.workModes[spec.state]
398
399 for _, effect in ipairs(mode.windrowerEffects) do
400 streamWriteBool(streamId, effect.lastChargeTime + 500 > g_currentMission.time)
401 end
402
403 streamWriteUIntN(streamId, spec.accumulatedFruitType, FruitTypeManager.SEND_NUM_BITS)
404 end
405 end
406end

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
21function WorkMode.prerequisitesPresent(specializations)
22 return SpecializationUtil.hasSpecialization(WorkArea, specializations)
23 and SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations)
24end

registerEventListeners

Description
Definition
registerEventListeners()
Code
107function WorkMode.registerEventListeners(vehicleType)
108 SpecializationUtil.registerEventListener(vehicleType, "onLoad", WorkMode)
109 SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", WorkMode)
110 SpecializationUtil.registerEventListener(vehicleType, "onDelete", WorkMode)
111 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", WorkMode)
112 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", WorkMode)
113 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", WorkMode)
114 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", WorkMode)
115 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", WorkMode)
116 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", WorkMode)
117 SpecializationUtil.registerEventListener(vehicleType, "onDraw", WorkMode)
118 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", WorkMode)
119 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", WorkMode)
120 SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", WorkMode)
121 SpecializationUtil.registerEventListener(vehicleType, "onSetLowered", WorkMode)
122 SpecializationUtil.registerEventListener(vehicleType, "onFoldStateChanged", WorkMode)
123 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", WorkMode)
124end

registerFunctions

Description
Definition
registerFunctions()
Code
86function WorkMode.registerFunctions(vehicleType)
87 SpecializationUtil.registerFunction(vehicleType, "setWorkMode", WorkMode.setWorkMode)
88 SpecializationUtil.registerFunction(vehicleType, "getIsWorkModeChangeAllowed", WorkMode.getIsWorkModeChangeAllowed)
89 SpecializationUtil.registerFunction(vehicleType, "deactivateWindrowerEffects", WorkMode.deactivateWindrowerEffects)
90end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
94function WorkMode.registerOverwrittenFunctions(vehicleType)
95 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsWorkAreaActive", WorkMode.getIsWorkAreaActive)
96 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", WorkMode.getCanBeSelected)
97 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAllowsLowering", WorkMode.getAllowsLowering)
98 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadSprayTypeFromXML", WorkMode.loadSprayTypeFromXML)
99 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsSprayTypeActive", WorkMode.getIsSprayTypeActive)
100 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadMovingToolFromXML", WorkMode.loadMovingToolFromXML)
101 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsMovingToolActive", WorkMode.getIsMovingToolActive)
102 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAreEffectsVisible", WorkMode.getAreEffectsVisible)
103end

registerWorkModeXMLPaths

Description
Called on specialization initializing
Definition
registerWorkModeXMLPaths()
Code
48function WorkMode.registerWorkModeXMLPaths(schema, basePath)
49 schema:register(XMLValueType.FLOAT, basePath .. "#foldMaxLimit", "Fold max. limit to change mode", 1)
50 schema:register(XMLValueType.FLOAT, basePath .. "#foldMinLimit", "Fold min. limit to change mode", 0)
51 schema:register(XMLValueType.BOOL, basePath .. "#allowChangeOnLowered", "Allow change while lowered", true)
52 schema:register(XMLValueType.BOOL, basePath .. "#allowChangeWhileTurnedOn", "Allow change while turned on", true)
53
54 schema:register(XMLValueType.L10N_STRING, basePath .. ".workMode(?)#name", "Work mode name")
55 schema:register(XMLValueType.STRING, basePath .. ".workMode(?)#inputBindingName", "Input action name for quick access")
56 schema:register(XMLValueType.STRING, basePath .. ".workMode(?).turnedOnAnimations.turnedOnAnimation(?)#name", "Turned on animation name")
57 schema:register(XMLValueType.FLOAT, basePath .. ".workMode(?).turnedOnAnimations.turnedOnAnimation(?)#turnOnFadeTime", "Turn on fade time (sec.)", 1)
58 schema:register(XMLValueType.FLOAT, basePath .. ".workMode(?).turnedOnAnimations.turnedOnAnimation(?)#turnOffFadeTime", "Turn off fade time (sec.)", 1)
59 schema:register(XMLValueType.FLOAT, basePath .. ".workMode(?).turnedOnAnimations.turnedOnAnimation(?)#speedScale", "Speed scale", 1)
60
61 schema:register(XMLValueType.STRING, basePath .. ".workMode(?).loweringAnimations.loweringAnimation(?)#name", "Lowering animation name")
62 schema:register(XMLValueType.FLOAT, basePath .. ".workMode(?).loweringAnimations.loweringAnimation(?)#speed", "Speed scale", 1)
63
64 schema:register(XMLValueType.INT, basePath .. ".workMode(?).workAreas.workArea(?)#workAreaIndex", "Work area index")
65 schema:register(XMLValueType.INT, basePath .. ".workMode(?).workAreas.workArea(?)#dropAreaIndex", "Drop area index")
66
67 schema:register(XMLValueType.STRING, basePath .. ".workMode(?).animation(?)#name", "Mode change animation name")
68 schema:register(XMLValueType.FLOAT, basePath .. ".workMode(?).animation(?)#speed", "Mode change animation speed", 1)
69 schema:register(XMLValueType.FLOAT, basePath .. ".workMode(?).animation(?)#stopTime", "Mode change animation stop time")
70 schema:register(XMLValueType.BOOL, basePath .. ".workMode(?).animation(?)#repeatAfterUnfolding", "Repeat animation after unfolding", false)
71 schema:register(XMLValueType.FLOAT, basePath .. ".workMode(?).animation(?)#repeatStartTime", "Repeat start time")
72
73 schema:register(XMLValueType.NODE_INDEX, basePath .. ".workMode(?).movingToolLimit#node", "Target moving tool node")
74 schema:register(XMLValueType.ANGLE, basePath .. ".workMode(?).movingToolLimit#minRot", "Min. rotation", 0)
75 schema:register(XMLValueType.ANGLE, basePath .. ".workMode(?).movingToolLimit#maxRot", "Max. rotation", 0)
76
77 EffectManager.registerEffectXMLPaths(schema, basePath .. ".workMode(?).windrowerEffect")
78 AnimationManager.registerAnimationNodesXMLPaths(schema, basePath .. ".workMode(?).animationNodes")
79
80 schema:register(XMLValueType.INT, Sprayer.SPRAY_TYPE_XML_KEY .. "#workModeIndex", "Index of work mode to activate spray type")
81 schema:register(XMLValueType.BOOL, Cylindered.MOVING_TOOL_XML_KEY .. "#allowWhileChangingWorkMode", "Allow movement while changing work mode", true)
82end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
321function WorkMode:saveToXMLFile(xmlFile, key, usedModNames)
322 local spec = self.spec_workMode
323
324 xmlFile:setValue(key.."#state", spec.state)
325end

setWorkMode

Description
Change work mode
Definition
setWorkMode(integer state, boolean noEventSend)
Arguments
integerstatenew state
booleannoEventSendno event send
Code
594function WorkMode:setWorkMode(state, noEventSend)
595 local spec = self.spec_workMode
596
597 if noEventSend == nil or noEventSend == false then
598 if g_server ~= nil then
599 g_server:broadcastEvent(SetWorkModeEvent.new(self, state), nil, nil, self)
600 else
601 g_client:getServerConnection():sendEvent(SetWorkModeEvent.new(self, state))
602 end
603 end
604
605 if state ~= spec.state then
606 local currentMode = spec.workModes[spec.state]
607 if currentMode.animations ~= nil then
608 for _,anim in pairs(currentMode.animations) do
609 local curTime = self:getAnimationTime(anim.animName)
610 if anim.stopTime == nil then
611 self:playAnimation(anim.animName, -anim.animSpeed, curTime, noEventSend)
612 end
613 end
614 g_animationManager:stopAnimations(currentMode.animationNodes)
615 end
616
617 local newMode = spec.workModes[state]
618 if newMode.animations ~= nil then
619 for _,anim in pairs(newMode.animations) do
620 local curTime = self:getAnimationTime(anim.animName)
621 if anim.stopTime ~= nil then
622 self:setAnimationStopTime(anim.animName, anim.stopTime)
623 local speed = math.abs(anim.animSpeed)
624 if curTime > anim.stopTime then
625 speed = -math.abs(anim.animSpeed)
626 end
627 self:playAnimation(anim.animName, speed, curTime, noEventSend)
628 else
629 self:playAnimation(anim.animName, anim.animSpeed, curTime, noEventSend)
630 end
631 end
632 if self:getIsTurnedOn() then
633 g_animationManager:startAnimations(newMode.animationNodes)
634 end
635 end
636
637 if self:getIsTurnedOn() then
638 for _, turnedOnAnimation in pairs(newMode.turnedOnAnimations) do
639 if self:getIsAnimationPlaying(turnedOnAnimation.name) then
640 for i=1, #spec.workModes do
641 local otherMode = spec.workModes[i]
642 if otherMode ~= newMode then
643 for j=1, #otherMode.turnedOnAnimations do
644 local otherAnimation = otherMode.turnedOnAnimations[j]
645 if otherAnimation.name == turnedOnAnimation.name then
646 local animationSpeed = self.spec_animatedVehicle.animations[turnedOnAnimation.name].currentSpeed
647 if animationSpeed ~= 0 then
648 local alpha = animationSpeed / turnedOnAnimation.speedScale
649 turnedOnAnimation.currentSpeed = alpha
650 otherAnimation.currentSpeed = 0
651 otherAnimation.speedDirection = 0
652 end
653 end
654 end
655 end
656 end
657 end
658
659 turnedOnAnimation.speedDirection = 1
660 end
661 end
662
663 for _, effect in pairs(currentMode.windrowerEffects) do
664 g_effectManager:stopEffect(effect)
665 end
666
667 if newMode.movingTool ~= nil then
668 local movingTool = newMode.movingTool
669 if newMode.movingToolMinRot ~= nil then
670 movingTool.rotMin = newMode.movingToolMinRot
671 end
672
673 if newMode.movingToolMaxRot ~= nil then
674 movingTool.rotMax = newMode.movingToolMaxRot
675 end
676
677 if self.isClient then
678 movingTool.networkInterpolators.rotation:setMinMax(movingTool.rotMin, movingTool.rotMax)
679 end
680 end
681 end
682
683 local workAreaSpec = self.spec_workArea
684 if workAreaSpec ~= nil then
685 local workAreas = workAreaSpec.workAreas
686 for _, workArea in pairs(spec.workModes[state].workAreas) do
687 local workAreaToSet = workAreas[workArea.workAreaIndex]
688 if workAreaToSet ~= nil then
689 workAreaToSet.dropWindrowWorkAreaIndex = workArea.dropAreaIndex -- windrower
690 workAreaToSet.dropAreaIndex = workArea.dropAreaIndex -- mower
691 end
692 end
693 end
694
695 spec.state = state
696end