Cancel.java 7.3 KB

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