LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

Sprayer

Description
Class for all sprayers
Functions

registerSprayType

Description
Register new spray type
Definition
registerSprayType(string name, string nameI18N, integer category, float pricePerLiter, float litersPerSecond, boolean showOnPriceTable, string hudOverlayFilename, string hudOverlayFilenameSmall, float massPerLiter)
Arguments
stringnamename of new type
stringnameI18NI18N text
integercategoryfill type category
floatpricePerLiterprice per liter
floatlitersPerSecondusage in liter per second
booleanshowOnPriceTableshow fill type on price table
stringhudOverlayFilenamehud overlay filename
stringhudOverlayFilenameSmallhud overlay filename small
floatmassPerLitermass per liter in t
Code
35function Sprayer.registerSprayType(name, nameI18N, category, pricePerLiter, litersPerSecond, showOnPriceTable, hudOverlayFilename, hudOverlayFilenameSmall, massPerLiter)
36 local key = "SPRAYTYPE_"..string.upper(name);
37 if Sprayer[key] == nil then
38 Sprayer.NUM_SPRAYTYPES = Sprayer.NUM_SPRAYTYPES+1;
39 Sprayer[key] = Sprayer.NUM_SPRAYTYPES;
40
41 local desc = {name = name, index = Sprayer.NUM_SPRAYTYPES};
42 desc.litersPerSecond = litersPerSecond;
43
44 Sprayer.sprayTypes[name] = desc;
45 Sprayer.sprayTypeIndexToDesc[Sprayer.NUM_SPRAYTYPES] = desc;
46
47 local fillType = FillUtil.registerFillType(name, nameI18N, category, pricePerLiter, showOnPriceTable, hudOverlayFilename, hudOverlayFilenameSmall, massPerLiter)
48 Sprayer.sprayTypeToFillType[Sprayer.NUM_SPRAYTYPES] = fillType;
49 Sprayer.fillTypeToSprayType[fillType] = Sprayer.NUM_SPRAYTYPES;
50 end
51end

initSpecialization

Description
Called on specialization initializing
Definition
initSpecialization()
Code
55function Sprayer.initSpecialization()
56 WorkArea.registerAreaType("sprayer");
57end

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
63function Sprayer.prerequisitesPresent(specializations)
64 return SpecializationUtil.hasSpecialization(Fillable, specializations) and
65 SpecializationUtil.hasSpecialization(WorkArea, specializations) and
66 SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations) and
67 SpecializationUtil.hasSpecialization(AttacherJoints, specializations);
68end

preLoad

