LUADOC - Farming Simulator 22

AnimatedObject

Description
Class for animated objects
Parent
Object
Functions

delete

Description
Delete animated object
Definition
delete()
Code
325function AnimatedObject:delete()
326
327 if self.triggerNode ~= nil then
328 removeTrigger(self.triggerNode)
329 for i=0, getNumOfChildren(self.triggerNode)-1 do
330 removeTrigger(getChildAt(self.triggerNode, i))
331 end
332 self.triggerNode = nil
333 end
334
335 if self.samplesMoving ~= nil then
336 g_soundManager:deleteSamples(self.samplesMoving)
337 self.samplesMoving = nil
338 end
339 if self.samplePosEnd ~= nil then
340 g_soundManager:deleteSample(self.samplePosEnd)
341 self.samplePosEnd = nil
342 end
343 if self.sampleNegEnd ~= nil then
344 g_soundManager:deleteSample(self.sampleNegEnd)
345 self.sampleNegEnd = nil
346 end
347
348 if self.animation.sharedLoadRequestId ~= nil then
349 g_i3DManager:releaseSharedI3DFile(self.animation.sharedLoadRequestId)
350 self.animation.sharedLoadRequestId = nil
351 end
352
353 g_currentMission.activatableObjectsSystem:removeActivatable(self.activatable)
354
355 g_messageCenter:unsubscribeAll(self)
356
357 self.isDeleted = true
358
359 AnimatedObject:superClass().delete(self)
360end

hourChanged

Description
Called on hour change
Definition
hourChanged()
Code
595function AnimatedObject:hourChanged()
596 if self.isServer then
597 local currentHour = g_currentMission.environment.currentHour
598 if self.openingHours ~= nil then
599 if currentHour >= self.openingHours.startTime and currentHour < self.openingHours.endTime then
600 if not self.openingHours.isOpen then
601 if self.isServer then
602 self.animation.direction = 1
603 self:raiseActive()
604 end
605 self.openingHours.isOpen = true
606 end
607 if self.openingHours.disableIfClosed then
608 self.isEnabled = true
609 end
610 else
611 if self.openingHours.isOpen then
612 if self.isServer then
613 self.animation.direction = -1
614 self:raiseActive()
615 end
616 self.openingHours.isOpen = false
617 end
618 if self.openingHours.disableIfClosed then
619 self.isEnabled = false
620 end
621 end
622 end
623 end
624end

load

