Sprache Deutsch Language English

Script Dokumentation LS 2015 - Drivable (Patch 1.3)

Script Dokumentation Übersicht

scripts/vehicles/specializations/Drivable.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-- Drivable
3-- Specialization class for Drivables
4--
5-- @author Stefan Geiger
6-- @date 30/11/08
7--
8-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
9
10source("dataS/scripts/vehicles/specializations/SetCruiseControlStateEvent.lua");
11source("dataS/scripts/vehicles/specializations/SetCruiseControlSpeedEvent.lua");
12source("dataS/scripts/vehicles/specializations/DrivableToggleLowerAllEvent.lua");
13
14Drivable = {};
15Drivable.CRUISECONTROL_STATE_OFF = 0;
16Drivable.CRUISECONTROL_STATE_ACTIVE = 1;
17Drivable.CRUISECONTROL_STATE_FULL = 2;
18
19
20function Drivable.prerequisitesPresent(specializations)
21 return SpecializationUtil.hasSpecialization(Motorized, specializations) and SpecializationUtil.hasSpecialization(Steerable, specializations);
22end;
23
24function Drivable:load(xmlFile)
25
26 self.getRpmLimit = Utils.overwrittenFunction(self.getRpmLimit, Drivable.getRpmLimit);
27 self.setCruiseControlState = Drivable.setCruiseControlState;
28 self.setCruiseControlMaxSpeed = Drivable.setCruiseControlMaxSpeed;
29 self.setMirrorVisible = Drivable.setMirrorVisible;
30 self.lowerImplementByJointIndex = Drivable.lowerImplementByJointIndex;
31 self.toggleLowerAllImplements = Drivable.toggleLowerAllImplements;
32 self.addOperatingTime = Drivable.addOperatingTime;
33 self.getDirtMultiplier = Utils.overwrittenFunction(self.getDirtMultiplier, Drivable.getDirtMultiplier);
34
35 self.steering = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.steering#index"));
36 Drivable.loadSettingsFromXML(self, xmlFile);
37
38 self.steeringEnabled = true;
39
40 self.axisSmoothTime = 500;
41 self.axisForward = 0;
42 self.lastDigitalForward = 0;
43 self.axisForwardIsAnalog = false;
44 self.axisSide = 0;
45 self.axisSideIsAnalog = false;
46 self.reverserDirection = 1;
47
48 -- mirrors
49 self.mirrors = {};
50 local i = 0;
51 while true do
52 local key = string.format("vehicle.mirrors.mirror(%d)", i);
53 if not hasXMLProperty(xmlFile, key) then
54 break;
55 end
56 local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
57 table.insert(self.mirrors, node);
58 i = i + 1;
59 end;
60 self:setMirrorVisible(false);
61 self.mirrorAvailable = g_settingsRearMirrors and g_rearMirrorsAvailable; -- show mirrors only on high profile
62 if self.mirrorAvailable and self.cameras[self.camIndex].useMirror then
63 self:setMirrorVisible(true);
64 else
65 self:setMirrorVisible(false);
66 end;
67
68
69 self.attacherJointLowerCombo = {};
70 self.attacherJointLowerCombo.duration = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.attacherJointLowerCombo#duration"), 2) * 1000;
71 self.attacherJointLowerCombo.currentTime = 0;
72 self.attacherJointLowerCombo.direction = -1;
73 self.attacherJointLowerCombo.isRunning = false;
74 self.attacherJointLowerCombo.joints = {};
75 local i=0;
76 while true do
77 local baseName = string.format("vehicle.attacherJointLowerCombo.attacherJoint(%d)", i);
78 if not hasXMLProperty(xmlFile, baseName) then
79 break;
80 end;
81
82 local attacherJointIndex = getXMLInt(xmlFile, baseName .. "#index");
83 if attacherJointIndex ~= nil and self.attacherJoints[attacherJointIndex] ~= nil then
84 local t = Utils.clamp(Utils.getNoNil(getXMLFloat(xmlFile, baseName .. "#time"), 0), 0, 1);
85 table.insert(self.attacherJointLowerCombo.joints, {jointIndex=attacherJointIndex, t=t*self.attacherJointLowerCombo.duration});
86 end;
87 i = i + 1;
88 end;
89
90 if table.getn(self.attacherJointLowerCombo.joints) == 0 then
91 self.attacherJointLowerCombo = nil;
92 end;
93
94
95 self.cruiseControl = {};
96 self.cruiseControl.maxSpeed = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cruiseControl#maxSpeed"), math.ceil(self.motor:getMaximumForwardSpeed()*3.6));
97 self.cruiseControl.minSpeed = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cruiseControl#minSpeed"), math.min(1, self.cruiseControl.maxSpeed));
98 self.cruiseControl.speed = self.cruiseControl.maxSpeed;
99 --self.cruiseControl.tempSpeed = self.cruiseControl.speed;
100 self.cruiseControl.isActive = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.cruiseControl#enabled"), true);
101 self.cruiseControl.state = Drivable.CRUISECONTROL_STATE_OFF;
102 self.cruiseControl.topSpeedTime = 2000;
103 self.cruiseControl.changeDelay = 250;
104 self.cruiseControl.changeCurrentDelay = 0;
105 self.cruiseControl.changeMultiplier = 1;
106 self.cruiseControl.speedSent = self.cruiseControl.speed;
107
108 self.operatingTime = 0;
109 self.maxOperatingTime = 99999.9 * 1000 * 60 * 60;
110
111 if self.isClient then
112 local defaultSample = nil;
113 if #self.turnSignals.left > 0 or #self.turnSignals.right > 0 then
114 defaultSample = "$data/vehicles/shared/blinker.wav";
115 end;
116 self.sampleTurnSignal = Utils.loadSample(xmlFile, {}, "vehicle.turnSignalSound", defaultSample, self.baseDirectory);
117 self.turnSignalRepetitionCount = 0;
118 end;
119
120 self.drivableGroundFlag = self:getNextDirtyFlag();
121end;
122
123function Drivable:loadSettingsFromXML(xmlFile)
124 self.speedRotScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.speedRotScale#scale"), 80);
125 self.speedRotScaleOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.speedRotScale#offset"), 0.7);
126 self.maxRotatedTimeSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.maxRotatedTimeSpeed#value"), 1)*0.001;
127end;
128
129function Drivable:postLoad(xmlFile)
130end;
131
132function Drivable:delete()
133end;
134
135function Drivable:readStream(streamId, connection)
136 if self.cruiseControl.isActive then
137 self:setCruiseControlState(streamReadUIntN(streamId, 2), true);
138 local speed = streamReadUInt8(streamId);
139 self:setCruiseControlMaxSpeed(speed);
140 self.cruiseControl.speedSent = speed;
141 end;
142
143 if self.attacherJointLowerCombo ~= nil then
144 self.attacherJointLowerCombo.direction = -1;
145 local dir = streamReadBool(streamId);
146 if dir then
147 self.attacherJointLowerCombo.direction = 1;
148 self.attacherJointLowerCombo.currentTime = self.attacherJointLowerCombo.duration;
149 end;
150 end;
151
152 self:addOperatingTime(streamReadFloat32(streamId), true);
153end;
154
155function Drivable:writeStream(streamId, connection)
156 if self.cruiseControl.isActive then
157 streamWriteUIntN(streamId, self.cruiseControl.state, 2);
158 streamWriteUInt8(streamId, self.cruiseControl.speed);
159 end;
160
161 if self.attacherJointLowerCombo ~= nil then
162 streamWriteBool(streamId, self.attacherJointLowerCombo.direction == 1);
163 end;
164
165 streamWriteFloat32(streamId, self.operatingTime);
166end;
167
168function Drivable:readUpdateStream(streamId, timestamp, connection)
169 --if not self.isServer and not self.isEntered or self.isServer and self.isEntered then
170 if connection:getIsServer() then
171 local brakeLightsVisibility = streamReadBool(streamId);
172 self:setBrakeLightsVisibility(brakeLightsVisibility);
173 local reverseLightsVisibility = streamReadBool(streamId);
174 self:setReverseLightsVisibility(reverseLightsVisibility);
175 else
176 local hasUpdate = streamReadBool(streamId);
177 if hasUpdate then
178 local axisForwardIsAnalog = streamReadBool(streamId);
179 local axisSideIsAnalog = streamReadBool(streamId);
180 local axisForward = streamReadFloat32(streamId);
181 local axisSide = streamReadFloat32(streamId);
182 local dt = streamReadFloat32(streamId);
183 if self.steeringEnabled and self.isControlled then
184 Drivable.updateVehiclePhysics(self, axisForward, axisForwardIsAnalog, axisSide, axisSideIsAnalog, dt);
185 end;
186 end;
187 end;
188end;
189
190function Drivable:writeUpdateStream(streamId, connection, dirtyMask)
191 if not connection:getIsServer() then
192 streamWriteBool(streamId, self.brakeLightsVisibility);
193 streamWriteBool(streamId, self.reverseLightsVisibility);
194 else
195 if streamWriteBool(streamId, bitAND(dirtyMask, self.drivableGroundFlag) ~= 0) then
196 streamWriteBool(streamId, self.axisForwardIsAnalog);
197 streamWriteBool(streamId, self.axisSideIsAnalog);
198 streamWriteFloat32(streamId, self.axisForward);
199 streamWriteFloat32(streamId, self.axisSide);
200 streamWriteFloat32(streamId, self.tickDt);
201 end;
202 end;
203end;
204
205function Drivable:mouseEvent(posX, posY, isDown, isUp, button)
206end;
207
208function Drivable:keyEvent(unicode, sym, modifier, isDown)
209end;
210
211function Drivable:update(dt)
212 if (self:getIsActive() and self.isMotorStarted) or self.isHired then
213 self:addOperatingTime(dt);
214 end;
215
216 if self.isEntered and self.isClient and not self.isHired then
217 -- do all the input handling
218 if self:getIsActiveForInput(false) then
219 if self.cruiseControl.isActive then
220 -- Cruise Control
221 if InputBinding.hasEvent(InputBinding.TOGGLE_CRUISE_CONTROL) then
222 if self.cruiseControl.state == Drivable.CRUISECONTROL_STATE_OFF then
223 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_ACTIVE);
224 else
225 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF);
226 end;
227 self.cruiseControl.topSpeedTime = 1000;
228 elseif InputBinding.isPressed(InputBinding.TOGGLE_CRUISE_CONTROL) then
229 self.cruiseControl.topSpeedTime = self.cruiseControl.topSpeedTime - dt;
230 if self.cruiseControl.topSpeedTime < 0 then
231 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_FULL);
232 end;
233 else
234 self.cruiseControl.topSpeedTime = 1000;
235 end;
236
237 local inputW = InputBinding.getDigitalInputAxis(InputBinding.AXIS_CRUISE_CONTROL);
238 if InputBinding.isAxisZero(inputW) then
239 inputW = InputBinding.getAnalogInputAxis(InputBinding.AXIS_CRUISE_CONTROL)
240 end;
241
242 if inputW ~= 0 then
243 self.cruiseControl.changeCurrentDelay = self.cruiseControl.changeCurrentDelay - dt*self.cruiseControl.changeMultiplier;
244 self.cruiseControl.changeMultiplier = math.min(self.cruiseControl.changeMultiplier + dt*0.0005, 5);
245 if self.cruiseControl.changeCurrentDelay < 0 then
246 local dir = 0;
247 if inputW > g_analogStickVTolerance then
248 dir = 1;
249 elseif inputW < -g_analogStickVTolerance then
250 dir = -1;
251 end;
252
253 if dir ~= 0 then
254 self.cruiseControl.wasSpeedChanged = true;
255 self:setCruiseControlMaxSpeed(self.cruiseControl.speed + dir);
256 self.cruiseControl.changeCurrentDelay = self.cruiseControl.changeDelay;
257 end;
258 end;
259 else
260 self.cruiseControl.wasSpeedChanged = false;
261 self.cruiseControl.changeMultiplier = 1;
262 self.cruiseControl.changeCurrentDelay = 0;
263 end;
264
265 if not self.cruiseControl.wasSpeedChanged and self.cruiseControl.speed ~= self.cruiseControl.speedSent then
266 if g_server ~= nil then
267 g_server:broadcastEvent(SetCruiseControlSpeedEvent:new(self, self.cruiseControl.speed), nil, nil, self);
268 else
269 g_client:getServerConnection():sendEvent(SetCruiseControlSpeedEvent:new(self, self.cruiseControl.speed));
270 end;
271 self.cruiseControl.speedSent = self.cruiseControl.speed;
272 end;
273 end;
274
275 if InputBinding.hasEvent(InputBinding.ATTACH) and not g_currentMission.inGameMessage:getIsVisible() then
276 self:handleAttachEvent();
277 end;
278
279 if InputBinding.hasEvent(InputBinding.LOWER_IMPLEMENT) then
280 self:handleLowerImplementEvent();
281 end;
282
283 if InputBinding.hasEvent(InputBinding.LOWER_ALL_IMPLEMENTS) then
284 self:toggleLowerAllImplements();
285 end;
286
287 if InputBinding.hasEvent(InputBinding.SWITCH_IMPLEMENT) then
288 self:selectNextSelectableImplement();
289 end;
290
291 if InputBinding.hasEvent(InputBinding.TOGGLE_TURNSIGNAL_HAZARD) then
292 local state = Vehicle.TURNSIGNAL_OFF;
293 if self.turnSignalState ~= Vehicle.TURNSIGNAL_HAZARD then
294 state = Vehicle.TURNSIGNAL_HAZARD;
295 end;
296 self:setTurnSignalState(state);
297 end;
298 if InputBinding.hasEvent(InputBinding.TOGGLE_TURNSIGNAL_LEFT) then
299 local state = Vehicle.TURNSIGNAL_OFF;
300 if self.turnSignalState ~= Vehicle.TURNSIGNAL_LEFT then
301 state = Vehicle.TURNSIGNAL_LEFT;
302 end;
303 self:setTurnSignalState(state);
304 end;
305 if InputBinding.hasEvent(InputBinding.TOGGLE_TURNSIGNAL_RIGHT) then
306 local state = Vehicle.TURNSIGNAL_OFF;
307 if self.turnSignalState ~= Vehicle.TURNSIGNAL_RIGHT then
308 state = Vehicle.TURNSIGNAL_RIGHT;
309 end;
310 self:setTurnSignalState(state);
311 end;
312
313 if InputBinding.hasEvent(InputBinding.TOGGLE_BEACON_LIGHTS) then
314 self:setBeaconLightsVisibility(not self.beaconLightsActive);
315 end;
316
317 end;
318
319 local turnSignalRepetitionCount = math.floor((getShaderTimeSec()*7 + math.acos(-0.2)) / (math.pi*2));
320 if self.turnSignalRepetitionCount ~= nil and turnSignalRepetitionCount ~= self.turnSignalRepetitionCount then
321 if self.turnSignalState > Vehicle.TURNSIGNAL_OFF then
322 Utils.playSample(self.sampleTurnSignal, 1, 0, nil);
323 end;
324 end
325 self.turnSignalRepetitionCount = turnSignalRepetitionCount;
326
327 end;
328end;
329
330function Drivable:updateTick(dt)
331 if self:getIsActive() then
332 local xt,yt,zt = getTranslation(self.components[1].node);
333 local deltaWater = yt-g_currentMission.waterY+2.5;
334 if deltaWater < 0 then
335 self.isBroken = true;
336 g_currentMission:onSunkVehicle(self);
337
338 if self.isEntered then
339 g_currentMission:onLeaveVehicle();
340
341 if self:getIsActiveForSound() then
342 local volume = math.min(1, self:getLastSpeed()/30);
343 if self.waterSplashSample == nil then
344 self.waterSplashSample = createSample("waterSplashSample");
345 loadSample(self.waterSplashSample, "data/maps/sounds/waterSplash.wav", false);
346 end;
347 playSample(self.waterSplashSample, 1, volume, 0);
348 end;
349 end;
350 end;
351 self.showWaterWarning = deltaWater < 2;
352
353 if self.attacherJointLowerCombo ~= nil and self.attacherJointLowerCombo.isRunning then
354 for k, joint in pairs(self.attacherJointLowerCombo.joints) do
355 if self.attacherJointLowerCombo.direction == 1 and self.attacherJointLowerCombo.currentTime >= joint.t then
356 self:lowerImplementByJointIndex(joint.jointIndex, true);
357 elseif self.attacherJointLowerCombo.direction == -1 and self.attacherJointLowerCombo.currentTime <= self.attacherJointLowerCombo.duration-joint.t then
358 self:lowerImplementByJointIndex(joint.jointIndex, false);
359 end;
360 end;
361
362 if (self.attacherJointLowerCombo.direction == -1 and self.attacherJointLowerCombo.currentTime == 0) or
363 (self.attacherJointLowerCombo.direction == 1 and self.attacherJointLowerCombo.currentTime == self.attacherJointLowerCombo.duration) then
364 self.attacherJointLowerCombo.isRunning = false;
365 end;
366
367 self.attacherJointLowerCombo.currentTime = Utils.clamp(self.attacherJointLowerCombo.currentTime + dt*self.attacherJointLowerCombo.direction, 0, self.attacherJointLowerCombo.duration);
368 end;
369
370 -- lock max speed to working tool
371 local speed,_ = self:getSpeedLimit(true);
372 if self.cruiseControl.state == Drivable.CRUISECONTROL_STATE_ACTIVE then
373 speed = math.min(speed, self.cruiseControl.speed);
374 end;
375 self.motor:setSpeedLimit(speed); --math.min(self.cruiseControl.tempSpeed, speed));
376 end;
377
378 if self.isEntered and self.isClient then
379 local axisForward = InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE);
380 if InputBinding.isAxisZero(axisForward) then
381 self.axisForward = InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE)
382 if not InputBinding.isAxisZero(self.axisForward) then
383 self.axisForwardIsAnalog = true;
384 end
385 self.lastDigitalForward = 0;
386 if math.abs(self.axisForward) > 0.1 and g_gui.currentGuiName ~= "ChatDialog" then
387 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF);
388 end;
389 else
390 self.axisForward = Utils.clamp(self.lastDigitalForward + dt/self.axisSmoothTime*axisForward, -1, 1);
391 self.axisForwardIsAnalog = false;
392 self.lastDigitalForward = self.axisForward;
393 if g_gui.currentGuiName ~= "ChatDialog" then
394 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF);
395 end;
396 end;
397
398 self.axisSide = InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_SIDE_VEHICLE);
399 if InputBinding.isAxisZero(self.axisSide) then
400 self.axisSide = InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_SIDE_VEHICLE)
401 if not InputBinding.isAxisZero(self.axisSide) then
402 self.axisSideIsAnalog = true;
403 end
404 else
405 self.axisSideIsAnalog = false;
406 end;
407
408 if not self:getIsActiveForInput(false) then
409 if not self.axisSideIsAnalog then
410 self.axisSide = 0;
411 end
412 if not self.axisForwardIsAnalog then
413 self.axisForward = 0;
414 end
415
416 if self.steeringEnabled then
417 if g_gui.currentGui ~= nil and g_gui.currentGuiName ~= "ChatDialog" then
418 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF);
419 end;
420 end;
421 end
422
423 if g_isServerStreamingVersion then self.axisSide = self.axisSide * 0.5; end; -- This is the factor to slow down the steering
424
425 if self.isServer then
426 if self.steeringEnabled then
427 Drivable.updateVehiclePhysics(self, self.axisForward, self.axisForwardIsAnalog, self.axisSide, self.axisSideIsAnalog, dt);
428 end;
429 else
430 self:raiseDirtyFlags(self.drivableGroundFlag);
431 end;
432 end;
433end;
434
435function Drivable:draw()
436
437 if not self.isEntered then
438 return;
439 end;
440
441 g_currentMission:drawVehicleHud(self);
442
443 setTextAlignment(RenderText.ALIGN_LEFT);
444 setTextBold(false);
445
446 if self.showWaterWarning then
447 g_currentMission:showBlinkingWarning(g_i18n:getText("Dont_drive_to_depth_into_the_water"), 2000);
448 end;
449
450 if GS_IS_CONSOLE_VERSION then
451 if #self.beaconLights > 0 then
452 g_currentMission:addHelpButtonText(g_i18n:getText("TOGGLE_BEACON_LIGHTS"), InputBinding.TOGGLE_BEACON_LIGHTS);
453 end;
454 g_currentMission:addHelpButtonText(g_i18n:getText("TOGGLE_CRUISE_CONTROL"), InputBinding.TOGGLE_CRUISE_CONTROL);
455 end;
456
457 if self == g_currentMission.controlledVehicle then
458 if g_currentMission.trailerInTipRange ~= nil then
459 g_currentMission:enableHudIcon("tip", 4);
460 g_currentMission:addHelpButtonText(g_currentMission.trailerInTipRange.tipText, InputBinding.ATTACH);
461 end;
462
463 -- enable attachment icon if needed
464 if (g_currentMission.attachableInMountRange ~= nil and g_currentMission.attachableInMountRangeVehicle.attacherJoints[g_currentMission.attachableInMountRangeIndex].jointIndex == 0) then
465 g_currentMission:enableHudIcon("attach", 3);
466 g_currentMission:addHelpButtonText(g_i18n:getText("Attach"), InputBinding.ATTACH);
467 else
468 -- if something is detachable is attached, show button help
469 if g_currentMission.trailerInTipRange == nil and self:detachingIsPossible() then
470 g_currentMission:addHelpButtonText(g_i18n:getText("Detach"), InputBinding.ATTACH);
471 end;
472 end;
473
474 if self.selectedImplement ~= nil and self.selectedImplement.object ~= nil and self.selectedImplement.object.attacherVehicle ~= nil and not self.isHired then
475 local object = self.selectedImplement.object;
476 local jointDesc = object.attacherVehicle.attacherJoints[self.selectedImplement.jointDescIndex];
477
478 if object.attacherJoint.allowsLowering and jointDesc.allowsLowering then
479 if jointDesc.moveDown then
480 g_currentMission:addHelpButtonText(string.format(g_i18n:getText("lift_OBJECT"), object.typeDesc), InputBinding.LOWER_IMPLEMENT);
481 else -- if object.needsLowering then
482 g_currentMission:addHelpButtonText(string.format(g_i18n:getText("lower_OBJECT"), object.typeDesc), InputBinding.LOWER_IMPLEMENT);
483 end;
484 end;
485 end;
486 end;
487
488
489 -- new in console version: show common commands (toggle lights, honk, etc) in button help
490 if not self.isHired then
491 local numDirectImplements = table.getn(self.attachedImplements);
492 local hasMoreThan1Selectable = (numDirectImplements > 1) or (self:getIsSelectable() and numDirectImplements > 0);
493 if not hasMoreThan1Selectable then
494 for _, implement in pairs(self.attachedImplements) do
495 if implement.object ~= nil and table.getn(implement.object.attachedImplements) > 0 then
496 hasMoreThan1Selectable = true;
497 break;
498 end
499 end
500 end
501
502 if hasMoreThan1Selectable then
503 g_currentMission:addHelpButtonText(g_i18n:getText("Change_tools"), InputBinding.SWITCH_IMPLEMENT);
504 end;
505 end;
506end;
507
508function Drivable:onEnter(isControlling)
509 self:startMotor(true);
510 self:onActivateAttachments();
511
512 if self.mirrorAvailable and self.cameras[self.camIndex].useMirror then
513 self:setMirrorVisible(true);
514 end;
515end;
516
517function Drivable:onLeave()
518 self:setBrakeLightsVisibility(false);
519 self:setTurnSignalState(Vehicle.TURNSIGNAL_OFF);
520 self:setReverseLightsVisibility(false);
521
522 self:setBeaconLightsVisibility(false, true);
523
524 if self.deactivateOnLeave then
525 if self.isServer then
526 if next(self.differentials) ~= nil and self.motorizedNode ~= nil then
527 setVehicleProps(self.motorizedNode, 0.0, 0.0, 0.0, self.motor.maxClutchTorque);
528 end
529 for _,wheel in pairs(self.wheels) do
530 setWheelShapeProps(wheel.node, wheel.wheelShape, 0, self.motor.brakeForce, 0);
531 end;
532 end;
533 self:onDeactivate();
534 self:onDeactivateSounds();
535 else
536 if self.deactivateLightsOnLeave then
537 self:onDeactivateAttachmentsLights();
538 end;
539 self:onDeactivateSounds();
540 end;
541
542 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF);
543
544 if self.mirrorAvailable then
545 self:setMirrorVisible(false);
546 end;
547end;
548
549function Drivable:setCruiseControlState(state, noEventSend)
550 if self.cruiseControl.state ~= state then
551 self.cruiseControl.state = state;
552 --[[
553 if self.cruiseControl.state ~= Drivable.CRUISECONTROL_STATE_OFF then
554 if self.cruiseControl.state == Drivable.CRUISECONTROL_STATE_ACTIVE then
555 self.cruiseControl.tempSpeed = self.cruiseControl.speed;
556 else
557 self.cruiseControl.tempSpeed = self.cruiseControl.maxSpeed;
558 end
559 else
560 self.cruiseControl.tempSpeed = math.huge;
561 end
562 ]]--
563 if not self.isServer and (noEventSend == nil or not noEventSend) then
564 g_client:getServerConnection():sendEvent(SetCruiseControlStateEvent:new(self, state));
565 end
566 end
567end
568
569function Drivable:setCruiseControlMaxSpeed(speed)
570 if speed ~= nil then
571 speed = Utils.clamp(speed, self.cruiseControl.minSpeed, self.cruiseControl.maxSpeed);
572 if self.cruiseControl.speed ~= speed then
573 self.cruiseControl.speed = speed;
574 --self.cruiseControl.tempSpeed = speed;
575 if self.cruiseControl.state == Drivable.CRUISECONTROL_STATE_FULL then
576 self.cruiseControl.state = Drivable.CRUISECONTROL_STATE_ACTIVE;
577 end;
578 end;
579
580 if self.cruiseControl.state ~= Drivable.CRUISECONTROL_STATE_OFF then
581 if self.cruiseControl.state == Drivable.CRUISECONTROL_STATE_ACTIVE then
582 self.motor:setSpeedLimit(self.cruiseControl.speed);
583 else
584 self.motor:setSpeedLimit(math.huge);
585 end;
586 end;
587 end;
588
589end;
590
591function Drivable:getRpmLimit(superFunc)
592 if superFunc ~= nil then
593 return superFunc(self);
594 end;
595 return math.huge;
596end;
597
598function Drivable:getDirtMultiplier(superFunc)
599 local multiplier = 0;
600 if superFunc ~= nil then
601 multiplier = multiplier + superFunc(self);
602 end;
603
604 --[[
605 for _, implement in pairs(self.attachedImplements) do
606 if implement.object.getDirtMultiplier ~= nil then
607 multiplier = math.max(multiplier, implement.object:getDirtMultiplier());
608 end;
609 end;
610 ]]--
611
612 return multiplier;
613end;
614
615function Drivable:setMirrorVisible(visible)
616 for _, mirror in pairs(self.mirrors) do
617 setVisibility(mirror, visible);
618 end;
619end;
620
621function Drivable:stopMotor(noEventSend)
622 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF, true);
623end
624
625function Drivable:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
626 local maxSpeed = getXMLInt(xmlFile, key.."#cruiseControl");
627 self:setCruiseControlMaxSpeed(maxSpeed);
628
629 local dir = getXMLInt(xmlFile, key.."#attacherJointComboDir");
630 if dir ~= nil then
631 self.attacherJointLowerCombo.direction = dir;
632 if dir == 1 then
633 self.attacherJointLowerCombo.currentTime = self.attacherJointLowerCombo.duration;
634 end;
635 end;
636 local operatingTime = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#operatingTime"), self.operatingTime) * 1000;
637 self:addOperatingTime(operatingTime);
638
639 return BaseMission.VEHICLE_LOAD_OK;
640end;
641
642function Drivable:getSaveAttributesAndNodes(nodeIdent)
643 local attributes = 'cruiseControl="'..tostring(self.cruiseControl.speed)..'" operatingTime="' .. tostring((self.operatingTime / 1000)) ..'"';
644
645 if self.attacherJointLowerCombo ~= nil then
646 attributes = attributes .. ' attacherJointComboDir="'..tostring(self.attacherJointLowerCombo.direction)..'"';
647 end;
648
649 local nodes = "";
650
651 return attributes, nodes;
652end;
653
654function Drivable.updateVehiclePhysics(self, axisForward, axisForwardIsAnalog, axisSide, axisSideIsAnalog, dt)
655
656 axisForward = self.reverserDirection * axisForward;
657 axisSide = self.reverserDirection * axisSide;
658
659 local acceleration = 0;
660 if self.isMotorStarted and self.motorStartTime <= g_currentMission.time then
661 acceleration = -axisForward;
662 if math.abs(acceleration) > 0.8 then
663 self:setCruiseControlState(Drivable.CRUISECONTROL_STATE_OFF, true);
664 end;
665 if self.cruiseControl.state ~= Drivable.CRUISECONTROL_STATE_OFF then
666 acceleration = self.reverserDirection * 1.0;
667 end
668 end;
669 if self.fuelFillLevel == 0 then
670 acceleration = 0;
671 end;
672
673 local inputAxisX = axisSide;
674 if axisSideIsAnalog then
675 local targetRotatedTime = 0;
676 if inputAxisX < 0 then
677 -- 0 to maxRotTime
678 targetRotatedTime = math.min(-self.maxRotTime*inputAxisX, self.maxRotTime);
679 else
680 -- 0 to minRotTime
681 targetRotatedTime = math.max(self.minRotTime*inputAxisX, self.minRotTime);
682 end;
683 local maxTime = self.maxRotatedTimeSpeed*dt;
684 if math.abs(targetRotatedTime-self.rotatedTime) > maxTime then
685 if targetRotatedTime > self.rotatedTime then
686 self.rotatedTime = self.rotatedTime + maxTime;
687 else
688 self.rotatedTime = self.rotatedTime - maxTime;
689 end;
690 else
691 self.rotatedTime = targetRotatedTime;
692 end;
693 else
694 local rotScale = math.min(1.0/(self.lastSpeed*self.speedRotScale+self.speedRotScaleOffset), 1);
695 if inputAxisX < 0 then
696 self.rotatedTime = math.min(self.rotatedTime - dt*0.001*inputAxisX*rotScale, self.maxRotTime);
697 elseif inputAxisX > 0 then
698 self.rotatedTime = math.max(self.rotatedTime - dt*0.001*inputAxisX*rotScale, self.minRotTime);
699 else
700 if self.autoRotateBackSpeed ~= 0 then
701 if self.rotatedTime > 0 then
702 self.rotatedTime = math.max(self.rotatedTime - dt*0.001*self.autoRotateBackSpeed*rotScale, 0);
703 else
704 self.rotatedTime = math.min(self.rotatedTime + dt*0.001*self.autoRotateBackSpeed*rotScale, 0);
705 end;
706 end;
707 end;
708 end;
709
710 if self.firstTimeRun then
711 self.motor.rpmLimit = self:getRpmLimit();
712 WheelsUtil.updateWheelsPhysics(self, dt, self.lastSpeedReal, acceleration, false, self.requiredDriveMode)
713 end;
714end;
715
716function Drivable:toggleLowerAllImplements(noEventSend)
717 if self.attacherJointLowerCombo ~= nil then
718 DrivableToggleLowerAllEvent.sendEvent(self, noEventSend);
719 self.attacherJointLowerCombo.direction = self.attacherJointLowerCombo.direction * -1;
720 self.attacherJointLowerCombo.isRunning = true;
721 end;
722end;
723
724function Drivable:lowerImplementByJointIndex(jointDescIndex, doLowering)
725 local implementIndex = self:getImplementIndexByJointDescIndex(jointDescIndex);
726 if implementIndex ~= nil then
727 local implement = self.attachedImplements[implementIndex];
728 if implement ~= nil then
729 implement.object:onLowerAll(doLowering, jointDescIndex);
730 end;
731 end;
732end;
733
734function Drivable:addOperatingTime(addTime)
735 local t = math.max(Utils.getNoNil(addTime, 0), 0);
736 self.operatingTime = self.operatingTime + t;
737
738 if self.operatingTime > self.maxOperatingTime then
739 self.operatingTime = 0;
740 end;
741end;
742
743function Drivable:developmentReloadFromXML(xmlFile)
744 Drivable.loadSettingsFromXML(self, xmlFile);
745end;
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