LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Windrower

Description
Specialization for windrowers providing additional animations, effects and drop area functionalities
Functions

doCheckSpeedLimit

Description
Definition
doCheckSpeedLimit()
Code
303function Windrower:doCheckSpeedLimit(superFunc)
304 local turnOn = true
305 if self.getIsTurnedOn ~= nil then
306 turnOn = self:getIsTurnedOn()
307 end
308
309 return superFunc(self) or (self:getIsImplementChainLowered() and turnOn)
310end

getDefaultSpeedLimit

Description
Definition
getDefaultSpeedLimit()
Code
314function Windrower.getDefaultSpeedLimit()
315 return 15
316end

getDirtMultiplier

Description
Definition
getDirtMultiplier()
Code
349function Windrower:getDirtMultiplier(superFunc)
350 local spec = self.spec_windrower
351
352 local multiplier = superFunc(self)
353
354 if spec.isWorking then
355 multiplier = multiplier + self:getWorkDirtMultiplier() * self:getLastSpeed() / self.speedLimit
356 end
357
358 return multiplier
359end

getWearMultiplier

Description
Definition
getWearMultiplier()
Code
363function Windrower:getWearMultiplier(superFunc)
364 local spec = self.spec_windrower
365
366 local multiplier = superFunc(self)
367
368 if spec.isWorking then
369 local stoneMultiplier = 1
370 if spec.stoneLastState ~= 0 and spec.stoneWearMultiplierData ~= nil then
371 stoneMultiplier = spec.stoneWearMultiplierData[spec.stoneLastState] or 1
372 end
373
374 multiplier = multiplier + self:getWorkWearMultiplier() * self:getLastSpeed() / self.speedLimit * stoneMultiplier
375 end
376
377 return multiplier
378end

initSpecialization

Description
Definition
initSpecialization()
Code
15function Windrower.initSpecialization()
16 g_workAreaTypeManager:addWorkAreaType("windrower", false)
17
18 local schema = Vehicle.xmlSchema
19 schema:setXMLSpecializationType("Windrower")
20
21 EffectManager.registerEffectXMLPaths(schema, "vehicle.windrower.effects.effect(?)")
22 schema:register(XMLValueType.INT, "vehicle.windrower.effects.effect(?)#workAreaIndex", "Work area index", 1)
23 schema:register(XMLValueType.INT, "vehicle.windrower.effects.effect(?)#dropAreaIndex", "Drop area index (if defined the effect is only active if this drop area is set on workArea)")
24
25 AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.windrower.animationNodes")
26 SoundManager.registerSampleXMLPaths(schema, "vehicle.windrower.sounds", "work")
27
28 schema:register(XMLValueType.BOOL, "vehicle.windrower#limitToLineHeight", "Limit pickup to work area line height", false)
29 schema:register(XMLValueType.STRING, "vehicle.windrower#fillTypeCategories", "Fill type categories")
30 schema:register(XMLValueType.STRING, "vehicle.windrower#fillTypes", "List of supported fill types")
31
32 schema:register(XMLValueType.INT, WorkArea.WORK_AREA_XML_KEY .. ".windrower#particleSystemIndex", "Particle system index")
33 schema:register(XMLValueType.INT, WorkArea.WORK_AREA_XML_KEY .. ".windrower#dropWindrowWorkAreaIndex", "Drop work area index", 1)
34
35 schema:register(XMLValueType.INT, WorkArea.WORK_AREA_XML_CONFIG_KEY .. ".windrower#particleSystemIndex", "Particle system index")
36 schema:register(XMLValueType.INT, WorkArea.WORK_AREA_XML_CONFIG_KEY .. ".windrower#dropWindrowWorkAreaIndex", "Drop work area index", 1)
37
38 schema:setXMLSpecializationType()
39end

loadWorkAreaFromXML

Description
Definition
loadWorkAreaFromXML()
Code
320function Windrower:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
321 local retValue = superFunc(self, workArea, xmlFile, key)
322
323 if workArea.type == WorkAreaType.DEFAULT then
324 workArea.type = WorkAreaType.WINDROWER
325 end
326
327 if workArea.type == WorkAreaType.WINDROWER then
328 workArea.particleSystemIndex = xmlFile:getValue(key .. ".windrower#particleSystemIndex")
329 workArea.dropWindrowWorkAreaIndex = xmlFile:getValue(key .. ".windrower#dropWindrowWorkAreaIndex", 1)
330
331 workArea.lastValidPickupFillType = FillType.UNKNOWN
332 workArea.lastPickupLiters = 0
333 workArea.lastDroppedLiters = 0
334 workArea.litersToDrop = 0
335
336 local spec = self.spec_windrower
337 if spec.windrowerWorkAreaFillTypes == nil then
338 spec.windrowerWorkAreaFillTypes = {}
339 end
340 table.insert(spec.windrowerWorkAreaFillTypes, FillType.UNKNOWN)
341 workArea.windrowerWorkAreaIndex = #spec.windrowerWorkAreaFillTypes
342 end
343
344 return retValue
345end