Description
Load animated object from object with given configuration file
Definition
load(integer nodeId, xmlFilename string, index integer)
Arguments
integernodeIdid of object
xmlFilenamestringPath of the xml configuration
indexintegerConfiguration index within the xml file
Return Values
booleansuccesssuccess
Code
50function AnimatedObject:load(rootNode, xmlFile, key, xmlFilename, i3dMappings)
51 self.xmlFilename = xmlFilename
52
53 local modName, baseDirectory = Utils.getModNameAndBaseDirectory(xmlFilename)
54 self.baseDirectory = baseDirectory
55 self.customEnvironment = modName
56
57 self.nodeId = rootNode
58 if type(rootNode) == "table" then
59 self.nodeId = rootNode[1].node
60 end
61
62 self.samples = {}
63
64 local success = true
65 self.saveId = xmlFile:getValue(key.."#saveId")
66 if self.saveId == nil then
67 self.saveId = "AnimatedObject_"..getName(self.nodeId)
68 end
69
70 local animKey = key .. ".animation"
71
72 self.animation = {}
73 self.animation.parts = {}
74 self.animation.shaderAnims = {}
75 self.animation.duration = xmlFile:getValue(animKey.."#duration")
76 self.animation.time = 0
77 self.animation.direction = 0
78 self.animation.maxTime = 0
79
80 xmlFile:iterate(animKey .. ".part", function(_, partKey)
81 local node = xmlFile:getValue(partKey.."#node", nil, rootNode, i3dMappings)
82 if node ~= nil then
83 local part = {}
84 part.node = node
85 part.frames = {}
86
87 local hasFrames = false
88 xmlFile:iterate(partKey .. ".keyFrame", function(_, frameKey)
89 local keyframe = {self:loadFrameValues(xmlFile, frameKey, node)}
90 keyframe.time = xmlFile:getValue(frameKey.."#time")
91 self.animation.maxTime = math.max(keyframe.time, self.animation.maxTime)
92
93 table.insert(part.frames, keyframe)
94 hasFrames = true
95 end)
96
97 if hasFrames then
98 table.insert(self.animation.parts, part)
99 end
100 end
101 end)
102
103 xmlFile:iterate(animKey .. ".shader", function(_, shaderKey)
104 local node = xmlFile:getValue(shaderKey.."#node", nil, rootNode, i3dMappings)
105 if node ~= nil then
106 local parameterName = xmlFile:getValue(shaderKey.."#parameterName")
107 if parameterName ~= nil and getHasShaderParameter(node, parameterName) then
108 local shader = {}
109
110 shader.node = node
111 shader.parameterName = parameterName
112 shader.frames = {}
113
114 local hasFrames = false
115 xmlFile:iterate(shaderKey .. ".keyFrame", function(_, frameKey)
116 local keyTime = xmlFile:getValue(frameKey.."#time")
117 local shaderX, shaderY, shaderZ, shaderW = getShaderParameter(node, parameterName)
118
119 local shaderValuesStr = xmlFile:getValue(frameKey.."#values", nil)
120 if shaderValuesStr ~= nil then
121 local splits = string.split(shaderValuesStr, " ")
122 local values = {}
123 values[1] = splits[1] and tonumber(splits[1]) or shaderX
124 values[2] = splits[2] and tonumber(splits[2]) or shaderY
125 values[3] = splits[3] and tonumber(splits[3]) or shaderZ
126 values[4] = splits[4] and tonumber(splits[4]) or shaderW
127
128 local keyframe = values
129 keyframe.time = keyTime
130 table.insert(shader.frames, keyframe)
131 hasFrames = true
132 end
133 end)
134
135 if hasFrames then
136 table.insert(self.animation.shaderAnims, shader)
137 end
138 end
139 end
140 end)
141
142 for _, part in ipairs(self.animation.parts) do
143 part.animCurve = AnimCurve.new(linearInterpolatorN)
144
145 for _, frame in ipairs(part.frames) do
146 if self.animation.duration == nil then
147 frame.time = frame.time / self.animation.maxTime
148 end
149
150 part.animCurve:addKeyframe(frame)
151 end
152 end
153
154 for _, shader in ipairs(self.animation.shaderAnims) do
155 shader.animCurve = AnimCurve.new(linearInterpolatorN)
156
157 for _, frame in ipairs(shader.frames) do
158 if self.animation.duration == nil then
159 frame.time = frame.time / self.animation.maxTime
160 end
161
162 shader.animCurve:addKeyframe(frame)
163 end
164 end
165
166 local clipRootNode = xmlFile:getValue(animKey .. ".clip#rootNode", nil, rootNode, i3dMappings)
167 local clipName = xmlFile:getValue(animKey .. ".clip#name")
168
169 if clipRootNode ~= nil and clipName ~= nil then
170 local clipFilename = xmlFile:getValue(animKey .. ".clip#filename")
171
172 self.animation.clipRootNode = clipRootNode
173 self.animation.clipName = clipName
174 self.animation.clipTrack = 0
175
176 if clipFilename ~= nil then
177 clipFilename = Utils.getFilename(clipFilename, self.baseDirectory)
178 self.animation.sharedLoadRequestId = g_i3DManager:loadSharedI3DFileAsync(clipFilename, false, false, self.onSharedAnimationFileLoaded, self, nil)
179 self.animation.clipFilename = clipFilename
180 else
181 self:applyAnimation()
182 end
183 end
184
185 if self.animation.duration == nil then
186 self.animation.duration = self.animation.maxTime
187 end
188 self.animation.duration = self.animation.duration * 1000
189
190
191 local initialTime = xmlFile:getValue(animKey.."#initialTime", 0)*1000
192 self:setAnimTime(initialTime / self.animation.duration, true)
193
194 local startTime = xmlFile:getValue(key..".openingHours#startTime")
195 local endTime = xmlFile:getValue(key..".openingHours#endTime")
196 if startTime ~= nil and endTime ~= nil then
197 local disableIfClosed = xmlFile:getValue(key..".openingHours#disableIfClosed", false)
198 local closedText = xmlFile:getValue(key..".openingHours#closedText", nil, self.customEnvironment)
199 self.openingHours = {startTime=startTime, endTime=endTime, disableIfClosed=disableIfClosed, closedText=closedText}
200 g_messageCenter:subscribe(MessageType.HOUR_CHANGED, self.hourChanged, self)
201 end
202
203 self.isEnabled = true
204
205
206 local triggerId = xmlFile:getValue(key..".controls#triggerNode", nil, rootNode, i3dMappings)
207 if triggerId ~= nil then
208 self.triggerNode = triggerId
209
210 addTrigger(self.triggerNode, "triggerCallback", self)
211 for i=0, getNumOfChildren(self.triggerNode)-1 do
212 addTrigger(getChildAt(self.triggerNode, i), "triggerCallback", self)
213 end
214
215 local posAction = xmlFile:getValue(key..".controls#posAction")
216 if posAction ~= nil then
217 if InputAction[posAction] then
218 self.controls.posAction = posAction
219
220 local posText = xmlFile:getValue(key..".controls#posText")
221 if posText ~= nil then
222 if g_i18n:hasText(posText, self.customEnvironment) then
223 posText = g_i18n:getText(posText, self.customEnvironment)
224 end
225 self.controls.posActionText = posText
226 end
227
228 local negText = xmlFile:getValue(key..".controls#negText")
229 if negText ~= nil then
230 if g_i18n:hasText(negText, self.customEnvironment) then
231 negText = g_i18n:getText(negText, self.customEnvironment)
232 end
233 self.controls.negActionText = negText
234 end
235
236 local negAction = xmlFile:getValue(key..".controls#negAction")
237 if negAction ~= nil then
238 if InputAction[negAction] then
239 self.controls.negAction = negAction
240 else
241 print("Warning: Negative direction action '"..negAction.."' not defined!")
242 end
243 end
244 else
245 print("Warning: Positive direction action '"..posAction.."' not defined!")
246 end
247 end
248 end
249
250 if g_client ~= nil then
251 local soundsKey = key .. ".sounds"
252 self.samplesMoving = g_soundManager:loadSamplesFromXML(xmlFile, soundsKey, "moving", self.baseDirectory, rootNode, 1, AudioGroup.ENVIRONMENT, i3dMappings, nil)
253 self.samplePosEnd = g_soundManager:loadSampleFromXML(xmlFile, soundsKey, "posEnd", self.baseDirectory, rootNode, 1, AudioGroup.ENVIRONMENT, i3dMappings, nil)
254 self.sampleNegEnd = g_soundManager:loadSampleFromXML(xmlFile, soundsKey, "negEnd", self.baseDirectory, rootNode, 1, AudioGroup.ENVIRONMENT, i3dMappings, nil)
255 end
256
257 self.animatedObjectDirtyFlag = self:getNextDirtyFlag()
258
259 return success
260end

