LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

ForageWagon

Description
Class for all ForageWagons
Functions

initSpecialization

Description
Called on specialization initializing
Definition
initSpecialization()
Code
17function ForageWagon.initSpecialization()
18 WorkArea.registerAreaType("forageWagon")
19end

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
25function ForageWagon.prerequisitesPresent(specializations)
26 return SpecializationUtil.hasSpecialization(Trailer, specializations) and SpecializationUtil.hasSpecialization(WorkArea, specializations) and SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations) and SpecializationUtil.hasSpecialization(Pickup, specializations)
27end

preLoad

Description
Called before loading
Definition
preLoad(table savegame)
Arguments
tablesavegamesavegame
Code
32function ForageWagon:preLoad(savegame)
33 self.loadWorkAreaFromXML = Utils.overwrittenFunction(self.loadWorkAreaFromXML, ForageWagon.loadWorkAreaFromXML)
34 self.loadSpeedRotatingPartFromXML = Utils.overwrittenFunction(self.loadSpeedRotatingPartFromXML, ForageWagon.loadSpeedRotatingPartFromXML)
35end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
40function ForageWagon:load(savegame)
41 Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.fillScale#value", "vehicle.forageWagon#fillScale")
42 Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.forageWagonSound", "vehicle.forageWagon#sound")
43 Utils.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.turnedOnTipScrollerSpeedFactor#value", "vehicle.forageWagon#turnedOnTipScrollerSpeedFactor")
44
45 self.doCheckSpeedLimit = Utils.overwrittenFunction(self.doCheckSpeedLimit, ForageWagon.doCheckSpeedLimit)
46 self.getIsSpeedRotatingPartActive = Utils.overwrittenFunction(self.getIsSpeedRotatingPartActive, ForageWagon.getIsSpeedRotatingPartActive)
47 self.getTipScrollerSpeed = Utils.overwrittenFunction(self.getTipScrollerSpeed, ForageWagon.getTipScrollerSpeed)
48 self.processForageWagonAreas = ForageWagon.processForageWagonAreas
49
50 self.forageWagon = {}
51 self.forageWagon.turnedOnRotationNodes = Utils.loadRotationNodes(self.xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "forageWagon", self.components)
52 self.forageWagon.isSpeedLimitActive = false
53 self.forageWagon.lastAreaBiggerZero = false
54 self.forageWagon.lastAreaBiggerZeroSent = false
55 self.forageWagon.lastAreaBiggerZeroTime = 0
56 self.forageWagon.fillScale = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.forageWagon#fillScale"), 1)
57 self.forageWagon.fillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#fillUnitIndex"), 1)
58 self.forageWagon.unloadInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#unloadInfoIndex"), 1)
59 self.forageWagon.loadInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#loadInfoIndex"), 1)
60 self.forageWagon.dischargeInfoIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.forageWagon#dischargeInfoIndex"), 1)
61 self.forageWagon.turnedOnTipScrollerSpeedFactor = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.forageWagon#turnedOnTipScrollerSpeedFactor"), 0.25)
62
63 if self.isClient then
64 self.forageWagon.sampleRunning = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.forageWagon.runningSound", nil, self.baseDirectory)
65 self.forageWagon.sampleAlarm = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.forageWagon.alarmSound", nil, self.baseDirectory)
66
67 self.forageWagon.fillEffects = EffectManager:loadEffect(self.xmlFile, "vehicle.forageWagon.fillEffect", self.components, self)
68
69 self.forageWagon.fillParticleSystems = {}
70 self.forageWagon.currentFillParticleSystem = nil
71 local i = 0
72 while true do
73 local key = string.format("vehicle.forageWagon.fillParticleSystems.emitterShape(%d)", i)
74 if not hasXMLProperty(self.xmlFile, key) then
75 break
76 end
77
78 local emitterShape = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node"))
79 local particleType = getXMLString(self.xmlFile, key.."#particleType")
80 if emitterShape ~= nil then
81 for index, _ in pairs(self.fillUnits) do
82 for fillType, _ in pairs(self:getUnitFillTypes(index)) do
83 if self.forageWagon.fillParticleSystems[fillType] == nil then
84 self.forageWagon.fillParticleSystems[fillType] = {}
85 end
86
87 local particleSystem = MaterialUtil.getParticleSystem(fillType, particleType)
88 if particleSystem ~= nil then
89 table.insert(self.forageWagon.fillParticleSystems[fillType], ParticleUtil.copyParticleSystem(self.xmlFile, key, particleSystem, emitterShape))
90 end
91 end
92 end
93 end
94 i = i + 1
95 end
96 end
97
98 self.forageWagon.dirtyFlag = self:getNextDirtyFlag()
99end

