Cancel.java 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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.actor.L2Character;
  20. import com.l2jserver.gameserver.model.actor.L2Npc;
  21. import com.l2jserver.gameserver.model.actor.L2Summon;
  22. import com.l2jserver.gameserver.model.effects.L2Effect;
  23. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  24. import com.l2jserver.gameserver.model.skills.L2Skill;
  25. import com.l2jserver.gameserver.model.skills.L2SkillType;
  26. import com.l2jserver.gameserver.model.stats.Formulas;
  27. import com.l2jserver.gameserver.model.stats.Stats;
  28. import com.l2jserver.util.Rnd;
  29. import com.l2jserver.util.StringUtil;
  30. /**
  31. * @author DS
  32. */
  33. public class Cancel implements ISkillHandler
  34. {
  35. private static final L2SkillType[] SKILL_IDS =
  36. {
  37. L2SkillType.CANCEL,
  38. };
  39. @Override
  40. public void useSkill(L2Character activeChar, L2Skill skill, L2Object[] targets)
  41. {
  42. final L2ItemInstance weaponInst = activeChar.getActiveWeaponInstance();
  43. if (weaponInst != null)
  44. {
  45. if (skill.isMagic())
  46. {
  47. if (weaponInst.getChargedSpiritshot() == L2ItemInstance.CHARGED_BLESSED_SPIRITSHOT)
  48. weaponInst.setChargedSpiritshot(L2ItemInstance.CHARGED_NONE);
  49. else if (weaponInst.getChargedSpiritshot() == L2ItemInstance.CHARGED_SPIRITSHOT)
  50. weaponInst.setChargedSpiritshot(L2ItemInstance.CHARGED_NONE);
  51. }
  52. }
  53. else if (activeChar instanceof L2Summon)
  54. {
  55. final L2Summon activeSummon = (L2Summon) activeChar;
  56. if (skill.isMagic())
  57. {
  58. if (activeSummon.getChargedSpiritShot() == L2ItemInstance.CHARGED_BLESSED_SPIRITSHOT)
  59. activeSummon.setChargedSpiritShot(L2ItemInstance.CHARGED_NONE);
  60. else if (activeSummon.getChargedSpiritShot() == L2ItemInstance.CHARGED_SPIRITSHOT)
  61. activeSummon.setChargedSpiritShot(L2ItemInstance.CHARGED_NONE);
  62. }
  63. }
  64. else if (activeChar instanceof L2Npc)
  65. {
  66. ((L2Npc)activeChar)._soulshotcharged = false;
  67. ((L2Npc)activeChar)._spiritshotcharged = false;
  68. }
  69. L2Character target;
  70. L2Effect effect;
  71. final int cancelLvl, minRate, maxRate;
  72. cancelLvl = skill.getMagicLevel();
  73. minRate = 25;
  74. maxRate = 80;
  75. for (L2Object obj : targets)
  76. {
  77. if (!(obj instanceof L2Character))
  78. continue;
  79. target = (L2Character)obj;
  80. if (target.isDead())
  81. continue;
  82. int lastCanceledSkillId = 0;
  83. int count = skill.getMaxNegatedEffects();
  84. double rate = skill.getPower();
  85. final double vulnModifier = target.calcStat(Stats.CANCEL_VULN, 0, target, null);
  86. final double profModifier = activeChar.calcStat(Stats.CANCEL_PROF, 0, target, null);
  87. double res = vulnModifier + profModifier;
  88. double resMod = 1;
  89. if (res != 0)
  90. {
  91. if (res < 0)
  92. {
  93. resMod = 1 - 0.075 * res;
  94. resMod = 1 / resMod;
  95. }
  96. else
  97. resMod = 1 + 0.02 * res;
  98. rate *= resMod;
  99. }
  100. if (activeChar.isDebug())
  101. {
  102. final StringBuilder stat = new StringBuilder(100);
  103. StringUtil.append(stat,
  104. skill.getName(),
  105. " power:", String.valueOf((int)skill.getPower()),
  106. " lvl:", String.valueOf(cancelLvl),
  107. " res:", String.format("%1.2f", resMod), "(",
  108. String.format("%1.2f", profModifier), "/",
  109. String.format("%1.2f", vulnModifier),
  110. ") total:", String.valueOf(rate)
  111. );
  112. final String result = stat.toString();
  113. if (activeChar.isDebug())
  114. activeChar.sendDebugMessage(result);
  115. if (Config.DEVELOPER)
  116. _log.info(result);
  117. }
  118. final L2Effect[] effects = target.getAllEffects();
  119. if (skill.getNegateAbnormals() != null) // Cancel for abnormals
  120. {
  121. for (L2Effect eff : effects)
  122. {
  123. if (eff == null)
  124. continue;
  125. for (String negateAbnormalType : skill.getNegateAbnormals().keySet())
  126. {
  127. if (negateAbnormalType.equalsIgnoreCase(eff.getAbnormalType()) && skill.getNegateAbnormals().get(negateAbnormalType) >= eff.getAbnormalLvl())
  128. {
  129. if (calcCancelSuccess(eff, cancelLvl, (int)rate, minRate, maxRate))
  130. eff.exit();
  131. }
  132. }
  133. }
  134. }
  135. else
  136. {
  137. for (int i = effects.length; --i >= 0;)
  138. {
  139. effect = effects[i];
  140. if (effect == null)
  141. continue;
  142. if (!effect.canBeStolen())
  143. {
  144. effects[i] = null;
  145. continue;
  146. }
  147. // first pass - dances/songs only
  148. if (!effect.getSkill().isDance())
  149. continue;
  150. if (effect.getSkill().getId() == lastCanceledSkillId)
  151. {
  152. effect.exit(); // this skill already canceled
  153. continue;
  154. }
  155. if (!calcCancelSuccess(effect, cancelLvl, (int)rate, minRate, maxRate))
  156. continue;
  157. lastCanceledSkillId = effect.getSkill().getId();
  158. effect.exit();
  159. count--;
  160. if (count == 0)
  161. break;
  162. }
  163. if (count != 0)
  164. {
  165. lastCanceledSkillId = 0;
  166. for (int i = effects.length; --i >= 0;)
  167. {
  168. effect = effects[i];
  169. if (effect == null)
  170. continue;
  171. // second pass - all except dances/songs
  172. if (effect.getSkill().isDance())
  173. continue;
  174. if (effect.getSkill().getId() == lastCanceledSkillId)
  175. {
  176. effect.exit(); // this skill already canceled
  177. continue;
  178. }
  179. if (!calcCancelSuccess(effect, cancelLvl, (int)rate, minRate, maxRate))
  180. continue;
  181. lastCanceledSkillId = effect.getSkill().getId();
  182. effect.exit();
  183. count--;
  184. if (count == 0)
  185. break;
  186. }
  187. }
  188. }
  189. //Possibility of a lethal strike
  190. Formulas.calcLethalHit(activeChar, target, skill);
  191. }
  192. // Applying self-effects
  193. if (skill.hasSelfEffects())
  194. {
  195. effect = activeChar.getFirstEffect(skill.getId());
  196. if (effect != null && effect.isSelfEffect())
  197. {
  198. //Replace old effect with new one.
  199. effect.exit();
  200. }
  201. skill.getEffectsSelf(activeChar);
  202. }
  203. }
  204. private boolean calcCancelSuccess(L2Effect effect, int cancelLvl, int baseRate, int minRate, int maxRate)
  205. {
  206. int rate = 2 * (cancelLvl - effect.getSkill().getMagicLevel());
  207. rate += effect.getAbnormalTime()/120;
  208. rate += baseRate;
  209. if (rate < minRate)
  210. rate = minRate;
  211. else if (rate > maxRate)
  212. rate = maxRate;
  213. return Rnd.get(100) < rate;
  214. }
  215. @Override
  216. public L2SkillType[] getSkillIds()
  217. {
  218. return SKILL_IDS;
  219. }
  220. }