Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_VehicleDamageManagerComponent.c
Go to the documentation of this file.
1 enum EVehicleHitZoneGroup : EHitZoneGroup
2 {
3  HULL = 10,
4  ENGINE = 20,
5  DRIVE_TRAIN = 30,
6  FUEL_TANKS = 40,
7  WHEELS = 50,
8  CARGO = 60,
10  TURRET = 80,
11  OPTICS = 90,
13  VIEWPORT = 100,
15  TAIL_ROTOR = 111,
16  LANDING_GEAR = 120,
17  PROPELLER = 130,
18  INSTRUMENTS = 140,
19  CONTROLS = 150,
20  LIGHT = 160,
21 }
22 
23 //#define VEHICLE_DAMAGE_DEBUG
24 //#define VEHICLE_DEBUG_OTHER
26 {
27  [Attribute("1.5", desc: "Max distance of hitzone, which should receive damage, from contact point.", category: "Collision Damage")]
28  protected float m_fMaxSharedDamageDistance;
29 
30  [Attribute("0.7", desc: "Damage multiplier for collisions from this side", params: "0.01 1000 0.01", category: "Collision Damage")]
32 
33  [Attribute("0.7", desc: "Damage multiplier for collisions from this side", params: "0.01 1000 0.01", category: "Collision Damage")]
35 
36  [Attribute("1", desc: "Damage multiplier for collisions from this side", params: "0.01 1000 0.01", category: "Collision Damage")]
38 
39  [Attribute("1.5", desc: "Damage multiplier for collisions from this side", params: "0.01 1000 0.01", category: "Collision Damage")]
41 
42  [Attribute("1.5", desc: "Damage multiplier for collisions from this side", params: "0.01 1000 0.01", category: "Collision Damage")]
44 
45  [Attribute("2", desc: "Damage multiplier for collisions from this side", params: "0.01 1000 0.01", category: "Collision Damage")]
47 
48  [Attribute("30", "Speed in km/h over which will occupants be dealt damage in collision", category: "Collision Damage")]
50 
51  [Attribute("100", "Speed in km/h over which will occupants die in collision", category: "Collision Damage")]
52  protected float m_fOccupantsSpeedDeath;
53 
54  [Attribute("0 0 0", "Position for frontal impact calculation", category: "Collision Damage", params: "inf inf 0 purpose=coords space=entity coordsVar=m_vFrontalImpact")]
55  protected vector m_vFrontalImpact;
56 
57  //------------------------------------------------------------------------------------------------
60  {
61  return m_fMaxSharedDamageDistance;
62  }
63 
64  //------------------------------------------------------------------------------------------------
67  {
68  return m_fFrontMultiplier;
69  }
70 
71  //------------------------------------------------------------------------------------------------
74  {
75  return m_fBottomMultiplier;
76  }
77 
78  //------------------------------------------------------------------------------------------------
81  {
82  return m_fRearMultiplier;
83  }
84 
85  //------------------------------------------------------------------------------------------------
88  {
89  return m_fLeftMultiplier;
90  }
91 
92  //------------------------------------------------------------------------------------------------
95  {
96  return m_fRightMultiplier;
97  }
98 
99  //------------------------------------------------------------------------------------------------
102  {
103  return m_fTopMultiplier;
104  }
105 
106  //------------------------------------------------------------------------------------------------
109  {
111  }
112 
113  //------------------------------------------------------------------------------------------------
116  {
117  return m_fOccupantsSpeedDeath;
118  }
119 
120  //------------------------------------------------------------------------------------------------
123  {
124  return m_vFrontalImpact;
125  }
126 
127  //------------------------------------------------------------------------------------------------
128  // constructor
130  void SCR_VehicleDamageManagerComponentClass(BaseContainer prefab);
131 }
132 
134 {
135  NORMAL = 0,
146 }
147 
148 class SCR_VehicleDamageManagerComponent : SCR_DamageManagerComponent
149 {
150  protected const int MIN_RESPONSE_INDEX = SCR_EPhysicsResponseIndex.TINY_MOMENTUM;
151  protected const int MAX_RESPONSE_INDEX = SCR_EPhysicsResponseIndex.HUGE_MOMENTUM;
152 
153  static ref map<SCR_EPhysicsResponseIndex, float> s_mResponseIndexMomentumMap = new map<SCR_EPhysicsResponseIndex, float>();
154 
155  [Attribute("0", desc: "Print relative force in collisions of this vehicle? Can be used to determine ideal Collision Damage Force Threshold.", category: "Debug")]
156  protected bool m_bPrintRelativeForce;
157 
158  [Attribute("0", "Frontal impact damage needed to destroy this vehicle\nTakes into account current damage multipliers\nUse context menu on Damage Manager component to compute this value.\n[hp]", category: "Collision Damage")]
159  protected float m_fVehicleDestroyDamage;
160 
161  [Attribute("15", "Speed of collision that damages the vehicle\n[km/h]", category: "Collision Damage")]
162  protected float m_fVehicleDamageSpeedThreshold;
163 
164  [Attribute("120", "Speed of collision that destroys the vehicle\n[km/h]", category: "Collision Damage")]
165  protected float m_fVehicleSpeedDestroy;
166 
167  [Attribute("0.7", "Engine efficiency at which it is considered to be malfunctioning\n[x * 100%]", category: "Vehicle Damage")]
168  protected float m_fEngineMalfunctioningThreshold;
169 
170  [Attribute(defvalue: "VehicleFireState", desc: "Vehicle parts fire state signal name", category: "Secondary damage")]
171  protected string m_sVehicleFireStateSignal;
172 
173  [Attribute(defvalue: "FuelTankFireState", desc: "Fuel tank fire signal name", category: "Secondary damage")]
174  protected string m_sFuelTankFireStateSignal;
175 
176  [Attribute(defvalue: "SuppliesFireState", desc: "Supplies fire signal name", category: "Secondary damage")]
177  protected string m_sSuppliesFireStateSignal;
178 
179  [Attribute(defvalue: "0.02", desc: "Fuel tank fire damage rate\n[x * 100%]", params: "0 100 0.001", category: "Secondary damage")]
180  protected float m_fFuelTankFireDamageRate;
181 
182  [Attribute(defvalue: "0.02", desc: "Supplies fire damage rate\n[x * 100%]", params: "0 100 0.001", category: "Secondary damage")]
183  protected float m_fSuppliesFireDamageRate;
184 
185  [Attribute(defvalue: "1", desc: "Delay between secondary fire damage\n[s]", params: "0 10000 0.1", category: "Secondary damage")]
186  protected float m_fSecondaryFireDamageDelay;
187 
188  protected bool m_bIsInContact;
189  protected float m_fMaxRelativeForce;
190  protected float m_fMinImpulse;
191  protected SCR_BaseCompartmentManagerComponent m_CompartmentManager;
192 
193  protected static ref ScriptInvokerInt s_OnVehicleDestroyed;
194 
196  protected ref array<HitZone> m_aVehicleHitZones = {};
197  protected CompartmentControllerComponent m_Controller;
198  protected VehicleBaseSimulation m_Simulation;
199 
200  protected float m_fEngineEfficiency = 1;
201  protected bool m_bEngineFunctional = true;
202 
203  protected float m_fGearboxEfficiency = 1;
204  protected bool m_bGearboxFunctional = true;
205 
206  // The vehicle damage manager needs to know about all the burning hitzones that it consists of
207  protected ref array<SCR_FlammableHitZone> m_aFlammableHitZones;
208  protected SignalsManagerComponent m_SignalsManager;
209 
210  // Vehicle fire
212 
213  // Fuel tanks fire
214  protected ParticleEffectEntity m_FuelTankFireParticle; // Burning fuel particle
215  protected FuelManagerComponent m_FuelManager;
217 
218  // Supplies fire
219  protected ParticleEffectEntity m_SuppliesFireParticle; // Burning supplies particle
221 
222  // Audio features
226 
227  // Impact FX
228  protected SCR_ImpactEffectComponent m_ImpactEffectComponent;
229 
230  [RplProp(onRplName: "OnVehicleFireStateChanged")]
231  SCR_ESecondaryExplosionScale m_eVehicleFireState;
232 
233  [RplProp(onRplName: "OnFuelTankFireStateChanged")]
234  SCR_ESecondaryExplosionScale m_eFuelTankFireState;
235 
236  [RplProp(onRplName: "OnSuppliesFireStateChanged")]
237  SCR_ESecondaryExplosionScale m_eSuppliesFireState;
238 
239  [RplProp()]
240  protected vector m_vVehicleFireOrigin;
241 
242  [RplProp()]
243  protected vector m_vFuelTankFireOrigin;
244 
245  [RplProp()]
246  protected vector m_vSuppliesFireOrigin;
247 
248  // Sound
249  protected static const float APPROXIMATE_CHARACTER_LETHAL_DAMAGE = 150;
250 
251 #ifdef VEHICLE_DAMAGE_DEBUG
252  protected ref array<ref Shape> m_aDebugShapes = {};
253 #endif
254 #ifdef VEHICLE_DEBUG_OTHER
255  protected ref array<ref Shape> m_aDebugShapes = {};
256 #endif
257 
258  //------------------------------------------------------------------------------------------------
261  {
262  return SCR_VehicleDamageManagerComponentClass.Cast(GetComponentData(GetOwner()));
263  }
264 
265  //------------------------------------------------------------------------------------------------
267  float GetTopMultiplier()
268  {
270  if (!prefabData)
271  return 2;
272 
273  return prefabData.GetTopMultiplier();
274  }
275 
276  //------------------------------------------------------------------------------------------------
278  float GetRightMultiplier()
279  {
281  if (!prefabData)
282  return 1.5;
283 
284  return prefabData.GetRightMultiplier();
285  }
286 
287  //------------------------------------------------------------------------------------------------
289  float GetLeftMultiplier()
290  {
292  if (!prefabData)
293  return 1.5;
294 
295  return prefabData.GetLeftMultiplier();
296  }
297 
298  //------------------------------------------------------------------------------------------------
300  float GetRearMultiplier()
301  {
303  if (!prefabData)
304  return 1;
305 
306  return prefabData.GetRearMultiplier();
307  }
308 
309  //------------------------------------------------------------------------------------------------
311  float GetBottomMultiplier()
312  {
314  if (!prefabData)
315  return 0.7;
316 
317  return prefabData.GetBottomMultiplier();
318  }
319 
320  //------------------------------------------------------------------------------------------------
322  float GetFrontMultiplier()
323  {
325  if (!prefabData)
326  return 0.7;
327 
328  return prefabData.GetFrontMultiplier();
329  }
330 
331  //------------------------------------------------------------------------------------------------
334  {
336  if (!prefabData)
337  return 1.5;
338 
339  return prefabData.GetMaxSharedDamageDistance();
340  }
341 
342  //------------------------------------------------------------------------------------------------
345  {
347  if (!prefabData)
348  return 30;
349 
350  return prefabData.GetOccupantsDamageSpeedThreshold();
351  }
352 
353  //------------------------------------------------------------------------------------------------
355  float GetOccupantsSpeedDeath()
356  {
358  if (!prefabData)
359  return 80;
360 
361  return prefabData.GetOccupantsSpeedDeath();
362  }
363 
364  //------------------------------------------------------------------------------------------------
366  vector GetFrontalImpact()
367  {
369  if (!prefabData)
370  return "0 1 1";
371 
372  return prefabData.GetFrontalImpact();
373  }
374 
375  //------------------------------------------------------------------------------------------------
379  {
380  switch (side)
381  {
382  case SCR_EBoxSide.FRONT:
383  return GetFrontMultiplier();
384  case SCR_EBoxSide.REAR:
385  return GetRearMultiplier();
386  case SCR_EBoxSide.BOTTOM:
387  return GetBottomMultiplier();
388  case SCR_EBoxSide.TOP:
389  return GetTopMultiplier();
390  case SCR_EBoxSide.LEFT:
391  return GetLeftMultiplier();
392  case SCR_EBoxSide.RIGHT:
393  return GetRightMultiplier();
394 
395  }
396 
397  return 1;
398  }
399 
400  //------------------------------------------------------------------------------------------------
402  bool IsInContact()
403  {
404  return m_bIsInContact;
405  }
406 
407  //------------------------------------------------------------------------------------------------
408  override void OnPostInit(IEntity owner)
409  {
410  super.OnPostInit(owner);
411 
412  Vehicle vehicle = Vehicle.Cast(owner);
413  if (!vehicle)
414  return;
415 
416  m_CompartmentManager = SCR_BaseCompartmentManagerComponent.Cast(vehicle.FindComponent(SCR_BaseCompartmentManagerComponent));
417  m_Controller = CompartmentControllerComponent.Cast(owner.FindComponent(CompartmentControllerComponent));
418  m_Simulation = VehicleBaseSimulation.Cast(owner.FindComponent(VehicleBaseSimulation));
419  m_FuelManager = FuelManagerComponent.Cast(owner.FindComponent(FuelManagerComponent));
420  m_SignalsManager = SignalsManagerComponent.Cast(owner.FindComponent(SignalsManagerComponent));
421  m_ImpactEffectComponent = SCR_ImpactEffectComponent.Cast(owner.FindComponent(SCR_ImpactEffectComponent));
422 
423  if (m_SignalsManager)
424  {
428  }
429 
431 
432  RplComponent rpl = vehicle.GetRplComponent();
433  if (rpl && rpl.IsProxy())
434  return;
435 
436  Physics physics = owner.GetPhysics();
437  if (physics)
438  m_fMinImpulse = physics.GetMass() * 2;
439 
440  if (m_fMinImpulse > 0)
441  SetEventMask(owner, EntityEvent.CONTACT);
442  }
443 
444  //------------------------------------------------------------------------------------------------
447  // Register simulation feature hit zone
448  void RegisterVehicleHitZone(notnull HitZone hitZone)
449  {
450  // Remove the hitzone if it was already registered
451  if (!m_aVehicleHitZones.Contains(hitZone))
452  m_aVehicleHitZones.Insert(hitZone);
453  }
454 
455  //------------------------------------------------------------------------------------------------
458  // Register simulation feature hit zone
460  {
461  m_aVehicleHitZones.RemoveItem(hitZone);
462  }
463 
464  //------------------------------------------------------------------------------------------------
468  {
469  int engineCount;
470  float engineEfficiency;
471  bool engineFunctional;
472 
473  int gearboxCount;
474  float gearboxEfficiency;
475  bool gearboxFunctional;
476 
477  SCR_EngineHitZone engineHitZone;
478  SCR_GearboxHitZone gearboxHitZone;
479 
480  foreach (HitZone hitZone : m_aVehicleHitZones)
481  {
482  engineHitZone = SCR_EngineHitZone.Cast(hitZone);
483  if (engineHitZone)
484  {
485  engineCount++;
486  engineEfficiency += engineHitZone.GetEfficiency();
487 
488  if (engineHitZone.GetDamageState() != EDamageState.DESTROYED)
489  engineFunctional = true;
490 
491  continue;
492  }
493 
494  gearboxHitZone = SCR_GearboxHitZone.Cast(hitZone);
495  if (gearboxHitZone)
496  {
497  gearboxCount++;
498  gearboxEfficiency += gearboxHitZone.GetEfficiency();
499 
500  if (gearboxHitZone.GetDamageState() != EDamageState.DESTROYED)
501  gearboxFunctional = true;
502 
503  continue;
504  }
505  }
506 
507  if (engineCount > 0)
508  {
509  SetEngineFunctional(engineFunctional);
510  SetEngineEfficiency(engineEfficiency / engineCount);
511  }
512 
513  if (gearboxCount > 0)
514  {
515  SetGearboxFunctional(gearboxFunctional);
516  SetGearboxEfficiency(gearboxEfficiency / gearboxCount);
517  }
518 
520  }
521 
522  //------------------------------------------------------------------------------------------------
525  {
526  float movementDamage;
527 
528  if (!m_bEngineFunctional)
529  movementDamage = 1;
530  else
531  movementDamage = 1 - (m_fGearboxEfficiency * m_fEngineEfficiency);
532 
533  SetMovementDamage(movementDamage);
534 
535  VehicleControllerComponent controller = VehicleControllerComponent.Cast(m_Controller);
536  if (controller)
537  controller.SetCanMove(movementDamage < 1);
538  }
539 
540  //------------------------------------------------------------------------------------------------
543  {
544  return m_bEngineFunctional;
545  }
546 
547  //------------------------------------------------------------------------------------------------
548  protected void SetEngineFunctional(bool functional)
549  {
550  m_bEngineFunctional = functional;
551 
552  if (functional)
553  return;
554 
556  {
557  VehicleControllerComponent controller = VehicleControllerComponent.Cast(m_Controller);
558  if (controller && controller.IsEngineOn())
559  controller.StopEngine(false);
560  }
561  else
562  {
563  VehicleControllerComponent_SA controller = VehicleControllerComponent_SA.Cast(m_Controller);
564  if (controller && controller.IsEngineOn())
565  controller.StopEngine(false);
566  }
567  }
568 
569  //------------------------------------------------------------------------------------------------
572  {
573  return m_fEngineMalfunctioningThreshold;
574  }
575 
576  //------------------------------------------------------------------------------------------------
579  {
580  return m_fEngineEfficiency;
581  }
582 
583  //------------------------------------------------------------------------------------------------
584  protected void SetEngineEfficiency(float efficiency)
585  {
586  m_fEngineEfficiency = efficiency;
587 
589  {
590  VehicleWheeledSimulation simulation = VehicleWheeledSimulation.Cast(m_Simulation);
591  if (simulation && simulation.IsValid())
592  {
593  simulation.EngineSetPeakTorqueState(efficiency * simulation.EngineGetPeakTorque());
594  simulation.EngineSetPeakPowerState(efficiency * simulation.EngineGetPeakPower());
595  }
596  }
597  else
598  {
599  VehicleWheeledSimulation_SA simulation = VehicleWheeledSimulation_SA.Cast(m_Simulation);
600  if (simulation && simulation.IsValid())
601  {
602  simulation.EngineSetPeakTorqueState(efficiency * simulation.EngineGetPeakTorque());
603  simulation.EngineSetPeakPowerState(efficiency * simulation.EngineGetPeakPower());
604  }
605  }
606  }
607 
608  //------------------------------------------------------------------------------------------------
609  protected void SetGearboxFunctional(bool functional)
610  {
611  m_bGearboxFunctional = functional;
613  {
614  VehicleControllerComponent controller = VehicleControllerComponent.Cast(m_Controller);
615  if (controller)
616  controller.SetCanMove(functional);
617  }
618  else
619  {
620  VehicleControllerComponent_SA controller = VehicleControllerComponent_SA.Cast(m_Controller);
621  if (controller)
622  controller.SetCanMove(functional);
623  }
624  }
625 
626  //------------------------------------------------------------------------------------------------
629  {
630  return m_bGearboxFunctional;
631  }
632 
633  //------------------------------------------------------------------------------------------------
636  {
637  return m_fGearboxEfficiency;
638  }
639 
640  //------------------------------------------------------------------------------------------------
641  protected void SetGearboxEfficiency(float efficiency)
642  {
643  m_fGearboxEfficiency = efficiency;
644 
646  {
647  VehicleWheeledSimulation simulation = VehicleWheeledSimulation.Cast(m_Simulation);
648  if (simulation && simulation.IsValid())
649  simulation.GearboxSetEfficiencyState(efficiency * simulation.GearboxGetEfficiency());
650  }
651  else
652  {
653  VehicleWheeledSimulation_SA simulation = VehicleWheeledSimulation_SA.Cast(m_Simulation);
654  if (simulation && simulation.IsValid())
655  simulation.GearboxSetEfficiencyState(efficiency * simulation.GearboxGetEfficiency());
656  }
657  }
658 
659  //------------------------------------------------------------------------------------------------
665  float DamageSurroundingHitzones(vector position, float damage, EDamageType damageType)
666  {
667  Physics physics = GetOwner().GetPhysics();
668  if (!physics)
669  return damage;
670 
671  array<HitZone> hitzones = {};
672 
673  int count = GetAllHitZones(hitzones);
674  float maxSharedDamageDistance = GetMaxSharedDamageDistance();
675  float maxDistanceSq = maxSharedDamageDistance * maxSharedDamageDistance; //SQUARE it for faster calculations of distance
676 
677  array<string> hitzoneColliderNames = {};
678  vector closestPosition;
679  int colliderCount;
680  float distancePercent;
681  float currentDistance;
682  float minDistance;
683  int geomIndex;
684  vector mat[4];
685  HitZone hitzone;
686  int hitzonesInRangeCount;
687  float hitzonesDistancePercentSum;
688  HitZoneContainerComponent hitzoneContainer;
689  IEntity hitzoneParentEntity;
690  vector mins, maxs;
691  vector center;
692 
693  map<HitZone, float> hitzoneDistancePercentMap = new map<HitZone, float>();
694  for (int i = count - 1; i >= 0; i--)
695  {
696  hitzone = hitzones[i];
697  minDistance = float.MAX;
698  colliderCount = hitzone.GetAllColliderNames(hitzoneColliderNames); //The array is cleared inside the GetAllColliderNames method
699 
700  if (colliderCount == 0)
701  {
702  hitzoneContainer = hitzone.GetHitZoneContainer();
703  if (!hitzoneContainer || hitzoneContainer == this)
704  continue;
705 
706  hitzoneParentEntity = hitzoneContainer.GetOwner();
707  hitzoneParentEntity.GetBounds(mins, maxs);
708 
709  for (int j = 0; j < 3; j++)
710  center[j] = mins[j] + Math.AbsFloat(((maxs[j] - mins[j]) * 0.5));
711 
712  minDistance = vector.DistanceSq(position, hitzoneParentEntity.CoordToParent(center));
713  }
714  else
715  {
716  for (int y = colliderCount - 1; y >= 0; y--)
717  {
718  geomIndex = physics.GetGeom(hitzoneColliderNames[y]);
719  if (geomIndex == -1)
720  continue;
721 
722  physics.GetGeomWorldTransform(geomIndex, mat);
723  currentDistance = vector.DistanceSq(position, mat[3]);
724 
725  if (currentDistance < minDistance)
726  {
727  minDistance = currentDistance;
728  closestPosition = mat[3];
729  }
730  }
731  }
732 
733  if (minDistance > maxDistanceSq)
734  continue;
735 
736  minDistance = Math.Sqrt(minDistance);
737  distancePercent = 1 - minDistance / GetMaxSharedDamageDistance();
738 
739  hitzonesInRangeCount++;
740  hitzonesDistancePercentSum += distancePercent;
741  hitzoneDistancePercentMap.Insert(hitzone, distancePercent);
742  }
743 
744  float leftoverDamage = damage;
745  float currentDamage;
746  float currentDamagePercent;
747  float hitzoneHealth;
748  float damageMultiplier;
749 
750  DamageManagerComponent damageManager;
751 
752  vector empty[3];
753  empty[0] = vector.Zero;
754  empty[1] = vector.Zero;
755  empty[2] = vector.Zero;
756 
757  for (int i = hitzonesInRangeCount - 1; i >= 0; i--)
758  {
759  hitzone = hitzoneDistancePercentMap.GetKey(i);
760  distancePercent = hitzoneDistancePercentMap.Get(hitzone);
761  currentDamagePercent = distancePercent / hitzonesDistancePercentSum;
762 
763  currentDamage = currentDamagePercent * damage;
764 
765  //TODO @Vojta LEVEL2: This currentDamage calculation that is being done here is automatically done by the HandleDamage.
766  //This means that we are applying damage reduction twice.
767  //Also you are dividing with the damage multiplier, making it the opposite effect.
768 
769  hitzoneHealth = hitzone.GetHealth();
770 
771  damageMultiplier = hitzone.GetDamageMultiplier(damageType) * hitzone.GetBaseDamageMultiplier();
772  if (damageMultiplier != 0)
773  currentDamage = Math.Clamp(currentDamage, 0, (hitzoneHealth + hitzone.GetDamageReduction()) / damageMultiplier);
774 
775  damageManager = DamageManagerComponent.Cast(hitzone.GetHitZoneContainer());
776  if (!damageManager)
777  continue;
778 
779  SCR_DamageContext damageContext = new SCR_DamageContext(damageType, currentDamage, empty, GetOwner(), hitzone, Instigator.CreateInstigator(null), null, -1, -1);
780  damageManager.HandleDamage(damageContext);
781 
782  leftoverDamage -= currentDamage;
783  }
784 
785  leftoverDamage = Math.Clamp(leftoverDamage, 0, float.MAX);
786 
787  return leftoverDamage;
788  }
789 
790  //------------------------------------------------------------------------------------------------
793  // TODO: This won't work properly for all the types of objects - E.G. flat boats with huge towers on them
794  // e.g x = collision point, this will say it got hit from the back, because it's inside the rear-side pyramid
795  // ||
796  // __x___||_______
797  // \ /
798  // \ /
799  // /TODO
800  // To trigger this, just crash a vehicle into something
801  // Make sure the vehicle has SCR_VehicleDamageManagerComponent with attribute "Print Relative Force" set to true.
803  {
804  IEntity owner = GetOwner();
805  //Get local space contact position
806  vector contact = owner.CoordToLocal(position);
807 
808  //Get local space mins and maxs
809  vector mins, maxs;
810  owner.GetBounds(mins, maxs);
811 
812  //Calculate bbox center
813  vector bboxCenter = (maxs - mins) * 0.5 + mins;
814 
815  //Get contact position relative to the bbox center, for correct dot product calculations later
816  contact = contact - bboxCenter;
817 
818  //Here we calculate all the normals of our 6 planes as well as their distances, but these broke the code completely, so I commented them out.
819  //Naming: XZA = plane A perpendicular to the X-Z plane and so on...
820  vector normalXZA, normalXZB, normalYZA, normalYZB, normalXYA, normalXYB;
821  float distanceXZA, distanceXZB, distanceYZA, distanceYZB, distanceXYA, distanceXYB;
822 
823  normalYZA = Vector(0, mins[2] - maxs[2], maxs[1] - mins[1]).Normalized();
824  distanceYZA = vector.Dot(normalYZA, Vector(0, mins[1], mins[2]));
825 
826  normalYZB = Vector(0, mins[2] - maxs[2], mins[1] - maxs[1]).Normalized();
827  distanceYZB = vector.Dot(normalYZB, Vector(0, mins[1], mins[2]));
828 
829  normalXZA = Vector(maxs[2] - mins[2], 0, mins[0] - maxs[0]).Normalized();
830  distanceXZA = vector.Dot(normalXZA, Vector(mins[0], 0, mins[2]));
831 
832  normalXZB = Vector(mins[2] - maxs[2], 0, mins[0] - maxs[0]).Normalized();
833  distanceXZB = vector.Dot(normalXZB, Vector(mins[0], 0, mins[2]));
834 
835  normalXYA = Vector(maxs[1] - mins[1], mins[0] - maxs[0], 0).Normalized();
836  distanceXYA = vector.Dot(normalXYA, Vector(mins[0], mins[1], 0));
837 
838  normalXYB = Vector(mins[1] - maxs[1], mins[0] - maxs[0], 0).Normalized();
839  distanceXYB = vector.Dot(normalXYB, Vector(mins[0], mins[1], 0));
840 
841 #ifdef VEHICLE_DAMAGE_DEBUG
842  //Debug shapes
843  //Here we just draw all the fancy stuff
844  m_aDebugShapes.Clear();
845 
846  m_aDebugShapes.Insert(Shape.Create(ShapeType.BBOX, ARGB(255, 0, 255, 255), ShapeFlags.NOZBUFFER | ShapeFlags.WIREFRAME, owner.CoordToParent(mins), owner.CoordToParent(maxs)));
847  m_aDebugShapes.Insert(Shape.CreateSphere(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER | ShapeFlags.WIREFRAME, position, 0.2));
848 
849  vector p[2];
850  p[0] = owner.CoordToParent(bboxCenter);
851  p[1] = owner.CoordToParent(normalXZA);
852  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
853 
854  p[1] = owner.CoordToParent(normalXZB);
855  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 0, 255, 0), ShapeFlags.NOZBUFFER, p, 2));
856 
857  p[1] = owner.CoordToParent(normalYZA);
858  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 0, 0, 255), ShapeFlags.NOZBUFFER, p, 2));
859 
860  p[1] = owner.CoordToParent(normalYZB);
861  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 255), ShapeFlags.NOZBUFFER, p, 2));
862 
863  p[1] = owner.CoordToParent(normalXYA);
864  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 0, 255, 255), ShapeFlags.NOZBUFFER, p, 2));
865 
866  p[1] = owner.CoordToParent(normalXYB);
867  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 0, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
868 
869  p[1] = owner.CoordToParent(contact);
870  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 155, 255), ShapeFlags.NOZBUFFER, p, 2));
871 #endif
872 #ifdef VEHICLE_DEBUG_OTHER
873  //This is a temporary solution, TODO: PROPER DEBUG
874  //Do not remove the commented scripts!
875  m_aDebugShapes.Clear();
876  vector p[2];
877 
878  vector globalMins, globalMaxs;
879  globalMins = owner.CoordToParent(mins);
880  globalMaxs = owner.CoordToParent(maxs);
881 
882  m_aDebugShapes.Insert(Shape.CreateSphere(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER | ShapeFlags.WIREFRAME, position, 0.2));
883 
884  /*p[0] = globalMins;
885  p[1] = globalMaxs;
886  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
887 
888  p[0][0] = globalMaxs[0];
889  p[1][0] = globalMins[0];
890  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
891 
892  p[0] = globalMins;
893  p[0][1] = globalMaxs[1];
894  p[1] = globalMaxs;
895  p[1][1] = globalMins[1];
896  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
897 
898  p[0] = globalMins;
899  p[0][2] = globalMaxs[2];
900  p[1] = globalMaxs;
901  p[1][2] = globalMins[2];
902  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2)); */
903 
904  //Corner lines
905  p[0] = globalMins;
906  p[1] = p[0];
907  p[1][1] = globalMaxs[1];
908  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
909 
910  p[0] = globalMins;
911  p[0][0] = globalMaxs[0];
912  p[1] = p[0];
913  p[1][1] = globalMaxs[1];
914  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
915 
916  p[0] = globalMaxs;
917  p[1] = p[0];
918  p[1][1] = globalMins[1];
919  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
920 
921  p[0] = globalMaxs;
922  p[0][0] = globalMins[0];
923  p[1] = p[0];
924  p[1][1] = globalMins[1];
925  m_aDebugShapes.Insert(Shape.CreateLines(ARGB(255, 255, 0, 0), ShapeFlags.NOZBUFFER, p, 2));
926 
927  vector mat[4];
928  Math3D.MatrixIdentity4(mat);
929  //Top pyramid
930  p[0] = mins;
931  p[0][1] = maxs[1] * 0.5;
932  p[1] = maxs;
933  Shape shape = Shape.Create(ShapeType.PYRAMID, ARGB(255, 0, 255, 0), ShapeFlags.NOZBUFFER, p[1], p[0]);
934  m_aDebugShapes.Insert(shape);
935  mat[3] = owner.GetOrigin();
936  shape.SetMatrix(mat);
937 
938  //Bottom pyramid
939  p[0] = mins;
940  p[1] = maxs;
941  p[1][1] = p[1][1] * 0.5;
942  shape = Shape.Create(ShapeType.PYRAMID, ARGB(255, 0, 255, 0), ShapeFlags.NOZBUFFER, p[0], p[1]);
943  m_aDebugShapes.Insert(shape);
944  shape.SetMatrix(mat);
945 
946  //Right pyramid
947  /*p[0][0] = maxs[1];
948  p[0][1] = mins[0];
949  p[0][2] = mins[2];
950  p[1][0] = mins[1];
951  p[1][1] = maxs[0];
952  p[1][2] = maxs[2];
953  /*p[0] = maxs;
954  p[1] = mins;
955  p[1][0] = mins[0]; */
956  /*shape = Shape.Create(ShapeType.PYRAMID, ARGB(255, 0, 255, 0), ShapeFlags.NOZBUFFER, p[1], p[0]);
957  m_aDebugShapes.Insert(shape);
958  mat[0] = -vector.Up;
959  mat[1] = vector.Right;
960  mat[2] = vector.Forward;
961  mat[3] = owner.GetOrigin() + maxs;
962  shape.SetMatrix(mat);
963  Math3D.MatrixIdentity4(mat); */
964 
965  /*mat[0] = vector.Up;
966  mat[1] = -vector.Right;
967  mat[2] = vector.Forward; */
968 #endif
969 
970  //Calculating where the contact point is relative to the plane by calculating the dot product of the contact point and the planes normal
971  bool XZA, XZB, YZA, YZB, XYA, XYB;
972  XZA = (vector.Dot(contact, normalXZA) > 0) - distanceXZA;
973  XZB = (vector.Dot(contact, normalXZB) > 0) - distanceXZB;
974  YZA = (vector.Dot(contact, normalYZA) > 0) - distanceYZA;
975  YZB = (vector.Dot(contact, normalYZB) > 0) - distanceYZB;
976  XYA = (vector.Dot(contact, normalXYA) > 0) - distanceXYA;
977  XYB = (vector.Dot(contact, normalXYB) > 0) - distanceXYB;
978 
979  //XZA = Front, right, bottom, top
980  //XZB = Rear, right, bottom, top
981  //YZA = Front, bottom, right, left
982  //YZB = Rear, bottom, right, left
983  //XYA = Front, Rear, top, left
984  //XYB = Front, Rear, top, right
985  // XZA XZB YZA YZB XYA XYB
986  //Top = - - 0 0 0 0
987  //Bottom= - - 1 1 1 1
988  //Left = 0 1 - - 0 1
989  //Right = 1 0 - - 1 0
990  //Front = 0 0 1 0 - -
991  //Rear = 1 1 0 1 - -
992 
993  //Right
994  if (XZA && !XZB && XYA && !XYB)
995  return SCR_EBoxSide.RIGHT;
996 
997  //Left
998  if (!XZA && XZB && !XYA && XYB)
999  return SCR_EBoxSide.LEFT;
1000 
1001  //Bottom
1002  if (YZA && YZB && XYA && XYB)
1003  return SCR_EBoxSide.BOTTOM;
1004 
1005  //Top
1006  if (!YZA && !YZB && !XYA && !XYB)
1007  return SCR_EBoxSide.TOP;
1008 
1009  //Front
1010  if (!XZA && !XZB && YZA && !YZB)
1011  return SCR_EBoxSide.FRONT;
1012 
1013  //Rear
1014  if (XZA && XZB && !YZA && YZB)
1015  return SCR_EBoxSide.REAR;
1016 
1017  return SCR_EBoxSide.FRONT;
1018  }
1019 
1020 #ifdef WORKBENCH
1021  //------------------------------------------------------------------------------------------------
1022  override array<ref WB_UIMenuItem> _WB_GetContextMenuItems(IEntity owner)
1023  {
1024  array<ref WB_UIMenuItem> items = { new WB_UIMenuItem("Compute collision damage", 0) };
1025 
1026  return items;
1027  }
1028 
1029  //------------------------------------------------------------------------------------------------
1030  override void _WB_OnContextMenu(IEntity owner, int id)
1031  {
1032  switch (id)
1033  {
1034  case 0:
1035  {
1036  GenericEntity entity = GenericEntity.Cast(owner);
1037  if (!entity)
1038  return;
1039 
1040  WorldEditorAPI api = entity._WB_GetEditorAPI();
1041  if (!api)
1042  return;
1043 
1044  array<HitZone> hitzones;
1045  int count = GetSurroundingHitzones(GetOwner().CoordToParent(GetFrontalImpact()), GetOwner().GetPhysics(), GetMaxSharedDamageDistance(), hitzones);
1046  hitzones.Insert(GetDefaultHitZone());
1047  count++;
1048  float damage = GetMinDestroyDamage(EDamageType.COLLISION, hitzones, count);
1049 
1050  // Damage is not valid - warn the user!
1051  if (damage < 0)
1052  {
1053  Print("Cannot destroy selected vehicle on collision", LogLevel.WARNING);
1054  return;
1055  }
1056 
1057  float newFrontMultiplier = GetFrontMultiplier();
1058  float targetFrontalDamage = Math.Ceil(damage / newFrontMultiplier);
1059 
1060  api.BeginEntityAction();
1061 
1062  IEntitySource ownerSource = api.EntityToSource(owner);
1063  IEntityComponentSource componentSource = SCR_BaseContainerTools.FindComponentSource(ownerSource, Type().ToString());
1064 
1065  if (componentSource && componentSource.Set("m_fVehicleDestroyDamage", targetFrontalDamage.ToString()))
1066  Print("Entity instance's m_fVehicleDestroyDamage set to " + targetFrontalDamage.ToString(), LogLevel.WARNING);
1067  else
1068  Print("Error setting m_fVehicleDestroyDamage set to " + targetFrontalDamage.ToString(), LogLevel.ERROR);
1069 
1070  api.EndEntityAction();
1071  }
1072  }
1073  }
1074 #endif
1075 
1076  //------------------------------------------------------------------------------------------------
1078  override bool OnContact(IEntity owner, IEntity other, Contact contact)
1079  {
1080  super.OnContact(owner, other, contact);
1081 
1082  if (m_ImpactEffectComponent && other)
1083  m_ImpactEffectComponent.OnImpact(other, contact);
1084 
1085  ChimeraCharacter char = ChimeraCharacter.Cast(other);
1086  if (char)
1087  {
1089  if (charDamageMan)
1090  charDamageMan.ContactDamage(other, owner, contact);
1091  }
1092 
1093  return CollisionDamage(owner, other, contact);
1094  }
1095 
1096  //------------------------------------------------------------------------------------------------
1102  bool CollisionDamage(notnull IEntity owner, notnull IEntity other, notnull Contact contact)
1103  {
1104  if (contact.Impulse < m_fMinImpulse)
1105  return false;
1106 
1107  // This data can be moved back to component
1109  if (!prefabData)
1110  return false;
1111 
1112  // Get the physics of the dynamic object (if owner is static we ignore the collision)
1113  Physics ownerPhysics = owner.GetPhysics();
1114  if (!ownerPhysics.IsDynamic())
1115  {
1116  m_bIsInContact = false;
1117  return false;
1118  }
1119 
1120  Physics otherPhysics = other.GetPhysics();
1121 
1122  // Now get the relative force, which is the impulse divided by the mass of the dynamic object
1123  float relativeForce = contact.Impulse / ownerPhysics.GetMass();
1124  // We keep relative force temporarily, until we re-calculate it to momentum
1125 
1126  // We hit a destructible that will break, static object -> deal no damage to vehicle or occupants
1127  int ownerResponseIndex = ownerPhysics.GetResponseIndex();
1128  int otherResponseIndex = otherPhysics.GetResponseIndex();
1129  if (otherPhysics && !otherPhysics.IsDynamic() && other.FindComponent(SCR_DestructionDamageManagerComponent) && otherResponseIndex - MIN_DESTRUCTION_RESPONSE_INDEX <= ownerResponseIndex - MIN_MOMENTUM_RESPONSE_INDEX)
1130  return false;
1131 
1132  float ownerMass = owner.GetPhysics().GetMass();
1133  float otherMass = otherPhysics.GetMass();
1134 
1135  // Store information about being in contact - so we don't delete physics objects
1136  m_bIsInContact = true;
1137 
1138 #ifdef DISABLE_VEHICLE_COLLISION_DAMAGE
1139  m_bIsInContact = false;
1140  return false;
1141 #endif
1142 
1143  //TODOv Pre-calculate these values into prefab data, when callback of prefab data cretion is added.
1144  float momentumVehicleThreshold = ownerMass * m_fVehicleDamageSpeedThreshold * KM_PER_H_TO_M_PER_S;
1145  float momentumVehicleDestroy = ownerMass * m_fVehicleSpeedDestroy * KM_PER_H_TO_M_PER_S;
1146  float damageScaleToVehicle = m_fVehicleDestroyDamage / (momentumVehicleDestroy - momentumVehicleThreshold);
1147  //TODO^
1148 
1149  // Debug stuff
1150  if (m_bPrintRelativeForce && relativeForce > m_fMaxRelativeForce)
1151  {
1152  m_fMaxRelativeForce = relativeForce;
1153  Print(contact.Impulse, LogLevel.DEBUG);
1154  Print(contact.VelocityBefore1, LogLevel.DEBUG);
1155  Print(m_fMaxRelativeForce, LogLevel.DEBUG);
1156  }
1157 
1158  float damageShare = 1;
1159  if (otherMass > 0) // mass == 0 is probably a static object
1160  damageShare -= ownerMass / (ownerMass + otherMass);
1161 
1162  float DotMultiplier = vector.Dot(contact.VelocityAfter1.Normalized(), contact.VelocityBefore1.Normalized());
1163  float MomentumBefore = ownerMass * contact.VelocityBefore1.Length();
1164  float MomentumAfter = ownerMass * contact.VelocityAfter1.Length() * DotMultiplier;
1165  float momentumA = Math.AbsFloat(MomentumBefore - MomentumAfter);
1166 
1167  DotMultiplier = vector.Dot(contact.VelocityAfter2.Normalized(), contact.VelocityBefore2.Normalized());
1168  MomentumBefore = otherMass * contact.VelocityBefore2.Length();
1169  MomentumAfter = otherMass * contact.VelocityAfter2.Length() * DotMultiplier;
1170  float momentumB = Math.AbsFloat(MomentumBefore - MomentumAfter);
1171 
1172  float collisionDamage = damageScaleToVehicle * (momentumA + momentumB - momentumVehicleThreshold);
1173  IEntity instigatorEntity;
1174 
1175  // Find compartment manager to damage occupants
1177  {
1178  //TODOv Pre-calculate these values into prefab data, when callback of prefab data cretion is added.
1179  float momentumOccupantsThreshold = ownerMass * GetOccupantsDamageSpeedThreshold() * KM_PER_H_TO_M_PER_S;
1180  float momentumOccupantsDeath = ownerMass * GetOccupantsSpeedDeath() * KM_PER_H_TO_M_PER_S;
1181  float damageScaleToCharacter = APPROXIMATE_CHARACTER_LETHAL_DAMAGE / (momentumOccupantsDeath - momentumOccupantsThreshold);
1182  //TODO^
1183 
1184  // This is the momentum, which will be transferred to damage
1185  float momentumOverOccupantsThreshold = (momentumA + momentumB) * damageShare - momentumOccupantsThreshold;
1186 
1187  // Deal damage if it's more that 0
1188  if (momentumOverOccupantsThreshold > 0)
1189  {
1190  //If the entity is dynamic, we need to look if the entity has a driver or not.
1191  //If the vehicle's speed is bigger than m_fVehicleDamageSpeedThreshold
1192  if (otherPhysics.IsDynamic() && contact.VelocityBefore1.LengthSq() > m_fVehicleDamageSpeedThreshold * m_fVehicleDamageSpeedThreshold)
1193  {
1194  IEntity otherPilot;
1195  Vehicle otherVehicle = Vehicle.Cast(other);
1196  if (otherVehicle)
1197  otherPilot = otherVehicle.GetPilot();
1198 
1199  //If the entity has a driver:
1200  if (otherPilot)
1201  {
1202  //If their speed is bigger than GetVehicleDamageSpeedThreshold and they are not running away from the vehicle
1203  //(their dot product indicates that they are within 60° cone):
1204  //their driver is the instigator of the damage the occupants of this vehicle's compartments receive.
1205  //If not, the driver of this vehicle is the instigator.
1206  vector directionToOther = (other.GetOrigin() - owner.GetOrigin()).Normalized();
1207  if (vector.Dot(contact.VelocityBefore1.Normalized(), directionToOther) < 0.5)
1208  instigatorEntity = otherPilot;
1209  }
1210  }
1211 
1212  // If there was no other pilot to blame, blame own pilot
1213  if (!instigatorEntity && Vehicle.Cast(owner))
1214  instigatorEntity = Vehicle.Cast(owner).GetPilot();
1215 
1216  //Implement instigator's logic
1217  m_CompartmentManager.DamageOccupants(momentumOverOccupantsThreshold * damageScaleToCharacter, EDamageType.COLLISION, Instigator.CreateInstigator(instigatorEntity), true, true);
1218  }
1219  }
1220 
1221  // Deal damage if collision damage is over threshold
1222  if (collisionDamage > 0)
1223  {
1224  // Get hit side multiplier (e. g. front is stronger than the left/right side)
1225  float damageSideMultiplier = GetSideDamageMultiplier(GetHitDirection(contact.Position));
1226 
1227  collisionDamage *= damageSideMultiplier * damageShare;
1228  // Handle damage requires a matrix, so we create an empty one
1229  vector empty[3];
1230  empty[0] = vector.Zero;
1231  empty[1] = vector.Zero;
1232  empty[2] = vector.Zero;
1233 
1234  SCR_DamageContext damageContext = new SCR_DamageContext(EDamageType.COLLISION, DamageSurroundingHitzones(contact.Position, collisionDamage, EDamageType.COLLISION), empty, GetOwner(), GetDefaultHitZone(), Instigator.CreateInstigator(instigatorEntity), null, -1, -1);
1235  // finally we deal damage
1236  HandleDamage(damageContext);
1237  }
1238 
1239  // Reset is in contact
1240  m_bIsInContact = false;
1241 
1242  return true;
1243  }
1244 
1245  //------------------------------------------------------------------------------------------------
1247  static ScriptInvokerInt GetOnVehicleDestroyed()
1248  {
1249  if (!s_OnVehicleDestroyed)
1250  s_OnVehicleDestroyed = new ScriptInvokerInt();
1251 
1252  return s_OnVehicleDestroyed;
1253  }
1254 
1255  //------------------------------------------------------------------------------------------------
1257  override void OnDamageStateChanged(EDamageState state)
1258  {
1259  super.OnDamageStateChanged(state);
1260  HitZone defaultHitZone = GetDefaultHitZone();
1261  if (!defaultHitZone)
1262  return;
1263 
1265  if (vehicleBuoyancy)
1266  vehicleBuoyancy.SetHealth(defaultHitZone.GetDamageStateThreshold(state));
1267 
1268  if (s_OnVehicleDestroyed && state == EDamageState.DESTROYED)
1269  s_OnVehicleDestroyed.Invoke(GetInstigator().GetInstigatorPlayerID());
1270  }
1271 
1272  //------------------------------------------------------------------------------------------------
1274  override bool CanBeHealed()
1275  {
1276  // Get drowned engine
1277  BaseVehicleNodeComponent vehicleNode = BaseVehicleNodeComponent.Cast(GetOwner().FindComponent(BaseVehicleNodeComponent));
1278  if (vehicleNode)
1279  {
1280  if (GetGame().GetIsClientAuthority())
1281  {
1282  VehicleControllerComponent vehicleController = VehicleControllerComponent.Cast(vehicleNode.FindComponent(VehicleControllerComponent));
1283  if (vehicleController && vehicleController.GetEngineDrowned())
1284  return true;
1285  }
1286  else
1287  {
1288  VehicleControllerComponent_SA vehicleController = VehicleControllerComponent_SA.Cast(vehicleNode.FindComponent(VehicleControllerComponent_SA));
1289  if (vehicleController && vehicleController.GetEngineDrowned())
1290  return true;
1291  }
1292  }
1293 
1294  return super.CanBeHealed();
1295  }
1296 
1297  //------------------------------------------------------------------------------------------------
1300  override void FullHeal(bool ignoreHealingDOT = true)
1301  {
1302  // Fix drowned engine
1303  BaseVehicleNodeComponent vehicleNode = BaseVehicleNodeComponent.Cast(GetOwner().FindComponent(BaseVehicleNodeComponent));
1304  if (vehicleNode)
1305  {
1306  if (GetGame().GetIsClientAuthority())
1307  {
1308  VehicleControllerComponent vehicleController = VehicleControllerComponent.Cast(vehicleNode.FindComponent(VehicleControllerComponent));
1309  if (vehicleController && vehicleController.GetEngineDrowned())
1310  vehicleController.SetEngineDrowned(false);
1311  }
1312  else
1313  {
1314  VehicleControllerComponent_SA vehicleController = VehicleControllerComponent_SA.Cast(vehicleNode.FindComponent(VehicleControllerComponent_SA));
1315  if (vehicleController && vehicleController.GetEngineDrowned())
1316  vehicleController.SetEngineDrowned(false);
1317  }
1318 
1319  }
1320 
1321  // Repair everything else that can be repaired
1322  super.FullHeal(ignoreHealingDOT);
1323  }
1324 
1325  //------------------------------------------------------------------------------------------------
1327  // Takes care of updating the reponse index
1329  {
1330  Physics physics = GetOwner().GetPhysics();
1331  if (!physics)
1332  return;
1333 
1334  float momentum = physics.GetMass() * physics.GetVelocity().Length(); // Calculate current vehicle's momentum
1335  float currentIndexMinMomentum = s_mResponseIndexMomentumMap.Get(physics.GetResponseIndex());
1336  int currentIndex = physics.GetResponseIndex();
1337 
1338  while (momentum > currentIndexMinMomentum && currentIndex < MAX_RESPONSE_INDEX)
1339  {
1340  currentIndex++;
1341  currentIndexMinMomentum = s_mResponseIndexMomentumMap.Get(currentIndex);
1342  if (momentum < currentIndexMinMomentum) // We are at a point, where current momentum isn't big enough for this index
1343  {
1344  // We go one index down and break from the loop
1345  currentIndex--;
1346  currentIndexMinMomentum = s_mResponseIndexMomentumMap.Get(currentIndex);
1347  break;
1348  }
1349  }
1350 
1351  while (momentum < currentIndexMinMomentum && currentIndex > MIN_RESPONSE_INDEX)
1352  {
1353  currentIndex--;
1354  currentIndexMinMomentum = s_mResponseIndexMomentumMap.Get(currentIndex);
1355  if (momentum > currentIndexMinMomentum) // We are at a point, where current momentum is big enough for this index
1356  break;
1357  }
1358 
1359  physics.SetResponseIndex(currentIndex);
1360  }
1361 
1362  //------------------------------------------------------------------------------------------------
1363  [RplRpc(RplChannel.Reliable, RplRcver.Server)]
1364  protected void RPC_OnPhysicsActive(bool activeState)
1365  {
1366  ToggleResponseIndexTicking(GetOwner(), activeState);
1367  }
1368 
1369  //------------------------------------------------------------------------------------------------
1373  void ToggleResponseIndexTicking(IEntity owner, bool activeState)
1374  {
1375  // Always remove first so we don't end up double-registering
1376  GetGame().GetCallqueue().Remove(TickResponseIndexCheck);
1377  if (activeState)
1378  GetGame().GetCallqueue().CallLater(TickResponseIndexCheck, 500, true);
1379  }
1380 
1381  //------------------------------------------------------------------------------------------------
1385  void EOnPhysicsActive(IEntity owner, bool activeState)
1386  {
1387  Vehicle vehicle = Vehicle.Cast(owner);
1388  if (!vehicle)
1389  return;
1390 
1391  RplComponent rplComponent = vehicle.GetRplComponent();
1392  if (!rplComponent)
1393  return;
1394 
1395  if (!GetGame().GetIsClientAuthority())
1396  {
1397  if (rplComponent.IsProxy() && !rplComponent.IsOwner())
1398  {
1399  // Make sure to always deactivate ticking on remote proxies
1400  if (!activeState)
1401  RPC_OnPhysicsActive(activeState);
1402  }
1403  else if (rplComponent.IsOwner() || !rplComponent.IsProxy())
1404  {
1405  RPC_OnPhysicsActive(activeState);
1406  }
1407  }
1408  else
1409  {
1410  if (rplComponent.IsProxy())
1411  {
1412  // Make sure to always deactivate ticking on remote proxies
1413  if (!activeState)
1414  RPC_OnPhysicsActive(activeState);
1415  // Only enable ticking on owner proxies
1416  else if (rplComponent.IsOwner())
1417  RPC_OnPhysicsActive(activeState);
1418  }
1419 
1420  Rpc(RPC_OnPhysicsActive, activeState);
1421  }
1422  }
1423 
1424  //------------------------------------------------------------------------------------------------
1427  void RegisterFlammableHitZone(notnull SCR_FlammableHitZone hitZone)
1428  {
1430  m_aFlammableHitZones.Insert(hitZone);
1431  else
1432  m_aFlammableHitZones = {hitZone};
1433  }
1434 
1435  //------------------------------------------------------------------------------------------------
1438  void UnregisterFlammableHitZone(notnull SCR_FlammableHitZone hitZone)
1439  {
1441  m_aFlammableHitZones.RemoveItem(hitZone);
1442 
1443  if (m_aFlammableHitZones.IsEmpty())
1444  m_aFlammableHitZones = null;
1445  }
1446 
1447  //------------------------------------------------------------------------------------------------
1448  override void UpdateFireDamage(float timeSlice)
1449  {
1450  if (!m_aFlammableHitZones)
1451  return;
1452 
1453  float fireRate;
1454  UpdateVehicleFireState(fireRate, timeSlice);
1455  UpdateFuelTankFireState(fireRate, timeSlice);
1456  UpdateSuppliesFireState(fireRate, timeSlice);
1457  }
1458 
1459  //------------------------------------------------------------------------------------------------
1460  protected void OnVehicleFireStateChanged()
1461  {
1462  if (m_SignalsManager)
1464  }
1465 
1466  //------------------------------------------------------------------------------------------------
1467  protected void SetVehicleFireState(SCR_ESecondaryExplosionScale state, vector origin = vector.Zero)
1468  {
1469  if (m_eVehicleFireState == state)
1470  return;
1471 
1472  m_eVehicleFireState = state;
1473  m_vVehicleFireOrigin = origin;
1474  Replication.BumpMe();
1475 
1477  }
1478 
1479  //------------------------------------------------------------------------------------------------
1481  {
1482  if (m_SignalsManager)
1484 
1485  UpdateFireParticles(m_vFuelTankFireOrigin, m_FuelTankFireParticle, m_eFuelTankFireState, SCR_ESecondaryExplosionType.FUEL);
1486  }
1487 
1488  //------------------------------------------------------------------------------------------------
1489  protected void SetFuelTankFireState(SCR_ESecondaryExplosionScale state, vector origin = vector.Zero)
1490  {
1491  if (m_eFuelTankFireState == state)
1492  return;
1493 
1494  m_eFuelTankFireState = state;
1495  m_vFuelTankFireOrigin = origin;
1496  Replication.BumpMe();
1497 
1499  }
1500 
1501  //------------------------------------------------------------------------------------------------
1503  {
1504  if (m_SignalsManager)
1506 
1507  UpdateFireParticles(m_vSuppliesFireOrigin, m_SuppliesFireParticle, m_eSuppliesFireState, SCR_ESecondaryExplosionType.RESOURCE, EResourceType.SUPPLIES);
1508  }
1509 
1510  //------------------------------------------------------------------------------------------------
1511  protected void SetSuppliesFireState(SCR_ESecondaryExplosionScale state, vector origin = vector.Zero)
1512  {
1513  if (m_eSuppliesFireState == state)
1514  return;
1515 
1516  m_eSuppliesFireState = state;
1517  m_vSuppliesFireOrigin = origin;
1518  Replication.BumpMe();
1519 
1521  }
1522 
1523  //------------------------------------------------------------------------------------------------
1524  protected void UpdateVehicleFireState(out float fireRate, float timeSlice)
1525  {
1526  vector averagePosition = GetSecondaryExplosionPosition(SCR_FlammableHitZone, fireRate);
1527 
1528  // Fire area damage
1529  m_fVehicleFireDamageTimeout -= timeSlice;
1531  {
1532  EntitySpawnParams spawnParams();
1533  spawnParams.Transform[3] = averagePosition;
1534  ResourceName fireDamage = GetSecondaryExplosion(fireRate, SCR_ESecondaryExplosionType.FUEL, fire: true);
1535  SecondaryExplosion(fireDamage, GetInstigator(), spawnParams);
1536 
1537  // Constant intervals for secondary damage
1538  m_fVehicleFireDamageTimeout = m_fSecondaryFireDamageDelay;
1539  }
1540 
1541  SCR_ESecondaryExplosionScale vehicleFireState = GetSecondaryExplosionScale(fireRate, SCR_ESecondaryExplosionType.FUEL);
1542  SetVehicleFireState(vehicleFireState, averagePosition);
1543  }
1544 
1545  //------------------------------------------------------------------------------------------------
1546  protected void UpdateFuelTankFireState(float fireRate, float timeSlice)
1547  {
1548  if (!m_FuelManager)
1549  {
1550  SetFuelTankFireState(SCR_ESecondaryExplosionScale.NONE);
1551  return;
1552  }
1553 
1554  if (fireRate <= 0)
1555  {
1556  SetFuelTankFireState(SCR_ESecondaryExplosionScale.NONE);
1557  return;
1558  }
1559 
1560  if (GetState() == EDamageState.DESTROYED)
1561  {
1562  SetFuelTankFireState(SCR_ESecondaryExplosionScale.NONE);
1563  return;
1564  }
1565 
1566  float burningFuel;
1567  vector averagePosition = GetSecondaryExplosionPosition(SCR_FuelHitZone, burningFuel);
1568  if (float.AlmostEqual(burningFuel, 0))
1569  {
1570  SetFuelTankFireState(SCR_ESecondaryExplosionScale.NONE);
1571  return;
1572  }
1573 
1574  // Fire area damage
1575  float fuelBurnRate;
1576  m_fFuelTankFireDamageTimeout -= timeSlice;
1578  {
1579  EntitySpawnParams spawnParams();
1580  spawnParams.Transform[3] = averagePosition;
1581  ResourceName fireDamage = GetSecondaryExplosion(burningFuel / fireRate, SCR_ESecondaryExplosionType.FUEL, fire: true);
1582  SecondaryExplosion(fireDamage, GetInstigator(), spawnParams);
1583 
1584  // Constant intervals for secondary damage
1585  m_fFuelTankFireDamageTimeout = m_fSecondaryFireDamageDelay;
1586  fuelBurnRate = fireRate * m_fSecondaryFireDamageDelay * m_fFuelTankFireDamageRate;
1587  }
1588 
1589  // Consume fuel
1590  if (fuelBurnRate > 0)
1591  {
1592  SCR_FuelNode fuelTank;
1593  float fuelLoss;
1594  array<BaseFuelNode> fuelTanks = {};
1595  m_FuelManager.GetFuelNodesList(fuelTanks);
1596  foreach (BaseFuelNode fuelNode : fuelTanks)
1597  {
1598  fuelTank = SCR_FuelNode.Cast(fuelNode);
1599  if (!fuelTank)
1600  continue;
1601 
1602  // Burn fuel based on fuel tank health and amount of fuel vs burning fuel amount
1603  fuelLoss = fuelBurnRate * (1 - fuelTank.GetHealth()) * fuelNode.GetFuel() / burningFuel;
1604  if (fuelLoss > 0)
1605  fuelTank.SetFuel(fuelTank.GetFuel() - fuelLoss);
1606  }
1607  }
1608 
1609  SCR_ESecondaryExplosionScale fuelTankFireState = GetSecondaryExplosionScale(fireRate, SCR_ESecondaryExplosionType.FUEL);
1610  SetFuelTankFireState(fuelTankFireState, averagePosition);
1611  }
1612 
1613  //------------------------------------------------------------------------------------------------
1614  protected void UpdateSuppliesFireState(float fireRate, float timeSlice)
1615  {
1616  if (fireRate <= 0)
1617  {
1618  SetSuppliesFireState(SCR_ESecondaryExplosionScale.NONE);
1619  return;
1620  }
1621 
1622  if (GetState() == EDamageState.DESTROYED)
1623  {
1624  SetSuppliesFireState(SCR_ESecondaryExplosionScale.NONE);
1625  return;
1626  }
1627 
1628  SCR_ResourceEncapsulator encapsulator = GetResourceEncapsulator();
1629  if (!encapsulator)
1630  {
1631  SetSuppliesFireState(SCR_ESecondaryExplosionScale.NONE);
1632  return;
1633  }
1634 
1635  float totalResources = encapsulator.GetAggregatedResourceValue();
1636  if (totalResources <= 0)
1637  {
1638  SetSuppliesFireState(SCR_ESecondaryExplosionScale.NONE);
1639  return;
1640  }
1641 
1642  SCR_ResourceContainerQueueBase containerQueue = encapsulator.GetContainerQueue();
1643  int containerCount = encapsulator.GetContainerCount();
1644 
1645  SCR_ResourceContainer container;
1646  float weight;
1647  vector position;
1648 
1649  vector averagePosition = GetOwner().CoordToLocal(encapsulator.GetOwnerOrigin());
1650 
1651  // Get the weighed average position of explosion relative to encapsulator
1652  for (int i; i < containerCount; i++)
1653  {
1654  container = containerQueue.GetContainerAt(i);
1655  if (!container)
1656  continue;
1657 
1658  // Determine secondary explosion position
1659  weight = container.GetResourceValue() / totalResources;
1660  if (weight <= 0)
1661  continue;
1662 
1663  position = GetOwner().CoordToLocal(container.GetOwnerOrigin());
1664  averagePosition += position * weight;
1665  }
1666 
1667  SCR_ESecondaryExplosionScale suppliesFireState = GetSecondaryExplosionScale(fireRate, SCR_ESecondaryExplosionType.RESOURCE);
1668  SetSuppliesFireState(suppliesFireState, averagePosition);
1669 
1670  // Fire area damage
1671  float suppliesDamage;
1672  m_fSuppliesFireDamageTimeout -= timeSlice;
1674  {
1675 
1676  EntitySpawnParams spawnParams();
1677  spawnParams.Transform[3] = averagePosition;
1678  ResourceName fireDamage = GetSecondaryExplosion(fireRate, SCR_ESecondaryExplosionType.RESOURCE, fire: true);
1679  SecondaryExplosion(fireDamage, GetInstigator(), spawnParams);
1680 
1681  // Constant intervals for secondary damage
1682  m_fSuppliesFireDamageTimeout = m_fSecondaryFireDamageDelay;
1683  suppliesDamage = Math.Ceil(fireRate * m_fSecondaryFireDamageDelay * m_fSuppliesFireDamageRate);
1684  }
1685 
1686  if (containerCount > 1)
1687  suppliesDamage /= containerCount;
1688 
1689  for (int i; i < containerCount; i++)
1690  {
1691  container = containerQueue.GetContainerAt(i);
1692  if (container)
1693  container.DecreaseResourceValue(suppliesDamage);
1694  }
1695  }
1696 
1697  //------------------------------------------------------------------------------------------------
1700  {
1701  return m_fMinImpulse;
1702  }
1703 
1704  //------------------------------------------------------------------------------------------------
1707  {
1708  s_mResponseIndexMomentumMap.Insert(SCR_EPhysicsResponseIndex.TINY_MOMENTUM, 0);
1709  s_mResponseIndexMomentumMap.Insert(SCR_EPhysicsResponseIndex.SMALL_MOMENTUM, 6666.6); // Approx UAZ (1600kg) at 15 km/h in kJ
1710  s_mResponseIndexMomentumMap.Insert(SCR_EPhysicsResponseIndex.MEDIUM_MOMENTUM, 22222.2); // 50 km/h
1711  s_mResponseIndexMomentumMap.Insert(SCR_EPhysicsResponseIndex.LARGE_MOMENTUM, 44444.4); // 100 km/h
1712  s_mResponseIndexMomentumMap.Insert(SCR_EPhysicsResponseIndex.HUGE_MOMENTUM, 133333.3); // 300 km/h
1713  }
1714 
1715  //------------------------------------------------------------------------------------------------
1716  // constructor
1720  void SCR_VehicleDamageManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
1721  {
1722  //Can be removed when this event is called on components
1723  Vehicle ownerVehicle = Vehicle.Cast(ent);
1724  if (ownerVehicle)
1725  ownerVehicle.GetOnPhysicsActive().Insert(EOnPhysicsActive);
1726 
1727  if (!s_mResponseIndexMomentumMap.Find(SCR_EPhysicsResponseIndex.TINY_MOMENTUM, null))
1729  }
1730 }
GetGearboxFunctional
bool GetGearboxFunctional()
Definition: SCR_VehicleDamageManagerComponent.c:628
INSTRUMENTS
INSTRUMENTS
Definition: SCR_VehicleDamageManagerComponent.c:17
SetEngineEfficiency
protected void SetEngineEfficiency(float efficiency)
Definition: SCR_VehicleDamageManagerComponent.c:584
GetSideDamageMultiplier
float GetSideDamageMultiplier(SCR_EBoxSide side)
Definition: SCR_VehicleDamageManagerComponent.c:378
SetEngineFunctional
protected void SetEngineFunctional(bool functional)
Definition: SCR_VehicleDamageManagerComponent.c:548
GetLeftMultiplier
float GetLeftMultiplier()
Definition: SCR_VehicleDamageManagerComponent.c:87
m_fFrontMultiplier
float m_fFrontMultiplier
Definition: SCR_VehicleDamageManagerComponent.c:31
m_SuppliesFireParticle
protected ParticleEffectEntity m_SuppliesFireParticle
Definition: SCR_VehicleDamageManagerComponent.c:219
GetState
EEditableEntityState GetState()
Definition: SCR_BaseEntitiesEditorUIEffect.c:7
GetFrontalImpact
vector GetFrontalImpact()
Definition: SCR_VehicleDamageManagerComponent.c:122
TURRET
TURRET
Definition: SCR_VehicleDamageManagerComponent.c:9
SCR_VehicleDamageManagerComponentClass
void SCR_VehicleDamageManagerComponentClass(BaseContainer prefab)
LANDING_GEAR
LANDING_GEAR
Definition: SCR_VehicleDamageManagerComponent.c:15
RegisterFlammableHitZone
void RegisterFlammableHitZone(notnull SCR_FlammableHitZone hitZone)
Definition: SCR_VehicleDamageManagerComponent.c:1427
GetSecondaryExplosionScale
override float GetSecondaryExplosionScale()
Definition: SCR_FlammableHitZone.c:775
SetGearboxEfficiency
protected void SetGearboxEfficiency(float efficiency)
Definition: SCR_VehicleDamageManagerComponent.c:641
UpdateVehicleState
void UpdateVehicleState()
Definition: SCR_VehicleDamageManagerComponent.c:467
GetPrefabData
SCR_VehicleDamageManagerComponentClass GetPrefabData()
Definition: SCR_VehicleDamageManagerComponent.c:260
GetEngineFunctional
bool GetEngineFunctional()
Definition: SCR_VehicleDamageManagerComponent.c:542
m_fRearMultiplier
float m_fRearMultiplier
Definition: SCR_VehicleDamageManagerComponent.c:37
DRIVE_TRAIN
DRIVE_TRAIN
Definition: SCR_VehicleDamageManagerComponent.c:4
HUGE_DESTRUCTIBLE
@ HUGE_DESTRUCTIBLE
Definition: SCR_VehicleDamageManagerComponent.c:145
m_vSuppliesFireOrigin
protected vector m_vSuppliesFireOrigin
Definition: SCR_VehicleDamageManagerComponent.c:246
m_Controller
protected CompartmentControllerComponent m_Controller
Definition: SCR_VehicleDamageManagerComponent.c:197
m_fMinImpulse
protected float m_fMinImpulse
Definition: SCR_VehicleDamageManagerComponent.c:190
m_fGearboxEfficiency
protected float m_fGearboxEfficiency
Definition: SCR_VehicleDamageManagerComponent.c:203
ScriptInvokerInt
ScriptInvokerBase< ScriptInvokerIntMethod > ScriptInvokerInt
Definition: SCR_ScriptInvokerHelper.c:24
HitZone
Definition: HitZone.c:12
BaseFuelNode
Definition: BaseFuelNode.c:12
SetSuppliesFireState
protected void SetSuppliesFireState(SCR_ESecondaryExplosionScale state, vector origin=vector.Zero)
Definition: SCR_VehicleDamageManagerComponent.c:1511
OnContact
override bool OnContact(IEntity owner, IEntity other, Contact contact)
Must be first enabled with event mask.
Definition: SCR_VehicleDamageManagerComponent.c:1078
MIN_RESPONSE_INDEX
enum SCR_EPhysicsResponseIndex MIN_RESPONSE_INDEX
LARGE_DESTRUCTIBLE
@ LARGE_DESTRUCTIBLE
Definition: SCR_VehicleDamageManagerComponent.c:144
OnDamageStateChanged
override void OnDamageStateChanged(EDamageState state)
Update buoyancy loss rate.
Definition: SCR_VehicleDamageManagerComponent.c:1257
MAX_RESPONSE_INDEX
const protected int MAX_RESPONSE_INDEX
Definition: SCR_VehicleDamageManagerComponent.c:151
VIEWPORT
VIEWPORT
Definition: SCR_VehicleDamageManagerComponent.c:12
FUEL_TANKS
FUEL_TANKS
Definition: SCR_VehicleDamageManagerComponent.c:5
RplProp
SCR_RplTestEntityClass RplProp
Used for handling entity spawning requests for SCR_CatalogEntitySpawnerComponent and inherited classe...
NORMAL
@ NORMAL
Definition: SCR_VehicleDamageManagerComponent.c:135
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
RPC_OnPhysicsActive
protected void RPC_OnPhysicsActive(bool activeState)
Definition: SCR_VehicleDamageManagerComponent.c:1364
m_fLeftMultiplier
float m_fLeftMultiplier
Definition: SCR_VehicleDamageManagerComponent.c:40
m_sSuppliesFireStateSignal
protected string m_sSuppliesFireStateSignal
Definition: SCR_VehicleDamageManagerComponent.c:177
m_sVehicleFireStateSignal
protected string m_sVehicleFireStateSignal
Definition: SCR_VehicleDamageManagerComponent.c:171
SCR_VehicleDamageManagerComponent
void SCR_VehicleDamageManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Definition: SCR_VehicleDamageManagerComponent.c:1720
OnVehicleFireStateChanged
protected void OnVehicleFireStateChanged()
Definition: SCR_VehicleDamageManagerComponent.c:1460
m_bGearboxFunctional
protected bool m_bGearboxFunctional
Definition: SCR_VehicleDamageManagerComponent.c:204
GetFrontMultiplier
float GetFrontMultiplier()
Definition: SCR_VehicleDamageManagerComponent.c:66
m_SignalsManager
protected SignalsManagerComponent m_SignalsManager
Definition: SCR_VehicleDamageManagerComponent.c:208
EDamageState
EDamageState
Definition: EDamageState.c:12
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
m_bEngineFunctional
protected bool m_bEngineFunctional
Definition: SCR_VehicleDamageManagerComponent.c:201
SCR_EPhysicsResponseIndex
SCR_EPhysicsResponseIndex
Definition: SCR_VehicleDamageManagerComponent.c:133
UnregisterFlammableHitZone
void UnregisterFlammableHitZone(notnull SCR_FlammableHitZone hitZone)
Definition: SCR_VehicleDamageManagerComponent.c:1438
RplRpc
SCR_AchievementsHandlerClass ScriptComponentClass RplRpc(RplChannel.Reliable, RplRcver.Owner)] void UnlockOnClient(AchievementId achievement)
Definition: SCR_AchievementsHandler.c:11
GenericEntity
SCR_GenericBoxEntityClass GenericEntity
OnFuelTankFireStateChanged
protected void OnFuelTankFireStateChanged()
Definition: SCR_VehicleDamageManagerComponent.c:1480
SCR_ResourceContainerQueueBase
Definition: SCR_ResourceContainerQueue.c:2
m_ImpactEffectComponent
protected SCR_ImpactEffectComponent m_ImpactEffectComponent
Definition: SCR_VehicleDamageManagerComponent.c:228
m_aFlammableHitZones
protected ref array< SCR_FlammableHitZone > m_aFlammableHitZones
Definition: SCR_VehicleDamageManagerComponent.c:207
m_vVehicleFireOrigin
protected vector m_vVehicleFireOrigin
Definition: SCR_VehicleDamageManagerComponent.c:240
Instigator
Definition: Instigator.c:6
m_Simulation
protected VehicleBaseSimulation m_Simulation
Definition: SCR_VehicleDamageManagerComponent.c:198
HitZoneContainerComponent
Definition: HitZoneContainerComponent.c:12
OPTICS
OPTICS
Definition: SCR_VehicleDamageManagerComponent.c:10
SetVehicleFireState
protected void SetVehicleFireState(SCR_ESecondaryExplosionScale state, vector origin=vector.Zero)
Definition: SCR_VehicleDamageManagerComponent.c:1467
GetOccupantsSpeedDeath
float GetOccupantsSpeedDeath()
Definition: SCR_VehicleDamageManagerComponent.c:115
UpdateVehicleFireState
protected void UpdateVehicleFireState(out float fireRate, float timeSlice)
Definition: SCR_VehicleDamageManagerComponent.c:1524
UpdateMovementDamage
void UpdateMovementDamage()
Definition: SCR_VehicleDamageManagerComponent.c:524
Attribute
enum EVehicleHitZoneGroup EHitZoneGroup Attribute("1.5", desc:"Max distance of hitzone, which should receive damage, from contact point.", category:"Collision Damage")] protected float m_fMaxSharedDamageDistance
PROPELLER
PROPELLER
Definition: SCR_VehicleDamageManagerComponent.c:16
GetIsClientAuthority
override bool GetIsClientAuthority()
Definition: game.c:268
ROTOR_ASSEMBLY
ROTOR_ASSEMBLY
Definition: SCR_VehicleDamageManagerComponent.c:13
m_fTopMultiplier
float m_fTopMultiplier
Definition: SCR_VehicleDamageManagerComponent.c:46
GetEngineEfficiency
float GetEngineEfficiency()
Definition: SCR_VehicleDamageManagerComponent.c:578
RegisterVehicleHitZone
void RegisterVehicleHitZone(notnull HitZone hitZone)
Definition: SCR_VehicleDamageManagerComponent.c:448
GetBottomMultiplier
float GetBottomMultiplier()
Definition: SCR_VehicleDamageManagerComponent.c:73
m_eSuppliesFireState
SCR_ESecondaryExplosionScale m_eSuppliesFireState
Definition: SCR_VehicleDamageManagerComponent.c:237
m_FuelManager
protected FuelManagerComponent m_FuelManager
Definition: SCR_VehicleDamageManagerComponent.c:215
GetInstigator
BaseProjectileComponentClass GameComponentClass GetInstigator()
HUGE_MOMENTUM
@ HUGE_MOMENTUM
Definition: SCR_VehicleDamageManagerComponent.c:140
m_fOccupantsSpeedDeath
protected float m_fOccupantsSpeedDeath
Definition: SCR_VehicleDamageManagerComponent.c:52
HULL
HULL
Definition: SCR_VehicleDamageManagerComponent.c:2
NIGHT_OPTICS
NIGHT_OPTICS
Definition: SCR_VehicleDamageManagerComponent.c:11
CARGO
CARGO
Definition: SCR_VehicleDamageManagerComponent.c:7
TINY_DESTRUCTIBLE
@ TINY_DESTRUCTIBLE
Definition: SCR_VehicleDamageManagerComponent.c:141
SCR_CharacterDamageManagerComponent
Definition: SCR_CharacterDamageManagerComponent.c:18
m_sFuelTankFireStateSignal
protected string m_sFuelTankFireStateSignal
Definition: SCR_VehicleDamageManagerComponent.c:174
TINY_MOMENTUM
@ TINY_MOMENTUM
Definition: SCR_VehicleDamageManagerComponent.c:136
EOnPhysicsActive
void EOnPhysicsActive(IEntity owner, bool activeState)
Definition: SCR_VehicleDamageManagerComponent.c:1385
m_eFuelTankFireState
SCR_ESecondaryExplosionScale m_eFuelTankFireState
Definition: SCR_VehicleDamageManagerComponent.c:234
m_vFuelTankFireOrigin
protected vector m_vFuelTankFireOrigin
Definition: SCR_VehicleDamageManagerComponent.c:243
SCR_DamageManagerComponentClass
enum ECharacterHitZoneGroup SCR_DamageManagerComponentClass
m_aVehicleHitZones
protected ref array< HitZone > m_aVehicleHitZones
Common vehicle features that will influence its simulation.
Definition: SCR_VehicleDamageManagerComponent.c:196
SetFuelTankFireState
protected void SetFuelTankFireState(SCR_ESecondaryExplosionScale state, vector origin=vector.Zero)
Definition: SCR_VehicleDamageManagerComponent.c:1489
m_CompartmentManager
protected SCR_BaseCompartmentManagerComponent m_CompartmentManager
Definition: SCR_VehicleDamageManagerComponent.c:191
GetRearMultiplier
float GetRearMultiplier()
Definition: SCR_VehicleDamageManagerComponent.c:80
SMALL_MOMENTUM
@ SMALL_MOMENTUM
Definition: SCR_VehicleDamageManagerComponent.c:137
m_fFuelTankFireDamageTimeout
protected float m_fFuelTankFireDamageTimeout
Definition: SCR_VehicleDamageManagerComponent.c:216
GetEngineMalfunctionThreshold
float GetEngineMalfunctionThreshold()
Definition: SCR_VehicleDamageManagerComponent.c:571
m_fVehicleFireDamageTimeout
protected float m_fVehicleFireDamageTimeout
Definition: SCR_VehicleDamageManagerComponent.c:211
EResourceType
EResourceType
Definition: SCR_ResourceContainer.c:1
OnPostInit
override void OnPostInit(IEntity owner)
Called on PostInit when all components are added.
Definition: SCR_VehicleDamageManagerComponent.c:408
MEDIUM_MOMENTUM
@ MEDIUM_MOMENTUM
Definition: SCR_VehicleDamageManagerComponent.c:138
m_bPrintRelativeForce
protected bool m_bPrintRelativeForce
Definition: SCR_VehicleDamageManagerComponent.c:156
GetDamageManager
proto external SCR_DamageManagerComponent GetDamageManager()
Returns component which handles damage.
m_iVehicleFireStateSignalIdx
protected int m_iVehicleFireStateSignalIdx
Definition: SCR_VehicleDamageManagerComponent.c:223
m_bIsInContact
protected bool m_bIsInContact
Definition: SCR_VehicleDamageManagerComponent.c:188
CollisionDamage
bool CollisionDamage(notnull IEntity owner, notnull IEntity other, notnull Contact contact)
Definition: SCR_VehicleDamageManagerComponent.c:1102
GetRightMultiplier
float GetRightMultiplier()
Definition: SCR_VehicleDamageManagerComponent.c:94
MEDIUM_DESTRUCTIBLE
@ MEDIUM_DESTRUCTIBLE
Definition: SCR_VehicleDamageManagerComponent.c:143
WHEELS
WHEELS
Definition: SCR_VehicleDamageManagerComponent.c:6
GetOwner
IEntity GetOwner()
Owner entity of the fuel tank.
Definition: SCR_FuelNode.c:128
m_fSuppliesFireDamageTimeout
protected float m_fSuppliesFireDamageTimeout
Definition: SCR_VehicleDamageManagerComponent.c:220
UpdateFuelTankFireState
protected void UpdateFuelTankFireState(float fireRate, float timeSlice)
Definition: SCR_VehicleDamageManagerComponent.c:1546
SCR_EngineHitZone
Definition: SCR_EngineHitZone.c:1
m_fMaxRelativeForce
protected float m_fMaxRelativeForce
Definition: SCR_VehicleDamageManagerComponent.c:189
m_fOccupantsDamageSpeedThreshold
protected float m_fOccupantsDamageSpeedThreshold
Definition: SCR_VehicleDamageManagerComponent.c:49
SMALL_DESTRUCTIBLE
@ SMALL_DESTRUCTIBLE
Definition: SCR_VehicleDamageManagerComponent.c:142
ToggleResponseIndexTicking
void ToggleResponseIndexTicking(IEntity owner, bool activeState)
Definition: SCR_VehicleDamageManagerComponent.c:1373
CanBeHealed
override bool CanBeHealed()
Return true if there is damage that can be repaired.
Definition: SCR_VehicleDamageManagerComponent.c:1274
GetMinImpulse
float GetMinImpulse()
Definition: SCR_VehicleDamageManagerComponent.c:1699
SCR_BaseContainerTools
Definition: SCR_BaseContainerTools.c:3
m_eVehicleFireState
SCR_ESecondaryExplosionScale m_eVehicleFireState
Definition: SCR_VehicleDamageManagerComponent.c:231
SCR_FuelHitZone
Definition: SCR_FuelHitZone.c:1
SCR_DamageContext
Definition: SCR_DamageContext.c:7
GetGearboxEfficiency
float GetGearboxEfficiency()
Definition: SCR_VehicleDamageManagerComponent.c:635
m_fEngineEfficiency
protected float m_fEngineEfficiency
Definition: SCR_VehicleDamageManagerComponent.c:200
UpdateSuppliesFireState
protected void UpdateSuppliesFireState(float fireRate, float timeSlice)
Definition: SCR_VehicleDamageManagerComponent.c:1614
SCR_ResourceContainer
Definition: SCR_ResourceContainer.c:34
LIGHT
LIGHT
Definition: SCR_VehicleDamageManagerComponent.c:19
m_aDebugShapes
protected ref array< ref Shape > m_aDebugShapes
Definition: SCR_PowerlineGeneratorEntity.c:64
IsInContact
bool IsInContact()
Definition: SCR_VehicleDamageManagerComponent.c:402
TAIL_ROTOR
TAIL_ROTOR
Definition: SCR_VehicleDamageManagerComponent.c:14
EDamageType
EDamageType
Definition: EDamageType.c:12
DamageSurroundingHitzones
float DamageSurroundingHitzones(vector position, float damage, EDamageType damageType)
Definition: SCR_VehicleDamageManagerComponent.c:665
EVehicleHitZoneGroup
EVehicleHitZoneGroup
Definition: SCR_VehicleDamageManagerComponent.c:1
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
GetTopMultiplier
float GetTopMultiplier()
Definition: SCR_VehicleDamageManagerComponent.c:101
CONTROLS
CONTROLS
Definition: SCR_VehicleDamageManagerComponent.c:18
SCR_ResourceEncapsulator
Definition: SCR_ResourceEncapsulator.c:1
SetGearboxFunctional
protected void SetGearboxFunctional(bool functional)
Definition: SCR_VehicleDamageManagerComponent.c:609
m_FuelTankFireParticle
protected ParticleEffectEntity m_FuelTankFireParticle
Definition: SCR_VehicleDamageManagerComponent.c:214
SCR_GearboxHitZone
Definition: SCR_GearboxHitZone.c:1
AMMO_STORAGE
AMMO_STORAGE
Definition: SCR_VehicleDamageManagerComponent.c:8
m_iFuelTankFireStateSignalIdx
protected int m_iFuelTankFireStateSignalIdx
Definition: SCR_VehicleDamageManagerComponent.c:224
TickResponseIndexCheck
void TickResponseIndexCheck()
Definition: SCR_VehicleDamageManagerComponent.c:1328
LARGE_MOMENTUM
@ LARGE_MOMENTUM
Definition: SCR_VehicleDamageManagerComponent.c:139
DamageManagerComponent
Definition: DamageManagerComponent.c:12
VehicleBuoyancyComponent
Definition: VehicleBuoyancyComponent.c:12
InitStaticMapForIndices
void InitStaticMapForIndices()
Definition: SCR_VehicleDamageManagerComponent.c:1706
UpdateFireDamage
override void UpdateFireDamage(float timeSlice)
Definition: SCR_VehicleDamageManagerComponent.c:1448
position
vector position
Definition: SCR_DestructibleTreeV2.c:30
ENGINE
ENGINE
Definition: SCR_VehicleDamageManagerComponent.c:3
m_iSuppliesFireStateSignalIdx
protected int m_iSuppliesFireStateSignalIdx
Definition: SCR_VehicleDamageManagerComponent.c:225
GetMaxSharedDamageDistance
float GetMaxSharedDamageDistance()
Definition: SCR_VehicleDamageManagerComponent.c:59
m_fBottomMultiplier
float m_fBottomMultiplier
Definition: SCR_VehicleDamageManagerComponent.c:34
OnSuppliesFireStateChanged
protected void OnSuppliesFireStateChanged()
Definition: SCR_VehicleDamageManagerComponent.c:1502
GetOccupantsDamageSpeedThreshold
float GetOccupantsDamageSpeedThreshold()
Definition: SCR_VehicleDamageManagerComponent.c:108
FullHeal
override void FullHeal(bool ignoreHealingDOT=true)
Definition: SCR_VehicleDamageManagerComponent.c:1300
m_vFrontalImpact
protected vector m_vFrontalImpact
Definition: SCR_VehicleDamageManagerComponent.c:55
GetHitDirection
SCR_EBoxSide GetHitDirection(vector position)
Definition: SCR_VehicleDamageManagerComponent.c:802
UnregisterVehicleHitZone
void UnregisterVehicleHitZone(HitZone hitZone)
Definition: SCR_VehicleDamageManagerComponent.c:459
SCR_EBoxSide
SCR_EBoxSide
Definition: SCR_EBoxSide.c:2
m_fRightMultiplier
float m_fRightMultiplier
Definition: SCR_VehicleDamageManagerComponent.c:43
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180