/* * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If * not, see <http://www.gnu.org/licenses/>. */ package silentium.scripts.handlers.skill; import silentium.commons.utils.Rnd; import silentium.gameserver.handler.ISkillHandler; import silentium.gameserver.model.L2Effect; import silentium.gameserver.model.L2ItemInstance; import silentium.gameserver.model.L2Object; import silentium.gameserver.model.L2Skill; import silentium.gameserver.model.actor.L2Character; import silentium.gameserver.model.actor.L2Npc; import silentium.gameserver.model.actor.L2Summon; import silentium.gameserver.skills.Formulas; import silentium.gameserver.templates.skills.L2SkillType; /** * @author DS */ public class Cancel implements ISkillHandler { private static final L2SkillType[] SKILL_IDS = { L2SkillType.CANCEL, L2SkillType.MAGE_BANE, L2SkillType.WARRIOR_BANE }; /** * @see silentium.gameserver.handler.ISkillHandler#useSkill(silentium.gameserver.model.actor.L2Character, silentium.gameserver.model.L2Skill, * silentium.gameserver.model.L2Object[]) */ @Override public void useSkill(final L2Character activeChar, final L2Skill skill, final L2Object... targets) { final L2ItemInstance weaponInst = activeChar.getActiveWeaponInstance(); if (weaponInst != null) { if (skill.isMagic()) { if (weaponInst.getChargedSpiritshot() == L2ItemInstance.CHARGED_BLESSED_SPIRITSHOT) weaponInst.setChargedSpiritshot(L2ItemInstance.CHARGED_NONE); else if (weaponInst.getChargedSpiritshot() == L2ItemInstance.CHARGED_SPIRITSHOT) weaponInst.setChargedSpiritshot(L2ItemInstance.CHARGED_NONE); } } else if (activeChar instanceof L2Summon) { final L2Summon activeSummon = (L2Summon) activeChar; if (skill.isMagic()) { if (activeSummon.getChargedSpiritShot() == L2ItemInstance.CHARGED_BLESSED_SPIRITSHOT) activeSummon.setChargedSpiritShot(L2ItemInstance.CHARGED_NONE); else if (activeSummon.getChargedSpiritShot() == L2ItemInstance.CHARGED_SPIRITSHOT) activeSummon.setChargedSpiritShot(L2ItemInstance.CHARGED_NONE); } } else if (activeChar instanceof L2Npc) { ((L2Npc) activeChar)._soulshotcharged = false; ((L2Npc) activeChar)._spiritshotcharged = false; } L2Character target; L2Effect effect; final int cancelLvl, minRate, maxRate; cancelLvl = skill.getMagicLevel(); switch (skill.getSkillType()) { case MAGE_BANE: case WARRIOR_BANE: minRate = 40; maxRate = 95; break; default: minRate = 25; maxRate = 75; break; } for (final L2Object obj : targets) { if (!(obj instanceof L2Character)) continue; target = (L2Character) obj; if (target.isDead()) continue; int lastCanceledSkillId = 0; int count = skill.getMaxNegatedEffects(); double rate = skill.getPower(); // Resistance/vulnerability final double res = Formulas.calcSkillVulnerability(activeChar, target, skill, skill.getSkillType()); rate *= res; final L2Effect[] effects = target.getAllEffects(); for (int i = effects.length; --i >= 0; ) { effect = effects[i]; if (effect == null) continue; switch (skill.getSkillType()) { case MAGE_BANE: if ("casting_time_down".equalsIgnoreCase(effect.getStackType())) break; if ("ma_up".equalsIgnoreCase(effect.getStackType())) break; effects[i] = null; continue; case WARRIOR_BANE: if ("attack_time_down".equalsIgnoreCase(effect.getStackType())) break; if ("speed_up".equalsIgnoreCase(effect.getStackType())) break; effects[i] = null; continue; } if (effect.getSkill().getId() == lastCanceledSkillId) { effect.exit(); // this skill already canceled continue; } if (!calcCancelSuccess(effect, cancelLvl, (int) rate, minRate, maxRate)) continue; lastCanceledSkillId = effect.getSkill().getId(); effect.exit(); count--; if (count == 0) break; } // Possibility of a lethal strike Formulas.calcLethalHit(activeChar, target, skill); } // Applying self-effects if (skill.hasSelfEffects()) { effect = activeChar.getFirstEffect(skill.getId()); if (effect != null && effect.isSelfEffect()) { // Replace old effect with new one. effect.exit(); } skill.getEffectsSelf(activeChar); } } private static boolean calcCancelSuccess(final L2Effect effect, final int cancelLvl, final int baseRate, final int minRate, final int maxRate) { int rate = 2 * (cancelLvl - effect.getSkill().getMagicLevel()); rate += effect.getPeriod() / 120; rate += baseRate; if (rate < minRate) rate = minRate; else if (rate > maxRate) rate = maxRate; return Rnd.get(100) < rate; } /** * @see silentium.gameserver.handler.ISkillHandler#getSkillIds() */ @Override public L2SkillType[] getSkillIds() { return SKILL_IDS; } }