Description
Called before loading
Definition
preLoad(table savegame)
Arguments
tablesavegamesavegame
Code
73function Sprayer:preLoad(savegame)
74 self.getIsReadyToSpray = Sprayer.getIsReadyToSpray;
75 self.getAreEffectsVisible = Sprayer.getAreEffectsVisible;
76 self.getLitersPerSecond = Sprayer.getLitersPerSecond;
77 self.supportsFillTriggers = true;
78 self.loadWorkAreaFromXML = Utils.overwrittenFunction(self.loadWorkAreaFromXML, Sprayer.loadWorkAreaFromXML);
79 self.doCheckSpeedLimit = Utils.overwrittenFunction(self.doCheckSpeedLimit, Sprayer.doCheckSpeedLimit);
80 self.getIsTurnedOnAllowed = Utils.overwrittenFunction(self.getIsTurnedOnAllowed, Sprayer.getIsTurnedOnAllowed);
81 self.getCanAddHelpButtonText = Utils.overwrittenFunction(self.getCanAddHelpButtonText, Sprayer.getCanAddHelpButtonText);
82 self.aiAllowedToRefill = Utils.overwrittenFunction(self.aiAllowedToRefill, Sprayer.aiAllowedToRefill);
83 self.getDrawFirstFillText = Utils.overwrittenFunction(self.getDrawFirstFillText, Sprayer.getDrawFirstFillText);
84 self.getHasSpray = Sprayer.getHasSpray;
85
86 self.processSprayerAreas = Sprayer.processSprayerAreas;
87end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
92function Sprayer:load(savegame)
93
94 self.isSprayerTank = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.sprayer#isTank"), false);
95 self.allowsSpraying = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.sprayer#allowsSpraying"), true);
96 self.needsTankActivation = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.sprayer#needsTankActivation"), false);
97 self.activateTankOnLowering = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.sprayer#activateTankOnLowering"), false);
98 self.stopAiOnEmpty = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.sprayer#stopAiOnEmpty"), true);
99 self.activateOnLowering = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.sprayer#activateOnLowering"), false);
100
101
102 self.sprayUsageScale = {}
103 self.sprayUsageScale.default = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.sprayUsageScales#scale"), 1)
104 self.sprayUsageScale.workingWidth = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.sprayUsageScales#workingWidth"), 12)
105 self.sprayUsageScale.fillTypeScales = {}
106 local i=0;
107 while true do
108 local key = string.format("vehicle.sprayUsageScales.sprayUsageScale(%d)", i);
109 if not hasXMLProperty(self.xmlFile, key) then
110 break;
111 end
112 local fillType = getXMLString(self.xmlFile, key.. "#fillType");
113 local scale = getXMLFloat(self.xmlFile, key.. "#scale");
114 if fillType ~= nil and scale ~= nil then
115 local fillTypeInt = FillUtil.fillTypeNameToInt[fillType];
116 if fillTypeInt ~= nil then
117 self.sprayUsageScale.fillTypeScales[fillTypeInt] = scale
118 else
119 print("Warning: Invalid spray usage scale fill type '"..fillType.."' in '" .. self.configFileName.. "'");
120 end
121 end
122 i = i+1;
123 end
124
125 self.lastSprayValveUpdateFoldTime = nil;
126 self.sprayParticleSystems = {};
127 self.sprayerEffects = {};
128
129 if self.isClient then
130 local i = 0;
131 while true do
132 local key = string.format("vehicle.sprayParticleSystems.sprayParticleSystem(%d)", i);
133 local t = getXMLString(self.xmlFile, key .. "#type");
134 if t == nil then
135 break;
136 end
137 local fillType = FillUtil.fillTypeNameToInt[t];
138 if fillType ~= nil then
139 self.sprayParticleSystems[fillType] = {}
140 local currentPS = Utils.getNoNil(self.sprayParticleSystems[fillType], {});
141 ParticleUtil.loadParticleSystem(self.xmlFile, currentPS, key, self.components, false, nil, self.baseDirectory);
142 currentPS.foldMinLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#foldMinLimit"), 0);
143 currentPS.foldMaxLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#foldMaxLimit"), 1);
144 table.insert(self.sprayParticleSystems[fillType], currentPS)
145 end
146 i = i + 1;
147 end
148
149 local i = 0
150 while true do
151 local key = string.format("vehicle.sprayParticles.emitterShape(%d)", i);
152 if not hasXMLProperty(self.xmlFile, key) then
153 break
154 end
155 local emitterShape = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node"));
156 local particleType = getXMLString(self.xmlFile, key.."#particleType")
157 if emitterShape ~= nil then
158 for index, _ in pairs(self.fillUnits) do
159 for fillType, _ in pairs(self:getUnitFillTypes(index)) do
160 if self.sprayParticleSystems[fillType] == nil then
161 self.sprayParticleSystems[fillType] = {}
162 end
163 local particleSystem = MaterialUtil.getParticleSystem(fillType, particleType)
164 if particleSystem ~= nil then
165 local currentPS = ParticleUtil.copyParticleSystem(self.xmlFile, key, particleSystem, emitterShape)
166 currentPS.foldMinLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#foldMinLimit"), 0);
167 currentPS.foldMaxLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#foldMaxLimit"), 1);
168 table.insert(self.sprayParticleSystems[fillType], currentPS)
169 end
170 end
171 end
172 end
173 i = i + 1
174 end
175
176 local i = 0;
177 while true do
178 local key = string.format("vehicle.sprayerEffects.sprayerEffect(%d)", i);
179 if not hasXMLProperty(self.xmlFile, key) then
180 break;
181 end
182
183 local effects = EffectManager:loadEffect(self.xmlFile, key, self.components, self);
184 if effects ~= nil then
185 local sprayerEffect = {}
186 sprayerEffect.effects = effects
187 sprayerEffect.foldMinLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#foldMinLimit"), 0);
188 sprayerEffect.foldMaxLimit = Utils.getNoNil(getXMLFloat(self.xmlFile, key .. "#foldMaxLimit"), 1);
189 table.insert(self.sprayerEffects, sprayerEffect);
190 end
191 i = i + 1;
192 end
193
194 self.sprayingAnimationName = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.sprayingAnimation#name"), "");
195
196 self.sampleSprayer = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.spraySound", nil, self.baseDirectory);
197
198 if self.sampleFill == nil then
199 local linkNode = Utils.indexToObject(self.components, Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.fillSound#linkNode"), "0>"));
200 self.sampleFill = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.fillSound", nil, self.baseDirectory, linkNode);
201 end
202 self.sampleFillEnabled = false;
203 self.sampleFillStopTime = -1;
204 self.lastFillLevel = -1;
205
206 self.sprayerTurnedOnRotationNodes = Utils.loadRotationNodes(self.xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "sprayer", self.components);
207 self.sprayerTurnedOnScrollers = Utils.loadScrollers(self.components, self.xmlFile, "vehicle.sprayerTurnedOnScrollers.sprayerTurnedOnScroller", {}, false);
208 end
209
210 self.showFieldNotOwnedWarning = false;
211
212 self.isSprayerSpeedLimitActive = false;
213
214 if self.sowingMachineGroundContactFlag == nil and self.cultivatorGroundContactFlag == nil then
215 table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.ploughValue, g_currentMission.ploughValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels});
216 table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.cultivatorValue, g_currentMission.cultivatorValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels});
217 table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.sowingValue, g_currentMission.sowingValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels});
218 table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.sowingWidthValue, g_currentMission.sowingWidthValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels});
219 table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.grassValue, g_currentMission.grassValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels});
220
221 table.insert(self.terrainDetailProhibitValueRanges, {1, 2, g_currentMission.sprayFirstChannel, g_currentMission.sprayNumChannels});
222 table.insert(self.terrainDetailProhibitValueRanges, {g_currentMission.sprayLevelMaxValue, g_currentMission.sprayLevelMaxValue, g_currentMission.sprayLevelFirstChannel, g_currentMission.sprayLevelNumChannels});
223 end
224
225 self.sprayer = {};
226 self.sprayer.fillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.sprayer#fillUnitIndex"), 1);
227 self.sprayer.unloadInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.sprayer#unloadInfoIndex"), 1);
228 self.sprayer.loadInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.sprayer#loadInfoIndex"), 1);
229 self.sprayer.dischargeInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.sprayer#dischargeInfoIndex"), 1);
230
231 self.sprayerDirtyFlag = self:getNextDirtyFlag();
232end

