LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Washable

Description
Specialization for vehicles which can get dirty and be cleaned by a pressure washer
Functions

addAllSubWashableNodes

Description
Definition
addAllSubWashableNodes()
Code
357function Washable:addAllSubWashableNodes(rootNode)
358 if rootNode ~= nil then
359 local nodes = {}
360 I3DUtil.getNodesByShaderParam(rootNode, "RDT", nodes, true)
361 self:addWashableNodes(nodes)
362 end
363
364 -- if we are done with adding new nodes we apply the last dirt amount to all nodes
365 self:addDirtAmount(0, true)
366end

addDirtAmount

Description
Definition
addDirtAmount()
Code
287function Washable:addDirtAmount(dirtAmount, force)
288 local spec = self.spec_washable
289 for i=1, #spec.washableNodes do
290 local nodeData = spec.washableNodes[i]
291 self:setNodeDirtAmount(nodeData, nodeData.dirtAmount + dirtAmount, force)
292 end
293end

addToGlobalWashableNode

Description
Definition
addToGlobalWashableNode()
Code
389function Washable:addToGlobalWashableNode(node)
390 local spec = self.spec_washable
391 if spec.washableNodes[1] ~= nil then
392 table.insert(spec.washableNodes[1].nodes, node)
393 end
394end

addToLocalWashableNode

Description
Definition
addToLocalWashableNode()
Code
404function Washable:addToLocalWashableNode(node, updateFunc, customIndex, extraParams)
405 local spec = self.spec_washable
406
407 local nodeData = {}
408
409 --if washableNode already exists we add node to existing washableNode
410 if customIndex ~= nil then
411 if spec.washableNodesByIndex[customIndex] ~= nil then
412 table.insert(spec.washableNodesByIndex[customIndex].nodes, node)
413 return
414 else
415 spec.washableNodesByIndex[customIndex] = nodeData
416 end
417 end
418
419 --if washableNode doesn't exists we create a new one
420 nodeData.nodes = {node}
421 nodeData.updateFunc = updateFunc
422 nodeData.dirtAmount = 0
423 nodeData.dirtAmountSent = 0
424
425 nodeData.colorChanged = false
426 local defaultColor, _ = g_currentMission.environment:getDirtColors()
427 nodeData.color = {defaultColor[1], defaultColor[2], defaultColor[3]}
428 nodeData.defaultColor = {defaultColor[1], defaultColor[2], defaultColor[3]}
429
430 if extraParams ~= nil then
431 for i, v in pairs(extraParams) do
432 nodeData[i] = v
433 end
434 end
435
436 table.insert(spec.washableNodes, nodeData)
437end

addWashableNodes

Description
Definition
addWashableNodes()
Code
370function Washable:addWashableNodes(nodes)
371 for _, node in ipairs(nodes) do
372 local isGlobal, updateFunc, customIndex, extraParams = self:validateWashableNode(node)
373 if isGlobal then
374 self:addToGlobalWashableNode(node)
375 elseif updateFunc ~= nil then
376 self:addToLocalWashableNode(node, updateFunc, customIndex, extraParams)
377 end
378 end
379end

getAllowsWashingByType

Description
Definition
getAllowsWashingByType()
Code
518function Washable:getAllowsWashingByType(type)
519 local spec = self.spec_washable
520 return spec.blockedWashTypes[type] == nil
521end

getDirtAmount

Description
Definition
getDirtAmount()
Code
297function Washable:getDirtAmount()
298 local spec = self.spec_washable
299 local dirtAmount = 0
300 for i=1, #spec.washableNodes do
301 dirtAmount = dirtAmount + spec.washableNodes[i].dirtAmount
302 end
303 dirtAmount = dirtAmount / #spec.washableNodes
304
305 return dirtAmount
306end

getDirtMultiplier

Description
Definition
getDirtMultiplier()
Code
466function Washable:getDirtMultiplier()
467 local spec = self.spec_washable
468
469 local multiplier = 1
470 if self:getLastSpeed() < 1 then
471 multiplier = 0
472 end
473
474 if self:getIsOnField() then
475 multiplier = multiplier * spec.fieldMultiplier
476
477 local wetness = g_currentMission.environment.weather:getGroundWetness()
478 if wetness > 0 then
479 multiplier = multiplier * (1 + wetness)
480 end
481 end
482
483 return multiplier
484end

getIntervalMultiplier

