/* * 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.gameserver.skills.effects; import silentium.commons.utils.Rnd; import silentium.gameserver.model.L2Effect; import silentium.gameserver.model.actor.L2Character; import silentium.gameserver.model.actor.instance.L2PcInstance; import silentium.gameserver.skills.Env; import silentium.gameserver.skills.Formulas; import silentium.gameserver.templates.skills.L2EffectType; /** * @author DS */ public class EffectCancel extends L2Effect { public EffectCancel(Env env, EffectTemplate template) { super(env, template); } @Override public L2EffectType getEffectType() { return L2EffectType.CANCEL; } @Override public boolean onStart() { return cancel(getEffector(), getEffected(), this); } @Override public boolean onActionTime() { return false; } private static boolean cancel(L2Character caster, L2Character target, L2Effect effect) { if (!(target instanceof L2PcInstance) || target.isDead()) return false; final int cancelLvl = effect.getSkill().getMagicLevel(); int count = effect.getSkill().getMaxNegatedEffects(); double rate = effect.getEffectPower(); // Resistance/vulnerability final double res = Formulas.calcSkillVulnerability(caster, target, effect.getSkill(), effect.getSkillType()); rate *= res; L2Effect eff; int lastCanceledSkillId = 0; final L2Effect[] effects = target.getAllEffects(); for (int i = effects.length; --i >= 0;) { eff = effects[i]; if (eff == null) continue; // first pass - dances/songs only if (!eff.getSkill().isDance()) continue; if (eff.getSkill().getId() == lastCanceledSkillId) { eff.exit(); // this skill already canceled continue; } if (!calcCancelSuccess(eff, cancelLvl, (int) rate)) continue; lastCanceledSkillId = eff.getSkill().getId(); eff.exit(); count--; if (count == 0) break; } if (count != 0) { lastCanceledSkillId = 0; for (int i = effects.length; --i >= 0;) { eff = effects[i]; if (eff == null) continue; // second pass - all except dances/songs if (eff.getSkill().isDance()) continue; if (eff.getSkill().getId() == lastCanceledSkillId) { eff.exit(); // this skill already canceled continue; } if (!calcCancelSuccess(eff, cancelLvl, (int) rate)) continue; lastCanceledSkillId = eff.getSkill().getId(); eff.exit(); count--; if (count == 0) break; } } return true; } private static boolean calcCancelSuccess(L2Effect effect, int cancelLvl, int baseRate) { int rate = 2 * (cancelLvl - effect.getSkill().getMagicLevel()); rate += effect.getPeriod() / 120; rate += baseRate; if (rate < 25) rate = 25; else if (rate > 75) rate = 75; return Rnd.get(100) < rate; } }