}
}
//************************************* Check Target *******************************************
// Create and set a L2Object containing the target of the skill
L2Object target = null;
SkillTargetType sklTargetType = skill.getTargetType();
SkillType sklType = skill.getSkillType();
switch(sklTargetType)
{
// Target the player if skill type is AURA, PARTY, CLAN or SELF
case TARGET_AURA:
if(isInOlympiadMode() && !isOlympiadStart())
setTarget(this);
case TARGET_PARTY:
case TARGET_ALLY:
case TARGET_CLAN:
case TARGET_GROUND:
case TARGET_SELF:
target = this;
break;
case TARGET_PET:
target = getPet();
break;
default:
target = getTarget();
break;
}
// Check the validity of the target
if(target == null)
{
sendPacket(new SystemMessage(SystemMessageId.TARGET_CANT_FOUND));
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// skills can be used on Walls and Doors only durring siege
// Ignore skill UNLOCK
if(skill.isOffensive() && target instanceof L2DoorInstance )
{
boolean isCastle = (((L2DoorInstance) target).getCastle() != null
&& ((L2DoorInstance) target).getCastle().getCastleId() > 0
&& ((L2DoorInstance) target).getCastle().getSiege().getIsInProgress());
boolean isFort = (((L2DoorInstance) target).getFort() != null
&& ((L2DoorInstance) target).getFort().getFortId() > 0
&& ((L2DoorInstance) target).getFort().getSiege().getIsInProgress());
if ((!isCastle && !isFort))
return;
}
// Like L2OFF you can't heal random purple people without using CTRL
SkillDat skilldat = getCurrentSkill();
if (skilldat != null && skill.getSkillType() == SkillType.HEAL && !skilldat.isCtrlPressed() && target instanceof L2PcInstance && ((L2PcInstance) target).getPvpFlag() == 1 && this != target)
{
if ((getClanId() == 0 || ((L2PcInstance) target).getClanId() == 0) || (getClanId() != ((L2PcInstance) target).getClanId()))
{
if ((getAllyId() == 0 || ((L2PcInstance) target).getAllyId() == 0) || (getAllyId() != ((L2PcInstance) target).getAllyId()))
{
if ((getParty() == null || ((L2PcInstance) target).getParty() == null) || (!getParty().equals(((L2PcInstance) target).getParty())))
{
sendPacket(new SystemMessage(SystemMessageId.INCORRECT_TARGET));
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
}
}
// Are the target and the player in the same duel?
if(isInDuel())
{
if(!(target instanceof L2PcInstance && ((L2PcInstance) target).getDuelId() == getDuelId()) && !(target instanceof L2SummonInstance && ((L2Summon) target).getOwner().getDuelId() == getDuelId()))
{
sendMessage("You cannot do this while duelling.");
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
//************************************* Check skill availability *******************************************
// Check if this skill is enabled (ex : reuse time)
if(isSkillDisabled(skill_id) /* && !getAccessLevel().allowPeaceAttack() */)
{
// SystemMessage sm = new SystemMessage(SystemMessageId.SKILL_NOT_AVAILABLE);
// sm.addString(skill.getName());
// sendPacket(sm);
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Check if all skills are disabled
if(isAllSkillsDisabled() && !getAccessLevel().allowPeaceAttack())
{
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// prevent casting signets to peace zone
if(skill.getSkillType() == SkillType.SIGNET || skill.getSkillType() == SkillType.SIGNET_CASTTIME)
{
if(isInsidePeaceZone(this))
{
SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED);
sm.addSkillName(skill_id);
sendPacket(sm);
return;
}
}
//************************************* Check Consumables *******************************************
// Check if the caster has enough MP
if(getCurrentMp() < getStat().getMpConsume(skill) + getStat().getMpInitialConsume(skill))
{
// Send a System Message to the caster
sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_MP));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Check if the caster has enough HP
if(getCurrentHp() <= skill.getHpConsume())
{
// Send a System Message to the caster
sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_HP));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Check if the spell consummes an Item
if(skill.getItemConsume() > 0)
{
// Get the L2ItemInstance consummed by the spell
L2ItemInstance requiredItems = getInventory().getItemByItemId(skill.getItemConsumeId());
// Check if the caster owns enought consummed Item to cast
if(requiredItems == null || requiredItems.getCount() < skill.getItemConsume())
{
// Checked: when a summon skill failed, server show required consume item count
if(sklType == L2Skill.SkillType.SUMMON)
{
SystemMessage sm = new SystemMessage(SystemMessageId.SUMMONING_SERVITOR_COSTS_S2_S1);
sm.addItemName(skill.getItemConsumeId());
sm.addNumber(skill.getItemConsume());
sendPacket(sm);
}
else
{
// Send a System Message to the caster
sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
}
return;
}
}
// Like L2OFF if you are mounted on wyvern you can't use own skills
if (isFlying())
{
if (skill_id != 327 && skill_id != 4289 && !skill.isPotion())
{
sendMessage("You cannot use skills while riding a wyvern.");
return;
}
}
// Like L2OFF if you have a summon you can't summon another one (ignore cubics)
if(sklType == L2Skill.SkillType.SUMMON && skill instanceof L2SkillSummon && !((L2SkillSummon) skill).isCubic())
{
if (getPet() != null || isMounted())
{
sendPacket(new SystemMessage(SystemMessageId.YOU_ALREADY_HAVE_A_PET));
return;
}
}
if(skill.getNumCharges() > 0
&& skill.getSkillType() != SkillType.CHARGE
&& skill.getSkillType() != SkillType.CHARGEDAM
&& skill.getSkillType() != SkillType.CHARGE_EFFECT
&& skill.getSkillType() != SkillType.PDAM)
{
EffectCharge effect = (EffectCharge) getFirstEffect(L2Effect.EffectType.CHARGE);
if(effect == null || effect.numCharges < skill.getNumCharges())
{
sendPacket(new SystemMessage(SystemMessageId.SKILL_NOT_AVAILABLE));
return;
}
effect.numCharges -= skill.getNumCharges();
sendPacket(new EtcStatusUpdate(this));
if(effect.numCharges == 0)
{
effect.exit(false);
}
}
//************************************* Check Casting Conditions *******************************************
// Check if the caster own the weapon needed
if(!skill.getWeaponDependancy(this))
{
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Check if all casting conditions are completed
if(!skill.checkCondition(this, target, false))
{
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
//************************************* Check Player State *******************************************
// Abnormal effects(ex : Stun, Sleep...) are checked in L2Character useMagic()
// Check if the player use "Fake Death" skill
if(isAlikeDead() && !skill.isPotion() && skill.getSkillType() != L2Skill.SkillType.FAKE_DEATH)
{
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(isFishing() && sklType != SkillType.PUMPING && sklType != SkillType.REELING && sklType != SkillType.FISHING)
{
//Only fishing skills are available
sendPacket(new SystemMessage(SystemMessageId.ONLY_FISHING_SKILLS_NOW));
return;
}
//************************************* Check Skill Type *******************************************
// Check if this is offensive magic skill
if(skill.isOffensive())
{
Boolean peace = isInsidePeaceZone(this, target);
if(peace
&& (skill.getId() != 3261 // Like L2OFF you can use cupid bow skills on peace zone
&& skill.getId() != 3260
&& skill.getId() != 3262 && sklTargetType != SkillTargetType.TARGET_AURA)) // Like L2OFF people can use TARGET_AURE skills on peace zone
{
// If L2Character or target is in a peace zone, send a system message TARGET_IN_PEACEZONE a Server->Client packet ActionFailed
sendPacket(new SystemMessage(SystemMessageId.TARGET_IN_PEACEZONE));
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(isInOlympiadMode() && !isOlympiadStart() && sklTargetType != SkillTargetType.TARGET_AURA)
{
// if L2PcInstance is in Olympia and the match isn't already start, send a Server->Client packet ActionFailed
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(!(target instanceof L2MonsterInstance) && sklType == SkillType.CONFUSE_MOB_ONLY)
{
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
/*
// Check if the target is attackable
if(target instanceof L2PcInstance && !target.isAttackable() && !getAccessLevel().allowPeaceAttack() && (!(_inEventTvT && TvT.is_started()) || !(_inEventCTF && CTF.is_started()) || !(_inEventDM && DM.is_started()) || !(_inEventVIP && VIP._started)))
{
if(!isInFunEvent() || !((L2PcInstance)target).isInFunEvent())
{
// If target is not attackable, send a Server->Client packet ActionFailed
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
*/
// Check if a Forced ATTACK is in progress on non-attackable target
//if (!target.isAutoAttackable(this) && !forceUse && !(_inEventTvT && TvT._started) && !(_inEventDM && DM._started) && !(_inEventCTF && CTF._started) && !(_inEventVIP && VIP._started)
if (!target.isAutoAttackable(this) && (!forceUse && (skill.getId() != 3261 && skill.getId() != 3260 && skill.getId() != 3262)) && !(_inEventTvT && TvT.is_started()) && !(_inEventDM && DM.is_started()) && !(_inEventCTF && CTF.is_started()) && !(_inEventVIP && VIP._started)
&& sklTargetType != SkillTargetType.TARGET_AURA
&& sklTargetType != SkillTargetType.TARGET_CLAN
&& sklTargetType != SkillTargetType.TARGET_ALLY
&& sklTargetType != SkillTargetType.TARGET_PARTY
&& sklTargetType != SkillTargetType.TARGET_SELF
&& sklTargetType != SkillTargetType.TARGET_GROUND)
{
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Check if the target is in the skill cast range
if (dontMove)
{
// Calculate the distance between the L2PcInstance and the target
if (sklTargetType == SkillTargetType.TARGET_GROUND)
{
if (!isInsideRadius(getCurrentSkillWorldPosition().getX(), getCurrentSkillWorldPosition().getY(), getCurrentSkillWorldPosition().getZ(), (int) (skill.getCastRange() + getTemplate().getCollisionRadius()), false, false))
{
// Send a System Message to the caster
sendPacket(SystemMessageId.TARGET_TOO_FAR);
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
else if (skill.getCastRange() > 0 && !isInsideRadius(target, skill.getCastRange() + getTemplate().collisionRadius, false, false)) // Calculate the distance between the L2PcInstance and the target
{
// Send a System Message to the caster
sendPacket(new SystemMessage(SystemMessageId.TARGET_TOO_FAR));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
else if (sklType == SkillType.SIGNET) // Check range for SIGNET skills
{
if (!isInsideRadius(getCurrentSkillWorldPosition().getX(), getCurrentSkillWorldPosition().getY(), getCurrentSkillWorldPosition().getZ(), (int) (skill.getCastRange() + getTemplate().getCollisionRadius()), false, false))
{
// Send a System Message to the caster
sendPacket(SystemMessageId.TARGET_TOO_FAR);
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
}
// Check if the skill is defensive
if(!skill.isOffensive())
{
// check if the target is a monster and if force attack is set.. if not then we don't want to cast.
if(target instanceof L2MonsterInstance && !forceUse && sklTargetType != SkillTargetType.TARGET_PET && sklTargetType != SkillTargetType.TARGET_AURA && sklTargetType != SkillTargetType.TARGET_CLAN && sklTargetType != SkillTargetType.TARGET_SELF && sklTargetType != SkillTargetType.TARGET_PARTY && sklTargetType != SkillTargetType.TARGET_ALLY && sklTargetType != SkillTargetType.TARGET_CORPSE_MOB && sklTargetType != SkillTargetType.TARGET_AREA_CORPSE_MOB && sklTargetType != SkillTargetType.TARGET_GROUND && sklType != SkillType.BEAST_FEED && sklType != SkillType.DELUXE_KEY_UNLOCK && sklType != SkillType.UNLOCK)
{
// send the action failed so that the skill doens't go off.
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
// Check if the skill is Spoil type and if the target isn't already spoiled
if(sklType == SkillType.SPOIL)
{
if(!(target instanceof L2MonsterInstance))
{
// Send a System Message to the L2PcInstance
sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
// Check if the skill is Sweep type and if conditions not apply
if(sklType == SkillType.SWEEP && target instanceof L2Attackable)
{
int spoilerId = ((L2Attackable) target).getIsSpoiledBy();
if(((L2Attackable) target).isDead())
{
if(!((L2Attackable) target).isSpoil())
{
// Send a System Message to the L2PcInstance
sendPacket(new SystemMessage(SystemMessageId.SWEEPER_FAILED_TARGET_NOT_SPOILED));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(getObjectId() != spoilerId && !isInLooterParty(spoilerId))
{
// Send a System Message to the L2PcInstance
sendPacket(new SystemMessage(SystemMessageId.SWEEP_NOT_ALLOWED));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
}
// Check if the skill is Drain Soul (Soul Crystals) and if the target is a MOB
if(sklType == SkillType.DRAIN_SOUL)
{
if(!(target instanceof L2MonsterInstance))
{
// Send a System Message to the L2PcInstance
sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
final Point3D worldPosition = getCurrentSkillWorldPosition();
if(sklTargetType == SkillTargetType.TARGET_GROUND && worldPosition == null)
{
_log.info("WorldPosition is null for skill: " + skill.getName() + ", player: " + getName() + ".");
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Check if this is a Pvp skill and target isn't a non-flagged/non-karma player
switch(sklTargetType)
{
case TARGET_PARTY:
case TARGET_ALLY: // For such skills, checkPvpSkill() is called from L2Skill.getTargetList()
case TARGET_CLAN: // For such skills, checkPvpSkill() is called from L2Skill.getTargetList()
case TARGET_AURA:
case TARGET_SELF:
case TARGET_GROUND:
break;
default:
//if pvp skill is not allowed for given target
if(!checkPvpSkill(target, skill) && !getAccessLevel().allowPeaceAttack() && (skill.getId() != 3261 && skill.getId() != 3260 && skill.getId() != 3262))
{
// Send a System Message to the L2PcInstance
sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
// Send a Server->Client packet ActionFailed to the L2PcInstance
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
if(sklTargetType == SkillTargetType.TARGET_HOLY && !TakeCastle.checkIfOkToCastSealOfRule(this, false))
{
sendPacket(ActionFailed.STATIC_PACKET);
abortCast();
return;
}
if(sklType == SkillType.SIEGEFLAG && !SiegeFlag.checkIfOkToPlaceFlag(this, false))
{
sendPacket(ActionFailed.STATIC_PACKET);
abortCast();
return;
}
else if(sklType == SkillType.STRSIEGEASSAULT && !StrSiegeAssault.checkIfOkToUseStriderSiegeAssault(this, false))
{
sendPacket(ActionFailed.STATIC_PACKET);
abortCast();
return;
}
// TEMPFIX: Check client Z coordinate instead of server z to avoid exploit
// killing Zaken from others floor
if ((target instanceof L2GrandBossInstance) && ((L2GrandBossInstance) target).getNpcId() == 29022)
{
if (Math.abs(this.getClientZ() - target.getZ()) > 200)
{
sendPacket(new SystemMessage(SystemMessageId.CANT_SEE_TARGET));
getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
sendPacket(ActionFailed.STATIC_PACKET);
return;