Description
Definition
getIntervalMultiplier()
Code
504function Washable.getIntervalMultiplier()
505 if g_currentMission.missionInfo.dirtInterval == 1 then
506 return 0
507 elseif g_currentMission.missionInfo.dirtInterval == 2 then
508 return 0.25
509 elseif g_currentMission.missionInfo.dirtInterval == 3 then
510 return 0.5
511 elseif g_currentMission.missionInfo.dirtInterval == 4 then
512 return 1
513 end
514end

getNodeDirtAmount

Description
Definition
getNodeDirtAmount()
Code
331function Washable:getNodeDirtAmount(nodeData)
332 return nodeData.dirtAmount
333end

getWashableNodeByCustomIndex

Description
Definition
getWashableNodeByCustomIndex()
Code
398function Washable:getWashableNodeByCustomIndex(customIndex)
399 return self.spec_washable.washableNodesByIndex[customIndex]
400end

getWashDuration

Description
Definition
getWashDuration()
Code
496function Washable:getWashDuration()
497 local spec = self.spec_washable
498
499 return spec.washDuration
500end

getWorkDirtMultiplier

Description
Definition
getWorkDirtMultiplier()
Code
488function Washable:getWorkDirtMultiplier()
489 local spec = self.spec_washable
490
491 return spec.workMultiplier
492end

initSpecialization

Description
Definition
initSpecialization()
Code
30function Washable.initSpecialization()
31 local schema = Vehicle.xmlSchema
32 schema:setXMLSpecializationType("Washable")
33 schema:register(XMLValueType.FLOAT, "vehicle.washable#dirtDuration", "Duration until fully dirty (minutes)", 90)
34 schema:register(XMLValueType.FLOAT, "vehicle.washable#washDuration", "Duration until fully clean (minutes)", 1)
35 schema:register(XMLValueType.FLOAT, "vehicle.washable#workMultiplier", "Multiplier while working", 4)
36 schema:register(XMLValueType.FLOAT, "vehicle.washable#fieldMultiplier", "Multiplier while on field", 2)
37 schema:register(XMLValueType.STRING, "vehicle.washable#blockedWashTypes", "Block specific ways to clean vehicle (HIGH_PRESSURE_WASHER, RAIN, TRIGGER)")
38 schema:setXMLSpecializationType()
39
40 local schemaSavegame = Vehicle.xmlSchemaSavegame
41 schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).washable.dirtNode(?)#amount", "Dirt amount")
42 schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).washable.dirtNode(?)#snowScale", "Snow scale")
43end

onLoad

Description
Definition
onLoad()
Code
82function Washable:onLoad(savegame)
83 local spec = self.spec_washable
84
85 spec.washableNodes = {}
86 spec.washableNodesByIndex = {}
87 self:addToLocalWashableNode(nil, Washable.updateDirtAmount, nil, nil) -- create global / default washableNode
88 spec.globalWashableNode = spec.washableNodes[1]
89
90 spec.dirtDuration = self.xmlFile:getValue("vehicle.washable#dirtDuration", 90) * 60 * 1000
91 if spec.dirtDuration ~= 0 then
92 spec.dirtDuration = 1 / spec.dirtDuration
93 end
94
95 spec.washDuration = math.max(self.xmlFile:getValue("vehicle.washable#washDuration", 1) * 60 * 1000, 0.00001) -- washDuration == 0 washes vehicle immediately
96
97 spec.workMultiplier = self.xmlFile:getValue("vehicle.washable#workMultiplier", 4)
98 spec.fieldMultiplier = self.xmlFile:getValue("vehicle.washable#fieldMultiplier", 2)
99
100 spec.blockedWashTypes = {}
101 local blockedWashTypesStr = self.xmlFile:getValue("vehicle.washable#blockedWashTypes")
102 if blockedWashTypesStr ~= nil then
103 local blockedWashTypes = blockedWashTypesStr:split(" ")
104 for _, typeStr in pairs(blockedWashTypes) do
105 typeStr = "WASHTYPE_" .. typeStr
106 if Washable[typeStr] ~= nil then
107 spec.blockedWashTypes[Washable[typeStr]] = true
108 else
109 Logging.xmlWarning(self.xmlFile, "Unknown wash type '%s' in '%s'", typeStr, "vehicle.washable#blockedWashTypes")
110 end
111 end
112 end
113
114 spec.lastDirtMultiplier = 0
115
116 spec.dirtyFlag = self:getNextDirtyFlag()
117end

onLoadFinished

