14 private float m_fMass;
15 [
Attribute(
"9",
UIWidgets.EditBox,
"Enter the max linear acceleration of this tree part for each local axis.",
category:
"Physics settings")]
16 private float m_fMaxAccelerationLinear;
18 private vector m_vMaxAccelerationAngular;
19 [
Attribute(
"0.05",
UIWidgets.EditBox,
"Enter the max speed of rotation around local Y axis of this tree part.",
category:
"Physics settings")]
20 private float m_fMaxYRotationVelocity;
22 private bool m_bAllowLinearMovement;
24 private bool m_bAllowGlobalYRotation;
26 private float m_fMaxJointLoad;
31 [
Attribute(
"1",
UIWidgets.EditBox,
"Enter the minimum impact that should be able to move with this object. Impact = reduced impulse.",
category:
"Damage settings")]
32 private float m_fMinImpact;
35 [
Attribute(
"1",
UIWidgets.EditBox,
"Enter explosion resistance of this tree part. Every explosive impulse on this tree part will be divided by this number.",
category:
"Damage settings")]
36 private float m_fExplosionResistance;
37 [
Attribute(
"1",
UIWidgets.EditBox,
"Enter kinetic resistance of this tree part. Every kinetic (projectile) impulse on this tree part will be divided by this number.",
category:
"Damage settings")]
38 private float m_fKineticResistance;
39 [
Attribute(
"1",
UIWidgets.EditBox,
"Enter collision resistance of this tree part. Every collision (vehicle) impulse on this tree part will be divided by this number.",
category:
"Damage settings")]
40 private float m_fCollisionResistance;
41 [
Attribute(
"1",
UIWidgets.EditBox,
"Enter melee resistance of this tree part. Every melee impulse on this tree part will be divided by this number.",
category:
"Damage settings")]
42 private float m_fMeleeResistance;
51 private int m_iTreePartIndex;
55 private vector m_vRootDirtOffset;
57#ifdef ENABLE_DESTRUCTION
64 static const float GO_TO_STATIC_THRESHOLD = 0.2;
65 static const float GO_TO_STATIC_ANGULAR_THRESHOLD = 0.2;
66 static const int GO_TO_STATIC_TIME_THRESHOLD = 2;
67 static const int GO_TO_STATIC_TIME_THRESHOLD_MAX = 20;
72 static const int TARGET_RPC_COUNT = 4;
73 static const float NET_TELEPORT_DISTANCE = 10;
74 static const float NET_TELEPORT_ANGLE = 5;
79 private Physics m_Physics = null;
85 private vector m_vCenterOfMass;
86 private float m_fLastSpeedLinear = 0;
87 private vector m_vLastSpeedAngular =
"0 0 0";
88 private bool m_bSpawnedRootBall =
false;
89 private IEntity m_RootsEntity = null;
90 private Physics m_RootsPhysics = null;
93 private vector m_vSynchVelocity;
94 private vector m_vLerpStartVector;
95 private vector m_vLerpTargetPosition;
96 private float m_fLerpStartQuat[4];
97 private float m_fLerpTargetQuat[4];
98 private float m_fLerpAmountPos = -1;
99 private float m_fLerpAmountRot = -1;
100 private ref array<IEntity> m_aQuerriedEnts =
new array<IEntity>();
101 private float m_fSynchTime = 0;
105 private vector m_vNetPosition;
106 private vector m_vNetVelocityLinear;
107 private vector m_vNetVelocityAngular;
108 private float m_fTimeSinceLastTick;
109 private float m_fNetRotation[4];
110 private bool m_bExtrapolate =
false;
115 private bool m_bApplyCachedRotation =
false;
116 private float m_fCachedRotation[4];
117 private bool m_bApplyCachedPosition =
false;
118 private vector m_vCachedPosition;
119 private bool m_bBreak =
false;
120 private vector m_vImpulseVector =
"0 0 0";
121 private vector m_vPositionVector =
"0 0 0";
127 private float m_fThresholdTime = 0;
128 private float m_fThresholdMaxTime = 0;
133 private bool m_bWakeUp =
false;
134 private bool m_bSwitchToDynamic;
135 private bool m_bSwitchToStatic;
136 private ref SCR_HybridPhysicsInfo m_HybridPhysicsInfo = null;
137 private int m_iContactsCount = 0;
138 private bool m_bBreakFromParent =
false;
143 private bool m_bCreatedJoints =
false;
144 private ref array<PhysicsJoint> m_aChildrenJoints =
new array<PhysicsJoint>();
150 private bool m_bSynchronizeHasParent =
true;
151 private static float m_fTargetSynchTime = -1;
156 private bool m_bSoundHitGroundPlayed =
false;
160 private void ClearPhysicsInfo()
162 if (!m_HybridPhysicsInfo)
165 delete m_HybridPhysicsInfo;
166 m_HybridPhysicsInfo = null;
171 private void StorePhysicsInfo(
IEntity owner)
173 if (!m_Physics || !owner)
178 m_HybridPhysicsInfo =
new SCR_HybridPhysicsInfo;
179 m_HybridPhysicsInfo.m_fMass = m_Physics.GetMass();
181 int numGeoms = m_Physics.GetNumGeoms();
182 for (
int i = 0; i < numGeoms; i++)
184 m_HybridPhysicsInfo.m_aLayerMasks.Insert(m_Physics.GetGeomInteractionLayer(i));
188 m_Physics =
Physics.CreateStatic(owner, -1);
190 int numStoredGeoms = m_HybridPhysicsInfo.m_aLayerMasks.Count();
191 numGeoms = m_Physics.GetNumGeoms();
192 for (
int i = 0; i < numStoredGeoms; i++)
197 m_Physics.SetGeomInteractionLayer(i, m_HybridPhysicsInfo.m_aLayerMasks.Get(i));
203 private void ApplyPhysicsInfo(
IEntity owner)
210 if (!owner || !m_HybridPhysicsInfo)
214 m_Physics =
Physics.CreateDynamic(owner, m_HybridPhysicsInfo.m_fMass, -1);
216 int numStoredGeoms = m_HybridPhysicsInfo.m_aLayerMasks.Count();
217 int numGeoms = m_Physics.GetNumGeoms();
218 for (
int i = 0; i < numStoredGeoms; i++)
223 m_Physics.SetGeomInteractionLayer(i, m_HybridPhysicsInfo.m_aLayerMasks.Get(i));
237 if (treePartIdx == -1)
238 treePartIdx = m_iTreePartIndex;
243 synchManager.SynchronizeSetToBreak(treePartIdx, positionVector, impulseVector, damageType, m_ParentTree.GetID());
248 m_vImpulseVector = impulseVector * 50;
249 m_vPositionVector = positionVector;
250 ResetThresholdTime();
251 m_eDamageType = damageType;
260 if (!m_Physics || !m_Physics.IsDynamic())
263 if (!m_bSpawnedRootBall && m_iTreePartIndex == 0)
268 if (m_vPositionVector ==
"0 0 0")
269 m_vPositionVector = (m_vCenterOfMass +
GetOrigin());
274 m_Physics.ApplyImpulseAt(m_vPositionVector, m_vImpulseVector);
278 if (!m_bAllowLinearMovement)
280 SetOrigin(m_vLockedOrigin);
281 m_Physics.SetVelocity(
"0 0 0");
288 if (!m_bSoundHitGroundPlayed)
292 BaseSoundComponent soundComponent = synchManager.GetSoundComponent();
296 Math3D.MatrixIdentity3(mat);
297 mat[3] = m_vPositionVector;
298 soundComponent.SetTransformation(mat);
309 private void SpawnRootDirt()
311 if (m_RootDirt.GetPath() ==
"-1")
316 if (!resource.IsValid())
324 traceParam.Start = worldPos +
vector.Up;
325 traceParam.End = worldPos -
vector.Up;
327 GetWorld().TraceMove(traceParam, null);
330 if (traceParam.TraceNorm !=
vector.Zero)
332 vector newUp = traceParam.TraceNorm;
338 vector newRight = newUp * mat[2];
339 newRight.Normalize();
342 vector newForward = newRight * newUp;
343 newForward.Normalize();
351 mat[3] = m_vRootDirtOffset;
355 param.TransformMode = ETransformMode.LOCAL;
356 param.Transform = mat;
364 m_RootsEntity =
game.SpawnEntityPrefab(resource, GetWorld(), param);
369 m_bSpawnedRootBall =
true;
374 void RemoveFromParent()
387 BreakJoint(m_ParentJoint,
this, parentTreePart);
388 m_bSynchronizeHasParent =
false;
393 if (m_ParentTree && synchManager)
394 synchManager.SynchronizeRemoveFromParent(m_iTreePartIndex, m_ParentTree.GetID());
401 return m_ParentJoint;
411 if (physicsJoint == m_ParentJoint)
413 m_ParentJoint = null;
417 int count = m_aChildrenJoints.Count();
418 for (
int i = 0; i < count; i++)
420 if (physicsJoint == m_aChildrenJoints.Get(i))
422 m_aChildrenJoints.Remove(i);
430 void DestroyAllJoints()
432 array<IEntity> children =
new array<IEntity>();
433 GetAllChildren(
this, children);
434 int count = children.Count();
436 for (
int i = 0; i < count; i++)
443 BreakJoint(physicsJoint,
this, treePart);
444 treePart.DestroyAllJoints();
451 private void SwitchPhysicsToStatic(
bool switchChildrenPhysics)
456 if (m_Physics.IsDynamic())
458 StorePhysicsInfo(
this);
463 m_bSwitchToStatic =
false;
476 m_bSwitchToStatic =
false;
477 m_bCreatedJoints =
false;
480 ResetThresholdTime();
483 m_Physics =
Physics.CreateStatic(
this, -1);
484 if (m_RootsEntity && !m_RootsPhysics)
486 m_RootsPhysics =
Physics.CreateStatic(m_RootsEntity, -1);
490 if (switchChildrenPhysics)
493 m_bCreatedJoints =
false;
494 array<IEntity> children =
new array<IEntity>();
495 SCR_Global.GetHierarchyEntityList(
this, children);
498 int count = children.Count();
499 for (
int i = 0; i < count; i++)
503 treePart.SwitchPhysicsToStatic(
false);
517 Math3D.MatrixToQuat(mat, q);
519 if (m_ParentTree && synchManager)
521 synchManager.SynchronizeStaticRotation(m_iTreePartIndex, q, m_ParentTree.GetID());
522 synchManager.SynchronizeStaticPosition(m_iTreePartIndex, mat[3], m_ParentTree.GetID());
528 private void SwitchPhysicsToDynamic()
530 if (m_Physics && m_Physics.IsDynamic())
534 array<IEntity> children =
new array<IEntity>();
535 SCR_Global.GetHierarchyEntityList(
this, children);
538 int count = children.Count();
539 for (
int i = 0; i < count; i++)
543 treePart.SwitchPhysicsToDynamic();
550 m_bSwitchToDynamic =
false;
551 ResetThresholdTime();
555 m_RootsPhysics.Destroy();
556 m_RootsPhysics = null;
562 if (!m_Physics.IsDynamic())
566 m_bSwitchToDynamic =
false;
571 m_Physics =
Physics.CreateDynamic(
this, m_fMass, -1);
576 ApplyPhysicsInfo(
this);
577 m_vCenterOfMass = m_Physics.GetCenterOfMass();
590 private void DestroyPhysics()
601 private void LimitAcceleration()
606 vector velocity = m_Physics.GetVelocity();
607 float currentSpeed = velocity.Length();
610 if (currentSpeed != 0)
614 float targetSpeed =
Math.Clamp(currentSpeed, 0, m_fLastSpeedLinear + m_fMaxAccelerationLinear);
615 float multiplier = targetSpeed / currentSpeed;
618 velocity *= multiplier;
619 m_Physics.SetVelocity(velocity);
620 m_fLastSpeedLinear = velocity.Length();
623 vector velocityAngular = m_Physics.GetAngularVelocity();
626 vector localVelocityAngular = velocityAngular.InvMultiply3(mat);
627 for (
int i = 0; i < 3; i++)
629 float targetVelocityAngular =
Math.Clamp(localVelocityAngular[i], 0, m_vLastSpeedAngular[i] + m_vMaxAccelerationAngular[i]);
630 localVelocityAngular[i] = targetVelocityAngular;
633 velocityAngular = localVelocityAngular.Multiply3(mat);
634 m_Physics.SetAngularVelocity(velocityAngular);
639 private void LimitYRotation()
643 if (!m_Physics.IsDynamic())
646 vector angularVelocity = m_Physics.GetAngularVelocity();
648 if (
Math.AbsFloat(angularVelocity[0]) > m_fMaxYRotationVelocity ||
649 Math.AbsFloat(angularVelocity[1]) > m_fMaxYRotationVelocity ||
650 Math.AbsFloat(angularVelocity[2]) > m_fMaxYRotationVelocity)
654 float scale = GetScale();
655 float matMultiplier = 1;
657 matMultiplier /= GetScale();
659 mat[0] = mat[0] * matMultiplier;
660 mat[1] = mat[1] * matMultiplier;
661 mat[2] = mat[2] * matMultiplier;
664 vector localAngularVelocity = angularVelocity.InvMultiply3(mat);
665 float velocity = localAngularVelocity[1];
668 velocity =
Math.Clamp(velocity, -m_fMaxYRotationVelocity, m_fMaxYRotationVelocity);
669 localAngularVelocity[1] = velocity;
672 angularVelocity = localAngularVelocity.Multiply3(mat);
676 if (!m_bAllowGlobalYRotation)
677 angularVelocity[1] = 0;
679 m_Physics.SetAngularVelocity(angularVelocity);
686 if (!joint || !ent1 || !ent2)
689 ent1.RemoveJoint(joint);
690 ent2.RemoveJoint(joint);
696 private void CreateJoints()
698 if (!m_Physics || m_bCreatedJoints)
702 array<IEntity> children =
new array<IEntity>();
703 GetAllChildren(
this, children);
704 int count = children.Count();
706 for (
int i = 0; i < count; i++)
709 if (treePart && !treePart.m_ParentJoint)
711 PhysicsJoint physicsJoint = treePart.CreateLowerJoint(
this);
713 m_aChildrenJoints.Insert(physicsJoint);
714 treePart.CreateJoints();
717 m_bCreatedJoints =
true;
723 private void GetAllChildren(
IEntity parent, notnull inout array<IEntity> allChildren)
732 allChildren.Insert(child);
739 private void StopSelf()
744 if (!m_Physics.IsDynamic())
747 if (!m_bAllowLinearMovement)
749 SetOrigin(m_vLockedOrigin);
750 m_Physics.SetVelocity(
vector.Zero);
757 private void CheckThreshold(
float timeSlice)
762 m_fThresholdMaxTime += timeSlice;
763 if (m_fThresholdMaxTime > GO_TO_STATIC_TIME_THRESHOLD_MAX)
765 if (m_ParentTree && synchManager)
766 synchManager.SynchronizeSwitchTreePartToStatic(m_iTreePartIndex, m_ParentTree.GetID());
767 m_bSwitchToStatic =
true;
770 if (m_iContactsCount <= 0)
772 m_bSoundHitGroundPlayed =
false;
773 m_fThresholdTime = 0;
777 if (!m_Physics || m_bSynchronizeHasParent)
779 if (!m_Physics.IsDynamic())
782 float velocity = m_Physics.GetVelocity().Length();
783 float angularVelocity = m_Physics.GetAngularVelocity().Length();
784 if (velocity < GO_TO_STATIC_THRESHOLD && angularVelocity < GO_TO_STATIC_ANGULAR_THRESHOLD)
786 m_fThresholdTime += timeSlice;
787 if (m_fThresholdTime > GO_TO_STATIC_TIME_THRESHOLD)
789 if (m_ParentTree && synchManager)
790 synchManager.SynchronizeSwitchTreePartToStatic(m_iTreePartIndex, m_ParentTree.GetID());
791 m_bSwitchToStatic =
true;
800 if (!parent || !m_Physics || m_ParentJoint)
803 m_ParentJoint =
PhysicsJoint.CreateFixed(parent,
this, m_vCenterOfMass * GetScale(), parent.m_vCenterOfMass * parent.GetScale(),
true, m_fMaxJointLoad);
805 return m_ParentJoint;
818 treePart.WakeUpParent();
822 private bool AddEnt(
IEntity ent)
824 m_aQuerriedEnts.Insert(ent);
829 private bool FilterEnt(
IEntity ent)
831 if (IsInHierarchy(ent) || ent ==
this)
837 private bool IsInHierarchy(
IEntity ent)
842 array<IEntity> children =
new array<IEntity>();
843 SCR_Global.GetHierarchyEntityList(
this, children);
844 int count = children.Count();
845 for (
int i = 0; i < count; i++)
847 if (ent == children[i])
857 m_aQuerriedEnts.Clear();
861 GetWorld().QueryEntitiesByOBB(m_vBBOXMin, m_vBBOXMax, mat, AddEnt, FilterEnt);
863 int count = m_aQuerriedEnts.Count();
864 for (
int i = 0; i < count; i++)
866 if (m_aQuerriedEnts[i])
870 treePart.WakeUp(
true);
877 void WakeUp(
bool wakeUpParent)
892 void WakeUpHierarchy()
894 SwitchPhysicsToDynamic();
903 int GetTreePartIndex()
905 return m_iTreePartIndex;
911 m_bExtrapolate =
true;
914 m_vNetVelocityLinear = velocityLinear;
915 m_vNetVelocityAngular = velocityAngular;
916 Math3D.QuatCopy(quat, m_fNetRotation);
920 if (m_Physics.IsDynamic())
922 m_Physics.SetVelocity(velocityLinear);
923 m_Physics.SetAngularVelocity(velocityAngular *
Math.DEG2RAD);
928 Math3D.QuatToMatrix(quat, mat);
937 m_fTimeSinceLastTick = 0;
941 void CacheRotation(
float quat[4])
945 m_bApplyCachedRotation =
true;
946 Math3D.QuatCopy(quat, m_fCachedRotation);
950 void CachePosition(
vector pos)
953 m_bApplyCachedPosition =
true;
954 m_vCachedPosition[0] = pos[0];
955 m_vCachedPosition[1] = pos[1];
956 m_vCachedPosition[2] = pos[2];
960 void SetRotation(
float quat[4])
963 Math3D.QuatToMatrix(quat, mat);
971 void SetPosition(
vector pos)
978 void SetVelocity(
vector velocity)
981 if (velocity.Length() < 0.02)
985 m_Physics.SetVelocity(velocity);
989 void SetAngularVelocity(
vector angularVelocity)
992 if (angularVelocity.Length() < 0.02)
996 m_Physics.SetAngularVelocity(angularVelocity);
1000 void SetPhysics(
bool dynamic)
1003 m_bSwitchToDynamic =
true;
1005 m_bSwitchToStatic =
true;
1009 void ClientSetToBreakFromParent()
1011 m_bBreakFromParent =
true;
1013 if (m_Physics && !m_Physics.IsDynamic())
1025 if (m_vCachedPosition && m_bApplyCachedPosition)
1028 SetPosition(m_vCachedPosition);
1029 m_bApplyCachedPosition =
false;
1034 if (m_fCachedRotation && m_bApplyCachedRotation)
1037 SetRotation(m_fCachedRotation);
1038 m_bApplyCachedRotation =
false;
1041 m_bBreakFromParent =
false;
1046 float GetQuatDiff(
float quat1[4],
float quat2[4])
1048 float diff0 =
Math.AbsFloat(quat1[0] - quat2[0]);
1049 float diff1 =
Math.AbsFloat(quat1[1] - quat2[1]);
1050 float diff2 =
Math.AbsFloat(quat1[2] - quat2[2]);
1051 float diff3 =
Math.AbsFloat(quat1[3] - quat2[3]);
1052 float diffSum = diff0 + diff1 + diff2 + diff3;
1060 float reducedDamage = -1;
1066 if (m_fMeleeResistance != 0)
1067 reducedDamage =
impulse / m_fMeleeResistance;
1072 if (m_fKineticResistance != 0)
1073 reducedDamage =
impulse / m_fKineticResistance;
1077 Print(
"Incendiary");
1082 if (m_fExplosionResistance != 0)
1083 reducedDamage =
impulse / m_fExplosionResistance;
1088 Print(
"Damage after reduction: " +
"NOT IMPLEMENTED YET");
1093 if (m_fCollisionResistance != 0)
1094 reducedDamage =
impulse / m_fCollisionResistance;
1100 if (reducedDamage != -1)
1101 Print(
"Damage after reduction: " + reducedDamage);
1102 else Print(
"Damage after reduction: NOT IMPLEMENTED YET");
1106 void ResetThresholdTime()
1108 m_fThresholdTime = 0;
1109 m_fThresholdMaxTime = 0;
1130 if (m_fMeleeResistance != 0)
1131 impulse /= m_fMeleeResistance;
1134 if (m_fKineticResistance != 0)
1135 impulse /= m_fKineticResistance;
1140 if (m_fExplosionResistance != 0)
1141 impulse /= m_fExplosionResistance;
1146 if (m_fCollisionResistance != 0)
1147 impulse /= m_fCollisionResistance;
1151 if (
impulse > (m_fMinImpact * GetScale()))
1165 if (m_fMeleeResistance != 0)
1166 reducedImpulse /= m_fMeleeResistance;
1169 if (m_fKineticResistance != 0)
1170 reducedImpulse /= m_fKineticResistance;
1175 if (m_fExplosionResistance != 0)
1176 reducedImpulse /= m_fExplosionResistance;
1181 if (m_fCollisionResistance != 0)
1182 reducedImpulse /= m_fCollisionResistance;
1186 if (reducedImpulse > (m_fMinImpact * GetScale()))
1193 override void OnDamage(
float damage,
1206 vector directionVector = -outMat[2];
1207 directionVector.Normalize();
1210 PrintDamageDebug(damage,
type);
1212 if (damage > m_fMinImpact)
1215 vector positionVector = outMat[0];
1219 positionVector =
"0 0 0";
1220 directionVector = (
GetOrigin() - outMat[0]);
1223 directionVector.Normalize();
1224 vector impulseVector = directionVector * (damage / 10);
1226 if (WouldBreak(damage,
type))
1227 SetToBreak(positionVector: positionVector, impulseVector: impulseVector, damageType:
type);
1239 if (m_bSwitchToDynamic)
1240 SwitchPhysicsToDynamic();
1241 if (m_bSwitchToStatic)
1243 SwitchPhysicsToStatic(
true);
1259 static void Extrapolate(
GenericEntity entity,
Physics physics,
vector netPosition,
vector netVelocityLinear,
float netTeleportDistance,
float netRotation[4],
vector netVelocityAngular,
float netTeleportAng,
float timeSinceLastTick,
float timeSlice,
float tickTime)
1271 if (!physics || !physics.IsDynamic())
1274 Math3D.QuatToMatrix(netRotation, currentMatrix);
1278 currentMatrix[3] = netPosition;
1286 vector projectedPos = netPosition + netVelocityLinear * timeSinceLastTick;
1288 netVelocityAngular = netVelocityAngular * timeSinceLastTick;
1289 vector netVelocityAngularFlipped = GetFixedAxisVector(netVelocityAngular);
1290 float projectedRotation[4];
1291 float netVelocityAngularQuat[4];
1292 netVelocityAngularFlipped.QuatFromAngles(netVelocityAngularQuat);
1293 Math3D.QuatMultiply(projectedRotation, netRotation, netVelocityAngularQuat);
1301 if (posError > netTeleportDistance)
1309 if (rotError > netTeleportAng)
1311 Math3D.QuatToMatrix(netRotation, currentMatrix);
1318 float timeStep =
Math.Clamp(timeSlice * 2, 0, 1);
1319 float timeStepTick =
Math.Clamp(timeSlice / tickTime, 0, 1);
1322 if (posError > 0.01)
1325 physics.SetVelocity(physics.GetVelocity() + (projectedPos -
position) * timeStepTick);
1328 if (rotError > 0.01)
1331 Math3D.QuatRotateTowards(outRot,
rotation, projectedRotation, (rotError * timeStep) *
Math.RAD2DEG);
1332 Math3D.QuatToMatrix(outRot, currentMatrix);
1341 Math3D.QuatMultiply(rotDiff, projectedRotation, rotInv);
1343 angularVelocity = FixEulerVector180(angularVelocity) *
Math.DEG2RAD * timeStepTick;
1344 angularVelocity += physics.GetAngularVelocity() *
Math.DEG2RAD;
1345 physics.SetAngularVelocity(angularVelocity);
1356 flipped[0] = toFlip[1];
1357 flipped[1] = toFlip[0];
1358 flipped[2] = toFlip[2];
1363 static void RotateTowards(out
float result[4],
float from[4],
float to[4],
float maxDegreesDelta)
1365 float num =
Math3D.QuatAngle(from, to);
1366 if (
float.AlmostEqual(num, 0.0))
1368 Math3D.QuatCopy(to, result);
1371 float t =
Math.Min(1, maxDegreesDelta / num);
1372 Math3D.QuatLerp(result, from, to, t);
1379 vector diff = target - start;
1380 float magnitude = diff.Length();
1381 if (magnitude <= maxDistanceDelta ||
float.AlmostEqual(magnitude, 0.0))
1383 return start + diff / magnitude * maxDistanceDelta;
1391 for (
int a = 0; a < 3; a++)
1408 m_bSwitchToStatic =
true;
1416 m_bSynchronizeHasParent =
true;
1418 GetBounds(m_vBBOXMin, m_vBBOXMax);
1420 SwitchPhysicsToStatic(
false);
1426 override void EOnSimulate(
IEntity owner,
float timeSlice)
1432 if (m_bBreakFromParent)
1438 if (treePart && m_ParentJoint)
1439 BreakJoint(m_ParentJoint,
this, treePart);
1444 if (m_vCachedPosition && m_bApplyCachedPosition)
1446 SetPosition(m_vCachedPosition);
1447 m_bApplyCachedPosition =
false;
1450 if (m_fCachedRotation && m_bApplyCachedRotation)
1452 SetRotation(m_fCachedRotation);
1453 m_bApplyCachedRotation =
false;
1456 m_bBreakFromParent =
false;
1469 CheckThreshold(timeSlice);
1471 m_iContactsCount = 0;
1475 override void EOnPostSimulate(
IEntity owner,
float timeSlice)
1481 m_fTimeSinceLastTick += timeSlice;
1482 Extrapolate(
this, m_Physics, m_vNetPosition, m_vNetVelocityLinear, NET_TELEPORT_DISTANCE, m_fNetRotation, m_vNetVelocityAngular, NET_TELEPORT_ANGLE, m_fTimeSinceLastTick, timeSlice, m_fTargetSynchTime);
1506 m_fSynchTime += timeSlice;
1507 if (m_fSynchTime > m_fTargetSynchTime)
1514 GetWorldTransform(mat);
1515 Math3D.MatrixToQuat(mat, q);
1519 vector parentOrigin = m_ParentTree.GetOrigin();
1523 synchManager.SynchronizeTreePartTransform(m_iTreePartIndex, q,
GetOrigin(), m_Physics.GetVelocity(), m_Physics.GetAngularVelocity(), m_ParentTree.GetID());
1538 if (m_bSoundHitGroundPlayed)
1541 if (GenericTerrainEntity.Cast(other))
1543 float vNormBefore = contact.GetRelativeNormalVelocityBefore();
1544 float vNormAfter = contact.GetRelativeNormalVelocityAfter();
1545 float dV = vNormAfter - vNormBefore;
1546 float impulse = contact.Impulse;
1548 if (dV > 2.5 &&
impulse > 100)
1552 m_ParentTree.OnTreePartHitGround();
1554 m_bSoundHitGroundPlayed =
true;
1562 superParent.ResetThresholdTime();
1571 if (TARGET_RPC_COUNT > 0 && m_fTargetSynchTime == -1)
1573 m_fTargetSynchTime = 1 / TARGET_RPC_COUNT;
1582 m_ParentJoint = null;
1583 m_HybridPhysicsInfo = null;
1584 m_aChildrenJoints = null;
1585 m_aQuerriedEnts = null;