LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

SpeedRotatingParts

Description
Specialization for vehicle with (non-wheel) parts rotating or scrolling dependent on its driving speed
Functions

getIsSpeedRotatingPartActive

Description
Returns true if speed rotating part is active
Definition
getIsSpeedRotatingPartActive(table speedRotatingPart)
Arguments
tablespeedRotatingPartspeedRotatingPart
Return Values
booleanisActivespeed rotating part is active
Code
409function SpeedRotatingParts:getIsSpeedRotatingPartActive(speedRotatingPart)
410 if speedRotatingPart.onlyActiveWhenLowered then
411 if self.getIsLowered ~= nil and not self:getIsLowered() then
412 return false
413 else
414 return true
415 end
416 end
417
418 return true
419end

getSpeedRotatingPartDirection

Description
Return direction of speed rotating part
Definition
getSpeedRotatingPartDirection(table speedRotatingPart)
Arguments
tablespeedRotatingPartspeed rotating part
Return Values
integerdirectiondirection
Code
425function SpeedRotatingParts:getSpeedRotatingPartDirection(speedRotatingPart)
426 return 1
427end

initSpecialization

Description
Definition
initSpecialization()
Code
26function SpeedRotatingParts.initSpecialization()
27 local schema = Vehicle.xmlSchema
28 schema:setXMLSpecializationType("SpeedRotatingParts")
29
30 schema:register(XMLValueType.NODE_INDEX, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#node", "Speed rotating part node")
31 schema:register(XMLValueType.NODE_INDEX, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#shaderNode", "Speed rotating part shader node")
32 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#useRotation", "Use shader rotation", true)
33 schema:register(XMLValueType.STRING, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#vtxPositionArrayFilename", "Path to vertex position filename (If this is set the shader variation 'vtxRotate_colorMask' is forced)")
34 schema:register(XMLValueType.VECTOR_2, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#scrollScale", "Shader scroll speed")
35 schema:register(XMLValueType.INT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#shaderComponent", "Shader parameter component to control", "Default based on available shader attributes")
36 schema:register(XMLValueType.FLOAT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#scrollLength", "Shader scroll length")
37 schema:register(XMLValueType.NODE_INDEX, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#driveNode", "Drive node to apply x drive", "speedRotatingPart#node")
38 schema:register(XMLValueType.INT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#refComponentIndex", "Reference component index")
39 schema:register(XMLValueType.INT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#wheelIndex", "Reference wheel index")
40
41 schema:register(XMLValueType.NODE_INDEX, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#dirRefNode", "Direction reference node")
42 schema:register(XMLValueType.NODE_INDEX, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#dirFrameNode", "Direction reference frame")
43
44 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#alignDirection", "Align direction", false)
45 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#applySteeringAngle", "Apply steering angle", false)
46 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#useWheelReprTranslation", "Apply wheel repr translation", true)
47 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#updateXDrive", "Update X drive", true)
48 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#versatileYRot", "Versatile Y rot", false)
49
50 schema:register(XMLValueType.ANGLE, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#minYRot", "Min. Y rotation")
51 schema:register(XMLValueType.ANGLE, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#maxYRot", "Max. Y rotation")
52
53 schema:register(XMLValueType.FLOAT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#wheelScale", "Wheel scale")
54 schema:register(XMLValueType.FLOAT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#radius", "Radius", 1)
55
56 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#onlyActiveWhenLowered", "Only active if lowered", false)
57 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#stopIfNotActive", "Stop if not active", false)
58 schema:register(XMLValueType.FLOAT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#fadeOutTime", "Fade out time", 3)
59 schema:register(XMLValueType.FLOAT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#activationSpeed", "Min. speed for activation", 1)
60 schema:register(XMLValueType.NODE_INDEX, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#speedReferenceNode", "Speed reference node")
61
62 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#hasTireTracks", "Has Tire Tracks", false)
63 schema:register(XMLValueType.INT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#tireTrackAtlasIndex", "Index on tire track atlas", 0)
64 schema:register(XMLValueType.FLOAT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#tireTrackWidth", "Width of tire tracks", 0.5)
65 schema:register(XMLValueType.BOOL, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#tireTrackInverted", "Tire track texture inverted", false)
66
67 schema:register(XMLValueType.FLOAT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#maxUpdateDistance", "Max. distance from current camera to vehicle to update part", SpeedRotatingParts.DEFAULT_MAX_UPDATE_DISTANCE)
68
69 schema:setXMLSpecializationType()
70end

loadSpeedRotatingPartFromXML

Description
Loads speed rotating parts from xml
Definition
loadSpeedRotatingPartFromXML(table speedRotatingPart, integer xmlFile, string key)
Arguments
tablespeedRotatingPartspeedRotatingPart
integerxmlFileid of xml object
stringkeykey
Return Values
booleansuccesssuccess
Code
256function SpeedRotatingParts:loadSpeedRotatingPartFromXML(speedRotatingPart, xmlFile, key)
257 speedRotatingPart.repr = xmlFile:getValue(key.."#node", nil, self.components, self.i3dMappings)
258 speedRotatingPart.shaderNode = xmlFile:getValue(key.."#shaderNode", nil, self.components, self.i3dMappings)
259
260 speedRotatingPart.shaderParameterName = "offsetUV"
261 speedRotatingPart.shaderParameterPrevName = nil
262 speedRotatingPart.shaderParameterComponent = 3
263 speedRotatingPart.shaderParameterSpeedScale = 1
264 speedRotatingPart.shaderParameterValues = {0, 0, 0, 0}
265 if speedRotatingPart.shaderNode ~= nil then
266 speedRotatingPart.useShaderRotation = xmlFile:getValue(key.."#useRotation", true)
267 speedRotatingPart.scrollScale = xmlFile:getValue(key.."#scrollScale", "1 0", true)
268 speedRotatingPart.scrollLength = xmlFile:getValue(key.."#scrollLength")
269
270 local vtxPositionArrayFilename = xmlFile:getValue(key.."#vtxPositionArrayFilename")
271 if vtxPositionArrayFilename ~= nil then
272 vtxPositionArrayFilename = Utils.getFilename(vtxPositionArrayFilename, self.baseDirectory)
273
274 local materialId = getMaterial(speedRotatingPart.shaderNode, 0)
275
276 local curVariation = getMaterialCustomShaderVariation(materialId)
277 if curVariation ~= "vtxRotate_colorMask" then
278 materialId = setMaterialCustomShaderVariation(materialId, "vtxRotate_colorMask", false)
279 materialId = setMaterialCustomMapFromFile(materialId, "mTrackArray", vtxPositionArrayFilename, true, false, true)
280 else
281 materialId = setMaterialCustomMapFromFile(materialId, "mTrackArray", vtxPositionArrayFilename, true, false, false)
282 end
283
284 setMaterial(speedRotatingPart.shaderNode, materialId, 0)
285 end
286
287 if getHasShaderParameter(speedRotatingPart.shaderNode, "rotationAngle") then
288 speedRotatingPart.shaderParameterName = "rotationAngle"
289 speedRotatingPart.shaderParameterPrevName = "prevRotationAngle"
290 speedRotatingPart.shaderParameterComponent = 1
291 speedRotatingPart.shaderParameterSpeedScale = -1
292 end
293
294 if getHasShaderParameter(speedRotatingPart.shaderNode, "scrollPosition") then
295 speedRotatingPart.shaderParameterName = "scrollPosition"
296 speedRotatingPart.shaderParameterPrevName = "prevScrollPosition"
297 speedRotatingPart.shaderParameterComponent = 1
298 speedRotatingPart.shaderParameterSpeedScale = 1
299 end
300
301 speedRotatingPart.shaderParameterComponent = xmlFile:getValue(key.."#shaderComponent", speedRotatingPart.shaderParameterComponent)
302 end
303
304 if speedRotatingPart.repr == nil and speedRotatingPart.shaderNode == nil then
305 Logging.xmlWarning(self.xmlFile, "Invalid speedRotationPart node '%s' in '%s'", tostring(getXMLString(xmlFile.handle, key.."#node") or getXMLString(xmlFile.handle, key.."#shaderNode")), key)
306 return false
307 end
308 speedRotatingPart.driveNode = xmlFile:getValue(key .. "#driveNode", speedRotatingPart.repr, self.components, self.i3dMappings)
309
310 local componentIndex = xmlFile:getValue(key.."#refComponentIndex")
311 if componentIndex ~= nil and self.components[componentIndex] ~= nil then
312 speedRotatingPart.componentNode = self.components[componentIndex].node
313 else
314 local node = Utils.getNoNil(speedRotatingPart.driveNode, speedRotatingPart.shaderNode)
315 speedRotatingPart.componentNode = self:getParentComponent(node)
316 end
317
318 speedRotatingPart.xDrive = 0
319 local wheelIndex = xmlFile:getValue(key.."#wheelIndex")
320 if wheelIndex ~= nil then
321 if self.getWheels == nil then
322 Logging.xmlWarning(self.xmlFile, "wheelIndex for speedRotatingPart '%s' given, but no wheels loaded/defined", key)
323 else
324 local wheels = self:getWheels()
325 local wheel = wheels[wheelIndex]
326 if wheel == nil then
327 Logging.xmlWarning(self.xmlFile, "Invalid wheel index '%s' for speedRotatingPart '%s'", tostring(wheelIndex), key)
328 return false
329 end
330 if not wheel.isSynchronized then
331 Logging.xmlWarning(self.xmlFile, "Referenced wheel with index '%s' for speedRotatingPart '%s' is not synchronized in multiplayer", tostring(wheelIndex), key)
332 end
333 speedRotatingPart.wheel = wheel
334 speedRotatingPart.lastWheelXRot = nil
335
336 speedRotatingPart.hasTireTracks = xmlFile:getValue(key .. "#hasTireTracks", false)
337 speedRotatingPart.tireTrackAtlasIndex = xmlFile:getValue(key .. "#tireTrackAtlasIndex", 0)
338 speedRotatingPart.tireTrackWidth = xmlFile:getValue(key .. "#tireTrackWidth", 0.5)
339 speedRotatingPart.tireTrackInverted = xmlFile:getValue(key .. "#tireTrackInverted", false)
340 if speedRotatingPart.hasTireTracks then
341 local activeFunc = function()
342 return self:getIsSpeedRotatingPartActive(speedRotatingPart)
343 end
344
345 speedRotatingPart.tireTrackNodeIndex = self:addTireTrackNode(wheel, true, speedRotatingPart.componentNode, speedRotatingPart.driveNode, speedRotatingPart.tireTrackAtlasIndex, speedRotatingPart.tireTrackWidth, wheel.radius, 0, speedRotatingPart.tireTrackInverted, activeFunc)
346 end
347 end
348 end
349
350 speedRotatingPart.dirRefNode = xmlFile:getValue(key.."#dirRefNode", nil, self.components, self.i3dMappings)
351 speedRotatingPart.dirFrameNode = xmlFile:getValue(key.."#dirFrameNode", nil, self.components, self.i3dMappings)
352 speedRotatingPart.alignDirection = xmlFile:getValue(key .. "#alignDirection", false)
353 speedRotatingPart.applySteeringAngle = xmlFile:getValue(key .. "#applySteeringAngle", false)
354 speedRotatingPart.useWheelReprTranslation = xmlFile:getValue(key .. "#useWheelReprTranslation", true)
355 speedRotatingPart.updateXDrive = xmlFile:getValue(key .. "#updateXDrive", true)
356
357 speedRotatingPart.versatileYRot = xmlFile:getValue(key .. "#versatileYRot", false)
358 if speedRotatingPart.versatileYRot and speedRotatingPart.repr == nil then
359 Logging.xmlWarning(self.xmlFile, "Versatile speedRotationPart '%s' does not support shaderNodes", key)
360 return false
361 end
362
363 speedRotatingPart.minYRot = xmlFile:getValue(key .. "#minYRot")
364 speedRotatingPart.maxYRot = xmlFile:getValue(key .. "#maxYRot")
365 speedRotatingPart.steeringAngle = 0
366 speedRotatingPart.steeringAngleSent = 0
367
368 speedRotatingPart.speedReferenceNode = xmlFile:getValue(key.."#speedReferenceNode", nil, self.components, self.i3dMappings)
369 if speedRotatingPart.speedReferenceNode ~= nil and speedRotatingPart.speedReferenceNode == speedRotatingPart.driveNode then
370 Logging.xmlWarning(self.xmlFile, "Ignoring speedRotationPart '%s' because speedReferenceNode is identical with driveNode. Need to be different!", key)
371 return false
372 end
373
374 speedRotatingPart.wheelScale = xmlFile:getValue(key .. "#wheelScale")
375 if speedRotatingPart.wheelScale == nil then
376 local baseRadius = 1.0
377 local radius = 1.0
378 if speedRotatingPart.wheel ~= nil and speedRotatingPart.speedReferenceNode == nil then
379 baseRadius = speedRotatingPart.wheel.radius
380 radius = speedRotatingPart.wheel.radius
381 end
382 speedRotatingPart.wheelScale = baseRadius / xmlFile:getValue(key.."#radius", radius)
383 end
384
385 speedRotatingPart.wheelScaleBackup = speedRotatingPart.wheelScale
386
387 speedRotatingPart.onlyActiveWhenLowered = xmlFile:getValue(key .. "#onlyActiveWhenLowered", false)
388 speedRotatingPart.stopIfNotActive = xmlFile:getValue(key .. "#stopIfNotActive", false)
389 speedRotatingPart.fadeOutTime = xmlFile:getValue(key .. "#fadeOutTime", 3) * 1000
390 speedRotatingPart.activationSpeed = xmlFile:getValue(key .. "#activationSpeed", 1)
391
392 speedRotatingPart.lastSpeed = 0
393 speedRotatingPart.lastDir = 1
394
395 speedRotatingPart.maxUpdateDistance = xmlFile:getValue(key .. "#maxUpdateDistance", SpeedRotatingParts.DEFAULT_MAX_UPDATE_DISTANCE)
396
397 -- always update to sync the correct angle to the clients
398 if self.isServer and speedRotatingPart.versatileYRot then
399 speedRotatingPart.maxUpdateDistance = math.huge
400 end
401
402 return true
403end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
102function SpeedRotatingParts:onLoad(savegame)
103 local spec = self.spec_speedRotatingParts
104
105 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.speedRotatingParts.speedRotatingPart(0)#index", "vehicle.speedRotatingParts.speedRotatingPart(0)#node") -- FS17
106
107 local maxUpdateDistance
108 spec.individualUpdateDistance = false
109 spec.speedRotatingParts = {}
110 local i = 0
111 while true do
112 local baseName = string.format("vehicle.speedRotatingParts.speedRotatingPart(%d)", i)
113 if not self.xmlFile:hasProperty(baseName) then
114 break
115 end
116 local speedRotatingPart = {}
117 if self:loadSpeedRotatingPartFromXML(speedRotatingPart, self.xmlFile, baseName) then
118 table.insert(spec.speedRotatingParts, speedRotatingPart)
119
120 if maxUpdateDistance ~= nil and maxUpdateDistance ~= speedRotatingPart.maxUpdateDistance then
121 spec.individualUpdateDistance = true
122 end
123 maxUpdateDistance = speedRotatingPart.maxUpdateDistance
124 end
125 i = i + 1
126 end
127 spec.maxUpdateDistance = maxUpdateDistance or SpeedRotatingParts.DEFAULT_MAX_UPDATE_DISTANCE
128
129 spec.dirtyFlag = self:getNextDirtyFlag()
130
131 if #spec.speedRotatingParts == 0 then
132 SpecializationUtil.removeEventListener(self, "onReadStream", SpeedRotatingParts)
133 SpecializationUtil.removeEventListener(self, "onWriteStream", SpeedRotatingParts)
134 SpecializationUtil.removeEventListener(self, "onReadUpdateStream", SpeedRotatingParts)
135 SpecializationUtil.removeEventListener(self, "onWriteUpdateStream", SpeedRotatingParts)
136 SpecializationUtil.removeEventListener(self, "onUpdate", SpeedRotatingParts)
137 SpecializationUtil.removeEventListener(self, "onUpdateTick", SpeedRotatingParts)
138 end
139end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
145function SpeedRotatingParts:onReadStream(streamId, connection)
146 local spec = self.spec_speedRotatingParts
147 for i=1, #spec.speedRotatingParts do
148 local speedRotatingPart = spec.speedRotatingParts[i]
149 if speedRotatingPart.versatileYRot then
150 local yRot = streamReadUIntN(streamId, 9)
151 speedRotatingPart.steeringAngle = yRot / 511 * math.pi*2
152 end
153 end
154end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
176function SpeedRotatingParts:onReadUpdateStream(streamId, timestamp, connection)
177 if connection.isServer then
178 local hasUpdate = streamReadBool(streamId)
179 if hasUpdate then
180 local spec = self.spec_speedRotatingParts
181 for i=1, #spec.speedRotatingParts do
182 local speedRotatingPart = spec.speedRotatingParts[i]
183 if speedRotatingPart.versatileYRot then
184 local yRot = streamReadUIntN(streamId, 9)
185 speedRotatingPart.steeringAngle = yRot / 511 * math.pi*2
186 end
187 end
188 end
189 end
190end

onUpdate

Description
Called on update
Definition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
217function SpeedRotatingParts:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
218 local spec = self.spec_speedRotatingParts
219
220 if spec.individualUpdateDistance or self.currentUpdateDistance < spec.maxUpdateDistance then
221 for i=1, #spec.speedRotatingParts do
222 local speedRotatingPart = spec.speedRotatingParts[i]
223 if not spec.individualUpdateDistance or self.currentUpdateDistance < speedRotatingPart.maxUpdateDistance then
224 if speedRotatingPart.isActive or (speedRotatingPart.lastSpeed ~= 0 and not speedRotatingPart.stopIfNotActive) then
225 self:updateSpeedRotatingPart(speedRotatingPart, dt, speedRotatingPart.isActive)
226 end
227 end
228 end
229 end
230end

onUpdateTick

Description
Called on update tick
Definition
onUpdateTick(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
237function SpeedRotatingParts:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
238 local spec = self.spec_speedRotatingParts
239
240 if spec.individualUpdateDistance or self.currentUpdateDistance < spec.maxUpdateDistance then
241 for i=1, #spec.speedRotatingParts do
242 local speedRotatingPart = spec.speedRotatingParts[i]
243 if not spec.individualUpdateDistance or self.currentUpdateDistance < speedRotatingPart.maxUpdateDistance then
244 speedRotatingPart.isActive = self:getIsSpeedRotatingPartActive(speedRotatingPart)
245 end
246 end
247 end
248end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
160function SpeedRotatingParts:onWriteStream(streamId, connection)
161 local spec = self.spec_speedRotatingParts
162 for i=1, #spec.speedRotatingParts do
163 local speedRotatingPart = spec.speedRotatingParts[i]
164 if speedRotatingPart.versatileYRot then
165 local yRot = speedRotatingPart.steeringAngle % (math.pi*2)
166 streamWriteUIntN(streamId, MathUtil.clamp(math.floor(yRot / (math.pi*2) * 511), 0, 511), 9)
167 end
168 end
169end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
197function SpeedRotatingParts:onWriteUpdateStream(streamId, connection, dirtyMask)
198 if not connection.isServer then
199 local spec = self.spec_speedRotatingParts
200 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
201 for i=1, #spec.speedRotatingParts do
202 local speedRotatingPart = spec.speedRotatingParts[i]
203 if speedRotatingPart.versatileYRot then
204 local yRot = speedRotatingPart.steeringAngle % (math.pi*2)
205 streamWriteUIntN(streamId, MathUtil.clamp(math.floor(yRot / (math.pi*2) * 511), 0, 511), 9)
206 end
207 end
208 end
209 end
210end

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
20function SpeedRotatingParts.prerequisitesPresent(specializations)
21 return true
22end

registerEventListeners

Description
Definition
registerEventListeners()
Code
89function SpeedRotatingParts.registerEventListeners(vehicleType)
90 SpecializationUtil.registerEventListener(vehicleType, "onLoad", SpeedRotatingParts)
91 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", SpeedRotatingParts)
92 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", SpeedRotatingParts)
93 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", SpeedRotatingParts)
94 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", SpeedRotatingParts)
95 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", SpeedRotatingParts)
96 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", SpeedRotatingParts)
97end

registerFunctions

Description
Definition
registerFunctions()
Code
74function SpeedRotatingParts.registerFunctions(vehicleType)
75 SpecializationUtil.registerFunction(vehicleType, "loadSpeedRotatingPartFromXML", SpeedRotatingParts.loadSpeedRotatingPartFromXML)
76 SpecializationUtil.registerFunction(vehicleType, "getIsSpeedRotatingPartActive", SpeedRotatingParts.getIsSpeedRotatingPartActive)
77 SpecializationUtil.registerFunction(vehicleType, "getSpeedRotatingPartDirection", SpeedRotatingParts.getSpeedRotatingPartDirection)
78 SpecializationUtil.registerFunction(vehicleType, "updateSpeedRotatingPart", SpeedRotatingParts.updateSpeedRotatingPart)
79end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
83function SpeedRotatingParts.registerOverwrittenFunctions(vehicleType)
84 SpecializationUtil.registerOverwrittenFunction(vehicleType, "validateWashableNode", SpeedRotatingParts.validateWashableNode)
85end

updateSpeedRotatingPart

Description
Definition
updateSpeedRotatingPart()
Code
431function SpeedRotatingParts:updateSpeedRotatingPart(speedRotatingPart, dt, isPartActive)
432 local spec = self.spec_speedRotatingParts
433 local speed = speedRotatingPart.lastSpeed
434 local dir = speedRotatingPart.lastDir
435
436 -- use angle from the repr node since the repr node could be rotated by another spec
437 if speedRotatingPart.repr ~= nil then
438 if self.isServer or not speedRotatingPart.versatileYRot then
439 local _
440 _, speedRotatingPart.steeringAngle, _ = getRotation(speedRotatingPart.repr)
441 end
442 end
443
444 if isPartActive then
445 if speedRotatingPart.speedReferenceNode ~= nil then
446 local newX, newY, newZ = getWorldTranslation(speedRotatingPart.speedReferenceNode)
447 if speedRotatingPart.lastPosition == nil then
448 speedRotatingPart.lastPosition = {newX, newY, newZ}
449 end
450
451 local dx, dy, dz = worldDirectionToLocal(speedRotatingPart.speedReferenceNode, newX-speedRotatingPart.lastPosition[1], newY-speedRotatingPart.lastPosition[2], newZ-speedRotatingPart.lastPosition[3])
452 speed = MathUtil.vector3Length(dx, dy, dz)
453
454 if dz > 0.001 then
455 dir = 1
456 elseif dz < -0.001 then
457 dir = -1
458 else
459 dir = 0
460 end
461
462 speedRotatingPart.lastPosition[1], speedRotatingPart.lastPosition[2], speedRotatingPart.lastPosition[3] = newX, newY, newZ
463 elseif speedRotatingPart.wheel ~= nil then
464 if speedRotatingPart.lastWheelXRot == nil then
465 speedRotatingPart.lastWheelXRot = speedRotatingPart.wheel.netInfo.xDrive
466 end
467
468 local rotDiff = speedRotatingPart.wheel.netInfo.xDrive - speedRotatingPart.lastWheelXRot
469 if rotDiff > math.pi then
470 rotDiff = rotDiff - (2*math.pi)
471 elseif rotDiff < -math.pi then
472 rotDiff = rotDiff + (2*math.pi)
473 end
474 speed = math.abs(rotDiff)
475 dir = MathUtil.sign(rotDiff)
476 speedRotatingPart.lastWheelXRot = speedRotatingPart.wheel.netInfo.xDrive
477
478 if not speedRotatingPart.versatileYRot then
479 local _
480 _, speedRotatingPart.steeringAngle, _ = getRotation(speedRotatingPart.wheel.repr)
481 end
482 else
483 speed = self.lastSpeedReal * dt
484 dir = self.movingDirection
485 end
486 speedRotatingPart.brakeForce = speed * dt/speedRotatingPart.fadeOutTime
487 else
488 speed = math.max(speed - speedRotatingPart.brakeForce, 0)
489 speedRotatingPart.lastWheelXRot = nil
490 end
491
492 speedRotatingPart.lastSpeed = speed
493 speedRotatingPart.lastDir = dir
494 if speedRotatingPart.updateXDrive then
495 speedRotatingPart.xDrive = (speedRotatingPart.xDrive + speed * dir * self:getSpeedRotatingPartDirection(speedRotatingPart) * speedRotatingPart.wheelScale) % (2*math.pi)
496 end
497
498 if speedRotatingPart.versatileYRot then
499 if speed > 0.0017 then -- 0.1deg threshold cause float accuracy
500 if self.isServer and self:getLastSpeed(true) > speedRotatingPart.activationSpeed then
501 local posX, posY, posZ = localToLocal(speedRotatingPart.repr, speedRotatingPart.componentNode, 0,0,0)
502 speedRotatingPart.steeringAngle = Utils.getVersatileRotation(speedRotatingPart.repr, speedRotatingPart.componentNode, dt, posX, posY, posZ, speedRotatingPart.steeringAngle, speedRotatingPart.minYRot, speedRotatingPart.maxYRot)
503
504 local steeringAngleSent = math.floor((speedRotatingPart.steeringAngle % (math.pi*2)) / (math.pi*2) * 511)
505 if steeringAngleSent ~= speedRotatingPart.steeringAngleSent then
506 speedRotatingPart.steeringAngleSent = steeringAngleSent
507 self:raiseDirtyFlags(spec.dirtyFlag)
508 end
509 end
510 end
511 else
512 if speedRotatingPart.componentNode ~= nil and speedRotatingPart.dirRefNode ~= nil and not speedRotatingPart.alignDirection then
513 speedRotatingPart.steeringAngle = Utils.getYRotationBetweenNodes(speedRotatingPart.componentNode, speedRotatingPart.dirRefNode)
514 local _,yTrans,_ = localToLocal(speedRotatingPart.driveNode, speedRotatingPart.wheel.driveNode, 0, 0, 0)
515 setTranslation(speedRotatingPart.driveNode, 0, yTrans, 0)
516 end
517
518 if speedRotatingPart.dirRefNode ~= nil and speedRotatingPart.alignDirection then
519 local upX, upY, upZ = localDirectionToWorld(speedRotatingPart.dirFrameNode, 0, 1, 0)
520 local dirX, dirY, dirZ = localDirectionToWorld(speedRotatingPart.dirRefNode, 0, 0, 1)
521 I3DUtil.setWorldDirection(speedRotatingPart.repr, dirX, dirY, dirZ, upX, upY, upZ, 2)
522 if speedRotatingPart.wheel ~= nil and speedRotatingPart.useWheelReprTranslation then
523 local _,yTrans,_ = localToLocal(speedRotatingPart.wheel.driveNode, getParent(speedRotatingPart.repr), 0,0,0)
524 setTranslation(speedRotatingPart.repr, 0, yTrans, 0)
525 end
526 end
527 end
528
529 if speedRotatingPart.driveNode ~= nil then
530 if speedRotatingPart.repr == speedRotatingPart.driveNode then
531 local steeringAngle = speedRotatingPart.steeringAngle
532 if not speedRotatingPart.applySteeringAngle then
533 steeringAngle = 0
534 end
535
536 setRotation(speedRotatingPart.repr, speedRotatingPart.xDrive, steeringAngle, 0)
537 else
538 if not speedRotatingPart.alignDirection and (speedRotatingPart.versatileYRot or speedRotatingPart.applySteeringAngle) then
539 setRotation(speedRotatingPart.repr, 0, speedRotatingPart.steeringAngle, 0)
540 end
541 setRotation(speedRotatingPart.driveNode, speedRotatingPart.xDrive, 0, 0)
542 end
543 end
544
545 if speedRotatingPart.shaderNode ~= nil then
546 if speedRotatingPart.useShaderRotation then
547 local values = speedRotatingPart.shaderParameterValues
548 if speedRotatingPart.scrollLength ~= nil then
549 values[speedRotatingPart.shaderParameterComponent] = (speedRotatingPart.xDrive * speedRotatingPart.shaderParameterSpeedScale) % speedRotatingPart.scrollLength
550 else
551 values[speedRotatingPart.shaderParameterComponent] = (speedRotatingPart.xDrive * speedRotatingPart.shaderParameterSpeedScale)
552 end
553
554 if speedRotatingPart.shaderParameterPrevName ~= nil then
555 g_animationManager:setPrevShaderParameter(speedRotatingPart.shaderNode, speedRotatingPart.shaderParameterName, values[1], values[2], values[3], values[4], false, speedRotatingPart.shaderParameterPrevName)
556 else
557 setShaderParameter(speedRotatingPart.shaderNode, speedRotatingPart.shaderParameterName, values[1], values[2], values[3], values[4], false)
558 end
559 else
560 local pos = (speedRotatingPart.xDrive % math.pi) / (2*math.pi) -- normalize rotation
561 setShaderParameter(speedRotatingPart.shaderNode, "offsetUV", pos*speedRotatingPart.scrollScale[1], pos*speedRotatingPart.scrollScale[2], 0, 0, false)
562 end
563 end
564end

validateWashableNode

Description
Definition
validateWashableNode()
Code
568function SpeedRotatingParts:validateWashableNode(superFunc, node)
569 local spec = self.spec_speedRotatingParts
570 for _, speedRotatingPart in pairs(spec.speedRotatingParts) do
571 if speedRotatingPart.wheel ~= nil then
572 local speedRotatingPartsNodes = {}
573
574 if speedRotatingPart.repr ~= nil then
575 I3DUtil.getNodesByShaderParam(speedRotatingPart.repr, "RDT", speedRotatingPartsNodes)
576 end
577
578 if speedRotatingPart.shaderNode ~= nil then
579 I3DUtil.getNodesByShaderParam(speedRotatingPart.shaderNode, "RDT", speedRotatingPartsNodes)
580 end
581
582 if speedRotatingPart.driveNode ~= nil then
583 I3DUtil.getNodesByShaderParam(speedRotatingPart.driveNode, "RDT", speedRotatingPartsNodes)
584 end
585
586 if speedRotatingPartsNodes[node] ~= nil then
587 local nodeData = {}
588 nodeData.wheel = speedRotatingPart.wheel
589 nodeData.fieldDirtMultiplier = speedRotatingPart.wheel.fieldDirtMultiplier
590 nodeData.streetDirtMultiplier = speedRotatingPart.wheel.streetDirtMultiplier
591 nodeData.minDirtPercentage = speedRotatingPart.wheel.minDirtPercentage
592 nodeData.maxDirtOffset = speedRotatingPart.wheel.maxDirtOffset
593 nodeData.dirtColorChangeSpeed = speedRotatingPart.wheel.dirtColorChangeSpeed
594 nodeData.isSnowNode = true
595
596 return false, self.updateWheelDirtAmount, speedRotatingPart.wheel, nodeData
597 end
598 end
599 end
600
601 return superFunc(self, node)
602end