onDelete

Description
Definition
onDelete()
Code
170function Windrower:onDelete()
171 local spec = self.spec_windrower g_soundManager:deleteSamples(spec.samples)
172 g_animationManager:deleteAnimations(spec.animationNodes)
173
174 if spec.effects ~= nil then
175 for _, effect in ipairs(spec.effects) do
176 g_effectManager:deleteEffects(effect.effects)
177 end
178 end
179end

onEndWorkAreaProcessing

Description
Definition
onEndWorkAreaProcessing()
Code
394function Windrower:onEndWorkAreaProcessing(dt, workAreas)
395 local spec = self.spec_windrower
396
397 if self.isClient then
398 if self.getIsTurnedOn == nil then
399 if spec.isWorking then
400 if not g_soundManager:getIsSamplePlaying(spec.samples.work) then
401 g_soundManager:playSample(spec.samples.work)
402 end
403 else
404 if g_soundManager:getIsSamplePlaying(spec.samples.work) then
405 g_soundManager:stopSample(spec.samples.work)
406 end
407 end
408 end
409 end
410end

onLoad

Description
Definition
onLoad()
Code
82function Windrower:onLoad(savegame)
83 local spec = self.spec_windrower
84
85 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.animation", "vehicle.windrowers.windrower") --FS13 to FS15
86
87 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.windrowerParticleSystems", "vehicle.windrower.effects") --FS17 to FS19
88 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnedOnRotationNodes.turnedOnRotationNode#type", "vehicle.windrower.animationNodes.animationNode", "windrower") --FS17 to FS19
89 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.windrowerSound", "vehicle.windrower.sounds.work") --FS17 to FS19
90
91 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.windrower.rakes.rake", "vehicle.windrower.animationNodes.animationNode with type 'RotationAnimationSpikes'") --FS19 to FS22
92
93 if self.isClient then
94 spec.animationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.windrower.animationNodes", self.components, self, self.i3dMappings)
95
96 spec.effects = {}
97 spec.workAreaToEffects = {}
98 local i = 0
99 while true do
100 local key = string.format("vehicle.windrower.effects.effect(%d)", i)
101 if not self.xmlFile:hasProperty(key) then
102 break
103 end
104 local effects = g_effectManager:loadEffect(self.xmlFile, key, self.components, self, self.i3dMappings)
105 if effects ~= nil then
106 local effect = {}
107 effect.effects = effects
108 effect.workAreaIndex = self.xmlFile:getValue(key .. "#workAreaIndex", 1)
109 effect.dropAreaIndex = self.xmlFile:getValue(key .. "#dropAreaIndex")
110 effect.activeTime = -1
111 effect.activeTimeDuration = 250
112 effect.isActive = false
113 effect.isActiveSent = false
114 table.insert(spec.effects, effect)
115
116 for j=1, #effects do
117 if effects[j].setWorkAreaIndex ~= nil then
118 effects[j]:setWorkAreaIndex(effect.workAreaIndex)
119 end
120 end
121 end
122 i = i + 1
123 end
124
125 spec.samples = {}
126 spec.samples.work = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.windrower.sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
127 end
128
129 spec.isWorking = false
130 spec.limitToLineHeight = self.xmlFile:getValue("vehicle.windrower#limitToLineHeight", false)
131
132 spec.stoneLastState = 0
133 spec.stoneWearMultiplierData = g_currentMission.stoneSystem:getWearMultiplierByType("WINDROWER")
134
135 spec.supportedFillTypes = g_fillTypeManager:getFillTypesFromXML(self.xmlFile, "vehicle.windrower#fillTypeCategories", "vehicle.windrower#fillTypes", true)
136
137 spec.fillTypesDirtyFlag = self:getNextDirtyFlag()
138 spec.effectDirtyFlag = self:getNextDirtyFlag()
139
140 if self.addAIDensityHeightTypeRequirement ~= nil then
141 for _, fillTypeIndex in ipairs(spec.supportedFillTypes) do
142 self:addAIDensityHeightTypeRequirement(fillTypeIndex)
143 end
144 end
145end

