LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Cultivator

Description
Specialization for all cultivators, requires WorkArea specialization
Functions

doCheckSpeedLimit

Description
Returns if speed limit should be checked
Definition
doCheckSpeedLimit()
Return Values
booleancheckSpeedlimitcheck speed limit
Code
276function Cultivator:doCheckSpeedLimit(superFunc)
277 return superFunc(self) or self:getIsImplementChainLowered()
278end

getCultivatorLimitToField

Description
Returns if cultivator is limited to the field
Definition
getCultivatorLimitToField()
Return Values
booleanisLimitedis limited to field
Code
194function Cultivator:getCultivatorLimitToField()
195 return self.spec_cultivator.limitToField
196end

getDefaultSpeedLimit

Description
Returns default speed limit
Definition
getDefaultSpeedLimit()
Return Values
floatspeedLimitspeed limit
Code
472function Cultivator.getDefaultSpeedLimit()
473 return 15
474end

getDirtMultiplier

Description
Returns current dirt multiplier
Definition
getDirtMultiplier()
Return Values
floatdirtMultipliercurrent dirt multiplier
Code
283function Cultivator:getDirtMultiplier(superFunc)
284 local spec = self.spec_cultivator
285
286 local multiplier = superFunc(self)
287 if spec.isWorking then
288 multiplier = multiplier + self:getWorkDirtMultiplier() * self:getLastSpeed() / spec.speedLimit
289 end
290
291 return multiplier
292end

getIsWorkAreaActive

Description
Definition
getIsWorkAreaActive()
Code
326function Cultivator:getIsWorkAreaActive(superFunc, workArea)
327 if workArea.type == WorkAreaType.CULTIVATOR then
328 local spec = self.spec_cultivator
329
330 if spec.startActivationTime > g_currentMission.time then
331 return false
332 end
333
334 if spec.onlyActiveWhenLowered and self.getIsLowered ~= nil then
335 if not self:getIsLowered(false) then
336 return false
337 end
338 end
339 end
340
341 return superFunc(self, workArea)
342end

getUseCultivatorAIRequirements

Description
Returns if cultivator ai requirements should be used
Definition
getUseCultivatorAIRequirements()
Return Values
booleanuseAIRequirementsuse ai requirements
Code
201function Cultivator:getUseCultivatorAIRequirements()
202 return true
203end

getWearMultiplier

Description
Returns current wear multiplier
Definition
getWearMultiplier()
Return Values
floatdirtMultipliercurrent wear multiplier
Code
297function Cultivator:getWearMultiplier(superFunc)
298 local spec = self.spec_cultivator
299 local multiplier = superFunc(self)
300
301 if spec.isWorking then
302 multiplier = multiplier + self:getWorkWearMultiplier() * self:getLastSpeed() / spec.speedLimit
303 end
304
305 return multiplier
306end

initSpecialization

Description
Called on specialization initializing
Definition
initSpecialization()
Code
47function Cultivator.initSpecialization()
48 g_workAreaTypeManager:addWorkAreaType("cultivator", true)
49
50 local schema = Vehicle.xmlSchema
51 schema:setXMLSpecializationType("Cultivator")
52
53 schema:register(XMLValueType.NODE_INDEX, "vehicle.cultivator.directionNode#node", "Direction node")
54 schema:register(XMLValueType.BOOL, "vehicle.cultivator.onlyActiveWhenLowered#value", "Only active when lowered", true)
55 schema:register(XMLValueType.BOOL, "vehicle.cultivator#isSubsoiler", "Is subsoiler", false)
56 schema:register(XMLValueType.BOOL, "vehicle.cultivator#useDeepMode", "If true the implement acts like a cultivator. If false it's a discharrow or seedbed combination", true)
57 schema:register(XMLValueType.BOOL, "vehicle.cultivator#isPowerHarrow", "If this is set the cultivator works standalone like a cultivator, but as soon as a sowing machine is attached to it, it's only using the sowing machine", false)
58
59 SoundManager.registerSampleXMLPaths(schema, "vehicle.cultivator.sounds", "work")
60
61 schema:setXMLSpecializationType()
62end

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
314function Cultivator:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
315 local retValue = superFunc(self, workArea, xmlFile, key)
316
317 if workArea.type == WorkAreaType.DEFAULT then
318 workArea.type = WorkAreaType.CULTIVATOR
319 end
320
321 return retValue
322end

