public virtual void FracturedBody_AfterReplaceBody(ref HkdReplaceBodyEvent e)
        {
            System.Diagnostics.Debug.Assert(Sync.IsServer, "Client must not simulate destructions");
            if (!Sandbox.Game.Multiplayer.Sync.IsServer)
            {
                return;
            }

            ProfilerShort.Begin("DestructionFracture.AfterReplaceBody");
            Debug.Assert(BreakableBody != null);
            e.GetNewBodies(m_tmpLst);
            if (m_tmpLst.Count == 0)// || e.OldBody != DestructionBody)
            {
                ProfilerShort.End();
                return;
            }

            MyPhysics.RemoveDestructions(RigidBody);
            foreach (var b in m_tmpLst)
            {
                var     bBody = MyFracturedPiecesManager.Static.GetBreakableBody(b);
                MatrixD m     = bBody.GetRigidBody().GetRigidBodyMatrix();
                m.Translation = ClusterToWorld(m.Translation);
                var piece = MyDestructionHelper.CreateFracturePiece(bBody, ref m, (Entity as MyFracturedPiece).OriginalBlocks);
                if (piece == null)
                {
                    MyFracturedPiecesManager.Static.ReturnToPool(bBody);
                    continue;
                }
            }
            m_tmpLst.Clear();

            BreakableBody.AfterReplaceBody -= FracturedBody_AfterReplaceBody;

            MyFracturedPiecesManager.Static.RemoveFracturePiece(Entity as MyFracturedPiece, 0);

            ProfilerShort.End();
        }
        /// <summary>
        ///  Sets default values for ragdoll bodies and constraints - useful if ragdoll model is not correct
        /// </summary>
        public void SetRagdollDefaults()
        {
            if (MyFakes.ENABLE_RAGDOLL_DEBUG)
            {
                Debug.WriteLine("MyPhysicsBody.SetRagdollDefaults");
                MyLog.Default.WriteLine("MyPhysicsBody.SetRagdollDefaults");
            }

            var wasKeyframed = Ragdoll.IsKeyframed;

            Ragdoll.SetToDynamic();

            // Compute total mass of the character and distribute it amongs ragdoll bodies
            var definedMass = (Entity as MyCharacter).Definition.Mass;

            if (definedMass <= 1)
            {
                definedMass = 80;
            }

            float totalVolume = 0f;

            foreach (var body in Ragdoll.RigidBodies)
            {
                float bodyLength = 0;

                var shape = body.GetShape();

                Vector4 min, max;

                shape.GetLocalAABB(0.01f, out min, out max);

                bodyLength = (max - min).Length();

                totalVolume += bodyLength;
            }

            // correcting the total volume
            if (totalVolume <= 0)
            {
                totalVolume = 1;
            }

            // bodies default settings
            foreach (var body in Ragdoll.RigidBodies)
            {
                body.MaxLinearVelocity  = 1000.0f;
                body.MaxAngularVelocity = 1000.0f;

                var shape = body.GetShape();

                Vector4 min, max;

                shape.GetLocalAABB(0.01f, out min, out max);

                float bodyLength = (max - min).Length();

                float computedMass = definedMass / totalVolume * bodyLength;

                body.Mass = MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(computedMass) : computedMass;

                float radius = shape.ConvexRadius;
                if (shape.ShapeType == HkShapeType.Capsule)
                {
                    HkCapsuleShape   capsule        = (HkCapsuleShape)shape;
                    HkMassProperties massProperties = HkInertiaTensorComputer.ComputeCapsuleVolumeMassProperties(capsule.VertexA, capsule.VertexB, radius, body.Mass);
                    body.InertiaTensor = massProperties.InertiaTensor;
                }
                else
                {
                    HkMassProperties massProperties = HkInertiaTensorComputer.ComputeBoxVolumeMassProperties(Vector3.One * bodyLength * 0.5f, body.Mass);
                    body.InertiaTensor = massProperties.InertiaTensor;
                }

                Debug.Assert(body.Mass != 0.0f, "Body's mass was set to 0!");
                body.AngularDamping          = 0.005f;
                body.LinearDamping           = 0.0f;
                body.Friction                = 6f;
                body.AllowedPenetrationDepth = 0.1f;
                body.Restitution             = 0.05f;
            }

            Ragdoll.OptimizeInertiasOfConstraintTree();

            if (wasKeyframed)
            {
                Ragdoll.SetToKeyframed();
            }

            // Constraints default settings
            foreach (var constraint in Ragdoll.Constraints)
            {
                if (constraint.ConstraintData is HkRagdollConstraintData)
                {
                    var constraintData = constraint.ConstraintData as HkRagdollConstraintData;
                    constraintData.MaxFrictionTorque = MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(0.5f) : 3f;
                }
                else if (constraint.ConstraintData is HkFixedConstraintData)
                {
                    var constraintData = constraint.ConstraintData as HkFixedConstraintData;
                    constraintData.MaximumLinearImpulse  = 3.40282e28f;
                    constraintData.MaximumAngularImpulse = 3.40282e28f;
                }
                else if (constraint.ConstraintData is HkHingeConstraintData)
                {
                    var constraintData = constraint.ConstraintData as HkHingeConstraintData;
                    constraintData.MaximumAngularImpulse = 3.40282e28f;
                    constraintData.MaximumLinearImpulse  = 3.40282e28f;
                }
                else if (constraint.ConstraintData is HkLimitedHingeConstraintData)
                {
                    var constraintData = constraint.ConstraintData as HkLimitedHingeConstraintData;
                    constraintData.MaxFrictionTorque = MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(0.5f) : 3f;
                }
            }

            if (MyFakes.ENABLE_RAGDOLL_DEBUG)
            {
                Debug.WriteLine("MyPhysicsBody.SetRagdollDefaults FINISHED");
                MyLog.Default.WriteLine("MyPhysicsBody.SetRagdollDefaults FINISHED");
            }
        }
