LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Wearable

Description
Specialization allowing vehicles to wear off (with visual and funcional consequences) and be repaired again
Functions

addAllSubWearableNodes

Description
Definition
addAllSubWearableNodes()
Code
482function Wearable:addAllSubWearableNodes(rootNode)
483 if rootNode ~= nil then
484 local nodes = {}
485 I3DUtil.getNodesByShaderParam(rootNode, "RDT", nodes)
486 self:addWearableNodes(nodes)
487 end
488end

addDamageAmount

Description
Definition
addDamageAmount()
Code
343function Wearable:addDamageAmount(amount, force)
344 local spec = self.spec_wearable
345 self:setDamageAmount(spec.damage + amount, force)
346end

addToGlobalWearableNode

Description
Definition
addToGlobalWearableNode()
Code
511function Wearable:addToGlobalWearableNode(node)
512 local spec = self.spec_wearable
513 if spec.wearableNodes[1] ~= nil then
514 table.insert(spec.wearableNodes[1].nodes, node)
515 end
516end

addToLocalWearableNode

Description
Definition
addToLocalWearableNode()
Code
520function Wearable:addToLocalWearableNode(node, updateFunc, customIndex, extraParams)
521 local spec = self.spec_wearable
522
523 local nodeData = {}
524
525 --if wearableNode already exists we add node to existing wearableNode
526 if customIndex ~= nil then
527 if spec.wearableNodesByIndex[customIndex] ~= nil then
528 table.insert(spec.wearableNodesByIndex[customIndex].nodes, node)
529 return
530 else
531 spec.wearableNodesByIndex[customIndex] = nodeData
532 end
533 end
534
535 --if wearableNode doesn't exists we create a new one
536 nodeData.nodes = {node}
537 nodeData.updateFunc = updateFunc
538 nodeData.wearAmount = 0
539 nodeData.wearAmountSent = 0
540 if extraParams ~= nil then
541 for i, v in pairs(extraParams) do
542 nodeData[i] = v
543 end
544 end
545
546 table.insert(spec.wearableNodes, nodeData)
547end

addWearableNodes

Description
Definition
addWearableNodes()
Code
492function Wearable:addWearableNodes(nodes)
493 for _, node in pairs(nodes) do
494 local isGlobal, updateFunc, customIndex, extraParams = self:validateWearableNode(node)
495 if isGlobal then
496 self:addToGlobalWearableNode(node)
497 elseif updateFunc ~= nil then
498 self:addToLocalWearableNode(node, updateFunc, customIndex, extraParams)
499 end
500 end
501end

addWearAmount

Description
Definition
addWearAmount()
Code
332function Wearable:addWearAmount(wearAmount, force)
333 local spec = self.spec_wearable
334 if spec.wearableNodes ~= nil then
335 for _, nodeData in ipairs(spec.wearableNodes) do
336 self:setNodeWearAmount(nodeData, self:getNodeWearAmount(nodeData) + wearAmount, force)
337 end
338 end
339end

calculateRepaintPrice

Description
Also used by the sale system
Definition
calculateRepaintPrice()
Code
470function Wearable.calculateRepaintPrice(price, wear)
471 return price * math.sqrt(wear / 100) * 2
472end

calculateRepairPrice

Description
Also used by the sale system
Definition
calculateRepairPrice()
Code
444function Wearable.calculateRepairPrice(price, damage)
445 -- up to 9% of the price at full damage
446 -- repairing more often at low damages is rewarded - repairing always at 10% saves about half of the repair price
447 return price * math.pow(damage, 1.5) * 0.09
448end

getDamageAmount

Description
Get the amount of damage this vehicle has.
Definition
getDamageAmount()
Return Values
numbertotal
Code
391function Wearable:getDamageAmount()
392 return self.spec_wearable.damage
393end

getDamageShowOnHud

Description
Returns if the damage should be visualized on the hud
Definition
getDamageShowOnHud()
Return Values
booleanshowOnHudshow damage on hud
Code
398function Wearable:getDamageShowOnHud()
399 return self.spec_wearable.showOnHud
400end

