return;
// Like L2OFF wait that the hit task finish and then player can move
if (this instanceof L2PcInstance && ((L2PcInstance) this).isMovingTaskDefined() && !((L2PcInstance) this).isAttackingNow())
{
L2ItemInstance rhand = ((L2PcInstance) this).getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
if ((rhand != null && rhand.getItemType() != L2WeaponType.BOW) || (rhand == null))
{
((L2PcInstance) this).startMovingTask();
return;
}
}
if(isAlikeDead())
{
// If L2PcInstance is dead or the target is dead, the action is stoped
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(this instanceof L2NpcInstance && target.isAlikeDead())
{
// If L2PcInstance is dead or the target is dead, the action is stoped
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(this instanceof L2PcInstance && target.isDead() && !target.isFakeDeath())
{
// If L2PcInstance is dead or the target is dead, the action is stoped
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(!getKnownList().knowsObject(target))
{
// If L2PcInstance is dead or the target is dead, the action is stoped
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(this instanceof L2PcInstance && isDead())
{
// If L2PcInstance is dead or the target is dead, the action is stoped
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(target instanceof L2PcInstance && ((L2PcInstance) target).getDuelState() == Duel.DUELSTATE_DEAD)
{
// If L2PcInstance is dead or the target is dead, the action is stoped
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(target instanceof L2DoorInstance && !((L2DoorInstance) target).isAttackable(this))
return;
if(isAttackingDisabled())
return;
if(this instanceof L2PcInstance)
{
if(((L2PcInstance) this).inObserverMode())
{
sendPacket(new SystemMessage(SystemMessageId.OBSERVERS_CANNOT_PARTICIPATE));
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(target instanceof L2PcInstance)
{
if(((L2PcInstance) target).isCursedWeaponEquiped() && ((L2PcInstance) this).getLevel() <= Config.MAX_LEVEL_NEWBIE)
{
((L2PcInstance) this).sendMessage("Can't attack a cursed player when under level 21.");
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if(((L2PcInstance) this).isCursedWeaponEquiped() && ((L2PcInstance) target).getLevel() <= Config.MAX_LEVEL_NEWBIE)
{
((L2PcInstance) this).sendMessage("Can't attack a newbie player using a cursed weapon.");
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
//thank l2dot
if(getObjectId() == target.getObjectId())
{
//((L2PcInstance) this).sendMessage("Can't attack yourself! Suicide? :)");
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (target instanceof L2NpcInstance && Config.DISABLE_ATTACK_NPC_TYPE)
{
String mobtype = ((L2NpcInstance) target).getTemplate().type;
if (!Config.LIST_ALLOWED_NPC_TYPES.contains(mobtype))
{
SystemMessage sm = new SystemMessage(SystemMessageId.S1_S2);
sm.addString("Npc Type "+mobtype+" has Protection - No Attack Allowed!");
((L2PcInstance) this).sendPacket(sm);
((L2PcInstance) this).sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
}
// 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);
sendPacket(ActionFailed.STATIC_PACKET);
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;
}
}
// 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(ActionFailed.STATIC_PACKET);
return;
}
// Check for a bow
if(weaponItem != null && weaponItem.getItemType() == L2WeaponType.BOW)
{
// 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(ActionFailed.STATIC_PACKET);
sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ARROWS));
return;
}
//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(ActionFailed.STATIC_PACKET);
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(ActionFailed.STATIC_PACKET);
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(ActionFailed.STATIC_PACKET);
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();
// Heading calculation on every attack
this.setHeading(Util.calculateHeadingFrom(this.getX(), this.getY(), target.getX(), target.getY()));
// 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())
{
hitted = doAttackHitByDual(attack, target, timeToHit);
}
else
{
hitted = doAttackHitSimple(attack, target, timeToHit);
}
// Flag the attacker if it's a L2PcInstance outside a PvP area
L2PcInstance player = null;
if(this instanceof L2PcInstance)
{
player = (L2PcInstance) this;
}
else if(this instanceof L2Summon)
{
player = ((L2Summon) this).getOwner();
}
if(player != null)
{
player.updatePvPStatus(target);
}
// Check if hit isn't missed
if(!hitted)
{
//MAJAX fix
sendPacket(new SystemMessage(SystemMessageId.MISSED_TARGET));
// Abort the attack of the L2Character and send Server->Client ActionFailed packet
abortAttack();
}
else
{
/* ADDED BY nexus - 2006-08-17
*
* As soon as we know that our hit landed, we must discharge any active soulshots.
* This must be done so to avoid unwanted soulshot consumption.
*/
// If we didn't miss the hit, discharge the shoulshots, if any
if(this instanceof L2Summon && !(this instanceof L2PetInstance))
{
((L2Summon) this).setChargedSoulShot(L2ItemInstance.CHARGED_NONE);
}
else if(weaponInst != null)
{
weaponInst.setChargedSoulshot(L2ItemInstance.CHARGED_NONE);
}
if(player != null)
{
if(player.isCursedWeaponEquiped())