private void AfterDamageApplied(object target, MyDamageInformation info)
        {
            MyCharacter targetCharacter = target as MyCharacter;
            if (targetCharacter == null || targetCharacter.IsDead) return;

            MyEntity entity = null;
            MyEntities.TryGetEntityById(info.AttackerId, out entity);

            MyPlayer attackerPlayer = null;
            MyStringHash hitCue = MyStringHash.NullOrEmpty;

            // Because damage system is retarded...
            if (entity is MyCharacter || entity is MyCubeGrid || entity is MyCubeBlock)
            {
                attackerPlayer = Sync.Players.GetControllingPlayer(entity);
                if (attackerPlayer == null) return;
            }
            else
            {
                var gunBaseUser = entity as IMyGunBaseUser;
                if (gunBaseUser == null) return;
                if (gunBaseUser.Owner == null) return;
                attackerPlayer = Sync.Players.GetControllingPlayer(gunBaseUser.Owner);

                if (MyPerGameSettings.Game == GameEnum.ME_GAME)
                {
                    //hitCue = MyStringHash.GetOrCompute("ToolCrossbHitBody");//this causes to play the hit sound at full volume regardless of distance
                }
            }

            if (attackerPlayer == null || attackerPlayer.Client == null || attackerPlayer.IsBot) return;
            if (targetCharacter.ControllerInfo.Controller != null && targetCharacter.ControllerInfo.Controller.Player == attackerPlayer) return;

            if (MyPerGameSettings.Game == GameEnum.ME_GAME)
            {
                MyMultiplayer.RaiseStaticEvent(s => AfterDamageAppliedClient, hitCue, new EndpointId(attackerPlayer.Client.SteamUserId));
            }
            else if (MyPerGameSettings.Game == GameEnum.SE_GAME || MyPerGameSettings.Game == GameEnum.VRS_GAME)
            {
                MyMultiplayer.RaiseStaticEvent(s => AfterDamageAppliedClient, hitCue, new EndpointId(attackerPlayer.Client.SteamUserId));
            }
        }
        public bool KillNotSelectedBots()
        {
            if (Sandbox.Engine.Utils.MyDebugDrawSettings.DEBUG_DRAW_BOTS)
            {
                MyBotCollection bots = MyAIComponent.Static.Bots;
                foreach (var entry in MyAIComponent.Static.Bots.GetAllBots())
                {
                    var localBot = entry.Value;
                    var agent = localBot as MyAgentBot;

                    // return to previous bot memory
                    if (agent != null && !bots.IsBotSelectedForDegugging(agent))
                    {
                        if (agent.Player.Controller.ControlledEntity is MyCharacter)
                        {
                            MyDamageInformation damageInfo = new MyDamageInformation(false, 1000, MyDamageType.Weapon, MySession.Static.LocalPlayerId);
                            (agent.Player.Controller.ControlledEntity as MyCharacter).Kill(true, damageInfo);
                        }
                    }
                }
            }
            return true;
        }
        private void ApplyVolumetriDamageToGrid(MyGridExplosion damageInfo, long attackerId)
        {
            var damagedBlocks = damageInfo.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.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();
                }
            }
        }