delete

Description
Called on deleting
Definition
delete()
Code
236function Sprayer:delete()
237 for _, sprayerEffect in pairs(self.sprayerEffects) do
238 EffectManager:deleteEffects(sprayerEffect.effects);
239 end
240
241 for _, particleSystems in pairs(self.sprayParticleSystems) do
242 ParticleUtil.deleteParticleSystems(particleSystems)
243 end
244
245 if self.isClient then
246 SoundUtil.deleteSample(self.sampleSprayer);
247 SoundUtil.deleteSample(self.sampleFill);
248 end
249end

readUpdateStream

Description
Called on on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
262function Sprayer:readUpdateStream(streamId, timestamp, connection)
263 if connection:getIsServer() then
264 self.showFieldNotOwnedWarning = streamReadBool(streamId);
265 end
266end

writeUpdateStream

Description
Called on on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
273function Sprayer:writeUpdateStream(streamId, connection, dirtyMask)
274 if not connection:getIsServer() then
275 streamWriteBool(streamId, self.showFieldNotOwnedWarning);
276 end
277end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
288function Sprayer:update(dt)
289 if self.isClient then
290 Utils.updateRotationNodes(self, self.sprayerTurnedOnRotationNodes, dt, self:getIsActive() and self:getIsTurnedOn());
291 Utils.updateScrollers(self.sprayerTurnedOnScrollers, dt, self:getIsActive() and self:getIsTurnedOn());
292 end
293end

updateTick