getNodeWearAmount

Description
Definition
getNodeWearAmount()
Code
377function Wearable:getNodeWearAmount(nodeData)
378 return nodeData.wearAmount
379end

getRepaintPrice

Description
Definition
getRepaintPrice()
Code
452function Wearable:getRepaintPrice(superFunc)
453 return superFunc(self) + Wearable.calculateRepaintPrice(self:getPrice() ,self:getWearTotalAmount())
454end

getRepairPrice

Description
Get the price of a repair
Definition
getRepairPrice()
Code
437function Wearable:getRepairPrice(superFunc)
438 return superFunc(self) + Wearable.calculateRepairPrice(self:getPrice(), self.spec_wearable.damage)
439end

getSpecValueCondition

Description
Definition
getSpecValueCondition()
Code
616function Wearable.getSpecValueCondition(storeItem, realItem)
617 if realItem == nil then
618 return nil
619 end
620
621 return string.format("%d%%", realItem:getDamageAmount() * 100)
622end

getUsageCausesDamage

Description
Damage causes lower performance which impacts mission results.
Definition
getUsageCausesDamage()
Code
320function Wearable:getUsageCausesDamage()
321 if self.spec_motorized == nil then
322 if getIsSleeping(self.rootNode) then
323 return false
324 end
325 end
326
327 return self.isActive and self.propertyState ~= Vehicle.PROPERTY_STATE_MISSION
328end

getUsageCausesWear

Description
Definition
getUsageCausesWear()
Code
314function Wearable:getUsageCausesWear()
315 return true
316end

getVehicleDamage

Description
Get damage: affects how well the machine works
Definition
getVehicleDamage()
Code
476function Wearable:getVehicleDamage(superFunc)
477 return math.min(superFunc(self) + self.spec_wearable.damageByCurve, 1)
478end

getWearMultiplier

Description
Get wear multiplier
Definition
getWearMultiplier()
Return Values
numbermultiplier
Code
565function Wearable:getWearMultiplier()
566 local spec = self.spec_wearable
567
568 local multiplier = 1
569 if self:getLastSpeed() < 1 then
570 multiplier = 0
571 end
572
573 if self:getIsOnField() then
574 multiplier = multiplier * spec.fieldMultiplier
575 end
576
577 return multiplier
578end

getWearTotalAmount

Description
Get the total wear
Definition
getWearTotalAmount()
Return Values
numbertotal
Code
384function Wearable:getWearTotalAmount()
385 return self.spec_wearable.totalAmount
386end

getWorkWearMultiplier

Description
Get work wear multiplier
Definition
getWorkWearMultiplier()
Return Values
numbermultiplier
Code
583function Wearable:getWorkWearMultiplier()
584 local spec = self.spec_wearable
585
586 return spec.workMultiplier
587end

initSpecialization

Description
Definition
initSpecialization()
Code
34function Wearable.initSpecialization()
35 g_storeManager:addSpecType("wearable", "shopListAttributeIconCondition", Wearable.loadSpecValueCondition, Wearable.getSpecValueCondition, "vehicle")
36
37 local schema = Vehicle.xmlSchema
38 schema:setXMLSpecializationType("Wearable")
39
40 schema:register(XMLValueType.FLOAT, "vehicle.wearable#wearDuration", "Duration until fully worn (minutes)", 600)
41 schema:register(XMLValueType.FLOAT, "vehicle.wearable#workMultiplier", "Multiplier while working", 20)
42 schema:register(XMLValueType.FLOAT, "vehicle.wearable#fieldMultiplier", "Multiplier while on field", 2)
43 schema:register(XMLValueType.BOOL, "vehicle.wearable#showOnHud", "Show the damage on the hud", true)
44
45 schema:setXMLSpecializationType()
46
47 local schemaSavegame = Vehicle.xmlSchemaSavegame
48 schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).wearable.wearNode(?)#amount", "Wear amount")
49 schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).wearable#damage", "Damage amount")
50end

loadSpecValueCondition