loadFrameValues

Description
Load frame values from xml
Definition
loadFrameValues(integer fileId, string key, integer node)
Arguments
integerfileIdxml file id
stringkeykey
integernodenode id
Return Values
floatxx translation
floatyy translation
floatzz translation
floatrxx rotation
floatryy rotation
floatrzz rotation
floatsxx scale
floatsyy scale
floatszz scale
integervisibilityvisibility
Code
281function AnimatedObject:loadFrameValues(xmlFile, key, node)
282 local rx, ry, rz = xmlFile:getValue(key.."#rotation", {getRotation(node)})
283 local x, y, z = xmlFile:getValue(key.."#translation", {getTranslation(node)})
284 local sx, sy, sz = xmlFile:getValue(key.."#scale", {getScale(node)})
285 local isVisible = xmlFile:getValue(key.."#visibility", true)
286
287 local visibility = 1
288 if not isVisible then
289 visibility = 0
290 end
291
292 return x, y, z, rx, ry, rz, sx, sy, sz, visibility
293end

loadFromXMLFile

Description
Loading from attributes and nodes
Definition
loadFromXMLFile(integer xmlFile, string key)
Arguments
integerxmlFileid of xml object
stringkeykey
Return Values
booleansuccesssuccess
Code
430function AnimatedObject:loadFromXMLFile(xmlFile, key)
431 local animTime = xmlFile:getValue(key .. "#time")
432 if animTime ~= nil then
433 self.animation.direction = xmlFile:getValue(key.."#direction", 0)
434 self:setAnimTime(animTime, true)
435 end
436
437 AnimatedObject.hourChanged(self)
438
439 return true
440end

