/* * 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.model; import javolution.util.FastMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import silentium.gameserver.handler.ISkillHandler; import silentium.gameserver.handler.SkillHandler; import silentium.gameserver.model.actor.L2Character; import silentium.gameserver.network.serverpackets.MagicSkillLaunched; import silentium.gameserver.network.serverpackets.MagicSkillUse; import silentium.gameserver.skills.effects.EffectChanceSkillTrigger; import silentium.gameserver.tables.SkillTable; import silentium.gameserver.templates.skills.L2SkillType; /** * CT2.3: Added support for allowing effect as a chance skill trigger (DrHouse) * * @author kombat */ public class ChanceSkillList extends FastMap<IChanceSkillTrigger, ChanceCondition> { protected static final Logger _log = LoggerFactory.getLogger(ChanceSkillList.class.getName()); private static final long serialVersionUID = 1L; private final L2Character _owner; public ChanceSkillList(L2Character owner) { super(); shared(); _owner = owner; } public L2Character getOwner() { return _owner; } public void onHit(L2Character target, int damage, boolean ownerWasHit, boolean wasCrit) { int event; if (ownerWasHit) { event = ChanceCondition.EVT_ATTACKED | ChanceCondition.EVT_ATTACKED_HIT; if (wasCrit) event |= ChanceCondition.EVT_ATTACKED_CRIT; } else { event = ChanceCondition.EVT_HIT; if (wasCrit) event |= ChanceCondition.EVT_CRIT; } onEvent(event, damage, target); } public void onEvadedHit(L2Character attacker) { onEvent(ChanceCondition.EVT_EVADED_HIT, 0, attacker); } public void onSkillHit(L2Character target, boolean ownerWasHit, boolean wasMagic, boolean wasOffensive, byte element) { int event; if (ownerWasHit) { event = ChanceCondition.EVT_HIT_BY_SKILL; if (wasOffensive) { event |= ChanceCondition.EVT_HIT_BY_OFFENSIVE_SKILL; event |= ChanceCondition.EVT_ATTACKED; } else { event |= ChanceCondition.EVT_HIT_BY_GOOD_MAGIC; } } else { event = ChanceCondition.EVT_CAST; event |= wasMagic ? ChanceCondition.EVT_MAGIC : ChanceCondition.EVT_PHYSICAL; event |= wasOffensive ? ChanceCondition.EVT_MAGIC_OFFENSIVE : ChanceCondition.EVT_MAGIC_GOOD; } onEvent(event, 0, target); } public void onStart() { onEvent(ChanceCondition.EVT_ON_START, 0, _owner); } public void onActionTime() { onEvent(ChanceCondition.EVT_ON_ACTION_TIME, 0, _owner); } public void onExit() { onEvent(ChanceCondition.EVT_ON_EXIT, 0, _owner); } public void onEvent(int event, int damage, L2Character target) { if (_owner.isDead()) return; for (FastMap.Entry<IChanceSkillTrigger, ChanceCondition> e = head(), end = tail(); (e = e.getNext()) != end;) { if (e.getValue() != null && e.getValue().trigger(event, damage)) { if (e.getKey() instanceof L2Skill) makeCast((L2Skill) e.getKey(), target); else if (e.getKey() instanceof EffectChanceSkillTrigger) makeCast((EffectChanceSkillTrigger) e.getKey(), target); } } } private void makeCast(L2Skill skill, L2Character target) { try { if (skill.getWeaponDependancy(_owner) && skill.checkCondition(_owner, target, false)) { if (skill.triggersChanceSkill()) // skill will trigger another skill, but only if its not chance skill { skill = SkillTable.getInstance().getInfo(skill.getTriggeredChanceId(), skill.getTriggeredChanceLevel()); if (skill == null || skill.getSkillType() == L2SkillType.NOTDONE) return; } if (_owner.isSkillDisabled(skill)) return; if (skill.getReuseDelay() > 0) _owner.disableSkill(skill, skill.getReuseDelay()); L2Object[] targets = skill.getTargetList(_owner, false, target); if (targets.length == 0) return; L2Character firstTarget = (L2Character) targets[0]; ISkillHandler handler = SkillHandler.getInstance().getSkillHandler(skill.getSkillType()); _owner.broadcastPacket(new MagicSkillLaunched(_owner, skill.getDisplayId(), skill.getLevel(), targets)); _owner.broadcastPacket(new MagicSkillUse(_owner, firstTarget, skill.getDisplayId(), skill.getLevel(), 0, 0)); // Launch the magic skill and calculate its effects // TODO: once core will support all possible effects, use effects (not handler) if (handler != null) handler.useSkill(_owner, skill, targets); else skill.useSkill(_owner, targets); } } catch (Exception e) { _log.warn("", e); } } private void makeCast(EffectChanceSkillTrigger effect, L2Character target) { try { if (effect == null || !effect.triggersChanceSkill()) return; L2Skill triggered = SkillTable.getInstance().getInfo(effect.getTriggeredChanceId(), effect.getTriggeredChanceLevel()); if (triggered == null) return; L2Character caster = triggered.getTargetType() == L2Skill.SkillTargetType.TARGET_SELF ? _owner : effect.getEffector(); if (caster == null || triggered.getSkillType() == L2SkillType.NOTDONE || caster.isSkillDisabled(triggered)) return; if (triggered.getReuseDelay() > 0) caster.disableSkill(triggered, triggered.getReuseDelay()); L2Object[] targets = triggered.getTargetList(caster, false, target); if (targets.length == 0) return; L2Character firstTarget = (L2Character) targets[0]; ISkillHandler handler = SkillHandler.getInstance().getSkillHandler(triggered.getSkillType()); _owner.broadcastPacket(new MagicSkillLaunched(_owner, triggered.getDisplayId(), triggered.getLevel(), targets)); _owner.broadcastPacket(new MagicSkillUse(_owner, firstTarget, triggered.getDisplayId(), triggered.getLevel(), 0, 0)); // Launch the magic skill and calculate its effects // TODO: once core will support all possible effects, use effects (not handler) if (handler != null) handler.useSkill(caster, triggered, targets); else triggered.useSkill(caster, targets); } catch (Exception e) { _log.warn("", e); } } }