Script v1_7_1_0
- AI
- Animals
- Collections
- Contracts
- Debug
- Economy
- Elements
- EnvironmentalScore
- Errors
- Events
- GUI
- Handtools
- Hud
- I3d
- Input
- Jobs
- Maps
- Materials
- Misc
- Objects
- Parameters
- Placeables
- Placement
- Player
- Shop
- Sounds
- Specialization
- Specializations
- AIConveyorBelt
- AIDrivable
- AIFieldWorker
- AIImplement
- AIJobVehicle
- AIVehicle
- AIVehicleObstacle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- AutoLoader
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BigBag
- BunkerSiloCompacter
- BunkerSiloInteractor
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- CropSensor
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- ExtendedAIVehicle
- ExtendedCombine
- ExtendedMotorized
- ExtendedMower
- ExtendedSowingMachine
- ExtendedSprayer
- ExtendedWearable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- HeadlandAnimation
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- InlineWrapper
- JigglingParts
- Leveler
- LicensePlates
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- ManureSensor
- MixerWagon
- Motorized
- Mountable
- Mower
- Mulcher
- MultipleItemPurchase
- Pallet
- Pickup
- Pipe
- PlaceableAI
- PlaceableAnimatedObjects
- PlaceableBeehive
- PlaceableBeehivePalletSpa...
- PlaceableBunkerSilo
- PlaceableBuyingStation
- PlaceableCartridgePlayer
- PlaceableChargingStation
- PlaceableClearAreas
- PlaceableColorable
- PlaceableDeletedNodes
- PlaceableDoghouse
- PlaceableDynamicallyLoade...
- PlaceableFarmhouse
- PlaceableFence
- PlaceableFoliageAreas
- PlaceableGreenhouse
- PlaceableHighPressureWash...
- PlaceableHotspots
- PlaceableHusbandry
- PlaceableHusbandryAnimals
- PlaceableHusbandryFeeding...
- PlaceableHusbandryFence
- PlaceableHusbandryFood
- PlaceableHusbandryLiquidM...
- PlaceableHusbandryMilk
- PlaceableHusbandryPallets
- PlaceableHusbandryStraw
- PlaceableHusbandryWater
- PlaceableIncomePerHour
- PlaceableIndoorAreas
- PlaceableInfoTrigger
- PlaceableLeveling
- PlaceableLights
- PlaceableManureHeap
- PlaceablePlacement
- PlaceableProductionPoint
- PlaceableSellingStation
- PlaceableSilo
- PlaceableSiloExtension
- PlaceableSolarPanels
- PlaceableTipOcclusionArea...
- PlaceableTrainSystem
- PlaceableTriggerMarkers
- PlaceableVine
- PlaceableWardrobe
- PlaceableWeatherStation
- PlaceableWeighingStation
- PlaceableWindTurbine
- PlaceableWorkshop
- Plow
- PlowPacker
- PowerConsumer
- PowerTakeOffs
- PrecisionFarmingStatistic
- PushHandTool
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- RTKStation
- SaltSpreader
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SoilSampler
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StonePicker
- StrawBlower
- StumpCutter
- SupportVehicle
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TestAreas
- TipOccluder
- Trailer
- TreePlanter
- TreeSaplingPallet
- TreeSaw
- TurnOnVehicle
- VariableWorkWidth
- VehicleSettings
- VineCutter
- VineDetector
- VinePrepruner
- Washable
- WaterTrailer
- Wearable
- Weeder
- WeedSpotSpray
- Wheels
- WindBending
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- StateMachine
- Statistics
- Tasks
- Triggers
- Utils
- Vehicles
Engine v1_7_1_0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- general
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- NoteNode
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- VoiceChat
- XML
Foundation Reference
Mower
DescriptionSpecialization for vehicles with grass mowing functionalityFunctions
- actionEventToggleDrop
- doCheckSpeedLimit
- getCanBeSelected
- getDefaultSpeedLimit
- getDirtMultiplier
- getDropArea
- getMowerLoadPercentage
- getWearMultiplier
- initSpecialization
- loadWorkAreaFromXML
- onDelete
- onEndWorkAreaProcessing
- onLoad
- onPostLoad
- onReadStream
- onReadUpdateStream
- onRegisterActionEvents
- onStartWorkAreaProcessing
- onTurnedOff
- onTurnedOn
- onWriteStream
- onWriteUpdateStream
- prerequisitesPresent
- processDropArea
- processMowerArea
- registerEventListeners
- registerFunctions
- registerOverwrittenFunctions
- setCutSoundEnabled
- setDropEffectEnabled
- setUseMowerWindrowDropAreas
- updateActionEventToggleDrop
actionEventToggleDrop
DescriptionDefinitionactionEventToggleDrop()Code
725 | function Mower.actionEventToggleDrop(self, actionName, inputValue, callbackState, isAnalog) |
726 | local spec = self.spec_mower |
727 | self:setUseMowerWindrowDropAreas(not spec.useWindrowDropAreas) |
728 | end |
doCheckSpeedLimit
DescriptionReturns if speed limit should be checkedDefinition
doCheckSpeedLimit()Return Values
boolean | checkSpeedlimit | check speed limit |
548 | function Mower:doCheckSpeedLimit(superFunc) |
549 | return superFunc(self) or (self:getIsTurnedOn() and (self.getIsLowered == nil or self:getIsLowered())) |
550 | end |
getCanBeSelected
DescriptionDefinitiongetCanBeSelected()Code
554 | function Mower:getCanBeSelected(superFunc) |
555 | return true |
556 | end |
getDefaultSpeedLimit
DescriptionReturns default speed limitDefinition
getDefaultSpeedLimit()Return Values
float | speedLimit | speed limit |
719 | function Mower.getDefaultSpeedLimit() |
720 | return 20 |
721 | end |
getDirtMultiplier
DescriptionDefinitiongetDirtMultiplier()Code
560 | function 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 |
570 | end |
getDropArea
DescriptionDefinitiongetDropArea()Code
414 | function 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 |
434 | end |
getMowerLoadPercentage
DescriptionDefinitiongetMowerLoadPercentage()Code
707 | function Mower:getMowerLoadPercentage() |
708 | if self.spec_mower ~= nil then |
709 | return self.spec_mower.workAreaParameters.lastUsedAreasPct |
710 | end |
711 | |
712 | return 0 |
713 | end |
getWearMultiplier
DescriptionDefinitiongetWearMultiplier()Code
574 | function 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 |
589 | end |
initSpecialization
DescriptionCalled on specialization initializingDefinition
initSpecialization()Code
17 | function 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() |
49 | end |
loadWorkAreaFromXML
DescriptionLoads work areas from xmlDefinition
loadWorkAreaFromXML(table workArea, integer xmlFile, string key)Arguments
table | workArea | workArea |
integer | xmlFile | id of xml object |
string | key | key |
boolean | success | success |
502 | function 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 |
526 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
229 | function 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 |
242 | end |
onEndWorkAreaProcessing
DescriptionDefinitiononEndWorkAreaProcessing()Code
648 | function 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 |
703 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
101 | function 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 |
208 | end |
onPostLoad
DescriptionCalled after loadingDefinition
onPostLoad(table savegame)Arguments
table | savegame | savegame |
213 | function 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 |
225 | end |
onReadStream
DescriptionCalled on client side on joinDefinition
onReadStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
248 | function 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 |
254 | end |
onReadUpdateStream
DescriptionCalled on on updateDefinition
onReadUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | stream ID |
integer | timestamp | timestamp |
table | connection | connection |
272 | function 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 |
287 | end |
onRegisterActionEvents
DescriptionDefinitiononRegisterActionEvents()Code
530 | function 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 |
543 | end |
onStartWorkAreaProcessing
DescriptionDefinitiononStartWorkAreaProcessing()Code
617 | function 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 |
644 | end |
onTurnedOff
DescriptionCalled on turn offDefinition
onTurnedOff(boolean noEventSend)Arguments
boolean | noEventSend | no event send |
604 | function 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 |
613 | end |
onTurnedOn
DescriptionCalled on turn offDefinition
onTurnedOn(boolean noEventSend)Arguments
boolean | noEventSend | no event send |
594 | function Mower:onTurnedOn() |
595 | if self.isClient then |
596 | local spec = self.spec_mower |
597 | g_animationManager:startAnimations(spec.animationNodes) |
598 | end |
599 | end |
onWriteStream
DescriptionCalled on server side on joinDefinition
onWriteStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
260 | function 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 |
265 | end |
onWriteUpdateStream
DescriptionCalled on on updateDefinition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)Arguments
integer | streamId | stream ID |
table | connection | connection |
integer | dirtyMask | dirty mask |
294 | function 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 |
309 | end |
prerequisitesPresent
DescriptionChecks if all prerequisite specializations are loadedDefinition
prerequisitesPresent(table specializations)Arguments
table | specializations | specializations |
boolean | hasPrerequisite | true if all prerequisite specializations are loaded |
55 | function Mower.prerequisitesPresent(specializations) |
56 | return SpecializationUtil.hasSpecialization(WorkArea, specializations) and SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations) |
57 | end |
processDropArea
DescriptionDefinitionprocessDropArea()Code
384 | function 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 |
410 | end |
processMowerArea
DescriptionDefinitionprocessMowerArea()Code
313 | function 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 |
380 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
82 | function 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) |
95 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
61 | function 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) |
68 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
72 | function 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) |
78 | end |
setCutSoundEnabled
DescriptionEnable cut soundsDefinition
setCutSoundEnabled(boolean isActive)Arguments
boolean | isActive | new is active state |
455 | function 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 |
473 | end |
setDropEffectEnabled
DescriptionEnable mower effectDefinition
setDropEffectEnabled(table mowerEffect, boolean isActive)Arguments
table | mowerEffect | mower effect |
boolean | isActive | new is active state |
440 | function 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 |
450 | end |
setUseMowerWindrowDropAreas
DescriptionToggle use of windrower drop areasDefinition
setUseMowerWindrowDropAreas(boolean useMowerWindrowDropAreas, boolean noEventSend)Arguments
boolean | useMowerWindrowDropAreas | use mower windrow drop areas |
boolean | noEventSend | no event send |
480 | function 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 |
494 | end |
updateActionEventToggleDrop
DescriptionDefinitionupdateActionEventToggleDrop()Code
732 | function 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 |
742 | end |