Description
Called on update tick
Definition
updateTick(float dt)
Arguments
floatdttime since last call in ms
Code
298function Sprayer:updateTick(dt)
299 self.isSprayerSpeedLimitActive = false;
300 if self:getIsActive() then
301 local showFieldNotOwnedWarning = false;
302
303 if self.isServer then
304 if self.turnOnDueToLoweredImplement ~= nil then
305 if self.turnOnDueToLoweredImplement.object == nil then
306 self.turnOnDueToLoweredImplement = nil;
307 end
308 end
309 if self.turnOnDueToLoweredImplement ~= nil then
310 if self:getIsTurnedOn() == false then
311 self:setIsTurnedOn(true);
312 end
313 if self.turnOnDueToLoweredImplement.object.activateOnLowering then
314 if self.turnOnDueToLoweredImplement.object:getIsTurnedOn() == false then
315 self.turnOnDueToLoweredImplement.object:setIsTurnedOn(true);
316 end
317 end
318 end
319 if self:getIsTurnedOn() then
320 if not self:getIsTurnedOnAllowed(true) then
321 self:setIsTurnedOn(false);
322 end
323 end
324
325 local tankActivators = {};
326 Sprayer.getTankActivators(self:getRootAttacherVehicle(), tankActivators);
327 if table.getn(tankActivators) > 0 then
328 local doTurnOn = false;
329 for _,tankActivator in pairs(tankActivators) do
330 local attacherVehicle = tankActivator.attacherVehicle;
331 if attacherVehicle ~= nil then
332 local implementIndex = attacherVehicle:getImplementIndexByObject(tankActivator);
333 local implement = attacherVehicle.attachedImplements[implementIndex];
334 local jointDescIndex = implement.jointDescIndex;
335 doTurnOn = doTurnOn or attacherVehicle.attacherJoints[jointDescIndex].moveDown;
336 end
337 end
338 self:setIsTurnedOn(doTurnOn);
339 end
340
341 if self.activateOnLowering and self.isLowered ~= nil then
342 if self:isLowered(false) then
343 if self:getCanBeTurnedOn() and not self:getIsTurnedOn(true) then
344 self:setIsTurnedOn(true);
345 end
346 else
347 self:setIsTurnedOn(false);
348 end
349 end
350 end
351
352
353 if self:getIsTurnedOn() and self.allowsSpraying then
354 if self.isClient and self:getIsActiveForSound() then
355 SoundUtil.playSample(self.sampleSprayer, 0, 0, nil);
356 end
357
358 local readyToSpray = self:getIsReadyToSpray();
359 self.isSprayerSpeedLimitActive = readyToSpray;
360
361 local fillType = self:getUnitLastValidFillType(self.sprayer.fillUnitIndex);
362 if fillType == FillUtil.FILLTYPE_UNKNOWN and self.fillUnits[self.sprayer.fillUnitIndex] ~= nil then
363 for unitFillType,state in pairs(self.fillUnits[self.sprayer.fillUnitIndex].fillTypes) do
364 if unitFillType ~= FillUtil.FILLTYPE_UNKNOWN and state then
365 fillType = unitFillType;
366 break;
367 end
368 end
369 end
370
371 if readyToSpray then
372 if self.isServer then
373 local litersPerSecond = self:getLitersPerSecond(fillType);
374 local usage = litersPerSecond * dt * 0.001;
375
376 local hasSpray, newFillType = self:getHasSpray(fillType, usage)
377 fillType = newFillType
378 if hasSpray then
379 local workAreas, showWarning, _ = self:getTypedNetworkAreas(WorkArea.AREATYPE_SPRAYER, true);
380 showFieldNotOwnedWarning = showWarning;
381 if (table.getn(workAreas) > 0) then
382 local pixels = self:processSprayerAreas(workAreas, fillType);
383 local ha = Utils.areaToHa(pixels, g_currentMission:getFruitPixelsToSqm());
384 g_currentMission.missionStats:updateStats("fertilizedHectares", ha);
385 g_currentMission.missionStats:updateStats("fertilizedTime", dt/(1000*60));
386 if self.lastSowingArea == nil then
387 g_currentMission.missionStats:updateStats("workedHectares", ha);
388 g_currentMission.missionStats:updateStats("workedTime", dt/(1000*60));
389 end
390 g_currentMission.missionStats:updateStats("sprayUsage", usage);
391 end
392 end
393 end
394 end
395
396 if self.isClient then
397 -- update valve particle systems
398 local foldAnimTime = self.foldAnimTime
399 if (foldAnimTime ~= nil and foldAnimTime ~= self.lastSprayValveUpdateFoldTime) or self.lastTurnedOn == false then
400
401 self.lastSprayValveUpdateFoldTime = foldAnimTime;
402 self.lastTurnedOn = true;
403
404 if self:getAreEffectsVisible() then
405 if foldAnimTime ~= nil then
406 if self.sprayParticleSystems[fillType] ~= nil then
407 for _, ps in pairs(self.sprayParticleSystems[fillType]) do
408 if foldAnimTime <= ps.foldMaxLimit and foldAnimTime >= ps.foldMinLimit then
409 ParticleUtil.setEmittingState(ps, true);
410 else
411 ParticleUtil.setEmittingState(ps, false);
412 end
413 end;
414 end
415
416 for _, sprayerEffect in pairs(self.sprayerEffects) do
417 readyToSpray = readyToSpray and (foldAnimTime > sprayerEffect.foldMinLimit);
418 if foldAnimTime <= sprayerEffect.foldMaxLimit and foldAnimTime >= sprayerEffect.foldMinLimit then
419 EffectManager:setFillType(sprayerEffect.effects, fillType)
420 EffectManager:startEffects(sprayerEffect.effects)
421 else
422 EffectManager:stopEffects(sprayerEffect.effects);
423 end
424 end
425 else
426 if self.sprayParticleSystems[fillType] ~= nil then
427 for _, ps in pairs(self.sprayParticleSystems[fillType]) do
428 ParticleUtil.setEmittingState(ps, true);
429 end;
430 end
431 for _, sprayerEffect in pairs(self.sprayerEffects) do
432 EffectManager:setFillType(sprayerEffect.effects, fillType)
433 EffectManager:startEffects(sprayerEffect.effects)
434 end
435 end
436 end
437 end
438 end
439
440 else
441
442 if self.isClient then
443 for _, particleSystems in pairs(self.sprayParticleSystems) do
444 for _, ps in pairs(particleSystems) do
445 ParticleUtil.setEmittingState(ps, false);
446 end;
447 end
448 for _, sprayerEffect in pairs(self.sprayerEffects) do
449 EffectManager:stopEffects(sprayerEffect.effects);
450 end
451 end
452 end
453 self.lastTurnedOn = self:getIsTurnedOn();
454
455 if self.isServer then
456 if self.sowingMachineGroundContactFlag == nil then
457 if showFieldNotOwnedWarning ~= self.showFieldNotOwnedWarning then
458 self.showFieldNotOwnedWarning = showFieldNotOwnedWarning;
459 self:raiseDirtyFlags(self.sprayerDirtyFlag);
460 end
461 end
462 end
463 end
464
465 if self.isClient then
466 if self.isFilling then
467 if self:getIsActiveForSound(true) then
468 SoundUtil.playSample(self.sampleFill, 0, 0, nil);
469 SoundUtil.stop3DSample(self.sampleFill);
470 else
471 SoundUtil.stopSample(self.sampleFill);
472 SoundUtil.play3DSample(self.sampleFill);
473 end
474 else
475 SoundUtil.stopSample(self.sampleFill);
476 SoundUtil.stop3DSample(self.sampleFill);
477 end
478 end
479end