onDeactivate

Description
Definition
onDeactivate()
Code
356function Cultivator:onDeactivate()
357 if self.isClient then
358 local spec = self.spec_cultivator
359 g_soundManager:stopSamples(spec.samples)
360 spec.isWorkSamplePlaying = false
361 end
362end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
149function Cultivator:onDelete()
150 local spec = self.spec_cultivator
151 g_soundManager:deleteSamples(spec.samples)
152end

onEndWorkAreaProcessing

Description
Definition
onEndWorkAreaProcessing()
Code
391function Cultivator:onEndWorkAreaProcessing(dt)
392 local spec = self.spec_cultivator
393
394 if self.isServer then
395 local stats = g_currentMission:farmStats(self:getLastTouchedFarmlandFarmId())
396 local lastStatsArea = spec.workAreaParameters.lastStatsArea
397
398 if lastStatsArea > 0 then
399 local ha = MathUtil.areaToHa(lastStatsArea, g_currentMission:getFruitPixelsToSqm()) -- 4096px are mapped to 2048m
400 stats:updateStats("cultivatedHectares", ha)
401 self:updateLastWorkedArea(lastStatsArea)
402 end
403
404 if spec.isWorking then
405 stats:updateStats("cultivatedTime", dt/(1000*60))
406 end
407 end
408
409 if self.isClient then
410 if spec.isWorking then
411 if not spec.isWorkSamplePlaying then
412 g_soundManager:playSample(spec.samples.work)
413 spec.isWorkSamplePlaying = true
414 end
415 else
416 if spec.isWorkSamplePlaying then
417 g_soundManager:stopSample(spec.samples.work)
418 spec.isWorkSamplePlaying = false
419 end
420 end
421 end
422end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
108function Cultivator:onLoad(savegame)
109
110 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.cultivator.directionNode#index", "vehicle.cultivator.directionNode#node") --FS17 to FS19
111
112 if self:getGroundReferenceNodeFromIndex(1) == nil then
113 print("Warning: No ground reference nodes in "..self.configFileName)
114 end
115
116 local spec = self.spec_cultivator
117
118 if self.isClient then
119 spec.samples = {}
120 spec.samples.work = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.cultivator.sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
121 spec.isWorkSamplePlaying = false
122 end
123
124 spec.directionNode = self.xmlFile:getValue("vehicle.cultivator.directionNode#node", self.components[1].node, self.components, self.i3dMappings)
125 spec.onlyActiveWhenLowered = self.xmlFile:getValue("vehicle.cultivator.onlyActiveWhenLowered#value", true)
126 spec.isSubsoiler = self.xmlFile:getValue("vehicle.cultivator#isSubsoiler", false)
127 spec.isPowerHarrow = self.xmlFile:getValue("vehicle.cultivator#isPowerHarrow", false)
128 spec.useDeepMode = self.xmlFile:getValue("vehicle.cultivator#useDeepMode", true)
129
130 self:updateCultivatorAIRequirements()
131
132 spec.isEnabled = true
133 spec.startActivationTimeout = 2000
134 spec.startActivationTime = 0
135 spec.hasGroundContact = false
136 spec.isWorking = false
137 spec.limitToField = true
138
139 spec.workAreaParameters = {}
140 spec.workAreaParameters.limitToField = self:getCultivatorLimitToField()
141 spec.workAreaParameters.angle = 0
142 spec.workAreaParameters.lastChangedArea = 0
143 spec.workAreaParameters.lastStatsArea = 0
144 spec.workAreaParameters.lastTotalArea = 0
145end

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
349function Cultivator:onPostAttach(attacherVehicle, inputJointDescIndex, jointDescIndex)
350 local spec = self.spec_cultivator
351 spec.startActivationTime = g_currentMission.time + spec.startActivationTimeout
352end

onStartWorkAreaProcessing

