/**
   * @param attacker
   * @param target
   * @param skillDamages
   * @return Damage made to target (-hp value)
   */
  public static int calculateMagicalAttackToTarget(
      Creature attacker, Creature attacked, SkillElement element) {
    CreatureGameStats<?> ags = attacker.getGameStats();

    int resultDamage = 0;

    if (attacker instanceof Player) {
      int min = ags.getCurrentStat(StatEnum.MAIN_MIN_DAMAGES);
      int max = ags.getCurrentStat(StatEnum.MAIN_MAX_DAMAGES);

      Equipment equipment = ((Player) attacker).getEquipment();

      int base = Math.round(Rnd.get(min, max) * ags.getCurrentStat(StatEnum.KNOWLEDGE) * 0.01f);

      resultDamage = base + ags.getStatBonus(StatEnum.MAGICAL_ATTACK);

      if (attacker.isInState(CreatureState.POWERSHARD)) {
        Item mainHandPowerShard = equipment.getMainHandPowerShard();
        if (mainHandPowerShard != null) {
          resultDamage += mainHandPowerShard.getItemTemplate().getWeaponBoost();

          equipment.usePowerShard(mainHandPowerShard, 1);
        }
      }
    }

    // magical resistance
    resultDamage =
        Math.round(
            resultDamage * (1 - attacked.getGameStats().getMagicalDefenseFor(element) / 1000f));

    if (resultDamage <= 0) resultDamage = 1;

    return resultDamage;
  }
  /**
   * @param player
   * @param target
   * @param skillDamages
   * @return Damage made to target (-hp value)
   */
  public static int calculatePhysicDamageToTarget(
      Creature attacker, Creature attacked, int skillDamages, int bonusDamages) {
    CreatureGameStats<?> ags = attacker.getGameStats();

    int resultDamage = 0;

    if (attacker instanceof Player) {
      int min = ags.getCurrentStat(StatEnum.MAIN_MIN_DAMAGES);
      int max = ags.getCurrentStat(StatEnum.MAIN_MAX_DAMAGES);
      int min2 = ags.getCurrentStat(StatEnum.SUB_MIN_DAMAGES);
      int max2 = ags.getCurrentStat(StatEnum.SUB_MAX_DAMAGES);

      // weapon with higher average should be taken into account for skills
      if (skillDamages > 0) {
        if (((min + max) / 2) < ((min2 + max2) / 2)) {
          min = min2;
          max = max2;
        }
      }

      int average = Math.round((min + max) / 2);

      Equipment equipment = ((Player) attacker).getEquipment();

      WeaponType weaponType = equipment.getMainHandWeaponType();

      if (weaponType != null) {
        if (average < 1) {
          average = 1;
          log.warn("Weapon stat MIN_MAX_DAMAGE resulted average zero in main-hand calculation");
          log.warn(
              "Weapon ID: "
                  + String.valueOf(
                      equipment.getMainHandWeapon().getItemTemplate().getTemplateId()));
          log.warn("MIN_DAMAGE = " + String.valueOf(min));
          log.warn("MAX_DAMAGE = " + String.valueOf(max));
        }

        int base = Math.round(Rnd.get(min, max) * ags.getCurrentStat(StatEnum.POWER) * 0.01f);

        resultDamage =
            base
                + ags.getStatBonus(StatEnum.MAIN_HAND_PHYSICAL_ATTACK)
                + skillDamages
                + bonusDamages;

      } else // if hand attack
      {
        int base = Rnd.get(16, 20);
        resultDamage = Math.round(base * (ags.getCurrentStat(StatEnum.POWER) * 0.01f));
      }

      if (attacker.isInState(CreatureState.POWERSHARD)) {
        Item mainHandPowerShard = equipment.getMainHandPowerShard();
        if (mainHandPowerShard != null) {
          resultDamage += mainHandPowerShard.getItemTemplate().getWeaponBoost();

          equipment.usePowerShard(mainHandPowerShard, 1);
        }
      }
    } else if (attacker instanceof Summon) {
      int baseDamage = ags.getCurrentStat(StatEnum.MAIN_HAND_PHYSICAL_ATTACK);
      // 10% range for summon attack
      int max = ((baseDamage * attacker.getLevel()) / 10);
      int min = Math.round(max * 0.9f);
      resultDamage += Rnd.get(min, max);
    } else {
      NpcRank npcRank = ((Npc) attacker).getObjectTemplate().getRank();
      double multipler = calculateRankMultipler(npcRank);
      double hpGaugeMod = 1 + (((Npc) attacker).getObjectTemplate().getHpGauge() / 10);
      int baseDamage = ags.getCurrentStat(StatEnum.MAIN_HAND_PHYSICAL_ATTACK);
      int max =
          (int) ((baseDamage * multipler * hpGaugeMod) + ((baseDamage * attacker.getLevel()) / 10));
      int min = max - ags.getCurrentStat(StatEnum.MAIN_HAND_PHYSICAL_ATTACK);
      resultDamage += Rnd.get(min, max);
    }

    // physical defense
    resultDamage -=
        Math.round(attacked.getGameStats().getCurrentStat(StatEnum.PHYSICAL_DEFENSE) * 0.10f);

    if (resultDamage <= 0) resultDamage = 1;

    return resultDamage;
  }