public void Damage(Player attacker, Attackable target, DamageType damageType, int damage, double shieldPenetration, bool deactiveCloak = true)
        {
            if (damageType == DamageType.MINE && target.Invincible)
            {
                return;
            }

            if (damageType == DamageType.LASER && Player.Settings.InGameSettings.selectedLaser == AmmunitionManager.SAB_50)
            {
                Absorbation(attacker, target, damageType, damage);
                return;
            }

            int damageShd = 0, damageHp = 0;

            if (attacker.Invincible)
            {
                attacker.Storage.DeactiveInvincibilityEffect();
            }

            if (target is Spaceball)
            {
                var spaceball = target as Spaceball;
                spaceball.AddDamage(attacker, damage);
            }

            double shieldAbsorb = System.Math.Abs(target.ShieldAbsorption - shieldPenetration);

            if (shieldAbsorb > 1)
            {
                shieldAbsorb = 1;
            }

            if ((target.CurrentShieldPoints - damage) >= 0)
            {
                damageShd = (int)(damage * shieldAbsorb);
                damageHp  = damage - damageShd;
            }
            else
            {
                int newDamage = damage - target.CurrentShieldPoints;
                damageShd = target.CurrentShieldPoints;
                damageHp  = (int)(newDamage + (damageShd * shieldAbsorb));
            }

            if ((target.CurrentHitPoints - damageHp) < 0)
            {
                damageHp = target.CurrentHitPoints;
            }

            if (target.Invincible || (target is Satellite satellite && satellite.BattleStation.Invincible) || (target is Player && !(target as Player).Attackable()))
            {
                damage    = 0;
                damageShd = 0;
                damageHp  = 0;
            }

            if (deactiveCloak)
            {
                Player.CpuManager.DisableCloak();
            }

            if (damageType == DamageType.LASER)
            {
                if (target is Player && (target as Player).Storage.Sentinel)
                {
                    damageShd -= Maths.GetPercentage(damageShd, 30);
                }

                if (Player.Storage.Diminisher)
                {
                    if (target == Player.Storage.UnderDiminisherEntity)
                    {
                        damageShd += Maths.GetPercentage(damage, 50);
                    }
                }

                if (target is Player && (target as Player).Storage.Diminisher)
                {
                    if ((target as Player).Storage.UnderDiminisherEntity == Player)
                    {
                        damageShd += Maths.GetPercentage(damage, 30);
                    }
                }

                var laserRunCommand = AttackLaserRunCommand.write(Player.Id, target.Id, GetSelectedLaser(), false, true);
                Player.SendCommand(laserRunCommand);
                Player.SendCommandToInRangePlayers(laserRunCommand);

                if (Player.Settings.InGameSettings.selectedLaser != AmmunitionManager.CBO_100)
                {
                    if (Player.Storage.EnergyLeech)
                    {
                        Player.TechManager.EnergyLeech.ExecuteHeal(damage);
                    }
                }
            }

            if (damage == 0)
            {
                if (damageType == DamageType.LASER || damageType == DamageType.ROCKET)
                {
                    AttackMissed(target, damageType);
                }
            }
            else
            {
                if (target is Npc)
                {
                    (target as Npc).ReceiveAttack(Player);
                }

                var attackHitCommand =
                    AttackHitCommand.write(new AttackTypeModule((short)damageType), Player.Id,
                                           target.Id, target.CurrentHitPoints,
                                           target.CurrentShieldPoints, target.CurrentNanoHull,
                                           damage > damageShd ? damage : damageShd, false);

                Player.SendCommand(attackHitCommand);
                Player.SendCommandToInRangePlayers(attackHitCommand);
            }

            if (Player.Settings.InGameSettings.selectedLaser == AmmunitionManager.CBO_100)
            {
                var sabDamage = RandomizeDamage(2 * Player.Damage, (Player.Storage.underPLD8 ? 0.5 : 0.1));

                if (Player.Storage.Spectrum)
                {
                    sabDamage -= Maths.GetPercentage(sabDamage, 50);
                }

                if (target is Player)
                {
                    if ((target as Player).Storage.Spectrum)
                    {
                        sabDamage -= Maths.GetPercentage(sabDamage, 80);
                    }
                }

                Player.CurrentShieldPoints += sabDamage;
            }

            if (damageHp >= target.CurrentHitPoints || target.CurrentHitPoints <= 0)
            {
                target.Destroy(Player, DestructionType.PLAYER);
            }
            else
            {
                if (target.CurrentNanoHull > 0)
                {
                    if (target.CurrentNanoHull - damageHp < 0)
                    {
                        var nanoDamage = damageHp - target.CurrentNanoHull;
                        target.CurrentNanoHull   = 0;
                        target.CurrentHitPoints -= nanoDamage;
                    }
                    else
                    {
                        target.CurrentNanoHull -= damageHp;
                    }
                }
                else
                {
                    target.CurrentHitPoints -= damageHp;
                }
            }

            target.CurrentShieldPoints -= damageShd;
            target.LastCombatTime       = DateTime.Now;

            if (Player.Settings.InGameSettings.selectedLaser == AmmunitionManager.CBO_100)
            {
                Player.UpdateStatus();
            }

            target.UpdateStatus();
        }
        public static void Damage(Player attacker, Attackable target, DamageType damageType, int damage, bool toDestroy, bool toHp, bool toShd, bool missedEffect = true)
        {
            if (damageType == DamageType.MINE && target.Invincible)
            {
                return;
            }

            if (attacker.Invincible && damageType != DamageType.RADIATION)
            {
                attacker.Storage.DeactiveInvincibilityEffect();
            }

            if (target is Player && !(target as Player).Attackable())
            {
                if (missedEffect)
                {
                    var attackMissedCommandToInRange = AttackMissedCommand.write(new AttackTypeModule((short)damageType), target.Id, 0);
                    var attackMissedCommand          = AttackMissedCommand.write(new AttackTypeModule((short)damageType), target.Id, 0);
                    attacker.SendCommand(attackMissedCommand);
                    attacker.SendCommandToInRangePlayers(attackMissedCommandToInRange);
                }
                damage = 0;
                return;
            }

            target.LastCombatTime = DateTime.Now;

            if (toHp && toDestroy && (damage >= target.CurrentHitPoints || target.CurrentHitPoints <= 0))
            {
                if (damageType == DamageType.RADIATION)
                {
                    target.Destroy(null, DestructionType.RADIATION);
                }
                else if (damageType == DamageType.MINE && attacker.Attackers.Count <= 0)
                {
                    target.Destroy(null, DestructionType.MINE);
                }
                else
                {
                    target.Destroy(attacker, DestructionType.PLAYER);
                }
            }
            else if (toHp)
            {
                if (target.CurrentNanoHull > 0)
                {
                    if (target.CurrentNanoHull - damage < 0)
                    {
                        var nanoDamage = damage - target.CurrentNanoHull;
                        target.CurrentNanoHull   = 0;
                        target.CurrentHitPoints -= nanoDamage;
                    }
                    else
                    {
                        target.CurrentNanoHull -= damage;
                    }
                }
                else
                {
                    target.CurrentHitPoints -= damage;
                }
            }

            if (toShd)
            {
                target.CurrentShieldPoints -= damage;
            }

            var attackHitCommand =
                AttackHitCommand.write(new AttackTypeModule((short)damageType), attacker.Id,
                                       target.Id, target.CurrentHitPoints,
                                       target.CurrentShieldPoints, target.CurrentNanoHull,
                                       damage, false);

            attacker.SendCommand(attackHitCommand);
            attacker.SendCommandToInRangePlayers(attackHitCommand);

            target.UpdateStatus();
        }
        public void Attack(Attackable target, double shieldPenetration = 0)
        {
            var missProbability = Type == StationModuleModule.LASER_LOW_RANGE ? 0.1 : Type == StationModuleModule.LASER_MID_RANGE ? 0.3 : Type == StationModuleModule.LASER_HIGH_RANGE ? 0.4 : Type == StationModuleModule.ROCKET_LOW_ACCURACY ? 0.5 : Type == StationModuleModule.ROCKET_MID_ACCURACY ? 0.3 : 1.00;

            var damage = AttackManager.RandomizeDamage((Type == StationModuleModule.LASER_LOW_RANGE ? 59850 : Type == StationModuleModule.LASER_MID_RANGE ? 48450 : Type == StationModuleModule.LASER_HIGH_RANGE ? 28500 : Type == StationModuleModule.ROCKET_LOW_ACCURACY ? 85500 : Type == StationModuleModule.ROCKET_MID_ACCURACY ? 71250 : 0), missProbability);

            damage = 1000; //for test

            var damageType = (Type == StationModuleModule.LASER_LOW_RANGE || Type == StationModuleModule.LASER_MID_RANGE || Type == StationModuleModule.LASER_HIGH_RANGE) ? DamageType.LASER : (Type == StationModuleModule.ROCKET_LOW_ACCURACY || Type == StationModuleModule.ROCKET_MID_ACCURACY) ? DamageType.ROCKET : DamageType.LASER;

            var cooldown = (Type == StationModuleModule.ROCKET_LOW_ACCURACY || Type == StationModuleModule.ROCKET_MID_ACCURACY) ? 2 : 1;

            if (target.Position.DistanceTo(Position) < GetRange())
            {
                if (!TargetDefinition(target))
                {
                    return;
                }

                if (lastAttackTime.AddSeconds(cooldown) < DateTime.Now)
                {
                    int damageShd = 0, damageHp = 0;

                    double shieldAbsorb = System.Math.Abs(target.ShieldAbsorption - shieldPenetration);

                    if (shieldAbsorb > 1)
                    {
                        shieldAbsorb = 1;
                    }

                    if ((target.CurrentShieldPoints - damage) >= 0)
                    {
                        damageShd = (int)(damage * shieldAbsorb);
                        damageHp  = damage - damageShd;
                    }
                    else
                    {
                        int newDamage = damage - target.CurrentShieldPoints;
                        damageShd = target.CurrentShieldPoints;
                        damageHp  = (int)(newDamage + (damageShd * shieldAbsorb));
                    }

                    if ((target.CurrentHitPoints - damageHp) < 0)
                    {
                        damageHp = target.CurrentHitPoints;
                    }

                    if (target is Player && !(target as Player).Attackable())
                    {
                        damage    = 0;
                        damageShd = 0;
                        damageHp  = 0;
                    }

                    if (damageType == DamageType.LASER)
                    {
                        if (target is Player && (target as Player).Storage.Sentinel)
                        {
                            damageShd -= Maths.GetPercentage(damageShd, 30);
                        }

                        if (target is Player && (target as Player).Storage.Diminisher)
                        {
                            if ((target as Player).Storage.UnderDiminisherEntity == this)
                            {
                                damageShd += Maths.GetPercentage(damage, 30);
                            }
                        }

                        var laserRunCommand = AttackLaserRunCommand.write(Id, target.Id, 0, false, false);
                        SendCommandToInRangeCharacters(laserRunCommand);
                    }
                    else if (damageType == DamageType.ROCKET)
                    {
                        var rocketRunPacket = $"0|v|{Id}|{target.Id}|H|" + 1 + "|0|1";
                        SendPacketToInRangeCharacters(rocketRunPacket);
                    }

                    if (damage == 0)
                    {
                        SendCommandToInRangeCharacters(AttackMissedCommand.write(new AttackTypeModule((short)damageType), target.Id, 1), target);

                        if (target is Player)
                        {
                            (target as Player).SendCommand(AttackMissedCommand.write(new AttackTypeModule((short)damageType), target.Id, 0));
                        }
                    }
                    else
                    {
                        var attackHitCommand =
                            AttackHitCommand.write(new AttackTypeModule((short)damageType), Id,
                                                   target.Id, target.CurrentHitPoints,
                                                   target.CurrentShieldPoints, target.CurrentNanoHull,
                                                   damage > damageShd ? damage : damageShd, false);

                        SendCommandToInRangeCharacters(attackHitCommand);
                    }

                    if (damageHp >= target.CurrentHitPoints || target.CurrentHitPoints <= 0)
                    {
                        target.Destroy(this, DestructionType.MISC);
                    }
                    else
                    {
                        if (target.CurrentNanoHull > 0)
                        {
                            if (target.CurrentNanoHull - damageHp < 0)
                            {
                                var nanoDamage = damageHp - target.CurrentNanoHull;
                                target.CurrentNanoHull   = 0;
                                target.CurrentHitPoints -= nanoDamage;
                            }
                            else
                            {
                                target.CurrentNanoHull -= damageHp;
                            }
                        }
                        else
                        {
                            target.CurrentHitPoints -= damageHp;
                        }
                    }

                    target.CurrentShieldPoints -= damageShd;
                    target.LastCombatTime       = DateTime.Now;

                    target.UpdateStatus();

                    lastAttackTime = DateTime.Now;
                }
            }
        }