Exemple #3
0
        /// <summary>
        /// Returns true when block is destroyed
        /// </summary>
        public void DoDamage(float damage, MyDamageType damageType, bool addDirtyParts = true, MyDestructionHelper.HitInfo? hitInfo = null)
        {
            if (!MySession.Static.DestructibleBlocks)
                return;

            damage *= DamageRatio; // Low-integrity blocks get more damage
            ProfilerShort.Begin("FatBlock.DoDamage");
            try
            {
                if (FatBlock != null && CubeGrid.Physics != null && CubeGrid.Physics.Enabled)  //Fatblock dont have physics
                {
                    var destroyable = FatBlock as IMyDestroyableObject;
                    if (destroyable != null)
                        destroyable.DoDamage(damage, damageType, false);
                }
            }
            finally { ProfilerShort.End(); }

            MySession.Static.NegativeIntegrityTotal += damage;

            AccumulatedDamage += damage;
            if (m_componentStack.Integrity - AccumulatedDamage <= MyComponentStack.MOUNT_THRESHOLD)
            {
                if (MyPerGameSettings.Destruction && hitInfo.HasValue)
                {
                    AccumulatedDamage = 0;
                    var gridPhysics = CubeGrid.Physics;
                    float maxDestructionRadius = CubeGrid.GridSizeEnum == MyCubeSize.Small ? 0.5f : 3;
                    Sandbox.Engine.Physics.MyDestructionHelper.TriggerDestruction(damage, gridPhysics, hitInfo.Value.Position, hitInfo.Value.Normal, maxDestructionRadius);
                }
                else
                {
                    ApplyAccumulatedDamage(addDirtyParts);
                }
                CubeGrid.RemoveFromDamageApplication(this);
            }
            else
                if (MyFakes.SHOW_DAMAGE_EFFECTS && FatBlock != null && BlockDefinition.RationEnoughForDamageEffect((Integrity-damage) / MaxIntegrity))
                    FatBlock.SetDamageEffect(true);

            return;
        }