LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Mower

Description
Specialization for vehicles with grass mowing functionality
Functions

actionEventToggleDrop

Description
Definition
actionEventToggleDrop()
Code
725function Mower.actionEventToggleDrop(self, actionName, inputValue, callbackState, isAnalog)
726 local spec = self.spec_mower
727 self:setUseMowerWindrowDropAreas(not spec.useWindrowDropAreas)
728end

doCheckSpeedLimit

Description
Returns if speed limit should be checked
Definition
doCheckSpeedLimit()
Return Values
booleancheckSpeedlimitcheck speed limit
Code
548function Mower:doCheckSpeedLimit(superFunc)
549 return superFunc(self) or (self:getIsTurnedOn() and (self.getIsLowered == nil or self:getIsLowered()))
550end

getCanBeSelected

Description
Definition
getCanBeSelected()
Code
554function Mower:getCanBeSelected(superFunc)
555 return true
556end

getDefaultSpeedLimit

Description
Returns default speed limit
Definition
getDefaultSpeedLimit()
Return Values
floatspeedLimitspeed limit
Code
719function Mower.getDefaultSpeedLimit()
720 return 20
721end

getDirtMultiplier

Description
Definition
getDirtMultiplier()
Code
560function Mower:getDirtMultiplier(superFunc)
561 local spec = self.spec_mower
562
563 local multiplier = superFunc(self)
564
565 if spec.isWorking then
566 multiplier = multiplier + self:getWorkDirtMultiplier() * self:getLastSpeed() / self.speedLimit
567 end
568
569 return multiplier
570end

getDropArea

Description
Definition
getDropArea()
Code
414function Mower:getDropArea(workArea)
415 if workArea.dropWindrow then
416 local dropArea
417 if workArea.dropAreaIndex ~= nil then
418 dropArea = self.spec_workArea.workAreas[workArea.dropAreaIndex]
419 if dropArea == nil then
420 print("Warning: Invalid dropAreaIndex '"..tostring(workArea.dropAreaIndex).."' in '"..tostring(self.configFileName).."'!")
421 workArea.dropAreaIndex = nil
422 end
423
424 if dropArea.type ~= WorkAreaType.AUXILIARY then
425 Logging.xmlWarning(self.xmlFile, "Invalid dropAreaIndex '%s'. Drop area type needs to be 'AUXILIARY'!", workArea.dropAreaIndex)
426 workArea.dropAreaIndex = nil
427 dropArea = nil
428 end
429 end
430 return dropArea
431 end
432
433 return nil
434end

getMowerLoadPercentage

Description
Definition
getMowerLoadPercentage()
Code
707function Mower:getMowerLoadPercentage()
708 if self.spec_mower ~= nil then
709 return self.spec_mower.workAreaParameters.lastUsedAreasPct
710 end
711
712 return 0
713end

getWearMultiplier

Description
Definition
getWearMultiplier()
Code
574function Mower:getWearMultiplier(superFunc)
575 local spec = self.spec_mower
576
577 local multiplier = superFunc(self)
578
579 if spec.isWorking then
580 local stoneMultiplier = 1
581 if spec.stoneLastState ~= 0 and spec.stoneWearMultiplierData ~= nil then
582 stoneMultiplier = spec.stoneWearMultiplierData[spec.stoneLastState] or 1
583 end
584
585 multiplier = multiplier + self:getWorkWearMultiplier() * self:getLastSpeed() / self.speedLimit * stoneMultiplier
586 end
587
588 return multiplier
589end

initSpecialization