Description
Definition
onStartWorkAreaProcessing()
Code
366function Cultivator:onStartWorkAreaProcessing(dt)
367 local spec = self.spec_cultivator
368
369 spec.isWorking = false
370
371 local limitToField = self:getCultivatorLimitToField()
372 local limitFruitDestructionToField = limitToField
373 if not g_currentMission:getHasPlayerPermission("createFields", self:getOwner()) then
374 limitToField = true
375 limitFruitDestructionToField = true
376 end
377
378 local dx,_,dz = localDirectionToWorld(spec.directionNode, 0, 0, 1)
379 local angle = FSDensityMapUtil.convertToDensityMapAngle(MathUtil.getYRotationFromDirection(dx, dz), g_currentMission.fieldGroundSystem:getGroundAngleMaxValue())
380
381 spec.workAreaParameters.limitToField = limitToField
382 spec.workAreaParameters.limitFruitDestructionToField = limitFruitDestructionToField
383 spec.workAreaParameters.angle = angle
384 spec.workAreaParameters.lastChangedArea = 0
385 spec.workAreaParameters.lastStatsArea = 0
386 spec.workAreaParameters.lastTotalArea = 0
387end

onStateChange

Description
Definition
onStateChange()
Code
426function Cultivator:onStateChange(state, data)
427 if state == Vehicle.STATE_CHANGE_ATTACH or state == Vehicle.STATE_CHANGE_DETACH then
428 self:updateCultivatorAIRequirements()
429 self:updateCultivatorEnabledState()
430 end
431
432 -- turn on attached sowing machines while we turn on the power harrow and vice versa
433 if self.isServer then
434 if state == Vehicle.STATE_CHANGE_TURN_ON or state == Vehicle.STATE_CHANGE_TURN_OFF then
435 local spec = self.spec_cultivator
436 if spec.isPowerHarrow then
437 if data == self and self.getAttachedImplements ~= nil then
438 for _, implement in pairs(self:getAttachedImplements()) do
439 local vehicle = implement.object
440 if vehicle ~= nil then
441 if state == Vehicle.STATE_CHANGE_TURN_ON then
442 vehicle:setIsTurnedOn(true)
443 else
444 if vehicle:getIsTurnedOn() then
445 vehicle:setIsTurnedOn(false)
446 end
447 end
448 end
449 end
450 elseif data.getAttacherVehicle ~= nil then
451 local attacherVehicle = data:getAttacherVehicle()
452 if attacherVehicle ~= nil then
453 if attacherVehicle == self then
454 if state == Vehicle.STATE_CHANGE_TURN_ON then
455 self:setIsTurnedOn(true)
456 else
457 if self:getIsTurnedOn() then
458 self:setIsTurnedOn(false)
459 end
460 end
461 end
462 end
463 end
464 end
465 end
466 end
467end

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
68function Cultivator.prerequisitesPresent(specializations)
69 return SpecializationUtil.hasSpecialization(WorkArea, specializations)
70end

processCultivatorArea

Description
Definition
processCultivatorArea()
Code
156function Cultivator:processCultivatorArea(workArea, dt)
157 local spec = self.spec_cultivator
158
159 local realArea, area = 0, 0
160 local xs,_,zs = getWorldTranslation(workArea.start)
161 local xw,_,zw = getWorldTranslation(workArea.width)
162 local xh,_,zh = getWorldTranslation(workArea.height)
163
164 if spec.isEnabled then
165 local params = spec.workAreaParameters
166
167 if spec.useDeepMode then
168 realArea, area = FSDensityMapUtil.updateCultivatorArea(xs,zs, xw,zw, xh,zh, not params.limitToField, params.limitFruitDestructionToField, params.angle, nil)
169 realArea = realArea + FSDensityMapUtil.updateVineCultivatorArea(xs, zs, xw, zw, xh, zh)
170 else
171 realArea, area = FSDensityMapUtil.updateDiscHarrowArea(xs,zs, xw,zw, xh,zh, not params.limitToField, params.limitFruitDestructionToField, params.angle, nil)
172 realArea = realArea + FSDensityMapUtil.updateVineCultivatorArea(xs, zs, xw, zw, xh, zh)
173 end
174
175 params.lastChangedArea = params.lastChangedArea + realArea
176 params.lastStatsArea = params.lastStatsArea + realArea
177 params.lastTotalArea = params.lastTotalArea + area
178 end
179
180 if spec.isSubsoiler then
181 FSDensityMapUtil.updateSubsoilerArea(xs, zs, xw, zw, xh, zh)
182 end
183
184 FSDensityMapUtil.eraseTireTrack(xs, zs, xw, zw, xh, zh)
185
186 spec.isWorking = self:getLastSpeed() > 0.5
187
188 return realArea, area
189end

