Index: /java/net/sf/l2j/gameserver/skills/Formulas.java =================================================================== --- /java/net/sf/l2j/gameserver/skills/Formulas.java (revision 1494) +++ /java/net/sf/l2j/gameserver/skills/Formulas.java (working copy) @@ -31,7 +31,6 @@ import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance; import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance; import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; -import net.sf.l2j.gameserver.model.actor.instance.L2PlayableInstance; import net.sf.l2j.gameserver.model.actor.instance.L2RaidBossInstance; import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance; import net.sf.l2j.gameserver.model.L2SiegeClan; @@ -40,7 +39,6 @@ import net.sf.l2j.gameserver.model.L2Skill.SkillType; import net.sf.l2j.gameserver.skills.ConditionPlayerState.CheckPlayerState; import net.sf.l2j.gameserver.templates.L2PcTemplate; -import net.sf.l2j.gameserver.templates.L2Armor; import net.sf.l2j.gameserver.templates.L2Weapon; import net.sf.l2j.gameserver.templates.L2WeaponType; import net.sf.l2j.gameserver.util.Util; @@ -1024,57 +1022,19 @@ mAtk *= 2; //double damage = Math.sqrt(mAtk/mDef)*skill.getPower()*10.18; - double damage = (91*Math.sqrt(mAtk)*skill.getPower(attacker))/mDef; - //double damage = 40/Math.pow(mAtk*mDef,1./6)*Math.sqrt(mAtk/mDef)*skill.getPower(attacker); + //double damage = 91*Math.sqrt(mAtk)/mDef*skill.getPower(attacker); //double damage = 5*Math.sqrt(mAtk/mDef)*skill.getPower(attacker); -// if(attacker instanceof L2PcInstance && target instanceof L2PcInstance) damage *= 0.9; // PvP modifier (-10%) + double damage = 40/Math.pow(mAtk*mDef,1./6)*Math.sqrt(mAtk/mDef)*skill.getPower(attacker); + if(attacker instanceof L2PcInstance && target instanceof L2PcInstance) damage *= 0.9; // PvP modifier (-10%) if(mcrit) damage *= 4; - if (target instanceof L2RaidBossInstance) - { - int cLevel = attacker.getLevel(); - int tLevel = target.getLevel(); - int rDamage = 1; - if ( cLevel > tLevel ) - { - rDamage = cLevel - tLevel; - if (rDamage > 9) - damage /= rDamage; - if (damage < 1) - damage = 1; - } - } - - if (target instanceof L2PlayableInstance && attacker instanceof L2RaidBossInstance) - { - int cLevel = attacker.getLevel(); - int tLevel = target.getLevel(); - int rDamage = 1; - if ( cLevel < tLevel ) - { - rDamage = tLevel - cLevel; - if (rDamage > 9) - damage *= rDamage; - } - } - - if (Config.ALT_GAME_MAGICFAILURES) // Failure calculation + // Failure calculation + if (Config.ALT_GAME_MAGICFAILURES && !calcMagicSuccess(attacker, target, skill)) { - /* Level difference: - * less then 7 : full chance - * 7 - 20 : reduced chance - * 20 and more : min chance - */ - // TODO: Temporary fix for skills with Power = 0 or LevelDepend not set - int rate = (int)(200 - 10 * (target.getLevel() - (skill.getMagicLevel()>0?skill.getMagicLevel():attacker.getLevel()))); - - if (target.isRaid()) rate /= 2; // chance is reduced for RaidBoss - - if (rate > 123) rate = 123; - if (rate < 1) rate = 1; - int check = _rnd.get(100); - if (rate <= check) damage = 1; - else if (rate <= check +25) damage /= 2; + if (attacker instanceof L2PcInstance) ((L2PcInstance)attacker).sendMessage("Attack failed"); + if (calcMagicSuccess(attacker, target, skill)) + damage /= 2; + else damage = 1; } return damage; @@ -1148,7 +1108,7 @@ return d > 0; } - public boolean calcSkillSuccess(L2Character player, L2Character target, L2Skill skill, boolean ss, boolean sps, boolean bss ) + public boolean calcSkillSuccessOld(L2Character player, L2Character target, L2Skill skill, boolean ss, boolean sps, boolean bss ) { if(Config.ALT_GAME_SKILL_FORMULAS.equalsIgnoreCase("alt") || Config.ALT_GAME_SKILL_FORMULAS.equalsIgnoreCase("true")) @@ -1358,6 +1318,129 @@ return success; } + public int calcSkillResistance(SkillType type, L2Character target) + { + if (type == null) return 0; + switch(type) + { + case BLEED: return (int) target.calcStat(Stats.BLEED_RES, 0, target, null); + case POISON: return (int) target.calcStat(Stats.POISON_RES, 0, target, null); + case STUN: return (int) target.calcStat(Stats.STUN_RES, 0, target, null); + case PARALYZE: return (int) target.calcStat(Stats.PARALYZE_RES, 0, target, null); + case ROOT: return (int) target.calcStat(Stats.ROOT_RES, 0, target, null); + case SLEEP: return (int) target.calcStat(Stats.SLEEP_RES, 0, target, null); + case MUTE: return (int) target.calcStat(Stats.MUTE_RES, 0, target, null); + case FEAR: + case CONFUSION: return (int) target.calcStat(Stats.CONFUSION_RES, 0, target, null); + default: return 0; + } + } + + public int calcSkillStatModifier(SkillType type, L2Character target) + { + if (type == null) return 0; + switch(type) + { + case STUN: return target.getCON(); + case ROOT: return target.getDEX(); + case SLEEP: return target.getWIT(); + case MUTE: + case CONFUSION: + case PARALYZE: return target.getMEN(); + default: return 0; + } + } + + public boolean calcSkillSuccess(L2Character attacker, L2Character target, L2Skill skill, boolean ss, boolean sps, boolean bss) + { + if(Config.ALT_GAME_SKILL_FORMULAS.equalsIgnoreCase("alt") || Config.ALT_GAME_SKILL_FORMULAS.equalsIgnoreCase("true")) + return calcAltSkillSuccess(attacker, target, skill); + + // Uncomment this if you want to revert to old skill success calculation: + // return calcSkillSuccessOld(attacker, target, skill, ss, sps, bss); + + SkillType type = skill.getSkillType(); + + if (target.isRaid() && (type == SkillType.CONFUSION || type == SkillType.MUTE || type == SkillType.PARALYZE || type == SkillType.ROOT)) + return false; // these skills should not work on RaidBoss + + int value = (int)skill.getPower(); + int lvlDepend = skill.getLevelDepend(); + + if (type == SkillType.PDAM || type == SkillType.MDAM) // For additional effects on PDAM skills (like STUN, SHOCK,...) + { + value = skill.getEffectPower(); + type = skill.getEffectType(); + } + // TODO: Temporary fix for skills with EffectPower = 0 or EffectType not set + if (value == 0 || type == null) + { + if (skill.getSkillType() == SkillType.PDAM) + { + value = 50; + type = SkillType.STUN; + } + if (skill.getSkillType() == SkillType.MDAM) + { + value = 30; + type = SkillType.PARALYZE; + } + } + + // TODO: Temporary fix for skills with Power = 0 or LevelDepend not set + if(value == 0) value = (type == SkillType.PARALYZE)? 50 : 80; + if(lvlDepend == 0) lvlDepend = (type == SkillType.PARALYZE)? 1 : 2; + + // TODO: Temporary fix for NPC skills with MagicLevel not set + // int lvlmodifier = (skill.getMagicLevel() - target.getLevel()) * lvlDepend; + int lvlmodifier = ((skill.getMagicLevel()>0?skill.getMagicLevel():attacker.getLevel()) - target.getLevel()) * lvlDepend; + int statmodifier = calcSkillStatModifier(type, target); + + int ssmodifier = 100; + if (bss) ssmodifier = 200; + else if (sps) ssmodifier = 150; + else if (ss) ssmodifier = 150; + + int rate = value + lvlmodifier - calcSkillResistance(type, target); + if (skill.isMagic()) rate *= Math.sqrt((double)attacker.getMAtk(target, skill)/target.getMDef(attacker, skill)); + if (statmodifier > 0) rate = rate * (100 - statmodifier) / 100; + + if (rate > 99) rate = 99; + else if (rate < 1) rate = 1; + + if (ssmodifier != 100) + { + if (rate > 10000/(100+ssmodifier)) + rate = 100-(100-rate)*100/ssmodifier; + else rate = rate*ssmodifier/100; + } + + if(Config.DEVELOPER) System.out.println(skill.getName() + ": " + value + ", " + lvlmodifier + ", " + calcSkillResistance(type, target) + ", " + statmodifier + ", " + ssmodifier + ", " + Math.sqrt((double)attacker.getMAtk(target, skill)/target.getMDef(attacker, skill)) + " ==> " + rate); + return (Rnd.get(100) < rate); + } + + public boolean calcMagicSuccess(L2Character attacker, L2Character target, L2Skill skill) + { + /* Level difference: + * less then 10 : full chance + * 10 - 20 : reduced chance + * 20 and more : min chance + */ + int value = target.isRaid()? 100 : 200; // chance is reduced for RaidBoss + int lvlDepend = 10; + + // TODO: Temporary fix for NPC skills with MagicLevel not set + // int lvlmodifier = (skill.getMagicLevel() - target.getLevel()) * lvlDepend; + int lvlmodifier = ((skill.getMagicLevel()>0?skill.getMagicLevel():attacker.getLevel()) - target.getLevel()) * lvlDepend; + + int rate = value + lvlmodifier; + + if (rate > 99) rate = 99; + else if (rate < 1) rate = 1; + + return (Rnd.get(100) < rate); + } + public boolean calcAltSkillSuccess(L2Character activeChar, L2Character target, L2Skill skill) { // Get our numbers and base success rate