draw

Description
Called on draw
Definition
draw()
Code
483function Sprayer:draw()
484 if self.isClient then
485 if self.showFieldNotOwnedWarning then
486 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_youDontOwnThisField"));
487 end
488 end
489end

getDrawFirstFillText

Description
Returns if 'first fill tool' text should be drawed
Definition
getDrawFirstFillText()
Return Values
booleandrawdraw text
Code
494function Sprayer:getDrawFirstFillText(superFunc)
495 if self.isClient then
496 if self:getIsActiveForInput(true) and not self.isAlwaysTurnedOn then
497 if not self:getIsTurnedOnAllowed(true) and self:getUnitFillLevel(self.sprayer.fillUnitIndex) <= 0 and self:getUnitCapacity(self.sprayer.fillUnitIndex) > 0 then
498 return true;
499 end
500 end
501 end
502 if superFunc ~= nil then
503 return superFunc(self);
504 end;
505
506 return false;
507end;

onDetach

Description
Called if vehicle gets detached
Definition
onDetach(table attacherVehicle, integer jointDescIndex)
Arguments
tableattacherVehicleattacher vehicle
integerjointDescIndexindex of attacher joint it was attached to
Code
513function Sprayer:onDetach(attacherVehicle, jointDescIndex)
514 if attacherVehicle.setIsTurnedOn ~= nil and attacherVehicle:getIsTurnedOn() then
515 attacherVehicle:setIsTurnedOn(false);
516 end
517end

onDeactivate

Description
Called on deactivate
Definition
onDeactivate()
Code
521function Sprayer:onDeactivate()
522 self.showFieldNotOwnedWarning = false;
523end

onDeactivateSounds

Description
Called on deactivating sounds
Definition
onDeactivateSounds()
Code
527function Sprayer:onDeactivateSounds()
528 if self.isClient then
529 SoundUtil.stopSample(self.sampleSprayer, true);
530 end
531end

getHasSpray