delete

Description
Called on deleting
Definition
delete()
Code
103function ForageWagon:delete()
104 if self.isClient then
105 SoundUtil.deleteSample(self.forageWagon.sampleRunning)
106 SoundUtil.deleteSample(self.forageWagon.sampleAlarm)
107
108 for _,v in pairs(self.forageWagon.fillParticleSystems) do
109 ParticleUtil.deleteParticleSystems(v)
110 end
111 end
112end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
118function ForageWagon:readStream(streamId, connection)
119 self.forageWagon.lastAreaBiggerZero = streamReadBool(streamId)
120end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
126function ForageWagon:writeStream(streamId, connection)
127 streamWriteBool(streamId, self.forageWagon.lastAreaBiggerZero)
128end

readUpdateStream

Description
Called on on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
135function ForageWagon:readUpdateStream(streamId, timestamp, connection)
136 if connection:getIsServer() then
137 self.forageWagon.lastAreaBiggerZero = streamReadBool(streamId)
138 end
139end

writeUpdateStream

Description
Called on on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
146function ForageWagon:writeUpdateStream(streamId, connection, dirtyMask)
147 if not connection:getIsServer() then
148 streamWriteBool(streamId, self.forageWagon.lastAreaBiggerZero)
149 end
150end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
161function ForageWagon:update(dt)
162 if self.isClient then
163 Utils.updateRotationNodes(self, self.forageWagon.turnedOnRotationNodes, dt, self:getIsActive() and self:getIsTurnedOn() )
164
165 if self:getIsActive() then
166 if self:getIsTurnedOn() then
167 if self.lastForageFillLevel ~= self:getFillLevel(self:getUnitFillType(self.forageWagon.fillUnitIndex)) then
168 self.lastForageFillLevel = self:getFillLevel(self:getUnitFillType(self.forageWagon.fillUnitIndex))
169 self.lastForageFillTime = g_currentMission.time + 250
170 end
171 if self.lastForageFillTime > g_currentMission.time then
172 if self.fillUnits ~= nil then
173 local fillUnit = self.fillUnits[self.forageWagon.fillUnitIndex];
174 if fillUnit ~= nil then
175 local fillVolume = self.fillVolumes[fillUnit.fillVolumeIndex];
176 if fillVolume ~= nil then
177 if fillVolume.scrollSpeedLoad[1] ~= 0 or fillVolume.scrollSpeedLoad[2] ~= 0 or fillVolume.scrollSpeedLoad[3] ~= 0 then
178 fillVolume.uvPosition[1] = fillVolume.uvPosition[1] + fillVolume.scrollSpeedLoad[1]*dt
179 fillVolume.uvPosition[2] = fillVolume.uvPosition[2] + fillVolume.scrollSpeedLoad[2]*dt
180 fillVolume.uvPosition[3] = fillVolume.uvPosition[3] + fillVolume.scrollSpeedLoad[3]*dt
181 setShaderParameter(fillVolume.volume, "uvOffset", fillVolume.uvPosition[1], fillVolume.uvPosition[2], fillVolume.uvPosition[3], 0, false)
182 end
183 end
184 end
185 end
186 end
187 end
188 end
189 end
190end

updateTick

