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; }
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); } }
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); } }
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); } } } } }
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(); }
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(); }
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(); }
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(); }