Description
Definition
loadSpecValueCondition()
Code
609function Wearable.loadSpecValueCondition(xmlFile, customEnvironment, baseDir)
610 -- No data to load as this spec is only for existing items
611 return nil
612end

onLoad

Description
Definition
onLoad()
Code
105function Wearable:onLoad(savegame)
106 local spec = self.spec_wearable
107
108 spec.wearableNodes = {}
109 spec.wearableNodesByIndex = {}
110 self:addToLocalWearableNode(nil, Wearable.updateWearAmount, nil, nil) -- create global / default wearableNode
111
112 spec.wearDuration = self.xmlFile:getValue("vehicle.wearable#wearDuration", 600) * 60 * 1000 -- default 600min / 10h
113 if spec.wearDuration ~= 0 then
114 spec.wearDuration = 1 / spec.wearDuration
115 end
116
117 spec.totalAmount = 0
118
119 spec.damage = 0
120 spec.damageByCurve = 0
121 spec.damageSent = 0
122
123 spec.workMultiplier = self.xmlFile:getValue("vehicle.wearable#workMultiplier", 20)
124 spec.fieldMultiplier = self.xmlFile:getValue("vehicle.wearable#fieldMultiplier", 2)
125
126 spec.showOnHud = self.xmlFile:getValue("vehicle.wearable#showOnHud", true)
127
128 spec.dirtyFlag = self:getNextDirtyFlag()
129end

onLoadFinished

Description
Definition
onLoadFinished()
Code
133function Wearable:onLoadFinished(savegame)
134 local spec = self.spec_wearable
135
136 if savegame ~= nil then
137 spec.damage = savegame.xmlFile:getValue(savegame.key .. ".wearable#damage", 0)
138 spec.damageByCurve = math.max(spec.damage - 0.3, 0) / 0.7
139 end
140
141 -- getting als wearable nodes in postLoad to make sure also linked nodes are wearable
142 if spec.wearableNodes ~= nil then
143 for _, component in pairs(self.components) do
144 self:addAllSubWearableNodes(component.node)
145 end
146
147 if savegame ~= nil then
148 for i, nodeData in ipairs(spec.wearableNodes) do
149 local nodeKey = string.format("%s.wearable.wearNode(%d)", savegame.key, i-1)
150 local amount = savegame.xmlFile:getValue(nodeKey.."#amount", 0)
151 self:setNodeWearAmount(nodeData, amount, true)
152 end
153 else
154 for _, nodeData in ipairs(spec.wearableNodes) do
155 self:setNodeWearAmount(nodeData, 0, true)
156 end
157 end
158 end
159end

onReadStream

Description
Definition
onReadStream()
Code
178function Wearable:onReadStream(streamId, connection)
179 local spec = self.spec_wearable
180
181 self:setDamageAmount(streamReadUIntN(streamId, Wearable.SEND_NUM_BITS) / Wearable.SEND_MAX_VALUE, true)
182
183 if spec.wearableNodes ~= nil then
184 for _, nodeData in ipairs(spec.wearableNodes) do
185 local wearAmount = streamReadUIntN(streamId, Wearable.SEND_NUM_BITS) / Wearable.SEND_MAX_VALUE
186 self:setNodeWearAmount(nodeData, wearAmount, true)
187 end
188 end
189end

onReadUpdateStream

Description
Definition
onReadUpdateStream()
Code
207function Wearable:onReadUpdateStream(streamId, timestamp, connection)
208 local spec = self.spec_wearable
209
210 if connection:getIsServer() then
211 if streamReadBool(streamId) then
212 self:setDamageAmount(streamReadUIntN(streamId, Wearable.SEND_NUM_BITS) / Wearable.SEND_MAX_VALUE, true)
213
214 if spec.wearableNodes ~= nil then
215 for _, nodeData in ipairs(spec.wearableNodes) do
216 local wearAmount = streamReadUIntN(streamId, Wearable.SEND_NUM_BITS) / Wearable.SEND_MAX_VALUE
217 self:setNodeWearAmount(nodeData, wearAmount, true)
218 end
219 end
220 end
221 end
222end

