//  Add new explosion to the list, but caller needs to start it using Start() method
        public static void AddExplosion(ref MyExplosionInfo explosionInfo, bool updateSync = true)
        {
            System.Diagnostics.Debug.Assert(explosionInfo.ExplosionSphere.Radius > 0);

            if (updateSync)
            {
                SyncObject.RequestExplosion(
                    explosionInfo.ExplosionSphere.Center, 
                    (float)explosionInfo.ExplosionSphere.Radius, 
                    explosionInfo.ExplosionType,
                    explosionInfo.VoxelExplosionCenter,
                    explosionInfo.ParticleScale
                    );
            }            
            
            m_explosionsWrite.Add(explosionInfo);            
        }
        //  Add new explosion to the list, but caller needs to start it using Start() method
        public static void AddExplosion(ref MyExplosionInfo explosionInfo, bool updateSync = true)
        {
            System.Diagnostics.Debug.Assert(explosionInfo.ExplosionSphere.Radius > 0);

            if (updateSync)
            {
                MyMultiplayer.RaiseStaticEvent(s => MyExplosions.ProxyExplosionRequest,
                    explosionInfo.ExplosionSphere.Center, 
                    (float)explosionInfo.ExplosionSphere.Radius, 
                    explosionInfo.ExplosionType,
                    explosionInfo.VoxelExplosionCenter,
                    explosionInfo.ParticleScale
                );
            }            
            
            m_explosionsWrite.Add(explosionInfo);            
        }
 private static void ProxyExplosionRequest(Vector3D center, float radius, MyExplosionTypeEnum type, Vector3D voxelCenter, float particleScale)
 {
     //Dont create explosion particles if message is bufferred, it is useless to create hundred explosion after scene load
     if (MySession.Static.Ready)
     {
         //  Create explosion
         MyExplosionInfo info = new MyExplosionInfo()
         {
             PlayerDamage = 0,
             //Damage = m_ammoProperties.Damage,
             Damage = 200,
             ExplosionType = type,
             ExplosionSphere = new BoundingSphere(center, radius),
             LifespanMiliseconds = MyExplosionsConstants.EXPLOSION_LIFESPAN,
             CascadeLevel = 0,
             HitEntity = null,
             ParticleScale = particleScale,
             OwnerEntity = null,
             Direction = Vector3.Forward,
             VoxelExplosionCenter = voxelCenter,
             ExplosionFlags = MyExplosionFlags.CREATE_DEBRIS | MyExplosionFlags.CREATE_DECALS | MyExplosionFlags.CREATE_PARTICLE_EFFECT | MyExplosionFlags.CREATE_SHRAPNELS,
             VoxelCutoutScale = 1.0f,
             PlaySound = true,
             ObjectsRemoveDelayInMiliseconds = 40
         };
         MyExplosions.AddExplosion(ref info, false);
     }
 }
        public override void Update()
        {
            base.Update();

            if (m_selfDestruct && MySandboxGame.TotalGamePlayTimeInMilliseconds >= m_selfDestructStartedInTime + SELF_DESTRUCT_TIME_MS)
            {
                MyAIComponent.Static.RemoveBot(AgentBot.Player.Id.SerialId, removeCharacter: true);

                var explosionSphere = new BoundingSphere(AgentBot.Player.GetPosition(), EXPLOSION_RADIUS);
                MyExplosionInfo info = new MyExplosionInfo()
                {
                    PlayerDamage = EXPLOSION_PLAYER_DAMAGE,
                    Damage = EXPLOSION_DAMAGE,
                    ExplosionType = MyExplosionTypeEnum.BOMB_EXPLOSION,
                    ExplosionSphere = explosionSphere,
                    LifespanMiliseconds = MyExplosionsConstants.EXPLOSION_LIFESPAN,
                    CascadeLevel = 0,
                    HitEntity = AgentBot.Player.Character,
                    ParticleScale = 0.5f,
                    OwnerEntity = AgentBot.Player.Character,
                    Direction = Vector3.Zero,
                    VoxelExplosionCenter = AgentBot.Player.Character.PositionComp.GetPosition(),// + 2 * WorldMatrix.Forward * 0.5f,
                    ExplosionFlags = MyExplosionFlags.AFFECT_VOXELS | MyExplosionFlags.APPLY_FORCE_AND_DAMAGE | MyExplosionFlags.CREATE_DEBRIS | MyExplosionFlags.CREATE_DECALS | MyExplosionFlags.CREATE_PARTICLE_EFFECT | MyExplosionFlags.CREATE_SHRAPNELS | MyExplosionFlags.APPLY_DEFORMATION,
                    VoxelCutoutScale = 0.6f,
                    PlaySound = true,
                    ApplyForceAndDamage = true,
                    ObjectsRemoveDelayInMiliseconds = 40
                };
                MyExplosions.AddExplosion(ref info);
            }

            var target = (AiTarget as MyCyberhoundTarget);
            Debug.Assert(target != null);
            if (AgentBot.Player.Character.UseNewAnimationSystem == false) // obsolete in new animation system
            {
                if ((!target.IsAttacking && !m_lastWasAttacking) && target.HasTarget()
                    && !target.PositionIsNearTarget(AgentBot.Player.Character.PositionComp.GetPosition(), 1.5f))
                {
                    if (AgentBot.Navigation.Stuck)
                    {
                        // correct aiming (aim in front of dog)
                        Vector3D houndPosition = AgentBot.Player.Character.PositionComp.GetPosition();
                        Vector3D gravity = MyGravityProviderSystem.CalculateNaturalGravityInPoint(houndPosition);
                        Vector3D aimingDirection = AgentBot.Player.Character.AimedPoint - houndPosition;
                        Vector3D newAimVector = aimingDirection -
                                                gravity*Vector3D.Dot(aimingDirection, gravity)/gravity.LengthSquared();
                        newAimVector.Normalize();
                        AgentBot.Navigation.AimAt(null, houndPosition + 100.0f*newAimVector);
                        // play idle animation
                        AgentBot.Player.Character.PlayCharacterAnimation("CyberhoundIdle1", MyBlendOption.Immediate,
                            MyFrameOption.Loop, 0);
                        AgentBot.Player.Character.DisableAnimationCommands();
                    }
                    else
                    {
                        AgentBot.Player.Character.EnableAnimationCommands();
                    }
                }
            }
            m_lastWasAttacking = target.IsAttacking;
        }
        public static void CreateExplosion(Vector3D position, float radius, int damage = 5000)
        {
            var explosionType = MyExplosionTypeEnum.WARHEAD_EXPLOSION_50;
            if (radius < 2)
                explosionType = MyExplosionTypeEnum.WARHEAD_EXPLOSION_02;
            else if (radius < 15)
                explosionType = MyExplosionTypeEnum.WARHEAD_EXPLOSION_15;
            else if (radius < 30)
                explosionType = MyExplosionTypeEnum.WARHEAD_EXPLOSION_30;

            //  Create explosion
            MyExplosionInfo info = new MyExplosionInfo
            {
                PlayerDamage = 0,
                Damage = damage,
                ExplosionType = explosionType,
                ExplosionSphere = new BoundingSphereD(position, radius),
                LifespanMiliseconds = MyExplosionsConstants.EXPLOSION_LIFESPAN,
                CascadeLevel = 0,
                ParticleScale = 1,
                Direction = Vector3.Down,
                VoxelExplosionCenter = position,
                ExplosionFlags = MyExplosionFlags.AFFECT_VOXELS |
                                    MyExplosionFlags.APPLY_FORCE_AND_DAMAGE |
                                    MyExplosionFlags.CREATE_DEBRIS |
                                    MyExplosionFlags.CREATE_DECALS |
                                    MyExplosionFlags.CREATE_PARTICLE_EFFECT |
                                    MyExplosionFlags.CREATE_SHRAPNELS |
                                    MyExplosionFlags.APPLY_DEFORMATION,
                VoxelCutoutScale = 1.0f,
                PlaySound = true,
                ApplyForceAndDamage = true,
                ObjectsRemoveDelayInMiliseconds = 40
            };
            MyExplosions.AddExplosion(ref info);
        }
        MyDamageInfo ApplyVolumetricExplosionOnGrid(ref MyExplosionInfo explosionInfo, ref BoundingSphereD sphere, List<MyEntity> entities)
        {
            Debug.Assert(Sandbox.Game.Multiplayer.Sync.IsServer, "This is supposed to be only server method");
            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionOnGrid");

            bool gridWasHit = false;

            HashSet<MySlimBlock> explodedBlocks = new HashSet<MySlimBlock>();
            Dictionary<MySlimBlock, float> damagedBlocks = new Dictionary<MySlimBlock, float>();
            HashSet<MyCubeGrid> explodedGrids = new HashSet<MyCubeGrid>();

            foreach (var entity in entities)
            {
                MyCubeGrid grid = entity as MyCubeGrid;
                if (grid != null && grid.CreatePhysics)
                {
                    explodedGrids.Add(grid);

                    var detectionHalfSize = grid.GridSize / 2 / 1.25f;
                    var invWorldGrid = MatrixD.Invert(grid.WorldMatrix);

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("GetBlocksInsideSpheres");
                    BoundingSphereD innerSphere = new BoundingSphereD(sphere.Center, (float)Math.Max(0.1f, sphere.Radius - grid.GridSize));
                    BoundingSphereD exactSphere = new BoundingSphereD(sphere.Center, sphere.Radius);
                    BoundingSphereD outerSphere = new BoundingSphereD(sphere.Center, sphere.Radius + grid.GridSize * 0.5f * (float)Math.Sqrt(3));
                    grid.GetBlocksInsideSpheres(
                        ref innerSphere,
                        ref exactSphere,
                        ref outerSphere,
                        m_explodedBlocksInner,
                        m_explodedBlocksExact,
                        m_explodedBlocksOuter,
                        false, detectionHalfSize, ref invWorldGrid);
                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    m_explodedBlocksInner.UnionWith(m_explodedBlocksExact);

                    explodedBlocks.UnionWith(m_explodedBlocksInner);

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("outerSphere2");

                    foreach (var cubeBlock in m_explodedBlocksOuter)
                    {
                        grid.Physics.AddDirtyBlock(cubeBlock);
                    }

                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    m_explodedBlocksInner.Clear();
                    m_explodedBlocksExact.Clear();
                    m_explodedBlocksOuter.Clear();

                    gridWasHit = true;
                }
            }
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

            var damage = new MyExplosionDamage(explodedBlocks, sphere, explosionInfo.Damage);
            

            var damageInfo = new MyDamageInfo
            {
                GridWasHit = gridWasHit,
                ExplosionDamage = damage,
                AffectedCubeBlocks = explodedBlocks,
                AffectedCubeGrids = explodedGrids,
                Sphere = sphere
            };

            return damageInfo;
        }
        void ApplyExplosionOnVoxel(ref MyExplosionInfo explosionInfo)   
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                return;
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionOnVoxel");

            if (explosionInfo.Damage > 0)
            {
                VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Voxel or collision");

                bool first = true;

                //  If explosion sphere intersects a voxel map, we need to cut out a sphere, spawn debrises, etc
                List<MyVoxelBase> voxelMaps = MySession.Static.VoxelMaps.GetAllOverlappingWithSphere(ref m_explosionSphere);
                voxelMaps.Sort(delegate(MyVoxelBase x, MyVoxelBase y) {
                    return y.GetOrePriority() - x.GetOrePriority();
                });

                foreach(var voxelMap in voxelMaps)
                {
                    // If the voxel is to be ignored.
                    if (voxelMap.GetOrePriority() == MyVoxelConstants.PRIORITY_IGNORE_EXTRACTION) continue;

                    bool createDebris = first; // We want to create debris

                    if (explosionInfo.HitEntity != null) // but not when we hit prefab
                    {
                        createDebris &= explosionInfo.HitEntity is MyVoxelBase;
                    }

                    createDebris &= explosionInfo.CreateDebris && (createDebris || explosionInfo.ForceDebris);

                    CutOutVoxelMap((float)m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale, explosionInfo.VoxelExplosionCenter, voxelMap, createDebris);

                    //Sync
                    voxelMap.RequestVoxelCutoutSphere(explosionInfo.VoxelExplosionCenter, (float)m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale, createDebris, false);

                    first = false;
                }
                VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
        // Doesn't get called anymore?
        bool ApplyExplosionOnGrid(ref MyExplosionInfo explosionInfo, ref BoundingSphereD sphere, List<MyEntity> entities)
        {
            Debug.Assert(Sandbox.Game.Multiplayer.Sync.IsServer, "This is supposed to be only server method");
            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionOnGrid");

            bool gridWasHit = false;
            foreach (var entity in entities)
            {
                MyCubeGrid grid = entity as MyCubeGrid;
                if (grid != null && grid.BlocksDestructionEnabled)
                {
                    var detectionHalfSize = grid.GridSize / 2 / 1.25f;
                    var invWorldGrid = MatrixD.Invert(grid.WorldMatrix);

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("GetBlocksInsideSpheres");
                    BoundingSphereD innerSphere = new BoundingSphereD(sphere.Center, (float)Math.Max(0.1f, sphere.Radius - grid.GridSize));
                    BoundingSphereD exactSphere = new BoundingSphereD(sphere.Center, sphere.Radius);
                    BoundingSphereD outerSphere = new BoundingSphereD(sphere.Center, sphere.Radius + grid.GridSize * 0.5f * (float)Math.Sqrt(3));
                    grid.GetBlocksInsideSpheres(
                        ref innerSphere,
                        ref exactSphere,
                        ref outerSphere,
                        m_explodedBlocksInner,
                        m_explodedBlocksExact,
                        m_explodedBlocksOuter, 
                        true, detectionHalfSize, ref invWorldGrid);
                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("foreach (var cubeBlock in m_explodedBlocks)");
                    foreach (var cubeBlock in m_explodedBlocksInner)
                    {
                        if (cubeBlock.FatBlock != null && cubeBlock.FatBlock.MarkedForClose)
                                continue;

                        if (cubeBlock.FatBlock != null)
                        {
                            grid.RemoveBlock(cubeBlock, updatePhysics: true);
                        }
                        else
                        {
                            grid.RemoveDestroyedBlock(cubeBlock);
                            grid.Physics.AddDirtyBlock(cubeBlock);
                        }
                    }
                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("GetBlocksInsideSphere outerSphere");
                    
                    foreach (var cubeBlock in m_explodedBlocksExact)
                    {
                        if ((cubeBlock.FatBlock != null) && cubeBlock.FatBlock.MarkedForClose)
                            continue;

                        if ((cubeBlock.FatBlock != null) && cubeBlock.FatBlock.MarkedToExplode)
                        {
                            grid.RemoveBlock(cubeBlock, updatePhysics: true);
                        }
                        else// if (MyVRageUtils.GetRandomFloat(0, 2) > 1)
                        {
                            grid.ApplyDestructionDeformation(cubeBlock);
                            grid.Physics.AddDirtyBlock(cubeBlock);
                        }
                        //else if (cubeBlock.FatBlock is IMyExplosiveObject)
                        //{
                        //    cubeBlock.OnDestroy();
                        //}
                    }
                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("outerSphere2");

                    foreach (var cubeBlock in m_explodedBlocksOuter)
                    {
                        grid.Physics.AddDirtyBlock(cubeBlock);
                    }

                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    m_explodedBlocksInner.Clear();
                    m_explodedBlocksExact.Clear();
                    m_explodedBlocksOuter.Clear();

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("AddDirtyArea");
                    
                    //Vector3 cornerVec = new Vector3(sphere.Radius + grid.GridSize / (float)grid.Skeleton.BoneDensity);
                    //BoundingBox box = new BoundingBox(sphere.Center - cornerVec, sphere.Center + cornerVec);

                    //var invee = Matrix.Invert(grid.WorldMatrix);
                    //box = box.Transform(ref invee);
                    //Vector3 min = box.Min;
                    //Vector3 max = box.Max;
                    //Vector3I start = new Vector3I((int)Math.Round(min.X / grid.GridSize), (int)Math.Round(min.Y / grid.GridSize), (int)Math.Round(min.Z / grid.GridSize));
                    //Vector3I end = new Vector3I((int)Math.Round(max.X / grid.GridSize), (int)Math.Round(max.Y / grid.GridSize), (int)Math.Round(max.Z / grid.GridSize));

                    //grid.Physics.AddDirtyArea(start, end);
                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("UpdateDirty");
                    grid.UpdateDirty();
                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("CreateExplosionDebris");
                    if (m_explosionInfo.HitEntity == grid)
                    {
                        BoundingBoxD aabb = BoundingBoxD.CreateFromSphere(new BoundingSphereD(sphere.Center, sphere.Radius * 1.5f));
                        MyDebris.Static.CreateExplosionDebris(ref sphere, grid, ref aabb, 0.5f, false);
                    }

                    VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

                    gridWasHit = true;
                }
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
            return gridWasHit;
        }
 // Doesn't get called anymore?
 private void ApplyExplosionOnEntities(ref MyExplosionInfo m_explosionInfo,List<MyEntity> entities)
 {
     Debug.Assert(Sync.IsServer);
     foreach (var entity in entities)
     {
         if (!(entity is IMyDestroyableObject))
             continue;
         float damage;
         if (entity is MyCharacter)
             damage = m_explosionInfo.PlayerDamage;
         else
             damage = m_explosionInfo.Damage;
         if (damage == 0)
             continue;
         var destroyableObj = entity as IMyDestroyableObject;
         destroyableObj.DoDamage(damage, MyDamageType.Explosion, true, attackerId: m_explosionInfo.OwnerEntity != null ? m_explosionInfo.OwnerEntity.EntityId : 0);
     }
 }
        private void ApplyVolumetricExplosionOnEntities(ref MyExplosionInfo m_explosionInfo, List<MyEntity> entities, MyDamageInfo explosionDamageInfo)
        {
            Debug.Assert(Sync.IsServer);
            foreach (var entity in entities)
            {
                //Special case for characters in cockpits
                var character = entity as MyCharacter;
                if (character != null)
                {
                    var cockpit = character.IsUsing as MyCockpit;
                    if (cockpit != null)
                    {
                        if (explosionDamageInfo.ExplosionDamage.DamagedBlocks.ContainsKey(cockpit.SlimBlock))
                        {
                            float damageRemaining = explosionDamageInfo.ExplosionDamage.DamageRemaining[cockpit.SlimBlock].DamageRemaining;
                            character.DoDamage(damageRemaining, MyDamageType.Explosion, true, attackerId: m_explosionInfo.OwnerEntity != null ? m_explosionInfo.OwnerEntity.EntityId : 0);
                        }
                        continue;
                    }
                }

                var raycastDamageInfo = explosionDamageInfo.ExplosionDamage.ComputeDamageForEntity(entity.PositionComp.WorldAABB.Center);
                float damage = raycastDamageInfo.DamageRemaining;

                float entityDistanceToExplosion = (float)(entity.PositionComp.WorldAABB.Center - explosionDamageInfo.Sphere.Center).Length();
                damage *= (float)(1 - (entityDistanceToExplosion - raycastDamageInfo.DistanceToExplosion) / (explosionDamageInfo.Sphere.Radius - raycastDamageInfo.DistanceToExplosion));

                if (damage <= 0f)
                    continue;

                if (entity.Physics != null && entity.Physics.Enabled)
                {
                    var ammoBase = entity as MyAmmoBase;
                    if (ammoBase != null)
                    {
                        if (Vector3.DistanceSquared(m_explosionSphere.Center, ammoBase.PositionComp.GetPosition()) < 4 * m_explosionSphere.Radius * m_explosionSphere.Radius)
                        {
                            ammoBase.MarkedToDestroy = true;
                        }
                        ammoBase.Explode();
                    }

                    float forceMultiplier = damage / 50000f;

                    //  Throws surrounding objects away from centre of the explosion.
                    if (m_explosionInfo.ApplyForceAndDamage)
                    {
                        m_explosionInfo.StrengthImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_IMPULSE * (float)m_explosionSphere.Radius;
                        m_explosionInfo.StrengthAngularImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_ANGULAR_IMPULSE;
                        m_explosionInfo.HitEntity = m_explosionInfo.HitEntity != null ? m_explosionInfo.HitEntity.GetBaseEntity() : null;

                        VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionForceAndDamage");

                        if (entity.PositionComp.WorldAABB.Center != m_explosionSphere.Center)
                        {
                            entity.Physics.AddForce(
                                MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE,
                                forceMultiplier * m_explosionInfo.StrengthImpulse * Vector3.Normalize(entity.PositionComp.WorldAABB.Center - m_explosionSphere.Center),
                                entity.PositionComp.WorldAABB.Center,
                                null);
                        }

                        VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
                    }
                }

                if (!(entity is IMyDestroyableObject))
                    continue;
                
                var destroyableObj = entity as IMyDestroyableObject;
                destroyableObj.DoDamage(damage, MyDamageType.Explosion, true, attackerId: m_explosionInfo.OwnerEntity != null ? m_explosionInfo.OwnerEntity.EntityId : 0);
            }
        }
        private bool ApplyVolumetricExplosion(ref MyExplosionInfo m_explosionInfo, ref BoundingSphereD influenceExplosionSphere, List<MyEntity> entities)
        {
            bool gridWasHit = false;

            ApplyExplosionOnVoxel(ref m_explosionInfo);

            var damageInfo = ApplyVolumetricExplosionOnGrid(ref m_explosionInfo, ref influenceExplosionSphere, entities);
            if ((m_explosionInfo.ExplosionFlags & MyExplosionFlags.APPLY_DEFORMATION) == MyExplosionFlags.APPLY_DEFORMATION)
            {
                damageInfo.ExplosionDamage.ComputeDamagedBlocks();
                gridWasHit = damageInfo.GridWasHit;
                ApplyVolumetriDamageToGrid(damageInfo, m_explosionInfo.OwnerEntity != null ? m_explosionInfo.OwnerEntity.EntityId : 0);
            }

            if (m_explosionInfo.HitEntity is MyWarhead)
            {
                var warhead = (m_explosionInfo.HitEntity as MyWarhead).SlimBlock;
                if (!warhead.CubeGrid.BlocksDestructionEnabled)
                {
                    warhead.CubeGrid.RemoveDestroyedBlock(warhead);
                    foreach (var neighbour in warhead.Neighbours)
                    {
                        neighbour.CubeGrid.Physics.AddDirtyBlock(neighbour);
                    }
                    warhead.CubeGrid.Physics.AddDirtyBlock(warhead);
                }
            }
            ApplyVolumetricExplosionOnEntities(ref m_explosionInfo, entities, damageInfo);

            entities.Clear();
            return gridWasHit;
        }
        // Doesn't get called anymore?
        private bool ApplyExplosion(ref MyExplosionInfo m_explosionInfo, ref BoundingSphereD influenceExplosionSphere, List<MyEntity> entities)
        {
            bool gridWasHit = false;

            ApplyExplosionOnVoxel(ref m_explosionInfo);

            ApplyExplosionOnEntities(ref m_explosionInfo, entities);

            if (((m_explosionInfo.ExplosionFlags & MyExplosionFlags.APPLY_DEFORMATION) == MyExplosionFlags.APPLY_DEFORMATION))
            {
                gridWasHit = ApplyExplosionOnGrid(ref m_explosionInfo, ref influenceExplosionSphere, entities);
            }

            entities.Clear();


            //  Throws surrounding objects away from centre of the explosion.
            if (m_explosionInfo.ApplyForceAndDamage)
            {
                m_explosionInfo.StrengthImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_IMPULSE * (float)m_explosionSphere.Radius;
                m_explosionInfo.StrengthAngularImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_ANGULAR_IMPULSE;
                m_explosionInfo.HitEntity = m_explosionInfo.HitEntity != null ? m_explosionInfo.HitEntity.GetBaseEntity() : null;

                VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionForceAndDamage");
                //MyEntities.ApplyExplosionForceAndDamage(ref explosionInfo);


                for (int s = 0; s < m_explosionForceSlices.Length; s++)
                {
                    BoundingSphereD forceImpactSphere = m_explosionSphere;
                    forceImpactSphere.Radius *= m_explosionForceSlices[s].X;
                    entities = MyEntities.GetEntitiesInSphere(ref forceImpactSphere);

                    foreach (var entity in entities)
                    {
                        if (!m_pushedEntities.Contains(entity))
                        {
                            if (entity.PositionComp.WorldAABB.Center != m_explosionSphere.Center)
                            {
                                if (entity.Physics != null && entity.Physics.Enabled)
                                {
                                    entity.Physics.AddForce(
                                        MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE,
                                        m_explosionForceSlices[s].Y * m_explosionInfo.StrengthImpulse * Vector3.Normalize(entity.PositionComp.WorldAABB.Center - m_explosionSphere.Center),
                                        entity.PositionComp.WorldAABB.Center,
                                        null);
                                }
                            }
                            m_pushedEntities.Add(entity);

                            if (entity.Physics != null && entity.Physics.Enabled)
                            {
                                var character = entity as Sandbox.Game.Entities.Character.MyCharacter;
                                if (character != null && !(character.IsUsing is MyCockpit))
                                {
                                    character.DoDamage(m_explosionInfo.Damage * m_explosionForceSlices[s].Y, MyDamageType.Explosion, true, m_explosionInfo.OwnerEntity != null ? m_explosionInfo.OwnerEntity.EntityId : 0);
                                }

                                var ammoBase = entity as MyAmmoBase;
                                if (ammoBase != null)
                                {
                                    if (Vector3.DistanceSquared(m_explosionSphere.Center, ammoBase.PositionComp.GetPosition()) < 4 * m_explosionSphere.Radius * m_explosionSphere.Radius)
                                    {
                                        ammoBase.MarkedToDestroy = true;
                                    }
                                    ammoBase.Explode();
                                }
                            }
                        }
                    }

                    entities.Clear();
                }

                m_pushedEntities.Clear();
                VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
            }
            return gridWasHit;
        }
        public void Start(MyExplosionInfo explosionInfo)
        {
            MyDebug.AssertDebug(explosionInfo.ExplosionSphere.Radius > 0);

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("MyExplosion.Start");

            m_explosionInfo = explosionInfo;
            ElapsedMiliseconds = 0;

            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
        void ApplyExplosionOnVoxel(ref MyExplosionInfo explosionInfo)
        {
            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionOnVoxel");

            if (explosionInfo.Damage > 0)
            {
                VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Voxel or collision");

                //  If explosion sphere intersects a voxel map, we need to cut out a sphere, spawn debrises, etc
                MyVoxelBase voxelMap = explosionInfo.AffectVoxels ? MySession.Static.VoxelMaps.GetOverlappingWithSphere(ref m_explosionSphere) : null;
                if (voxelMap != null)
                {
                    bool createDebris = true; // We want to create debris

                    if (explosionInfo.HitEntity != null) // but not when we hit prefab
                    {
                        createDebris &= explosionInfo.HitEntity is MyVoxelMap;
                    }

                    createDebris &= explosionInfo.CreateDebris && (createDebris || explosionInfo.ForceDebris);

                    CutOutVoxelMap((float)m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale, explosionInfo.VoxelExplosionCenter, voxelMap, createDebris);

                    //Sync
                    voxelMap.SyncObject.RequestVoxelCutoutSphere(explosionInfo.VoxelExplosionCenter, (float)m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale, createDebris);
                }
                VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
Exemple #15
0
        void ApplyExplosionOnVoxel(ref MyExplosionInfo explosionInfo)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                return;
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyExplosionOnVoxel");

            if (explosionInfo.Damage > 0)
            {
                VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Voxel or collision");

                bool first = true;

                //  If explosion sphere intersects a voxel map, we need to cut out a sphere, spawn debrises, etc
                List<MyVoxelBase> voxelMaps = MySession.Static.VoxelMaps.GetAllOverlappingWithSphere(ref m_explosionSphere);

                for (int i = voxelMaps.Count - 1; i > 0; --i)
                {
                    m_VoxelsToCutTmp.Add(voxelMaps[i].RootVoxel);
                }

                foreach (var voxelMap in m_VoxelsToCutTmp)
                {
                    bool createDebris = first; // We want to create debris
                    /*
                    if (explosionInfo.HitEntity != null) // but not when we hit prefab
                    {
                        createDebris &= explosionInfo.HitEntity is MyVoxelBase;
                    }*/

                    createDebris &= explosionInfo.CreateDebris && (createDebris || explosionInfo.ForceDebris);

                    CutOutVoxelMap((float)m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale, explosionInfo.VoxelExplosionCenter, voxelMap, createDebris);

                    //Sync
                    voxelMap.RequestVoxelCutoutSphere(explosionInfo.VoxelExplosionCenter, (float)m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale, createDebris, false);

                    first = false;
                }

                m_VoxelsToCutTmp.Clear();
                VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }