1 #define ENABLE_BASE_DESTRUCTION
5 [
Attribute(
"0", UIWidgets.Slider,
"Scale of damage passed to parent default hitzone\nIgnores base damage multiplier, reduction and threshold\nDamage type multipliers are applied",
"0 100 0.001")]
6 protected float m_fPassDamageToParentScale;
8 [
Attribute(
desc:
"Rules for passing damage to parent and root damage managers")]
9 protected ref array<ref SCR_DamagePassRule> m_aDamagePassRules;
12 protected ref PointInfo m_SecondaryExplosionPoint;
18 protected string m_sDestructionSoundEvent;
21 protected ResourceName m_sDestructionParticle;
23 [
Attribute(uiwidget: UIWidgets.Coords,
"Position of the effect in model space",
category:
"Effects")]
24 protected vector m_vParticleOffset;
26 protected ParticleEffectEntity m_DstParticle;
27 protected SCR_DamageManagerComponent m_ParentDamageManager;
28 protected SCR_DamageManagerComponent m_RootDamageManager;
29 protected SCR_BaseCompartmentManagerComponent m_CompartmentManager;
31 #ifdef ENABLE_BASE_DESTRUCTION
35 return m_pDestructionHandler;
39 override void OnInit(IEntity pOwnerEntity, GenericComponent pManagerComponent)
41 super.OnInit(pOwnerEntity, pManagerComponent);
43 m_CompartmentManager = SCR_BaseCompartmentManagerComponent.Cast(pOwnerEntity.FindComponent(SCR_BaseCompartmentManagerComponent));
46 IEntity parent = pOwnerEntity.GetParent();
48 m_ParentDamageManager = SCR_DamageManagerComponent.Cast(parent.FindComponent(SCR_DamageManagerComponent));
51 IEntity root = pOwnerEntity.GetRootParent();
53 m_RootDamageManager = SCR_DamageManagerComponent.Cast(root.FindComponent(SCR_DamageManagerComponent));
55 if (m_pDestructionHandler)
56 m_pDestructionHandler.Init(pOwnerEntity,
this);
58 if (m_SecondaryExplosionPoint)
59 m_SecondaryExplosionPoint.Init(pOwnerEntity);
78 override float ComputeEffectiveDamage(notnull
BaseDamageContext damageContext,
bool isDOT)
80 vector hitTransform[3] = {damageContext.hitPosition, damageContext.hitDirection, damageContext.hitNormal};
83 if (!isDOT && m_fPassDamageToParentScale != 0)
84 PassDamageToParent(damageContext.damageType, damageContext.damageValue, damageContext.instigator, hitTransform, damageContext.material);
90 if (isDOT && !rule.m_bAllowDOT)
94 if (!rule.m_aSourceDamageTypes.IsEmpty() && !rule.m_aSourceDamageTypes.Contains(damageContext.damageType))
98 if (!rule.m_aDamageStates.IsEmpty() && !rule.m_aDamageStates.Contains(GetDamageState()))
102 type = damageContext.damageType;
104 type = rule.m_eOutputDamageType;
106 if (rule.m_bPassToRoot)
107 PassDamageToRoot(damageContext.damageType, damageContext.damageValue * rule.m_fMultiplier, damageContext.instigator, hitTransform, damageContext.material);
109 if (rule.m_bPassToParent)
110 PassDamageToParent(damageContext.damageType, damageContext.damageValue * rule.m_fMultiplier, damageContext.instigator, hitTransform, damageContext.material);
112 if (rule.m_bPassToDefaultHitZone)
113 PassDamageToDefaultHitZone(damageContext.damageType, damageContext.damageValue * rule.m_fMultiplier, damageContext.instigator, hitTransform, damageContext.material);
116 return super.ComputeEffectiveDamage(damageContext, isDOT);
128 void PassDamageToParent(
EDamageType type,
float damage, notnull
Instigator instigator, inout vector transform[3], SurfaceProperties surface =
null)
130 if (!m_ParentDamageManager)
136 SCR_DamageContext damageContext =
new SCR_DamageContext(
type, damage, transform, m_ParentDamageManager.GetOwner(), m_ParentDamageManager.GetDefaultHitZone(), instigator, surface, -1, -1);
138 m_ParentDamageManager.HandleDamage(damageContext);
150 void PassDamageToRoot(
EDamageType type,
float damage, notnull
Instigator instigator, inout vector transform[3], SurfaceProperties surface =
null)
159 if (defaultHZ !=
this)
176 void PassDamageToDefaultHitZone(
EDamageType type,
float damage, notnull
Instigator instigator, inout vector transform[3], SurfaceProperties surface =
null)
178 SCR_DamageManagerComponent damageManager = SCR_DamageManagerComponent.Cast(GetHitZoneContainer());
179 if (!damageManager || !damageManager.GetDefaultHitZone())
185 HitZone defaultHZ = damageManager.GetDefaultHitZone();
186 if (defaultHZ !=
this)
189 damageManager.HandleDamage(damageContext);
195 float GetSecondaryExplosionScale()
202 PointInfo GetSecondaryExplosionPoint()
204 return m_SecondaryExplosionPoint;
209 override void OnDamageStateChanged()
211 super.OnDamageStateChanged();
229 PlayDestructionSound(state);
230 PlayDestructionParticle(state);
235 void StartDestruction(
bool immediate =
false)
246 SCR_DamageManagerComponent damageManager = parentDamageManager;
248 damageManager = SCR_DamageManagerComponent.Cast(GetHitZoneContainer());
252 instigator = damageManager.GetInstigator();
257 if (m_pDestructionHandler)
258 m_pDestructionHandler.StartDestruction(immediate);
263 protected void StopDestruction()
266 if (m_pDestructionHandler)
267 GetGame().GetCallqueue().CallLater(m_pDestructionHandler.OnRepair);
275 if (!hitZoneContainer)
280 return damageManager;
284 return damageManager;
286 IEntity parent =
GetOwner().GetParent();
291 return damageManager;
293 parent = parent.GetParent();
296 return damageManager;
301 protected void PlayDestructionSound(
EDamageState damageState)
304 if (System.IsConsoleApp())
310 if (m_sDestructionSoundEvent.IsEmpty())
318 SCR_DamageManagerComponent hitZoneContainer = SCR_DamageManagerComponent.Cast(GetHitZoneContainer());
319 if (
IsProxy() && hitZoneContainer && !hitZoneContainer.IsRplReady())
328 owner.GetBounds(mins, maxs);
329 vector center = vector.Lerp(mins, maxs, 0.5);
336 slotInfo.GetModelTransform(mat);
337 center = center + mat[3];
340 SoundComponent soundComponent = SoundComponent.Cast(mainParent.FindComponent(SoundComponent));
344 soundComponent.SoundEventOffset(m_sDestructionSoundEvent, center);
348 SoundComponent soundComponent = SoundComponent.Cast(owner.FindComponent(SoundComponent));
352 soundComponent.SoundEvent(m_sDestructionSoundEvent);
361 if (System.IsConsoleApp())
364 if (state ==
EDamageState.DESTROYED && !m_DstParticle && !m_sDestructionParticle.IsEmpty())
366 ParticleEffectEntitySpawnParams spawnParams();
367 spawnParams.Transform[3] = m_vParticleOffset;
369 spawnParams.UseFrameEvent =
true;
370 m_DstParticle = ParticleEffectEntity.SpawnParticleEffect(m_sDestructionParticle, spawnParams);