示例#1
0
        void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
        {
            if (Physics.CharacterProxy == null)
            {
                return;
            }

            if (!MySession.Static.Ready)
            {
                return;
            }

            if (value.Base.BodyA == null || value.Base.BodyB == null)
            {
                return;
            }

            if (value.Base.BodyA.UserObject == null || value.Base.BodyB.UserObject == null)
            {
                return;
            }

            if (value.Base.BodyA.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || value.Base.BodyB.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))
            {
                return;
            }
        }
        public static MyPhysicsBody GetPhysicsBody(this HkContactPointEvent eventInfo, int index)
        {
            var rb = eventInfo.Base.GetRigidBody(index);

            if (rb == null)
            {
                return(null);
            }

            var body = rb.GetBody();

            if (body != null && body.IsWelded)
            {
                uint shapeKey = 0;
                int  i        = 0;
                for (; i < 4; i++)
                {
                    if (eventInfo.GetShapeKey(0, i) == uint.MaxValue)
                    {
                        break;
                    }
                }
                shapeKey = eventInfo.GetShapeKey(0, i - 1);
                body     = HkRigidBody.FromShape(rb.GetShape().GetContainer().GetShape(shapeKey)).GetBody();
            }
            return(body);
        }
示例#3
0
 private void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
 {
     if (this.ContactPointCallback != null)
     {
         this.ContactPointCallback(ref value);
     }
 }
示例#4
0
 public void RegisterObstacleContact(ref HkContactPointEvent e)
 {
     if (m_obstacleContact == false && m_fallSoundShouldPlay.Value == true && (DateTime.UtcNow - m_soundStart).TotalSeconds >= 1f)
     {
         m_obstacleContact = true;
     }
 }
示例#5
0
 void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
 {
     if (ContactPointCallback != null)
     {
         ContactPointCallback(ref value);
     }
 }
 public MyGridContactInfo(ref HkContactPointEvent evnt, MyCubeGrid grid)
 {
     Event = evnt;
     ContactPosition = grid.Physics.ClusterToWorld(evnt.ContactPoint.Position); 
     m_currentEntity = grid;
     m_collidingEntity = Event.GetOtherEntity(grid) as MyEntity;
     m_currentBlock = null;
     m_otherBlock = null;
     ImpulseMultiplier = 1;
 }
 public MyGridContactInfo(ref HkContactPointEvent evnt, MyCubeGrid grid)
 {
     Event             = evnt;
     ContactPosition   = grid.Physics.ClusterToWorld(evnt.ContactPoint.Position);
     m_currentEntity   = grid;
     m_collidingEntity = Event.GetOtherEntity(grid) as MyEntity;
     m_currentBlock    = null;
     m_otherBlock      = null;
     ImpulseMultiplier = 1;
 }
 protected IMyEntity GetOtherEntity(ref HkContactPointEvent value)
 {
     if (value.Base.BodyA.GetEntity() == this)
     {
         return(value.Base.BodyB.GetEntity());
     }
     else
     {
         return(value.Base.BodyA.GetEntity());
     }
 }
示例#9
0
 private void RigidBody_ContactPointCallback(ref HkContactPointEvent e)
 {
     if ((e.EventType == HkContactPointEvent.Type.Manifold) && (this.Physics.RigidBody.GetShape().ShapeType == HkShapeType.Sphere))
     {
         Vector3 item = e.ContactPoint.Position - this.Physics.RigidBody.Position;
         if (item.Normalize() > 0.001f)
         {
             this.m_supportNormals.Add(item);
         }
     }
 }
示例#10
0
 protected Sandbox.ModAPI.IMyEntity GetOtherEntity(ref HkContactPointEvent value)
 {
     if (value.Base.BodyA.GetEntity() == Entity)
     {
         return(value.Base.BodyB.GetEntity());
     }
     else
     {
         return(value.Base.BodyA.GetEntity());
     }
 }
示例#11
0
 private void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
 {
     if (Sync.IsServer)
     {
         VRage.ModAPI.IMyEntity otherEntity = value.GetOtherEntity(this);
         if (otherEntity is MyFloatingObject)
         {
             this.m_entitiesToTake.Add(otherEntity as MyFloatingObject);
             MySandboxGame.Static.Invoke(() => base.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME, "MyCollector::NeedsUpdate");
         }
     }
 }
示例#12
0
        public ContactPointWrapper(ref HkContactPointEvent e)
        {
            this.bodyA    = e.Base.BodyA.GetBody();
            this.bodyB    = e.Base.BodyB.GetBody();
            this.position = e.ContactPoint.Position;
            this.normal   = e.ContactPoint.Normal;
            MyPhysicsBody physicsBody = e.GetPhysicsBody(0);
            MyPhysicsBody body2       = e.GetPhysicsBody(1);

            this.entityA            = physicsBody.Entity;
            this.entityB            = body2.Entity;
            this.separatingVelocity = e.SeparatingVelocity;
        }
        void RigidBody_ContactPointCallback(ref HkContactPointEvent e)
        {
            //if (e.Base.BodyA.IsFixed || e.Base.BodyB.IsFixed)
            {
                Vector3 supportNormal = e.ContactPoint.Position - Physics.RigidBody.Position;
                float   normalLen     = supportNormal.Normalize();

                if (normalLen > 0.001f)
                {
                    m_supportNormals.Add(supportNormal);
                }
            }
        }
