Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1 | -- |
2 | -- Shovel |
3 | -- Class for all shovels |
4 | -- |
5 | -- @author Stefan Geiger |
6 | -- @date 12/09/11 |
7 | -- |
8 | -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. |
9 | |
10 | Shovel = {}; |
11 | source("dataS/scripts/vehicles/specializations/RemoveGroundValueAreaEvent.lua"); |
12 | source("dataS/scripts/vehicles/specializations/TrailerTipAreaEvent.lua"); |
13 | |
14 | function Shovel.prerequisitesPresent(specializations) |
15 | return SpecializationUtil.hasSpecialization(Fillable, specializations); |
16 | end; |
17 | |
18 | function Shovel:load(xmlFile) |
19 | |
20 | self.findTrailerRaycastCallback = Shovel.findTrailerRaycastCallback; |
21 | |
22 | self.setFillLevel = Utils.overwrittenFunction(self.setFillLevel, Shovel.setFillLevel); |
23 | self.getDoRenderFillType = Utils.overwrittenFunction(self.getDoRenderFillType, Shovel.getDoRenderFillType); |
24 | self.getAllowFillShovel = Shovel.getAllowFillShovel; |
25 | self.getShovelEmptyingSpeed = Shovel.getShovelEmptyingSpeed; |
26 | self.fillShovelFromGroundValue = Shovel.fillShovelFromGroundValue; |
27 | self.fillShovelFromTrigger = Shovel.fillShovelFromTrigger; |
28 | self.updateShovelParticleSystems = SpecializationUtil.callSpecializationsFunction("updateShovelParticleSystems"); |
29 | |
30 | |
31 | self.shovelTipReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.shovel#tipReferenceNode")); |
32 | self.shovelTipRaycastDistance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.shovel#tipRaycastDistance"), 10); |
33 | self.shovelOpenNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.shovel#openNode")); |
34 | self.shovelOpenRotation = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.shovel#openRotation"), 0)); |
35 | self.shovelOpenDirection = Utils.sign(Utils.getNoNil(getXMLInt(xmlFile, "vehicle.shovel#openDirection"), 1)); |
36 | self.shovelEmptyStartCosAngle = math.cos(math.rad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.shovel#emptyStartAngle"), 110))); |
37 | self.shovelEmptyFullCosAngle = math.cos(math.rad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.shovel#emptyFullAngle"), 135))); |
38 | self.shovelEmptySpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.shovel#emptySpeed"), self:getCapacity()/2)*0.001; |
39 | self.allowFillFromGroundValue = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.shovel#allowFillFromGroundValue"), false); |
40 | self.allowFillFromShovelTrigger = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.shovel#allowFillFromShovelTrigger"), true); |
41 | |
42 | self.shovelShowFillTypeIcon = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.shovel#showFillTypeIcon"), true); |
43 | |
44 | self.shovelFillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.shovel#fillLitersPerSecond"), 10000); |
45 | self.ignoreVehicleDirectionOnLoad = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.shovel#ignoreVehicleDirectionOnLoad"), false); |
46 | |
47 | local hasShovelNodes = false; |
48 | local shovelNodes = {}; |
49 | local i = 0; |
50 | while true do |
51 | local key = string.format("vehicle.shovel.node(%d)", i); |
52 | if not hasXMLProperty(xmlFile, key) then |
53 | break; |
54 | end; |
55 | hasShovelNodes = true; |
56 | local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index")); |
57 | if node ~= nil then |
58 | shovelNodes[node] = true; |
59 | end; |
60 | i = i + 1; |
61 | end; |
62 | if hasShovelNodes then |
63 | self.shovelNodes = shovelNodes; |
64 | end; |
65 | |
66 | |
67 | if self.isClient then |
68 | self.emptyParticleSystems = {}; |
69 | local i = 0; |
70 | while true do |
71 | local key = string.format("vehicle.emptyParticleSystems.emptyParticleSystem(%d)", i); |
72 | local t = getXMLString(xmlFile, key .. "#type"); |
73 | if t == nil then |
74 | break; |
75 | end; |
76 | local fillType = Fillable.fillTypeNameToInt[t]; |
77 | if fillType ~= nil then |
78 | local currentPS = {}; |
79 | |
80 | local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, nil, self.baseDirectory); |
81 | self.emptyParticleSystems[fillType] = currentPS; |
82 | end; |
83 | i = i + 1; |
84 | end; |
85 | |
86 | self.shovelEmptyEffect = EffectManager:loadEffect(xmlFile, "vehicle.shovelEmptyEffect", self.components, self); |
87 | |
88 | self.shovelEmptyEffectRotateNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.shovelEmptyEffect#rotationNode")); |
89 | self.shovelEmptyEffectRotateTimeOut = 0; |
90 | |
91 | self.shovelEmptyEffectFillTypes = {}; |
92 | local fillTypes = getXMLString(xmlFile, "vehicle.shovelEmptyEffect#fillTypes"); |
93 | if fillTypes ~= nil then |
94 | for _, typeStr in pairs(Utils.splitString(" ", fillTypes)) do |
95 | if Fillable.fillTypeNameToInt[typeStr] ~= nil then |
96 | self.shovelEmptyEffectFillTypes[Fillable.fillTypeNameToInt[typeStr]] = true; |
97 | end; |
98 | end; |
99 | end; |
100 | |
101 | self.shovelFillParticleSystems = {}; |
102 | local i = 0; |
103 | while true do |
104 | local key = string.format("vehicle.shovelFillParticleSystems.shovelFillParticleSystem(%d)", i); |
105 | local t = getXMLString(xmlFile, key .. "#type"); |
106 | if t == nil then |
107 | break; |
108 | end; |
109 | local fillType = Fillable.fillTypeNameToInt[t]; |
110 | if fillType ~= nil then |
111 | local currentPS = {}; |
112 | |
113 | local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, nil, self.baseDirectory); |
114 | self.shovelFillParticleSystems[fillType] = currentPS; |
115 | end; |
116 | i = i + 1; |
117 | end; |
118 | |
119 | self.shovelFillEffect = EffectManager:loadEffect(xmlFile, "vehicle.shovelFillEffect", self.components, self); |
120 | end; |
121 | |
122 | local shovelTipTriggerId = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.shovelTipTrigger#index")); |
123 | if shovelTipTriggerId ~= nil then |
124 | local shovelTipTrigger = FillableTipTrigger:new(self.isServer, self.isClient); |
125 | if shovelTipTrigger:load(shovelTipTriggerId, self) then |
126 | self.shovelTipTrigger = shovelTipTrigger; |
127 | self.shovelTipTrigger:register(true); |
128 | else |
129 | shovelTipTrigger:delete(); |
130 | end |
131 | end |
132 | |
133 | self.groundValueFillAreas = {} |
134 | local i=0; |
135 | while true do |
136 | local areaKey = string.format("vehicle.groundValueFillAreas.groundValueFillArea(%d)", i); |
137 | if not hasXMLProperty(xmlFile, areaKey) then |
138 | break; |
139 | end; |
140 | local area = {}; |
141 | if self:loadAreaFromXML(area, xmlFile, areaKey) then |
142 | local groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, areaKey .. "#groundReferenceNode")); |
143 | |
144 | if groundReferenceNode ~= nil then |
145 | area.groundReferenceNode = groundReferenceNode; |
146 | area.groundReferenceMinDistance = Utils.getNoNil(getXMLFloat(xmlFile, areaKey .. "#groundReferenceMinDistance"), 0.05); |
147 | area.groundReferenceMaxDistance = Utils.getNoNil(getXMLFloat(xmlFile, areaKey .. "#groundReferenceMaxDistance"), 0.95); |
148 | |
149 | table.insert(self.groundValueFillAreas, area); |
150 | end; |
151 | end; |
152 | i = i + 1; |
153 | end; |
154 | self.groundValueFillAreasSend = {}; |
155 | |
156 | |
157 | self.groundValueDropSizeX = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundValueDrop#sizeX"), 4); |
158 | self.groundValueDropSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundValueDrop#sizeZ"), 1); |
159 | self.groundValueDropStartNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundValueDrop#startNode")); |
160 | self.groundValueDropRefNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundValueDrop#refNode")); |
161 | if self.groundValueDropRefNode == nil then |
162 | self.groundValueDropRefNode = self.components[1].node; |
163 | end; |
164 | self.groundValueDropAccumulation = 0; |
165 | |
166 | self.lastShovelEmptyTime = -10000; |
167 | |
168 | self.shovelFillEffectTimeOut = -1; |
169 | self.shovelEmptyEffectTimeOut = -1; |
170 | |
171 | if self.shovelDirtyFlag == nil then |
172 | self.shovelDirtyFlag = self:getNextDirtyFlag(); |
173 | end |
174 | self.lastShovelPSFillDelta = 0; |
175 | self.lastShovelPSFillType = Fillable.FILLTYPE_UNKNOWN; |
176 | end; |
177 | |
178 | function Shovel:delete() |
179 | if self.isClient then |
180 | EffectManager:deleteEffect(self.shovelFillEffect); |
181 | EffectManager:deleteEffect(self.shovelEmptyEffect); |
182 | for _, particleSystem in pairs(self.emptyParticleSystems) do |
183 | Utils.deleteParticleSystem(particleSystem); |
184 | end; |
185 | for _, particleSystem in pairs(self.shovelFillParticleSystems) do |
186 | Utils.deleteParticleSystem(particleSystem); |
187 | end; |
188 | end; |
189 | if self.shovelTipTrigger ~= nil then |
190 | if self.isServer then |
191 | g_server:unregisterObject(self.shovelTipTrigger, true); |
192 | else |
193 | g_client:unregisterObject(self.shovelTipTrigger, true); |
194 | end; |
195 | self.shovelTipTrigger:delete(); |
196 | end |
197 | end; |
198 | |
199 | |
200 | function Shovel:addNodeVehicleMapping(list) |
201 | if self.shovelNodes ~= nil then |
202 | for node,_ in pairs(self.shovelNodes) do |
203 | list[node] = self; |
204 | end |
205 | end |
206 | end; |
207 | |
208 | function Shovel:removeNodeVehicleMapping(list) |
209 | if self.shovelNodes ~= nil then |
210 | for node,_ in pairs(self.shovelNodes) do |
211 | list[node] = nil; |
212 | end |
213 | end |
214 | end; |
215 | |
216 | function Shovel:readStream(streamId, connection) |
217 | if connection:getIsServer() then |
218 | if streamReadBool(streamId) then |
219 | local shovelTipTriggerId = streamReadInt32(streamId); |
220 | g_client:finishRegisterObject(self.shovelTipTrigger, shovelTipTriggerId); |
221 | end; |
222 | end; |
223 | end; |
224 | |
225 | function Shovel:writeStream(streamId, connection) |
226 | if not connection:getIsServer() then |
227 | local hasShovelTipTrigger = self.shovelTipTrigger ~= nil; |
228 | streamWriteBool(streamId, hasShovelTipTrigger); |
229 | if hasShovelTipTrigger then |
230 | streamWriteInt32(streamId, self.shovelTipTrigger.id); |
231 | end; |
232 | end; |
233 | end; |
234 | |
235 | function Shovel:readUpdateStream(streamId, timestamp, connection) |
236 | if connection:getIsServer() then |
237 | if streamReadBool(streamId) then |
238 | local fillLevelDelta = streamReadFloat32(streamId); |
239 | local fillType = streamReadUIntN(streamId, Fillable.sendNumBits); |
240 | self:updateShovelParticleSystems(fillLevelDelta, fillType); |
241 | end |
242 | end |
243 | end; |
244 | |
245 | function Shovel:writeUpdateStream(streamId, connection, dirtyMask) |
246 | if not connection:getIsServer() then |
247 | if streamWriteBool(streamId, bitAND(dirtyMask, self.shovelDirtyFlag) ~= 0) then |
248 | streamWriteFloat32(streamId, self.sentLastShovelPSFillDelta); |
249 | streamWriteUIntN(streamId, self.sentLastShovelPSFillType, Fillable.sendNumBits); |
250 | end |
251 | end; |
252 | end; |
253 | |
254 | function Shovel:mouseEvent(posX, posY, isDown, isUp, button) |
255 | end; |
256 | |
257 | function Shovel:keyEvent(unicode, sym, modifier, isDown) |
258 | end; |
259 | |
260 | function Shovel:update(dt) |
261 | if self:getIsActive() then |
262 | if self.shovelEmptyEffectRotateTimeOut > 0 and self.shovelEmptyEffectRotateNode ~= nil then |
263 | self.shovelEmptyEffectRotateTimeOut = self.shovelEmptyEffectRotateTimeOut - dt; |
264 | local dx,dy,dz = localDirectionToWorld(getParent(self.shovelEmptyEffectRotateNode), 0,0,1); |
265 | local alpha = math.acos(dy); |
266 | setRotation(self.shovelEmptyEffectRotateNode, -alpha+math.pi/2,0,0); |
267 | end |
268 | end; |
269 | end; |
270 | |
271 | function Shovel:updateTick(dt) |
272 | if self:getIsActive() then |
273 | if self.isServer then |
274 | local emptySpeed = self:getShovelEmptyingSpeed(); |
275 | if emptySpeed > 0 then |
276 | if self.fillLevel > 0 then |
277 | if self.shovelTipReferenceNode ~= nil then |
278 | -- do raycast and empty.. |
279 | |
280 | self.trailerFound = nil; |
281 | self.objectFound = nil; |
282 | local x,y,z = getWorldTranslation(self.shovelTipReferenceNode); |
283 | raycastAll(x, y, z, 0, -1, 0, "findTrailerRaycastCallback", self.shovelTipRaycastDistance, self); |
284 | |
285 | local delta = math.min(self.fillLevel, emptySpeed*dt); |
286 | if self.trailerFound ~= nil or self.objectFound ~= nil then |
287 | if self.trailerFound ~= nil and self.trailerFoundSupported then |
288 | self.trailerFound:resetFillLevelIfNeeded(self.currentFillType); |
289 | local oldFillLevel = self.trailerFound:getFillLevel(self.currentFillType); |
290 | |
291 | local x,y,z = getWorldTranslation(self.fillVolumeDischargeInfo.node); |
292 | |
293 | local dx,dy,dz = localDirectionToWorld(getParent(self.fillVolumeDischargeInfo.node), 0,0,1); |
294 | local alpha = math.acos(dy); |
295 | setRotation(self.fillVolumeDischargeInfo.node, -alpha+math.pi/2,0,0); |
296 | |
297 | |
298 | local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeDischargeInfo.node, self.fillVolumeDischargeInfo.width,0,0); |
299 | local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeDischargeInfo.node, 0,0,self.fillVolumeDischargeInfo.length); |
300 | local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z}; |
301 | self.trailerFound:setFillLevel(oldFillLevel + delta, self.currentFillType, false, fillSourceStruct); |
302 | |
303 | delta = self.trailerFound:getFillLevel(self.currentFillType) - oldFillLevel; |
304 | elseif self.objectFound ~= nil and self.objectFoundSupported then |
305 | local delta1 = self.objectFound:addShovelFillLevel(self, delta, self.currentFillType); |
306 | if delta1 ~= nil then |
307 | delta = delta1; |
308 | end; |
309 | else |
310 | -- do not empty shovel above unsupported trailer or shovel target |
311 | delta = 0; |
312 | end |
313 | elseif self.groundValueDropStartNode ~= nil then |
314 | local groundValueId = g_currentMission.groundValueIds[self.currentFillType]; |
315 | if groundValueId ~= nil then |
316 | local x,_,z = getWorldTranslation(self.groundValueDropStartNode); |
317 | local dx,_,dz = localDirectionToWorld(self.groundValueDropRefNode,0,0,1); |
318 | local l = 1.0/math.sqrt(dx*dx + dz*dz); |
319 | dx = dx * l; |
320 | dz = dz * l; |
321 | |
322 | local x1 = x + dz*self.groundValueDropSizeX; -- width point |
323 | local z1 = z - dx*self.groundValueDropSizeX; |
324 | |
325 | local x2 = x + dx*self.groundValueDropSizeZ; -- height point |
326 | local z2 = z + dz*self.groundValueDropSizeZ; |
327 | |
328 | local area = {x,z,x1,z1,x2,z2, delta}; |
329 | local area, bitType, valueAccumulation = TrailerTipAreaEvent.runLocally(area, self.currentFillType, self.groundValueDropAccumulation) |
330 | if area ~= nil then |
331 | g_server:broadcastEvent(TrailerTipAreaEvent:new(area, bitType, self.currentFillType)); |
332 | end; |
333 | if valueAccumulation ~= nil then |
334 | self.groundValueDropAccumulation = valueAccumulation; |
335 | end; |
336 | end; |
337 | end; |
338 | if delta ~= 0 then |
339 | local fillType = self.currentFillType; |
340 | local oldFillLevel = self.fillLevel; |
341 | |
342 | if self.fillVolumeUnloadInfo ~= nil then |
343 | local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeUnloadInfo.node, self.fillVolumeUnloadInfo.width,0,0); |
344 | local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeUnloadInfo.node, 0,0,self.fillVolumeUnloadInfo.length); |
345 | local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z}; |
346 | self:setFillLevel(oldFillLevel - delta, fillType, false, fillSourceStruct); |
347 | else |
348 | self:setFillLevel(oldFillLevel - delta, fillType); |
349 | end; |
350 | self:updateShovelParticleSystems(self.fillLevel - oldFillLevel, fillType); |
351 | self.lastShovelEmptyTime = g_currentMission.time; |
352 | else |
353 | -- stop PS |
354 | if self.lastShovelPSFillType ~= 0 and self.lastShovelPSFillType ~= nil then |
355 | self:updateShovelParticleSystems(0, self.lastShovelPSFillType); |
356 | end; |
357 | end; |
358 | end; |
359 | end; |
360 | else |
361 | -- not emptying, see if we can fill it |
362 | if self.allowFillFromGroundValue and self.fillLevel < self:getCapacity() and self.movingDirection > 0 then |
363 | |
364 | for _,area in pairs(self.groundValueFillAreas) do |
365 | if self:getIsAreaActive(area) then |
366 | local x,y,z = getWorldTranslation(area.groundReferenceNode); |
367 | local h = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z); |
368 | local groundDistance = y - h; |
369 | if groundDistance < area.groundReferenceMaxDistance then |
370 | local valueToLeavePercentage = math.max((groundDistance-area.groundReferenceMinDistance)/(area.groundReferenceMaxDistance - area.groundReferenceMinDistance), 0); |
371 | local x,y,z = getWorldTranslation(area.start); |
372 | local x1,y1,z1 = getWorldTranslation(area.width); |
373 | local x2,y2,z2 = getWorldTranslation(area.height); |
374 | table.insert(self.groundValueFillAreasSend, {x,z,x1,z1,x2,z2,valueToLeavePercentage}); |
375 | end; |
376 | end; |
377 | end; |
378 | if table.getn(self.groundValueFillAreasSend) > 0 then |
379 | |
380 | if self.fillLevel > 0 then |
381 | self:fillShovelFromGroundValue(self.groundValueFillAreasSend, self.currentFillType); |
382 | else |
383 | for fillType,enabled in pairs(self.fillTypes) do |
384 | if self:allowFillType(fillType) then |
385 | if self:fillShovelFromGroundValue(self.groundValueFillAreasSend, fillType) then |
386 | break; |
387 | end; |
388 | end; |
389 | end; |
390 | end; |
391 | |
392 | self.groundValueFillAreasSend = {}; |
393 | end; |
394 | end; |
395 | |
396 | -- stop PS |
397 | if self.lastShovelPSFillType ~= 0 and self.lastShovelPSFillType ~= nil then |
398 | self:updateShovelParticleSystems(0, self.lastShovelPSFillType); |
399 | end; |
400 | end; |
401 | |
402 | |
403 | if self.sentLastShovelPSFillDelta ~= self.lastShovelPSFillDelta or self.sentLastShovelPSFillType ~= self.lastShovelPSFillType then |
404 | self:raiseDirtyFlags(self.shovelDirtyFlag); |
405 | self.sentLastShovelPSFillDelta = self.lastShovelPSFillDelta; |
406 | self.sentLastShovelPSFillType = self.lastShovelPSFillType; |
407 | |
408 | self.lastShovelPSFillDelta = 0; |
409 | --self.lastShovelPSFillType = Fillable.FILLTYPE_UNKNOWN; |
410 | end; |
411 | end; |
412 | end; |
413 | |
414 | if self.isClient then |
415 | if self.shovelFillEffectTimeOut > 0 and self.shovelFillEffect ~= nil then |
416 | self.shovelFillEffectTimeOut = self.shovelFillEffectTimeOut - dt; |
417 | if self.shovelFillEffectTimeOut <= 0 then |
418 | EffectManager:stopEffect(self.shovelFillEffect); |
419 | end; |
420 | end; |
421 | if self.shovelEmptyEffectTimeOut > 0 and self.shovelEmptyEffect ~= nil then |
422 | self.shovelEmptyEffectTimeOut = self.shovelEmptyEffectTimeOut - dt; |
423 | if self.shovelEmptyEffectTimeOut <= 0 then |
424 | EffectManager:stopEffect(self.shovelEmptyEffect); |
425 | end; |
426 | end; |
427 | end; |
428 | end; |
429 | |
430 | function Shovel:draw() |
431 | end; |
432 | |
433 | function Shovel:getAllowFillShovel(fillType) |
434 | if self.shovelOpenNode ~= nil then |
435 | local x,y,z = getRotation(self.shovelOpenNode); |
436 | if self.shovelOpenDirection > 0 then |
437 | if x < self.shovelOpenRotation then |
438 | return false; |
439 | end; |
440 | else |
441 | if x > self.shovelOpenRotation then |
442 | return false; |
443 | end; |
444 | end |
445 | end; |
446 | if self:getShovelEmptyingSpeed() > 0 then |
447 | return false; |
448 | end; |
449 | return self:allowFillType(fillType, false) |
450 | end; |
451 | |
452 | function Shovel:getShovelEmptyingSpeed() |
453 | if self.shovelOpenNode ~= nil then |
454 | local x,y,z = getRotation(self.shovelOpenNode); |
455 | if self.shovelOpenDirection > 0 then |
456 | if x < self.shovelOpenRotation then |
457 | return 0; |
458 | end; |
459 | else |
460 | if x > self.shovelOpenRotation then |
461 | return 0; |
462 | end; |
463 | end |
464 | end; |
465 | if self.shovelTipReferenceNode ~= nil then |
466 | local dx,dy,dz = localDirectionToWorld(self.shovelTipReferenceNode, 0,0,1); |
467 | -- more than 55° rotated towards the ground |
468 | --if dy < -0.573576436351 then |
469 | if dy < self.shovelEmptyStartCosAngle then |
470 | local scale = math.min((self.shovelEmptyStartCosAngle-dy) / (self.shovelEmptyStartCosAngle - self.shovelEmptyFullCosAngle), 1); |
471 | return self.shovelEmptySpeed * scale; |
472 | end; |
473 | end; |
474 | return 0; |
475 | end; |
476 | |
477 | function Shovel:updateShovelParticleSystems(fillLevelDelta, fillType) |
478 | if self.isClient then |
479 | if fillLevelDelta < -0.00001 then |
480 | if self.fillLevel > 0 then |
481 | local ps = self.emptyParticleSystems[fillType]; |
482 | if ps ~= nil then |
483 | Utils.resetNumOfEmittedParticles(ps); |
484 | Utils.setEmittingState(ps, true); |
485 | end; |
486 | end |
487 | if self.shovelEmptyEffect ~= nil and self.shovelEmptyEffectFillTypes[fillType] == true then |
488 | self.shovelEmptyEffect:setFillType(fillType); |
489 | EffectManager:startEffect(self.shovelEmptyEffect); |
490 | self.shovelEmptyEffectTimeOut = 250; |
491 | self.shovelEmptyEffectRotateTimeOut = 250 + 1500; |
492 | end; |
493 | |
494 | elseif fillLevelDelta > 0.00001 then |
495 | local ps = self.shovelFillParticleSystems[fillType]; |
496 | if ps ~= nil then |
497 | Utils.resetNumOfEmittedParticles(ps); |
498 | Utils.setEmittingState(ps, true); |
499 | end; |
500 | if self.shovelFillEffect ~= nil then |
501 | self.shovelFillEffect:setFillType(fillType); |
502 | EffectManager:startEffect(self.shovelFillEffect); |
503 | self.shovelFillEffectTimeOut = 250; |
504 | end; |
505 | end; |
506 | end; |
507 | |
508 | if fillLevelDelta == 0 then |
509 | local ps = self.emptyParticleSystems[fillType]; |
510 | if ps ~= nil then |
511 | Utils.resetNumOfEmittedParticles(ps); |
512 | Utils.setEmittingState(ps, false); |
513 | end; |
514 | end; |
515 | |
516 | if self.isServer then |
517 | if self.lastShovelPSFillDelta == 0 and fillLevelDelta > 0 then |
518 | self.lastShovelPSFillType = fillType; |
519 | end; |
520 | self.lastShovelPSFillDelta = self.lastShovelPSFillDelta + fillLevelDelta; |
521 | end |
522 | end |
523 | |
524 | function Shovel:setFillLevel(oldSetFillLevel, fillLevel, fillType, force, fillSourceStruct) |
525 | |
526 | if fillType ~= self.currentFillType then |
527 | self.groundValueDropAccumulation = 0; |
528 | end; |
529 | |
530 | if oldSetFillLevel ~= nil then |
531 | oldSetFillLevel(self, fillLevel, fillType, force, fillSourceStruct); |
532 | end; |
533 | end; |
534 | |
535 | function Shovel:getDoRenderFillType(superFunc) |
536 | if not self.shovelShowFillTypeIcon or self.fillLevel == 0 then |
537 | return false; |
538 | end; |
539 | |
540 | if superFunc ~= nil then |
541 | return superFunc(self); |
542 | end |
543 | |
544 | return true; |
545 | end; |
546 | |
547 | function Shovel:findTrailerRaycastCallback(transformId, x, y, z, distance) |
548 | local trailer = g_currentMission.objectToTrailer[transformId]; |
549 | if trailer ~= nil and trailer ~= self then |
550 | if trailer:allowFillType(self.currentFillType) and trailer.getAllowFillFromAir ~= nil and trailer:getAllowFillFromAir() then |
551 | self.trailerFound = trailer; |
552 | self.trailerFoundSupported = true; |
553 | else |
554 | if self.trailerFound == nil then |
555 | self.trailerFound = trailer; |
556 | self.trailerFoundSupported = false; |
557 | end |
558 | end |
559 | return false; |
560 | end; |
561 | local object = g_currentMission:getNodeObject(transformId); |
562 | if object ~= nil then |
563 | -- fix for greenhouse placeable |
564 | if object.manurePlaneObject ~= nil and transformId == object.manurePlaneCollisionNode then |
565 | object = object.manurePlaneObject; |
566 | end |
567 | end; |
568 | if object ~= nil and object ~= self and object.addShovelFillLevel ~= nil and object.getAllowShovelFillType ~= nil then |
569 | if object:getAllowShovelFillType(self.currentFillType) then |
570 | self.objectFound = object; |
571 | self.objectFoundSupported = true; |
572 | return false; |
573 | else |
574 | if self.objectFound == nil then |
575 | self.objectFound = object; |
576 | self.objectFoundSupported = false; |
577 | end |
578 | end |
579 | end; |
580 | |
581 | return true; |
582 | |
583 | end; |
584 | |
585 | function Shovel:fillShovelFromGroundValue(areas, fillType) |
586 | local groundValueId = g_currentMission.groundValueIds[fillType]; |
587 | if groundValueId ~= nil then |
588 | local areas, bitType, valueRemoved = RemoveGroundValueAreaEvent.runLocally(areas, fillType); |
589 | if (table.getn(areas) > 0) then |
590 | g_server:broadcastEvent(RemoveGroundValueAreaEvent:new(areas, fillType, bitType)); |
591 | |
592 | local delta = valueRemoved*groundValueId.groundAmountToFillLevel; |
593 | if delta > 0 then |
594 | self:resetFillLevelIfNeeded(fillType); |
595 | local oldFillLevel = self:getFillLevel(fillType); |
596 | self:setFillLevel(oldFillLevel + delta, fillType); |
597 | self:updateShovelParticleSystems(self:getFillLevel(fillType) - oldFillLevel, fillType); |
598 | end |
599 | |
600 | return true; |
601 | end; |
602 | end; |
603 | |
604 | return false; |
605 | end; |
606 | |
607 | function Shovel:fillShovelFromTrigger(shovelTrigger, deltaFillLevel, fillType, dt) |
608 | if self:getAllowFillShovel(fillType) and (self.movingDirection == self.vehicleMovingDirection or self.ignoreVehicleDirectionOnLoad) then |
609 | local fillFactor |
610 | if self.ignoreVehicleDirectionOnLoad then |
611 | fillFactor = 0.001; |
612 | else |
613 | fillFactor = math.min(math.abs(self:getLastSpeed()), 5) * 0.0001; |
614 | end; |
615 | deltaFillLevel = math.min(deltaFillLevel, self.shovelFillLitersPerSecond*dt*fillFactor); |
616 | self:resetFillLevelIfNeeded(fillType); |
617 | |
618 | local oldFillLevel = self:getFillLevel(fillType); |
619 | |
620 | if self.fillVolumeLoadInfo == nil then |
621 | self:setFillLevel(oldFillLevel + deltaFillLevel, fillType); |
622 | else |
623 | local x,y,z = getWorldTranslation(self.fillVolumeLoadInfo.node); |
624 | local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeLoadInfo.node, self.fillVolumeLoadInfo.width,0,0); |
625 | local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeLoadInfo.node, 0,0,self.fillVolumeLoadInfo.length); |
626 | local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z}; |
627 | self:setFillLevel(oldFillLevel + deltaFillLevel, fillType, false, fillSourceStruct); |
628 | end; |
629 | |
630 | local finalDelta = self:getFillLevel(fillType) - oldFillLevel; |
631 | |
632 | self:updateShovelParticleSystems(finalDelta, fillType); |
633 | |
634 | return finalDelta; |
635 | end |
636 | return 0; |
637 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de