/* * Copyright (C) 2004-2014 L2J Server * * This file is part of L2J Server. * * L2J Server 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. * * L2J Server 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 com.l2jserver.gameserver.model; import java.util.logging.Level; import java.util.logging.Logger; import javolution.util.FastMap; import com.l2jserver.gameserver.datatables.SkillData; import com.l2jserver.gameserver.model.actor.L2Character; import com.l2jserver.gameserver.model.actor.L2Playable; import com.l2jserver.gameserver.model.effects.AbstractEffect; import com.l2jserver.gameserver.model.interfaces.IChanceSkillTrigger; import com.l2jserver.gameserver.model.skills.Skill; import com.l2jserver.gameserver.network.serverpackets.MagicSkillLaunched; import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse; /** * 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 = Logger.getLogger(ChanceSkillList.class.getName()); private static final long serialVersionUID = 1L; private final L2Character _owner; public ChanceSkillList(L2Character owner) { 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, null, Elementals.NONE); } public void onEvadedHit(L2Character attacker) { onEvent(ChanceCondition.EVT_EVADED_HIT, 0, attacker, null, Elementals.NONE); } public void onSkillHit(L2Character target, Skill skill, boolean ownerWasHit) { int event; if (ownerWasHit) { event = ChanceCondition.EVT_HIT_BY_SKILL; if (skill.isBad()) { event |= ChanceCondition.EVT_HIT_BY_OFFENSIVE_SKILL; event |= ChanceCondition.EVT_ATTACKED; event |= ChanceCondition.EVT_ATTACKED_HIT; } else { event |= ChanceCondition.EVT_HIT_BY_GOOD_MAGIC; } } else { event = ChanceCondition.EVT_CAST; event |= skill.isMagic() ? ChanceCondition.EVT_MAGIC : ChanceCondition.EVT_PHYSICAL; event |= skill.isBad() ? ChanceCondition.EVT_MAGIC_OFFENSIVE : ChanceCondition.EVT_MAGIC_GOOD; } onEvent(event, 0, target, skill, skill.getElement()); } public void onStart(byte element) { onEvent(ChanceCondition.EVT_ON_START, 0, _owner, null, element); } public void onActionTime(byte element) { onEvent(ChanceCondition.EVT_ON_ACTION_TIME, 0, _owner, null, element); } public void onExit(byte element) { onEvent(ChanceCondition.EVT_ON_EXIT, 0, _owner, null, element); } public void onEvent(int event, int damage, L2Character target, Skill skill, byte element) { if (_owner.isDead()) { return; } final boolean playable = target instanceof L2Playable; for (FastMap.Entry<IChanceSkillTrigger, ChanceCondition> e = head(), end = tail(); (e = e.getNext()) != end;) { if ((e.getValue() != null) && e.getValue().trigger(event, damage, element, playable, skill)) { if (e.getKey() instanceof Skill) { _owner.makeTriggerCast((Skill) e.getKey(), target); } else { makeCast((AbstractEffect) e.getKey(), target); } } } } private void makeCast(AbstractEffect effect, L2Character target) { try { if ((effect == null) || !effect.triggersChanceSkill()) { return; } final Skill triggered = SkillData.getInstance().getSkill(effect.getTriggeredChanceId(), effect.getTriggeredChanceLevel()); if (triggered == null) { return; } if ((_owner == null) || _owner.isSkillDisabled(triggered)) { return; } if (triggered.getReuseDelay() > 0) { _owner.disableSkill(triggered, triggered.getReuseDelay()); } final L2Object[] targets = triggered.getTargetList(_owner, false, target); if (targets.length == 0) { return; } _owner.broadcastPacket(new MagicSkillLaunched(_owner, triggered.getDisplayId(), triggered.getDisplayLevel(), targets)); _owner.broadcastPacket(new MagicSkillUse(_owner, target, triggered.getDisplayId(), triggered.getDisplayLevel(), 0, 0)); // Launch the magic skill and calculate its effects triggered.activateSkill(_owner, targets); } catch (Exception e) { _log.log(Level.WARNING, "", e); } } }