/* * 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 . */ package com.l2jserver.gameserver.model; import com.l2jserver.gameserver.datatables.SkillTable; import com.l2jserver.gameserver.handler.ISkillHandler; import com.l2jserver.gameserver.handler.SkillHandler; import com.l2jserver.gameserver.model.actor.L2Character; import com.l2jserver.gameserver.model.actor.L2Playable; import com.l2jserver.gameserver.network.serverpackets.MagicSkillLaunched; import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse; import com.l2jserver.gameserver.skills.effects.EffectChanceSkillTrigger; import com.l2jserver.gameserver.templates.skills.L2SkillType; import javolution.util.FastMap; /** * CT2.3: Added support for allowing effect as a chance skill trigger (DrHouse) * * @author kombat */ public class ChanceSkillList extends FastMap { 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, 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, target, Elementals.NONE); } public void onEvadedHit(L2Character attacker) { onEvent(ChanceCondition.EVT_EVADED_HIT, attacker, Elementals.NONE); } 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, target, element); } public void onStart(byte element) { onEvent(ChanceCondition.EVT_ON_START, _owner, element); } public void onActionTime(byte element) { onEvent(ChanceCondition.EVT_ON_ACTION_TIME, _owner, element); } public void onExit(byte element) { onEvent(ChanceCondition.EVT_ON_EXIT, _owner, element); } public void onEvent(int event, L2Character target, byte element) { if (_owner.isDead()) return; final boolean playable = target instanceof L2Playable; for (FastMap.Entry e = head(), end = tail(); (e = e.getNext()) != end;) { if (e.getValue() != null && e.getValue().trigger(event, element, playable)) { 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,true) && 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) { e.printStackTrace(); } } 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) { e.printStackTrace(); } } }