onPostLoad

Description
Definition
onPostLoad()
Code
149function Windrower:onPostLoad(savegame)
150 local spec = self.spec_windrower
151 for i=#spec.effects, 1, -1 do
152 local effect = spec.effects[i]
153 local workArea = self:getWorkAreaByIndex(effect.workAreaIndex)
154 if workArea ~= nil then
155 effect.windrowerWorkAreaFillTypeIndex = workArea.windrowerWorkAreaIndex
156
157 if spec.workAreaToEffects[workArea.index] == nil then
158 spec.workAreaToEffects[workArea.index] = {}
159 end
160 table.insert(spec.workAreaToEffects[workArea.index], effect)
161 else
162 Logging.xmlWarning(self.xmlFile, "Invalid workAreaIndex '%d' for effect 'vehicle.windrower.effects.effect(%d)'!", effect.workAreaIndex, i)
163 table.insert(spec.effects, i)
164 end
165 end
166end

onReadStream

Description
Definition
onReadStream()
Code
184function Windrower:onReadStream(streamId, connection)
185 local spec = self.spec_windrower
186 for index, _ in ipairs(spec.windrowerWorkAreaFillTypes) do
187 local fillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS)
188 spec.windrowerWorkAreaFillTypes[index] = fillType
189 end
190 for _, effect in ipairs(spec.effects) do
191 if streamReadBool(streamId) then
192 local fillType = spec.windrowerWorkAreaFillTypes[effect.windrowerWorkAreaFillTypeIndex]
193 g_effectManager:setFillType(effect.effects, fillType)
194 g_effectManager:startEffects(effect.effects)
195 else
196 g_effectManager:stopEffects(effect.effects)
197 end
198 end
199end

onReadUpdateStream

Description
Definition
onReadUpdateStream()
Code
215function Windrower:onReadUpdateStream(streamId, timestamp, connection)
216 if connection:getIsServer() then
217 local spec = self.spec_windrower
218
219 if streamReadBool(streamId) then
220 for index, _ in ipairs(spec.windrowerWorkAreaFillTypes) do
221 local fillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS)
222 spec.windrowerWorkAreaFillTypes[index] = fillType
223 end
224 end
225
226 if streamReadBool(streamId) then
227 for _, effect in ipairs(spec.effects) do
228 if streamReadBool(streamId) then
229 local fillType = spec.windrowerWorkAreaFillTypes[effect.windrowerWorkAreaFillTypeIndex]
230 g_effectManager:setFillType(effect.effects, fillType)
231 g_effectManager:startEffects(effect.effects)
232 else
233 g_effectManager:stopEffects(effect.effects)
234 end
235 end
236 end
237 end
238end

onStartWorkAreaProcessing

Description
Definition
onStartWorkAreaProcessing()
Code
382function Windrower:onStartWorkAreaProcessing(dt, workAreas)
383 local spec = self.spec_windrower
384 for _, workArea in pairs(workAreas) do
385 workArea.lastValidPickupFillType = FillType.UNKNOWN
386 workArea.lastPickupLiters = 0
387 workArea.lastDroppedLiters = 0
388 end
389 spec.isWorking = false
390end

onTurnedOff

Description
Definition
onTurnedOff()
Code
291function Windrower:onTurnedOff()
292 local spec = self.spec_windrower
293 g_soundManager:stopSamples(spec.samples)
294
295 for _, effect in ipairs(spec.effects) do
296 g_effectManager:stopEffects(effect.effects)
297 end
298 g_animationManager:stopAnimations(spec.animationNodes)
299end

onTurnedOn

Description
Definition
onTurnedOn()
Code
281function Windrower:onTurnedOn()
282 local spec = self.spec_windrower
283 if self.isClient then
284 g_soundManager:playSample(spec.samples.work)
285 g_animationManager:startAnimations(spec.animationNodes)
286 end
287end

onUpdateTick

Description
Definition
onUpdateTick()
Code
262function Windrower:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
263 local spec = self.spec_windrower
264
265 if self.isServer then
266 for _, effect in ipairs(spec.effects) do
267 if effect.isActive and g_currentMission.time > effect.activeTime then
268 effect.isActive = false
269 if effect.isActiveSent then
270 effect.isActiveSent = false
271 self:raiseDirtyFlags(spec.effectDirtyFlag)
272 end
273 g_effectManager:stopEffects(effect.effects)
274 end
275 end
276 end
277end

onWriteStream

