private void ApplyVolumetriDamageToGrid(MyDamageInfo damageInfo, long attackerId)
        {
            var damagedBlocks = damageInfo.ExplosionDamage.DamagedBlocks;
            var explodedBlocks = damageInfo.AffectedCubeBlocks;
            var explodedGrids = damageInfo.AffectedCubeGrids;

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("foreach (var damagedBlock in damagedBlocks)");

            if (MyDebugDrawSettings.DEBUG_DRAW_VOLUMETRIC_EXPLOSION_COLORING)
            {
                foreach (var explodedBlock in explodedBlocks)
                {
                    explodedBlock.CubeGrid.ChangeColor(explodedBlock, new Vector3(0.66f, 1f, 1f));
                }
                foreach (var damagedBlock in damagedBlocks)
                {
                    float hue = 1f - damagedBlock.Value / damageInfo.ExplosionDamage.Damage;
                    damagedBlock.Key.CubeGrid.ChangeColor(damagedBlock.Key, new Vector3(hue / 3f, 1.0f, 0.5f));
                }
            }
            else
            {
                foreach (var damagedBlock in damagedBlocks)
                {
                    var cubeBlock = damagedBlock.Key;
                    if (cubeBlock.FatBlock != null && cubeBlock.FatBlock.MarkedForClose)
                        continue;

                    if (!cubeBlock.CubeGrid.BlocksDestructionEnabled)
                        continue;

                    // Allow mods to modify damage.  This will cause a double call.  Once here and once in the DoDamage, but only real way to do a check here
                    MyDamageInformation checkInfo = new MyDamageInformation(false, damagedBlock.Value, MyDamageType.Explosion, attackerId);
                    if (cubeBlock.UseDamageSystem)
                        MyDamageSystem.Static.RaiseBeforeDamageApplied(cubeBlock, ref checkInfo);

                    if (cubeBlock.FatBlock == null && cubeBlock.Integrity / cubeBlock.DeformationRatio < checkInfo.Amount)
                    {
                        VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("RemoveBlock");
                        cubeBlock.CubeGrid.RemoveDestroyedBlock(cubeBlock);
                        VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
                    }
                    else
                    {
                        VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyDestructionDeformation");
                        float damage = damagedBlock.Value;
                        if (cubeBlock.FatBlock != null)
                        {
                            damage *= 7f;
                        }
                        (cubeBlock as IMyDestroyableObject).DoDamage(damage, MyDamageType.Explosion, true);
                        if (!cubeBlock.IsDestroyed)
                        {
                            cubeBlock.CubeGrid.ApplyDestructionDeformation(cubeBlock);
                        }
                        VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
                    }

                    foreach (var neighbour in cubeBlock.Neighbours)
                    {
                        neighbour.CubeGrid.Physics.AddDirtyBlock(neighbour);
                    }
                    cubeBlock.CubeGrid.Physics.AddDirtyBlock(cubeBlock);
                }
            }

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

            var sphere = damageInfo.Sphere;
            if (!MyDebugDrawSettings.DEBUG_DRAW_VOLUMETRIC_EXPLOSION_COLORING)
            {
                foreach (var grid in explodedGrids)
                {
                    /*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();
                }
            }
        }
        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);
            }
        }
        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;
        }
Пример #4
0
        private void ApplyVolumetriDamageToGrid(MyDamageInfo damageInfo)
        {
            var damagedBlocks = damageInfo.ExplosionDamage.DamagedBlocks;
            var explodedBlocks = damageInfo.AffectedCubeBlocks;
            var explodedGrids = damageInfo.AffectedCubeGrids;

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("foreach (var damagedBlock in damagedBlocks)");

            if (MyDebugDrawSettings.DEBUG_DRAW_VOLUMETRIC_EXPLOSION_COLORING)
            {
                foreach (var explodedBlock in explodedBlocks)
                {
                    explodedBlock.CubeGrid.ChangeColor(explodedBlock, new Vector3(0.66f, 1f, 1f));
                }
                foreach (var damagedBlock in damagedBlocks)
                {
                    float hue = 1f - damagedBlock.Value / damageInfo.ExplosionDamage.Damage;
                    damagedBlock.Key.CubeGrid.ChangeColor(damagedBlock.Key, new Vector3(hue / 3f, 1.0f, 0.5f));
                }
            }
            else
            {
                foreach (var damagedBlock in damagedBlocks)
                {
                    var cubeBlock = damagedBlock.Key;
                    if (cubeBlock.FatBlock != null && cubeBlock.FatBlock.MarkedForClose)
                        continue;

                    if (cubeBlock.FatBlock == null && cubeBlock.Integrity / cubeBlock.DeformationRatio < damagedBlock.Value)
                    {
                        VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("RemoveBlock");
                        cubeBlock.CubeGrid.RemoveDestroyedBlock(cubeBlock);
                        VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
                    }
                    else
                    {
                        VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ApplyDestructionDeformation");
                        float damage = damagedBlock.Value;
                        if (cubeBlock.FatBlock != null)
                        {
                            damage *= 7f;
                        }
                        (cubeBlock as IMyDestroyableObject).DoDamage(damage, MyDamageType.Explosion, true);
                        if (!cubeBlock.IsDestroyed)
                        {
                            cubeBlock.CubeGrid.ApplyDestructionDeformation(cubeBlock);
                        }
                        VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
                    }

                    foreach (var neighbour in cubeBlock.Neighbours)
                    {
                        neighbour.CubeGrid.Physics.AddDirtyBlock(neighbour);
                    }
                    cubeBlock.CubeGrid.Physics.AddDirtyBlock(cubeBlock);
                }
            }

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

            var sphere = damageInfo.Sphere;
            if (!MyDebugDrawSettings.DEBUG_DRAW_VOLUMETRIC_EXPLOSION_COLORING)
            {
                foreach (var grid in explodedGrids)
                {
                    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();
                }
            }
        }