/** * @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; }
@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)); }
@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); }
@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; }
@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; }