示例#14
0
        //isnt used
        void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
        {
            if (!Sync.IsServer)
            {
                return;
            }
            var entity = value.GetOtherEntity(this);

            if (entity is MyFloatingObject)
            {
                m_entitiesToTake.Add(entity as MyFloatingObject);
                NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME;
            }
        }
        public static Sandbox.ModAPI.IMyEntity GetOtherEntity(this HkContactPointEvent eventInfo, Sandbox.ModAPI.IMyEntity sourceEntity)
        {
            var entityA = eventInfo.Base.BodyA.GetEntity();
            var entityB = eventInfo.Base.BodyB.GetEntity();

            if (sourceEntity == entityA)
            {
                return(entityB);
            }
            else
            {
                //Debug.Assert(sourceEntity == entityB);
                return(entityA);
            }
        }
        public static IMyEntity GetOtherEntity(this HkContactPointEvent eventInfo, IMyEntity sourceEntity)
        {
            var bodyA = eventInfo.GetPhysicsBody(0);
            var bodyB = eventInfo.GetPhysicsBody(1);

            var entityA = bodyA == null ? null : bodyA.Entity;
            var entityB = bodyB == null ? null : bodyB.Entity;

            if (sourceEntity == entityA)
            {
                return(entityB);
            }
            else
            {
                //Debug.Assert(sourceEntity == entityB);
                return(entityA);
            }
        }
示例#17
0
        //Vector3 GetVelocityAtPoint(Vector3D worldPos)
        //{
        //    return LinearVelocity + AngularVelocity.Cross(worldPos - CenterOfMassWorld);
        //}

        void OnContactPointCallback(ref HkContactPointEvent e)
        {
            ProfilerShort.Begin("PhysicsBody.OnContacPointCallback");
            if (ContactPointCallback != null)
            {
                var offset = MyPhysics.Clusters.GetObjectOffset(ClusterObjectID);

                MyPhysics.MyContactPointEvent ce = new MyPhysics.MyContactPointEvent()
                {
                    ContactPointEvent = e,
                    Position = e.ContactPoint.Position + offset
                };

                ContactPointCallback(ref ce);
            }
            ProfilerShort.End();
        }
示例#18
0
 //isnt used
 void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
 {
     if (!Sync.IsServer)
         return;
     var entity = value.GetOtherEntity(this);
     if (entity is MyFloatingObject)
     {
         m_entitiesToTake.Add(entity as MyFloatingObject);
         NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME;
     }
 }
        private DamageImpactEnum GetDamageFromHit(HkRigidBody collidingBody, MyEntity collidingEntity, ref HkContactPointEvent value)
        {
            if (collidingBody.LinearVelocity.Length() < MyPerGameSettings.CharacterDamageHitObjectMinVelocity) return DamageImpactEnum.NoDamage;

            if (collidingEntity == ManipulatedEntity) return DamageImpactEnum.NoDamage;

            if (collidingBody.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT)) return DamageImpactEnum.NoDamage;

            var mass = (MyPerGameSettings.Destruction ? MyDestructionHelper.MassFromHavok(collidingBody.Mass) : collidingBody.Mass);
            if (mass < MyPerGameSettings.CharacterDamageHitObjectMinMass) return DamageImpactEnum.NoDamage;

            // Get the objects energies to calculate the damage - must be higher above treshold
            float objectEnergy = Math.Abs(value.SeparatingVelocity) * mass;

            if (objectEnergy > MyPerGameSettings.CharacterDamageHitObjectDeadlyEnergy) return DamageImpactEnum.DeadlyDamage;
            if (objectEnergy > MyPerGameSettings.CharacterDamageHitObjectCriticalEnergy) return DamageImpactEnum.CriticalDamage;
            if (objectEnergy > MyPerGameSettings.CharacterDamageHitObjectMediumEnergy) return DamageImpactEnum.MediumDamage;
            if (objectEnergy > MyPerGameSettings.CharacterDamageHitObjectSmallEnergy) return DamageImpactEnum.SmallDamage;

            return DamageImpactEnum.NoDamage;
        }
        private void CalculateDamageAfterCollision(ref HkContactPointEvent value)
        {
            // Are bodies moving one to another? if not we do not apply damage
            if (value.SeparatingVelocity < 0)
            {
                if (!Sync.IsServer) return;

                DamageImpactEnum damageImpact = DamageImpactEnum.NoDamage;

                // Get the colliding object and skip collisions between characters
                HkRigidBody collidingBody;
                int collidingBodyIdx = 0;
                if (value.Base.BodyA == Physics.CharacterProxy.GetHitRigidBody())
                {
                    collidingBody = value.Base.BodyB;
                    collidingBodyIdx = 1;
                }
                else
                    collidingBody = value.Base.BodyA;
                MyEntity collidingEntity = value.GetPhysicsBody(collidingBodyIdx).Entity as MyEntity;
                if (collidingEntity == null || collidingEntity is MyCharacter) return;

                if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_SHOW_DAMAGE)
                {
                    MatrixD worldMatrix = collidingEntity.Physics.GetWorldMatrix();
                    int index = 0;
                    MyPhysicsDebugDraw.DrawCollisionShape(collidingBody.GetShape(), worldMatrix, 1, ref index, "hit");
                }

                damageImpact = GetDamageFromFall(collidingBody, collidingEntity, ref value);

                if (damageImpact != DamageImpactEnum.NoDamage) ApplyDamage(damageImpact, MyDamageType.Fall);

                damageImpact = GetDamageFromHit(collidingBody, collidingEntity, ref value);

                if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_SHOW_DAMAGE)
                {
                    if (damageImpact != DamageImpactEnum.NoDamage)
                    {
                        MatrixD worldMatrix = collidingEntity.Physics.GetWorldMatrix();
                        VRageRender.MyRenderProxy.DebugDrawSphere(worldMatrix.Translation, collidingBody.Mass, Color.Red, 1, false);
                        VRageRender.MyRenderProxy.DebugDrawText3D(worldMatrix.Translation, "MASS: " + collidingBody.Mass, Color.Red, 1, false);
                    }
                }

                if (damageImpact != DamageImpactEnum.NoDamage) ApplyDamage(damageImpact, MyDamageType.Environment);

                damageImpact = GetDamageFromSqueeze(collidingBody, collidingEntity, ref value);

                if (damageImpact != DamageImpactEnum.NoDamage) ApplyDamage(damageImpact, MyDamageType.Squeez);

            }
        }
