Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1 | -- |
2 | -- StumpCutter |
3 | -- This is the specialization for wood crushers |
4 | -- |
5 | -- @author Manuel Leithner |
6 | -- @date 26/09/14 |
7 | -- |
8 | -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. |
9 | |
10 | StumpCutter = {}; |
11 | |
12 | function StumpCutter.prerequisitesPresent(specializations) |
13 | return SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations); |
14 | end |
15 | |
16 | function StumpCutter:load(xmlFile) |
17 | self.getDirtMultiplier = Utils.overwrittenFunction(self.getDirtMultiplier, StumpCutter.getDirtMultiplier); |
18 | self.stumpCutterSplitShapeCallback = StumpCutter.stumpCutterSplitShapeCallback; |
19 | self.crushSplitShape = StumpCutter.crushSplitShape; |
20 | |
21 | self.stumpCutterCutNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.stumpCutter#cutNode")); |
22 | self.stumpCutterCutSizeY = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.stumpCutter#cutSizeY"), 1); |
23 | self.stumpCutterCutSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.stumpCutter#cutSizeZ"), 1); |
24 | |
25 | |
26 | if self.isClient then |
27 | self.sampleStumpCutterStart = Utils.loadSample(xmlFile, {}, "vehicle.stumpCutterStartSound", nil, self.baseDirectory); |
28 | self.sampleStumpCutterStop = Utils.loadSample(xmlFile, {}, "vehicle.stumpCutterStopSound", nil, self.baseDirectory); |
29 | self.sampleStumpCutterIdle = Utils.loadSample(xmlFile, {}, "vehicle.stumpCutterIdleSound", nil, self.baseDirectory); |
30 | self.sampleStumpCutterWork = Utils.loadSample(xmlFile, {}, "vehicle.stumpCutterWorkSound", nil, self.baseDirectory); |
31 | self.maxWorkFadeTime = 300; |
32 | self.workFadeTime = 0; |
33 | |
34 | self.stumpCutterParticleSystems = {}; |
35 | Utils.loadParticleSystem(xmlFile, self.stumpCutterParticleSystems, "vehicle.stumpCutter.particleSystem", self.components, false, nil, self.baseDirectory); |
36 | |
37 | self.stumpCutterTurnedOnRotationNodes = Utils.loadRotationNodes(xmlFile, {}, "vehicle.turnedOnRotationNodes.turnedOnRotationNode", "stumpCutter", self.components); |
38 | end; |
39 | |
40 | self.maxCutTime = 4000; |
41 | self.nextCutTime = self.maxCutTime; |
42 | self.maxResetCutTime = 1000; |
43 | self.resetCutTime = self.maxResetCutTime; |
44 | end |
45 | |
46 | function StumpCutter:delete() |
47 | if self.isClient then |
48 | if self.stumpCutterParticleSystems ~= nil then |
49 | Utils.deleteParticleSystem(self.stumpCutterParticleSystems); |
50 | end; |
51 | Utils.deleteSample(self.sampleStumpCutterStart); |
52 | Utils.deleteSample(self.sampleStumpCutterStop); |
53 | Utils.deleteSample(self.sampleStumpCutterIdle); |
54 | Utils.deleteSample(self.sampleStumpCutterWork); |
55 | end; |
56 | end |
57 | |
58 | function StumpCutter:readStream(streamId, connection) |
59 | end |
60 | |
61 | function StumpCutter:writeStream(streamId, connection) |
62 | end |
63 | |
64 | function StumpCutter:readUpdateStream(streamId, timestamp, connection) |
65 | end |
66 | |
67 | function StumpCutter:writeUpdateStream(streamId, connection, dirtyMask) |
68 | end |
69 | |
70 | function StumpCutter:loadFromAttributesAndNodes(xmlFile, key, resetVehicles) |
71 | return BaseMission.VEHICLE_LOAD_OK; |
72 | end; |
73 | |
74 | function StumpCutter:getSaveAttributesAndNodes(nodeIdent) |
75 | local attributes = ''; |
76 | local nodes = ""; |
77 | return attributes, nodes; |
78 | end; |
79 | |
80 | function StumpCutter:mouseEvent(posX, posY, isDown, isUp, button) |
81 | end |
82 | |
83 | function StumpCutter:keyEvent(unicode, sym, modifier, isDown) |
84 | end |
85 | |
86 | function StumpCutter:update(dt) |
87 | if self.isClient then |
88 | Utils.updateRotationNodes(self, self.stumpCutterTurnedOnRotationNodes, dt, self:getIsActive() and self:getIsTurnedOn()); |
89 | end; |
90 | end |
91 | |
92 | function StumpCutter:updateTick(dt) |
93 | if self:getIsActive() then |
94 | if self:getIsTurnedOn() then |
95 | if self.stumpCutterCutNode ~= nil then |
96 | self.curLenAbove = 0; |
97 | local x,y,z = getWorldTranslation(self.stumpCutterCutNode); |
98 | local nx,ny,nz = localDirectionToWorld(self.stumpCutterCutNode, 1,0,0); |
99 | local yx,yy,yz = localDirectionToWorld(self.stumpCutterCutNode, 0,1,0); |
100 | if self.curSplitShape ~= nil then |
101 | if testSplitShape(self.curSplitShape, x,y,z, nx,ny,nz, yx,yy,yz, self.stumpCutterCutSizeY, self.stumpCutterCutSizeZ) == nil then |
102 | self.curSplitShape = nil; |
103 | end |
104 | end |
105 | if self.curSplitShape == nil then |
106 | local shape, minY, maxY, minZ, maxZ = findSplitShape(x,y,z, nx,ny,nz, yx,yy,yz, self.stumpCutterCutSizeY, self.stumpCutterCutSizeZ); |
107 | if shape ~= 0 then |
108 | self.curSplitShape = shape; |
109 | end |
110 | end |
111 | if self.isClient and self.stumpCutterParticleSystems ~= nil then |
112 | Utils.setEmittingState(self.stumpCutterParticleSystems, self.curSplitShape ~= nil); |
113 | end; |
114 | |
115 | if self.curSplitShape ~= nil then |
116 | self.workFadeTime = math.min(self.maxWorkFadeTime, self.workFadeTime + dt); |
117 | if self.isServer then |
118 | self.resetCutTime = self.maxResetCutTime; |
119 | if self.nextCutTime > 0 then |
120 | self.nextCutTime = self.nextCutTime - dt; |
121 | if self.nextCutTime <= 0 then |
122 | -- cut |
123 | local lenBelow, lenAbove = getSplitShapePlaneExtents(self.curSplitShape, x,y,z, nx,ny,nz); |
124 | local lx,ly,lz = worldToLocal(self.curSplitShape, x,y,z); |
125 | if (lenBelow <= 0.4 or ly < 0.21) and lenAbove < 1 then -- only delete tree if lenAbove < 1 to avoid full tree deletion |
126 | -- Delete full tree: Not much left below the cut or cutting near the ground |
127 | self:crushSplitShape(self.curSplitShape); |
128 | self.curSplitShape = nil; |
129 | elseif lenAbove >= 0.2 then |
130 | -- Normal cut: Splitting 20cm below the top |
131 | self.nextCutTime = self.maxCutTime; |
132 | local curSplitShape = self.curSplitShape; |
133 | self.curSplitShape = nil; |
134 | self.curLenAbove = lenAbove; |
135 | splitShape(curSplitShape, x,y,z, nx,ny,nz, yx,yy,yz, self.stumpCutterCutSizeY, self.stumpCutterCutSizeZ, "stumpCutterSplitShapeCallback", self); |
136 | else |
137 | self.nextCutTime = self.maxCutTime; |
138 | end; |
139 | end; |
140 | end; |
141 | end |
142 | else |
143 | self.workFadeTime = math.max(0, self.workFadeTime - dt); |
144 | if self.isServer then |
145 | if self.resetCutTime > 0 then |
146 | self.resetCutTime = self.resetCutTime - dt; |
147 | if self.resetCutTime <= 0 then |
148 | self.nextCutTime = self.maxCutTime; |
149 | end; |
150 | end; |
151 | end |
152 | end; |
153 | end |
154 | |
155 | if self.isClient then |
156 | if self:getIsActiveForSound() then |
157 | if not Utils.isSamplePlaying(self.sampleStumpCutterStart, 1.8*dt) then |
158 | Utils.playSample(self.sampleStumpCutterIdle, 0, 0, nil); |
159 | Utils.playSample(self.sampleStumpCutterWork, 0, 0, nil); |
160 | end |
161 | local volume = self.sampleStumpCutterWork.volume * self.workFadeTime/self.maxWorkFadeTime; |
162 | Utils.setSampleVolume(self.sampleStumpCutterWork, volume); |
163 | end |
164 | end; |
165 | end |
166 | end |
167 | end |
168 | |
169 | function StumpCutter:draw() |
170 | end |
171 | |
172 | function StumpCutter:onDeactivate() |
173 | StumpCutter.onDeactivateSounds(self); |
174 | if self.isClient and self.stumpCutterParticleSystems ~= nil then |
175 | Utils.setEmittingState(self.stumpCutterParticleSystems, false); |
176 | end; |
177 | end |
178 | |
179 | function StumpCutter:onDeactivateSounds() |
180 | if self.isClient then |
181 | Utils.stopSample(self.sampleStumpCutterIdle, true); |
182 | Utils.stopSample(self.sampleStumpCutterWork, true); |
183 | Utils.stopSample(self.sampleStumpCutterStart, true); |
184 | end; |
185 | end |
186 | |
187 | function StumpCutter:onTurnedOn(noEventSend) |
188 | if self.isClient then |
189 | StumpCutter.onDeactivateSounds(self); |
190 | Utils.stopSample(self.sampleStumpCutterStop, true); |
191 | if self:getIsActiveForSound() then |
192 | Utils.playSample(self.sampleStumpCutterStart, 1, 0, nil); |
193 | end; |
194 | end; |
195 | end; |
196 | |
197 | function StumpCutter:onTurnedOff(noEventSend) |
198 | if self.isClient then |
199 | self.workFadeTime = 0; |
200 | if self.stumpCutterParticleSystems ~= nil then |
201 | Utils.setEmittingState(self.stumpCutterParticleSystems, false); |
202 | end; |
203 | StumpCutter.onDeactivateSounds(self); |
204 | if self:getIsActiveForSound() then |
205 | Utils.playSample(self.sampleStumpCutterStop, 1, 0, nil); |
206 | end; |
207 | end; |
208 | end; |
209 | |
210 | function StumpCutter:crushSplitShape(shape) |
211 | if self.isServer then |
212 | delete(shape); |
213 | end |
214 | end |
215 | |
216 | function StumpCutter:stumpCutterSplitShapeCallback(shape, isBelow, isAbove, minY, maxY, minZ, maxZ) |
217 | if not isBelow then |
218 | if self.curLenAbove < 1 then -- split tree if lenAbove > 1 to avoid fulltree deletion |
219 | self:crushSplitShape(shape); |
220 | end; |
221 | else |
222 | local yPos = minY + (maxY-minY)/2; |
223 | local zPos = minZ + (maxZ-minZ)/2; |
224 | local _,y,_ = localToWorld(self.stumpCutterCutNode, -0.05, yPos, zPos); |
225 | local height = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, getWorldTranslation(self.stumpCutterCutNode)); |
226 | if y < height then |
227 | self:crushSplitShape(shape); |
228 | else |
229 | self.curSplitShape = shape; |
230 | end; |
231 | end |
232 | end |
233 | |
234 | function StumpCutter:getDirtMultiplier(superFunc) |
235 | local multiplier = 0; |
236 | if superFunc ~= nil then |
237 | multiplier = multiplier + superFunc(self); |
238 | end; |
239 | |
240 | if self.curSplitShape ~= nil then |
241 | multiplier = multiplier + self.workMultiplier; |
242 | end; |
243 | |
244 | return multiplier; |
245 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de