/*
* 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);
}
}
}