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