Example #1
0
        public override void ContactPointCallback(ref MyGridContactInfo value)
        {
            //return;
            var prop = value.Event.ContactProperties;
            prop.Friction = Friction;
            prop.Restitution = 0.5f;
            value.EnableParticles = false;
            value.RubberDeformation = true;

            string particle = null;
            if (value.CollidingEntity is MyVoxelBase && MyFakes.ENABLE_DRIVING_PARTICLES)
            {
                MyVoxelBase voxel = value.CollidingEntity as MyVoxelBase;
                Vector3D contactPosition = value.ContactPosition;
                var vmat = voxel.GetMaterialAt(ref contactPosition);
                if (vmat == null) return;

                MyStringHash material = MyStringHash.GetOrCompute(vmat.MaterialTypeName);
                particle = MyMaterialPropertiesHelper.Static.GetCollisionEffect(MyMaterialPropertiesHelper.CollisionType.Start, m_wheelStringHash, material);
            }
            else if (value.CollidingEntity is MyCubeGrid && MyFakes.ENABLE_DRIVING_PARTICLES)
            {
                MyCubeGrid grid = value.CollidingEntity as MyCubeGrid;
                MyStringHash material = grid.Physics.GetMaterialAt(value.ContactPosition);
                particle = MyMaterialPropertiesHelper.Static.GetCollisionEffect(MyMaterialPropertiesHelper.CollisionType.Start, m_wheelStringHash, material);
            }
            if (Render != null && particle != null)
                Render.TrySpawnParticle((Vector3)value.ContactPosition, value.Event.ContactPoint.Normal, particle);
        }
Example #2
0
 internal override void ContactPointCallback(ref MyGridContactInfo info)
 {
     if (info.CollidingEntity != null && m_attachedTo == info.CollidingEntity)
     {
         info.EnableDeformation = false;
         info.EnableParticles   = false;
     }
 }
Example #3
0
 public override void ContactPointCallback(ref MyGridContactInfo value)
 {
     //return;
     var prop = value.Event.ContactProperties;
     prop.Friction = Friction;
     prop.Restitution = 0.5f;
     value.EnableParticles = false;
     value.RubberDeformation = true;
 }
Example #4
0
 public override void ContactPointCallback(ref MyGridContactInfo value)
 {
     base.ContactPointCallback(ref value);
     if (m_pistonBlock == null)
         return;
     //if (value.CollidingEntity == m_pistonBlock.CubeGrid || value.CollidingEntity == m_pistonBlock.Subpart3)
     if (value.CollidingEntity == m_pistonBlock.Subpart3)
     {
         value.EnableDeformation = false;
         value.EnableParticles = false;
     }
 }
Example #5
0
        internal override void ContactPointCallback(ref MyGridContactInfo value)
        {
            base.ContactPointCallback(ref value);

            if (value.CollidingEntity is MyDebrisBase)
            {
                return;
            }

            if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional)
            {
                if (MySession.Static.DestructibleBlocks)
                {
                    Explode();
                }
            }
        }
Example #6
0
        public override void ContactPointCallback(ref MyGridContactInfo value)
        {
            base.ContactPointCallback(ref value);

            if (value.CollidingEntity is MyDebrisBase)
            {
                return;
            }

            if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional)
            {
                if (CubeGrid.BlocksDestructionEnabled)
                {
                    Explode();
                }
            }
        }
