Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_DestructibleHitzone.c
Go to the documentation of this file.
1//---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
2// TODO: Visual destruction effects should be handled via separate component called by damage manager, not hitzone
3#define ENABLE_BASE_DESTRUCTION
5{
6 [Attribute(desc: "Secondary explosion reference point", category: "Secondary damage")]
8
9 [Attribute("", UIWidgets.Auto, desc: "Destruction Handler")]
11
12 [Attribute(desc: "Destruction sound event name", category: "Effects")]
13 protected string m_sDestructionSoundEvent;
14
15 [Attribute(desc: "Particle effect for destruction", params: "ptc", category: "Effects")]
17
18 [Attribute(uiwidget: UIWidgets.Coords, "Position of the effect in model space", category: "Effects")]
20
21 protected ParticleEffectEntity m_DstParticle; // Destruction particle
22 protected SCR_DamageManagerComponent m_ParentDamageManager; // Damage manager of the direct parent
23 protected SCR_DamageManagerComponent m_RootDamageManager;
24 protected SCR_BaseCompartmentManagerComponent m_CompartmentManager; // The part may have occupants that we want to damage
25 protected ref array<ChimeraCharacter> m_aEjectedCharacters;
26
28 protected const int FORCED_DESTRUCTION_DELAY = 1000;
29
30#ifdef ENABLE_BASE_DESTRUCTION
31 //------------------------------------------------------------------------------------------------
36
37 //------------------------------------------------------------------------------------------------
38 override void OnInit(IEntity pOwnerEntity, GenericComponent pManagerComponent)
39 {
40 super.OnInit(pOwnerEntity, pManagerComponent);
41
42 m_CompartmentManager = SCR_BaseCompartmentManagerComponent.Cast(pOwnerEntity.FindComponent(SCR_BaseCompartmentManagerComponent));
43
44 // Parent damage manager
45 IEntity parent = pOwnerEntity.GetParent();
46 if (parent)
47 m_ParentDamageManager = SCR_DamageManagerComponent.Cast(parent.FindComponent(SCR_DamageManagerComponent));
48
49 // Root damage manager
50 IEntity root = pOwnerEntity.GetRootParent();
51 if (root)
52 m_RootDamageManager = SCR_DamageManagerComponent.Cast(root.FindComponent(SCR_DamageManagerComponent));
53
55 m_pDestructionHandler.Init(pOwnerEntity, this);
56
58 m_SecondaryExplosionPoint.Init(pOwnerEntity);
59 }
60
61 //------------------------------------------------------------------------------------------------
64 {
65 return GetMaxHealth();
66 }
67
68 //------------------------------------------------------------------------------------------------
74
75 //------------------------------------------------------------------------------------------------
77 override void OnDamageStateChanged(EDamageState newState, EDamageState previousDamageState, bool isJIP)
78 {
79 super.OnDamageStateChanged(newState, previousDamageState, isJIP);
80
81 EDamageState state = GetDamageState();
82
83 // Restrict AI from accessing this parts compartments
85 m_CompartmentManager.SetCompartmentsAccessibleForAI(state != EDamageState.DESTROYED);
86
87 // Change from destroyed can only mean repair
88 if (GetPreviousDamageState() == EDamageState.DESTROYED)
89 {
91 return;
92 }
93
94 if (state == EDamageState.DESTROYED)
96
97 if(isJIP)
98 return;
99
102 }
103
104 //------------------------------------------------------------------------------------------------
106 void StartDestruction(bool immediate = false)
107 {
109 {
110 bool allEjectedImmediately;
111 if (m_CompartmentManager.EjectRandomOccupants(1, true, allEjectedImmediately, true) && !allEjectedImmediately)//ejects all occupants of the vehicle
112 {
113 array<BaseCompartmentSlot> compartments = {};
114 m_CompartmentManager.GetCompartments(compartments);
115 ChimeraCharacter character;
117 PlayerManager playerMGR = GetGame().GetPlayerManager();
118 foreach (BaseCompartmentSlot compartment : compartments)
119 {
120 if (!compartment)
121 continue;
122
123 character = ChimeraCharacter.Cast(compartment.GetOccupant());
124 if (!character)
125 continue;
126
127 access = SCR_CompartmentAccessComponent.Cast(character.GetCompartmentAccessComponent());
128 if (!access)
129 continue;
130
131 if (playerMGR && playerMGR.GetPlayerIdFromControlledEntity(character) == 0)
132 continue;//we dont wait for AI as they are ejected immediately
133
136
137 m_aEjectedCharacters.Insert(character);
139 }
140
142 {
143 //since its possible that client may fail the excecution of the getting out process (freeze/CTD/timeout/etc) then we have to have a backup plan
144 GetGame().GetCallqueue().CallLater(ForceStartDestruction, FORCED_DESTRUCTION_DELAY);
145
146 return;//now we wait for all characters to be ejected from the vehicle before we delete it
147 }
148 }
149 }
150
152 m_pDestructionHandler.StartDestruction(immediate);
153 }
154
155 //------------------------------------------------------------------------------------------------
159 protected void OnCharacterEjectedFromDestroyedCompartment(ChimeraCharacter playerCharacter, IEntity compartmentEntity)
160 {
161 if (GetOwner() && GetOwner().GetRootParent() != compartmentEntity.GetRootParent())
162 return;
163
164 SCR_CompartmentAccessComponent access = SCR_CompartmentAccessComponent.Cast(playerCharacter.GetCompartmentAccessComponent());
165 if (!access)
166 return;
167
169
170 //since CompartmentAccessComponent and BaseCompartmentSlot will indicate that the character is still present when OnPlayerCompartmentExit is invoked, we need to manually keep track of whom we are waiting for
171 m_aEjectedCharacters.RemoveItem(playerCharacter);
172
173 foreach (ChimeraCharacter character : m_aEjectedCharacters)
174 {//if for some reason some character was deleted before it left then we need to remove such entry
175 if (!character)
176 {
177 m_aEjectedCharacters.RemoveItem(null);
178 break;
179 }
180 }
181
183 {
184 GetGame().GetCallqueue().Remove(ForceStartDestruction);
185 m_pDestructionHandler.StartDestruction(false);
186 }
187 }
188
189 //------------------------------------------------------------------------------------------------
191 protected void ForceStartDestruction()
192 {
194 m_pDestructionHandler.StartDestruction(true);
195 }
196
197 //------------------------------------------------------------------------------------------------
199 protected void StopDestruction()
200 {
201 // Must not change model outside frame
203 GetGame().GetCallqueue().CallLater(m_pDestructionHandler.OnRepair);
204 }
205
206 //------------------------------------------------------------------------------------------------
208 {
209 // Futile if there is no hitzonecontainer anymore
210 HitZoneContainerComponent hitZoneContainer = GetHitZoneContainer();
211 if (!hitZoneContainer)
212 return null;
213
214 SCR_VehicleDamageManagerComponent damageManager = SCR_VehicleDamageManagerComponent.Cast(hitZoneContainer);
215 if (damageManager)
216 return damageManager;
217
219 if (damageManager)
220 return damageManager;
221
222 IEntity parent = GetOwner().GetParent();
223 while (parent)
224 {
226 if (damageManager)
227 return damageManager;
228
229 parent = parent.GetParent();
230 }
231
232 return damageManager;
233 }
234
235 //------------------------------------------------------------------------------------------------
237 protected void PlayDestructionSound(EDamageState damageState)
238 {
239 // Sounds are only relevant for non-dedicated clients
240 if (System.IsConsoleApp())
241 return;
242
243 if (damageState != EDamageState.DESTROYED)
244 return;
245
246 if (m_sDestructionSoundEvent.IsEmpty())
247 return;
248
249 IEntity owner = GetOwner();
250 if (!owner)
251 return;
252
253
254 IEntity mainParent = SCR_EntityHelper.GetMainParent(owner);
255 if (mainParent)
256 {
257 // Get position offset for slotted entities
258 vector mins;
259 vector maxs;
260 owner.GetBounds(mins, maxs);
261 vector center = vector.Lerp(mins, maxs, 0.5);
262
263 // Add bone offset
264 EntitySlotInfo slotInfo = EntitySlotInfo.GetSlotInfo(owner);
265 if (slotInfo)
266 {
267 vector mat[4];
268 slotInfo.GetModelTransform(mat);
269 center = center + mat[3];
270 }
271
272 SoundComponent soundComponent = SoundComponent.Cast(mainParent.FindComponent(SoundComponent));
273 if (!soundComponent)
274 return;
275
276 soundComponent.SoundEventOffset(m_sDestructionSoundEvent, center);
277 }
278 else
279 {
280 SoundComponent soundComponent = SoundComponent.Cast(owner.FindComponent(SoundComponent));
281 if (!soundComponent)
282 return;
283
284 soundComponent.SoundEvent(m_sDestructionSoundEvent);
285 }
286 }
287
288 //------------------------------------------------------------------------------------------------
291 {
292 // Particles are only relevant for non-dedicated clients
293 if (System.IsConsoleApp())
294 return;
295
296 if (state == EDamageState.DESTROYED && !m_DstParticle && !m_sDestructionParticle.IsEmpty())
297 {
299 spawnParams.Transform[3] = m_vParticleOffset;
300 spawnParams.Parent = GetOwner();
301 spawnParams.UseFrameEvent = true;
302 m_DstParticle = ParticleEffectEntity.SpawnParticleEffect(m_sDestructionParticle, spawnParams);
303 }
304 }
305#endif
306}
307//---- REFACTOR NOTE END ----
ArmaReforgerScripted GetGame()
Definition game.c:1398
float GetMaxHealth()
void ParticleEffectEntity(IEntitySource src, IEntity parent)
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
void SCR_VehicleDamageManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Adds ability to attach an object to a slot.
proto external Managed FindComponent(typename typeName)
proto external void GetBounds(out vector mins, out vector maxs)
proto external IEntity GetParent()
proto external IEntity GetRootParent()
PointInfo - allows to define position.
Definition PointInfo.c:9
OnPlayerExitCompartment GetOnPlayerCompartmentExit(bool createNew=true)
void PlayDestructionParticle(EDamageState state)
Start destruction particle.
override void OnInit(IEntity pOwnerEntity, GenericComponent pManagerComponent)
void OnCharacterEjectedFromDestroyedCompartment(ChimeraCharacter playerCharacter, IEntity compartmentEntity)
ref SCR_DestructionBaseHandler m_pDestructionHandler
void PlayDestructionSound(EDamageState damageState)
Start destruction sounds.
float GetSecondaryExplosionScale()
Get secondary explosion desired scale. It will determine the prefab retrieved from secondary explosio...
void ForceStartDestruction()
Force begining of the destruction process.
SCR_BaseCompartmentManagerComponent m_CompartmentManager
ref SCR_DestructionBaseHandler GetDestructionHandler()
ref array< ChimeraCharacter > m_aEjectedCharacters
PointInfo GetSecondaryExplosionPoint()
Get secondary explosion desired scale. It will determine the prefab retrieved from secondary explosio...
SCR_VehicleDamageManagerComponent FindParentVehicleDamageManager()
const int FORCED_DESTRUCTION_DELAY
Time after which we will no longer wait for players to leave destroyed vehicle and force start the de...
ParticleEffectEntity m_DstParticle
void StopDestruction()
Stop destruction effects.
void StartDestruction(bool immediate=false)
Start destruction effects.
override void OnDamageStateChanged(EDamageState newState, EDamageState previousDamageState, bool isJIP)
Kill occupants and start destruction.
SCR_DamageManagerComponent m_RootDamageManager
SCR_DamageManagerComponent m_ParentDamageManager
static IEntity GetMainParent(IEntity entity, bool self=false)
EHitZoneGroup GetHitZoneGroup()
Definition SCR_HitZone.c:12
IEntity GetOwner()
Definition SCR_HitZone.c:42
SCR_FieldOfViewSettings Attribute
EDamageState