Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1 | -- |
2 | -- Trailer |
3 | -- This is the specialization for trailers |
4 | -- Note: tipState is not perfectly synced. It is only as accurate as the animation, which is only triggered by start and end events |
5 | -- lastFillDelta is only valid on the server |
6 | -- |
7 | -- @author Stefan Geiger |
8 | -- @date 30/11/08 |
9 | -- |
10 | -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. |
11 | |
12 | source("dataS/scripts/vehicles/specializations/TrailerToggleTipEvent.lua"); |
13 | source("dataS/scripts/vehicles/specializations/TrailerTipAreaEvent.lua"); |
14 | |
15 | Trailer = {}; |
16 | |
17 | Trailer.TIPSTATE_CLOSED = 0; |
18 | Trailer.TIPSTATE_OPENING = 1; |
19 | Trailer.TIPSTATE_OPEN = 2; |
20 | Trailer.TIPSTATE_CLOSING = 3; |
21 | |
22 | function Trailer.prerequisitesPresent(specializations) |
23 | return SpecializationUtil.hasSpecialization(Fillable, specializations); |
24 | end; |
25 | |
26 | function Trailer:load(xmlFile) |
27 | |
28 | self.toggleTipState = Trailer.toggleTipState; |
29 | self.onStartTip = SpecializationUtil.callSpecializationsFunction("onStartTip"); |
30 | self.onEndTip = SpecializationUtil.callSpecializationsFunction("onEndTip"); |
31 | self.enableTipAnimation = SpecializationUtil.callSpecializationsFunction("enableTipAnimation"); |
32 | self.disableCurrentTipAnimation = SpecializationUtil.callSpecializationsFunction("disableCurrentTipAnimation"); |
33 | self.setCurrentTipAnimationTime = SpecializationUtil.callSpecializationsFunction("setCurrentTipAnimationTime"); |
34 | self.getCurrentTipAnimationTime = Trailer.getCurrentTipAnimationTime; |
35 | self.getCurrentTipAnimationDuration = Trailer.getCurrentTipAnimationDuration; |
36 | self.setFillLevel = Utils.prependedFunction(self.setFillLevel, Trailer.setFillLevel); |
37 | self.getCurrentFruitType = Trailer.getCurrentFruitType; |
38 | self.updateTipping = Trailer.updateTipping; |
39 | self.getCanTipToGround = Trailer.getCanTipToGround; |
40 | self.getCanTip = Trailer.getCanTip; |
41 | self.getIsToggleCoverAllowed = Utils.overwrittenFunction(self.getIsToggleCoverAllowed, Trailer.getIsToggleCoverAllowed); |
42 | self.getTipScrollerSpeed = Trailer.getTipScrollerSpeed; |
43 | self.getEndTipIfEmpty = Trailer.getEndTipIfEmpty; |
44 | |
45 | self.tipText = Utils.getXMLI18NValue(xmlFile, "vehicle", getXMLString, "tipText", g_i18n:getText("Dump"), self.customEnvironment, false); |
46 | |
47 | self.lastFillDelta = 0; |
48 | |
49 | self.tipAnimations = {}; |
50 | local i = 0; |
51 | while true do |
52 | local key = string.format("vehicle.tipAnimations.tipAnimation(%d)", i); |
53 | if not hasXMLProperty(xmlFile, key) then |
54 | break; |
55 | end |
56 | |
57 | local tipAnimation = {}; |
58 | tipAnimation.dischargeEndTime = getXMLFloat(xmlFile, key.."#dischargeEndTime"); |
59 | if tipAnimation.dischargeEndTime ~= nil then |
60 | tipAnimation.dischargeEndTime = tipAnimation.dischargeEndTime * 1000; |
61 | end |
62 | tipAnimation.dischargeStartTime = Utils.getNoNil(getXMLFloat(xmlFile, key.."#dischargeStartTime"), 0)*1000; |
63 | local animationName = getXMLString(xmlFile, key.."#animationName"); |
64 | |
65 | tipAnimation.animationOpenSpeedScale = getXMLFloat(xmlFile, key.."#openSpeedScale"); |
66 | tipAnimation.animationCloseSpeedScale = getXMLFloat(xmlFile, key.."#closeSpeedScale"); |
67 | |
68 | local speedScale = Utils.getNoNil(getXMLFloat(xmlFile, key.."#speedScale"), 1); |
69 | if tipAnimation.animationOpenSpeedScale == nil then |
70 | tipAnimation.animationOpenSpeedScale = speedScale; |
71 | end |
72 | if tipAnimation.animationCloseSpeedScale == nil then |
73 | tipAnimation.animationCloseSpeedScale = -speedScale; |
74 | end |
75 | |
76 | if animationName ~= nil then |
77 | if self.playAnimation ~= nil and self.getAnimationDuration ~= nil then |
78 | tipAnimation.animationName = animationName; |
79 | tipAnimation.animationDuration = self:getAnimationDuration(animationName); |
80 | else |
81 | print("Error: tip animation "..i.." has animation name, but misses specialization AnimatedVehicle in "..self.configFileName); |
82 | end |
83 | else |
84 | local animationRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#rootNode")); |
85 | if animationRootNode ~= nil then |
86 | local animationCharSet = getAnimCharacterSet(animationRootNode); |
87 | if animationCharSet ~= nil then |
88 | local clip = getAnimClipIndex(animationCharSet, getXMLString(xmlFile, key.."#clip")); |
89 | assignAnimTrackClip(animationCharSet, 0, clip); |
90 | setAnimTrackLoopState(animationCharSet, 0, false); |
91 | |
92 | tipAnimation.animationCharSet = animationCharSet; |
93 | tipAnimation.animationDuration = getAnimClipDuration(animationCharSet, clip); |
94 | end |
95 | end |
96 | end |
97 | if tipAnimation.dischargeEndTime == nil and tipAnimation.animationDuration ~= nil then |
98 | tipAnimation.dischargeEndTime = tipAnimation.animationDuration*2.0; |
99 | end |
100 | if tipAnimation.dischargeEndTime ~= nil then |
101 | if self.isClient then |
102 | tipAnimation.dischargeParticleSystems = {}; |
103 | local i = 0; |
104 | while true do |
105 | local keyPS = string.format(key..".dischargeParticleSystems.dischargeParticleSystem(%d)", i); |
106 | local t = getXMLString(xmlFile, keyPS .. "#type"); |
107 | if t == nil then |
108 | break; |
109 | end; |
110 | local fillType = Fillable.fillTypeNameToInt[t]; |
111 | if fillType ~= nil then |
112 | local currentPS = Utils.getNoNil(tipAnimation.dischargeParticleSystems[fillType], {}); |
113 | local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, keyPS, self.components, false, nil, self.baseDirectory); |
114 | tipAnimation.dischargeParticleSystems[fillType] = currentPS; |
115 | end; |
116 | i = i + 1; |
117 | end; |
118 | |
119 | local fillTypes = getXMLString(xmlFile, key..".tipEffect#fillTypes"); |
120 | if fillTypes ~= nil then |
121 | for _, typeStr in pairs(Utils.splitString(" ", fillTypes)) do |
122 | if Fillable.fillTypeNameToInt[typeStr] ~= nil then |
123 | if tipAnimation.tipEffectFillTypes == nil then |
124 | tipAnimation.tipEffectFillTypes = {}; |
125 | end; |
126 | tipAnimation.tipEffectFillTypes[Fillable.fillTypeNameToInt[typeStr]] = true; |
127 | end; |
128 | end; |
129 | end; |
130 | |
131 | tipAnimation.tipEffect = EffectManager:loadEffect(xmlFile, key..".tipEffect", self.components, self); |
132 | end |
133 | |
134 | tipAnimation.doorAnimationName = getXMLString(xmlFile, key.."#doorAnimationName"); |
135 | tipAnimation.doorAnimationSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, key.."#doorAnimationSpeedScale"), 1.0); |
136 | tipAnimation.doorAnimationOpenSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, key.."#doorAnimationOpenSpeedScale"), speedScale); |
137 | tipAnimation.doorAnimationCloseSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, key.."#doorAnimationCloseSpeedScale"), -speedScale); |
138 | |
139 | tipAnimation.fillVolumeDischargeInfo = {}; |
140 | tipAnimation.fillVolumeDischargeInfo.node = Utils.indexToObject(self.components, Utils.getNoNil(getXMLString(xmlFile, key..".fillVolumeDischargeInfo#index"), "0>")); |
141 | tipAnimation.fillVolumeDischargeInfo.width = Utils.getNoNil(getXMLFloat(xmlFile, key..".fillVolumeDischargeInfo#width"), 1.0); |
142 | tipAnimation.fillVolumeDischargeInfo.length = Utils.getNoNil(getXMLFloat(xmlFile, key..".fillVolumeDischargeInfo#length"), 1.0); |
143 | |
144 | tipAnimation.fillVolumeDischargeInfo.alsoUseLoadInfoForDischarge = Utils.getNoNil(getXMLBool(xmlFile, key..".fillVolumeDischargeInfo#alsoUseLoadInfoForDischarge"), false); |
145 | tipAnimation.fillVolumeDischargeInfo.loadInfoSizeScale = Utils.getVectorNFromString( Utils.getNoNil(getXMLString(xmlFile, key..".fillVolumeDischargeInfo#loadInfoSizeScale"), "1 1"), 2 ); |
146 | tipAnimation.fillVolumeDischargeInfo.loadInfoFillFactor = Utils.getNoNil(getXMLFloat(xmlFile, key..".fillVolumeDischargeInfo#loadInfoFillFactor"), 0.6); |
147 | |
148 | tipAnimation.fillVolumeHeightIndex = getXMLInt(xmlFile, key..".fillVolumeHeight#index"); |
149 | |
150 | table.insert(self.tipAnimations, tipAnimation); |
151 | else |
152 | print("Error: invalid tip animation "..i.." in "..self.configFileName); |
153 | end |
154 | i = i + 1; |
155 | end |
156 | |
157 | -- Fallback for old tipAnimation and tipDischargeEndTime |
158 | if table.getn(self.tipAnimations) == 0 then |
159 | local tipAnimation = {}; |
160 | tipAnimation.dischargeEndTime = getXMLFloat(xmlFile, "vehicle.tipDischargeEndTime#value"); |
161 | tipAnimation.dischargeStartTime = 0; |
162 | |
163 | local animationRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.tipAnimation#rootNode")); |
164 | if animationRootNode ~= nil then |
165 | local animationCharSet = getAnimCharacterSet(animationRootNode); |
166 | if animationCharSet ~= 0 then |
167 | |
168 | local clip = getAnimClipIndex(animationCharSet, getXMLString(xmlFile, "vehicle.tipAnimation#clip")); |
169 | assignAnimTrackClip(animationCharSet, 0, clip); |
170 | setAnimTrackLoopState(animationCharSet, 0, false); |
171 | |
172 | tipAnimation.animationOpenSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.tipAnimation#speedScale"), 1); |
173 | tipAnimation.animationCloseSpeedScale = -tipAnimation.animationOpenSpeedScale; |
174 | tipAnimation.animationCharSet = animationCharSet; |
175 | tipAnimation.animationDuration = getAnimClipDuration(animationCharSet, clip); |
176 | if tipAnimation.dischargeEndTime == nil then |
177 | tipAnimation.dischargeEndTime = tipAnimation.animationDuration*2.0; |
178 | end |
179 | end |
180 | end |
181 | |
182 | if tipAnimation.dischargeEndTime ~= nil then |
183 | if self.isClient then |
184 | tipAnimation.dischargeParticleSystems = {}; |
185 | local i = 0; |
186 | while true do |
187 | local keyPS = string.format("vehicle.dischargeParticleSystems.dischargeParticleSystem(%d)", i); |
188 | local t = getXMLString(xmlFile, keyPS .. "#type"); |
189 | if t == nil then |
190 | break; |
191 | end; |
192 | local fillType = Fillable.fillTypeNameToInt[t]; |
193 | if fillType ~= nil then |
194 | local currentPS = Utils.getNoNil(tipAnimation.dischargeParticleSystems[fillType], {}); |
195 | local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, keyPS, self.components, false, nil, self.baseDirectory); |
196 | tipAnimation.dischargeParticleSystems[fillType] = currentPS; |
197 | end; |
198 | i = i + 1; |
199 | end; |
200 | end |
201 | |
202 | table.insert(self.tipAnimations, tipAnimation); |
203 | end |
204 | end |
205 | self.tipState = Trailer.TIPSTATE_CLOSED; |
206 | |
207 | self.fillLevelToTippedFillLevel = 1; |
208 | |
209 | self.tipReferencePoints = {}; |
210 | local i = 0; |
211 | while true do |
212 | local key = string.format("vehicle.tipReferencePoints.tipReferencePoint(%d)", i); |
213 | if not hasXMLProperty(xmlFile, key) then |
214 | break; |
215 | end |
216 | |
217 | node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index")); |
218 | if node ~= nil then |
219 | local width = Utils.getNoNil(getXMLFloat(xmlFile, key.."#width"), 0); |
220 | table.insert(self.tipReferencePoints, {node=node, width=width}); |
221 | end |
222 | i = i + 1; |
223 | end |
224 | |
225 | if hasXMLProperty(xmlFile, "vehicle.tipReferencePoint") then |
226 | print("Warning: vehicle.tipReferencePoint is not supported anymore. Use vehicle.tipReferencePoints.tipReferencePoint instead"); |
227 | end; |
228 | |
229 | if self.isClient then |
230 | if hasXMLProperty(xmlFile, "vehicle.hydraulicSound#file") then |
231 | print("Warning: vehicle.hydraulicSound is not supported anymore. Use vehicle.cylinderedHydraulicSound instead"); |
232 | end |
233 | |
234 | self.sampleFillSound = Utils.loadSample(xmlFile, {}, "vehicle.fillSound", nil, self.baseDirectory); |
235 | |
236 | self.tipRotationNodes = Utils.loadRotationNodes(xmlFile, {}, "vehicle.tipRotationNodes.tipRotationNode", "trailer", self.components); |
237 | self.tipScrollers = Utils.loadScrollers(self.components, xmlFile, "vehicle.tipScrollerNodes.tipScrollerNode", {}, false); |
238 | end; |
239 | |
240 | local start = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundDropArea#startIndex")); |
241 | local width = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundDropArea#widthIndex")); |
242 | local height = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundDropArea#heightIndex")); |
243 | if start ~= nil and width ~= nil and height ~= nil then |
244 | local area = {}; |
245 | area.start = start; |
246 | area.width = width; |
247 | area.height = height; |
248 | self.groundDropArea = area; |
249 | end; |
250 | |
251 | self.groundAmountAccumulation = 0; |
252 | |
253 | self.isSelectable = true; |
254 | |
255 | self.allowTipDischarge = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.allowTipDischarge#value"), true); |
256 | end; |
257 | |
258 | function Trailer:delete() |
259 | if self.isClient then |
260 | for _, tipAnimation in pairs(self.tipAnimations) do |
261 | for _, particleSystem in pairs(tipAnimation.dischargeParticleSystems) do |
262 | Utils.deleteParticleSystem(particleSystem); |
263 | end |
264 | if tipAnimation.tipEffect ~= nil then |
265 | EffectManager:deleteEffect(tipAnimation.tipEffect); |
266 | end; |
267 | end |
268 | Utils.deleteSample(self.sampleFillSound); |
269 | end |
270 | end; |
271 | |
272 | function Trailer:mouseEvent(posX, posY, isDown, isUp, button) |
273 | end; |
274 | |
275 | function Trailer:keyEvent(unicode, sym, modifier, isDown) |
276 | end; |
277 | |
278 | function Trailer:readStream(streamId, connection) |
279 | if connection:getIsServer() then |
280 | local tipState = streamReadUIntN(streamId, 2); |
281 | if tipState ~= Trailer.TIPSTATE_CLOSED then |
282 | local tipReferencePointIndex = streamReadUIntN(streamId, 4); |
283 | local animTime = streamReadFloat32(streamId); |
284 | |
285 | if self.currentTipReferencePointIndex ~= nil and self.currentTipReferencePointIndex ~= tipReferencePointIndex then |
286 | self:disableCurrentTipAnimation(0); |
287 | end |
288 | |
289 | if tipState == Trailer.TIPSTATE_CLOSING then |
290 | self.currentTipReferencePointIndex = tipReferencePointIndex; |
291 | self:onEndTip(true); |
292 | else |
293 | self:onStartTip(nil, tipReferencePointIndex, true); |
294 | end; |
295 | self:setCurrentTipAnimationTime(animTime); |
296 | else |
297 | self:disableCurrentTipAnimation(0); |
298 | end; |
299 | self.tipState = tipState; |
300 | end; |
301 | end; |
302 | |
303 | function Trailer:writeStream(streamId, connection) |
304 | if not connection:getIsServer() then |
305 | assert(self.tipState >= 0 and self.tipState <= 3); |
306 | streamWriteUIntN(streamId, self.tipState, 2); |
307 | if self.tipState ~= Trailer.TIPSTATE_CLOSED then |
308 | local animTime = self:getCurrentTipAnimationTime(); |
309 | streamWriteFloat32(streamId, animTime); |
310 | |
311 | local tipReferencePointIndex = Utils.getNoNil(self.currentTipReferencePointIndex, 1); |
312 | assert(tipReferencePointIndex <= 15); |
313 | streamWriteUIntN(streamId, tipReferencePointIndex, 4); |
314 | end; |
315 | end; |
316 | end; |
317 | |
318 | --[[function Trailer:readUpdateStream(streamId, timestamp, connection) |
319 | end; |
320 | |
321 | function Trailer:writeUpdateStream(streamId, connection, dirtyMask) |
322 | end;]] |
323 | |
324 | function Trailer:update(dt) |
325 | if self:getIsActiveForInput() then |
326 | if self ~= g_currentMission.trailerInTipRange and self:getCanTipToGround() then |
327 | if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then |
328 | self:toggleTipState(nil, 1, true); |
329 | end; |
330 | end; |
331 | end; |
332 | |
333 | if self.isClient then |
334 | local tipScrollersSpeed = self:getTipScrollerSpeed() |
335 | Utils.updateScrollers(self.tipScrollers, dt*tipScrollersSpeed, tipScrollersSpeed > 0 ); |
336 | Utils.updateRotationNodes(self, self.tipRotationNodes, dt, self:getIsActive() and self.tipState ~= Trailer.TIPSTATE_CLOSED ); |
337 | |
338 | if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN then |
339 | for i,fillVolume in pairs(self.fillVolumes) do |
340 | if fillVolume.scrollSpeedDischarge[1] ~= 0 or fillVolume.scrollSpeedDischarge[2] ~= 0 or fillVolume.scrollSpeedDischarge[3] ~= 0 then |
341 | fillVolume.uvPosition[1] = fillVolume.uvPosition[1] + fillVolume.scrollSpeedDischarge[1]*dt; |
342 | fillVolume.uvPosition[2] = fillVolume.uvPosition[2] + fillVolume.scrollSpeedDischarge[2]*dt; |
343 | fillVolume.uvPosition[3] = fillVolume.uvPosition[3] + fillVolume.scrollSpeedDischarge[3]*dt; |
344 | setShaderParameter(fillVolume.volume, "uvOffset", fillVolume.uvPosition[1], fillVolume.uvPosition[2], fillVolume.uvPosition[3], 0, false); |
345 | end; |
346 | end; |
347 | end; |
348 | end; |
349 | end; |
350 | |
351 | function Trailer:updateTick(dt) |
352 | |
353 | if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN then |
354 | |
355 | if self.isServer then |
356 | self:updateTipping(dt); |
357 | end; |
358 | |
359 | if self.fillLevel <= 0 and self:getEndTipIfEmpty() then |
360 | self:onEndTip(true); |
361 | end; |
362 | |
363 | if self.tipState == Trailer.TIPSTATE_OPENING then |
364 | if self:getCurrentTipAnimationTime() >= self:getCurrentTipAnimationDuration() then |
365 | self.tipState = Trailer.TIPSTATE_OPEN; |
366 | end; |
367 | end; |
368 | |
369 | if self.isClient then |
370 | -- check if we still are in opening/open state. Maybe we ended tipping before. |
371 | if (self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN) and self.fillLevel > 0 then |
372 | if self:getIsActiveForSound() then |
373 | Utils.playSample(self.sampleFillSound, 0, 0, nil); |
374 | end; |
375 | else |
376 | Utils.stopSample(self.sampleFillSound); |
377 | end; |
378 | |
379 | if self.currentTipReferencePointIndex ~= nil then |
380 | if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN then |
381 | local tipAnimation = self.tipAnimations[self.currentTipReferencePointIndex]; |
382 | if tipAnimation ~= nil and tipAnimation.fillVolumeHeightIndex ~= nil then |
383 | if self.fillVolumeHeights[tipAnimation.fillVolumeHeightIndex] ~= nil then |
384 | self.fillVolumeHeights[tipAnimation.fillVolumeHeightIndex].volumeHeightIsDirty = true; |
385 | end; |
386 | end; |
387 | end; |
388 | end; |
389 | |
390 | end; |
391 | |
392 | elseif self.tipState == Trailer.TIPSTATE_CLOSING then |
393 | if self:getCurrentTipAnimationTime() <= 0.0 then |
394 | self:disableCurrentTipAnimation(); |
395 | self.tipState = Trailer.TIPSTATE_CLOSED; |
396 | end; |
397 | end; |
398 | |
399 | if self.isClient then |
400 | if self.currentTipReferencePointIndex ~= nil then |
401 | local tipAnimation = self.tipAnimations[self.currentTipReferencePointIndex]; |
402 | if tipAnimation ~= nil then |
403 | if (self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN) and self.fillLevel > 0 and self:getCurrentTipAnimationTime() >= tipAnimation.dischargeStartTime then |
404 | Utils.setEmittingState(tipAnimation.dischargeParticleSystems[self.currentFillType], true); |
405 | if tipAnimation.tipEffect ~= nil and self.currentTipEffect == nil then |
406 | if tipAnimation.tipEffectFillTypes == nil or tipAnimation.tipEffectFillTypes[self.currentFillType] ~= nil then |
407 | self.currentTipEffect = tipAnimation.tipEffect; |
408 | self.currentTipEffect:setFillType(self.currentFillType); |
409 | EffectManager:startEffect(self.currentTipEffect); |
410 | end; |
411 | end; |
412 | else |
413 | Utils.setEmittingState(tipAnimation.dischargeParticleSystems[self.currentFillType], false); |
414 | end; |
415 | end |
416 | end |
417 | |
418 | if self.currentTipEffect ~= nil then |
419 | if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN then |
420 | if self.currentTipReferencePointIndex ~= nil then |
421 | local tipAnimation = self.tipAnimations[self.currentTipReferencePointIndex]; |
422 | if tipAnimation ~= nil then |
423 | if self.fillLevel > 0 then |
424 | if tipAnimation.dischargeEndTime > tipAnimation.dischargeStartTime then |
425 | local m = self:getCapacity()/((tipAnimation.dischargeEndTime-tipAnimation.dischargeStartTime)/tipAnimation.animationOpenSpeedScale); |
426 | if self.fillLevel <= m * self.currentTipEffect.planeFadeTime then |
427 | EffectManager:stopEffect(self.currentTipEffect); |
428 | self.currentTipEffect = nil; |
429 | end; |
430 | end; |
431 | end; |
432 | end; |
433 | end; |
434 | end; |
435 | end; |
436 | end; |
437 | end; |
438 | |
439 | function Trailer:updateTipping(dt) |
440 | if not self.isServer then |
441 | return; |
442 | end; |
443 | if self:getCanTip() then |
444 | local fillType = self.currentFillType; |
445 | |
446 | local fillDelta = -self.fillLevel; |
447 | if self.currentTipReferencePointIndex ~= nil then |
448 | local animation = self.tipAnimations[self.currentTipReferencePointIndex]; |
449 | if animation ~= nil and animation.dischargeEndTime > animation.dischargeStartTime then |
450 | if self:getCurrentTipAnimationTime() >= animation.dischargeStartTime then |
451 | local m = self:getCapacity()/((animation.dischargeEndTime-animation.dischargeStartTime)/animation.animationOpenSpeedScale); |
452 | fillDelta = -m * dt; |
453 | else |
454 | fillDelta = 0; |
455 | end |
456 | end |
457 | end |
458 | |
459 | if fillDelta < 0 then |
460 | local curFill = self.fillLevel; |
461 | |
462 | if self.tipAnimations[self.currentTipReferencePointIndex].fillVolumeDischargeInfo ~= nil then |
463 | local info = self.tipAnimations[self.currentTipReferencePointIndex].fillVolumeDischargeInfo; |
464 | local x,y,z = getWorldTranslation(info.node); |
465 | local d1x,d1y,d1z = localDirectionToWorld(info.node, info.width,0,0); -- ToDo: estimate length of vector by ?delta filllevel?! |
466 | local d2x,d2y,d2z = localDirectionToWorld(info.node, 0,0,info.length); |
467 | local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z}; |
468 | |
469 | if fillDelta < 0 then |
470 | if info.alsoUseLoadInfoForDischarge and self.fillVolumeLoadInfo ~= nil then |
471 | local fillDeltaLoadInfo = fillDelta*info.loadInfoFillFactor; |
472 | fillDelta = fillDelta - fillDeltaLoadInfo; |
473 | local x,y,z = getWorldTranslation(self.fillVolumeLoadInfo.node); |
474 | local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeLoadInfo.node, self.fillVolumeLoadInfo.width*info.loadInfoSizeScale[1],0,0); |
475 | local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeLoadInfo.node, 0,0,self.fillVolumeLoadInfo.length*info.loadInfoSizeScale[2]); |
476 | local fss2 = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z}; |
477 | self:setFillLevel(self.fillLevel + fillDeltaLoadInfo, fillType, false, fss2); |
478 | end; |
479 | end; |
480 | |
481 | self:setFillLevel(self.fillLevel + fillDelta, fillType, false, fillSourceStruct); |
482 | else |
483 | local fillSourceStruct = {x=0,y=0,z=0, d1x=0,d1y=0,d1z=0, d2x=0,d2y=0,d2z=0}; |
484 | self:setFillLevel(self.fillLevel + fillDelta, fillType, false, fillSourceStruct); |
485 | end; |
486 | |
487 | -- |
488 | local fillDelta = self.fillLevel - curFill; |
489 | self.lastFillDelta = fillDelta; |
490 | |
491 | if self.currentTipTrigger ~= nil then |
492 | if self.currentTipTrigger.updateTrailerTipping ~= nil then |
493 | self.currentTipTrigger:updateTrailerTipping(self, fillDelta*self.fillLevelToTippedFillLevel, fillType); |
494 | end |
495 | elseif self:getCanTipToGround() then |
496 | if fillDelta < 0 then |
497 | local x, _,z = getWorldTranslation(self.groundDropArea.start); |
498 | local x1,_,z1 = getWorldTranslation(self.groundDropArea.width); |
499 | local x2,_,z2 = getWorldTranslation(self.groundDropArea.height); |
500 | |
501 | local area = {x,z,x1,z1,x2,z2, -fillDelta*self.fillLevelToTippedFillLevel}; |
502 | local area, bitType, valueAccumulation = TrailerTipAreaEvent.runLocally(area, fillType, self.groundAmountAccumulation) |
503 | if area ~= nil then |
504 | g_server:broadcastEvent(TrailerTipAreaEvent:new(area, bitType, fillType)); |
505 | end; |
506 | if valueAccumulation ~= nil then |
507 | self.groundAmountAccumulation = valueAccumulation; |
508 | end; |
509 | end; |
510 | end; |
511 | end |
512 | |
513 | else |
514 | self:onEndTip(); |
515 | end; |
516 | end; |
517 | |
518 | function Trailer:draw() |
519 | if self.isClient then |
520 | if self:getIsActiveForInput(true) then |
521 | if self ~= g_currentMission.trailerInTipRange and self:getCanTipToGround() then |
522 | g_currentMission:addHelpButtonText(g_i18n:getText("Dump"), InputBinding.IMPLEMENT_EXTRA); |
523 | end; |
524 | end |
525 | end; |
526 | end; |
527 | |
528 | function Trailer:toggleTipState(tipTrigger, tipReferencePointIndex, tipManually) |
529 | |
530 | if self.tipState == Trailer.TIPSTATE_CLOSED or self.tipState == Trailer.TIPSTATE_CLOSING then |
531 | self:onStartTip(tipTrigger, tipReferencePointIndex, false, tipManually); |
532 | else |
533 | self:onEndTip(); |
534 | end; |
535 | end; |
536 | |
537 | |
538 | -- TODO FS17: correct order of parameters |
539 | function Trailer:onStartTip(tipTrigger, tipReferencePointIndex, noEventSend, tipManually) |
540 | -- we can not start tipping while we are tipping with another animation |
541 | if self.isServer then |
542 | if self.currentTipReferencePointIndex ~= nil and self.currentTipReferencePointIndex ~= tipReferencePointIndex then |
543 | return; |
544 | end |
545 | end |
546 | |
547 | if noEventSend == nil or noEventSend == false then |
548 | if g_server ~= nil then |
549 | g_server:broadcastEvent(TrailerToggleTipEvent:new(self, true, tipTrigger, tipReferencePointIndex, tipManually), nil, nil, self); |
550 | else |
551 | g_client:getServerConnection():sendEvent(TrailerToggleTipEvent:new(self, true, tipTrigger, tipReferencePointIndex, tipManually)); |
552 | end; |
553 | end; |
554 | |
555 | if self.isServer then |
556 | self.currentTipTrigger = tipTrigger; |
557 | self.groundAmountAccumulation = 0; |
558 | end |
559 | self:enableTipAnimation(tipReferencePointIndex, 1); |
560 | self.currentTipReferencePointIndex = tipReferencePointIndex; |
561 | self.tipState = Trailer.TIPSTATE_OPENING; |
562 | |
563 | if self.setCoverState ~= nil then |
564 | self:setCoverState(true, true); |
565 | end; |
566 | |
567 | local tipAnimation = self.tipAnimations[tipReferencePointIndex]; |
568 | if tipAnimation ~= nil then |
569 | if tipAnimation.fillVolumeHeightIndex ~= nil then |
570 | if self.fillVolumeHeights[tipAnimation.fillVolumeHeightIndex] ~= nil then |
571 | self.fillVolumeHeights[tipAnimation.fillVolumeHeightIndex].volumeHeightIsDirty = true; |
572 | end; |
573 | end; |
574 | end; |
575 | end; |
576 | |
577 | function Trailer:onEndTip(noEventSend) |
578 | if noEventSend == nil or noEventSend == false then |
579 | if g_server ~= nil then |
580 | g_server:broadcastEvent(TrailerToggleTipEvent:new(self, false), nil, nil, self); |
581 | else |
582 | g_client:getServerConnection():sendEvent(TrailerToggleTipEvent:new(self, false)); |
583 | end; |
584 | end; |
585 | if self.currentTipReferencePointIndex ~= nil then |
586 | self:enableTipAnimation(self.currentTipReferencePointIndex, -1); |
587 | end |
588 | |
589 | if self.isServer then |
590 | self.currentTipTrigger = nil; |
591 | end |
592 | |
593 | if self.isClient then |
594 | Utils.stopSample(self.sampleFillSound); |
595 | end; |
596 | |
597 | self.tipState = Trailer.TIPSTATE_CLOSING; |
598 | end; |
599 | |
600 | function Trailer:getCurrentFruitType() |
601 | local fruitType = FruitUtil.fillTypeToFruitType[self.currentFillType]; |
602 | if fruitType == nil then |
603 | fruitType = FruitUtil.FRUITTYPE_UNKNOWN; |
604 | end; |
605 | return fruitType; |
606 | end; |
607 | |
608 | function Trailer:setFillLevel(fillLevel, fillType, force, fillSourceStruct) |
609 | |
610 | if self.isClient then |
611 | -- disable particle system if we switch the type or if the trailer is empty |
612 | if (self.currentFillType ~= fillType or fillLevel <= 0) and self.currentTipReferencePointIndex ~= nil then |
613 | local tipAnimation = self.tipAnimations[self.currentTipReferencePointIndex]; |
614 | if tipAnimation ~= nil then |
615 | Utils.setEmittingState(tipAnimation.dischargeParticleSystems[self.currentFillType], false); |
616 | end |
617 | end |
618 | end |
619 | end; |
620 | |
621 | function Trailer:onAttach(attacherVehicle) |
622 | end; |
623 | |
624 | function Trailer:onDeactivateSounds() |
625 | if self.isClient then |
626 | Utils.stopSample(self.sampleFillSound, true); |
627 | end; |
628 | end; |
629 | |
630 | function Trailer:getCanTip() |
631 | if self.currentFillType ~= Fillable.FILLTYPE_UNKNOWN then |
632 | if self.currentTipTrigger ~= nil then |
633 | return g_currentMission:getIsTrailerInTipRange(self, self.currentTipTrigger, self.currentTipReferencePointIndex); |
634 | else |
635 | return self:getCanTipToGround(); |
636 | end |
637 | end |
638 | return false; |
639 | end |
640 | |
641 | function Trailer:getCanTipToGround() |
642 | return g_currentMission.groundValueIds[self.currentFillType] ~= nil and self.groundDropArea ~= nil; |
643 | end; |
644 | |
645 | function Trailer:getEndTipIfEmpty() |
646 | return true; |
647 | end; |
648 | |
649 | function Trailer:enableTipAnimation(tipReferencePointIndex, direction, animTime) |
650 | if self.currentTipReferencePointIndex ~= tipReferencePointIndex then |
651 | self:disableCurrentTipAnimation(0); |
652 | end |
653 | |
654 | self.currentTipReferencePointIndex = tipReferencePointIndex; |
655 | |
656 | local animation = self.tipAnimations[tipReferencePointIndex]; |
657 | |
658 | if animation ~= nil then |
659 | local speedScale = animation.animationOpenSpeedScale; |
660 | if direction < 0 then |
661 | speedScale = animation.animationCloseSpeedScale; |
662 | end |
663 | if animation.animationName ~= nil then |
664 | self:playAnimation(animation.animationName, speedScale, self:getAnimationTime(animation.animationName), true); |
665 | if animTime ~= nil then |
666 | self:setRealAnimationTime(animation.animationName, animTime); |
667 | end |
668 | elseif animation.animationCharSet ~= nil then |
669 | enableAnimTrack(animation.animationCharSet, 0); |
670 | setAnimTrackSpeedScale(animation.animationCharSet, 0, speedScale); |
671 | if animTime ~= nil then |
672 | setAnimTrackTime(animation.animationCharSet, 0, animTime); |
673 | else |
674 | if direction > 0 then |
675 | if getAnimTrackTime(animation.animationCharSet, 0) < 0 then |
676 | setAnimTrackTime(animation.animationCharSet, 0, 0); |
677 | end; |
678 | else |
679 | if getAnimTrackTime(animation.animationCharSet, 0) > animation.animationDuration then |
680 | setAnimTrackTime(animation.animationCharSet, 0, animation.animationDuration); |
681 | end; |
682 | end |
683 | end |
684 | end |
685 | |
686 | if animation.doorAnimationName ~= nil then |
687 | local speedScale = animation.doorAnimationOpenSpeedScale; |
688 | if direction < 0 then |
689 | speedScale = animation.doorAnimationCloseSpeedScale; |
690 | end; |
691 | self:playAnimation(animation.doorAnimationName, speedScale, self:getAnimationTime(animation.doorAnimationName), true); |
692 | end; |
693 | |
694 | if direction <= 0 then |
695 | if self.currentTipEffect ~= nil then |
696 | EffectManager:stopEffect(self.currentTipEffect); |
697 | self.currentTipEffect = nil; |
698 | end; |
699 | end; |
700 | end |
701 | end |
702 | |
703 | function Trailer:disableCurrentTipAnimation(animTime) |
704 | if self.currentTipReferencePointIndex ~= nil then |
705 | local animation = self.tipAnimations[self.currentTipReferencePointIndex]; |
706 | if animation ~= nil then |
707 | Utils.setEmittingState(animation.dischargeParticleSystems[self.currentFillType], false); |
708 | |
709 | if animation.animationName ~= nil then |
710 | if animTime ~= nil then |
711 | self:setRealAnimationTime(animation.animationName, math.min(animTime, animation.animationDuration)); |
712 | end |
713 | self:stopAnimation(animation.animationName, true); |
714 | elseif animation.animationCharSet ~= nil then |
715 | if animTime ~= nil then |
716 | enableAnimTrack(animation.animationCharSet, 0); |
717 | setAnimTrackTime(animation.animationCharSet, 0, animTime, true); |
718 | end |
719 | disableAnimTrack(animation.animationCharSet, 0); |
720 | end |
721 | end |
722 | self.currentTipReferencePointIndex = nil; |
723 | end |
724 | end |
725 | |
726 | function Trailer:setCurrentTipAnimationTime(animTime) |
727 | if self.currentTipReferencePointIndex ~= nil then |
728 | local animation = self.tipAnimations[self.currentTipReferencePointIndex]; |
729 | if animation ~= nil then |
730 | if animation.animationName ~= nil then |
731 | self:setRealAnimationTime(animation.animationName, math.min(animTime, animation.animationDuration)); |
732 | elseif animation.animationCharSet ~= nil then |
733 | setAnimTrackTime(animation.animationCharSet, 0, animTime); |
734 | end |
735 | end |
736 | end |
737 | end |
738 | |
739 | function Trailer:getCurrentTipAnimationTime() |
740 | if self.currentTipReferencePointIndex ~= nil then |
741 | local animation = self.tipAnimations[self.currentTipReferencePointIndex]; |
742 | if animation ~= nil then |
743 | if animation.animationName ~= nil then |
744 | return self:getRealAnimationTime(animation.animationName); |
745 | elseif animation.animationCharSet ~= nil then |
746 | return getAnimTrackTime(animation.animationCharSet, 0); |
747 | end |
748 | end |
749 | end |
750 | return 0; |
751 | end |
752 | |
753 | function Trailer:getCurrentTipAnimationDuration() |
754 | if self.currentTipReferencePointIndex ~= nil then |
755 | local animation = self.tipAnimations[self.currentTipReferencePointIndex]; |
756 | if animation ~= nil then |
757 | return animation.animationDuration; |
758 | end |
759 | end |
760 | return 0; |
761 | end |
762 | |
763 | function Trailer:getIsToggleCoverAllowed(superFunc, isCoverOpen) |
764 | if not isCoverOpen and self.tipState ~= Trailer.TIPSTATE_CLOSED then |
765 | return false; |
766 | end; |
767 | |
768 | if superFunc ~= nil then |
769 | return superFunc(self, isCoverOpen); |
770 | end; |
771 | |
772 | return true; |
773 | end |
774 | |
775 | function Trailer:getTipScrollerSpeed() |
776 | if self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN then |
777 | return 1.0; |
778 | else |
779 | return 0; |
780 | end; |
781 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de