LUADOC - Farming Simulator 17

Printable Version

SiloTrigger

Description
Class for silo triggers
Functions

onCreate

Description
On create silo trigger
Definition
onCreate(integer id)
Arguments
integeridtrigger node id
Code
17function SiloTrigger:onCreate(id)
18 local trigger = SiloTrigger:new(g_server ~= nil, g_client ~= nil);
19 g_currentMission:addOnCreateLoadedObject(trigger);
20 if trigger:load(id) then
21 trigger:register(true);
22 else
23 trigger:delete();
24 end;
25end;

new

Description
Creating silo trigger object
Definition
new(boolean isServer, boolean isClient)
Arguments
booleanisServeris server
booleanisClientis client
Return Values
tableinstanceInstance of object
Code
32function SiloTrigger:new(isServer, isClient)
33 local self = Object:new(isServer, isClient, SiloTrigger_mt);
34 self.rootNode = 0;
35 self.activeTriggers = 0;
36 self.siloTriggerDirtyFlag = self:getNextDirtyFlag();
37 g_currentMission:addSiloTrigger(self);
38 return self;
39end;

load

Description
Load silo trigger attributes
Definition
load(integer id)
Arguments
integeridtrigger node id
Return Values
booleansuccesssuccess
Code
45function SiloTrigger:load(id)
46 self.rootNode = id;
47
48 self.triggerIds = {};
49 local triggerRoot = Utils.indexToObject(id, getUserAttribute(id, "triggerIndex"));
50 if triggerRoot == nil then
51 triggerRoot = id;
52 end
53 table.insert(self.triggerIds, triggerRoot);
54 addTrigger(triggerRoot, "triggerCallback", self);
55 for i=1, 3 do
56 local child = getChildAt(triggerRoot, i-1);
57 table.insert(self.triggerIds, child);
58 addTrigger(child, "triggerCallback", self);
59 end;
60
61 self.fillVolumeDischargeInfos = {};
62 self.fillVolumeDischargeInfos.name = "fillVolumeDischargeInfo";
63 self.fillVolumeDischargeInfos.nodes = {};
64 local node = Utils.indexToObject(id, getUserAttribute(id, "fillVolumeDischargeNode"));
65 local width = Utils.getNoNil( getUserAttribute(id, "fillVolumeDischargeNodeWidth"), 0.5 );
66 local length = Utils.getNoNil( getUserAttribute(id, "fillVolumeDischargeNodeLength"), 0.5 );
67 table.insert(self.fillVolumeDischargeInfos.nodes, {node=node, width=width, length=length, priority=1});
68
69 self.selectedFillType = nil;
70 self.fillLitersPerSecond = Utils.getNoNil(tonumber(getUserAttribute(id, "fillLitersPerSecond")), 1500);
71 self.stationName = g_i18n:getText(Utils.getNoNil(getUserAttribute(id, "stationName"), "station_farmSilo"));
72 self.storageRadius = Utils.getNoNil(getUserAttribute(id, "storageRadius"), 50);
73 self.isFarmSilo = Utils.getNoNil(getUserAttribute(id, "isFarmSilo"), false)
74 self.supportsExtension = Utils.getNoNil(getUserAttribute(id, "supportsExtension"), true)
75 if self.isFarmSilo then
76 if g_currentMission.farmSiloTrigger == nil then
77 g_currentMission.farmSiloTrigger = self
78 end
79 end
80 self.isEnabled = true;
81 self.siloTrailer = nil;
82 self.siloTrailerSend = nil;
83 self.isFilling = false;
84 self.startFillText = g_i18n:getText("action_siloStartFilling");
85 self.stopFillText = g_i18n:getText("action_siloStopFilling");
86 self.activateText = self.startFillText;
87 self.objectActivated = false;
88
89
90 if self.isClient then
91 local dropParticleSystem = Utils.indexToObject(id, getUserAttribute(id, "dropParticleSystemIndex"));
92 if dropParticleSystem ~= nil then
93 self.dropParticleSystems = {}
94 for i=getNumOfChildren(dropParticleSystem)-1, 0, -1 do
95 local child = getChildAt(dropParticleSystem, i)
96 local ps = {}
97 ParticleUtil.loadParticleSystemFromNode(child, ps, true, true)
98 table.insert(self.dropParticleSystems, ps)
99 end
100 end
101
102 local lyingParticleSystem = Utils.indexToObject(id, getUserAttribute(id, "lyingParticleSystemIndex"));
103 if lyingParticleSystem ~= nil then
104 self.lyingParticleSystems = {};
105
106 for i=getNumOfChildren(lyingParticleSystem)-1, 0, -1 do
107 local child = getChildAt(lyingParticleSystem, i)
108 local ps = {}
109 ParticleUtil.loadParticleSystemFromNode(child, ps, false, true)
110 ParticleUtil.addParticleSystemSimulationTime(ps, ps.originalLifespan)
111 ParticleUtil.setParticleSystemTimeScale(ps, 0);
112 table.insert(self.lyingParticleSystems, ps)
113 end
114 end
115
116 if self.dropParticleSystems == nil then
117 local effectsNode = Utils.indexToObject(id, getUserAttribute(id, "effectsNode"));
118 if effectsNode ~= nil then
119 self.dropEffects = EffectManager:loadFromNode(effectsNode, self);
120 end
121
122 if self.dropEffects == nil then
123 local x,y,z = getTranslation(id);
124
125 local particlePositionStr = getUserAttribute(id, "particlePosition");
126 if particlePositionStr ~= nil then
127 local psx,psy,psz = Utils.getVectorFromString(particlePositionStr);
128 if psx ~= nil and psy ~= nil and psz ~= nil then
129 x = x + psx;
130 y = y + psy;
131 z = z + psz;
132 end;
133 end;
134
135 local psData = {};
136 psData.psFile = getUserAttribute(id, "particleSystemFilename");
137 if psData.psFile == nil then
138 local particleSystem = Utils.getNoNil(getUserAttribute(id, "particleSystem"), "unloadingSiloParticles");
139 psData.psFile = "$data/vehicles/particleAnimation/shared/" .. particleSystem .. ".i3d";
140 end
141 psData.posX, psData.posY, psData.posZ = x,y,z;
142 psData.worldSpace = false;
143
144 self.dropParticleSystems = {};
145 local ps = {}
146 ParticleUtil.loadParticleSystemFromData(psData, ps, nil, false, nil, g_currentMission.baseDirectory, getParent(id));
147 table.insert(self.dropParticleSystems, ps)
148 end;
149 end
150
151 local fillSoundFilename = getUserAttribute(id, "fillSoundFilename");
152 if fillSoundFilename == nil then
153 fillSoundFilename = "$data/maps/sounds/siloFillSound.wav";
154 end
155 if fillSoundFilename ~= "" and fillSoundFilename ~= "none" then
156 fillSoundFilename = Utils.getFilename(fillSoundFilename, g_currentMission.baseDirectory);
157 self.siloFillSound = createAudioSource("siloFillSound", fillSoundFilename, 30, 10, 1, 0);
158 link(id, self.siloFillSound);
159 setVisibility(self.siloFillSound, false);
160 end
161
162
163 self.scroller = Utils.indexToObject(id, getUserAttribute(id, "scrollerIndex"));
164 if self.scroller ~= nil then
165 self.scrollerShaderParameterName = Utils.getNoNil(getUserAttribute(self.scroller, "shaderParameterName"), "uvScrollSpeed");
166 local scrollerScrollSpeed = getUserAttribute(self.scroller, "scrollSpeed");
167 if scrollerScrollSpeed ~= nil then
168 self.scrollerSpeedX, self.scrollerSpeedY = Utils.getVectorFromString(scrollerScrollSpeed);
169 end
170 self.scrollerSpeedX = Utils.getNoNil(self.scrollerSpeedX, 0);
171 self.scrollerSpeedY = Utils.getNoNil(self.scrollerSpeedY, -0.75);
172 setShaderParameter(self.scroller, self.scrollerShaderParameterName, 0, 0, 0, 0, false);
173 end
174 end;
175
176 return true;
177end;