Description
Called on update tick
Definition
updateTick(float dt)
Arguments
floatdttime since last call in ms
Code
195function ForageWagon:updateTick(dt)
196 self.forageWagon.isSpeedLimitActive = false
197 if self.isServer then
198 self.forageWagon.lastAreaBiggerZero = false
199 end
200
201 if self:getIsActive() then
202 if self:getIsTurnedOn() then
203 if self:getUnitFillLevel(self.forageWagon.fillUnitIndex) < self:getUnitCapacity(self.forageWagon.fillUnitIndex) then
204 if self:allowPickingUp() then
205 self.forageWagon.isSpeedLimitActive = true
206 if self.isServer then
207 local workAreas, _, _ = self:getTypedNetworkAreas(WorkArea.AREATYPE_FORAGEWAGON, false)
208
209 if (table.getn(workAreas) > 0) then
210 local fruitTypeFix = false
211 local fruitType = FruitUtil.FRUITTYPE_UNKNOWN
212 local fillType = self:getUnitFillType(self.forageWagon.fillUnitIndex)
213
214 if self:getUnitFillLevel(self.forageWagon.fillUnitIndex) > self:getUnitCapacity(self.forageWagon.fillUnitIndex)*self.fillTypeChangeThreshold and FruitUtil.fillTypeToFruitType[fillType] ~= nil and FruitUtil.fillTypeIsWindrow[fillType] then
215 fruitTypeFix = true
216 fruitType = FruitUtil.fillTypeToFruitType[fillType]
217 end
218 local liters, usedFruitType = self:processForageWagonAreas(workAreas, self:getUnitFillTypes(self.forageWagon.fillUnitIndex), fruitTypeFix, fruitType)
219
220 if liters > 0 then
221 local deltaLevel = liters * self.forageWagon.fillScale
222 self:setUnitFillLevel(self.forageWagon.fillUnitIndex, self:getUnitFillLevel(self.forageWagon.fillUnitIndex)+deltaLevel, FruitUtil.fruitTypeToWindrowFillType[usedFruitType], true, self.fillVolumeLoadInfos[self.forageWagon.loadInfoIndex])
223
224 self.forageWagon.lastAreaBiggerZero = true
225 if self.forageWagon.lastAreaBiggerZero ~= self.forageWagon.lastAreaBiggerZeroSent then
226 self:raiseDirtyFlags(self.forageWagon.dirtyFlag)
227 self.forageWagon.lastAreaBiggerZeroSent = self.forageWagon.lastAreaBiggerZero
228 end
229 end
230 end
231 end
232 end
233
234 if self:getIsActiveForSound() then
235 SoundUtil.playSample(self.forageWagon.sampleRunning, 0, 0, nil)
236 end
237
238 if self.forageWagon.lastAreaBiggerZero and self.fillUnits[self.forageWagon.fillUnitIndex].lastValidFillType ~= FillUtil.FILLTYPE_UNKNOWN then
239 self.forageWagon.lastAreaBiggerZeroTime = 500
240 else
241 if self.forageWagon.lastAreaBiggerZeroTime > 0 then
242 self.forageWagon.lastAreaBiggerZeroTime = self.forageWagon.lastAreaBiggerZeroTime - dt
243 end
244 end
245
246 if self.isClient then
247 if self.forageWagon.fillEffects ~= nil then
248 if self.forageWagon.lastAreaBiggerZeroTime > 0 then
249 EffectManager:setFillType(self.forageWagon.fillEffects, self.fillUnits[self.forageWagon.fillUnitIndex].lastValidFillType)
250 EffectManager:startEffects(self.forageWagon.fillEffects)
251 else
252 EffectManager:stopEffects(self.forageWagon.fillEffects)
253 end
254 end
255
256 local currentFillParticleSystem = self.forageWagon.fillParticleSystems[self.fillUnits[self.forageWagon.fillUnitIndex].lastValidFillType]
257 if currentFillParticleSystem ~= self.forageWagon.currentFillParticleSystem then
258 if self.forageWagon.currentFillParticleSystem ~= nil then
259 for _, ps in pairs(self.forageWagon.currentFillParticleSystem) do
260 ParticleUtil.setEmittingState(ps, false)
261 end
262 self.forageWagon.currentFillParticleSystem = nil
263 end
264 self.forageWagon.currentFillParticleSystem = currentFillParticleSystem
265 end
266
267 if self.forageWagon.currentFillParticleSystem ~= nil then
268 for _, ps in pairs(self.forageWagon.currentFillParticleSystem) do
269 ParticleUtil.setEmittingState(ps, self.forageWagon.lastAreaBiggerZeroTime > 0)
270 end
271 end
272
273 end
274 else
275 self:setIsTurnedOn(false)
276 if self.setPickupState ~= nil then
277 self:setPickupState(false)
278 end
279 end
280 end
281
282 -- alarm sound
283 if self.isClient then
284 if self:getIsTurnedOn() and self:getUnitFillLevel(self.forageWagon.fillUnitIndex) > (self:getUnitCapacity(self.forageWagon.fillUnitIndex) * 0.98) and self:getUnitFillLevel(self.forageWagon.fillUnitIndex) < self:getUnitCapacity(self.forageWagon.fillUnitIndex) then
285 if self:getIsActiveForSound() then
286 SoundUtil.playSample(self.forageWagon.sampleAlarm, 0, 0, nil)
287 end
288 else
289 SoundUtil.stopSample(self.forageWagon.sampleAlarm)
290 end
291 end
292 end
293end

