LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Weeder

Description
Specialization for weeder tool used to remove growing weeds on fields
Functions

doCheckSpeedLimit

Description
Returns if speed limit should be checked
Definition
doCheckSpeedLimit()
Return Values
booleancheckSpeedlimitcheck speed limit
Code
270function Weeder:doCheckSpeedLimit(superFunc)
271 return superFunc(self) or self:getIsImplementChainLowered()
272end

getDefaultSpeedLimit

Description
Returns default speed limit
Definition
getDefaultSpeedLimit()
Return Values
floatspeedLimitspeed limit
Code
400function Weeder.getDefaultSpeedLimit()
401 return 15
402end

getDirtMultiplier

Description
Returns current dirt multiplier
Definition
getDirtMultiplier()
Return Values
floatdirtMultipliercurrent dirt multiplier
Code
277function 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
286end

getIsWorkAreaActive

Description
Returns true if work area is active
Definition
getIsWorkAreaActive(table workArea)
Arguments
tableworkAreaworkArea
Return Values
booleanisActivework area is active
Code
252function 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)
265end

getWearMultiplier

Description
Returns current wear multiplier
Definition
getWearMultiplier()
Return Values
floatdirtMultipliercurrent wear multiplier
Code
291function 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
305end

initSpecialization

Description
Called on specialization initializing
Definition
initSpecialization()
Code
15function 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()
28end

loadGroundParticleMapping

Description
Load ground particle mapping from xml file
Definition
loadGroundParticleMapping(integer xmlFile, string key, table mapping, integer index, integer i3dNode)
Arguments
integerxmlFileid of xml object
stringkeykey
tablemappingmapping
integerindexindex
integeri3dNodeid of i3d node
Return Values
booleansuccesssuccess
Code
315function 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
332end

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
240function 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)
246end

onDeactivate

Description
Definition
onDeactivate()
Code
379function 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
385end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
102function Weeder:onDelete()
103 local spec = self.spec_weeder
104 g_soundManager:deleteSamples(spec.samples)
105end

onEndWorkAreaProcessing

Description
Definition
onEndWorkAreaProcessing()
Code
345function 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
367end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
73function 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()
98end

onPostAttach

Description
Called if vehicle gets attached
Definition
onPostAttach(table attacherVehicle, integer inputJointDescIndex, integer jointDescIndex)
Arguments
tableattacherVehicleattacher vehicle
integerinputJointDescIndexindex of input attacher joint
integerjointDescIndexindex of attacher joint it gets attached to
Code
392function Weeder:onPostAttach(attacherVehicle, inputJointDescIndex, jointDescIndex)
393 local spec = self.spec_weeder
394 spec.startActivationTime = g_currentMission.time + spec.startActivationTimeout
395end

onStartWorkAreaProcessing

Description
Definition
onStartWorkAreaProcessing()
Code
336function Weeder:onStartWorkAreaProcessing(dt)
337 local spec = self.spec_weeder
338 spec.isWorking = false
339 spec.workAreaParameters.lastArea = 0
340 spec.workAreaParameters.lastStatsArea = 0
341end

onStateChange

Description
Definition
onStateChange()
Code
371function Weeder:onStateChange(state, data)
372 if state == Vehicle.STATE_CHANGE_ATTACH or state == Vehicle.STATE_CHANGE_DETACH then
373 self:updateWeederAIRequirements()
374 end
375end

onUpdateTick

Description
Definition
onUpdateTick()
Code
109function 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
149end

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
34function Weeder.prerequisitesPresent(specializations)
35 return SpecializationUtil.hasSpecialization(WorkArea, specializations) and
36 SpecializationUtil.hasSpecialization(AttacherJoints, specializations)
37end

processWeederArea

Description
Definition
processWeederArea()
Code
153function 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
176end

registerEventListeners

Description
Definition
registerEventListeners()
Code
59function 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)
68end

registerFunctions

Description
Definition
registerFunctions()
Code
41function Weeder.registerFunctions(vehicleType)
42 SpecializationUtil.registerFunction(vehicleType, "processWeederArea", Weeder.processWeederArea)
43 SpecializationUtil.registerFunction(vehicleType, "updateWeederAIRequirements", Weeder.updateWeederAIRequirements)
44end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
48function 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)
55end

updateWeederAIRequirements

Description
Definition
updateWeederAIRequirements()
Code
181function 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
231end