Sprache Deutsch Language English

Script Dokumentation LS 2015 - WoodCrusher (Patch 1.3)

Script Dokumentation Übersicht

scripts/vehicles/specializations/WoodCrusher.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-- WoodCrusher
3-- This is the specialization for wood crushers
4--
5-- @author Stefan Geiger
6-- @date 22/09/14
7--
8-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
9
10WoodCrusher = {};
11
12function WoodCrusher.prerequisitesPresent(specializations)
13 return SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations) and SpecializationUtil.hasSpecialization(Fillable, specializations);
14end
15
16function WoodCrusher:load(xmlFile)
17 self.getDirtMultiplier = Utils.overwrittenFunction(self.getDirtMultiplier, WoodCrusher.getDirtMultiplier);
18 self.woodCrusherSplitShapeCallback = WoodCrusher.woodCrusherSplitShapeCallback;
19 self.woodCrusherMoveTriggerCallback = WoodCrusher.woodCrusherMoveTriggerCallback;
20 self.crushSplitShape = WoodCrusher.crushSplitShape;
21
22 self.woodCrusherCutNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.woodCrusher#cutNode"));
23 self.woodCrusherMainDrumRefNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.woodCrusher#mainDrumRefNode"));
24 self.woodCrusherMoveTrigger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.woodCrusher#moveTrigger"));
25 self.woodCrusherMoveColNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.woodCrusher#moveCol"));
26 local moveColDisableCollisionPairs = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.woodCrusher#moveColDisableCollisionPairs"), true);
27 self.woodCrusherMoveVelocityZ = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.woodCrusher#moveVelocityZ"), 0.8); -- m/s
28 self.woodCrusherMoveMaxForce = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.woodCrusher#moveMaxForce"), 7); -- input is kN
29 self.woodCrusherDownForceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.woodCrusher#downForceNode"));
30 self.woodCrusherDownForce = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.woodCrusher#downForce"), 2);
31 self.woodCrusherCutSizeY = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.woodCrusher#cutSizeY"), 1);
32 self.woodCrusherCutSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.woodCrusher#cutSizeZ"), 1);
33
34 if self.woodCrusherMoveColNode ~= nil and moveColDisableCollisionPairs then
35 for _, component in pairs(self.components) do
36 setPairCollision(component.node, self.woodCrusherMoveColNode, false);
37 end
38 end
39
40 self.woodCrusherMoveTriggerNodes = {};
41 if self.isServer and self.woodCrusherMoveTrigger ~= nil then
42 addTrigger(self.woodCrusherMoveTrigger, "woodCrusherMoveTriggerCallback", self);
43 end
44
45 self.woodCrusherCrushNodes = {};
46
47 if self.isClient then
48 self.woodCrusherParticleSystems = {};
49
50 local i=0;
51 while true do
52 local key = string.format("vehicle.woodCrusher.particleSystem(%d)", i);
53 if not hasXMLProperty(xmlFile, key) then
54 break;
55 end
56 Utils.loadParticleSystem(xmlFile, self.woodCrusherParticleSystems, key, self.components, false, nil, self.baseDirectory);
57 i = i+1;
58 end;
59
60 self.woodCrusherTurnedOnRotationNode = Utils.loadRotationNodes(xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "woodCrusher", self.components);
61 self.woodCrusherTurnedOnScrollers = Utils.loadScrollers(self.components, xmlFile, "vehicle.turnedOnScrollers.turnedOnScroller", {}, false);
62
63 self.sampleWoodCrusherStart = Utils.loadSample(xmlFile, {}, "vehicle.woodCrusherStartSound", nil, self.baseDirectory);
64 self.sampleWoodCrusherStop = Utils.loadSample(xmlFile, {}, "vehicle.woodCrusherStopSound", nil, self.baseDirectory);
65 self.sampleWoodCrusherIdle = Utils.loadSample(xmlFile, {}, "vehicle.woodCrusherIdleSound", nil, self.baseDirectory);
66 self.sampleWoodCrusherWork = Utils.loadSample(xmlFile, {}, "vehicle.woodCrusherWorkSound", nil, self.baseDirectory);
67
68 self.maxWorkFadeTime = 300;
69 self.workFadeTime = 0;
70 end;
71
72 self.crushingTime = 0;
73
74 self.woodCrusherDirtyFlag = self:getNextDirtyFlag();
75end
76
77function WoodCrusher:delete()
78 if self.isClient then
79 if self.woodCrusherParticleSystems ~= nil then
80 Utils.deleteParticleSystem(self.woodCrusherParticleSystems);
81 end;
82 Utils.deleteSample(self.sampleWoodCrusherStart);
83 Utils.deleteSample(self.sampleWoodCrusherStop);
84 Utils.deleteSample(self.sampleWoodCrusherIdle);
85 Utils.deleteSample(self.sampleWoodCrusherWork);
86 end;
87 if self.isServer and self.woodCrusherMoveTrigger ~= nil then
88 removeTrigger(self.woodCrusherMoveTrigger);
89 end;
90end
91
92function WoodCrusher:readStream(streamId, connection)
93end
94
95function WoodCrusher:writeStream(streamId, connection)
96end
97
98function WoodCrusher:readUpdateStream(streamId, timestamp, connection)
99 if connection:getIsServer() then
100 if streamReadBool(streamId) then
101 self.crushingTime = 1000;
102 else
103 self.crushingTime = 0;
104 end
105 end
106end
107
108function WoodCrusher:writeUpdateStream(streamId, connection, dirtyMask)
109 if not connection:getIsServer() then
110 streamWriteBool(streamId, self.crushingTime > 0);
111 end
112end
113
114function WoodCrusher:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
115 return BaseMission.VEHICLE_LOAD_OK;
116end;
117
118function WoodCrusher:getSaveAttributesAndNodes(nodeIdent)
119 local attributes = '';
120 local nodes = "";
121 return attributes, nodes;
122end;
123
124function WoodCrusher:mouseEvent(posX, posY, isDown, isUp, button)
125end
126
127function WoodCrusher:keyEvent(unicode, sym, modifier, isDown)
128end
129
130function WoodCrusher:update(dt)
131 if self:getIsActive() then
132 if self:getIsTurnedOn() then
133 if self.isServer then
134 for node in pairs(self.woodCrusherCrushNodes) do
135 self:crushSplitShape(node);
136 self.woodCrusherCrushNodes[node] = nil;
137 self.woodCrusherMoveTriggerNodes[node] = nil;
138 end
139
140 local x,y,z = getTranslation(self.woodCrusherMainDrumRefNode);
141 local tx = 0;
142 local ty = 0;
143 local tz = 0;
144 local maxTreeSizeY = 0;
145 for id in pairs(self.woodCrusherMoveTriggerNodes) do
146 if not entityExists(id) then
147 self.woodCrusherMoveTriggerNodes[id] = nil;
148 else
149 if self.woodCrusherMoveColNode == nil then
150 local vx,vy,vz = getLinearVelocity(id);
151 local _,_,lvz = worldDirectionToLocal(self.woodCrusherMoveTrigger, vx,vy,vz);
152 if lvz < self.woodCrusherMoveVelocityZ then
153 local dvz = math.min(self.woodCrusherMoveVelocityZ - lvz, self.woodCrusherMoveMaxForce*dt*0.001/getMass(id));
154 local dvx,dvy,dvz = localDirectionToWorld(self.woodCrusherMoveTrigger, 0,0,dvz);
155 setLinearVelocity(id, vx+dvx, vy+dvy, vz+dvz);
156 end
157 end
158 if self.woodCrusherDownForceNode ~= nil then
159 local x,y,z = getWorldTranslation(self.woodCrusherDownForceNode);
160 local nx,ny,nz = localDirectionToWorld(self.woodCrusherDownForceNode, 1,0,0);
161 local yx,yy,yz = localDirectionToWorld(self.woodCrusherDownForceNode, 0,1,0);
162
163 local minY,maxY, minZ,maxZ = testSplitShape(id, x,y,z, nx,ny,nz, yx,yy,yz, self.woodCrusherCutSizeY, self.woodCrusherCutSizeZ);
164 if minY ~= nil then
165 local cx,cy,cz = localToWorld(self.woodCrusherDownForceNode, 0, (minY+maxY)*0.5, (minZ+maxZ)*0.5);
166 local downX,downY,downZ = localDirectionToWorld(self.woodCrusherDownForceNode, 0,-self.woodCrusherDownForce,0);
167 addForce(id, downX, downY, downZ, cx,cy,cz, false);
168
169 if self.woodCrusherMainDrumRefNode ~= nil then
170 maxTreeSizeY = math.max(maxTreeSizeY, maxY);
171 end;
172 end
173 end
174 end
175 end
176 if self.woodCrusherMainDrumRefNode ~= nil then
177 if maxTreeSizeY > 0 then
178 local a,b,c = localToWorld(self.woodCrusherDownForceNode, 0, maxTreeSizeY, 0);
179 _, ty, _ = worldToLocal(getParent(self.woodCrusherMainDrumRefNode), a,b,c);
180 end;
181 if ty > y then
182 y = math.min(y + 0.0003*dt, ty);
183 else
184 y = math.max(y - 0.0003*dt, ty);
185 end;
186 setTranslation(self.woodCrusherMainDrumRefNode, x,y,z);
187 end;
188 end
189 end
190 end
191
192 if self.isClient then
193 Utils.updateRotationNodes(self, self.woodCrusherTurnedOnRotationNode, dt, self:getIsActive() and self:getIsTurnedOn());
194 Utils.updateScrollers(self.woodCrusherTurnedOnScrollers, dt, self:getIsActive() and self:getIsTurnedOn());
195 end;
196end
197
198function WoodCrusher:updateTick(dt)
199 if self:getIsActive() then
200 if self:getIsTurnedOn() then
201 if self:getCapacity() <= 0 then
202 self.lastLostFillLevel = self.fillLevel;
203 if self.fillLevel > 0 then
204 self:setFillLevel(0, Fillable.FILLTYPE_WOODCHIPS);
205 end
206 end
207
208 if self.crushingTime > 0 then
209 self.crushingTime = self.crushingTime - dt;
210 if self.crushingTime <= 0 then
211 self:raiseDirtyFlags(self.woodCrusherDirtyFlag);
212 end
213 self.workFadeTime = math.min(self.maxWorkFadeTime, self.workFadeTime + dt);
214 else
215 self.workFadeTime = math.max(0, self.workFadeTime - dt);
216 end;
217 if self.isClient and self.woodCrusherParticleSystems ~= nil then
218 Utils.setEmittingState(self.woodCrusherParticleSystems, self.crushingTime > 0);
219 end;
220
221 if self.isServer then
222 if self.woodCrusherCutNode ~= nil and next(self.woodCrusherMoveTriggerNodes) ~= nil then
223 local x,y,z = getWorldTranslation(self.woodCrusherCutNode);
224 local nx,ny,nz = localDirectionToWorld(self.woodCrusherCutNode, 1,0,0);
225 local yx,yy,yz = localDirectionToWorld(self.woodCrusherCutNode, 0,1,0);
226 for id in pairs(self.woodCrusherMoveTriggerNodes) do
227 local lenBelow, lenAbove = getSplitShapePlaneExtents(id, x,y,z, nx,ny,nz);
228 if lenAbove ~= nil and lenBelow ~= nil then
229 if lenBelow <= 0.4 then
230 self.woodCrusherMoveTriggerNodes[id] = nil;
231 self:crushSplitShape(id);
232 elseif lenAbove >= 0.2 then
233 local minY = splitShape(id, x,y,z, nx,ny,nz, yx,yy,yz, self.woodCrusherCutSizeY, self.woodCrusherCutSizeZ, "woodCrusherSplitShapeCallback", self);
234 if minY ~= nil then
235 self.woodCrusherMoveTriggerNodes[id] = nil;
236 end
237 end
238 end;
239 end
240 end
241 end
242
243 if self.isClient then
244 if self:getIsActiveForSound() then
245 if not Utils.isSamplePlaying(self.sampleWoodCrusherStart, 1.8*dt) then
246 Utils.playSample(self.sampleWoodCrusherIdle, 0, 0, nil);
247 Utils.playSample(self.sampleWoodCrusherWork, 0, 0, nil);
248 end
249 local volume = self.sampleWoodCrusherWork.volume * self.workFadeTime/self.maxWorkFadeTime;
250 Utils.setSampleVolume(self.sampleWoodCrusherWork, volume);
251 end
252 end;
253 end
254 end
255end
256
257function WoodCrusher:draw()
258end
259
260function WoodCrusher:onDeactivate()
261 WoodCrusher.onDeactivateSounds(self);
262 if self.isClient then
263 if self.woodCrusherParticleSystems ~= nil then
264 Utils.setEmittingState(self.woodCrusherParticleSystems, false);
265 end;
266 end;
267end
268
269function WoodCrusher:onDeactivateSounds()
270 if self.isClient then
271 Utils.stopSample(self.sampleWoodCrusherIdle, true);
272 Utils.stopSample(self.sampleWoodCrusherWork, true);
273 Utils.stopSample(self.sampleWoodCrusherStart, true);
274 end;
275end
276
277function WoodCrusher:onTurnedOn(noEventSend)
278 if self.isClient then
279 WoodCrusher.onDeactivateSounds(self);
280 Utils.stopSample(self.sampleWoodCrusherStop, true);
281 if self:getIsActiveForSound() then
282 Utils.playSample(self.sampleWoodCrusherStart, 1, 0, nil);
283 end;
284 if self.woodCrusherMoveColNode ~= nil then
285 setFrictionVelocity(self.woodCrusherMoveColNode, self.woodCrusherMoveVelocityZ);
286 end
287 end;
288end;
289
290function WoodCrusher:onTurnedOff(noEventSend)
291 if self.isServer then
292 for node in pairs(self.woodCrusherCrushNodes) do
293 self:crushSplitShape(node);
294 self.woodCrusherCrushNodes[node] = nil;
295 end
296 if self.woodCrusherMoveColNode ~= nil then
297 setFrictionVelocity(self.woodCrusherMoveColNode, 0.0);
298 end
299 end
300 if self.isClient then
301 self.workFadeTime = 0;
302 if self.woodCrusherParticleSystems ~= nil then
303 Utils.setEmittingState(self.woodCrusherParticleSystems, false);
304 end;
305 WoodCrusher.onDeactivateSounds(self);
306 if self:getIsActiveForSound() then
307 Utils.playSample(self.sampleWoodCrusherStop, 1, 0, nil);
308 end;
309 end;
310end
311
312function WoodCrusher:crushSplitShape(shape)
313 local splitType = SplitUtil.splitTypes[getSplitType(shape)];
314 if splitType ~= nil and splitType.woodChipsPerLiter > 0 then
315 local volume = getVolume(shape);
316 self.crushingTime = 1000;
317 self:raiseDirtyFlags(self.woodCrusherDirtyFlag);
318 delete(shape);
319
320 local newFillLevel = self.fillLevel+volume*1000*splitType.woodChipsPerLiter;
321
322 local x,y,z = getWorldTranslation(self.fillVolumeLoadInfo.node);
323 local d1x,d1y,d1z = localDirectionToWorld(self.fillVolumeLoadInfo.node, self.fillVolumeLoadInfo.width,0,0);
324 local d2x,d2y,d2z = localDirectionToWorld(self.fillVolumeLoadInfo.node, 0,0,self.fillVolumeLoadInfo.length);
325 local fillSourceStruct = {x=x,y=y,z=z, d1x=d1x,d1y=d1y,d1z=d1z, d2x=d2x,d2y=d2y,d2z=d2z};
326 self:setFillLevel(newFillLevel, Fillable.FILLTYPE_WOODCHIPS, false, fillSourceStruct);
327 end
328end
329
330function WoodCrusher:woodCrusherSplitShapeCallback(shape, isBelow, isAbove, minY, maxY, minZ, maxZ)
331 if not isBelow then
332 self.woodCrusherCrushNodes[shape] = shape;
333 end
334end
335
336function WoodCrusher:woodCrusherMoveTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
337 local vehicle = g_currentMission.nodeToVehicle[otherActorId];
338 if vehicle == nil and getRigidBodyType(otherActorId) == "Dynamic" then
339 local splitType = SplitUtil.splitTypes[getSplitType(otherActorId)];
340 if splitType ~= nil and splitType.woodChipsPerLiter > 0 then
341 if onEnter then
342 self.woodCrusherMoveTriggerNodes[otherActorId] = Utils.getNoNil(self.woodCrusherMoveTriggerNodes[otherActorId],0)+1;
343 elseif onLeave then
344 local c = self.woodCrusherMoveTriggerNodes[otherActorId];
345 if c ~= nil then
346 c = c-1;
347 if c == 0 then
348 self.woodCrusherMoveTriggerNodes[otherActorId] = nil;
349 else
350 self.woodCrusherMoveTriggerNodes[otherActorId] = c;
351 end
352 end
353 end
354 end
355 end
356end
357
358function WoodCrusher:getDirtMultiplier(superFunc)
359 local multiplier = 0;
360 if superFunc ~= nil then
361 multiplier = multiplier + superFunc(self);
362 end;
363
364 if self.crushingTime > 0 then
365 multiplier = multiplier + self.workMultiplier;
366 end;
367
368 return multiplier;
369end;
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