Sprache Deutsch Language English

Script Dokumentation LS 2015 - Overloading (Patch 1.3)

Script Dokumentation Übersicht

scripts/vehicles/specializations/Overloading.lua

Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1--
2-- Overloading
3--
4--
5-- @author Manuel Leithner
6-- @date 26/09/13
7--
8-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
9
10Overloading = {};
11source("dataS/scripts/vehicles/specializations/OverloadingSetPipeStateEvent.lua");
12source("dataS/scripts/vehicles/specializations/OverloadingToggleUnloadEvent.lua");
13
14function Overloading.prerequisitesPresent(specializations)
15 return SpecializationUtil.hasSpecialization(Fillable, specializations);
16end;
17
18function Overloading:load(xmlFile)
19 self.getIsFoldAllowed = Utils.overwrittenFunction(self.getIsFoldAllowed, Overloading.getIsFoldAllowed);
20 self.setPipeState = SpecializationUtil.callSpecializationsFunction("setPipeState");
21 self.getOverloadingTrailerInRangePipeState = Overloading.getOverloadingTrailerInRangePipeState;
22 self.getIsPipeStateChangeAllowed = Overloading.getIsPipeStateChangeAllowed;
23 self.getIsPipeUnloadingAllowed = Overloading.getIsPipeUnloadingAllowed;
24 self.findAutoAimTrailerToUnload = Overloading.findAutoAimTrailerToUnload;
25 self.findTrailerToUnload = Overloading.findTrailerToUnload;
26 self.findTrailerRaycastCallback = Overloading.findTrailerRaycastCallback;
27 self.onOverloadingTrailerTrigger = Overloading.onOverloadingTrailerTrigger;
28 self.setOverloadingActive = Overloading.setOverloadingActive;
29 self.activatePipeUnloadingEffects = Overloading.activatePipeUnloadingEffects;
30
31 if hasXMLProperty(xmlFile, string.format("vehicle.combineTrailerTriggers.combineTrailerTrigger(%d)", 0)) then
32 print("Warning: combineTrailerTriggers are no longer supported. Use vehicle.trailerTriggers.trailerTrigger instead");
33 end
34
35 self.trailerTriggers = {};
36 local i = 0;
37 while true do
38 local key = string.format("vehicle.trailerTriggers.trailerTrigger(%d)", i);
39 if not hasXMLProperty(xmlFile, key) then
40 key = string.format("vehicle.combineTrailerTriggers.combineTrailerTrigger(%d)", i);
41 if not hasXMLProperty(xmlFile, key) then
42 break;
43 end;
44 end;
45 local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
46 if node ~= nil then
47 local pipeState = Utils.getNoNil(getXMLInt(xmlFile, key.."#pipeState"), 2);
48 self.trailerTriggers[node] = {node=node, pipeState=pipeState};
49 end;
50 i = i + 1;
51 end;
52 for _, trigger in pairs(self.trailerTriggers) do
53 addTrigger(trigger.node, "onOverloadingTrailerTrigger", self);
54 end;
55
56 self.overloadingTrailersInRange = {};
57 self.overloadingTriggersTrailers = {};
58
59 self.foldMaxPipeState = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.pipe#foldMaxState"), 999);
60 self.foldMinPipeState = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.pipe#foldMinState"), 0);
61 self.pipeNodes = {};
62 self.numPipeStates = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.pipe#numStates"), 0);
63 self.currentPipeState = 1;
64 self.targetPipeState = 1;
65 self.pipeStateIsUnloading = {};
66 self.pipeStateIsAutoAiming = {};
67 local unloadingPipeStates = Utils.getVectorNFromString(getXMLString(xmlFile, "vehicle.pipe#unloadingStates"));
68 if unloadingPipeStates ~= nil then
69 for i=1, table.getn(unloadingPipeStates) do
70 if unloadingPipeStates[i] ~= nil then
71 self.pipeStateIsUnloading[unloadingPipeStates[i] ] = true;
72 end;
73 end;
74 end;
75 local autoAimPipeStates = Utils.getVectorNFromString(getXMLString(xmlFile, "vehicle.pipe#autoAimStates"));
76 if autoAimPipeStates ~= nil then
77 for i=1, table.getn(autoAimPipeStates) do
78 if autoAimPipeStates[i] ~= nil then
79 self.pipeStateIsAutoAiming[autoAimPipeStates[i] ] = true;
80 end;
81 end;
82 end;
83 local i = 0;
84 while true do
85 local key = string.format("vehicle.pipe.node(%d)", i);
86 if not hasXMLProperty(xmlFile, key) then
87 break;
88 end;
89 local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
90 if node ~= nil then
91 local entry = {};
92 entry.node = node;
93 entry.autoAimXRotation = Utils.getNoNil(getXMLBool(xmlFile, key.."#autoAimXRotation"), false);
94 entry.autoAimYRotation = Utils.getNoNil(getXMLBool(xmlFile, key.."#autoAimYRotation"), false);
95 entry.autoAimInvertZ = Utils.getNoNil(getXMLBool(xmlFile, key.."#autoAimInvertZ"), false);
96 entry.states = {};
97 for state=1,self.numPipeStates do
98 local stateKey = key..string.format(".state%d", state);
99 entry.states[state] = {};
100 local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, stateKey.."#translation"));
101 if x == nil or y == nil or z == nil then
102 x,y,z = getTranslation(node);
103 else
104 if state == 1 then
105 setTranslation(node, x,y,z);
106 end;
107 end;
108 entry.states[state].translation = {x,y,z};
109 local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, stateKey.."#rotation"));
110 if x == nil or y == nil or z == nil then
111 x,y,z = getRotation(node);
112 else
113 x,y,z = math.rad(x),math.rad(y),math.rad(z);
114 if state == 1 then
115 setRotation(node, x,y,z);
116 end;
117 end;
118 entry.states[state].rotation = {x,y,z};
119 end;
120 local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, key.."#translationSpeeds"));
121 if x ~= nil and y ~= nil and z ~= nil then
122 x,y,z = x*0.001,y*0.001,z*0.001;
123 if x ~= 0 or y ~= 0 or z ~= 0 then
124 entry.translationSpeeds = {x,y,z};
125 end;
126 end;
127 local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, key.."#rotationSpeeds"));
128 if x ~= nil and y ~= nil and z ~= nil then
129 x,y,z = math.rad(x)*0.001,math.rad(y)*0.001,math.rad(z)*0.001;
130 if x ~= 0 or y ~= 0 or z ~= 0 then
131 entry.rotationSpeeds = {x,y,z};
132 end;
133 end;
134
135 local x,y,z = getTranslation(node);
136 entry.curTranslation = {x,y,z};
137 local x,y,z = getRotation(node);
138 entry.curRotation = {x,y,z};
139 table.insert(self.pipeNodes, entry);
140 end;
141 i = i + 1;
142 end;
143
144 self.pipeAnimation = getXMLString(xmlFile, "vehicle.pipe#animName");
145 self.pipeAnimSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipe#animSpeedScale"), 1);
146 self.pipeRaycastNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pipe#raycastNodeIndex"));
147 self.pipeRaycastDistance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipe#raycastDistance"), 7);
148 self.pipeUnloadingDistance = 0;
149 self.pipeParticleSystemExtraDistance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipeParticleSystems#extraDistance"), 1.5);
150 self.hasPipe = table.getn(self.pipeNodes) ~= 0 or self.pipeAnimation ~= nil;
151 self.doAutoAiming = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.pipe#doAutoAiming"), self.pipeRaycastNode == nil);
152
153 if self.isClient then
154 local defaultPipePSNode = self.components[1].node;
155 if table.getn(self.pipeNodes) > 0 then
156 defaultPipePSNode = self.pipeNodes[1].node;
157 end
158
159 self.pipeParticleSystems = {};
160 -- load the pipe particle system for each fruit type
161 local i = 0;
162 while true do
163 local key = string.format("vehicle.pipeParticleSystems.pipeParticleSystem(%d)", i);
164 local t = getXMLString(xmlFile, key .. "#type");
165 if t == nil then
166 break;
167 end;
168
169 local desc = FruitUtil.fruitTypes[t];
170 if desc ~= nil then
171 local currentPS = Utils.getNoNil(self.pipeParticleSystems[desc.index], {});
172
173 local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, nil, self.baseDirectory, defaultPipePSNode);
174
175 for _, v in ipairs(currentPS) do
176 local normalSpeed,tangentSpeed = getParticleSystemAverageSpeed(v.geometry);
177 v.speed = math.sqrt(normalSpeed*normalSpeed + tangentSpeed*tangentSpeed);
178 v.originalLifespan = getParticleSystemLifespan(v.geometry);
179 end
180 self.pipeParticleSystems[desc.index] = currentPS;
181 if self.defaultPipeParticleSystem == nil then
182 self.defaultPipeParticleSystem = currentPS;
183 end;
184
185 if self.pipeRaycastNode == nil then
186 self.pipeRaycastNode = particleNode;
187 end;
188 end;
189 i = i + 1;
190 end;
191
192 self.pipeEffect = EffectManager:loadEffect(xmlFile, "vehicle.pipeEffect", self.components, self);
193
194 self.overloadingTurnedOnRotationNodes = Utils.loadRotationNodes(xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "overloading", self.components);
195
196 self.pipeScrollers = Utils.loadScrollers(self.components, xmlFile, "vehicle.pipeScrollers.pipeScroller", {}, true);
197
198 self.samplePipe = Utils.loadSample(xmlFile, {}, "vehicle.pipeSound", nil, self.baseDirectory);
199
200 local linkNode = Utils.indexToObject(self.components, Utils.getNoNil(getXMLString(xmlFile, "vehicle.fillSound#linkNode"), "0>"));
201 self.sampleFill = Utils.loadSample(xmlFile, {}, "vehicle.fillSound", nil, self.baseDirectory, linkNode);
202 Utils.stop3DSample(self.sampleFill);
203 self.sampleFillEnabled = false;
204 self.sampleFillStopTime = -1;
205 self.lastFillLevel = -1;
206 self.sampleFillUseOnDischarge = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.fillSound#useOnDischarge"), false);
207 self.sampleFillUseOnCharge = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.fillSound#useOnCharge"), false);
208 end;
209
210 if self.pipeRaycastNode == nil then
211 self.pipeRaycastNode = self.components[1].node;
212 end;
213
214 self.pipeUnloadEffectStopTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipe#unloadingEffectStopTime"), 0) * 1000;
215 self.currentUnloadEffectStopTime = 0;
216
217 self.overloadingCapacity = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.overloadingCapacity"), 10);
218 self.pipeIsUnloading = false;
219 self.pipeParticleDeactivateTime = -1;
220
221 self.doAutoUnloadIfHired = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.pipe#doAutoUnloadIfHired"), false);
222 self.allowFoldWhileUnloading = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.threshingFold#allowFoldWhileUnloading"), false);
223 self.pipeFoldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipe#foldMinLimit"), 0);
224 self.pipeFoldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipe#foldMaxLimit"), 1);
225
226 self.overloadingDirtyFlag = self:getNextDirtyFlag();
227
228 self.isOverloadingActive = false;
229 self.isSelectable = true;
230 self:addConflictCheckedInput(InputBinding.EMPTY_GRAIN);
231end;
232
233function Overloading:delete()
234 for _, trailerTrigger in pairs(self.trailerTriggers) do
235 removeTrigger(trailerTrigger.node);
236 end;
237
238 if self.isClient then
239 EffectManager:deleteEffect(self.pipeEffect);
240
241 for _,v in pairs(self.pipeParticleSystems) do
242 Utils.deleteParticleSystem(v);
243 end;
244 Utils.deleteSample(self.samplePipe);
245 end;
246
247 if self.isClient then
248 Utils.deleteSample(self.sampleFill);
249 end;
250end;
251
252function Overloading:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
253 if not resetVehicles then
254 local pipeState = Utils.getNoNil(getXMLInt(xmlFile, key.."#pipeState"), 1);
255 self:setPipeState(pipeState, true);
256 end
257 return BaseMission.VEHICLE_LOAD_OK;
258end
259
260function Overloading:getSaveAttributesAndNodes(nodeIdent)
261 local attributes = 'pipeState="'..self.currentPipeState..'"';
262 return attributes, nil;
263end
264
265function Overloading:readStream(streamId, connection)
266 if self.hasPipe then
267 local pipeState = streamReadUIntN(streamId, 3);
268 local pipeUnloadingDistance = streamReadUIntN(streamId, 5);
269 if pipeUnloadingDistance == 0 then
270 self.pipeIsUnloading = false;
271 else
272 self.pipeIsUnloading = true;
273 self.pipeUnloadingDistance = pipeUnloadingDistance*self.pipeRaycastDistance / 31;
274 end
275 self:setPipeState(pipeState, true);
276 else
277 self:setOverloadingActive(streamReadBool(streamId), true);
278 end;
279end;
280
281function Overloading:writeStream(streamId, connection)
282 if self.hasPipe then
283 streamWriteUIntN(streamId, self.targetPipeState, 3);
284 if self.pipeIsUnloading then
285 streamWriteUIntN(streamId, Utils.clamp(math.floor(self.pipeUnloadingDistance/self.pipeRaycastDistance*31), 1, 31), 5);
286 else
287 streamWriteUIntN(streamId, 0, 5);
288 end;
289 else
290 streamWriteBool(streamId, self.isOverloadingActive);
291 end;
292end;
293
294function Overloading:readUpdateStream(streamId, timestamp, connection)
295 if connection:getIsServer() then
296 --if self.hasPipe then
297 if streamReadBool(streamId) then
298 local pipeUnloadingDistance = streamReadUIntN(streamId, 5);
299 if pipeUnloadingDistance == 0 then
300 self.pipeIsUnloading = false;
301 else
302 self.pipeIsUnloading = true;
303 self.pipeUnloadingDistance = pipeUnloadingDistance*self.pipeRaycastDistance / 31;
304 end
305 end;
306 --end;
307 end;
308end;
309
310function Overloading:writeUpdateStream(streamId, connection, dirtyMask)
311 if not connection:getIsServer() then
312 --if self.hasPipe then
313 if streamWriteBool(streamId, bitAND(dirtyMask, self.overloadingDirtyFlag) ~= 0) then
314 if self.pipeIsUnloading then
315 streamWriteUIntN(streamId, Utils.clamp(math.floor(self.pipeUnloadingDistance/self.pipeRaycastDistance*31), 1, 31), 5);
316 else
317 streamWriteUIntN(streamId, 0, 5);
318 end
319 end;
320 --end;
321 end;
322end;
323
324function Overloading:mouseEvent(posX, posY, isDown, isUp, button)
325end;
326
327function Overloading:keyEvent(unicode, sym, modifier, isDown)
328end;
329
330function Overloading:update(dt)
331 if self:getIsActive() then
332 if self.isClient and self:getIsActiveForInput(true) and not self:hasInputConflictWithSelection() then
333 if InputBinding.hasEvent(InputBinding.EMPTY_GRAIN) then
334 if self.hasPipe then
335 local nextState = self.targetPipeState+1;
336 if nextState > self.numPipeStates then
337 nextState = 1;
338 end;
339 if self:getIsPipeStateChangeAllowed(nextState) then
340 self:setPipeState(nextState);
341 elseif nextState ~= 1 and self:getIsPipeStateChangeAllowed(1) then
342 -- also try to close the pipe if other states are not allowed
343 self:setPipeState(1);
344 end
345 else
346 self:setOverloadingActive(not self.isOverloadingActive);
347 end;
348 end;
349 end;
350
351 if not self.hasPipe and self.doAutoUnloadIfHired then
352 local rootAttacher = self:getRootAttacherVehicle();
353 if self:findTrailerToUnload(self.currentFillType) ~= nil and self.fillLevel > 0 and rootAttacher.isHired then
354 self:setOverloadingActive(true);
355 end;
356 end;
357
358 if self.hasPipe then
359 local doAutoAiming = self.pipeStateIsAutoAiming[self.currentPipeState];
360 local targetTrailer = nil;
361 if doAutoAiming then
362 targetTrailer = self:findAutoAimTrailerToUnload(self.lastValidFillType);
363
364 if targetTrailer == nil then
365 doAutoAiming = false;
366 end;
367 end;
368 if (self.currentPipeState ~= self.targetPipeState or doAutoAiming) and self.targetPipeState <= self.numPipeStates then
369 local autoAimX, autoAimY, autoAimZ;
370 if doAutoAiming then
371 autoAimX, autoAimY, autoAimZ = getWorldTranslation(targetTrailer.fillAutoAimTargetNode);
372 end;
373
374 local moved = false;
375 for i=1, table.getn(self.pipeNodes) do
376 local nodeMoved = false;
377 local pipeNode = self.pipeNodes[i];
378
379 local state = pipeNode.states[self.targetPipeState];
380 if pipeNode.translationSpeeds ~= nil then
381 for i=1, 3 do
382 if math.abs(pipeNode.curTranslation[i] - state.translation[i]) > 0.000001 then
383 nodeMoved = true;
384 if pipeNode.curTranslation[i] < state.translation[i] then
385 pipeNode.curTranslation[i] = math.min(pipeNode.curTranslation[i] + dt*pipeNode.translationSpeeds[i], state.translation[i]);
386 else
387 pipeNode.curTranslation[i] = math.max(pipeNode.curTranslation[i] - dt*pipeNode.translationSpeeds[i], state.translation[i]);
388 end;
389 end;
390 end;
391 setTranslation(pipeNode.node, pipeNode.curTranslation[1],pipeNode.curTranslation[2],pipeNode.curTranslation[3])
392 end;
393 if pipeNode.rotationSpeeds ~= nil then
394 for i=1, 3 do
395 local targetRotation = state.rotation[i];
396 if doAutoAiming then
397 if pipeNode.autoAimXRotation and i == 1 then
398 local x,y,z = getWorldTranslation(pipeNode.node);
399 local x,y,z = worldDirectionToLocal(getParent(pipeNode.node), autoAimX-x, autoAimY-y, autoAimZ-z);
400 targetRotation = -math.atan2(y,z);
401 if pipeNode.autoAimInvertZ then
402 targetRotation = targetRotation+math.pi;
403 end;
404 targetRotation = Utils.normalizeRotationForShortestPath(targetRotation, pipeNode.curRotation[i]);
405 elseif pipeNode.autoAimYRotation and i == 2 then
406 local x,y,z = getWorldTranslation(pipeNode.node);
407 local x,y,z = worldDirectionToLocal(getParent(pipeNode.node), autoAimX-x, autoAimY-y, autoAimZ-z);
408 targetRotation = math.atan2(x,z);
409 if pipeNode.autoAimInvertZ then
410 targetRotation = targetRotation+math.pi;
411 end;
412 targetRotation = Utils.normalizeRotationForShortestPath(targetRotation, pipeNode.curRotation[i]);
413 end;
414 end;
415 if math.abs(pipeNode.curRotation[i] - targetRotation) > 0.000001 then
416 nodeMoved = true;
417 if pipeNode.curRotation[i] < targetRotation then
418 pipeNode.curRotation[i] = math.min(pipeNode.curRotation[i] + dt*pipeNode.rotationSpeeds[i], targetRotation);
419 else
420 pipeNode.curRotation[i] = math.max(pipeNode.curRotation[i] - dt*pipeNode.rotationSpeeds[i], targetRotation);
421 end;
422 end;
423 end;
424 setRotation(pipeNode.node, pipeNode.curRotation[1],pipeNode.curRotation[2],pipeNode.curRotation[3])
425 end;
426 moved = moved or nodeMoved;
427
428 if nodeMoved and self.setMovingToolDirty ~= nil then
429 self:setMovingToolDirty(pipeNode.node);
430 end;
431 end;
432 if table.getn(self.pipeNodes) == 0 and self.pipeAnimation ~= nil then
433 if self:getIsAnimationPlaying(self.pipeAnimation) then
434 moved = true;
435 end;
436 end;
437 if not moved then
438 self.currentPipeState = self.targetPipeState;
439 end;
440 end;
441
442 if self.isClient then
443 if self:getIsActiveForSound() and self.currentPipeState ~= self.targetPipeState then
444 Utils.playSample(self.samplePipe, 0, 0, nil);
445 else
446 Utils.stopSample(self.samplePipe);
447 end;
448 end;
449 end;
450 end;
451
452 if self.isClient then
453
454 Utils.updateRotationNodes(self, self.overloadingTurnedOnRotationNodes, dt, self.pipeIsUnloading);
455
456 if self.pipeIsUnloading then
457 local currentPipeScrollers = self.pipeScrollers[self.lastValidFillType];
458 if currentPipeScrollers ~= self.currentPipeScrollers and self.currentPipeScrollers ~= nil then
459 self.lastPipeScrollers = self.currentPipeScrollers;
460 end
461 self.currentPipeScrollers = currentPipeScrollers;
462 if self.currentPipeScrollers ~= nil then
463 Utils.updateScrollers(self.currentPipeScrollers, dt, true, true);
464 end
465 else
466 if self.currentPipeScrollers ~= nil then
467 if self.currentPipeScrollers.isRunning == true then
468 Utils.updateScrollers(self.currentPipeScrollers, dt, false, true);
469 else
470 Utils.updateScrollers(self.currentPipeScrollers, dt, false, false);
471 self.currentPipeScrollers = nil;
472 end;
473 end
474 end;
475 if self.lastPipeScrollers ~= nil then
476 Utils.updateScrollers(self.lastPipeScrollers, dt, false, false);
477 self.lastPipeScrollers = nil;
478 end;
479 end;
480end;
481
482function Overloading:updateTick(dt)
483 if self.isServer then
484 if self.pipeIsUnloading then
485 self.currentUnloadEffectStopTime = self.currentUnloadEffectStopTime - dt;
486 if self.currentUnloadEffectStopTime <= 0 then
487 self.pipeIsUnloading = false;
488 end;
489 end;
490 --self.pipeIsUnloading = false;
491 if (self.hasPipe and (self.pipeStateIsUnloading[self.currentPipeState] or self.numPipeStates == 0) and self:getIsPipeUnloadingAllowed()) or (not self.hasPipe and self.isOverloadingActive) then
492 if self.fillLevel > 0 then
493 -- test if we should drain the grain tank
494 local trailer, trailerDistance;
495 local doAutoAiming = false;
496 if self.hasPipe then
497 doAutoAiming = self.pipeStateIsAutoAiming[self.currentPipeState];
498 else
499 doAutoAiming = self.doAutoAiming;
500 end;
501
502 if doAutoAiming then
503 trailer, _ = self:findAutoAimTrailerToUnload(self.currentFillType);
504 trailerDistance = 1;
505 else
506 trailer, trailerDistance = self:findTrailerToUnload(self.currentFillType);
507 end;
508
509 if trailer == nil then
510 if self:getCapacity() == 0 then
511 self:activatePipeUnloadingEffects(); -- show particle if capacity is 0
512 end;
513 --self.pipeIsUnloading = self:getCapacity() == 0;
514 if not self.hasPipe then
515 self:setOverloadingActive(false);
516 end;
517 else
518 trailer:resetFillLevelIfNeeded(self.currentFillType);
519
520 local deltaLevel = self.fillLevel;
521 if self:getCapacity() > 0 then
522 deltaLevel = math.min(self.fillLevel, self.overloadingCapacity*dt/1000.0);
523 end;
524 deltaLevel = math.min(deltaLevel, trailer:getCapacity() - trailer.fillLevel);
525 if deltaLevel > 0 then
526 self:activatePipeUnloadingEffects();
527 --self.pipeIsUnloading = true;
528 self.pipeUnloadingDistance = trailerDistance;
529
530 local x,y,z = getWorldTranslation(self.fillVolumeDischargeInfo.node);
531 local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeDischargeInfo.node, self.fillVolumeDischargeInfo.width,0,0);
532 local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeDischargeInfo.node, 0,0,self.fillVolumeDischargeInfo.length);
533 local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z};
534 trailer:setFillLevel(trailer.fillLevel+deltaLevel, self.currentFillType, false, fillSourceStruct);
535
536
537 local x,y,z = getWorldTranslation(self.fillVolumeUnloadInfo.node);
538 local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeUnloadInfo.node, self.fillVolumeUnloadInfo.width,0,0);
539 local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeUnloadInfo.node, 0,0,self.fillVolumeUnloadInfo.length);
540 local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z};
541 self:setFillLevel(self.fillLevel-deltaLevel, self.currentFillType, false, fillSourceStruct);
542 end
543 end;
544 else
545 self:setOverloadingActive(false);
546 end;
547 end;
548
549 if self.pipeIsUnloading ~= self.sentPipeIsUnloading or self.pipeUnloadingDistance ~= self.sentPipeUnloadingDistance then
550 self:raiseDirtyFlags(self.overloadingDirtyFlag);
551 self.sentPipeIsUnloading = self.pipeIsUnloading;
552 self.sentPipeUnloadingDistance = self.pipeUnloadingDistance;
553 end;
554 end;
555
556 if self.isClient then
557 if self.pipeIsUnloading then
558 self.pipeParticleDeactivateTime = g_currentMission.time + 200;
559 local currentPipeParticleSystem = self.pipeParticleSystems[self.lastValidFillType];
560 if currentPipeParticleSystem == nil then
561 currentPipeParticleSystem = self.defaultPipeParticleSystem;
562 end;
563 if currentPipeParticleSystem ~= self.currentPipeParticleSystem then
564 Utils.setEmittingState(self.currentPipeParticleSystem, false);
565
566 self.currentPipeParticleSystem = currentPipeParticleSystem;
567 Utils.setEmittingState(self.currentPipeParticleSystem, true);
568 end
569
570 if self.currentPipeParticleSystem ~= nil then
571 for _, v in ipairs(self.currentPipeParticleSystem) do
572 if not v.forceFullLifespan then
573 local lifespan = math.min(v.originalLifespan, (self.pipeUnloadingDistance+self.pipeParticleSystemExtraDistance)/v.speed);
574 setParticleSystemLifespan(v.geometry, lifespan, true);
575 end;
576 end
577 end
578
579 if self.pipeEffect ~= nil then
580 self.pipeEffect:setFillType(self.lastValidFillType);
581 EffectManager:startEffect(self.pipeEffect);
582 end;
583 else
584 if self.pipeParticleDeactivateTime >= 0 and self.pipeParticleDeactivateTime <= g_currentMission.time then
585 self.pipeParticleDeactivateTime = -1;
586 if self.currentPipeParticleSystem ~= nil then
587 Utils.setEmittingState(self.currentPipeParticleSystem, false);
588 self.currentPipeParticleSystem = nil;
589 end
590
591 if self.pipeEffect ~= nil then
592 EffectManager:stopEffect(self.pipeEffect);
593 end;
594 end
595 end;
596 end;
597
598 if self.isClient then
599 if self.lastFillLevel ~= self.fillLevel and self.fillLevel > 0 then
600 if ((self.lastFillLevel < self.fillLevel and self.sampleFillUseOnCharge) or (self.sampleFillUseOnDischarge and self.isOverloadingActive)) and self.lastFillLevel ~= -1 then
601 self.sampleFillStopTime = g_currentMission.time + 150;
602 end;
603 self.lastFillLevel = self.fillLevel;
604 end;
605
606 if self.sampleFillStopTime > g_currentMission.time then
607 if self:getIsActiveForSound(true) then
608 Utils.playSample(self.sampleFill, 0, 0, nil);
609 Utils.stop3DSample(self.sampleFill);
610 else
611 Utils.stopSample(self.sampleFill);
612 Utils.play3DSample(self.sampleFill);
613 end;
614 else
615 Utils.stopSample(self.sampleFill);
616 Utils.stop3DSample(self.sampleFill);
617 end;
618 end;
619end;
620
621function Overloading:draw()
622 if self.isClient and self:getIsActiveForInput(true) and not self:hasInputConflictWithSelection() then
623 if self.hasPipe then
624 if self.numPipeStates == 2 then
625 if self.targetPipeState == 2 then
626 if self:getIsPipeStateChangeAllowed(1) then
627 g_currentMission:addHelpButtonText(g_i18n:getText("Pipe_in"), InputBinding.EMPTY_GRAIN);
628 end
629 else
630 if self:getIsPipeStateChangeAllowed(2) then
631 g_currentMission:addHelpButtonText(g_i18n:getText("Dump_corn"), InputBinding.EMPTY_GRAIN);
632 end
633 end
634 end;
635 else
636 if self:findAutoAimTrailerToUnload(self.currentFillType) ~= nil then
637 if self.isOverloadingActive then
638 g_currentMission:addHelpButtonText(g_i18n:getText("Stop_overloading"), InputBinding.EMPTY_GRAIN);
639 else
640 g_currentMission:addHelpButtonText(g_i18n:getText("Start_overloading"), InputBinding.EMPTY_GRAIN);
641 end;
642 end;
643 end;
644 end;
645end;
646
647function Overloading:activatePipeUnloadingEffects()
648 self.currentUnloadEffectStopTime = self.pipeUnloadEffectStopTime;
649 self.pipeIsUnloading = true;
650end;
651
652function Overloading:onDeactivateSounds()
653 if self.isClient then
654 Utils.stopSample(self.samplePipe, true);
655 end;
656end;
657
658function Overloading:getIsPipeStateChangeAllowed(pipeState)
659 if pipeState ~= 1 and self.foldAnimTime ~= nil and (self.foldAnimTime > self.pipeFoldMaxLimit or self.foldAnimTime < self.pipeFoldMinLimit) then
660 return false;
661 end
662 return true;
663end
664
665function Overloading:getIsPipeUnloadingAllowed()
666 if self.foldAnimTime ~= nil and (self.foldAnimTime > self.pipeFoldMaxLimit or self.foldAnimTime < self.pipeFoldMinLimit) then
667 return false;
668 end
669 return true;
670end
671
672function Overloading:setOverloadingActive(isActive, noEventSend)
673 if isActive ~= self.isOverloadingActive then
674 OverloadingToggleUnloadEvent.sendEvent(self, isActive, noEventSend);
675 self.isOverloadingActive = isActive;
676 end;
677end;
678
679function Overloading:setPipeState(pipeState, noEventSend)
680 pipeState = math.min(pipeState, self.numPipeStates);
681 if self.targetPipeState ~= pipeState then
682 if noEventSend == nil or noEventSend == false then
683 if g_server ~= nil then
684 g_server:broadcastEvent(OverloadingSetPipeStateEvent:new(self, pipeState));
685 else
686 g_client:getServerConnection():sendEvent(OverloadingSetPipeStateEvent:new(self, pipeState), nil, nil, self);
687 end;
688 end;
689 self.targetPipeState = pipeState;
690 self.currentPipeState = 0;
691 if self.pipeAnimation ~= nil then
692 if pipeState == 1 then
693 self:playAnimation(self.pipeAnimation, -self.pipeAnimSpeedScale, self:getAnimationTime(self.pipeAnimation), true);
694 else
695 self:playAnimation(self.pipeAnimation, self.pipeAnimSpeedScale, self:getAnimationTime(self.pipeAnimation), true);
696 end;
697 end;
698 end;
699end;
700
701function Overloading:getIsFoldAllowed(superFunc)
702 if not self.allowFoldWhileUnloading and self.pipeIsUnloading then
703 return false;
704 end
705 if self.currentPipeState > self.foldMaxPipeState or self.currentPipeState < self.foldMinPipeState then
706 return false;
707 end
708
709 if superFunc ~= nil then
710 return superFunc(self);
711 end
712 return true;
713end
714
715function Overloading:findAutoAimTrailerToUnload(fillType)
716 local trailer = nil;
717 local smallestTrailerId = nil;
718 local trailerIsAttached = false;
719 for trailerInRange, pipeStage in pairs(self.overloadingTrailersInRange) do
720 if trailerInRange.isDeleted then
721 self.overloadingTrailersInRange[trailerInRange] = nil;
722 else
723 if trailerInRange:allowFillType(fillType) and trailerInRange.getAllowFillFromAir ~= nil and trailerInRange:getAllowFillFromAir() and trailerInRange.fillLevel < trailerInRange:getCapacity() then
724 local id = networkGetObjectId(trailerInRange);
725 -- always take the trailer with the smallest network id which is attached if possible
726 -- This is deterministic and is the same on the client
727 local isAttached = trailerInRange:getIsAttachedTo(self)
728 if trailer == nil or (isAttached and not trailerIsAttached) or (isAttached == trailerIsAttached and id < smallestTrailerId) then
729 trailer = trailerInRange;
730 smallestTrailerId = id;
731 trailerIsAttached = isAttached
732 end;
733 end;
734 end
735 end;
736 return trailer;
737end;
738
739function Overloading:findTrailerToUnload(fillType)
740 local x,y,z = getWorldTranslation(self.pipeRaycastNode);
741 local dx,dy,dz = localDirectionToWorld(self.pipeRaycastNode, 0,-1,0);
742 self.trailerFound = 0;
743 self.trailerFoundDistance = 0;
744 raycastAll(x, y, z, dx,dy,dz, "findTrailerRaycastCallback", self.pipeRaycastDistance, self);
745
746 local trailer = g_currentMission.nodeToVehicle[self.trailerFound];
747 if trailer == nil or not trailer:allowFillType(fillType) or trailer.getAllowFillFromAir == nil or not trailer:getAllowFillFromAir() or trailer.fillLevel >= trailer:getCapacity() then
748 return nil;
749 end;
750 return trailer, self.trailerFoundDistance;
751end;
752
753function Overloading:findTrailerRaycastCallback(transformId, x, y, z, distance)
754 local vehicle = g_currentMission.nodeToVehicle[transformId];
755 if vehicle ~= nil then
756 if vehicle.exactFillRootNode == transformId then
757 self.trailerFound = transformId;
758 self.trailerFoundDistance = distance;
759 return false;
760 end;
761 end;
762
763 return true;
764end;
765
766function Overloading:getOverloadingTrailerInRangePipeState()
767 local maxPipeState = 0;
768 for trailer, pipeState in pairs(self.overloadingTrailersInRange) do
769 if trailer.isDeleted then
770 self.overloadingTrailersInRange[trailer] = nil;
771 else
772 maxPipeState = math.max(maxPipeState, pipeState);
773 end
774 end;
775 return maxPipeState;
776end
777
778function Overloading:onOverloadingTrailerTrigger(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
779 if onEnter or onLeave then
780 local trailer = g_currentMission.nodeToVehicle[otherId];
781 if trailer ~= nil and trailer.fillRootNode ~= nil and trailer ~= self then
782 if onEnter then
783 self.overloadingTriggersTrailers[trailer] = Utils.getNoNil(self.overloadingTriggersTrailers[trailer], 0) + 1;
784 else
785 self.overloadingTriggersTrailers[trailer] = math.max(Utils.getNoNil(self.overloadingTriggersTrailers[trailer], 0) - 1, 0);
786 end;
787 if self.overloadingTriggersTrailers[trailer] > 0 then
788 self.overloadingTrailersInRange[trailer] = self.trailerTriggers[triggerId].pipeState;
789 else
790 self.overloadingTrailersInRange[trailer] = nil;
791 end;
792 end;
793 end;
794end;
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
Script Dokumentation Übersicht