Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1 | -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. |
2 | |
3 | MultiSiloTrigger = {}; |
4 | |
5 | source("dataS/scripts/triggers/MultiSiloTriggerSetIsFillingEvent.lua"); |
6 | |
7 | local MultiSiloTrigger_mt = Class(MultiSiloTrigger, Object); |
8 | |
9 | InitStaticObjectClass(MultiSiloTrigger, "MultiSiloTrigger", ObjectIds.OBJECT_MULTI_SILO_TRIGGER); |
10 | |
11 | function MultiSiloTrigger:onCreate(id) |
12 | local trigger = MultiSiloTrigger:new(g_server ~= nil, g_client ~= nil); |
13 | local index = g_currentMission:addOnCreateLoadedObject(trigger); |
14 | trigger:load(id); |
15 | trigger:register(true); |
16 | end; |
17 | |
18 | function MultiSiloTrigger:new(isServer, isClient) |
19 | local self = Object:new(isServer, isClient, MultiSiloTrigger_mt); |
20 | self.rootNode = 0; |
21 | self.multiSiloTriggerDirtyFlag = self:getNextDirtyFlag(); |
22 | return self; |
23 | end; |
24 | |
25 | |
26 | function MultiSiloTrigger:load(id) |
27 | self.rootNode = id; |
28 | if self.isServer then |
29 | self.triggerIds = {}; |
30 | |
31 | local triggerRoot = Utils.indexToObject(id, getUserAttribute(id, "triggerIndex")); |
32 | if triggerRoot == nil then |
33 | triggerRoot = id; |
34 | end |
35 | |
36 | table.insert(self.triggerIds, triggerRoot); |
37 | addTrigger(triggerRoot, "triggerCallback", self); |
38 | for i=1, 3 do |
39 | local child = getChildAt(triggerRoot, i-1); |
40 | table.insert(self.triggerIds, child); |
41 | addTrigger(child, "triggerCallback", self); |
42 | end; |
43 | end; |
44 | |
45 | self.fillVolumeDischargeInfo = {}; |
46 | self.fillVolumeDischargeInfo.name = "fillVolumeDischargeInfo"; |
47 | self.fillVolumeDischargeInfo.node = Utils.indexToObject(id, getUserAttribute(id, "fillVolumeDischargeNode")); |
48 | self.fillVolumeDischargeInfo.width = Utils.getNoNil( getUserAttribute(id, "fillVolumeDischargeNodeWidth"), 0.5 ); |
49 | self.fillVolumeDischargeInfo.length = Utils.getNoNil( getUserAttribute(id, "fillVolumeDischargeNodeLength"), 0.5 ); |
50 | |
51 | self.fillTypes = {}; |
52 | self.selectedFillType = nil; |
53 | local fillTypesStr = getUserAttribute(id, "fillTypes"); |
54 | if fillTypesStr ~= nil then |
55 | local fillTypes = Utils.splitString(" ", fillTypesStr); |
56 | for k,v in pairs(fillTypes) do |
57 | local fillType = Fillable.fillTypeNameToInt[v]; |
58 | if fillType ~= nil then |
59 | if self.selectedFillType == nil then |
60 | self.selectedFillType = fillType; |
61 | end; |
62 | self.fillTypes[fillType] = fillType; |
63 | end; |
64 | end; |
65 | end; |
66 | |
67 | if self.isClient then |
68 | local dropParticleSystem = Utils.indexToObject(id, getUserAttribute(id, "dropParticleSystemIndex")); |
69 | if dropParticleSystem ~= nil then |
70 | self.dropParticleSystems = {}; |
71 | Utils.loadParticleSystemFromNode(dropParticleSystem, self.dropParticleSystems, false, true); |
72 | end |
73 | local lyingParticleSystem = Utils.indexToObject(id, getUserAttribute(id, "lyingParticleSystemIndex")); |
74 | if lyingParticleSystem ~= nil then |
75 | self.lyingParticleSystems = {}; |
76 | Utils.loadParticleSystemFromNode(lyingParticleSystem, self.lyingParticleSystems, true, true); |
77 | |
78 | for _, ps in ipairs(self.lyingParticleSystems) do |
79 | local lifespan = getParticleSystemLifespan(ps.geometry); |
80 | addParticleSystemSimulationTime(ps.geometry, lifespan); |
81 | end |
82 | |
83 | Utils.setParticleSystemTimeScale(self.lyingParticleSystems, 0); |
84 | end |
85 | |
86 | if self.dropParticleSystems == nil then |
87 | self.dropEffect = EffectManager:loadFromNode(id, self); |
88 | |
89 | if self.dropEffect == nil then |
90 | local particleSystem = Utils.getNoNil(getUserAttribute(id, "particleSystem"), "unloadingSiloParticles"); |
91 | |
92 | local x,y,z = getTranslation(id); |
93 | |
94 | local particlePositionStr = getUserAttribute(id, "particlePosition"); |
95 | if particlePositionStr ~= nil then |
96 | local psx,psy,psz = Utils.getVectorFromString(particlePositionStr); |
97 | if psx ~= nil and psy ~= nil and psz ~= nil then |
98 | x = x + psx; |
99 | y = y + psy; |
100 | z = z + psz; |
101 | end; |
102 | end; |
103 | |
104 | local psData = {}; |
105 | psData.psFile = getUserAttribute(id, "particleSystemFilename"); |
106 | if psData.psFile == nil then |
107 | local particleSystem = Utils.getNoNil(getUserAttribute(id, "particleSystem"), "unloadingSiloParticles"); |
108 | psData.psFile = "$data/vehicles/particleAnimation/shared/" .. particleSystem .. ".i3d"; |
109 | end |
110 | psData.posX, psData.posY, psData.posZ = x,y,z; |
111 | psData.forceNoWorldSpace = true; |
112 | |
113 | self.dropParticleSystems = {}; |
114 | Utils.loadParticleSystemFromData(psData, self.dropParticleSystems, nil, false, nil, g_currentMission.baseDirectory, getParent(id)); |
115 | end; |
116 | end |
117 | |
118 | local fillSoundFilename = getUserAttribute(id, "fillSoundFilename"); |
119 | if fillSoundFilename == nil then |
120 | fillSoundFilename = "$data/maps/sounds/siloFillSound.wav"; |
121 | end |
122 | if fillSoundFilename ~= "" and fillSoundFilename ~= "none" then |
123 | fillSoundFilename = Utils.getFilename(fillSoundFilename, g_currentMission.baseDirectory); |
124 | self.siloFillSound = createAudioSource("siloFillSound", fillSoundFilename, 30, 10, 1, 0); |
125 | link(id, self.siloFillSound); |
126 | setVisibility(self.siloFillSound, false); |
127 | end |
128 | |
129 | |
130 | self.scroller = Utils.indexToObject(id, getUserAttribute(id, "scrollerIndex")); |
131 | if self.scroller ~= nil then |
132 | self.scrollerShaderParameterName = Utils.getNoNil(getUserAttribute(self.scroller, "shaderParameterName"), "uvScrollSpeed"); |
133 | local scrollerScrollSpeed = getUserAttribute(self.scroller, "scrollSpeed"); |
134 | if scrollerScrollSpeed ~= nil then |
135 | self.scrollerSpeedX, self.scrollerSpeedY = Utils.getVectorFromString(scrollerScrollSpeed); |
136 | end |
137 | if self.scrollerSpeedX == nil then |
138 | self.scrollerSpeedX = 0; |
139 | end |
140 | if self.scrollerSpeedY == nil then |
141 | self.scrollerSpeedY = -0.75; |
142 | end |
143 | setShaderParameter(self.scroller, self.scrollerShaderParameterName, 0, 0, 0, 0, false); |
144 | end |
145 | end; |
146 | |
147 | self.fillLitersPerSecond = Utils.getNoNil(tonumber(getUserAttribute(id, "fillLitersPerSecond")), 1500); |
148 | |
149 | self.stationName = g_i18n:getText(Utils.getNoNil(getUserAttribute(id, "stationName"), "StationFarmSilo")); |
150 | self.isEnabled = true; |
151 | self.fill = 0; |
152 | self.siloTrailer = nil; |
153 | self.siloTrailerSend = nil; |
154 | self.isFilling = false; |
155 | |
156 | self.startFillText = g_i18n:getText("siloStartFilling"); |
157 | self.stopFillText = g_i18n:getText("siloStopFilling"); |
158 | |
159 | self.activateText = self.startFillText; |
160 | self.objectActivated = false; |
161 | end; |
162 | |
163 | function MultiSiloTrigger:delete() |
164 | |
165 | if self.isClient then |
166 | if self.siloFillSound ~= nil then |
167 | delete(self.siloFillSound); |
168 | end |
169 | EffectManager:deleteEffect(self.dropEffect); |
170 | Utils.deleteParticleSystem(self.dropParticleSystems); |
171 | Utils.deleteParticleSystem(self.lyingParticleSystems); |
172 | end |
173 | |
174 | if self.isServer then |
175 | for i=1, table.getn(self.triggerIds) do |
176 | removeTrigger(self.triggerIds[i]); |
177 | end |
178 | end |
179 | |
180 | delete(self.rootNode); |
181 | MultiSiloTrigger:superClass().delete(self); |
182 | end; |
183 | |
184 | function MultiSiloTrigger:readStream(streamId, connection) |
185 | MultiSiloTrigger:superClass().readStream(self, streamId); |
186 | if connection:getIsServer() then |
187 | local isFilling = streamReadBool(streamId); |
188 | if isFilling then |
189 | local fillType = streamReadUIntN(streamId, Fillable.sendNumBits); |
190 | self:setIsFilling(true, fillType, true); |
191 | else |
192 | self:setIsFilling(false, Fillable.FILLTYPE_UNKNOWN, true); |
193 | end; |
194 | local siloTrailer = streamReadInt32(streamId); |
195 | if siloTrailer ~= 0 then |
196 | self.siloTrailer = networkGetObject(siloTrailer); |
197 | else |
198 | self.siloTrailer = nil; |
199 | end; |
200 | end; |
201 | end; |
202 | |
203 | function MultiSiloTrigger:writeStream(streamId, connection) |
204 | MultiSiloTrigger:superClass().writeStream(self, streamId); |
205 | if not connection:getIsServer() then |
206 | streamWriteBool(streamId, self.isFilling); |
207 | if self.isFilling then |
208 | streamWriteUIntN(streamId, self.selectedFillType, Fillable.sendNumBits); |
209 | end; |
210 | if self.siloTrailerSend ~= nil then |
211 | streamWriteInt32(streamId, networkGetObjectId(self.object)); |
212 | else |
213 | streamWriteInt32(streamId, 0); |
214 | end; |
215 | end; |
216 | end; |
217 | |
218 | function MultiSiloTrigger:readUpdateStream(streamId, timestamp, connection) |
219 | MultiSiloTrigger:superClass().readUpdateStream(self, streamId, timestamp, connection); |
220 | if connection:getIsServer() then |
221 | if streamReadBool(streamId) then |
222 | local siloTrailer = streamReadInt32(streamId); |
223 | if siloTrailer ~= 0 then |
224 | self.siloTrailer = networkGetObject(siloTrailer); |
225 | g_currentMission:addActivatableObject(self); |
226 | else |
227 | self.siloTrailer = nil; |
228 | g_currentMission:removeActivatableObject(self); |
229 | end; |
230 | end; |
231 | end; |
232 | end; |
233 | |
234 | function MultiSiloTrigger:writeUpdateStream(streamId, connection, dirtyMask) |
235 | MultiSiloTrigger:superClass().writeUpdateStream(self, streamId, connection, dirtyMask); |
236 | if not connection:getIsServer() then |
237 | if streamWriteBool(streamId, bitAND(dirtyMask, self.multiSiloTriggerDirtyFlag) ~= 0) then |
238 | if self.siloTrailerSend ~= nil then |
239 | streamWriteInt32(streamId, networkGetObjectId(self.siloTrailerSend)); |
240 | else |
241 | streamWriteInt32(streamId, 0); |
242 | end; |
243 | end; |
244 | end; |
245 | end; |
246 | |
247 | function MultiSiloTrigger:update(dt) |
248 | |
249 | if self.isServer then |
250 | local trailer = self.siloTrailer; |
251 | if self.fill >= 4 and trailer ~= nil then |
252 | if self.isFilling then |
253 | trailer:resetFillLevelIfNeeded(self.selectedFillType); |
254 | local fillLevel = trailer:getFillLevel(self.selectedFillType); |
255 | local siloAmount = g_currentMission:getSiloAmount(self.selectedFillType); |
256 | if siloAmount > 0 and trailer:allowFillType(self.selectedFillType, false) then |
257 | local deltaFillLevel = math.min(self.fillLitersPerSecond*0.001*dt, siloAmount); |
258 | local x,y,z = getWorldTranslation(self.fillVolumeDischargeInfo.node); |
259 | local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeDischargeInfo.node, self.fillVolumeDischargeInfo.width,0,0); |
260 | local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeDischargeInfo.node, 0,0,self.fillVolumeDischargeInfo.length); |
261 | local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z}; |
262 | trailer:setFillLevel(fillLevel+deltaFillLevel, self.selectedFillType, false, fillSourceStruct); |
263 | local newFillLevel = trailer:getFillLevel(self.selectedFillType); |
264 | |
265 | if fillLevel ~= newFillLevel then |
266 | g_currentMission:setSiloAmount(self.selectedFillType, math.max(siloAmount-(newFillLevel-fillLevel), 0)); |
267 | else |
268 | self:setIsFilling(false, Fillable.FILLTYPE_UNKNOWN); |
269 | end; |
270 | else |
271 | self:setIsFilling(false, Fillable.FILLTYPE_UNKNOWN); |
272 | end; |
273 | end; |
274 | elseif self.isFilling then |
275 | self:setIsFilling(false, Fillable.FILLTYPE_UNKNOWN); |
276 | end; |
277 | |
278 | if self.siloTrailerSend ~= self.siloTrailer then |
279 | self.siloTrailerSend = self.siloTrailer; |
280 | self:raiseDirtyFlags(self.multiSiloTriggerDirtyFlag); |
281 | end; |
282 | |
283 | end; |
284 | end; |
285 | |
286 | function MultiSiloTrigger:getIsActivatable() |
287 | if not self.isEnabled then |
288 | return false; |
289 | end; |
290 | if self.isFilling then |
291 | if self.siloTrailer:getRootAttacherVehicle() == g_currentMission.controlledVehicle then |
292 | return true; |
293 | end; |
294 | else |
295 | if self.siloTrailer ~= nil then |
296 | local trailer = self.siloTrailer; |
297 | if trailer:getRootAttacherVehicle() ~= g_currentMission.controlledVehicle then |
298 | return false; |
299 | end; |
300 | if trailer.fillLevel == 0 then |
301 | return true; |
302 | elseif trailer.fillLevel > 0 and self.fillTypes[trailer.currentFillType] ~= nil and trailer.fillLevel < trailer:getCapacity() and g_currentMission:getSiloAmount(trailer.currentFillType) > 0 then |
303 | return true; |
304 | end; |
305 | end; |
306 | end; |
307 | |
308 | return false; |
309 | end; |
310 | |
311 | function MultiSiloTrigger:drawActivate() |
312 | return; |
313 | end; |
314 | |
315 | function MultiSiloTrigger:onActivateObject() |
316 | if not self.isFilling then |
317 | if self.siloTrailer ~= nil and self.siloTrailer.fillLevel > 0 then |
318 | self:setIsFilling(true, self.siloTrailer.currentFillType); |
319 | else |
320 | g_multiSiloDialog:setFillTypes(self.fillTypes); |
321 | g_multiSiloDialog:setTitle(self.stationName); |
322 | g_multiSiloDialog:setSelectionCallback(self.onFillTypeSelection, self); |
323 | self.multiSiloDialog = g_gui:showGui("MultiSiloDialog"); |
324 | end; |
325 | else |
326 | self:setIsFilling(false, Fillable.FILLTYPE_UNKNOWN); |
327 | end; |
328 | g_currentMission:addActivatableObject(self); |
329 | end; |
330 | |
331 | function MultiSiloTrigger:onFillTypeSelection(fillType) |
332 | if fillType ~= nil then |
333 | if self.siloTrailer ~= nil then |
334 | if self:getIsValidTrailer(self.siloTrailer) then |
335 | self:setIsFilling(true, fillType); |
336 | end; |
337 | end; |
338 | end; |
339 | end; |
340 | |
341 | function MultiSiloTrigger:setIsFilling(isFilling, fillType, noEventSend) |
342 | MultiSiloTriggerSetIsFillingEvent.sendEvent(self, isFilling, fillType, noEventSend); |
343 | if isFilling then |
344 | self:startFill(fillType); |
345 | else |
346 | self:stopFill(); |
347 | end; |
348 | end; |
349 | |
350 | function MultiSiloTrigger:stopFill() |
351 | if self.isFilling then |
352 | self.isFilling = false; |
353 | self.activateText = self.startFillText; |
354 | if self.isClient then |
355 | if self.siloFillSoundEnabled then |
356 | setVisibility(self.siloFillSound, false); |
357 | self.siloFillSoundEnabled = false; |
358 | end; |
359 | Utils.setEmittingState(self.dropParticleSystems, false); |
360 | Utils.setParticleSystemTimeScale(self.lyingParticleSystems, 0); |
361 | EffectManager:stopEffect(self.dropEffect); |
362 | if self.scroller ~= nil then |
363 | setShaderParameter(self.scroller, self.scrollerShaderParameterName, 0, 0, 0, 0, false); |
364 | end |
365 | end; |
366 | end; |
367 | end; |
368 | |
369 | function MultiSiloTrigger:startFill(fillType) |
370 | if not self.isFilling then |
371 | self.activateText = self.stopFillText; |
372 | self.isFilling = true; |
373 | self.selectedFillType = fillType; |
374 | if self.isClient then |
375 | if not self.siloFillSoundEnabled and self.siloFillSound ~= nil then |
376 | setVisibility(self.siloFillSound, true); |
377 | self.siloFillSoundEnabled = true; |
378 | end; |
379 | Utils.setEmittingState(self.dropParticleSystems, true); |
380 | Utils.setParticleSystemTimeScale(self.lyingParticleSystems, 1.0); |
381 | if self.dropEffect ~= nil then |
382 | self.dropEffect:setFillType(self.selectedFillType); |
383 | EffectManager:startEffect(self.dropEffect); |
384 | end; |
385 | |
386 | if self.scroller ~= nil then |
387 | setShaderParameter(self.scroller, self.scrollerShaderParameterName, self.scrollerSpeedX, self.scrollerSpeedY, 0, 0, false); |
388 | end |
389 | end; |
390 | end; |
391 | end; |
392 | |
393 | function MultiSiloTrigger:getIsValidTrailer(trailer) |
394 | for _, fillType in pairs(self.fillTypes) do |
395 | if trailer:allowFillType(fillType, false) then |
396 | return true; |
397 | end; |
398 | end; |
399 | |
400 | return false; |
401 | end; |
402 | |
403 | function MultiSiloTrigger:triggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
404 | assert(self.isServer); |
405 | if self.isEnabled then |
406 | local trailer = g_currentMission.objectToTrailer[otherShapeId]; |
407 | if trailer ~= nil then |
408 | if onEnter then |
409 | if self:getIsValidTrailer(trailer) and trailer.getAllowFillFromAir ~= nil and trailer:getAllowFillFromAir() then |
410 | self.fill = self.fill+1; |
411 | self.siloTrailer = trailer; |
412 | if self.fill >= 4 then |
413 | g_currentMission:addActivatableObject(self); |
414 | end; |
415 | end; |
416 | elseif onLeave then |
417 | self.fill = math.max(self.fill-1, 0); |
418 | self.siloTrailer = nil; |
419 | --self:stopFill(); |
420 | self:setIsFilling(false, Fillable.FILLTYPE_UNKNOWN); |
421 | g_currentMission:removeActivatableObject(self); |
422 | end; |
423 | end; |
424 | end; |
425 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de