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); }
private void RigidBody_ContactPointCallback(ref HkContactPointEvent value) { if (this.ContactPointCallback != null) { this.ContactPointCallback(ref value); } }
public void RegisterObstacleContact(ref HkContactPointEvent e) { if (m_obstacleContact == false && m_fallSoundShouldPlay.Value == true && (DateTime.UtcNow - m_soundStart).TotalSeconds >= 1f) { m_obstacleContact = true; } }
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; }
protected IMyEntity GetOtherEntity(ref HkContactPointEvent value) { if (value.Base.BodyA.GetEntity() == this) { return(value.Base.BodyB.GetEntity()); } else { return(value.Base.BodyA.GetEntity()); } }
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); } } }
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()); } }
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"); } } }
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); } } }
//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); } }
//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(); }
//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); } }
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(); }
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)); }
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)); }
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); } } } } } } } }
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; }
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(); }
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(); }
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(); }
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); } } } } }
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; }
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; }
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; }
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(); }
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, }; }
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(); }