Description
Called on specialization initializing
Definition
initSpecialization()
Code
17function Mower.initSpecialization()
18 g_workAreaTypeManager:addWorkAreaType("mower", false)
19
20 local schema = Vehicle.xmlSchema
21 schema:setXMLSpecializationType("Mower")
22
23 AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.mower.animationNodes")
24
25 EffectManager.registerEffectXMLPaths(schema, "vehicle.mower.dropEffects.dropEffect(?)")
26 schema:register(XMLValueType.INT, "vehicle.mower.dropEffects.dropEffect(?)#dropAreaIndex", "Drop area index", 1)
27 schema:register(XMLValueType.INT, "vehicle.mower.dropEffects.dropEffect(?)#workAreaIndex", "Work area index", 1)
28
29 schema:register(XMLValueType.STRING, "vehicle.mower#fruitTypeConverter", "Fruit type converter name")
30 schema:register(XMLValueType.INT, "vehicle.mower#fillUnitIndex", "Fill unit index")
31 schema:register(XMLValueType.FLOAT, "vehicle.mower#pickupFillScale", "Pickup fill scale", 1)
32 schema:register(XMLValueType.L10N_STRING, "vehicle.mower.toggleWindrowDrop#enableText", "Enable windrow drop text")
33 schema:register(XMLValueType.L10N_STRING, "vehicle.mower.toggleWindrowDrop#disableText", "Disable windrow drop text")
34
35 schema:register(XMLValueType.STRING, "vehicle.mower.toggleWindrowDrop#animationName", "Windrow drop animation name")
36 schema:register(XMLValueType.FLOAT, "vehicle.mower.toggleWindrowDrop#animationEnableSpeed", "Animation enable speed", 1)
37 schema:register(XMLValueType.FLOAT, "vehicle.mower.toggleWindrowDrop#animationDisableSpeed", "Animation disable speed", "inversed 'animationEnableSpeed'")
38 schema:register(XMLValueType.BOOL, "vehicle.mower.toggleWindrowDrop#startEnabled", "Start windrow drop enabled", false)
39
40 SoundManager.registerSampleXMLPaths(schema, "vehicle.mower.sounds", "cut(?)")
41
42 schema:register(XMLValueType.BOOL, WorkArea.WORK_AREA_XML_KEY .. ".mower#dropWindrow", "Drop windrow", true)
43 schema:register(XMLValueType.INT, WorkArea.WORK_AREA_XML_KEY .. ".mower#dropAreaIndex", "Drop area index", 1)
44
45 schema:register(XMLValueType.BOOL, WorkArea.WORK_AREA_XML_CONFIG_KEY .. ".mower#dropWindrow", "Drop windrow", true)
46 schema:register(XMLValueType.INT, WorkArea.WORK_AREA_XML_CONFIG_KEY .. ".mower#dropAreaIndex", "Drop area index", 1)
47
48 schema:setXMLSpecializationType()
49end

loadWorkAreaFromXML

Description
Loads work areas from xml
Definition
loadWorkAreaFromXML(table workArea, integer xmlFile, string key)
Arguments
tableworkAreaworkArea
integerxmlFileid of xml object
stringkeykey
Return Values
booleansuccesssuccess
Code
502function Mower:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
503 local retValue = superFunc(self, workArea, xmlFile, key)
504
505 if workArea.type == WorkAreaType.DEFAULT then
506 workArea.type = WorkAreaType.MOWER
507 end
508
509 if workArea.type == WorkAreaType.MOWER then
510 workArea.dropWindrow = xmlFile:getValue(key .. ".mower#dropWindrow", true)
511 workArea.dropAreaIndex = xmlFile:getValue(key .. ".mower#dropAreaIndex", 1)
512
513 workArea.lastPickupLiters = 0
514 workArea.pickedUpLiters = 0
515 end
516
517 if workArea.type == WorkAreaType.AUXILIARY then
518 workArea.litersToDrop = 0
519 if self.spec_mower.dropAreas == nil then
520 self.spec_mower.dropAreas = {}
521 end
522 table.insert(self.spec_mower.dropAreas, workArea)
523 end
524
525 return retValue
526end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
229function Mower:onDelete()
230 local spec = self.spec_mower
231
232 if self.isClient then
233 g_animationManager:deleteAnimations(spec.animationNodes)
234 g_soundManager:deleteSamples(spec.samples.cut)
235 end
236
237 if spec.dropEffects ~= nil then
238 for _, dropEffect in pairs(spec.dropEffects) do
239 g_effectManager:deleteEffects(dropEffect.effects)
240 end
241 end
242end

onEndWorkAreaProcessing