示例#21
0
        void OnContactPointCallback(ref HkContactPointEvent e)
        {
            ProfilerShort.Begin("PhysicsBody.OnContacPointCallback");
            if (ContactPointCallback != null)
            {
                MyPhysics.MyContactPointEvent ce = new MyPhysics.MyContactPointEvent()
                {
                    ContactPointEvent = e,
                    Position = e.ContactPoint.Position + Offset
                };

                ContactPointCallback(ref ce);
            }
            ProfilerShort.End();
        }
        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();
        }
示例#23
0
        internal void TrySpawnWalkingParticles(ref HkContactPointEvent value)
        {
            if (!MyFakes.ENABLE_WALKING_PARTICLES)
            {
                return;
            }

            var oldCheckTime = m_lastWalkParticleCheckTime;

            m_lastWalkParticleCheckTime   = MySandboxGame.TotalGamePlayTimeInMilliseconds;
            m_walkParticleSpawnCounterMs -= m_lastWalkParticleCheckTime - oldCheckTime;
            if (m_walkParticleSpawnCounterMs > 0)
            {
                return;
            }

            var naturalGravityMultiplier = MyGravityProviderSystem.CalculateHighestNaturalGravityMultiplierInPoint(Entity.PositionComp.WorldMatrix.Translation);

            if (naturalGravityMultiplier <= 0f)
            {
                m_walkParticleSpawnCounterMs = m_walkParticleGravityDelay;
                return;
            }

            var character = Entity as MyCharacter;

            if (character.JetpackComp != null && character.JetpackComp.Running)
            {
                m_walkParticleSpawnCounterMs = m_walkParticleJetpackOffDelay;
                return;
            }

            var currentMovementState = character.GetCurrentMovementState();

            if (currentMovementState.GetDirection() == MyCharacterMovement.NoDirection || currentMovementState == MyCharacterMovementEnum.Falling)
            {
                m_walkParticleSpawnCounterMs = m_walkParticleDefaultDelay;
                return;
            }

            var otherPhysicsBody = value.GetOtherEntity(character).Physics as MyVoxelPhysicsBody;        //value.Base.BodyA.UserObject == character.Physics ? value.Base.BodyB.UserObject : value.Base.BodyA.UserObject)) as MyVoxelPhysicsBody;

            if (otherPhysicsBody == null)
            {
                return;
            }

            MyStringId movementType;

            const int walkParticleWalkDelay   = 500;
            const int walkParticleRunDelay    = 275;
            const int walkParticleSprintDelay = 250;

            switch (currentMovementState.GetSpeed())
            {
            case MyCharacterMovement.NormalSpeed:
                movementType = MyMaterialPropertiesHelper.CollisionType.Walk;
                m_walkParticleSpawnCounterMs = walkParticleWalkDelay;
                break;

            case MyCharacterMovement.Fast:
                movementType = MyMaterialPropertiesHelper.CollisionType.Run;
                m_walkParticleSpawnCounterMs = walkParticleRunDelay;
                break;

            case MyCharacterMovement.VeryFast:
                movementType = MyMaterialPropertiesHelper.CollisionType.Sprint;
                m_walkParticleSpawnCounterMs = walkParticleSprintDelay;
                break;

            default:
                movementType = MyMaterialPropertiesHelper.CollisionType.Walk;
                m_walkParticleSpawnCounterMs = m_walkParticleDefaultDelay;
                break;
            }

            var spawnPosition = otherPhysicsBody.ClusterToWorld(value.ContactPoint.Position);

            MyVoxelMaterialDefinition voxelMaterialDefinition = otherPhysicsBody.m_voxelMap.GetMaterialAt(ref spawnPosition);

            if (voxelMaterialDefinition == null)
            {
                return;
            }

            MyMaterialPropertiesHelper.Static.TryCreateCollisionEffect(
                movementType,
                spawnPosition,
                value.ContactPoint.Normal,
                m_characterMaterial,
                MyStringHash.GetOrCompute(voxelMaterialDefinition.MaterialTypeName));
        }
