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
Weeder
DescriptionSpecialization for weeder tool used to remove growing weeds on fieldsFunctions
- doCheckSpeedLimit
- getDefaultSpeedLimit
- getDirtMultiplier
- getIsWorkAreaActive
- getWearMultiplier
- initSpecialization
- loadGroundParticleMapping
- loadWorkAreaFromXML
- onDeactivate
- onDelete
- onEndWorkAreaProcessing
- onLoad
- onPostAttach
- onStartWorkAreaProcessing
- onStateChange
- onUpdateTick
- prerequisitesPresent
- processWeederArea
- registerEventListeners
- registerFunctions
- registerOverwrittenFunctions
- updateWeederAIRequirements
doCheckSpeedLimit
DescriptionReturns if speed limit should be checkedDefinition
doCheckSpeedLimit()Return Values
boolean | checkSpeedlimit | check speed limit |
270 | function Weeder:doCheckSpeedLimit(superFunc) |
271 | return superFunc(self) or self:getIsImplementChainLowered() |
272 | end |
getDefaultSpeedLimit
DescriptionReturns default speed limitDefinition
getDefaultSpeedLimit()Return Values
float | speedLimit | speed limit |
400 | function Weeder.getDefaultSpeedLimit() |
401 | return 15 |
402 | end |
getDirtMultiplier
DescriptionReturns current dirt multiplierDefinition
getDirtMultiplier()Return Values
float | dirtMultiplier | current dirt multiplier |
277 | function Weeder:getDirtMultiplier(superFunc) |
278 | local spec = self.spec_weeder |
279 | local multiplier = superFunc(self) |
280 | |
281 | if spec.isWorking then |
282 | multiplier = multiplier + self:getWorkDirtMultiplier() * self:getLastSpeed() / self.speedLimit |
283 | end |
284 | |
285 | return multiplier |
286 | end |
getIsWorkAreaActive
DescriptionReturns true if work area is activeDefinition
getIsWorkAreaActive(table workArea)Arguments
table | workArea | workArea |
boolean | isActive | work area is active |
252 | function Weeder:getIsWorkAreaActive(superFunc, workArea) |
253 | if workArea.type == WorkAreaType.WEEDER then |
254 | local isActive = true |
255 | if workArea.requiresGroundContact and workArea.groundReferenceNode ~= nil then |
256 | isActive = isActive and self:getIsGroundReferenceNodeActive(workArea.groundReferenceNode) |
257 | end |
258 | if isActive and workArea.disableBackwards then |
259 | isActive = isActive and self.movingDirection > 0 |
260 | end |
261 | return isActive |
262 | end |
263 | |
264 | return superFunc(self, workArea) |
265 | end |
getWearMultiplier
DescriptionReturns current wear multiplierDefinition
getWearMultiplier()Return Values
float | dirtMultiplier | current wear multiplier |
291 | function Weeder:getWearMultiplier(superFunc) |
292 | local spec = self.spec_weeder |
293 | local multiplier = superFunc(self) |
294 | |
295 | if spec.isWorking then |
296 | local stoneMultiplier = 1 |
297 | if spec.stoneLastState ~= 0 and spec.stoneWearMultiplierData ~= nil then |
298 | stoneMultiplier = spec.stoneWearMultiplierData[spec.stoneLastState] or 1 |
299 | end |
300 | |
301 | multiplier = multiplier + self:getWorkWearMultiplier() * self:getLastSpeed() / self.speedLimit * stoneMultiplier |
302 | end |
303 | |
304 | return multiplier |
305 | end |
initSpecialization
DescriptionCalled on specialization initializingDefinition
initSpecialization()Code
15 | function Weeder.initSpecialization() |
16 | g_workAreaTypeManager:addWorkAreaType("weeder", true) |
17 | |
18 | local schema = Vehicle.xmlSchema |
19 | schema:setXMLSpecializationType("Weeder") |
20 | |
21 | SoundManager.registerSampleXMLPaths(schema, "vehicle.weeder.sounds", "work") |
22 | schema:register(XMLValueType.BOOL, "vehicle.weeder#isHoe", "Is hoe weeder", false) |
23 | schema:register(XMLValueType.BOOL, "vehicle.weeder#isGrasslandWeeder", "Is a grassland weeder (grass fertilizer state + grass grwoth reset)", false) |
24 | |
25 | schema:register(XMLValueType.BOOL, WorkParticles.PARTICLE_MAPPING_XML_PATH .. "#adjustColor", "Adjust color", false) |
26 | |
27 | schema:setXMLSpecializationType() |
28 | end |
loadGroundParticleMapping
DescriptionLoad ground particle mapping from xml fileDefinition
loadGroundParticleMapping(integer xmlFile, string key, table mapping, integer index, integer i3dNode)Arguments
integer | xmlFile | id of xml object |
string | key | key |
table | mapping | mapping |
integer | index | index |
integer | i3dNode | id of i3d node |
boolean | success | success |
315 | function Weeder:loadGroundParticleMapping(superFunc, xmlFile, key, mapping, index, i3dNode) |
316 | if not superFunc(self, xmlFile, key, mapping, index, i3dNode) then |
317 | return false |
318 | end |
319 | |
320 | mapping.adjustColor = xmlFile:getValue(key.."#adjustColor", false) |
321 | if mapping.adjustColor then |
322 | local spec = self.spec_weeder |
323 | if spec.colorParticleSystems == nil then |
324 | spec.colorParticleSystems = {} |
325 | end |
326 | mapping.lastColor = {} |
327 | |
328 | table.insert(spec.colorParticleSystems, mapping) |
329 | end |
330 | |
331 | return true |
332 | 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 |
240 | function Weeder:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key) |
241 | if workArea.type == WorkAreaType.DEFAULT then |
242 | workArea.type = WorkAreaType.WEEDER |
243 | end |
244 | |
245 | return superFunc(self, workArea, xmlFile, key) |
246 | end |
onDeactivate
DescriptionDefinitiononDeactivate()Code
379 | function Weeder:onDeactivate() |
380 | if self.isClient then |
381 | local spec = self.spec_weeder |
382 | g_soundManager:stopSamples(spec.samples) |
383 | spec.isWorkSamplePlaying = false |
384 | end |
385 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
102 | function Weeder:onDelete() |
103 | local spec = self.spec_weeder |
104 | g_soundManager:deleteSamples(spec.samples) |
105 | end |
onEndWorkAreaProcessing
DescriptionDefinitiononEndWorkAreaProcessing()Code
345 | function Weeder:onEndWorkAreaProcessing(dt, hasProcessed) |
346 | local spec = self.spec_weeder |
347 | |
348 | if self.isServer then |
349 | if spec.workAreaParameters.lastStatsArea > 0 then |
350 | self:updateLastWorkedArea(spec.workAreaParameters.lastStatsArea) |
351 | end |
352 | end |
353 | |
354 | if self.isClient then |
355 | if spec.isWorking then |
356 | if not spec.isWorkSamplePlaying then |
357 | g_soundManager:playSample(spec.samples.work) |
358 | spec.isWorkSamplePlaying = true |
359 | end |
360 | else |
361 | if spec.isWorkSamplePlaying then |
362 | g_soundManager:stopSample(spec.samples.work) |
363 | spec.isWorkSamplePlaying = false |
364 | end |
365 | end |
366 | end |
367 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
73 | function Weeder:onLoad(savegame) |
74 | local spec = self.spec_weeder |
75 | |
76 | if self.isClient then |
77 | spec.samples = {} |
78 | spec.samples.work = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.weeder.sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
79 | spec.isWorkSamplePlaying = false |
80 | end |
81 | |
82 | spec.startActivationTimeout = 2000 |
83 | spec.startActivationTime = 0 |
84 | |
85 | spec.isHoeWeeder = self.xmlFile:getValue("vehicle.weeder#isHoe", false) |
86 | spec.isGrasslandWeeder = self.xmlFile:getValue("vehicle.weeder#isGrasslandWeeder", false) |
87 | |
88 | spec.workAreaParameters = {} |
89 | spec.workAreaParameters.lastArea = 0 |
90 | spec.workAreaParameters.lastStatsArea = 0 |
91 | |
92 | spec.isWorking = false |
93 | |
94 | spec.stoneLastState = 0 |
95 | spec.stoneWearMultiplierData = g_currentMission.stoneSystem:getWearMultiplierByType("WEEDER") |
96 | |
97 | self:updateWeederAIRequirements() |
98 | end |
onPostAttach
DescriptionCalled if vehicle gets attachedDefinition
onPostAttach(table attacherVehicle, integer inputJointDescIndex, integer jointDescIndex)Arguments
table | attacherVehicle | attacher vehicle |
integer | inputJointDescIndex | index of input attacher joint |
integer | jointDescIndex | index of attacher joint it gets attached to |
392 | function Weeder:onPostAttach(attacherVehicle, inputJointDescIndex, jointDescIndex) |
393 | local spec = self.spec_weeder |
394 | spec.startActivationTime = g_currentMission.time + spec.startActivationTimeout |
395 | end |
onStartWorkAreaProcessing
DescriptionDefinitiononStartWorkAreaProcessing()Code
336 | function Weeder:onStartWorkAreaProcessing(dt) |
337 | local spec = self.spec_weeder |
338 | spec.isWorking = false |
339 | spec.workAreaParameters.lastArea = 0 |
340 | spec.workAreaParameters.lastStatsArea = 0 |
341 | end |
onStateChange
DescriptionDefinitiononStateChange()Code
371 | function Weeder:onStateChange(state, data) |
372 | if state == Vehicle.STATE_CHANGE_ATTACH or state == Vehicle.STATE_CHANGE_DETACH then |
373 | self:updateWeederAIRequirements() |
374 | end |
375 | end |
onUpdateTick
DescriptionDefinitiononUpdateTick()Code
109 | function Weeder:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
110 | local spec = self.spec_weeder |
111 | |
112 | if spec.isWorking then |
113 | if spec.colorParticleSystems ~= nil then |
114 | for _, mapping in ipairs(spec.colorParticleSystems) do |
115 | local wx, wy, wz = getWorldTranslation(mapping.node) |
116 | |
117 | local isOnField, densityBits = FSDensityMapUtil.getFieldDataAtWorldPosition(wx, wy, wz) |
118 | |
119 | if isOnField then |
120 | mapping.lastColor[1], mapping.lastColor[2], mapping.lastColor[3], _ = g_currentMission.fieldGroundSystem:getFieldGroundTyreTrackColor(densityBits) |
121 | else |
122 | mapping.lastColor[1], mapping.lastColor[2], mapping.lastColor[3], _, _ = getTerrainAttributesAtWorldPos(g_currentMission.terrainRootNode, wx, wy, wz, true, true, true, true, false) |
123 | end |
124 | |
125 | -- interpolate between different ground colors to avoid unrealisitic particle color changes |
126 | if mapping.targetColor == nil then |
127 | mapping.targetColor = {mapping.lastColor[1],mapping.lastColor[2],mapping.lastColor[3]} |
128 | mapping.currentColor = {mapping.lastColor[1],mapping.lastColor[2],mapping.lastColor[3]} |
129 | mapping.alpha = 1 |
130 | end |
131 | |
132 | if mapping.alpha ~= 1 then |
133 | mapping.alpha = math.min(mapping.alpha + dt/1000, 1) |
134 | mapping.currentColor = {MathUtil.vector3ArrayLerp(mapping.lastColor, mapping.targetColor, mapping.alpha)} |
135 | if mapping.alpha == 1 then |
136 | mapping.lastColor = {mapping.currentColor[1], mapping.currentColor[2], mapping.currentColor[3]} |
137 | end |
138 | end |
139 | |
140 | if mapping.alpha == 1 and mapping.lastColor[1] ~= mapping.targetColor[1] and mapping.lastColor[2] ~= mapping.targetColor[2] and mapping.lastColor[3] ~= mapping.targetColor[3] then |
141 | mapping.alpha = 0 |
142 | mapping.targetColor = {mapping.lastColor[1], mapping.lastColor[2], mapping.lastColor[3]} |
143 | end |
144 | |
145 | setShaderParameter(mapping.particleSystem.shape, "psColor", mapping.currentColor[1], mapping.currentColor[2], mapping.currentColor[3], 1, false) |
146 | end |
147 | end |
148 | end |
149 | 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 |
34 | function Weeder.prerequisitesPresent(specializations) |
35 | return SpecializationUtil.hasSpecialization(WorkArea, specializations) and |
36 | SpecializationUtil.hasSpecialization(AttacherJoints, specializations) |
37 | end |
processWeederArea
DescriptionDefinitionprocessWeederArea()Code
153 | function Weeder:processWeederArea(workArea, dt) |
154 | local spec = self.spec_weeder |
155 | local xs,_,zs = getWorldTranslation(workArea.start) |
156 | local xw,_,zw = getWorldTranslation(workArea.width) |
157 | local xh,_,zh = getWorldTranslation(workArea.height) |
158 | local area = FSDensityMapUtil.updateWeederArea(xs,zs, xw,zw, xh,zh, spec.isHoeWeeder) |
159 | |
160 | if spec.isGrasslandWeeder then |
161 | local _area = FSDensityMapUtil.updateGrassRollerArea(xs, zs, xw, zw, xh, zh, false) |
162 | area = math.max(area, _area) |
163 | end |
164 | |
165 | spec.workAreaParameters.lastArea = spec.workAreaParameters.lastArea + area |
166 | spec.workAreaParameters.lastStatsArea = spec.workAreaParameters.lastStatsArea + area |
167 | |
168 | spec.isWorking = self:getLastSpeed() > 0.5 |
169 | if spec.isWorking then |
170 | spec.stoneLastState = FSDensityMapUtil.getStoneArea(xs, zs, xw, zw, xh, zh) |
171 | else |
172 | spec.stoneLastState = 0 |
173 | end |
174 | |
175 | return area, area |
176 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
59 | function Weeder.registerEventListeners(vehicleType) |
60 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", Weeder) |
61 | SpecializationUtil.registerEventListener(vehicleType, "onDelete", Weeder) |
62 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Weeder) |
63 | SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", Weeder) |
64 | SpecializationUtil.registerEventListener(vehicleType, "onPostAttach", Weeder) |
65 | SpecializationUtil.registerEventListener(vehicleType, "onStartWorkAreaProcessing", Weeder) |
66 | SpecializationUtil.registerEventListener(vehicleType, "onEndWorkAreaProcessing", Weeder) |
67 | SpecializationUtil.registerEventListener(vehicleType, "onStateChange", Weeder) |
68 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
41 | function Weeder.registerFunctions(vehicleType) |
42 | SpecializationUtil.registerFunction(vehicleType, "processWeederArea", Weeder.processWeederArea) |
43 | SpecializationUtil.registerFunction(vehicleType, "updateWeederAIRequirements", Weeder.updateWeederAIRequirements) |
44 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
48 | function Weeder.registerOverwrittenFunctions(vehicleType) |
49 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "doCheckSpeedLimit", Weeder.doCheckSpeedLimit) |
50 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDirtMultiplier", Weeder.getDirtMultiplier) |
51 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getWearMultiplier", Weeder.getWearMultiplier) |
52 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadWorkAreaFromXML", Weeder.loadWorkAreaFromXML) |
53 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsWorkAreaActive", Weeder.getIsWorkAreaActive) |
54 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadGroundParticleMapping", Weeder.loadGroundParticleMapping) |
55 | end |
updateWeederAIRequirements
DescriptionDefinitionupdateWeederAIRequirements()Code
181 | function Weeder:updateWeederAIRequirements() |
182 | local spec = self.spec_weeder |
183 | if self.addAITerrainDetailRequiredRange ~= nil then |
184 | local hasSowingMachine = false |
185 | local vehicles = self.rootVehicle:getChildVehicles() |
186 | for i=1, #vehicles do |
187 | if SpecializationUtil.hasSpecialization(SowingMachine, vehicles[i].specializations) then |
188 | if vehicles[i]:getUseSowingMachineAIRequirements() then |
189 | hasSowingMachine = true |
190 | end |
191 | end |
192 | end |
193 | |
194 | self:clearAIFruitRequirements() |
195 | |
196 | -- if we also have a active sowing machine attached the sowingMachine is fully handling it |
197 | if not hasSowingMachine then |
198 | local weedSystem = g_currentMission.weedSystem |
199 | if weedSystem ~= nil then |
200 | local weedMapId, weedFirstChannel, weedNumChannels = weedSystem:getDensityMapData() |
201 | local replacementData = weedSystem:getWeederReplacements(spec.isHoeWeeder) |
202 | if replacementData.weed ~= nil then |
203 | local startState, lastState = -1, -1 |
204 | for sourceState, targetState in pairs(replacementData.weed.replacements) do |
205 | if startState == -1 then |
206 | startState = sourceState |
207 | else |
208 | if sourceState ~= lastState + 1 then |
209 | self:addAIFruitRequirement(nil, startState, lastState, weedMapId, weedFirstChannel, weedNumChannels) |
210 | startState = sourceState |
211 | end |
212 | end |
213 | |
214 | lastState = sourceState |
215 | end |
216 | |
217 | if startState ~= -1 then |
218 | self:addAIFruitRequirement(nil, startState, lastState, weedMapId, weedFirstChannel, weedNumChannels) |
219 | end |
220 | end |
221 | end |
222 | |
223 | if spec.isGrasslandWeeder then |
224 | local fruitTypeDesc = g_fruitTypeManager:getFruitTypeByIndex(FruitType.GRASS) |
225 | if fruitTypeDesc.terrainDataPlaneId ~= nil then |
226 | self:addAIFruitRequirement(fruitTypeDesc.index, 2, fruitTypeDesc.cutState + 1) |
227 | end |
228 | end |
229 | end |
230 | end |
231 | end |