Description
Try to spray and return if something was consumed to update the spray areas
Definition
getHasSpray(integer fillType, float usage)
Arguments
integerfillTypefill type
floatusageusage
Return Values
booleanhasSprayhas spray
integerfillTypefill type
Code
539function Sprayer:getHasSpray(fillType, usage)
540
541 local hasSpray = false;
542
543 if not hasSpray and self:getIsHired() and self:aiAllowedToRefill() then
544
545 if fillType == FillUtil.FILLTYPE_LIQUIDMANURE or
546 fillType == FillUtil.FILLTYPE_DIGESTATE or
547 (fillType == FillUtil.FILLTYPE_UNKNOWN and (self:allowUnitFillType(self.sprayer.fillUnitIndex, FillUtil.FILLTYPE_LIQUIDMANURE) or self:allowUnitFillType(self.sprayer.fillUnitIndex, FillUtil.FILLTYPE_DIGESTATE))) then
548 if g_currentMission.missionInfo.helperSlurrySource == 2 then -- buy manure
549 hasSpray = true;
550 if g_currentMission.economyManager:getCostPerLiter(FillUtil.FILLTYPE_LIQUIDMANURE) then
551 fillType = FillUtil.FILLTYPE_LIQUIDMANURE;
552 else
553 fillType = FillUtil.FILLTYPE_DIGESTATE;
554 end
555 local price = usage * g_currentMission.economyManager:getCostPerLiter(fillType) * 1.5 -- increase price if AI is active to reward the player's manual work
556 g_currentMission.missionStats:updateStats("expenses", price);
557 g_currentMission:addSharedMoney(-price, "purchaseFertilizer");
558 elseif g_currentMission.missionInfo.helperSlurrySource > 2 then
559 local trigger = g_currentMission.liquidManureTriggers[g_currentMission.missionInfo.helperSlurrySource-2].trigger
560 if trigger.fillLevel > 0 then
561 hasSpray = true;
562 fillType = trigger.fillType
563 trigger:setFillLevel(trigger.fillLevel-usage)
564 end
565 end
566
567 elseif fillType == FillUtil.FILLTYPE_MANURE or (fillType == FillUtil.FILLTYPE_UNKNOWN and self:allowUnitFillType(self.sprayer.fillUnitIndex, FillUtil.FILLTYPE_MANURE)) then
568 if g_currentMission.missionInfo.helperManureSource == 2 then -- buy manure
569 hasSpray = true;
570 fillType = FillUtil.FILLTYPE_MANURE;
571 local price = usage * g_currentMission.economyManager:getCostPerLiter(fillType) * 1.5 -- increase price if AI is active to reward the player's manual work
572 g_currentMission.missionStats:updateStats("expenses", price);
573 g_currentMission:addSharedMoney(-price, "purchaseFertilizer");
574 elseif g_currentMission.missionInfo.helperManureSource > 2 then
575 local manureHeap = g_currentMission.manureHeaps[g_currentMission.missionInfo.helperManureSource-2].manureHeap
576 if manureHeap:removeManure(usage) > 0 then
577 hasSpray = true;
578 fillType = FillUtil.FILLTYPE_MANURE
579 end
580 end
581
582 elseif fillType == FillUtil.FILLTYPE_FERTILIZER or
583 fillType == FillUtil.FILLTYPE_LIQUIDFERTILIZER or
584 (fillType == FillUtil.FILLTYPE_UNKNOWN and (self:allowUnitFillType(self.sprayer.fillUnitIndex, FillUtil.FILLTYPE_LIQUIDFERTILIZER) or self:allowUnitFillType(self.sprayer.fillUnitIndex, FillUtil.FILLTYPE_FERTILIZER))) then
585 if g_currentMission.missionInfo.helperBuyFertilizer then
586 hasSpray = true;
587 if self:allowUnitFillType(self.sprayer.fillUnitIndex, FillUtil.FILLTYPE_LIQUIDFERTILIZER) then
588 fillType = FillUtil.FILLTYPE_LIQUIDFERTILIZER;
589 else
590 fillType = FillUtil.FILLTYPE_FERTILIZER;
591 end
592 local price = usage * g_currentMission.economyManager:getCostPerLiter(fillType) * 1.5 -- increase price if AI is active to reward the player's manual work
593 g_currentMission.missionStats:updateStats("expenses", price);
594 g_currentMission:addSharedMoney(-price, "purchaseFertilizer");
595 end
596
597 else
598
599 end
600 end
601
602 if not hasSpray then
603 local sprayUsageVehicle = self
604 local newFillType = fillType;
605 if self:getUnitFillLevel(self.sprayer.fillUnitIndex) == 0 then
606 sprayUsageVehicle, newFillType = Sprayer.findAttachedSprayerTank(self:getRootAttacherVehicle(), self:getUnitFillTypes(self.sprayer.fillUnitIndex), self.needsTankActivation);
607 end
608
609 local oldFillLevel = 0
610 if sprayUsageVehicle ~= nil then
611 fillType = newFillType;
612 oldFillLevel = sprayUsageVehicle:getUnitFillLevel(sprayUsageVehicle.sprayer.fillUnitIndex);
613 sprayUsageVehicle:setUnitFillLevel(sprayUsageVehicle.sprayer.fillUnitIndex, oldFillLevel - usage, fillType, false, sprayUsageVehicle.fillVolumeUnloadInfos[sprayUsageVehicle.sprayer.unloadInfoIndex]);
614 end
615 hasSpray = oldFillLevel > 0;
616 end
617
618 if not hasSpray and self:getIsHired() and self.stopAiOnEmpty then
619 local rootVehicle = self:getRootAttacherVehicle()
620 rootVehicle:stopAIVehicle(AIVehicle.STOP_REASON_OUT_OF_FILL)
621 end
622
623 return hasSpray, fillType
624end

aiAllowedToRefill

Description
Return if ai is allowed to refill
Definition
aiAllowedToRefill()
Return Values
booleanallowai is allowed to refill
Code
629function Sprayer:aiAllowedToRefill(superFunc)
630 if self.needsTankActivation then
631 local sprayUsageVehicle, _ = Sprayer.findAttachedSprayerTank(self:getRootAttacherVehicle(), self:getUnitFillTypes(self.sprayer.fillUnitIndex), false, true);
632 if sprayUsageVehicle == nil then
633 return false;
634 end;
635 end;
636
637 if superFunc ~= nil then
638 return superFunc(self);
639 end
640
641 return true;
642end;

getCanAddHelpButtonText

Description
Returns if turn on help button texts are allowed to display
Definition
getCanAddHelpButtonText()
Return Values
booleanallowallow
Code
647function Sprayer:getCanAddHelpButtonText(superFunc)
648 if self.activateOnLowering then
649 return false;
650 end;
651
652 if superFunc ~= nil then
653 return superFunc(self);
654 end
655 return true;
656end;

getTankActivators

Description
Returns sprayers who need a tank to activate
Definition
getTankActivators(table currentVehicle, table result)
Arguments
tablecurrentVehiclecurrent vehicle to check
tableresulttable to add found tank activators
Code
662function Sprayer.getTankActivators(currentVehicle, results)
663 if currentVehicle.needsTankActivation then
664 table.insert(results, currentVehicle);
665 end
666 for _,implement in pairs(currentVehicle.attachedImplements) do
667 if implement.object ~= nil then
668 Sprayer.getTankActivators(implement.object, results);
669 end
670 end
671end

getIsTurnedOnAllowed