Description
Definition
onEndWorkAreaProcessing()
Code
648function Mower:onEndWorkAreaProcessing(dt, hasProcessed)
649 local spec = self.spec_mower
650
651 for _, dropArea in ipairs(spec.dropAreas) do
652 self:processDropArea(dropArea, dt)
653 end
654
655 for i=1, #spec.workAreas do
656 local workArea = spec.workAreas[i]
657 for j=1, #workArea.dropEffects do
658 local dropEffect = workArea.dropEffects[j]
659 local dropArea = self:getDropArea(workArea)
660 if dropEffect.dropAreaIndex == dropArea.index then
661 if workArea.pickedUpLiters > 0 then
662 if dropEffect.fillType ~= dropArea.fillType then
663 dropEffect.fillType = dropArea.fillType
664 g_effectManager:setFillType(dropEffect.effects, dropEffect.fillType)
665 end
666 dropEffect.activeTime = dropEffect.activeTimeDuration
667 dropEffect.isActive = true
668 else
669 dropEffect.activeTime = math.max(dropEffect.activeTime - dt, 0)
670 if dropEffect.activeTime > 0 then
671 dropEffect.isActive = true
672 end
673 end
674 end
675 end
676 end
677
678 if self.isServer then
679 local lastStatsArea = spec.workAreaParameters.lastStatsArea
680
681 if lastStatsArea > 0 then
682 local ha = MathUtil.areaToHa(lastStatsArea, g_currentMission:getFruitPixelsToSqm()) -- 4096px are mapped to 2048m
683 local stats = g_currentMission:farmStats(self:getLastTouchedFarmlandFarmId())
684 stats:updateStats("threshedHectares", ha)
685 self:updateLastWorkedArea(lastStatsArea)
686 end
687
688 local isCutting = g_time - spec.lastDropTime < 500
689 if spec.isCutting ~= isCutting then
690 spec.isCutting = isCutting
691 self:raiseDirtyFlags(spec.dirtyFlag)
692 self:setCutSoundEnabled(spec.isCutting)
693 end
694 end
695
696 spec.workAreaParameters.lastUsedAreasTime = spec.workAreaParameters.lastUsedAreasTime + dt
697 if spec.workAreaParameters.lastUsedAreasTime > 500 then
698 spec.workAreaParameters.lastUsedAreasPct = spec.workAreaParameters.lastUsedAreas / math.max(spec.workAreaParameters.lastUsedAreasSum, 0.01)
699 spec.workAreaParameters.lastUsedAreas = 0
700 spec.workAreaParameters.lastUsedAreasSum = 0
701 spec.workAreaParameters.lastUsedAreasTime = 0
702 end
703end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
101function Mower:onLoad(savegame)
102 local spec = self.spec_mower
103
104 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mowerEffects.mowerEffect", "vehicle.mower.dropEffects.dropEffect") --FS17 to FS19
105 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mowerEffects.mowerEffect#mowerCutArea", "vehicle.mower.dropEffects.dropEffect#dropAreaIndex") --FS17 to FS19
106 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnedOnRotationNodes.turnedOnRotationNode#type", "vehicle.mower.turnOnNodes.turnOnNode", "mower") --FS17 to FS19
107 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mowerStartSound", "vehicle.turnOnVehicle.sounds.start") --FS17 to FS19
108 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mowerStopSound", "vehicle.turnOnVehicle.sounds.stop") --FS17 to FS19
109 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mowerSound", "vehicle.turnOnVehicle.sounds.work") --FS17 to FS19
110
111 if self.isClient then
112 spec.animationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.mower.animationNodes", self.components, self, self.i3dMappings)
113
114 spec.samples = {}
115 spec.samples.cut = g_soundManager:loadSamplesFromXML(self.xmlFile, "vehicle.mower.sounds", "cut", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
116 end
117
118 spec.dropEffects = {}
119
120 self.xmlFile:iterate("vehicle.mower.dropEffects.dropEffect", function(_, key)
121 local effects = g_effectManager:loadEffect(self.xmlFile, key, self.components, self, self.i3dMappings)
122 if effects ~= nil then
123 local dropEffect = {}
124 dropEffect.effects = effects
125 dropEffect.dropAreaIndex = self.xmlFile:getValue(key .. "#dropAreaIndex", 1)
126 dropEffect.workAreaIndex = self.xmlFile:getValue(key .. "#workAreaIndex", 1)
127 if self:getWorkAreaByIndex(dropEffect.dropAreaIndex) ~= nil then
128 if self:getWorkAreaByIndex(dropEffect.workAreaIndex) ~= nil then
129 dropEffect.activeTime = -1
130 dropEffect.activeTimeDuration = 750
131 dropEffect.isActive = false
132 dropEffect.isActiveSent = false
133 table.insert(spec.dropEffects, dropEffect)
134 else
135 Logging.xmlWarning(self.xmlFile, "Invalid workAreaIndex '%s' in '%s'", dropEffect.workAreaIndex, key)
136 end
137 else
138 Logging.xmlWarning(self.xmlFile, "Invalid dropAreaIndex '%s' in '%s'", dropEffect.dropAreaIndex, key)
139 end
140 end
141 end)
142
143 if spec.dropAreas == nil then
144 spec.dropAreas = {}
145 end
146
147 spec.fruitTypeConverters = {}
148 local converter = self.xmlFile:getValue("vehicle.mower#fruitTypeConverter")
149 if converter ~= nil then
150 local data = g_fruitTypeManager:getConverterDataByName(converter)
151 if data ~= nil then
152 for input, converted in pairs(data) do
153 spec.fruitTypeConverters[input] = converted
154 end
155 end
156 else
157 print(string.format("Warning: Missing fruit type converter in '%s'", self.configFileName))
158 end
159
160 spec.fillUnitIndex = self.xmlFile:getValue("vehicle.mower#fillUnitIndex")
161 spec.pickupFillScale = self.xmlFile:getValue("vehicle.mower#pickupFillScale", 1)
162
163 spec.toggleWindrowDropEnableText = self.xmlFile:getValue("vehicle.mower.toggleWindrowDrop#enableText", nil, self.customEnvironment, false)
164 spec.toggleWindrowDropDisableText = self.xmlFile:getValue("vehicle.mower.toggleWindrowDrop#disableText", nil, self.customEnvironment, false)
165
166 spec.toggleWindrowDropAnimation = self.xmlFile:getValue("vehicle.mower.toggleWindrowDrop#animationName")
167 spec.enableWindrowDropAnimationSpeed = self.xmlFile:getValue("vehicle.mower.toggleWindrowDrop#animationEnableSpeed", 1)
168 spec.disableWindrowDropAnimationSpeed = self.xmlFile:getValue("vehicle.mower.toggleWindrowDrop#animationDisableSpeed", -spec.enableWindrowDropAnimationSpeed)
169
170 spec.useWindrowDropAreas = self.xmlFile:getValue("vehicle.mower.toggleWindrowDrop#startEnabled", false)
171
172 spec.workAreaParameters = {}
173 spec.workAreaParameters.lastChangedArea = 0
174 spec.workAreaParameters.lastStatsArea = 0
175 spec.workAreaParameters.lastTotalArea = 0
176 spec.workAreaParameters.lastUsedAreas = 0
177 spec.workAreaParameters.lastUsedAreasSum = 0
178 spec.workAreaParameters.lastUsedAreasPct = 0
179 spec.workAreaParameters.lastUsedAreasTime = 0
180 spec.workAreaParameters.lastCutTime = -math.huge
181 spec.workAreaParameters.lastInputFruitType = FruitType.UNKNOWN
182 spec.workAreaParameters.lastInputGrowthState = 0
183
184 spec.isWorking = false
185 spec.isCutting = false
186 spec.lastDropTime = -math.huge
187
188 spec.stoneLastState = 0
189 spec.stoneWearMultiplierData = g_currentMission.stoneSystem:getWearMultiplierByType("MOWER")
190
191 spec.dirtyFlag = self:getNextDirtyFlag()
192
193 if self.addAITerrainDetailRequiredRange ~= nil then
194 local mission = g_currentMission
195 local _, groundTypeFirstChannel, groundTypeNumChannels = mission.fieldGroundSystem:getDensityMapData(FieldDensityMap.GROUND_TYPE)
196 local sowingValue = mission.fieldGroundSystem:getFieldGroundValue(FieldGroundType.SOWN)
197 local grassValue = mission.fieldGroundSystem:getFieldGroundValue(FieldGroundType.GRASS)
198 self:addAITerrainDetailRequiredRange(grassValue, grassValue, groundTypeFirstChannel, groundTypeNumChannels)
199 self:addAITerrainDetailRequiredRange(sowingValue, sowingValue, groundTypeFirstChannel, groundTypeNumChannels)
200 end
201
202 if self.addAIFruitRequirement ~= nil then
203 for inputFruitType, _ in pairs(spec.fruitTypeConverters) do
204 local desc = g_fruitTypeManager:getFruitTypeByIndex(inputFruitType)
205 self:addAIFruitRequirement(desc.index, desc.minHarvestingGrowthState, desc.maxHarvestingGrowthState)
206 end
207 end
208end

onPostLoad

Description
Called after loading
Definition
onPostLoad(table savegame)
Arguments
tablesavegamesavegame
Code
213function Mower:onPostLoad(savegame)
214 local spec = self.spec_mower
215 spec.workAreas = self:getTypedWorkAreas(WorkAreaType.MOWER)
216 for i=1, #spec.workAreas do
217 local workArea = spec.workAreas[i]
218 workArea.dropEffects = {}
219 for _, dropEffect in pairs(spec.dropEffects) do
220 if dropEffect.workAreaIndex == workArea.index then
221 table.insert(workArea.dropEffects, dropEffect)
222 end
223 end
224 end
225end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
248function Mower:onReadStream(streamId, connection)
249 local spec = self.spec_mower
250 if spec.toggleWindrowDropEnableText ~= nil and spec.toggleWindrowDropDisableText ~= nil then
251 local useMowerWindrowDropAreas = streamReadBool(streamId)
252 self:setUseMowerWindrowDropAreas(useMowerWindrowDropAreas, true)
253 end
254end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
272function Mower:onReadUpdateStream(streamId, timestamp, connection)
273 if connection:getIsServer() then
274 local spec = self.spec_mower
275
276 if #spec.dropEffects > 0 then
277 if streamReadBool(streamId) then
278 for _, dropEffect in ipairs(spec.dropEffects) do
279 dropEffect.fillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS)
280 self:setDropEffectEnabled(dropEffect, streamReadBool(streamId))
281 end
282 end
283 else
284 self:setCutSoundEnabled(streamReadBool(streamId))
285 end
286 end
287end

