private void DestroyGrid(ref MyPhysics.MyContactPointEvent value, MyCubeGrid grid) { MyGridContactInfo info = new MyGridContactInfo(ref value.ContactPointEvent, grid); info.EnableDeformation = false; info.EnableParticles = false; HkBreakOffPointInfo breakInfo = new HkBreakOffPointInfo() { ContactPoint = value.ContactPointEvent.ContactPoint, ContactPosition = info.ContactPosition, ContactPointProperties = value.ContactPointEvent.ContactProperties, IsContact = true, BreakingImpulse = grid.Physics.Shape.BreakImpulse, CollidingBody = value.ContactPointEvent.Base.BodyA == grid.Physics.RigidBody ? value.ContactPointEvent.Base.BodyB : value.ContactPointEvent.Base.BodyA, ContactPointDirection = value.ContactPointEvent.Base.BodyB == grid.Physics.RigidBody ? -1 : 1, }; grid.Physics.PerformMeteoritDeformation(ref breakInfo, value.ContactPointEvent.SeparatingVelocity); m_closeAfterSimulation = Sync.IsServer; }
public void PerformMeteoritDeformation(ref HkBreakOffPointInfo pt, float separatingVelocity) { ProfilerShort.Begin("PerformDeformation"); Debug.Assert(Sync.IsServer, "Function PerformDeformation should not be called from client"); // Calculate deformation offset float deformationOffset = 0.3f + Math.Max(0, ((float)Math.Sqrt(Math.Abs(separatingVelocity) + Math.Pow(pt.CollidingBody.Mass, 0.72))) / 10); deformationOffset *= 6; const float maxDeformationHardLimit = 5; // Max offset is 5 for meteors deformationOffset = Math.Min(deformationOffset, maxDeformationHardLimit); float softAreaPlanar = (float)Math.Pow(pt.CollidingBody.Mass, 0.15f); softAreaPlanar -= 0.3f; softAreaPlanar *= m_grid.GridSizeEnum == MyCubeSize.Large ? 4 : 1f; // About 4 meters for large grid and 1m for small float softAreaVertical = deformationOffset; softAreaVertical *= m_grid.GridSizeEnum == MyCubeSize.Large ? 1 : 0.2f; var invWorld = m_grid.PositionComp.GetWorldMatrixNormalizedInv(); var pos = Vector3D.Transform(pt.ContactPosition, invWorld); var normal = Vector3.TransformNormal(pt.ContactPoint.Normal, invWorld) * pt.ContactPointDirection; bool destroyed = ApplyDeformation(deformationOffset, softAreaPlanar, softAreaVertical, pos, normal, MyDamageType.Deformation, 0, m_grid.GridSizeEnum == MyCubeSize.Large ? 0.6f : 0.16f); MyPhysics.CastRay(pt.ContactPoint.Position, pt.ContactPoint.Position - softAreaVertical * Vector3.Normalize(pt.ContactPoint.Normal), m_hitList); foreach (var hit in m_hitList) { var entity = hit.HkHitInfo.Body.GetEntity(); if (entity != m_grid.Components && entity is MyCubeGrid) { var grid = entity as MyCubeGrid; invWorld = grid.PositionComp.GetWorldMatrixNormalizedInv(); pos = Vector3D.Transform(pt.ContactPosition, invWorld); normal = Vector3.TransformNormal(pt.ContactPoint.Normal, invWorld) * pt.ContactPointDirection; grid.Physics.ApplyDeformation(deformationOffset, softAreaPlanar * (m_grid.GridSizeEnum == grid.GridSizeEnum ? 1 : grid.GridSizeEnum == MyCubeSize.Large ? 2 : 0.25f), softAreaVertical * (m_grid.GridSizeEnum == grid.GridSizeEnum ? 1 : grid.GridSizeEnum == MyCubeSize.Large ? 2.5f : 0.2f), pos, normal, MyDamageType.Deformation, 0, grid.GridSizeEnum == MyCubeSize.Large ? 0.6f : 0.16f); } } m_hitList.Clear(); float explosionRadius = Math.Max(m_grid.GridSize, deformationOffset * (m_grid.GridSizeEnum == MyCubeSize.Large ? 0.25f : 0.05f)); if (explosionRadius > 0 && deformationOffset > m_grid.GridSize / 2 && destroyed) { var info = new ExplosionInfo() { Position = pt.ContactPosition, ExplosionType = MyExplosionTypeEnum.GRID_DESTRUCTION, Radius = explosionRadius, ModelDebris = destroyed, }; m_explosions.Add(info); } else { AddCollisionEffect(pt.ContactPosition, normal); } ProfilerShort.End(); }
private void PerformDeformation(ref HkBreakOffPointInfo pt, bool fromBreakParts, float separatingVelocity) { ProfilerShort.Begin("PerformDeformation"); Debug.Assert(Sync.IsServer, "Function PerformDeformation should not be called from client"); var mass = this.Mass; if (IsStatic) { mass = pt.CollidingBody.Mass; } float velocity = separatingVelocity; float deltaV = pt.BreakingImpulse / mass; // Calculate deformation offset float deformationOffset = 0.3f + Math.Max(0, (Math.Abs(velocity) - deltaV) / 15); deformationOffset *= 2; deformationOffset *= MyFakes.DEFORMATION_RATIO; const float maxDeformationHardLimit = 25; // Happens during copy pasting //Debug.Assert(deformationOffset < maxDeformationHardLimit, "Deformation is bigger than maximum."); deformationOffset = Math.Min(deformationOffset, maxDeformationHardLimit); float explosionRadius = Math.Max(m_grid.GridSize, deformationOffset); MyEntity otherEntity = pt.CollidingBody.GetEntity() as MyEntity; bool hitVoxel = otherEntity is MyVoxelMap; if (hitVoxel) { // Hardness from 0 to 1 float hardness = 0.0f; deformationOffset *= 1 + hardness; explosionRadius *= 1 - hardness; } float softAreaPlanar = m_grid.GridSizeEnum == MyCubeSize.Large ? 4 : 1.2f; // About 4 meters for large grid and 1.2m for small float softAreaVertical = 2 * deformationOffset; var invWorld = m_grid.PositionComp.GetWorldMatrixNormalizedInv(); var pos = Vector3D.Transform(pt.ContactPosition, invWorld); var normal = Vector3D.TransformNormal(pt.ContactPoint.Normal, invWorld) * pt.ContactPointDirection; bool destroyed = ApplyDeformation(deformationOffset, softAreaPlanar, softAreaVertical, pos, normal, MyDamageType.Deformation); if (explosionRadius > 0 && deformationOffset > m_grid.GridSize / 2 && destroyed) { var info = new ExplosionInfo() { Position = pt.ContactPosition, //ExplosionType = destroyed ? MyExplosionTypeEnum.GRID_DESTRUCTION : MyExplosionTypeEnum.GRID_DEFORMATION, ExplosionType = MyExplosionTypeEnum.GRID_DESTRUCTION, Radius = explosionRadius, ModelDebris = destroyed, }; m_explosions.Add(info); } else { //cannot be here since its onlyexecuted on server //AddCollisionEffect(pt.ContactPoint.Position, normal); } ProfilerShort.End(); }
private bool BreakAtPoint(ref HkBreakOffPointInfo pt, ref HkArrayUInt32 brokenKeysOut) { return true; }
private bool PerformDeformation(ref HkBreakOffPointInfo pt, bool fromBreakParts, float separatingVelocity, MyEntity otherEntity) { if (!m_grid.BlocksDestructionEnabled) return false; ProfilerShort.Begin("PerformDeformation"); Debug.Assert(Sync.IsServer, "Function PerformDeformation should not be called from client"); var mass = this.Mass; if (IsStatic) { mass = pt.CollidingBody.Mass; } float velocity = separatingVelocity; float deltaV = pt.BreakingImpulse / mass; // Calculate deformation offset float deformationOffset = 0.3f + Math.Max(0, (Math.Abs(velocity) - deltaV) / 15); deformationOffset *= 3; deformationOffset *= MyFakes.DEFORMATION_RATIO; const float maxDeformationHardLimit = 20; // Happens during copy pasting //Debug.Assert(deformationOffset < maxDeformationHardLimit, "Deformation is bigger than maximum."); deformationOffset = Math.Min(deformationOffset, maxDeformationHardLimit); float explosionRadius = Math.Max(m_grid.GridSize, deformationOffset); explosionRadius = Math.Min(explosionRadius, 10); bool hitVoxel = otherEntity is MyVoxelBase; if (hitVoxel) { // Hardness from 0 to 1 float hardness = 0.0f; deformationOffset *= 1 + hardness; explosionRadius *= 1 - hardness; } float softAreaPlanar = m_grid.GridSizeEnum == MyCubeSize.Large ? 4 : 1.2f; // About 4 meters for large grid and 1.2m for small float softAreaVertical = 1.5f * deformationOffset; var invWorld = m_grid.PositionComp.WorldMatrixNormalizedInv; var pos = Vector3D.Transform(pt.ContactPosition, invWorld); var velAtPoint = GetVelocityAtPoint(pt.ContactPosition); if (!velAtPoint.IsValid() || velAtPoint == Vector3.Zero) velAtPoint = pt.ContactPoint.Normal; var len = velAtPoint.Normalize(); Vector3 normal; if (len > 5) { normal = Vector3.TransformNormal(velAtPoint, invWorld) * pt.ContactPointDirection; normal.Normalize(); } else normal = pt.ContactPointDirection * pt.ContactPoint.Normal; int destroyed = ApplyDeformation(deformationOffset, softAreaPlanar, softAreaVertical, pos, normal, MyDamageType.Deformation, attackerId: otherEntity != null ? otherEntity.EntityId : 0); if (destroyed != 0) { if (len > 1) len = len / 10; RigidBody.ApplyPointImpulse(-velAtPoint *0.3f* Math.Min(destroyed * len * (Mass / 5), Mass * 5), pt.ContactPoint.Position); RigidBody.Gravity = Vector3.Zero; DisableGravity = 1; } if (explosionRadius > 0 && deformationOffset > m_grid.GridSize / 2 && destroyed != 0) { var info = new ExplosionInfo() { Position = pt.ContactPosition + pt.ContactPointDirection * pt.ContactPoint.Normal * explosionRadius * 0.5f, //ExplosionType = destroyed ? MyExplosionTypeEnum.GRID_DESTRUCTION : MyExplosionTypeEnum.GRID_DEFORMATION, ExplosionType = MyExplosionTypeEnum.GRID_DESTRUCTION, Radius = explosionRadius, ShowParticles = (otherEntity is MyVoxelPhysics) == false && (otherEntity is MyTrees) == false, GenerateDebris = true }; m_explosions.Add(info); } else { //cannot be here since its onlyexecuted on server //AddCollisionEffect(pt.ContactPoint.Position, normal); } ProfilerShort.End(); return destroyed != 0; }
private bool PerformDeformationOnGroup(MyEntity entity, MyEntity other, ref HkBreakOffPointInfo pt, float separatingVelocity) { bool destroyed = false; var group = MyWeldingGroups.Static.GetGroup((MyEntity)entity); if (group != null) { foreach (var node in group.Nodes) { if (node.NodeData.MarkedForClose) continue; m_tmpEntities.Add(node.NodeData); } foreach (var node in m_tmpEntities) { var gp = node.Physics as MyGridPhysics; if (gp == null || gp.Entity.PositionComp.WorldAABB.Contains(pt.ContactPosition) == ContainmentType.Disjoint) continue; destroyed |= gp.PerformDeformation(ref pt, false, separatingVelocity, other as MyEntity); } m_tmpEntities.Clear(); } return destroyed; }
private bool BreakAtPoint(ref HkBreakOffPointInfo pt, ref HkArrayUInt32 brokenKeysOut) { //if (pt.BreakingImpulse < Shape.BreakImpulse * 0.75f && MyUtils.GetRandomInt(3) != 0) //return false; if(RigidBody == null || pt.CollidingBody == null) { VRage.Trace.MyTrace.Send(VRage.Trace.TraceWindow.Analytics, string.Format("BreakAtPoint:Breaking body {0} null", RigidBody == null ? "A" : "B")); return false; } var separatingVelocity = Math.Abs(HkUtils.CalculateSeparatingVelocity(RigidBody, pt.CollidingBody, ref pt.ContactPoint)); //if (separatingVelocity < 2) // return false; var otherEntity = pt.CollidingBody.GetEntity(0); if (otherEntity is Sandbox.Game.WorldEnvironment.MyEnvironmentSector) //jn:HACK //ab:HACK return false; if (otherEntity.GetTopMostParent() == Entity) return false; pt.ContactPosition = ClusterToWorld(pt.ContactPoint.Position); var destroyed = PerformDeformationOnGroup((MyEntity)Entity, (MyEntity)otherEntity, ref pt, separatingVelocity); pt.ContactPointDirection *= -1; destroyed |= PerformDeformationOnGroup((MyEntity)otherEntity, (MyEntity)Entity, ref pt, separatingVelocity); return destroyed; }
private bool BreakAtPoint(ref HkBreakOffPointInfo pt, ref HkArrayUInt32 brokenKeysOut) { //if (pt.BreakingImpulse < Shape.BreakImpulse * 0.75f && MyUtils.GetRandomInt(3) != 0) //return false; if(RigidBody == null || pt.CollidingBody == null) { VRage.Trace.MyTrace.Send(VRage.Trace.TraceWindow.Analytics, string.Format("BreakAtPoint:Breaking body {0} null", RigidBody == null ? "A" : "B")); return false; } var separatingVelocity = Math.Abs(HkUtils.CalculateSeparatingVelocity(RigidBody, pt.CollidingBody, ref pt.ContactPoint)); if (Math.Abs(separatingVelocity) < 2) return false; var otherEntity = pt.CollidingBody.GetEntity(0); pt.ContactPosition = ClusterToWorld(pt.ContactPoint.Position); var destroyed = false; var group = MyWeldingGroups.Static.GetGroup((MyEntity)Entity); if (group != null) { foreach (var node in group.Nodes) { m_tmpEntities.Add(node.NodeData); } foreach (var node in m_tmpEntities) { if (node.MarkedForClose) continue; var gp = node.Physics as MyGridPhysics; if (gp == null) continue; destroyed |= gp.PerformDeformation(ref pt, false, separatingVelocity, otherEntity as MyEntity); } m_tmpEntities.Clear(); } group = MyWeldingGroups.Static.GetGroup((MyEntity)otherEntity); if (group != null) { foreach (var node in group.Nodes) { m_tmpEntities.Add(node.NodeData); } pt.ContactPointDirection *= -1; foreach (var node in m_tmpEntities) { if (node.MarkedForClose) continue; var gp = node.Physics as MyGridPhysics; if (gp == null) continue; destroyed |= gp.PerformDeformation(ref pt, false, separatingVelocity, Entity as MyEntity); } } return destroyed; }