Description
Returns if turn on is allowed
Definition
getIsTurnedOnAllowed(boolean isTurnedOn)
Arguments
booleanisTurnedOnis turned on
Return Values
booleanallowallow turn on
Code
677function Sprayer:getIsTurnedOnAllowed(superFunc, isTurnedOn)
678 if not self.allowsSpraying then
679 return false;
680 end
681
682 if self.activateOnLowering and self.isLowered ~= nil then
683 return self:isLowered(false);
684 end
685
686 -- if sowingMachine is involved dismiss sprayer complains
687 if isTurnedOn and self.sowingMachineGroundContactFlag ~= nil then
688 return superFunc(self, isTurnedOn);
689 end
690
691 if isTurnedOn and self:getUnitFillLevel(self.sprayer.fillUnitIndex) <= 0 then
692
693 if self:getIsHired() then
694 return true;
695 end
696
697 -- try to find tank
698 local sprayerTank, fillType = Sprayer.findAttachedSprayerTank(self:getRootAttacherVehicle(), self:getUnitFillTypes(self.sprayer.fillUnitIndex), self.needsTankActivation);
699
700 if sprayerTank ~= nil and fillType ~= nil then
701 return true;
702 else
703 return false;
704 end
705 end
706
707 if superFunc ~= nil then
708 return superFunc(self, isTurnedOn);
709 end
710
711 return true;
712end

onTurnedOn

