Sync with L2jServer HighFive May 19th 2015.

This commit is contained in:
MobiusDev 2015-05-19 14:57:13 +00:00
parent 0337dd64a2
commit 6b9ed81821
17 changed files with 146 additions and 124 deletions

View File

@ -1,4 +1,4 @@
<html><body>Instant Moving Device:<br> <html><body>Instant Moving Device:<br>
This device can teleport you deep inside the Seed of Destruction.<br> This device can teleport you deep inside the Seed of Destruction.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SoDStage1">Teleport</Button> <Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Stage1">Teleport</Button>
</body></html> </body></html>

View File

@ -380,6 +380,7 @@ public final class MinionSpawnManager extends AbstractNpcAI
NPC.add(27266); // Fallen Angel Haures NPC.add(27266); // Fallen Angel Haures
NPC.add(27267); // Fallen Angel Haures NPC.add(27267); // Fallen Angel Haures
NPC.add(27290); // White Wing Commander NPC.add(27290); // White Wing Commander
NPC.add(29001); // Queen Ant
NPC.add(29030); // Fenril Hound Kerinne NPC.add(29030); // Fenril Hound Kerinne
NPC.add(29033); // Fenril Hound Freki NPC.add(29033); // Fenril Hound Freki
NPC.add(29037); // Fenril Hound Kinaz NPC.add(29037); // Fenril Hound Kinaz

View File

@ -520,7 +520,7 @@ public final class Antharas extends AbstractNpcAI
} }
else else
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant skip waiting time right now!"); player.sendMessage(getClass().getSimpleName() + ": You can't skip waiting time right now!");
} }
break; break;
} }
@ -535,7 +535,7 @@ public final class Antharas extends AbstractNpcAI
} }
else else
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant respawn antharas while antharas is alive!"); player.sendMessage(getClass().getSimpleName() + ": You can't respawn antharas while antharas is alive!");
} }
break; break;
} }
@ -553,12 +553,12 @@ public final class Antharas extends AbstractNpcAI
} }
if (player != null) // Player dont will be null just when is this event called from GM command if (player != null) // Player dont will be null just when is this event called from GM command
{ {
player.sendMessage(getClass().getSimpleName() + ": All minions has been deleted!"); player.sendMessage(getClass().getSimpleName() + ": All minions have been deleted!");
} }
} }
else if (player != null) // Player dont will be null just when is this event called from GM command else if (player != null) // Player dont will be null just when is this event called from GM command
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant despawn minions right now!"); player.sendMessage(getClass().getSimpleName() + ": You can't despawn minions right now!");
} }
break; break;
} }
@ -594,7 +594,7 @@ public final class Antharas extends AbstractNpcAI
} }
else else
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant abort fight right now!"); player.sendMessage(getClass().getSimpleName() + ": You can't abort fight right now!");
} }
break; break;
} }
@ -713,6 +713,7 @@ public final class Antharas extends AbstractNpcAI
{ {
cancelQuestTimer("SET_REGEN", npc, null); cancelQuestTimer("SET_REGEN", npc, null);
startQuestTimer("SET_REGEN", 60000, npc, null); startQuestTimer("SET_REGEN", 60000, npc, null);
((L2Attackable) npc).setOnKillDelay(0);
} }
else else
{ {

View File

@ -564,27 +564,28 @@ public final class RainbowSpringsChateau extends ClanHallSiegeEngine
} }
} }
} }
else if (event.startsWith("getItem")) // TODO(Zoey76): Rewrite this to prevent exploits...
{ // else if (event.startsWith("getItem"))
if (!_pendingItemToGet.containsKey(clan)) // {
{ // if (!_pendingItemToGet.containsKey(clan))
html = "yeti_cannot_exchange.htm"; // {
} // html = "yeti_cannot_exchange.htm";
// }
int left = _pendingItemToGet.get(clan); //
if (left > 0) // int left = _pendingItemToGet.get(clan);
{ // if (left > 0)
int itemId = Integer.parseInt(event.split("_")[1]); // {
player.addItem("Rainbow Spring Chateau Siege", itemId, 1, npc, true); // int itemId = Integer.parseInt(event.split("_")[1]);
--left; // player.addItem("Rainbow Spring Chateau Siege", itemId, 1, npc, true);
_pendingItemToGet.put(clan, left); // --left;
html = "yeti_main.htm"; // _pendingItemToGet.put(clan, left);
} // html = "yeti_main.htm";
else // }
{ // else
html = "yeti_cannot_exchange.htm"; // {
} // html = "yeti_cannot_exchange.htm";
} // }
// }
return html; return html;
} }