Description
Definition
onLoadFinished()
Code
121function Washable:onLoadFinished(savegame)
122 local spec = self.spec_washable
123
124 -- getting als washable nodes in postLoad to make sure also linked nodes are washable
125 for _, component in pairs(self.components) do
126 self:addAllSubWashableNodes(component.node)
127 end
128
129 if savegame ~= nil and Washable.getIntervalMultiplier() ~= 0 then
130 for i=1, #spec.washableNodes do
131 local nodeData = spec.washableNodes[i]
132 local nodeKey = string.format("%s.washable.dirtNode(%d)", savegame.key, i-1)
133 local amount = savegame.xmlFile:getValue(nodeKey.."#amount", 0)
134 self:setNodeDirtAmount(nodeData, amount, true)
135
136 if nodeData.loadFromSavegameFunc ~= nil then
137 nodeData.loadFromSavegameFunc(savegame.xmlFile, nodeKey)
138 end
139 end
140 else
141 for i=1, #spec.washableNodes do
142 local nodeData = spec.washableNodes[i]
143 self:setNodeDirtAmount(nodeData, 0, true)
144 end
145 end
146end

onReadStream

Description
Definition
onReadStream()
Code
166function Washable:onReadStream(streamId, connection)
167 Washable.readWashableNodeData(self, streamId, connection)
168end

onReadUpdateStream

Description
Definition
onReadUpdateStream()
Code
178function Washable:onReadUpdateStream(streamId, timestamp, connection)
179 if connection:getIsServer() then
180 local spec = self.spec_washable
181 if spec.washableNodes ~= nil then
182 if streamReadBool(streamId) then
183 Washable.readWashableNodeData(self, streamId, connection)
184 end
185 end
186 end
187end

onUpdateTick

Description
Definition
onUpdateTick()
Code
239function Washable:onUpdateTick(dt, isActive, isActiveForInput, isSelected)
240 if self.isServer then
241 local spec = self.spec_washable
242 spec.lastDirtMultiplier = self:getDirtMultiplier() * Washable.getIntervalMultiplier() * Platform.gameplay.dirtDurationScale
243
244 local allowsWashingByRain = self:getAllowsWashingByType(Washable.WASHTYPE_RAIN)
245 local rainScale, timeSinceLastRain, temperature = 0, 0, 0
246 if allowsWashingByRain then
247 local weather = g_currentMission.environment.weather
248 rainScale = weather:getRainFallScale()
249 timeSinceLastRain = weather:getTimeSinceLastRain()
250 temperature = weather:getCurrentTemperature()
251 end
252
253 for i=1, #spec.washableNodes do
254 local nodeData = spec.washableNodes[i]
255 local changedAmount = nodeData.updateFunc(self, nodeData, dt, allowsWashingByRain, rainScale, timeSinceLastRain, temperature)
256 if changedAmount ~= 0 then
257 self:setNodeDirtAmount(nodeData, nodeData.dirtAmount + changedAmount)
258 end
259 end
260 end
261end

onWriteStream

Description
Definition
onWriteStream()
Code
172function Washable:onWriteStream(streamId, connection)
173 Washable.writeWashableNodeData(self, streamId, connection)
174end

onWriteUpdateStream

Description
Definition
onWriteUpdateStream()
Code
191function Washable:onWriteUpdateStream(streamId, connection, dirtyMask)
192 if not connection:getIsServer() then
193 local spec = self.spec_washable
194 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
195 Washable.writeWashableNodeData(self, streamId, connection)
196 end
197 end
198end

prerequisitesPresent

Description
Definition
prerequisitesPresent()
Code
24function Washable.prerequisitesPresent(specializations)
25 return true
26end

readWashableNodeData

Description
Definition
readWashableNodeData()
Code
202function Washable.readWashableNodeData(self, streamId, connection)
203 local spec = self.spec_washable
204 for i=1, #spec.washableNodes do
205 local nodeData = spec.washableNodes[i]
206 local dirtAmount = streamReadUIntN(streamId, Washable.SEND_NUM_BITS) / Washable.SEND_MAX_VALUE
207 self:setNodeDirtAmount(nodeData, dirtAmount, true)
208
209 if streamReadBool(streamId) then
210 local r = streamReadUIntN(streamId, Washable.SEND_NUM_BITS) / Washable.SEND_MAX_VALUE
211 local g = streamReadUIntN(streamId, Washable.SEND_NUM_BITS) / Washable.SEND_MAX_VALUE
212 local b = streamReadUIntN(streamId, Washable.SEND_NUM_BITS) / Washable.SEND_MAX_VALUE
213
214 self:setNodeDirtColor(nodeData, r, g, b, true)
215 end
216 end
217end

registerEventListeners