onUpdateTick

Description
Definition
onUpdateTick()
Code
244function Wearable:onUpdateTick(dt, isActive, isActiveForInput, isSelected)
245 local spec = self.spec_wearable
246
247 if spec.wearableNodes ~= nil then
248 if self.isServer then
249 local changeAmount = self:updateDamageAmount(dt)
250 if changeAmount ~= 0 then
251 self:setDamageAmount(spec.damage + changeAmount)
252 end
253
254 for _, nodeData in ipairs(spec.wearableNodes) do
255 local changedAmount = nodeData.updateFunc(self, nodeData, dt)
256 if changedAmount ~= 0 then
257 self:setNodeWearAmount(nodeData, self:getNodeWearAmount(nodeData) + changedAmount)
258 end
259 end
260 end
261 end
262end

onWriteStream

Description
Definition
onWriteStream()
Code
193function Wearable:onWriteStream(streamId, connection)
194 local spec = self.spec_wearable
195
196 streamWriteUIntN(streamId, math.floor(spec.damage * Wearable.SEND_MAX_VALUE + 0.5), Wearable.SEND_NUM_BITS)
197
198 if spec.wearableNodes ~= nil then
199 for _, nodeData in ipairs(spec.wearableNodes) do
200 streamWriteUIntN(streamId, math.floor(self:getNodeWearAmount(nodeData) * Wearable.SEND_MAX_VALUE + 0.5), Wearable.SEND_NUM_BITS)
201 end
202 end
203end

onWriteUpdateStream

Description
Definition
onWriteUpdateStream()
Code
226function Wearable:onWriteUpdateStream(streamId, connection, dirtyMask)
227 local spec = self.spec_wearable
228
229 if not connection:getIsServer() then
230 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
231 streamWriteUIntN(streamId, math.floor(spec.damage * Wearable.SEND_MAX_VALUE + 0.5), Wearable.SEND_NUM_BITS)
232
233 if spec.wearableNodes ~= nil then
234 for _, nodeData in ipairs(spec.wearableNodes) do
235 streamWriteUIntN(streamId, math.floor(self:getNodeWearAmount(nodeData) * Wearable.SEND_MAX_VALUE + 0.5), Wearable.SEND_NUM_BITS)
236 end
237 end
238 end
239 end
240end

prerequisitesPresent

Description
Definition
prerequisitesPresent()
Code
28function Wearable.prerequisitesPresent(specializations)
29 return true
30end

registerEventListeners

Description
Definition
registerEventListeners()
Code
90function Wearable.registerEventListeners(vehicleType)
91 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Wearable)
92 SpecializationUtil.registerEventListener(vehicleType, "onLoadFinished", Wearable)
93
94 if not GS_IS_MOBILE_VERSION then
95 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Wearable)
96 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Wearable)
97 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Wearable)
98 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Wearable)
99 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Wearable)
100 end
101end

registerFunctions