Example #7
0
        public override void ContactPointCallback(ref MyGridContactInfo value)
        {
            //return;
            var prop = value.Event.ContactProperties;
            prop.Friction = Friction;
            prop.Restitution = 0.5f;
            value.EnableParticles = false;
            value.RubberDeformation = true;

            if (value.CollidingEntity is MyVoxelBase && MyFakes.ENABLE_DRIVING_PARTICLES)
            {
                MyVoxelBase voxel = value.CollidingEntity as MyVoxelBase;
                Vector3D contactPosition = value.ContactPosition;
                MyStringHash material = MyStringHash.GetOrCompute(voxel.GetMaterialAt(ref contactPosition).MaterialTypeName);
                MyTuple<int, ContactPropertyParticleProperties> particle = MyMaterialPropertiesHelper.Static.GetCollisionEffectAndProperties(MyMaterialPropertiesHelper.CollisionType.Start, m_wheelStringHash, material);
                
                if (Render != null && particle.Item1 > 0)
                    Render.TrySpawnParticle(value.ContactPosition, particle);
            }
        }
        void Physics_ContactPointCallback(ref Engine.Physics.MyPhysics.MyContactPointEvent e)
        {
          //  RestoreDynamicMasses();
            //if (m_frameCounter > DYNAMIC_UPDATE_DELAY)
            //    m_frameCounter = 0;
            //else
            //    return;

            if (m_lastFrameCollision != m_frameCounter)
                DynamicWeights.Clear();

            MyGridContactInfo info = new MyGridContactInfo(ref e.ContactPointEvent, m_grid);
            
            if (info.CollidingEntity.Physics.IsStatic)
                return;

            float speed = info.CollidingEntity.Physics.LinearVelocity.Length();
            if (speed < 0.1f)
                return;

            Vector3I blockPos = m_grid.WorldToGridInteger(info.ContactPosition + Vector3.Up * 0.25f);

            float dot = Vector3.Dot(Vector3.Normalize(info.CollidingEntity.Physics.LinearVelocity), Vector3.Down);

            float collidingMass = 0;
            m_constrainedGrid.Clear();
            MyCubeGrid collidingGrid = info.CollidingEntity as MyCubeGrid;
            if (collidingGrid != null)
            {
                
                m_constrainedGrid.Add(collidingGrid);

                AddConstrainedGrids(collidingGrid);

                foreach (var grid in m_constrainedGrid)
                {
                    collidingMass += grid.Physics.Mass;
                }
            }
            else
            {
                collidingMass = info.CollidingEntity.Physics.Mass;
            }

            collidingMass = info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter ? MassToSI(collidingMass) : MassToSI(MyDestructionHelper.MassFromHavok(collidingMass));

            float siMass = collidingMass * MyPetaInputComponent.SI_DYNAMICS_MULTIPLIER;

            //if (dot < 0) //impact from downside
            //    return;

            
            float impact =  siMass * speed * dot + siMass;
            if (impact < 0)
                return;

            if (m_grid.GridSizeEnum == Common.ObjectBuilders.MyCubeSize.Large)
            {
            }

            DynamicWeights[blockPos] = impact;

            m_needsRecalc = true;

            m_lastFrameCollision = m_frameCounter;

            if (!m_collidingEntities.ContainsKey(info.CollidingEntity))
            {
                m_collidingEntities.Add(info.CollidingEntity, new CollidingEntityInfo()
                {
                    Position = blockPos,
                    FrameTime = m_frameCounter
                });
                info.CollidingEntity.PositionComp.OnPositionChanged += PositionComp_OnPositionChanged;
            }
            else
                m_collidingEntities[info.CollidingEntity].FrameTime = m_frameCounter;
        }