onRegisterActionEvents

Description
Definition
onRegisterActionEvents()
Code
530function Mower:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
531 if self.isClient then
532 local spec = self.spec_mower
533 self:clearActionEventsTable(spec.actionEvents)
534
535 if isActiveForInputIgnoreSelection then
536 if spec.toggleWindrowDropEnableText ~= nil and spec.toggleWindrowDropDisableText ~= nil then
537 local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.IMPLEMENT_EXTRA3, self, Mower.actionEventToggleDrop, false, true, false, true, nil)
538 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_LOW)
539 Mower.updateActionEventToggleDrop(self)
540 end
541 end
542 end
543end

onStartWorkAreaProcessing

Description
Definition
onStartWorkAreaProcessing()
Code
617function Mower:onStartWorkAreaProcessing(dt)
618 local spec = self.spec_mower
619
620 if self.isServer then
621 for _, dropEffect in pairs(spec.dropEffects) do
622 -- activate or deactivate dropEffect. Could be 1 frame delayed but safes a second for loop in onEndWorkAreaProcessing
623 if dropEffect.isActive ~= dropEffect.isActiveSent then
624 dropEffect.isActiveSent = dropEffect.isActive
625 self:setDropEffectEnabled(dropEffect, dropEffect.isActiveSent)
626 self:raiseDirtyFlags(spec.dirtyFlag)
627 end
628
629 dropEffect.isActive = false
630 end
631 end
632
633 local workAreas = self:getTypedWorkAreas(WorkAreaType.MOWER)
634 for i=1, #workAreas do
635 local workArea = workAreas[i]
636 workArea.pickedUpLiters = 0
637 end
638
639 spec.workAreaParameters.lastChangedArea = 0
640 spec.workAreaParameters.lastStatsArea = 0
641 spec.workAreaParameters.lastTotalArea = 0
642
643 spec.isWorking = false
644end