Description
Definition
onWriteStream()
Code
203function Windrower:onWriteStream(streamId, connection)
204 local spec = self.spec_windrower
205 for _, fillTypeIndex in ipairs(spec.windrowerWorkAreaFillTypes) do
206 streamWriteUIntN(streamId, fillTypeIndex, FillTypeManager.SEND_NUM_BITS)
207 end
208 for _, effect in ipairs(spec.effects) do
209 streamWriteBool(streamId, effect.isActiveSent)
210 end
211end

onWriteUpdateStream

Description
Definition
onWriteUpdateStream()
Code
242function Windrower:onWriteUpdateStream(streamId, connection, dirtyMask)
243 if not connection:getIsServer() then
244 local spec = self.spec_windrower
245
246 if streamWriteBool(streamId, bitAND(dirtyMask, spec.fillTypesDirtyFlag) ~= 0) then
247 for _, fillTypeIndex in ipairs(spec.windrowerWorkAreaFillTypes) do
248 streamWriteUIntN(streamId, fillTypeIndex, FillTypeManager.SEND_NUM_BITS)
249 end
250 end
251
252 if streamWriteBool(streamId, bitAND(dirtyMask, spec.effectDirtyFlag) ~= 0) then
253 for _, effect in ipairs(spec.effects) do
254 streamWriteBool(streamId, effect.isActiveSent)
255 end
256 end
257 end
258end

prerequisitesPresent

Description
Definition
prerequisitesPresent()
Code
43function Windrower.prerequisitesPresent(specializations)
44 return SpecializationUtil.hasSpecialization(WorkArea, specializations)
45end

processDropArea

Description
Definition
processDropArea()
Code
527function Windrower:processDropArea(dropArea, litersToDrop, fillType)
528 local lsx, lsy, lsz, lex, ley, lez, radius = DensityMapHeightUtil.getLineByArea(dropArea.start, dropArea.width, dropArea.height)
529 local dropped, lineOffset = DensityMapHeightUtil.tipToGroundAroundLine(self, litersToDrop, fillType, lsx,lsy,lsz, lex,ley,lez, radius, nil, dropArea.lineOffset, false, nil, false)
530 dropArea.lineOffset = lineOffset
531
532 return dropped
533end

processWindrowerArea

