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