registerEventListeners

Description
Definition
registerEventListeners()
Code
95function Cultivator.registerEventListeners(vehicleType)
96 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Cultivator)
97 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Cultivator)
98 SpecializationUtil.registerEventListener(vehicleType, "onPostAttach", Cultivator)
99 SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", Cultivator)
100 SpecializationUtil.registerEventListener(vehicleType, "onStartWorkAreaProcessing", Cultivator)
101 SpecializationUtil.registerEventListener(vehicleType, "onEndWorkAreaProcessing", Cultivator)
102 SpecializationUtil.registerEventListener(vehicleType, "onStateChange", Cultivator)
103end

registerFunctions

Description
Definition
registerFunctions()
Code
74function Cultivator.registerFunctions(vehicleType)
75 SpecializationUtil.registerFunction(vehicleType, "processCultivatorArea", Cultivator.processCultivatorArea)
76 SpecializationUtil.registerFunction(vehicleType, "getCultivatorLimitToField", Cultivator.getCultivatorLimitToField)
77 SpecializationUtil.registerFunction(vehicleType, "getUseCultivatorAIRequirements", Cultivator.getUseCultivatorAIRequirements)
78 SpecializationUtil.registerFunction(vehicleType, "updateCultivatorAIRequirements", Cultivator.updateCultivatorAIRequirements)
79 SpecializationUtil.registerFunction(vehicleType, "updateCultivatorEnabledState", Cultivator.updateCultivatorEnabledState)
80 SpecializationUtil.registerFunction(vehicleType, "getIsCultivationEnabled", Cultivator.getIsCultivationEnabled)
81end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
85function Cultivator.registerOverwrittenFunctions(vehicleType)
86 SpecializationUtil.registerOverwrittenFunction(vehicleType, "doCheckSpeedLimit", Cultivator.doCheckSpeedLimit)
87 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDirtMultiplier", Cultivator.getDirtMultiplier)
88 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getWearMultiplier", Cultivator.getWearMultiplier)
89 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadWorkAreaFromXML", Cultivator.loadWorkAreaFromXML)
90 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsWorkAreaActive", Cultivator.getIsWorkAreaActive)
91end

updateCultivatorAIRequirements

Description
Update cultivator ai requirements and optional exclude the given ground type
Definition
updateCultivatorAIRequirements()
Code
207function Cultivator:updateCultivatorAIRequirements()
208 if self:getUseCultivatorAIRequirements() then
209 if self.addAITerrainDetailRequiredRange ~= nil then
210 local hasSowingMachine = false
211 local excludedType1, excludedType2
212 local vehicles = self.rootVehicle:getChildVehicles()
213 for i=1, #vehicles do
214 if SpecializationUtil.hasSpecialization(SowingMachine, vehicles[i].specializations) then
215 if vehicles[i]:getAIRequiresTurnOn() or vehicles[i]:getUseSowingMachineAIRequirements() then
216 hasSowingMachine = true
217 end
218 end
219
220 if SpecializationUtil.hasSpecialization(Roller, vehicles[i].specializations) then
221 excludedType1 = FieldGroundType.ROLLER_LINES
222 excludedType2 = FieldGroundType.ROLLED_SEEDBED
223 end
224 end
225
226 -- if we also have a active sowing machine attached the sowingMachine is fully handling it
227 if not hasSowingMachine then
228 if self.spec_cultivator.useDeepMode then
229 self:addAIGroundTypeRequirements(Cultivator.AI_REQUIRED_GROUND_TYPES_DEEP, excludedType1, excludedType2)
230 else
231 self:addAIGroundTypeRequirements(Cultivator.AI_REQUIRED_GROUND_TYPES_FLAT, excludedType1, excludedType2)
232 end
233 else
234 self:clearAITerrainDetailRequiredRange()
235 end
236 end
237 end
238end