Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
carscript.c
Go to the documentation of this file.
7
8enum CarHeadlightBulbsState
9{
13 BOTH
14}
15
16enum CarRearLightType
17{
18 NONE,
21 BRAKES_AND_REVERSE
22}
23
24enum ECarOperationalState
25{
26 OK = 0,
27 RUINED = 1,
31}
32
33enum CarEngineSoundState
34{
35 NONE,
42 STOP_NO_FUEL
43}
44
45enum ECarHornState
46{
47 OFF = 0,
48 SHORT = 1,
49 LONG = 2
50}
51
52#ifdef DIAG_DEVELOPER
53enum EVehicleDebugOutputType
54{
55 NONE,
56 DAMAGE_APPLIED = 1,
57 DAMAGE_CONSIDERED = 2,
58 CONTACT = 4
59 //OTHER = 8
60 //OTHER = 16
61}
62
63class CrashDebugData
64{
65 static ref array<ref CrashDebugData> m_CrashData = new array<ref CrashDebugData>;
66 static ref CrashDebugData m_CrashDataPoint;
67 //data is recorded on server, upon request, sent to the client
68 static void SendData(PlayerBase player)
69 {
70 /*
71 m_CrashData.Clear();
72 CrashDebugData fakeData = new CrashDebugData();
73 fakeData.m_VehicleType = "FakeVehicle";
74 m_CrashData.Insert(fakeData);
75 */
76 GetGame().RPCSingleParam(player, ERPCs.DIAG_VEHICLES_DUMP_CRASH_DATA_CONTENTS, new Param1<array<ref CrashDebugData>>(m_CrashData), true, player.GetIdentity());
77 }
78
79 //this is client requesting to dump the data it previously received from the server
80 static void DumpDataArray(array<ref CrashDebugData> dataArray)
81 {
82 Print("Vehicle; DamageType; Damage; Zone; Momentum; Momentum Prev; Momentum Delta; Speedometer; SpeedWorld; SpeedWorld Prev; SpeedWorld Delta; Velocity; Velocity Prev; Velocity Dot; TimeStamp (ms); CrewDamageBase; ShockTemp; DMGHealth; DMGShock");
83 foreach (CrashDebugData data:dataArray)
84 {
85 DumpData(data);
86 }
87 }
88
89 static void DumpData(CrashDebugData data)
90 {
91 string output = data.m_VehicleType+";"+data.m_DamageType+";"+data.m_Damage+";"+data.m_Zone+";"+data.m_MomentumCurr+";"+data.m_MomentumPrev+";"+data.m_MomentumDelta+";"+data.m_Speedometer;
92 output += ";"+data.m_SpeedWorld+";"+data.m_SpeedWorldPrev+";"+data.m_SpeedWorldDelta+";"+data.m_VelocityCur;
93 output += ";"+data.m_VelocityPrev+";"+data.m_VelocityDot+";"+data.m_Time+";"+data.m_CrewDamageBase+";"+data.m_ShockTemp+";"+data.m_DMGHealth+";"+data.m_DMGShock;
94 Print(output);
95 }
96
97 string m_VehicleType;
98 string m_DamageType;
99 float m_Damage;
100 string m_Zone;
101 float m_MomentumCurr;
102 float m_MomentumPrev;
103 float m_MomentumDelta;
104 float m_Speedometer;
105 float m_SpeedWorld;
106 float m_SpeedWorldPrev;
107 float m_SpeedWorldDelta;
108 vector m_VelocityCur;
109 vector m_VelocityPrev;
110 float m_VelocityDot;
111 float m_Time;
112 float m_CrewDamageBase;
113 float m_ShockTemp;
114 float m_DMGHealth;
115 float m_DMGShock;
116}
117
118#endif
119class CarContactData
120{
121 vector localPos;
122 IEntity other;
123 float impulse;
124
125 void CarContactData(vector _localPos, IEntity _other, float _impulse)
126 {
127 localPos = _localPos;
128 other = _other;
129 impulse = _impulse;
130 }
131}
132
134
135class CarScriptOwnerState : CarOwnerState
136{
137 float m_fTime;
138
139 protected override event void Write(PawnStateWriter ctx)
140 {
141 ctx.Write(m_fTime);
142 }
143
144 protected override event void Read(PawnStateReader ctx)
145 {
146 ctx.Read(m_fTime);
147 }
148};
149
151{
152};
153
154#ifdef DIAG_DEVELOPER
155CarScript _car;
156#endif
157
161class CarScript extends Car
162{
163 #ifdef DIAG_DEVELOPER
164 static EVehicleDebugOutputType DEBUG_OUTPUT_TYPE;
165 bool m_ContactCalled;
166 #endif
170 protected float m_MomentumPrevTick;
172 ref CarContactCache m_ContactCache;
173
174 protected float m_Time;
175
176 static float DROWN_ENGINE_THRESHOLD = 0.5;
177 static float DROWN_ENGINE_DAMAGE = 350.0;
178
179 static const string MEMORY_POINT_NAME_CAR_HORN = "pos_carHorn";
180
182 protected float m_FuelAmmount;
183 protected float m_CoolantAmmount;
184 protected float m_OilAmmount;
185 protected float m_BrakeAmmount;
186
188 //protected float m_dmgContactCoef = 0.023;
189 protected float m_dmgContactCoef = 0.058;
191
193 protected float m_DrownTime;
195
197 protected float m_EngineHealth;
198 protected float m_RadiatorHealth;
199 protected float m_FuelTankHealth;
200 protected float m_BatteryHealth;
201 protected float m_PlugHealth;
202
204
205 protected float m_BatteryConsume = 15; //Battery energy consumption upon engine start
206 protected float m_BatteryContinuousConsume = 0.25; //Battery consumption with lights on and engine is off
207 protected float m_BatteryRecharge = 0.15; //Battery recharge rate when engine is on
208 private float m_BatteryTimer = 0; //Used to factor energy consumption / recharging
209 private const float BATTERY_UPDATE_DELAY = 100;
210
215
216 protected int m_enginePtcFx;
217 protected int m_coolantPtcFx;
218 protected int m_exhaustPtcFx;
219
224
227 protected vector m_backPos;
232
234 string m_EngineStartOK = "";
235 string m_EngineStartBattery = "";
236 string m_EngineStartPlug = "";
237 string m_EngineStartFuel = "";
238 string m_EngineStop = "";
239 string m_EngineStopFuel = "";
240
241 string m_CarDoorOpenSound = "";
242 string m_CarDoorCloseSound = "";
243 string m_CarSeatShiftInSound = "";
244 string m_CarSeatShiftOutSound = "";
245
246 string m_CarHornShortSoundName = "";
247 string m_CarHornLongSoundName = "";
248
253 private ref EffectSound m_PreStartSound;
254
256 protected ref NoiseParams m_NoisePar;
258
259 protected bool m_PlayCrashSoundLight;
260 protected bool m_PlayCrashSoundHeavy;
261
262 protected bool m_HeadlightsOn;
263 protected bool m_HeadlightsState;
264 protected bool m_BrakesArePressed;
265 protected bool m_RearLightType;
266
267 protected bool m_ForceUpdateLights;
268 protected bool m_EngineStarted;
269 protected bool m_EngineDestroyed;
270
271 protected int m_CarHornState;
272
275
276 // Memory points
277 static string m_ReverseLightPoint = "light_reverse";
278 static string m_LeftHeadlightPoint = "light_left";
279 static string m_RightHeadlightPoint = "light_right";
280 static string m_LeftHeadlightTargetPoint = "light_left_dir";
281 static string m_RightHeadlightTargetPoint = "light_right_dir";
282 static string m_DrownEnginePoint = "drown_engine";
283
284 // Model selection IDs for texture/material changes
285 // If each car needs different IDs, then feel free to remove the 'static' flag and overwrite these numbers down the hierarchy
286 static const int SELECTION_ID_FRONT_LIGHT_L = 0;
287 static const int SELECTION_ID_FRONT_LIGHT_R = 1;
288 static const int SELECTION_ID_BRAKE_LIGHT_L = 2;
289 static const int SELECTION_ID_BRAKE_LIGHT_R = 3;
290 static const int SELECTION_ID_REVERSE_LIGHT_L = 4;
291 static const int SELECTION_ID_REVERSE_LIGHT_R = 5;
292 static const int SELECTION_ID_TAIL_LIGHT_L = 6;
293 static const int SELECTION_ID_TAIL_LIGHT_R = 7;
294 static const int SELECTION_ID_DASHBOARD_LIGHT = 8;
295
298
301
302 #ifdef DEVELOPER
303 private const int DEBUG_MESSAGE_CLEAN_TIME_SECONDS = 10;
304 private float m_DebugMessageCleanTime;
305 private string m_DebugContactDamageMessage;
306 #endif
307
309 {
310#ifdef DIAG_DEVELOPER
311 _car = this;
312#endif
313
314 SetEventMask(EntityEvent.POSTSIMULATE);
315 SetEventMask(EntityEvent.POSTFRAME);
316
317 m_ContactCache = new CarContactCache;
318
319 m_Time = 0;
320 // sets max health for all components at init
321 m_EngineHealth = 1;
322 m_FuelTankHealth = 1;
323 m_RadiatorHealth = -1;
324 m_BatteryHealth = -1;
325 m_PlugHealth = -1;
326
327 m_enginePtcFx = -1;
328 m_coolantPtcFx = -1;
329 m_exhaustPtcFx = -1;
330
331 m_EnviroHeatComfortOverride = 0;
332
333 m_PlayCrashSoundLight = false;
334 m_PlayCrashSoundHeavy = false;
335
336 m_CarHornState = ECarHornState.OFF;
337 m_CarEngineSoundState = CarEngineSoundState.NONE;
338
339 RegisterNetSyncVariableBool("m_HeadlightsOn");
340 RegisterNetSyncVariableBool("m_BrakesArePressed");
341 RegisterNetSyncVariableBool("m_ForceUpdateLights");
342 RegisterNetSyncVariableBoolSignal("m_PlayCrashSoundLight");
343 RegisterNetSyncVariableBoolSignal("m_PlayCrashSoundHeavy");
344 RegisterNetSyncVariableInt("m_CarHornState", ECarHornState.OFF, ECarHornState.LONG);
345 RegisterNetSyncVariableInt("m_CarEngineSoundState", CarEngineSoundState.NONE, CarEngineSoundState.STOP_NO_FUEL);
346
347 if ( MemoryPointExists("ptcExhaust_end") )
348 {
349 m_exhaustPtcPos = GetMemoryPointPos("ptcExhaust_end");
350 if ( MemoryPointExists("ptcExhaust_start") )
351 {
352 vector exhaustStart = GetMemoryPointPos("ptcExhaust_start");
353 vector tempOri = vector.Direction( exhaustStart, m_exhaustPtcPos);
354
355 m_exhaustPtcDir[0] = -tempOri[2];
356 m_exhaustPtcDir[1] = tempOri[1];
357 m_exhaustPtcDir[2] = tempOri[0];
358
359 m_exhaustPtcDir = m_exhaustPtcDir.Normalized().VectorToAngles();
360 }
361 }
362 else
363 {
364 m_exhaustPtcPos = "0 0 0";
365 m_exhaustPtcDir = "1 1 1";
366 }
367
368 if ( MemoryPointExists("ptcEnginePos") )
369 m_enginePtcPos = GetMemoryPointPos("ptcEnginePos");
370 else
371 m_enginePtcPos = "0 0 0";
372
373 if ( MemoryPointExists("ptcCoolantPos") )
374 m_coolantPtcPos = GetMemoryPointPos("ptcCoolantPos");
375 else
376 m_coolantPtcPos = "0 0 0";
377
378 if ( MemoryPointExists("drown_engine") )
379 m_DrownEnginePos = GetMemoryPointPos("drown_engine");
380 else
381 m_DrownEnginePos = "0 0 0";
382
383 if ( MemoryPointExists("dmgZone_engine") )
384 m_enginePos = GetMemoryPointPos("dmgZone_engine");
385 else
386 m_enginePos = "0 0 0";
387
388 if ( MemoryPointExists("dmgZone_front") )
389 m_frontPos = GetMemoryPointPos("dmgZone_front");
390 else
391 m_frontPos = "0 0 0";
392
393 if ( MemoryPointExists("dmgZone_back") )
394 m_backPos = GetMemoryPointPos("dmgZone_back");
395 else
396 m_backPos = "0 0 0";
397
398 if ( MemoryPointExists("dmgZone_fender_1_1") )
399 m_side_1_1Pos = GetMemoryPointPos("dmgZone_fender_1_1");
400 else
401 m_side_1_1Pos = "0 0 0";
402
403 if ( MemoryPointExists("dmgZone_fender_1_2") )
404 m_side_1_2Pos = GetMemoryPointPos("dmgZone_fender_1_2");
405 else
406 m_side_1_2Pos = "0 0 0";
407
408 if ( MemoryPointExists("dmgZone_fender_2_1") )
409 m_side_2_1Pos = GetMemoryPointPos("dmgZone_fender_2_1");
410 else
411 m_side_2_1Pos = "0 0 0";
412
413 if ( MemoryPointExists("dmgZone_fender_2_2") )
414 m_side_2_2Pos = GetMemoryPointPos("dmgZone_fender_2_2");
415 else
416 m_side_2_2Pos = "0 0 0";
417
418 if (!GetGame().IsDedicatedServer())
419 {
420 m_WheelSmokeFx = new array<ref EffWheelSmoke>;
421 m_WheelSmokeFx.Resize(WheelCount());
422 m_WheelSmokePtcFx = new array<int>;
423 m_WheelSmokePtcFx.Resize(WheelCount());
424 for (int i = 0; i < m_WheelSmokePtcFx.Count(); i++)
425 {
426 m_WheelSmokePtcFx.Set(i, -1);
427 }
428 }
429 }
430
431 override void EEInit()
432 {
433 super.EEInit();
434
435 if (GetGame().IsServer())
436 {
437 m_NoiseSystem = GetGame().GetNoiseSystem();
438 if (m_NoiseSystem && !m_NoisePar)
439 {
440 m_NoisePar = new NoiseParams();
441 m_NoisePar.LoadFromPath("cfgVehicles " + GetType() + " NoiseCarHorn");
442 }
443 }
444 }
445
446 #ifdef DIAG_DEVELOPER
447
448 override void FixEntity()
449 {
450 if (GetGame().IsServer())
451 {
452 FillUpCarFluids();
453 //server and single
454
455 for (int i = 5; i > 0; i--)//there is a problem with wheels when performed only once, this solves it
456 super.FixEntity();
457 if (!GetGame().IsMultiplayer())
458 {
459 //single
460 SEffectManager.DestroyEffect(m_engineFx);
461 }
462 }
463 else
464 {
465 //MP client
466 SEffectManager.DestroyEffect(m_engineFx);
467 }
468 }
469 #endif
470
471 override string GetVehicleType()
472 {
473 return "VehicleTypeCar";
474 }
475
477 {
478 return ModelToWorld( m_DrownEnginePos );
479 }
480
482 {
483 return ModelToWorld( m_coolantPtcPos );
484 }
485
487 {
488 return ModelToWorld( m_enginePos );
489 }
491 {
492 return ModelToWorld( m_frontPos );
493 }
495 {
496 return ModelToWorld( m_backPos );
497 }
499 {
500 return ModelToWorld( m_side_1_1Pos );
501 }
503 {
504 return ModelToWorld( m_side_1_2Pos );
505 }
507 {
508 return ModelToWorld( m_side_2_1Pos );
509 }
511 {
512 return ModelToWorld( m_side_2_2Pos );
513 }
514
515 override float GetLiquidThroughputCoef()
516 {
518 }
519
520 //here we should handle the damage dealt in OnContact event, but maybe we will react even in that event
521 override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
522 {
523 super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
524
525 ForceUpdateLightsStart();
526 GetGame().GetCallQueue(CALL_CATEGORY_GAMEPLAY).CallLater(ForceUpdateLightsEnd, 100, false);
527 }
528
529 override void EEDelete(EntityAI parent)
530 {
531 #ifndef SERVER
532 CleanupEffects();
533 #endif
534 }
535
537 {
538 #ifndef SERVER
539 CleanupEffects();
540 #endif
541 }
542
544 {
545 for (int i = 0; i < m_WheelSmokeFx.Count(); i++ )
546 {
547 Effect ps = m_WheelSmokeFx.Get(i);
548 if (ps)
549 {
551 }
552 }
553
554 m_WheelSmokeFx.Clear();
555 m_WheelSmokePtcFx.Clear();
556
557 SEffectManager.DestroyEffect(m_coolantFx);
558 SEffectManager.DestroyEffect(m_exhaustFx);
559 SEffectManager.DestroyEffect(m_engineFx);
560
561 if (m_Headlight)
562 m_Headlight.Destroy();
563
564 if (m_RearLight)
565 m_RearLight.Destroy();
566
567 SEffectManager.DestroyEffect(m_CrashSoundLight);
568 SEffectManager.DestroyEffect(m_CrashSoundHeavy);
569 SEffectManager.DestroyEffect(m_WindowSmall);
570 SEffectManager.DestroyEffect(m_WindowLarge);
571 CleanupSound(m_CarHornSoundEffect);
572 }
573
575 {
577 }
578
579 override void GetDebugActions(out TSelectableActionInfoArrayEx outputList)
580 {
581 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_HORN_START_SHORT, "Car Horn Start Short", FadeColors.LIGHT_GREY));
582 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_HORN_START_LONG, "Car Horn Start Long", FadeColors.LIGHT_GREY));
583 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_HORN_STOP, "Car Horn Stop", FadeColors.LIGHT_GREY));
584 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
585
586 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "Car Fuel", FadeColors.RED));
587 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_FUEL_FULL, "Full", FadeColors.LIGHT_GREY));
588 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_FUEL_EMPTY, "Empty", FadeColors.LIGHT_GREY));
589 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_FUEL_INCREASE, "10% increase", FadeColors.LIGHT_GREY));
590 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_FUEL_DECREASE, "10% decrease", FadeColors.LIGHT_GREY));
591 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
592
593 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "Car Cooler", FadeColors.RED));
594 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_COOLANT_FULL, "Full", FadeColors.LIGHT_GREY));
595 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_COOLANT_EMPTY, "Empty", FadeColors.LIGHT_GREY));
596 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_COOLANT_INCREASE, "10% increase", FadeColors.LIGHT_GREY));
597 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.CAR_COOLANT_DECREASE, "10% decrease", FadeColors.LIGHT_GREY));
598 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
599
600 super.GetDebugActions(outputList);
601 }
602
603 override bool OnAction(int action_id, Man player, ParamsReadContext ctx)
604 {
605 if (super.OnAction(action_id, player, ctx))
606 return true;
607
608 if (!GetGame().IsServer())
609 {
610 return false;
611 }
612
613 switch (action_id)
614 {
615 case EActions.CAR_HORN_START_SHORT:
616 SetCarHornState(ECarHornState.SHORT);
617 return true;
618 case EActions.CAR_HORN_START_LONG:
619 SetCarHornState(ECarHornState.LONG);
620 return true;
621 case EActions.CAR_HORN_STOP:
622 SetCarHornState(ECarHornState.OFF);
623 return true;
624
625 case EActions.CAR_FUEL_FULL:
626 Fill(CarFluid.FUEL, GetFluidCapacity(CarFluid.FUEL));
627 return true;
628 case EActions.CAR_FUEL_EMPTY:
629 LeakAll(CarFluid.FUEL);
630 return true;
631 case EActions.CAR_FUEL_INCREASE:
632 Fill(CarFluid.FUEL, GetFluidCapacity(CarFluid.FUEL) * 0.1);
633 return true;
634 case EActions.CAR_FUEL_DECREASE:
635 Leak(CarFluid.FUEL, GetFluidCapacity(CarFluid.FUEL) * 0.1);
636 return true;
637
638 case EActions.CAR_COOLANT_FULL:
639 Fill(CarFluid.COOLANT, GetFluidCapacity(CarFluid.COOLANT));
640 return true;
641 case EActions.CAR_COOLANT_EMPTY:
642 LeakAll(CarFluid.COOLANT);
643 return true;
644 case EActions.CAR_COOLANT_INCREASE:
645 Fill(CarFluid.COOLANT, GetFluidCapacity(CarFluid.COOLANT) * 0.1);
646 return true;
647 case EActions.CAR_COOLANT_DECREASE:
648 Leak(CarFluid.COOLANT, GetFluidCapacity(CarFluid.COOLANT) * 0.1);
649 return true;
650 }
651
652 return false;
653 }
654
656 {
657 super.OnVariablesSynchronized();
658
659 if (GetCrashHeavySound())
660 {
661 PlayCrashHeavySound();
662 }
663 else if (GetCrashLightSound())
664 {
665 PlayCrashLightSound();
666 }
667
668 HandleCarHornSound(m_CarHornState);
669
670 if (!IsOwner() && m_CarEngineSoundState != m_CarEngineLastSoundState)
671 HandleEngineSound(m_CarEngineSoundState);
672
673 UpdateLights();
674 }
675
677 {
678 if ( !SEffectManager.IsEffectExist( m_enginePtcFx ) && GetGame().GetWaterDepth( GetEnginePosWS() ) <= 0 )
679 {
680 m_engineFx = new EffEngineSmoke();
681 m_engineFx.SetParticleStateHeavy();
682 m_enginePtcFx = SEffectManager.PlayOnObject( m_engineFx, this, m_enginePtcPos, Vector(0,0,0));
683 }
684 }
685
686 override void EEItemAttached(EntityAI item, string slot_name)
687 {
688 super.EEItemAttached(item, slot_name);
689
690 switch (slot_name)
691 {
692 case "Reflector_1_1":
693 if (GetGame().IsServer())
694 {
695 SetHealth("Reflector_1_1", "Health", item.GetHealth());
696 }
697 break;
698 case "Reflector_2_1":
699 if (GetGame().IsServer())
700 {
701 SetHealth("Reflector_2_1", "Health", item.GetHealth());
702 }
703 break;
704 case "CarBattery":
705 case "TruckBattery":
706 if (GetGame().IsServer())
707 {
708 m_BatteryHealth = item.GetHealth01();
709 }
710 break;
711 case "SparkPlug":
712 case "GlowPlug":
713 if (GetGame().IsServer())
714 {
715 m_PlugHealth = item.GetHealth01();
716 }
717 break;
718 case "CarRadiator":
719 if (GetGame().IsServer())
720 {
721 m_RadiatorHealth = item.GetHealth01();
722 }
723
724 m_Radiator = item;
725 break;
726 }
727
728 if (GetGame().IsServer())
729 {
730 Synchronize();
731 }
732
733 UpdateHeadlightState();
734 UpdateLights();
735 }
736
737 // Updates state of attached headlight bulbs for faster access
739 {
740 EntityAI bulb_L = FindAttachmentBySlotName("Reflector_1_1");
741 EntityAI bulb_R = FindAttachmentBySlotName("Reflector_2_1");
742
743 if (bulb_L && !bulb_L.IsRuined() && bulb_R && !bulb_R.IsRuined())
744 {
745 m_HeadlightsState = CarHeadlightBulbsState.BOTH;
746 }
747 else if (bulb_L && !bulb_L.IsRuined())
748 {
749 m_HeadlightsState = CarHeadlightBulbsState.LEFT;
750 }
751 else if (bulb_R && !bulb_R.IsRuined())
752 {
753 m_HeadlightsState = CarHeadlightBulbsState.RIGHT;
754 }
755 else if ((!bulb_L || bulb_L.IsRuined()) && (!bulb_R || bulb_R.IsRuined()))
756 {
757 m_HeadlightsState = CarHeadlightBulbsState.NONE;
758 }
759 }
760
761 override void EEItemDetached(EntityAI item, string slot_name)
762 {
763 switch (slot_name)
764 {
765 case "CarBattery":
766 case "TruckBattery":
767 m_BatteryHealth = -1;
768 if (IsServerOrOwner())
769 {
770 if (EngineIsOn())
771 {
772 EngineStop();
773 }
774 }
775
776 if (GetGame().IsServer())
777 {
778 if (IsScriptedLightsOn())
779 {
780 ToggleHeadlights();
781 }
782
783 UpdateBattery(ItemBase.Cast(item));
784 }
785 break;
786 case "SparkPlug":
787 case "GlowPlug":
788 m_PlugHealth = -1;
789 if (GetGame().IsServer() && EngineIsOn())
790 {
791 EngineStop();
792 }
793 break;
794 case "CarRadiator":
795 m_Radiator = null;
796 if (IsServerOrOwner())
797 {
798 LeakAll(CarFluid.COOLANT);
799 }
800
801 if (GetGame().IsServer())
802 {
803 if (m_DamageZoneMap.Contains("Radiator"))
804 {
805 SetHealth("Radiator", "Health", 0);
806 }
807 }
808 break;
809 }
810
811 if (GetGame().IsServer())
812 {
813 Synchronize();
814 }
815
816 UpdateHeadlightState();
817 UpdateLights();
818 }
819
820 override void OnAttachmentRuined(EntityAI attachment)
821 {
822 super.OnAttachmentRuined(attachment);
823
824 UpdateHeadlightState();
825 UpdateLights();
826 }
827
828 override bool CanReceiveAttachment(EntityAI attachment, int slotId)
829 {
830 if (!super.CanReceiveAttachment(attachment, slotId))
831 return false;
832
833 InventoryLocation attachmentInventoryLocation = new InventoryLocation();
834 attachment.GetInventory().GetCurrentInventoryLocation(attachmentInventoryLocation);
835 if (attachmentInventoryLocation.GetParent() == null)
836 {
837 return true;
838 }
839
840 if (attachment && attachment.Type().IsInherited(CarWheel))
841 {
842 string slotSelectionName;
843 InventorySlots.GetSelectionForSlotId(slotId, slotSelectionName);
844
845 switch (slotSelectionName)
846 {
847 case "wheel_spare_1":
848 case "wheel_spare_2":
849 return CanManipulateSpareWheel(slotSelectionName);
850 break;
851 }
852 }
853
854 return true;
855 }
856
857 override bool CanReleaseAttachment(EntityAI attachment)
858 {
859 if (!super.CanReleaseAttachment(attachment))
860 {
861 return false;
862 }
863
864 if (EngineIsOn() && IsMoving())
865 {
866 return false;
867 }
868
869 if (attachment && attachment.Type().IsInherited(CarWheel))
870 {
871 InventoryLocation attachmentInventoryLocation = new InventoryLocation();
872 attachment.GetInventory().GetCurrentInventoryLocation(attachmentInventoryLocation);
873
874 string slotSelectionName;
875 InventorySlots.GetSelectionForSlotId(attachmentInventoryLocation.GetSlot(), slotSelectionName);
876
877 switch (slotSelectionName)
878 {
879 case "wheel_spare_1":
880 case "wheel_spare_2":
881 return CanManipulateSpareWheel(slotSelectionName);
882 break;
883 }
884 }
885
886 return true;
887 }
888
889 protected bool CanManipulateSpareWheel(string slotSelectionName)
890 {
891 return false;
892 }
893
894 override void EOnPostSimulate(IEntity other, float timeSlice)
895 {
896 m_Time += timeSlice;
897
898 if (GetGame().IsServer())
899 {
900 #ifdef DIAG_DEVELOPER
901 if (DEBUG_OUTPUT_TYPE & EVehicleDebugOutputType.CONTACT)
902 {
903 if (m_ContactCalled)
904 {
905 Debug.Log("Momentum delta: " + (GetMomentum() - m_MomentumPrevTick));
906 Debug.Log("--------------------------------------------------------------------");
907 m_ContactCalled = false;
908 }
909 }
910 #endif
911
912
913 CheckContactCache();
914 m_VelocityPrevTick = GetVelocity(this);
915 m_MomentumPrevTick = GetMomentum();
916 #ifdef DEVELOPER
917 m_DebugMessageCleanTime += timeSlice;
918 if (m_DebugMessageCleanTime >= DEBUG_MESSAGE_CLEAN_TIME_SECONDS)
919 {
920 m_DebugMessageCleanTime = 0;
921 m_DebugContactDamageMessage = "";
922 }
923 #endif
924 }
925
926 if ( m_Time >= GameConstants.CARS_FLUIDS_TICK )
927 {
928 m_Time = 0;
929
930 CarPartsHealthCheck();
931
932 bool isServerOrOwner = IsServerOrOwner();
933
934 //First of all check if the car should stop the engine
935 if (isServerOrOwner && EngineIsOn())
936 {
937 if (IsDamageDestroyed() || GetFluidFraction(CarFluid.FUEL) <= 0 || m_EngineHealth <= 0)
938 EngineStop();
939
940 //CheckVitalItem(IsVitalCarBattery(), CarBattery.SLOT_ID);
941 //CheckVitalItem(IsVitalTruckBattery(), TruckBattery.SLOT_ID);
942 CheckVitalItem(IsVitalSparkPlug(), "SparkPlug");
943 CheckVitalItem(IsVitalGlowPlug(), "GlowPlug");
944 }
945
946 if (GetGame().IsServer())
947 {
948 if (IsVitalFuelTank())
949 {
950 if (m_FuelTankHealth == GameConstants.DAMAGE_RUINED_VALUE && m_EngineHealth > GameConstants.DAMAGE_RUINED_VALUE)
951 {
952 SetHealth("Engine", "Health", GameConstants.DAMAGE_RUINED_VALUE);
953 }
954 }
955 }
956
958 if ( EngineIsOn() )
959 {
960 if ( GetGame().IsServer() )
961 {
962 float dmg;
963
964 if ( EngineGetRPM() >= EngineGetRPMRedline() )
965 {
966 if (EngineGetRPM() > EngineGetRPMMax())
967 AddHealth( "Engine", "Health", -GetMaxHealth("Engine", "") * 0.05 ); //CAR_RPM_DMG
968
969 // only called on server, don't use deterministic RandomFloat
970 dmg = EngineGetRPM() * 0.001 * Math.RandomFloat( 0.02, 1.0 ); //CARS_TICK_DMG_MIN; //CARS_TICK_DMG_MAX
971 ProcessDirectDamage(DamageType.CUSTOM, null, "Engine", "EnviroDmg", vector.Zero, dmg);
972 SetEngineZoneReceivedHit(true);
973 }
974 else
975 {
976 SetEngineZoneReceivedHit(false);
977 }
978 }
979
980 if (isServerOrOwner)
981 {
983 if ( IsVitalRadiator() )
984 {
985 if ( GetFluidFraction(CarFluid.COOLANT) > 0 && m_RadiatorHealth < 0.5 ) //CARS_LEAK_THRESHOLD
986 LeakFluid( CarFluid.COOLANT );
987 }
988
989 if ( GetFluidFraction(CarFluid.FUEL) > 0 && m_FuelTankHealth < GameConstants.DAMAGE_DAMAGED_VALUE )
990 LeakFluid( CarFluid.FUEL );
991
992 if ( GetFluidFraction(CarFluid.BRAKE) > 0 && m_EngineHealth < GameConstants.DAMAGE_DAMAGED_VALUE )
993 LeakFluid( CarFluid.BRAKE );
994
995 if ( GetFluidFraction(CarFluid.OIL) > 0 && m_EngineHealth < GameConstants.DAMAGE_DAMAGED_VALUE )
996 LeakFluid( CarFluid.OIL );
997
998 if ( m_EngineHealth < 0.25 )
999 LeakFluid( CarFluid.OIL );
1000 }
1001
1002 if ( GetGame().IsServer() )
1003 {
1004 if ( IsVitalRadiator() )
1005 {
1006 if ( GetFluidFraction( CarFluid.COOLANT ) < 0.5 && GetFluidFraction( CarFluid.COOLANT ) >= 0 )
1007 {
1008 // only called on server, don't use deterministic RandomFloat
1009 dmg = ( 1 - GetFluidFraction(CarFluid.COOLANT) ) * Math.RandomFloat( 0.02, 10.00 ); //CARS_DMG_TICK_MIN_COOLANT; //CARS_DMG_TICK_MAX_COOLANT
1010 AddHealth( "Engine", "Health", -dmg );
1011 SetEngineZoneReceivedHit(true);
1012 }
1013 }
1014 }
1015
1016 //FX only on Client and in Single
1017 if (!GetGame().IsDedicatedServer())
1018 {
1019 if (!SEffectManager.IsEffectExist(m_exhaustPtcFx))
1020 {
1021 m_exhaustFx = new EffExhaustSmoke();
1022 m_exhaustPtcFx = SEffectManager.PlayOnObject( m_exhaustFx, this, m_exhaustPtcPos, m_exhaustPtcDir );
1023 m_exhaustFx.SetParticleStateLight();
1024 }
1025
1026 if (IsVitalRadiator() && GetFluidFraction(CarFluid.COOLANT) < 0.5)
1027 {
1028 if (!SEffectManager.IsEffectExist(m_coolantPtcFx))
1029 {
1030 m_coolantFx = new EffCoolantSteam();
1031 m_coolantPtcFx = SEffectManager.PlayOnObject(m_coolantFx, this, m_coolantPtcPos, vector.Zero);
1032 }
1033
1034 if (m_coolantFx)
1035 {
1036 if (GetFluidFraction(CarFluid.COOLANT) > 0)
1037 m_coolantFx.SetParticleStateLight();
1038 else
1039 m_coolantFx.SetParticleStateHeavy();
1040 }
1041 }
1042 else
1043 {
1044 if (SEffectManager.IsEffectExist(m_coolantPtcFx))
1045 SEffectManager.Stop(m_coolantPtcFx);
1046 }
1047 }
1048 }
1049 else
1050 {
1051 //FX only on Client and in Single
1052 if ( !GetGame().IsDedicatedServer() )
1053 {
1054 if (SEffectManager.IsEffectExist(m_exhaustPtcFx))
1055 {
1056 SEffectManager.Stop(m_exhaustPtcFx);
1057 m_exhaustPtcFx = -1;
1058 }
1059
1060 if (SEffectManager.IsEffectExist(m_coolantPtcFx))
1061 {
1062 SEffectManager.Stop(m_coolantPtcFx);
1063 m_coolantPtcFx = -1;
1064 }
1065 }
1066 }
1067
1068 }
1069
1070 //FX only on Client and in Single
1071 if ( !GetGame().IsDedicatedServer() )
1072 {
1073 float carSpeed = GetVelocity(this).Length();
1074 for (int i = 0; i < WheelCount(); i++)
1075 {
1076 EffWheelSmoke eff = m_WheelSmokeFx.Get(i);
1077 int ptrEff = m_WheelSmokePtcFx.Get(i);
1078 bool haveParticle = false;
1079
1080 CarWheel wheel = CarWheel.Cast(WheelGetEntity(i));
1081 if (wheel && WheelHasContact(i))
1082 {
1083 float wheelSpeed = WheelGetAngularVelocity(i) * wheel.GetRadius();
1084
1085 vector wheelPos = WheelGetContactPosition(i);
1086 vector wheelVel = dBodyGetVelocityAt(this, wheelPos);
1087
1088 vector transform[3];
1089 transform[2] = WheelGetDirection(i);
1090 transform[1] = vector.Up;
1091 transform[0] = transform[2] * transform[1];
1092
1093 wheelVel = wheelVel.InvMultiply3(transform);
1094
1095 float bodySpeed = wheelVel[2];
1096
1097 bool applyEffect = false;
1098 if ((wheelSpeed > 0 && bodySpeed > 0) || (wheelSpeed < 0 && bodySpeed < 0))
1099 {
1100 applyEffect = Math.AbsFloat(wheelSpeed) > Math.AbsFloat(bodySpeed) + EffWheelSmoke.WHEEL_SMOKE_THRESHOLD;
1101 }
1102 else
1103 {
1104 applyEffect = Math.AbsFloat(wheelSpeed) > EffWheelSmoke.WHEEL_SMOKE_THRESHOLD;
1105 }
1106
1107 if (applyEffect)
1108 {
1109 haveParticle = true;
1110
1111 string surface;
1112 GetGame().SurfaceGetType(wheelPos[0], wheelPos[2], surface);
1113 wheelPos = WorldToModel(wheelPos);
1114
1115 if (!SEffectManager.IsEffectExist(ptrEff))
1116 {
1117 eff = new EffWheelSmoke();
1118 eff.SetSurface(surface);
1119 ptrEff = SEffectManager.PlayOnObject(eff, this, wheelPos, "0 1 -1");
1120 eff.SetCurrentLocalPosition(wheelPos);
1121 m_WheelSmokeFx.Set(i, eff);
1122 m_WheelSmokePtcFx.Set(i, ptrEff);
1123 }
1124 else
1125 {
1126 if (!eff.IsPlaying() && Surface.GetWheelParticleID(surface) != 0)
1127 eff.Start();
1128 eff.SetSurface(surface);
1129 eff.SetCurrentLocalPosition(wheelPos);
1130 }
1131 }
1132 }
1133
1134 if (!haveParticle)
1135 {
1136 if (eff && eff.IsPlaying())
1137 eff.Stop();
1138 }
1139 }
1140 }
1141 }
1142
1144 {
1145 UpdateLights();
1146 }
1147
1149 {
1150 UpdateLights();
1151 }
1152
1153 override void OnDriverExit(Human player)
1154 {
1155 super.OnDriverExit(player);
1156
1157 if (GetGear() != GetNeutralGear())
1158 {
1159 EngineStop();
1160 }
1161 }
1162
1163 // Server side event for jump out processing
1165 {
1166 PlayerBase player = gotActionData.m_Player;
1167
1168 array<ClothingBase> equippedClothes = new array<ClothingBase>;
1169 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("LEGS")));
1170 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("BACK")));
1171 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("VEST")));
1172 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("HeadGear")));
1173 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("Mask")));
1174 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("BODY")));
1175 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("FEET")));
1176 equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("GLOVES")));
1177
1178 // -----------------------------------------------
1179 float shockTaken = (gotActionData.m_Speed * gotActionData.m_Speed) / ActionGetOutTransport.DMG_FACTOR;
1180
1181 //Lower shock taken if player uses a helmet
1182 ItemBase headGear = ClothingBase.Cast(player.GetItemOnHead());
1183 HelmetBase helmet;
1184 if (Class.CastTo(helmet, headGear))
1185 shockTaken *= 0.5;
1186
1187 // -----------------------------------------------
1188
1189 int randNum; //value used for probability evaluation
1190 randNum = Math.RandomInt(0, 100);
1191 if (gotActionData.m_Speed < ActionGetOutTransport.LOW_SPEED_VALUE)
1192 {
1193 if (randNum < 20)
1194 player.GiveShock(-shockTaken); //To inflict shock, a negative value must be passed
1195
1196 randNum = Math.RandomIntInclusive(0, PlayerBase.m_BleedingSourcesLow.Count() - 1);
1197
1198 if (player.m_BleedingManagerServer)
1199 player.m_BleedingManagerServer.AttemptAddBleedingSourceBySelection(PlayerBase.m_BleedingSourcesLow[randNum]);
1200 }
1201 else if (gotActionData.m_Speed >= ActionGetOutTransport.LOW_SPEED_VALUE && gotActionData.m_Speed < ActionGetOutTransport.HIGH_SPEED_VALUE)
1202 {
1203 if (randNum < 50)
1204 player.GiveShock(-shockTaken);
1205
1206 randNum = Math.RandomInt(0, PlayerBase.m_BleedingSourcesUp.Count() - 1);
1207
1208 if (player.m_BleedingManagerServer)
1209 player.m_BleedingManagerServer.AttemptAddBleedingSourceBySelection(PlayerBase.m_BleedingSourcesUp[randNum]);
1210 }
1211 else if (gotActionData.m_Speed >= ActionGetOutTransport.HIGH_SPEED_VALUE)
1212 {
1213 if (!headGear && player.m_BleedingManagerServer)
1214 player.m_BleedingManagerServer.AttemptAddBleedingSourceBySelection("Head");
1215
1216 if (randNum < 75)
1217 player.GiveShock(-shockTaken);
1218 }
1219
1220 float dmgTaken = (gotActionData.m_Speed * gotActionData.m_Speed) / ActionGetOutTransport.SHOCK_FACTOR;
1221
1222 //Damage all currently equipped clothes
1223 foreach (ClothingBase cloth : equippedClothes)
1224 {
1225 //If no item is equipped on slot, slot is ignored
1226 if (cloth == null)
1227 continue;
1228
1229 cloth.DecreaseHealth(dmgTaken, false);
1230 }
1231
1232 vector posMS = gotActionData.m_Player.WorldToModel(gotActionData.m_Player.GetPosition());
1233 gotActionData.m_Player.DamageAllLegs(dmgTaken); //Additionnal leg specific damage dealing
1234
1235 float healthCoef = Math.InverseLerp(ActionGetOutTransport.HEALTH_LOW_SPEED_VALUE, ActionGetOutTransport.HEALTH_HIGH_SPEED_VALUE, gotActionData.m_Speed);
1236 healthCoef = Math.Clamp(healthCoef, 0.0, 1.0);
1237 gotActionData.m_Player.ProcessDirectDamage(DamageType.CUSTOM, gotActionData.m_Player, "", "FallDamageHealth", posMS, healthCoef);
1238 }
1239
1240 protected override bool DetectFlipped(VehicleFlippedContext ctx)
1241 {
1242 if (!DetectFlippedUsingWheels(ctx, GameConstants.VEHICLE_FLIP_WHEELS_LIMITED))
1243 return false;
1244 if (!DetectFlippedUsingSurface(ctx, GameConstants.VEHICLE_FLIP_ANGLE_TOLERANCE))
1245 return false;
1246 return true;
1247 }
1248
1249 override void OnUpdate( float dt )
1250 {
1251 Human driver = CrewDriver();
1252 if (driver && !driver.IsControllingVehicle())
1253 {
1254 // likely unconscious
1255 if (driver.IsAlive())
1256 {
1257 SetBrake(0.5);
1258 }
1259 }
1260
1261 if (GetGame().IsServer())
1262 {
1263 ItemBase battery = GetBattery();
1264 if (battery)
1265 {
1266 m_BatteryTimer += dt;
1267 if (m_BatteryTimer >= BATTERY_UPDATE_DELAY)
1268 {
1269 UpdateBattery(battery);
1270 }
1271 }
1272
1273 if ( GetGame().GetWaterDepth( GetEnginePosWS() ) > 0 )
1274 {
1275 m_DrownTime += dt;
1276 if ( m_DrownTime > DROWN_ENGINE_THRESHOLD )
1277 {
1278 // *dt to get damage per second
1279 AddHealth( "Engine", "Health", -DROWN_ENGINE_DAMAGE * dt);
1280 SetEngineZoneReceivedHit(true);
1281 }
1282 }
1283 else
1284 {
1285 m_DrownTime = 0;
1286 }
1287 }
1288
1289 // For visualisation of brake lights for all players
1290 float brake_coef = GetBrake();
1291 if ( brake_coef > 0 )
1292 {
1293 if ( !m_BrakesArePressed )
1294 {
1295 m_BrakesArePressed = true;
1296 SetSynchDirty();
1297 OnBrakesPressed();
1298 }
1299 }
1300 else
1301 {
1302 if ( m_BrakesArePressed )
1303 {
1304 m_BrakesArePressed = false;
1305 SetSynchDirty();
1306 OnBrakesReleased();
1307 }
1308 }
1309
1310 if ( (!GetGame().IsDedicatedServer()) && m_ForceUpdateLights )
1311 {
1312 UpdateLights();
1313 m_ForceUpdateLights = false;
1314 }
1315 }
1316
1317 override void EEKilled(Object killer)
1318 {
1319 super.EEKilled(killer);
1320 m_EngineDestroyed = true;
1321 }
1322
1324 override void OnContact( string zoneName, vector localPos, IEntity other, Contact data )
1325 {
1326 if (GetGame().IsServer())
1327 {
1328 #ifdef DIAG_DEVELOPER
1329 m_ContactCalled = true;
1330 if (DEBUG_OUTPUT_TYPE & EVehicleDebugOutputType.CONTACT)
1331 {
1332 string output = "Zone: " + zoneName + " | Impulse:" + data.Impulse;
1333 Debug.Log(output);
1334 }
1335 #endif
1336 if (m_ContactCache.Count() == 0)
1337 {
1339 m_ContactCache.Insert(zoneName, ccd);
1340 float momentumDelta = GetMomentum() - m_MomentumPrevTick;
1341 float dot = vector.Dot(m_VelocityPrevTick.Normalized(), GetVelocity(this).Normalized());
1342 if (dot < 0)
1343 {
1344 momentumDelta = m_MomentumPrevTick;
1345 }
1346
1347 ccd.Insert(new CarContactData(localPos, other, momentumDelta));
1348 }
1349 }
1350 }
1351
1354 {
1355
1356 int contactZonesCount = m_ContactCache.Count();
1357
1358 if (contactZonesCount == 0)
1359 return;
1360
1361
1362 for (int i = 0; i < contactZonesCount; ++i)
1363 {
1364 string zoneName = m_ContactCache.GetKey(i);
1365 array<ref CarContactData> data = m_ContactCache[zoneName];
1366
1367 float dmg = Math.AbsInt(data[0].impulse * m_dmgContactCoef);
1368 float crewDmgBase = Math.AbsInt((data[0].impulse / dBodyGetMass(this)) * 1000 * m_dmgContactCoef);// calculates damage as if the object's weight was 1000kg instead of its actual weight
1369
1370 #ifdef DIAG_DEVELOPER
1371 CrashDebugData.m_CrashDataPoint = new CrashDebugData();
1372 CrashDebugData.m_CrashDataPoint.m_VehicleType = GetDisplayName();
1373 CrashDebugData.m_CrashDataPoint.m_Damage = dmg;
1374 CrashDebugData.m_CrashDataPoint.m_Zone = zoneName;
1375 CrashDebugData.m_CrashDataPoint.m_MomentumCurr = GetMomentum();
1376 CrashDebugData.m_CrashDataPoint.m_MomentumPrev = m_MomentumPrevTick;
1377 CrashDebugData.m_CrashDataPoint.m_MomentumDelta = data[0].impulse;
1378 CrashDebugData.m_CrashDataPoint.m_SpeedWorld = GetVelocity(this).Length() * 3.6;
1379 CrashDebugData.m_CrashDataPoint.m_SpeedWorldPrev = m_VelocityPrevTick.Length() * 3.6;
1380 CrashDebugData.m_CrashDataPoint.m_SpeedWorldDelta = (m_VelocityPrevTick.Length() - GetVelocity(this).Length()) * 3.6;
1381 CrashDebugData.m_CrashDataPoint.m_VelocityCur = GetVelocity(this);
1382 CrashDebugData.m_CrashDataPoint.m_VelocityPrev = m_VelocityPrevTick;
1383 CrashDebugData.m_CrashDataPoint.m_VelocityDot = vector.Dot(m_VelocityPrevTick.Normalized(), GetVelocity(this).Normalized());
1384 CrashDebugData.m_CrashDataPoint.m_Time = GetGame().GetTime();
1385
1386
1387
1388 if (DEBUG_OUTPUT_TYPE & EVehicleDebugOutputType.DAMAGE_CONSIDERED)
1389 {
1390 Debug.Log("--------------------------------------------------");
1391 Debug.Log("Vehicle:" + GetDisplayName());
1392 Debug.Log("DMG: " + dmg);
1393 Debug.Log("zoneName : "+ zoneName);
1394 Debug.Log("momentumCurr : "+ GetMomentum());
1395 Debug.Log("momentumPrev : "+ m_MomentumPrevTick);
1396 Debug.Log("momentumDelta : "+ data[0].impulse);
1397 Debug.Log("speed(km/h): "+ GetVelocity(this).Length() * 3.6);
1398 Debug.Log("speedPrev(km/h): "+ m_VelocityPrevTick.Length() * 3.6);
1399 Debug.Log("speedDelta(km/h) : "+ (m_VelocityPrevTick.Length() - GetVelocity(this).Length()) * 3.6);
1400 Debug.Log("velocityCur.): "+ GetVelocity(this));
1401 Debug.Log("velocityPrev.): "+ m_VelocityPrevTick);
1402 Debug.Log("velocityDot): "+ vector.Dot(m_VelocityPrevTick.Normalized(), GetVelocity(this).Normalized()));
1403 Debug.Log("GetGame().GetTime(): "+ GetGame().GetTime());
1404 Debug.Log("--------------------------------------------------");
1405 }
1406 #endif
1407 if ( dmg < GameConstants.CARS_CONTACT_DMG_MIN )
1408 continue;
1409
1410 int pddfFlags;
1411 #ifdef DIAG_DEVELOPER
1412 CrashDebugData.m_CrashData.Insert(CrashDebugData.m_CrashDataPoint);
1413 CrashDebugData.m_CrashDataPoint.m_Speedometer = GetSpeedometer();
1414 //Print("Crash data recorded");
1415 #endif
1416 if (dmg < GameConstants.CARS_CONTACT_DMG_THRESHOLD)
1417 {
1418 #ifdef DIAG_DEVELOPER
1419 CrashDebugData.m_CrashDataPoint.m_DamageType = "Small";
1420 if (DEBUG_OUTPUT_TYPE & EVehicleDebugOutputType.DAMAGE_APPLIED)
1421 Debug.Log(string.Format("[Vehiles:Damage]:: DMG %1 to the %2 zone is SMALL (threshold: %3), SPEEDOMETER: %4, TIME: %5", dmg, zoneName, GameConstants.CARS_CONTACT_DMG_MIN, GetSpeedometer(), GetGame().GetTime() ));
1422 #endif
1423 SynchCrashLightSound(true);
1424 pddfFlags = ProcessDirectDamageFlags.NO_TRANSFER;
1425 }
1426 else
1427 {
1428 #ifdef DIAG_DEVELOPER
1429 CrashDebugData.m_CrashDataPoint.m_DamageType = "Big";
1430 if (DEBUG_OUTPUT_TYPE & EVehicleDebugOutputType.DAMAGE_APPLIED)
1431 Debug.Log(string.Format("[Vehiles:Damage]:: DMG %1 to the %2 zone is BIG (threshold: %3), SPEED: %4, TIME: %5", dmg, zoneName, GameConstants.CARS_CONTACT_DMG_THRESHOLD, GetSpeedometer(), GetGame().GetTime() ));
1432 #endif
1433 DamageCrew(crewDmgBase);
1434 SynchCrashHeavySound(true);
1435 pddfFlags = 0;
1436 }
1437
1438 #ifdef DEVELOPER
1439 m_DebugContactDamageMessage += string.Format("%1: %2\n", zoneName, dmg);
1440 #endif
1441
1442 ProcessDirectDamage(DamageType.CUSTOM, null, zoneName, "EnviroDmg", "0 0 0", dmg, pddfFlags);
1443
1444 //if (data[0].impulse > TRESHOLD)
1445 //{
1446 Object targetEntity = Object.Cast(data[0].other);
1447 if (targetEntity && targetEntity.IsTree())
1448 {
1449 SEffectManager.CreateParticleServer(targetEntity.GetPosition(), new TreeEffecterParameters("TreeEffecter", 1.0, 0.1));
1450 }
1451 //}
1452 }
1453
1454 UpdateHeadlightState();
1455 UpdateLights();
1456
1457 m_ContactCache.Clear();
1458
1459 }
1460
1462 void DamageCrew(float dmg)
1463 {
1464 for ( int c = 0; c < CrewSize(); ++c )
1465 {
1466 Human crew = CrewMember( c );
1467 if ( !crew )
1468 continue;
1469
1470 PlayerBase player;
1471 if ( Class.CastTo(player, crew ) )
1472 {
1473 if ( dmg > GameConstants.CARS_CONTACT_DMG_KILLCREW )
1474 {
1475 #ifdef DIAG_DEVELOPER
1476 CrashDebugData.m_CrashDataPoint.m_CrewDamageBase = dmg;
1477 CrashDebugData.m_CrashDataPoint.m_DMGHealth = -100;
1478 if (DEBUG_OUTPUT_TYPE & EVehicleDebugOutputType.DAMAGE_APPLIED)
1479 {
1480 Debug.Log("--------------------------------------------------");
1481 Debug.Log("Killing the player");
1482 Debug.Log("Crew DMG Base: " + dmg);
1483 Debug.Log("--------------------------------------------------");
1484
1485 }
1486 #endif
1487 player.SetHealth(0.0);
1488 }
1489 else
1490 {
1491 float shockTemp = Math.InverseLerp(GameConstants.CARS_CONTACT_DMG_THRESHOLD, GameConstants.CARS_CONTACT_DMG_KILLCREW, dmg);
1492 shockTemp = Math.Clamp(shockTemp,0,1);
1493 float shock = Math.Lerp( 50, 150, shockTemp );
1494 float hp = Math.Lerp( 2, 100, shockTemp );
1495
1496 #ifdef DIAG_DEVELOPER
1497 CrashDebugData.m_CrashDataPoint.m_CrewDamageBase = dmg;
1498 CrashDebugData.m_CrashDataPoint.m_ShockTemp = shockTemp;
1499 CrashDebugData.m_CrashDataPoint.m_DMGHealth = hp;
1500 CrashDebugData.m_CrashDataPoint.m_DMGShock = shock;
1501 if (DEBUG_OUTPUT_TYPE & EVehicleDebugOutputType.DAMAGE_APPLIED)
1502 {
1503 Debug.Log("--------------------------------------------------");
1504 Debug.Log("Crew DMG Base: " + dmg);
1505 Debug.Log("Crew shockTemp: " + shockTemp);
1506 Debug.Log("Crew DMG Health: " + hp);
1507 Debug.Log("Crew DMG Shock: " + shock);
1508 Debug.Log("--------------------------------------------------");
1509 }
1510 #endif
1511
1512 player.AddHealth("", "Shock", -shock );
1513 player.AddHealth("", "Health", -hp );
1514 }
1515 }
1516 }
1517 }
1518
1524 override float OnSound( CarSoundCtrl ctrl, float oldValue )
1525 {
1526 switch (ctrl)
1527 {
1528 case CarSoundCtrl.ENGINE:
1529 if (!m_EngineStarted)
1530 {
1531 return 0.0;
1532 }
1533 break;
1534 }
1535
1536 return oldValue;
1537 }
1538
1539 override void OnAnimationPhaseStarted(string animSource, float phase)
1540 {
1541 #ifndef SERVER
1542 HandleDoorsSound(animSource, phase);
1543 HandleSeatAdjustmentSound(animSource, phase);
1544 #endif
1545 }
1546
1547 protected EffectSound CreateSoundForAnimationSource(string animSource)
1548 {
1549 vector position = vector.Zero;
1550 int pivotIndex = -1;
1551
1552 string selectionName = GetSelectionFromAnimSource(animSource);
1553 if (selectionName != "")
1554 {
1555 position = GetSelectionBasePositionLS(selectionName);
1556
1557 int level = GetViewGeometryLevel();
1558
1559 array<int> pivots = new array<int>();
1560
1561 pivots.Clear();
1562 GetBonePivotsForAnimationSource(level, animSource, pivots);
1563
1564 if (pivots.Count())
1565 {
1566 pivotIndex = pivots[0];
1567 }
1568 }
1569
1570 WaveKind waveKind = WaveKind.WAVEEFFECTEX;
1571
1572 EffectSound sound = new EffectSound();
1573
1574 PlayerBase player;
1575 if (Class.CastTo(player, GetGame().GetPlayer()))
1576 {
1577 if (player.IsCameraInsideVehicle())
1578 {
1579 waveKind = WaveKind.WAVEEFFECT;
1580 }
1581 }
1582
1583 sound.SetAutodestroy(true);
1584 sound.SetParent(this, pivotIndex);
1585 sound.SetPosition(ModelToWorld(position));
1586 sound.SetLocalPosition(position);
1587 sound.SetSoundWaveKind(waveKind);
1588
1589 return sound;
1590 }
1591
1592 protected void HandleDoorsSound(string animSource, float phase)
1593 {
1594 switch (animSource)
1595 {
1596 case "doorsdriver":
1597 case "doorscodriver":
1598 case "doorscargo1":
1599 case "doorscargo2":
1600 case "doorshood":
1601 case "doorstrunk":
1602 EffectSound sound = CreateSoundForAnimationSource(animSource);
1603
1604 if (phase == 0)
1605 sound.SetSoundSet(m_CarDoorOpenSound);
1606 else
1607 sound.SetSoundSet(m_CarDoorCloseSound);
1608
1610 sound.SoundPlay();
1611
1612 break;
1613 }
1614 }
1615
1616 protected void HandleSeatAdjustmentSound(string animSource, float phase)
1617 {
1618 switch (animSource)
1619 {
1620 case "seatdriver":
1621 case "seatcodriver":
1622 EffectSound sound = CreateSoundForAnimationSource(animSource);
1623
1624 if (phase == 0)
1625 sound.SetSoundSet(m_CarSeatShiftInSound);
1626 else
1627 sound.SetSoundSet(m_CarSeatShiftOutSound);
1628
1630 sound.SoundPlay();
1631
1632 break;
1633 }
1634 }
1635
1636
1637 protected void HandleCarHornSound(ECarHornState pState)
1638 {
1639 switch (pState)
1640 {
1641 case ECarHornState.SHORT:
1642 PlaySoundSet(m_CarHornSoundEffect, m_CarHornShortSoundName, 0, 0, false);
1643 break;
1644 case ECarHornState.LONG:
1645 PlaySoundSet(m_CarHornSoundEffect, m_CarHornLongSoundName, 0, 0, true);
1646 break;
1647 default:
1648 CleanupSound(m_CarHornSoundEffect);
1649 break;
1650 }
1651 }
1652
1653 // Only used for sound states which happen before engine start
1654 void SetCarEngineSoundState(CarEngineSoundState pState)
1655 {
1656 m_CarEngineSoundState = pState;
1657 SetSynchDirty();
1658 }
1659
1660 void HandleEngineSound(CarEngineSoundState state)
1661 {
1662 SetCarEngineSoundState(state);
1663 m_CarEngineLastSoundState = state;
1664
1665 #ifndef SERVER
1666 PlayerBase player = null;
1667 EffectSound sound = null;
1668 WaveKind waveKind = WaveKind.WAVEEFFECTEX;
1669
1670 bool doInside = false;
1671
1672 m_CarEngineLastSoundState = state;
1673
1674 switch (state)
1675 {
1676 case CarEngineSoundState.STARTING:
1677 sound = new EffectSound();
1678 sound.SetSoundSet("Offroad_02_Starting_SoundSet");
1679 sound.SetSoundFadeOut(0.15);
1680
1681 m_PreStartSound = sound;
1682 break;
1683 case CarEngineSoundState.START_OK:
1684 doInside = true;
1685
1686 sound = new EffectSound();
1687 sound.SetSoundSet(m_EngineStartOK);
1688 sound.SetAutodestroy(true);
1689
1691 GetGame().GetCallQueue(CALL_CATEGORY_GAMEPLAY).CallLater(SetEngineStarted, 1000, false, true);
1692 break;
1693
1694 case CarEngineSoundState.START_NO_FUEL:
1695 sound = new EffectSound();
1696 sound.SetSoundSet("offroad_engine_failed_start_fuel_SoundSet");
1697 sound.SetAutodestroy(true);
1698 break;
1699
1700 case CarEngineSoundState.START_NO_BATTERY:
1701 sound = new EffectSound();
1702 sound.SetSoundSet("offroad_engine_failed_start_battery_SoundSet");
1703 sound.SetAutodestroy(true);
1704 break;
1705
1706 case CarEngineSoundState.START_NO_SPARKPLUG:
1707 sound = new EffectSound();
1708 sound.SetSoundSet("offroad_engine_failed_start_sparkplugs_SoundSet");
1709 sound.SetAutodestroy(true);
1710 break;
1711
1712 case CarEngineSoundState.STOP_OK:
1713 doInside = true;
1714
1715 sound = new EffectSound();
1716 sound.SetSoundSet(m_EngineStop);
1717 sound.SetAutodestroy(true);
1718 break;
1719 case CarEngineSoundState.STOP_NO_FUEL:
1720 doInside = true;
1721
1722 sound = new EffectSound();
1723 sound.SetSoundSet(m_EngineStopFuel);
1724 sound.SetAutodestroy(true);
1725 break;
1726
1727 default:
1728 break;
1729 }
1730
1731 // play different sound based on selected camera
1732 if (doInside && Class.CastTo(player, GetGame().GetPlayer()))
1733 {
1734 if (player.IsCameraInsideVehicle())
1735 {
1736 waveKind = WaveKind.WAVEEFFECT;
1737 }
1738 }
1739
1740 if (sound)
1741 {
1742 vector enginePos = GetEnginePos();
1743
1744 sound.SetParent(this);
1745 sound.SetPosition(ModelToWorld(enginePos));
1746 sound.SetLocalPosition(enginePos);
1747 sound.SetSoundWaveKind(waveKind);
1749
1750 sound.SoundPlay();
1751 }
1752
1753 #endif
1754 }
1755
1756 override void MarkCrewMemberUnconscious(int crewMemberIndex)
1757 {
1758 if (!IsAuthority())
1759 return;
1760
1761 if (crewMemberIndex == DayZPlayerConstants.VEHICLESEAT_DRIVER)
1762 {
1763 EngineStop();
1764 }
1765 }
1766
1767 override void MarkCrewMemberDead(int crewMemberIndex)
1768 {
1769 if (!IsAuthority())
1770 return;
1771
1772 if (crewMemberIndex == DayZPlayerConstants.VEHICLESEAT_DRIVER)
1773 {
1774 EngineStop();
1775 }
1776 }
1777
1784 override void OnFluidChanged(CarFluid fluid, float newValue, float oldValue)
1785 {
1786 switch ( fluid )
1787 {
1788 case CarFluid.FUEL:
1789 m_FuelAmmount = newValue;
1790 break;
1791
1792 case CarFluid.OIL:
1793 m_OilAmmount = newValue;
1794 break;
1795
1796 case CarFluid.BRAKE:
1797 m_BrakeAmmount = newValue;
1798 break;
1799
1800 case CarFluid.COOLANT:
1801 m_CoolantAmmount = newValue;
1802 break;
1803 }
1804 }
1805
1811 override bool OnBeforeEngineStart()
1812 {
1813 ECarOperationalState state = CheckOperationalRequirements();
1814 SetCarEngineSoundState(CarEngineSoundState.NONE);
1815 return state == ECarOperationalState.OK;
1816 }
1817
1819 {
1820 ECarOperationalState state = CheckOperationalRequirements();
1821
1822 if (state == ECarOperationalState.RUINED)
1823 {
1824 return;
1825 }
1826
1827 if (state & ECarOperationalState.NO_BATTERY)
1828 {
1829 HandleEngineSound(CarEngineSoundState.START_NO_BATTERY);
1830 return;
1831 }
1832
1833 if (state & ECarOperationalState.NO_IGNITER)
1834 {
1835 HandleEngineSound(CarEngineSoundState.START_NO_SPARKPLUG);
1836 return;
1837 }
1838
1839 if (state & ECarOperationalState.NO_FUEL)
1840 {
1841 HandleEngineSound(CarEngineSoundState.START_NO_FUEL);
1842 return;
1843 }
1844
1845 HandleEngineSound(CarEngineSoundState.STARTING);
1846 }
1847
1848 // Whether the car engine can be started
1850 {
1851 int state = ECarOperationalState.OK;
1852
1853 EntityAI item = null;
1854
1855 if (IsDamageDestroyed() || GetHealthLevel("Engine") >= GameConstants.STATE_RUINED)
1856 {
1857 state |= ECarOperationalState.RUINED;
1858 }
1859
1860 if (GetFluidFraction(CarFluid.FUEL) <= 0)
1861 {
1862 state |= ECarOperationalState.NO_FUEL;
1863 }
1864
1866 {
1867 item = GetBattery();
1868 float batteryConsume = GetBatteryConsumption();
1869 if (!item || (item && (item.IsRuined() || item.GetCompEM().GetEnergy() < batteryConsume)))
1870 state |= ECarOperationalState.NO_BATTERY;
1871 }
1872
1873 if (IsVitalSparkPlug())
1874 {
1875 item = FindAttachmentBySlotName("SparkPlug");
1876 if (!item || (item && item.IsRuined()))
1877 state |= ECarOperationalState.NO_IGNITER;
1878 }
1879
1880 if (IsVitalGlowPlug())
1881 {
1882 item = FindAttachmentBySlotName("GlowPlug");
1883 if (!item || (item && item.IsRuined()))
1884 state |= ECarOperationalState.NO_IGNITER;
1885 }
1886
1887 return state;
1888 }
1889
1891 {
1892 return CheckOperationalRequirements() == ECarOperationalState.OK;
1893 }
1894
1895 override void OnGearChanged(int newGear, int oldGear)
1896 {
1897 //Debug.Log(string.Format("OnGearChanged newGear=%1,oldGear=%2", newGear, oldGear));
1898 UpdateLights(newGear);
1899 }
1900
1902 override void OnEngineStart()
1903 {
1904 ItemBase battery = GetBattery();
1905 if (GetGame().IsServer() && battery)
1906 {
1907 float batteryConsume = GetBatteryConsumption();
1908 battery.GetCompEM().ConsumeEnergy(batteryConsume);
1909
1910 UpdateBattery(battery);
1911 }
1912
1913 UpdateLights();
1914
1915 HandleEngineSound(CarEngineSoundState.START_OK);
1916 }
1917
1919 override void OnEngineStop()
1920 {
1921 ItemBase battery = GetBattery();
1922 if (GetGame().IsServer() && battery)
1923 {
1924 UpdateBattery(battery);
1925 }
1926
1927 UpdateLights();
1928
1929 CarEngineSoundState stopSoundState = CarEngineSoundState.STOP_OK;
1930 if (GetFluidFraction(CarFluid.FUEL) <= 0)
1931 stopSoundState = CarEngineSoundState.STOP_NO_FUEL;
1932
1933 HandleEngineSound(stopSoundState);
1934
1935 SetEngineZoneReceivedHit(false);
1936 }
1937
1940 {
1941 return m_HeadlightsOn;
1942 }
1943
1946 {
1947 // TODO(kumarjac): Call 'UpdateBattery' here. Probably can't right now
1948
1949 m_HeadlightsOn = !m_HeadlightsOn;
1950 SetSynchDirty();
1951 }
1952
1953 void UpdateLights(int new_gear = -1)
1954 {
1955 #ifndef SERVER
1956 UpdateLightsClient(new_gear);
1957 #endif
1958 UpdateLightsServer(new_gear);
1959 }
1960
1961 void UpdateLightsClient(int newGear = -1)
1962 {
1963 int gear;
1964
1965 if (newGear == -1)
1966 {
1967 gear = GetGear();
1968 }
1969 else
1970 {
1971 gear = newGear;
1972 }
1973
1974 if (m_HeadlightsOn)
1975 {
1976 if (!m_Headlight && m_HeadlightsState != CarHeadlightBulbsState.NONE)
1977 {
1978 m_Headlight = CreateFrontLight();
1979 }
1980
1981 if (m_Headlight)
1982 {
1983 switch (m_HeadlightsState)
1984 {
1985 case CarHeadlightBulbsState.LEFT:
1986 m_Headlight.AttachOnMemoryPoint(this, m_LeftHeadlightPoint, m_LeftHeadlightTargetPoint);
1987 m_Headlight.SegregateLight();
1988 break;
1989 case CarHeadlightBulbsState.RIGHT:
1990 m_Headlight.AttachOnMemoryPoint(this, m_RightHeadlightPoint, m_RightHeadlightTargetPoint);
1991 m_Headlight.SegregateLight();
1992 break;
1993 case CarHeadlightBulbsState.BOTH:
1994 vector local_pos_left = GetMemoryPointPos(m_LeftHeadlightPoint);
1995 vector local_pos_right = GetMemoryPointPos(m_RightHeadlightPoint);
1996
1997 vector local_pos_middle = (local_pos_left + local_pos_right) * 0.5;
1998 m_Headlight.AttachOnObject(this, local_pos_middle);
1999 m_Headlight.AggregateLight();
2000 break;
2001 default:
2002 m_Headlight.FadeOut();
2003 m_Headlight = null;
2004 }
2005 }
2006 }
2007 else
2008 {
2009 if (m_Headlight)
2010 {
2011 m_Headlight.FadeOut();
2012 m_Headlight = null;
2013 }
2014 }
2015
2016 // brakes & reverse
2017 switch (gear)
2018 {
2019 case CarGear.REVERSE:
2021 if (m_BrakesArePressed)
2022 m_RearLightType = CarRearLightType.BRAKES_AND_REVERSE;
2023 else
2024 m_RearLightType = CarRearLightType.REVERSE_ONLY;
2025 break;
2026 default:
2027 if (m_BrakesArePressed)
2028 m_RearLightType = CarRearLightType.BRAKES_ONLY;
2029 else
2030 m_RearLightType = CarRearLightType.NONE;
2031 }
2032
2033 //Debug.Log(string.Format("m_BrakesArePressed=%1, m_RearLightType=%2", m_BrakesArePressed.ToString(), EnumTools.EnumToString(CarRearLightType, m_RearLightType)));
2034
2035 if (!m_RearLight && m_RearLightType != CarRearLightType.NONE && m_HeadlightsState != CarHeadlightBulbsState.NONE)
2036 {
2037 if (EngineIsOn() || m_RearLightType == CarRearLightType.BRAKES_ONLY || m_RearLightType == CarRearLightType.BRAKES_AND_REVERSE)
2038 {
2039 m_RearLight = CreateRearLight();
2040 vector localPos = GetMemoryPointPos(m_ReverseLightPoint);
2041 m_RearLight.AttachOnObject(this, localPos, "180 0 0");
2042 }
2043 }
2044
2045 // rear lights
2046 if (m_RearLight && m_RearLightType != CarRearLightType.NONE && m_HeadlightsState != CarHeadlightBulbsState.NONE)
2047 {
2048 switch (m_RearLightType)
2049 {
2050 case CarRearLightType.BRAKES_ONLY:
2051 BrakesRearLight();
2052 break;
2053 case CarRearLightType.REVERSE_ONLY:
2054 if (EngineIsOn())
2055 ReverseRearLight();
2056 else
2057 NoRearLight();
2058
2059 break;
2060 case CarRearLightType.BRAKES_AND_REVERSE:
2061 if (EngineIsOn())
2062 BrakeAndReverseRearLight();
2063 else
2064 BrakesRearLight();
2065
2066 break;
2067 default:
2068 NoRearLight();
2069 }
2070 }
2071 else
2072 {
2073 if (m_RearLight)
2074 {
2075 NoRearLight();
2076 }
2077 }
2078 }
2079
2080 void UpdateLightsServer(int newGear = -1)
2081 {
2082 int gear;
2083
2084 if (newGear == -1)
2085 {
2086 gear = GetGear();
2087 if (GearboxGetType() == CarGearboxType.AUTOMATIC)
2088 {
2089 gear = GearboxGetMode();
2090 }
2091 }
2092 else
2093 {
2094 gear = newGear;
2095 }
2096
2097 if (m_HeadlightsOn)
2098 {
2099 DashboardShineOn();
2100 TailLightsShineOn();
2101
2102 switch (m_HeadlightsState)
2103 {
2104 case CarHeadlightBulbsState.LEFT:
2105 LeftFrontLightShineOn();
2106 RightFrontLightShineOff();
2107 break;
2108 case CarHeadlightBulbsState.RIGHT:
2109 LeftFrontLightShineOff();
2110 RightFrontLightShineOn();
2111 break;
2112 case CarHeadlightBulbsState.BOTH:
2113 LeftFrontLightShineOn();
2114 RightFrontLightShineOn();
2115 break;
2116 default:
2117 LeftFrontLightShineOff();
2118 RightFrontLightShineOff();
2119 }
2120
2121 //Debug.Log(string.Format("m_HeadlightsOn=%1, m_HeadlightsState=%2", m_HeadlightsOn.ToString(), EnumTools.EnumToString(CarHeadlightBulbsState, m_HeadlightsState)));
2122 }
2123 else
2124 {
2125 TailLightsShineOff();
2126 DashboardShineOff();
2127 LeftFrontLightShineOff();
2128 RightFrontLightShineOff();
2129 }
2130
2131
2132 // brakes & reverse
2133 switch (gear)
2134 {
2135 case CarGear.REVERSE:
2137 if (m_BrakesArePressed)
2138 m_RearLightType = CarRearLightType.BRAKES_AND_REVERSE;
2139 else
2140 m_RearLightType = CarRearLightType.REVERSE_ONLY;
2141 break;
2142 default:
2143 if (m_BrakesArePressed)
2144 m_RearLightType = CarRearLightType.BRAKES_ONLY;
2145 else
2146 m_RearLightType = CarRearLightType.NONE;
2147 }
2148
2149 //Debug.Log(string.Format("m_BrakesArePressed=%1, m_RearLightType=%2", m_BrakesArePressed.ToString(), EnumTools.EnumToString(CarRearLightType, m_RearLightType)));
2150
2151
2152 // rear lights
2153 if (m_RearLightType != CarRearLightType.NONE && m_HeadlightsState != CarHeadlightBulbsState.NONE)
2154 {
2155 switch (m_RearLightType)
2156 {
2157 case CarRearLightType.BRAKES_ONLY:
2158 ReverseLightsShineOff();
2159 BrakeLightsShineOn();
2160 break;
2161 case CarRearLightType.REVERSE_ONLY:
2162 if (EngineIsOn())
2163 {
2164 ReverseLightsShineOn();
2165 BrakeLightsShineOff();
2166 }
2167 else
2168 {
2169 ReverseLightsShineOff();
2170 BrakeLightsShineOff();
2171 }
2172 break;
2173 case CarRearLightType.BRAKES_AND_REVERSE:
2174 if (EngineIsOn())
2175 {
2176 BrakeLightsShineOn();
2177 ReverseLightsShineOn();
2178 }
2179 else
2180 {
2181 ReverseLightsShineOff();
2182 BrakeLightsShineOn();
2183 }
2184 break;
2185 default:
2186 ReverseLightsShineOff();
2187 BrakeLightsShineOff();
2188 }
2189 }
2190 else
2191 {
2192 ReverseLightsShineOff();
2193 BrakeLightsShineOff();
2194 }
2195 }
2196
2197 protected void BrakesRearLight()
2198 {
2199 m_RearLight.SetAsSegregatedBrakeLight();
2200 }
2201
2202 protected void ReverseRearLight()
2203 {
2204 m_RearLight.SetAsSegregatedReverseLight();
2205 }
2206
2208 {
2209 m_RearLight.AggregateLight();
2210 m_RearLight.SetFadeOutTime(1);
2211 }
2212
2213 protected void NoRearLight()
2214 {
2215 m_RearLight.FadeOut();
2216 m_RearLight = null;
2217 }
2218
2219 protected void LeftFrontLightShineOn()
2220 {
2221 string material = ConfigGetString("frontReflectorMatOn");
2222
2223 if (material)
2224 {
2225 SetObjectMaterial(SELECTION_ID_FRONT_LIGHT_L, material);
2226 }
2227 }
2228
2229 protected void RightFrontLightShineOn()
2230 {
2231 string material = ConfigGetString("frontReflectorMatOn");
2232
2233 if (material)
2234 {
2235 SetObjectMaterial(SELECTION_ID_FRONT_LIGHT_R, material);
2236 }
2237 }
2238
2239 protected void LeftFrontLightShineOff()
2240 {
2241 string material = ConfigGetString("frontReflectorMatOff");
2242
2243 if (material)
2244 {
2245 SetObjectMaterial(SELECTION_ID_FRONT_LIGHT_L, material);
2246 }
2247 }
2248
2250 {
2251 string material = ConfigGetString("frontReflectorMatOff");
2252
2253 if (material)
2254 {
2255 SetObjectMaterial(SELECTION_ID_FRONT_LIGHT_R, material);
2256 }
2257 }
2258
2259 protected void ReverseLightsShineOn()
2260 {
2261 string material = ConfigGetString("ReverseReflectorMatOn");
2262
2263 if (material)
2264 {
2265 SetObjectMaterial(SELECTION_ID_REVERSE_LIGHT_L, material);
2266 SetObjectMaterial(SELECTION_ID_REVERSE_LIGHT_R, material);
2267 }
2268 }
2269
2270 protected void ReverseLightsShineOff()
2271 {
2272 string material = ConfigGetString("ReverseReflectorMatOff");
2273
2274 if (material)
2275 {
2276 SetObjectMaterial(SELECTION_ID_REVERSE_LIGHT_L, material);
2277 SetObjectMaterial(SELECTION_ID_REVERSE_LIGHT_R, material);
2278 }
2279 }
2280
2281 protected void BrakeLightsShineOn()
2282 {
2283 string material = ConfigGetString("brakeReflectorMatOn");
2284
2285 if (material)
2286 {
2287 SetObjectMaterial(SELECTION_ID_BRAKE_LIGHT_L, material);
2288 SetObjectMaterial(SELECTION_ID_BRAKE_LIGHT_R, material);
2289 }
2290 }
2291
2292 protected void BrakeLightsShineOff()
2293 {
2294 string material = ConfigGetString("brakeReflectorMatOff");
2295
2296 if (material)
2297 {
2298 SetObjectMaterial(SELECTION_ID_BRAKE_LIGHT_L, material);
2299 SetObjectMaterial(SELECTION_ID_BRAKE_LIGHT_R, material);
2300 }
2301 }
2302
2303 protected void TailLightsShineOn()
2304 {
2305 string material = ConfigGetString("TailReflectorMatOn");
2306 string materialOff = ConfigGetString("TailReflectorMatOff");
2307
2308 if (material && materialOff)
2309 {
2310 if (m_HeadlightsState == CarHeadlightBulbsState.LEFT)
2311 {
2312 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_L, material);
2313 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_R, materialOff);
2314 }
2315 else if (m_HeadlightsState == CarHeadlightBulbsState.RIGHT)
2316 {
2317 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_L, materialOff);
2318 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_R, material);
2319 }
2320 else if (m_HeadlightsState == CarHeadlightBulbsState.BOTH)
2321 {
2322 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_L, material);
2323 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_R, material);
2324 }
2325 }
2326 }
2327
2328 protected void TailLightsShineOff()
2329 {
2330 string material = ConfigGetString("TailReflectorMatOff");
2331
2332 if (material)
2333 {
2334 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_L, material);
2335 SetObjectMaterial(SELECTION_ID_TAIL_LIGHT_R, material);
2336 }
2337 }
2338
2339 protected void DashboardShineOn()
2340 {
2341 string material = ConfigGetString("dashboardMatOn");
2342
2343 if (material)
2344 {
2345 SetObjectMaterial(SELECTION_ID_DASHBOARD_LIGHT, material);
2346 }
2347 }
2348
2349 protected void DashboardShineOff()
2350 {
2351 string material = ConfigGetString("dashboardMatOff");
2352
2353 if (material)
2354 {
2355 SetObjectMaterial(SELECTION_ID_DASHBOARD_LIGHT, material);
2356 }
2357 }
2358
2359 // Override this for a car-specific light type
2361 {
2362 return CarRearLightBase.Cast(ScriptedLightBase.CreateLight(OffroadHatchbackFrontLight));
2363 }
2364
2365 // Override this for a car-specific light type
2367 {
2368 return CarLightBase.Cast(ScriptedLightBase.CreateLight(OffroadHatchbackFrontLight));
2369 }
2370
2371 protected void CheckVitalItem(bool isVital, int slotId)
2372 {
2373 if ( !isVital || !GetInventory() )
2374 return;
2375
2376 EntityAI item = GetInventory().FindAttachment(slotId);
2377
2378 if (!item || item.IsRuined())
2379 {
2380 EngineStop();
2381 }
2382 }
2383
2384 protected void CheckVitalItem(bool isVital, string slot_name)
2385 {
2386 if ( !isVital )
2387 return;
2388
2389 int slotId = InventorySlots.GetSlotIdFromString(slot_name);
2390 CheckVitalItem(isVital, slotId);
2391 }
2392
2393 protected void LeakFluid(CarFluid fluid)
2394 {
2395 float ammount = 0;
2396
2397 switch (fluid)
2398 {
2399 case CarFluid.COOLANT:
2400 ammount = (1 - m_RadiatorHealth) * RandomFloat(0.02, 0.05);//CARS_LEAK_TICK_MIN; CARS_LEAK_TICK_MAX
2401 Leak(fluid, ammount);
2402 break;
2403
2404 case CarFluid.OIL:
2405 ammount = (1 - m_EngineHealth) * RandomFloat(0.02, 1.0);//CARS_LEAK_OIL_MIN; CARS_LEAK_OIL_MAX
2406 Leak(fluid, ammount);
2407 break;
2408
2409 case CarFluid.FUEL:
2410 ammount = (1 - m_FuelTankHealth) * RandomFloat(0.02, 0.05);//CARS_LEAK_TICK_MIN; CARS_LEAK_TICK_MAX
2411 Leak(fluid, ammount);
2412 break;
2413 }
2414 }
2415
2416 protected void CarPartsHealthCheck()
2417 {
2418 if (HasRadiator())
2419 {
2420 EntityAI radiator = GetRadiator();
2421 int radiatorHealthLevel = radiator.GetHealthLevel("");
2422 m_RadiatorHealth = GetHealthLevelValue(radiatorHealthLevel, "");
2423 }
2424 else
2425 {
2426 m_RadiatorHealth = 0;
2427 }
2428
2429 int engineHealthLevel = GetHealthLevel("Engine");
2430 m_EngineHealth = GetHealthLevelValue(engineHealthLevel, "Engine");
2431
2432 int fuelTankHealthLevel = GetHealthLevel("FuelTank");
2433 m_FuelTankHealth = GetHealthLevelValue(fuelTankHealthLevel, "FuelTank");
2434 }
2435
2437 {
2438 return m_PlayCrashSoundLight;
2439 }
2440
2441 void SynchCrashLightSound(bool play)
2442 {
2443 if (m_PlayCrashSoundLight != play)
2444 {
2445 m_PlayCrashSoundLight = play;
2446 SetSynchDirty();
2447 }
2448 }
2449
2451 {
2452 PlaySoundEx("offroad_hit_light_SoundSet", m_CrashSoundLight, m_PlayCrashSoundLight);
2453 }
2454
2456 {
2457 return m_PlayCrashSoundHeavy;
2458 }
2459
2460 void SynchCrashHeavySound(bool play)
2461 {
2462 if (m_PlayCrashSoundHeavy != play)
2463 {
2464 m_PlayCrashSoundHeavy = play;
2465 SetSynchDirty();
2466 }
2467 }
2468
2470 {
2471 PlaySoundEx("offroad_hit_heavy_SoundSet", m_CrashSoundHeavy, m_PlayCrashSoundHeavy);
2472 }
2473
2474 void PlaySoundEx(string soundset, EffectSound sound, out bool soundbool)
2475 {
2476 #ifndef SERVER
2477 if (!sound)
2478 {
2480 if( sound )
2481 {
2482 sound.SetAutodestroy(true);
2483 }
2484 }
2485 else
2486 {
2487 if (!sound.IsSoundPlaying())
2488 {
2489 sound.SetPosition(GetPosition());
2490 sound.SoundPlay();
2491 }
2492 }
2493
2494 soundbool = false;
2495 #endif
2496 }
2497
2498 void PlaySound(string soundset, EffectSound sound, out bool soundbool)
2499 {
2500 PlaySoundEx(soundset, sound, soundbool);
2501 }
2502
2503 string GetAnimSourceFromSelection( string selection )
2504 {
2505 return "";
2506 }
2507
2508 string GetSelectionFromAnimSource( string animSource )
2509 {
2510 // Brute force for vehicles that aren't set up
2511
2512 TStringArray allSelections = new TStringArray();
2513 GetSelectionList(allSelections);
2514
2515 foreach (string selectionAll : allSelections)
2516 {
2517 string animSrc = GetAnimSourceFromSelection(selectionAll);
2518 animSrc.ToLower();
2519 if (animSrc != animSource)
2520 continue;
2521
2522 if (animSrc)
2523 {
2524 return selectionAll;
2525 }
2526 }
2527
2528 return "";
2529 }
2530
2531 string GetDoorConditionPointFromSelection( string selection )
2532 {
2533 switch( selection )
2534 {
2535 case "seat_driver":
2536 return "seat_con_1_1";
2537 break;
2538 case "seat_codriver":
2539 return "seat_con_2_1";
2540 break;
2541 case "seat_cargo1":
2542 return "seat_con_1_2";
2543 break;
2544 case "seat_cargo2":
2545 return "seat_con_2_2";
2546 break;
2547 }
2548
2549 return "";
2550 }
2551
2553 {
2554 return "";
2555 }
2556
2558 {
2559 return "";
2560 }
2561
2562 int GetCrewIndex( string selection )
2563 {
2564 return -1;
2565 }
2566
2567 override bool CanReachSeatFromDoors( string pSeatSelection, vector pFromPos, float pDistance = 1.0 )
2568 {
2569 string conPointName = GetDoorConditionPointFromSelection(pSeatSelection);
2570 if (conPointName.Length() > 0)
2571 {
2572 if ( MemoryPointExists(conPointName) )
2573 {
2574 vector conPointMS = GetMemoryPointPos(conPointName);
2575 vector conPointWS = ModelToWorld(conPointMS);
2576
2578 conPointWS[1] = 0;
2579 pFromPos[1] = 0;
2580
2581 if (vector.Distance(pFromPos, conPointWS) <= pDistance)
2582 {
2583 return true;
2584 }
2585 }
2586 }
2587
2588 return false;
2589 }
2590
2592 {
2593 return true;
2594 }
2595
2597 {
2598 return true;
2599 }
2600
2602 {
2603 return true;
2604 }
2605
2607 {
2608 return true;
2609 }
2610
2612 {
2613 return true;
2614 }
2615
2617 {
2618 return true;
2619 }
2620
2622 {
2623 return m_Radiator != null;
2624 }
2625
2627 {
2628 return m_Radiator;
2629 }
2630
2632 {
2633 return GetSpeedometerAbsolute() > 3.5;
2634 }
2635
2637 {
2638 return GetHandbrake() > 0.0;
2639 }
2640
2643 {
2644 return DayZPlayerCameras.DAYZCAMERA_3RD_VEHICLE;
2645
2646 }
2647
2648 void SetEngineStarted(bool started)
2649 {
2650 m_EngineStarted = started;
2651 }
2652
2653 int GetCarDoorsState(string slotType)
2654 {
2655 return CarDoorState.DOORS_MISSING;
2656 }
2657
2659 {
2660 if (GetAnimationPhase(animation) > 0.5)
2661 {
2662 return CarDoorState.DOORS_OPEN;
2663 }
2664 else
2665 {
2666 return CarDoorState.DOORS_CLOSED;
2667 }
2668 }
2669
2671 {
2672 return "radiator";
2673 }
2674
2676 {
2677 return 2.0;
2678 }
2679
2681 {
2682 return "carradiator";
2683 }
2684
2686 {
2687 return 2.0;
2688 }
2689
2691 {
2692 return "carradiator";
2693 }
2694
2696 {
2697 return 2.0;
2698 }
2699
2700 override bool CanPutIntoHands(EntityAI parent)
2701 {
2702 return false;
2703 }
2704
2706 {
2707 m_InputActionMap = m_CarTypeActionsMap.Get( this.Type() );
2708 if (!m_InputActionMap)
2709 {
2711 m_InputActionMap = iam;
2712 SetActions();
2713 m_CarTypeActionsMap.Insert(this.Type(), m_InputActionMap);
2714 }
2715 }
2716
2717 override void GetActions(typename action_input_type, out array<ActionBase_Basic> actions)
2718 {
2720 {
2721 m_ActionsInitialize = true;
2723 }
2724
2725 actions = m_InputActionMap.Get(action_input_type);
2726 }
2727
2738
2739 void AddAction(typename actionName)
2740 {
2741 ActionBase action = ActionManagerBase.GetAction(actionName);
2742
2743 if (!action)
2744 {
2745 Debug.LogError("Action " + actionName + " dosn't exist!");
2746 return;
2747 }
2748
2749 typename ai = action.GetInputType();
2750 if (!ai)
2751 {
2752 m_ActionsInitialize = false;
2753 return;
2754 }
2755 array<ActionBase_Basic> action_array = m_InputActionMap.Get(ai);
2756
2757 if (!action_array)
2758 {
2759 action_array = new array<ActionBase_Basic>;
2760 m_InputActionMap.Insert(ai, action_array);
2761 }
2762
2763 if ( LogManager.IsActionLogEnable() )
2764 {
2765 Debug.ActionLog(action.ToString() + " -> " + ai, this.ToString() , "n/a", "Add action" );
2766 }
2767 action_array.Insert(action);
2768 }
2769
2770 void RemoveAction(typename actionName)
2771 {
2772 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
2773 ActionBase action = player.GetActionManager().GetAction(actionName);
2774 typename ai = action.GetInputType();
2775 array<ActionBase_Basic> action_array = m_InputActionMap.Get(ai);
2776
2777 if (action_array)
2778 {
2779 action_array.RemoveItem(action);
2780 }
2781 }
2782
2783 override bool IsInventoryVisible()
2784 {
2785 return ( GetGame().GetPlayer() && ( !GetGame().GetPlayer().GetCommand_Vehicle() || GetGame().GetPlayer().GetCommand_Vehicle().GetTransport() == this ) );
2786 }
2787
2788 override void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
2789 {
2790 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2791
2792 if (newLevel == GameConstants.STATE_RUINED && oldLevel != newLevel)
2793 {
2794 bool dummy;
2795 switch ( zone )
2796 {
2797 case "WindowLR":
2798 case "WindowRR":
2799 if (m_Initialized)
2800 {
2801 PlaySoundEx("offroad_hit_window_small_SoundSet", m_WindowSmall, dummy);
2802 }
2803 break;
2804
2805 case "WindowFront":
2806 case "WindowBack":
2807 case "WindowFrontLeft":
2808 case "WindowFrontRight":
2809 if (m_Initialized)
2810 {
2811 PlaySoundEx("offroad_hit_window_large_SoundSet", m_WindowLarge, dummy);
2812 }
2813 break;
2814
2815 case "Engine":
2816 #ifndef SERVER
2817 CreateCarDestroyedEffect();
2818 #endif
2819 break;
2820 }
2821 }
2822 }
2823
2824 override void EEOnCECreate()
2825 {
2826
2827 float maxVolume = GetFluidCapacity( CarFluid.FUEL );
2828 float amount = Math.RandomFloat(0.0, maxVolume * 0.35 );
2829
2830 Fill( CarFluid.FUEL, amount );
2831 }
2832
2833 /*override void EOnPostFrame(IEntity other, int extra)
2834 {
2835 //Prepared for fix particle simulation when player is not in vehicle
2836 }*/
2837
2839 {
2840 if (!m_ForceUpdateLights)
2841 {
2842 m_ForceUpdateLights = true;
2843 SetSynchDirty();
2844 }
2845 }
2846
2848 {
2849 if (m_ForceUpdateLights)
2850 {
2851 m_ForceUpdateLights = false;
2852 SetSynchDirty();
2853 }
2854 }
2855
2856 //Get the engine start battery consumption
2858 {
2859 return m_BatteryConsume;
2860 }
2861
2863 {
2864 return m_BatteryContinuousConsume;
2865 }
2866
2868 {
2869 return -m_BatteryRecharge;
2870 }
2871
2873 {
2874 if (IsVitalCarBattery())
2875 {
2876 return ItemBase.Cast(GetInventory().FindAttachment(CarBattery.SLOT_ID));
2877 }
2878 else if (IsVitalTruckBattery())
2879 {
2880 return ItemBase.Cast(GetInventory().FindAttachment(TruckBattery.SLOT_ID));
2881 }
2882
2883 return null;
2884 }
2885
2886 protected void UpdateBattery(ItemBase battery)
2887 {
2888 if (!battery)
2889 {
2890 m_BatteryTimer = 0;
2891 return;
2892 }
2893
2894 // unlikely
2895 if (m_BatteryTimer < 0)
2896 {
2897 m_BatteryTimer = 0;
2898 }
2899
2900 bool engineOn = EngineIsOn();
2901 bool lightsOn = IsScriptedLightsOn();
2902
2903 if (engineOn)
2904 {
2905 // alternator
2906 battery.GetCompEM().ConsumeEnergy(GetBatteryRechargeRate() * m_BatteryTimer);
2907 }
2908 else if (!engineOn && lightsOn)
2909 {
2910 battery.GetCompEM().ConsumeEnergy(GetBatteryRuntimeConsumption() * m_BatteryTimer);
2911 }
2912
2913 if (lightsOn && battery.GetCompEM().GetEnergy() <= 0)
2914 {
2915 // lights currently don't automatically turn back on if the headlight was last turned on, so we just keep them on if the engine is on
2916 if (!engineOn)
2917 {
2918 ToggleHeadlights();
2919 }
2920 }
2921
2922 m_BatteryTimer = 0;
2923 }
2924
2925 void SetCarHornState(int pState)
2926 {
2927 m_CarHornState = pState;
2928 SetSynchDirty();
2929
2930 if (GetGame().IsServer())
2931 {
2932 GenerateCarHornAINoise(pState);
2933 }
2934 }
2935
2936 protected void GenerateCarHornAINoise(int pState)
2937 {
2938 if (pState != ECarHornState.OFF)
2939 {
2940 if (m_NoiseSystem && m_NoisePar)
2941 {
2942 float noiseMultiplier = 1.0;
2943 if (pState == ECarHornState.LONG)
2944 noiseMultiplier = 2.0;
2945
2946 noiseMultiplier *= NoiseAIEvaluate.GetNoiseReduction(GetGame().GetWeather());
2947
2948 m_NoiseSystem.AddNoiseTarget(GetPosition(), 5, m_NoisePar, noiseMultiplier);
2949 }
2950 }
2951 }
2952
2954 {
2955 return vector.Zero;
2956 }
2957
2959 {
2960 return 1.0;
2961 }
2962
2963#ifdef DEVELOPER
2964 override protected string GetDebugText()
2965 {
2966 string debug_output = super.GetDebugText();
2967 if (GetGame().IsServer())
2968 {
2969 debug_output += m_DebugContactDamageMessage + "\n";
2970 }
2971 debug_output += "Entity momentum: " + GetMomentum();
2972 debug_output += "\nIsEngineON: " + EngineIsOn();
2973
2974 return debug_output;
2975 }
2976#endif
2977
2978 protected void SpawnUniversalParts()
2979 {
2980 GetInventory().CreateInInventory("HeadlightH7");
2981 GetInventory().CreateInInventory("HeadlightH7");
2982 GetInventory().CreateInInventory("HeadlightH7");
2983 GetInventory().CreateInInventory("HeadlightH7");
2984
2985 if (IsVitalCarBattery())
2986 {
2987 GetInventory().CreateInInventory("CarBattery");
2988 GetInventory().CreateInInventory("CarBattery");
2989 }
2990
2991 if (IsVitalTruckBattery())
2992 {
2993 GetInventory().CreateInInventory("TruckBattery");
2994 GetInventory().CreateInInventory("TruckBattery");
2995 }
2996
2997 if (IsVitalRadiator())
2998 {
2999 GetInventory().CreateInInventory("CarRadiator");
3000 GetInventory().CreateInInventory("CarRadiator");
3001 }
3002
3003 if (IsVitalSparkPlug())
3004 {
3005 GetInventory().CreateInInventory("SparkPlug");
3006 GetInventory().CreateInInventory("SparkPlug");
3007 }
3008
3009 if (IsVitalGlowPlug())
3010 {
3011 GetInventory().CreateInInventory("GlowPlug");
3012 GetInventory().CreateInInventory("GlowPlug");
3013 }
3014 }
3015
3016 protected void SpawnAdditionalItems()
3017 {
3018 GetInventory().CreateInInventory("Wrench");
3019 GetInventory().CreateInInventory("LugWrench");
3020 GetInventory().CreateInInventory("Screwdriver");
3021 GetInventory().CreateInInventory("EpoxyPutty");
3022
3023 GetInventory().CreateInInventory("CanisterGasoline");
3024
3025 EntityAI ent;
3026 ItemBase container;
3027 ent = GetInventory().CreateInInventory("CanisterGasoline");
3028 if (Class.CastTo(container, ent))
3029 {
3030 container.SetLiquidType(LIQUID_WATER, true);
3031 }
3032
3033 ent = GetInventory().CreateInInventory("Blowtorch");
3034 if (ent)
3035 {
3036 ent.GetInventory().CreateInInventory("LargeGasCanister");
3037 }
3038
3039 ent = GetInventory().CreateInInventory("Blowtorch");
3040 if (ent)
3041 {
3042 ent.GetInventory().CreateInInventory("LargeGasCanister");
3043 }
3044 }
3045
3046 protected void FillUpCarFluids()
3047 {
3048 Fill(CarFluid.FUEL, 200.0);
3049 Fill(CarFluid.COOLANT, 200.0);
3050 Fill(CarFluid.OIL, 200.0);
3051 }
3052
3053 protected override event typename GetOwnerStateType()
3054 {
3055 return CarScriptOwnerState;
3056 }
3057
3058 protected override event typename GetMoveType()
3059 {
3060 return CarScriptMove;
3061 }
3062
3063 protected override event void ObtainState(/*inout*/ PawnOwnerState pState)
3064 {
3065 auto state = CarScriptOwnerState.Cast(pState);
3066 state.m_fTime = m_Time;
3067 }
3068
3069 protected override event void RewindState(PawnOwnerState pState, /*inout*/ PawnMove pMove, inout NetworkRewindType pRewindType)
3070 {
3071 auto state = CarScriptOwnerState.Cast(pState);
3072 m_Time = state.m_fTime;
3073 }
3074
3075 // Cars that use the old networking only perform this part of the simulation on the server and not the clients
3076 // TODO(kumarjac): Obsolete this function once new networking is permanently enabled
3078 {
3079 bool isServer = GetGame().IsServer();
3080 if (isServer || GetNetworkMoveStrategy() != NetworkMoveStrategy.PHYSICS)
3081 {
3082 return isServer;
3083 }
3084
3085 return IsOwner();
3086 }
3087
3089 protected float m_BatteryEnergyStartMin = 5.0;
3090
3095 [Obsolete("no replacement")]
3096 bool OnBeforeSwitchLights(bool toOn)
3097 {
3098 return true;
3099 }
3100
3101 [Obsolete("no replacement")]
3103}
Param4< int, int, string, int > TSelectableActionInfoWithColor
Definition entityai.c:97
bool m_Initialized
eBleedingSourceType GetType()
CarHornActionData ActionData ActionCarHornShort()
map< typename, ref array< ActionBase_Basic > > TInputActionMap
ref NoiseParams m_NoisePar
ActionPushCarCB ActionPushObjectCB ActionPushCar()
void AddAction(typename actionName)
TInputActionMap m_InputActionMap
bool m_ActionsInitialize
void InitializeActions()
int m_DamageType
#define LIQUID_WATER
CarAutomaticGearboxMode
Enumerated automatic gearbox modes. (native, do not change or extend)
Definition car.c:69
CarSoundCtrl
Car's sound controller list. (native, do not change or extend)
Definition car.c:4
CarFluid
Type of vehicle's fluid. (native, do not change or extend)
Definition car.c:19
CarGearboxType
Enumerated gearbox types. (native, do not change or extend)
Definition car.c:35
enum CarDoorState START_NO_BATTERY
enum CarDoorState START_NO_FUEL
CarDoorState
Definition carscript.c:2
@ DOORS_CLOSED
Definition carscript.c:5
@ DOORS_MISSING
Definition carscript.c:3
@ DOORS_OPEN
Definition carscript.c:4
enum CarDoorState OK
enum CarDoorState NONE
enum CarDoorState LONG
enum CarDoorState NO_FUEL
override event void Read(PawnStateReader ctx)
Definition carscript.c:144
enum CarDoorState NO_BATTERY
enum CarDoorState STOP_OK
enum CarDoorState SHORT
enum CarDoorState LEFT
enum CarDoorState STARTING
enum CarDoorState OFF
enum CarDoorState REVERSE_ONLY
enum CarDoorState NO_IGNITER
enum CarDoorState START_OK
enum CarDoorState RIGHT
enum CarDoorState BRAKES_ONLY
override event void Write(PawnStateWriter ctx)
Definition carscript.c:139
enum CarDoorState START_NO_SPARKPLUG
enum CarDoorState RUINED
proto native bool IsServer()
proto float SurfaceGetType(float x, float z, out string type)
Returns: Y position the surface was found.
proto int GetTime()
returns mission time in milliseconds
int m_CarHornState
Definition carscript.c:271
float m_DrownTime
Definition carscript.c:193
float GetEnviroHeatComfortOverride()
override void OnGearChanged(int newGear, int oldGear)
Definition carscript.c:1895
vector m_side_2_2Pos
Definition carscript.c:231
override event void ObtainState(PawnOwnerState pState)
Definition carscript.c:3063
vector GetEnginePosWS()
Definition carscript.c:476
override void OnContact(string zoneName, vector localPos, IEntity other, Contact data)
WARNING: Can be called very frequently in one frame, use with caution.
Definition carscript.c:1324
ref EffVehicleSmoke m_engineFx
Definition carscript.c:213
bool IsVitalGlowPlug()
Definition carscript.c:2601
float m_FuelAmmount
keeps ammount of each fluid
Definition carscript.c:182
EffectSound CreateSoundForAnimationSource(string animSource)
Definition carscript.c:1547
void RemoveAction(typename actionName)
Definition carscript.c:2770
int m_CarEngineLastSoundState
Definition carscript.c:300
override vector GetDefaultHitPosition()
Definition carscript.c:2953
void CarScript()
Definition carscript.c:308
string GetActionCompNameOil()
Definition carscript.c:2680
void BrakeAndReverseRearLight()
Definition carscript.c:2207
override void MarkCrewMemberUnconscious(int crewMemberIndex)
Definition carscript.c:1756
int m_CarEngineSoundState
Definition carscript.c:299
bool IsVitalRadiator()
Definition carscript.c:2611
void OnIgnition()
Definition carscript.c:1818
float GetBatteryRechargeRate()
Definition carscript.c:2867
void BrakeLightsShineOn()
Definition carscript.c:2281
void CleanupSound(EffectSound sound)
Definition carscript.c:574
ItemBase GetBattery()
Definition carscript.c:2872
vector m_exhaustPtcDir
Definition carscript.c:221
override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
Definition carscript.c:521
float GetActionDistanceOil()
Definition carscript.c:2685
void LeftFrontLightShineOn()
Definition carscript.c:2219
vector m_coolantPtcPos
Definition carscript.c:223
override void MarkCrewMemberDead(int crewMemberIndex)
Definition carscript.c:1767
bool m_RearLightType
Definition carscript.c:265
void UpdateLightsServer(int newGear=-1)
Definition carscript.c:2080
void TailLightsShineOn()
Definition carscript.c:2303
vector GetEnginePointPosWS()
Definition carscript.c:486
void LeftFrontLightShineOff()
Definition carscript.c:2239
bool IsVitalTruckBattery()
Definition carscript.c:2596
EntityAI GetRadiator()
Definition carscript.c:2626
void SetEngineStarted(bool started)
Definition carscript.c:2648
void RightFrontLightShineOff()
Definition carscript.c:2249
override event GetMoveType()
Definition carscript.c:3058
void CheckVitalItem(bool isVital, string slot_name)
Definition carscript.c:2384
override void EEItemAttached(EntityAI item, string slot_name)
Definition carscript.c:686
void HandleCarHornSound(ECarHornState pState)
Definition carscript.c:1637
float m_BrakeAmmount
Definition carscript.c:185
override void OnFluidChanged(CarFluid fluid, float newValue, float oldValue)
Definition carscript.c:1784
bool GetCrashHeavySound()
Definition carscript.c:2455
ref EffectSound m_CrashSoundHeavy
Definition carscript.c:250
void ReverseLightsShineOn()
Definition carscript.c:2259
float m_EnviroHeatComfortOverride
Definition carscript.c:190
bool CheckOperationalState()
Definition carscript.c:1890
vector m_side_1_1Pos
Definition carscript.c:228
void UpdateHeadlightState()
Definition carscript.c:738
void UpdateBattery(ItemBase battery)
Definition carscript.c:2886
override float GetLiquidThroughputCoef()
Definition carscript.c:515
void ForceUpdateLightsEnd()
Definition carscript.c:2847
void HandleEngineSound(CarEngineSoundState state)
Definition carscript.c:1660
vector m_side_1_2Pos
Definition carscript.c:229
void LeakFluid(CarFluid fluid)
Definition carscript.c:2393
override bool CanPutIntoHands(EntityAI parent)
Definition carscript.c:2700
ref EffectSound m_CarHornSoundEffect
Definition carscript.c:255
void OnBrakesPressed()
Definition carscript.c:1143
bool m_HeadlightsOn
Definition carscript.c:262
vector m_enginePos
Definition carscript.c:225
void OnBrakesReleased()
Definition carscript.c:1148
float m_PlugHealth
Definition carscript.c:201
bool IsScriptedLightsOn()
Proper way to get if light is swiched on. Use instead of IsLightsOn().
Definition carscript.c:1939
override int Get3rdPersonCameraType()
camera type
Definition carscript.c:2642
bool m_HeadlightsState
Definition carscript.c:263
vector m_VelocityPrevTick
Definition carscript.c:171
override event void RewindState(PawnOwnerState pState, PawnMove pMove, inout NetworkRewindType pRewindType)
Definition carscript.c:3069
vector Get_1_1PointPosWS()
Definition carscript.c:498
override void OnEngineStop()
Gets called everytime the engine stops.
Definition carscript.c:1919
override void OnEngineStart()
Gets called everytime the engine starts.
Definition carscript.c:1902
void TailLightsShineOff()
Definition carscript.c:2328
float m_MomentumPrevTick
Definition carscript.c:170
override float OnSound(CarSoundCtrl ctrl, float oldValue)
Definition carscript.c:1524
override void OnUpdate(float dt)
Definition carscript.c:1249
ref EffVehicleSmoke m_coolantFx
Particles.
Definition carscript.c:212
void NoRearLight()
Definition carscript.c:2213
int CheckOperationalRequirements()
Definition carscript.c:1849
override string GetVehicleType()
Definition carscript.c:471
ref EffectSound m_WindowSmall
Definition carscript.c:251
void PlayCrashHeavySound()
Definition carscript.c:2469
float m_OilAmmount
Definition carscript.c:184
float GetBatteryConsumption()
Definition carscript.c:2857
vector m_enginePtcPos
Definition carscript.c:222
string GetDoorSelectionNameFromSeatPos(int posIdx)
Definition carscript.c:2552
void CleanupEffects()
Definition carscript.c:543
vector m_side_2_1Pos
Definition carscript.c:230
void SetActions()
Definition carscript.c:2728
NoiseSystem m_NoiseSystem
Definition carscript.c:257
ref NoiseParams m_NoisePar
Definition carscript.c:256
void CreateCarDestroyedEffect()
Definition carscript.c:676
void BrakesRearLight()
Definition carscript.c:2197
void PlaySoundEx(string soundset, EffectSound sound, out bool soundbool)
Definition carscript.c:2474
CarLightBase m_Headlight
Definition carscript.c:273
int GetCrewIndex(string selection)
Definition carscript.c:2562
bool GetCrashLightSound()
Definition carscript.c:2436
override bool CanReleaseAttachment(EntityAI attachment)
Definition carscript.c:857
override bool OnBeforeEngineStart()
Definition carscript.c:1811
vector m_frontPos
Definition carscript.c:226
override void OnAttachmentRuined(EntityAI attachment)
Definition carscript.c:820
vector GetCoolantPtcPosWS()
Definition carscript.c:481
float m_Time
Definition carscript.c:174
vector Get_2_1PointPosWS()
Definition carscript.c:506
float m_EngineHealth
Definition carscript.c:197
void ReverseRearLight()
Definition carscript.c:2202
void HandleSeatAdjustmentSound(string animSource, float phase)
Definition carscript.c:1616
override void OnVariablesSynchronized()
Definition carscript.c:655
CarRearLightBase m_RearLight
Definition carscript.c:274
string GetAnimSourceFromSelection(string selection)
Definition carscript.c:2503
bool IsMoving()
Definition carscript.c:2631
override bool DetectFlipped(VehicleFlippedContext ctx)
Definition carscript.c:1240
override void EEInit()
Definition carscript.c:431
void CarPartsHealthCheck()
Definition carscript.c:2416
vector m_exhaustPtcPos
Definition carscript.c:220
void SetCarHornState(int pState)
Definition carscript.c:2925
void FillUpCarFluids()
Definition carscript.c:3046
void SynchCrashHeavySound(bool play)
Definition carscript.c:2460
override void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
Definition carscript.c:2788
string GetSelectionFromAnimSource(string animSource)
Definition carscript.c:2508
bool m_EngineStarted
Definition carscript.c:268
override bool OnAction(int action_id, Man player, ParamsReadContext ctx)
Definition carscript.c:603
void DashboardShineOff()
Definition carscript.c:2349
string GetActionCompNameCoolant()
Definition carscript.c:2670
bool IsVitalCarBattery()
Definition carscript.c:2591
override void EEItemDetached(EntityAI item, string slot_name)
Definition carscript.c:761
CarLightBase CreateFrontLight()
Definition carscript.c:2366
void CheckContactCache()
Responsible for damaging the car according to contact events from OnContact.
Definition carscript.c:1353
float m_RadiatorHealth
Definition carscript.c:198
void OnVehicleJumpOutServer(GetOutTransportActionData gotActionData)
Definition carscript.c:1164
void SynchCrashLightSound(bool play)
Definition carscript.c:2441
override void OnAnimationPhaseStarted(string animSource, float phase)
Definition carscript.c:1539
void GenerateCarHornAINoise(int pState)
Definition carscript.c:2936
override void EEDelete(EntityAI parent)
Definition carscript.c:529
void PlayCrashLightSound()
Definition carscript.c:2450
float m_FuelTankHealth
Definition carscript.c:199
CarDoorState TranslateAnimationPhaseToCarDoorState(string animation)
Definition carscript.c:2658
void HandleDoorsSound(string animSource, float phase)
Definition carscript.c:1592
void ReverseLightsShineOff()
Definition carscript.c:2270
ref EffectSound m_CrashSoundLight
Definition carscript.c:249
float m_CoolantAmmount
Definition carscript.c:183
override event GetOwnerStateType()
Definition carscript.c:3053
int m_exhaustPtcFx
Definition carscript.c:218
vector Get_1_2PointPosWS()
Definition carscript.c:502
override void EEKilled(Object killer)
Definition carscript.c:1317
override void GetDebugActions(out TSelectableActionInfoArrayEx outputList)
Definition carscript.c:579
float GetBatteryRuntimeConsumption()
Definition carscript.c:2862
ref EffectSound m_WindowLarge
Definition carscript.c:252
ref EffVehicleSmoke m_exhaustFx
Definition carscript.c:214
bool m_EngineDestroyed
Definition carscript.c:269
override void OnDriverExit(Human player)
Definition carscript.c:1153
bool OnBeforeSwitchLights(bool toOn)
Definition carscript.c:3096
static vector m_DrownEnginePos
Definition carscript.c:194
override bool CanReceiveAttachment(EntityAI attachment, int slotId)
Definition carscript.c:828
vector GetBackPointPosWS()
Definition carscript.c:494
void SpawnUniversalParts()
Definition carscript.c:2978
float GetActionDistanceBrakes()
Definition carscript.c:2695
void AddAction(typename actionName)
Definition carscript.c:2739
vector m_backPos
Definition carscript.c:227
bool IsVitalEngineBelt()
Definition carscript.c:2606
string GetDoorConditionPointFromSelection(string selection)
Definition carscript.c:2531
string GetActionCompNameBrakes()
Definition carscript.c:2690
bool m_PlayCrashSoundLight
Definition carscript.c:259
ref array< int > m_WheelSmokePtcFx
Definition carscript.c:297
vector Get_2_2PointPosWS()
Definition carscript.c:510
float GetPushForceCoefficientMultiplier()
Definition carscript.c:2958
void CheckVitalItem(bool isVital, int slotId)
Definition carscript.c:2371
void DashboardShineOn()
Definition carscript.c:2339
bool m_ForceUpdateLights
Definition carscript.c:267
override bool CanReachSeatFromDoors(string pSeatSelection, vector pFromPos, float pDistance=1.0)
Definition carscript.c:2567
CarRearLightBase CreateRearLight()
Definition carscript.c:2360
string GetDoorInvSlotNameFromSeatPos(int posIdx)
Definition carscript.c:2557
void SpawnAdditionalItems()
Definition carscript.c:3016
void RightFrontLightShineOn()
Definition carscript.c:2229
ref CarContactCache m_ContactCache
Definition carscript.c:172
float m_BatteryHealth
Definition carscript.c:200
override void GetActions(typename action_input_type, out array< ActionBase_Basic > actions)
Definition carscript.c:2717
bool CanManipulateSpareWheel(string slotSelectionName)
Definition carscript.c:889
void SetCarEngineSoundState(CarEngineSoundState pState)
Definition carscript.c:1654
vector GetFrontPointPosWS()
Definition carscript.c:490
bool HasRadiator()
Definition carscript.c:2621
void DamageCrew(float dmg)
Responsible for damaging crew in a car crash.
Definition carscript.c:1462
void ForceUpdateLightsStart()
Definition carscript.c:2838
override void EEOnCECreate()
Definition carscript.c:2824
void UpdateLights(int new_gear=-1)
Definition carscript.c:1953
int m_coolantPtcFx
Definition carscript.c:217
override bool IsInventoryVisible()
Definition carscript.c:2783
void PlaySound(string soundset, EffectSound sound, out bool soundbool)
Definition carscript.c:2498
void BrakeLightsShineOff()
Definition carscript.c:2292
override void EOnPostSimulate(IEntity other, float timeSlice)
Definition carscript.c:894
void ~CarScript()
Definition carscript.c:536
ref array< ref EffWheelSmoke > m_WheelSmokeFx
Definition carscript.c:296
bool IsHandbrakeActive()
Definition carscript.c:2636
bool m_BrakesArePressed
Definition carscript.c:264
bool IsVitalFuelTank()
Definition carscript.c:2616
bool IsServerOrOwner()
Definition carscript.c:3077
void InitializeActions()
Definition carscript.c:2705
void UpdateLightsClient(int newGear=-1)
Definition carscript.c:1961
int m_enginePtcFx
Definition carscript.c:216
bool m_PlayCrashSoundHeavy
Definition carscript.c:260
EntityAI m_Radiator
Definition carscript.c:203
void ToggleHeadlights()
Switches headlights on/off, including the illumination of the control panel and synchronizes this cha...
Definition carscript.c:1945
int GetCarDoorsState(string slotType)
Definition carscript.c:2653
float GetActionDistanceCoolant()
Definition carscript.c:2675
Definition car.c:90
override CarRearLightBase CreateRearLight()
override string GetDoorConditionPointFromSelection(string selection)
override CarLightBase CreateFrontLight()
override bool IsVitalGlowPlug()
override bool IsVitalTruckBattery()
override string GetAnimSourceFromSelection(string selection)
override void SetActions()
override bool IsVitalRadiator()
Definition offroad_02.c:385
override bool IsVitalCarBattery()
override bool IsVitalSparkPlug()
Definition offroad_02.c:380
bool CanManipulateSpareWheel(string slotSelectionName)
Super root of all classes in Enforce script.
Definition enscript.c:11
Definition debug.c:2
Wrapper class for managing sound through SEffectManager.
Definition effectsound.c:5
void SetSoundSet(string snd)
Set soundset for the sound.
override void SetAutodestroy(bool auto_destroy)
Sets whether Effect automatically cleans up when it stops.
void SetSoundWaveKind(WaveKind wave_kind)
Set WaveKind for the sound.
void SetSoundFadeOut(float fade_out)
Set the sound fade out duration.
bool IsSoundPlaying()
Get whether EffectSound is currently playing.
override void SetParent(Object parent_obj, int pivot)
Set parent for the sound to follow.
bool SoundPlay()
Plays sound.
InventoryLocation.
provides access to slot configuration
Definition enmath.c:7
Manager class for managing Effect (EffectParticle, EffectSound)
static EffectSound PlaySoundCachedParams(string sound_set, vector position, float play_fade_in=0, float stop_fade_out=0, bool loop=false)
Create and play an EffectSound, using or creating cached SoundParams.
static int PlayOnObject(notnull Effect eff, Object obj, vector local_pos="0 0 0", vector local_ori="0 0 0", bool force_rotation_relative_to_world=false)
Play an Effect.
static int CreateParticleServer(vector pos, EffecterParameters parameters)
returns unique effecter ID
static void Stop(int effect_id)
Stops the Effect.
static bool IsEffectExist(int effect_id)
Checks whether an Effect ID is registered in SEffectManager.
static int EffectRegister(Effect effect)
Registers Effect in SEffectManager.
static void DestroyEffect(Effect effect)
Unregisters, stops and frees the Effect.
Serialization general interface. Serializer API works with:
Definition serializer.c:56
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
void Synchronize()
DamageType
exposed from C++ (do not change)
DayZPlayerConstants
defined in C++
Definition dayzplayer.c:602
EActions
Definition eactions.c:2
float m_Time
Definition environment.c:59
ERPCs
Definition erpcs.c:2
proto native CGame GetGame()
proto void Print(void var)
Prints content of variable to console/log.
array< string > TStringArray
Definition enscript.c:709
void Obsolete(string msg="")
Definition enscript.c:371
EntityEvent
Entity events for event-mask, or throwing event from code.
Definition enentity.c:45
@ CONTACT
Definition enentity.c:97
const float LIQUID_THROUGHPUT_CAR_DEFAULT
Definition constants.c:572
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
proto native vector dBodyGetVelocityAt(notnull IEntity body, vector globalpos)
proto native vector GetVelocity(notnull IEntity ent)
Returns linear velocity.
proto native float dBodyGetMass(notnull IEntity ent)
const int SAT_DEBUG_ACTION
Definition constants.c:454
class JsonUndergroundAreaTriggerData GetPosition
const int CALL_CATEGORY_GAMEPLAY
Definition tools.c:10
bool IsOwner()
Definition hand_events.c:60
class BoxCollidingParams component
ComponentInfo for BoxCollidingResult.
string Type
string GetDebugText()
PlayerBase GetPlayer()
class NoiseSystem NoiseParams()
Definition noise.c:15
float GetTime()
ProcessDirectDamageFlags
Definition object.c:2
WaveKind
Definition sound.c:2