57#ifdef ENABLE_DESTRUCTION
58 static const int INACTIVE_TREE_INDEX = -1;
59 static const int DESTROYED_TREE_INDEX = -2;
61 static bool s_bPrintTreeDamage = 0;
66 private int m_iIndex = INACTIVE_TREE_INDEX;
72 return m_iIndex == DESTROYED_TREE_INDEX;
77 void SetToDestroy(
bool sentRPC =
false)
90 synchManager.SynchronizeSetToDestroy(
id);
100 if (!GetIsDestroyed())
102 Physics physics = GetPhysics();
108 IEntity child = BuildHierarchy();
114 if (m_iIndex < 0 || !synchManager)
117 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
119 if (treeData && treeData.m_aTreePartsToBreak)
121 foreach (
int i : treeData.m_aTreePartsToBreak)
124 RemoveTreePartFromParent(i)
127 treeData.m_aTreePartsToBreak.Clear();
128 treeData.m_aTreePartsToBreak = null;
131 m_iIndex = DESTROYED_TREE_INDEX;
134 if (treeData && treeData.m_aTreeParts)
144 if (!treeData || !treeData.m_aCachedTreePartsToDestroy)
147 int cachedTreePartsCount = treeData.m_aCachedTreePartsToDestroy.Count();
148 for (
int i = cachedTreePartsCount-1; i >= 0; i--)
150 SCR_TreePartV2 treePart = FindTreePart(treeData.m_aCachedTreePartsToDestroy[i].treePartIdx);
154 if (treeData.m_aCachedTreePartsToDestroy[i].isDynamic)
155 treePart.SetPhysics(
true);
157 treePart.SetPhysics(
false);
159 treePart.CachePosition(treeData.m_aCachedTreePartsToDestroy[i].position);
160 treePart.CacheRotation(treeData.m_aCachedTreePartsToDestroy[i].rotation);
163 if (!treeData.m_aCachedTreePartsToDestroy[i].isParented)
164 treePart.ClientSetToBreakFromParent();
166 treeData.m_aCachedTreePartsToDestroy[i] = null;
167 treeData.m_aCachedTreePartsToDestroy.Remove(i);
169 treeData.m_aCachedTreePartsToDestroy.Clear();
170 treeData.m_aCachedTreePartsToDestroy = null;
174 private IEntity BuildHierarchy()
177 if (!prefabData || !prefabData.m_TreePartHierarchy || prefabData.m_TreePartHierarchy.m_Prefab.GetPath() ==
"-1")
180 if (m_iIndex < 0 || !synchManager)
183 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
186 treeData =
new SCR_ActiveTreeData();
188 if (!treeData.m_aTreeParts)
189 treeData.m_aTreeParts = {};
192 if (!resource.IsValid())
210 rootTreePart.m_vLockedOrigin =
GetOrigin();
211 treeData.m_aTreeParts.Insert(rootTreePart);
214 prefabData.m_TreePartHierarchy.SpawnAllChildren(rootEnt, treeData.m_aTreeParts);
216 array<IEntity> children = {};
217 SCR_Global.GetHierarchyEntityList(rootEnt, children);
221 treePart.m_ParentTree =
this;
224 prefabData.m_TreePartHierarchy = null;
232 void SetRotationOfTreePart(
int treePartIdx,
float quat[4])
238 foundTreePart.SetRotation(quat);
245 void CacheRotationOfTreePart(
int treePartIdx,
float quat[4])
252 foundTreePart.CacheRotation(quat);
259 void CacheSwitchTreePartPhysics(
int treePartIdx,
bool toDynamic)
266 foundTreePart.SetPhysics(toDynamic);
281 foundTreePart.SetToBreak(treePartIdx, positionVector, impulseVector, damageType);
286 void SetToBreak(
int treePartIdx)
292 if (m_iIndex < 0 || !synchManager)
295 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
298 treeData =
new SCR_ActiveTreeData();
300 if (!treeData.m_aTreePartsToBreak)
301 treeData.m_aTreePartsToBreak = {};
303 treeData.m_aTreePartsToBreak.Insert(treePartIdx);
307 foundTreePart.SetToBreak();
313 void RemoveTreePartFromParent(
int treePartIndex)
319 foundTreePart.RemoveFromParent();
329 void CacheDestroyedTreePart(
int treePartIdx,
vector position,
float quat[4],
bool isDynamic,
bool isParented)
332 data.treePartIdx = treePartIdx;
337 data.isDynamic = isDynamic;
338 data.isParented = isParented;
340 if (m_iIndex < 0 || !synchManager)
343 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
346 treeData =
new SCR_ActiveTreeData();
348 if (!treeData.m_aCachedTreePartsToDestroy)
349 treeData.m_aCachedTreePartsToDestroy = {};
351 treeData.m_aCachedTreePartsToDestroy.Insert(
data);
361 void UpdateTransformOfTreePart(
int treePartIdx,
vector pos,
float quat[4],
vector velocityLinear,
vector velocityAngular)
367 treePart.UpdateTransform(pos, quat, velocityLinear, velocityAngular);
373 void SetPositionOfTreePart(
int treePartIdx,
vector pos)
379 foundTreePart.SetPosition(pos);
386 void CachePositionOfTreePart(
int treePartIdx,
vector pos)
392 foundTreePart.CachePosition(pos);
399 void UpdateVelocityOfTreePart(
int treePartIdx,
vector velocity)
405 foundTreePart.SetVelocity(velocity);
412 void UpdateAngularVelocityOfTreePart(
int treePartIdx,
vector angularVelocity)
418 foundTreePart.SetAngularVelocity(angularVelocity);
424 void ClientSwitchTreePartToStatic(
int treePartIdx)
430 foundTreePart.SetPhysics(
false);
442 SCR_TreeTraceInfo info =
new SCR_TreeTraceInfo();
449 if (m_iIndex < 0 || !synchManager)
452 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
455 treeData =
new SCR_ActiveTreeData();
457 if (!treeData.m_aTreeTraceInfo)
458 treeData.m_aTreeTraceInfo = {};
460 treeData.m_aTreeTraceInfo.Insert(info);
467 if (m_iIndex < 0 || !synchManager)
470 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
472 if (!treeData || !treeData.m_aTreeTraceInfo)
475 int count = treeData.m_aTreeTraceInfo.Count();
476 for (
int i = count - 1; i >= 0; i--)
478 SCR_TreeTraceInfo info = treeData.m_aTreeTraceInfo[i];
484 if (treePart.m_bDebugDamage)
485 treePart.PrintDamageDebug(info.impulse, info.type);
487 float reducedImpulse;
488 if (treePart.WouldBreak(info.impulse, info.type, reducedImpulse))
489 treePart.SetToBreak(positionVector: info.position, impulseVector: reducedImpulse * info.direction, damageType: info.type);
497 param.Start = info.position;
498 param.End = info.position + info.direction;
500 param.LayerMask = EPhysicsLayerDefs.Camera;
504 vector tracePos = GetWorld().TraceMove(param,
SCR_Global.FilterCallback_IgnoreAllButEntityWithChildren) * (param.End - param.Start) + param.Start;
506 IEntity traceEnt = param.TraceEnt;
512 if (tracedTreePart.m_bDebugDamage)
513 tracedTreePart.PrintDamageDebug(info.impulse, info.type);
515 float reducedImpulse;
516 if (tracedTreePart.WouldBreak(info.impulse, info.type, reducedImpulse))
517 tracedTreePart.SetToBreak(positionVector: info.position, impulseVector: reducedImpulse * info.direction, damageType: info.type);
521 treeData.m_aTreeTraceInfo[i] = null;
525 treeData.m_aTreeTraceInfo.Clear();
526 treeData.m_aTreeTraceInfo = null;
530 void OnTreePartHitGround()
532 if (m_iIndex < 0 || !synchManager)
535 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
537 if (treeData.m_fTimeSinceLastSoundEvent < 0.5)
539 treeData.m_fTimeSinceLastSoundEvent = 0;
543 BaseSoundComponent soundComponent = synchManager.GetSoundComponent();
554 inout
vector hitTransform[3],
562 if (s_bPrintTreeDamage)
567 if (damage < prefabData.m_fDamageThreshold)
574 m_iIndex = synchManager.AddActiveTree();
579 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
581 treeData.m_fDamage += damage;
582 if (treeData.m_fDamage < prefabData.m_fHealth)
590 vector positionVector = outMat[0];
595 positionVector =
"0 0 0";
615 if (m_iIndex < 0 || !synchManager)
618 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
620 if (!treeData || !treeData.m_aTreeParts)
625 if (treePart.GetTreePartIndex() == treePartIdx)
635 if (m_iIndex < 0 || !synchManager)
638 SCR_ActiveTreeData treeData = synchManager.GetActiveTreeData(m_iIndex);
640 if (!GetIsDestroyed())
644 treeData.m_fTimeSinceLastSoundEvent = 0;
647 treeData.m_fTimeSinceLastSoundEvent += timeSlice;
649 if (treeData.m_fTimeSinceLastSoundEvent > 10)
651 treeData.m_fTimeSinceLastSoundEvent = 0;