示例#24
0
 void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
 {
     if (ContactPointCallback != null)
         ContactPointCallback(ref value);
 }
	    internal void TrySpawnWalkingParticles(ref HkContactPointEvent value)
	    {
		    if (!MyFakes.ENABLE_WALKING_PARTICLES)
			    return;
            
		    var oldCheckTime = m_lastWalkParticleCheckTime;
		    m_lastWalkParticleCheckTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
		    m_walkParticleSpawnCounterMs -= m_lastWalkParticleCheckTime - oldCheckTime;
		    if (m_walkParticleSpawnCounterMs > 0)
			    return;

			var naturalGravityMultiplier = MyGravityProviderSystem.CalculateHighestNaturalGravityMultiplierInPoint(Entity.PositionComp.WorldMatrix.Translation);
		    if (naturalGravityMultiplier <= 0f)
		    {
			    m_walkParticleSpawnCounterMs = m_walkParticleGravityDelay;
			    return;
		    }

		    var character = Entity as MyCharacter;
		    if (character.JetpackComp != null && character.JetpackComp.Running)
		    {
			    m_walkParticleSpawnCounterMs = m_walkParticleJetpackOffDelay;
			    return;
		    }

		    var currentMovementState = character.GetCurrentMovementState();
		    if (currentMovementState.GetDirection() == MyCharacterMovement.NoDirection || currentMovementState == MyCharacterMovementEnum.Falling)
		    {
			    m_walkParticleSpawnCounterMs = m_walkParticleDefaultDelay;
			    return;
		    }

		    var otherPhysicsBody = value.GetOtherEntity(character).Physics as MyVoxelPhysicsBody;//value.Base.BodyA.UserObject == character.Physics ? value.Base.BodyB.UserObject : value.Base.BodyA.UserObject)) as MyVoxelPhysicsBody;
		    if (otherPhysicsBody == null)
			    return;
	       
			MyStringId movementType;

		    const int walkParticleWalkDelay = 500;
			const int walkParticleRunDelay = 275;
			const int walkParticleSprintDelay = 250;
		    switch (currentMovementState.GetSpeed())
		    {
			    case MyCharacterMovement.NormalSpeed:
				    movementType = MyMaterialPropertiesHelper.CollisionType.Walk;
				    m_walkParticleSpawnCounterMs = walkParticleWalkDelay;
				    break;
				case MyCharacterMovement.Fast:
					movementType = MyMaterialPropertiesHelper.CollisionType.Run;
				    m_walkParticleSpawnCounterMs = walkParticleRunDelay;
				    break;
				case MyCharacterMovement.VeryFast:
					movementType = MyMaterialPropertiesHelper.CollisionType.Sprint;
				    m_walkParticleSpawnCounterMs = walkParticleSprintDelay;
				    break;
				default:
				    movementType = MyMaterialPropertiesHelper.CollisionType.Walk;
				    m_walkParticleSpawnCounterMs = m_walkParticleDefaultDelay;
				    break;

		    }

            var spawnPosition = otherPhysicsBody.ClusterToWorld(value.ContactPoint.Position);

            MyVoxelMaterialDefinition voxelMaterialDefinition = otherPhysicsBody.m_voxelMap.GetMaterialAt(ref spawnPosition);
		    if (voxelMaterialDefinition == null)
			    return;

		    MyMaterialPropertiesHelper.Static.TryCreateCollisionEffect(
				movementType,
				spawnPosition,
				value.ContactPoint.Normal,
				m_characterMaterial,
				MyStringHash.GetOrCompute(voxelMaterialDefinition.MaterialTypeName));
	    }
示例#26
0
 internal void TrySpawnWalkingParticles(ref HkContactPointEvent value)
 {
     if (MyFakes.ENABLE_WALKING_PARTICLES)
     {
         int lastWalkParticleCheckTime = this.m_lastWalkParticleCheckTime;
         this.m_lastWalkParticleCheckTime   = MySandboxGame.TotalGamePlayTimeInMilliseconds;
         this.m_walkParticleSpawnCounterMs -= this.m_lastWalkParticleCheckTime - lastWalkParticleCheckTime;
         if (this.m_walkParticleSpawnCounterMs <= 0)
         {
             if (MyGravityProviderSystem.CalculateHighestNaturalGravityMultiplierInPoint(base.Entity.PositionComp.WorldMatrix.Translation) <= 0f)
             {
                 this.m_walkParticleSpawnCounterMs = 0x2710;
             }
             else
             {
                 MyCharacter entity = base.Entity as MyCharacter;
                 if (entity.JetpackRunning)
                 {
                     this.m_walkParticleSpawnCounterMs = 0x7d0;
                 }
                 else
                 {
                     MyCharacterMovementEnum currentMovementState = entity.GetCurrentMovementState();
                     if ((currentMovementState.GetDirection() == 0) || (currentMovementState == MyCharacterMovementEnum.Falling))
                     {
                         this.m_walkParticleSpawnCounterMs = 0x3e8;
                     }
                     else
                     {
                         MyVoxelPhysicsBody physics = value.GetOtherEntity(entity).Physics as MyVoxelPhysicsBody;
                         if (physics != null)
                         {
                             MyStringId walk;
                             ushort     speed = currentMovementState.GetSpeed();
                             if (speed == 0)
                             {
                                 walk = MyMaterialPropertiesHelper.CollisionType.Walk;
                                 this.m_walkParticleSpawnCounterMs = 500;
                             }
                             else if (speed == 0x400)
                             {
                                 walk = MyMaterialPropertiesHelper.CollisionType.Run;
                                 this.m_walkParticleSpawnCounterMs = 0x113;
                             }
                             else if (speed != 0x800)
                             {
                                 walk = MyMaterialPropertiesHelper.CollisionType.Walk;
                                 this.m_walkParticleSpawnCounterMs = 0x3e8;
                             }
                             else
                             {
                                 walk = MyMaterialPropertiesHelper.CollisionType.Sprint;
                                 this.m_walkParticleSpawnCounterMs = 250;
                             }
                             Vector3D worldPosition = physics.ClusterToWorld(value.ContactPoint.Position);
                             MyVoxelMaterialDefinition materialAt = physics.m_voxelMap.GetMaterialAt(ref worldPosition);
                             if (materialAt != null)
                             {
                                 MyMaterialPropertiesHelper.Static.TryCreateCollisionEffect(walk, worldPosition, value.ContactPoint.Normal, ID_CHARACTER, materialAt.MaterialTypeNameHash, null);
                             }
                         }
                     }
                 }
             }
         }
     }
 }
示例#27
0
        void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
        {
            if (Physics.CharacterProxy == null)
                return;

            if (!MySession.Static.Ready)
                return;

            if (value.Base.BodyA == null || value.Base.BodyB == null)
                return;

            if (value.Base.BodyA.UserObject == null || value.Base.BodyB.UserObject == null)
                return;

            if (value.Base.BodyA.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || value.Base.BodyB.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))
                return;
        }
示例#28
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();
        }
 protected Sandbox.ModAPI.IMyEntity GetOtherEntity(ref HkContactPointEvent value)
 {
     if (value.Base.BodyA.GetEntity() == this)
         return value.Base.BodyB.GetEntity();
     else
         return value.Base.BodyA.GetEntity();
 }