Description
Called on turn on
Definition
onTurnedOn(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
717function Sprayer:onTurnedOn(noEventSend)
718 if self.isClient then
719 if self.foldAnimTime == nil then
720 -- If the sprayer is foldable, the spray valves are only turned on within the update loop
721 for _, particleSystems in pairs(self.sprayParticleSystems) do
722 for _, particleSystem in pairs(particleSystems) do
723 ParticleUtil.setEmittingState(particleSystem, false);
724 end;
725 end
726
727 local fillType = self:getUnitLastValidFillType(self.sprayer.fillUnitIndex);
728 if fillType == FillUtil.FILLTYPE_UNKNOWN then
729 fillType = self:getFirstEnabledFillType();
730 end
731 for _, sprayerEffect in pairs(self.sprayerEffects) do
732 EffectManager:setFillType(sprayerEffect.effects, fillType)
733 EffectManager:startEffects(sprayerEffect.effects)
734 end
735 end
736 if self.sprayingAnimationName ~= "" and self.playAnimation ~= nil then
737 self:playAnimation(self.sprayingAnimationName, 1, self:getAnimationTime(self.sprayingAnimationName), true);
738 end
739 end
740end

onTurnedOff

Description
Called on turn off
Definition
onTurnedOff(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
745function Sprayer:onTurnedOff(noEventSend)
746 if self.isClient then
747 for _, particleSystems in pairs(self.sprayParticleSystems) do
748 for _, particleSystem in pairs(particleSystems) do
749 ParticleUtil.setEmittingState(particleSystem, false);
750 end
751 end
752 for _, sprayerEffect in pairs(self.sprayerEffects) do
753 EffectManager:stopEffects(sprayerEffect.effects);
754 end
755 SoundUtil.stopSample(self.sampleSprayer);
756
757 if self.sprayingAnimationName ~= "" and self.stopAnimation ~= nil then
758 self:stopAnimation(self.sprayingAnimationName, true);
759 end
760 end
761end

onAiTurnOn

Description
Called on ai turn on
Definition
onAiTurnOn()
Code
765function Sprayer:onAiTurnOn()
766 if self.setIsTurnedOn ~= nil then
767 self:setIsTurnedOn(true, false);
768 end
769end

onAiTurnOff

Description
Called on ai turn off
Definition
onAiTurnOff()
Code
773function Sprayer:onAiTurnOff()
774 if self.setIsTurnedOn ~= nil then
775 self:setIsTurnedOn(false, false);
776 end
777end

onAiLower

Description
Called on ai lower
Definition
onAiLower()
Code
781function Sprayer:onAiLower()
782 if self.setIsTurnedOn ~= nil then
783 self:setIsTurnedOn(true, false);
784 end
785end

onAiRaise

Description
Called on ai raise
Definition
onAiRaise()
Code
789function Sprayer:onAiRaise()
790 if self.setIsTurnedOn ~= nil then
791 self:setIsTurnedOn(false, false);
792 end
793end

findAttachedSprayerTank

Description
Find attached sprayer tanks
Definition
findAttachedSprayerTank(table currentVehicle, integer fillType, boolean needsTankActivation, boolean ignoreFillLevel)
Arguments
tablecurrentVehiclecurrent vehicle to check
integerfillTypefill types
booleanneedsTankActivationfound tank must be activated
booleanignoreFillLevelignore fill level
Return Values
tablefoundTankfound tank
integerfillTypetank fill type
Code
803function Sprayer.findAttachedSprayerTank(currentVehicle, fillTypes, needsTankActivation, ignoreFillLevel)
804 if currentVehicle.isSprayerTank and currentVehicle.getFillLevel ~= nil and currentVehicle.setFillLevel ~= nil then
805 if (not needsTankActivation or (currentVehicle.getIsTurnedOn ~= nil and currentVehicle:getIsTurnedOn())) then
806
807 local fillUnit = currentVehicle.fillUnits[currentVehicle.sprayer.fillUnitIndex];
808 for fillType,state in pairs(fillTypes) do
809 if state and fillUnit.fillTypes[fillType] then
810 if (fillUnit.currentFillType == fillType and fillUnit.fillLevel > 0) or ignoreFillLevel then
811 return currentVehicle, fillType;
812 end
813 end
814 end
815 end
816 end
817 for _,implement in pairs(currentVehicle.attachedImplements) do
818 if implement.object ~= nil then
819 local ret1, ret2 = Sprayer.findAttachedSprayerTank(implement.object, fillTypes, needsTankActivation, ignoreFillLevel);
820 if ret1 ~= nil and ret2 ~= nil then
821 return ret1, ret2;
822 end
823 end
824 end
825 return nil;
826end

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
834function Sprayer:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
835 local retValue = true;
836 if superFunc ~= nil then
837 retValue = superFunc(self, workArea, xmlFile, key)
838 end
839
840 if workArea.type == WorkArea.AREATYPE_DEFAULT then
841 workArea.type = WorkArea.AREATYPE_SPRAYER;
842 end
843
844 return retValue;
845end

getIsReadyToSpray

Description
Returns if tool is ready to spray
Definition
getIsReadyToSpray()
Return Values
booleanisReadyis ready to spray
Code
850function Sprayer:getIsReadyToSpray()
851 if self.lastSowingArea ~= nil then
852 return self.lastSowingArea > 0;
853 end
854
855 return true;
856end

getAreEffectsVisible

Description
Return if effects are visible
Definition
getAreEffectsVisible()
Return Values
booleanvisibleeffects are visible
Code
861function Sprayer:getAreEffectsVisible()
862 return true;
863end

getLitersPerSecond

Description
Returns liters per second to consume
Definition
getLitersPerSecond(integer fillType)
Arguments
integerfillTypefill type
Return Values
floatliterPerSecondliter per second
Code
869function Sprayer:getLitersPerSecond(fillType)
870
871 local scale = Utils.getNoNil(self.sprayUsageScale.fillTypeScales[fillType], self.sprayUsageScale.default)
872 local litersPerSecond = 1
873
874 local sprayTypeIndex = Sprayer.fillTypeToSprayType[fillType]
875 if sprayTypeIndex ~= nil then
876 local spray = Sprayer.sprayTypeIndexToDesc[sprayTypeIndex]
877 if spray ~= nil then
878 litersPerSecond = spray.litersPerSecond
879 end
880 end
881
882 return scale * litersPerSecond * self.speedLimit * self.sprayUsageScale.workingWidth
883end

doCheckSpeedLimit

Description
Returns if speed limit should be checked
Definition
doCheckSpeedLimit()
Return Values
booleancheckSpeedlimitcheck speed limit
Code
888function Sprayer:doCheckSpeedLimit(superFunc)
889 local parent = false;
890 if superFunc ~= nil then
891 parent = superFunc(self);
892 end
893
894 return parent or self.isSprayerSpeedLimitActive;
895end

getDefaultSpeedLimit

Description
Returns default speed limit
Definition
getDefaultSpeedLimit()
Return Values
floatspeedLimitspeed limit
Code
900function Sprayer.getDefaultSpeedLimit()
901 return 15;
902end

processSprayerAreas

Description
Process sprayer areas
Definition
processSprayerAreas(table workAreas, integer filltype)
Arguments
tableworkAreaswork areas to consume
integerfilltypefill type
Return Values
floattotalPixelstotal pixels changed
Code
909function Sprayer:processSprayerAreas(workAreas, fillType)
910 local sprayType = 1;
911 if fillType == FillUtil.FILLTYPE_MANURE then
912 sprayType = 2;
913 end
914 local totalPixels = 0;
915 local numAreas = table.getn(workAreas);
916 for i=1, numAreas do
917 local x = workAreas[i][1];
918 local z = workAreas[i][2];
919 local x1 = workAreas[i][3];
920 local z1 = workAreas[i][4];
921 local x2 = workAreas[i][5];
922 local z2 = workAreas[i][6];
923
924 local pixels, pixelsTotal;
925 if self.cultivatorGroundContactFlag ~= nil and self.sowingMachineGroundContactFlag == nil then
926 pixels, pixelsTotal = Utils.updateSprayArea(x, z, x1, z1, x2, z2, g_currentMission.cultivatorValue, sprayType);
927 else
928 pixels, pixelsTotal = Utils.updateSprayArea(x, z, x1, z1, x2, z2, nil, sprayType);
929 end
930 totalPixels = totalPixels + pixels;
931 end;
932 return totalPixels;
933end;