/**
   * Calculates BLOCK chance
   *
   * @param attacker
   * @param attacked
   * @return int
   */
  public static boolean calculatePhysicalBlockRate(Creature attacker, Creature attacked) {
    // check always block
    if (attacked.getObserveController().checkAttackStatus(AttackStatus.BLOCK)) {
      return true;
    }

    float accuracy = attacker.getGameStats().getMainHandPAccuracy().getCurrent();
    float block = 0;
    if (attacked instanceof Player) {
      block =
          attacked.getGameStats().getBlock().getBonus()
              + getMovementModifier(
                  attacked, StatEnum.BLOCK, attacked.getGameStats().getBlock().getBase())
              + attacked.getGameStats().getStat(StatEnum.PVP_BLOCK, 0).getCurrent();
    } else {
      block =
          attacked.getGameStats().getBlock().getBonus()
              + getMovementModifier(
                  attacked, StatEnum.BLOCK, attacked.getGameStats().getBlock().getBase());
    }
    float blockRate = block - accuracy;
    // blockRate = blockRate*0.6f+50;
    if (blockRate > 500) {
      blockRate = 500;
    }
    return Rnd.nextInt(1000) < blockRate;
  }
 /**
  * Accuracy (includes evasion/parry/block formulas): Accuracy formula is based on opponents
  * evasion/parry/block vs your own Accuracy. If your Accuracy is 300 or more above opponents
  * evasion/parry/block then you can not be evaded, parried or blocked. <br>
  * https://docs.google.com/spreadsheet/ccc?key=0AqxBGNJV9RrzdF9tOWpwUlVLOXE5bVRWeHQtbGQxaUE&hl=en_US#gid=2
  */
 public static boolean calculatePhysicalEvasion(float diff, int upperCap) {
   diff = diff * 0.6f + 50;
   if (diff > upperCap) {
     diff = upperCap;
   }
   return Rnd.nextInt(1000) < diff;
 }
  /**
   * Calculates MAGICAL CRITICAL chance
   *
   * @param attacker
   * @param attacke
   * @return boolean
   */
  public static boolean calculateMagicalCriticalRate(
      Creature attacker, Creature attacked, int criticalProb) {
    if (attacker instanceof Servant || attacker instanceof Homing) {
      return false;
    }

    int critical = attacker.getGameStats().getMCritical().getCurrent();
    if (attacked instanceof Player) {
      critical =
          attacked.getGameStats().getPositiveReverseStat(StatEnum.MAGICAL_CRITICAL_RESIST, critical)
              + attacked
                  .getGameStats()
                  .getPositiveReverseStat(StatEnum.PVP_MAGICAL_RESIST, critical);
    } else {
      critical =
          attacked
              .getGameStats()
              .getPositiveReverseStat(StatEnum.MAGICAL_CRITICAL_RESIST, critical);
    }

    // add critical Prob
    critical *= (float) criticalProb / 100f;

    double criticalRate;

    if (critical <= 440) {
      criticalRate = critical * 0.1f;
    } else if (critical <= 600) {
      criticalRate = (440 * 0.1f) + ((critical - 440) * 0.05f);
    } else {
      criticalRate = (440 * 0.1f) + (160 * 0.05f) + ((critical - 600) * 0.02f);
    }

    return Rnd.nextInt(100) < criticalRate;
  }
  /**
   * Calculates CRITICAL chance
   * http://www.wolframalpha.com/input/?i=quadratic+fit+%7B%7B300%2C+30.97%7D%2C+%7B320%2C+31.68%7D%2C+%7B340%2C+33.30%7D%2C+%7B360%2C+36.09%7D%2C+%7B380%2C+37.81%7D%2C+%7B400%2C+40.72%7D%2C+%7B420%2C+42.12%7D%2C+%7B440%2C+44.03%7D%2C+%7B480%2C+44.66%7D%2C+%7B500%2C+45.96%7D%2C%7B604%2C+51.84%7D%2C+%7B649%2C+52.69%7D%7D
   * http://www.aionsource.com/topic/40542-character-stats-xp-dp-origin-gerbatorteam-july-2009/
   * http://www.wolframalpha.com/input/?i=-0.000126341+x%5E2%2B0.184411+x-13.7738
   * https://docs.google.com/spreadsheet/ccc?key=0AqxBGNJV9RrzdGNjbEhQNHN3S3M5bUVfUVQxRkVIT3c&hl=en_US#gid=0
   *
   * @param attacker
   * @return double
   */
  public static boolean calculatePhysicalCriticalRate(
      Creature attacker, Creature attacked, boolean isMainHand, int criticalProb, boolean isSkill) {
    if (attacker instanceof Servant || attacker instanceof Homing) {
      return false;
    }
    int critical;
    if (attacker instanceof Player && !isMainHand) {
      critical = ((PlayerGameStats) attacker.getGameStats()).getOffHandPCritical().getCurrent();
    } else {
      critical = attacker.getGameStats().getMainHandPCritical().getCurrent();
    }

    // check one time boost skill critical
    AttackerCriticalStatus acStatus =
        attacker.getObserveController().checkAttackerCriticalStatus(AttackStatus.CRITICAL, isSkill);
    if (acStatus.isResult()) {
      if (acStatus.isPercent()) {
        critical *= (1 + acStatus.getValue() / 100);
      } else {
        return Rnd.nextInt(1000) < acStatus.getValue();
      }
    }

    critical =
        attacked.getGameStats().getPositiveReverseStat(StatEnum.PHYSICAL_CRITICAL_RESIST, critical)
            - attacker.getGameStats().getStat(StatEnum.PVP_HIT_ACCURACY, 0).getCurrent();

    // add critical Prob
    critical *= (float) criticalProb / 100f;

    double criticalRate;

    if (critical <= 440) {
      criticalRate = critical * 0.1f;
    } else if (critical <= 600) {
      criticalRate = (440 * 0.1f) + ((critical - 440) * 0.05f);
    } else {
      criticalRate = (440 * 0.1f) + (160 * 0.05f) + ((critical - 600) * 0.02f);
    }

    return Rnd.nextInt(100) < criticalRate;
  }