Example #9
0
        public override void ContactPointCallback(ref MyGridContactInfo value)
        {
            var prop = value.Event.ContactProperties;

            value.EnableDeformation = false;
            value.EnableParticles = false;
            value.RubberDeformation = false;

            if (MyPerGameSettings.BallFriendlyPhysics)
            {
                prop.Friction = Friction;
                prop.Restitution = Restitution > REAL_MAXIMUM_RESTITUTION ? REAL_MAXIMUM_RESTITUTION : Restitution;
            }
        }
 private MyGridContactInfo ReduceVelocities(MyGridContactInfo info)
 {
     info.Event.AccessVelocities(0);
     info.Event.AccessVelocities(1);
     if (!info.CollidingEntity.Physics.IsStatic && info.CollidingEntity.Physics.Mass < 600)
         info.CollidingEntity.Physics.LinearVelocity /= 2;
     if (!this.IsStatic && MyDestructionHelper.MassFromHavok(Mass) < 600)
         LinearVelocity /= 2;
     info.Event.UpdateVelocities(0);
     info.Event.UpdateVelocities(1);
     return info;
 }
        void RigidBody_ContactPointCallback_Destruction(ref HkContactPointEvent value)
        {
            ProfilerShort.Begin("Grid Contact counter");
            ProfilerShort.End();
            MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid);

            if (info.IsKnown)
                return;

            var myBody = info.CurrentEntity.Physics.RigidBody;//value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA : value.Base.BodyB;
            var myEntity = info.CurrentEntity;//value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA.GetEntity() : value.Base.BodyB.GetEntity();

            // CH: DEBUG
            var entity1 = value.Base.BodyA.GetEntity();
            var entity2 = value.Base.BodyB.GetEntity();

            var rigidBody1 = value.Base.BodyA;
            var rigidBody2 = value.Base.BodyB;

            if (entity1 == null || entity2 == null || entity1.Physics == null || entity2.Physics == null)
                return;

            if (entity1 is MyFracturedPiece && entity2 is MyFracturedPiece)
                return;

            info.HandleEvents();
            if (rigidBody1.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || rigidBody2.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))
                return;

            if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity == null || info.CollidingEntity.MarkedForClose)
                return;

            if (MyFakes.ENABLE_CHARACTER_VIRTUAL_PHYSICS)
            {
                MyCharacter character = MySession.ControlledEntity as MyCharacter;
                if (character != null && character.VirtualPhysics != null)
                {
                    foreach (var constraint in character.VirtualPhysics.Constraints) 
                    {
                        IMyEntity cstrEntityA = constraint.RigidBodyA.GetEntity();
                        IMyEntity cstrEntityB = constraint.RigidBodyB.GetEntity();

                        if (info.CurrentEntity == cstrEntityA || info.CurrentEntity == cstrEntityB || info.CollidingEntity == cstrEntityA || info.CollidingEntity == cstrEntityB)
                            return;
                    }
                }
            }

            var grid1 = entity1 as MyCubeGrid;
            var grid2 = entity2 as MyCubeGrid;

            if (grid1 != null && grid2 != null && (MyCubeGridGroups.Static.Physical.GetGroup(grid1) == MyCubeGridGroups.Static.Physical.GetGroup(grid2)))
                return;

            ProfilerShort.Begin("Grid contact point callback");

            if (Sync.IsServer)
            {
                var vel = Math.Abs(value.SeparatingVelocity);
                bool enoughSpeed = vel > 3;
                //float dot = Vector3.Dot(Vector3.Normalize(LinearVelocity), Vector3.Normalize(info.CollidingEntity.Physics.LinearVelocity));


                Vector3 velocity1 = rigidBody1.GetVelocityAtPoint(info.Event.ContactPoint.Position);
                Vector3 velocity2 = rigidBody2.GetVelocityAtPoint(info.Event.ContactPoint.Position);

                float speed1 = velocity1.Length();
                float speed2 = velocity2.Length();

                Vector3 dir1 = speed1 > 0 ? Vector3.Normalize(velocity1) : Vector3.Zero;
                Vector3 dir2 = speed2 > 0 ? Vector3.Normalize(velocity2) : Vector3.Zero;

                float mass1 = MyDestructionHelper.MassFromHavok(rigidBody1.Mass);
                float mass2 = MyDestructionHelper.MassFromHavok(rigidBody2.Mass);

                float impact1 = speed1 * mass1;
                float impact2 = speed2 * mass2;

                float dot1withNormal = speed1 > 0 ? Vector3.Dot(dir1, value.ContactPoint.Normal) : 0;
                float dot2withNormal = speed2 > 0 ? Vector3.Dot(dir2, value.ContactPoint.Normal) : 0;

                speed1 *= Math.Abs(dot1withNormal);
                speed2 *= Math.Abs(dot2withNormal);

                bool is1Static = mass1 == 0;
                bool is2Static = mass2 == 0;

                bool is1Small = entity1 is MyFracturedPiece || (grid1 != null && grid1.GridSizeEnum == MyCubeSize.Small);
                bool is2Small = entity2 is MyFracturedPiece || (grid2 != null && grid2.GridSizeEnum == MyCubeSize.Small);
                

                float dot = Vector3.Dot(dir1, dir2);

                float maxDestructionRadius = 0.5f;

                impact1 *= info.ImpulseMultiplier;
                impact2 *= info.ImpulseMultiplier;

                MyHitInfo hitInfo = new MyHitInfo();
                var hitPos = info.ContactPosition;
                hitInfo.Normal = value.ContactPoint.Normal;

                //direct hit
                if (dot1withNormal < 0.0f)
                {
                    if (entity1 is MyFracturedPiece)
                        impact1 /= 10;

                    impact1 *= Math.Abs(dot1withNormal); //respect angle of hit

                    if (entity2 is MyFracturedPiece)
                    {
                    }

                    if ((impact1 > 2000 && speed1 > 2 && !is2Small) ||
                        (impact1 > 500 && speed1 > 10)) //must be fast enought to destroy fracture piece (projectile)
                    {  //1 is big hitting

                        if (is2Static || impact1 / impact2 > 10)
                        {
                            hitInfo.Position = hitPos + 0.1f * hitInfo.Normal;
                            impact1 -= mass1;
                            if (grid1 != null)
                            {
                                var blockPos = GetGridPosition(value, grid1, 0);
                                grid1.DoDamage(impact1, hitInfo, blockPos);
                            }
                            else
                                MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);
                            hitInfo.Position = hitPos - 0.1f * hitInfo.Normal;
                            if (grid2 != null)
                            {
                                var blockPos = GetGridPosition(value, grid2, 1);
                                grid2.DoDamage(impact1, hitInfo, blockPos);
                            }
                            else
                                MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);

                            ReduceVelocities(info);
                        }
                    }
                }

                if (dot2withNormal < 0.0f)
                {
                    if (entity2 is MyFracturedPiece)
                        impact2 /= 10;

                    impact2 *= Math.Abs(dot1withNormal); //respect angle of hit

                    if (impact2 > 2000 && speed2 > 2 && !is1Small ||
                        (impact2 > 500 && speed2 > 10)) //must be fast enought to destroy fracture piece (projectile)
                    {  //2 is big hitting

                        if (is1Static || impact2 / impact1 > 10)
                        {
                            hitInfo.Position = hitPos + 0.1f * hitInfo.Normal;
                            impact2 -= mass2;
                            if (grid1 != null)
                            {
                                var blockPos = GetGridPosition(value, grid1, 0);
                                grid1.DoDamage(impact2, hitInfo, blockPos);
                            }
                            else
                                MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);
                            hitInfo.Position = hitPos - 0.1f * hitInfo.Normal;
                            if (grid2 != null)
                            {
                                var blockPos = GetGridPosition(value, grid2, 1);
                                grid2.DoDamage(impact2, hitInfo, blockPos);
                            }
                            else
                                MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);

                            ReduceVelocities(info);
                        }
                    }
                }

                //float destructionImpact = vel * (MyDestructionHelper.MassFromHavok(Mass) + MyDestructionHelper.MassFromHavok(info.CollidingEntity.Physics.Mass));
                //destructionImpact *= info.ImpulseMultiplier;

                //if (destructionImpact > 2000 && enoughSpeed)
                //{
                //    CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, this, info, value.ContactPoint.Normal);
                //    CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, info.CollidingEntity.Physics, info, value.ContactPoint.Normal);

                //    ReduceVelocities(info);
                //}
            }

            ProfilerShort.End();
        }
        void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
        {
            ProfilerShort.Begin("Grid Contact counter");
            ProfilerShort.End();

            var entity1 = value.Base.BodyA.GetEntity();
            var entity2 = value.Base.BodyB.GetEntity();
            if (entity1 == null || entity2 == null)
                return;

            //DA used to stop appliyng force when there is planet/ship collisions to  increase performance after ship crashes on planet
            if ((Math.Abs(value.SeparatingVelocity) < 0.3f) && (entity1 is MyTrees || entity1 is MyVoxelPhysics || entity2 is MyVoxelPhysics || entity2 is MyTrees))
            {
                return;
            }

            MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid);

            var myBody = value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA : value.Base.BodyB;

            // CH: DEBUG
           

            if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity.MarkedForClose)
                return;

            if (MyFakes.LANDING_GEAR_IGNORE_DAMAGE_CONTACTS && MyCubeGridGroups.Static.NoContactDamage.HasSameGroupAndIsGrid(entity1, entity2))
                return;
            
            ProfilerShort.Begin("Grid contact point callback");
            bool doSparks = MyPerGameSettings.EnableCollisionSparksEffect && (info.CollidingEntity is MyCubeGrid || info.CollidingEntity is MyVoxelMap);

            // According to Petr, WasUsed does not work everytime
            //if (value.ContactProperties.WasUsed)
            {
                // Handle callbacks here
                info.HandleEvents();
            }

            bool deformationPerformed = false;

            if (Sync.IsServer && value.ContactProperties.ImpulseApplied > MyGridShape.BreakImpulse && info.CollidingEntity != null && info.EnableDeformation && m_grid.BlocksDestructionEnabled)
            {
                float deformation = value.SeparatingVelocity;
                if (info.RubberDeformation)
                {
                    deformation /= 5;
                }

                HkBreakOffPointInfo breakInfo = CreateBreakOffPoint(value, info.ContactPosition, MyGridShape.BreakImpulse);
                PerformDeformation(ref breakInfo, false, value.SeparatingVelocity);
                deformationPerformed = true;
            }
            else if (doSparks && value.SeparatingVelocity > 2.0f && value.ContactProperties.WasUsed && !m_lastContacts.ContainsKey(value.ContactPointId) && info.EnableParticles)
            {
                m_lastContacts[value.ContactPointId] = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                AddCollisionEffect(info.ContactPosition, value.ContactPoint.Normal);
            }

            // Large dynamic ships colliding with floating objects
            // When low separating velocity or deformation performed, disable contact point
            // Floating object will still collide with kinematic part of ship and won't push it
            if (m_grid.GridSizeEnum == MyCubeSize.Large && !myBody.IsFixedOrKeyframed && info.CollidingEntity is MyFloatingObject && (Math.Abs(value.SeparatingVelocity) < 0.2f || deformationPerformed))
            {
                var prop = value.ContactProperties;
                prop.IsDisabled = true;
            }

            ProfilerShort.End();
        }
