LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

Pipe

Description
Class for all vehicles with a pipe
Functions

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
20function Pipe.prerequisitesPresent(specializations)
21 return SpecializationUtil.hasSpecialization(Overloading, specializations);
22end

preLoad

Description
Called before loading
Definition
preLoad(table savegame)
Arguments
tablesavegamesavegame
Code
27function Pipe:preLoad(savegame)
28 self.getAllowPipeEffects = Utils.overwrittenFunction(self.getAllowPipeEffects, Pipe.getAllowPipeEffects);
29 self.getOverloadingActive = Utils.overwrittenFunction(self.getOverloadingActive, Pipe.getOverloadingActive);
30end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
35function Pipe:load(savegame)
36 self.getIsTurnedOnAllowed = Utils.overwrittenFunction(self.getIsTurnedOnAllowed, Pipe.getIsTurnedOnAllowed);
37 self.getTurnedOnNotAllowedWarning = Utils.overwrittenFunction(self.getTurnedOnNotAllowedWarning, Pipe.getTurnedOnNotAllowedWarning);
38 self.getAutomaticOverloadingState = Utils.overwrittenFunction(self.getAutomaticOverloadingState, Pipe.getAutomaticOverloadingState);
39
40 self.getCanTipToGround = Pipe.getCanTipToGround;
41 self.setDischargeToGround = SpecializationUtil.callSpecializationsFunction("setDischargeToGround");
42
43 self.doOverload = Utils.overwrittenFunction(self.doOverload, Pipe.doOverload);
44
45 self.getIsFoldAllowed = Utils.overwrittenFunction(self.getIsFoldAllowed, Pipe.getIsFoldAllowed);
46 self.getIsOverloadingAllowed = Utils.overwrittenFunction(self.getIsOverloadingAllowed, Pipe.getIsOverloadingAllowed);
47 self.findValidTrailer = Utils.overwrittenFunction(self.findValidTrailer, Pipe.findValidTrailer);
48
49 self.getIsPipeStateChangeAllowed = Pipe.getIsPipeStateChangeAllowed;
50 self.setPipeState = SpecializationUtil.callSpecializationsFunction("setPipeState");
51 self.findTrailerRaycastCallback = Pipe.findTrailerRaycastCallback;
52 self.updatePipe = Pipe.updatePipe;
53
54 self.setActiveControlGroup = Utils.overwrittenFunction(self.setActiveControlGroup, Pipe.setActiveControlGroup);
55 self.getNextValidControlGroupIndex = Utils.overwrittenFunction(self.getNextValidControlGroupIndex, Pipe.getNextValidControlGroupIndex);
56 self.getIsControlGroupChangeAllowed = Utils.overwrittenFunction(self.getIsControlGroupChangeAllowed, Pipe.getIsControlGroupChangeAllowed);
57
58 self.pipeFoldMinTime = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.pipe#foldMinTime"), 0);
59 self.pipeFoldMaxTime = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.pipe#foldMaxTime"), 1);
60
61 self.pipeFoldMinState = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.pipe#foldMinState"), 0);
62 self.pipeFoldMaxState = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.pipe#foldMaxState"), 7);
63 if self.pipeFoldMaxState > 7 then
64 print("Warning: pipe#foldMaxState must have a value between 0 and 7");
65 end
66
67 self.pipeNodes = {};
68 self.pipeNumStates = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.pipe#numStates"), 0);
69 self.pipeCurrentState = 1;
70 self.pipeTargetState = 1;
71 self.pipeStateIsUnloading = {};
72 self.pipeStateIsAutoAiming = {};
73 local unloadingPipeStates = Utils.getVectorNFromString(getXMLString(self.xmlFile, "vehicle.pipe#unloadingStates"));
74 if unloadingPipeStates ~= nil then
75 for i=1, table.getn(unloadingPipeStates) do
76 if unloadingPipeStates[i] ~= nil then
77 self.pipeStateIsUnloading[unloadingPipeStates[i] ] = true;
78 end
79 end
80 end
81 local autoAimPipeStates = Utils.getVectorNFromString(getXMLString(self.xmlFile, "vehicle.pipe#autoAimStates"));
82 if autoAimPipeStates ~= nil then
83 for i=1, table.getn(autoAimPipeStates) do
84 if autoAimPipeStates[i] ~= nil then
85 self.pipeStateIsAutoAiming[autoAimPipeStates[i] ] = true;
86 end
87 end
88 end
89 local i = 0;
90 while true do
91 local key = string.format("vehicle.pipe.node(%d)", i);
92 if not hasXMLProperty(self.xmlFile, key) then
93 break;
94 end
95 local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#index"));
96 if node ~= nil then
97 local entry = {};
98 entry.node = node;
99 entry.autoAimXRotation = Utils.getNoNil(getXMLBool(self.xmlFile, key.."#autoAimXRotation"), false);
100 entry.autoAimYRotation = Utils.getNoNil(getXMLBool(self.xmlFile, key.."#autoAimYRotation"), false);
101 entry.autoAimInvertZ = Utils.getNoNil(getXMLBool(self.xmlFile, key.."#autoAimInvertZ"), false);
102 entry.states = {};
103 for state=1,self.pipeNumStates do
104 local stateKey = key..string.format(".state%d", state);
105 entry.states[state] = {};
106 local x,y,z = Utils.getVectorFromString(getXMLString(self.xmlFile, stateKey.."#translation"));
107 if x == nil or y == nil or z == nil then
108 x,y,z = getTranslation(node);
109 else
110 if state == 1 then
111 setTranslation(node, x,y,z);
112 end
113 end
114 entry.states[state].translation = {x,y,z};
115 local x,y,z = Utils.getVectorFromString(getXMLString(self.xmlFile, stateKey.."#rotation"));
116 if x == nil or y == nil or z == nil then
117 x,y,z = getRotation(node);
118 else
119 x,y,z = math.rad(x),math.rad(y),math.rad(z);
120 if state == 1 then
121 setRotation(node, x,y,z);
122 end
123 end
124 entry.states[state].rotation = {x,y,z};
125 end
126 local x,y,z = Utils.getVectorFromString(getXMLString(self.xmlFile, key.."#translationSpeeds"));
127 if x ~= nil and y ~= nil and z ~= nil then
128 x,y,z = x*0.001,y*0.001,z*0.001;
129 if x ~= 0 or y ~= 0 or z ~= 0 then
130 entry.translationSpeeds = {x,y,z};
131 end
132 end
133 local x,y,z = Utils.getVectorFromString(getXMLString(self.xmlFile, key.."#rotationSpeeds"));
134 if x ~= nil and y ~= nil and z ~= nil then
135 x,y,z = math.rad(x)*0.001,math.rad(y)*0.001,math.rad(z)*0.001;
136 if x ~= 0 or y ~= 0 or z ~= 0 then
137 entry.rotationSpeeds = {x,y,z};
138 end
139 end
140
141 local x,y,z = getTranslation(node);
142 entry.curTranslation = {x,y,z};
143 local x,y,z = getRotation(node);
144 entry.curRotation = {x,y,z};
145 table.insert(self.pipeNodes, entry);
146 end
147 i = i + 1;
148 end
149
150 self.pipeAnimation = getXMLString(self.xmlFile, "vehicle.pipe#animName");
151 self.pipeAnimSpeedScale = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.pipe#animSpeedScale"), 1);
152 if self.pipeAnimation ~= nil then
153 local targetTime = 0;
154 if self.pipeAnimSpeedScale < 0 then
155 targetTime = 1;
156 end
157 self:playAnimation(self.pipeAnimation, -self.pipeAnimSpeedScale, nil, true);
158 self:setAnimationTime(self.pipeAnimation, targetTime);
159 end
160
161 self.pipeRaycastNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.pipe#raycastNodeIndex"));
162 self.pipeRaycastDistance = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.pipe#raycastDistance"), 7);
163 self.pipeUnloadingDistance = 0;
164 self.pipeParticleSystemExtraDistance = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.pipe#effectExtraDistance"), 1);
165 self.pipeParticleSystemExtraDistanceOnTrailer = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.pipe#effectExtraDistanceOnTrailer"), 0);
166
167 self.pipeDischargeInfoIndex = getXMLInt(self.xmlFile, "vehicle.pipe#dischargeInfoIndex");
168
169 self.trailerFound = 0;
170 self.pipeFoundTrailer = false;
171 self.sentPipeFoundTrailer = false;
172 self.trailerFoundDistance = 0;
173
174 self.hasPipe = self.pipeRaycastNode ~= nil;
175
176
177 if self.isClient then
178 self.pipeParticleSystems = {};
179 local i=0;
180 while true do
181 local key = string.format("vehicle.pipeParticleSystems.emitterShape(%d)", i);
182 if not hasXMLProperty(self.xmlFile, key) then
183 break
184 end
185
186 local emitterShape = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node"));
187 local particleType = getXMLString(self.xmlFile, key.."#particleType")
188 if emitterShape ~= nil then
189 for _,fillUnit in pairs(self.fillUnits) do
190 for fillType,_ in pairs(fillUnit.fillTypes) do
191 local particleSystem = MaterialUtil.getParticleSystem(fillType, particleType)
192 if particleSystem ~= nil then
193 if self.pipeParticleSystems[fillType] == nil then
194 self.pipeParticleSystems[fillType] = {}
195 end
196
197 local currentPS = ParticleUtil.copyParticleSystem(self.xmlFile, key, particleSystem, emitterShape)
198 local ps = currentPS
199 local normalSpeed,tangentSpeed = ParticleUtil.getParticleSystemAverageSpeed(ps);
200 ps.speed = math.sqrt(normalSpeed*normalSpeed + tangentSpeed*tangentSpeed);
201
202 table.insert(self.pipeParticleSystems[fillType], currentPS)
203 end
204 end
205 end
206 end
207
208 i=i+1;
209 end
210
211 self.pipeEffects = EffectManager:loadEffect(self.xmlFile, "vehicle.pipeEffect", self.components, self);
212 self.pipeTurnedOnRotationNodes = Utils.loadRotationNodes(self.xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "pipe", self.components);
213 self.pipeScrollers = Utils.loadScrollers(self.components, self.xmlFile, "vehicle.pipeScrollers.pipeScroller", {}, true);
214
215 local i = 0
216 while true do
217 local key = string.format("vehicle.pipe.offset(%d)", i);
218 if not hasXMLProperty(self.xmlFile, key) then
219 break
220 end
221
222 local movingToolNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#movingToolNode"))
223 if movingToolNode ~= nil and self.nodesToMovingTools[movingToolNode] ~= nil then
224 if self.pipeOffsets == nil then
225 self.pipeOffsets = {}
226 end
227
228 local offset = {}
229 offset.movingTool = self.nodesToMovingTools[movingToolNode]
230 offset.effects = {}
231 local j = 0
232 while true do
233 local effectKey = string.format(key..".effect(%d)", j);
234 if not hasXMLProperty(self.xmlFile, effectKey) then
235 break
236 end
237
238 local effectIndex = Utils.getNoNil(getXMLInt(self.xmlFile, effectKey.."#index"), 0)
239 if self.pipeEffects[effectIndex] ~= nil and self.pipeEffects[effectIndex].setOffset ~= nil and self.pipeEffects[effectIndex].setDelays ~= nil then
240 local effect = {}
241 effect.effect = self.pipeEffects[effectIndex]
242 effect.minValue = Utils.getNoNil(getXMLFloat(self.xmlFile, effectKey.."#minValue"), 0)
243 effect.maxValue = Utils.getNoNil(getXMLFloat(self.xmlFile, effectKey.."#maxValue"), 1)
244 local minDelay = getXMLFloat(self.xmlFile, effectKey.."#minDelay")
245 local maxDelay = getXMLFloat(self.xmlFile, effectKey.."#maxDelay")
246 effect.minDelay = Utils.getNoNil(minDelay, effect.effect.startDelay)*1000
247 effect.maxDelay = Utils.getNoNil(maxDelay, effect.effect.startDelay)*1000
248 effect.adjustDelay = minDelay ~= nil and maxDelay ~= nil
249 effect.inverted = Utils.getNoNil(getXMLBool(self.xmlFile, effectKey.."#inverted"), false)
250 table.insert(offset.effects, effect)
251 end
252 j = j + 1
253 end
254
255 table.insert(self.pipeOffsets, offset)
256 end
257 i = i + 1
258 end
259 end
260
261 local effectIndex = getXMLInt(self.xmlFile, "vehicle.pipe#delayEffectIndex")
262 if effectIndex ~= nil and self.pipeEffects[effectIndex] ~= nil then
263 self.delayEffect = self.pipeEffects[effectIndex]
264 end
265
266
267 self.pipeBaseDelay = self.overloading.delay.time;
268 self.pipeUnloadingGroundStartTime = -1;
269 self.pipeUnloadingStartTime = -1;
270 self.pipeScrollerEndTime = -1;
271
272 self.pipeParticleDeactivateTime = -1;
273 self.pipeUnloadEffectStopTime = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.pipe#unloadingEffectStopTime"), 0.25) * 1000;
274
275 self.allowDischargeToGround = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.pipe#allowDischargeToGround"), true);
276 self.dischargeToGround = false;
277 self.remainingFillLevelToGround = 0;
278 self.limitDischargeToPipeHeight = false;
279
280 self.isSelectable = true;
281
282 self.pipeTurnOnAllowedStates = { Utils.getVectorFromString(getXMLString(self.xmlFile, "vehicle.pipe#turnOnAllowedStates")) };
283 self.pipeTurnOnStateWarning = string.format(g_i18n:getText(Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.pipe#unfoldWarning"), "warning_firstSetPipeState")), self.typeDesc);
284
285 self.pipeDisableManualMovement = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.pipe#disableManualMovement"), true);
286 self.pipeControlGroupName = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.pipe#controlGroup"), "pipe");
287
288 self.pipeAutomaticOverload = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.pipe#automaticOverload"), true);
289 if self.pipeAutomaticOverload then
290 self.overloading.canToggleOverloading = false;
291 end
292
293 self.pipeDirtyFlag = self:getNextDirtyFlag();
294 self.pipeTargetDirtyFlag = self:getNextDirtyFlag();
295
296 self:addConflictCheckedInput(InputBinding.TOGGLE_PIPE);
297
298 self.groundUnloadingPosition = {0,0,0};
299 self.groundUnloadingPipeEffect = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.pipe#groundUnloadingPipeEffect"), 1);
300end

postLoad

Description
Called after loading
Definition
postLoad(table savegame)
Arguments
tablesavegamesavegame
Code
305function Pipe:postLoad(savegame)
306 if savegame ~= nil and not savegame.resetVehicles then
307 local pipeState = Utils.getNoNil(getXMLInt(savegame.xmlFile, savegame.key.."#pipeState"), 1);
308 self:setPipeState(pipeState, true);
309 self:updatePipe(99999);
310 end
311end;

delete

Description
Called on deleting
Definition
delete()
Code
315function Pipe:delete()
316 if self.isClient then
317 EffectManager:deleteEffects(self.pipeEffects);
318 for _,particleSystems in pairs(self.pipeParticleSystems) do
319 ParticleUtil.deleteParticleSystems(particleSystems)
320 end
321 end
322end

getSaveAttributesAndNodes

Description
Returns attributes and nodes to save
Definition
getSaveAttributesAndNodes(table nodeIdent)
Arguments
tablenodeIdentnode ident
Return Values
stringattributesattributes
stringnodesnodes
Code
329function Pipe:getSaveAttributesAndNodes(nodeIdent)
330 local attributes = 'pipeState="'..self.pipeCurrentState..'"';
331 return attributes, nil;
332end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
338function Pipe:readStream(streamId, connection)
339 if self.hasPipe then
340 local pipeState = streamReadUIntN(streamId, 2);
341 self:setPipeState(pipeState, true);
342
343 local pipeUnloadingDistance = streamReadUIntN(streamId, 8);
344 self.pipeUnloadingDistance = pipeUnloadingDistance*self.pipeRaycastDistance / 255;
345
346 if streamReadBool(streamId) then
347 self.targetTrailer = readNetworkNodeObject(streamId);
348 end
349 end
350end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
356function Pipe:writeStream(streamId, connection)
357 if self.hasPipe then
358 streamWriteUIntN(streamId, self.pipeTargetState, 2);
359 streamWriteUIntN(streamId, Utils.clamp(math.floor(self.pipeUnloadingDistance/self.pipeRaycastDistance*255), 1, 255), 8);
360
361 if streamWriteBool(streamId, self.targetTrailer ~= nil) then
362 writeNetworkNodeObject(streamId, self.targetTrailer);
363 end
364 end
365end

readUpdateStream

Description
Called on on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
372function Pipe:readUpdateStream(streamId, timestamp, connection)
373 if connection:getIsServer() then
374 if streamReadBool(streamId) then
375 self.pipeUnloadingDistance = streamReadUIntN(streamId, 8)*self.pipeRaycastDistance / 255;
376
377 self.pipeFoundTrailer = streamReadBool(streamId);
378 end
379
380 if streamReadBool(streamId) then
381 self.targetTrailer = readNetworkNodeObject(streamId);
382 self.shovelTargetFound = streamReadBool(streamId) and 1 or nil;
383 end
384 end
385end

writeUpdateStream

Description
Called on on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
392function Pipe:writeUpdateStream(streamId, connection, dirtyMask)
393 if not connection:getIsServer() then
394 if streamWriteBool(streamId, bitAND(dirtyMask, self.pipeDirtyFlag) ~= 0) then
395 streamWriteUIntN(streamId, Utils.clamp(math.floor(self.pipeUnloadingDistance/self.pipeRaycastDistance*255), 1, 255), 8);
396
397 streamWriteBool(streamId, self.pipeFoundTrailer)
398 end
399
400 if streamWriteBool(streamId, bitAND(dirtyMask, self.pipeTargetDirtyFlag) ~= 0) then
401 writeNetworkNodeObject(streamId, self.targetTrailer);
402 streamWriteBool(streamId, self.shovelTargetFound ~= nil)
403
404 self.targetTrailerSend = self.targetTrailer;
405 self.shovelTargetFoundSend = self.shovelTargetFound;
406 end
407 end
408end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
419function Pipe:update(dt)
420 if self:getIsActive() then
421 if self.isClient and self:getIsActiveForInput(true) and not self:hasInputConflictWithSelection() then
422 if InputBinding.hasEvent(InputBinding.TOGGLE_PIPE) then
423 if self.hasPipe then
424 local nextState = self.pipeTargetState+1;
425 if nextState > self.pipeNumStates then
426 nextState = 1;
427 end
428 if self:getIsPipeStateChangeAllowed(nextState) then
429 self:setPipeState(nextState);
430 elseif nextState ~= 1 and self:getIsPipeStateChangeAllowed(1) then
431 -- also try to close the pipe if other states are not allowed
432 self:setPipeState(1);
433 end
434 end
435 end
436 if InputBinding.hasEvent(InputBinding.TOGGLE_TIPSTATE_GROUND) then
437 if self.trailerFound == 0 and self.shovelTargetFound == nil and self:getCanTipToGround() then
438 self:setDischargeToGround(not self.dischargeToGround);
439 end
440 end
441 end
442 end
443
444 if self.hasPipe then
445 if self.pipeStateIsAutoAiming[self.pipeTargetState] then
446 self:updatePipe(dt, self.targetTrailer);
447 else
448 self:updatePipe(dt, nil);
449 end
450 end
451
452 if self.isServer then
453 if self.targetTrailerSend ~= self.targetTrailer or self.shovelTargetFoundSend ~= self.shovelTargetFound then
454 self:raiseDirtyFlags(self.pipeTargetDirtyFlag);
455 end
456 end
457
458 if self.isClient then
459 Utils.updateRotationNodes(self, self.pipeTurnedOnRotationNodes, dt, self:getAllowDelayEffects() or self:getAllowDelayedEffects());
460 if self.pipeScrollers ~= nil then
461 if self:getAllowDelayEffects() or self:getAllowDelayedEffects() then
462 Utils.updateScrollers(self.pipeScrollers, dt, true, true, self:getUnitLastValidFillType(self.overloading.fillUnitIndex));
463 else
464 Utils.updateScrollers(self.pipeScrollers, dt, false, true, self:getUnitLastValidFillType(self.overloading.fillUnitIndex));
465 end
466 end;
467 end
468end

updateTick

Description
Called on update tick
Definition
updateTick(float dt)
Arguments
floatdttime since last call in ms
Code
473function Pipe:updateTick(dt)
474 -- if a trailer was found, check (and adjust) control group of cylindered
475 if self.isServer and self.hasPipe then --and self:getIsActive() then
476
477 if self.pipeStateIsUnloading[self.pipeCurrentState] and self.trailerFound ~= 0 and self.pipeDisableManualMovement then
478
479 if self.numControlGroups ~= nil and self.numControlGroups > 1 then
480
481 local activeGroup = self.controlGroups[self.activeControlGroupIndex];
482 if activeGroup.groupName == self.pipeControlGroupName then
483
484 local nextIndex = self:getNextValidControlGroupIndex();
485 if nextIndex ~= self.activeControlGroupIndex then
486 self:setActiveControlGroup(nextIndex);
487 end
488 end
489 end
490 end
491
492 self.pipeFoundTrailer = false;
493
494 if not self:getOverloadingActive() then
495 self:stopOverloadingDelay();
496 end;
497 end
498
499 if self.isServer then
500 if (self:getUnitFillLevel(self.overloading.fillUnitIndex) > 0 or self:getUnitCapacity(self.overloading.fillUnitIndex) == 0) and self.pipeStateIsUnloading[self.pipeCurrentState] then
501
502 if self.pipeEffects ~= nil then
503 if self.pipeEffects[self.groundUnloadingPipeEffect] ~= nil then
504 local controlPointY = self.pipeEffects[self.groundUnloadingPipeEffect].controlPointY;
505 local distance = self.pipeEffects[self.groundUnloadingPipeEffect].distance;
506
507 if controlPointY ~= nil and distance ~= nil and controlPointY ~= 0 then
508 local mCos = math.cos(controlPointY);
509 local mSin = math.sin(controlPointY);
510
511 local y = Utils.dotProduct(0, 0, distance, 0.0, mCos, -mSin);
512 local z = Utils.dotProduct(0, 0, distance, 0.0, mSin, mCos);
513
514 if self.pipeStateIsUnloading[self.pipeTargetState] then
515 local x, y, z = localToWorld(self.pipeEffects[self.groundUnloadingPipeEffect].node, 0, y, z);
516 self.groundUnloadingPosition = {x, y, z};
517 end;
518 end;
519 end;
520 end;
521
522 -- do raycast
523 self.trailerFound = 0;
524 self.shovelTargetFound = nil;
525 self.trailerFoundDistance = 0;
526 if self.pipeRaycastNode ~= nil then
527 local doRaycast = self.pipeStateIsUnloading[self.pipeTargetState];
528
529 if doRaycast then
530 local x,y,z = getWorldTranslation(self.pipeRaycastNode);
531 local dx,dy,dz = localDirectionToWorld(self.pipeRaycastNode, 0,-1,0);
532 raycastAll(x, y, z, dx,dy,dz, "findTrailerRaycastCallback", self.pipeRaycastDistance, self);
533 end
534
535 if self.trailerFoundDistance == 0 then
536 self.trailerFound = 0;
537 end;
538
539 if self.targetTrailer ~= nil then
540 if self.targetTrailer.coverAnimation ~= nil then
541 if not self.targetTrailer.isCoverOpen then
542 self.trailerFound = 0;
543 end;
544 end;
545 end;
546 end
547
548 if self.trailerFound ~= 0 or self.shovelTargetFound ~= nil then
549 if self.dischargeToGround then
550 self:setDischargeToGround(false);
551 end
552 else
553 if self.dischargeToGround then
554 if not self:getCanTipToGround() or (self.overloading.stopOverloadIfEmpty and (self:getUnitLastValidFillType(self.overloading.fillUnitIndex) == FillUtil.FILLTYPE_UNKNOWN or self:getUnitFillLevel(self.overloading.fillUnitIndex) == 0)) then
555 self:setDischargeToGround(false);
556 end
557 end
558 end
559
560 if self.dischargeToGround then
561 if self:getUnitFillLevel(self.overloading.fillUnitIndex) > 0 and not self:getOverloadingDelayIsActive() then
562 self:startOverloadingDelay();
563 end;
564
565 local node = self.pipeRaycastNode;
566 if self.pipeDischargeInfoIndex ~= nil then
567 node = self.fillVolumeDischargeInfos[self.pipeDischargeInfoIndex].nodes[1].node;
568 end;
569
570 local speed = 10;
571 local x,y,z = Utils.getIntersectionOfLinearMovementAndTerrain(node, speed);
572 local x0,y0,z0 = getWorldTranslation(node);
573 self.pipeUnloadingDistance = Utils.vector3Length(x0-x, y0-y, z0-z);
574
575 if self.groundUnloadingPosition[1] ~= 0 then
576 x,y,z = unpack(self.groundUnloadingPosition);
577 end;
578
579 if self:getAllowDelayedUnloading() then
580 local fillType = self:getUnitLastValidFillType(self.overloading.fillUnitIndex);
581 local fillLevel = self:getUnitFillLevel(self.overloading.fillUnitIndex);
582
583 local deltaFill = fillLevel;
584 if self.lastLostFillLevel ~= nil then
585 deltaFill = math.max(fillLevel, self.lastLostFillLevel);
586 end
587
588 if self:getUnitCapacity(self.overloading.fillUnitIndex) > 0 then
589 deltaFill = math.min(deltaFill, self.overloading.capacity*dt/1000.0);
590 end
591
592 self.remainingFillLevelToGround = math.min(self.remainingFillLevelToGround + deltaFill, math.max(self.overloading.capacity*dt/1000.0, TipUtil.getMinValidLiterValue(fillType)));
593
594 if self.remainingFillLevelToGround > 0 then
595 local infos = self.fillVolumeDischargeInfos[self.overloading.dischargeInfoIndex];
596 local dx,dy,dz;
597 if infos ~= nil then
598 dx,dy,dz = localDirectionToWorld(infos.nodes[1].node, infos.nodes[1].width,0,0);
599 else
600 dx,dy,dz = localDirectionToWorld(self.components[1].node, 0,0,0.25);
601 end
602
603 local sx, sy, sz = x+dx, y+dy, z+dz;
604 local ex, ey, ez = x-dx, y-dy, z-dz;
605
606 if self.limitDischargeToPipeHeight then
607 if infos ~= nil then
608 local _,y,_ = localToWorld(infos.nodes[1].node, infos.nodes[1].width,0,0);
609 sy = y;
610 local _,y,_ = localToWorld(infos.nodes[1].node, -infos.nodes[1].width,0,0);
611 ey = y;
612 else
613 local _,y,_ = getWorldTranslation(self.pipeRaycastNode);
614 sy = y;
615 ey = y;
616 end
617 else
618 end
619
620 local dropped, lineOffset = TipUtil.tipToGroundAroundLine(self, self.remainingFillLevelToGround, fillType, sx,sy,sz, ex,ey,ez, 0.1, nil, self.tipToGroundLineOffset, self.limitDischargeToPipeHeight, self.tipOcclusionAreas);
621
622 self.tipToGroundLineOffset = lineOffset;
623
624 self.remainingFillLevelToGround = self.remainingFillLevelToGround - dropped;
625 self:setUnitFillLevel(self.overloading.fillUnitIndex, fillLevel - dropped, fillType, false, self.fillVolumeUnloadInfos[self.overloading.unloadInfoIndex]);
626 self.overloading.didOverload = dropped > 0;
627 end
628 end;
629
630 if not self:getCanTipToGround() or (self.overloading.stopOverloadIfEmpty and (self:getUnitLastValidFillType(self.overloading.fillUnitIndex) == FillUtil.FILLTYPE_UNKNOWN or self:getUnitFillLevel(self.overloading.fillUnitIndex) == 0)) then
631 self:setDischargeToGround(false);
632 end
633 elseif not self.dischargeToGround and self.overloading.isActive then
634 self.pipeUnloadingDistance = self.trailerFoundDistance;
635 end
636 else
637 self.trailerFound = 0;
638 self.shovelTargetFound = nil;
639
640 -- stop discharge to ground if pipe gets folden
641 if self.dischargeToGround and (not self.pipeStateIsUnloading[self.pipeCurrentState] or (self.overloading.stopOverloadIfEmpty and (self:getUnitLastValidFillType(self.overloading.fillUnitIndex) == FillUtil.FILLTYPE_UNKNOWN or self:getUnitFillLevel(self.overloading.fillUnitIndex) == 0))) then
642 self:setDischargeToGround(false);
643 end
644 end
645 end;
646
647 if self.isServer then
648 if self.pipeUnloadingDistance ~= self.sentPipeUnloadingDistance or self.sentPipeFoundTrailer ~= self.pipeFoundTrailer then
649 self:raiseDirtyFlags(self.pipeDirtyFlag);
650
651 self.sentPipeUnloadingDistance = self.pipeUnloadingDistance;
652 self.sentPipeFoundTrailer = self.pipeFoundTrailer;
653 end
654 end
655
656 if self.isClient then
657 self.overloading.delay.time = self.pipeBaseDelay
658 if self.delayEffect ~= nil then
659 self.overloading.delay.time = self.delayEffect.startDelay + (1-self.delayEffect.offset)*self.delayEffect.fadeInTime
660 end
661 if self:getIsActiveForInput(self) then
662 if self.pipeOffsets ~= nil then
663 for _, offset in pairs(self.pipeOffsets) do
664 local movingTool = offset.movingTool
665 local state = Cylindered.getMovingToolState(self, movingTool);
666
667 for _, effect in pairs(offset.effects) do
668 local effectState = state
669 if effect.inverted then
670 effectState = 1 - effectState
671 end
672 effect.effect:setOffset(Utils.lerp(effect.minValue, effect.maxValue, effectState))
673 if effect.adjustDelay then
674 local delay = Utils.lerp(effect.minDelay, effect.maxDelay, effectState)
675 effect.effect:setDelays(delay, delay)
676 end
677 end
678 end
679 end
680 end
681
682 if self:getAllowDelayEffects() and (self.pipeFoundTrailer or self.dischargeToGround or self.shovelTargetFound ~= nil) then
683 self.pipeParticleDeactivateTime = g_currentMission.time + self.pipeUnloadEffectStopTime;
684
685 local currentPipeParticleSystems = self.pipeParticleSystems[self:getUnitLastValidFillType(self.overloading.fillUnitIndex)];
686 if currentPipeParticleSystems ~= self.currentPipeParticleSystems then
687 if self.currentPipeParticleSystems ~= nil then
688 for _, ps in pairs(self.currentPipeParticleSystems) do
689 ParticleUtil.setEmittingState(ps, false)
690 end
691 end
692 self.currentPipeParticleSystems = currentPipeParticleSystems
693 if self.currentPipeParticleSystems ~= nil then
694 for _, ps in pairs(self.currentPipeParticleSystems) do
695 ParticleUtil.setEmittingState(ps, true)
696 end
697 end
698 end
699
700 if self.currentPipeParticleSystems ~= nil then
701 for _, currentPS in pairs(self.currentPipeParticleSystems) do
702 local ps = currentPS
703 if not ps.forceFullLifespan then
704 local factor = 1+((8-self.pipeUnloadingDistance-self.pipeParticleSystemExtraDistance)/15);
705 local lifespan = ps.originalLifespan * (self.pipeUnloadingDistance+self.pipeParticleSystemExtraDistance) * factor;
706 ParticleUtil.setParticleLifespan(ps, lifespan)
707 end
708 end
709 end
710
711 if self.pipeEffects ~= nil then
712 EffectManager:setFillType(self.pipeEffects, self:getUnitLastValidFillType(self.overloading.fillUnitIndex))
713 EffectManager:startEffects(self.pipeEffects)
714 end
715 end
716
717 if self.pipeEffects ~= nil then
718 for _, effect in pairs(self.pipeEffects) do
719 if effect.setUnloadingDistance ~= nil then
720 effect:setUnloadingDistance(self.pipeUnloadingDistance+self.pipeParticleSystemExtraDistance, g_currentMission.terrainRootNode)
721 end
722 end;
723 end
724
725 if self.pipeParticleDeactivateTime >= 0 and self.pipeParticleDeactivateTime <= g_currentMission.time then
726 self.pipeParticleDeactivateTime = -1;
727 if self.currentPipeParticleSystems ~= nil then
728 for _, ps in pairs(self.currentPipeParticleSystems) do
729 ParticleUtil.setEmittingState(ps, false)
730 end
731 self.currentPipeParticleSystems = nil;
732 end
733
734 if self.pipeEffects ~= nil then
735 EffectManager:stopEffects(self.pipeEffects);
736 end
737 end
738 end
739end

draw

Description
Called on draw
Definition
draw()
Code
743function Pipe:draw()
744 if self.isClient and self:getIsActiveForInput(true) and not self:hasInputConflictWithSelection() then
745 if self.hasPipe then
746 if self.pipeNumStates == 2 then
747 if self.pipeTargetState == 2 then
748 if self:getIsPipeStateChangeAllowed(1) then
749 g_currentMission:addHelpButtonText(g_i18n:getText("action_pipeIn"), InputBinding.TOGGLE_PIPE, nil, GS_PRIO_HIGH);
750 end
751 else
752 if self:getIsPipeStateChangeAllowed(2) then
753 g_currentMission:addHelpButtonText(g_i18n:getText("action_pipeOut"), InputBinding.TOGGLE_PIPE, nil, GS_PRIO_HIGH);
754 end
755 end
756 end
757 end
758
759 if not self.pipeFoundTrailer and self:getCanTipToGround() and self.shovelTargetFound == nil then
760 if self.dischargeToGround then
761 g_currentMission:addHelpButtonText(g_i18n:getText("action_stopTipToGround"), InputBinding.TOGGLE_TIPSTATE_GROUND, nil, GS_PRIO_HIGH);
762 elseif not self.overloading.didOverload then
763 g_currentMission:addHelpButtonText(g_i18n:getText("action_startTipToGround"), InputBinding.TOGGLE_TIPSTATE_GROUND, nil, GS_PRIO_HIGH);
764 end
765 end
766 end
767end

getIsTurnedOnAllowed

Description
Returns if turn on is allowed
Definition
getIsTurnedOnAllowed(boolean isTurnedOn)
Arguments
booleanisTurnedOnis turned on
Return Values
booleanallowallow turn on
Code
773function Pipe:getIsTurnedOnAllowed(superFunc, isTurnedOn)
774 if isTurnedOn and self.hasPipe then
775 if table.getn(self.pipeTurnOnAllowedStates) > 0 then
776 local isAllowed = false;
777 for _,pipeState in pairs(self.pipeTurnOnAllowedStates) do
778 if pipeState == self.pipeCurrentState then
779 isAllowed = true;
780 break;
781 end
782 end
783 if not isAllowed then
784 return false;
785 end
786 end
787 end
788
789 if superFunc ~= nil then
790 return superFunc(self, isTurnedOn);
791 end
792
793 return true;
794end

getAutomaticOverloadingState

Description
Returns if it is in automatic overloading state
Definition
getAutomaticOverloadingState()
Return Values
booleanisInAutomaticOverloadingStateis in automatic overloading state
Code
799function Pipe:getAutomaticOverloadingState(superFunc)
800 local automaticOverloadingState = false
801 if superFunc ~= nil then
802 if superFunc(self) then
803 automaticOverloadingState = true
804 end
805 end
806
807 if self.trailerFound ~= 0 or self.shovelTargetFound ~= nil then
808 if self.pipeAutomaticOverload then
809 if self:getIsOverloadingAllowed() and (not (self:getUnitLastValidFillType(self.overloading.fillUnitIndex) == FillUtil.FILLTYPE_UNKNOWN or self:getUnitFillLevel(self.overloading.fillUnitIndex) == 0) or not self.overloading.stopOverloadIfEmpty) then
810 automaticOverloadingState = true
811 end
812 end
813 end
814
815 return automaticOverloadingState
816end

getTurnedOnNotAllowedWarning

Description
Returns turn on not allowed warning text
Definition
getTurnedOnNotAllowedWarning()
Return Values
stringwarningTextturn on not allowed warning text
Code
821function Pipe:getTurnedOnNotAllowedWarning(superFunc)
822 if self.hasPipe then
823 if table.getn(self.pipeTurnOnAllowedStates) > 0 then
824 local isAllowed = false;
825 for _,pipeState in pairs(self.pipeTurnOnAllowedStates) do
826 if pipeState == self.pipeCurrentState then
827 isAllowed = true;
828 break;
829 end
830 end
831 if not isAllowed then
832 return self.pipeTurnOnStateWarning;
833 end
834 end
835 end
836
837 if superFunc ~= nil then
838 return superFunc(self);
839 end
840 return nil;
841end;

getAllowPipeEffects

Description
Returns if pipe effects are allowed
Definition
getAllowPipeEffects()
Return Values
booleanallowedpipe effects are allowed
Code
846function Pipe:getAllowPipeEffects(superFunc)
847 if not (self:getAllowDelayEffects() or self:getAllowDelayedUnloading()) then
848 return false;
849 end;
850
851 if superFunc ~= nil then
852 return superFunc(self);
853 end
854 return true;
855end;

getCanTipToGround

Description
Returns if can be tipped to ground
Definition
getCanTipToGround()
Return Values
booleancanTipToGroundcan tip to ground
Code
860function Pipe:getCanTipToGround()
861 if self.pipeStateIsUnloading[self.pipeCurrentState] and TipUtil.isValid() then
862 local fillType = self:getUnitLastValidFillType(self.overloading.fillUnitIndex);
863 if fillType ~= FillUtil.FILLTYPE_UNKNOWN then
864 return TipUtil.getCanTipToGround(fillType);
865 else
866 return true;
867 end
868 else
869 return false;
870 end
871end

setDischargeToGround

Description
Toggle discharge to ground state
Definition
setDischargeToGround(boolean state)
Arguments
booleanstatenew state
Code
876function Pipe:setDischargeToGround(state, noEventSend)
877 SetDischargeToGroundEvent.sendEvent(self, state, noEventSend)
878 self.dischargeToGround = state;
879 if not state then
880 self.pipeUnloadingGroundStartTime = -1;
881 end;
882end

getOverloadingActive

Description
Returns if overloading is active
Definition
getOverloadingActive()
Return Values
booleanisActiveoverloading is active
Code
887function Pipe:getOverloadingActive(superFunc)
888 if self.dischargeToGround then
889 return true;
890 end;
891
892 if superFunc ~= nil then
893 return superFunc(self);
894 end
895 return false;
896end

doOverload

Description
Do overload
Definition
doOverload(table tagetTrailer, integer fillType, float deltaFill)
Arguments
tabletagetTrailertrailer to fill
integerfillTypefill type to overload
floatdeltaFilldelta to fill
Return Values
booleandidOverloaddid overload something
Code
904function Pipe:doOverload(superFunc, targetTrailer, fillType, deltaFill)
905 if self.pipeRaycastNode == nil then
906 return superFunc(self, targetTrailer, fillType, deltaFill);
907 end
908
909 local trailer = g_currentMission.nodeToVehicle[self.trailerFound];
910 if targetTrailer == trailer and targetTrailer:getAllowFillFromAir() and deltaFill > 0 then
911 targetTrailer:resetFillLevelIfNeeded(fillType);
912
913 local trailerFillLevel = targetTrailer:getFillLevel(fillType);
914 local trailerCapacity = targetTrailer:getCapacity(fillType);
915
916 deltaFill = math.min(deltaFill, trailerCapacity - trailerFillLevel);
917 if deltaFill > 0 then
918 targetTrailer:setFillLevel(trailerFillLevel+deltaFill, fillType, false, self.fillVolumeDischargeInfos[self.overloading.dischargeInfoIndex]);
919 local newFillLevel = targetTrailer:getFillLevel(fillType);
920 local diff = newFillLevel - trailerFillLevel;
921 self:setUnitFillLevel(self.overloading.fillUnitIndex, self:getUnitFillLevel(self.overloading.fillUnitIndex)-diff, fillType, false, self.fillVolumeUnloadInfos[self.overloading.unloadInfoIndex]);
922 return true;
923 else
924 return false;
925 end
926 else
927 return false;
928 end
929end

getIsFoldAllowed

Description
Returns if fold is allowed
Definition
getIsFoldAllowed(boolean onAiTurnOn)
Arguments
booleanonAiTurnOncalled on ai turn on
Return Values
booleanallowsFoldallows folding
Code
935function Pipe:getIsFoldAllowed(superFunc, onAiTurnOn)
936 if self.hasPipe and false then
937 if self.overloading.didOverload or (self.dischargeToGround and self:getUnitFillLevel(self.overloading.fillUnitIndex) > 0) then
938 return false;
939 end
940
941 if self.pipeCurrentState > self.pipeFoldMaxState or self.pipeCurrentState < self.pipeFoldMinState then
942 return false;
943 end
944 end
945
946 if superFunc ~= nil then
947 return superFunc(self, onAiTurnOn);
948 end
949 return true;
950end

getIsOverloadingAllowed

Description
Returns if overloading is allowed
Definition
getIsOverloadingAllowed()
Return Values
booleanisAllowedoverloading is allowed
Code
955function Pipe:getIsOverloadingAllowed(superFunc)
956 if self.hasPipe then
957 if self.foldAnimTime ~= nil and (self.foldAnimTime > self.pipeFoldMaxTime or self.foldAnimTime < self.pipeFoldMinTime) then
958 return false;
959 end
960
961 if not self.pipeStateIsUnloading[self.pipeCurrentState] then
962 return false;
963 end
964
965 -- stop overloading if no trailer available or trailer is full or no shovel target trigger found
966 if not self.dischargeToGround and self.trailerFound == 0 and self.shovelTargetFound == nil then
967 return false
968 end
969 end
970
971 if superFunc ~= nil then
972 return superFunc(self);
973 end
974end

findValidTrailer

Description
Find valid trailer in given table
Definition
findValidTrailer(table trailers)
Arguments
tabletrailerstrailers to search
Return Values
tabletrailervalid trailer
Code
980function Pipe:findValidTrailer(superFunc, trailers)
981 if self.pipeRaycastNode == nil then
982 return superFunc(self, trailers);
983 end
984
985 local nearestTrailer;
986 local fillType = self:getUnitLastValidFillType(self.overloading.fillUnitIndex);
987
988 -- check if a trailer is attached
989 for _,implement in pairs(self.attachedImplements) do
990 if implement.object ~= nil then
991 if implement.object.exactFillRootNode ~= nil then
992 for trailer,value in pairs(trailers) do
993 if value > 0 then
994 if entityExists(trailer.components[1].node) then
995 if trailer == implement.object and trailer:allowFillType(fillType) and trailer:getFillLevel(fillType) < trailer:getCapacity(fillType) then
996 nearestTrailer = trailer;
997 break;
998 end
999 end
1000 end
1001 end
1002 end
1003 end
1004 if nearestTrailer ~= nil then
1005 break;
1006 end
1007 end
1008
1009 -- find closest trailer to raycast node in triggers
1010 if nearestTrailer == nil then
1011 local nearestDistance = math.huge;
1012 local x0,y0,z0 = getWorldTranslation(self.pipeRaycastNode);
1013
1014 for trailer,value in pairs(trailers) do
1015 if not entityExists(trailer.components[1].node) then
1016 value = 0;
1017 end
1018 if value > 0 then
1019 if trailer:allowFillType(fillType) and trailer.exactFillRootNode ~= nil then
1020 if trailer:getFillLevel(fillType) < trailer:getCapacity(fillType) then
1021 local x1,y1,z1 = getWorldTranslation(trailer.exactFillRootNode);
1022 local dist = Utils.vector3LengthSq(x0-x1, y0-y1, z0-z1);
1023 if dist < nearestDistance then
1024 nearestTrailer = trailer;
1025 nearestDistance = dist;
1026 end
1027 end
1028 end
1029 end
1030 end
1031 end
1032
1033 return nearestTrailer;
1034end

findTrailerRaycastCallback

Description
Raycast callback
Definition
findTrailerRaycastCallback(integer transformId, float x, float y, float z, float distance)
Arguments
integertransformIdid raycasted object
floatxx raycast position
floatyy raycast position
floatzz raycast position
floatdistancedistance to raycast position
Return Values
booleancontinuecontinue raycasting
Code
1044function Pipe:findTrailerRaycastCallback(transformId, x, y, z, distance)
1045 local vehicle = g_currentMission.nodeToVehicle[transformId];
1046 if vehicle ~= nil and vehicle ~= self then
1047 if self.trailerFound ~= 0 and self.trailerFoundDistance ~= 0 then
1048 return false;
1049 end;
1050
1051 self.pipeFoundTrailer = true;
1052
1053 if vehicle.exactFillRootNode == transformId then
1054 local fillType = self:getUnitLastValidFillType(self.overloading.fillUnitIndex);
1055 if vehicle:allowFillType(fillType) and vehicle.exactFillRootNode ~= nil then
1056 if vehicle:getFillLevel(fillType) < vehicle:getCapacity(fillType) then
1057 self.trailerFound = transformId;
1058 end
1059 end
1060 else
1061 self.trailerFoundDistance = distance+self.pipeParticleSystemExtraDistanceOnTrailer;
1062 end
1063 else
1064 local object = g_currentMission:getNodeObject(transformId);
1065 if object ~= nil and object.parent ~= nil and object.parent.getAllowFillTypeFromTool ~= nil then
1066 if object.parent:getAllowFillTypeFromTool(self:getUnitLastValidFillType(self.overloading.fillUnitIndex), TipTrigger.TOOL_TYPE_PIPE) then
1067 self.shovelTargetFound = object;
1068 self.trailerFoundDistance = distance+self.pipeParticleSystemExtraDistanceOnTrailer;
1069 end;
1070 end;
1071 end
1072
1073 return true;
1074end

getIsPipeStateChangeAllowed

Description
Returns if pipe state can be changed
Definition
getIsPipeStateChangeAllowed(integer state)
Arguments
integerstatenew pipe state
Return Values
booleanallowedpipe state change is allowed
Code
1080function Pipe:getIsPipeStateChangeAllowed(pipeState)
1081 if pipeState ~= 1 and self.foldAnimTime ~= nil and (self.foldAnimTime > self.pipeFoldMaxTime or self.foldAnimTime < self.pipeFoldMinTime) then
1082 return false;
1083 end
1084 return true;
1085end

setPipeState

Description
Set pipe state
Definition
setPipeState(integer pipeState, boolean noEventSend)
Arguments
integerpipeStatenew pipe state
booleannoEventSendno event send
Code
1091function Pipe:setPipeState(pipeState, noEventSend)
1092 pipeState = math.min(pipeState, self.pipeNumStates);
1093 if self.pipeTargetState ~= pipeState then
1094 if noEventSend == nil or noEventSend == false then
1095 if g_server ~= nil then
1096 g_server:broadcastEvent(SetPipeStateEvent:new(self, pipeState));
1097 else
1098 g_client:getServerConnection():sendEvent(SetPipeStateEvent:new(self, pipeState), nil, nil, self);
1099 end
1100 end
1101 self.pipeTargetState = pipeState;
1102 self.pipeCurrentState = 0;
1103 if self.pipeAnimation ~= nil then
1104 if pipeState == 1 then
1105 self:playAnimation(self.pipeAnimation, -self.pipeAnimSpeedScale, self:getAnimationTime(self.pipeAnimation), true);
1106 else
1107 self:playAnimation(self.pipeAnimation, self.pipeAnimSpeedScale, self:getAnimationTime(self.pipeAnimation), true);
1108 end
1109 end
1110 end
1111end

updatePipe

Description
Update pipe aiming
Definition
updatePipe(float dt, table trailer)
Arguments
floatdttime since last call in ms
tabletrailercurrent target trailer
Code
1117function Pipe:updatePipe(dt, trailer)
1118 if (self.pipeCurrentState ~= self.pipeTargetState or (trailer ~= nil and trailer.getAllowFillFromAir ~= nil and trailer:getAllowFillFromAir())) and self.pipeTargetState <= self.pipeNumStates then
1119 local doAutoAiming = trailer ~= nil and entityExists(trailer.components[1].node) and self.pipeStateIsAutoAiming[self.pipeCurrentState];
1120 local autoAimX, autoAimY, autoAimZ;
1121 if doAutoAiming then
1122 autoAimX, autoAimY, autoAimZ = getWorldTranslation(trailer.fillAutoAimTarget.node);
1123 end
1124
1125 local moved = false;
1126 for i=1, table.getn(self.pipeNodes) do
1127 local nodeMoved = false;
1128 local pipeNode = self.pipeNodes[i];
1129
1130 local state = pipeNode.states[self.pipeTargetState];
1131 if pipeNode.translationSpeeds ~= nil then
1132 for i=1, 3 do
1133 if math.abs(pipeNode.curTranslation[i] - state.translation[i]) > 0.000001 then
1134 nodeMoved = true;
1135 if pipeNode.curTranslation[i] < state.translation[i] then
1136 pipeNode.curTranslation[i] = math.min(pipeNode.curTranslation[i] + dt*pipeNode.translationSpeeds[i], state.translation[i]);
1137 else
1138 pipeNode.curTranslation[i] = math.max(pipeNode.curTranslation[i] - dt*pipeNode.translationSpeeds[i], state.translation[i]);
1139 end
1140 end
1141 end
1142 setTranslation(pipeNode.node, pipeNode.curTranslation[1],pipeNode.curTranslation[2],pipeNode.curTranslation[3])
1143 end
1144 if pipeNode.rotationSpeeds ~= nil then
1145 for i=1, 3 do
1146 local targetRotation = state.rotation[i];
1147 if doAutoAiming then
1148 if pipeNode.autoAimXRotation and i == 1 then
1149 local x,y,z = getWorldTranslation(pipeNode.node);
1150 local _,y,z = worldDirectionToLocal(getParent(pipeNode.node), autoAimX-x, autoAimY-y, autoAimZ-z);
1151 targetRotation = -math.atan2(y,z);
1152 if pipeNode.autoAimInvertZ then
1153 targetRotation = targetRotation+math.pi;
1154 end
1155 targetRotation = Utils.normalizeRotationForShortestPath(targetRotation, pipeNode.curRotation[i]);
1156 elseif pipeNode.autoAimYRotation and i == 2 then
1157 local x,y,z = getWorldTranslation(pipeNode.node);
1158 local x,_,z = worldDirectionToLocal(getParent(pipeNode.node), autoAimX-x, autoAimY-y, autoAimZ-z);
1159 targetRotation = math.atan2(x,z);
1160 if pipeNode.autoAimInvertZ then
1161 targetRotation = targetRotation+math.pi;
1162 end
1163 targetRotation = Utils.normalizeRotationForShortestPath(targetRotation, pipeNode.curRotation[i]);
1164 end
1165 end
1166 if math.abs(pipeNode.curRotation[i] - targetRotation) > 0.000001 then
1167 nodeMoved = true;
1168 if pipeNode.curRotation[i] < targetRotation then
1169 pipeNode.curRotation[i] = math.min(pipeNode.curRotation[i] + dt*pipeNode.rotationSpeeds[i], targetRotation);
1170 else
1171 pipeNode.curRotation[i] = math.max(pipeNode.curRotation[i] - dt*pipeNode.rotationSpeeds[i], targetRotation);
1172 end
1173 if pipeNode.curRotation[i] > 2*math.pi then
1174 pipeNode.curRotation[i] = pipeNode.curRotation[i] - 2*math.pi;
1175 elseif pipeNode.curRotation[i] < -2*math.pi then
1176 pipeNode.curRotation[i] = pipeNode.curRotation[i] + 2*math.pi;
1177 end
1178 end
1179 end
1180 setRotation(pipeNode.node, pipeNode.curRotation[1],pipeNode.curRotation[2],pipeNode.curRotation[3])
1181 end
1182 moved = moved or nodeMoved;
1183
1184 if nodeMoved and self.setMovingToolDirty ~= nil then
1185 self:setMovingToolDirty(pipeNode.node);
1186 end
1187 end
1188 if table.getn(self.pipeNodes) == 0 and self.pipeAnimation ~= nil then
1189 if self:getIsAnimationPlaying(self.pipeAnimation) then
1190 moved = true;
1191 end
1192 end
1193 if not moved then
1194 self.pipeCurrentState = self.pipeTargetState;
1195 end
1196 end
1197end

getNextValidControlGroupIndex

Description
Returns next valid control group index
Definition
getNextValidControlGroupIndex()
Return Values
integerindexnext valid index
Code
1206function Pipe:getNextValidControlGroupIndex(superFunc)
1207 local nextIndex = superFunc(self);
1208
1209 if self.pipeDisableManualMovement and self.trailerFound ~= 0 then
1210 local index = self.activeControlGroupIndex;
1211 for i=1,self.numControlGroups-1 do
1212 index = index + 1;
1213 if index > self.numControlGroups then
1214 index = 1;
1215 end
1216
1217 if self.controlGroups[index].groupName ~= self.pipeControlGroupName then
1218 return index;
1219 end
1220 end
1221 return self.activeControlGroupIndex;
1222 end
1223
1224 return nextIndex;
1225end