public virtual void FracturedBody_AfterReplaceBody(ref HkdReplaceBodyEvent e) { System.Diagnostics.Debug.Assert(Sync.IsServer, "Client must not simulate destructions"); if (!Sandbox.Game.Multiplayer.Sync.IsServer) return; ProfilerShort.Begin("DestructionFracture.AfterReplaceBody"); Debug.Assert(BreakableBody != null); e.GetNewBodies(m_tmpLst); if (m_tmpLst.Count == 0)// || e.OldBody != DestructionBody) { ProfilerShort.End(); return; } MyPhysics.RemoveDestructions(RigidBody); foreach (var b in m_tmpLst) { var bBody = MyFracturedPiecesManager.Static.GetBreakableBody(b); MatrixD m = bBody.GetRigidBody().GetRigidBodyMatrix(); m.Translation = ClusterToWorld(m.Translation); var piece = MyDestructionHelper.CreateFracturePiece(bBody, ref m, (Entity as MyFracturedPiece).OriginalBlocks); if (piece == null) { MyFracturedPiecesManager.Static.ReturnToPool(bBody); continue; } } m_tmpLst.Clear(); BreakableBody.AfterReplaceBody -= FracturedBody_AfterReplaceBody; MyFracturedPiecesManager.Static.RemoveFracturePiece(Entity as MyFracturedPiece, 0); ProfilerShort.End(); }
public override void FracturedBody_AfterReplaceBody(ref HkdReplaceBodyEvent e) { if (!MyFakes.ENABLE_AFTER_REPLACE_BODY) return; System.Diagnostics.Debug.Assert(Sync.IsServer, "Client must not simulate destructions"); if (!Sync.IsServer) return; Debug.Assert(!m_recreateBody, "Only one destruction per entity per frame"); if (m_recreateBody) return; ProfilerShort.Begin("DestructionFracture.AfterReplaceBody"); HavokWorld.DestructionWorld.RemoveBreakableBody(e.OldBody); // To remove from HkpWorld rigidBodies list m_oldLinVel = RigidBody.LinearVelocity; m_oldAngVel = RigidBody.AngularVelocity; MyPhysics.RemoveDestructions(RigidBody); e.GetNewBodies(m_newBodies); if (m_newBodies.Count == 0)// || e.OldBody != DestructionBody) { ProfilerShort.End(); return; } bool createdEffect = false; m_tmpBlocksToDelete.Clear(); m_tmpBlocksUpdateDamage.Clear(); MySlimBlock destructionSoundBlock = null; ProfilerShort.Begin("ProcessBodies"); foreach (var b in m_newBodies) { if (!b.IsFracture() || (MyFakes.ENABLE_FRACTURE_COMPONENT && m_grid.BlocksCount == 1 && m_grid.IsStatic && MyDestructionHelper.IsFixed(b))) { m_newBreakableBodies.Add(MyFracturedPiecesManager.Static.GetBreakableBody(b)); ProfilerShort.Begin("FindFracturedBlocks"); FindFracturedBlocks(b); ProfilerShort.BeginNextBlock("RemoveBBfromWorld"); HavokWorld.DestructionWorld.RemoveBreakableBody(b); ProfilerShort.End(); } else { ProfilerShort.Begin("CreateFracture"); var bBody = MyFracturedPiecesManager.Static.GetBreakableBody(b); var bodyMatrix = bBody.GetRigidBody().GetRigidBodyMatrix(); var pos = ClusterToWorld(bodyMatrix.Translation); MySlimBlock cb; var shape = bBody.BreakableShape; ProfilerShort.Begin("Properties"); HkVec3IProperty prop = shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); if (!prop.IsValid() && shape.IsCompound()) //TODO: this is last block in grid and is fractured { //its compound of childs of our block shape that has position prop, prop = shape.GetChild(0).Shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); } ProfilerShort.End(); Debug.Assert(prop.IsValid()); bool removePiece = false; cb = m_grid.GetCubeBlock(prop.Value); MyCompoundCubeBlock compoundBlock = cb != null ? cb.FatBlock as MyCompoundCubeBlock : null; if (cb != null) { if (destructionSoundBlock == null) destructionSoundBlock = cb; if (!createdEffect) { ProfilerShort.Begin("CreateParticle"); AddDestructionEffect(m_grid.GridIntegerToWorld(cb.Position), Vector3.Down); createdEffect = true; ProfilerShort.End(); } MatrixD m = bodyMatrix; m.Translation = pos; MyFracturedPiece fp = null; if (MyFakes.ENABLE_FRACTURE_COMPONENT) { // Get compound ids Debug.Assert(m_tmpCompoundIds.Count == 0); HkSimpleValueProperty compoundIdProperty = shape.GetProperty(HkdBreakableShape.PROPERTY_BLOCK_COMPOUND_ID); if (compoundIdProperty.IsValid()) { m_tmpCompoundIds.Add((ushort)compoundIdProperty.ValueUInt); } else if (!compoundIdProperty.IsValid() && shape.IsCompound()) { m_tmpChildren_CompoundIds.Clear(); shape.GetChildren(m_tmpChildren_CompoundIds); foreach (var child in m_tmpChildren_CompoundIds) { HkSimpleValueProperty compoundIdChildProperty = child.Shape.GetProperty(HkdBreakableShape.PROPERTY_BLOCK_COMPOUND_ID); if (compoundIdChildProperty.IsValid()) m_tmpCompoundIds.Add((ushort)compoundIdChildProperty.ValueUInt); } } // Remove shapes bool fracturePieceValid = true; if (m_tmpCompoundIds.Count > 0) { Debug.Assert(m_tmpDefinitions.Count == 0); Debug.Assert(compoundBlock != null); foreach (var compoundId in m_tmpCompoundIds) { var blockInCompound = compoundBlock.GetBlock(compoundId); if (blockInCompound == null) { fracturePieceValid = false; continue; } m_tmpDefinitions.Add(blockInCompound.BlockDefinition.Id); fracturePieceValid &= RemoveShapesFromFracturedBlocks(bBody, blockInCompound, compoundId, m_tmpBlocksToDelete, m_tmpBlocksUpdateDamage); } } else { Debug.Assert(compoundBlock == null); m_tmpDefinitions.Add(cb.BlockDefinition.Id); fracturePieceValid = RemoveShapesFromFracturedBlocks(bBody, cb, null, m_tmpBlocksToDelete, m_tmpBlocksUpdateDamage); } // Test invalid shapes (from block which has been removed from grid). Debug.Assert(fracturePieceValid); if (fracturePieceValid) { fp = MyDestructionHelper.CreateFracturePiece(bBody, ref m, m_tmpDefinitions, compoundBlock != null ? compoundBlock : cb.FatBlock); if (fp == null) removePiece = true; } else { removePiece = true; } m_tmpChildren_CompoundIds.Clear(); m_tmpCompoundIds.Clear(); m_tmpDefinitions.Clear(); } else { fp = MyDestructionHelper.CreateFracturePiece(bBody, ref m, null, compoundBlock != null ? compoundBlock : cb.FatBlock); if (fp == null) removePiece = true; } } else { //Debug.Fail("Fracture piece missing block!");//safe to ignore removePiece = true; } if (removePiece) { HavokWorld.DestructionWorld.RemoveBreakableBody(b); MyFracturedPiecesManager.Static.ReturnToPool(bBody); } ProfilerShort.End(); } } m_newBodies.Clear(); bool oldGeneratorsEnabled = m_grid.EnableGenerators(false); if (destructionSoundBlock != null) MyAudioComponent.PlayDestructionSound(destructionSoundBlock); if (MyFakes.ENABLE_FRACTURE_COMPONENT) { // Cache blocks with fracture components FindFractureComponentBlocks(); // Remove blocks from blocksToDelete which are marked for creating fracture component. foreach (var info in m_fractureBlockComponentsCache) m_tmpBlocksToDelete.Remove(((MyCubeBlock)info.Entity).SlimBlock); // Remove blocks from update collection when the block is also in delete colection. foreach (var blockToDelete in m_tmpBlocksToDelete) m_tmpBlocksUpdateDamage.Remove(blockToDelete); // Delete blocks foreach (var cb in m_tmpBlocksToDelete) { // Update deleted blocks destruction damage for multiblocks if (cb.IsMultiBlockPart) { var multiBlockInfo = cb.CubeGrid.GetMultiBlockInfo(cb.MultiBlockId); // Only apply damage if there is some other block in multiblock. if (multiBlockInfo != null && multiBlockInfo.Blocks.Count > 1) { var fractureComponent = cb.GetFractureComponent(); if (fractureComponent != null) cb.ApplyDestructionDamage(0f); } } if (cb.FatBlock != null) cb.FatBlock.OnDestroy(); m_grid.RemoveBlockWithId(cb, true); } // Update blocks destruction damage foreach (var cb in m_tmpBlocksUpdateDamage) { var fractureComponent = cb.GetFractureComponent(); if (fractureComponent != null) cb.ApplyDestructionDamage(fractureComponent.GetIntegrityRatioFromFracturedPieceCounts()); } } else { foreach (var cb in m_tmpBlocksToDelete) { var b = m_grid.GetCubeBlock(cb.Position); if (b != null) { if (b.FatBlock != null) b.FatBlock.OnDestroy(); m_grid.RemoveBlock(b, true); } } } m_grid.EnableGenerators(oldGeneratorsEnabled); m_tmpBlocksToDelete.Clear(); m_tmpBlocksUpdateDamage.Clear(); ProfilerShort.End(); //SplitGrid(e); m_recreateBody = true; ProfilerShort.End(); }
void DestructionBody_AfterReplaceBody(ref HkdReplaceBodyEvent e) { e.GetNewBodies(m_tmpBodyInfos); foreach (var b in m_tmpBodyInfos) { var m = b.Body.GetRigidBody().GetRigidBodyMatrix(); var t = m.Translation; var o = Quaternion.CreateFromRotationMatrix(m.GetOrientation()); Physics.HavokWorld.GetPenetrationsShape(b.Body.BreakableShape.GetShape(), ref t, ref o, m_tmpResults, MyPhysics.DefaultCollisionLayer); foreach (var res in m_tmpResults) { if (res.GetCollisionEntity() is MyVoxelMap) { b.Body.GetRigidBody().Quality = HkCollidableQualityType.Fixed; break; } } m_tmpResults.Clear(); b.Body.GetRigidBody(); b.Body.Dispose(); } }
public override void FracturedBody_AfterReplaceBody(ref HkdReplaceBodyEvent e) { if (!MyFakes.ENABLE_AFTER_REPLACE_BODY) return; System.Diagnostics.Debug.Assert(Sync.IsServer, "Client must not simulate destructions"); if (!Sync.IsServer) return; Debug.Assert(!m_recreateBody, "Only one destruction per entity per frame"); if (m_recreateBody) return; ProfilerShort.Begin("DestructionFracture.AfterReplaceBody"); HavokWorld.DestructionWorld.RemoveBreakableBody(e.OldBody); // To remove from HkpWorld rigidBodies list m_oldLinVel = RigidBody.LinearVelocity; m_oldAngVel = RigidBody.AngularVelocity; MyPhysics.RemoveDestructions(RigidBody); e.GetNewBodies(m_newBodies); if (m_newBodies.Count == 0)// || e.OldBody != DestructionBody) return; bool createdEffect = false; var lst = new List<MySlimBlock>(); ProfilerShort.Begin("ProcessBodies"); foreach (var b in m_newBodies) { if (!b.IsFracture())// && m_grid.BlocksCount > 1)// || !IsFracture(b.Body.BreakableShape)) { m_newBreakableBodies.Add(MyFracturedPiecesManager.Static.GetBreakableBody(b)); ProfilerShort.Begin("FindFracturedBlocks"); FindFracturedBlocks(b); ProfilerShort.BeginNextBlock("RemoveBBfromWorld"); HavokWorld.DestructionWorld.RemoveBreakableBody(b); ProfilerShort.End(); } else { ProfilerShort.Begin("CreateFracture"); var bBody = MyFracturedPiecesManager.Static.GetBreakableBody(b); var bodyMatrix = bBody.GetRigidBody().GetRigidBodyMatrix(); var pos = ClusterToWorld(bodyMatrix.Translation); MySlimBlock cb; var shape = bBody.BreakableShape; ProfilerShort.Begin("GetPositionProp"); HkVec3IProperty prop = shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); if (!prop.IsValid() && shape.IsCompound()) //TODO: this is last block in grid and is fractured { //its compound of childs of our block shape that has position prop, prop = shape.GetChild(0).Shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); } ProfilerShort.End(); Debug.Assert(prop.IsValid()); bool removePiece = false; cb = m_grid.GetCubeBlock(prop.Value); if (cb != null) { if (!createdEffect) { ProfilerShort.Begin("CreateParticle"); AddDestructionEffect(m_grid.GridIntegerToWorld(cb.Position), Vector3.Down); createdEffect = true; ProfilerShort.End(); } if (!lst.Contains(cb)) { lst.Add(cb); } MatrixD m = bodyMatrix; m.Translation = pos; MyFracturedPiece fp = null; fp = MyDestructionHelper.CreateFracturePiece(bBody, ref m, null, cb.FatBlock); if (fp == null) { removePiece = true; } } else { //Debug.Fail("Fracture piece missing block!");//safe to ignore removePiece = true; } if (removePiece) { HavokWorld.DestructionWorld.RemoveBreakableBody(b); MyFracturedPiecesManager.Static.ReturnToPool(bBody); } ProfilerShort.End(); } } m_newBodies.Clear(); m_grid.EnableGenerators(false); bool first = true; foreach (var cb in lst) { var b = m_grid.GetCubeBlock(cb.Position); if ( b!= null) { if(b.FatBlock != null) b.FatBlock.OnDestroy(); m_grid.RemoveBlock(b, true); if(first) { PlayDestructionSound(b); first = false; } } } m_grid.EnableGenerators(true); ProfilerShort.End(); //SplitGrid(e); m_recreateBody = true; ProfilerShort.End(); }
public override void FracturedBody_AfterReplaceBody(ref HkdReplaceBodyEvent e) { if (!MyFakes.ENABLE_AFTER_REPLACE_BODY) return; System.Diagnostics.Debug.Assert(Sync.IsServer, "Client must not simulate destructions"); if (!Sync.IsServer) return; Debug.Assert(!m_recreateBody, "Only one destruction per entity per frame"); if (m_recreateBody) return; ProfilerShort.Begin("DestructionFracture.AfterReplaceBody"); HavokWorld.DestructionWorld.RemoveBreakableBody(e.OldBody); // To remove from HkpWorld rigidBodies list m_oldLinVel = RigidBody.LinearVelocity; m_oldAngVel = RigidBody.AngularVelocity; MyPhysics.RemoveDestructions(RigidBody); e.GetNewBodies(m_newBodies); if (m_newBodies.Count == 0)// || e.OldBody != DestructionBody) return; bool createdEffect = false; var blocksToDelete = new HashSet<MySlimBlock>(); MySlimBlock destructionSoundBlock = null; ProfilerShort.Begin("ProcessBodies"); foreach (var b in m_newBodies) { if (!b.IsFracture())// && m_grid.BlocksCount > 1)// || !IsFracture(b.Body.BreakableShape)) { m_newBreakableBodies.Add(MyFracturedPiecesManager.Static.GetBreakableBody(b)); ProfilerShort.Begin("FindFracturedBlocks"); FindFracturedBlocks(b); ProfilerShort.BeginNextBlock("RemoveBBfromWorld"); HavokWorld.DestructionWorld.RemoveBreakableBody(b); ProfilerShort.End(); } else { ProfilerShort.Begin("CreateFracture"); var bBody = MyFracturedPiecesManager.Static.GetBreakableBody(b); var bodyMatrix = bBody.GetRigidBody().GetRigidBodyMatrix(); var pos = ClusterToWorld(bodyMatrix.Translation); MySlimBlock cb; var shape = bBody.BreakableShape; ProfilerShort.Begin("Properties"); HkVec3IProperty prop = shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); if (!prop.IsValid() && shape.IsCompound()) //TODO: this is last block in grid and is fractured { //its compound of childs of our block shape that has position prop, prop = shape.GetChild(0).Shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); } // Block id in compound. ushort? compoundId = null; if (MyFakes.ENABLE_FRACTURE_COMPONENT) { HkSimpleValueProperty compoundIdProperty = shape.GetProperty(HkdBreakableShape.PROPERTY_BLOCK_COMPOUND_ID); if (!compoundIdProperty.IsValid() && shape.IsCompound()) compoundIdProperty = shape.GetChild(0).Shape.GetProperty(HkdBreakableShape.PROPERTY_BLOCK_COMPOUND_ID); if (compoundIdProperty.IsValid()) compoundId = (ushort)compoundIdProperty.ValueUInt; } ProfilerShort.End(); Debug.Assert(prop.IsValid()); bool removePiece = false; cb = m_grid.GetCubeBlock(prop.Value); if (MyFakes.ENABLE_FRACTURE_COMPONENT && cb != null) { // Prepare block from compound MyCompoundCubeBlock compoundBlock = cb.FatBlock as MyCompoundCubeBlock; if (compoundBlock != null) { if (compoundId != null) { var blockInCompound = compoundBlock.GetBlock(compoundId.Value); if (blockInCompound != null) { cb = blockInCompound; } else { Debug.Fail("Block with the BlockId not found in compound"); cb = null; } } else { Debug.Fail("CompoundId not set to internal block in compound"); cb = null; } } else { Debug.Assert(compoundId == null, "CompoundId set to block which is not in compound"); } } if (cb != null) { if (destructionSoundBlock == null) destructionSoundBlock = cb; if (!createdEffect) { ProfilerShort.Begin("CreateParticle"); AddDestructionEffect(m_grid.GridIntegerToWorld(cb.Position), Vector3.Down); createdEffect = true; ProfilerShort.End(); } MatrixD m = bodyMatrix; m.Translation = pos; MyFracturedPiece fp = null; fp = MyDestructionHelper.CreateFracturePiece(bBody, ref m, null, cb.FatBlock); if (fp == null) { removePiece = true; } if (MyFakes.ENABLE_FRACTURE_COMPONENT && cb.FatBlock.Components.Has<MyFractureComponentBase>()) { // Block can be removed when the removed shape is the last one! MyFractureComponentCubeBlock fractureComponent = cb.GetFractureComponent(); if (fractureComponent != null) { var bShape = bBody.BreakableShape; if (IsBreakableShapeCompound(bShape)) { m_tmpShapeNames.Clear(); m_tmpChildren_RemoveShapes.Clear(); bShape.GetChildren(m_tmpChildren_RemoveShapes); m_tmpChildren_RemoveShapes.ForEach(c => m_tmpShapeNames.Add(c.ShapeName)); // Remove on server. fractureComponent.RemoveChildShapes(m_tmpShapeNames); MySyncDestructions.RemoveShapesFromFractureComponent(cb.CubeGrid.EntityId, cb.Position, compoundId ?? 0xFFFF, m_tmpShapeNames); m_tmpChildren_RemoveShapes.Clear(); m_tmpShapeNames.Clear(); } else { var name = bBody.BreakableShape.Name; // Remove on server. fractureComponent.RemoveChildShapes(new string[] { name }); MySyncDestructions.RemoveShapeFromFractureComponent(cb.CubeGrid.EntityId, cb.Position, compoundId ?? 0xFFFF, name); } } } else { blocksToDelete.Add(cb); } } else { //Debug.Fail("Fracture piece missing block!");//safe to ignore removePiece = true; } if (removePiece) { HavokWorld.DestructionWorld.RemoveBreakableBody(b); MyFracturedPiecesManager.Static.ReturnToPool(bBody); } ProfilerShort.End(); } } m_newBodies.Clear(); bool oldGeneratorsEnabled = m_grid.EnableGenerators(false); if (destructionSoundBlock != null) MyAudioComponent.PlayDestructionSound(destructionSoundBlock); if (MyFakes.ENABLE_FRACTURE_COMPONENT) { // Remove blocks from blocksToDelete which are marked for creating fracture component. m_fractureBlockComponentsCache.ForEach(info => blocksToDelete.Remove(((MyCubeBlock)info.Entity).SlimBlock)); foreach (var cb in blocksToDelete) { if (cb.FatBlock != null) cb.FatBlock.OnDestroy(); m_grid.RemoveBlockWithId(cb, true); } } else { foreach (var cb in blocksToDelete) { var b = m_grid.GetCubeBlock(cb.Position); if (b != null) { if (b.FatBlock != null) b.FatBlock.OnDestroy(); m_grid.RemoveBlock(b, true); } } } m_grid.EnableGenerators(oldGeneratorsEnabled); ProfilerShort.End(); //SplitGrid(e); m_recreateBody = true; ProfilerShort.End(); }