示例#30
0
        public void PlayContactSound(HkContactPointEvent value, float volume = 0)
        {
            ProfilerShort.Begin("PlayContactSound");
            var bodyA = value.Base.BodyA.GetBody();
            var bodyB = value.Base.BodyB.GetBody();
            if (bodyA == null || bodyB == null)
            {
                ProfilerShort.End();
                return;
            }
            ProfilerShort.BeginNextBlock("GetMaterial");
            var worldPos = ClusterToWorld(value.ContactPoint.Position);
            var materialA = bodyA.GetMaterialAt(worldPos + value.ContactPoint.Normal * 0.1f);
            var materialB = bodyB.GetMaterialAt(worldPos - value.ContactPoint.Normal * 0.1f);
            /*if (materialA == m_character || materialB == m_character)
            {
                ProfilerShort.End();
                return;
            }*/
            ProfilerShort.Begin("Lambdas");
            var colision = value.Base;
            Func<bool> canHear = () =>
            {
                if (MySession.Static.ControlledEntity != null)
                {
                    var entity = MySession.Static.ControlledEntity.Entity.GetTopMostParent();
                    return (entity == value.GetPhysicsBody(0).Entity || entity == value.GetPhysicsBody(1).Entity);
                }
                return false;
            };

            Func<bool> shouldPlay2D = () => MySession.Static.ControlledEntity != null && MySession.Static.ControlledEntity.Entity is MyCharacter && (
                            MySession.Static.ControlledEntity.Entity.Components == value.GetPhysicsBody(0).Entity || MySession.Static.ControlledEntity.Entity.Components == value.GetPhysicsBody(1).Entity);

            ProfilerShort.BeginNextBlock("Volume");
            if (volume == 0)
            {
                //var vel = value.Base.BodyA.LinearVelocity - value.Base.BodyB.LinearVelocity;
                //if (System.Math.Abs(Vector3.Normalize(vel).Dot(value.ContactPoint.Normal)) < 0.7f)\
                //var val = System.Math.Abs(Vector3.Normalize(vel).Dot(value.ContactPoint.Normal)) * vel.Length();
                //var mass = value.Base.BodyA.Mass;
                //var massB = value.Base.BodyB.Mass;
                //mass = mass == 0 ? massB : massB == 0 ? mass : mass < massB ? mass : massB; // select smaller mass > 0
                //mass /= 40; //reference mass
                //val *= mass;
                if (Math.Abs(value.SeparatingVelocity) < 10f)
                    volume = 0.5f + Math.Abs(value.SeparatingVelocity) / 20f;
                else
                    volume = 1f;
            }

            ProfilerShort.BeginNextBlock("PlaySound");
            bool firstOneIsLighter = bodyB.Entity is MyVoxelBase || bodyB.Entity.Physics == null;
            if (firstOneIsLighter == false && bodyA.Entity.Physics != null && bodyA.Entity.Physics.IsStatic == false && (bodyB.Entity.Physics.IsStatic || bodyA.Entity.Physics.Mass < bodyB.Entity.Physics.Mass))
                firstOneIsLighter = true;
            if (firstOneIsLighter)
                MyAudioComponent.PlayContactSound(bodyA.Entity.EntityId, m_startCue, worldPos, materialA, materialB, volume, canHear, surfaceEntity: (MyEntity)bodyB.Entity, separatingVelocity: Math.Abs(value.SeparatingVelocity));
            else
                MyAudioComponent.PlayContactSound(bodyB.Entity.EntityId, m_startCue, worldPos, materialB, materialA, volume, canHear, surfaceEntity: (MyEntity)bodyA.Entity, separatingVelocity: Math.Abs(value.SeparatingVelocity));
            ProfilerShort.End();
            ProfilerShort.End();
        }
示例#31
0
        public void PlayContactSound(HkContactPointEvent value, float volume = 0)
        {
            ProfilerShort.Begin("PlayContactSound");
            var bodyA = value.Base.BodyA.GetBody();
            var bodyB = value.Base.BodyB.GetBody();
            if (bodyA == null || bodyB == null)
            {
                ProfilerShort.End();
                return;
            }

            var colision = value.Base;
            Func<bool> canHear = () =>
            {
                if (MySession.ControlledEntity != null)
                {
                    var entity = MySession.ControlledEntity.Entity.GetTopMostParent();
                    return (entity == value.GetPhysicsBody(0).Entity || entity == value.GetPhysicsBody(1).Entity);
                }
                return false;
            };

            Func<bool> shouldPlay2D = () => MySession.ControlledEntity != null && MySession.ControlledEntity.Entity is MyCharacter && (
                            MySession.ControlledEntity.Entity.Components == value.GetPhysicsBody(0).Entity || MySession.ControlledEntity.Entity.Components == value.GetPhysicsBody(1).Entity);

            if (volume == 0)
            {
                var vel = value.Base.BodyA.LinearVelocity - value.Base.BodyB.LinearVelocity;
                //if (System.Math.Abs(Vector3.Normalize(vel).Dot(value.ContactPoint.Normal)) < 0.7f)\
                var val = System.Math.Abs(Vector3.Normalize(vel).Dot(value.ContactPoint.Normal)) * vel.Length();
                //var mass = value.Base.BodyA.Mass;
                //var massB = value.Base.BodyB.Mass;
                //mass = mass == 0 ? massB : massB == 0 ? mass : mass < massB ? mass : massB; // select smaller mass > 0
                //mass /= 40; //reference mass
                //val *= mass;
                if (val < 10)
                    volume = val / 10;
                else
                    volume = 1;
            }

            var worldPos = ClusterToWorld(value.ContactPoint.Position);
            var materialA = bodyA.GetMaterialAt(worldPos + value.ContactPoint.Normal * 0.1f);
            var materialB = bodyB.GetMaterialAt(worldPos - value.ContactPoint.Normal * 0.1f);


            MyAudioComponent.PlayContactSound(Entity.EntityId, worldPos, materialA, materialB, volume, canHear);

            ProfilerShort.End();
        }