delete

Description
Delete silo trigger
Definition
delete()
Code
181function SiloTrigger:delete()
182 if self.isClient then
183 if self.siloFillSound ~= nil then
184 delete(self.siloFillSound);
185 end
186 EffectManager:deleteEffects(self.dropEffects);
187 ParticleUtil.deleteParticleSystems(self.dropParticleSystems)
188 ParticleUtil.deleteParticleSystems(self.lyingParticleSystems)
189 end
190 for i=1, table.getn(self.triggerIds) do
191 removeTrigger(self.triggerIds[i]);
192 end
193 g_currentMission:removeSiloTrigger(self);
194 delete(self.rootNode);
195 SiloTrigger:superClass().delete(self);
196end;

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
204function SiloTrigger:readStream(streamId, connection)
205 SiloTrigger:superClass().readStream(self, streamId);
206 if connection:getIsServer() then
207 local isFilling = streamReadBool(streamId);
208 if isFilling then
209 local fillType = streamReadUIntN(streamId, FillUtil.sendNumBits);
210 self:setIsFilling(true, fillType, true);
211 else
212 self:setIsFilling(false, FillUtil.FILLTYPE_UNKNOWN, true);
213 end;
214 self.siloTrailer = readNetworkNodeObject(streamId);
215 end;
216end;

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
222function SiloTrigger:writeStream(streamId, connection)
223 SiloTrigger:superClass().writeStream(self, streamId);
224 if not connection:getIsServer() then
225 streamWriteBool(streamId, self.isFilling);
226 if self.isFilling then
227 streamWriteUIntN(streamId, self.selectedFillType, FillUtil.sendNumBits);
228 end;
229 writeNetworkNodeObject(streamId, self.siloTrailerSend);
230 end;
231end;