new

Description
Creating new instance of animated object class
Definition
new(boolean isServer, boolean isClient, table customMt)
Arguments
booleanisServeris server
booleanisClientis client
tablecustomMtcustom metatable
Return Values
tableselfnew instance of object
Code
20function AnimatedObject.new(isServer, isClient, customMt)
21 local self = Object.new(isServer, isClient, customMt or AnimatedObject_mt)
22 self.nodeId = 0
23 self.isMoving = false
24
25 -- input controls fields:
26 self.controls = {}
27 self.controls.wasPressed = false
28 self.controls.active = false
29 self.controls.posAction = nil
30 self.controls.negAction = nil
31 self.controls.posText = nil
32 self.controls.negText = nil
33 self.controls.posActionEventId = nil
34 self.controls.negActionEventId = nil
35
36 self.networkTimeInterpolator = InterpolationTime.new(1.2)
37 self.networkAnimTimeInterpolator = InterpolatorValue.new(0)
38
39 self.activatable = AnimatedObjectActivatable.new(self)
40
41 return self
42end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
366function AnimatedObject:readStream(streamId, connection)
367 AnimatedObject:superClass().readStream(self, streamId, connection)
368 if connection:getIsServer() then
369 local animTime = streamReadFloat32(streamId)
370 self:setAnimTime(animTime, true)
371 local direction = streamReadUIntN(streamId, 2) - 1
372 self.animation.direction = direction
373
374 self.networkAnimTimeInterpolator:setValue(animTime)
375
376 self.networkTimeInterpolator:reset()
377 end
378end

readUpdateStream

Description
Called on client side on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
397function AnimatedObject:readUpdateStream(streamId, timestamp, connection)
398 AnimatedObject:superClass().readUpdateStream(self, streamId, timestamp, connection)
399 if connection:getIsServer() then
400 if streamReadBool(streamId) then
401 self.networkTimeInterpolator:startNewPhaseNetwork()
402 local animTime = streamReadFloat32(streamId)
403 self.networkAnimTimeInterpolator:setTargetValue(animTime)
404 local direction = streamReadUIntN(streamId, 2) - 1
405 self.animation.direction = direction
406 end
407 end
408end

registerSavegameXMLPaths

Description
Definition
registerSavegameXMLPaths()
Code
698function AnimatedObject.registerSavegameXMLPaths(schema, basePath)
699 schema:register(XMLValueType.FLOAT, basePath .. "#time", "Animated object time")
700 schema:register(XMLValueType.INT, basePath .. "#direction", "Animated object direction", 0)
701end

registerXMLPaths