onTurnedOff

Description
Called on turn off
Definition
onTurnedOff(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
604function Mower:onTurnedOff()
605 if self.isClient then
606 local spec = self.spec_mower
607 for _, dropEffect in pairs(spec.dropEffects) do
608 self:setDropEffectEnabled(dropEffect, false)
609 end
610
611 g_animationManager:stopAnimations(spec.animationNodes)
612 end
613end

onTurnedOn

Description
Called on turn off
Definition
onTurnedOn(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
594function Mower:onTurnedOn()
595 if self.isClient then
596 local spec = self.spec_mower
597 g_animationManager:startAnimations(spec.animationNodes)
598 end
599end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
260function Mower:onWriteStream(streamId, connection)
261 local spec = self.spec_mower
262 if spec.toggleWindrowDropEnableText ~= nil and spec.toggleWindrowDropDisableText ~= nil then
263 streamWriteBool(streamId, spec.useWindrowDropAreas)
264 end
265end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
294function Mower:onWriteUpdateStream(streamId, connection, dirtyMask)
295 if not connection:getIsServer() then
296 local spec = self.spec_mower
297
298 if #spec.dropEffects > 0 then
299 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
300 for _, dropEffect in ipairs(spec.dropEffects) do
301 streamWriteUIntN(streamId, dropEffect.fillType or FillType.UNKNOWN, FillTypeManager.SEND_NUM_BITS)
302 streamWriteBool(streamId, dropEffect.isActiveSent)
303 end
304 end
305 else
306 streamWriteBool(streamId, spec.isCutting)
307 end
308 end
309end

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
55function Mower.prerequisitesPresent(specializations)
56 return SpecializationUtil.hasSpecialization(WorkArea, specializations) and SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations)
57end

processDropArea

Description
Definition
processDropArea()
Code
384function Mower:processDropArea(dropArea, dt)
385 if dropArea.litersToDrop > g_densityMapHeightManager:getMinValidLiterValue(dropArea.fillType) then
386 local dropped, lineOffset
387 local xs,_,zs = getWorldTranslation(dropArea.start)
388 local xw,_,zw = getWorldTranslation(dropArea.width)
389 local xh,_,zh = getWorldTranslation(dropArea.height)
390
391 local f = math.random() -- any benefit from randomness in this case?
392 local sx = xs + (f * (xh - xs))
393 local sz = zs + (f * (zh - zs))
394 local sy = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, sx,0,sz)
395
396 f = math.random()
397 local ex = xw + (f * (xh - xs))
398 local ez = zw + (f * (zh - zs))
399 local ey = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, ex,0,ez)
400
401 dropped, lineOffset = DensityMapHeightUtil.tipToGroundAroundLine(self, dropArea.litersToDrop, dropArea.fillType, sx,sy,sz, ex,ey,ez, 0, nil, dropArea.dropLineOffset, false, nil, false)
402
403 dropArea.litersToDrop = dropArea.litersToDrop - dropped
404 dropArea.dropLineOffset = lineOffset
405
406 if dropped ~= 0 then
407 self.spec_mower.lastDropTime = g_time
408 end
409 end
410end