View File

@ -183,6 +183,7 @@ public final class HallOfSuffering extends AbstractNpcAI
// Misc // Misc
private static final int TEMPLATE_ID = 115; private static final int TEMPLATE_ID = 115;
private static final int MIN_LEVEL = 75; private static final int MIN_LEVEL = 75;
private static final int MAX_LEVEL = 82;
private static final boolean debug = false; private static final boolean debug = false;
public HallOfSuffering() public HallOfSuffering()
@ -219,7 +220,7 @@ public final class HallOfSuffering extends AbstractNpcAI
for (L2PcInstance partyMember : party.getMembers()) for (L2PcInstance partyMember : party.getMembers())
{ {
if (partyMember.getLevel() < MIN_LEVEL) if ((partyMember.getLevel() < MIN_LEVEL) || (partyMember.getLevel() > MAX_LEVEL))
{ {
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY); final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
sm.addPcName(partyMember); sm.addPcName(partyMember);

View File

@ -19,18 +19,18 @@
package handlers.actionhandlers; package handlers.actionhandlers;
import com.l2jserver.Config; import com.l2jserver.Config;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention; import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.InstanceType; import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.handler.IActionHandler; import com.l2jserver.gameserver.handler.IActionHandler;
import com.l2jserver.gameserver.model.L2Object; import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character; import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Npc; import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.L2Event; import com.l2jserver.gameserver.model.entity.L2Event;
import com.l2jserver.gameserver.model.events.EventDispatcher; import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.EventType; import com.l2jserver.gameserver.model.events.EventType;
import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcFirstTalk; import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcFirstTalk;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.MoveToPawn; import com.l2jserver.gameserver.network.serverpackets.MoveToPawn;
import com.l2jserver.util.Rnd; import com.l2jserver.util.Rnd;
@ -79,23 +79,27 @@ public class L2NpcAction implements IActionHandler
else if (interact) else if (interact)
{ {
// Check if the activeChar is attackable (without a forced attack) and isn't dead // Check if the activeChar is attackable (without a forced attack) and isn't dead
if (target.isAutoAttackable(activeChar) && !((L2Character) target).isAlikeDead()) if (target.isAutoAttackable(activeChar) && !((L2Npc) target).isAlikeDead())
{ {
// Check the height difference if (GeoData.getInstance().canSeeTarget(activeChar, target))
if (Math.abs(activeChar.getZ() - target.getZ()) < 400) // this max heigth difference might need some tweaking
{ {
// Set the L2PcInstance Intention to AI_INTENTION_ATTACK
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
// activeChar.startAttack(this);
} }
else else
{ {
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet final Location destination = GeoData.getInstance().moveCheck(activeChar, target);
activeChar.sendPacket(ActionFailed.STATIC_PACKET); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
} }
} }
else if (!target.isAutoAttackable(activeChar)) else if (!target.isAutoAttackable(activeChar))
{ {
if (GeoData.getInstance().canSeeTarget(activeChar, target))
{
final Location destination = GeoData.getInstance().moveCheck(activeChar, target);
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
return true;
}
// Calculate the distance between the L2PcInstance and the L2Npc // Calculate the distance between the L2PcInstance and the L2Npc
if (!((L2Npc) target).canInteract(activeChar)) if (!((L2Npc) target).canInteract(activeChar))
{ {

View File

@ -25,7 +25,6 @@ import com.l2jserver.gameserver.enums.PrivateStoreType;
import com.l2jserver.gameserver.handler.IActionHandler; import com.l2jserver.gameserver.handler.IActionHandler;
import com.l2jserver.gameserver.model.L2Object; import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.Location; import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.TvTEvent; import com.l2jserver.gameserver.model.entity.TvTEvent;
import com.l2jserver.gameserver.network.SystemMessageId; import com.l2jserver.gameserver.network.SystemMessageId;
@ -33,6 +32,8 @@ import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
public class L2PcInstanceAction implements IActionHandler public class L2PcInstanceAction implements IActionHandler
{ {
private static final int CURSED_WEAPON_VICTIM_MIN_LEVEL = 21;
/** /**
* Manage actions when a player click on this L2PcInstance.<BR> * Manage actions when a player click on this L2PcInstance.<BR>
* <BR> * <BR>
@ -83,50 +84,48 @@ public class L2PcInstanceAction implements IActionHandler
} }
else if (interact) else if (interact)
{ {
final L2PcInstance player = target.getActingPlayer();
// Check if this L2PcInstance has a Private Store // Check if this L2PcInstance has a Private Store
if (((L2PcInstance) target).getPrivateStoreType() != PrivateStoreType.NONE) if (player.getPrivateStoreType() != PrivateStoreType.NONE)
{ {
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, player);
} }
else else
{ {
// Check if this L2PcInstance is autoAttackable // Check if this L2PcInstance is autoAttackable
if (target.isAutoAttackable(activeChar)) if (player.isAutoAttackable(activeChar))
{ {
// activeChar with lvl < 21 can't attack a cursed weapon holder if ((player.isCursedWeaponEquipped() && (activeChar.getLevel() < CURSED_WEAPON_VICTIM_MIN_LEVEL)) //
// And a cursed weapon holder can't attack activeChars with lvl < 21 || (activeChar.isCursedWeaponEquipped() && (player.getLevel() < CURSED_WEAPON_VICTIM_MIN_LEVEL)))
if ((((L2PcInstance) target).isCursedWeaponEquipped() && (activeChar.getLevel() < 21)) || (activeChar.isCursedWeaponEquipped() && (((L2Character) target).getLevel() < 21)))
{ {
activeChar.sendPacket(ActionFailed.STATIC_PACKET); activeChar.sendPacket(ActionFailed.STATIC_PACKET);
} }
else else
{ {
if (GeoData.getInstance().canSeeTarget(activeChar, target)) if (GeoData.getInstance().canSeeTarget(activeChar, player))
{ {
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
activeChar.onActionRequest();
} }
else else
{ {
final Location destination = GeoData.getInstance().moveCheck(activeChar.getX(), activeChar.getY(), activeChar.getZ(), target.getX(), target.getY(), target.getZ(), activeChar.getInstanceId()); final Location destination = GeoData.getInstance().moveCheck(activeChar, player);
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
activeChar.onActionRequest();
} }
activeChar.onActionRequest();
} }
} }
else else
{ {
// This Action Failed packet avoids activeChar getting stuck when clicking three or more times // This Action Failed packet avoids activeChar getting stuck when clicking three or more times
activeChar.sendPacket(ActionFailed.STATIC_PACKET); activeChar.sendPacket(ActionFailed.STATIC_PACKET);
if (GeoData.getInstance().canSeeTarget(activeChar, target)) if (GeoData.getInstance().canSeeTarget(activeChar, player))
{ {
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
} }
else else
{ {
final Location destination = GeoData.getInstance().moveCheck(activeChar.getX(), activeChar.getY(), activeChar.getZ(), target.getX(), target.getY(), target.getZ(), activeChar.getInstanceId()); final Location destination = GeoData.getInstance().moveCheck(activeChar, player);
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
activeChar.onActionRequest();
} }
} }
} }

View File

@ -35,7 +35,7 @@ public class Q10502_FreyaEmbroideredSoulCloak extends Quest
// NPC // NPC
private static final int OLF_ADAMS = 32612; private static final int OLF_ADAMS = 32612;
// Monster // Monster
private static final int FREYA = 29180; private static final int FREYA = 29179;
// Items // Items
private static final int FREYAS_SOUL_FRAGMENT = 21723; private static final int FREYAS_SOUL_FRAGMENT = 21723;
private static final int SOUL_CLOAK_OF_FREYA = 21720; private static final int SOUL_CLOAK_OF_FREYA = 21720;

View File

@ -251,6 +251,7 @@ public final class MinionSpawnManager extends AbstractNpcAI
NPC.add(27186); // Fairy Tree of Star NPC.add(27186); // Fairy Tree of Star
NPC.add(27187); // Fairy Tree of Twilight NPC.add(27187); // Fairy Tree of Twilight
NPC.add(27188); // Fairy Tree of Abyss NPC.add(27188); // Fairy Tree of Abyss
NPC.add(29001); // Queen Ant
} }
private static final NpcStringId[] ON_ATTACK_MSG = private static final NpcStringId[] ON_ATTACK_MSG =

View File

@ -521,7 +521,7 @@ public final class Antharas extends AbstractNpcAI
} }
else else
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant skip waiting time right now!"); player.sendMessage(getClass().getSimpleName() + ": You can't skip waiting time right now!");
} }
break; break;
} }
@ -536,7 +536,7 @@ public final class Antharas extends AbstractNpcAI
} }
else else
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant respawn antharas while antharas is alive!"); player.sendMessage(getClass().getSimpleName() + ": You can't respawn antharas while antharas is alive!");
} }
break; break;
} }
@ -554,12 +554,12 @@ public final class Antharas extends AbstractNpcAI
} }
if (player != null) // Player dont will be null just when is this event called from GM command if (player != null) // Player dont will be null just when is this event called from GM command
{ {
player.sendMessage(getClass().getSimpleName() + ": All minions has been deleted!"); player.sendMessage(getClass().getSimpleName() + ": All minions have been deleted!");
} }
} }
else if (player != null) // Player dont will be null just when is this event called from GM command else if (player != null) // Player dont will be null just when is this event called from GM command
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant despawn minions right now!"); player.sendMessage(getClass().getSimpleName() + ": You can't despawn minions right now!");
} }
break; break;
} }
@ -595,7 +595,7 @@ public final class Antharas extends AbstractNpcAI
} }
else else
{ {
player.sendMessage(getClass().getSimpleName() + ": You cant abort fight right now!"); player.sendMessage(getClass().getSimpleName() + ": You can't abort fight right now!");
} }
break; break;
} }

View File

@ -19,18 +19,18 @@
package handlers.actionhandlers; package handlers.actionhandlers;
import com.l2jserver.Config; import com.l2jserver.Config;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention; import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.InstanceType; import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.handler.IActionHandler; import com.l2jserver.gameserver.handler.IActionHandler;
import com.l2jserver.gameserver.model.L2Object; import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character; import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Npc; import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.L2Event; import com.l2jserver.gameserver.model.entity.L2Event;
import com.l2jserver.gameserver.model.events.EventDispatcher; import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.EventType; import com.l2jserver.gameserver.model.events.EventType;
import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcFirstTalk; import com.l2jserver.gameserver.model.events.impl.character.npc.OnNpcFirstTalk;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.MoveToPawn; import com.l2jserver.gameserver.network.serverpackets.MoveToPawn;
import com.l2jserver.util.Rnd; import com.l2jserver.util.Rnd;
@ -79,23 +79,27 @@ public class L2NpcAction implements IActionHandler
else if (interact) else if (interact)
{ {
// Check if the activeChar is attackable (without a forced attack) and isn't dead // Check if the activeChar is attackable (without a forced attack) and isn't dead
if (target.isAutoAttackable(activeChar) && !((L2Character) target).isAlikeDead()) if (target.isAutoAttackable(activeChar) && !((L2Npc) target).isAlikeDead())
{ {
// Check the height difference if (GeoData.getInstance().canSeeTarget(activeChar, target))
if (Math.abs(activeChar.getZ() - target.getZ()) < 400) // this max heigth difference might need some tweaking
{ {
// Set the L2PcInstance Intention to AI_INTENTION_ATTACK
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
// activeChar.startAttack(this);
} }
else else
{ {
// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet final Location destination = GeoData.getInstance().moveCheck(activeChar, target);
activeChar.sendPacket(ActionFailed.STATIC_PACKET); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
} }
} }
else if (!target.isAutoAttackable(activeChar)) else if (!target.isAutoAttackable(activeChar))
{ {
if (GeoData.getInstance().canSeeTarget(activeChar, target))
{
final Location destination = GeoData.getInstance().moveCheck(activeChar, target);
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
return true;
}
// Calculate the distance between the L2PcInstance and the L2Npc // Calculate the distance between the L2PcInstance and the L2Npc
if (!((L2Npc) target).canInteract(activeChar)) if (!((L2Npc) target).canInteract(activeChar))
{ {

View File

@ -25,7 +25,6 @@ import com.l2jserver.gameserver.enums.PrivateStoreType;
import com.l2jserver.gameserver.handler.IActionHandler; import com.l2jserver.gameserver.handler.IActionHandler;
import com.l2jserver.gameserver.model.L2Object; import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.Location; import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.TvTEvent; import com.l2jserver.gameserver.model.entity.TvTEvent;
import com.l2jserver.gameserver.network.SystemMessageId; import com.l2jserver.gameserver.network.SystemMessageId;
@ -33,6 +32,8 @@ import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
public class L2PcInstanceAction implements IActionHandler public class L2PcInstanceAction implements IActionHandler
{ {
private static final int CURSED_WEAPON_VICTIM_MIN_LEVEL = 21;
/** /**
* Manage actions when a player click on this L2PcInstance.<BR> * Manage actions when a player click on this L2PcInstance.<BR>
* <BR> * <BR>
@ -71,7 +72,7 @@ public class L2PcInstanceAction implements IActionHandler
// Aggression target lock effect // Aggression target lock effect
if (activeChar.isLockedTarget() && (activeChar.getLockedTarget() != target)) if (activeChar.isLockedTarget() && (activeChar.getLockedTarget() != target))
{ {
activeChar.sendPacket(SystemMessageId.FAILED_TO_CHANGE_ENMITY); activeChar.sendPacket(SystemMessageId.FAILED_CHANGE_TARGET);
return false; return false;
} }
@ -83,50 +84,48 @@ public class L2PcInstanceAction implements IActionHandler
} }
else if (interact) else if (interact)
{ {
final L2PcInstance player = target.getActingPlayer();
// Check if this L2PcInstance has a Private Store // Check if this L2PcInstance has a Private Store
if (((L2PcInstance) target).getPrivateStoreType() != PrivateStoreType.NONE) if (player.getPrivateStoreType() != PrivateStoreType.NONE)
{ {
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, player);
} }
else else
{ {
// Check if this L2PcInstance is autoAttackable // Check if this L2PcInstance is autoAttackable
if (target.isAutoAttackable(activeChar)) if (player.isAutoAttackable(activeChar))
{ {
// activeChar with lvl < 21 can't attack a cursed weapon holder if ((player.isCursedWeaponEquipped() && (activeChar.getLevel() < CURSED_WEAPON_VICTIM_MIN_LEVEL)) //
// And a cursed weapon holder can't attack activeChars with lvl < 21 || (activeChar.isCursedWeaponEquipped() && (player.getLevel() < CURSED_WEAPON_VICTIM_MIN_LEVEL)))
if ((((L2PcInstance) target).isCursedWeaponEquipped() && (activeChar.getLevel() < 21)) || (activeChar.isCursedWeaponEquipped() && (((L2Character) target).getLevel() < 21)))
{ {
activeChar.sendPacket(ActionFailed.STATIC_PACKET); activeChar.sendPacket(ActionFailed.STATIC_PACKET);
} }
else else
{ {
if (GeoData.getInstance().canSeeTarget(activeChar, target)) if (GeoData.getInstance().canSeeTarget(activeChar, player))
{ {
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
activeChar.onActionRequest();
} }
else else
{ {
final Location destination = GeoData.getInstance().moveCheck(activeChar.getX(), activeChar.getY(), activeChar.getZ(), target.getX(), target.getY(), target.getZ(), activeChar.getInstanceId()); final Location destination = GeoData.getInstance().moveCheck(activeChar, player);
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
activeChar.onActionRequest();
} }
activeChar.onActionRequest();
} }
} }
else else
{ {
// This Action Failed packet avoids activeChar getting stuck when clicking three or more times // This Action Failed packet avoids activeChar getting stuck when clicking three or more times
activeChar.sendPacket(ActionFailed.STATIC_PACKET); activeChar.sendPacket(ActionFailed.STATIC_PACKET);
if (GeoData.getInstance().canSeeTarget(activeChar, target)) if (GeoData.getInstance().canSeeTarget(activeChar, player))
{ {
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, target); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
} }
else else
{ {
final Location destination = GeoData.getInstance().moveCheck(activeChar.getX(), activeChar.getY(), activeChar.getZ(), target.getX(), target.getY(), target.getZ(), activeChar.getInstanceId()); final Location destination = GeoData.getInstance().moveCheck(activeChar, player);
activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination); activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
activeChar.onActionRequest();
} }
} }
} }

View File

@ -436,6 +436,17 @@ public class GeoData
return true; return true;
} }
/**
* Verifies if the is a path between origin's location and destination, if not returns the closest location.
* @param origin the origin
* @param destination the destination
* @return the destination if there is a path or the closes location
*/
public Location moveCheck(ILocational origin, ILocational destination)
{
return moveCheck(origin.getX(), origin.getY(), origin.getZ(), destination.getX(), destination.getY(), destination.getZ(), origin.getInstanceId());
}
/** /**
* Move check. * Move check.
* @param x the x coordinate * @param x the x coordinate

View File

@ -33,6 +33,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.StampedLock; import java.util.concurrent.locks.StampedLock;
import java.util.logging.Level; import java.util.logging.Level;
@ -263,7 +264,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
/** This creature's target. */ /** This creature's target. */
private L2Object _target; private L2Object _target;
// set by the start of attack, in game ticks /** Represents the time where the attack should end, in nanoseconds. */
private volatile long _attackEndTime; private volatile long _attackEndTime;
private int _disableBowAttackEndTime; private int _disableBowAttackEndTime;
private int _disableCrossBowAttackEndTime; private int _disableCrossBowAttackEndTime;
@ -1093,7 +1094,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
final int timeAtk = calculateTimeBetweenAttacks(target, weaponItem); final int timeAtk = calculateTimeBetweenAttacks(target, weaponItem);
// the hit is calculated to happen halfway to the animation - might need further tuning e.g. in bow case // the hit is calculated to happen halfway to the animation - might need further tuning e.g. in bow case
final int timeToHit = timeAtk / 2; final int timeToHit = timeAtk / 2;
_attackEndTime = System.currentTimeMillis() + timeAtk; _attackEndTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeAtk, TimeUnit.MILLISECONDS);
final int ssGrade = (weaponItem != null) ? weaponItem.getItemGrade().ordinal() : 0; final int ssGrade = (weaponItem != null) ? weaponItem.getItemGrade().ordinal() : 0;
// Create a Server->Client packet Attack // Create a Server->Client packet Attack
Attack attack = new Attack(this, target, wasSSCharged, ssGrade); Attack attack = new Attack(this, target, wasSSCharged, ssGrade);
@ -4061,11 +4062,12 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
} }
/** /**
* @return True if the L2Character is attacking. * Verifies if the creature is attacking now.
* @return {@code true} if the creature is attacking now, {@code false} otherwise
*/ */
public final boolean isAttackingNow() public final boolean isAttackingNow()
{ {
return _attackEndTime > System.currentTimeMillis(); return _attackEndTime > System.nanoTime();
} }
/** /**
@ -5539,9 +5541,9 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
if ((targets.length > 0) && (escapeRange > 0)) if ((targets.length > 0) && (escapeRange > 0))
{ {
int _skiprange = 0; int skipRange = 0;
int _skipgeo = 0; int skipLOS = 0;
int _skippeace = 0; int skipPeaceZone = 0;
final List<L2Object> targetList = new ArrayList<>(); final List<L2Object> targetList = new ArrayList<>();
for (L2Object target : targets) for (L2Object target : targets)
{ {
@ -5549,21 +5551,25 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
{ {
if (!isInsideRadius(target.getX(), target.getY(), target.getZ(), escapeRange + getTemplate().getCollisionRadius(), true, false)) if (!isInsideRadius(target.getX(), target.getY(), target.getZ(), escapeRange + getTemplate().getCollisionRadius(), true, false))
{ {
_skiprange++; skipRange++;
continue; continue;
} }
if ((escapeRange > 0) && !GeoData.getInstance().canSeeTarget(this, target))
// Healing party members should ignore LOS.
if (((skill.getTargetType() != L2TargetType.PARTY) || !skill.hasEffectType(L2EffectType.HEAL)) //
&& !GeoData.getInstance().canSeeTarget(this, target))
{ {
_skipgeo++; skipLOS++;
continue; continue;
} }
if (skill.isBad()) if (skill.isBad())
{ {
if (isPlayer()) if (isPlayer())
{ {
if (((L2Character) target).isInsidePeaceZone(getActingPlayer())) if (((L2Character) target).isInsidePeaceZone(getActingPlayer()))
{ {
_skippeace++; skipPeaceZone++;
continue; continue;
} }
} }
@ -5571,7 +5577,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
{ {
if (((L2Character) target).isInsidePeaceZone(this, target)) if (((L2Character) target).isInsidePeaceZone(this, target))
{ {
_skippeace++; skipPeaceZone++;
continue; continue;
} }
} }
@ -5583,15 +5589,15 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
{ {
if (isPlayer()) if (isPlayer())
{ {
if (_skiprange > 0) if (skipRange > 0)
{ {
sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED); sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
} }
else if (_skipgeo > 0) else if (skipLOS > 0)
{ {
sendPacket(SystemMessageId.CANNOT_SEE_TARGET); sendPacket(SystemMessageId.CANNOT_SEE_TARGET);
} }
else if (_skippeace > 0) else if (skipPeaceZone > 0)
{ {
sendPacket(SystemMessageId.A_MALICIOUS_SKILL_CANNOT_BE_USED_IN_A_PEACE_ZONE); sendPacket(SystemMessageId.A_MALICIOUS_SKILL_CANNOT_BE_USED_IN_A_PEACE_ZONE);
} }

View File

@ -30,14 +30,15 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -407,7 +408,7 @@ public final class L2PcInstance extends L2Playable
public static final String WORLD_CHAT_VARIABLE_NAME = "WORLD_CHAT_POINTS"; public static final String WORLD_CHAT_VARIABLE_NAME = "WORLD_CHAT_POINTS";
private final List<IEventListener> _eventListeners = new CopyOnWriteArrayList<>(); private final Queue<IEventListener> _eventListeners = new ConcurrentLinkedQueue<>();
private L2GameClient _client; private L2GameClient _client;
@ -9038,6 +9039,7 @@ public final class L2PcInstance extends L2Playable
case AURA: case AURA:
case FRONT_AURA: case FRONT_AURA:
case BEHIND_AURA: case BEHIND_AURA:
case AREA_SUMMON:
case GROUND: case GROUND:
case SELF: case SELF:
break; break;
@ -14667,16 +14669,7 @@ public final class L2PcInstance extends L2Playable
public void removeEventListener(Class<? extends IEventListener> clazz) public void removeEventListener(Class<? extends IEventListener> clazz)
{ {
final Iterator<IEventListener> it = _eventListeners.iterator(); _eventListeners.removeIf(e -> e.getClass() == clazz);
IEventListener event;
while (it.hasNext())
{
event = it.next();
if (event.getClass() == clazz)
{
it.remove();
}
}
} }
public Collection<IEventListener> getEventListeners() public Collection<IEventListener> getEventListeners()

View File

@ -696,9 +696,9 @@ public class PcStat extends PlayableStat
} }
} }
public synchronized void updateVitalityPoints(int points, boolean useRates, boolean quiet) public synchronized void updateVitalityPoints(int _value, boolean useRates, boolean quiet)
{ {
if ((points == 0) || !Config.ENABLE_VITALITY) if ((_value == 0) || !Config.ENABLE_VITALITY)
{ {
return; return;
} }
@ -710,7 +710,7 @@ public class PcStat extends PlayableStat
return; return;
} }
if (points < 0) // vitality consumed if (_value < 0) // vitality consumed
{ {
int stat = (int) calcStat(Stats.VITALITY_CONSUME_RATE, 1, getActiveChar(), null); int stat = (int) calcStat(Stats.VITALITY_CONSUME_RATE, 1, getActiveChar(), null);
@ -720,37 +720,37 @@ public class PcStat extends PlayableStat
} }
if (stat < 0) if (stat < 0)
{ {
points = -points; _value = -_value;
} }
} }
if (points > 0) if (_value > 0)
{ {
// vitality increased // vitality increased
points *= Config.RATE_VITALITY_GAIN; _value *= Config.RATE_VITALITY_GAIN;
} }
else else
{ {
// vitality decreased // vitality decreased
points *= Config.RATE_VITALITY_LOST; _value *= Config.RATE_VITALITY_LOST;
} }
} }
if (points > 0) if (_value > 0)
{ {
points = Math.min(getActiveChar().getVitalityPoints() + points, MAX_VITALITY_POINTS); _value = Math.min(getActiveChar().getVitalityPoints() + _value, MAX_VITALITY_POINTS);
} }
else else
{ {
points = Math.max(getActiveChar().getVitalityPoints() + points, MIN_VITALITY_POINTS); _value = Math.max(getActiveChar().getVitalityPoints() + _value, MIN_VITALITY_POINTS);
} }
if (Math.abs(points - getActiveChar().getVitalityPoints()) <= 1e-6) if (Math.abs(_value - getActiveChar().getVitalityPoints()) <= 1e-6)
{ {
return; return;
} }
getActiveChar().setVitalityPoints(points); getActiveChar().setVitalityPoints(_value);
} }
public double getVitalityMultiplier() public double getVitalityMultiplier()

View File

@ -23,6 +23,7 @@ import com.l2jserver.gameserver.model.itemcontainer.ItemContainer;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance; import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
/** /**
* ExReplySentPost packet implementation.
* @author Migi, DS * @author Migi, DS
*/ */
public class ExReplySentPost extends AbstractItemPacket public class ExReplySentPost extends AbstractItemPacket