readUpdateStream

Description
Called on client side on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
238function SiloTrigger:readUpdateStream(streamId, timestamp, connection)
239 SiloTrigger:superClass().readUpdateStream(self, streamId, timestamp, connection);
240 if connection:getIsServer() then
241 if streamReadBool(streamId) then
242 local siloTrailer = readNetworkNodeObject(streamId);
243 if siloTrailer ~= nil then
244 g_currentMission:addActivatableObject(self);
245 else
246 g_currentMission:removeActivatableObject(self);
247 end;
248 end;
249 end;
250end;

writeUpdateStream

Description
Called on server side on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
257function SiloTrigger:writeUpdateStream(streamId, connection, dirtyMask)
258 SiloTrigger:superClass().writeUpdateStream(self, streamId, connection, dirtyMask);
259 if not connection:getIsServer() then
260 if streamWriteBool(streamId, bitAND(dirtyMask, self.siloTriggerDirtyFlag) ~= 0) then
261 writeNetworkNodeObject(streamId, self.siloTrailerSend);
262 end;
263 end;
264end;

update

Description
Update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
269function SiloTrigger:update(dt)
270 if self.isServer then
271 local trailer = self.siloTrailer;
272 if self.activeTriggers >= 4 and trailer ~= nil then
273 if self.isFilling then
274 trailer:resetFillLevelIfNeeded(self.selectedFillType);
275 local fillLevel = trailer:getFillLevel(self.selectedFillType);
276
277 local siloAmount, siloSource = self:getFillLevelTarget(self.selectedFillType);
278 if siloAmount > 0 and trailer:allowFillType(self.selectedFillType, false) and trailer:getAllowFillFromAir() then
279 local deltaFillLevel = math.min(self.fillLitersPerSecond*0.001*dt, siloAmount);
280 trailer:setFillLevel(fillLevel+deltaFillLevel, self.selectedFillType, false, self.fillVolumeDischargeInfos);
281 local newFillLevel = trailer:getFillLevel(self.selectedFillType);
282
283 if fillLevel ~= newFillLevel then
284 siloSource:setFillLevel(math.max(siloAmount-(newFillLevel-fillLevel), 0), self.selectedFillType, trailer);
285 else
286 self:setIsFilling(false, FillUtil.FILLTYPE_UNKNOWN);
287 end;
288 else
289 self:setIsFilling(false, FillUtil.FILLTYPE_UNKNOWN);
290 end;
291 end;
292 elseif self.isFilling then
293 self:setIsFilling(false, FillUtil.FILLTYPE_UNKNOWN);
294 end;
295
296 if self.siloTrailerSend ~= self.siloTrailer then
297 self.siloTrailerSend = self.siloTrailer;
298 self:raiseDirtyFlags(self.siloTriggerDirtyFlag);
299 end;
300 end;
301end;

