/**
   * @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;
  }
  @Override
  public void onDie(Creature lastAttacker) {
    super.onDie(lastAttacker);

    Npc owner = getOwner();

    addTask(TaskId.DECAY, RespawnService.scheduleDecayTask(this.getOwner()));
    scheduleRespawn();

    PacketSendUtility.broadcastPacket(
        owner,
        new SM_EMOTION(
            owner, EmotionType.DIE, 0, lastAttacker == null ? 0 : lastAttacker.getObjectId()));

    // Monster Controller overrides this method.
    this.doReward();
    Npc npc = getOwner();
    List<QuestDrop> drops = QuestEngine.getInstance().getQuestDrop(npc.getNpcId());
    if (drops.size() > 0) {
      DropService.getInstance()
          .registerDrop(getOwner(), (Player) lastAttacker, lastAttacker.getLevel());
    }
    owner.getAi().handleEvent(Event.DIED);

    // deselect target at the end
    owner.setTarget(null);
    PacketSendUtility.broadcastPacket(owner, new SM_LOOKATOBJECT(owner));
  }
  @Override
  public void attackTarget(Creature target) {
    Npc npc = getOwner();

    /** Check all prerequisites */
    if (npc == null || npc.getLifeStats().isAlreadyDead() || !npc.isSpawned()) return;

    if (!npc.canAttack()) return;

    AI<?> ai = npc.getAi();
    NpcGameStats gameStats = npc.getGameStats();

    if (target == null || target.getLifeStats().isAlreadyDead()) {
      ai.handleEvent(Event.MOST_HATED_CHANGED);
      return;
    }

    /** notify attack observers */
    super.attackTarget(target);

    /** Calculate and apply damage */
    List<AttackResult> attackList = AttackUtil.calculateAttackResult(npc, target);

    int damage = 0;
    for (AttackResult result : attackList) {
      damage += result.getDamage();
    }

    int attackType = 0; // TODO investigate attack types (0 or 1)
    PacketSendUtility.broadcastPacket(
        npc, new SM_ATTACK(npc, target, gameStats.getAttackCounter(), 274, attackType, attackList));

    target.getController().onAttack(npc, damage, true);
    gameStats.increaseAttackCounter();
  }
  /**
   * 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;
  }
Exemple #6
0
 @Override
 public void startEffect(Effect effect) {
   final Creature effected = effect.getEffected();
   effected.getController().cancelCurrentSkill();
   effect.setAbnormal(EffectId.STUMBLE.getEffectId());
   effected.getEffectController().setAbnormal(EffectId.STUMBLE.getEffectId());
   PacketSendUtility.broadcastPacketAndReceive(
       effected, new SM_FORCED_MOVE(effect.getEffector(), effected));
 }
Exemple #7
0
 @Override
 public void onPeriodicAction(Effect effect) {
   Creature effected = effect.getEffected();
   Creature effector = effect.getEffector();
   int valueWithDelta = value + delta * effect.getSkillLevel();
   int damage =
       AttackUtil.calculateMagicalOverTimeSkillResult(
           effect, valueWithDelta, element, this.position);
   effected
       .getController()
       .onAttack(effector, effect.getSkillId(), TYPE.DAMAGE, damage, false, LOG.POISON);
   effected.getObserveController().notifyDotAttackedObservers(effector, effect);
 }
Exemple #8
0
  @Override
  public void calculate(Effect effect) {
    if (effect.getEffected() == null) return;
    if (!(effect.getEffector() instanceof Player)) return;

    if (!super.calculate(effect, DamageType.PHYSICAL)) return;

    Creature effected = effect.getEffected();
    effect.setDashStatus(DashStatus.DASH);
    effect
        .getSkill()
        .setTargetPosition(
            effected.getX(), effected.getY(), effected.getZ(), effected.getHeading());
  }
  /**
   * @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;
  }
  /**
   * @param player
   * @param target
   * @return
   */
  public static long calculateGroupExperienceReward(int maxLevelInRange, Creature target) {
    int targetLevel = target.getLevel();

    int baseXP = ((Npc) target).getObjectTemplate().getStatsTemplate().getMaxXp();
    int xpPercentage = XPRewardEnum.xpRewardFrom(targetLevel - maxLevelInRange);

    return (int) Math.floor(baseXP * xpPercentage / 100);
  }
  /**
   * @param player
   * @param target
   * @return XP reward from target
   */
  public static long calculateSoloExperienceReward(Player player, Creature target) {
    int playerLevel = player.getCommonData().getLevel();
    int targetLevel = target.getLevel();

    int baseXP = ((Npc) target).getObjectTemplate().getStatsTemplate().getMaxXp();
    int xpPercentage = XPRewardEnum.xpRewardFrom(targetLevel - playerLevel);

    return (int) Math.floor(baseXP * xpPercentage * player.getRates().getXpRate() / 100);
  }
  /**
   * 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;
  }
  /**
   * @param maxLevelInRange
   * @param target
   * @return
   */
  public static int calculateGroupAPReward(int maxLevelInRange, Creature target) {
    int targetLevel = target.getLevel();
    NpcRank npcRank = ((Npc) target).getObjectTemplate().getRank();

    // TODO: fix to see monster Rank level, NORMAL lvl 1, 2 | ELITE lvl 1, 2 etc..
    int baseAP = 10 + calculateRankMultipler(npcRank) - 1;

    int apPercentage = XPRewardEnum.xpRewardFrom(targetLevel - maxLevelInRange);

    return (int) Math.floor(baseAP * apPercentage / 100);
  }
  /**
   * @param player
   * @param target
   * @return DP reward
   */
  public static int calculateGroupDPReward(Player player, Creature target) {
    int playerLevel = player.getCommonData().getLevel();
    int targetLevel = target.getLevel();
    NpcRank npcRank = ((Npc) target).getObjectTemplate().getRank();

    // TODO: fix to see monster Rank level, NORMAL lvl 1, 2 | ELITE lvl 1, 2 etc..
    int baseDP = targetLevel * calculateRankMultipler(npcRank);

    int xpPercentage = XPRewardEnum.xpRewardFrom(targetLevel - playerLevel);

    return (int) Math.floor(baseDP * xpPercentage * player.getRates().getGroupXpRate() / 100);
  }
  @Override
  public void applyEffect(Effect effect) {
    super.applyEffect(effect);

    Creature effected = effect.getEffected();
    Effect placedSignet = effected.getEffectController().getAnormalEffect(signet);
    int nextSignetlvl = 1;
    if (placedSignet != null) {
      nextSignetlvl = placedSignet.getSkillId() - this.signetid + 2;
      if (nextSignetlvl > signetlvl || nextSignetlvl > 5) return;
      placedSignet.endEffect();
    }

    SkillTemplate template = DataManager.SKILL_DATA.getSkillTemplate(signetid + nextSignetlvl - 1);
    int effectsDuration = template.getEffectsDuration();
    Effect newEffect =
        new Effect(
            effect.getEffector(), effect.getEffected(), template, nextSignetlvl, effectsDuration);
    newEffect.initialize();
    newEffect.applyEffect();
  }
  /**
   * 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;
  }
  /**
   * ref:
   * http://www.aionsource.com/forum/mechanic-analysis/42597-character-stats-xp-dp-origin-gerbator-team-july-2009-a.html
   *
   * @param player
   * @param target
   * @return DP reward from target
   */
  public static int calculateSoloDPReward(Player player, Creature target) {
    int playerLevel = player.getCommonData().getLevel();
    int targetLevel = target.getLevel();
    NpcRank npcRank = ((Npc) target).getObjectTemplate().getRank();

    // TODO: fix to see monster Rank level, NORMAL lvl 1, 2 | ELITE lvl 1, 2 etc..
    // look at:
    // http://www.aionsource.com/forum/mechanic-analysis/42597-character-stats-xp-dp-origin-gerbator-team-july-2009-a.html
    int baseDP = targetLevel * calculateRankMultipler(npcRank);

    int xpPercentage = XPRewardEnum.xpRewardFrom(targetLevel - playerLevel);
    return (int) Math.floor(baseDP * xpPercentage * player.getRates().getXpRate() / 100);
  }
  /**
   * 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;
  }
Exemple #21
0
  @Override
  public boolean onDie(Player player, Creature lastAttacker) {
    Summon summon = player.getSummon();
    if (summon != null) {
      summon.getController().release(UnsummonType.UNSPECIFIED);
    }

    PacketSendUtility.broadcastPacket(
        player,
        new SM_EMOTION(
            player, EmotionType.DIE, 0, lastAttacker == null ? 0 : lastAttacker.getObjectId()),
        true);

    PacketSendUtility.sendPacket(player, new SM_DIE(false, false, 0, 8));
    return true;
  }
  @Override
  public void onAttack(
      final Creature creature,
      int skillId,
      TYPE type,
      int damage,
      boolean notifyAttackedObservers) {
    if (getOwner().getLifeStats().isAlreadyDead()) return;

    super.onAttack(creature, skillId, type, damage, notifyAttackedObservers);

    Npc npc = getOwner();

    Creature actingCreature = creature.getActingCreature();
    if (actingCreature instanceof Player)
      if (QuestEngine.getInstance().onAttack(new QuestCookie(npc, (Player) actingCreature, 0, 0)))
        return;

    AI<?> ai = npc.getAi();
    if (ai instanceof DummyAi) {
      log.warn("CHECKPOINT: npc attacked without ai " + npc.getObjectTemplate().getTemplateId());
      return;
    }
    if (getOwner().getTribe().equals("DUMMY")) damage = 0;

    getOwner()
        .getKnownList()
        .doOnAllNpcs(
            new Executor<Npc>() {
              @Override
              public boolean run(Npc tmp) {
                if (getOwner().isSupportFrom(tmp) && MathUtil.isInRange(getOwner(), tmp, 10)) {
                  tmp.getAggroList().addHate(creature, 10);
                }
                return true;
              }
            },
            true);

    npc.getLifeStats().reduceHp(damage, actingCreature);

    PacketSendUtility.broadcastPacket(npc, new SM_ATTACK_STATUS(npc, type, skillId, damage));
  }
  /** {@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());
    }
  }
 /**
  * @param player
  * @param target
  * @return AP reward
  */
 public static int calculateSoloAPReward(Player player, Creature target) {
   int playerLevel = player.getCommonData().getLevel();
   int targetLevel = target.getLevel();
   int percentage = XPRewardEnum.xpRewardFrom(targetLevel - playerLevel);
   return (int) Math.floor(10 * percentage * player.getRates().getApNpcRate() / 100);
 }
 /**
  * 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);
 }
 public void broadCastEffects() {
   owner.addPacketBroadcastMask(BroadcastMode.BROAD_CAST_EFFECTS);
 }
  /**
   * @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;
  }