// Get the active weapon instance (always equiped in the right hand)
L2ItemInstance weaponInst = getActiveWeaponInstance();
// Get the active weapon item corresponding to the active weapon instance (always equiped in the right hand)
L2Weapon weaponItem = getActiveWeaponItem();
if ((weaponItem != null) && (weaponItem.getItemType() == L2WeaponType.ROD))
{
// You can't make an attack with a fishing pole.
((L2PcInstance) this).sendPacket(new SystemMessage(SystemMessageId.CANNOT_ATTACK_WITH_FISHING_POLE));
getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
ActionFailed af = new ActionFailed();
sendPacket(af);
return;
}
// GeoData Los Check here (or dz > 1000)
if (!GeoData.getInstance().canSeeTarget(this, target))
{
sendPacket(new SystemMessage(SystemMessageId.CANT_SEE_TARGET));
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(new ActionFailed());
return;
}
// Check for a bow
if (((weaponItem != null) && (weaponItem.getItemType() == L2WeaponType.BOW)))
{
// Check for arrows and MP
if (this instanceof L2PcInstance)
{
// Checking if target has moved to peace zone - only for player-bow attacks at the moment
// Other melee is checked in movement code and for offensive spells a check is done every time
if (target.isInsidePeaceZone((L2PcInstance) this))
{
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(new ActionFailed());
return;
}
// Verify if the bow can be use
if (_disableBowAttackEndTime <= GameTimeController.getGameTicks())
{
// Verify if L2PcInstance owns enough MP
int saMpConsume = (int) getStat().calcStat(Stats.MP_CONSUME, 0, null, null);
int mpConsume = saMpConsume == 0 ? weaponItem.getMpConsume() : saMpConsume;
if (getCurrentMp() < mpConsume)
{
// If L2PcInstance doesn't have enough MP, stop the attack
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), 1000);
sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_MP));
sendPacket(new ActionFailed());
return;
}
// If L2PcInstance have enough MP, the bow consummes it
getStatus().reduceMp(mpConsume);
// Set the period of bow non re-use
_disableBowAttackEndTime = (5 * GameTimeController.TICKS_PER_SECOND) + GameTimeController.getGameTicks();
}
else
{
// Cancel the action because the bow can't be re-use at this moment
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), 1000);
sendPacket(new ActionFailed());
return;
}
// Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2PcINstance then return True
if (!checkAndEquipArrows())
{
// Cancel the action because the L2PcInstance have no arrow
getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
sendPacket(new ActionFailed());
sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ARROWS));
return;
}
}
else if (this instanceof L2NpcInstance)
{
if (_disableBowAttackEndTime > GameTimeController.getGameTicks())
{
return;
}
}
}
// Add the L2PcInstance to _knownObjects and _knownPlayer of the target
target.getKnownList().addKnownObject(this);
// Reduce the current CP if TIREDNESS configuration is activated
if (Config.ALT_GAME_TIREDNESS)
{
setCurrentCp(getCurrentCp() - 10);
}
// Recharge any active auto soulshot tasks for player (or player's summon if one exists).
if (this instanceof L2PcInstance)
{
((L2PcInstance) this).rechargeAutoSoulShot(true, false, false);
}
else if (this instanceof L2Summon)
{
((L2Summon) this).getOwner().rechargeAutoSoulShot(true, false, true);
}
// Verify if soulshots are charged.
boolean wasSSCharged;
if ((this instanceof L2Summon) && !(this instanceof L2PetInstance))
{
wasSSCharged = (((L2Summon) this).getChargedSoulShot() != L2ItemInstance.CHARGED_NONE);
}
else
{
wasSSCharged = ((weaponInst != null) && (weaponInst.getChargedSoulshot() != L2ItemInstance.CHARGED_NONE));
}
// Get the Attack Speed of the L2Character (delay (in milliseconds) before next attack)
int timeAtk = calculateTimeBetweenAttacks(target, weaponItem);
// the hit is calculated to happen halfway to the animation - might need further tuning e.g. in bow case
int timeToHit = timeAtk / 2;
_attackEndTime = GameTimeController.getGameTicks();
_attackEndTime += (timeAtk / GameTimeController.MILLIS_IN_TICK);
_attackEndTime -= 1;
int ssGrade = 0;
if (weaponItem != null)
{
ssGrade = weaponItem.getCrystalType();
}
// Create a Server->Client packet Attack
Attack attack = new Attack(this, wasSSCharged, ssGrade);
boolean hitted;
// Set the Attacking Body part to CHEST
setAttackingBodypart();
// Get the Attack Reuse Delay of the L2Weapon
int reuse = calculateReuseTime(target, weaponItem);
// Select the type of attack to start
if (weaponItem == null)
{
hitted = doAttackHitSimple(attack, target, timeToHit);
}
else if (weaponItem.getItemType() == L2WeaponType.BOW)
{
hitted = doAttackHitByBow(attack, target, timeAtk, reuse);
}
else if (weaponItem.getItemType() == L2WeaponType.POLE)
{
hitted = doAttackHitByPole(attack, timeToHit);
}
else if (isUsingDualWeapon())
{