onTurnedOff

Description
Called on turn off
Definition
onTurnedOff(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
301function ForageWagon:onTurnedOff(noEventSend)
302 ForageWagon.onDeactivateSounds(self)
303 if self.isClient then
304 if self.forageWagon.fillEffects ~= nil then
305 EffectManager:stopEffects(self.forageWagon.fillEffects)
306 end
307 if self.forageWagon.currentFillParticleSystem ~= nil then
308 for _, ps in pairs(self.forageWagon.currentFillParticleSystem) do
309 ParticleUtil.setEmittingState(ps, false)
310 end
311 end
312 end
313end

onDeactivate

Description
Called on deactivate
Definition
onDeactivate()
Code
317function ForageWagon:onDeactivate()
318 if self.isClient then
319 if self.forageWagon.fillEffects ~= nil then
320 EffectManager:stopEffects(self.forageWagon.fillEffects)
321 end
322 if self.forageWagon.currentFillParticleSystem ~= nil then
323 for _, ps in pairs(self.forageWagon.currentFillParticleSystem) do
324 ParticleUtil.setEmittingState(ps, false)
325 end
326 end
327 end
328end

onDeactivateSounds

Description
Called on deactivating sounds
Definition
onDeactivateSounds()
Code
332function ForageWagon:onDeactivateSounds()
333 if self.isClient then
334 SoundUtil.stopSample(self.forageWagon.sampleRunning, true)
335 SoundUtil.stopSample(self.forageWagon.sampleBalerAlarm, true)
336 end
337end

doCheckSpeedLimit

Description
Returns if speed limit should be checked
Definition
doCheckSpeedLimit()
Return Values
booleancheckSpeedlimitcheck speed limit
Code
342function ForageWagon:doCheckSpeedLimit(superFunc)
343 local parent = false
344 if superFunc ~= nil then
345 parent = superFunc(self)
346 end
347
348 return parent or self.forageWagon.isSpeedLimitActive
349end

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
357function ForageWagon:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
358 local retValue = true
359 if superFunc ~= nil then
360 retValue = superFunc(self, workArea, xmlFile, key)
361 end
362
363 if workArea.type == WorkArea.AREATYPE_DEFAULT then
364 workArea.type = WorkArea.AREATYPE_FORAGEWAGON
365 end
366
367 return retValue
368end

getDefaultSpeedLimit

Description
Returns default speed limit
Definition
getDefaultSpeedLimit()
Return Values
floatspeedLimitspeed limit
Code
373function ForageWagon.getDefaultSpeedLimit()
374 return 20
375end

loadSpeedRotatingPartFromXML

Description
Loads speed rotating parts from xml
Definition
loadSpeedRotatingPartFromXML(table speedRotatingPart, integer xmlFile, string key)
Arguments
tablespeedRotatingPartspeedRotatingPart
integerxmlFileid of xml object
stringkeykey
Return Values
booleansuccesssuccess
Code
383function ForageWagon:loadSpeedRotatingPartFromXML(superFunc, speedRotatingPart, xmlFile, key)
384 if superFunc ~= nil then
385 if not superFunc(self, speedRotatingPart, xmlFile, key) then
386 return false
387 end
388 end
389
390 speedRotatingPart.rotateOnlyIfFillLevelIncreased = Utils.getNoNil(getXMLBool(xmlFile, key .. "#rotateOnlyIfFillLevelIncreased"), false)
391
392 return true
393end

getIsSpeedRotatingPartActive

Description
Returns true if speed rotating part is active
Definition
getIsSpeedRotatingPartActive(table speedRotatingPart)
Arguments
tablespeedRotatingPartspeedRotatingPart
Return Values
booleanisActivespeed rotating part is active
Code
399function ForageWagon:getIsSpeedRotatingPartActive(superFunc, speedRotatingPart)
400 if speedRotatingPart.rotateOnlyIfFillLevelIncreased ~= nil then
401 if speedRotatingPart.rotateOnlyIfFillLevelIncreased and not self.forageWagon.lastAreaBiggerZeroTime then
402 return false
403 end
404 end
405
406 if superFunc ~= nil then
407 return superFunc(self, speedRotatingPart)
408 end
409 return true
410end

getTipScrollerSpeed

Description
Returns tip scroller speed
Definition
getTipScrollerSpeed()
Return Values
floattipScrollerSpeedtip scroller speed
Code
415function ForageWagon:getTipScrollerSpeed(superFunc)
416 local value = 0
417 if self:getIsTurnedOn() then
418 value = self.forageWagon.turnedOnTipScrollerSpeedFactor
419 end
420 return math.max(value, superFunc(self))
421end

processForageWagonAreas

Description
Process forage wagon areas
Definition
processForageWagonAreas(table workAreas, table fillTypes, boolean fruitTypeFix, integer fruitType)
Arguments
tableworkAreaswork areas
tablefillTypesfill types
booleanfruitTypeFixuse fixed fruit type
integerfruitTypefruit type
Return Values
floattotalLitersliters collected
integerfruitTypeused fruit type
Code
431function ForageWagon:processForageWagonAreas(workAreas, fillTypes, fruitTypeFix, fruitType)
432
433 local numAreas = table.getn(workAreas)
434 local totalLiters = 0
435 for i=1, numAreas do
436 local x0 = workAreas[i][1]
437 local z0 = workAreas[i][2]
438 local x1 = workAreas[i][3]
439 local z1 = workAreas[i][4]
440 local x2 = workAreas[i][5]
441 local z2 = workAreas[i][6]
442
443 local hx = x2 - x0
444 local hz = z2 - z0
445 local hLength = Utils.vector2Length(hx, hz)
446 local hLength_2 = 0.5 * hLength
447
448 local wx = x1 - x0
449 local wz = z1 - z0
450 local wLength = Utils.vector2Length(wx, wz)
451
452 local sx = x0 + (hx * 0.5) + ((wx/wLength)*hLength_2)
453 local sz = z0 + (hz * 0.5) + ((wz/wLength)*hLength_2)
454
455 local ex = x1 + (hx * 0.5) - ((wx/wLength)*hLength_2)
456 local ez = z1 + (hz * 0.5) - ((wz/wLength)*hLength_2)
457
458 local sy = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, sx,0,sz)
459 local ey = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, ex,0,ez)
460
461
462 local liters = 0
463 if fruitTypeFix then
464 local fillType = FruitUtil.fruitTypeToWindrowFillType[fruitType]
465 liters = -TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil)
466
467 local fruitDesc = FruitUtil.fruitIndexToDesc[fruitType]
468 if fruitDesc ~= nil then
469 for fruitTypeSrc,_ in pairs(fruitDesc.forageWagonConversionSources) do
470 local fillType = FruitUtil.fruitTypeToWindrowFillType[fruitTypeSrc]
471 liters = liters - TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil)
472 end
473 end
474 else
475 for fillType, enabled in pairs(fillTypes) do
476 -- Note: we count both grass and dry grass as grass (ignore dry grass in the loop, and pickup dry grass when cutting normal grass)
477 -- and we do the same with barley and wheat windrows
478 -- This is generalized with the forageWagonConversionTarget and forageWagonConversionSources attributes of the fruitTypeDesc
479 local localFruitType = FruitUtil.fillTypeToFruitType[fillType]
480 local fruitDesc
481 if localFruitType ~= nil then
482 fruitDesc = FruitUtil.fruitIndexToDesc[localFruitType]
483 end
484 if enabled and fruitDesc ~= nil then
485 liters = -TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil)
486
487 if fruitDesc ~= nil and FruitUtil.fillTypeIsWindrow[fillType] and fruitDesc.forageWagonConversionTarget == nil then
488 for fruitTypeSrc,_ in pairs(fruitDesc.forageWagonConversionSources) do
489 local fillType = FruitUtil.fruitTypeToWindrowFillType[fruitTypeSrc]
490 liters = liters - TipUtil.tipToGroundAroundLine(self, -math.huge, fillType, sx,sy,sz, ex,ey,ez, hLength_2, nil, nil, false, nil)
491 end
492 end
493 if liters > 0 then
494 fruitTypeFix = true
495 fruitType = localFruitType;
496 break
497 end
498 end
499 end
500 end
501 if liters > 0 then
502 -- now that we removed the windrow, maybe there is some hidden drygrass to grow (set it to growth state 1 if there is some)
503 if fruitType == FruitUtil.FRUITTYPE_GRASS then
504 Utils.switchFruitTypeArea(FruitUtil.FRUITTYPE_GRASS, FruitUtil.FRUITTYPE_DRYGRASS, x0, z0, x1, z1, x2, z2, 2)
505 end
506 totalLiters = totalLiters + liters
507 end
508 end
509 return totalLiters, fruitType
510end