Description
Definition
registerFunctions()
Code
54function Wearable.registerFunctions(vehicleType)
55 SpecializationUtil.registerFunction(vehicleType, "addAllSubWearableNodes", Wearable.addAllSubWearableNodes)
56 SpecializationUtil.registerFunction(vehicleType, "addDamageAmount", Wearable.addDamageAmount)
57 SpecializationUtil.registerFunction(vehicleType, "addToGlobalWearableNode", Wearable.addToGlobalWearableNode)
58 SpecializationUtil.registerFunction(vehicleType, "addToLocalWearableNode", Wearable.addToLocalWearableNode)
59 SpecializationUtil.registerFunction(vehicleType, "addWearableNodes", Wearable.addWearableNodes)
60 SpecializationUtil.registerFunction(vehicleType, "addWearAmount", Wearable.addWearAmount)
61 SpecializationUtil.registerFunction(vehicleType, "getDamageAmount", Wearable.getDamageAmount)
62 SpecializationUtil.registerFunction(vehicleType, "getDamageShowOnHud", Wearable.getDamageShowOnHud)
63 SpecializationUtil.registerFunction(vehicleType, "getNodeWearAmount", Wearable.getNodeWearAmount)
64 SpecializationUtil.registerFunction(vehicleType, "getUsageCausesDamage", Wearable.getUsageCausesDamage)
65 SpecializationUtil.registerFunction(vehicleType, "getUsageCausesWear", Wearable.getUsageCausesWear)
66 SpecializationUtil.registerFunction(vehicleType, "getWearMultiplier", Wearable.getWearMultiplier)
67 SpecializationUtil.registerFunction(vehicleType, "getWearTotalAmount", Wearable.getWearTotalAmount)
68 SpecializationUtil.registerFunction(vehicleType, "getWorkWearMultiplier", Wearable.getWorkWearMultiplier)
69 SpecializationUtil.registerFunction(vehicleType, "removeWearableNode", Wearable.removeWearableNode)
70 SpecializationUtil.registerFunction(vehicleType, "repaintVehicle", Wearable.repaintVehicle)
71 SpecializationUtil.registerFunction(vehicleType, "repairVehicle", Wearable.repairVehicle)
72 SpecializationUtil.registerFunction(vehicleType, "setDamageAmount", Wearable.setDamageAmount)
73 SpecializationUtil.registerFunction(vehicleType, "setNodeWearAmount", Wearable.setNodeWearAmount)
74 SpecializationUtil.registerFunction(vehicleType, "updateDamageAmount", Wearable.updateDamageAmount)
75 SpecializationUtil.registerFunction(vehicleType, "updateWearAmount", Wearable.updateWearAmount)
76 SpecializationUtil.registerFunction(vehicleType, "validateWearableNode", Wearable.validateWearableNode)
77end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
81function Wearable.registerOverwrittenFunctions(vehicleType)
82 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getVehicleDamage", Wearable.getVehicleDamage)
83 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getRepairPrice", Wearable.getRepairPrice)
84 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getRepaintPrice", Wearable.getRepaintPrice)
85 SpecializationUtil.registerOverwrittenFunction(vehicleType, "showInfo", Wearable.showInfo)
86end

removeWearableNode

Description
Remove wearable node
Definition
removeWearableNode(node table)
Arguments
nodetablenode
Code
552function Wearable:removeWearableNode(node)
553 local spec = self.spec_wearable
554
555 if spec.wearableNodes ~= nil and node ~= nil then
556 for _, nodeData in ipairs(spec.wearableNodes) do
557 nodeData.nodes[node] = nil
558 end
559 end
560end

repairVehicle

Description
Repair the vehicle. Owner pays. Causes damage to be reset
Definition
repairVehicle()
Code
404function Wearable:repairVehicle()
405 if self.isServer then
406 g_currentMission:addMoney(-self:getRepairPrice(), self:getOwnerFarmId(), MoneyType.VEHICLE_REPAIR, true, true)
407
408 self:setDamageAmount(0)
409
410 self:raiseDirtyFlags(self.spec_wearable.dirtyFlag)
411
412 local total = g_currentMission:farmStats(self:getOwnerFarmId()):updateStats("repairVehicleCount", 1)
413 g_achievementManager:tryUnlock("VehicleRepairFirst", total)
414 g_achievementManager:tryUnlock("VehicleRepair", total)
415 end
416end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
163function Wearable:saveToXMLFile(xmlFile, key, usedModNames)
164 local spec = self.spec_wearable
165
166 xmlFile:setValue(key.."#damage", spec.damage)
167
168 if spec.wearableNodes ~= nil then
169 for i, nodeData in ipairs(spec.wearableNodes) do
170 local nodeKey = string.format("%s.wearNode(%d)", key, i-1)
171 xmlFile:setValue(nodeKey.."#amount", self:getNodeWearAmount(nodeData))
172 end
173 end
174end

setDamageAmount