Description
Definition
registerEventListeners()
Code
70function Washable.registerEventListeners(vehicleType)
71 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Washable)
72 SpecializationUtil.registerEventListener(vehicleType, "onLoadFinished", Washable)
73 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Washable)
74 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Washable)
75 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Washable)
76 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Washable)
77 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Washable)
78end

registerFunctions

Description
Definition
registerFunctions()
Code
47function Washable.registerFunctions(vehicleType)
48 SpecializationUtil.registerFunction(vehicleType, "updateDirtAmount", Washable.updateDirtAmount)
49 SpecializationUtil.registerFunction(vehicleType, "addDirtAmount", Washable.addDirtAmount)
50 SpecializationUtil.registerFunction(vehicleType, "getDirtAmount", Washable.getDirtAmount)
51 SpecializationUtil.registerFunction(vehicleType, "setNodeDirtAmount", Washable.setNodeDirtAmount)
52 SpecializationUtil.registerFunction(vehicleType, "getNodeDirtAmount", Washable.getNodeDirtAmount)
53 SpecializationUtil.registerFunction(vehicleType, "setNodeDirtColor", Washable.setNodeDirtColor)
54 SpecializationUtil.registerFunction(vehicleType, "addAllSubWashableNodes", Washable.addAllSubWashableNodes)
55 SpecializationUtil.registerFunction(vehicleType, "addWashableNodes", Washable.addWashableNodes)
56 SpecializationUtil.registerFunction(vehicleType, "validateWashableNode", Washable.validateWashableNode)
57 SpecializationUtil.registerFunction(vehicleType, "addToGlobalWashableNode", Washable.addToGlobalWashableNode)
58 SpecializationUtil.registerFunction(vehicleType, "getWashableNodeByCustomIndex", Washable.getWashableNodeByCustomIndex)
59 SpecializationUtil.registerFunction(vehicleType, "addToLocalWashableNode", Washable.addToLocalWashableNode)
60 SpecializationUtil.registerFunction(vehicleType, "removeAllSubWashableNodes", Washable.removeAllSubWashableNodes)
61 SpecializationUtil.registerFunction(vehicleType, "removeWashableNode", Washable.removeWashableNode)
62 SpecializationUtil.registerFunction(vehicleType, "getDirtMultiplier", Washable.getDirtMultiplier)
63 SpecializationUtil.registerFunction(vehicleType, "getWorkDirtMultiplier", Washable.getWorkDirtMultiplier)
64 SpecializationUtil.registerFunction(vehicleType, "getWashDuration", Washable.getWashDuration)
65 SpecializationUtil.registerFunction(vehicleType, "getAllowsWashingByType", Washable.getAllowsWashingByType)
66end

removeAllSubWashableNodes

Description
Definition
removeAllSubWashableNodes()
Code
441function Washable:removeAllSubWashableNodes(rootNode)
442 if rootNode ~= nil then
443 local nodes = {}
444 I3DUtil.getNodesByShaderParam(rootNode, "RDT", nodes)
445 for _, node in pairs(nodes) do
446 self:removeWashableNode(node)
447 end
448 end
449end

removeWashableNode

Description
Definition
removeWashableNode()
Code
453function Washable:removeWashableNode(node)
454 local spec = self.spec_washable
455
456 if node ~= nil then
457 for i=1, #spec.washableNodes do
458 local nodeData = spec.washableNodes[i]
459 table.removeElement(nodeData.nodes, node)
460 end
461 end
462end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
150function Washable:saveToXMLFile(xmlFile, key, usedModNames)
151 local spec = self.spec_washable
152
153 for i=1, #spec.washableNodes do
154 local nodeData = spec.washableNodes[i]
155 local nodeKey = string.format("%s.dirtNode(%d)", key, i-1)
156 xmlFile:setValue(nodeKey.."#amount", nodeData.dirtAmount)
157
158 if nodeData.saveToSavegameFunc ~= nil then
159 nodeData.saveToSavegameFunc(xmlFile, nodeKey)
160 end
161 end
162end

setNodeDirtAmount

Description
Definition
setNodeDirtAmount()
Code
310function Washable:setNodeDirtAmount(nodeData, dirtAmount, force)
311 local spec = self.spec_washable
312 nodeData.dirtAmount = MathUtil.clamp(dirtAmount, 0, 1)
313
314 local diff = nodeData.dirtAmountSent - nodeData.dirtAmount
315 if math.abs(diff) > Washable.SEND_THRESHOLD or force then
316 for i=1, #nodeData.nodes do
317 local node = nodeData.nodes[i]
318 local x, _, z, w = getShaderParameter(node, "RDT")
319 setShaderParameter(node, "RDT", x, nodeData.dirtAmount, 0, w, false)
320 end
321
322 if self.isServer then
323 self:raiseDirtyFlags(spec.dirtyFlag)
324 nodeData.dirtAmountSent = nodeData.dirtAmount
325 end
326 end
327end