Description
Definition
registerXMLPaths()
Code
654function AnimatedObject.registerXMLPaths(schema, basePath)
655 schema:setXMLSharedRegistration("AnimatedObject", basePath)
656
657 basePath = basePath .. ".animatedObject(?)"
658 schema:register(XMLValueType.STRING, basePath .. "#saveId", "Save identifier", "AnimatedObject_[nodeName]")
659 schema:register(XMLValueType.FLOAT, basePath .. ".animation#duration", "Animation duration (sec.)", 3)
660 schema:register(XMLValueType.NODE_INDEX, basePath .. ".animation.part(?)#node", "Part node")
661 schema:register(XMLValueType.FLOAT, basePath .. ".animation.part(?).keyFrame(?)#time", "Key time")
662 schema:register(XMLValueType.VECTOR_ROT, basePath .. ".animation.part(?).keyFrame(?)#rotation", "Key rotation", "values read from i3d node")
663 schema:register(XMLValueType.VECTOR_TRANS, basePath .. ".animation.part(?).keyFrame(?)#translation", "Key translation", "values read from i3d node")
664 schema:register(XMLValueType.VECTOR_SCALE, basePath .. ".animation.part(?).keyFrame(?)#scale", "Key scale", "values read from i3d node")
665 schema:register(XMLValueType.BOOL, basePath .. ".animation.part(?).keyFrame(?)#visibility", "Key visibility", true)
666
667 schema:register(XMLValueType.NODE_INDEX, basePath .. ".animation.shader(?)#node", "Shader node")
668 schema:register(XMLValueType.STRING, basePath .. ".animation.shader(?)#parameterName", "Shader parameter name")
669 schema:register(XMLValueType.FLOAT, basePath .. ".animation.shader(?).keyFrame(?)#time", "Key time")
670 schema:register(XMLValueType.STRING, basePath .. ".animation.shader(?).keyFrame(?)#values", "Key shader parameter values. Use '-' to force using existing shader parameter value")
671
672 schema:register(XMLValueType.NODE_INDEX, basePath .. ".animation.clip#rootNode", "I3d animation rootnode")
673 schema:register(XMLValueType.STRING, basePath .. ".animation.clip#name", "I3d animation clipName")
674 schema:register(XMLValueType.STRING, basePath .. ".animation.clip#filename", "I3d animation external animation")
675
676 schema:register(XMLValueType.FLOAT, basePath .. ".animation#initialTime", "Animation time after loading", 0)
677 schema:register(XMLValueType.FLOAT, basePath .. ".openingHours#startTime", "Start day time")
678 schema:register(XMLValueType.FLOAT, basePath .. ".openingHours#endTime", "End day time")
679 schema:register(XMLValueType.BOOL, basePath .. ".openingHours#disableIfClosed", "Disabled if closed")
680 schema:register(XMLValueType.L10N_STRING, basePath .. ".openingHours#closedText", "Closed text")
681
682 schema:register(XMLValueType.NODE_INDEX, basePath .. ".controls#triggerNode", "Player trigger node")
683
684 schema:register(XMLValueType.STRING, basePath .. ".controls#posAction", "Positive direction action event name")
685 schema:register(XMLValueType.STRING, basePath .. ".controls#posText", "Positive direction text")
686 schema:register(XMLValueType.STRING, basePath .. ".controls#negText", "Negative direction text")
687 schema:register(XMLValueType.STRING, basePath .. ".controls#negAction", "Negative direction action event name")
688
689 SoundManager.registerSampleXMLPaths(schema, basePath .. ".sounds", "moving(?)")
690 SoundManager.registerSampleXMLPaths(schema, basePath .. ".sounds", "posEnd")
691 SoundManager.registerSampleXMLPaths(schema, basePath .. ".sounds", "negEnd")
692
693 schema:setXMLSharedRegistration()
694end

setAnimTime

Description
Set animation time
Definition
setAnimTime(float t)
Arguments
floatttime
Code
554function AnimatedObject:setAnimTime(t, omitSound)
555 t = MathUtil.clamp(t, 0, 1)
556
557 for _, part in pairs(self.animation.parts) do
558 local v = part.animCurve:get(t)
559 self:setFrameValues(part.node, v)
560 end
561
562 for _, shader in pairs(self.animation.shaderAnims) do
563 local v = shader.animCurve:get(t)
564 local parameterName = shader.parameterName
565
566 setShaderParameter(shader.node, parameterName, v[1], v[2], v[3], v[4], false)
567 end
568
569 local characterSet = self.animation.clipCharacterSet
570 if characterSet ~= nil then
571 enableAnimTrack(characterSet, self.animation.clipTrack)
572 setAnimTrackTime(characterSet, self.animation.clipTrack, t * self.animation.clipDuration, true)
573 disableAnimTrack(characterSet, self.animation.clipTrack)
574 end
575
576 self.animation.time = t
577 self.isMoving = true
578
579 return t
580end

setFrameValues

Description
Set frame values
Definition
setFrameValues(integer node, table v)
Arguments
integernodenode id
tablevvalues
Code
586function AnimatedObject:setFrameValues(node, v)
587 setTranslation(node, v[1], v[2], v[3])
588 setRotation(node, v[4], v[5], v[6])
589 setScale(node, v[7], v[8], v[9])
590 setVisibility(node, v[10] == 1)
591end

triggerCallback

