public static int calculateMagicalSkillDamage(
      Creature speller,
      Creature target,
      int baseDamages,
      int bonus,
      SkillElement element,
      boolean useMagicBoost,
      boolean useKnowledge,
      boolean noReduce,
      int pvpDamage) {
    CreatureGameStats<?> sgs = speller.getGameStats();
    CreatureGameStats<?> tgs = target.getGameStats();

    int magicBoost = useMagicBoost ? sgs.getMBoost().getCurrent() : 0;

    magicBoost -= tgs.getMBResist().getCurrent();

    if (magicBoost < 0) {
      magicBoost = 0;
    } else if (magicBoost > 2900) {
      magicBoost = 2901;
    }

    int knowledge = useKnowledge ? sgs.getKnowledge().getCurrent() : 100;

    float damages = baseDamages * (knowledge / 100f + magicBoost / 1000f);

    damages = sgs.getStat(StatEnum.BOOST_SPELL_ATTACK, (int) damages).getCurrent();

    // add bonus damage
    damages += bonus;

    /* element resist: fire, wind, water, eath
     * 10 elemental resist ~ 1% reduce of magical baseDamages
     */
    if (!noReduce && element != SkillElement.NONE) {
      float elementalDef =
          getMovementModifier(
              target,
              SkillElement.getResistanceForElement(element),
              tgs.getMagicalDefenseFor(element));
      damages = Math.round(damages * (1 - (elementalDef / 1250f)));
    }
    elements = element;
    damages = adjustDamages(speller, target, damages, pvpDamage, useKnowledge);

    // magical defense
    // if (!noReduce && element != SkillElement.NONE) {
    //	damages -= target.getGameStats().getMDef().getCurrent();
    // }
    if (damages <= 0) {
      damages = 1;
    }

    if (target instanceof Npc) {
      return target.getAi2().modifyDamage((int) damages);
    }

    return Math.round(damages);
  }
  public static int calculateMagicalAttackDamage(
      Creature attacker, Creature target, SkillElement element, boolean isMainHand) {
    Preconditions.checkNotNull(element, "Skill element should be NONE instead of null");
    Stat2 mAttack;

    if (isMainHand) {
      mAttack = attacker.getGameStats().getMainHandMAttack();
    } else {
      mAttack = attacker.getGameStats().getOffHandMAttack();
    }

    float resultDamage = mAttack.getCurrent();

    if (attacker instanceof Player) {
      Equipment equipment = ((Player) attacker).getEquipment();
      Item weapon = equipment.getMainHandWeapon();

      if (weapon != null) {
        WeaponStats weaponStat = weapon.getItemTemplate().getWeaponStats();
        if (weaponStat == null) {
          return 0;
        }
        int totalMin = weaponStat.getMinDamage();
        int totalMax = weaponStat.getMaxDamage();
        if (totalMax - totalMin < 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(totalMin));
          log.warn("MAX_DAMAGE = " + String.valueOf(totalMax));
        }
        float knowledge = attacker.getGameStats().getKnowledge().getCurrent() * 0.01f;
        int diff = Math.round((totalMax - totalMin) * knowledge / 2);
        resultDamage =
            mAttack.getBonus()
                + getMovementModifier(attacker, StatEnum.MAGICAL_ATTACK, mAttack.getBase());
        resultDamage += Rnd.get(-diff, diff);

        if (attacker.isInState(CreatureState.POWERSHARD)) {
          Item firstShard = equipment.getMainHandPowerShard();
          Item secondShard = equipment.getOffHandPowerShard();
          if (firstShard != null) {
            equipment.usePowerShard(firstShard, 1);
            resultDamage += firstShard.getItemTemplate().getWeaponBoost();
          }

          if (secondShard != null) {
            equipment.usePowerShard(secondShard, 1);
            resultDamage += secondShard.getItemTemplate().getWeaponBoost();
          }
        }
      }
    }

    if (element != SkillElement.NONE) {
      float elementalDef =
          getMovementModifier(
              target,
              SkillElement.getResistanceForElement(element),
              target.getGameStats().getMagicalDefenseFor(element));
      resultDamage = Math.round(resultDamage * (1 - elementalDef / 1300f));
    }

    if (resultDamage <= 0) {
      resultDamage = 1;
    }

    return Math.round(resultDamage);
  }