Cancel.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package handlers.skillhandlers;
  16. import com.l2jserver.Config;
  17. import com.l2jserver.gameserver.handler.ISkillHandler;
  18. import com.l2jserver.gameserver.model.L2Object;
  19. import com.l2jserver.gameserver.model.ShotType;
  20. import com.l2jserver.gameserver.model.actor.L2Character;
  21. import com.l2jserver.gameserver.model.effects.L2Effect;
  22. import com.l2jserver.gameserver.model.skills.L2Skill;
  23. import com.l2jserver.gameserver.model.skills.L2SkillType;
  24. import com.l2jserver.gameserver.model.stats.Formulas;
  25. import com.l2jserver.gameserver.model.stats.Stats;
  26. import com.l2jserver.util.Rnd;
  27. import com.l2jserver.util.StringUtil;
  28. /**
  29. * @author DS
  30. */
  31. public class Cancel implements ISkillHandler
  32. {
  33. private static final L2SkillType[] SKILL_IDS =
  34. {
  35. L2SkillType.CANCEL,
  36. };
  37. @Override
  38. public void useSkill(L2Character activeChar, L2Skill skill, L2Object[] targets)
  39. {
  40. L2Character target;
  41. L2Effect effect;
  42. final int cancelLvl, minRate, maxRate;
  43. cancelLvl = skill.getMagicLevel();
  44. minRate = 25;
  45. maxRate = 80;
  46. for (L2Object obj : targets)
  47. {
  48. if (!(obj instanceof L2Character))
  49. continue;
  50. target = (L2Character)obj;
  51. if (target.isDead())
  52. continue;
  53. int lastCanceledSkillId = 0;
  54. int count = skill.getMaxNegatedEffects();
  55. double rate = skill.getPower();
  56. final double vulnModifier = target.calcStat(Stats.CANCEL_VULN, 0, target, null);
  57. final double profModifier = activeChar.calcStat(Stats.CANCEL_PROF, 0, target, null);
  58. double res = vulnModifier + profModifier;
  59. double resMod = 1;
  60. if (res != 0)
  61. {
  62. if (res < 0)
  63. {
  64. resMod = 1 - 0.075 * res;
  65. resMod = 1 / resMod;
  66. }
  67. else
  68. resMod = 1 + 0.02 * res;
  69. rate *= resMod;
  70. }
  71. if (activeChar.isDebug())
  72. {
  73. final StringBuilder stat = new StringBuilder(100);
  74. StringUtil.append(stat,
  75. skill.getName(),
  76. " power:", String.valueOf((int)skill.getPower()),
  77. " lvl:", String.valueOf(cancelLvl),
  78. " res:", String.format("%1.2f", resMod), "(",
  79. String.format("%1.2f", profModifier), "/",
  80. String.format("%1.2f", vulnModifier),
  81. ") total:", String.valueOf(rate)
  82. );
  83. final String result = stat.toString();
  84. if (activeChar.isDebug())
  85. activeChar.sendDebugMessage(result);
  86. if (Config.DEVELOPER)
  87. _log.info(result);
  88. }
  89. final L2Effect[] effects = target.getAllEffects();
  90. if (skill.getNegateAbnormals() != null) // Cancel for abnormals
  91. {
  92. for (L2Effect eff : effects)
  93. {
  94. if (eff == null)
  95. continue;
  96. for (String negateAbnormalType : skill.getNegateAbnormals().keySet())
  97. {
  98. if (negateAbnormalType.equalsIgnoreCase(eff.getAbnormalType()) && skill.getNegateAbnormals().get(negateAbnormalType) >= eff.getAbnormalLvl())
  99. {
  100. if (calcCancelSuccess(eff, cancelLvl, (int)rate, minRate, maxRate))
  101. eff.exit();
  102. }
  103. }
  104. }
  105. }
  106. else
  107. {
  108. for (int i = effects.length; --i >= 0;)
  109. {
  110. effect = effects[i];
  111. if (effect == null)
  112. continue;
  113. if (!effect.canBeStolen())
  114. {
  115. effects[i] = null;
  116. continue;
  117. }
  118. // first pass - dances/songs only
  119. if (!effect.getSkill().isDance())
  120. continue;
  121. if (effect.getSkill().getId() == lastCanceledSkillId)
  122. {
  123. effect.exit(); // this skill already canceled
  124. continue;
  125. }
  126. if (!calcCancelSuccess(effect, cancelLvl, (int)rate, minRate, maxRate))
  127. continue;
  128. lastCanceledSkillId = effect.getSkill().getId();
  129. effect.exit();
  130. count--;
  131. if (count == 0)
  132. break;
  133. }
  134. if (count != 0)
  135. {
  136. lastCanceledSkillId = 0;
  137. for (int i = effects.length; --i >= 0;)
  138. {
  139. effect = effects[i];
  140. if (effect == null)
  141. continue;
  142. // second pass - all except dances/songs
  143. if (effect.getSkill().isDance())
  144. continue;
  145. if (effect.getSkill().getId() == lastCanceledSkillId)
  146. {
  147. effect.exit(); // this skill already canceled
  148. continue;
  149. }
  150. if (!calcCancelSuccess(effect, cancelLvl, (int)rate, minRate, maxRate))
  151. continue;
  152. lastCanceledSkillId = effect.getSkill().getId();
  153. effect.exit();
  154. count--;
  155. if (count == 0)
  156. break;
  157. }
  158. }
  159. }
  160. //Possibility of a lethal strike
  161. Formulas.calcLethalHit(activeChar, target, skill);
  162. }
  163. // Applying self-effects
  164. if (skill.hasSelfEffects())
  165. {
  166. effect = activeChar.getFirstEffect(skill.getId());
  167. if (effect != null && effect.isSelfEffect())
  168. {
  169. //Replace old effect with new one.
  170. effect.exit();
  171. }
  172. skill.getEffectsSelf(activeChar);
  173. }
  174. activeChar.setChargedShot(activeChar.isChargedShot(ShotType.BLESSED_SPIRITSHOTS) ? ShotType.BLESSED_SPIRITSHOTS : ShotType.SPIRITSHOTS, false);
  175. }
  176. private boolean calcCancelSuccess(L2Effect effect, int cancelLvl, int baseRate, int minRate, int maxRate)
  177. {
  178. int rate = 2 * (cancelLvl - effect.getSkill().getMagicLevel());
  179. rate += effect.getAbnormalTime()/120;
  180. rate += baseRate;
  181. if (rate < minRate)
  182. rate = minRate;
  183. else if (rate > maxRate)
  184. rate = maxRate;
  185. return Rnd.get(100) < rate;
  186. }
  187. @Override
  188. public L2SkillType[] getSkillIds()
  189. {
  190. return SKILL_IDS;
  191. }
  192. }