processMowerArea

Description
Definition
processMowerArea()
Code
313function Mower:processMowerArea(workArea, dt)
314 local spec = self.spec_mower
315
316 local xs,_,zs = getWorldTranslation(workArea.start)
317 local xw,_,zw = getWorldTranslation(workArea.width)
318 local xh,_,zh = getWorldTranslation(workArea.height)
319
320 if self:getLastSpeed() > 1 then
321 spec.isWorking = true
322 spec.stoneLastState = FSDensityMapUtil.getStoneArea(xs, zs, xw, zw, xh, zh)
323 else
324 spec.stoneLastState = 0
325 end
326
327 local limitToField = self:getIsAIActive()
328 for inputFruitType, converterData in pairs(spec.fruitTypeConverters) do
329 local changedArea, totalArea, sprayFactor, plowFactor, limeFactor, weedFactor, stubbleFactor, rollerFactor, _, growthState, _ = FSDensityMapUtil.updateMowerArea(inputFruitType, xs, zs, xw, zw, xh, zh, limitToField)
330
331 if changedArea > 0 then
332 local multiplier = g_currentMission:getHarvestScaleMultiplier(inputFruitType, sprayFactor, plowFactor, limeFactor, weedFactor, stubbleFactor, rollerFactor)
333 changedArea = changedArea * multiplier
334
335 local pixelToSqm = g_currentMission:getFruitPixelsToSqm()
336 local sqm = changedArea * pixelToSqm
337 local litersToDrop = sqm * g_fruitTypeManager:getFillTypeLiterPerSqm(converterData.fillTypeIndex, 1)
338
339 workArea.lastPickupLiters = litersToDrop
340 workArea.pickedUpLiters = litersToDrop
341
342 local dropArea = self:getDropArea(workArea)
343 if dropArea ~= nil then
344 dropArea.litersToDrop = dropArea.litersToDrop + litersToDrop
345 dropArea.fillType = converterData.fillTypeIndex
346 dropArea.workAreaIndex = workArea.index
347
348 -- if there is already dryGrass on the field and we cannot tip grass on the same spot
349 -- we pickup the dryGrass and drop it as grass again
350 if dropArea.fillType == FillType.GRASS_WINDROW then
351 local lsx, lsy, lsz, lex, ley, lez, radius = DensityMapHeightUtil.getLineByArea(workArea.start, workArea.width, workArea.height, true)
352 local pickup
353 pickup, workArea.lineOffset = DensityMapHeightUtil.tipToGroundAroundLine(self, -math.huge, FillType.DRYGRASS_WINDROW, lsx, lsy, lsz, lex, ley, lez, radius, nil, workArea.lineOffset or 0, false, nil, false)
354 dropArea.litersToDrop = dropArea.litersToDrop - pickup
355 end
356
357 -- limit liters to drop so we don't buffer unlimited amount of grass
358 dropArea.litersToDrop = math.min(dropArea.litersToDrop, 1000)
359 elseif spec.fillUnitIndex ~= nil then
360 if self.isServer then
361 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, litersToDrop, converterData.fillTypeIndex, ToolType.UNDEFINED)
362 end
363 end
364
365 spec.workAreaParameters.lastInputFruitType = inputFruitType
366 spec.workAreaParameters.lastInputGrowthState = growthState
367 spec.workAreaParameters.lastCutTime = g_time
368
369 spec.workAreaParameters.lastChangedArea = spec.workAreaParameters.lastChangedArea + changedArea
370 spec.workAreaParameters.lastStatsArea = spec.workAreaParameters.lastStatsArea + changedArea
371 spec.workAreaParameters.lastTotalArea = spec.workAreaParameters.lastTotalArea + totalArea
372
373 spec.workAreaParameters.lastUsedAreas = spec.workAreaParameters.lastUsedAreas + 1
374 end
375 end
376
377 spec.workAreaParameters.lastUsedAreasSum = spec.workAreaParameters.lastUsedAreasSum + 1
378
379 return spec.workAreaParameters.lastChangedArea, spec.workAreaParameters.lastTotalArea
380end