Example #13
0
 private void DestroyGrid(ref MyPhysics.MyContactPointEvent value, MyCubeGrid grid)
 {
     MyGridContactInfo info = new MyGridContactInfo(ref value.ContactPointEvent, grid);
     info.EnableDeformation = false;
     info.EnableParticles = false;
     HkBreakOffPointInfo breakInfo = new HkBreakOffPointInfo()
     {
         ContactPoint = value.ContactPointEvent.ContactPoint,
         ContactPosition = info.ContactPosition,
         ContactPointProperties = value.ContactPointEvent.ContactProperties,
         IsContact = true,
         BreakingImpulse = grid.Physics.Shape.BreakImpulse,
         CollidingBody = value.ContactPointEvent.Base.BodyA == grid.Physics.RigidBody ? value.ContactPointEvent.Base.BodyB : value.ContactPointEvent.Base.BodyA,
         ContactPointDirection = value.ContactPointEvent.Base.BodyB == grid.Physics.RigidBody ? -1 : 1,
     };
     grid.Physics.PerformMeteoritDeformation(ref breakInfo, value.ContactPointEvent.SeparatingVelocity);
     m_closeAfterSimulation = Sync.IsServer;
 }
        void CreateDestructionFor(float destructionImpact, Vector3 contactVelocity, MyPhysicsBody body, MyGridContactInfo info, Vector3 normal, float maxDestructionRadius)
        {
            if (body.BreakableBody != null)
            {
                float collidingMass = body.Mass == 0 ? Mass : body.Mass; //fall on voxel
                float destructionRadius = Math.Min(destructionImpact / 8000, maxDestructionRadius);
                float destructionImpulse = MyDestructionConstants.STRENGTH + destructionImpact / 10000;
                float expandVelocity = Math.Min(destructionImpact / 10000, 3);

                MyPhysics.FractureImpactDetails destruction;
                HkdFractureImpactDetails details;
                details = HkdFractureImpactDetails.Create();
                details.SetBreakingBody(body.RigidBody);
                details.SetContactPoint(WorldToCluster(info.ContactPosition));
                details.SetDestructionRadius(destructionRadius);
                details.SetBreakingImpulse(destructionImpulse);
                details.SetParticleExpandVelocity(expandVelocity);
                details.SetParticleVelocity(contactVelocity);
                details.SetParticlePosition(WorldToCluster(info.ContactPosition - normal * 0.25f));
                details.SetParticleMass(collidingMass);
                details.ZeroCollidingParticleVelocity();
                details.Flag = details.Flag | HkdFractureImpactDetails.Flags.FLAG_DONT_RECURSE | HkdFractureImpactDetails.Flags.FLAG_TRIGGERED_DESTRUCTION;

                destruction = new MyPhysics.FractureImpactDetails();
                destruction.Details = details;
                destruction.World = HavokWorld;
                destruction.ContactInWorld = info.ContactPosition;
                destruction.Entity = (MyEntity)body.Entity;

                MyPhysics.EnqueueDestruction(destruction);
            }
        }
 internal override void ContactPointCallback(ref MyGridContactInfo info)
 {
     if (info.CollidingEntity != null && m_attachedTo == info.CollidingEntity)
     {
         info.EnableDeformation = false;
         info.EnableParticles = false;
     }
 }
        void RigidBody_ContactPointCallback_Destruction(ref HkContactPointEvent value)
        {
            ProfilerShort.Begin("Grid Contact counter");
            ProfilerShort.End();
            MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid);

            if (info.IsKnown)
                return;

            var myEntity = info.CurrentEntity;//value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA.GetEntity() : value.Base.BodyB.GetEntity();
            if (myEntity == null || myEntity.Physics == null || myEntity.Physics.RigidBody == null)
            {
                return;
            }
            var myBody = myEntity.Physics.RigidBody;

            // CH: DEBUG
            var physicsBody1 = value.GetPhysicsBody(0);
            var physicsBody2 = value.GetPhysicsBody(1);
            if (physicsBody1 == null || physicsBody2 == null)
                return;

            var entity1 = physicsBody1.Entity;
            var entity2 = physicsBody2.Entity;
            if (entity1 == null || entity2 == null || entity1.Physics == null || entity2.Physics == null)
                return;

            if (entity1 is MyFracturedPiece && entity2 is MyFracturedPiece)
                return;

            var rigidBody1 = value.Base.BodyA;
            var rigidBody2 = value.Base.BodyB;

            info.HandleEvents();
            if (rigidBody1.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || rigidBody2.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))
                return;

            if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity == null || info.CollidingEntity.MarkedForClose)
                return;

            var grid1 = entity1 as MyCubeGrid;
            var grid2 = entity2 as MyCubeGrid;

            // CH: TODO: This is a hack Instead, the IMyDestroyableObject should be used and the subpart DoDamage code could delegate it to the grid
            // The thing is, this approach would probably need a rewrite of this whole method...
            if (grid2 == null && entity2 is MyEntitySubpart)
            {
                while (entity2 != null && !(entity2 is MyCubeGrid))
                {
                    entity2 = entity2.Parent;
                }

                if (entity2 != null)
                {
                    physicsBody2 = entity2.Physics as MyPhysicsBody;
                    rigidBody2 = physicsBody2.RigidBody;
                    grid2 = entity2 as MyCubeGrid;
                }
            }

            if (grid1 != null && grid2 != null && (MyCubeGridGroups.Static.Physical.GetGroup(grid1) == MyCubeGridGroups.Static.Physical.GetGroup(grid2)))
                return;

            ProfilerShort.Begin("Grid contact point callback");

            {
                var vel = Math.Abs(value.SeparatingVelocity);
                bool enoughSpeed = vel > 3;
                //float dot = Vector3.Dot(Vector3.Normalize(LinearVelocity), Vector3.Normalize(info.CollidingEntity.Physics.LinearVelocity));


                Vector3 velocity1 = rigidBody1.GetVelocityAtPoint(info.Event.ContactPoint.Position);
                Vector3 velocity2 = rigidBody2.GetVelocityAtPoint(info.Event.ContactPoint.Position);

                float speed1 = velocity1.Length();
                float speed2 = velocity2.Length();

                Vector3 dir1 = speed1 > 0 ? Vector3.Normalize(velocity1) : Vector3.Zero;
                Vector3 dir2 = speed2 > 0 ? Vector3.Normalize(velocity2) : Vector3.Zero;

                float mass1 = MyDestructionHelper.MassFromHavok(rigidBody1.Mass);
                float mass2 = MyDestructionHelper.MassFromHavok(rigidBody2.Mass);

                float impact1 = speed1 * mass1;
                float impact2 = speed2 * mass2;

                float dot1withNormal = speed1 > 0 ? Vector3.Dot(dir1, value.ContactPoint.Normal) : 0;
                float dot2withNormal = speed2 > 0 ? Vector3.Dot(dir2, value.ContactPoint.Normal) : 0;

                speed1 *= Math.Abs(dot1withNormal);
                speed2 *= Math.Abs(dot2withNormal);

                bool is1Static = mass1 == 0;
                bool is2Static = mass2 == 0;

                bool is1Small = entity1 is MyFracturedPiece || (grid1 != null && grid1.GridSizeEnum == MyCubeSize.Small);
                bool is2Small = entity2 is MyFracturedPiece || (grid2 != null && grid2.GridSizeEnum == MyCubeSize.Small);


                float dot = Vector3.Dot(dir1, dir2);

                float maxDestructionRadius = 0.5f;

                impact1 *= info.ImpulseMultiplier;
                impact2 *= info.ImpulseMultiplier;

                MyHitInfo hitInfo = new MyHitInfo();
                var hitPos = info.ContactPosition;
                hitInfo.Normal = value.ContactPoint.Normal;

                //direct hit
                if (dot1withNormal < 0.0f)
                {
                    if (entity1 is MyFracturedPiece)
                        impact1 /= 10;

                    impact1 *= Math.Abs(dot1withNormal); //respect angle of hit

                    if ((impact1 > 2000 && speed1 > 2 && !is2Small) ||
                        (impact1 > 500 && speed1 > 10)) //must be fast enought to destroy fracture piece (projectile)
                    {  //1 is big hitting

                        if (is2Static || impact1 / impact2 > 10)
                        {
                            hitInfo.Position = hitPos + 0.1f * hitInfo.Normal;
                            impact1 -= mass1;

                            if (Sync.IsServer && impact1 > 0)
                            {
                                if (grid1 != null)
                                {
                                    var blockPos = GetGridPosition(value.ContactPoint, rigidBody1, grid1, 0);
                                    grid1.DoDamage(impact1, hitInfo, blockPos, grid2 != null ? grid2.EntityId : 0);
                                }
                                else
                                    MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);
                                hitInfo.Position = hitPos - 0.1f * hitInfo.Normal;
                                if (grid2 != null)
                                {
                                    var blockPos = GetGridPosition(value.ContactPoint, rigidBody2, grid2, 1);
                                    grid2.DoDamage(impact1, hitInfo, blockPos, grid1 != null ? grid1.EntityId : 0);
                                }
                                else
                                    MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);

                                ReduceVelocities(info);
                            }

                            MyDecals.HandleAddDecal(entity1, hitInfo);
                            MyDecals.HandleAddDecal(entity2, hitInfo);
                        }
                    }
                }

                if (dot2withNormal < 0.0f)
                {
                    if (entity2 is MyFracturedPiece)
                        impact2 /= 10;

                    impact2 *= Math.Abs(dot2withNormal); //respect angle of hit

                    if (impact2 > 2000 && speed2 > 2 && !is1Small ||
                        (impact2 > 500 && speed2 > 10)) //must be fast enought to destroy fracture piece (projectile)
                    {  //2 is big hitting

                        if (is1Static || impact2 / impact1 > 10)
                        {
                            hitInfo.Position = hitPos + 0.1f * hitInfo.Normal;
                            impact2 -= mass2;

                            if (Sync.IsServer && impact2 > 0)
                            {
                                if (grid1 != null)
                                {
                                    var blockPos = GetGridPosition(value.ContactPoint, rigidBody1, grid1, 0);
                                    grid1.DoDamage(impact2, hitInfo, blockPos, grid2 != null ? grid2.EntityId : 0);
                                }
                                else
                                    MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);
                                hitInfo.Position = hitPos - 0.1f * hitInfo.Normal;
                                if (grid2 != null)
                                {
                                    var blockPos = GetGridPosition(value.ContactPoint, rigidBody2, grid2, 1);
                                    grid2.DoDamage(impact2, hitInfo, blockPos, grid1 != null ? grid1.EntityId : 0);
                                }
                                else
                                    MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius);

                                ReduceVelocities(info);
                            }

                            MyDecals.HandleAddDecal(entity1, hitInfo);
                            MyDecals.HandleAddDecal(entity2, hitInfo);
                        }
                    }
                }

                //float destructionImpact = vel * (MyDestructionHelper.MassFromHavok(Mass) + MyDestructionHelper.MassFromHavok(info.CollidingEntity.Physics.Mass));
                //destructionImpact *= info.ImpulseMultiplier;

                //if (destructionImpact > 2000 && enoughSpeed)
                //{
                //    CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, this, info, value.ContactPoint.Normal);
                //    CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, info.CollidingEntity.Physics, info, value.ContactPoint.Normal);

                //    ReduceVelocities(info);
                //}
            }

            ProfilerShort.End();
        }