示例#32
0
 protected IMyEntity GetOtherEntity(ref HkContactPointEvent value)
 {
     if (value.Base.BodyA.GetEntity() == Entity)
         return value.Base.BodyB.GetEntity();
     else
         return value.Base.BodyA.GetEntity();
 }
        void RigidBody_ContactPointCallback(ref HkContactPointEvent value)
        {
            if (IsDead || Sync.IsServer == false)
                return;

            if (Physics.CharacterProxy == null)
                return;

            if (!MySession.Static.Ready)
                return;

            if (value.Base.BodyA == null || value.Base.BodyB == null)
                return;

            if (value.Base.BodyA.UserObject == null || value.Base.BodyB.UserObject == null)
                return;

            if (value.Base.BodyA.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || value.Base.BodyB.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))
                return;



            //MyCharacter charA = null;//((MyPhysicsBody)value.Base.BodyA.UserObject).Entity as MyCharacter;
            //MyCharacter charB = null;//((MyPhysicsBody)value.Base.BodyB.UserObject).Entity as MyCharacter;

            //if (charA != null && charA.AIMode)
            //    return;

            //if (charB != null && charB.AIMode)
            //    return;

            Render.TrySpawnWalkingParticles(ref value);

            // DAMAGE COMPUTATION TO THE CHARACTER
            // GET THE OTHER COLLIDING BODY AND COMPUTE DAMAGE BASED ON BODIES MASS AND VELOCITIES
            if (MyPerGameSettings.EnableCharacterCollisionDamage && !MyFakes.NEW_CHARACTER_DAMAGE)
            {
                CalculateDamageAfterCollision(ref value);
            }
            //// ORIGINAL DAMAGE COMPUTATION
            else
            {
                float impact = 0;

                if (MyFakes.NEW_CHARACTER_DAMAGE)
                {
                    var normal = value.ContactPoint.Normal;
                    MyEntity other = value.GetPhysicsBody(0).Entity as MyEntity;

                    HkRigidBody otherRb = value.Base.BodyA;
                    if (other == this)
                    {
                        other = value.GetPhysicsBody(1).Entity as MyEntity;
                        otherRb = value.Base.BodyB;
                        normal = -normal;
                    }

                    var otherChar = (other as MyCharacter);
                    if (otherChar != null)
                    {
                        if (otherChar.IsDead)
                        {
                            if (otherChar.Physics.Ragdoll != null && otherChar.Physics.Ragdoll.GetRootRigidBody().HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))
                                return;
                        }
                        else
                        {
                            if (Physics.CharacterProxy.Supported && otherChar.Physics.CharacterProxy.Supported)
                                return;
                        }
                    }

                    if (Math.Abs(value.SeparatingVelocity) < 3)
                    {
                        return;
                    }

                    Vector3 velocity1 = Physics.LinearVelocity;

                    Vector3 difference = velocity1 - m_previousLinearVelocity;

                    float lenght = difference.Length();

                    if (lenght > 10)
                    {
                        //strange angle / magnitude force mismatch
                        return;
                    }

                    Vector3 velocity2 = otherRb.GetVelocityAtPoint(value.ContactPoint.Position);

                    float velocity = velocity1.Length();
                    float speed1 = Math.Max(velocity - (MyFakes.ENABLE_CUSTOM_CHARACTER_IMPACT ? 12.6f : 17.0f), 0);//treshold for falling dmg
                    float speed2 = velocity2.Length() - 2.0f;

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

                    float dot1withNormal = speed1 > 0 ? Vector3.Dot(dir1, normal) : 0;
                    float dot2withNormal = speed2 > 0 ? -Vector3.Dot(dir2, normal) : 0;

                    speed1 *= dot1withNormal;
                    speed2 *= dot2withNormal;

                    float vel = Math.Min(speed1 + speed2, Math.Abs(value.SeparatingVelocity) - 17.0f);
                    if (vel >= -8f && m_canPlayImpact <= 0f)//impact sound
                    {
                        m_canPlayImpact = 0.3f;
                        HkContactPointEvent hkContactPointEvent = value;
                        Func<bool> canHear = () =>
                        {
                            if (MySession.Static.ControlledEntity != null)
                            {
                                var entity = MySession.Static.ControlledEntity.Entity.GetTopMostParent();
                                return (entity == hkContactPointEvent.GetPhysicsBody(0).Entity || entity == hkContactPointEvent.GetPhysicsBody(1).Entity);
                            }
                            return false;
                        };
                        var bodyB = value.Base.BodyB.GetBody();
                        var worldPos = Physics.ClusterToWorld(value.ContactPoint.Position);
                        var materialB = bodyB.GetMaterialAt(worldPos - value.ContactPoint.Normal * 0.1f);
                        float volume = (Math.Abs(value.SeparatingVelocity) < 15f) ? (0.5f + Math.Abs(value.SeparatingVelocity) / 30f) : 1f;
                        MyAudioComponent.PlayContactSound(Entity.EntityId, m_stringIdStart, worldPos, m_stringHashCharacter, materialB, volume, canHear);
                    }
                    if (vel < 0)
                        return;

                    float mass1 = MyDestructionHelper.MassFromHavok(Physics.Mass * this.m_massChangeForCollisions);
                    float mass2 = MyDestructionHelper.MassFromHavok(otherRb.Mass * other.m_massChangeForCollisions);

                    float impact1 = (speed1 * speed1 * mass1) * 0.5f;
                    float impact2 = (speed2 * speed2 * mass2) * 0.5f;


                    float mass;
                    if (mass1 > mass2 && !otherRb.IsFixedOrKeyframed)
                    {
                        mass = mass2;
                        //impact = impact2;
                    }
                    else
                    {
                        mass = MyDestructionHelper.MassToHavok(70);// Physics.Mass;
                        if (Physics.CharacterProxy.Supported && !otherRb.IsFixedOrKeyframed)
                            mass += Math.Abs(Vector3.Dot(Vector3.Normalize(velocity2), Physics.CharacterProxy.SupportNormal)) * mass2 / 10;
                    }
                    mass = MyDestructionHelper.MassFromHavok(mass);

                    impact = (mass * vel * vel) / 2;
                    if (speed2 > 2) //dont reduce pure fall damage
                        impact -= 400;
                    impact /= 10; //scaling damage
                    if (impact < 1)
                        return;
                }

                //int bodyId = value.Base.BodyA == Physics.CharacterProxy.GetRigidBody() ? 1 : 0;
                // Ca
                //uint shapeKey = value.GetShapeKey(bodyId);
                //if (shapeKey != uint.MaxValue)
                {

                    //m_shapeContactPoints.Add(shapeKey);

                    //MyTrace.Send(TraceWindow.Default, "Velocity: " + value.SeparatingVelocity.ToString());
                    //if (Math.Abs(value.SeparatingVelocity) > 0)
                    //{
                    //}

                    //2 large blocks (14.3m/s)
                    //3 large blocks (17.0m/s)
                    //5 large blocks (22.3m/s)                
                    //6 large blocks (24.2m/s)
                    float damageImpact = (Math.Abs(value.SeparatingVelocity) - 17.0f) * 14.0f;



                    if (MyFakes.ENABLE_CUSTOM_CHARACTER_IMPACT)
                    {
                        // 1.5 ~ start damage (12.6m/s)
                        // 3 blocks - dead (17.0)
                        damageImpact = (Math.Abs(value.SeparatingVelocity) - 12.6f) * 25f;
                    }
                    if (MyFakes.NEW_CHARACTER_DAMAGE)
                        damageImpact = impact;
                    if (damageImpact > 0)
                    {
                        if (Sync.IsServer)
                        {
                            IMyEntity other = value.GetPhysicsBody(0).Entity;
                            if (other == this)
                                other = value.GetPhysicsBody(1).Entity;

                            DoDamage(damageImpact, MyDamageType.Environment, true, other != null ? other.EntityId : 0);
                        }
                    }
                }
            }
        }