getFillLevelTarget

Description
Returns fill level of first valid silo source
Definition
getFillLevelTarget(integer fillType)
Arguments
integerfillTypefill type
Return Values
floatfillLevelfill level
tablesiloSourcesilo source
Code
308function SiloTrigger:getFillLevelTarget(fillType)
309 if self.siloSources == nil then
310 return nil;
311 end
312
313 local fillLevel = 0;
314 local siloSource = nil;
315 for silo,_ in pairs(self.siloSources) do
316 fillLevel = Utils.getNoNil(silo:getFillLevel(fillType), 0);
317 if fillLevel > 0 then
318 siloSource = silo;
319 break;
320 end;
321 end;
322
323 return fillLevel, siloSource;
324end;

getFillLevel

Description
Get fill type fill level from all silo sources
Definition
getFillLevel(integer fillType)
Arguments
integerfillTypefill type index
Return Values
floatfillLevelfill level
Code
330function SiloTrigger:getFillLevel(fillType)
331 if self.siloSources == nil then
332 return nil;
333 end
334
335 local level = 0;
336 for siloSource,_ in pairs(self.siloSources) do
337 level = level + Utils.getNoNil(siloSource:getFillLevel(fillType), 0);
338 end;
339 return level;
340end;

getAllFillLevels

Description
Returns fill levels of all fill types and the capacity
Definition
getAllFillLevels()
Return Values
tablefillLevelsfill levels sorted by fill type
floatcapacitycapacity of all silo sources
Code
346function SiloTrigger:getAllFillLevels()
347 local fillLevels = {};
348 local capacity = 0
349
350 for siloSource,_ in pairs(self.siloSources) do
351 for fillType, fillLevel in pairs(siloSource.fillLevels) do
352 fillLevels[fillType] = Utils.getNoNil(fillLevels[fillType], 0) + fillLevel;
353 end;
354 capacity = capacity + siloSource.capacity
355 end;
356
357 return fillLevels, capacity;
358end;

getIsActivatable

Description
Returns true if it is activateable
Definition
getIsActivatable()
Return Values
booleanisActivateableis activateable
Code
363function SiloTrigger:getIsActivatable()
364 if not self.isEnabled then
365 return false;
366 end;
367 if self.isFilling then
368 if self.siloTrailer:getRootAttacherVehicle() == g_currentMission.controlledVehicle then
369 return true;
370 end;
371 else
372 if self.siloTrailer ~= nil and self.activeTriggers >= 4 then
373 local trailer = self.siloTrailer;
374 if trailer:getRootAttacherVehicle() ~= g_currentMission.controlledVehicle then
375 return false;
376 end;
377 if not trailer:getAllowFillFromAir() then
378 return false
379 end
380 if trailer:getFillLevel() == 0 then
381 return true;
382 else
383 local fillTypes = trailer:getCurrentFillTypes();
384 for _,fillType in pairs(fillTypes) do
385 if self.fillTypes[fillType] ~= nil and trailer:getFillLevel(fillType) < trailer:getCapacity() and self:getFillLevel(fillType) > 0 then
386 return true;
387 end
388 end
389 end;
390 end;
391 end;
392
393 return false;
394end;

onActivateObject