setNodeDirtColor

Description
Definition
setNodeDirtColor()
Code
337function Washable:setNodeDirtColor(nodeData, r, g, b, force)
338 local spec = self.spec_washable
339 local cr, cg, cb = nodeData.color[1], nodeData.color[2], nodeData.color[3]
340 if (math.abs(r-cr) > Washable.SEND_THRESHOLD or math.abs(g-cg) > Washable.SEND_THRESHOLD or math.abs(b-cb) > Washable.SEND_THRESHOLD) or force then
341 for _, node in pairs(nodeData.nodes) do
342 local _, _, _, w = getShaderParameter(node, "dirtColor")
343 setShaderParameter(node, "dirtColor", r, g, b, w, false)
344 end
345
346 nodeData.color[1], nodeData.color[2], nodeData.color[3] = r, g, b
347
348 if self.isServer then
349 self:raiseDirtyFlags(spec.dirtyFlag)
350 nodeData.colorChanged = true
351 end
352 end
353end

updateDebugValues

Description
Definition
updateDebugValues()
Code
525function Washable:updateDebugValues(values)
526 local spec = self.spec_washable
527 if spec.washableNodes ~= nil then
528 local allowsWashingByRain = self:getAllowsWashingByType(Washable.WASHTYPE_RAIN)
529 local rainScale, timeSinceLastRain, temperature = 0, 0, 0
530 if allowsWashingByRain then
531 local weather = g_currentMission.environment.weather
532 rainScale = weather:getRainFallScale()
533 timeSinceLastRain = weather:getTimeSinceLastRain()
534 temperature = weather:getCurrentTemperature()
535 end
536
537 for i, nodeData in ipairs(spec.washableNodes) do
538 local changedAmount = nodeData.updateFunc(self, nodeData, 3600000, allowsWashingByRain, rainScale, timeSinceLastRain, temperature)
539 table.insert(values, {name="WashableNode"..i, value=string.format("%.4f a/h (%.2f) (color %.2f %.2f %.2f)", changedAmount, spec.washableNodes[i].dirtAmount, nodeData.color[1], nodeData.color[2], nodeData.color[3])})
540 end
541 end
542end

updateDirtAmount

Description
Definition
updateDirtAmount()
Code
265function Washable:updateDirtAmount(nodeData, dt, allowsWashingByRain, rainScale, timeSinceLastRain, temperature)
266 local spec = self.spec_washable
267 local change = 0
268
269 if allowsWashingByRain then
270 if rainScale > 0.1 and timeSinceLastRain < 30 and temperature > 0 then
271 if nodeData.dirtAmount > 0.5 then
272 change = -(dt / spec.washDuration)
273 end
274 end
275 end
276
277 local dirtMultiplier = spec.lastDirtMultiplier
278 if dirtMultiplier ~= 0 then
279 change = dt * spec.dirtDuration * dirtMultiplier
280 end
281
282 return change
283end

validateWashableNode

Description
Definition
validateWashableNode()
Code
383function Washable:validateWashableNode(node)
384 return true, nil -- by default all nodes are global
385end

writeWashableNodeData

Description
Definition
writeWashableNodeData()
Code
221function Washable.writeWashableNodeData(self, streamId, connection)
222 local spec = self.spec_washable
223 for i=1, #spec.washableNodes do
224 local nodeData = spec.washableNodes[i]
225 streamWriteUIntN(streamId, math.floor(nodeData.dirtAmount * Washable.SEND_MAX_VALUE + 0.5), Washable.SEND_NUM_BITS)
226
227 streamWriteBool(streamId, nodeData.colorChanged)
228 if nodeData.colorChanged then
229 streamWriteUIntN(streamId, math.floor(nodeData.color[1] * Washable.SEND_MAX_VALUE + 0.5), Washable.SEND_NUM_BITS)
230 streamWriteUIntN(streamId, math.floor(nodeData.color[2] * Washable.SEND_MAX_VALUE + 0.5), Washable.SEND_NUM_BITS)
231 streamWriteUIntN(streamId, math.floor(nodeData.color[3] * Washable.SEND_MAX_VALUE + 0.5), Washable.SEND_NUM_BITS)
232 nodeData.colorChanged = false
233 end
234 end
235end