示例#34
0
        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();
        }
        private DamageImpactEnum GetDamageFromSqueeze(HkRigidBody collidingBody, MyEntity collidingEntity, ref HkContactPointEvent value)
        {
            if (collidingBody.IsFixed || collidingBody.Mass < MyPerGameSettings.CharacterSqueezeMinMass) return DamageImpactEnum.NoDamage;

            if (value.ContactProperties.IsNew) return DamageImpactEnum.NoDamage;

            // the object has to be moving towards the character even slowly and that also the character is not moving away from it
            Vector3 direction = Physics.CharacterProxy.GetHitRigidBody().Position - collidingBody.Position;
            Vector3 gravity = MyGravityProviderSystem.CalculateTotalGravityInPoint(PositionComp.WorldAABB.Center) + Physics.HavokWorld.Gravity;
            direction.Normalize();
            gravity.Normalize();

            float resultToPlayer = Vector3.Dot(direction, gravity);

            if (resultToPlayer < 0.5f) return DamageImpactEnum.NoDamage;

            if (m_squeezeDamageTimer > 0)
            {
                m_squeezeDamageTimer -= VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
                return DamageImpactEnum.NoDamage;
            }
            m_squeezeDamageTimer = MyPerGameSettings.CharacterSqueezeDamageDelay;

            if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_SHOW_DAMAGE)
            {
                MatrixD worldMatrix = collidingEntity.Physics.GetWorldMatrix();
                int index = 2;
                MyPhysicsDebugDraw.DrawCollisionShape(collidingBody.GetShape(), worldMatrix, 1, ref index);
                VRageRender.MyRenderProxy.DebugDrawText3D(worldMatrix.Translation, "SQUEEZE, MASS:" + collidingBody.Mass, Color.Yellow, 2, false);
            }

            if (collidingBody.Mass > MyPerGameSettings.CharacterSqueezeDeadlyDamageMass) return DamageImpactEnum.DeadlyDamage;

            if (collidingBody.Mass > MyPerGameSettings.CharacterSqueezeCriticalDamageMass) return DamageImpactEnum.CriticalDamage;

            if (collidingBody.Mass > MyPerGameSettings.CharacterSqueezeMediumDamageMass) return DamageImpactEnum.MediumDamage;

            return DamageImpactEnum.SmallDamage;
        }
示例#36
0
        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();
        }
        private DamageImpactEnum GetDamageFromFall(HkRigidBody collidingBody, MyEntity collidingEntity, ref HkContactPointEvent value)
        {
            //if (m_currentMovementState != MyCharacterMovementEnum.Falling || m_currentMovementState != MyCharacterMovementEnum.Jump) return DamageImpactEnum.NoDamage;
            //if (!collidingBody.IsFixed && collidingBody.Mass < Physics.Mass * 50) return DamageImpactEnum.NoDamage;

            float dotProd = Vector3.Dot(value.ContactPoint.Normal, Vector3.Normalize(Physics.HavokWorld.Gravity));

            bool falledOnEntity = dotProd <= 0.0f;

            if (!falledOnEntity) return DamageImpactEnum.NoDamage;

            if (Math.Abs(value.SeparatingVelocity * dotProd) < MyPerGameSettings.CharacterDamageMinVelocity) return DamageImpactEnum.NoDamage;

            if (Math.Abs(value.SeparatingVelocity * dotProd) > MyPerGameSettings.CharacterDamageDeadlyDamageVelocity) return DamageImpactEnum.DeadlyDamage;

            if (Math.Abs(value.SeparatingVelocity * dotProd) > MyPerGameSettings.CharacterDamageMediumDamageVelocity) return DamageImpactEnum.MediumDamage;

            return DamageImpactEnum.SmallDamage;
        }