Description
Trigger callback
Definition
triggerCallback(integer triggerId, integer otherId, boolean onEnter, boolean onLeave, boolean onStay)
Arguments
integertriggerIdid of trigger
integerotherIdid of object that calls callback
booleanonEntercalled on enter
booleanonLeavecalled on leave
booleanonStaycalled on stay
Code
633function AnimatedObject:triggerCallback(triggerId, otherId, onEnter, onLeave, onStay)
634 if g_currentMission.missionInfo:isa(FSCareerMissionInfo) then
635 if onEnter or onLeave then
636 if g_currentMission.player ~= nil and otherId == g_currentMission.player.rootNode then
637 if onEnter then
638 if self.ownerFarmId == nil or self.ownerFarmId == AccessHandler.EVERYONE or g_currentMission.accessHandler:canFarmAccessOtherId(g_currentMission:getFarmId(), self.ownerFarmId) then
639 g_currentMission.activatableObjectsSystem:addActivatable(self.activatable)
640 end
641 else
642 g_currentMission.activatableObjectsSystem:removeActivatable(self.activatable)
643 end
644
645 self:raiseActive()
646 end
647 end
648 end
649end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
471function AnimatedObject:update(dt)
472 AnimatedObject:superClass().update(self, dt)
473
474
475 local finishedAnimation = false
476
477 -- former updateTick()
478 if self.isServer then
479 if self.animation.direction ~= 0 then
480 local newAnimTime = MathUtil.clamp(self.animation.time + (self.animation.direction*dt)/self.animation.duration, 0, 1)
481
482 self:setAnimTime(newAnimTime)
483 if newAnimTime == 0 or newAnimTime == 1 then
484 self.animation.direction = 0
485 finishedAnimation = true
486 end
487 end
488
489 if self.animation.time ~= self.animation.timeSend then
490 self.animation.timeSend = self.animation.time
491 self:raiseDirtyFlags(self.animatedObjectDirtyFlag)
492 end
493 else
494 self.networkTimeInterpolator:update(dt)
495 local interpolationAlpha = self.networkTimeInterpolator:getAlpha()
496 local animTime = self.networkAnimTimeInterpolator:getInterpolatedValue(interpolationAlpha)
497 local newAnimTime = self:setAnimTime(animTime)
498
499 if self.animation.direction ~= 0 then
500 if self.animation.direction > 0 then
501 if newAnimTime == 1 then
502 self.animation.direction = 0
503 finishedAnimation = true
504 end
505 else
506 if newAnimTime == 0 then
507 self.animation.direction = 0
508 finishedAnimation = true
509 end
510 end
511 end
512
513 if self.networkTimeInterpolator:isInterpolating() then
514 self:raiseActive()
515 end
516 end
517
518 if self.samplesMoving ~= nil then
519 if self.isMoving and self.animation.direction ~= 0 then
520 if not self.samplesMovingArePlaying then
521 g_soundManager:playSamples(self.samplesMoving)
522 self.samplesMovingArePlaying = true
523 end
524 else
525 if self.samplesMovingArePlaying then
526 g_soundManager:stopSamples(self.samplesMoving)
527 self.samplesMovingArePlaying = false
528 end
529 end
530 end
531
532 if finishedAnimation and self.animation.direction == 0 then
533 if self.samplePosEnd ~= nil and self.animation.time == 1 then
534 g_soundManager:playSample(self.samplePosEnd)
535 elseif self.sampleNegEnd ~= nil and self.animation.time == 0 then
536 g_soundManager:playSample(self.sampleNegEnd)
537 end
538 end
539
540 self.isMoving = false
541
542 if self.animation.direction ~= 0 then
543 self:raiseActive()
544 end
545end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
384function AnimatedObject:writeStream(streamId, connection)
385 AnimatedObject:superClass().writeStream(self, streamId, connection)
386 if not connection:getIsServer() then
387 streamWriteFloat32(streamId, self.animation.time)
388 streamWriteUIntN(streamId, self.animation.direction + 1, 2)
389 end
390end

writeUpdateStream

Description
Called on server side on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
415function AnimatedObject:writeUpdateStream(streamId, connection, dirtyMask)
416 AnimatedObject:superClass().writeUpdateStream(self, streamId, connection, dirtyMask)
417 if not connection:getIsServer() then
418 if streamWriteBool(streamId, bitAND(dirtyMask, self.animatedObjectDirtyFlag) ~= 0) then
419 streamWriteFloat32(streamId, self.animation.timeSend)
420 streamWriteUIntN(streamId, self.animation.direction + 1, 2)
421 end
422 end
423end