Description
Called on activate object
Definition
onActivateObject()
Code
402function SiloTrigger:onActivateObject()
403 if not self.isFilling then
404 local numFillTypes = 0;
405 local fillType = nil;
406 for f,_ in pairs(self.fillTypes) do
407 numFillTypes = numFillTypes + 1;
408 fillType = f
409 end;
410 if self.siloTrailer ~= nil and self.siloTrailer:getFillLevel() > 0 then
411 local fillTypes = self.siloTrailer:getCurrentFillTypes();
412 for _,fillType in pairs(fillTypes) do
413 if self.fillTypes[fillType] ~= nil and self.siloTrailer:getFillLevel(fillType) < self.siloTrailer:getCapacity(fillType) then
414 self:setIsFilling(true, fillType);
415 end
416 end
417 elseif numFillTypes == 1 then
418 self:setIsFilling(true, fillType);
419 else
420 local fillLevels, capacity = self:getAllFillLevels()
421 g_gui:showSiloDialog({title=string.format("%s (%d %s)", self.stationName, g_i18n:getFluid(capacity, 0), g_i18n:getText("unit_literShort")), fillLevels=fillLevels, capacity=capacity, callback=self.onFillTypeSelection, target=self})
422 end;
423 else
424 self:setIsFilling(false, FillUtil.FILLTYPE_UNKNOWN);
425 end;
426 g_currentMission:addActivatableObject(self);
427end;

addSiloSource

Description
Add silo source to silo trigger
Definition
addSiloSource(table siloSource)
Arguments
tablesiloSourcesilo source to add
Code
432function SiloTrigger:addSiloSource(siloSource)
433 if self.siloSources == nil then
434 self.siloSources = {};
435 end;
436 self.siloSources[siloSource] = siloSource;
437 if siloSource.addSiloTrigger ~= nil then
438 siloSource:addSiloTrigger(self)
439 end
440 self:updateFillTypes();
441end;

removeSiloSource

Description
Remove silo source from silo trigger
Definition
removeSiloSource(table siloSource)
Arguments
tablesiloSourcesilo source to remove
Code
446function SiloTrigger:removeSiloSource(siloSource)
447 self.siloSources[siloSource] = nil;
448 local numSources = 0;
449 for _, _ in pairs(self.siloSources) do
450 numSources = numSources + 1;
451 end;
452 if numSources == 0 then
453 self.siloSources = nil;
454 end;
455 if siloSource.removeSiloTrigger ~= nil then
456 siloSource:removeSiloTrigger(self)
457 end
458 self:updateFillTypes();
459end;

updateFillTypes

Description
Update available fill types
Definition
updateFillTypes()
Code
463function SiloTrigger:updateFillTypes()
464 self.fillTypes = {};
465 if self.siloSources ~= nil then
466 for siloSource,_ in pairs(self.siloSources) do
467 for fillType,_ in pairs(siloSource.fillTypes) do
468 self.fillTypes[fillType] = fillType;
469 end;
470 end;
471 end;
472end;

stopFill

Description
Stop filling
Definition
stopFill()
Code
476function SiloTrigger:stopFill()
477 if self.isFilling then
478 self.isFilling = false;
479 self.activateText = self.startFillText;
480 if self.isClient then
481 if self.siloFillSoundEnabled then
482 setVisibility(self.siloFillSound, false);
483 self.siloFillSoundEnabled = false;
484 end;
485 if self.dropParticleSystems ~= nil then
486 for _, ps in pairs(self.dropParticleSystems) do
487 ParticleUtil.setEmittingState(ps, false);
488 end
489 end
490 if self.lyingParticleSystems ~= nil then
491 for _, ps in pairs(self.lyingParticleSystems) do
492 ParticleUtil.setParticleSystemTimeScale(ps, 0);
493 end
494 end
495 EffectManager:stopEffects(self.dropEffects);
496 if self.scroller ~= nil then
497 setShaderParameter(self.scroller, self.scrollerShaderParameterName, 0, 0, 0, 0, false);
498 end
499 end;
500 end;
501end;

startFill