registerEventListeners

Description
Definition
registerEventListeners()
Code
82function Mower.registerEventListeners(vehicleType)
83 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Mower)
84 SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", Mower)
85 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Mower)
86 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Mower)
87 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Mower)
88 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Mower)
89 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Mower)
90 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Mower)
91 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", Mower)
92 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", Mower)
93 SpecializationUtil.registerEventListener(vehicleType, "onStartWorkAreaProcessing", Mower)
94 SpecializationUtil.registerEventListener(vehicleType, "onEndWorkAreaProcessing", Mower)
95end

registerFunctions

Description
Definition
registerFunctions()
Code
61function Mower.registerFunctions(vehicleType)
62 SpecializationUtil.registerFunction(vehicleType, "processMowerArea", Mower.processMowerArea)
63 SpecializationUtil.registerFunction(vehicleType, "processDropArea", Mower.processDropArea)
64 SpecializationUtil.registerFunction(vehicleType, "getDropArea", Mower.getDropArea)
65 SpecializationUtil.registerFunction(vehicleType, "setDropEffectEnabled", Mower.setDropEffectEnabled)
66 SpecializationUtil.registerFunction(vehicleType, "setCutSoundEnabled", Mower.setCutSoundEnabled)
67 SpecializationUtil.registerFunction(vehicleType, "setUseMowerWindrowDropAreas", Mower.setUseMowerWindrowDropAreas)
68end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
72function Mower.registerOverwrittenFunctions(vehicleType)
73 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadWorkAreaFromXML", Mower.loadWorkAreaFromXML)
74 SpecializationUtil.registerOverwrittenFunction(vehicleType, "doCheckSpeedLimit", Mower.doCheckSpeedLimit)
75 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", Mower.getCanBeSelected)
76 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDirtMultiplier", Mower.getDirtMultiplier)
77 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getWearMultiplier", Mower.getWearMultiplier)
78end