Example #17
0
        void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
        {
            ProfilerShort.Begin("Grid Contact counter");
            ProfilerShort.End();

            var otherEntity = value.GetOtherEntity(m_grid);
            var otherPhysicsBody = value.GetPhysicsBody(0);
            var thisEntity = m_grid;
            if (otherEntity == null || thisEntity == null)
                return;

            //DA used to stop appliyng force when there is planet/ship collisions to  increase performance after ship crashes on planet
            if ((Math.Abs(value.SeparatingVelocity) < 0.3f) && (otherEntity is MyTrees || otherEntity is MyVoxelPhysics))
            {
                return;
            }

            MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid);

            var myBody = RigidBody;// value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA : value.Base.BodyB;

            if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity.MarkedForClose)
                return;

            if (MyFakes.LANDING_GEAR_IGNORE_DAMAGE_CONTACTS && MyCubeGridGroups.Static.NoContactDamage.HasSameGroupAndIsGrid(otherEntity, thisEntity))
                return;

            ProfilerShort.Begin("Grid contact point callback");
            bool hitVoxel = info.CollidingEntity is MyVoxelMap || info.CollidingEntity is MyVoxelPhysics;

            if(hitVoxel && m_grid.Render != null) {
                m_grid.Render.ResetLastVoxelContactTimer();
            }

            bool doSparks = MyPerGameSettings.EnableCollisionSparksEffect && (info.CollidingEntity is MyCubeGrid || hitVoxel);

            // According to Petr, WasUsed does not work everytime
            //if (value.ContactProperties.WasUsed)
            {
                // Handle callbacks here
                info.HandleEvents();
            }

            if(MyDebugDrawSettings.DEBUG_DRAW_FRICTION)
            {
                var pos = ClusterToWorld(value.ContactPoint.Position);
                var vel = -GetVelocityAtPoint(pos);
                vel *= 0.1f;
                var fn = Math.Abs(Gravity.Dot(value.ContactPoint.Normal) * value.ContactProperties.Friction);
                if (vel.Length() > 0.5f)
                {
                    vel.Normalize();
                    MyRenderProxy.DebugDrawArrow3D(pos, pos + fn * vel, Color.Gray, Color.Gray, false);
                }
            }

            if (doSparks && Math.Abs(value.SeparatingVelocity) > 2.0f && value.ContactProperties.WasUsed && !m_lastContacts.ContainsKey(value.ContactPointId) && info.EnableParticles)
            {
                ProfilerShort.Begin("AddCollisionEffect");
                m_lastContacts[value.ContactPointId] = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                AddCollisionEffect(info.ContactPosition, value.ContactPoint.Normal);
                ProfilerShort.End();
            }

            ProfilerShort.Begin("Dust");
            bool doDust = MyPerGameSettings.EnableCollisionSparksEffect && hitVoxel;
            float force = Math.Abs(value.SeparatingVelocity * (Mass / 100000));
            if (doDust && force > 0.25f && info.EnableParticles)
            {
                float scale = MathHelper.Clamp(force / 10.0f, 0.2f, 4.0f);
                AddDustEffect(info.ContactPosition, scale);
            }
            ProfilerShort.End();
            // Large dynamic ships colliding with floating objects
            // When low separating velocity or deformation performed, disable contact point
            // Floating object will still collide with kinematic part of ship and won't push it
            if (m_grid.GridSizeEnum == MyCubeSize.Large && !myBody.IsFixedOrKeyframed && info.CollidingEntity is MyFloatingObject && (Math.Abs(value.SeparatingVelocity) < 0.2f))
            {
                var prop = value.ContactProperties;
                prop.IsDisabled = true;
            }

            ProfilerShort.End();
        }
Example #18
0
        public override void ContactPointCallback(ref MyGridContactInfo value)
        {
            base.ContactPointCallback(ref value);

            if (value.CollidingEntity is MyDebrisBase)
                return;

            if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional)
            {
                if (CubeGrid.BlocksDestructionEnabled)
                    Explode();
            }
        }
Example #19
0
        internal override void ContactPointCallback(ref MyGridContactInfo value)
        {
            base.ContactPointCallback(ref value);

            if (value.CollidingEntity is MyDebrisBase)
                return;

            if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional)
            {
                if (MySession.Static.DestructibleBlocks)
                    Explode();
            }
        }