示例#38
0
 private static Vector3 GetGridPosition(HkContactPointEvent value, MyCubeGrid grid, int body)
 {
     var position = value.ContactPoint.Position + (body == 0 ? 0.1f : -0.1f) * value.ContactPoint.Normal;
     var local = Vector3.Transform(value.ContactPoint.Position, Matrix.Invert(value.Base.GetRigidBody(body).GetRigidBodyMatrix()));
     return local;
 }
示例#39
0
        public void PlayContactSound(HkContactPointEvent value)
        {
            ProfilerShort.Begin("PlayContactSound");
            var bodyA = value.Base.BodyA.GetBody();
            var bodyB = value.Base.BodyB.GetBody();
            if (bodyA == null || bodyB == null)
            {
                ProfilerShort.End();
                return;
            }
            MySoundPair cue = null;
            var worldPos = ClusterToWorld(value.ContactPoint.Position);
            cue = MyMaterialSoundsHelper.Static.GetCollisionCue(m_startCue, bodyA.GetMaterialAt(worldPos), bodyB.GetMaterialAt(worldPos));
            //cue = MyMaterialsConstants.GetCollisionCue(MyMaterialsConstants.MyMaterialCollisionType.Start, value.Base.BodyA.GetBody().MaterialType, value.Base.BodyB.GetBody().MaterialType);

            if (cue.SoundId != MyStringId.NullOrEmpty)
            {
                MyEntity3DSoundEmitter emitter;
                {
                    emitter = MyAudioComponent.TryGetSoundEmitter();
                    if (emitter == null)
                    {
                        ProfilerShort.End();
                        return;
                    }
                    //emitter = new MyEntity3DSoundEmitter(null);
                    MyAudioComponent.ContactSoundsPool.TryAdd(Entity.EntityId, 0);
                    emitter.StoppedPlaying += (e) => 
                    { 
                        byte val;
                        MyAudioComponent.ContactSoundsPool.TryRemove(Entity.EntityId, out val); 
                    };
                    if (MySession.Static.Settings.RealisticSound && MyFakes.ENABLE_NEW_SOUNDS)
                    {
                        var colision = value.Base;
                        Func<bool> canHear = () =>
                        {
                            if (MySession.ControlledEntity != null)
                            {
                                var entity = MySession.ControlledEntity.Entity.GetTopMostParent();
                                return (entity == colision.BodyA.GetEntity() || entity == colision.BodyB.GetEntity());
                            }
                            return false;
                        };
                        Func<bool> shouldPlay2D = () => MySession.ControlledEntity != null && MySession.ControlledEntity.Entity is MyCharacter && (
                                MySession.ControlledEntity.Entity.Components == colision.BodyA.GetEntity() || MySession.ControlledEntity.Entity.Components == colision.BodyB.GetEntity());
                        Action<MyEntity3DSoundEmitter> remove = null;
                        remove = (e) =>
                            {
                                emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.CanHear].Remove(canHear);
                                emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.ShouldPlay2D].Remove(shouldPlay2D);
                                emitter.StoppedPlaying -= remove;
                            };
                        emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.CanHear].Add(canHear);
                        emitter.EmitterMethods[MyEntity3DSoundEmitter.MethodsEnum.ShouldPlay2D].Add(shouldPlay2D);
                        emitter.StoppedPlaying += remove;
                    }
                }
                emitter.SetPosition(ClusterToWorld(value.ContactPoint.Position));
                emitter.PlaySound(cue, true);
                if (emitter.Sound != null)
                {
                    var vel = value.Base.BodyA.LinearVelocity - value.Base.BodyB.LinearVelocity;
                    //if (System.Math.Abs(Vector3.Normalize(vel).Dot(value.ContactPoint.Normal)) < 0.7f)\
                    var val = System.Math.Abs(Vector3.Normalize(vel).Dot(value.ContactPoint.Normal)) * vel.Length();
                    //var mass = value.Base.BodyA.Mass;
                    //var massB = value.Base.BodyB.Mass;
                    //mass = mass == 0 ? massB : massB == 0 ? mass : mass < massB ? mass : massB; // select smaller mass > 0
                    //mass /= 40; //reference mass
                    //val *= mass;
                    if (val < 10)
                        emitter.Sound.SetVolume(val  / 10);
                    else
                        emitter.Sound.SetVolume(1);
                }
            }
            ProfilerShort.End();
        }
示例#40
0
 HkBreakOffPointInfo CreateBreakOffPoint(HkContactPointEvent value, Vector3D contactPosition, float breakImpulse)
 {
     return new HkBreakOffPointInfo()
     {
         ContactPoint = value.ContactPoint,
         ContactPosition = contactPosition,
         ContactPointProperties = value.ContactProperties,
         IsContact = true,
         BreakingImpulse = breakImpulse,
         CollidingBody = value.Base.BodyA == RigidBody ? value.Base.BodyB : value.Base.BodyA,
         ContactPointDirection = value.Base.BodyB == RigidBody ? -1 : 1,
     };
 }
示例#41
0
 void MyPhysicsBody_ContactSoundCallback(ref HkContactPointEvent e)
 {
     ProfilerShort.Begin("PhysicsBody.ContacSoundCallback");
     byte val;
     if (e.EventType != HkContactPointEvent.Type.Manifold || MyAudioComponent.ContactSoundsPool.TryGetValue(Entity.EntityId, out val))
     {
         ProfilerShort.End();
         return;
     }
     PlayContactSound(e);
     ProfilerShort.End();
 }
示例#42
0
 public void RegisterObstacleContact(ref HkContactPointEvent e)
 {
     if (m_obstacleContact == false && m_fallSoundShouldPlay.Value == true && (DateTime.UtcNow - m_soundStart).TotalSeconds >= 1f)
     {
         m_obstacleContact = true;
     }
 }