setCutSoundEnabled

Description
Enable cut sounds
Definition
setCutSoundEnabled(boolean isActive)
Arguments
booleanisActivenew is active state
Code
455function Mower:setCutSoundEnabled(isActive)
456 if self.isClient then
457 local spec = self.spec_mower
458
459 if isActive then
460 for i=1, #spec.samples.cut do
461 if not g_soundManager:getIsSamplePlaying(spec.samples.cut[i]) then
462 g_soundManager:playSample(spec.samples.cut[i])
463 end
464 end
465 else
466 for i=1, #spec.samples.cut do
467 if g_soundManager:getIsSamplePlaying(spec.samples.cut[i]) then
468 g_soundManager:stopSample(spec.samples.cut[i])
469 end
470 end
471 end
472 end
473end

setDropEffectEnabled

Description
Enable mower effect
Definition
setDropEffectEnabled(table mowerEffect, boolean isActive)
Arguments
tablemowerEffectmower effect
booleanisActivenew is active state
Code
440function Mower:setDropEffectEnabled(dropEffect, isActive)
441 dropEffect.isActive = isActive
442 if self.isClient then
443 if isActive then
444 g_effectManager:setFillType(dropEffect.effects, dropEffect.fillType)
445 g_effectManager:startEffects(dropEffect.effects)
446 else
447 g_effectManager:stopEffects(dropEffect.effects)
448 end
449 end
450end

setUseMowerWindrowDropAreas

Description
Toggle use of windrower drop areas
Definition
setUseMowerWindrowDropAreas(boolean useMowerWindrowDropAreas, boolean noEventSend)
Arguments
booleanuseMowerWindrowDropAreasuse mower windrow drop areas
booleannoEventSendno event send
Code
480function Mower:setUseMowerWindrowDropAreas(useMowerWindrowDropAreas, noEventSend)
481 local spec = self.spec_mower
482 if useMowerWindrowDropAreas ~= spec.useWindrowDropAreas then
483 MowerToggleWindrowDropEvent.sendEvent(self, useMowerWindrowDropAreas, noEventSend)
484 spec.useWindrowDropAreas = useMowerWindrowDropAreas
485
486 if spec.toggleWindrowDropAnimation ~= nil and self.playAnimation ~= nil then
487 local speed = spec.enableWindrowDropAnimationSpeed
488 if not useMowerWindrowDropAreas then
489 speed = spec.disableWindrowDropAnimationSpeed
490 end
491 self:playAnimation(spec.toggleWindrowDropAnimation, speed, nil, true)
492 end
493 end
494end

updateActionEventToggleDrop

Description
Definition
updateActionEventToggleDrop()
Code
732function Mower.updateActionEventToggleDrop(self)
733 local spec = self.spec_mower
734 local actionEvent = spec.actionEvents[InputAction.IMPLEMENT_EXTRA3]
735 if actionEvent ~= nil then
736 local text = string.format(spec.toggleWindrowDropDisableText, self.typeDesc)
737 if not spec.useWindrowDropAreas then
738 text = string.format(spec.toggleWindrowDropEnableText, self.typeDesc)
739 end
740 g_inputBinding:setActionEventText(actionEvent.actionEventId, text)
741 end
742end