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 | HighPressureWasher = {}; |
4 | HighPressureWasher_mt = Class(HighPressureWasher, Placeable); |
5 | |
6 | InitStaticObjectClass(HighPressureWasher, "HighPressureWasher", ObjectIds.OBJECT_HIGHPRESSURE_WASHER_PLACEABLE); |
7 | |
8 | function HighPressureWasher:new(isServer, isClient, customMt) |
9 | local mt = customMt; |
10 | if mt == nil then |
11 | mt = HighPressureWasher_mt; |
12 | end; |
13 | |
14 | local self = Placeable:new(isServer, isClient, mt); |
15 | registerObjectClassName(self, "HighPressureWasher"); |
16 | |
17 | self.messageShown = false; |
18 | |
19 | return self; |
20 | end; |
21 | |
22 | function HighPressureWasher:load(xmlFilename, x,y,z, rx,ry,rz, initRandom) |
23 | if not HighPressureWasher:superClass().load(self, xmlFilename, x,y,z, rx,ry,rz, initRandom) then |
24 | return false; |
25 | end; |
26 | |
27 | local xmlFile = loadXMLFile("TempXML", xmlFilename); |
28 | |
29 | self.playerInRangeDistance = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.playerInRangeDistance"), 3); |
30 | |
31 | self.washDistance = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.washDistance"), 10); |
32 | self.actionRadius = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.actionRadius#distance"), 15); |
33 | self.washMultiplier = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.washMultiplier"), 1); |
34 | self.pricePerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.pricePerMinute"), 10) / 1000; |
35 | self.lanceNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.lance#index")); |
36 | self.linkPosition = Utils.getVectorNFromString(Utils.getNoNil(getXMLString(xmlFile, "placeable.lance#position"), "0 0 0"), 3); |
37 | self.linkRotation = Utils.getRadiansFromString(Utils.getNoNil(getXMLString(xmlFile, "placeable.lance#rotation"), "0 0 0"), 3); |
38 | self.lanceNodeParent = getParent(self.lanceNode); |
39 | |
40 | self.lanceRaycastNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.lance#raycastNode")); |
41 | |
42 | if self.isClient then |
43 | self.particleSystems = {}; |
44 | Utils.loadParticleSystem(xmlFile, self.particleSystems, "placeable.particleSystem", self.nodeId, false, nil, g_currentMission.baseDirectory, nil); |
45 | |
46 | self.waterEffect = EffectManager:loadEffect(xmlFile, "placeable.waterEffect", self.nodeId, self); |
47 | |
48 | self.sampleCompressor = Utils.loadSample(xmlFile, {}, "placeable.compressorSound", nil, self.baseDirectory, self.nodeId); |
49 | self.compressorPitchMin = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.compressorSound#pitchMin"), 0.5); |
50 | self.sampleWashing = Utils.loadSample(xmlFile, {}, "placeable.washingSound", nil, self.baseDirectory); |
51 | self.sampleSwitch = Utils.loadSample(xmlFile, {}, "placeable.switchSound", nil, self.baseDirectory); |
52 | |
53 | local filename = getXMLString(xmlFile, "placeable.exhaust#filename"); |
54 | if filename ~= nil then |
55 | local i3dNode = Utils.loadSharedI3DFile(filename, self.baseDirectory, false, false, false); |
56 | if i3dNode ~= 0 then |
57 | local linkNode = Utils.getNoNil(Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.exhaust#index")), self.nodeId); |
58 | self.exhaustFilename = filename; |
59 | self.exhaustNode = getChildAt(i3dNode, 0); |
60 | link(linkNode, self.exhaustNode); |
61 | setVisibility(self.exhaustNode, false); |
62 | delete(i3dNode); |
63 | end; |
64 | end; |
65 | |
66 | self.targets = {}; |
67 | HandTool.loadTargets(xmlFile, "placeable", self.nodeId, self.targets); |
68 | end; |
69 | |
70 | delete(xmlFile); |
71 | |
72 | self.isPlayerInRange = false; |
73 | self.isTurnedOn = false; |
74 | self.activatable = HighPressureWasherActivatable:new(self); |
75 | self.doWashing = false; |
76 | self.lastInRangePosition = {0,0,0}; |
77 | self.isTurningOff = false; |
78 | self.turnOffTime = 0; |
79 | self.turnOffDuration = 500; |
80 | |
81 | return true; |
82 | end; |
83 | |
84 | function HighPressureWasher:delete() |
85 | self:setIsTurnedOn(false, nil, false); |
86 | if self.isClient then |
87 | EffectManager:deleteEffect(self.waterEffect); |
88 | if self.exhaustFilename ~= nil then |
89 | Utils.releaseSharedI3DFile(self.exhaustFilename, self.baseDirectory, true); |
90 | end; |
91 | if self.particleSystems ~= nil then |
92 | Utils.deleteParticleSystem(self.particleSystems); |
93 | end; |
94 | if self.sampleCompressor ~= nil then |
95 | Utils.deleteSample(self.sampleCompressor); |
96 | end; |
97 | if self.sampleWashing ~= nil then |
98 | Utils.deleteSample(self.sampleWashing); |
99 | end; |
100 | if self.sampleSwitch ~= nil then |
101 | Utils.deleteSample(self.sampleSwitch); |
102 | end; |
103 | end; |
104 | |
105 | unregisterObjectClassName(self); |
106 | g_currentMission:removeActivatableObject(self.activatable); |
107 | HighPressureWasher:superClass().delete(self); |
108 | end; |
109 | |
110 | function HighPressureWasher:readStream(streamId, connection) |
111 | HighPressureWasher:superClass().readStream(self, streamId, connection); |
112 | if connection:getIsServer() then |
113 | local isTurnedOn = streamReadBool(streamId); |
114 | if isTurnedOn then |
115 | local player = networkGetObject(streamReadInt32(streamId)); |
116 | if player ~= nil then |
117 | self:setIsTurnedOn(isTurnedOn, player, true); |
118 | end; |
119 | end; |
120 | end; |
121 | end; |
122 | |
123 | function HighPressureWasher:writeStream(streamId, connection) |
124 | HighPressureWasher:superClass().writeStream(self, streamId, connection); |
125 | if not connection:getIsServer() then |
126 | streamWriteBool(streamId, self.isTurnedOn); |
127 | if self.isTurnedOn then |
128 | streamWriteInt32(streamId, networkGetObjectId(self.currentPlayer)); |
129 | end; |
130 | end; |
131 | end; |
132 | |
133 | function HighPressureWasher:activateHandtool(player) |
134 | self:setIsTurnedOn(true, player, true); |
135 | end; |
136 | |
137 | function HighPressureWasher:update(dt) |
138 | HighPressureWasher:superClass().update(self, dt); |
139 | |
140 | if self.currentPlayer ~= nil then |
141 | local isPlayerInRange = self:getIsPlayerInRange(self.actionRadius, self.currentPlayer); |
142 | if isPlayerInRange then |
143 | self.lastInRangePosition = {getTranslation(self.currentPlayer.rootNode)}; |
144 | else |
145 | local kx, _, kz = getWorldTranslation(self.nodeId); |
146 | local px, _, pz = getWorldTranslation(self.currentPlayer.rootNode); |
147 | local len = Utils.vector2Length(px-kx, pz-kz); |
148 | |
149 | local x,y,z = unpack(self.lastInRangePosition); |
150 | x = kx + ((px-kx) / len) * (self.actionRadius-0.00001*dt); |
151 | z = kz + ((pz-kz) / len) * (self.actionRadius-0.00001*dt); |
152 | y = math.max(y, getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z)); |
153 | self.currentPlayer:moveToAbsoluteInternal(x, y, z); |
154 | self.lastInRangePosition = {x,y,z}; |
155 | |
156 | if not self.messageShown and self.currentPlayer == g_currentMission.player then |
157 | g_currentMission:showBlinkingWarning(g_i18n:getText("HighPressureWasherRangeRestriction"), 6000); |
158 | self.messageShown = true; |
159 | end; |
160 | end; |
161 | end; |
162 | |
163 | if self.isServer then |
164 | if self.isTurnedOn and self.doWashing then |
165 | self.foundVehicle = nil; |
166 | self:cleanVehicle(self.currentPlayer.cameraId, dt); |
167 | if self.lanceRaycastNode ~= nil then |
168 | self:cleanVehicle(self.lanceRaycastNode, dt); |
169 | end; |
170 | |
171 | local price = self.pricePerSecond * (dt / 1000); |
172 | g_currentMission.missionStats:updateStats("expenses", price); |
173 | g_currentMission:addSharedMoney(-price, "vehicleRunningCost"); |
174 | end; |
175 | end; |
176 | |
177 | if self.isTurningOff then |
178 | if g_currentMission.time < self.turnOffTime then |
179 | if self.sampleCompressor ~= nil then |
180 | local pitch = Utils.lerp(self.compressorPitchMin, self.sampleCompressor.pitchOffset, Utils.clamp((self.turnOffTime - g_currentMission.time) / self.turnOffDuration, 0, 1)); |
181 | local volume = Utils.lerp(0, self.sampleCompressor.volume, Utils.clamp((self.turnOffTime - g_currentMission.time) / self.turnOffDuration, 0, 1)); |
182 | Utils.setSamplePitch(self.sampleCompressor, pitch); |
183 | Utils.setSampleVolume(self.sampleCompressor, volume); |
184 | end; |
185 | else |
186 | self.isTurningOff = false; |
187 | if self.sampleCompressor ~= nil then |
188 | Utils.stop3DSample(self.sampleCompressor); |
189 | end; |
190 | end; |
191 | end; |
192 | end; |
193 | |
194 | function HighPressureWasher:cleanVehicle(node, dt) |
195 | local x,y,z = getWorldTranslation(node); |
196 | local dx, dy, dz = localDirectionToWorld(node, 0, 0, -1); |
197 | local lastFoundVehicle = self.foundVehicle; |
198 | --drawDebugLine(x, y, z, 1, 0, 0, x+dx*2, y+dy*2,z+dz*2, 0,0,1); |
199 | raycastAll(x, y, z, dx, dy, dz, "washRaycastCallback", self.washDistance, self, 32+64+128+256+4096+8194); |
200 | |
201 | if self.foundVehicle ~= nil and lastFoundVehicle ~= self.foundVehicle then |
202 | --drawDebugPoint(self.foundCoords[1], self.foundCoords[2], self.foundCoords[3], 1,1,1,1); |
203 | self.foundVehicle:setDirtAmount(self.foundVehicle:getDirtAmount() - self.washMultiplier*dt/self.foundVehicle.washDuration); |
204 | end; |
205 | end; |
206 | |
207 | function HighPressureWasher:updateTick(dt) |
208 | HighPressureWasher:superClass().updateTick(self, dt); |
209 | local isPlayerInRange, player = self:getIsPlayerInRange(self.playerInRangeDistance); |
210 | if isPlayerInRange then |
211 | self.playerInRange = player; |
212 | self.isPlayerInRange = true; |
213 | g_currentMission:addActivatableObject(self.activatable); |
214 | else |
215 | self.playerInRange = nil; |
216 | self.isPlayerInRange = false; |
217 | g_currentMission:removeActivatableObject(self.activatable); |
218 | end; |
219 | end; |
220 | |
221 | function HighPressureWasher:setIsWashing(doWashing, force, noEventSend) |
222 | HPWPlaceableStateEvent.sendEvent(self, doWashing, noEventSend); |
223 | if self.doWashing ~= doWashing then |
224 | if self.isClient then |
225 | Utils.setEmittingState(self.particleSystems, doWashing and self:getIsActiveForInput()); |
226 | if doWashing then |
227 | EffectManager:startEffect(self.waterEffect) |
228 | if self.sampleWashing ~= nil and self.currentPlayer == g_currentMission.player then |
229 | if self:getIsActiveForSound() then |
230 | Utils.playSample(self.sampleWashing, 0, 0, 1); |
231 | end; |
232 | end; |
233 | else |
234 | if force then |
235 | EffectManager:resetEffect(self.waterEffect); |
236 | else |
237 | EffectManager:stopEffect(self.waterEffect); |
238 | end; |
239 | if self.sampleWashing ~= nil then |
240 | Utils.stopSample(self.sampleWashing, true); |
241 | end; |
242 | end; |
243 | end; |
244 | self.doWashing = doWashing; |
245 | end; |
246 | end; |
247 | |
248 | function HighPressureWasher:setIsTurnedOn(isTurnedOn, player, noEventSend) |
249 | HPWPlaceableTurnOnEvent.sendEvent(self, isTurnedOn, player, noEventSend); |
250 | |
251 | if self.isTurnedOn ~= isTurnedOn then |
252 | if isTurnedOn then |
253 | self.isTurnedOn = isTurnedOn; |
254 | self.currentPlayer = player; |
255 | |
256 | -- player stuff |
257 | local tool = {}; |
258 | tool.node = self.lanceNode; |
259 | link(player.toolsRootNode, tool.node); |
260 | setVisibility(tool.node, false); |
261 | setTranslation(tool.node, unpack(self.linkPosition)); |
262 | setRotation(tool.node, unpack(self.linkRotation)); |
263 | tool.update = HighPressureWasher.updateLance; |
264 | tool.updateTick = HighPressureWasher.updateTickLance; |
265 | tool.delete = HighPressureWasher.deleteLance; |
266 | tool.draw = HighPressureWasher.drawLance; |
267 | tool.onActivate = HighPressureWasher.activateLance; |
268 | tool.onDeactivate = HighPressureWasher.deactivateLance; |
269 | tool.targets = self.targets; |
270 | tool.owner = self; |
271 | tool.static = false; |
272 | self.tool = tool; |
273 | self.currentPlayer:setTool(tool); |
274 | self.currentPlayer.hasHPWLance = true; |
275 | |
276 | if self.isClient then |
277 | if self.sampleSwitch ~= nil and self:getIsActiveForSound() then |
278 | Utils.playSample(self.sampleSwitch, 1, 0, nil); |
279 | end; |
280 | if self.sampleCompressor ~= nil then |
281 | Utils.setSamplePitch(self.sampleCompressor, self.sampleCompressor.pitchOffset); |
282 | Utils.setSampleVolume(self.sampleCompressor, self.sampleCompressor.volume); |
283 | Utils.play3DSample(self.sampleCompressor); |
284 | end; |
285 | if self.isTurningOff then |
286 | self.isTurningOff = false; |
287 | end; |
288 | setVisibility(self.lanceNode, g_currentMission.player == player); |
289 | end; |
290 | else |
291 | self:onDeactivate(); |
292 | end; |
293 | if self.exhaustNode ~= nil then |
294 | setVisibility(self.exhaustNode, isTurnedOn); |
295 | end; |
296 | end; |
297 | end; |
298 | |
299 | function HighPressureWasher:onDeactivate() |
300 | if self.isClient then |
301 | if self.sampleSwitch ~= nil and self:getIsActiveForSound() then |
302 | Utils.playSample(self.sampleSwitch, 1, 0, nil); |
303 | end; |
304 | end; |
305 | self.isTurnedOn = false; |
306 | setVisibility(self.lanceNode, true); |
307 | self:setIsWashing(false, true, true); |
308 | if self.currentPlayer ~= nil then |
309 | self.currentPlayer:setToolById(0, true); |
310 | self.currentPlayer.hasHPWLance = false; |
311 | end; |
312 | if self.isClient then |
313 | if self.sampleWashing ~= nil then |
314 | Utils.stopSample(self.sampleWashing, true); |
315 | end; |
316 | self.isTurningOff = true; |
317 | self.turnOffTime = g_currentMission.time + self.turnOffDuration; |
318 | link(self.lanceNodeParent, self.lanceNode); |
319 | setTranslation(self.lanceNode, 0,0,0); |
320 | setRotation(self.lanceNode, 0,0,0); |
321 | end; |
322 | self.currentPlayer = nil; |
323 | end; |
324 | |
325 | function HighPressureWasher:getIsActiveForInput() |
326 | if self.isTurnedOn and self.currentPlayer == g_currentMission.player and g_gui.currentGui == nil then |
327 | return true; |
328 | end; |
329 | return false; |
330 | end; |
331 | |
332 | function HighPressureWasher:getIsActiveForSound() |
333 | return self:getIsActiveForInput(); |
334 | end; |
335 | |
336 | function HighPressureWasher:washRaycastCallback(hitObjectId, x, y, z, distance) |
337 | local vehicle = g_currentMission.nodeToVehicle[hitObjectId]; |
338 | if vehicle ~= nil and vehicle.getDirtAmount ~= nil and vehicle.setDirtAmount ~= nil and vehicle.washDuration ~= nil then |
339 | self.foundCoords = {x,y,z}; |
340 | self.foundVehicle = vehicle; |
341 | return false; |
342 | end; |
343 | |
344 | return true; |
345 | end; |
346 | |
347 | function HighPressureWasher.activateLance(tool) |
348 | setVisibility(tool.node, true); |
349 | end |
350 | |
351 | function HighPressureWasher.deactivateLance(tool) |
352 | tool.owner:setIsTurnedOn(false, nil); |
353 | end |
354 | |
355 | function HighPressureWasher.deleteLance(tool) |
356 | tool.owner:setIsTurnedOn(false, nil); |
357 | end |
358 | |
359 | function HighPressureWasher.drawLance(tool) |
360 | if tool.owner.currentPlayer == g_currentMission.player then |
361 | g_currentMission:addHelpButtonText(g_i18n:getText("ACTIVATE_HANDTOOL"), InputBinding.ACTIVATE_HANDTOOL); |
362 | end; |
363 | end |
364 | |
365 | function HighPressureWasher.updateLance(tool, dt, allowInput) |
366 | if allowInput then |
367 | tool.owner:setIsWashing(InputBinding.isPressed(InputBinding.ACTIVATE_HANDTOOL), false, false); |
368 | end; |
369 | end; |
370 | |
371 | function HighPressureWasher.updateTickLance(tool, dt, allowInput) |
372 | end; |
373 | |
374 | HighPressureWasherActivatable = {} |
375 | local HighPressureWasherActivatable_mt = Class(HighPressureWasherActivatable); |
376 | |
377 | function HighPressureWasherActivatable:new(highPressureWasher) |
378 | local self = {}; |
379 | setmetatable(self, HighPressureWasherActivatable_mt); |
380 | |
381 | self.highPressureWasher = highPressureWasher; |
382 | self.activateText = "unknown"; |
383 | |
384 | return self; |
385 | end; |
386 | |
387 | function HighPressureWasherActivatable:getIsActivatable() |
388 | if not self.highPressureWasher.isPlayerInRange then |
389 | return false; |
390 | end; |
391 | |
392 | if self.highPressureWasher.playerInRange ~= g_currentMission.player then |
393 | return false; |
394 | end; |
395 | |
396 | if not self.highPressureWasher.playerInRange.isControlled then |
397 | return false; |
398 | end; |
399 | |
400 | if self.highPressureWasher.isTurnedOn and self.highPressureWasher.currentPlayer ~= g_currentMission.player then |
401 | return false; |
402 | end; |
403 | |
404 | if not self.highPressureWasher.isTurnedOn and g_currentMission.player.hasHPWLance == true then |
405 | return false; |
406 | end; |
407 | |
408 | if self.highPressureWasher.isDeleted then |
409 | return false; |
410 | end; |
411 | |
412 | self:updateActivateText(); |
413 | return true; |
414 | end; |
415 | |
416 | function HighPressureWasherActivatable:onActivateObject() |
417 | self.highPressureWasher:setIsTurnedOn(not self.highPressureWasher.isTurnedOn, g_currentMission.player); |
418 | self:updateActivateText(); |
419 | g_currentMission:addActivatableObject(self); |
420 | end; |
421 | |
422 | function HighPressureWasherActivatable:drawActivate() |
423 | end; |
424 | |
425 | function HighPressureWasherActivatable:updateActivateText() |
426 | if self.highPressureWasher.isTurnedOn then |
427 | self.activateText = string.format(g_i18n:getText("turn_off_OBJECT"), g_i18n:getText("TypeDesc_HighPressureWasher")); |
428 | else |
429 | self.activateText = string.format(g_i18n:getText("turn_on_OBJECT"), g_i18n:getText("TypeDesc_HighPressureWasher")); |
430 | end; |
431 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de