Description
Definition
processWindrowerArea()
Code
414function Windrower:processWindrowerArea(workArea, dt)
415 local spec = self.spec_windrower
416 local workAreaSpec = self.spec_workArea
417 spec.isWorking = self:getLastSpeed() > 0.5
418
419 local sx, sy, sz = getWorldTranslation(workArea.start)
420 local wx, wy, wz = getWorldTranslation(workArea.width)
421 local hx, hy, hz = getWorldTranslation(workArea.height)
422
423 if spec.isWorking then
424 spec.stoneLastState = FSDensityMapUtil.getStoneArea(sx, sz, wx, wz, hx, hz)
425 else
426 spec.stoneLastState = 0
427 end
428
429 -- pick up
430 local lsx, lsy, lsz, lex, ley, lez, radius = DensityMapHeightUtil.getLineByAreaDimensions(sx, sy, sz, wx, wy, wz, hx, hy, hz)
431
432 -- loop over all fruitTypes or use only lastValidPickupFillType
433 local pickupLiters = 0
434 local pickupFillType = FillType.UNKNOWN
435
436 if workArea.lastPickupLiters == 0 and (workArea.lastValidPickupFillType == FillType.UNKNOWN or workArea.litersToDrop < g_densityMapHeightManager:getMinValidLiterValue(workArea.lastValidPickupFillType)) then
437 for _, fillTypeIndex in ipairs(spec.supportedFillTypes) do
438 pickupLiters = -DensityMapHeightUtil.tipToGroundAroundLine(self, -math.huge, fillTypeIndex, lsx,lsy,lsz, lex,ley,lez, radius, nil, nil, spec.limitToLineHeight, nil)
439 if pickupLiters > 0 then
440 pickupFillType = fillTypeIndex
441 break
442 end
443 end
444 else
445 pickupLiters = -DensityMapHeightUtil.tipToGroundAroundLine(self, -math.huge, workArea.lastValidPickupFillType, lsx,lsy,lsz, lex,ley,lez, radius, nil, nil, false, nil)
446
447 if workArea.lastValidPickupFillType == FillType.GRASS_WINDROW then
448 pickupLiters = pickupLiters - DensityMapHeightUtil.tipToGroundAroundLine(self, -math.huge, FillType.DRYGRASS_WINDROW, lsx,lsy,lsz, lex,ley,lez, radius, nil, nil, false, nil)
449 elseif workArea.lastValidPickupFillType == FillType.DRYGRASS_WINDROW then
450 pickupLiters = pickupLiters - DensityMapHeightUtil.tipToGroundAroundLine(self, -math.huge, FillType.GRASS_WINDROW, lsx,lsy,lsz, lex,ley,lez, radius, nil, nil, false, nil)
451 end
452
453 if pickupLiters > 0 then
454 pickupFillType = workArea.lastValidPickupFillType
455 end
456 end
457
458 if pickupFillType ~= FillType.UNKNOWN then
459 workArea.lastValidPickupFillType = pickupFillType
460
461 self:setTestAreaRequirements(nil, pickupFillType, nil)
462 end
463 workArea.lastPickupLiters = pickupLiters
464 workArea.litersToDrop = workArea.litersToDrop + pickupLiters
465
466 --calculating area by area width multiplied by last moved distance (not 100% accuracy in corners)
467 local areaWidth = MathUtil.vector3Length(lsx-lex, lsy-ley, lsz-lez)
468 local area = areaWidth * self.lastMovedDistance
469
470 -- drop
471 if workArea.lastPickupLiters > 0 then
472 local dropArea = workAreaSpec.workAreas[workArea.dropWindrowWorkAreaIndex]
473 if dropArea ~= nil then
474 local dropType = workArea.lastValidPickupFillType
475 local dropped = self:processDropArea(dropArea, workArea.lastPickupLiters, dropType)
476 workArea.lastDroppedLiters = dropped
477 workArea.litersToDrop = workArea.litersToDrop - dropped
478
479 if self.isServer then
480 --particles
481 if self:getLastSpeed(true) > 0.5 then
482 if dropped > 0 then
483 local changedFillType = false
484 if spec.windrowerWorkAreaFillTypes[workArea.windrowerWorkAreaIndex] ~= dropType then
485 spec.windrowerWorkAreaFillTypes[workArea.windrowerWorkAreaIndex] = dropType
486 self:raiseDirtyFlags(spec.fillTypesDirtyFlag)
487 changedFillType = true
488 end
489
490 local effects = spec.workAreaToEffects[workArea.index]
491 if effects ~= nil then
492 for _, effect in ipairs(effects) do
493 if effect.dropAreaIndex == nil or effect.dropAreaIndex == workArea.dropWindrowWorkAreaIndex then
494 effect.activeTime = g_currentMission.time + effect.activeTimeDuration
495
496 -- sync mp
497 if not effect.isActiveSent then
498 effect.isActiveSent = true
499 self:raiseDirtyFlags(spec.effectDirtyFlag)
500 end
501
502 if changedFillType then
503 g_effectManager:setFillType(effect.effects, dropType)
504 end
505
506 -- enable effect
507 if not effect.isActive then
508 g_effectManager:setFillType(effect.effects, dropType)
509 g_effectManager:startEffects(effect.effects)
510 end
511
512 effect.isActive = true
513 end
514 end
515 end
516 end
517 end
518 end
519 end
520 end
521
522 return workArea.lastDroppedLiters, area
523end

registerEventListeners

Description
Definition
registerEventListeners()
Code
65function Windrower.registerEventListeners(vehicleType)
66 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Windrower)
67 SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", Windrower)
68 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Windrower)
69 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Windrower)
70 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Windrower)
71 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Windrower)
72 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Windrower)
73 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Windrower)
74 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", Windrower)
75 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", Windrower)
76 SpecializationUtil.registerEventListener(vehicleType, "onStartWorkAreaProcessing", Windrower)
77 SpecializationUtil.registerEventListener(vehicleType, "onEndWorkAreaProcessing", Windrower)
78end

registerFunctions

Description
Definition
registerFunctions()
Code
49function Windrower.registerFunctions(vehicleType)
50 SpecializationUtil.registerFunction(vehicleType, "processWindrowerArea", Windrower.processWindrowerArea)
51 SpecializationUtil.registerFunction(vehicleType, "processDropArea", Windrower.processDropArea)
52end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
56function Windrower.registerOverwrittenFunctions(vehicleType)
57 SpecializationUtil.registerOverwrittenFunction(vehicleType, "doCheckSpeedLimit", Windrower.doCheckSpeedLimit)
58 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadWorkAreaFromXML", Windrower.loadWorkAreaFromXML)
59 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDirtMultiplier", Windrower.getDirtMultiplier)
60 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getWearMultiplier", Windrower.getWearMultiplier)
61end