Description
Definition
setDamageAmount()
Code
266function Wearable:setDamageAmount(amount, force)
267 local spec = self.spec_wearable
268
269 spec.damage = math.min(math.max(amount, 0), 1)
270 spec.damageByCurve = math.max(spec.damage - 0.3, 0) / 0.7
271
272 local diff = spec.damageSent - spec.damage
273 if math.abs(diff) > Wearable.SEND_THRESHOLD or force then
274 if self.isServer then
275 self:raiseDirtyFlags(spec.dirtyFlag)
276 spec.damageSent = spec.damage
277 end
278 end
279end

setNodeWearAmount

Description
Definition
setNodeWearAmount()
Code
350function Wearable:setNodeWearAmount(nodeData, wearAmount, force)
351 local spec = self.spec_wearable
352 nodeData.wearAmount = MathUtil.clamp(wearAmount, 0, 1)
353
354 local diff = nodeData.wearAmountSent - nodeData.wearAmount
355 if math.abs(diff) > Wearable.SEND_THRESHOLD or force then
356 for _, node in pairs(nodeData.nodes) do
357 local _, y, z, w = getShaderParameter(node, "RDT")
358 setShaderParameter(node, "RDT", nodeData.wearAmount, y, 0, w, false)
359 end
360
361 if self.isServer then
362 self:raiseDirtyFlags(spec.dirtyFlag)
363 nodeData.wearAmountSent = nodeData.wearAmount
364 end
365
366 -- calculate total wearable amount
367 spec.totalAmount = 0
368 for i = 1, #spec.wearableNodes do
369 spec.totalAmount = spec.totalAmount + spec.wearableNodes[i].wearAmount
370 end
371 spec.totalAmount = spec.totalAmount / #spec.wearableNodes
372 end
373end

showInfo

Description
Definition
showInfo()
Code
458function Wearable:showInfo(superFunc, box)
459 local damage = self.spec_wearable.damage
460 if damage > 0.01 then
461 box:addLine(g_i18n:getText("infohud_damage"), string.format("%d %%", damage * 100))
462 end
463
464 superFunc(self, box)
465end

updateDamageAmount

Description
Definition
updateDamageAmount()
Code
294function Wearable:updateDamageAmount(dt)
295 local spec = self.spec_wearable
296 if self:getUsageCausesDamage() then
297 local factor = 1
298 if self.lifetime ~= nil and self.lifetime ~= 0 then
299 local ageMultiplier = 0.15 * math.min(self.age / self.lifetime, 1)
300 local operatingTime = self.operatingTime / (1000*60*60)
301 local operatingTimeMultiplier = 0.85 * math.min(operatingTime / (self.lifetime * EconomyManager.LIFETIME_OPERATINGTIME_RATIO), 1)
302
303 factor = 1 + EconomyManager.MAX_DAILYUPKEEP_MULTIPLIER * (ageMultiplier + operatingTimeMultiplier)
304 end
305
306 return dt * spec.wearDuration * 0.35 * factor
307 else
308 return 0
309 end
310end

updateDebugValues

Description
Definition
updateDebugValues()
Code
591function Wearable:updateDebugValues(values)
592 local spec = self.spec_wearable
593
594 local changedAmount = self:updateDamageAmount(3600000)
595 table.insert(values, {name="Damage", value=string.format("%.4f a/h (%.2f)", changedAmount, self:getDamageAmount())})
596
597 if spec.wearableNodes ~= nil then
598 if self.isServer then
599 for i, nodeData in ipairs(spec.wearableNodes) do
600 changedAmount = nodeData.updateFunc(self, nodeData, 3600000)
601 table.insert(values, {name="WearableNode"..i, value=string.format("%.4f a/h (%.6f)", changedAmount, self:getNodeWearAmount(nodeData))})
602 end
603 end
604 end
605end

updateWearAmount

Description
Definition
updateWearAmount()
Code
283function Wearable:updateWearAmount(nodeData, dt)
284 local spec = self.spec_wearable
285 if self:getUsageCausesWear() then
286 return dt * spec.wearDuration * self:getWearMultiplier(nodeData) * 0.5
287 else
288 return 0
289 end
290end

validateWearableNode

Description
Definition
validateWearableNode()
Code
505function Wearable:validateWearableNode(node)
506 return true, nil -- by default all nodes are global
507end