/**
   * @param player
   * @param target
   * @param effectTemplate
   * @param skillDamages
   * @return Damage made to target (-hp value)
   */
  public static int calculatePhysicalAttackDamage(
      Creature attacker, Creature target, boolean isMainHand) {
    Stat2 pAttack;
    if (isMainHand) {
      pAttack = attacker.getGameStats().getMainHandPAttack();
    } else {
      pAttack = ((Player) attacker).getGameStats().getOffHandPAttack();
    }
    float resultDamage = pAttack.getCurrent();
    float baseDamage = pAttack.getBase();
    if (attacker instanceof Player) {
      Equipment equipment = ((Player) attacker).getEquipment();
      Item weapon;
      if (isMainHand) {
        weapon = equipment.getMainHandWeapon();
      } else {
        weapon = equipment.getOffHandWeapon();
      }

      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 power = attacker.getGameStats().getPower().getCurrent() * 0.01f;
        int diff = Math.round((totalMax - totalMin) * power / 2);
        resultDamage = pAttack.getBonus() + baseDamage;

        // adjust with value from WeaponDualEffect
        // it makes lower cap of damage lower, so damage is more random on offhand
        int negativeDiff = diff;
        if (!isMainHand) {
          negativeDiff =
              (int) Math.round((200 - ((Player) attacker).getDualEffectValue()) * 0.01 * diff);
        }

        resultDamage += Rnd.get(-negativeDiff, diff);

        // add powerShard damage
        if (attacker.isInState(CreatureState.POWERSHARD)) {
          Item firstShard;
          Item secondShard = null;
          if (isMainHand) {
            firstShard = equipment.getMainHandPowerShard();
            if (weapon.getItemTemplate().isTwoHandWeapon()) {
              secondShard = equipment.getOffHandPowerShard();
            }
          } else {
            firstShard = equipment.getOffHandPowerShard();
          }

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

          if (secondShard != null) {
            equipment.usePowerShard(secondShard, 1);
            resultDamage += secondShard.getItemTemplate().getWeaponBoost();
          }
        }
      } else { // if hand attack
        int totalMin = 16;
        int totalMax = 20;

        float power = attacker.getGameStats().getPower().getCurrent() * 0.01f;
        int diff = Math.round((totalMax - totalMin) * power / 2);
        resultDamage = pAttack.getBonus() + baseDamage;
        resultDamage += Rnd.get(-diff, diff);
      }
    } else {
      int rnd = (int) (resultDamage * 0.25);
      resultDamage += Rnd.get(-rnd, rnd);
    }

    // subtract defense
    float pDef =
        target.getGameStats().getPDef().getBonus()
            + getMovementModifier(
                target, StatEnum.PHYSICAL_DEFENSE, target.getGameStats().getPDef().getBase());
    resultDamage -= (pDef * 0.10f);

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

    return Math.round(resultDamage);
  }
  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);
  }
Ejemplo n.º 3
0
  private boolean checkAnimationTime() {
    if (!(effector instanceof Player) || skillMethod != SkillMethod.CAST) // TODO item skills?
    return true;
    Player player = (Player) effector;

    // if player is without weapon, dont check animation time
    if (player.getEquipment().getMainHandWeaponType() == null) return true;

    /** exceptions for certain skills -herb and mana treatment -traps */
    // dont check herb , mana treatment and concentration enhancement
    switch (this.getSkillId()) {
      case 1803: // bandage heal
      case 1804: // herb treatment
      case 1805:
      case 1825:
      case 1827:
      case 2672:
      case 1823: // mana treatment
      case 1824:
      case 1826:
      case 1828:
      case 2673:
      case 1078: // concentration enhancement
      case 1125:
      case 1468:
      case 11580:
        return true;
    }
    if (this.getSkillTemplate().getSubType() == SkillSubType.SUMMONTRAP) return true;

    Motion motion = this.getSkillTemplate().getMotion();

    if (motion == null || motion.getName() == null) {
      log.warn("missing motion for skillId: " + this.getSkillId());
      return true;
    }

    if (motion.getInstantSkill() && hitTime != 0) {
      log.warn(
          "Instant and hitTime not 0! modified client_skills? player objectid: "
              + player.getObjectId());
      return false;
    } else if (!motion.getInstantSkill() && hitTime == 0) {
      log.warn("modified client_skills! player objectid: " + player.getObjectId());
      return false;
    }

    MotionTime motionTime = DataManager.MOTION_DATA.getMotionTime(motion.getName());

    if (motionTime == null) {
      log.warn(
          "missing motiontime for motionName: "
              + motion.getName()
              + " skillId: "
              + this.getSkillId());
      return true;
    }

    WeaponTypeWrapper weapons =
        new WeaponTypeWrapper(
            player.getEquipment().getMainHandWeaponType(),
            player.getEquipment().getOffHandWeaponType());
    float serverTime = motionTime.getTimeForWeapon(player.getRace(), player.getGender(), weapons);
    int clientTime = hitTime;

    if (serverTime == 0) {
      log.warn(
          "missing weapon time for motionName: "
              + motion.getName()
              + " weapons: "
              + weapons.toString()
              + " skillId: "
              + this.getSkillId());
      return true;
    }

    // adjust client time with ammotime
    long ammoTime = 0;
    double distance = MathUtil.getDistance(effector, firstTarget);
    if (getSkillTemplate().getAmmoSpeed() != 0)
      ammoTime =
          Math.round(distance / getSkillTemplate().getAmmoSpeed() * 1000); // checked with client
    clientTime -= ammoTime;

    // adjust servertime with motion play speed
    if (motion.getSpeed() != 100) {
      serverTime /= 100f;
      serverTime *= (float) motion.getSpeed();
    }

    Stat2 attackSpeed = player.getGameStats().getAttackSpeed();

    // adjust serverTime with attackSpeed
    if (attackSpeed.getBase() != attackSpeed.getCurrent())
      serverTime *= ((float) attackSpeed.getCurrent() / (float) attackSpeed.getBase());

    // tolerance
    if (duration == 0) serverTime *= 0.9f;
    else serverTime *= 0.5f;

    int finalTime = Math.round(serverTime);
    if (motion.getInstantSkill() && hitTime == 0) {
      this.serverTime = (int) ammoTime;
    } else {
      if (clientTime < finalTime) {
        // check for no animation Hacks
        if (SecurityConfig.NO_ANIMATION) {
          float clientTme = clientTime;
          float serverTme = serverTime;
          float checkTme = clientTme / serverTme;
          // check if values are too low
          if (clientTime < 0 || checkTme < SecurityConfig.NO_ANIMATION_VALUE) {
            if (SecurityConfig.NO_ANIMATION_KICK) {
              player.getClientConnection().close(new SM_QUIT_RESPONSE(), false);
              AuditLogger.info(
                  player,
                  "Modified client_skills:"
                      + this.getSkillId()
                      + " (clientTime<finalTime:"
                      + clientTime
                      + "/"
                      + finalTime
                      + ") Kicking Player: "
                      + player.getName());
            } else {
              AuditLogger.info(
                  player,
                  "Modified client_skills:"
                      + this.getSkillId()
                      + " (clientTime<finalTime:"
                      + clientTime
                      + "/"
                      + finalTime
                      + ")");
            }
            return false;
          }
        }
        log.warn(
            "Possible modified client_skills:"
                + this.getSkillId()
                + " (clientTime<finalTime:"
                + clientTime
                + "/"
                + finalTime
                + ") player Name: "
                + player.getName());
      }
      this.serverTime = hitTime;
    }
    player.setNextSkillUse(System.currentTimeMillis() + duration + finalTime);
    return true;
  }