Description
Start filling
Definition
startFill(integer fillType)
Arguments
integerfillTypefill type
Code
506function SiloTrigger:startFill(fillType)
507 if not self.isFilling then
508 self.activateText = self.stopFillText;
509 self.isFilling = true;
510 self.selectedFillType = fillType;
511 if self.isClient then
512 if not self.siloFillSoundEnabled and self.siloFillSound ~= nil then
513 setVisibility(self.siloFillSound, true);
514 self.siloFillSoundEnabled = true;
515 end;
516 if self.dropParticleSystems ~= nil then
517 for _, ps in pairs(self.dropParticleSystems) do
518 ParticleUtil.setEmittingState(ps, true);
519 end
520 end
521 if self.lyingParticleSystems ~= nil then
522 for _, ps in pairs(self.lyingParticleSystems) do
523 ParticleUtil.setParticleSystemTimeScale(ps, 1.0);
524 end
525 end
526 if self.dropEffects ~= nil then
527 EffectManager:setFillType(self.dropEffects, self.selectedFillType)
528 EffectManager:startEffects(self.dropEffects);
529 end;
530
531 if self.scroller ~= nil then
532 setShaderParameter(self.scroller, self.scrollerShaderParameterName, self.scrollerSpeedX, self.scrollerSpeedY, 0, 0, false);
533 end
534 end;
535 end;
536end;

onFillTypeSelection

Description
Called if fill type was selected
Definition
onFillTypeSelection(integer fillType)
Arguments
integerfillTypefill type
Code
541function SiloTrigger:onFillTypeSelection(fillType)
542 if fillType ~= nil and fillType ~= FillUtil.FILLTYPE_UNKNOWN then
543 if self.siloTrailer ~= nil then
544 if self:getIsValidTrailer(self.siloTrailer) then
545 self:setIsFilling(true, fillType);
546 end;
547 end;
548 end;
549end;

setIsFilling

Description
Set is filling
Definition
setIsFilling(boolean isFilling, integer fillType, boolean noEventSend)
Arguments
booleanisFillingis filling
integerfillTypefill type
booleannoEventSendno event send
Code
556function SiloTrigger:setIsFilling(isFilling, fillType, noEventSend)
557 SiloTriggerSetIsFillingEvent.sendEvent(self, isFilling, fillType, noEventSend);
558 if isFilling then
559 self:startFill(fillType);
560 else
561 self:stopFill();
562 end;
563end;

getIsValidTrailer

Description
Returns true if trailer supports any fill type of silo
Definition
getIsValidTrailer(table trailer)
Arguments
tabletrailertrailer to check
Code
568function SiloTrigger:getIsValidTrailer(trailer)
569 for _, fillType in pairs(self.fillTypes) do
570 if trailer:allowFillType(fillType, false) then
571 return true;
572 end;
573 end;
574
575 return false;
576end;

triggerCallback

Description
Trigger callback
Definition
triggerCallback(integer triggerId, integer otherActorId, boolean onEnter, boolean onLeave, boolean onStay, integer otherShapeId)
Arguments
integertriggerIdid of trigger
integerotherActorIdid of other actor
booleanonEnteron enter
booleanonLeaveon leave
booleanonStayon stay
integerotherShapeIdid of other shape
Code
586function SiloTrigger:triggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
587 if self.isEnabled then
588 local trailer = g_currentMission.objectToTrailer[otherActorId];
589 if trailer ~= nil and otherActorId == trailer.exactFillRootNode and self:getIsValidTrailer(trailer) then
590 if onEnter and trailer.getAllowFillFromAir ~= nil then
591 self.activeTriggers = self.activeTriggers + 1;
592 self.siloTrailer = trailer;
593 g_currentMission:addActivatableObject(self);
594
595 if self.activeTriggers >= 4 then
596 if self.siloTrailer.coverAnimation ~= nil then
597 self.siloTrailer:setCoverState(true);
598 end
599 end
600 elseif onLeave then
601 if self.siloTrailer ~= nil and self.siloTrailer.coverAnimation ~= nil and self.siloTrailer.autoReactToTrigger == true then
602 self.siloTrailer:setCoverState(false);
603 end
604
605 self.activeTriggers = math.max(self.activeTriggers - 1, 0);
606 self.siloTrailer = nil;
607 self:setIsFilling(false, FillUtil.FILLTYPE_UNKNOWN);
608 g_currentMission:removeActivatableObject(self);
609 end;
610 end;
611 end;
612end;