Script v1.7.1.0
- AI
- Animals
- Contracts
- Debug
- Economy
- Effects
- Events
- Farms
- GUI
- Handtools
- I3d
- Materials
- Misc
- Objects
- Placeables
- Player
- Shop
- Sounds
- Specializations
- AIConveyorBelt
- AIImplement
- AIVehicle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BunkerSiloCompacter
- BunkerSiloInteractor
- BuyableBale
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- JigglingParts
- Leveler
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- MixerWagon
- Motorized
- Mountable
- Mower
- Pickup
- Pipe
- Plow
- PowerConsumer
- PowerTakeOffs
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StrawBlower
- StumpCutter
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TipOccluder
- Trailer
- TreePlanter
- TreeSaw
- TurnOnVehicle
- Washable
- WaterTrailer
- Wearable
- Weeder
- Wheels
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- Triggers
- Utils
- Vehicles
- Weather
Engine v1.7.1.0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- XML
- general
Foundation Reference
WorkMode
DescriptionSpecialization for tools with switchable work modes by providing grouping of different animations and work areasFunctions
- actionEventWorkModeChange
- actionEventWorkModeChangeDirect
- deactivateWindrowerEffects
- getCanBeSelected
- getIsWorkAreaActive
- getIsWorkModeChangeAllowed
- onDeactivate
- onDelete
- onDraw
- onFoldStateChanged
- onLoad
- onPostLoad
- onReadStream
- onReadUpdateStream
- onRegisterActionEvents
- onSetLowered
- onTurnedOff
- onTurnedOn
- onUpdate
- onUpdateTick
- onWriteStream
- onWriteUpdateStream
- prerequisitesPresent
- registerEventListeners
- registerFunctions
- registerOverwrittenFunctions
- saveToXMLFile
- setWorkMode
actionEventWorkModeChange
DescriptionDefinitionactionEventWorkModeChange()Code
765 | function WorkMode.actionEventWorkModeChange(self, actionName, inputValue, callbackState, isAnalog) |
766 | local spec = self.spec_workMode |
767 | local state = spec.state + 1 |
768 | if state > spec.stateMax then |
769 | state = 1 |
770 | end |
771 | |
772 | if state ~= spec.state then |
773 | self:setWorkMode(state) |
774 | end |
775 | end |
actionEventWorkModeChangeDirect
DescriptionDefinitionactionEventWorkModeChangeDirect()Code
779 | function WorkMode.actionEventWorkModeChangeDirect(self, actionName, inputValue, callbackState, isAnalog) |
780 | local spec = self.spec_workMode |
781 | |
782 | for state, mode in ipairs(spec.workModes) do |
783 | if mode.inputAction == InputAction[actionName] then |
784 | if state ~= spec.state then |
785 | self:setWorkMode(state) |
786 | end |
787 | end |
788 | end |
789 | end |
deactivateWindrowerEffects
DescriptionCalled on deactivateDefinition
deactivateWindrowerEffects()Code
482 | function WorkMode:deactivateWindrowerEffects() |
483 | if self.isClient then |
484 | local spec = self.spec_workMode |
485 | for _, mode in pairs(spec.workModes) do |
486 | if mode.windrowerEffects ~= nil then |
487 | g_effectManager:stopEffects(mode.windrowerEffects) |
488 | end |
489 | end |
490 | end |
491 | end |
getCanBeSelected
DescriptionDefinitiongetCanBeSelected()Code
607 | function WorkMode:getCanBeSelected(superFunc) |
608 | return true |
609 | end |
getIsWorkAreaActive
DescriptionDefinitiongetIsWorkAreaActive()Code
588 | function WorkMode:getIsWorkAreaActive(superFunc, workArea) |
589 | local spec = self.spec_workMode |
590 | if spec.stateMax == 0 then |
591 | return superFunc(self, workArea) |
592 | end |
593 | |
594 | for _, workArea2 in pairs(spec.workModes[spec.state].workAreas) do |
595 | if workArea.index == workArea2.workAreaIndex then |
596 | if workArea2.dropAreaIndex == 0 then |
597 | return false |
598 | end |
599 | end |
600 | end |
601 | |
602 | return superFunc(self, workArea) |
603 | end |
getIsWorkModeChangeAllowed
DescriptionReturns if work mode change is allowedDefinition
getIsWorkModeChangeAllowed()Return Values
boolean | isAllowed | is allowed |
614 | function WorkMode:getIsWorkModeChangeAllowed() |
615 | local spec = self.spec_workMode |
616 | |
617 | if self.getFoldAnimTime ~= nil then |
618 | if self:getFoldAnimTime() > spec.foldMaxLimit or self:getFoldAnimTime() < spec.foldMinLimit then |
619 | return false |
620 | end |
621 | end |
622 | |
623 | if not spec.allowChangeOnLowered then |
624 | local attacherVehicle = self:getAttacherVehicle() |
625 | if attacherVehicle ~= nil then |
626 | local index = attacherVehicle:getAttacherJointIndexFromObject(self) |
627 | local attacherJoint = attacherVehicle:getAttacherJointByJointDescIndex(index) |
628 | |
629 | if attacherJoint.moveDown then |
630 | return false |
631 | end |
632 | end |
633 | end |
634 | |
635 | return true |
636 | end |
onDeactivate
DescriptionCalled on deactivateDefinition
onDeactivate()Code
476 | function WorkMode:onDeactivate() |
477 | WorkMode.deactivateWindrowerEffects(self) |
478 | end |
onDelete
DescriptionDefinitiononDelete()Code
234 | function WorkMode:onDelete() |
235 | local spec = self.spec_workMode |
236 | for _, mode in ipairs(spec.workModes) do |
237 | g_effectManager:deleteEffects(mode.windrowerEffects) |
238 | g_animationManager:deleteAnimations(mode.animationNodes) |
239 | end |
240 | end |
onDraw
DescriptionCalled on drawDefinition
onDraw(boolean isActiveForInput, boolean isSelected)Arguments
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
448 | function WorkMode:onDraw(isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
449 | local spec = self.spec_workMode |
450 | if spec.stateMax == 0 then |
451 | return |
452 | else |
453 | local mode = spec.workModes[spec.state] |
454 | g_currentMission:addExtraPrintText(string.format(g_i18n:getText("action_workModeSelected"), mode.name)) |
455 | |
456 | local allowWorkModeChange = self:getIsWorkModeChangeAllowed() |
457 | |
458 | local actionEvent = spec.actionEvents[InputAction.TOGGLE_WORKMODE] |
459 | if actionEvent ~= nil then |
460 | g_inputBinding:setActionEventActive(actionEvent.actionEventId, allowWorkModeChange) |
461 | end |
462 | |
463 | for _, workMode in ipairs(spec.workModes) do |
464 | if workMode.inputAction ~= nil then |
465 | actionEvent = spec.actionEvents[workMode.inputAction] |
466 | if actionEvent ~= nil then |
467 | g_inputBinding:setActionEventActive(actionEvent.actionEventId, allowWorkModeChange) |
468 | end |
469 | end |
470 | end |
471 | end |
472 | end |
onFoldStateChanged
DescriptionCalled on fold state changeDefinition
onFoldStateChanged(integer direction)Arguments
integer | direction | direction of folding |
713 | function WorkMode:onFoldStateChanged(direction, moveToMiddle) |
714 | local spec = self.spec_workMode |
715 | if spec.stateMax == 0 then |
716 | return |
717 | end |
718 | |
719 | if direction > 0 then |
720 | local mode = spec.workModes[spec.state] |
721 | |
722 | for _, anim in pairs(mode.animations) do |
723 | if anim.repeatAfterUnfolding then |
724 | anim.repeated = false |
725 | end |
726 | end |
727 | |
728 | -- if the tool is still lowered while folding we lift it |
729 | if self:getIsLowered() then |
730 | if self.getAttacherVehicle ~= nil then |
731 | local attacherVehicle = self:getAttacherVehicle() |
732 | if attacherVehicle ~= nil then |
733 | attacherVehicle:handleLowerImplementEvent() |
734 | end |
735 | end |
736 | end |
737 | end |
738 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
65 | function WorkMode:onLoad(savegame) |
66 | local spec = self.spec_workMode |
67 | |
68 | spec.state = 1 |
69 | spec.stateMax = 0 |
70 | |
71 | local baseKey = "vehicle.workModes" |
72 | |
73 | spec.foldMaxLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, string.format("%s#foldMaxLimit", baseKey)), 1) |
74 | spec.foldMinLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, string.format("%s#foldMinLimit", baseKey)), 0) |
75 | spec.allowChangeOnLowered = Utils.getNoNil(getXMLBool(self.xmlFile, string.format("%s#allowChangeOnLowered", baseKey)), true) |
76 | |
77 | spec.workModes = {} |
78 | local i = 0 |
79 | while true do |
80 | local key = string.format("%s.workMode(%d)", baseKey, i) |
81 | if not hasXMLProperty(self.xmlFile, key) then |
82 | break |
83 | end |
84 | |
85 | local entry = {} |
86 | entry.name = g_i18n:getText(getXMLString(self.xmlFile, key .. "#name"), self.customEnvironment) |
87 | local inputBindingName = getXMLString(self.xmlFile, key .. "#inputBindingName") |
88 | if inputBindingName ~= nil then |
89 | if InputAction[inputBindingName] ~= nil then |
90 | entry.inputAction = InputAction[inputBindingName] |
91 | end |
92 | end |
93 | |
94 | entry.turnedOnAnimations = {} |
95 | local j = 0 |
96 | while true do |
97 | local key2 = string.format("%s.turnedOnAnimations.turnedOnAnimation(%d)", key, j) |
98 | if not hasXMLProperty(self.xmlFile, key2) then |
99 | break |
100 | end |
101 | |
102 | local turnedOnAnimation = {} |
103 | turnedOnAnimation.name = getXMLString(self.xmlFile, key2.."#name") |
104 | turnedOnAnimation.turnOnFadeTime = Utils.getNoNil(getXMLFloat(self.xmlFile, key2.."#turnOnFadeTime"), 1) * 1000 |
105 | turnedOnAnimation.turnOffFadeTime = Utils.getNoNil(getXMLFloat(self.xmlFile, key2.."#turnOffFadeTime"), 1) * 1000 |
106 | turnedOnAnimation.speedScale = Utils.getNoNil(getXMLFloat(self.xmlFile, key2.."#speedScale"), 1) |
107 | |
108 | turnedOnAnimation.speedDirection = 0 |
109 | turnedOnAnimation.currentSpeed = 0 |
110 | |
111 | if self:getAnimationExists(turnedOnAnimation.name) then |
112 | table.insert(entry.turnedOnAnimations, turnedOnAnimation) |
113 | end |
114 | |
115 | j = j + 1 |
116 | end |
117 | |
118 | entry.loweringAnimations = {} |
119 | j = 0 |
120 | while true do |
121 | local key2 = string.format("%s.loweringAnimations.loweringAnimation(%d)", key, j) |
122 | if not hasXMLProperty(self.xmlFile, key2) then |
123 | break |
124 | end |
125 | |
126 | local loweringAnimation = {} |
127 | loweringAnimation.name = getXMLString(self.xmlFile, key2.."#name") |
128 | loweringAnimation.speed = Utils.getNoNil(getXMLFloat(self.xmlFile, key2.."#speed"), 1) |
129 | |
130 | if self:getAnimationExists(loweringAnimation.name) then |
131 | table.insert(entry.loweringAnimations, loweringAnimation) |
132 | end |
133 | |
134 | j = j + 1 |
135 | end |
136 | |
137 | entry.workAreas = {} |
138 | j = 0 |
139 | while true do |
140 | local key2 = string.format("%s.workAreas.workArea(%d)", key, j) |
141 | if not hasXMLProperty(self.xmlFile, key2) then |
142 | break |
143 | end |
144 | |
145 | local workArea = {} |
146 | workArea.workAreaIndex = Utils.getNoNil(getXMLInt(self.xmlFile, key2.."#workAreaIndex"), j+1) |
147 | workArea.dropAreaIndex = Utils.getNoNil(getXMLInt(self.xmlFile, key2.."#dropAreaIndex"), j+1) |
148 | |
149 | table.insert(entry.workAreas, workArea) |
150 | |
151 | j = j + 1 |
152 | end |
153 | |
154 | entry.animations = {} |
155 | j = 0 |
156 | while true do |
157 | local animKey = string.format("%s.animation(%d)", key, j) |
158 | if not hasXMLProperty(self.xmlFile, animKey) then |
159 | break |
160 | end |
161 | |
162 | local animation = {} |
163 | animation.animName = getXMLString(self.xmlFile, animKey .. "#name") |
164 | animation.animSpeed = Utils.getNoNil(getXMLFloat(self.xmlFile, animKey .. "#speed"), 1.0) |
165 | animation.stopTime = getXMLFloat(self.xmlFile, animKey .. "#stopTime") |
166 | animation.repeatAfterUnfolding = Utils.getNoNil(getXMLBool(self.xmlFile, animKey .. "#repeatAfterUnfolding"), false) |
167 | animation.repeatStartTime = getXMLFloat(self.xmlFile, animKey .. "#repeatStartTime") |
168 | animation.repeated = false |
169 | |
170 | if self:getAnimationExists(animation.animName) then |
171 | table.insert(entry.animations, animation) |
172 | end |
173 | |
174 | j = j + 1 |
175 | end |
176 | |
177 | entry.windrowerEffects = g_effectManager:loadEffect(self.xmlFile, string.format("%s.windrowerEffect", key), self.components, self, self.i3dMappings) |
178 | entry.animationNodes = g_animationManager:loadAnimations(self.xmlFile, key..".animationNodes", self.components, self, self.i3dMappings) |
179 | |
180 | table.insert(spec.workModes, entry) |
181 | i = i + 1 |
182 | end |
183 | |
184 | spec.stateMax = table.getn(spec.workModes) |
185 | if spec.stateMax > ((2^WorkMode.WORKMODE_SEND_NUM_BITS) - 1) then |
186 | print("Error: WorkMode only supports "..((2^WorkMode.WORKMODE_SEND_NUM_BITS) - 1).." modes!") |
187 | end |
188 | |
189 | if spec.stateMax > 0 then |
190 | self:setWorkMode(1, true) |
191 | end |
192 | |
193 | spec.accumulatedFruitType = FruitType.UNKNOWN |
194 | spec.dirtyFlag = self:getNextDirtyFlag() |
195 | end |
onPostLoad
DescriptionDefinitiononPostLoad()Code
199 | function WorkMode:onPostLoad(savegame) |
200 | if savegame ~= nil and not savegame.resetVehicles then |
201 | local spec = self.spec_workMode |
202 | if spec.stateMax > 0 then |
203 | if hasXMLProperty(savegame.xmlFile, savegame.key..".workMode#state") then |
204 | local workMode = Utils.getNoNil(getXMLInt(savegame.xmlFile, savegame.key..".workMode#state"), 1) |
205 | workMode = MathUtil.clamp(workMode, 1, spec.stateMax) |
206 | |
207 | self:setWorkMode(workMode, true) |
208 | AnimatedVehicle.updateAnimations(self, 99999999) |
209 | |
210 | if self.getFoldAnimTime ~= nil then |
211 | if self.spec_foldable.foldMoveDirection == 0 then |
212 | if self:getFoldAnimTime() <= 0 then |
213 | self.spec_foldable.foldMoveDirection = -1 |
214 | else |
215 | self.spec_foldable.foldMoveDirection = 1 |
216 | end |
217 | end |
218 | end |
219 | end |
220 | end |
221 | end |
222 | end |
onReadStream
DescriptionCalled on client side on joinDefinition
onReadStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
246 | function WorkMode:onReadStream(streamId, connection) |
247 | local spec = self.spec_workMode |
248 | if spec.stateMax == 0 then |
249 | return |
250 | end |
251 | |
252 | local state = streamReadUIntN(streamId, WorkMode.WORKMODE_SEND_NUM_BITS) |
253 | self:setWorkMode(state, true) |
254 | end |
onReadUpdateStream
DescriptionCalled on on updateDefinition
onReadUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | stream ID |
integer | timestamp | timestamp |
table | connection | connection |
274 | function WorkMode:onReadUpdateStream(streamId, timestamp, connection) |
275 | if connection:getIsServer() then |
276 | if streamReadBool(streamId) then |
277 | local spec = self.spec_workMode |
278 | |
279 | local mode = spec.workModes[spec.state] |
280 | for _, effect in ipairs(mode.windrowerEffects) do |
281 | if streamReadBool(streamId) then |
282 | effect.lastChargeTime = g_currentMission.time |
283 | end |
284 | end |
285 | |
286 | spec.accumulatedFruitType = streamReadUIntN(streamId, 6) |
287 | end |
288 | end |
289 | end |
onRegisterActionEvents
DescriptionDefinitiononRegisterActionEvents()Code
742 | function WorkMode:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
743 | if self.isClient then |
744 | local spec = self.spec_workMode |
745 | if spec.stateMax > 0 then |
746 | self:clearActionEventsTable(spec.actionEvents) |
747 | |
748 | if isActiveForInputIgnoreSelection then |
749 | local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_WORKMODE, self, WorkMode.actionEventWorkModeChange, false, true, false, true, nil) |
750 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL) |
751 | |
752 | for _, mode in ipairs(spec.workModes) do |
753 | if mode.inputAction ~= nil then |
754 | _, actionEventId = self:addActionEvent(spec.actionEvents, mode.inputAction, self, WorkMode.actionEventWorkModeChangeDirect, false, true, false, true, nil) |
755 | g_inputBinding:setActionEventTextVisibility(actionEventId, false) |
756 | end |
757 | end |
758 | end |
759 | end |
760 | end |
761 | end |
onSetLowered
DescriptionCalled on change lowering stateDefinition
onSetLowered(boolean lowered)Arguments
boolean | lowered | attachable is lowered |
681 | function WorkMode:onSetLowered(lowered) |
682 | local spec = self.spec_workMode |
683 | if spec.stateMax == 0 then |
684 | return |
685 | end |
686 | |
687 | if self.getFoldAnimTime ~= nil then |
688 | local foldAnimTime = self:getFoldAnimTime() |
689 | if foldAnimTime ~= 1 and foldAnimTime ~= 0 and foldAnimTime ~= self.foldMiddleAnimTime then |
690 | spec.playDelayedLoweringAnimation = lowered |
691 | return |
692 | end |
693 | end |
694 | |
695 | local mode = spec.workModes[spec.state] |
696 | |
697 | for _, loweringAnimation in pairs(mode.loweringAnimations) do |
698 | if lowered then |
699 | if self:getAnimationTime(loweringAnimation.name) < 1 then |
700 | self:playAnimation(loweringAnimation.name, loweringAnimation.speed, nil, true) |
701 | end |
702 | else |
703 | if self:getAnimationTime(loweringAnimation.name) > 0 then |
704 | self:playAnimation(loweringAnimation.name, -loweringAnimation.speed, nil, true) |
705 | end |
706 | end |
707 | end |
708 | end |
onTurnedOff
DescriptionCalled on turn offDefinition
onTurnedOff(boolean noEventSend)Arguments
boolean | noEventSend | no event send |
641 | function WorkMode:onTurnedOff() |
642 | local spec = self.spec_workMode |
643 | if spec.stateMax == 0 then |
644 | return |
645 | end |
646 | |
647 | if self.isClient then |
648 | WorkMode.deactivateWindrowerEffects(self) |
649 | local mode = spec.workModes[spec.state] |
650 | |
651 | for _, turnedOnAnimation in pairs(mode.turnedOnAnimations) do |
652 | turnedOnAnimation.speedDirection = -1 |
653 | end |
654 | g_animationManager:stopAnimations(mode.animationNodes) |
655 | end |
656 | end |
onTurnedOn
DescriptionCalled on turn onDefinition
onTurnedOn(boolean noEventSend)Arguments
boolean | noEventSend | no event send |
661 | function WorkMode:onTurnedOn() |
662 | local spec = self.spec_workMode |
663 | if spec.stateMax == 0 then |
664 | return |
665 | end |
666 | |
667 | if self.isClient then |
668 | local mode = spec.workModes[spec.state] |
669 | |
670 | for _, turnedOnAnimation in pairs(mode.turnedOnAnimations) do |
671 | turnedOnAnimation.speedDirection = 1 |
672 | end |
673 | |
674 | g_animationManager:startAnimations(mode.animationNodes) |
675 | end |
676 | end |
onUpdate
DescriptionCalled on updateDefinition
onUpdate(float dt)Arguments
float | dt | time since last call in ms |
314 | function WorkMode:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
315 | local spec = self.spec_workMode |
316 | if spec.stateMax == 0 then |
317 | return |
318 | end |
319 | |
320 | if self.isClient then |
321 | local mode = spec.workModes[spec.state] |
322 | |
323 | for i=1, #spec.workModes do |
324 | for _, turnedOnAnimation in pairs(spec.workModes[i].turnedOnAnimations) do |
325 | if turnedOnAnimation.speedDirection ~= 0 then |
326 | local duration = turnedOnAnimation.turnOnFadeTime |
327 | if turnedOnAnimation.speedDirection == -1 then |
328 | duration = turnedOnAnimation.turnOffFadeTime |
329 | end |
330 | local min, max = 0, 1 |
331 | if turnedOnAnimation.speedDirection == 1 then |
332 | min, max = -1, 1 |
333 | end |
334 | |
335 | turnedOnAnimation.currentSpeed = MathUtil.clamp(turnedOnAnimation.currentSpeed + turnedOnAnimation.speedDirection * dt/duration, min, max) |
336 | |
337 | if not self:getIsAnimationPlaying(turnedOnAnimation.name) then |
338 | self:playAnimation(turnedOnAnimation.name, turnedOnAnimation.currentSpeed*turnedOnAnimation.speedScale, self:getAnimationTime(turnedOnAnimation.name), true) |
339 | else |
340 | self:setAnimationSpeed(turnedOnAnimation.name, turnedOnAnimation.currentSpeed*turnedOnAnimation.speedScale) |
341 | end |
342 | |
343 | if turnedOnAnimation.speedDirection == -1 and turnedOnAnimation.currentSpeed == 0 then |
344 | self:stopAnimation(turnedOnAnimation.name, true) |
345 | end |
346 | |
347 | if turnedOnAnimation.currentSpeed == 1 or turnedOnAnimation.currentSpeed == 0 then |
348 | turnedOnAnimation.speedDirection = 0 |
349 | end |
350 | end |
351 | end |
352 | end |
353 | |
354 | for _, effect in pairs(mode.windrowerEffects) do |
355 | if effect.lastChargeTime + 500 > g_currentMission.time then |
356 | local fillType = g_fruitTypeManager:getWindrowFillTypeIndexByFruitTypeIndex(spec.accumulatedFruitType) |
357 | if fillType ~= nil then |
358 | effect:setFillType(fillType) |
359 | if not effect:isRunning() then |
360 | g_effectManager:startEffect(effect) |
361 | end |
362 | end |
363 | else |
364 | if effect.turnOffRequiredEffect == 0 or (effect.turnOffRequiredEffect ~= 0 and not mode.windrowerEffects[effect.turnOffRequiredEffect]:isRunning()) then |
365 | g_effectManager:stopEffect(effect) |
366 | end |
367 | end |
368 | end |
369 | end |
370 | |
371 | if self.isServer then |
372 | local mode = spec.workModes[spec.state] |
373 | |
374 | local fruitType |
375 | local workAreaCharge |
376 | for _, area in ipairs(mode.workAreas) do |
377 | local workArea = self.spec_workArea.workAreas[area.workAreaIndex] |
378 | if workArea ~= nil then |
379 | if workArea.lastValidPickupFruitType ~= FruitType.UNKNOWN then |
380 | fruitType = workArea.lastValidPickupFruitType |
381 | end |
382 | workAreaCharge = workAreaCharge or workArea.lastPickupLiters ~= 0 |
383 | end |
384 | end |
385 | |
386 | if fruitType ~= nil then |
387 | if fruitType ~= spec.accumulatedFruitType then |
388 | spec.accumulatedFruitType = fruitType |
389 | self:raiseDirtyFlags(spec.dirtyFlag) |
390 | end |
391 | end |
392 | |
393 | for _, effect in pairs(mode.windrowerEffects) do |
394 | if workAreaCharge then |
395 | effect.lastChargeTime = g_currentMission.time |
396 | self:raiseDirtyFlags(spec.dirtyFlag) |
397 | end |
398 | end |
399 | end |
400 | end |
onUpdateTick
DescriptionDefinitiononUpdateTick()Code
404 | function WorkMode:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
405 | local spec = self.spec_workMode |
406 | if spec.stateMax == 0 then |
407 | return |
408 | end |
409 | |
410 | if self.getFoldAnimTime ~= nil then |
411 | local foldAnimTime = self:getFoldAnimTime() |
412 | if foldAnimTime == 0 or foldAnimTime == self.spec_foldable.foldMiddleAnimTime then |
413 | local mode = spec.workModes[spec.state] |
414 | for _, anim in pairs(mode.animations) do |
415 | if anim.repeatAfterUnfolding then |
416 | if not anim.repeated then |
417 | local curTime = self:getAnimationTime(anim.animName) |
418 | if anim.stopTime ~= nil then |
419 | self:setAnimationStopTime(anim.animName, anim.stopTime) |
420 | local speed = 1.0 |
421 | if curTime > anim.stopTime then |
422 | speed = -1.0 |
423 | end |
424 | self:playAnimation(anim.animName, speed, Utils.getNoNil(anim.repeatStartTime, curTime), true) |
425 | else |
426 | self:playAnimation(anim.animName, anim.animSpeed, Utils.getNoNil(anim.repeatStartTime, curTime), true) |
427 | end |
428 | |
429 | anim.repeated = true |
430 | end |
431 | end |
432 | end |
433 | end |
434 | |
435 | if spec.playDelayedLoweringAnimation ~= nil then |
436 | if foldAnimTime == 1 or foldAnimTime == 0 or foldAnimTime == self.spec_foldable.foldMiddleAnimTime then |
437 | WorkMode.onSetLowered(self, spec.playDelayedLoweringAnimation) |
438 | spec.playDelayedLoweringAnimation = nil |
439 | end |
440 | end |
441 | end |
442 | end |
onWriteStream
DescriptionCalled on server side on joinDefinition
onWriteStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
260 | function WorkMode:onWriteStream(streamId, connection) |
261 | local spec = self.spec_workMode |
262 | if spec.stateMax == 0 then |
263 | return |
264 | end |
265 | |
266 | streamWriteUIntN(streamId, spec.state, WorkMode.WORKMODE_SEND_NUM_BITS) |
267 | end |
onWriteUpdateStream
DescriptionCalled on on updateDefinition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)Arguments
integer | streamId | stream ID |
table | connection | connection |
integer | dirtyMask | dirty mask |
296 | function WorkMode:onWriteUpdateStream(streamId, connection, dirtyMask) |
297 | if not connection:getIsServer() then |
298 | local spec = self.spec_workMode |
299 | if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then |
300 | local mode = spec.workModes[spec.state] |
301 | |
302 | for _, effect in ipairs(mode.windrowerEffects) do |
303 | streamWriteBool(streamId, effect.lastChargeTime + 500 > g_currentMission.time) |
304 | end |
305 | |
306 | streamWriteUIntN(streamId, spec.accumulatedFruitType, 6) |
307 | end |
308 | end |
309 | end |
prerequisitesPresent
DescriptionChecks if all prerequisite specializations are loadedDefinition
prerequisitesPresent(table specializations)Arguments
table | specializations | specializations |
boolean | hasPrerequisite | true if all prerequisite specializations are loaded |
21 | function WorkMode.prerequisitesPresent(specializations) |
22 | return SpecializationUtil.hasSpecialization(WorkArea, specializations) |
23 | and SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations) |
24 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
43 | function WorkMode.registerEventListeners(vehicleType) |
44 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", WorkMode) |
45 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", WorkMode) |
46 | SpecializationUtil.registerEventListener(vehicleType, "onDelete", WorkMode) |
47 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", WorkMode) |
48 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", WorkMode) |
49 | SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", WorkMode) |
50 | SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", WorkMode) |
51 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", WorkMode) |
52 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", WorkMode) |
53 | SpecializationUtil.registerEventListener(vehicleType, "onDraw", WorkMode) |
54 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", WorkMode) |
55 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", WorkMode) |
56 | SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", WorkMode) |
57 | SpecializationUtil.registerEventListener(vehicleType, "onSetLowered", WorkMode) |
58 | SpecializationUtil.registerEventListener(vehicleType, "onFoldStateChanged", WorkMode) |
59 | SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", WorkMode) |
60 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
28 | function WorkMode.registerFunctions(vehicleType) |
29 | SpecializationUtil.registerFunction(vehicleType, "setWorkMode", WorkMode.setWorkMode) |
30 | SpecializationUtil.registerFunction(vehicleType, "getIsWorkModeChangeAllowed", WorkMode.getIsWorkModeChangeAllowed) |
31 | SpecializationUtil.registerFunction(vehicleType, "deactivateWindrowerEffects", WorkMode.deactivateWindrowerEffects) |
32 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
36 | function WorkMode.registerOverwrittenFunctions(vehicleType) |
37 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsWorkAreaActive", WorkMode.getIsWorkAreaActive) |
38 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", WorkMode.getCanBeSelected) |
39 | end |
saveToXMLFile
DescriptionDefinitionsaveToXMLFile()Code
226 | function WorkMode:saveToXMLFile(xmlFile, key, usedModNames) |
227 | local spec = self.spec_workMode |
228 | |
229 | setXMLInt(xmlFile, key.."#state", spec.state) |
230 | end |
setWorkMode
DescriptionChange work modeDefinition
setWorkMode(integer state, boolean noEventSend)Arguments
integer | state | new state |
boolean | noEventSend | no event send |
497 | function WorkMode:setWorkMode(state, noEventSend) |
498 | local spec = self.spec_workMode |
499 | |
500 | if noEventSend == nil or noEventSend == false then |
501 | if g_server ~= nil then |
502 | g_server:broadcastEvent(SetWorkModeEvent:new(self, state), nil, nil, self) |
503 | else |
504 | g_client:getServerConnection():sendEvent(SetWorkModeEvent:new(self, state)) |
505 | end |
506 | end |
507 | |
508 | if state ~= spec.state then |
509 | local currentMode = spec.workModes[spec.state] |
510 | if currentMode.animations ~= nil then |
511 | for _,anim in pairs(currentMode.animations) do |
512 | local curTime = self:getAnimationTime(anim.animName) |
513 | if anim.stopTime == nil then |
514 | self:playAnimation(anim.animName, -anim.animSpeed, curTime, noEventSend) |
515 | end |
516 | end |
517 | g_animationManager:stopAnimations(currentMode.animationNodes) |
518 | end |
519 | |
520 | local newMode = spec.workModes[state] |
521 | if newMode.animations ~= nil then |
522 | for _,anim in pairs(newMode.animations) do |
523 | local curTime = self:getAnimationTime(anim.animName) |
524 | if anim.stopTime ~= nil then |
525 | self:setAnimationStopTime(anim.animName, anim.stopTime) |
526 | local speed = 1.0 |
527 | if curTime > anim.stopTime then |
528 | speed = -1.0 |
529 | end |
530 | self:playAnimation(anim.animName, speed, curTime, noEventSend) |
531 | else |
532 | self:playAnimation(anim.animName, anim.animSpeed, curTime, noEventSend) |
533 | end |
534 | end |
535 | if self:getIsTurnedOn() then |
536 | g_animationManager:startAnimations(newMode.animationNodes) |
537 | end |
538 | end |
539 | |
540 | if self:getIsTurnedOn() then |
541 | for _, turnedOnAnimation in pairs(newMode.turnedOnAnimations) do |
542 | if self:getIsAnimationPlaying(turnedOnAnimation.name) then |
543 | for i=1, #spec.workModes do |
544 | local otherMode = spec.workModes[i] |
545 | if otherMode ~= newMode then |
546 | for j=1, #otherMode.turnedOnAnimations do |
547 | local otherAnimation = otherMode.turnedOnAnimations[j] |
548 | if otherAnimation.name == turnedOnAnimation.name then |
549 | local animationSpeed = self.spec_animatedVehicle.animations[turnedOnAnimation.name].currentSpeed |
550 | if animationSpeed ~= 0 then |
551 | local alpha = animationSpeed / turnedOnAnimation.speedScale |
552 | turnedOnAnimation.currentSpeed = alpha |
553 | otherAnimation.currentSpeed = 0 |
554 | otherAnimation.speedDirection = 0 |
555 | end |
556 | end |
557 | end |
558 | end |
559 | end |
560 | end |
561 | |
562 | turnedOnAnimation.speedDirection = 1 |
563 | end |
564 | end |
565 | |
566 | for _, effect in pairs(currentMode.windrowerEffects) do |
567 | g_effectManager:stopEffect(effect) |
568 | end |
569 | end |
570 | |
571 | local workAreaSpec = self.spec_workArea |
572 | if workAreaSpec ~= nil then |
573 | local workAreas = workAreaSpec.workAreas |
574 | for _, workArea in pairs(spec.workModes[state].workAreas) do |
575 | local workAreaToSet = workAreas[workArea.workAreaIndex] |
576 | if workAreaToSet ~= nil then |
577 | workAreaToSet.dropWindrowWorkAreaIndex = workArea.dropAreaIndex -- windrower |
578 | workAreaToSet.dropAreaIndex = workArea.dropAreaIndex -- mower |
579 | end |
580 | end |
581 | end |
582 | |
583 | spec.state = state |
584 | end |