/**
   * Calculates DODGE chance
   *
   * @param attacker
   * @param attacked
   * @param accMod
   * @return int
   */
  public static int calculatePhysicalDodgeRate(Creature attacker, Creature attacked, int accMod) {
    // check attack status = BLIND
    if (attacker.getObserveController().checkAttackerStatus(AttackStatus.DODGE)) return 100;
    if (attacker.getEffectController().isAbnormalSet(EffectId.BLIND)) return 100;
    if (attacker.getEffectController().isAbnormalSet(EffectId.BLIND)) return 100;
    int accurancy;

    if (attacker instanceof Player
        && ((Player) attacker).getEquipment().getSubHandWeaponType() != null)
      accurancy =
          Math.round(
              (attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_ACCURACY)
                      + attacker.getGameStats().getCurrentStat(StatEnum.SUB_HAND_ACCURACY))
                  / 2);
    else accurancy = attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_ACCURACY);

    // add bonus stat from effecttemplate
    accurancy += accMod;

    int dodgeRate = (attacked.getGameStats().getCurrentStat(StatEnum.EVASION) - accurancy) / 10;

    // maximal dodge rate
    if (dodgeRate > 30) dodgeRate = 30;

    if (dodgeRate <= 0) return 1;

    return dodgeRate;
  }
  /**
   * Calculates PHYSICAL CRITICAL chance
   *
   * @param attacker
   * @param attacked
   * @float criticalProb
   * @return double
   */
  public static double calculatePhysicalCriticalRate(
      Creature attacker, Creature attacked, float criticalProb) {
    int critical;

    // check always critical
    if (attacker.getObserveController().checkAttackerStatus(AttackStatus.CRITICAL)) return 100;

    if (attacker instanceof Player
        && ((Player) attacker).getEquipment().getSubHandWeaponType() != null)
      critical =
          Math.round(
              (attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_CRITICAL)
                      + attacker.getGameStats().getCurrentStat(StatEnum.SUB_HAND_CRITICAL))
                  / 2);
    else critical = attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_CRITICAL);

    critical =
        Math.round(
            critical * criticalProb
                - attacked.getGameStats().getCurrentStat(StatEnum.PHYSICAL_CRITICAL_RESIST));

    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);
    // minimal critical rate
    if (criticalRate < 1) criticalRate = 1;

    return criticalRate;
  }
  /**
   * @param player
   * @param target
   * @param skillEffectTemplate
   * @param dot -whether its damage over time - dot is not multiplied by knowledge
   * @return HP damage to target
   */
  public static int calculateMagicDamageToTarget(
      Creature speller,
      Creature effected,
      int baseDamages,
      int bonusDamages,
      SkillElement element,
      boolean dot) {
    CreatureGameStats<?> sgs = speller.getGameStats();

    int totalBoostMagicalSkill = sgs.getCurrentStat(StatEnum.BOOST_MAGICAL_SKILL);

    int knowledge = 0;

    if (dot) knowledge = 100;
    else knowledge = sgs.getCurrentStat(StatEnum.KNOWLEDGE);

    int damages = Math.round(baseDamages * ((knowledge / 100f) + (totalBoostMagicalSkill / 1000f)));

    // add damage from actionmodifiers
    damages += bonusDamages;

    // elemental resistance
    damages =
        Math.round(damages * (1 - effected.getGameStats().getMagicalDefenseFor(element) / 1000f));

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

    return damages;
  }
  /**
   * @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 attacker
   * @param target
   * @return
   */
  public static int calculateSubHandPhysicDamageToTarget(Creature attacker, Creature attacked) {
    CreatureGameStats<?> ags = attacker.getGameStats();

    int min = ags.getCurrentStat(StatEnum.SUB_MIN_DAMAGES);
    int max = ags.getCurrentStat(StatEnum.SUB_MAX_DAMAGES);
    int average = Math.round((min + max) / 2);

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

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

    int base = Rnd.get(min, max);

    int damage = base + ags.getStatBonus(StatEnum.SUB_HAND_PHYSICAL_ATTACK);

    if (attacker.isInState(CreatureState.POWERSHARD)) {
      Item subHandPowerShard = equipment.getSubHandPowerShard();
      if (subHandPowerShard != null) {
        damage += subHandPowerShard.getItemTemplate().getWeaponBoost();
        equipment.usePowerShard(subHandPowerShard, 1);
      }
    }
    int dualEffect = ((Player) attacker).getEffectController().getDualEffect();
    if (dualEffect == 0) {
      log.warn(
          "Missing dualeffect for player "
              + ((Player) attacker).getName()
              + " possible hack? or bug?");
      dualEffect = 25;
    }

    if (Rnd.get(0, 100) < 25) damage *= (dualEffect * 0.007f);

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

    if (damage <= 0) damage = 1;

    return damage;
  }
  /**
   * Calculates MAGICAL CRITICAL chance
   *
   * @param attacker
   * @param attacked
   * @param criticalProb
   * @return double
   */
  public static double calculateMagicalCriticalRate(
      Creature attacker, Creature attacked, float criticalProb) {
    int critical;

    critical =
        Math.round(
            attacker.getGameStats().getCurrentStat(StatEnum.MAGICAL_CRITICAL) * criticalProb
                - attacked.getGameStats().getCurrentStat(StatEnum.MAGICAL_CRITICAL_RESIST));

    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);
    // minimal critical rate
    if (criticalRate < 1) criticalRate = 1;

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

    int accuracy;

    if (attacker instanceof Player
        && ((Player) attacker).getEquipment().getSubHandWeaponType() != null)
      accuracy =
          Math.round(
              (attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_ACCURACY)
                      + attacker.getGameStats().getCurrentStat(StatEnum.SUB_HAND_ACCURACY))
                  / 2);
    else accuracy = attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_ACCURACY);

    int blockRate = (attacked.getGameStats().getCurrentStat(StatEnum.BLOCK) - accuracy) / 10;
    // maximal block rate
    if (blockRate > 50) blockRate = 50;

    if (blockRate <= 0) return 1;

    return blockRate;
  }
  /**
   * Calculates PARRY chance
   *
   * @param attacker
   * @param attacked
   * @return int
   */
  public static int calculatePhysicalParryRate(Creature attacker, Creature attacked) {
    // check always parry
    if (attacked.getObserveController().checkAttackStatus(AttackStatus.PARRY)) return 100;

    int accuracy;

    if (attacker instanceof Player
        && ((Player) attacker).getEquipment().getSubHandWeaponType() != null)
      accuracy =
          Math.round(
              (attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_ACCURACY)
                      + attacker.getGameStats().getCurrentStat(StatEnum.SUB_HAND_ACCURACY))
                  / 2);
    else accuracy = attacker.getGameStats().getCurrentStat(StatEnum.MAIN_HAND_ACCURACY);

    int parryRate = (attacked.getGameStats().getCurrentStat(StatEnum.PARRY) - accuracy) / 10;
    // maximal parry rate
    if (parryRate > 40) parryRate = 40;

    if (parryRate <= 0) return 1;

    return parryRate;
  }
  /**
   * Calculates RESIST chance
   *
   * @param attacker
   * @param attacked
   * @param accMod
   * @return int
   */
  public static int calculateMagicalResistRate(Creature attacker, Creature attacked, int accMod) {
    if (attacked.getObserveController().checkAttackStatus(AttackStatus.RESIST)) return 100;
    // if(attacker.getEffectController().isAbnormalSet(EffectId.BLIND))
    //  return 100;

    int stat_res = attacked.getGameStats().getCurrentStat(StatEnum.MAGICAL_RESIST);
    int stat_acc = attacker.getGameStats().getCurrentStat(StatEnum.MAGICAL_ACCURACY);

    int attackerLevel = attacker.getLevel();
    int targetLevel = attacked.getLevel();

    // add bonus stat from effecttemplate
    stat_acc += accMod;

    int resist = (stat_res - stat_acc) / 10;

    if ((targetLevel - attackerLevel) > 2) resist += (targetLevel - attackerLevel - 2) * 10;

    if (resist <= 0) // cant resist
    return 0;
    else if (resist > 95) // hardcap 95%
    return 95;
    else return resist;
  }
  /** {@inheritDoc} */
  @Override
  protected void writeImpl(AionConnection con, ByteBuffer buf) {
    writeF(buf, npc.getX()); // x
    writeF(buf, npc.getY()); // y
    writeF(buf, npc.getZ()); // z
    writeD(buf, npc.getObjectId());
    writeD(buf, npcId);
    writeD(buf, npcId);

    writeC(buf, npcTypeId);

    writeH(
        buf,
        npc
            .getState()); // unk 65=normal,0x47 (71)= [dead npc ?]no drop,0x21(33)=fight
                          // state,0x07=[dead monster?]
    // no drop
    // 3,19 - wings spread (NPCs)
    // 5,6,11,21 - sitting (NPC)
    // 7,23 - dead (no drop)
    // 8,24 - [dead][NPC only] - looks like some orb of light (no normal mesh)
    // 32,33 - fight mode

    writeC(buf, npc.getHeading());
    writeD(buf, npcTemplate.getNameId());
    writeD(buf, npcTemplate.getTitleId()); // titleID

    writeH(buf, 0x00); // unk
    writeC(buf, 0x00); // unk
    writeD(buf, 0x00); // unk

    /*
     * Master Info (Summon, Kisk, Etc)
     */
    writeD(buf, masterObjId); // masterObjectId
    writeS(buf, masterName); // masterName

    int maxHp = npc.getLifeStats().getMaxHp();
    int currHp = npc.getLifeStats().getCurrentHp();
    writeC(buf, 100 * currHp / maxHp); // %hp
    writeD(buf, npc.getGameStats().getCurrentStat(StatEnum.MAXHP));
    writeC(buf, npc.getLevel()); // lvl

    NpcEquippedGear gear = npcTemplate.getEquipment();
    if (gear == null) writeH(buf, 0x00);
    else {
      writeH(buf, gear.getItemsMask());
      for (Entry<ItemSlot, ItemTemplate> item :
          gear) // getting it from template ( later if we make sure that npcs actually use items,
                // we'll make Item from it )
      {
        writeD(buf, item.getValue().getTemplateId());
        writeD(buf, 0x00);
        writeD(buf, 0x00);
        writeH(buf, 0x00);
      }
    }

    writeF(buf, 1.5f); // unk
    writeF(buf, npcTemplate.getHeight());
    writeF(buf, npc.getMoveController().getSpeed()); // speed

    writeH(buf, 2000); // 0x834 (depends on speed ? )
    writeH(buf, 2000); // 0x834

    if (npc instanceof Servant) writeC(buf, 0x01); // unk
    else writeC(buf, 0x00);

    /** Movement */
    writeF(buf, npc.getX()); // x
    writeF(buf, npc.getY()); // y
    writeF(buf, npc.getZ()); // z
    writeC(buf, 0x00); // move type

    SpawnTemplate spawn = npc.getSpawn();
    if (spawn == null) {
      writeH(buf, 0);
    } else {
      int mask =
          (Math.round(spawn.getStaticid() / 0xFF) < 0 ? 0 : Math.round(spawn.getStaticid() / 0xFF));
      byte[] statics = new byte[] {(byte) spawn.getStaticid(), (byte) mask};
      writeB(buf, statics);
    }

    writeC(buf, 0);
    writeC(buf, 0); // all unknown
    writeC(buf, 0);
    writeC(buf, 0);
    writeC(buf, 0);
    writeC(buf, 0);
    writeC(buf, 0);
    writeC(buf, 0);
    writeC(buf, npc.getVisualState()); // visualState

    /** 1 : normal (kisk too) 2 : summon 32 : trap 1024 : holy servant, noble energy */
    writeH(buf, npc.getNpcObjectType().getId());
    writeC(buf, 0x00); // unk
    if (npc instanceof Artifact) {
      writeD(buf, 0);
    } else {
      writeD(buf, npc.getTarget() == null ? 0 : npc.getTarget().getObjectId());
    }
  }
Beispiel #11
0
  /**
   * @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;
  }
Beispiel #12
0
 /**
  * Hate based on BOOST_HATE stat Now used only from skills, probably need to use for regular
  * attack
  *
  * @param creature
  * @param value
  * @return
  */
 public static int calculateHate(Creature creature, int value) {
   return Math.round(value * creature.getGameStats().getCurrentStat(StatEnum.BOOST_HATE) / 100f);
 }