Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/clientpackets/RequestMoveToLocationInVehicle.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/clientpackets/RequestMoveToLocationInVehicle.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/clientpackets/RequestMoveToLocationInVehicle.java (working copy) @@ -1,101 +1,101 @@ -/* - * 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 2, 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * http://www.gnu.org/copyleft/gpl.html - */ -package net.sf.l2j.gameserver.clientpackets; - -import java.nio.ByteBuffer; - -import net.sf.l2j.gameserver.ClientThread; -import net.sf.l2j.gameserver.TaskPriority; -import net.sf.l2j.gameserver.ai.CtrlIntention; -import net.sf.l2j.gameserver.instancemanager.BoatManager; -import net.sf.l2j.gameserver.model.L2CharPosition; -import net.sf.l2j.gameserver.model.actor.instance.L2BoatInstance; -import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; -import net.sf.l2j.gameserver.serverpackets.ActionFailed; -import net.sf.l2j.gameserver.templates.L2WeaponType; -import net.sf.l2j.util.Point3D; - - -public class RequestMoveToLocationInVehicle extends ClientBasePacket -{ - private final Point3D _pos = new Point3D(0,0,0); - private final Point3D _origin_pos = new Point3D(0,0,0); - private final int _BoatId; - - public TaskPriority getPriority() { return TaskPriority.PR_HIGH; } - - /** - * @param buf - * @param client - */ - public RequestMoveToLocationInVehicle(ByteBuffer buf, ClientThread client) - { - super(buf, client); - _BoatId = readD(); //objectId of boat - _pos.x = readD(); - _pos.y = readD(); - _pos.z = readD(); - _origin_pos.x = readD(); - _origin_pos.y = readD(); - _origin_pos.z = readD(); - } - - /* (non-Javadoc) - * @see net.sf.l2j.gameserver.clientpackets.ClientBasePacket#runImpl() - */ - @Override - void runImpl() - { - L2PcInstance activeChar = getClient().getActiveChar(); - if (activeChar == null) - return; - else if (activeChar.isAttackingNow() && activeChar.getActiveWeaponItem() != null && (activeChar.getActiveWeaponItem().getItemType() == L2WeaponType.BOW)) - { - activeChar.sendPacket(new ActionFailed()); - } - else - { - if(!activeChar.isInBoat()) - { - activeChar.setInBoat(true); - } - L2BoatInstance boat = BoatManager.getInstance().GetBoat(_BoatId); - activeChar.setBoat(boat); - activeChar.setInBoatPosition(_pos); - activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO_IN_A_BOAT, new L2CharPosition(_pos.getX(),_pos.getY(), _pos.getZ(), 0), new L2CharPosition(_origin_pos.getX(),_origin_pos.getY(),_origin_pos.getZ(), 0)); - } - - } - - /** - * @return - */ - - - /* (non-Javadoc) - * @see net.sf.l2j.gameserver.BasePacket#getType() - */ - @Override - public String getType() - { - // TODO Auto-generated method stub - return null; - } - +/* + * 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 2, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * http://www.gnu.org/copyleft/gpl.html + */ +package net.sf.l2j.gameserver.clientpackets; + +import java.nio.ByteBuffer; + +import net.sf.l2j.gameserver.ClientThread; +import net.sf.l2j.gameserver.TaskPriority; +import net.sf.l2j.gameserver.ai.CtrlIntention; +import net.sf.l2j.gameserver.instancemanager.BoatManager; +import net.sf.l2j.gameserver.model.L2CharPosition; +import net.sf.l2j.gameserver.model.actor.instance.L2BoatInstance; +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; +import net.sf.l2j.gameserver.serverpackets.ActionFailed; +import net.sf.l2j.gameserver.templates.L2WeaponType; +import net.sf.l2j.util.Point3D; + + +public class RequestMoveToLocationInVehicle extends ClientBasePacket +{ + private final Point3D _pos = new Point3D(0,0,0); + private final Point3D _origin_pos = new Point3D(0,0,0); + private final int _BoatId; + + public TaskPriority getPriority() { return TaskPriority.PR_HIGH; } + + /** + * @param buf + * @param client + */ + public RequestMoveToLocationInVehicle(ByteBuffer buf, ClientThread client) + { + super(buf, client); + _BoatId = readD(); //objectId of boat + _pos.setX(readD()); + _pos.setY(readD()); + _pos.setZ(readD()); + _origin_pos.setX(readD()); + _origin_pos.setY(readD()); + _origin_pos.setZ(readD()); + } + + /* (non-Javadoc) + * @see net.sf.l2j.gameserver.clientpackets.ClientBasePacket#runImpl() + */ + @Override + void runImpl() + { + L2PcInstance activeChar = getClient().getActiveChar(); + if (activeChar == null) + return; + else if (activeChar.isAttackingNow() && activeChar.getActiveWeaponItem() != null && (activeChar.getActiveWeaponItem().getItemType() == L2WeaponType.BOW)) + { + activeChar.sendPacket(new ActionFailed()); + } + else + { + if(!activeChar.isInBoat()) + { + activeChar.setInBoat(true); + } + L2BoatInstance boat = BoatManager.getInstance().GetBoat(_BoatId); + activeChar.setBoat(boat); + activeChar.setInBoatPosition(_pos); + activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO_IN_A_BOAT, new L2CharPosition(_pos.getX(),_pos.getY(), _pos.getZ(), 0), new L2CharPosition(_origin_pos.getX(),_origin_pos.getY(),_origin_pos.getZ(), 0)); + } + + } + + /** + * @return + */ + + + /* (non-Javadoc) + * @see net.sf.l2j.gameserver.BasePacket#getType() + */ + @Override + public String getType() + { + // TODO Auto-generated method stub + return null; + } + } \ No newline at end of file Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/L2Object.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/L2Object.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/L2Object.java (working copy) @@ -1,375 +1,375 @@ -/* - * 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 2, 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * http://www.gnu.org/copyleft/gpl.html - */ -package net.sf.l2j.gameserver.model; - -import net.sf.l2j.Config; -import net.sf.l2j.gameserver.ClientThread; -import net.sf.l2j.gameserver.idfactory.IdFactory; -import net.sf.l2j.gameserver.instancemanager.MercTicketManager; -import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; -import net.sf.l2j.gameserver.model.actor.knownlist.ObjectKnownList; -import net.sf.l2j.gameserver.model.actor.poly.ObjectPoly; -import net.sf.l2j.gameserver.model.actor.position.ObjectPosition; -import net.sf.l2j.gameserver.serverpackets.ActionFailed; -import net.sf.l2j.gameserver.serverpackets.GetItem; - - -/** - * Mother class of all objects in the world wich ones is it possible - * to interact (PC, NPC, Item...)

- * - * L2Object :

- *
  • L2Character
  • - *
  • L2ItemInstance
  • - *
  • L2Potion
  • - * - */ - -public abstract class L2Object -{ - // ========================================================= - // Data Field - private boolean _IsVisible; // Object visibility - private ObjectKnownList _KnownList; - private String _Name; - private int _ObjectId; // Object identifier - private ObjectPoly _Poly; - private ObjectPosition _Position; - - // ========================================================= - // Constructor - public L2Object(int objectId) - { - _ObjectId = objectId; - } - - // ========================================================= - // Event - Public - public void onAction(L2PcInstance player) - { - player.sendPacket(new ActionFailed()); - } - - public void onActionShift(ClientThread client) - { - client.getActiveChar().sendPacket(new ActionFailed()); - } - - public void onForcedAttack(L2PcInstance player) - { - player.sendPacket(new ActionFailed()); - } - - /** - * Do Nothing.

    - * - * Overriden in :

    - *
  • L2GuardInstance : Set the home location of its L2GuardInstance
  • - *
  • L2Attackable : Reset the Spoiled falg


  • - * - */ - public void OnSpawn() - { - } - - // ========================================================= - // Position - Should remove to fully move to L2ObjectPosition - public final void setXYZ(int x, int y, int z) - { - getPosition().setXYZ(x, y, z); - } - - public final void setXYZInvisible(int x, int y, int z) - { - getPosition().setXYZInvisible(x, y, z); - } - - public final int getX() - { - if (Config.ASSERT) assert getPosition().getWorldRegion() != null || _IsVisible; - return getPosition().getX(); - } - - public final int getY() - { - if (Config.ASSERT) assert getPosition().getWorldRegion() != null || _IsVisible; - return getPosition().getY(); - } - - public final int getZ() - { - if (Config.ASSERT) assert getPosition().getWorldRegion() != null || _IsVisible; - return getPosition().getZ(); - } - - // ========================================================= - // Method - Public - /** - * Remove a L2Object from the world.

    - * - * Actions :

    - *
  • Remove the L2Object from the world


  • - * - * Caution : This method DOESN'T REMOVE the object from _allObjects of L2World
    - * Caution : This method DOESN'T SEND Server->Client packets to players

    - * - * Assert :

    - *
  • _worldRegion != null (L2Object is visible at the beginning)


  • - * - * Example of use :

    - *
  • Delete NPC/PC or Unsummon


  • - * - */ - public final void decayMe() - { - if (Config.ASSERT) assert getPosition().getWorldRegion() != null; - - L2WorldRegion reg = getPosition().getWorldRegion(); - - synchronized (this) - { - _IsVisible = false; - getPosition().setWorldRegion(null); - } - - // this can synchronize on others instancies, so it's out of - // synchronized, to avoid deadlocks - // Remove the L2Object from the world - L2World.getInstance().removeVisibleObject(this, reg); - } - - - /** - * Remove a L2ItemInstance from the world and send server->client GetItem packets.

    - * - * Actions :

    - *
  • Send a Server->Client Packet GetItem to player that pick up and its _knowPlayers member
  • - *
  • Remove the L2Object from the world


  • - * - * Caution : This method DOESN'T REMOVE the object from _allObjects of L2World

    - * - * Assert :

    - *
  • this instanceof L2ItemInstance
  • - *
  • _worldRegion != null (L2Object is visible at the beginning)


  • - * - * Example of use :

    - *
  • Do Pickup Item : PCInstance and Pet


  • - * - * @param player Player that pick up the item - * - */ - public final void pickupMe(L2Character player) // NOTE: Should move this function into L2ItemInstance because it does not apply to L2Character - { - if (Config.ASSERT) assert this instanceof L2ItemInstance; - if (Config.ASSERT) assert getPosition().getWorldRegion() != null; - - L2WorldRegion oldregion = getPosition().getWorldRegion(); - - // Create a server->client GetItem packet to pick up the L2ItemInstance - GetItem gi = new GetItem((L2ItemInstance)this, player.getObjectId()); - player.broadcastPacket(gi); - - synchronized (this) - { - _IsVisible = false; - getPosition().setWorldRegion(null); - } - - // if this item is a mercenary ticket, remove the spawns! - if (this instanceof L2ItemInstance) - { - int itemId = ((L2ItemInstance)this).getItemId(); - if (itemId >=3960 && itemId <=4021) - { - MercTicketManager.getInstance().removeTicket((L2ItemInstance)this); - } - } - - - // this can synchronize on others instancies, so it's out of - // synchronized, to avoid deadlocks - // Remove the L2ItemInstance from the world - L2World.getInstance().removeVisibleObject(this, oldregion); - } - - public void refreshID() - { - L2World.getInstance().removeObject(this); - IdFactory.getInstance().releaseId(getObjectId()); - _ObjectId = IdFactory.getInstance().getNextId(); - } - - /** - * Init the position of a L2Object spawn and add it in the world as a visible object.

    - * - * Actions :

    - *
  • Set the x,y,z position of the L2Object spawn and update its _worldregion
  • - *
  • Add the L2Object spawn in the _allobjects of L2World
  • - *
  • Add the L2Object spawn to _visibleObjects of its L2WorldRegion
  • - *
  • Add the L2Object spawn in the world as a visible object


  • - * - * Assert :

    - *
  • _worldRegion == null (L2Object is invisible at the beginning)


  • - * - * Example of use :

    - *
  • Create Door
  • - *
  • Spawn : Monster, Minion, CTs, Summon...

  • - * - */ - public final void spawnMe() - { - if (Config.ASSERT) assert getPosition().getWorldRegion() == null && getPosition().getWorldPosition().x != 0 && getPosition().getWorldPosition().y != 0 && getPosition().getWorldPosition().z != 0; - - synchronized (this) - { - // Set the x,y,z position of the L2Object spawn and update its _worldregion - _IsVisible = true; - getPosition().setWorldRegion(L2World.getInstance().getRegion(getPosition().getWorldPosition())); - - // Add the L2Object spawn in the _allobjects of L2World - L2World.getInstance().storeObject(this); - - // Add the L2Object spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion - getPosition().getWorldRegion().addVisibleObject(this); - } - - // this can synchronize on others instancies, so it's out of - // synchronized, to avoid deadlocks - // Add the L2Object spawn in the world as a visible object - L2World.getInstance().addVisibleObject(this, getPosition().getWorldRegion(), null); - } - - public final void spawnMe(int x, int y, int z) - { - if (Config.ASSERT) assert getPosition().getWorldRegion() == null; - - synchronized (this) - { - // Set the x,y,z position of the L2Object spawn and update its _worldregion - _IsVisible = true; - - if (x > L2World.MAP_MAX_X) x = L2World.MAP_MAX_X - 5000; - if (x < L2World.MAP_MIN_X) x = L2World.MAP_MIN_X + 5000; - if (y > L2World.MAP_MAX_Y) y = L2World.MAP_MAX_Y - 5000; - if (y < L2World.MAP_MIN_Y) y = L2World.MAP_MIN_Y + 5000; - - getPosition().setWorldPosition(x, y ,z); - getPosition().setWorldRegion(L2World.getInstance().getRegion(getPosition().getWorldPosition())); - - // Add the L2Object spawn in the _allobjects of L2World - L2World.getInstance().storeObject(this); - - // Add the L2Object spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion - getPosition().getWorldRegion().addVisibleObject(this); - } - - // this can synchronize on others instancies, so it's out of - // synchronized, to avoid deadlocks - // Add the L2Object spawn in the world as a visible object - L2World.getInstance().addVisibleObject(this, getPosition().getWorldRegion(), null); - } - - public void toggleVisible() - { - if (isVisible()) - decayMe(); - else - spawnMe(); - } - - // ========================================================= - // Method - Private - - // ========================================================= - // Property - Public - public boolean isAttackable() - { - return false; - } - - public abstract boolean isAutoAttackable(L2Character attacker); - - public boolean isMarker() - { - return false; - } - - /** - * Return the visibilty state of the L2Object.

    - * - * Concept :

    - * A L2Object is visble if __IsVisible=true and _worldregion!=null

    - */ - public final boolean isVisible() - { - //return getPosition().getWorldRegion() != null && _IsVisible; - return getPosition().getWorldRegion() != null; - } - public final void setIsVisible(boolean value) - { - _IsVisible = value; - if (!_IsVisible) getPosition().setWorldRegion(null); - } - - public ObjectKnownList getKnownList() - { - if (_KnownList == null) _KnownList = new ObjectKnownList(new L2Object[]{this}); - return _KnownList; - } - public final void setKnownList(ObjectKnownList value) { _KnownList = value; } - - public final String getName() - { - return _Name; - } - public final void setName(String value) - { - _Name = value; - } - - public final int getObjectId() - { - return _ObjectId; - } - - public final ObjectPoly getPoly() - { - if (_Poly == null) _Poly = new ObjectPoly(new L2Object[] {this}); - return _Poly; - } - - public final ObjectPosition getPosition() - { - if (_Position == null) _Position = new ObjectPosition(new L2Object[] {this}); - return _Position; - } - - /** - * returns reference to region this object is in - */ - public L2WorldRegion getWorldRegion() - { - return getPosition().getWorldRegion(); - } - - public String toString() - { - return "" + getObjectId(); - } +/* + * 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 2, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * http://www.gnu.org/copyleft/gpl.html + */ +package net.sf.l2j.gameserver.model; + +import net.sf.l2j.Config; +import net.sf.l2j.gameserver.ClientThread; +import net.sf.l2j.gameserver.idfactory.IdFactory; +import net.sf.l2j.gameserver.instancemanager.MercTicketManager; +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; +import net.sf.l2j.gameserver.model.actor.knownlist.ObjectKnownList; +import net.sf.l2j.gameserver.model.actor.poly.ObjectPoly; +import net.sf.l2j.gameserver.model.actor.position.ObjectPosition; +import net.sf.l2j.gameserver.serverpackets.ActionFailed; +import net.sf.l2j.gameserver.serverpackets.GetItem; + + +/** + * Mother class of all objects in the world wich ones is it possible + * to interact (PC, NPC, Item...)

    + * + * L2Object :

    + *
  • L2Character
  • + *
  • L2ItemInstance
  • + *
  • L2Potion
  • + * + */ + +public abstract class L2Object +{ + // ========================================================= + // Data Field + private boolean _IsVisible; // Object visibility + private ObjectKnownList _KnownList; + private String _Name; + private int _ObjectId; // Object identifier + private ObjectPoly _Poly; + private ObjectPosition _Position; + + // ========================================================= + // Constructor + public L2Object(int objectId) + { + _ObjectId = objectId; + } + + // ========================================================= + // Event - Public + public void onAction(L2PcInstance player) + { + player.sendPacket(new ActionFailed()); + } + + public void onActionShift(ClientThread client) + { + client.getActiveChar().sendPacket(new ActionFailed()); + } + + public void onForcedAttack(L2PcInstance player) + { + player.sendPacket(new ActionFailed()); + } + + /** + * Do Nothing.

    + * + * Overriden in :

    + *
  • L2GuardInstance : Set the home location of its L2GuardInstance
  • + *
  • L2Attackable : Reset the Spoiled falg


  • + * + */ + public void OnSpawn() + { + } + + // ========================================================= + // Position - Should remove to fully move to L2ObjectPosition + public final void setXYZ(int x, int y, int z) + { + getPosition().setXYZ(x, y, z); + } + + public final void setXYZInvisible(int x, int y, int z) + { + getPosition().setXYZInvisible(x, y, z); + } + + public final int getX() + { + if (Config.ASSERT) assert getPosition().getWorldRegion() != null || _IsVisible; + return getPosition().getX(); + } + + public final int getY() + { + if (Config.ASSERT) assert getPosition().getWorldRegion() != null || _IsVisible; + return getPosition().getY(); + } + + public final int getZ() + { + if (Config.ASSERT) assert getPosition().getWorldRegion() != null || _IsVisible; + return getPosition().getZ(); + } + + // ========================================================= + // Method - Public + /** + * Remove a L2Object from the world.

    + * + * Actions :

    + *
  • Remove the L2Object from the world


  • + * + * Caution : This method DOESN'T REMOVE the object from _allObjects of L2World
    + * Caution : This method DOESN'T SEND Server->Client packets to players

    + * + * Assert :

    + *
  • _worldRegion != null (L2Object is visible at the beginning)


  • + * + * Example of use :

    + *
  • Delete NPC/PC or Unsummon


  • + * + */ + public final void decayMe() + { + if (Config.ASSERT) assert getPosition().getWorldRegion() != null; + + L2WorldRegion reg = getPosition().getWorldRegion(); + + synchronized (this) + { + _IsVisible = false; + getPosition().setWorldRegion(null); + } + + // this can synchronize on others instancies, so it's out of + // synchronized, to avoid deadlocks + // Remove the L2Object from the world + L2World.getInstance().removeVisibleObject(this, reg); + } + + + /** + * Remove a L2ItemInstance from the world and send server->client GetItem packets.

    + * + * Actions :

    + *
  • Send a Server->Client Packet GetItem to player that pick up and its _knowPlayers member
  • + *
  • Remove the L2Object from the world


  • + * + * Caution : This method DOESN'T REMOVE the object from _allObjects of L2World

    + * + * Assert :

    + *
  • this instanceof L2ItemInstance
  • + *
  • _worldRegion != null (L2Object is visible at the beginning)


  • + * + * Example of use :

    + *
  • Do Pickup Item : PCInstance and Pet


  • + * + * @param player Player that pick up the item + * + */ + public final void pickupMe(L2Character player) // NOTE: Should move this function into L2ItemInstance because it does not apply to L2Character + { + if (Config.ASSERT) assert this instanceof L2ItemInstance; + if (Config.ASSERT) assert getPosition().getWorldRegion() != null; + + L2WorldRegion oldregion = getPosition().getWorldRegion(); + + // Create a server->client GetItem packet to pick up the L2ItemInstance + GetItem gi = new GetItem((L2ItemInstance)this, player.getObjectId()); + player.broadcastPacket(gi); + + synchronized (this) + { + _IsVisible = false; + getPosition().setWorldRegion(null); + } + + // if this item is a mercenary ticket, remove the spawns! + if (this instanceof L2ItemInstance) + { + int itemId = ((L2ItemInstance)this).getItemId(); + if (itemId >=3960 && itemId <=4021) + { + MercTicketManager.getInstance().removeTicket((L2ItemInstance)this); + } + } + + + // this can synchronize on others instancies, so it's out of + // synchronized, to avoid deadlocks + // Remove the L2ItemInstance from the world + L2World.getInstance().removeVisibleObject(this, oldregion); + } + + public void refreshID() + { + L2World.getInstance().removeObject(this); + IdFactory.getInstance().releaseId(getObjectId()); + _ObjectId = IdFactory.getInstance().getNextId(); + } + + /** + * Init the position of a L2Object spawn and add it in the world as a visible object.

    + * + * Actions :

    + *
  • Set the x,y,z position of the L2Object spawn and update its _worldregion
  • + *
  • Add the L2Object spawn in the _allobjects of L2World
  • + *
  • Add the L2Object spawn to _visibleObjects of its L2WorldRegion
  • + *
  • Add the L2Object spawn in the world as a visible object


  • + * + * Assert :

    + *
  • _worldRegion == null (L2Object is invisible at the beginning)


  • + * + * Example of use :

    + *
  • Create Door
  • + *
  • Spawn : Monster, Minion, CTs, Summon...

  • + * + */ + public final void spawnMe() + { + if (Config.ASSERT) assert getPosition().getWorldRegion() == null && getPosition().getWorldPosition().getX() != 0 && getPosition().getWorldPosition().getY() != 0 && getPosition().getWorldPosition().getZ() != 0; + + synchronized (this) + { + // Set the x,y,z position of the L2Object spawn and update its _worldregion + _IsVisible = true; + getPosition().setWorldRegion(L2World.getInstance().getRegion(getPosition().getWorldPosition())); + + // Add the L2Object spawn in the _allobjects of L2World + L2World.getInstance().storeObject(this); + + // Add the L2Object spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion + getPosition().getWorldRegion().addVisibleObject(this); + } + + // this can synchronize on others instancies, so it's out of + // synchronized, to avoid deadlocks + // Add the L2Object spawn in the world as a visible object + L2World.getInstance().addVisibleObject(this, getPosition().getWorldRegion(), null); + } + + public final void spawnMe(int x, int y, int z) + { + if (Config.ASSERT) assert getPosition().getWorldRegion() == null; + + synchronized (this) + { + // Set the x,y,z position of the L2Object spawn and update its _worldregion + _IsVisible = true; + + if (x > L2World.MAP_MAX_X) x = L2World.MAP_MAX_X - 5000; + if (x < L2World.MAP_MIN_X) x = L2World.MAP_MIN_X + 5000; + if (y > L2World.MAP_MAX_Y) y = L2World.MAP_MAX_Y - 5000; + if (y < L2World.MAP_MIN_Y) y = L2World.MAP_MIN_Y + 5000; + + getPosition().setWorldPosition(x, y ,z); + getPosition().setWorldRegion(L2World.getInstance().getRegion(getPosition().getWorldPosition())); + + // Add the L2Object spawn in the _allobjects of L2World + L2World.getInstance().storeObject(this); + + // Add the L2Object spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion + getPosition().getWorldRegion().addVisibleObject(this); + } + + // this can synchronize on others instancies, so it's out of + // synchronized, to avoid deadlocks + // Add the L2Object spawn in the world as a visible object + L2World.getInstance().addVisibleObject(this, getPosition().getWorldRegion(), null); + } + + public void toggleVisible() + { + if (isVisible()) + decayMe(); + else + spawnMe(); + } + + // ========================================================= + // Method - Private + + // ========================================================= + // Property - Public + public boolean isAttackable() + { + return false; + } + + public abstract boolean isAutoAttackable(L2Character attacker); + + public boolean isMarker() + { + return false; + } + + /** + * Return the visibilty state of the L2Object.

    + * + * Concept :

    + * A L2Object is visble if __IsVisible=true and _worldregion!=null

    + */ + public final boolean isVisible() + { + //return getPosition().getWorldRegion() != null && _IsVisible; + return getPosition().getWorldRegion() != null; + } + public final void setIsVisible(boolean value) + { + _IsVisible = value; + if (!_IsVisible) getPosition().setWorldRegion(null); + } + + public ObjectKnownList getKnownList() + { + if (_KnownList == null) _KnownList = new ObjectKnownList(new L2Object[]{this}); + return _KnownList; + } + public final void setKnownList(ObjectKnownList value) { _KnownList = value; } + + public final String getName() + { + return _Name; + } + public final void setName(String value) + { + _Name = value; + } + + public final int getObjectId() + { + return _ObjectId; + } + + public final ObjectPoly getPoly() + { + if (_Poly == null) _Poly = new ObjectPoly(new L2Object[] {this}); + return _Poly; + } + + public final ObjectPosition getPosition() + { + if (_Position == null) _Position = new ObjectPosition(new L2Object[] {this}); + return _Position; + } + + /** + * returns reference to region this object is in + */ + public L2WorldRegion getWorldRegion() + { + return getPosition().getWorldRegion(); + } + + public String toString() + { + return "" + getObjectId(); + } } \ No newline at end of file Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/L2World.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/L2World.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/L2World.java (working copy) @@ -1,695 +1,695 @@ -/* - * 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 2, 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * http://www.gnu.org/copyleft/gpl.html - */ -package net.sf.l2j.gameserver.model; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import javolution.util.FastList; -import javolution.util.FastMap; -import net.sf.l2j.Config; -import net.sf.l2j.gameserver.GmListTable; -import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; -import net.sf.l2j.util.L2ObjectMap; -import net.sf.l2j.util.Point3D; - -/** - * This class ... - * - * @version $Revision: 1.21.2.5.2.7 $ $Date: 2005/03/27 15:29:32 $ - */ -public final class L2World -{ - private static Logger _log = Logger.getLogger(L2World.class.getName()); - - /* - * biteshift, defines number of regions - * note, shifting by 15 will result in regions corresponding to map tiles - * shifting by 12 divides one tile to 8x8 regions - */ - private static final int SHIFT_BY = 13; - - /** Map dimensions */ - public static final int MAP_MIN_X = -131072; - public static final int MAP_MAX_X = 228608; - public static final int MAP_MIN_Y = -256144; - public static final int MAP_MAX_Y = 262144; - - /** calculated offset used so top left region is 0,0 */ - private static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); - private static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - - /** number of regions */ - private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; - private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - - - //private FastMap _allGms; - - /** HashMap(String Player name, L2PcInstance) containing all the players in game */ - private Map _allPlayers; - - /** L2ObjectHashMap(L2Object) containing all visible objects */ - private L2ObjectMap _allObjects; - - private static final L2World _instance = new L2World(); - - private L2WorldRegion[][] _worldRegions; - - - /** - * Constructor of L2World.

    - */ - private L2World() - { - //_allGms = new FastMap(); - _allPlayers = new FastMap().setShared(true); - _allObjects = L2ObjectMap.createL2ObjectMap(); - - initRegions(); - } - - - /** - * Return the current instance of L2World.

    - */ - public static L2World getInstance() - { - return _instance; - } - - /** - * Add L2Object object in _allObjects.

    - * - * Example of use :

    - *
  • Withdraw an item from the warehouse, create an item
  • - *
  • Spawn a L2Character (PC, NPC, Pet)

  • - */ - public void storeObject(L2Object object) - { - if(_allObjects.get(object.getObjectId()) != null) - { - if (Config.DEBUG) - _log.warning("[L2World] objectId "+object.getObjectId()+" already exist in OID map!"); - return; - } - - _allObjects.put(object); - } - - public long timeStoreObject(L2Object object) - { - long time = System.currentTimeMillis(); - _allObjects.put(object); - time -= System.currentTimeMillis(); - return time; - } - - /** - * Remove L2Object object from _allObjects of L2World.

    - * - * Example of use :

    - *
  • Delete item from inventory, tranfer Item from inventory to warehouse
  • - *
  • Crystallize item
  • - *
  • Remove NPC/PC/Pet from the world

  • - * - * @param object L2Object to remove from _allObjects of L2World - * - */ - public void removeObject(L2Object object) - { - _allObjects.remove(object); // suggestion by whatev - //IdFactory.getInstance().releaseId(object.getObjectId()); - } - - public void removeObjects(List list) - { - for(L2Object o : list) _allObjects.remove(o); // suggestion by whatev - //IdFactory.getInstance().releaseId(object.getObjectId()); - } - - public void removeObjects(L2Object[] objects) - { - for(L2Object o : objects) _allObjects.remove(o); // suggestion by whatev - //IdFactory.getInstance().releaseId(object.getObjectId()); - } - - public long timeRemoveObject(L2Object object) - { - long time = System.currentTimeMillis(); - _allObjects.remove(object); - time -= System.currentTimeMillis(); - return time; - } - - /** - * Return the L2Object object that belongs to an ID or null if no object found.

    - * - * Example of use :

    - *
  • Client packets : Action, AttackRequest, RequestJoinParty, RequestJoinPledge...

  • - * - * @param oID Identifier of the L2Object - */ - public L2Object findObject(int oID) - { - return _allObjects.get(oID); - } - - public long timeFindObject(int objectID) - { - long time = System.currentTimeMillis(); - _allObjects.get(objectID); - time -= System.currentTimeMillis(); - return time; - } - - /** - * Added by Tempy - 08 Aug 05 - * Allows easy retrevial of all visible objects in world. - * - * -- do not use that fucntion, its unsafe! - * - * @deprecated - */ - @Deprecated - public final L2ObjectMap getAllVisibleObjects() - { - return _allObjects; - } - - - /** - * Get the count of all visible objects in world.

    - * - * @return count off all L2World objects - */ - public final int getAllVisibleObjectsCount() - { - return _allObjects.size(); - } - - /** - * Return a table containing all GMs.

    - * - */ - public L2PcInstance[] getAllGMs() - { - return GmListTable.getInstance().getAllGms(); - } - - /** - * Return a collection containing all players in game.

    - * - * Caution : Read-only, please!

    - */ - public Collection getAllPlayers() - { - return _allPlayers.values(); - } - - /** - * Return how many players are online.

    - * - * @return number of online players. - */ - public int getAllPlayersCount() - { - return _allPlayers.size(); - } - - /** - * Return the player instance corresponding to the given name.

    - * - * @param name Name of the player to get Instance - */ - public L2PcInstance getPlayer(String name) - { - return _allPlayers.get(name.toLowerCase()); - } - - - /** - * Add a L2Object in the world.

    - * - * Concept :

    - * L2Object (including L2PcInstance) are identified in _visibleObjects of his current L2WorldRegion and in _knownObjects of other surrounding L2Characters
    - * L2PcInstance are identified in _allPlayers of L2World, in _allPlayers of his current L2WorldRegion and in _knownPlayer of other surrounding L2Characters

    - * - * Actions :

    - *
  • Add the L2Object object in _allPlayers* of L2World
  • - *
  • Add the L2Object object in _gmList** of GmListTable
  • - *
  • Add object in _knownObjects and _knownPlayer* of all surrounding L2WorldRegion L2Characters

  • - * - *
  • If object is a L2Character, add all surrounding L2Object in its _knownObjects and all surrounding L2PcInstance in its _knownPlayer

  • - * - * * only if object is a L2PcInstance
    - * ** only if object is a GM L2PcInstance

    - * - * Caution : This method DOESN'T ADD the object in _visibleObjects and _allPlayers* of L2WorldRegion (need synchronisation)
    - * Caution : This method DOESN'T ADD the object to _allObjects and _allPlayers* of L2World (need synchronisation)

    - * - * Example of use :

    - *
  • Drop an Item
  • - *
  • Spawn a L2Character
  • - *
  • Apply Death Penalty of a L2PcInstance


  • - * - * @param object L2object to add in the world - * @param newregion L2WorldRegion in wich the object will be add (not used) - * @param dropper L2Character who has dropped the object (if necessary) - * - */ - public void addVisibleObject(L2Object object, @SuppressWarnings("unused") L2WorldRegion newRegion, L2Character dropper) - { - // If selected L2Object is a L2PcIntance, add it in L2ObjectHashSet(L2PcInstance) _allPlayers of L2World - // XXX TODO: this code should be obsoleted by protection in putObject func... - if (object instanceof L2PcInstance) - { - L2PcInstance player = (L2PcInstance) object; - - L2PcInstance tmp = _allPlayers.get(player.getName().toLowerCase()); - if(tmp!= null) - { - _log.warning("Duplicate character!? Closing both characters ("+player.getName()+")"); - player.closeNetConnection(); - tmp.closeNetConnection(); - return; - } - - _allPlayers.put(player.getName().toLowerCase(), player); - } - - // Get all visible objects contained in the _visibleObjects of L2WorldRegions - // in a circular area of 2000 units - L2Object[] visible = getVisibleObjects(object, 2000); - if (Config.DEBUG) _log.finest("objects in range:"+visible.length); - - // tell the player about the surroundings - // Go through the visible objects contained in the circular area - for (int i = 0; i < visible.length; i++) - { - // Add the object in L2ObjectHashSet(L2Object) _knownObjects of the visible L2Character according to conditions : - // - L2Character is visible - // - object is not already known - // - object is in the watch distance - // If L2Object is a L2PcInstance, add L2Object in L2ObjectHashSet(L2PcInstance) _knownPlayer of the visible L2Character - visible[i].getKnownList().addKnownObject(object, dropper); - - // Add the visible L2Object in L2ObjectHashSet(L2Object) _knownObjects of the object according to conditions - // If visible L2Object is a L2PcInstance, add visible L2Object in L2ObjectHashSet(L2PcInstance) _knownPlayer of the object - object.getKnownList().addKnownObject(visible[i], dropper); - } - } - - - /** - * Remove the L2PcInstance from _allPlayers of L2World.

    - * - * Example of use :

    - *
  • Remove a player fom the visible objects

  • - * - */ - public void removeFromAllPlayers(L2PcInstance cha) - { - _allPlayers.remove(cha.getName().toLowerCase()); - } - - - /** - * Remove a L2Object from the world.

    - * - * Concept :

    - * L2Object (including L2PcInstance) are identified in _visibleObjects of his current L2WorldRegion and in _knownObjects of other surrounding L2Characters
    - * L2PcInstance are identified in _allPlayers of L2World, in _allPlayers of his current L2WorldRegion and in _knownPlayer of other surrounding L2Characters

    - * - * Actions :

    - *
  • Remove the L2Object object from _allPlayers* of L2World
  • - *
  • Remove the L2Object object from _visibleObjects and _allPlayers* of L2WorldRegion
  • - *
  • Remove the L2Object object from _gmList** of GmListTable
  • - *
  • Remove object from _knownObjects and _knownPlayer* of all surrounding L2WorldRegion L2Characters

  • - * - *
  • If object is a L2Character, remove all L2Object from its _knownObjects and all L2PcInstance from its _knownPlayer


  • - * - * Caution : This method DOESN'T REMOVE the object from _allObjects of L2World

    - * - * * only if object is a L2PcInstance
    - * ** only if object is a GM L2PcInstance

    - * - * Example of use :

    - *
  • Pickup an Item
  • - *
  • Decay a L2Character


  • - * - * @param object L2object to remove from the world - * @param oldregion L2WorldRegion in wich the object was before removing - * - */ - public void removeVisibleObject(L2Object object, L2WorldRegion oldRegion) - { - if (object == null) - return; - - //removeObject(object); - - if (oldRegion != null) - { - // Remove the object from the L2ObjectHashSet(L2Object) _visibleObjects of L2WorldRegion - // If object is a L2PcInstance, remove it from the L2ObjectHashSet(L2PcInstance) _allPlayers of this L2WorldRegion - oldRegion.removeVisibleObject(object); - - - // Go through all surrounding L2WorldRegion L2Characters - for (L2WorldRegion reg : oldRegion.getSurroundingRegions()) { - Iterator iter = reg.iterateVisibleObjects(); - while (iter.hasNext()) - { - L2Object obj = iter.next(); - - // Remove the L2Object from the L2ObjectHashSet(L2Object) _knownObjects of the surrounding L2WorldRegion L2Characters - // If object is a L2PcInstance, remove the L2Object from the L2ObjectHashSet(L2PcInstance) _knownPlayer of the surrounding L2WorldRegion L2Characters - // If object is targeted by one of the surrounding L2WorldRegion L2Characters, cancel ATTACK and cast - if (obj != null && obj.getKnownList() != null) - obj.getKnownList().removeKnownObject(object); - - // Remove surrounding L2WorldRegion L2Characters from the L2ObjectHashSet(L2Object) _KnownObjects of object - // If surrounding L2WorldRegion L2Characters is a L2PcInstance, remove it from the L2ObjectHashSet(L2PcInstance) _knownPlayer of object - // TODO Delete this line if all the stuff is done by the next line object.removeAllKnownObjects() - if (object.getKnownList() != null) - object.getKnownList().removeKnownObject(obj); - } - } - - // If object is a L2Character : - // Remove all L2Object from L2ObjectHashSet(L2Object) containing all L2Object detected by the L2Character - // Remove all L2PcInstance from L2ObjectHashSet(L2PcInstance) containing all player ingame detected by the L2Character - object.getKnownList().removeAllKnownObjects(); - - - // If selected L2Object is a L2PcIntance, remove it from L2ObjectHashSet(L2PcInstance) _allPlayers of L2World - if (object instanceof L2PcInstance) - { - removeFromAllPlayers((L2PcInstance)object); - - // If selected L2Object is a GM L2PcInstance, remove it from Set(L2PcInstance) _gmList of GmListTable - //if (((L2PcInstance)object).isGM()) - //GmListTable.getInstance().deleteGm((L2PcInstance)object); - } - - } - } - - - /** - * Return all visible objects of the L2WorldRegion object's and of its surrounding L2WorldRegion.

    - * - * Concept :

    - * All visible object are identified in _visibleObjects of their current L2WorldRegion
    - * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    - * - * Example of use :

    - *
  • Find Close Objects for L2Character

  • - * - * @param object L2object that determine the current L2WorldRegion - * - */ - public Collection getVisibleObjects(L2Object object) - { - L2WorldRegion reg = object.getWorldRegion(); - - if (reg == null) - return null; - - // Create an FastList in order to contain all visible L2Object - FastList result = new FastList(); - - // Create a FastList containing all regions around the current region - List _regions = reg.getSurroundingRegions(); - - // Go through the FastList of region - for (int i = 0; i < _regions.size(); i++) - { - // Create an Iterator to go through the visible L2Object of the L2WorldRegion - Iterator _objects = _regions.get(i).iterateVisibleObjects(); - - // Go through visible object of the selected region - while (_objects.hasNext()) - { - L2Object _object = _objects.next(); - - if (_object == null) - continue; - - if (_object.equals(object)) - continue; // skip our own character - - if (!_object.isVisible()) - continue; // skip dying objects - - result.add(_object); - } - } - - return result; - } - - - /** - * Return all visible objects of the L2WorldRegions in the circular area (radius) centered on the object.

    - * - * Concept :

    - * All visible object are identified in _visibleObjects of their current L2WorldRegion
    - * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    - * - * Example of use :

    - *
  • Define the aggrolist of monster
  • - *
  • Define visible objects of a L2Object
  • - *
  • Skill : Confusion...

  • - * - * @param object L2object that determine the center of the circular area - * @param radius Radius of the circular area - * - */ - public L2Object[] getVisibleObjects(L2Object object, int radius) - { - if (object == null || !object.isVisible()) - return new L2Object[0]; - - int x = object.getX(); - int y = object.getY(); - int sqRadius = radius*radius; - - // Create an FastList in order to contain all visible L2Object - List result = new FastList(); - - // Create an FastList containing all regions around the current region - List _regions = object.getWorldRegion().getSurroundingRegions(); - - // Go through the FastList of region - for (int i = 0; i < _regions.size(); i++) { - - // Create an Iterator to go through the visible L2Object of the L2WorldRegion - Iterator _objects = _regions.get(i).iterateVisibleObjects(); - - // Go through visible object of the selected region - while (_objects.hasNext()) - { - L2Object _object = _objects.next(); - if (_object.equals(object)) continue; // skip our own character - - int x1 = _object.getX(); - int y1 = _object.getY(); - - int dx = x1 - x; - //if (dx > radius || -dx > radius) - // continue; - int dy = y1 - y; - //if (dy > radius || -dy > radius) - // continue; - - // If the visible object is inside the circular area - // add the object to the FastList result - if (dx*dx + dy*dy < sqRadius) - result.add(_object); - } - } - - return result.toArray(new L2Object[result.size()]); - } - - - /** - * Return all visible objects of the L2WorldRegions in the spheric area (radius) centered on the object.

    - * - * Concept :

    - * All visible object are identified in _visibleObjects of their current L2WorldRegion
    - * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    - * - * Example of use :

    - *
  • Define the target list of a skill
  • - *
  • Define the target list of a polearme attack


  • - * - * @param object L2object that determine the center of the circular area - * @param radius Radius of the spheric area - * - */ - public L2Object[] getVisibleObjects3D(L2Object object, int radius) - { - if (object == null || !object.isVisible()) - return new L2Object[0]; - - int x = object.getX(); - int y = object.getY(); - int z = object.getZ(); - int sqRadius = radius*radius; - - // Create an FastList in order to contain all visible L2Object - List result = new FastList(); - - // Create an FastList containing all regions around the current region - List _regions = object.getWorldRegion().getSurroundingRegions(); - - // Go through visible object of the selected region - for (int i = 0; i < _regions.size(); i++) - { - // Create an Iterator to go through the visible L2Object of the L2WorldRegion - Iterator _objects = _regions.get(i).iterateVisibleObjects(); - - // Go through visible object of the selected region - while (_objects.hasNext()) - { - L2Object _object = _objects.next(); - if (_object.equals(object)) continue; // skip our own character - - int x1 = _object.getX(); - int y1 = _object.getY(); - int z1 = _object.getZ(); - - int dx = x1 - x; - //if (dx > radius || -dx > radius) - // continue; - int dy = y1 - y; - //if (dy > radius || -dy > radius) - // continue; - int dz = z1 - z; - - if (dx*dx + dy*dy + dz*dz < sqRadius) - result.add(_object); - } - } - - return result.toArray(new L2Object[result.size()]); - } - - /** - * Calculate the current L2WorldRegions of the object according to its position (x,y).

    - * - * Example of use :

    - *
  • Set position of a new L2Object (drop, spawn...)
  • - *
  • Update position of a L2Object after a mouvement

  • - * - * @param Point3D point position of the object - */ - public L2WorldRegion getRegion(Point3D point) - { - return _worldRegions[(point.x >> SHIFT_BY) + OFFSET_X][(point.y >> SHIFT_BY) + OFFSET_Y]; - } - - public L2WorldRegion getRegion(int x, int y) - { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; - } - - /** - * Check if the current L2WorldRegions of the object is valid according to its position (x,y).

    - * - * Example of use :

    - *
  • Init L2WorldRegions

  • - * - * @param x X position of the object - * @param y Y position of the object - * - * @return True if the L2WorldRegion is valid - */ - private boolean validRegion(int x, int y) - { - return (x >= 0 && x < REGIONS_X && y >= 0 && y < REGIONS_Y); - } - - /** - * Init each L2WorldRegion and their surrounding table.

    - * - * Concept :

    - * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    - * - * Example of use :

    - *
  • Constructor of L2World

  • - * - */ - private void initRegions() - { - _log.config("L2World: Setting up World Regions"); - - _worldRegions = new L2WorldRegion[REGIONS_X+1][REGIONS_Y+1]; - - for (int i = 0; i <= REGIONS_X; i++) - { - for (int j = 0; j <= REGIONS_Y; j++) - { - _worldRegions[i][j] = new L2WorldRegion(i, j); - } - } - - for (int x=0; x < REGIONS_X; x++) - { - for (int y=0; y < REGIONS_Y; y++) - { - for (int a = -1; a <= 1; a++) - { - for (int b = -1; b <= 1; b++) - { - if (validRegion(x + a, y + b)) - { - _worldRegions[x + a][y + b].addSurroundingRegion(_worldRegions[x][y]); - } - } - } - } - } - - _log.config("L2World: ("+REGIONS_X+" by "+REGIONS_Y+") World Region Grid set up."); - - } - - /** - * Deleted all spawns in the world. - */ - public synchronized void deleteVisibleNpcSpawns() - { - _log.info("Deleting all visible NPC's."); - for (int i = 0; i <= REGIONS_X; i++) - { - for (int j = 0; j <= REGIONS_Y; j++) - { - _worldRegions[i][j].deleteVisibleNpcSpawns(); - } - } - _log.info("All visible NPC's deleted."); - } -} +/* + * 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 2, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * http://www.gnu.org/copyleft/gpl.html + */ +package net.sf.l2j.gameserver.model; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import javolution.util.FastList; +import javolution.util.FastMap; +import net.sf.l2j.Config; +import net.sf.l2j.gameserver.GmListTable; +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; +import net.sf.l2j.util.L2ObjectMap; +import net.sf.l2j.util.Point3D; + +/** + * This class ... + * + * @version $Revision: 1.21.2.5.2.7 $ $Date: 2005/03/27 15:29:32 $ + */ +public final class L2World +{ + private static Logger _log = Logger.getLogger(L2World.class.getName()); + + /* + * biteshift, defines number of regions + * note, shifting by 15 will result in regions corresponding to map tiles + * shifting by 12 divides one tile to 8x8 regions + */ + private static final int SHIFT_BY = 13; + + /** Map dimensions */ + public static final int MAP_MIN_X = -131072; + public static final int MAP_MAX_X = 228608; + public static final int MAP_MIN_Y = -256144; + public static final int MAP_MAX_Y = 262144; + + /** calculated offset used so top left region is 0,0 */ + private static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); + private static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); + + /** number of regions */ + private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; + private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; + + + //private FastMap _allGms; + + /** HashMap(String Player name, L2PcInstance) containing all the players in game */ + private Map _allPlayers; + + /** L2ObjectHashMap(L2Object) containing all visible objects */ + private L2ObjectMap _allObjects; + + private static final L2World _instance = new L2World(); + + private L2WorldRegion[][] _worldRegions; + + + /** + * Constructor of L2World.

    + */ + private L2World() + { + //_allGms = new FastMap(); + _allPlayers = new FastMap().setShared(true); + _allObjects = L2ObjectMap.createL2ObjectMap(); + + initRegions(); + } + + + /** + * Return the current instance of L2World.

    + */ + public static L2World getInstance() + { + return _instance; + } + + /** + * Add L2Object object in _allObjects.

    + * + * Example of use :

    + *
  • Withdraw an item from the warehouse, create an item
  • + *
  • Spawn a L2Character (PC, NPC, Pet)

  • + */ + public void storeObject(L2Object object) + { + if(_allObjects.get(object.getObjectId()) != null) + { + if (Config.DEBUG) + _log.warning("[L2World] objectId "+object.getObjectId()+" already exist in OID map!"); + return; + } + + _allObjects.put(object); + } + + public long timeStoreObject(L2Object object) + { + long time = System.currentTimeMillis(); + _allObjects.put(object); + time -= System.currentTimeMillis(); + return time; + } + + /** + * Remove L2Object object from _allObjects of L2World.

    + * + * Example of use :

    + *
  • Delete item from inventory, tranfer Item from inventory to warehouse
  • + *
  • Crystallize item
  • + *
  • Remove NPC/PC/Pet from the world

  • + * + * @param object L2Object to remove from _allObjects of L2World + * + */ + public void removeObject(L2Object object) + { + _allObjects.remove(object); // suggestion by whatev + //IdFactory.getInstance().releaseId(object.getObjectId()); + } + + public void removeObjects(List list) + { + for(L2Object o : list) _allObjects.remove(o); // suggestion by whatev + //IdFactory.getInstance().releaseId(object.getObjectId()); + } + + public void removeObjects(L2Object[] objects) + { + for(L2Object o : objects) _allObjects.remove(o); // suggestion by whatev + //IdFactory.getInstance().releaseId(object.getObjectId()); + } + + public long timeRemoveObject(L2Object object) + { + long time = System.currentTimeMillis(); + _allObjects.remove(object); + time -= System.currentTimeMillis(); + return time; + } + + /** + * Return the L2Object object that belongs to an ID or null if no object found.

    + * + * Example of use :

    + *
  • Client packets : Action, AttackRequest, RequestJoinParty, RequestJoinPledge...

  • + * + * @param oID Identifier of the L2Object + */ + public L2Object findObject(int oID) + { + return _allObjects.get(oID); + } + + public long timeFindObject(int objectID) + { + long time = System.currentTimeMillis(); + _allObjects.get(objectID); + time -= System.currentTimeMillis(); + return time; + } + + /** + * Added by Tempy - 08 Aug 05 + * Allows easy retrevial of all visible objects in world. + * + * -- do not use that fucntion, its unsafe! + * + * @deprecated + */ + @Deprecated + public final L2ObjectMap getAllVisibleObjects() + { + return _allObjects; + } + + + /** + * Get the count of all visible objects in world.

    + * + * @return count off all L2World objects + */ + public final int getAllVisibleObjectsCount() + { + return _allObjects.size(); + } + + /** + * Return a table containing all GMs.

    + * + */ + public L2PcInstance[] getAllGMs() + { + return GmListTable.getInstance().getAllGms(); + } + + /** + * Return a collection containing all players in game.

    + * + * Caution : Read-only, please!

    + */ + public Collection getAllPlayers() + { + return _allPlayers.values(); + } + + /** + * Return how many players are online.

    + * + * @return number of online players. + */ + public int getAllPlayersCount() + { + return _allPlayers.size(); + } + + /** + * Return the player instance corresponding to the given name.

    + * + * @param name Name of the player to get Instance + */ + public L2PcInstance getPlayer(String name) + { + return _allPlayers.get(name.toLowerCase()); + } + + + /** + * Add a L2Object in the world.

    + * + * Concept :

    + * L2Object (including L2PcInstance) are identified in _visibleObjects of his current L2WorldRegion and in _knownObjects of other surrounding L2Characters
    + * L2PcInstance are identified in _allPlayers of L2World, in _allPlayers of his current L2WorldRegion and in _knownPlayer of other surrounding L2Characters

    + * + * Actions :

    + *
  • Add the L2Object object in _allPlayers* of L2World
  • + *
  • Add the L2Object object in _gmList** of GmListTable
  • + *
  • Add object in _knownObjects and _knownPlayer* of all surrounding L2WorldRegion L2Characters

  • + * + *
  • If object is a L2Character, add all surrounding L2Object in its _knownObjects and all surrounding L2PcInstance in its _knownPlayer

  • + * + * * only if object is a L2PcInstance
    + * ** only if object is a GM L2PcInstance

    + * + * Caution : This method DOESN'T ADD the object in _visibleObjects and _allPlayers* of L2WorldRegion (need synchronisation)
    + * Caution : This method DOESN'T ADD the object to _allObjects and _allPlayers* of L2World (need synchronisation)

    + * + * Example of use :

    + *
  • Drop an Item
  • + *
  • Spawn a L2Character
  • + *
  • Apply Death Penalty of a L2PcInstance


  • + * + * @param object L2object to add in the world + * @param newregion L2WorldRegion in wich the object will be add (not used) + * @param dropper L2Character who has dropped the object (if necessary) + * + */ + public void addVisibleObject(L2Object object, @SuppressWarnings("unused") L2WorldRegion newRegion, L2Character dropper) + { + // If selected L2Object is a L2PcIntance, add it in L2ObjectHashSet(L2PcInstance) _allPlayers of L2World + // XXX TODO: this code should be obsoleted by protection in putObject func... + if (object instanceof L2PcInstance) + { + L2PcInstance player = (L2PcInstance) object; + + L2PcInstance tmp = _allPlayers.get(player.getName().toLowerCase()); + if(tmp!= null) + { + _log.warning("Duplicate character!? Closing both characters ("+player.getName()+")"); + player.closeNetConnection(); + tmp.closeNetConnection(); + return; + } + + _allPlayers.put(player.getName().toLowerCase(), player); + } + + // Get all visible objects contained in the _visibleObjects of L2WorldRegions + // in a circular area of 2000 units + L2Object[] visible = getVisibleObjects(object, 2000); + if (Config.DEBUG) _log.finest("objects in range:"+visible.length); + + // tell the player about the surroundings + // Go through the visible objects contained in the circular area + for (int i = 0; i < visible.length; i++) + { + // Add the object in L2ObjectHashSet(L2Object) _knownObjects of the visible L2Character according to conditions : + // - L2Character is visible + // - object is not already known + // - object is in the watch distance + // If L2Object is a L2PcInstance, add L2Object in L2ObjectHashSet(L2PcInstance) _knownPlayer of the visible L2Character + visible[i].getKnownList().addKnownObject(object, dropper); + + // Add the visible L2Object in L2ObjectHashSet(L2Object) _knownObjects of the object according to conditions + // If visible L2Object is a L2PcInstance, add visible L2Object in L2ObjectHashSet(L2PcInstance) _knownPlayer of the object + object.getKnownList().addKnownObject(visible[i], dropper); + } + } + + + /** + * Remove the L2PcInstance from _allPlayers of L2World.

    + * + * Example of use :

    + *
  • Remove a player fom the visible objects

  • + * + */ + public void removeFromAllPlayers(L2PcInstance cha) + { + _allPlayers.remove(cha.getName().toLowerCase()); + } + + + /** + * Remove a L2Object from the world.

    + * + * Concept :

    + * L2Object (including L2PcInstance) are identified in _visibleObjects of his current L2WorldRegion and in _knownObjects of other surrounding L2Characters
    + * L2PcInstance are identified in _allPlayers of L2World, in _allPlayers of his current L2WorldRegion and in _knownPlayer of other surrounding L2Characters

    + * + * Actions :

    + *
  • Remove the L2Object object from _allPlayers* of L2World
  • + *
  • Remove the L2Object object from _visibleObjects and _allPlayers* of L2WorldRegion
  • + *
  • Remove the L2Object object from _gmList** of GmListTable
  • + *
  • Remove object from _knownObjects and _knownPlayer* of all surrounding L2WorldRegion L2Characters

  • + * + *
  • If object is a L2Character, remove all L2Object from its _knownObjects and all L2PcInstance from its _knownPlayer


  • + * + * Caution : This method DOESN'T REMOVE the object from _allObjects of L2World

    + * + * * only if object is a L2PcInstance
    + * ** only if object is a GM L2PcInstance

    + * + * Example of use :

    + *
  • Pickup an Item
  • + *
  • Decay a L2Character


  • + * + * @param object L2object to remove from the world + * @param oldregion L2WorldRegion in wich the object was before removing + * + */ + public void removeVisibleObject(L2Object object, L2WorldRegion oldRegion) + { + if (object == null) + return; + + //removeObject(object); + + if (oldRegion != null) + { + // Remove the object from the L2ObjectHashSet(L2Object) _visibleObjects of L2WorldRegion + // If object is a L2PcInstance, remove it from the L2ObjectHashSet(L2PcInstance) _allPlayers of this L2WorldRegion + oldRegion.removeVisibleObject(object); + + + // Go through all surrounding L2WorldRegion L2Characters + for (L2WorldRegion reg : oldRegion.getSurroundingRegions()) { + Iterator iter = reg.iterateVisibleObjects(); + while (iter.hasNext()) + { + L2Object obj = iter.next(); + + // Remove the L2Object from the L2ObjectHashSet(L2Object) _knownObjects of the surrounding L2WorldRegion L2Characters + // If object is a L2PcInstance, remove the L2Object from the L2ObjectHashSet(L2PcInstance) _knownPlayer of the surrounding L2WorldRegion L2Characters + // If object is targeted by one of the surrounding L2WorldRegion L2Characters, cancel ATTACK and cast + if (obj != null && obj.getKnownList() != null) + obj.getKnownList().removeKnownObject(object); + + // Remove surrounding L2WorldRegion L2Characters from the L2ObjectHashSet(L2Object) _KnownObjects of object + // If surrounding L2WorldRegion L2Characters is a L2PcInstance, remove it from the L2ObjectHashSet(L2PcInstance) _knownPlayer of object + // TODO Delete this line if all the stuff is done by the next line object.removeAllKnownObjects() + if (object.getKnownList() != null) + object.getKnownList().removeKnownObject(obj); + } + } + + // If object is a L2Character : + // Remove all L2Object from L2ObjectHashSet(L2Object) containing all L2Object detected by the L2Character + // Remove all L2PcInstance from L2ObjectHashSet(L2PcInstance) containing all player ingame detected by the L2Character + object.getKnownList().removeAllKnownObjects(); + + + // If selected L2Object is a L2PcIntance, remove it from L2ObjectHashSet(L2PcInstance) _allPlayers of L2World + if (object instanceof L2PcInstance) + { + removeFromAllPlayers((L2PcInstance)object); + + // If selected L2Object is a GM L2PcInstance, remove it from Set(L2PcInstance) _gmList of GmListTable + //if (((L2PcInstance)object).isGM()) + //GmListTable.getInstance().deleteGm((L2PcInstance)object); + } + + } + } + + + /** + * Return all visible objects of the L2WorldRegion object's and of its surrounding L2WorldRegion.

    + * + * Concept :

    + * All visible object are identified in _visibleObjects of their current L2WorldRegion
    + * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    + * + * Example of use :

    + *
  • Find Close Objects for L2Character

  • + * + * @param object L2object that determine the current L2WorldRegion + * + */ + public Collection getVisibleObjects(L2Object object) + { + L2WorldRegion reg = object.getWorldRegion(); + + if (reg == null) + return null; + + // Create an FastList in order to contain all visible L2Object + FastList result = new FastList(); + + // Create a FastList containing all regions around the current region + List _regions = reg.getSurroundingRegions(); + + // Go through the FastList of region + for (int i = 0; i < _regions.size(); i++) + { + // Create an Iterator to go through the visible L2Object of the L2WorldRegion + Iterator _objects = _regions.get(i).iterateVisibleObjects(); + + // Go through visible object of the selected region + while (_objects.hasNext()) + { + L2Object _object = _objects.next(); + + if (_object == null) + continue; + + if (_object.equals(object)) + continue; // skip our own character + + if (!_object.isVisible()) + continue; // skip dying objects + + result.add(_object); + } + } + + return result; + } + + + /** + * Return all visible objects of the L2WorldRegions in the circular area (radius) centered on the object.

    + * + * Concept :

    + * All visible object are identified in _visibleObjects of their current L2WorldRegion
    + * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    + * + * Example of use :

    + *
  • Define the aggrolist of monster
  • + *
  • Define visible objects of a L2Object
  • + *
  • Skill : Confusion...

  • + * + * @param object L2object that determine the center of the circular area + * @param radius Radius of the circular area + * + */ + public L2Object[] getVisibleObjects(L2Object object, int radius) + { + if (object == null || !object.isVisible()) + return new L2Object[0]; + + int x = object.getX(); + int y = object.getY(); + int sqRadius = radius*radius; + + // Create an FastList in order to contain all visible L2Object + List result = new FastList(); + + // Create an FastList containing all regions around the current region + List _regions = object.getWorldRegion().getSurroundingRegions(); + + // Go through the FastList of region + for (int i = 0; i < _regions.size(); i++) { + + // Create an Iterator to go through the visible L2Object of the L2WorldRegion + Iterator _objects = _regions.get(i).iterateVisibleObjects(); + + // Go through visible object of the selected region + while (_objects.hasNext()) + { + L2Object _object = _objects.next(); + if (_object.equals(object)) continue; // skip our own character + + int x1 = _object.getX(); + int y1 = _object.getY(); + + int dx = x1 - x; + //if (dx > radius || -dx > radius) + // continue; + int dy = y1 - y; + //if (dy > radius || -dy > radius) + // continue; + + // If the visible object is inside the circular area + // add the object to the FastList result + if (dx*dx + dy*dy < sqRadius) + result.add(_object); + } + } + + return result.toArray(new L2Object[result.size()]); + } + + + /** + * Return all visible objects of the L2WorldRegions in the spheric area (radius) centered on the object.

    + * + * Concept :

    + * All visible object are identified in _visibleObjects of their current L2WorldRegion
    + * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    + * + * Example of use :

    + *
  • Define the target list of a skill
  • + *
  • Define the target list of a polearme attack


  • + * + * @param object L2object that determine the center of the circular area + * @param radius Radius of the spheric area + * + */ + public L2Object[] getVisibleObjects3D(L2Object object, int radius) + { + if (object == null || !object.isVisible()) + return new L2Object[0]; + + int x = object.getX(); + int y = object.getY(); + int z = object.getZ(); + int sqRadius = radius*radius; + + // Create an FastList in order to contain all visible L2Object + List result = new FastList(); + + // Create an FastList containing all regions around the current region + List _regions = object.getWorldRegion().getSurroundingRegions(); + + // Go through visible object of the selected region + for (int i = 0; i < _regions.size(); i++) + { + // Create an Iterator to go through the visible L2Object of the L2WorldRegion + Iterator _objects = _regions.get(i).iterateVisibleObjects(); + + // Go through visible object of the selected region + while (_objects.hasNext()) + { + L2Object _object = _objects.next(); + if (_object.equals(object)) continue; // skip our own character + + int x1 = _object.getX(); + int y1 = _object.getY(); + int z1 = _object.getZ(); + + int dx = x1 - x; + //if (dx > radius || -dx > radius) + // continue; + int dy = y1 - y; + //if (dy > radius || -dy > radius) + // continue; + int dz = z1 - z; + + if (dx*dx + dy*dy + dz*dz < sqRadius) + result.add(_object); + } + } + + return result.toArray(new L2Object[result.size()]); + } + + /** + * Calculate the current L2WorldRegions of the object according to its position (x,y).

    + * + * Example of use :

    + *
  • Set position of a new L2Object (drop, spawn...)
  • + *
  • Update position of a L2Object after a mouvement

  • + * + * @param Point3D point position of the object + */ + public L2WorldRegion getRegion(Point3D point) + { + return _worldRegions[(point.getX() >> SHIFT_BY) + OFFSET_X][(point.getY() >> SHIFT_BY) + OFFSET_Y]; + } + + public L2WorldRegion getRegion(int x, int y) + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; + } + + /** + * Check if the current L2WorldRegions of the object is valid according to its position (x,y).

    + * + * Example of use :

    + *
  • Init L2WorldRegions

  • + * + * @param x X position of the object + * @param y Y position of the object + * + * @return True if the L2WorldRegion is valid + */ + private boolean validRegion(int x, int y) + { + return (x >= 0 && x < REGIONS_X && y >= 0 && y < REGIONS_Y); + } + + /** + * Init each L2WorldRegion and their surrounding table.

    + * + * Concept :

    + * All surrounding L2WorldRegion are identified in _surroundingRegions of the selected L2WorldRegion in order to scan a large area around a L2Object

    + * + * Example of use :

    + *
  • Constructor of L2World

  • + * + */ + private void initRegions() + { + _log.config("L2World: Setting up World Regions"); + + _worldRegions = new L2WorldRegion[REGIONS_X+1][REGIONS_Y+1]; + + for (int i = 0; i <= REGIONS_X; i++) + { + for (int j = 0; j <= REGIONS_Y; j++) + { + _worldRegions[i][j] = new L2WorldRegion(i, j); + } + } + + for (int x=0; x < REGIONS_X; x++) + { + for (int y=0; y < REGIONS_Y; y++) + { + for (int a = -1; a <= 1; a++) + { + for (int b = -1; b <= 1; b++) + { + if (validRegion(x + a, y + b)) + { + _worldRegions[x + a][y + b].addSurroundingRegion(_worldRegions[x][y]); + } + } + } + } + } + + _log.config("L2World: ("+REGIONS_X+" by "+REGIONS_Y+") World Region Grid set up."); + + } + + /** + * Deleted all spawns in the world. + */ + public synchronized void deleteVisibleNpcSpawns() + { + _log.info("Deleting all visible NPC's."); + for (int i = 0; i <= REGIONS_X; i++) + { + for (int j = 0; j <= REGIONS_Y; j++) + { + _worldRegions[i][j].deleteVisibleNpcSpawns(); + } + } + _log.info("All visible NPC's deleted."); + } +} Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java (working copy) @@ -1,8371 +1,8371 @@ -/* - * 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 2, 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * http://www.gnu.org/copyleft/gpl.html - */ -package net.sf.l2j.gameserver.model.actor.instance; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.util.Calendar; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import javolution.util.FastList; -import javolution.util.FastMap; -import javolution.util.FastSet; -import net.sf.l2j.Config; -import net.sf.l2j.L2DatabaseFactory; -import net.sf.l2j.gameserver.CharTemplateTable; -import net.sf.l2j.gameserver.ClanTable; -import net.sf.l2j.gameserver.Connection; -import net.sf.l2j.gameserver.GameTimeController; -import net.sf.l2j.gameserver.GmListTable; -import net.sf.l2j.gameserver.HennaTable; -import net.sf.l2j.gameserver.ItemTable; -import net.sf.l2j.gameserver.LoginServerThread; -import net.sf.l2j.gameserver.MapRegionTable; -import net.sf.l2j.gameserver.Olympiad; -import net.sf.l2j.gameserver.RecipeController; -import net.sf.l2j.gameserver.SevenSigns; -import net.sf.l2j.gameserver.SevenSignsFestival; -import net.sf.l2j.gameserver.SkillTable; -import net.sf.l2j.gameserver.SkillTreeTable; -import net.sf.l2j.gameserver.ThreadPoolManager; -import net.sf.l2j.gameserver.Universe; -import net.sf.l2j.gameserver.ai.CtrlIntention; -import net.sf.l2j.gameserver.ai.L2CharacterAI; -import net.sf.l2j.gameserver.ai.L2PlayerAI; -import net.sf.l2j.gameserver.cache.HtmCache; -import net.sf.l2j.gameserver.communitybbs.BB.Forum; -import net.sf.l2j.gameserver.communitybbs.Manager.ForumsBBSManager; -import net.sf.l2j.gameserver.handler.IItemHandler; -import net.sf.l2j.gameserver.handler.ItemHandler; -import net.sf.l2j.gameserver.handler.skillhandlers.SiegeFlag; -import net.sf.l2j.gameserver.handler.skillhandlers.TakeCastle; -import net.sf.l2j.gameserver.instancemanager.ArenaManager; -import net.sf.l2j.gameserver.instancemanager.CastleManager; -import net.sf.l2j.gameserver.instancemanager.QuestManager; -import net.sf.l2j.gameserver.instancemanager.SiegeManager; -import net.sf.l2j.gameserver.instancemanager.ZoneManager; -import net.sf.l2j.gameserver.lib.Rnd; -import net.sf.l2j.gameserver.model.BlockList; -import net.sf.l2j.gameserver.model.Inventory; -import net.sf.l2j.gameserver.model.ItemContainer; -import net.sf.l2j.gameserver.model.L2Attackable; -import net.sf.l2j.gameserver.model.L2CharPosition; -import net.sf.l2j.gameserver.model.L2Character; -import net.sf.l2j.gameserver.model.L2Clan; -import net.sf.l2j.gameserver.model.L2ClanMember; -import net.sf.l2j.gameserver.model.L2DropData; -import net.sf.l2j.gameserver.model.L2Effect; -import net.sf.l2j.gameserver.model.L2Fishing; -import net.sf.l2j.gameserver.model.L2HennaInstance; -import net.sf.l2j.gameserver.model.L2ItemInstance; -import net.sf.l2j.gameserver.model.L2Macro; -import net.sf.l2j.gameserver.model.L2ManufactureList; -import net.sf.l2j.gameserver.model.L2Object; -import net.sf.l2j.gameserver.model.L2Party; -import net.sf.l2j.gameserver.model.L2Radar; -import net.sf.l2j.gameserver.model.L2RecipeList; -import net.sf.l2j.gameserver.model.L2ShortCut; -import net.sf.l2j.gameserver.model.L2Skill; -import net.sf.l2j.gameserver.model.L2SkillLearn; -import net.sf.l2j.gameserver.model.L2Summon; -import net.sf.l2j.gameserver.model.L2World; -import net.sf.l2j.gameserver.model.MacroList; -import net.sf.l2j.gameserver.model.PcFreight; -import net.sf.l2j.gameserver.model.PcInventory; -import net.sf.l2j.gameserver.model.PcWarehouse; -import net.sf.l2j.gameserver.model.PetInventory; -import net.sf.l2j.gameserver.model.ShortCuts; -import net.sf.l2j.gameserver.model.TradeList; -import net.sf.l2j.gameserver.model.L2Skill.SkillTargetType; -import net.sf.l2j.gameserver.model.L2Skill.SkillType; -import net.sf.l2j.gameserver.model.actor.knownlist.PcKnownList; -import net.sf.l2j.gameserver.model.actor.stat.PcStat; -import net.sf.l2j.gameserver.model.actor.status.PcStatus; -import net.sf.l2j.gameserver.model.base.ClassId; -import net.sf.l2j.gameserver.model.base.Race; -import net.sf.l2j.gameserver.model.base.SubClass; -import net.sf.l2j.gameserver.model.entity.Castle; -import net.sf.l2j.gameserver.model.entity.L2Event; -import net.sf.l2j.gameserver.model.entity.Siege; -import net.sf.l2j.gameserver.model.entity.Zone; -import net.sf.l2j.gameserver.model.entity.ZoneType; -import net.sf.l2j.gameserver.model.quest.Quest; -import net.sf.l2j.gameserver.model.quest.QuestState; -import net.sf.l2j.gameserver.model.waypoint.WayPointNode; -import net.sf.l2j.gameserver.serverpackets.ActionFailed; -import net.sf.l2j.gameserver.serverpackets.ChangeWaitType; -import net.sf.l2j.gameserver.serverpackets.CharInfo; -import net.sf.l2j.gameserver.serverpackets.ExFishingEnd; -import net.sf.l2j.gameserver.serverpackets.ExFishingStart; -import net.sf.l2j.gameserver.serverpackets.ExOlympiadMode; -import net.sf.l2j.gameserver.serverpackets.ExOlympiadUserInfo; -import net.sf.l2j.gameserver.serverpackets.HennaInfo; -import net.sf.l2j.gameserver.serverpackets.InventoryUpdate; -import net.sf.l2j.gameserver.serverpackets.ItemList; -import net.sf.l2j.gameserver.serverpackets.MagicSkillCanceld; -import net.sf.l2j.gameserver.serverpackets.MyTargetSelected; -import net.sf.l2j.gameserver.serverpackets.NpcHtmlMessage; -import net.sf.l2j.gameserver.serverpackets.ObservationMode; -import net.sf.l2j.gameserver.serverpackets.ObservationReturn; -import net.sf.l2j.gameserver.serverpackets.PartySmallWindowUpdate; -import net.sf.l2j.gameserver.serverpackets.PetInventoryUpdate; -import net.sf.l2j.gameserver.serverpackets.PledgeShowMemberListAdd; -import net.sf.l2j.gameserver.serverpackets.PrivateStoreListBuy; -import net.sf.l2j.gameserver.serverpackets.PrivateStoreListSell; -import net.sf.l2j.gameserver.serverpackets.RecipeShopSellList; -import net.sf.l2j.gameserver.serverpackets.Ride; -import net.sf.l2j.gameserver.serverpackets.SendTradeDone; -import net.sf.l2j.gameserver.serverpackets.ServerBasePacket; -import net.sf.l2j.gameserver.serverpackets.SetupGauge; -import net.sf.l2j.gameserver.serverpackets.ShortCutInit; -import net.sf.l2j.gameserver.serverpackets.Snoop; -import net.sf.l2j.gameserver.serverpackets.SocialAction; -import net.sf.l2j.gameserver.serverpackets.StatusUpdate; -import net.sf.l2j.gameserver.serverpackets.StopMove; -import net.sf.l2j.gameserver.serverpackets.SystemMessage; -import net.sf.l2j.gameserver.serverpackets.TargetSelected; -import net.sf.l2j.gameserver.serverpackets.TradeStart; -import net.sf.l2j.gameserver.serverpackets.UserInfo; -import net.sf.l2j.gameserver.skills.Stats; -import net.sf.l2j.gameserver.templates.L2Armor; -import net.sf.l2j.gameserver.templates.L2ArmorType; -import net.sf.l2j.gameserver.templates.L2CharTemplate; -import net.sf.l2j.gameserver.templates.L2Henna; -import net.sf.l2j.gameserver.templates.L2Item; -import net.sf.l2j.gameserver.templates.L2PcTemplate; -import net.sf.l2j.gameserver.templates.L2Weapon; -import net.sf.l2j.gameserver.templates.L2WeaponType; -import net.sf.l2j.gameserver.util.Broadcast; -import net.sf.l2j.gameserver.util.Util; -import net.sf.l2j.util.Point3D; - -/** - * This class represents all player characters in the world. - * There is always a client-thread connected to this (except if a player-store is activated upon logout).

    - * - * @version $Revision: 1.66.2.41.2.33 $ $Date: 2005/04/11 10:06:09 $ - */ -public final class L2PcInstance extends L2PlayableInstance -{ - private static final String RESTORE_SKILLS_FOR_CHAR = "SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? AND class_index=?"; - private static final String ADD_NEW_SKILL = "INSERT INTO character_skills (char_obj_id,skill_id,skill_level,skill_name,class_index) VALUES (?,?,?,?,?)"; - private static final String UPDATE_CHARACTER_SKILL_LEVEL = "UPDATE character_skills SET skill_level=? WHERE skill_id=? AND char_obj_id=? AND class_index=?"; - private static final String DELETE_SKILL_FROM_CHAR = "DELETE FROM character_skills WHERE skill_id=? AND char_obj_id=? AND class_index=?"; - private static final String DELETE_CHAR_SKILLS = "DELETE FROM character_skills WHERE char_obj_id=? AND class_index=?"; - - private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (char_obj_id,skill_id,skill_level,effect_count,effect_cur_time,class_index) VALUES (?,?,?,?,?,?)"; - private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,effect_count,effect_cur_time FROM character_skills_save WHERE char_obj_id=? AND class_index=?"; - private static final String DELETE_SKILL_SAVE = "DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=?"; - - private static final String UPDATE_CHARACTER = "UPDATE characters SET level=?,maxHp=?,curHp=?,maxCp=?,curCp=?,maxMp=?,curMp=?,str=?,con=?,dex=?,_int=?,men=?,wit=?,face=?,hairStyle=?,hairColor=?,heading=?,x=?,y=?,z=?,exp=?,sp=?,karma=?,pvpkills=?,pkkills=?,rec_have=?,rec_left=?,clanid=?,maxload=?,race=?,classid=?,deletetime=?,title=?,allyId=?,accesslevel=?,online=?,isin7sdungeon=?,clan_privs=?,wantspeace=?,deleteclan=?,base_class=?,onlinetime=?,in_jail=?,jail_timer=?,newbie=? WHERE obj_id=?"; - private static final String RESTORE_CHARACTER = "SELECT account_name, obj_Id, char_name, level, maxHp, curHp, maxCp, curCp, maxMp, curMp, acc, crit, evasion, mAtk, mDef, mSpd, pAtk, pDef, pSpd, runSpd, walkSpd, str, con, dex, _int, men, wit, face, hairStyle, hairColor, sex, heading, x, y, z, movement_multiplier, attack_speed_multiplier, colRad, colHeight, exp, sp, karma, pvpkills, pkkills, clanid, maxload, race, classid, deletetime, cancraft, title, allyId, rec_have, rec_left, accesslevel, online, char_slot, lastAccess, clan_privs, wantspeace, deleteclan, base_class, onlinetime, isin7sdungeon, in_jail, jail_timer, newbie FROM characters WHERE obj_id=?"; - private static final String RESTORE_CHAR_SUBCLASSES = "SELECT class_id,exp,sp,level,class_index FROM character_subclasses WHERE char_obj_id=? ORDER BY class_index ASC"; - private static final String ADD_CHAR_SUBCLASS = "INSERT INTO character_subclasses (char_obj_id,class_id,exp,sp,level,class_index) VALUES (?,?,?,?,?,?)"; - private static final String UPDATE_CHAR_SUBCLASS = "UPDATE character_subclasses SET exp=?,sp=?,level=?,class_id=? WHERE char_obj_id=? AND class_index =?"; - private static final String DELETE_CHAR_SUBCLASS = "DELETE FROM character_subclasses WHERE char_obj_id=? AND class_index=?"; - - private static final String RESTORE_CHAR_HENNAS = "SELECT slot,symbol_id FROM character_hennas WHERE char_obj_id=? AND class_index=?"; - private static final String ADD_CHAR_HENNA = "INSERT INTO character_hennas (char_obj_id,symbol_id,slot,class_index) VALUES (?,?,?,?)"; - private static final String DELETE_CHAR_HENNA = "DELETE FROM character_hennas WHERE char_obj_id=? AND slot=? AND class_index=?"; - private static final String DELETE_CHAR_HENNAS = "DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=?"; - private static final String DELETE_CHAR_SHORTCUTS = "DELETE FROM character_shortcuts WHERE char_obj_id=? AND class_index=?"; - - public static final int REQUEST_TIMEOUT = 15; - - public static final int STORE_PRIVATE_NONE = 0; - public static final int STORE_PRIVATE_SELL = 1; - public static final int STORE_PRIVATE_BUY = 3; - public static final int STORE_PRIVATE_MANUFACTURE = 5; - - /** The table containing all minimum level needed for each Expertise (None, D, C, B, A, S)*/ - private static final int[] EXPERTISE_LEVELS = - { - SkillTreeTable.getInstance().getExpertiseLevel(0), //NONE - SkillTreeTable.getInstance().getExpertiseLevel(1), //D - SkillTreeTable.getInstance().getExpertiseLevel(2), //C - SkillTreeTable.getInstance().getExpertiseLevel(3), //B - SkillTreeTable.getInstance().getExpertiseLevel(4), //A - SkillTreeTable.getInstance().getExpertiseLevel(5), //S - }; - - private static final int[] COMMON_CRAFT_LEVELS = - { - 5,20,28,36,43,49,55,62 - }; - - //private static Logger _log = Logger.getLogger(L2PcInstance.class.getName()); - - public class AIAccessor extends L2Character.AIAccessor - { - protected AIAccessor() {} - public L2PcInstance getPlayer() { return L2PcInstance.this; } - public void doPickupItem(L2Object object) { - L2PcInstance.this.doPickupItem(object); - } - public void doInteract(L2Character target) { - L2PcInstance.this.doInteract(target); - } - - public void doAttack(L2Character target) - { - super.doAttack(target); - - for (L2CubicInstance cubic : getCubics().values()) - if (cubic.getId() != L2CubicInstance.LIFE_CUBIC) - cubic.doAction(target); - } - } - - private Connection _connection; - - //private L2Object _newTarget = null; - - /** The Identifier of the L2PcInstance */ - private int _charId = 0x00030b7a; - - /** The Experience of the L2PcInstance before the last Death Penalty */ - private int _expBeforeDeath = 0; - - /** The Karma of the L2PcInstance (if higher than 0, the name of the L2PcInstance appears in red) */ - private int _karma; - - /** The number of player killed during a PvP (the player killed was PvP Flagged) */ - private int _pvpKills; - - /** The hexadecimal Color of players name (white is 0xFFFFFF) */ - private int _nameColor; - - /** The PK counter of the L2PcInstance (= Number of non PvP Flagged player killed) */ - private int _pkKills; - - /** The PvP Flag state of the L2PcInstance (0=White, 1=Purple) */ - private int _pvpFlag; - - private boolean _inPvpZone; - - /** The number of recommandation obtained by the L2PcInstance */ - private int _recomHave; // how much I was recommended by others - - /** The number of recommandation that the L2PcInstance can give */ - private int _recomLeft; // how many recomendations I can give to others - - /** List with the recomendations that I've give */ - private List _recomChars = new FastList(); - - /** The random number of the L2PcInstance */ - //private static final Random _rnd = new Random(); - - private final int _baseLoad; - private int _curWeightPenalty = 0; - - private int _deleteTimer; - private PcInventory _inventory = new PcInventory(this); - private PcWarehouse _warehouse = new PcWarehouse(this); - private PcFreight _freight = new PcFreight(this); - - /** True if the L2PcInstance is sitting */ - private boolean _waitTypeSitting; - - /** True if the L2PcInstance is using the relax skill */ - private boolean _relax; - - /** True if the L2PcInstance is in a boat */ - private boolean _inBoat; - - /** Last NPC Id talked on a quest */ - private int _questNpcObject = 0; - - /** The face type Identifier of the L2PcInstance */ - private int _face; - - /** The hair style Identifier of the L2PcInstance */ - private int _hairStyle; - - /** The hair color Identifier of the L2PcInstance */ - private int _hairColor; - - /** True if the L2PcInstance is newbie */ - private boolean _newbie; - - /** The table containing all Quests began by the L2PcInstance */ - private Map _quests = new FastMap(); - - /** The list containing all shortCuts of this L2PcInstance */ - private ShortCuts _shortCuts = new ShortCuts(this); - - /** The list containing all macroses of this L2PcInstance */ - private MacroList _macroses = new MacroList(this); - - /** The Alliance Identifier of the L2PcInstance */ - //private int _allyId; - - private TradeList _activeTradeList; - private ItemContainer _activeWarehouse; - private L2ManufactureList _createList; - private TradeList _sellList; - private TradeList _buyList; - - private List _SnoopListener = new FastList(); - private List _SnoopedPlayer = new FastList(); - - /** The Private Store type of the L2PcInstance (STORE_PRIVATE_NONE=0, STORE_PRIVATE_SELL=1, sellmanage=2, STORE_PRIVATE_BUY=3, buymanage=4, STORE_PRIVATE_MANUFACTURE=5) */ - private int _privatestore; - private ClassId _skillLearningClassId; - - // hennas - private final L2HennaInstance[] _henna = new L2HennaInstance[3]; - private int _hennaSTR; - private int _hennaINT; - private int _hennaDEX; - private int _hennaMEN; - private int _hennaWIT; - private int _hennaCON; - - /** The L2Summon of the L2PcInstance */ - private L2Summon _summon = null; - - // client radar - //TODO: This needs to be better intergrated and saved/loaded - private L2Radar _radar; - - // these values are only stored temporarily - private boolean _partyMatchingAutomaticRegistration; - private boolean _partyMatchingShowLevel; - private boolean _partyMatchingShowClass; - private String _partyMatchingMemo; - - private L2Party _party; - // clan related attributes - - /** The Clan Identifier of the L2PcInstance */ - private int _clanId; - - /** The Clan object of the L2PcInstance */ - private L2Clan _clan; - - /** The Clan Leader Flag of the L2PcInstance (True : the L2PcInstance is the leader of the clan) */ - private boolean _clanLeader; - - private long _deleteClanTime; - - private long _onlineTime; - private long _onlineBeginTime; - - //GM Stuff - private boolean _isInvul; - private boolean _isGm; - private int _accessLevel; - - private boolean _chatBanned = false; // Chat Banned - private ScheduledFuture _chatUnbanTask = null; - private boolean _messageRefusal = false; // message refusal mode - private boolean _dietMode = false; // ignore weight penalty - private boolean _tradeRefusal = false; // Trade refusal - private boolean _exchangeRefusal = false; // Exchange refusal - - public boolean _exploring = false; - - // this is needed to find the inviting player for Party response - // there can only be one active party request at once - private L2PcInstance _activeRequester; - private long _requestExpireTime = 0; - private L2ItemInstance _arrowItem; - - // Used for protection after teleport - private long _protectEndTime = 0; - - /** The fists L2Weapon of the L2PcInstance (used when no weapon is equiped) */ - private L2Weapon _fistsWeaponItem; - - private long _uptime; - private String _accountName; - - private final Map _chars = new FastMap(); - - public byte _updateKnownCounter = 0; - - /** The table containing all L2RecipeList of the L2PcInstance */ - private Map _dwarvenRecipeBook = new FastMap(); - private Map _commonRecipeBook = new FastMap(); - - private int _mountType; - - /** The current higher Expertise of the L2PcInstance (None=0, D=1, C=2, B=3, A=4, S=5)*/ - private int _expertiseIndex; // index in EXPERTISE_LEVELS - private int _expertisePenalty = 0; - - private L2ItemInstance _activeEnchantItem = null; - - private boolean _isOnline = false; - private boolean _isIn7sDungeon = false; - - protected boolean _inventoryDisable = false; - - protected Map _cubics = new FastMap(); - - /** The L2FolkInstance corresponding to the last Folk wich one the player talked. */ - private L2FolkInstance _lastFolkNpc = null; - - private boolean _isSilentMoving = false; - - protected Set _activeSoulShots = new FastSet(); - private boolean _isPathNodeMode; - private boolean _isPathNodesVisible; - private Map> _pathNodeMap; - private WayPointNode _selectedNode; - private int _clanPrivileges = 0; - private boolean _linkToggle = true; - - /** 1 if the player is invisible */ - private int _invisible = 0; - - /** Location before entering Observer Mode */ - private int _obsX; - private int _obsY; - private int _obsZ; - private boolean _observerMode = false; - - /** Event parameters */ - public int eventX; - public int eventY; - public int eventZ; - public int eventkarma; - public int eventpvpkills; - public int eventpkkills; - public String eventTitle; - public LinkedList kills = new LinkedList(); - public boolean eventSitForced = false; - public boolean atEvent = false; - - public int _telemode = 0; - - /** new loto ticket **/ - public int _loto[] = new int[5]; - //public static int _loto_nums[] = {0,1,2,3,4,5,6,7,8,9,}; - /** new race ticket **/ - public int _race[] = new int[2]; - - private final BlockList _blockList = new BlockList(); - private boolean _isConnected = true; - - private boolean _hero = false; - private int _team = 0; - private int _wantsPeace = 0; - - private boolean _noble = false; - private boolean _inOlympiadMode = false; - private int _olympiadGameId = -1; - private int _olympiadSide = -1; - - /** The list of sub-classes this character has. */ - private Map _subClasses; - protected int _baseClass; - protected int _activeClass; - protected int _classIndex = 0; - - private long _lastAccess; - private int _boatId; - - private L2Fishing _fish; - private boolean _fishing = false; - private int _fishx = 0; - private int _fishy = 0; - private int _fishz = 0; - - private ScheduledFuture _taskRentPet; - private ScheduledFuture _taskWater; - private L2BoatInstance _boat; - private Point3D _inBoatPosition; - - /** Stored from last ValidatePosition **/ - public Point3D _lastClientPosition = new Point3D(0, 0, 0); - public Point3D _lastServerPosition = new Point3D(0, 0, 0); - - /** Bypass validations */ - private List _validBypass = new FastList(); - private List _validBypass2 = new FastList(); - - private boolean _inCrystallize; - private boolean _inCraftMode; - private Forum _forumMail; - private Forum _forumMemo; - - /** Current skill in use */ - private SkillDat _currentSkill; - - /** Skills queued because a skill is already in progress */ - private SkillDat _queuedSkill; - - /** Store object used to summon the strider you are mounting **/ - private int _mountObjectID = 0; - - private boolean _inJail = false; - private long _jailTimer = 0; - - /** Flag to disable equipment/skills while wearing formal wear **/ - private boolean _IsWearingFormalWear = false; - - - /** Skill casting information (used to queue when several skills are cast in a short time) **/ - public class SkillDat - { - private L2Skill _skill; - private boolean _ctrlPressed; - private boolean _shiftPressed; - - protected SkillDat(L2Skill skill, boolean ctrlPressed, boolean shiftPressed) - { - _skill = skill; - _ctrlPressed = ctrlPressed; - _shiftPressed = shiftPressed; - } - - public boolean isCtrlPressed() - { - return _ctrlPressed; - } - - public boolean isShiftPressed() - { - return _shiftPressed; - } - - public L2Skill getSkill() - { - return _skill; - } - - public int getSkillId() - { - return (getSkill() != null) ? getSkill().getId() : -1; - } - } - - /** - * Create a new L2PcInstance and add it in the characters table of the database.

    - * - * Actions :

    - *
  • Create a new L2PcInstance with an account name
  • - *
  • Set the name, the Hair Style, the Hair Color and the Face type of the L2PcInstance
  • - *
  • Add the player in the characters table of the database


  • - * - * @param objectId Identifier of the object to initialized - * @param template The L2PcTemplate to apply to the L2PcInstance - * @param accountName The name of the L2PcInstance - * @param name The name of the L2PcInstance - * @param hairStyle The hair style Identifier of the L2PcInstance - * @param hairColor The hair color Identifier of the L2PcInstance - * @param face The face type Identifier of the L2PcInstance - * - * @return The L2PcInstance added to the database or null - * - */ - public static L2PcInstance create(int objectId, L2PcTemplate template, String accountName, - String name, int hairStyle, int hairColor, int face) - { - // Create a new L2PcInstance with an account name - L2PcInstance player = new L2PcInstance(objectId, template, accountName); - - // Set the name of the L2PcInstance - player.setName(name); - - // Set the Hair Style of the L2PcInstance - player.setHairStyle(hairStyle); - - // Set the Hair Color of the L2PcInstance - player.setHairColor(hairColor); - - // Set the Face type of the L2PcInstance - player.setFace(face); - - // Set the base class ID to that of the actual class ID. - player.setBaseClass(player.getClassId()); - - if (Config.ALT_GAME_NEW_CHAR_ALWAYS_IS_NEWBIE) - player.setNewbie(true); - - // Add the player in the characters table of the database - boolean ok = player.createDb(); - - if (!ok) - return null; - - return player; - } - - public static L2PcInstance createDummyPlayer(int objectId, String name) - { - // Create a new L2PcInstance with an account name - L2PcInstance player = new L2PcInstance(objectId); - player.setName(name); - - return player; - } - - public String getAccountName() - { - if (_connection == null) - return ""; - - return _connection.getClient().getLoginName(); - } - - public Map getAccountChars() - { - return _chars; - } - - /** - * Retrieve a L2PcInstance from the characters table of the database and add it in _allObjects of the L2world (call restore method).

    - * - * Actions :

    - *
  • Retrieve the L2PcInstance from the characters table of the database
  • - *
  • Add the L2PcInstance object in _allObjects
  • - *
  • Set the x,y,z position of the L2PcInstance and make it invisible
  • - *
  • Update the overloaded status of the L2PcInstance


  • - * - * @param objectId Identifier of the object to initialized - * - * @return The L2PcInstance loaded from the database - * - */ - public static L2PcInstance load(int objectId) - { - return restore(objectId); - } - - /** - * Constructor of L2PcInstance (use L2Character constructor).

    - * - * Actions :

    - *
  • Call the L2Character constructor to create an empty _skills slot and copy basic Calculator set to this L2PcInstance
  • - *
  • Set the name of the L2PcInstance


  • - * - * Caution : This method SET the level of the L2PcInstance to 1

    - * - * @param objectId Identifier of the object to initialized - * @param template The L2PcTemplate to apply to the L2PcInstance - * @param accountName The name of the account including this L2PcInstance - * - */ - private L2PcInstance(int objectId, L2PcTemplate template, String accountName) - { - super(objectId, template); - super.setKnownList(new PcKnownList(new L2PcInstance[] {this})); - super.setStat(new PcStat(new L2PcInstance[] {this})); - super.setStatus(new PcStatus(new L2PcInstance[] {this})); - - _accountName = accountName; - _nameColor = 0xFFFFFF; - _baseLoad = template.baseLoad; - - // Create an AI - _ai = new L2PlayerAI(new L2PcInstance.AIAccessor()); - - // Create a L2Radar object - _radar = new L2Radar(this); - - // Retrieve from the database all skills of this L2PcInstance and add them to _skills - // Retrieve from the database all items of this L2PcInstance and add them to _inventory - getInventory().restore(); - getWarehouse().restore(); - getFreight().restore(); - } - - private L2PcInstance(int objectId) - { - super(objectId, null); - super.setKnownList(new PcKnownList(new L2PcInstance[] {this})); - super.setStat(new PcStat(new L2PcInstance[] {this})); - super.setStatus(new PcStatus(new L2PcInstance[] {this})); - - _baseLoad = 0; - } - - public final PcKnownList getKnownList() { return (PcKnownList)super.getKnownList(); } - public final PcStat getStat() { return (PcStat)super.getStat(); } - public final PcStatus getStatus() { return (PcStatus)super.getStatus(); } - - /** - * Return the base L2PcTemplate link to the L2PcInstance.

    - */ - public final L2PcTemplate getBaseTemplate() - { - return CharTemplateTable.getInstance().getTemplate(_baseClass, getSex() == 1); - } - - /** Return the L2PcTemplate link to the L2PcInstance. */ - public final L2PcTemplate getTemplate() { return (L2PcTemplate)super.getTemplate(); } - - public void setTemplate(ClassId newclass, boolean female) { super.setTemplate(CharTemplateTable.getInstance().getTemplate(newclass, female)); } - - public void changeSex() { super.setTemplate(CharTemplateTable.getInstance().getTemplate(getClassId(), (getSex() == 1))); } - - /** - * Return the AI of the L2PcInstance (create it if necessary).

    - */ - public L2CharacterAI getAI() - { - if (_ai == null) - { - synchronized(this) - { - if (_ai == null) - _ai = new L2PlayerAI(new L2PcInstance.AIAccessor()); - } - } - - return _ai; - } - - - /** - * Calculate a destination to explore the area and set the AI Intension to AI_INTENTION_MOVE_TO.

    - */ - public void explore() - { - if (!_exploring) return; - - if(getMountType() == 2) - return; - - // Calculate the destination point (random) - - int x = getX()+Rnd.nextInt(6000)-3000; - int y = getY()+Rnd.nextInt(6000)-3000; - - if (x > Universe.MAX_X) x = Universe.MAX_X; - if (x < Universe.MIN_X) x = Universe.MIN_X; - if (y > Universe.MAX_Y) y = Universe.MAX_Y; - if (y < Universe.MIN_Y) y = Universe.MIN_Y; - - int z = getZ(); - - L2CharPosition pos = new L2CharPosition(x,y,z,0); - - // Set the AI Intention to AI_INTENTION_MOVE_TO - getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO,pos); - - } - - /** Return the Level of the L2PcInstance. */ - public final int getLevel() { return getStat().getLevel(); } - - /** - * Return the Sex of the L2PcInstance (Male=0, Female=1).

    - */ - public int getSex() { return getTemplate().isMale ? 0 : 1; } - - /** - * Return the Face type Identifier of the L2PcInstance.

    - */ - public int getFace() - { - return _face; - } - - /** - * Set the Face type of the L2PcInstance.

    - * - * @param face The Identifier of the Face type

    - * - */ - public void setFace(int face) - { - _face = face; - } - - /** - * Return the Hair Color Identifier of the L2PcInstance.

    - */ - public int getHairColor() - { - return _hairColor; - } - - /** - * Set the Hair Color of the L2PcInstance.

    - * - * @param hairColor The Identifier of the Hair Color

    - * - */ - public void setHairColor(int hairColor) - { - _hairColor = hairColor; - } - - /** - * Return the Hair Style Identifier of the L2PcInstance.

    - */ - public int getHairStyle() - { - return _hairStyle; - } - - /** - * Set the Hair Style of the L2PcInstance.

    - * - * @param hairStyle The Identifier of the Hair Style

    - * - */ - public void setHairStyle(int hairStyle) - { - _hairStyle = hairStyle; - } - - /** - * Return the _newbie state of the L2PcInstance.

    - */ - public boolean isNewbie() - { - return _newbie; - } - - /** - * Set the _newbie state of the L2PcInstance.

    - * - * @param isNewbie The Identifier of the _newbie state

    - * - */ - public void setNewbie(boolean isNewbie) - { - _newbie = isNewbie; - } - - - public void setBaseClass(int baseClass) - { - _baseClass = baseClass; - } - - public void setBaseClass(ClassId classId) - { - _baseClass = classId.ordinal(); - } - - public boolean isInStoreMode() { return (getPrivateStoreType() > 0); } -// public boolean isInCraftMode() { return (getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE); } - - public boolean isInCraftMode() - { - return _inCraftMode; - } - - public void isInCraftMode(boolean b) - { - _inCraftMode = b; - } - - /** - * Manage Logout Task.

    - */ - public void logout() - { - // Delete all Path Nodes - clearPathNodes(); - - // Close the connection with the client - if (_connection != null) - _connection.close(); - } - - /** - * Return a table containing all Common L2RecipeList of the L2PcInstance.

    - */ - public L2RecipeList[] getCommonRecipeBook() - { - return _commonRecipeBook.values().toArray(new L2RecipeList[_commonRecipeBook.values().size()]); - } - - /** - * Return a table containing all Dwarf L2RecipeList of the L2PcInstance.

    - */ - public L2RecipeList[] getDwarvenRecipeBook() - { - return _dwarvenRecipeBook.values().toArray(new L2RecipeList[_dwarvenRecipeBook.values().size()]); - } - - /** - * Add a new L2RecipList to the table _commonrecipebook containing all L2RecipeList of the L2PcInstance

    - * - * @param recipe The L2RecipeList to add to the _recipebook - * - */ - public void registerCommonRecipeList(L2RecipeList recipe) - { - _commonRecipeBook.put(recipe.getId(), recipe); - } - - /** - * Add a new L2RecipList to the table _recipebook containing all L2RecipeList of the L2PcInstance

    - * - * @param recipe The L2RecipeList to add to the _recipebook - * - */ - public void registerDwarvenRecipeList(L2RecipeList recipe) - { - _dwarvenRecipeBook.put(recipe.getId(), recipe); - } - - /** - * @param RecipeID The Identifier of the L2RecipeList to check in the player's recipe books - * - * @return - * TRUE if player has the recipe on Common or Dwarven Recipe book else returns FALSE - */ - public boolean hasRecipeList(int recipeId) - { - if (_dwarvenRecipeBook.containsKey(recipeId)) - return true; - else if(_commonRecipeBook.containsKey(recipeId)) - return true; - else - return false; - } - - /** - * Tries to remove a L2RecipList from the table _DwarvenRecipeBook or from table _CommonRecipeBook, those table contain all L2RecipeList of the L2PcInstance

    - * - * @param RecipeID The Identifier of the L2RecipeList to remove from the _recipebook - * - */ - public void unregisterRecipeList(int recipeId) - { - if (_dwarvenRecipeBook.containsKey(recipeId)) - _dwarvenRecipeBook.remove(recipeId); - else if(_commonRecipeBook.containsKey(recipeId)) - _commonRecipeBook.remove(recipeId); - else - _log.warning("Attempted to remove unknown RecipeList: "+recipeId); - } - - /** - * Returns the Id for the last talked quest NPC.

    - */ - public int getLastQuestNpcObject() - { - return _questNpcObject; - } - - public void setLastQuestNpcObject(int npcId) - { - _questNpcObject = npcId; - } - - /** - * Add Quest drops to the table containing all possible drops of a L2NpcInstance.

    - * - * @param npc The L2NpcInstance killed by the L2PcInstance - * @param drops The table containing all possible drops of the L2NpcInstance - * - */ - public void fillQuestDrops(L2NpcInstance npc, List drops) - { - for (QuestState qs : _quests.values()) - qs.fillQuestDrops(npc, drops); - } - - /** - * Return the QuestState object corresponding to the quest name.

    - * - * @param quest The name of the quest - * - */ - public QuestState getQuestState(String quest) - { - return _quests.get(quest); - } - - /** - * Add a QuestState to the table _quest containing all quests began by the L2PcInstance.

    - * - * @param qs The QuestState to add to _quest - * - */ - public void setQuestState(QuestState qs) - { - _quests.put(qs.getQuest().getName(), qs); - } - - - /** - * Remove a QuestState from the table _quest containing all quests began by the L2PcInstance.

    - * - * @param quest The name of the quest - * - */ - public void delQuestState(String quest) - { - _quests.remove(quest); - } - - private QuestState[] addToQuestStateArray(QuestState[] questStateArray, QuestState state) { - int len = questStateArray.length; - QuestState[] tmp = new QuestState[len+1]; - for (int i=0; i < len; i++) - tmp[i] = questStateArray[i]; - tmp[len] = state; - return tmp; - } - - /** - * Return a table containing all Quest in progress from the table _quests.

    - */ - public Quest[] getAllActiveQuests() - { - FastList quests = new FastList(); - - for (QuestState qs : _quests.values()) - { - if (qs.getQuest().getQuestIntId()>=1999) - continue; - - if (qs.isCompleted() && !Config.DEVELOPER) - continue; - - if (!qs.isStarted() && !Config.DEVELOPER) - continue; - - quests.add(qs.getQuest()); - } - - return quests.toArray(new Quest[quests.size()]); - } - - /** - * Return a table containing all QuestState to modify after a L2Attackable killing.

    - * - * @param npcId The Identifier of the L2Attackable attacked - * - */ - public QuestState[] getQuestsForAttacks(L2NpcInstance npc) - { - // Create a QuestState table that will contain all QuestState to modify - QuestState[] states = null; - - // Go through the QuestState of the L2PcInstance quests - for (QuestState qs : _quests.values()) - { - // Check if the Identifier of the L2Attackable attck is needed for the current quest - if (qs.waitsForAttack(npc)) - { - // Copy the current L2PcInstance QuestState in the QuestState table - if (states == null) - states = new QuestState[]{qs}; - else - states = addToQuestStateArray(states, qs); - } - } - - // Return a table containing all QuestState to modify - return states; - } - - /** - * Return a table containing all QuestState to modify after a L2Attackable killing.

    - * - * @param npcId The Identifier of the L2Attackable killed - * - */ - public QuestState[] getQuestsForKills(L2NpcInstance npc) - { - // Create a QuestState table that will contain all QuestState to modify - QuestState[] states = null; - - // Go through the QuestState of the L2PcInstance quests - for (QuestState qs : _quests.values()) - { - // Check if the Identifier of the L2Attackable killed is needed for the current quest - if (qs.waitsForKill(npc)) - { - // Copy the current L2PcInstance QuestState in the QuestState table - if (states == null) - states = new QuestState[]{qs}; - else - states = addToQuestStateArray(states, qs); - } - } - - // Return a table containing all QuestState to modify - return states; - } - - /** - * Return a table containing all QuestState from the table _quests in which the L2PcInstance must talk to the NPC.

    - * - * @param npcId The Identifier of the NPC - * - */ - public QuestState[] getQuestsForTalk(int npcId) - { - // Create a QuestState table that will contain all QuestState to modify - QuestState[] states = null; - - // Go through the QuestState of the L2PcInstance quests - for (QuestState qs : _quests.values()) - { - // Check if the Identifier of the L2Attackable talk is needed for the current quest - if (qs.waitsForTalk(npcId)) - { - // Copy the current L2PcInstance QuestState in the QuestState table - if (states == null) - states = new QuestState[]{qs}; - else - states = addToQuestStateArray(states, qs); - } - } - - // Return a table containing all QuestState to modify - return states; - } - - public QuestState processQuestEvent(String quest, String event) - { - QuestState retval = null; - if (event == null) - event = ""; - if (!_quests.containsKey(quest)) - return retval; - QuestState qs = getQuestState(quest); - if (qs == null && event.length() == 0) - return retval; - if (qs == null) { - Quest q = QuestManager.getInstance().getQuest(quest); - if (q == null) - return retval; - qs = q.newQuestState(this); - } - if (qs != null) { - if (getLastQuestNpcObject() > 0) - { - L2Object object = L2World.getInstance().findObject(getLastQuestNpcObject()); - if (object instanceof L2NpcInstance && isInsideRadius(object, L2NpcInstance.INTERACTION_DISTANCE, false, false)) - { - L2NpcInstance npc = (L2NpcInstance)object; - QuestState[] states = getQuestsForTalk(npc.getNpcId()); - - if (states != null) - { - for (QuestState state : states) - { - if ((state.getQuest().getQuestIntId() == qs.getQuest().getQuestIntId()) && !qs.isCompleted()) - { - if (qs.getQuest().notifyEvent(event, qs)) - showQuestWindow(quest, qs.getStateId()); - - retval = qs; - } - } - } - } - } - } - - return retval; - } - - private void showQuestWindow(String questId, String stateId) - { - String path = "data/jscript/quests/"+questId+"/"+stateId+".htm"; - String content = HtmCache.getInstance().getHtm(path); //TODO path for quests html - - if (content != null) - { - if (Config.DEBUG) - _log.fine("Showing quest window for quest "+questId+" state "+stateId+" html path: " + path); - - NpcHtmlMessage npcReply = new NpcHtmlMessage(5); - npcReply.setHtml(content); - sendPacket(npcReply); - } - - sendPacket( new ActionFailed() ); - } - - /** - * Return a table containing all L2ShortCut of the L2PcInstance.

    - */ - public L2ShortCut[] getAllShortCuts() - { - return _shortCuts.getAllShortCuts(); - } - - /** - * Return the L2ShortCut of the L2PcInstance corresponding to the position (page-slot).

    - * - * @param slot The slot in wich the shortCuts is equiped - * @param page The page of shortCuts containing the slot - * - */ - public L2ShortCut getShortCut(int slot, int page) - { - return _shortCuts.getShortCut(slot, page); - } - - /** - * Add a L2shortCut to the L2PcInstance _shortCuts

    - */ - public void registerShortCut(L2ShortCut shortcut) - { - _shortCuts.registerShortCut(shortcut); - } - - /** - * Delete the L2ShortCut corresponding to the position (page-slot) from the L2PcInstance _shortCuts.

    - */ - public void deleteShortCut(int slot, int page) - { - _shortCuts.deleteShortCut(slot, page); - } - - /** - * Add a L2Macro to the L2PcInstance _macroses

    - */ - public void registerMacro(L2Macro macro) - { - _macroses.registerMacro(macro); - } - - /** - * Delete the L2Macro corresponding to the Identifier from the L2PcInstance _macroses.

    - */ - public void deleteMacro(int id) - { - _macroses.deleteMacro(id); - } - - /** - * Return all L2Macro of the L2PcInstance.

    - */ - public MacroList getMacroses() - { - return _macroses; - } - - /** - * Set the PvP Flag of the L2PcInstance.

    - */ - public void setPvpFlag(int pvpFlag) - { - _pvpFlag = pvpFlag; - } - - public boolean getInPvpZone() - { - return _inPvpZone; - } - - /** - * Update the _inPvpZone flag and send a message to player.

    - * @param inPvpZone : true if player is in a pvp zone - * @see net.sf.l2j.gameserver.model.actor.instance.L2PcInstance.setInPvpZone(boolean, boolean) - */ - public void setInPvpZone(boolean inPvpZone) - { - setInPvpZone(inPvpZone, true); - } - /** - * Update the _inPvpZone flag.

    - * @param inPvpZone : true if player is in a pvp zone - * @param warnPlayer : true if a message should be send to player - */ - public void setInPvpZone(boolean inPvpZone, boolean warnPlayer) - { - if (_inPvpZone != inPvpZone) - { - _inPvpZone = inPvpZone; - - if (warnPlayer) - if (_inPvpZone) - sendPacket(new SystemMessage(283)); - else - sendPacket(new SystemMessage(284)); - } - } - - private void revalidateInPvpZone () - { - setInPvpZone(ZoneManager.getInstance().checkIfInZonePvP(this)); - } - - public void revalidateZone() - { - revalidateInPvpZone(); - } - - /** - * Return True if the L2PcInstance can Craft Dwarven Recipes.

    - */ - public boolean hasDwarvenCraft() - { - return getSkillLevel(L2Skill.SKILL_CREATE_DWARVEN) >= 1; - } - - public int getDwarvenCraft() - { - return getSkillLevel(L2Skill.SKILL_CREATE_DWARVEN); - } - - /** - * Return True if the L2PcInstance can Craft Dwarven Recipes.

    - */ - public boolean hasCommonCraft() - { - return getSkillLevel(L2Skill.SKILL_CREATE_COMMON) >= 1; - } - - public int getCommonCraft() - { - return getSkillLevel(L2Skill.SKILL_CREATE_COMMON); - } - - /** - * Return the PK counter of the L2PcInstance.

    - */ - public int getPkKills() - { - return _pkKills; - } - - /** - * Set the PK counter of the L2PcInstance.

    - */ - public void setPkKills(int pkKills) - { - _pkKills = pkKills; - } - - /** - * Return the _deleteTimer of the L2PcInstance.

    - */ - public int getDeleteTimer() - { - return _deleteTimer; - } - - /** - * Set the _deleteTimer of the L2PcInstance.

    - */ - public void setDeleteTimer(int deleteTimer) - { - _deleteTimer = deleteTimer; - } - - /** - * Return the current weight of the L2PcInstance.

    - */ - public int getCurrentLoad() - { - return _inventory.getTotalWeight(); - } - /** - * Return the number of recommandation obtained by the L2PcInstance.

    - */ - public int getRecomHave() - { - return _recomHave; - } - - /** - * Increment the number of recommandation obtained by the L2PcInstance (Max : 255).

    - */ - protected void incRecomHave() - { - if (_recomHave < 255) - _recomHave++; - } - - /** - * Set the number of recommandation obtained by the L2PcInstance (Max : 255).

    - */ - public void setRecomHave(int value) - { - if (value > 255) - _recomHave = 255; - else if (value < 0) - _recomHave = 0; - else - _recomHave = value; - } - - - - /** - * Return the number of recommandation that the L2PcInstance can give.

    - */ - public int getRecomLeft() - { - return _recomLeft; - } - - /** - * Increment the number of recommandation that the L2PcInstance can give.

    - */ - protected void decRecomLeft() - { - if (_recomLeft > 0) - _recomLeft--; - } - - public void giveRecom(L2PcInstance target) - { - target.incRecomHave(); - decRecomLeft(); - _recomChars.add(target.getName().hashCode()); - } - - public boolean canRecom(L2PcInstance target) - { - return !_recomChars.contains(target.getName().hashCode()); - } - - /** - * Return the Karma of the L2PcInstance.

    - */ - public int getKarma() - { - return _karma; - } - - /** - * Set the Karma of the L2PcInstance and send a Server->Client packet StatusUpdate (broadcast).

    - */ - public void setKarma(int karma) - { - if (karma < 0) karma = 0; - if (_karma == 0 && karma > 0) - { - for (L2Object object : getKnownList().getKnownObjects()) - { - if (object == null || !(object instanceof L2GuardInstance)) continue; - - if (((L2GuardInstance)object).getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE) - ((L2GuardInstance)object).getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE,null); - } - } - else if (_karma > 0 && karma == 0) - { - // Send a Server->Client StatusUpdate packet with Karma and PvP Flag to the L2PcInstance and all L2PcInstance to inform (broadcast) - setKarmaFlag(0); - } - - _karma = karma; - updateKarma(); - } - - /** - * Return the max weight that the L2PcInstance can load.

    - */ - public int getMaxLoad() - { - return (int)calcStat(Stats.MAX_LOAD, _baseLoad, this, null); - } - - public int getexpertisePenalty() - { - return _expertisePenalty; - } - - public int getWeightPenalty() - { - if (_dietMode) - return 0; - - return _curWeightPenalty; - } - - /** - * Update the overloaded status of the L2PcInstance.

    - */ - public void refreshOverloaded() - { - if (getMaxLoad() > 0 && !_dietMode) - { - setIsOverloaded(getCurrentLoad() > getMaxLoad()); - int weightproc = getCurrentLoad() * 1000 / getMaxLoad(); - int newWeightPenalty; - if ( weightproc < 500) newWeightPenalty = 0; - else if ( weightproc < 666) newWeightPenalty = 1; - else if ( weightproc < 800) newWeightPenalty = 2; - else if ( weightproc < 1000) newWeightPenalty = 3; - else newWeightPenalty = 4; - - if (_curWeightPenalty != newWeightPenalty) - { - _curWeightPenalty = newWeightPenalty; - if (newWeightPenalty > 0) - super.addSkill(SkillTable.getInstance().getInfo(4270,newWeightPenalty)); - else super.removeSkill(getKnownSkill(4270)); - - super.updateEffectIcons(); - } - } - } - - public void refreshExpertisePenalty() - { - int newPenalty = 0; - - for (L2ItemInstance item : getInventory().getItems()) - { - if (item.isEquipped()) - { - int crystaltype = item.getItem().getCrystalType(); - - if (crystaltype > newPenalty) - newPenalty = crystaltype; - } - } - - newPenalty = newPenalty - getExpertiseIndex(); - - if (newPenalty <= 0) - newPenalty = 0; - - if (getexpertisePenalty() != newPenalty) - { - _expertisePenalty = newPenalty; - - if (newPenalty > 0) - super.addSkill(SkillTable.getInstance().getInfo(4267, newPenalty)); - else - super.removeSkill(getKnownSkill(4267)); - - super.updateEffectIcons(); - } - } - - public void CheckIfWeaponIsAllowed() - { - // Override for Gamemasters - if (isGM()) - return; - - // Iterate through all effects currently on the character. - for (L2Effect currenteffect : this.getAllEffects()) - { - L2Skill effectSkill = currenteffect.getSkill(); - - // Ignore all buff skills that are party related (ie. songs, dances) while still remaining weapon dependant on cast though. - if (!(effectSkill.getTargetType() == SkillTargetType.TARGET_PARTY && effectSkill.getSkillType() == SkillType.BUFF)) - { - // Check to rest to assure current effect meets weapon requirements. - if (!effectSkill.getWeaponDependancy(this)) - { - sendMessage(effectSkill.getName() + " cannot be used with this weapon."); - - if (Config.DEBUG) - _log.info(" | Skill "+effectSkill.getName()+" has been disabled for ("+this.getName()+"); Reason: Incompatible Weapon Type."); - - currenteffect.exit(); - } - } - - continue; - } - } - - /** - * Return the the PvP Kills of the L2PcInstance (Number of player killed during a PvP).

    - */ - public int getPvpKills() - { - return _pvpKills; - } - - /** - * Set the the PvP Kills of the L2PcInstance (Number of player killed during a PvP).

    - */ - public void setPvpKills(int pvpKills) - { - _pvpKills = pvpKills; - } - - /** - * Return the ClassId object of the L2PcInstance contained in L2PcTemplate.

    - */ - public ClassId getClassId() - { - return getTemplate().classId; - } - - /** - * Set the template of the L2PcInstance.

    - * - * @param Id The Identifier of the L2PcTemplate to set to the L2PcInstance - * - */ - public void setClassId(int Id) - { - _activeClass = Id; - L2PcTemplate t = CharTemplateTable.getInstance().getTemplate(Id, getSex()==1); - - if (t == null) - { - _log.severe("Missing template for classId: "+Id); - throw new Error(); - } - - // Set the template of the L2PcInstance - setTemplate(t); - } - - /** Return the Experience of the L2PcInstance. */ - public int getExp() { return getStat().getExp(); } - - - public void setActiveEnchantItem(L2ItemInstance scroll) - { - _activeEnchantItem = scroll; - } - - public L2ItemInstance getActiveEnchantItem() - { - return _activeEnchantItem; - } - - /** - * Set the fists weapon of the L2PcInstance (used when no weapon is equiped).

    - * - * @param weaponItem The fists L2Weapon to set to the L2PcInstance - * - */ - public void setFistsWeaponItem(L2Weapon weaponItem) - { - _fistsWeaponItem = weaponItem; - } - - /** - * Return the fists weapon of the L2PcInstance (used when no weapon is equiped).

    - */ - public L2Weapon getFistsWeaponItem() - { - return _fistsWeaponItem; - } - - /** - * Return the fists weapon of the L2PcInstance Class (used when no weapon is equiped).

    - */ - public L2Weapon findFistsWeaponItem(int classId) - { - L2Weapon weaponItem = null; - if ((classId >= 0x00) && (classId <= 0x09)) - { - //human fighter fists - L2Item temp = ItemTable.getInstance().getTemplate(246); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x0a) && (classId <= 0x11)) - { - //human mage fists - L2Item temp = ItemTable.getInstance().getTemplate(251); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x12) && (classId <= 0x18)) - { - //elven fighter fists - L2Item temp = ItemTable.getInstance().getTemplate(244); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x19) && (classId <= 0x1e)) - { - //elven mage fists - L2Item temp = ItemTable.getInstance().getTemplate(249); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x1f) && (classId <= 0x25)) - { - //dark elven fighter fists - L2Item temp = ItemTable.getInstance().getTemplate(245); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x26) && (classId <= 0x2b)) - { - //dark elven mage fists - L2Item temp = ItemTable.getInstance().getTemplate(250); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x2c) && (classId <= 0x30)) - { - //orc fighter fists - L2Item temp = ItemTable.getInstance().getTemplate(248); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x31) && (classId <= 0x34)) - { - //orc mage fists - L2Item temp = ItemTable.getInstance().getTemplate(252); - weaponItem = (L2Weapon)temp; - } - else if ((classId >= 0x35) && (classId <= 0x39)) - { - //dwarven fists - L2Item temp = ItemTable.getInstance().getTemplate(247); - weaponItem = (L2Weapon)temp; - } - - return weaponItem; - } - - /** - * Give Expertise skill of this level and remove beginner Lucky skill.

    - * - * Actions :

    - *
  • Get the Level of the L2PcInstance
  • - *
  • If L2PcInstance Level is 5, remove beginner Lucky skill
  • - *
  • Add the Expertise skill corresponding to its Expertise level
  • - *
  • Update the overloaded status of the L2PcInstance


  • - * - * Caution : This method DOESN'T give other free skills (SP needed = 0)

    - * - */ - public void rewardSkills() - { - // Get the Level of the L2PcInstance - int lvl = getLevel(); - - // Remove beginner Lucky skill - if (lvl == 5) - { - L2Skill skill = SkillTable.getInstance().getInfo(194, 1); - skill = removeSkill(skill); - - if (Config.DEBUG && skill != null) _log.fine("removed skill 'Lucky' from "+getName()); - } - - // Calculate the current higher Expertise of the L2PcInstance - for (int i=0; i < EXPERTISE_LEVELS.length; i++) - { - if (lvl >= EXPERTISE_LEVELS[i]) - setExpertiseIndex(i); - } - - // Add the Expertise skill corresponding to its Expertise level - if (getExpertiseIndex() > 0) - { - L2Skill skill = SkillTable.getInstance().getInfo(239, getExpertiseIndex()); - addSkill(skill); - - if (Config.DEBUG) _log.fine("awarded "+getName()+" with new expertise."); - - } - else - { - if (Config.DEBUG) _log.fine("No skills awarded at lvl: "+lvl); - } - - //Active skill dwarven craft - - if (getSkillLevel(1321) < 1 && getRace() == Race.dwarf) - { - L2Skill skill = SkillTable.getInstance().getInfo(1321,1); - addSkill(skill); - } - - //Active skill common craft - if (getSkillLevel(1322) < 1) - { - L2Skill skill = SkillTable.getInstance().getInfo(1322,1); - addSkill(skill); - } - - for(int i = 0; i < COMMON_CRAFT_LEVELS.length; i++) - { - if(lvl >= COMMON_CRAFT_LEVELS[i] && getSkillLevel(1320) < (i+1)) - { - L2Skill skill = SkillTable.getInstance().getInfo(1320, (i+1)); - addSkill(skill); - } - } - - // This function gets called on login, so not such a bad place to check weight - refreshOverloaded(); // Update the overloaded status of the L2PcInstance - refreshExpertisePenalty(); // Update the expertise status of the L2PcInstance - } - - - /** Set the Experience value of the L2PcInstance. */ - public void setExp(int exp) { getStat().setExp(exp); } - - /** - * Return the Race object of the L2PcInstance.

    - */ - public Race getRace() - { - if (!isSubClassActive()) - return getTemplate().race; - - boolean isFemale = (getSex() == 1); - L2PcTemplate charTemp = CharTemplateTable.getInstance().getTemplate(_baseClass, isFemale); - - return charTemp.race; - } - - public L2Radar getRadar() - { - return _radar; - } - - /** Return the SP amount of the L2PcInstance. */ - public int getSp() { return getStat().getSp(); } - - /** Set the SP amount of the L2PcInstance. */ - public void setSp(int sp) { super.getStat().setSp(sp); } - - public int getPvpFlag() - { - return _pvpFlag; - } - - /** - * Return true if this L2PcInstance is a clan leader in - * ownership of the passed castle - */ - public boolean isCastleLord(int castleId) - { - L2Clan clan = getClan(); - - // player has clan and is the clan leader, check the castle info - if ((clan != null) && (clan.getLeader().getPlayerInstance() == this)) - { - // if the clan has a castle and it is actually the queried castle, return true - Castle castle = CastleManager.getInstance().getCastleByOwner(clan); - if ((castle != null) && (castle == CastleManager.getInstance().getCastle(castleId))) - return true; - } - - return false; - } - /** - * Return the Clan Identifier of the L2PcInstance.

    - */ - public int getClanId() - { - return _clanId; - } - - /** - * Return the Clan Crest Identifier of the L2PcInstance or 0.

    - */ - public int getClanCrestId() - { - if (_clan != null && _clan.hasCrest()) - return _clan.getCrestId(); - - return 0; - } - - /** - * @return The Clan CrestLarge Identifier or 0 - */ - public int getClanCrestLargeId() - { - if (_clan != null && _clan.hasCrestLarge()) - return _clan.getCrestLargeId(); - - return 0; - } - - public long getDeleteClanTime() - { - return _deleteClanTime; - } - - public void setDeleteClanTime(long time) - { - _deleteClanTime = time; - } - - public void setDeleteClanCurTime() - { - _deleteClanTime = System.currentTimeMillis(); - } - - public void setOnlineTime(long time) - { - _onlineTime = time; - _onlineBeginTime = System.currentTimeMillis(); - } - - public boolean canJoinClan() - { - return (_deleteClanTime == 0) || ((System.currentTimeMillis() - _deleteClanTime) >= Config.ALT_CLAN_JOIN_DAYS*24*60*60*1000); - } - - public boolean canCreateClan() - { - return (_deleteClanTime == 0) || ((System.currentTimeMillis() - _deleteClanTime) >= Config.ALT_CLAN_CREATE_DAYS*24*60*60*1000); - } - - /** - * Return the PcInventory Inventory of the L2PcInstance contained in _inventory.

    - */ - public PcInventory getInventory() - { - return _inventory; - } - - /** - * Delete a ShortCut of the L2PcInstance _shortCuts.

    - */ - public void removeItemFromShortCut(int objectId) - { - _shortCuts.deleteShortCutByObjectId(objectId); - } - - /** - * Return True if the L2PcInstance is sitting.

    - */ - public boolean isSitting() - { - return _waitTypeSitting; - } - - /** - * Sit down the L2PcInstance, set the AI Intention to AI_INTENTION_REST and send a Server->Client ChangeWaitType packet (broadcast)

    - */ - public void sitDown() - { - if (isCastingNow()) - { - sendMessage("Cannot sit while casting"); - return; - } - - if (!_waitTypeSitting && !isAttackingDisabled() && !isOutOfControl() && !isImobilised()) - { - breakAttack(); - - _waitTypeSitting = true; - getAI().setIntention(CtrlIntention.AI_INTENTION_REST); - broadcastPacket(new ChangeWaitType (this, ChangeWaitType.WT_SITTING)); - } - } - - /** - * Stand up the L2PcInstance, set the AI Intention to AI_INTENTION_IDLE and send a Server->Client ChangeWaitType packet (broadcast)

    - */ - public void standUp() - { - if (L2Event.active && eventSitForced) - { - sendMessage("A dark force beyond your mortal understanding makes your knees to shake when you try to stand up ..."); - } - else if (_waitTypeSitting && !isInStoreMode() && !isAlikeDead()) - { - if (_relax) - { - setRelax(false); - stopEffects(L2Effect.EffectType.RELAXING); - } - - _waitTypeSitting = false; - getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); - broadcastPacket(new ChangeWaitType (this, ChangeWaitType.WT_STANDING)); - } - } - - /** - * Set the value of the _relax value. Must be True if using skill Relax and False if not. - */ - public void setRelax(boolean val) - { - _relax = val; - } - - /** - * Return the PcWarehouse object of the L2PcInstance.

    - */ - public PcWarehouse getWarehouse() - { - return _warehouse; - } - - /** - * Return the PcFreight object of the L2PcInstance.

    - */ - public PcFreight getFreight() - { - return _freight; - } - - /** - * Return the Identifier of the L2PcInstance.

    - */ - public int getCharId() - { - return _charId; - } - - /** - * Set the Identifier of the L2PcInstance.

    - */ - public void setCharId(int charId) - { - _charId = charId; - } - - /** - * Return the Adena amount of the L2PcInstance.

    - */ - public int getAdena() - { - return _inventory.getAdena(); - } - - /** - * Return the Ancient Adena amount of the L2PcInstance.

    - */ - public int getAncientAdena() - { - return _inventory.getAncientAdena(); - } - - /** - * Add adena to Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param count : int Quantity of adena to be added - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - */ - public void addAdena(String process, int count, L2Object reference, boolean sendMessage) - { - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.EARNED_ADENA); - sm.addNumber(count); - sendPacket(sm); - } - - if (count > 0) - { - _inventory.addAdena(process, count, this, reference); - - // Send update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate iu = new InventoryUpdate(); - iu.addItem(_inventory.getAdenaInstance()); - sendPacket(iu); - } - else sendPacket(new ItemList(this, false)); - } - } - - /** - * Reduce adena in Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param count : int Quantity of adena to be reduced - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return boolean informing if the action was successfull - */ - public boolean reduceAdena(String process, int count, L2Object reference, boolean sendMessage) - { - if (count > getAdena()) - { - if (sendMessage) sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA)); - return false; - } - - if (count > 0) - { - L2ItemInstance adenaItem = _inventory.getAdenaInstance(); - _inventory.reduceAdena(process, count, this, reference); - - // Send update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate iu = new InventoryUpdate(); - iu.addItem(adenaItem); - sendPacket(iu); - } - else sendPacket(new ItemList(this, false)); - - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ADENA); - sm.addNumber(count); - sendPacket(sm); - } - } - - return true; - } - - /** - * Add ancient adena to Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * - * @param process : String Identifier of process triggering this action - * @param count : int Quantity of ancient adena to be added - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - */ - public void addAncientAdena(String process, int count, L2Object reference, boolean sendMessage) - { - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.EARNED_S2_S1_s); - sm.addItemName(PcInventory.ANCIENT_ADENA_ID); - sm.addNumber(count); - sendPacket(sm); - } - - if (count > 0) - { - _inventory.addAncientAdena(process, count, this, reference); - - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate iu = new InventoryUpdate(); - iu.addItem(_inventory.getAncientAdenaInstance()); - sendPacket(iu); - } - else sendPacket(new ItemList(this, false)); - } - } - - /** - * Reduce ancient adena in Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param count : int Quantity of ancient adena to be reduced - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return boolean informing if the action was successfull - */ - public boolean reduceAncientAdena(String process, int count, L2Object reference, boolean sendMessage) - { - if (count > getAncientAdena()) - { - if (sendMessage) - sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA)); - - return false; - } - - if (count > 0) - { - L2ItemInstance ancientAdenaItem = _inventory.getAncientAdenaInstance(); - _inventory.reduceAncientAdena(process, count, this, reference); - - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate iu = new InventoryUpdate(); - iu.addItem(ancientAdenaItem); - sendPacket(iu); - } - else - { - sendPacket(new ItemList(this, false)); - } - - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); - sm.addNumber(count); - sm.addItemName(PcInventory.ANCIENT_ADENA_ID); - sendPacket(sm); - } - } - - return true; - } - - /** - * Adds item to inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param item : L2ItemInstance to be added - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - */ - public void addItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) - { - if (item.getCount() > 0) - { - // Sends message to client if requested - if (sendMessage) - { - if (item.getCount() > 1) - { - SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1_S2); - sm.addItemName(item.getItemId()); - sm.addNumber(item.getCount()); - sendPacket(sm); - } - else - { - SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1); - sm.addItemName(item.getItemId()); - sendPacket(sm); - } - } - - // Add the item to inventory - L2ItemInstance newitem = _inventory.addItem(process, item, this, reference); - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - playerIU.addItem(newitem); - sendPacket(playerIU); - } - else - { - sendPacket(new ItemList(this, false)); - } - - // Update current load as well - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // If over capacity, trop the item - if (!isGM() && !_inventory.validateCapacity(0)) - dropItem("InvDrop", item, null, true); - } - } - - /** - * Adds item to Inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param itemId : int Item Identifier of the item to be added - * @param count : int Quantity of items to be added - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - */ - public void addItem(String process, int itemId, int count, L2Object reference, boolean sendMessage) - { - if (count > 0) - { - // Sends message to client if requested - if (sendMessage) - { - if (count > 1) - { - if (process.equalsIgnoreCase("sweep") || process.equalsIgnoreCase("Quest")) - { - SystemMessage sm = new SystemMessage(SystemMessage.EARNED_S2_S1_s); - sm.addItemName(itemId); - sm.addNumber(count); - sendPacket(sm); - } - else - { - SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1_S2); - sm.addItemName(itemId); - sm.addNumber(count); - sendPacket(sm); - } - } - else - { - if (process.equalsIgnoreCase("sweep") || process.equalsIgnoreCase("Quest")) - { - SystemMessage sm = new SystemMessage(SystemMessage.EARNED_ITEM); - sm.addItemName(itemId); - sendPacket(sm); - } - else - { - SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1); - sm.addItemName(itemId); - sendPacket(sm); - } - } - } - - // Add the item to inventory - L2ItemInstance item = _inventory.addItem(process, itemId, count, this, reference); - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - playerIU.addItem(item); - sendPacket(playerIU); - } - else sendPacket(new ItemList(this, false)); - - // Update current load as well - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // If over capacity, trop the item - if (!isGM() && !_inventory.validateCapacity(0)) dropItem("InvDrop", item, null, true); - } - } - - /** - * Destroy item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param item : L2ItemInstance to be destroyed - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return boolean informing if the action was successfull - */ - public boolean destroyItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) - { - int oldCount = item.getCount(); - item = _inventory.destroyItem(process, item, this, reference); - - if (item == null) - { - if (sendMessage) - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); - - return false; - } - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - playerIU.addItem(item); - sendPacket(playerIU); - } - else sendPacket(new ItemList(this, false)); - - // Update current load as well - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // Sends message to client if requested - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); - sm.addNumber(oldCount); - sm.addItemName(item.getItemId()); - sendPacket(sm); - } - - return true; - } - - /** - * Destroys item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param objectId : int Item Instance identifier of the item to be destroyed - * @param count : int Quantity of items to be destroyed - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return boolean informing if the action was successfull - */ - public boolean destroyItem(String process, int objectId, int count, L2Object reference, boolean sendMessage) - { - L2ItemInstance item = _inventory.getItemByObjectId(objectId); - - if (item == null || item.getCount() < count || _inventory.destroyItem(process, objectId, count, this, reference) == null) - { - if (sendMessage) - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); - - return false; - } - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - playerIU.addItem(item); - sendPacket(playerIU); - } - else sendPacket(new ItemList(this, false)); - - // Update current load as well - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // Sends message to client if requested - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); - sm.addNumber(count); - sm.addItemName(item.getItemId()); - sendPacket(sm); - } - - return true; - } - - /** - * Destroy item from inventory by using its itemId and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param itemId : int Item identifier of the item to be destroyed - * @param count : int Quantity of items to be destroyed - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return boolean informing if the action was successfull - */ - public boolean destroyItemByItemId(String process, int itemId, int count, L2Object reference, boolean sendMessage) - { - L2ItemInstance item = _inventory.getItemByItemId(itemId); - - if (item == null || item.getCount() < count || _inventory.destroyItemByItemId(process, itemId, count, this, reference) == null) - { - if (sendMessage) - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); - - return false; - } - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - playerIU.addItem(item); - sendPacket(playerIU); - } - else sendPacket(new ItemList(this, false)); - - // Update current load as well - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // Sends message to client if requested - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); - sm.addNumber(count); - sm.addItemName(itemId); - sendPacket(sm); - } - - return true; - } - - /** - * Destroy all weared items from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return boolean informing if the action was successfull - */ - public void destroyWearedItems(String process, L2Object reference, boolean sendMessage) - { - - // Go through all Items of the inventory - for (L2ItemInstance item : getInventory().getItems()) - { - // Check if the item is a Try On item in order to remove it - if (item.isWear()) - { - if (item.isEquipped()) - getInventory().unEquipItemInSlotAndRecord(item.getEquipSlot()); - - if (_inventory.destroyItem(process, item, this, reference) == null) - { - _log.warning("Player " + getName() + " can't destroy weared item: " + item.getName() + "[ " + item.getObjectId() + " ]"); - continue; - } - - // Send an Unequipped Message in system window of the player for each Item - SystemMessage sm = new SystemMessage(0x1a1); - sm.addItemName(item.getItemId()); - sendPacket(sm); - - } - } - - - // Send the StatusUpdate Server->Client Packet to the player with new CUR_LOAD (0x0e) information - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // Send the ItemList Server->Client Packet to the player in order to refresh its Inventory - ItemList il = new ItemList(getInventory().getItems(), true); - sendPacket(il); - - // Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers - broadcastUserInfo(); - - // Sends message to client if requested - sendMessage("Trying-on mode has ended."); - - } - - /** - * Transfers item to another ItemContainer and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param itemId : int Item Identifier of the item to be transfered - * @param count : int Quantity of items to be transfered - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @return L2ItemInstance corresponding to the new item or the updated item in inventory - */ - public L2ItemInstance transferItem(String process, int objectId, int count, Inventory target, L2Object reference) - { - L2ItemInstance oldItem = checkItemManipulation(objectId, count, "transfer"); - if (oldItem == null) return null; - L2ItemInstance newItem = getInventory().transferItem(process, objectId, count, target, this, reference); - if (newItem == null) return null; - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - - if (oldItem.getCount() > 0 && oldItem != newItem) - playerIU.addModifiedItem(oldItem); - else - playerIU.addRemovedItem(oldItem); - - sendPacket(playerIU); - } - else sendPacket(new ItemList(this, false)); - - // Update current load as well - StatusUpdate playerSU = new StatusUpdate(getObjectId()); - playerSU.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(playerSU); - - // Send target update packet - if (target instanceof PcInventory) - { - L2PcInstance targetPlayer = ((PcInventory)target).getOwner(); - - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - - if (newItem.getCount() > count) - playerIU.addModifiedItem(newItem); - else - playerIU.addNewItem(newItem); - - targetPlayer.sendPacket(playerIU); - } - else targetPlayer.sendPacket(new ItemList(targetPlayer, false)); - - // Update current load as well - playerSU = new StatusUpdate(targetPlayer.getObjectId()); - playerSU.addAttribute(StatusUpdate.CUR_LOAD, targetPlayer.getCurrentLoad()); - targetPlayer.sendPacket(playerSU); - } - else if (target instanceof PetInventory) - { - PetInventoryUpdate petIU = new PetInventoryUpdate(); - - if (newItem.getCount() > count) - petIU.addModifiedItem(newItem); - else - petIU.addNewItem(newItem); - - ((PetInventory)target).getOwner().getOwner().sendPacket(petIU); - } - - return newItem; - } - - /** - * Drop item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param item : L2ItemInstance to be dropped - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return boolean informing if the action was successfull - */ - public boolean dropItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) - { - item = _inventory.dropItem(process, item, this, reference); - - if (item == null) - { - if (sendMessage) - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); - - return false; - } - - item.dropMe(this, getClientX() + Rnd.get(50) - 25, getClientY() + Rnd.get(50) - 25, getClientZ() + 20); - // Avoids it from beeing removed by the auto item destroyer - item.setDropTime(0); - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - playerIU.addItem(item); - sendPacket(playerIU); - } - else sendPacket(new ItemList(this, false)); - - // Update current load as well - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // Sends message to client if requested - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.YOU_DROPPED_S1); - sm.addItemName(item.getItemId()); - sendPacket(sm); - } - - return true; - } - - /** - * Drop item from inventory by using its objectID and send a Server->Client InventoryUpdate packet to the L2PcInstance. - * @param process : String Identifier of process triggering this action - * @param objectId : int Item Instance identifier of the item to be dropped - * @param count : int Quantity of items to be dropped - * @param x : int coordinate for drop X - * @param y : int coordinate for drop Y - * @param z : int coordinate for drop Z - * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation - * @param sendMessage : boolean Specifies whether to send message to Client about this action - * @return L2ItemInstance corresponding to the new item or the updated item in inventory - */ - public L2ItemInstance dropItem(String process, int objectId, int count, int x, int y, int z, L2Object reference, boolean sendMessage) - { - L2ItemInstance invitem = _inventory.getItemByObjectId(objectId); - L2ItemInstance item = _inventory.dropItem(process, objectId, count, this, reference); - - if (item == null) - { - if (sendMessage) - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); - - return null; - } - - item.dropMe(this, x, y, z); - // Avoids it from beeing removed by the auto item destroyer - item.setDropTime(0); - - // Send inventory update packet - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate playerIU = new InventoryUpdate(); - playerIU.addItem(invitem); - sendPacket(playerIU); - } - else - { - sendPacket(new ItemList(this, false)); - } - - // Update current load as well - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); - sendPacket(su); - - // Sends message to client if requested - if (sendMessage) - { - SystemMessage sm = new SystemMessage(SystemMessage.YOU_DROPPED_S1); - sm.addItemName(item.getItemId()); - sendPacket(sm); - } - - return item; - } - - public L2ItemInstance checkItemManipulation(int objectId, int count, String action) - { - //TODO: if we remove objects that are not visisble from the L2World, we'll have to remove this check - if (L2World.getInstance().findObject(objectId) == null) - { - _log.finest(getObjectId()+": player tried to " + action + " item not available in L2World"); - return null; - } - - L2ItemInstance item = getInventory().getItemByObjectId(objectId); - - if (item == null || item.getOwnerId() != getObjectId()) - { - _log.finest(getObjectId()+": player tried to " + action + " item he is not owner of"); - return null; - } - - if (count < 0 || (count > 1 && !item.isStackable())) - { - _log.finest(getObjectId()+": player tried to " + action + " item with invalid count: "+ count); - return null; - } - - if (count > item.getCount()) - { - _log.finest(getObjectId()+": player tried to " + action + " more items than he owns"); - return null; - } - - // Pet is summoned and not the item that summoned the pet AND not the buggle from strider you're mounting - if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId) - { - if (Config.DEBUG) - _log.finest(getObjectId()+": player tried to " + action + " item controling pet"); - - return null; - } - - if (getActiveEnchantItem() != null && getActiveEnchantItem().getObjectId() == objectId) - { - if (Config.DEBUG) - _log.finest(getObjectId()+":player tried to " + action + " an enchant scroll he was using"); - - return null; - } - - if (item.isWear()) - { - Util.handleIllegalPlayerAction(this, "Warning!! Character "+getName()+" tried to " + action + " weared item: "+item.getObjectId(),Config.DEFAULT_PUNISH); - return null; - } - - return item; - } - - /** - * Set _protectEndTime according settings. - */ - public void setProtection(boolean protect) - { - if (Config.DEVELOPER && (protect || _protectEndTime > 0)) - System.out.println(this.getName() + ": Protection " + (protect?"ON " + (GameTimeController.getGameTicks() + Config.PLAYER_SPAWN_PROTECTION * GameTimeController.TICKS_PER_SECOND) :"OFF") + " (currently " + GameTimeController.getGameTicks() + ")"); - - _protectEndTime = protect ? GameTimeController.getGameTicks() + Config.PLAYER_SPAWN_PROTECTION * GameTimeController.TICKS_PER_SECOND : 0; - } - - /** - * Return the active connection with the client.

    - */ - public Connection getNetConnection() - { - return _connection; - } - - /** - * Set the active connection with the client.

    - */ - public void setNetConnection(Connection connection) - { - _connection = connection; - } - - /** - * Close the active connection with the client.

    - */ - public void closeNetConnection() - { - if (getNetConnection() != null) - getNetConnection().close(); - } - - /** - * Manage actions when a player click on this L2PcInstance.

    - * - * Actions on first click on the L2PcInstance (Select it) :

    - *
  • Set the target of the player
  • - *
  • Send a Server->Client packet MyTargetSelected to the player (display the select window)


  • - * - * Actions on second click on the L2PcInstance (Follow it/Attack it/Intercat with it) :

    - *
  • Send a Server->Client packet MyTargetSelected to the player (display the select window)
  • - *
  • If this L2PcInstance has a Private Store, notify the player AI with AI_INTENTION_INTERACT
  • - *
  • If this L2PcInstance is autoAttackable, notify the player AI with AI_INTENTION_ATTACK


  • - *
  • If this L2PcInstance is NOT autoAttackable, notify the player AI with AI_INTENTION_FOLLOW


  • - * - * Example of use :

    - *
  • Client packet : Action, AttackRequest


  • - * - * @param player The player that start an action on this L2PcInstance - * - */ - public void onAction(L2PcInstance player) - { - // Check if the L2PcInstance is confused - if (player.isConfused()) - { - // Send a Server->Client packet ActionFailed to the player - ActionFailed af = new ActionFailed(); - player.sendPacket(af); - } - - // Check if the player already target this L2PcInstance - if (player.getTarget() != this) - { - // Set the target of the player - player.setTarget(this); - - // Send a Server->Client packet MyTargetSelected to the player - // The color to display in the select window is White - MyTargetSelected my = new MyTargetSelected(getObjectId(), 0); - player.sendPacket(my); - } - else - { - // Check if this L2PcInstance has a Private Store - if (getPrivateStoreType() != 0) - { - player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this); - } - else - { - // Check if this L2PcInstance is autoAttackable - if (isAutoAttackable(player)) - player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this); - else - player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this); - } - } - } - - /** - * Send packet StatusUpdate with current HP,MP and CP to the L2PcInstance and only current HP, MP and Level to all other L2PcInstance of the Party.

    - * - * Actions :

    - *
  • Send the Server->Client packet StatusUpdate with current HP, MP and CP to this L2PcInstance

  • - *
  • Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2PcInstance of the Party


  • - * - * Caution : This method DOESN'T SEND current HP and MP to all L2PcInstance of the _statusListener

    - * - */ - public void broadcastStatusUpdate() - { - //TODO We mustn't send these informations to other players - // Send the Server->Client packet StatusUpdate with current HP and MP to all L2PcInstance that must be informed of HP/MP updates of this L2PcInstance - //super.broadcastStatusUpdate(); - - // Send the Server->Client packet StatusUpdate with current HP, MP and CP to this L2PcInstance - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp()); - su.addAttribute(StatusUpdate.CUR_MP, (int) getCurrentMp()); - su.addAttribute(StatusUpdate.CUR_CP, (int) getCurrentCp()); - su.addAttribute(StatusUpdate.MAX_CP, getMaxCp()); - sendPacket(su); - - // Check if a party is in progress - if (isInParty()) - { - // Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2PcInstance of the Party - PartySmallWindowUpdate update = new PartySmallWindowUpdate(this); - getParty().broadcastToPartyMembers(this, update); - } - - if (isInOlympiadMode()) - { - if(Olympiad.getInstance().getSpectators(_olympiadGameId) != null) - { - for(L2PcInstance spectator : Olympiad.getInstance().getSpectators(_olympiadGameId)) - { - if (spectator == null) continue; - spectator.sendPacket(new ExOlympiadUserInfo(this, getOlympiadSide())); - } - } - } - } - - /** - * Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers.

    - * - * Concept :

    - * Others L2PcInstance in the detection area of the L2PcInstance are identified in _knownPlayers. - * In order to inform other players of this L2PcInstance state modifications, server just need to go through _knownPlayers to send Server->Client Packet

    - * - * Actions :

    - *
  • Send a Server->Client packet UserInfo to this L2PcInstance (Public and Private Data)
  • - *
  • Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance (Public data only)


  • - * - * Caution : DON'T SEND UserInfo packet to other players instead of CharInfo packet. - * Indeed, UserInfo packet contains PRIVATE DATA as MaxHP, STR, DEX...

    - * - */ - public final void broadcastUserInfo() - { - // Send a Server->Client packet UserInfo to this L2PcInstance - sendPacket(new UserInfo(this)); - - // Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance - if (Config.DEBUG) - _log.fine("players to notify:" + getKnownList().getKnownPlayers().size() + " packet: [S] 03 CharInfo"); - - Broadcast.toKnownPlayers(this, new CharInfo(this)); - } - - /** - * Return the Alliance Identifier of the L2PcInstance.

    - */ - public int getAllyId() - { - if (_clan == null) - return 0; - - return _clan.getAllyId(); - } - - public int getAllyCrestId() - { - if (getAllyId() == 0) - return 0; - - return _clan.getAllyCrestId(); - } - - /** - * Manage hit process (called by Hit Task of L2Character).

    - * - * Actions :

    - *
  • If the attacker/target is dead or use fake death, notify the AI with EVT_CANCEL and send a Server->Client packet ActionFailed (if attacker is a L2PcInstance)
  • - *
  • If attack isn't aborted, send a message system (critical hit, missed...) to attacker/target if they are L2PcInstance
  • - *
  • If attack isn't aborted and hit isn't missed, reduce HP of the target and calculate reflection damage to reduce HP of attacker if necessary
  • - *
  • if attack isn't aborted and hit isn't missed, manage attack or cast break of the target (calculating rate, sending message...)


  • - * - * @param target The L2Character targeted - * @param damage Nb of HP to reduce - * @param crit True if hit is critical - * @param miss True if hit is missed - * @param soulshot True if SoulShot are charged - * @param shld True if shield is efficient - * - */ - protected void onHitTimer(L2Character target, int damage, boolean crit, boolean miss, boolean soulshot, boolean shld) - { - super.onHitTimer(target, damage, crit, miss, soulshot, shld); - } - - /** - * Send a Server->Client packet StatusUpdate to the L2PcInstance.

    - */ - public void sendPacket(ServerBasePacket packet) - { - if(_isConnected) - { - try - { - if (_connection != null) - _connection.sendPacket(packet); - } - catch (Exception e) - { - _log.log(Level.INFO, "", e); - } - } - } - - /** - * Manage Interact Task with another L2PcInstance.

    - * - * Actions :

    - *
  • If the private store is a STORE_PRIVATE_SELL, send a Server->Client PrivateBuyListSell packet to the L2PcInstance
  • - *
  • If the private store is a STORE_PRIVATE_BUY, send a Server->Client PrivateBuyListBuy packet to the L2PcInstance
  • - *
  • If the private store is a STORE_PRIVATE_MANUFACTURE, send a Server->Client RecipeShopSellList packet to the L2PcInstance


  • - * - * @param target The L2Character targeted - * - */ - public void doInteract(L2Character target) - { - if (target instanceof L2PcInstance) - { - L2PcInstance temp = (L2PcInstance) target; - sendPacket(new ActionFailed()); - - if (temp.getPrivateStoreType() == STORE_PRIVATE_SELL) - sendPacket(new PrivateStoreListSell(this, temp)); - else if (temp.getPrivateStoreType() == STORE_PRIVATE_BUY) - sendPacket(new PrivateStoreListBuy(this, temp)); - else if (temp.getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE) - sendPacket(new RecipeShopSellList(this, temp)); - - } - else - { - // _interactTarget=null should never happen but one never knows ^^; - if (target != null) - target.onAction(this); - } - } - - /** - * Manage AutoLoot Task.

    - * - * Actions :

    - *
  • Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2
  • - *
  • Add the Item to the L2PcInstance inventory
  • - *
  • Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new slot) or ModifiedItem (increase amount)
  • - *
  • Send a Server->Client packet StatusUpdate to this L2PcInstance with current weight


  • - * - * Caution : If a Party is in progress, distribute Items between party members

    - * - * @param target The L2ItemInstance dropped - * - */ - public void doAutoLoot(L2Attackable target, L2Attackable.RewardItem item) - { - if (isInParty()) getParty().distributeItem(this, item, false); - else if (item.getItemId() == 57) addAdena("Loot", item.getCount(), target, true); - else addItem("Loot", item.getItemId(), item.getCount(), target, true); - } - - /** - * Manage Pickup Task.

    - * - * Actions :

    - *
  • Send a Server->Client packet StopMove to this L2PcInstance
  • - *
  • Remove the L2ItemInstance from the world and send server->client GetItem packets
  • - *
  • Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2
  • - *
  • Add the Item to the L2PcInstance inventory
  • - *
  • Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new slot) or ModifiedItem (increase amount)
  • - *
  • Send a Server->Client packet StatusUpdate to this L2PcInstance with current weight


  • - * - * Caution : If a Party is in progress, distribute Items between party members

    - * - * @param object The L2ItemInstance to pick up - * - */ - protected void doPickupItem(L2Object object) - { - if (isAlikeDead() || isFakeDeath()) return; - - // Set the AI Intention to AI_INTENTION_IDLE - getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); - - // Check if the L2Object to pick up is a L2ItemInstance - if (! (object instanceof L2ItemInstance)) - { - // dont try to pickup anything that is not an item :) - _log.warning("trying to pickup wrong target."+getTarget()); - return; - } - - L2ItemInstance target = (L2ItemInstance) object; - - // Send a Server->Client packet ActionFailed to this L2PcInstance - sendPacket(new ActionFailed()); - - // Send a Server->Client packet StopMove to this L2PcInstance - StopMove sm = new StopMove(getObjectId(), getX(), getY(), getZ(), getHeading()); - if (Config.DEBUG) _log.fine("pickup pos: "+ target.getX() + " "+target.getY()+ " "+target.getZ() ); - sendPacket(sm); - - synchronized (target) - { - // Check if the target to pick up is visible - if (!target.isVisible()) - { - // Send a Server->Client packet ActionFailed to this L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - if ( ((isInParty() && getParty().getLootDistribution() == L2Party.ITEM_LOOTER) || !isInParty()) && !_inventory.validateCapacity(target)) - { - sendPacket(new ActionFailed()); - sendPacket(new SystemMessage(SystemMessage.SLOTS_FULL)); - return; - } - - // Remove the L2ItemInstance from the world and send server->client GetItem packets - target.pickupMe(this); - } - - // Check if a Party is in progress - if (isInParty()) getParty().distributeItem(this, target); - // Target is adena - else if (target.getItemId() == 57 && getInventory().getAdenaInstance() != null) - { - addAdena("Pickup", target.getCount(), null, true); - ItemTable.getInstance().destroyItem("Pickup", target, this, null); - } - // Target is regular item - else addItem("Pickup", target, null, true); - } - - - /** - * Set a target.

    - * - * Actions :

    - *
  • Remove the L2PcInstance from the _statusListener of the old target if it was a L2Character
  • - *
  • Add the L2PcInstance to the _statusListener of the new target if it's a L2Character
  • - *
  • Target the new L2Object (add the target to the L2PcInstance _target, _knownObject and L2PcInstance to _KnownObject of the L2Object)


  • - * - * @param newTarget The L2Object to target - * - */ - public void setTarget(L2Object newTarget) - { - // Check if the new target is visible - if (newTarget != null && !newTarget.isVisible()) - newTarget = null; - - // Get the current target - L2Object oldTarget = getTarget(); - - if (oldTarget != null) - { - if (oldTarget.equals(newTarget)) - return; // no target change - - // Remove the L2PcInstance from the _statusListener of the old target if it was a L2Character - if (oldTarget instanceof L2Character) - ((L2Character) oldTarget).removeStatusListener(this); - } - - // Add the L2PcInstance to the _statusListener of the new target if it's a L2Character - if (newTarget != null && newTarget instanceof L2Character) - { - ((L2Character) newTarget).addStatusListener(this); - TargetSelected my = new TargetSelected(getObjectId(), newTarget.getObjectId(), getX(), getY(), getZ()); - broadcastPacket(my); - } - - // Target the new L2Object (add the target to the L2PcInstance _target, _knownObject and L2PcInstance to _KnownObject of the L2Object) - super.setTarget(newTarget); - } - - /** - * Return the active weapon instance (always equiped in the right hand).

    - */ - public L2ItemInstance getActiveWeaponInstance() - { - return getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND); - } - - /** - * Return the active weapon item (always equiped in the right hand).

    - */ - public L2Weapon getActiveWeaponItem() - { - L2ItemInstance weapon = getActiveWeaponInstance(); - - if (weapon == null) - return getFistsWeaponItem(); - - return (L2Weapon) weapon.getItem(); - } - - public L2ItemInstance getChestArmorInstance() - { - return getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST); - } - - public L2Armor getActiveChestArmorItem() - { - L2ItemInstance armor = getChestArmorInstance(); - - if (armor == null) - return null; - - return (L2Armor) armor.getItem(); - } - - public boolean isWearingHeavyArmor() - { - L2ItemInstance armor = getChestArmorInstance(); - - if ((L2ArmorType)armor.getItemType() == L2ArmorType.HEAVY) - return true; - - return false; - } - - public boolean isWearingLightArmor() - { - L2ItemInstance armor = getChestArmorInstance(); - - if ((L2ArmorType)armor.getItemType() == L2ArmorType.LIGHT) - return true; - - return false; - } - - public boolean isWearingMagicArmor() - { - L2ItemInstance armor = getChestArmorInstance(); - - if ((L2ArmorType)armor.getItemType() == L2ArmorType.MAGIC) - return true; - - return false; - } - - public boolean isWearingFormalWear() - { - return _IsWearingFormalWear; - } - - public void setIsWearingFormalWear(boolean value) { - _IsWearingFormalWear = value; - } - - /** - * Return the secondary weapon instance (always equiped in the left hand).

    - */ - public L2ItemInstance getSecondaryWeaponInstance() - { - return getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); - } - - /** - * Return the secondary weapon item (always equiped in the left hand) or the fists weapon.

    - */ - public L2Weapon getSecondaryWeaponItem() - { - L2ItemInstance weapon = getSecondaryWeaponInstance(); - - if (weapon == null) - return getFistsWeaponItem(); - - L2Item item = weapon.getItem(); - - if (item instanceof L2Weapon) - return (L2Weapon) item; - - return null; - } - - - /** - * Kill the L2Character, Apply Death Penalty, Manage gain/loss Karma and Item Drop.

    - * - * Actions :

    - *
  • Reduce the Experience of the L2PcInstance in function of the calculated Death Penalty
  • - *
  • If necessary, unsummon the Pet of the killed L2PcInstance
  • - *
  • Manage Karma gain for attacker and Karam loss for the killed L2PcInstance
  • - *
  • If the killed L2PcInstance has Karma, manage Drop Item
  • - *
  • Kill the L2PcInstance


  • - * - * - * @param i The HP decrease value - * @param attacker The L2Character who attacks - * - */ - public void doDie(L2Character killer) - { - // Kill the L2PcInstance - super.doDie(killer); - - if (killer != null) - { - if (atEvent && killer instanceof L2PcInstance) - { - L2PcInstance pk = (L2PcInstance) killer; - pk.kills.add(getName()); - } - - onDieDropItem(killer); // Check if any item should be dropped - - if (!ArenaManager.getInstance().checkIfInZone(this)) - { - if (Config.ALT_GAME_DELEVEL) - { - // Reduce the Experience of the L2PcInstance in function of the calculated Death Penalty - // NOTE: deathPenalty +- Exp will update karma - if (getSkillLevel(L2Skill.SKILL_LUCKY) < 0 || getStat().getLevel() > 4) - deathPenalty((killer instanceof L2PcInstance && this.getClan() != null && ((L2PcInstance)killer).getClan() != null && ((L2PcInstance)killer).getClan().isAtWarWith(this.getClanId()))); - } - else - onDieUpdateKarma(); // Update karma if delevel is not allowed - } - } - - setPvpFlag(0); // Clear the pvp flag - - // Unsummon the Pet - if (getPet() != null) - getPet().unSummon(this); - - // Unsummon Cubics - if (_cubics.size() > 0) - { - for (L2CubicInstance cubic : _cubics.values()) - { - cubic.stopAction(); - cubic.cancelDisappear(); - } - - _cubics.clear(); - } - - stopRentPet(); - stopWaterTask(); - } - - private void onDieDropItem(L2Character killer) - { - if (atEvent || killer == null) - return; - - if (getKarma()<=0 - && killer instanceof L2PcInstance - && ((L2PcInstance)killer).getClan()!=null - && this.getClan()!=null - && ( - ((L2PcInstance)killer).getClan().isAtWarWith(this.getClanId()) -// || this.getClan().isAtWarWith(((L2PcInstance)killer).getClanId()) - ) - ) - return; - - if (!ZoneManager.getInstance().checkIfInZonePvP(this) && (!isGM() || Config.KARMA_DROP_GM)) - { - boolean isKarmaDrop = false; - boolean isKillerNpc = (killer instanceof L2NpcInstance); - int pkLimit = Config.KARMA_PK_LIMIT;; - - int dropEquip = 0; - int dropEquipWeapon = 0; - int dropItem = 0; - int dropLimit = 0; - int dropPercent = 0; - - if (getKarma() > 0 && this.getPkKills() >= pkLimit) - { - isKarmaDrop = true; - dropPercent = Config.KARMA_RATE_DROP; - dropEquip = Config.KARMA_RATE_DROP_EQUIP; - dropEquipWeapon = Config.KARMA_RATE_DROP_EQUIP_WEAPON; - dropItem = Config.KARMA_RATE_DROP_ITEM; - dropLimit = Config.KARMA_DROP_LIMIT; - } - else if (isKillerNpc && getLevel() > 4 && !isFestivalParticipant()) - { - dropPercent = Config.PLAYER_RATE_DROP; - dropEquip = Config.PLAYER_RATE_DROP_EQUIP; - dropEquipWeapon = Config.PLAYER_RATE_DROP_EQUIP_WEAPON; - dropItem = Config.PLAYER_RATE_DROP_ITEM; - dropLimit = Config.PLAYER_DROP_LIMIT; - } - - if (dropPercent > 0 && Rnd.get(100) < dropPercent) - { - List nonDroppableList = new FastList(); - List nonDroppableListPet = new FastList(); - - nonDroppableList = Config.KARMA_LIST_NONDROPPABLE_ITEMS; - nonDroppableListPet = Config.KARMA_LIST_NONDROPPABLE_ITEMS; - - int dropCount = 0; - for (L2ItemInstance itemDrop : getInventory().getItems()) - { - // Don't drop - if ( - itemDrop.getItemId() == 57 || // Adena - itemDrop.getItem().getType2() == L2Item.TYPE2_QUEST || // Quest Items - nonDroppableList.contains(itemDrop.getItemId()) || // Item listed in the non droppable item list - nonDroppableListPet.contains(itemDrop.getItemId()) || // Item listed in the non droppable pet item list - getPet() != null && getPet().getControlItemId() == itemDrop.getItemId() // Control Item of active pet - ) continue; - - if (itemDrop.isEquipped()) - { - // Set proper chance according to Item type of equipped Item - dropPercent = itemDrop.getItem().getType2() == L2Item.TYPE2_WEAPON ? dropEquipWeapon : dropEquip; - getInventory().unEquipItemInSlotAndRecord(itemDrop.getEquipSlot()); - } - else dropPercent = dropItem; // Item in inventory - - // NOTE: Each time an item is dropped, the chance of another item being dropped gets lesser (dropCount * 2) - if (Rnd.get(100) < dropPercent - (dropCount * 2)) - { - dropItem("DieDrop", itemDrop, killer, true); - - if (isKarmaDrop) - _log.warning(getName() + " has karma and dropped id = " + itemDrop.getItemId() + ", count = " + itemDrop.getCount()); - else - _log.warning(getName() + " dropped id = " + itemDrop.getItemId() + ", count = " + itemDrop.getCount()); - - dropCount++; - if (dropCount >= dropLimit) break; - } - } - } - } - } - - private void onDieUpdateKarma() - { - // Karma lose for server that does not allow delevel - if ( getKarma() > 0 ) - { - // this formula seems to work relatively well: - // baseKarma * thisLVL * (thisLVL/100) - // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti - double karmaLost = Config.KARMA_LOST_BASE; - karmaLost *= getLevel(); // multiply by char lvl - karmaLost *= (getLevel() / 100); // divide by 0.charLVL - karmaLost = Math.round(karmaLost); - if ( karmaLost < 0 ) karmaLost = 1; - - // Decrease Karma of the L2PcInstance and Send it a Server->Client StatusUpdate packet with Karma and PvP Flag if necessary - setKarma(getKarma() - (int)karmaLost); - } - } - - public void onKillUpdatePvPKarma(L2Character target) - { - if (target == null) return; - if (!(target instanceof L2PlayableInstance)) return; - - L2PcInstance targetPlayer = null; - if (target instanceof L2PcInstance) - targetPlayer = (L2PcInstance)target; - else if (target instanceof L2Summon) - targetPlayer = ((L2Summon)target).getOwner(); - - if (targetPlayer == null) return; // Target player is null - if (targetPlayer == this) return; // Target player is self - - // If in Arena, do nothing - if (ArenaManager.getInstance().getArenaIndex(this.getX(),this.getY())!=-1 || - ArenaManager.getInstance().getArenaIndex(target.getX(),target.getY())!=-1) - return; - - // Check if it's pvp - if ( - ( - checkIfPvP(target) && // Can pvp and - targetPlayer.getPvpFlag() != 0 // Target player has pvp flag set - ) || // or - ( - ZoneManager.getInstance().checkIfInZonePvP(this) && // Player is inside pvp zone and - ZoneManager.getInstance().checkIfInZonePvP(target) // Target player is inside pvp zone - ) - ) - { - increasePvpKills(); - } - else // Target player doesn't have pvp flag set - { - // check about wars - if (targetPlayer.getClan() != null && this.getClan() != null) - { - if (this.getClan().isAtWarWith(targetPlayer.getClanId())) - { - if (targetPlayer.getClan().isAtWarWith(this.getClanId())) - { - // both way war - // Add a pvp kill - increasePvpKills(); - return; - } else - { - // one way war - increasePkKillsAndKarma(targetPlayer.getLevel()); - return; - } - } else - { - if (targetPlayer.getClan().isAtWarWith(this.getClanId())) - { - // one way war - increasePkKillsAndKarma(targetPlayer.getLevel()); - return; - } - } - } - - // not in war, normal PK - if (targetPlayer.getKarma() > 0) // Target player has karma - { - if ( Config.KARMA_AWARD_PK_KILL ) - { - increasePvpKills(); - } - } - else // Target player doesn't have karma - { - increasePkKillsAndKarma(targetPlayer.getLevel()); - } - } - } - - /** - * Increase the pvp kills count and send the info to the player - * - */ - public void increasePvpKills() - { - // Add karma to attacker and increase its PK counter - setPvpKills(getPvpKills() + 1); - - // Send a Server->Client UserInfo packet to attacker with its Karma and PK Counter - sendPacket(new UserInfo(this)); - } - - /** - * Increase pk count, karma and send the info to the player - * - * @param targLVL : level of the killed player - */ - public void increasePkKillsAndKarma(int targLVL) - { - int baseKarma = Config.KARMA_MIN_KARMA; - int newKarma = baseKarma; - int karmaLimit = Config.KARMA_MAX_KARMA; - - int pkLVL = getLevel(); - int pkPKCount = getPkKills(); - - int lvlDiffMulti = 0; - int pkCountMulti = 0; - - // Check if the attacker has a PK counter greater than 0 - if ( pkPKCount > 0 ) - pkCountMulti = pkPKCount / 2; - else - pkCountMulti = 1; - if ( pkCountMulti < 1 ) pkCountMulti = 1; - - // Calculate the level difference Multiplier between attacker and killed L2PcInstance - if ( pkLVL > targLVL ) - lvlDiffMulti = pkLVL / targLVL; - else - lvlDiffMulti = 1; - if ( lvlDiffMulti < 1 ) lvlDiffMulti = 1; - - // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti - newKarma *= pkCountMulti; - newKarma *= lvlDiffMulti; - - // Make sure newKarma is less than karmaLimit and higher than baseKarma - if ( newKarma < baseKarma ) newKarma = baseKarma; - if ( newKarma > karmaLimit ) newKarma = karmaLimit; - - // Fix to prevent overflow (=> karma has a max value of 2 147 483 647) - if (getKarma() > (Integer.MAX_VALUE - newKarma)) - newKarma = Integer.MAX_VALUE - getKarma(); - - // Add karma to attacker and increase its PK counter - setPkKills(getPkKills() + 1); - setKarma(getKarma() + newKarma); - - // Send a Server->Client UserInfo packet to attacker with its Karma and PK Counter - sendPacket(new UserInfo(this)); - } - - public int calculateKarmaLost(int exp) - { - // KARMA LOSS - // When a PKer gets killed by another player or a L2MonsterInstance, it loses a certain amount of Karma based on their level. - // this (with defaults) results in a level 1 losing about ~2 karma per death, and a lvl 70 loses about 11760 karma per death... - // You lose karma as long as you were not in a pvp zone and you did not kill urself. - // NOTE: exp for death (if delevel is allowed) is based on the players level - - int karmaLost = Math.abs(exp); - karmaLost /= Config.KARMA_XP_DIVIDER; - - if (karmaLost < Config.KARMA_LOST_BASE) karmaLost = Config.KARMA_LOST_BASE; - if (karmaLost > getKarma()) karmaLost = getKarma(); - - return karmaLost; - } - - public void updatePvPStatus() - { - if (getPvpFlag() == 0) startPvPFlag(); - if (getPvpFlag() != 0) setlastPvpAttack (System.currentTimeMillis()); //update last pvp ATTACK controller - } - - public void updatePvPStatus(L2Character target) - { - if ( - checkIfPvP(target) && - ( - !ZoneManager.getInstance().checkIfInZonePvP(this) || // Player is not inside pvp zone or - !ZoneManager.getInstance().checkIfInZonePvP(target) // Target player is not inside pvp zone - ) - ) updatePvPStatus(); - } - - /** - * Restore the specified % of experience this L2PcInstance has - * lost and sends a Server->Client StatusUpdate packet.

    - */ - public void restoreExp(double restorePercent) - { - if (_expBeforeDeath > 0) - { - // Restore the specified % of lost experience. - getStat().addExp((int)Math.round((_expBeforeDeath - getExp()) * restorePercent / 100)); - _expBeforeDeath = 0; - } - } - - /** - * Reduce the Experience (and level if necessary) of the L2PcInstance in function of the calculated Death Penalty.

    - * - * Actions :

    - *
  • Calculate the Experience loss
  • - *
  • Set the value of _expBeforeDeath
  • - *
  • Set the new Experience value of the L2PcInstance and Decrease its level if necessary
  • - *
  • Send a Server->Client StatusUpdate packet with its new Experience


  • - * - */ - public void deathPenalty(boolean atwar) - { - // TODO Need Correct Penalty - // Get the level of the L2PcInstance - final int lvl = getLevel(); - - //The death steal you some Exp - double percentLost = -0.07 * lvl + 6.5; - - if (getKarma() > 0) - percentLost *= Config.RATE_KARMA_EXP_LOST; - - if (isFestivalParticipant() || atwar || SiegeManager.getInstance().checkIfInZone(this)) - percentLost /= 4.0; - - // Calculate the Experience loss - int lostExp = (int) Math.round((getStat().getExpForLevel(lvl+1) - getStat().getExpForLevel(lvl)) * percentLost /100); - - if (atEvent) - lostExp = 0; - - // Get the Experience before applying penalty - _expBeforeDeath = getExp(); - - if (Config.DEBUG) - _log.fine(getName() + " died and lost " + lostExp + " experience."); - - // Set the new Experience value of the L2PcInstance - getStat().addExp(-lostExp); - } - - /** - * @param b - */ - public void setPartyMatchingAutomaticRegistration(boolean b) - { - _partyMatchingAutomaticRegistration = b; - } - - /** - * @param b - */ - public void setPartyMatchingShowLevel(boolean b) - { - _partyMatchingShowLevel = b; - } - - /** - * @param b - */ - public void setPartyMatchingShowClass(boolean b) - { - _partyMatchingShowClass = b; - } - - /** - * @param memo - */ - public void setPartyMatchingMemo(String memo) - { - _partyMatchingMemo = memo; - } - - public boolean isPartyMatchingAutomaticRegistration() - { - return _partyMatchingAutomaticRegistration; - } - - public String getPartyMatchingMemo() - { - return _partyMatchingMemo; - } - - public boolean isPartyMatchingShowClass() - { - return _partyMatchingShowClass; - } - - public boolean isPartyMatchingShowLevel() - { - return _partyMatchingShowLevel; - } - - /** - * Manage the increase level task of a L2PcInstance (Max MP, Max MP, Recommandation, Expertise and beginner skills...).

    - * - * Actions :

    - *
  • Send a Server->Client System Message to the L2PcInstance : YOU_INCREASED_YOUR_LEVEL
  • - *
  • Send a Server->Client packet StatusUpdate to the L2PcInstance with new LEVEL, MAX_HP and MAX_MP
  • - *
  • Set the current HP and MP of the L2PcInstance, Launch/Stop a HP/MP/CP Regeneration Task and send StatusUpdate packet to all other L2PcInstance to inform (exclusive broadcast)
  • - *
  • Recalculate the party level
  • - *
  • Recalculate the number of Recommandation that the L2PcInstance can give
  • - *
  • Give Expertise skill of this level and remove beginner Lucky skill


  • - * - */ - public void increaseLevel() - { - // Set the current HP and MP of the L2Character, Launch/Stop a HP/MP/CP Regeneration Task and send StatusUpdate packet to all other L2PcInstance to inform (exclusive broadcast) - setCurrentHpMp(getMaxHp(),getMaxMp()); - setCurrentCp(getMaxCp()); - } - - /** - * Stop the HP/MP/CP Regeneration task.

    - * - * Actions :

    - *
  • Set the RegenActive flag to False
  • - *
  • Stop the HP/MP/CP Regeneration task


  • - * - */ - public void stopAllTimers() - { - stopHpMpRegeneration(); - stopWarnUserTakeBreak(); - stopWaterTask(); - stopRentPet(); - stopJailTask(); - } - - /** - * Return the L2Summon of the L2PcInstance or null.

    - */ - public L2Summon getPet() - { - return _summon; - } - - /** - * Set the L2Summon of the L2PcInstance.

    - */ - public void setPet(L2Summon summon) - { - _summon = summon; - } - - /** - * Set the L2PcInstance requester of a transaction (ex : FriendInvite, JoinAlly, JoinParty...).

    - */ - public synchronized void setActiveRequester(L2PcInstance requester) - { - _activeRequester = requester; - } - - /** - * Return the L2PcInstance requester of a transaction (ex : FriendInvite, JoinAlly, JoinParty...).

    - */ - public L2PcInstance getActiveRequester() - { - return _activeRequester; - } - - /** - * Return True if a transaction is in progress.

    - */ - public boolean isProcessingRequest() - { - return _activeRequester != null || _requestExpireTime > GameTimeController.getGameTicks(); - } - - /** - * Return True if a transaction is in progress.

    - */ - public boolean isProcessingTransaction() { return _activeRequester != null || _activeTradeList != null || _requestExpireTime > GameTimeController.getGameTicks(); } - - /** - * Select the Warehouse to be used in next activity.

    - */ - public void onTransactionRequest(L2PcInstance partner) - { - _requestExpireTime = GameTimeController.getGameTicks() + REQUEST_TIMEOUT * GameTimeController.TICKS_PER_SECOND; - partner.setActiveRequester(this); - } - - /** - * Select the Warehouse to be used in next activity.

    - */ - public void onTransactionResponse() - { - _requestExpireTime = 0; - } - - /** - * Select the Warehouse to be used in next activity.

    - */ - public void setActiveWarehouse(ItemContainer warehouse) - { - _activeWarehouse = warehouse; - } - - /** - * Return active Warehouse.

    - */ - public ItemContainer getActiveWarehouse() - { - return _activeWarehouse; - } - - /** - * Select the TradeList to be used in next activity.

    - */ - public void setActiveTradeList(TradeList tradeList) - { - _activeTradeList = tradeList; - } - - /** - * Return active TradeList.

    - */ - public TradeList getActiveTradeList() - { - return _activeTradeList; - } - - public void onTradeStart(L2PcInstance partner) - { - _activeTradeList = new TradeList(this); - _activeTradeList.setPartner(partner); - - SystemMessage msg = new SystemMessage(SystemMessage.BEGIN_TRADE_WITH_S1); - msg.addString(partner.getName()); - sendPacket(msg); - sendPacket(new TradeStart(this)); - } - - public void onTradeConfirm(L2PcInstance partner) - { - SystemMessage msg = new SystemMessage(SystemMessage.S1_CONFIRMED_TRADE); - msg.addString(partner.getName()); - sendPacket(msg); - } - - public void onTradeCancel(L2PcInstance partner) - { - if (_activeTradeList == null) - return; - - _activeTradeList.Lock(); - _activeTradeList = null; - - sendPacket(new SendTradeDone(0)); - SystemMessage msg = new SystemMessage(SystemMessage.S1_CANCELED_TRADE); - msg.addString(partner.getName()); - sendPacket(msg); - } - - public void onTradeFinish(boolean successfull) - { - _activeTradeList = null; - sendPacket(new SendTradeDone(1)); - if (successfull) - sendPacket(new SystemMessage(SystemMessage.TRADE_SUCCESSFUL)); - } - - public void startTrade(L2PcInstance partner) - { - this.onTradeStart(partner); - partner.onTradeStart(this); - } - - public void cancelActiveTrade() - { - if (_activeTradeList == null) - return; - - L2PcInstance partner = _activeTradeList.getPartner(); - if (partner != null) partner.onTradeCancel(this); - onTradeCancel(this); - } - - /** - * Return the _createList object of the L2PcInstance.

    - */ - public L2ManufactureList getCreateList() - { - return _createList; - } - - /** - * Set the _createList object of the L2PcInstance.

    - */ - public void setCreateList(L2ManufactureList x) - { - _createList = x; - } - - /** - * Return the _buyList object of the L2PcInstance.

    - */ - public TradeList getSellList() - { - if (_sellList == null) _sellList = new TradeList(this); - return _sellList; - } - - /** - * Return the _buyList object of the L2PcInstance.

    - */ - public TradeList getBuyList() - { - if (_buyList == null) _buyList = new TradeList(this); - return _buyList; - } - - /** - * Set the Private Store type of the L2PcInstance.

    - * - * Values :

    - *
  • 0 : STORE_PRIVATE_NONE
  • - *
  • 1 : STORE_PRIVATE_SELL
  • - *
  • 2 : sellmanage

  • - *
  • 3 : STORE_PRIVATE_BUY

  • - *
  • 4 : buymanage

  • - *
  • 5 : STORE_PRIVATE_MANUFACTURE

  • - * - */ - public void setPrivateStoreType(int type) - { - _privatestore = type; - } - - /** - * Return the Private Store type of the L2PcInstance.

    - * - * Values :

    - *
  • 0 : STORE_PRIVATE_NONE
  • - *
  • 1 : STORE_PRIVATE_SELL
  • - *
  • 2 : sellmanage

  • - *
  • 3 : STORE_PRIVATE_BUY

  • - *
  • 4 : buymanage

  • - *
  • 5 : STORE_PRIVATE_MANUFACTURE

  • - * - */ - public int getPrivateStoreType() - { - return _privatestore; - } - - /** - * Set the _skillLearningClassId object of the L2PcInstance.

    - */ - public void setSkillLearningClassId(ClassId classId) - { - _skillLearningClassId = classId; - } - - /** - * Return the _skillLearningClassId object of the L2PcInstance.

    - */ - public ClassId getSkillLearningClassId() - { - return _skillLearningClassId; - } - - /** - * Set the _clan object, _clanId, _clanLeader Flag and title of the L2PcInstance.

    - */ - public void setClan(L2Clan clan) - { - _clan = clan; - - if (clan == null) - { - _clanId = 0; - _clanLeader = false; - _clanPrivileges = 0; - return; - } - - if (!clan.isMember(getName())) - { - // char has been kicked from clan - setClan(null); - setTitle(""); - return; - } - - _clanId = clan.getClanId(); - _clanLeader = getObjectId() == clan.getLeaderId(); - setTitle(""); - } - - /** - * Return the _clan object of the L2PcInstance.

    - */ - public L2Clan getClan() - { - return _clan; - } - - /** - * Return True if the L2PcInstance is the leader of its clan.

    - */ - public boolean isClanLeader() - { - return _clanLeader; - } - - /** - * Reduce the number of arrows owned by the L2PcInstance and send it Server->Client Packet InventoryUpdate or ItemList (to unequip if the last arrow was consummed).

    - */ - protected void reduceArrowCount() - { - L2ItemInstance arrows = getInventory().destroyItem("Consume", getInventory().getPaperdollObjectId(Inventory.PAPERDOLL_LHAND), 1, this, null); - - if (Config.DEBUG) _log.fine("arrow count:" + (arrows==null? 0 : arrows.getCount())); - - if (arrows == null || arrows.getCount() == 0) - { - getInventory().unEquipItemInSlot(Inventory.PAPERDOLL_LHAND); - _arrowItem = null; - - if (Config.DEBUG) _log.fine("removed arrows count"); - sendPacket(new ItemList(this,false)); - } - else - { - if (!Config.FORCE_INVENTORY_UPDATE) - { - InventoryUpdate iu = new InventoryUpdate(); - iu.addModifiedItem(arrows); - sendPacket(iu); - } - else sendPacket(new ItemList(this, false)); - } - } - - /** - * Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2PcINstance then return True.

    - */ - protected boolean checkAndEquipArrows() - { - // Check if nothing is equiped in left hand - if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null) - { - // Get the L2ItemInstance of the arrows needed for this bow - _arrowItem = getInventory().findArrowForBow(getActiveWeaponItem()); - - if (_arrowItem != null) - { - // Equip arrows needed in left hand - getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, _arrowItem); - - // Send a Server->Client packet ItemList to this L2PcINstance to update left hand equipement - ItemList il = new ItemList(this, false); - sendPacket(il); - } - } - else - { - // Get the L2ItemInstance of arrows equiped in left hand - _arrowItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); - } - - return _arrowItem != null; - } - - - /** - * Return True if the L2PcInstance use a dual weapon.

    - */ - public boolean isUsingDualWeapon() - { - L2Weapon weaponItem = getActiveWeaponItem(); - - if (weaponItem.getItemType() == L2WeaponType.DUAL) - return true; - else if (weaponItem.getItemType() == L2WeaponType.DUALFIST) - return true; - else if (weaponItem.getItemId() == 248) // orc fighter fists - return true; - else if (weaponItem.getItemId() == 252) // orc mage fists - return true; - else - return false; - } - - public void setUptime(long time) - { - _uptime = time; - } - - public long getUptime() - { - return System.currentTimeMillis()-_uptime; - } - - /** - * Set the invulnerability Flag of the L2PcInstance.

    - */ - public void setIsInvul(boolean b) - { - _isInvul = b; - } - - /** - * Return True if the L2PcInstance is invulnerable.

    - */ - public boolean isInvul() - { - return _isInvul || isTeleporting() || _protectEndTime > GameTimeController.getGameTicks(); - } - - /** - * Return True if the L2PcInstance has a Party in progress.

    - */ - public boolean isInParty() - { - return _party != null; - } - - /** - * Set the _party object of the L2PcInstance (without joining it).

    - */ - public void setParty(L2Party party) - { - _party = party; - } - - /** - * Set the _party object of the L2PcInstance AND join it.

    - */ - public void joinParty(L2Party party) - { - if (party != null) - { - // First set the party otherwise this wouldn't be considered - // as in a party into the L2Character.updateEffectIcons() call. - _party = party; - party.addPartyMember(this); - } - } - - - /** - * Manage the Leave Party task of the L2PcInstance.

    - */ - public void leaveParty() - { - if (isInParty()) - { - _party.removePartyMember(this); - _party = null; - } - } - - /** - * Return the _party object of the L2PcInstance.

    - */ - public L2Party getParty() - { - return _party; - } - - /** - * Set the _isGm Flag of the L2PcInstance.

    - */ - public void setIsGM(boolean status) - { - _isGm = status; - } - - /** - * Return True if the L2PcInstance is a GM.

    - */ - public boolean isGM() - { - return _isGm; - } - - /** - * Manage a cancel cast task for the L2PcInstance.

    - * - * Actions :

    - *
  • Set the Intention of the AI to AI_INTENTION_IDLE
  • - *
  • Enable all skills (set _allSkillsDisabled to False)
  • - *
  • Send a Server->Client Packet MagicSkillCanceld to the L2PcInstance and all L2PcInstance in the _KnownPlayers of the L2Character (broadcast)


  • - * - */ - public void cancelCastMagic() - { - // Set the Intention of the AI to AI_INTENTION_IDLE - getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); - - // Enable all skills (set _allSkillsDisabled to False) - enableAllSkills(); - - // Send a Server->Client Packet MagicSkillCanceld to the L2PcInstance and all L2PcInstance in the _KnownPlayers of the L2Character (broadcast) - MagicSkillCanceld msc = new MagicSkillCanceld(getObjectId()); - - // Broadcast the packet to self and known players. - Broadcast.toSelfAndKnownPlayersInRadius(this, msc, 810000/*900*/); - } - - /** - * Set the _accessLevel of the L2PcInstance.

    - */ - public void setAccessLevel(int level) - { - _accessLevel = level; - - if (_accessLevel > 0 || Config.EVERYBODY_HAS_ADMIN_RIGHTS) - setIsGM(true); - } - - public void setAccountAccesslevel(int level) - { - if (_connection != null) - LoginServerThread.getInstance().sendAccessLevel(getAccountName(),level); - else - _log.info("Couldnt set the player's account access level"); - } - - /** - * Return the _accessLevel of the L2PcInstance.

    - */ - public int getAccessLevel() - { - if (Config.EVERYBODY_HAS_ADMIN_RIGHTS && _accessLevel <= 200) - return 200; - - return _accessLevel; - } - - public double getLevelMod() - { - return (100.0 - 11 + getLevel()) / 100.0; - } - - /** - * Update Stats of the L2PcInstance client side by sending Server->Client packet UserInfo/StatusUpdate to this L2PcInstance and CharInfo/StatusUpdate to all L2PcInstance in its _KnownPlayers (broadcast).

    - */ - public void updateStats() - { - super.updateStats(); - refreshOverloaded(); - refreshExpertisePenalty(); - // Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers (broadcast) - broadcastUserInfo(); - - // Send a Server->Client StatusUpdate packet with Karma to the L2PcInstance and to all L2PcInstance in its _KnownPlayers (broadcast) - updateKarma(); - } - - /** - * Send a Server->Client StatusUpdate packet with Karma and PvP Flag to the L2PcInstance and all L2PcInstance to inform (broadcast).

    - */ - public void setKarmaFlag(int flag) - { - // Send a Server->Client StatusUpdate packet with Karma and PvP Flag to the L2PcInstance and all L2PcInstance to inform (broadcast) - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.KARMA, getKarma()); - su.addAttribute(StatusUpdate.PVP_FLAG, flag); - sendPacket(su); - broadcastPacket(su); - } - - /** - * Send a Server->Client StatusUpdate packet with Karma to the L2PcInstance and all L2PcInstance to inform (broadcast).

    - */ - public void updateKarma() - { - // Send a Server->Client StatusUpdate packet with Karma to the L2PcInstance - StatusUpdate su = new StatusUpdate(getObjectId()); - su.addAttribute(StatusUpdate.KARMA, getKarma()); - sendPacket(su); - broadcastPacket(su); - } - - /** - * Set the online Flag to True or False and update the characters table of the database with online status and lastAccess (called when login and logout).

    - */ - public void setOnlineStatus(boolean isOnline) - { - if (_isOnline != isOnline) - _isOnline = isOnline; - - // Update the characters table of the database with online status and lastAccess (called when login and logout) - updateOnlineStatus(); - } - - public void setIsIn7sDungeon(boolean isIn7sDungeon) - { - if (_isIn7sDungeon != isIn7sDungeon) - _isIn7sDungeon = isIn7sDungeon; - - updateIsIn7sDungeonStatus(); - } - - /** - * Update the characters table of the database with online status and lastAccess of this L2PcInstance (called when login and logout).

    - */ - public void updateOnlineStatus() - { - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement("UPDATE characters SET online=?, lastAccess=? WHERE obj_id=?"); - statement.setInt(1, isOnline()); - statement.setLong(2, System.currentTimeMillis()); - statement.setInt(3, getObjectId()); - statement.execute(); - statement.close(); - } - catch (Exception e) - { - _log.warning("could not set char online status:"+e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - } - - public void updateIsIn7sDungeonStatus() - { - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement("UPDATE characters SET isIn7sDungeon=?, lastAccess=? WHERE obj_id=?"); - statement.setInt(1, isIn7sDungeon() ? 1 : 0); - statement.setLong(2, System.currentTimeMillis()); - statement.setInt(3, getObjectId()); - statement.execute(); - statement.close(); - } - catch (Exception e) - { - _log.warning("could not set char isIn7sDungeon status:"+e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - } - - /** - * Create a new player in the characters table of the database.

    - */ - private boolean createDb() - { - java.sql.Connection con = null; - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - statement = con.prepareStatement( - "INSERT INTO characters " + - "(account_name,obj_Id,char_name,level,maxHp,curHp,maxCp,curCp,maxMp,curMp," + - "acc,crit,evasion,mAtk,mDef,mSpd,pAtk,pDef,pSpd,runSpd,walkSpd," + - "str,con,dex,_int,men,wit,face,hairStyle,hairColor,sex," + - "movement_multiplier,attack_speed_multiplier,colRad,colHeight," + - "exp,sp,karma,pvpkills,pkkills,clanid,maxload,race,classid,deletetime," + - "cancraft,title,allyId,accesslevel,online,isin7sdungeon,clan_privs,wantspeace,deleteclan," + - "base_class,newbie) " + - "values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); - statement.setString(1, _accountName); - statement.setInt(2, getObjectId()); - statement.setString(3, getName()); - statement.setInt(4, getLevel()); - statement.setInt(5, getMaxHp()); - statement.setDouble(6, getCurrentHp()); - statement.setInt(7, getMaxCp()); - statement.setDouble(8, getCurrentCp()); - statement.setInt(9, getMaxMp()); - statement.setDouble(10, getCurrentMp()); - statement.setInt(11, getAccuracy()); - statement.setInt(12, getCriticalHit(null, null)); - statement.setInt(13, getEvasionRate(null)); - statement.setInt(14, getMAtk(null, null)); - statement.setInt(15, getMDef(null, null)); - statement.setInt(16, getMAtkSpd()); - statement.setInt(17, getPAtk(null)); - statement.setInt(18, getPDef(null)); - statement.setInt(19, getPAtkSpd()); - statement.setInt(20, getRunSpeed()); - statement.setInt(21, getWalkSpeed()); - statement.setInt(22, getSTR()); - statement.setInt(23, getCON()); - statement.setInt(24, getDEX()); - statement.setInt(25, getINT()); - statement.setInt(26, getMEN()); - statement.setInt(27, getWIT()); - statement.setInt(28, getFace()); - statement.setInt(29, getHairStyle()); - statement.setInt(30, getHairColor()); - statement.setInt(31, getSex()); - statement.setDouble(32, 1/*getMovementMultiplier()*/); - statement.setDouble(33, 1/*getAttackSpeedMultiplier()*/); - statement.setDouble(34, getTemplate().collisionRadius/*getCollisionRadius()*/); - statement.setDouble(35, getTemplate().collisionHeight/*getCollisionHeight()*/); - statement.setInt(36, getExp()); - statement.setInt(37, getSp()); - statement.setInt(38, getKarma()); - statement.setInt(39, getPvpKills()); - statement.setInt(40, getPkKills()); - statement.setInt(41, getClanId()); - statement.setInt(42, getMaxLoad()); - statement.setInt(43, getRace().ordinal()); - statement.setInt(44, getClassId().getId()); - statement.setInt(45, getDeleteTimer()); - statement.setInt(46, hasDwarvenCraft() ? 1 : 0); - statement.setString(47, getTitle()); - statement.setInt(48, getAllyId()); - statement.setInt(49, getAccessLevel()); - statement.setInt(50, isOnline()); - statement.setInt(51, isIn7sDungeon() ? 1 : 0); - statement.setInt(52, getClanPrivileges()); - statement.setInt(53, getWantsPeace()); - statement.setLong(54, getDeleteClanTime()); - statement.setInt(55, getBaseClass()); - statement.setInt(56, isNewbie() ? 1 : 0); - statement.executeUpdate(); - statement.close(); - } - catch (Exception e) - { - _log.warning("Could not insert char data: " + e); - return false; - } - finally - { - try { con.close(); } catch (Exception e) {} - } - return true; - } - - /** - * Retrieve a L2PcInstance from the characters table of the database and add it in _allObjects of the L2world.

    - * - * Actions :

    - *
  • Retrieve the L2PcInstance from the characters table of the database
  • - *
  • Add the L2PcInstance object in _allObjects
  • - *
  • Set the x,y,z position of the L2PcInstance and make it invisible
  • - *
  • Update the overloaded status of the L2PcInstance


  • - * - * @param objectId Identifier of the object to initialized - * - * @return The L2PcInstance loaded from the database - * - */ - private static L2PcInstance restore(int objectId) - { - L2PcInstance player = null; - java.sql.Connection con = null; - - try - { - // Retrieve the L2PcInstance from the characters table of the database - con = L2DatabaseFactory.getInstance().getConnection(); - - PreparedStatement statement = con.prepareStatement(RESTORE_CHARACTER); - statement.setInt(1, objectId); - ResultSet rset = statement.executeQuery(); - - double currentCp = 0; - double currentHp = 0; - double currentMp = 0; - - while (rset.next()) - { - final int activeClassId = rset.getInt("classid"); - final boolean female = rset.getInt("sex")!=0; - final L2PcTemplate template = CharTemplateTable.getInstance().getTemplate(activeClassId, female); - - player = new L2PcInstance(objectId, template, rset.getString("account_name")); - player.setName(rset.getString("char_name")); - player._lastAccess = rset.getLong("lastAccess"); - - player._activeClass = activeClassId; - try { player.setBaseClass(rset.getInt("base_class")); } - catch (Exception e) { player.setBaseClass(activeClassId); } - - player._classIndex = 0; - player.getStat().setExp(rset.getInt("exp")); - player.getStat().setLevel(rset.getInt("level")); - player.getStat().setSp(rset.getInt("sp")); - - player.setFace(rset.getInt("face")); - player.setHairStyle(rset.getInt("hairStyle")); - player.setHairColor(rset.getInt("hairColor")); - player.setClanPrivileges(rset.getInt("clan_privs")); - player.setWantsPeace(rset.getInt("wantspeace")); - - player.setHeading(rset.getInt("heading")); - - player.setKarma(rset.getInt("karma")); - player.setPvpKills(rset.getInt("pvpkills")); - player.setPkKills(rset.getInt("pkkills")); - player.setDeleteClanTime(rset.getLong("deleteclan")); - player.setOnlineTime(rset.getLong("onlinetime")); - player.setNewbie(rset.getInt("newbie")==1); - - if (player.getDeleteClanTime() > 0 && player.canCreateClan()) - player.setDeleteClanTime(0); - - int clanId = rset.getInt("clanid"); - - if (clanId > 0) - player.setClan(ClanTable.getInstance().getClan(clanId)); - - player.setDeleteTimer(rset.getInt("deletetime")); - - player.setTitle(rset.getString("title")); - player.setAccessLevel(rset.getInt("accesslevel")); - player.setFistsWeaponItem(player.findFistsWeaponItem(activeClassId)); - player.setUptime(System.currentTimeMillis()); - - currentHp = rset.getDouble("curHp"); - player.setCurrentHp(rset.getDouble("curHp")); - currentCp = rset.getDouble("curCp"); - player.setCurrentCp(rset.getDouble("curCp")); - currentMp = rset.getDouble("curMp"); - player.setCurrentMp(rset.getDouble("curMp")); - - //Check recs - player.checkRecom(rset.getInt("rec_have"),rset.getInt("rec_left")); - - // Restore Subclass Data - if (restoreSubClassData(player)) - { - if (player.getActiveClass() != player.getBaseClass()) - { - for (SubClass subClass : player.getSubClasses().values()) - if (subClass.getClassId() == player.getActiveClass()) - player._classIndex = subClass.getClassIndex(); - } - } - - player.setIsIn7sDungeon((rset.getInt("isin7sdungeon")==1)? true : false); - player.setInJail((rset.getInt("in_jail")==1)? true : false); - player.setJailTimer(rset.getLong("jail_timer")); - - // Add the L2PcInstance object in _allObjects - //L2World.getInstance().storeObject(player); - - // Set the x,y,z position of the L2PcInstance and make it invisible - player.setXYZInvisible(rset.getInt("x"), rset.getInt("y"), rset.getInt("z")); - - // Retrieve the name and ID of the other characters assigned to this account. - PreparedStatement stmt = con.prepareStatement("SELECT obj_Id, char_name FROM characters WHERE account_name=? AND obj_Id<>?"); - stmt.setString(1, player._accountName); - stmt.setInt(2, objectId); - ResultSet chars = stmt.executeQuery(); - - while (chars.next()) - { - Integer charId = chars.getInt("obj_Id"); - String charName = chars.getString("char_name"); - player._chars.put(charId, charName); - } - - break; - } - - rset.close(); - statement.close(); - - // Retrieve from the database all secondary data of this L2PcInstance - // and reward expertise/lucky skills if necessary. - player.restoreCharData(); - player.rewardSkills(); - - // Restore current Cp, HP and MP values - player.setCurrentCp(currentCp); - player.setCurrentHp(currentHp); - player.setCurrentMp(currentMp); - - // Update the overloaded status of the L2PcInstance - player.refreshOverloaded(); - } - catch (Exception e) - { - _log.warning("Could not restore char data: " + e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - - return player; - } - - /** - * @return - */ - public Forum getMail() - { - if (_forumMail == null) - { - setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").GetChildByName(getName())); - - if (_forumMail == null) - { - ForumsBBSManager.getInstance().CreateNewForum(getName(),ForumsBBSManager.getInstance().getForumByName("MailRoot"),Forum.MAIL,Forum.OWNERONLY,getObjectId()); - setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").GetChildByName(getName())); - } - } - - return _forumMail; - } - - /** - * @param forum - */ - public void setMail(Forum forum) - { - _forumMail = forum; - } - - /** - * @return - */ - public Forum getMemo() - { - if (_forumMemo == null) - { - setMemo(ForumsBBSManager.getInstance().getForumByName("MemoRoot").GetChildByName(_accountName)); - - if (_forumMemo == null) - { - ForumsBBSManager.getInstance().CreateNewForum(_accountName,ForumsBBSManager.getInstance().getForumByName("MemoRoot"),Forum.MEMO,Forum.OWNERONLY,getObjectId()); - setMemo(ForumsBBSManager.getInstance().getForumByName("MemoRoot").GetChildByName(_accountName)); - } - } - - return _forumMemo; - } - - /** - * @param forum - */ - public void setMemo(Forum forum) - { - _forumMemo = forum; - } - - /** - * Restores sub-class data for the L2PcInstance, used to check the current - * class index for the character. - */ - private static boolean restoreSubClassData(L2PcInstance player) - { - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_SUBCLASSES); - statement.setInt(1, player.getObjectId()); - - ResultSet rset = statement.executeQuery(); - - while (rset.next()) - { - SubClass subClass = new SubClass(); - subClass.setClassId(rset.getInt("class_id")); - subClass.setLevel(rset.getInt("level")); - subClass.setExp(rset.getInt("exp")); - subClass.setSp(rset.getInt("sp")); - subClass.setClassIndex(rset.getInt("class_index")); - - // Enforce the correct indexing of _subClasses against their class indexes. - player.getSubClasses().put(subClass.getClassIndex(), subClass); - } - - statement.close(); - } - catch (Exception e) { - _log.warning("Could not restore classes for " + player.getName() + ": " + e); - e.printStackTrace(); - } - finally { - try { con.close(); } catch (Exception e) {} - } - - return true; - } - - /** - * Restores secondary data for the L2PcInstance, based on the current class index. - */ - private void restoreCharData() - { - // Retrieve from the database all skills of this L2PcInstance and add them to _skills. - restoreSkills(); - - // Retrieve from the database all macroses of this L2PcInstance and add them to _macroses. - _macroses.restore(); - - // Retrieve from the database all shortCuts of this L2PcInstance and add them to _shortCuts. - _shortCuts.restore(); - - // Retrieve from the database all henna of this L2PcInstance and add them to _henna. - restoreHenna(); - - // Retrieve from the database the recipe book of this L2PcInstance. - if (!isSubClassActive()) - restoreRecipeBook(); - } - - /** - * Store recipe book data for this L2PcInstance, if not on an active sub-class. - */ - private void storeRecipeBook() - { - // If the player is on a sub-class don't even attempt to store a recipe book. - if (isSubClassActive()) - return; - if (getCommonRecipeBook().length == 0 && getDwarvenRecipeBook().length == 0) - return; - - java.sql.Connection con = null; - - try { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement("DELETE FROM character_recipebook WHERE char_id=?"); - statement.setInt(1, getObjectId()); - statement.execute(); - statement.close(); - - L2RecipeList[] recipes = getCommonRecipeBook(); - - for (int count = 0; count < recipes.length; count++) - { - statement = con.prepareStatement("INSERT INTO character_recipebook (char_id, id, type) values(?,?,0)"); - statement.setInt(1, getObjectId()); - statement.setInt(2, recipes[count].getId()); - statement.execute(); - statement.close(); - } - - recipes = getDwarvenRecipeBook(); - for (int count = 0; count < recipes.length; count++) - { - statement = con.prepareStatement("INSERT INTO character_recipebook (char_id, id, type) values(?,?,1)"); - statement.setInt(1, getObjectId()); - statement.setInt(2, recipes[count].getId()); - statement.execute(); - statement.close(); - } - } - catch (Exception e) { - _log.warning("Could not store recipe book data: " + e); - } - finally { - try { con.close(); } catch (Exception e) {} - } - } - - /** - * Restore recipe book data for this L2PcInstance. - */ - private void restoreRecipeBook() - { - java.sql.Connection con = null; - - try { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement("SELECT id, type FROM character_recipebook WHERE char_id=?"); - statement.setInt(1, getObjectId()); - ResultSet rset = statement.executeQuery(); - - L2RecipeList recipe; - while (rset.next()) { - recipe = RecipeController.getInstance().getRecipeList(rset.getInt("id") - 1); - - if (rset.getInt("type") == 1) - registerDwarvenRecipeList(recipe); - else - registerCommonRecipeList(recipe); - } - - rset.close(); - statement.close(); - } - catch (Exception e) { - _log.warning("Could not restore recipe book data:" + e); - } - finally { - try { con.close(); } catch (Exception e) {} - } - } - - /** - * Update L2PcInstance stats in the characters table of the database.

    - */ - public void store() - { - //update client coords, if these look like true - if (isInsideRadius(getClientX(), getClientY(), 1000, true)) - setXYZ(getClientX(), getClientY(), getClientZ()); - - storeCharBase(); - storeCharSub(); - storeEffect(); - storeRecipeBook(); - } - - private void storeCharBase() - { - java.sql.Connection con = null; - - try - { - // Get the exp, level, and sp of base class to store in base table - int currentClassIndex = getClassIndex(); - _classIndex = 0; - int exp = getStat().getExp(); - int level = getStat().getLevel(); - int sp = getStat().getSp(); - _classIndex = currentClassIndex; - - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - - // Update base class - statement = con.prepareStatement(UPDATE_CHARACTER); - statement.setInt(1, level); - statement.setInt(2, getMaxHp()); - statement.setDouble(3, getCurrentHp()); - statement.setInt(4, getMaxCp()); - statement.setDouble(5, getCurrentCp()); - statement.setInt(6, getMaxMp()); - statement.setDouble(7, getCurrentMp()); - statement.setInt(8, getSTR()); - statement.setInt(9, getCON()); - statement.setInt(10, getDEX()); - statement.setInt(11, getINT()); - statement.setInt(12, getMEN()); - statement.setInt(13, getWIT()); - statement.setInt(14, getFace()); - statement.setInt(15, getHairStyle()); - statement.setInt(16, getHairColor()); - statement.setInt(17, getHeading()); - statement.setInt(18, getX()); - statement.setInt(19, getY()); - statement.setInt(20, getZ()); - statement.setInt(21, exp); - statement.setInt(22, sp); - statement.setInt(23, getKarma()); - statement.setInt(24, getPvpKills()); - statement.setInt(25, getPkKills()); - statement.setInt(26, getRecomHave()); - statement.setInt(27, getRecomLeft()); - statement.setInt(28, getClanId()); - statement.setInt(29, getMaxLoad()); - statement.setInt(30, getRace().ordinal()); - -// if (!isSubClassActive()) - -// else -// statement.setInt(30, getBaseTemplate().race.ordinal()); - - statement.setInt(31, getClassId().getId()); - statement.setInt(32, getDeleteTimer()); - statement.setString(33, getTitle()); - statement.setInt(34, getAllyId()); - statement.setInt(35, getAccessLevel()); - statement.setInt(36, isOnline()); - statement.setInt(37, isIn7sDungeon() ? 1 : 0); - statement.setInt(38, getClanPrivileges()); - statement.setInt(39, getWantsPeace()); - statement.setLong(40, getDeleteClanTime()); - statement.setInt(41, getBaseClass()); - - long totalOnlineTime = _onlineTime; - - if (_onlineBeginTime > 0) - totalOnlineTime += (System.currentTimeMillis()-_onlineBeginTime)/1000; - - statement.setLong(42, totalOnlineTime); - statement.setInt(43, isInJail() ? 1 : 0); - statement.setLong(44, getJailTimer()); - statement.setInt(45, isNewbie() ? 1 : 0); - statement.setInt(46, getObjectId()); - - statement.execute(); - statement.close(); - } - catch (Exception e) { _log.warning("Could not store char base data: "+ e); } - finally { try { con.close(); } catch (Exception e) {} } - } - - private void storeCharSub() - { - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - - if (getTotalSubClasses() > 0) - { - for (SubClass subClass : getSubClasses().values()) - { - statement = con.prepareStatement(UPDATE_CHAR_SUBCLASS); - statement.setInt(1, subClass.getExp()); - statement.setInt(2, subClass.getSp()); - statement.setInt(3, subClass.getLevel()); - statement.setInt(4, subClass.getClassId()); - statement.setInt(5, getObjectId()); - statement.setInt(6, subClass.getClassIndex()); - - statement.execute(); - statement.close(); - } - } - } - catch (Exception e) { - _log.warning("Could not store sub class data for " + getName() + ": "+ e); - } - finally { try { con.close(); } catch (Exception e) {} } - } - - private void storeEffect() - { - if (!Config.STORE_SKILL_COOLTIME) return; - - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - - // Delete all current stored effects for char to avoid dupe - statement = con.prepareStatement(DELETE_SKILL_SAVE); - statement.setInt(1, getObjectId()); - statement.setInt(2, getClassIndex()); - statement.execute(); - statement.close(); - - // Loop thru all effects for char and same them each to database - for (L2Effect effect : getAllEffects()) - { - if (effect != null && effect.getInUse() && !effect.getSkill().isToggle()) - { - statement = con.prepareStatement(ADD_SKILL_SAVE); - statement.setInt(1, getObjectId()); - statement.setInt(2, effect.getSkill().getId()); - statement.setInt(3, effect.getSkill().getLevel()); - statement.setInt(4, effect.getCount()); - statement.setInt(5, effect.getTime()); - statement.setInt(6, getClassIndex()); - statement.execute(); - statement.close(); - } - } - } - catch (Exception e) { _log.warning("Could not store char effect data: "+ e); } - finally { try { con.close(); } catch (Exception e) {} } - } - - /** - * Return True if the L2PcInstance is on line.

    - */ - public int isOnline() - { - return (_isOnline ? 1 : 0); - } - - public boolean isIn7sDungeon() - { - return _isIn7sDungeon; - } - - /** - * Add a skill to the L2PcInstance _skills and its Func objects to the calculator set of the L2PcInstance and save update in the character_skills table of the database.

    - * - * Concept :

    - * All skills own by a L2PcInstance are identified in _skills

    - * - * Actions :

    - *
  • Replace oldSkill by newSkill or Add the newSkill
  • - *
  • If an old skill has been replaced, remove all its Func objects of L2Character calculator set
  • - *
  • Add Func objects of newSkill to the calculator set of the L2Character


  • - * - * @param newSkill The L2Skill to add to the L2Character - * - * @return The L2Skill replaced or null if just added a new L2Skill - * - */ - public L2Skill addSkill(L2Skill newSkill) - { - // Add a skill to the L2PcInstance _skills and its Func objects to the calculator set of the L2PcInstance - L2Skill oldSkill = super.addSkill(newSkill); - - // Add or update a L2PcInstance skill in the character_skills table of the database - storeSkill(newSkill, oldSkill, -1); - - return oldSkill; - } - - /** - * Remove a skill from the L2Character and its Func objects from calculator set of the L2Character and save update in the character_skills table of the database.

    - * - * Concept :

    - * All skills own by a L2Character are identified in _skills

    - * - * Actions :

    - *
  • Remove the skill from the L2Character _skills
  • - *
  • Remove all its Func objects from the L2Character calculator set


  • - * - * Overriden in :

    - *
  • L2PcInstance : Save update in the character_skills table of the database


  • - * - * @param skill The L2Skill to remove from the L2Character - * - * @return The L2Skill removed - * - */ - public L2Skill removeSkill(L2Skill skill) - { - // Remove a skill from the L2Character and its Func objects from calculator set of the L2Character - L2Skill oldSkill = super.removeSkill(skill); - - java.sql.Connection con = null; - - try - { - // Remove or update a L2PcInstance skill from the character_skills table of the database - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - - if (oldSkill != null) - { - statement = con.prepareStatement(DELETE_SKILL_FROM_CHAR); - statement.setInt(1, oldSkill.getId()); - statement.setInt(2, getObjectId()); - statement.setInt(3, getClassIndex()); - statement.execute(); - statement.close(); - } - } - catch (Exception e) - { - _log.warning("Error could not delete skill: " + e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - - return oldSkill; - } - - /** - * Add or update a L2PcInstance skill in the character_skills table of the database. - *

    - * If newClassIndex > -1, the skill will be stored with that class index, not the current one. - */ - private void storeSkill(L2Skill newSkill, L2Skill oldSkill, int newClassIndex) - { - int classIndex = _classIndex; - - if (newClassIndex > -1) - classIndex = newClassIndex; - - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - - if (oldSkill != null && newSkill != null) - { - statement = con.prepareStatement(UPDATE_CHARACTER_SKILL_LEVEL); - statement.setInt(1, newSkill.getLevel()); - statement.setInt(2, oldSkill.getId()); - statement.setInt(3, getObjectId()); - statement.setInt(4, classIndex); - statement.execute(); - statement.close(); - } - else if (newSkill != null) - { - statement = con.prepareStatement(ADD_NEW_SKILL); - statement.setInt(1, getObjectId()); - statement.setInt(2, newSkill.getId()); - statement.setInt(3, newSkill.getLevel()); - statement.setString(4, newSkill.getName()); - statement.setInt(5, classIndex); - statement.execute(); - statement.close(); - } - else - { - _log.warning("could not store new skill. its NULL"); - } - } - catch (Exception e) - { - _log.warning("Error could not store char skills: " + e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - } - - /** - * Retrieve from the database all skills of this L2PcInstance and add them to _skills.

    - */ - private void restoreSkills() - { - java.sql.Connection con = null; - - try - { - // Retrieve all skills of this L2PcInstance from the database - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement(RESTORE_SKILLS_FOR_CHAR); - statement.setInt(1, getObjectId()); - statement.setInt(2, getClassIndex()); - ResultSet rset = statement.executeQuery(); - - // Go though the recordset of this SQL query - while (rset.next()) - { - int id = rset.getInt("skill_id"); - int level = rset.getInt("skill_level"); - - if (id > 9000) - continue; // fake skills for base stats - - // Create a L2Skill object for each record - L2Skill skill = SkillTable.getInstance().getInfo(id, level); - - // Add the L2Skill object to the L2Character _skills and its Func objects to the calculator set of the L2Character - super.addSkill(skill); - } - - rset.close(); - statement.close(); - } - catch (Exception e) - { - _log.warning("Could not restore character skills: " + e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - } - - /** - * HRetrieve from the database all skill effects of this L2PcInstance and add them to the player.

    - */ - public void restoreEffects() - { - L2Object[] targets = new L2Character[]{this}; - java.sql.Connection con = null; - - try { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - - statement = con.prepareStatement(RESTORE_SKILL_SAVE); - statement.setInt(1, getObjectId()); - statement.setInt(2, getClassIndex()); - - ResultSet rset = statement.executeQuery(); - - while (rset.next()) - { - int skillId = rset.getInt("skill_id"); - int skillLvl = rset.getInt("skill_level"); - int effectCount = rset.getInt("effect_count"); - int effectCurTime = rset.getInt("effect_cur_time"); - - L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl); - callSkill(skill, targets); - - for (L2Effect effect : getAllEffects()) - { - if (effect.getSkill().getId() == skillId) - { - effect.setCount(effectCount); - effect.setFirstTime(effectCurTime); - } - } - } - - statement = con.prepareStatement(DELETE_SKILL_SAVE); - statement.setInt(1, getObjectId()); - statement.setInt(2, getClassIndex()); - statement.executeUpdate(); - } - catch (Exception e) { - _log.warning("Could not restore active effect data: " + e); - } - finally { - try {con.close();} catch (Exception e) {} - } - - updateEffectIcons(); - } - - /** - * Retrieve from the database all Henna of this L2PcInstance, add them to _henna and calculate stats of the L2PcInstance.

    - */ - private void restoreHenna() - { - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_HENNAS); - statement.setInt(1, getObjectId()); - statement.setInt(2, getClassIndex()); - ResultSet rset = statement.executeQuery(); - - for (int i=0;i<3;i++) - _henna[i]=null; - - while (rset.next()) - { - int slot = rset.getInt("slot"); - - if (slot<1 || slot>3) - continue; - - int symbol_id = rset.getInt("symbol_id"); - - L2HennaInstance sym = null; - - if (symbol_id != 0) - { - L2Henna tpl = HennaTable.getInstance().getTemplate(symbol_id); - - if (tpl != null) - { - sym = new L2HennaInstance(tpl); - _henna[slot-1] = sym; - } - } - } - - rset.close(); - statement.close(); - } - catch (Exception e) - { - _log.warning("could not restore henna: "+e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - - // Calculate Henna modifiers of this L2PcInstance - recalcHennaStats(); - } - - /** - * Return the number of Henna empty slot of the L2PcInstance.

    - */ - public int getHennaEmptySlots() - { - int totalSlots = 1 + getClassId().level(); - - for (int i = 0; i < 3; i++) - if (_henna[i] != null) - totalSlots--; - - if (totalSlots <= 0) - return 0; - - return totalSlots; - } - - /** - * Remove a Henna of the L2PcInstance, save update in the character_hennas table of the database and send Server->Client HennaInfo/UserInfo packet to this L2PcInstance.

    - */ - public boolean removeHenna(int slot) - { - if (slot<1 || slot>3) - return false; - - slot--; - - if (_henna[slot]==null) - return false; - - L2HennaInstance henna = _henna[slot]; - _henna[slot] = null; - - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA); - statement.setInt(1, getObjectId()); - statement.setInt(2, slot+1); - statement.setInt(3, getClassIndex()); - statement.execute(); - statement.close(); - } - catch (Exception e) - { - _log.warning("could not remove char henna: "+e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - - // Calculate Henna modifiers of this L2PcInstance - recalcHennaStats(); - - // Send Server->Client HennaInfo packet to this L2PcInstance - sendPacket(new HennaInfo(this)); - - // Send Server->Client UserInfo packet to this L2PcInstance - sendPacket(new UserInfo(this)); - - // Add the recovered dyes to the player's inventory and notify them. - getInventory().addItem("Henna", henna.getItemIdDye(), henna.getAmountDyeRequire() / 2, this, null); - - SystemMessage sm = new SystemMessage(SystemMessage.EARNED_S2_S1_s); - sm.addItemName(henna.getItemIdDye()); - sm.addNumber(henna.getAmountDyeRequire() / 2); - sendPacket(sm); - - return true; - } - - /** - * Add a Henna to the L2PcInstance, save update in the character_hennas table of the database and send Server->Client HennaInfo/UserInfo packet to this L2PcInstance.

    - */ - public boolean addHenna(L2HennaInstance henna) - { - if (getHennaEmptySlots()==0) - { - this.sendMessage("You may not have more than three equipped symbols at a time."); - return false; - } - - // int slot = 0; - for (int i=0;i<3;i++) - { - if (_henna[i]==null) - { - _henna[i]=henna; - - // Calculate Henna modifiers of this L2PcInstance - recalcHennaStats(); - - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement(ADD_CHAR_HENNA); - statement.setInt(1, getObjectId()); - statement.setInt(2, henna.getSymbolId()); - statement.setInt(3, i+1); - statement.setInt(4, getClassIndex()); - statement.execute(); - statement.close(); - } - catch (Exception e) - { - _log.warning("could not save char henna: "+e); - } - finally - { - try { con.close(); } catch (Exception e) {} - } - - // Send Server->Client HennaInfo packet to this L2PcInstance - HennaInfo hi = new HennaInfo(this); - this.sendPacket(hi); - - // Send Server->Client UserInfo packet to this L2PcInstance - UserInfo ui = new UserInfo(this); - this.sendPacket(ui); - - return true; - } - } - - return false; - } - - /** - * Calculate Henna modifiers of this L2PcInstance.

    - */ - private void recalcHennaStats() - { - _hennaINT = 0; - _hennaSTR = 0; - _hennaCON = 0; - _hennaMEN = 0; - _hennaWIT = 0; - _hennaDEX = 0; - - for (int i=0;i<3;i++) - { - if (_henna[i]==null)continue; - _hennaINT += _henna[i].getStatINT(); - _hennaSTR += _henna[i].getStatSTR(); - _hennaMEN += _henna[i].getStatMEM(); - _hennaCON += _henna[i].getStatCON(); - _hennaWIT += _henna[i].getStatWIT(); - _hennaDEX += _henna[i].getStatDEX(); - } - - if (_hennaINT>5)_hennaINT=5; - if (_hennaSTR>5)_hennaSTR=5; - if (_hennaMEN>5)_hennaMEN=5; - if (_hennaCON>5)_hennaCON=5; - if (_hennaWIT>5)_hennaWIT=5; - if (_hennaDEX>5)_hennaDEX=5; - } - - /** - * Return the Henna of this L2PcInstance corresponding to the selected slot.

    - */ - public L2HennaInstance getHenna(int slot) - { - if (slot < 1 || slot > 3) - return null; - - return _henna[slot - 1]; - } - - /** - * Return the INT Henna modifier of this L2PcInstance.

    - */ - public int getHennaStatINT() - { - return _hennaINT; - } - - /** - * Return the STR Henna modifier of this L2PcInstance.

    - */ - public int getHennaStatSTR() - { - return _hennaSTR; - } - - /** - * Return the CON Henna modifier of this L2PcInstance.

    - */ - public int getHennaStatCON() - { - return _hennaCON; - } - - /** - * Return the MEN Henna modifier of this L2PcInstance.

    - */ - public int getHennaStatMEN() - { - return _hennaMEN; - } - - /** - * Return the WIT Henna modifier of this L2PcInstance.

    - */ - public int getHennaStatWIT() - { - return _hennaWIT; - } - - /** - * Return the DEX Henna modifier of this L2PcInstance.

    - */ - public int getHennaStatDEX() - { - return _hennaDEX; - } - - /** - * Return True if the L2PcInstance is autoAttackable.

    - * - * Actions :

    - *
  • Check if the attacker isn't the L2PcInstance Pet
  • - *
  • Check if the attacker is L2MonsterInstance
  • - *
  • If the attacker is a L2PcInstance, check if it is not in the same party
  • - *
  • Check if the L2PcInstance has Karma
  • - *
  • If the attacker is a L2PcInstance, check if it is not in the same siege clan (Attacker, Defender)


  • - * - */ - public boolean isAutoAttackable(L2Character attacker) - { - // Check if the attacker isn't the L2PcInstance Pet - if (attacker == this || attacker == this.getPet()) - return false; - - // TODO: check for friendly mobs - // Check if the attacker is a L2MonsterInstance - if (attacker instanceof L2MonsterInstance) - return true; - - // Check if the attacker is not in the same party - if (getParty() != null && getParty().getPartyMembers().contains(attacker)) - return false; - - // Check if the attacker is not in the same clan - if (getClan() != null && attacker != null && getClan().isMember(attacker.getName())) - return false; - - // Check if the L2PcInstance has Karma - if (getKarma() > 0 || getPvpFlag() > 0) - return true; - - // Check if the attacker is a L2PcInstance - if (attacker instanceof L2PcInstance) - { - // Check if the L2PcInstance is in an arena or a siege area - if (ZoneManager.getInstance().checkIfInZonePvP(this) && ZoneManager.getInstance().checkIfInZonePvP(attacker)) - return true; - - if (this.getClan() != null) - { - Siege siege = SiegeManager.getInstance().getSiege(getX(), getY()); - if (siege != null) - { - // Check if a siege is in progress and if attacker and the L2PcInstance aren't in the Defender clan - if (siege.checkIsDefender(((L2PcInstance)attacker).getClan()) && - siege.checkIsDefender(this.getClan())) - return false; - - // Check if a siege is in progress and if attacker and the L2PcInstance aren't in the Attacker clan - if (siege.checkIsAttacker(((L2PcInstance)attacker).getClan()) && - siege.checkIsAttacker(this.getClan())) - return false; - } - - // Check if clan is at war -// if (this.getClan() != null && ((L2PcInstance)attacker).getClan() != null && (this.getClan().isAtWarWith(((L2PcInstance)attacker).getClanId()) && this.getWantsPeace() == 0 && ((L2PcInstance)attacker).getWantsPeace() == 0)) -// return true; - } - } - else if (attacker instanceof L2SiegeGuardInstance) - { - if (this.getClan() != null) - { - Siege siege = SiegeManager.getInstance().getSiege(this); - return (siege != null && siege.checkIsAttacker(this.getClan())); - } - } - - return false; - } - - - /** - * Check if the active L2Skill can be casted.

    - * - * Actions :

    - *
  • Check if the skill isn't toggle and is offensive
  • - *
  • Check if the target is in the skill cast range
  • - *
  • Check if the skill is Spoil type and if the target isn't already spoiled
  • - *
  • Check if the caster owns enought consummed Item, enough HP and MP to cast the skill
  • - *
  • Check if the caster isn't sitting
  • - *
  • Check if all skills are enabled and this skill is enabled


  • - *
  • Check if the caster own the weapon needed


  • - *
  • Check if the skill is active


  • - *
  • Check if all casting conditions are completed


  • - *
  • Notify the AI with AI_INTENTION_CAST and target


  • - * - * @param skill The L2Skill to use - * @param forceUse used to force ATTACK on players - * @param dontMove used to prevent movement, if not in range - * - */ - public void useMagic(L2Skill skill, boolean forceUse, boolean dontMove) - { - if (isDead()) - { - abortCast(); - sendPacket(new ActionFailed()); - return; - } - - if (isWearingFormalWear() && !skill.isPotion()) - { - sendPacket(new SystemMessage(SystemMessage.CANNOT_USE_ITEMS_SKILLS_WITH_FORMALWEAR)); - - sendPacket(new ActionFailed()); - abortCast(); - return; - } - - if (inObserverMode()) - { - sendMessage("Cant use magic in observer mode"); - abortCast(); - sendPacket(new ActionFailed()); - return; - } - - - // Check if the skill type is TOGGLE - if (skill.isToggle()) - { - // Get effects of the skill - L2Effect effect = getEffect(skill); - - if (effect != null) - { - effect.exit(); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - } - - // Check if the skill is active - if (skill.isPassive()) - { - // just ignore the passive skill request. why does the client send it anyway ?? - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - - //************************************* Check Casting in Progress ******************************************* - - // If a skill is currently being used, queue this one if this is not the same - if (getCurrentSkill() != null && isCastingNow()) - { - // Check if new skill different from current skill in progress - if (skill.getId() == getCurrentSkill().getSkillId()) - return; - - if (Config.DEBUG && getQueuedSkill() != null) - _log.info(getQueuedSkill().getSkill().getName() + " is already queued for " + getName() + "."); - - //setCurrentSkill(null, false, false); - - // Create a new SkillDat object and queue it in the player _queuedSkill - setQueuedSkill(skill, forceUse, dontMove); - return; - } - - - - //************************************* Check Target ******************************************* - - // Create and set a L2Object containing the target of the skill - L2Object target = null; - - switch (skill.getTargetType()) - { - // Target the player if skill type is AURA, PARTY, CLAN or SELF - case TARGET_AURA: - case TARGET_PARTY: - case TARGET_ALLY: - case TARGET_CLAN: - case TARGET_SELF: - target = this; - break; - default: - target = getTarget(); - break; - } - - // Check the validity of the target - if (target == null) - { - sendPacket(new SystemMessage(SystemMessage.TARGET_CANT_FOUND)); - sendPacket(new ActionFailed()); - return; - } - - //Don't allow casting on players on different dungeon lvls etc - if ((Math.abs(target.getZ() - getZ()) > 1000)) - { - sendPacket(new SystemMessage(SystemMessage.CANT_SEE_TARGET)); - sendPacket(new ActionFailed()); - return; - } - - - - //************************************* Check skill availability ******************************************* - - // Check if this skill is enabled (ex : reuse time) - if (isSkillDisabled(skill.getId()) && (getAccessLevel() < Config.GM_PEACEATTACK)) - { - SystemMessage sm = new SystemMessage(SystemMessage.SKILL_NOT_AVAILABLE); - sm.addString(skill.getName()); - sendPacket(sm); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - // Check if all skills are disabled - if (isAllSkillsDisabled() && (getAccessLevel() < Config.GM_PEACEATTACK)) - { - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - - - //************************************* Check Consumables ******************************************* - - // Check if the caster has enough MP - if (getCurrentMp() < skill.getMpConsume()) - { - // Send a System Message to the caster - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - // Check if the caster has enough HP - if (getCurrentHp() <= skill.getHpConsume()) - { - // Send a System Message to the caster - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_HP)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - 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()) - { - // Send a System Message to the caster - sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); - return; - } - } - - - - //************************************* 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(new ActionFailed()); - return; - } - - // Check if all casting conditions are completed - if (!skill.checkCondition(this)) - { - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - - - //************************************* Check Player State ******************************************* - - // Abnormal effects(ex : Stun, Sleep...) are checked in L2Character useMagic() - - // Check if the player use "Fake Death" skill - if (isAlikeDead()) - { - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - // Check if the caster is sitting - if (isSitting() && !skill.isPotion()) - { - // Send a System Message to the caster - sendPacket(new SystemMessage(SystemMessage.CANT_MOVE_SITTING)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - if (isFishing() && (skill.getSkillType() != SkillType.PUMPING && skill.getSkillType() != SkillType.REELING && skill.getSkillType() != SkillType.FISHING)) - { - //Only fishing skills are available - this.sendPacket(new SystemMessage(1448)); - return; - } - - - - //************************************* Check Skill Type ******************************************* - - // Check if this is offensive magic skill - if (skill.isOffensive()) - { - if ((isInsidePeaceZone(this, target)) && (getAccessLevel() < Config.GM_PEACEATTACK)) - { - // If L2Character or target is in a peace zone, send a system message TARGET_IN_PEACEZONE a Server->Client packet ActionFailed - sendPacket(new SystemMessage(SystemMessage.TARGET_IN_PEACEZONE)); - sendPacket(new ActionFailed()); - return; - } - - - // Check if the target is attackable - if (!target.isAttackable() && (getAccessLevel() < Config.GM_PEACEATTACK)) - { - // If target is not attackable, send a Server->Client packet ActionFailed - sendPacket(new ActionFailed()); - return; - } - - // Check if a Forced ATTACK is in progress on non-attackable target - if (!target.isAutoAttackable(this) && !forceUse && - skill.getTargetType() != SkillTargetType.TARGET_AURA && - skill.getTargetType() != SkillTargetType.TARGET_CLAN && - skill.getTargetType() != SkillTargetType.TARGET_ALLY && - skill.getTargetType() != SkillTargetType.TARGET_PARTY && - skill.getTargetType() != SkillTargetType.TARGET_SELF) - { - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - - // Check if the target is in the skill cast range - if (dontMove) - { - // Calculate the distance between the L2PcInstance and the target - if (skill.getCastRange() > 0 && !isInsideRadius(target, skill.getCastRange(), false, false)) - { - // Send a System Message to the caster - sendPacket(new SystemMessage(SystemMessage.TARGET_TOO_FAR)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - 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 - && (skill.getTargetType() != SkillTargetType.TARGET_PET) - && (skill.getTargetType() != SkillTargetType.TARGET_AURA) - && (skill.getTargetType() != SkillTargetType.TARGET_CLAN) - && (skill.getTargetType() != SkillTargetType.TARGET_SELF) - && (skill.getTargetType() != SkillTargetType.TARGET_PARTY) - && (skill.getTargetType() != SkillTargetType.TARGET_ALLY) - && (skill.getTargetType() != SkillTargetType.TARGET_CORPSE_MOB) - && (skill.getTargetType() != SkillTargetType.TARGET_AREA_CORPSE_MOB)) - { - // send the action failed so that the skill doens't go off. - sendPacket (new ActionFailed()); - return; - } - } - - // Check if the skill is Spoil type and if the target isn't already spoiled - if (skill.getSkillType() == SkillType.SPOIL) - { - if (target instanceof L2Attackable && ((L2Attackable)target).isSpoil()) - { - // Send a System Message to the caster - sendPacket(new SystemMessage(SystemMessage.ALREDAY_SPOILED)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - } - - // Check if the skill is Sweep type and if conditions not apply - if (skill.getSkillType() == SkillType.SWEEP && target instanceof L2Attackable) - { - int spoilerId = ((L2Attackable)target).getIsSpoiledBy(); - - if ((((L2Attackable)target).isDead() && !((L2Attackable)target).isSpoil()) || (getObjectId() != spoilerId && !isInSpoilerParty(spoilerId))) - { - // Send a System Message to the L2PcInstance - sendPacket(new SystemMessage(SystemMessage.SWEEPER_FAILED_TARGET_NOT_SPOILED)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - } - - // Check if the skill is Drain Soul (Soul Crystals) and if the target is a MOB - if (skill.getSkillType() == SkillType.DRAIN_SOUL) - { - if (!(target instanceof L2MonsterInstance)) - { - // Send a System Message to the L2PcInstance - sendPacket(new SystemMessage(SystemMessage.TARGET_IS_INCORRECT)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - } - - // Check if this is a Pvp skill and target isn't a non-flagged/non-karma player - switch (skill.getTargetType()) - { - 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: - break; - default: - if (!checkPvpSkill(target, skill) && (getAccessLevel() < Config.GM_PEACEATTACK)) - { - // Send a System Message to the L2PcInstance - sendPacket(new SystemMessage(SystemMessage.TARGET_IS_INCORRECT)); - - // Send a Server->Client packet ActionFailed to the L2PcInstance - sendPacket(new ActionFailed()); - return; - } - } - - if (skill.getTargetType() == SkillTargetType.TARGET_HOLY && !TakeCastle.checkIfOkToCastSealOfRule(this, false)) - { - sendPacket(new ActionFailed()); - abortCast(); - return; - } - - if (skill.getSkillType() == SkillType.SIEGEFLAG && !SiegeFlag.checkIfOkToPlaceFlag(this, false)) - { - sendPacket(new ActionFailed()); - abortCast(); - return; - } - - - - // If all conditions are checked, create a new SkillDat object and set the player _currentSkill - setCurrentSkill(skill, forceUse, dontMove); - - // Check if the active L2Skill can be casted (ex : not sleeping...), Check if the target is correct and Notify the AI with AI_INTENTION_CAST and target - super.useMagic(skill); - - } - - public boolean isInSpoilerParty(int SpoilerId) - { - L2PcInstance spoiler = (L2PcInstance)L2World.getInstance().findObject(SpoilerId); - - if (isInParty() && spoiler != null) - return getParty().getPartyMembers().contains(spoiler); - - return false; - } - - /** - * Check if the requested casting is a Pc->Pc skill cast and if it's a valid pvp condition - * @param target L2Object instance containing the target - * @param skill L2Skill instance with the skill being casted - * @return False if the skill is a pvpSkill and target is not a valid pvp target - */ - public boolean checkPvpSkill(L2Object target, L2Skill skill) - { - // check for PC->PC Pvp status - if ( - target != null && // target not null and - target != this && // target is not self and - target instanceof L2PcInstance && // target is L2PcInstance and - skill.isPvpSkill() && // pvp skill and - !ZoneManager.getInstance().checkIfInZonePvP(this) && // Pc is not in PvP zone - !ZoneManager.getInstance().checkIfInZonePvP(target) // target is not in PvP zone - ) - { - if ( - ((L2PcInstance)target).getPvpFlag() == 0 && // target's pvp flag is not set and - ((L2PcInstance)target).getKarma() == 0 // target has no karma - ) - return false; - } - return true; - } - - /** - * Reduce Item quantity of the L2PcInstance Inventory and send it a Server->Client packet InventoryUpdate.

    - */ - public void consumeItem(int itemConsumeId, int itemCount) - { - if (itemConsumeId != 0 && itemCount != 0) - destroyItemByItemId("Consume", itemConsumeId, itemCount, null, false); - } - - /** - * Return True if the L2PcInstance is a Mage.

    - */ - public boolean isMageClass() - { - L2CharTemplate template = CharTemplateTable.getInstance().getTemplate(getClassId(), getSex()!=0); - - if (template.baseMAtk > 3) - return true; - - return false; - } - - - public boolean isMounted() - { - return _mountType > 0; - } - - /** - * Set the type of Pet mounted (0 : none, 1 : Stridder, 2 : Wyvern) and send a Server->Client packet InventoryUpdate to the L2PcInstance.

    - */ - public boolean checkLandingState() - { - // Check if char is in a no landing zone - if (ZoneManager.getInstance().checkIfInZoneNoLanding(this)) - return true; - else - // if this is a castle that is currently being sieged, and the rider is NOT a castle owner - // he cannot land. - // castle owner is the leader of the clan that owns the castle where the pc is - if (SiegeManager.getInstance().checkIfInZone(this) && - !(getClan()!=null && - CastleManager.getInstance().getCastle(this) == CastleManager.getInstance().getCastleByOwner(getClan()) && - this == getClan().getLeader().getPlayerInstance())) - return true; - - return false; - } - - public void setMountType(int mountType) - { - if (checkLandingState() && mountType !=0) - return; - - switch(mountType) - { - case 0: - setIsFlying(false); - setIsRiding(false); - break; //Dismounted - case 1: - setIsRiding(true); - break; - case 2: - setIsFlying(true); - break; //Flying Wyvern - } - - _mountType = mountType; - - // Send a Server->Client packet InventoryUpdate to the L2PcInstance in order to update speed - UserInfo ui = new UserInfo(this); - sendPacket(ui); - - } - - /** - * Return the type of Pet mounted (0 : none, 1 : Stridder, 2 : Wyvern).

    - */ - public int getMountType() - { - return _mountType; - } - - /** - * Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers.

    - * - * Concept :

    - * Others L2PcInstance in the detection area of the L2PcInstance are identified in _knownPlayers. - * In order to inform other players of this L2PcInstance state modifications, server just need to go through _knownPlayers to send Server->Client Packet

    - * - * Actions :

    - *
  • Send a Server->Client packet UserInfo to this L2PcInstance (Public and Private Data)
  • - *
  • Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance (Public data only)


  • - * - * Caution : DON'T SEND UserInfo packet to other players instead of CharInfo packet. - * Indeed, UserInfo packet contains PRIVATE DATA as MaxHP, STR, DEX...

    - * - */ - public void updateAbnormalEffect() - { - broadcastUserInfo(); - } - - /** - * Disable the Inventory and create a new task to enable it after 1.5s.

    - */ - public void tempInvetoryDisable() - { - _inventoryDisable = true; - - ThreadPoolManager.getInstance().scheduleGeneral(new InventoryEnable(), 1500); - } - - /** - * Return True if the Inventory is disabled.

    - */ - public boolean isInvetoryDisabled() - { - return _inventoryDisable; - } - - class InventoryEnable implements Runnable - { - public void run() - { - _inventoryDisable = false; - } - } - - public Map getCubics() - { - return _cubics; - } - - /** - * Add a L2CubicInstance to the L2PcInstance _cubics.

    - */ - public void addCubic(int id, int level) - { - L2CubicInstance cubic = new L2CubicInstance(this, id, level); - _cubics.put(id, cubic); - } - - /** - * Remove a L2CubicInstance from the L2PcInstance _cubics.

    - */ - public void delCubic(int id) - { - _cubics.remove(id); - } - - /** - * Return the L2CubicInstance corresponding to the Identifier of the L2PcInstance _cubics.

    - */ - public L2CubicInstance getCubic(int id) - { - return _cubics.get(id); - } - - public String toString() - { - return "player "+getName(); - } - - /** - * Return the modifier corresponding to the Enchant Effect of the Active Weapon (Min : 127).

    - */ - public int getEnchantEffect() - { - L2ItemInstance wpn = getActiveWeaponInstance(); - - if (wpn == null) - return 0; - - return Math.min(127, wpn.getEnchantLevel()); - } - - /** - * Set the _lastFolkNpc of the L2PcInstance corresponding to the last Folk wich one the player talked.

    - */ - public void setLastFolkNPC(L2FolkInstance folkNpc) - { - _lastFolkNpc = folkNpc; - } - - /** - * Return the _lastFolkNpc of the L2PcInstance corresponding to the last Folk wich one the player talked.

    - */ - public L2FolkInstance getLastFolkNPC() - { - return _lastFolkNpc; - } - - /** - * Set the Silent Moving mode Flag.

    - */ - public void setSilentMoving(boolean flag) - { - _isSilentMoving = flag; - } - - /** - * Return True if the Silent Moving mode is active.

    - */ - public boolean isSilentMoving() - { - return _isSilentMoving; - } - - /** - * Return True if L2PcInstance is a participant in the Festival of Darkness.

    - */ - public boolean isFestivalParticipant() - { - return SevenSignsFestival.getInstance().isParticipant(this); - } - - public void addAutoSoulShot(int itemId) - { - _activeSoulShots.add(itemId); - } - - public void removeAutoSoulShot(int itemId) - { - _activeSoulShots.remove(itemId); - } - - public Set getAutoSoulShot() - { - return _activeSoulShots; - } - - public void rechargeAutoSoulShot(boolean physical, boolean magic, boolean summon) - { - L2ItemInstance item; - IItemHandler handler; - - if (_activeSoulShots == null || _activeSoulShots.size() == 0) - return; - - for (int itemId : _activeSoulShots) - { - item = getInventory().getItemByItemId(itemId); - - if (item != null) - { - if (magic) - { - if (!summon) - { - if (itemId == 2509 || itemId == 2510 || itemId == 2511 || - itemId == 2512 || itemId == 2513 || itemId == 2514 || - itemId == 3947 || itemId == 3948 || itemId == 3949 || - itemId == 3950 || itemId == 3951 || itemId == 3952 || - itemId == 5790) - { - handler = ItemHandler.getInstance().getItemHandler(itemId); - - if (handler != null) - handler.useItem(this, item); - } - } else - { - if (itemId == 6646 || itemId == 6647) - { - handler = ItemHandler.getInstance().getItemHandler(itemId); - - if (handler != null) - handler.useItem(this, item); - } - } - } - - if (physical) - { - if (!summon) - { - if (itemId == 1463 || itemId == 1464 || itemId == 1465 || - itemId == 1466 || itemId == 1467 || itemId == 1835 || - itemId == 5789) - { - handler = ItemHandler.getInstance().getItemHandler(itemId); - - if (handler != null) - handler.useItem(this, item); - } - } else - { - if (itemId == 6645) - { - handler = ItemHandler.getInstance().getItemHandler(itemId); - - if (handler != null) - handler.useItem(this, item); - } - } - } - } - else - { - removeAutoSoulShot(itemId); - } - } - } - - - - private ScheduledFuture _taskWarnUserTakeBreak; - - class WarnUserTakeBreak implements Runnable - { - public void run() - { - if (L2PcInstance.this.isOnline() == 1) - { - SystemMessage msg = new SystemMessage(764); - L2PcInstance.this.sendPacket(msg); - } - else - stopWarnUserTakeBreak(); - } - } - - class RentPetTask implements Runnable - { - public void run() - { - stopRentPet(); - } - } - - private ScheduledFuture _taskforfish; - - class WaterTask implements Runnable - { - public void run() - { - double reduceHp = getMaxHp()/100; - - if (reduceHp < 1) - reduceHp = 1; - - reduceCurrentHp(reduceHp,L2PcInstance.this,false); - //reduced hp, becouse not rest - SystemMessage sm = new SystemMessage(297); - sm.addNumber((int)reduceHp); - sendPacket(sm); - - } - } - - class LokingForFishTask implements Runnable - { - public void run() - { - int rate = 90; //Only for now - int check = Rnd.get(100); - StopLookingForFishTask(); - if(rate > check) - { - StartFishCombat(); - } - else EndFishing(false); - } - } - - public void setInvisible() - { - _invisible = 1; - } - - public void setVisible() - { - _invisible = 0; - } - - public int getInvisible() - { - return _invisible; - } - - public void togglePathNodeMode() - { - _isPathNodeMode = !_isPathNodeMode; - } - - public void toggleViewPathNodes() - { - _isPathNodesVisible = !_isPathNodesVisible; - } - - public boolean isPathNodeModeActive() - { - return _isPathNodeMode; - } - - public boolean isPathNodeVisible() - { - return _isPathNodesVisible; - } - - public Map> getPathNodeMap() - { - if (_pathNodeMap == null) - _pathNodeMap = new FastMap>(); - - return _pathNodeMap; - } - - public void addPathNodePoint() - { - //add Node to Players PathNode List - //TODO: Addcheck for nearby point in radius - setSelectedNode(WayPointNode.spawn(this)); - getPathNodeMap().put(getSelectedNode(), new FastList()); - } - - /** - * Delete all Path Nodes.

    - */ - public void clearPathNodes() - { - if (getPathNodeMap() != null) - { - for (WayPointNode node : getPathNodeMap().keySet()) - removePathNodePoint(node); - - getPathNodeMap().clear(); - } - - setSelectedNode(null); - } - - public void setSelectedNode(WayPointNode decoInstance) - { - if (getSelectedNode() != null) - { - List linkedNodes = getPathNodeMap().get(getSelectedNode()); - - if (linkedNodes != null) - for (WayPointNode node : linkedNodes) - node.setNormal(); - - getSelectedNode().setNormal(); - } - - _selectedNode = decoInstance; - - if (_selectedNode != null) - { - _selectedNode.setSelected(); - - List linkedNodes = getPathNodeMap().get(_selectedNode); - - if (linkedNodes != null) - for (WayPointNode linked : linkedNodes) - linked.setLinked(); - } - } - - public WayPointNode getSelectedNode() - { - return _selectedNode; - } - - public void addLink(WayPointNode target) - { - if (getSelectedNode() != null) - { - List list = getPathNodeMap().get(getSelectedNode()); - - if (list == null) - list = new FastList(); - - list.add(target); - _pathNodeMap.put(getSelectedNode(), list); - - List list2 = getPathNodeMap().get(target); - - if (list2 == null) - list2 = new FastList(); - - list2.add(getSelectedNode()); - _pathNodeMap.put(target, list2); - - target.setLinked(); - WayPointNode.drawLine(target, getSelectedNode()); - } - } - - public void removeLink(WayPointNode target) - { - if (getSelectedNode() != null) - { - List list = getPathNodeMap().get(getSelectedNode()); - - if (list != null && list.contains(target)) - { - list.remove(target); - _pathNodeMap.put(getSelectedNode(), list); - - List list2 = getPathNodeMap().get(target); - - if (list2 != null && list2.contains(getSelectedNode())) - { - list2.remove(getSelectedNode()); - _pathNodeMap.put(target, list2); - } - - target.setNormal(); - WayPointNode.eraseLine(target, getSelectedNode()); - } - else - { - sendPacket(SystemMessage.sendString("Target not a Linked Node.")); - } - } - } - - public void removePathNodePoint() - { - removePathNodePoint(getSelectedNode()); - } - - public void removePathNodePoint(WayPointNode node) - { - if (node != null) - { - List list = getPathNodeMap().get(node); - - if (list != null) - { - synchronized (list) - { - try - { - for (WayPointNode link : list) - { - //WayPointNode.eraseLine(node, link); - removeLink(link); - } - } - catch (Exception e) - { - e.printStackTrace(); - } - } - } - - node.decayMe(); - node = null; - } - } - - /** - * @param string - */ - public void savePathNodes(String fileName) - { - try - { - //File file = new File(Config.DATAPACK_ROOT, "pathnode/" + fileName + ".bin"); - FileOutputStream fos = new FileOutputStream("pathnode/" + fileName + ".bin"); // Save to file - GZIPOutputStream gzos = new GZIPOutputStream(fos); // Compressed - ObjectOutputStream out = new ObjectOutputStream(gzos); // Save objects - out.writeObject(getSaveList()); // Write the entire pathNodeMap of Positions - out.flush(); // Always flush the output. - out.close(); // And close the stream. - sendPacket(SystemMessage.sendString("Path Node table saved to: L2J/pathnode/"+fileName+".bin")); - } - catch (Exception e) - { - e.printStackTrace(); - sendPacket(SystemMessage.sendString("Could not Save Path Node Table.")); - } - } - - public Map> getSaveList() - { - Map> saveList = null; - - if (getPathNodeMap() != null) - { - saveList = Collections.synchronizedMap(new WeakHashMap>()); - - for (WayPointNode node : getPathNodeMap().keySet()) - { - Point3D nodePoint = Point3D.getPosition(node); - - List links = getPathNodeMap().get(node); - List linkPoints = null; - - if (links != null) - { - linkPoints = new FastList(); - - for (WayPointNode link : links) - linkPoints.add(Point3D.getPosition(link)); - } - - saveList.put(nodePoint, linkPoints); - } - } - - return saveList; - } - - /** - * @param string - */ - @SuppressWarnings(value = { "unchecked" }) - public void loadPathNodes(String fileName) - { - Map> newNodeMap = null; - - try - { - //Create necessary input streams - //File file = new File(Config.DATAPACK_ROOT, "pathnode/" + fileName + ".bin"); - FileInputStream fis = new FileInputStream("pathnode/" + fileName + ".bin"); // Read from file - GZIPInputStream gzis = new GZIPInputStream(fis); // Uncompress - ObjectInputStream in = new ObjectInputStream(gzis); // Read objects - // Read in an object. It should be a vector of scribbles - - newNodeMap = (FastMap>)in.readObject(); - in.close(); // Close the stream. - } - catch (Exception e) - { - sendPacket(SystemMessage.sendString("Could not Load Path Node Table from: L2J/pathnode/"+fileName+".bin")); - e.printStackTrace(); - return; - } - - clearPathNodes(); - loadNodeList(newNodeMap); - sendPacket(SystemMessage.sendString("Path Node table loaded from: L2J/pathnode/"+fileName+".bin")); - } - - /** - * @param newNodeMap - */ - private void loadNodeList(Map> newNodeMap) - { - _pathNodeMap = Collections.synchronizedMap(new WeakHashMap>()); - Map map = new FastMap(); - WayPointNode newNode = null; - - for (Point3D point : newNodeMap.keySet()) - { - newNode = WayPointNode.spawn(point); - newNode.setNormal(); - map.put(point, newNode); - } - - for (Point3D point : newNodeMap.keySet()) - { - WayPointNode node = map.get(point); - List links = newNodeMap.get(point); - List nodeLinks = null; - - if (links != null) - { - nodeLinks = new FastList(); - - for (Point3D link : links) - { - WayPointNode linkNode = map.get(link); - nodeLinks.add(linkNode); - - if (getPathNodeMap().get(linkNode) != null && - !getPathNodeMap().get(linkNode).contains(node)) - WayPointNode.drawLine(linkNode, node); - } - } - - _pathNodeMap.put(node, nodeLinks); - } - } - - public int getClanPrivileges() - { - return _clanPrivileges; - } - - public void setClanPrivileges(int n) - { - _clanPrivileges = n; - } - - public void refreshLinks() - { - if (_linkToggle) - { - for (WayPointNode node : getPathNodeMap().keySet()) - { - for (WayPointNode lineNode : node.getLineNodes()) - { - lineNode.decayMe(); - lineNode.refreshID(); - //lineNode.spawnMe(); - } - } - } - else - { - for (WayPointNode node : getPathNodeMap().keySet()) - { - for (WayPointNode lineNode : node.getLineNodes()) - { - //lineNode.decayMe(); - //lineNode.refreshID(); - lineNode.spawnMe(); - } - } - } - - _linkToggle = !_linkToggle; - } - - public void sendMessage(String message) - { - sendPacket(SystemMessage.sendString(message)); - } - - public void enterObserverMode(int x, int y, int z) - { - _obsX = getX(); - _obsY = getY(); - _obsZ = getZ(); - - setTarget(null); - stopMove(null); - setIsParalyzed(true); - setIsInvul(true); - setInvisible(); - sendPacket(new ObservationMode(x, y, z)); - setXYZ(x, y, z); - - _observerMode = true; - broadcastPacket(new CharInfo(this)); - } - - public void enterOlympiadObserverMode(int x, int y, int z, int id) - { - if (getPet() != null) - getPet().unSummon(this); - _olympiadGameId = id; - _obsX = getX(); - if (isSitting()) - standUp(); - _obsY = getY(); - _obsZ = getZ(); - setTarget(null); - setIsInvul(true); - setInvisible(); - teleToLocation(x, y, z); - sendPacket(new ExOlympiadMode(3)); - _observerMode = true; - } - - public void leaveObserverMode() - { - setTarget(null); - setXYZ(_obsX, _obsY, _obsZ); - setIsParalyzed(false); - setVisible(); - setIsInvul(false); - - if (getAI() != null) - getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); - - _observerMode = false; - sendPacket(new ObservationReturn(this)); - broadcastPacket(new CharInfo(this)); - } - - public void leaveOlympiadObserverMode() - { - setTarget(null); - sendPacket(new ExOlympiadMode(0)); - teleToLocation(_obsX, _obsY, _obsZ); - setVisible(); - setIsInvul(false); - if (getAI() != null) - { - getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); - } - Olympiad.getInstance().removeSpectator(_olympiadGameId, this); - _olympiadGameId = -1; - _observerMode = false; - broadcastPacket(new CharInfo(this)); - } - - public void setOlympiadSide(int i) - { - _olympiadSide = i; - } - - public int getOlympiadSide() - { - return _olympiadSide; - } - - public void setOlympiadGameId(int id) - { - _olympiadGameId = id; - } - - public int getOlympiadGameId() - { - return _olympiadGameId; - } - - public int getObsX() - { - return _obsX; - } - - public int getObsY() - { - return _obsY; - } - - public int getObsZ() - { - return _obsZ; - } - - public boolean inObserverMode() - { - return _observerMode; - } - - public int getTeleMode() - { - return _telemode; - } - - public void setTeleMode(int mode) - { - _telemode = mode; - } - - public void setLoto(int i, int val) - { - _loto[i] = val; - } - - public int getLoto(int i) - { - return _loto[i]; - } - - public void setRace(int i, int val) - { - _race[i] = val; - } - - public int getRace(int i) - { - return _race[i]; - } - - public void setChatBanned(boolean isBanned) - { - _chatBanned = isBanned; - - if (isChatBanned()) - sendMessage("You have been chat banned by a server admin."); - else - { - sendMessage("Your chat ban has been lifted."); - if (_chatUnbanTask != null) - _chatUnbanTask.cancel(false); - _chatUnbanTask = null; - } - } - - public boolean isChatBanned() - { - return _chatBanned; - } - - public void setChatUnbanTask(ScheduledFuture task) - { - _chatUnbanTask = task; - } - public ScheduledFuture getChatUnbanTask() - { - return _chatUnbanTask; - } - - public boolean getMessageRefusal() - { - return _messageRefusal; - } - - public void setMessageRefusal(boolean mode) - { - _messageRefusal = mode; - updateEffectIcons(); - } - - public void setDietMode(boolean mode) - { - _dietMode = mode; - } - - public boolean getDietMode() - { - return _dietMode; - } - - public void setTradeRefusal(boolean mode) - { - _tradeRefusal = mode; - } - - public boolean getTradeRefusal() - { - return _tradeRefusal; - } - - public void setExchangeRefusal(boolean mode) - { - _exchangeRefusal = mode; - } - - public boolean getExchangeRefusal() - { - return _exchangeRefusal; - } - - public BlockList getBlockList() - { - return _blockList; - } - - public void setConnected(boolean connected) - { - _isConnected = connected; - } - - public void setHero(boolean hero) - { - _hero = hero; - } - - public void setIsInOlympiadMode(boolean b) - { - _inOlympiadMode = b; - } - - public boolean isHero() - { - return _hero; - } - - public boolean isInOlympiadMode() - { - return _inOlympiadMode; - } - - public boolean isNoble() - { - _noble = false; - - if (isSubClassActive()) - { - if (getTotalSubClasses() > 1) - { - _noble = true; - return _noble; - } - if (getLevel() >= 75) - { - _noble = true; - return _noble; - } - } - else - { - if (getSubClasses() == null) - return _noble; - - if (getLevel() >= 76 && getClassId().getId() >= 88) - { - for (SubClass sub : getSubClasses().values()) - { - if (sub.getLevel() >= 75) - { - _noble = true; - return _noble; - } - } - } - } - - return _noble; - } - - public void setTeam(int team) - { - _team = team; - } - - public int getTeam() - { - return _team; - } - - public int getNameColor() - { - return _nameColor; - } - - public void setNameColor(int nameColor) - { - _nameColor = nameColor; - } - - public void setNameColor(int red, int green, int blue) - { - _nameColor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16); - } - - public void setWantsPeace(int wantsPeace) - { - _wantsPeace = wantsPeace; - } - - public int getWantsPeace() - { - return _wantsPeace; - } - - public boolean isFishing() - { - return _fishing; - } - - public void setFishing(boolean fishing) - { - _fishing = fishing; - } - - /** - * 1. Add the specified class ID as a subclass (up to the maximum number of three) - * for this character.
    - * 2. This method no longer changes the active _classIndex of the player. This is only - * done by the calling of setActiveClass() method as that should be the only way to do so. - * - * @param int classId - * @param int classIndex - * @return boolean subclassAdded - */ - public boolean addSubClass(int classId, int classIndex) - { - if (getTotalSubClasses() == 3 || classIndex == 0) - return false; - - if (getSubClasses().containsKey(classIndex)) - return false; - - // Note: Never change _classIndex in any method other than setActiveClass(). - - SubClass newClass = new SubClass(); - newClass.setClassId(classId); - newClass.setClassIndex(classIndex); - - java.sql.Connection con = null; - - try - { - // Store the basic info about this new sub-class. - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement = con.prepareStatement(ADD_CHAR_SUBCLASS); - statement.setInt(1, getObjectId()); - statement.setInt(2, newClass.getClassId()); - statement.setInt(3, newClass.getExp()); - statement.setInt(4, newClass.getSp()); - statement.setInt(5, newClass.getLevel()); - statement.setInt(6, newClass.getClassIndex()); // <-- Added - statement.execute(); - statement.close(); - } - catch (Exception e) { - _log.warning("WARNING: Could not add character sub class for " + getName() + ": " + e); - return false; - } - finally { - try { con.close(); } catch (Exception e) {} - } - - // Commit after database INSERT incase exception is thrown. - getSubClasses().put(newClass.getClassIndex(), newClass); - - if (Config.DEBUG) - _log.info(getName() + " added class ID " + classId + " as a sub class at index " + classIndex + "."); - - ClassId subTemplate = ClassId.values()[classId]; - List skillTree = SkillTreeTable.getInstance().getAllowedSkills(subTemplate); - - if (skillTree == null) - return true; - - Map prevSkillList = new FastMap(); - - for (L2SkillLearn skillInfo : skillTree) - { - if (skillInfo.getMinLevel() <= 40) - { - L2Skill prevSkill = prevSkillList.get(skillInfo.getId()); - L2Skill newSkill = SkillTable.getInstance().getInfo(skillInfo.getId(), skillInfo.getLevel()); - - if (prevSkill != null && (prevSkill.getLevel() > newSkill.getLevel())) - continue; - - prevSkillList.put(newSkill.getId(), newSkill); - storeSkill(newSkill, prevSkill, classIndex); - } - } - - if (Config.DEBUG) - _log.info(getName() + " was given " + getAllSkills().length + " skills for their new sub class."); - - return true; - } - - /** - * 1. Completely erase all existance of the subClass linked to the classIndex.
    - * 2. Send over the newClassId to addSubClass()to create a new instance on this classIndex.
    - * 3. Upon Exception, revert the player to their BaseClass to avoid further problems.
    - * - * @param int classIndex - * @param int newClassId - * @return boolean subclassAdded - */ - public boolean modifySubClass(int classIndex, int newClassId) - { - int oldClassId = getSubClasses().get(classIndex).getClassId(); - - if (Config.DEBUG) - _log.info(getName() + " has requested to modify sub class index " + classIndex + " from class ID " + oldClassId + " to " + newClassId + "."); - - java.sql.Connection con = null; - - try - { - con = L2DatabaseFactory.getInstance().getConnection(); - PreparedStatement statement; - - // Remove all henna info stored for this sub-class. - statement = con.prepareStatement(DELETE_CHAR_HENNAS); - statement.setInt(1, getObjectId()); - statement.setInt(2, classIndex); - statement.execute(); - statement.close(); - - // Remove all shortcuts info stored for this sub-class. - statement = con.prepareStatement(DELETE_CHAR_SHORTCUTS); - statement.setInt(1, getObjectId()); - statement.setInt(2, classIndex); - statement.execute(); - statement.close(); - - // Remove all effects info stored for this sub-class. - statement = con.prepareStatement(DELETE_SKILL_SAVE); - statement.setInt(1, getObjectId()); - statement.setInt(2, classIndex); - statement.execute(); - statement.close(); - - // Remove all skill info stored for this sub-class. - statement = con.prepareStatement(DELETE_CHAR_SKILLS); - statement.setInt(1, getObjectId()); - statement.setInt(2, classIndex); - statement.execute(); - statement.close(); - - // Remove all basic info stored about this sub-class. - statement = con.prepareStatement(DELETE_CHAR_SUBCLASS); - statement.setInt(1, getObjectId()); - statement.setInt(2, classIndex); - statement.execute(); - statement.close(); - } - catch (Exception e) - { - _log.warning("Could not modify sub class for " + getName() + " to class index " + classIndex + ": " + e); - - // This must be done in order to maintain data consistency. - getSubClasses().remove(classIndex); - return false; - } - finally { - try { con.close(); } catch (Exception e) {} - } - - getSubClasses().remove(classIndex); - return addSubClass(newClassId, classIndex); - } - - public boolean isSubClassActive() - { - return _classIndex > 0; - } - - public Map getSubClasses() - { - if (_subClasses == null) - _subClasses = new FastMap(); - - return _subClasses; - } - - public int getTotalSubClasses() - { - return getSubClasses().size(); - } - - public int getBaseClass() - { - return _baseClass; - } - - public int getActiveClass() - { - return _activeClass; - } - - public int getClassIndex() - { - return _classIndex; - } - - /** - * Changes the character's class based on the given class index. - *

    - * An index of zero specifies the character's original (base) class, - * while indexes 1-3 specifies the character's sub-classes respectively. - * - * @param classIndex - */ - public boolean setActiveClass(int classIndex) - { - /* - * 1. Call store() before modifying _classIndex to avoid skill effects rollover. - * 2. Register the correct _classId against applied 'classIndex'. - */ - store(); - - if (classIndex == 0) - { - setClassId(getBaseClass()); - } - else - { - try { - setClassId(getSubClasses().get(classIndex).getClassId()); - } - catch (Exception e) { - _log.info("Could not switch " + getName() + "'s sub class to class index " + classIndex + ": " + e); - return false; - } - } - - _classIndex = classIndex; - - /* - * Update the character's change in class status. - * - * 1. Remove any active cubics from the player. - * 2. Renovate the characters table in the database with the new class info, storing also buff/effect data. - * 3. Remove all existing skills. - * 4. Restore all the learned skills for the current class from the database. - * 5. Restore effect/buff data for the new class. - * 6. Restore henna data for the class, applying the new stat modifiers while removing existing ones. - * 7. Reset HP/MP/CP stats and send Server->Client character status packet to reflect changes. - * 8. Restore shortcut data related to this class. - * 9. Resend a class change animation effect to broadcast to all nearby players. - */ - - if (getCubics().size() > 0) - { - for (L2CubicInstance cubic : getCubics().values()) - { - cubic.stopAction(); - cubic.cancelDisappear(); - } - - getCubics().clear(); - } - - for (L2Skill oldSkill : getAllSkills()) - super.removeSkill(oldSkill); - - for (L2Effect effect : getAllEffects()) - effect.exit(); - - if (isSubClassActive()) - { - _dwarvenRecipeBook.clear(); - _commonRecipeBook.clear(); - } - else - { - restoreRecipeBook(); - } - - restoreSkills(); - rewardSkills(); - restoreEffects(); - - for (int i = 0; i < 3; i++) - _henna[i] = null; - - restoreHenna(); - sendPacket(new HennaInfo(this)); - - setCurrentHpMp(getMaxHp(), getMaxMp()); - setCurrentCp(getMaxCp()); - updateStats(); - - //_macroses.restore(); - //_macroses.sendUpdate(); - _shortCuts.restore(); - sendPacket(new ShortCutInit(this)); - - broadcastPacket(new SocialAction(getObjectId(), 15)); - - //decayMe(); - //spawnMe(getX(), getY(), getZ()); - - return true; - } - - public void stopWarnUserTakeBreak() - { - if (_taskWarnUserTakeBreak != null) - { - _taskWarnUserTakeBreak.cancel(false); - _taskWarnUserTakeBreak = null; - } - } - - public void startWarnUserTakeBreak() - { - if (_taskWarnUserTakeBreak == null) - _taskWarnUserTakeBreak = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new WarnUserTakeBreak(), 7200000, 7200000); - } - - public void stopRentPet() - { - if (_taskRentPet != null) - { - // if the rent of a wyvern expires while over a flying zone, tp to down before unmounting - if (checkLandingState() && getMountType()==2) - teleToLocation(MapRegionTable.getInstance().getTeleToLocation(this, MapRegionTable.TeleportWhereType.Town)); - _taskRentPet.cancel(false); - Ride dismount = new Ride(getObjectId(), Ride.ACTION_DISMOUNT, 0); - sendPacket(dismount); - broadcastPacket(dismount); - _taskRentPet = null; - setMountType(0); - } - } - - public void startRentPet(int seconds) - { - if (_taskRentPet == null) - _taskRentPet = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new RentPetTask(), seconds * 1000, seconds * 1000); - } - - public boolean isRentedPet() - { - if (_taskRentPet != null) - return true; - - return false; - } - - public void stopWaterTask() - { - if (_taskWater != null) - { - _taskWater.cancel(false); - - _taskWater = null; - sendPacket(new SetupGauge(2, 0)); - } - } - - public void startWaterTask() - { - if (!isDead() && _taskWater == null) - { - int timeinwater = 86; - - sendPacket(new SetupGauge(2, timeinwater * 1000)); - _taskWater = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new WaterTask(), timeinwater * 1000, 1000); - } - } - - public boolean isInWater() - { - if (_taskWater != null) - return true; - - return false; - } - - public void checkWaterState() - { - //checking if char is over base level of water (sea, rivers) - if (getZ() > -3793) - { - stopWaterTask(); - return; - } - - // Check if char is in water or is underground and in water - int[] coord; - Zone zone = ZoneManager.getInstance().getZone(ZoneType.getZoneTypeName(ZoneType.ZoneTypeEnum.Water), getX(), getY()); //checking if char is in water zone - - if (zone == null) - zone = ZoneManager.getInstance().getZoneType(ZoneType.getZoneTypeName(ZoneType.ZoneTypeEnum.Underground)).getZone(getX(), getY()); //checking if char is in underground and in water - - if (zone != null) - { - coord = zone.getCoord(getX(), getY()); - - if (coord != null && getZ() > coord[4]) - { - stopWaterTask(); - return; - } - } - - startWaterTask(); - } - - public void onPlayerEnter() - { - startWarnUserTakeBreak(); - - if (SevenSigns.getInstance().isSealValidationPeriod() || SevenSigns.getInstance().isCompResultsPeriod()) - { - if (!isGM() && isIn7sDungeon() && SevenSigns.getInstance().getPlayerCabal(this) != SevenSigns.getInstance().getCabalHighestScore()) - { - teleToLocation(MapRegionTable.TeleportWhereType.Town); - setIsIn7sDungeon(false); - sendMessage("You have been teleported to the nearest town due to the beginning of the Seal Validation period."); - } - } - else - { - if (!isGM() && isIn7sDungeon() && SevenSigns.getInstance().getPlayerCabal(this) == SevenSigns.CABAL_NULL) - { - teleToLocation(MapRegionTable.TeleportWhereType.Town); - setIsIn7sDungeon(false); - sendMessage("You have been teleported to the nearest town because you have not signed for any cabal."); - } - } - - // jail task - updateJailState(); - - if (getInvisible() == 1) - sendMessage("Entering world in Invisible mode."); - if (getMessageRefusal()) - sendMessage("Entering world in Message Refusal mode."); - - // Reset Pvp Zone flag withour sending a message to the client - setInPvpZone(false, false); - revalidateInPvpZone(); - } - - public long getLastAccess() - { - return _lastAccess; - } - - private void checkRecom(int recsHave, int recsLeft) - { - Calendar check = Calendar.getInstance(); - check.setTimeInMillis(_lastAccess); - check.add(Calendar.DAY_OF_MONTH,1); - - Calendar min = Calendar.getInstance(); - min.set(Calendar.HOUR_OF_DAY, 13); - min.set(Calendar.MINUTE, 0); - - Calendar max = Calendar.getInstance(); - max.add(Calendar.DAY_OF_MONTH,1); - max.set(Calendar.HOUR_OF_DAY, 13); - max.set(Calendar.MINUTE, 0); - - if (getStat().getLevel() < 10 || !(check.after(min) && check.before(max)) ) - { - _recomHave = recsHave; - _recomLeft = recsLeft; - return; - } - - restartRecom(); - } - - public void restartRecom() - { - _recomChars.clear(); - - if (getStat().getLevel() < 20) - { - _recomLeft = 3; - _recomHave--; - } - else if (getStat().getLevel() < 40) - { - _recomLeft = 3; - _recomHave -= 2; - } - else - { - _recomLeft = 6; - _recomHave -= 3; - } - - if (_recomHave < 0) - _recomHave = 0; - } - - public int getBoatId() - { - return _boatId; - } - - public void setBoatId(int boatId) - { - _boatId = boatId; - } - - public void doRevive() - { - super.doRevive(); - updateEffectIcons(); - } - - public void doRevive(L2Skill skill) - { - // Restore the player's lost experience, - // depending on the % return of the skill used (based on its power). - restoreExp(skill.getPower()); - doRevive(); - } - - public void onActionRequest() - { - setProtection(false); - } - - /** - * @param expertiseIndex The expertiseIndex to set. - */ - public void setExpertiseIndex(int expertiseIndex) - { - _expertiseIndex = expertiseIndex; - } - - /** - * @return Returns the expertiseIndex. - */ - public int getExpertiseIndex() - { - return _expertiseIndex; - } - - public final void onTeleported() - { - super.onTeleported(); - - if (Config.PLAYER_SPAWN_PROTECTION > 0) - setProtection(true); - - if (Config.ALLOW_WATER) - checkWaterState(); - } - - public final boolean updatePosition(int gameTicks) - { - // Disables custom movement for L2PCInstance when Old Synchronization is selected - if (Config.COORD_SYNCHRONIZE == -1) - return super.updatePosition(gameTicks); - - // Get movement data - MoveData m = _move; - - if (_move == null) - return true; - - if (!isVisible()) - { - _move = null; - return true; - } - - // Check if the position has alreday be calculated - if (m._moveTimestamp == 0) - m._moveTimestamp = m._moveStartTime; - - // Check if the position has alreday be calculated - if (m._moveTimestamp == gameTicks) - return false; - - int dx = m._xDestination - getX(); - int dy = m._yDestination - getY(); - int dz = m._zDestination - getZ(); - int distPassed = (int)getStat().getMoveSpeed() * (gameTicks - m._moveTimestamp) / GameTimeController.TICKS_PER_SECOND; - double distFraction = (distPassed) / Math.sqrt(dx*dx + dy*dy + dz*dz); -// if (Config.DEVELOPER) System.out.println("Move Ticks:" + (gameTicks - m._moveTimestamp) + ", distPassed:" + distPassed + ", distFraction:" + distFraction); - - if (distFraction > 1) - { - // Set the position of the L2Character to the destination - super.setXYZ(m._xDestination, m._yDestination, m._zDestination); - - // Cancel the move action - _move = null; - } - else - { - // Set the position of the L2Character to estimated after parcial move - super.setXYZ(getX() + (int)(dx * distFraction + 0.5), getY() + (int)(dy * distFraction + 0.5), getZ() + (int)(dz * distFraction)); - } - - // Set the timer of last position update to now - m._moveTimestamp = gameTicks; - return (_move == null); - } - - public void setLastClientPosition(int x, int y, int z) - { - _lastClientPosition.x = x; - _lastClientPosition.y = y; - _lastClientPosition.z = z; - } - - public boolean checkLastClientPosition(int x, int y, int z) - { - return _lastClientPosition.x == x && _lastClientPosition.y == y && _lastClientPosition.z == z; - } - - public int getLastClientDistance(int x, int y, int z) - { - int dx = (x - _lastClientPosition.x); - int dy = (y - _lastClientPosition.y); - int dz = (z - _lastClientPosition.z); - - return (int)Math.sqrt(dx*dx + dy*dy + dz*dz); - } - - public void setLastServerPosition(int x, int y, int z) - { - _lastServerPosition.x = x; - _lastServerPosition.y = y; - _lastServerPosition.z = z; - } - - public boolean checkLastServerPosition(int x, int y, int z) - { - return _lastServerPosition.x == x && _lastServerPosition.y == y && _lastServerPosition.z == z; - } - - public int getLastServerDistance(int x, int y, int z) - { - int dx = (x - _lastServerPosition.x); - int dy = (y - _lastServerPosition.y); - int dz = (z - _lastServerPosition.z); - - return (int)Math.sqrt(dx*dx + dy*dy + dz*dz); - } - - public void addExpAndSp(int addToExp, int addToSp) { getStat().addExpAndSp(addToExp, addToSp); } - public void reduceCurrentHp(double i, L2Character attacker) { getStatus().reduceHp(i, attacker); } - public void reduceCurrentHp(double value, L2Character attacker, boolean awake) { getStatus().reduceHp(value, attacker, awake); } - - public void broadcastSnoop(int type, String name, String _text) - { - if(_SnoopListener.size() > 0) - { - Snoop sn = new Snoop(getObjectId(),getName(),type,name,_text); - - for (L2PcInstance pci : _SnoopListener) - if (pci != null) - pci.sendPacket(sn); - } - } - - public void addSnooper(L2PcInstance pci ) - { - if(!_SnoopListener.contains(pci)) - _SnoopListener.add(pci); - } - - public void removeSnooper(L2PcInstance pci ) - { - _SnoopListener.remove(pci); - } - - public void addSnooped(L2PcInstance pci ) - { - if(!_SnoopedPlayer.contains(pci)) - _SnoopedPlayer.add(pci); - } - - public void removeSnooped(L2PcInstance pci ) - { - _SnoopedPlayer.remove(pci); - } - - public void addBypass(String bypass) - { - _validBypass.add(bypass); - //_log.warning("[BypassAdd]"+getName()+" '"+bypass+"'"); - } - - public void addBypass2(String bypass) - { - _validBypass2.add(bypass); - //_log.warning("[BypassAdd]"+getName()+" '"+bypass+"'"); - } - - public boolean validateBypass(String cmd) - { - if (!Config.BYPASS_VALIDATION) - return true; - - for (String bp : _validBypass) - { - if (bp == null) - return false; - - //_log.warning("[BypassValidation]"+getName()+" '"+bp+"'"); - if (bp.equals(cmd)) - return true; - } - - for (String bp : _validBypass2) - { - if (bp == null) - return false; - - //_log.warning("[BypassValidation]"+getName()+" '"+bp+"'"); - if (cmd.startsWith(bp)) - return true; - } - - _log.warning("[L2PcInstance] player ["+getName()+"] sent invalid bypass '"+cmd+"', ban this player!"); - return false; - } - - public boolean validateItemManipulation(int objectId, String action) - { - L2ItemInstance item = getInventory().getItemByObjectId(objectId); - - if (item == null || item.getOwnerId() != getObjectId()) - { - _log.finest(getObjectId()+": player tried to " + action + " item he is not owner of"); - return false; - } - - // Pet is summoned and not the item that summoned the pet AND not the buggle from strider you're mounting - if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId) - { - if (Config.DEBUG) - _log.finest(getObjectId()+": player tried to " + action + " item controling pet"); - - return false; - } - - if(getActiveEnchantItem() != null && getActiveEnchantItem().getObjectId() == objectId) - { - if (Config.DEBUG) - _log.finest(getObjectId()+":player tried to " + action + " an enchant scroll he was using"); - - return false; - } - - if (item.isWear()) - { - Util.handleIllegalPlayerAction(this, "Warning!! Character "+getName()+" tried to "+action+" weared item: "+item.getObjectId(),Config.DEFAULT_PUNISH); - return false; - } - - return true; - } - - public void clearBypass() - { - synchronized (this) - { - _validBypass.clear(); - _validBypass2.clear(); - } - } - - /** - * @return Returns the inBoat. - */ - public boolean isInBoat() - { - return _inBoat; - } - - /** - * @param inBoat The inBoat to set. - */ - public void setInBoat(boolean inBoat) - { - _inBoat = inBoat; - } - - /** - * @return - */ - public L2BoatInstance getBoat() - { - return _boat; - } - - /** - * @param boat - */ - public void setBoat(L2BoatInstance boat) - { - _boat = boat; - } - - public void setInCrystallize(boolean inCrystallize) - { - _inCrystallize = inCrystallize; - } - - public boolean isInCrystallize() - { - return _inCrystallize; - } - - /** - * @return - */ - public Point3D getInBoatPosition() - { - return _inBoatPosition; - } - - public void setInBoatPosition(Point3D pt) - { - _inBoatPosition = pt; - } - - /** - * Manage the delete task of a L2PcInstance (Leave Party, Unsummon pet, Save its inventory in the database, Remove it from the world...).

    - * - * Actions :

    - *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • - *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • - *
  • Stop the HP/MP/CP Regeneration task
  • - *
  • Cancel Crafting, Attak or Cast
  • - *
  • Remove the L2PcInstance from the world
  • - *
  • Stop Party and Unsummon Pet
  • - *
  • Update database with items in its inventory and remove them from the world
  • - *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • - *
  • Close the connection with the client


  • - * - */ - public void deleteMe() - { - // Check if the L2PcInstance is in observer mode to set its position to its position before entering in observer mode - if (inObserverMode()) - setXYZ(_obsX, _obsY, _obsZ); - - // Set the online Flag to True or False and update the characters table of the database with online status and lastAccess (called when login and logout) - try { setOnlineStatus(false); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Stop the HP/MP/CP Regeneration task (scheduled tasks) - try { stopAllTimers(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Stop crafting, if in progress - try { RecipeController.getInstance().requestMakeItemAbort(this); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Cancel Attak or Cast - try { setTarget(null); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Remove the L2PcInstance from the world - if (isVisible()) - try { decayMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // If a Party is in progress, leave it - if (isInParty()) try { leaveParty(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // If the L2PcInstance has Pet, unsummon it - if (getPet() != null) - { - try { getPet().unSummon(this); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); }// returns pet to control item - } - - if (getClanId() != 0 && getClan() != null) - { - // set the status for pledge member list to OFFLINE - try - { - L2ClanMember clanMember = getClan().getClanMember(getName()); - if (clanMember != null) clanMember.setPlayerInstance(null); - } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - } - - if (getActiveRequester() != null) - { - // deals with sudden exit in the middle of transaction - setActiveRequester(null); - } - - // If the L2PcInstance is a GM, remove it from the GM List - if (isGM()) - { - try { GmListTable.getInstance().deleteGm(this); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - } - - // Update database with items in its inventory and remove them from the world - try { getInventory().deleteMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Update database with items in its warehouse and remove them from the world - try { getWarehouse().deleteMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Update database with items in its freight and remove them from the world - try { getFreight().deleteMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI - try { getKnownList().removeAllKnownObjects(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - // Close the connection with the client - try { setNetConnection(null); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } - - clearPathNodes(); - - if (getClanId() > 0) - ClanTable.getInstance().getClan(getClanId()).broadcastToOnlineMembers(new PledgeShowMemberListAdd(this)); - - for(L2PcInstance player : _SnoopedPlayer) - player.removeSnooper(this); - - for(L2PcInstance player : _SnoopListener) - player.removeSnooped(this); - - // Remove L2Object object from _allObjects of L2World - L2World.getInstance().removeObject(this); - } - - public void StartFishing() - { - stopMove(null); - int rnd = Rnd.get(50) + 150; - double angle = Util.convertHeadingToDegree(getHeading()); - //this.sendMessage("Angel: "+angle+" Heading: "+getHeading()); - double radian = Math.toRadians(angle - 90); - double sin = Math.sin(radian); - double cos = Math.cos(radian); - int x1 = -(int)(sin * rnd); //Somthing wrong with L2j Heding calculation o_0? - int y1 = (int)(cos * rnd); //Somthing wrong with L2j Heding calculation o_0? - int x = getX()+x1; - int y = getY()+y1; - int z = getZ()-30; - _fishx = x; - _fishy = y; - _fishz = z; - - //check the fishing floats x,y,z is in a fishing zone - //if not the abort fishing mode else continue - if (!ZoneManager.getInstance().checkIfInZoneFishing(x,y)) - { - //abort fishing - this.sendMessage("Your Lure didnt land in a fishing zone."); - return; - } - this.sendMessage("Get Ready to Fish"); - this.setIsImobilised(true); - _fishing = true; - broadcastUserInfo(); - //Starts fishing - sendPacket(new SystemMessage(1461)); - ExFishingStart efs = new ExFishingStart(this,x,y,z); - broadcastPacket(efs); - StartLookingForFishTask(); - } - public void StopLookingForFishTask() - { - if (_taskforfish != null) - { - _taskforfish.cancel(false); - _taskforfish = null; - } - } - public void StartLookingForFishTask() - { - if (!isDead() && _taskforfish == null) - { - int waittime = 30; - //Time for fish is dependet to lure type - if (_lure != null) - { - int lureid = _lure.getItemId(); - if (lureid == 6519 || lureid == 6522 |lureid == 6525)//low grade - waittime = 25; - else if (lureid == 6520 || lureid == 6523 |lureid == 6526)//medium grade - waittime = 20; - else if (lureid == 6521 || lureid == 6524 |lureid == 6527)//high grade - waittime = 15; - } - _taskforfish = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new LokingForFishTask(), waittime * 1000, waittime * 1000); - } - } - public void StartFishCombat() - { - _fish = new L2Fishing (this); - } - public void EndFishing(boolean win) - { - if (win) - { - //Succeeded in fishing - sendPacket(new SystemMessage(1469)); - } - ExFishingEnd efe = new ExFishingEnd(win, this); - broadcastPacket(efe); - _fishing = false; - _fishx = 0; - _fishy = 0; - _fishz = 0; - broadcastUserInfo(); - _fish = null; - _lure = null; - //Ends fishing - sendPacket(new SystemMessage(1460)); - setIsImobilised(false); - StopLookingForFishTask(); - } - public L2Fishing GetFish() - { - return _fish; - } - public int GetFishx() - { - return _fishx; - } - public int GetFishy() - { - return _fishy; - } - public int GetFishz() - { - return _fishz; - } - public void SetLure (L2ItemInstance lure) - { - _lure = lure; - } - public L2ItemInstance GetLure() - { - return _lure; - } - public int GetInventoryLimit() - { - int ivlim; - if (isGM()) { - ivlim = Config.INVENTORY_MAXIMUM_GM; - } - else if (getRace() == Race.dwarf) - { - ivlim = Config.INVENTORY_MAXIMUM_DWARF; - } - else - { - ivlim = Config.INVENTORY_MAXIMUM_NO_DWARF; - } - ivlim += (int)getStat().calcStat(Stats.INV_LIM, 0, null, null); - - return ivlim; - } - public int GetWareHouseLimit() - { - int whlim; - if (getRace() == Race.dwarf){ - whlim = Config.WAREHOUSE_SLOTS_DWARF; - } - else{ - whlim = Config.WAREHOUSE_SLOTS_NO_DWARF; - } - whlim += (int)getStat().calcStat(Stats.WH_LIM, 0, null, null); - - return whlim; - } - public int GetPrivateSellStoreLimit() - { - int pslim; - if (getRace() == Race.dwarf){ - pslim = Config.MAX_PVTSTORE_SLOTS_DWARF; - } - else{ - pslim = Config.MAX_PVTSTORE_SLOTS_OTHER; - } - pslim += (int)getStat().calcStat(Stats.P_SELL_LIM, 0, null, null); - - return pslim; - } - public int GetPrivateBuyStoreLimit() - { - int pblim; - if (getRace() == Race.dwarf){ - pblim = Config.MAX_PVTSTORE_SLOTS_DWARF; - } - else - { - pblim = Config.MAX_PVTSTORE_SLOTS_OTHER; - } - pblim += (int)getStat().calcStat(Stats.P_BUY_LIM, 0, null, null); - - return pblim; - } - public int GetFreightLimit() - { - return Config.FREIGHT_SLOTS + (int)getStat().calcStat(Stats.FREIGHT_LIM, 0, null, null); - } - - public int GetDwarfRecipeLimit() - { - int recdlim = Config.DWARF_RECIPE_LIMIT; - recdlim += (int)getStat().calcStat(Stats.REC_D_LIM, 0, null, null); - return recdlim; - } - - public int GetCommonRecipeLimit() - { - int recclim = Config.COMMON_RECIPE_LIMIT; - recclim += (int)getStat().calcStat(Stats.REC_C_LIM, 0, null, null); - return recclim; - } - - public void setMountObjectID(int newID) - { - _mountObjectID = newID; - } - - public int getMountObjectID() - { - return _mountObjectID; - } - - private L2ItemInstance _lure = null; - - /** - * Get the current skill in use or return null.

    - * - */ - public SkillDat getCurrentSkill() - { - return _currentSkill; - } - - - /** - * Create a new SkillDat object and set the player _currentSkill.

    - * - */ - public void setCurrentSkill(L2Skill currentSkill, boolean ctrlPressed, - boolean shiftPressed) - { - if (currentSkill == null) - { - if (Config.DEBUG) - _log.info("Setting current skill: NULL for " + getName() + "."); - - _currentSkill = null; - return; - } - - if (Config.DEBUG) - _log.info("Setting current skill: " + currentSkill.getName() + " (ID: " + currentSkill.getId() + ") for " + getName() + "."); - - _currentSkill = new SkillDat(currentSkill, ctrlPressed, shiftPressed); - } - - public SkillDat getQueuedSkill() - { - return _queuedSkill; - } - - - /** - * Create a new SkillDat object and queue it in the player _queuedSkill.

    - * - */ - public void setQueuedSkill(L2Skill queuedSkill, boolean ctrlPressed, boolean shiftPressed) - { - if (queuedSkill == null) - { - if (Config.DEBUG) - _log.info("Setting queued skill: NULL for " + getName() + "."); - - _queuedSkill = null; - return; - } - - if (Config.DEBUG) - _log.info("Setting queued skill: " + queuedSkill.getName() + " (ID: " + queuedSkill.getId() + ") for " + getName() + "."); - - _queuedSkill = new SkillDat(queuedSkill, ctrlPressed, shiftPressed); - } - - public boolean isInJail() - { - return _inJail; - } - - public void setInJail(boolean state) - { - _inJail = state; - } - - public void setInJail(boolean state, int delayInMinutes) - { - _inJail = state; - _jailTimer = 0; - - if (_inJail) - { - if (delayInMinutes > 0) - { - _jailTimer = delayInMinutes * 60 * 1000; // in millisec - - // start the countdown - _jailTask = ThreadPoolManager.getInstance().scheduleGeneral(new JailTask(this), _jailTimer); - sendMessage("You are in jail for "+delayInMinutes+" minutes."); - } - - // Open a Html message to inform the player - NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0); - String jailInfos = HtmCache.getInstance().getHtm("data/html/jail_in.htm"); - if (jailInfos != null) - htmlMsg.setHtml(jailInfos); - else - htmlMsg.setHtml("You have been put in jail by an admin."); - sendPacket(htmlMsg); - - teleToLocation(-114356, -249645, -2984); // Jail - } else - { - // Open a Html message to inform the player - NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0); - String jailInfos = HtmCache.getInstance().getHtm("data/html/jail_out.htm"); - if (jailInfos != null) - htmlMsg.setHtml(jailInfos); - else - htmlMsg.setHtml("You are free for now, respect server rules!"); - sendPacket(htmlMsg); - - teleToLocation(17836, 170178, -3507); // Floran - } - - // store in database - storeCharBase(); - } - - public long getJailTimer() - { - return _jailTimer; - } - - public void setJailTimer(long time) - { - _jailTimer = time; - } - - private void updateJailState() - { - if (isInJail()) - { - // If jail time is elapsed, free the player - if (_jailTimer > 0) - { - // restart the countdown - _jailTask = ThreadPoolManager.getInstance().scheduleGeneral(new JailTask(this), _jailTimer); - sendMessage("You are still in jail for "+Math.round(_jailTimer/60000)+" minutes."); - } - - // If player escaped, put him back in jail - if (!ZoneManager.getInstance().checkIfInZone(ZoneType.getZoneTypeName(ZoneType.ZoneTypeEnum.Jail), this)) - teleToLocation(-114356,-249645,-2984); - } - } - - public void stopJailTask() - { - stopJailTask(true); - } - public void stopJailTask(boolean save) - { - if (_jailTask != null) - { - if (save) - setJailTimer(_jailTask.getDelay(TimeUnit.MILLISECONDS)); - _jailTask.cancel(false); - _jailTask = null; - } - } - - private ScheduledFuture _jailTask; - private class JailTask implements Runnable - { - L2PcInstance _player; - protected long _startedAt; - - protected JailTask(L2PcInstance player) - { - _player = player; - _startedAt = System.currentTimeMillis(); - } - - public void run() - { - _player.setInJail(false, 0); - } - } -} +/* + * 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 2, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * http://www.gnu.org/copyleft/gpl.html + */ +package net.sf.l2j.gameserver.model.actor.instance; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.Calendar; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import javolution.util.FastList; +import javolution.util.FastMap; +import javolution.util.FastSet; +import net.sf.l2j.Config; +import net.sf.l2j.L2DatabaseFactory; +import net.sf.l2j.gameserver.CharTemplateTable; +import net.sf.l2j.gameserver.ClanTable; +import net.sf.l2j.gameserver.Connection; +import net.sf.l2j.gameserver.GameTimeController; +import net.sf.l2j.gameserver.GmListTable; +import net.sf.l2j.gameserver.HennaTable; +import net.sf.l2j.gameserver.ItemTable; +import net.sf.l2j.gameserver.LoginServerThread; +import net.sf.l2j.gameserver.MapRegionTable; +import net.sf.l2j.gameserver.Olympiad; +import net.sf.l2j.gameserver.RecipeController; +import net.sf.l2j.gameserver.SevenSigns; +import net.sf.l2j.gameserver.SevenSignsFestival; +import net.sf.l2j.gameserver.SkillTable; +import net.sf.l2j.gameserver.SkillTreeTable; +import net.sf.l2j.gameserver.ThreadPoolManager; +import net.sf.l2j.gameserver.Universe; +import net.sf.l2j.gameserver.ai.CtrlIntention; +import net.sf.l2j.gameserver.ai.L2CharacterAI; +import net.sf.l2j.gameserver.ai.L2PlayerAI; +import net.sf.l2j.gameserver.cache.HtmCache; +import net.sf.l2j.gameserver.communitybbs.BB.Forum; +import net.sf.l2j.gameserver.communitybbs.Manager.ForumsBBSManager; +import net.sf.l2j.gameserver.handler.IItemHandler; +import net.sf.l2j.gameserver.handler.ItemHandler; +import net.sf.l2j.gameserver.handler.skillhandlers.SiegeFlag; +import net.sf.l2j.gameserver.handler.skillhandlers.TakeCastle; +import net.sf.l2j.gameserver.instancemanager.ArenaManager; +import net.sf.l2j.gameserver.instancemanager.CastleManager; +import net.sf.l2j.gameserver.instancemanager.QuestManager; +import net.sf.l2j.gameserver.instancemanager.SiegeManager; +import net.sf.l2j.gameserver.instancemanager.ZoneManager; +import net.sf.l2j.gameserver.lib.Rnd; +import net.sf.l2j.gameserver.model.BlockList; +import net.sf.l2j.gameserver.model.Inventory; +import net.sf.l2j.gameserver.model.ItemContainer; +import net.sf.l2j.gameserver.model.L2Attackable; +import net.sf.l2j.gameserver.model.L2CharPosition; +import net.sf.l2j.gameserver.model.L2Character; +import net.sf.l2j.gameserver.model.L2Clan; +import net.sf.l2j.gameserver.model.L2ClanMember; +import net.sf.l2j.gameserver.model.L2DropData; +import net.sf.l2j.gameserver.model.L2Effect; +import net.sf.l2j.gameserver.model.L2Fishing; +import net.sf.l2j.gameserver.model.L2HennaInstance; +import net.sf.l2j.gameserver.model.L2ItemInstance; +import net.sf.l2j.gameserver.model.L2Macro; +import net.sf.l2j.gameserver.model.L2ManufactureList; +import net.sf.l2j.gameserver.model.L2Object; +import net.sf.l2j.gameserver.model.L2Party; +import net.sf.l2j.gameserver.model.L2Radar; +import net.sf.l2j.gameserver.model.L2RecipeList; +import net.sf.l2j.gameserver.model.L2ShortCut; +import net.sf.l2j.gameserver.model.L2Skill; +import net.sf.l2j.gameserver.model.L2SkillLearn; +import net.sf.l2j.gameserver.model.L2Summon; +import net.sf.l2j.gameserver.model.L2World; +import net.sf.l2j.gameserver.model.MacroList; +import net.sf.l2j.gameserver.model.PcFreight; +import net.sf.l2j.gameserver.model.PcInventory; +import net.sf.l2j.gameserver.model.PcWarehouse; +import net.sf.l2j.gameserver.model.PetInventory; +import net.sf.l2j.gameserver.model.ShortCuts; +import net.sf.l2j.gameserver.model.TradeList; +import net.sf.l2j.gameserver.model.L2Skill.SkillTargetType; +import net.sf.l2j.gameserver.model.L2Skill.SkillType; +import net.sf.l2j.gameserver.model.actor.knownlist.PcKnownList; +import net.sf.l2j.gameserver.model.actor.stat.PcStat; +import net.sf.l2j.gameserver.model.actor.status.PcStatus; +import net.sf.l2j.gameserver.model.base.ClassId; +import net.sf.l2j.gameserver.model.base.Race; +import net.sf.l2j.gameserver.model.base.SubClass; +import net.sf.l2j.gameserver.model.entity.Castle; +import net.sf.l2j.gameserver.model.entity.L2Event; +import net.sf.l2j.gameserver.model.entity.Siege; +import net.sf.l2j.gameserver.model.entity.Zone; +import net.sf.l2j.gameserver.model.entity.ZoneType; +import net.sf.l2j.gameserver.model.quest.Quest; +import net.sf.l2j.gameserver.model.quest.QuestState; +import net.sf.l2j.gameserver.model.waypoint.WayPointNode; +import net.sf.l2j.gameserver.serverpackets.ActionFailed; +import net.sf.l2j.gameserver.serverpackets.ChangeWaitType; +import net.sf.l2j.gameserver.serverpackets.CharInfo; +import net.sf.l2j.gameserver.serverpackets.ExFishingEnd; +import net.sf.l2j.gameserver.serverpackets.ExFishingStart; +import net.sf.l2j.gameserver.serverpackets.ExOlympiadMode; +import net.sf.l2j.gameserver.serverpackets.ExOlympiadUserInfo; +import net.sf.l2j.gameserver.serverpackets.HennaInfo; +import net.sf.l2j.gameserver.serverpackets.InventoryUpdate; +import net.sf.l2j.gameserver.serverpackets.ItemList; +import net.sf.l2j.gameserver.serverpackets.MagicSkillCanceld; +import net.sf.l2j.gameserver.serverpackets.MyTargetSelected; +import net.sf.l2j.gameserver.serverpackets.NpcHtmlMessage; +import net.sf.l2j.gameserver.serverpackets.ObservationMode; +import net.sf.l2j.gameserver.serverpackets.ObservationReturn; +import net.sf.l2j.gameserver.serverpackets.PartySmallWindowUpdate; +import net.sf.l2j.gameserver.serverpackets.PetInventoryUpdate; +import net.sf.l2j.gameserver.serverpackets.PledgeShowMemberListAdd; +import net.sf.l2j.gameserver.serverpackets.PrivateStoreListBuy; +import net.sf.l2j.gameserver.serverpackets.PrivateStoreListSell; +import net.sf.l2j.gameserver.serverpackets.RecipeShopSellList; +import net.sf.l2j.gameserver.serverpackets.Ride; +import net.sf.l2j.gameserver.serverpackets.SendTradeDone; +import net.sf.l2j.gameserver.serverpackets.ServerBasePacket; +import net.sf.l2j.gameserver.serverpackets.SetupGauge; +import net.sf.l2j.gameserver.serverpackets.ShortCutInit; +import net.sf.l2j.gameserver.serverpackets.Snoop; +import net.sf.l2j.gameserver.serverpackets.SocialAction; +import net.sf.l2j.gameserver.serverpackets.StatusUpdate; +import net.sf.l2j.gameserver.serverpackets.StopMove; +import net.sf.l2j.gameserver.serverpackets.SystemMessage; +import net.sf.l2j.gameserver.serverpackets.TargetSelected; +import net.sf.l2j.gameserver.serverpackets.TradeStart; +import net.sf.l2j.gameserver.serverpackets.UserInfo; +import net.sf.l2j.gameserver.skills.Stats; +import net.sf.l2j.gameserver.templates.L2Armor; +import net.sf.l2j.gameserver.templates.L2ArmorType; +import net.sf.l2j.gameserver.templates.L2CharTemplate; +import net.sf.l2j.gameserver.templates.L2Henna; +import net.sf.l2j.gameserver.templates.L2Item; +import net.sf.l2j.gameserver.templates.L2PcTemplate; +import net.sf.l2j.gameserver.templates.L2Weapon; +import net.sf.l2j.gameserver.templates.L2WeaponType; +import net.sf.l2j.gameserver.util.Broadcast; +import net.sf.l2j.gameserver.util.Util; +import net.sf.l2j.util.Point3D; + +/** + * This class represents all player characters in the world. + * There is always a client-thread connected to this (except if a player-store is activated upon logout).

    + * + * @version $Revision: 1.66.2.41.2.33 $ $Date: 2005/04/11 10:06:09 $ + */ +public final class L2PcInstance extends L2PlayableInstance +{ + private static final String RESTORE_SKILLS_FOR_CHAR = "SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? AND class_index=?"; + private static final String ADD_NEW_SKILL = "INSERT INTO character_skills (char_obj_id,skill_id,skill_level,skill_name,class_index) VALUES (?,?,?,?,?)"; + private static final String UPDATE_CHARACTER_SKILL_LEVEL = "UPDATE character_skills SET skill_level=? WHERE skill_id=? AND char_obj_id=? AND class_index=?"; + private static final String DELETE_SKILL_FROM_CHAR = "DELETE FROM character_skills WHERE skill_id=? AND char_obj_id=? AND class_index=?"; + private static final String DELETE_CHAR_SKILLS = "DELETE FROM character_skills WHERE char_obj_id=? AND class_index=?"; + + private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (char_obj_id,skill_id,skill_level,effect_count,effect_cur_time,class_index) VALUES (?,?,?,?,?,?)"; + private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,effect_count,effect_cur_time FROM character_skills_save WHERE char_obj_id=? AND class_index=?"; + private static final String DELETE_SKILL_SAVE = "DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=?"; + + private static final String UPDATE_CHARACTER = "UPDATE characters SET level=?,maxHp=?,curHp=?,maxCp=?,curCp=?,maxMp=?,curMp=?,str=?,con=?,dex=?,_int=?,men=?,wit=?,face=?,hairStyle=?,hairColor=?,heading=?,x=?,y=?,z=?,exp=?,sp=?,karma=?,pvpkills=?,pkkills=?,rec_have=?,rec_left=?,clanid=?,maxload=?,race=?,classid=?,deletetime=?,title=?,allyId=?,accesslevel=?,online=?,isin7sdungeon=?,clan_privs=?,wantspeace=?,deleteclan=?,base_class=?,onlinetime=?,in_jail=?,jail_timer=?,newbie=? WHERE obj_id=?"; + private static final String RESTORE_CHARACTER = "SELECT account_name, obj_Id, char_name, level, maxHp, curHp, maxCp, curCp, maxMp, curMp, acc, crit, evasion, mAtk, mDef, mSpd, pAtk, pDef, pSpd, runSpd, walkSpd, str, con, dex, _int, men, wit, face, hairStyle, hairColor, sex, heading, x, y, z, movement_multiplier, attack_speed_multiplier, colRad, colHeight, exp, sp, karma, pvpkills, pkkills, clanid, maxload, race, classid, deletetime, cancraft, title, allyId, rec_have, rec_left, accesslevel, online, char_slot, lastAccess, clan_privs, wantspeace, deleteclan, base_class, onlinetime, isin7sdungeon, in_jail, jail_timer, newbie FROM characters WHERE obj_id=?"; + private static final String RESTORE_CHAR_SUBCLASSES = "SELECT class_id,exp,sp,level,class_index FROM character_subclasses WHERE char_obj_id=? ORDER BY class_index ASC"; + private static final String ADD_CHAR_SUBCLASS = "INSERT INTO character_subclasses (char_obj_id,class_id,exp,sp,level,class_index) VALUES (?,?,?,?,?,?)"; + private static final String UPDATE_CHAR_SUBCLASS = "UPDATE character_subclasses SET exp=?,sp=?,level=?,class_id=? WHERE char_obj_id=? AND class_index =?"; + private static final String DELETE_CHAR_SUBCLASS = "DELETE FROM character_subclasses WHERE char_obj_id=? AND class_index=?"; + + private static final String RESTORE_CHAR_HENNAS = "SELECT slot,symbol_id FROM character_hennas WHERE char_obj_id=? AND class_index=?"; + private static final String ADD_CHAR_HENNA = "INSERT INTO character_hennas (char_obj_id,symbol_id,slot,class_index) VALUES (?,?,?,?)"; + private static final String DELETE_CHAR_HENNA = "DELETE FROM character_hennas WHERE char_obj_id=? AND slot=? AND class_index=?"; + private static final String DELETE_CHAR_HENNAS = "DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=?"; + private static final String DELETE_CHAR_SHORTCUTS = "DELETE FROM character_shortcuts WHERE char_obj_id=? AND class_index=?"; + + public static final int REQUEST_TIMEOUT = 15; + + public static final int STORE_PRIVATE_NONE = 0; + public static final int STORE_PRIVATE_SELL = 1; + public static final int STORE_PRIVATE_BUY = 3; + public static final int STORE_PRIVATE_MANUFACTURE = 5; + + /** The table containing all minimum level needed for each Expertise (None, D, C, B, A, S)*/ + private static final int[] EXPERTISE_LEVELS = + { + SkillTreeTable.getInstance().getExpertiseLevel(0), //NONE + SkillTreeTable.getInstance().getExpertiseLevel(1), //D + SkillTreeTable.getInstance().getExpertiseLevel(2), //C + SkillTreeTable.getInstance().getExpertiseLevel(3), //B + SkillTreeTable.getInstance().getExpertiseLevel(4), //A + SkillTreeTable.getInstance().getExpertiseLevel(5), //S + }; + + private static final int[] COMMON_CRAFT_LEVELS = + { + 5,20,28,36,43,49,55,62 + }; + + //private static Logger _log = Logger.getLogger(L2PcInstance.class.getName()); + + public class AIAccessor extends L2Character.AIAccessor + { + protected AIAccessor() {} + public L2PcInstance getPlayer() { return L2PcInstance.this; } + public void doPickupItem(L2Object object) { + L2PcInstance.this.doPickupItem(object); + } + public void doInteract(L2Character target) { + L2PcInstance.this.doInteract(target); + } + + public void doAttack(L2Character target) + { + super.doAttack(target); + + for (L2CubicInstance cubic : getCubics().values()) + if (cubic.getId() != L2CubicInstance.LIFE_CUBIC) + cubic.doAction(target); + } + } + + private Connection _connection; + + //private L2Object _newTarget = null; + + /** The Identifier of the L2PcInstance */ + private int _charId = 0x00030b7a; + + /** The Experience of the L2PcInstance before the last Death Penalty */ + private int _expBeforeDeath = 0; + + /** The Karma of the L2PcInstance (if higher than 0, the name of the L2PcInstance appears in red) */ + private int _karma; + + /** The number of player killed during a PvP (the player killed was PvP Flagged) */ + private int _pvpKills; + + /** The hexadecimal Color of players name (white is 0xFFFFFF) */ + private int _nameColor; + + /** The PK counter of the L2PcInstance (= Number of non PvP Flagged player killed) */ + private int _pkKills; + + /** The PvP Flag state of the L2PcInstance (0=White, 1=Purple) */ + private int _pvpFlag; + + private boolean _inPvpZone; + + /** The number of recommandation obtained by the L2PcInstance */ + private int _recomHave; // how much I was recommended by others + + /** The number of recommandation that the L2PcInstance can give */ + private int _recomLeft; // how many recomendations I can give to others + + /** List with the recomendations that I've give */ + private List _recomChars = new FastList(); + + /** The random number of the L2PcInstance */ + //private static final Random _rnd = new Random(); + + private final int _baseLoad; + private int _curWeightPenalty = 0; + + private int _deleteTimer; + private PcInventory _inventory = new PcInventory(this); + private PcWarehouse _warehouse = new PcWarehouse(this); + private PcFreight _freight = new PcFreight(this); + + /** True if the L2PcInstance is sitting */ + private boolean _waitTypeSitting; + + /** True if the L2PcInstance is using the relax skill */ + private boolean _relax; + + /** True if the L2PcInstance is in a boat */ + private boolean _inBoat; + + /** Last NPC Id talked on a quest */ + private int _questNpcObject = 0; + + /** The face type Identifier of the L2PcInstance */ + private int _face; + + /** The hair style Identifier of the L2PcInstance */ + private int _hairStyle; + + /** The hair color Identifier of the L2PcInstance */ + private int _hairColor; + + /** True if the L2PcInstance is newbie */ + private boolean _newbie; + + /** The table containing all Quests began by the L2PcInstance */ + private Map _quests = new FastMap(); + + /** The list containing all shortCuts of this L2PcInstance */ + private ShortCuts _shortCuts = new ShortCuts(this); + + /** The list containing all macroses of this L2PcInstance */ + private MacroList _macroses = new MacroList(this); + + /** The Alliance Identifier of the L2PcInstance */ + //private int _allyId; + + private TradeList _activeTradeList; + private ItemContainer _activeWarehouse; + private L2ManufactureList _createList; + private TradeList _sellList; + private TradeList _buyList; + + private List _SnoopListener = new FastList(); + private List _SnoopedPlayer = new FastList(); + + /** The Private Store type of the L2PcInstance (STORE_PRIVATE_NONE=0, STORE_PRIVATE_SELL=1, sellmanage=2, STORE_PRIVATE_BUY=3, buymanage=4, STORE_PRIVATE_MANUFACTURE=5) */ + private int _privatestore; + private ClassId _skillLearningClassId; + + // hennas + private final L2HennaInstance[] _henna = new L2HennaInstance[3]; + private int _hennaSTR; + private int _hennaINT; + private int _hennaDEX; + private int _hennaMEN; + private int _hennaWIT; + private int _hennaCON; + + /** The L2Summon of the L2PcInstance */ + private L2Summon _summon = null; + + // client radar + //TODO: This needs to be better intergrated and saved/loaded + private L2Radar _radar; + + // these values are only stored temporarily + private boolean _partyMatchingAutomaticRegistration; + private boolean _partyMatchingShowLevel; + private boolean _partyMatchingShowClass; + private String _partyMatchingMemo; + + private L2Party _party; + // clan related attributes + + /** The Clan Identifier of the L2PcInstance */ + private int _clanId; + + /** The Clan object of the L2PcInstance */ + private L2Clan _clan; + + /** The Clan Leader Flag of the L2PcInstance (True : the L2PcInstance is the leader of the clan) */ + private boolean _clanLeader; + + private long _deleteClanTime; + + private long _onlineTime; + private long _onlineBeginTime; + + //GM Stuff + private boolean _isInvul; + private boolean _isGm; + private int _accessLevel; + + private boolean _chatBanned = false; // Chat Banned + private ScheduledFuture _chatUnbanTask = null; + private boolean _messageRefusal = false; // message refusal mode + private boolean _dietMode = false; // ignore weight penalty + private boolean _tradeRefusal = false; // Trade refusal + private boolean _exchangeRefusal = false; // Exchange refusal + + public boolean _exploring = false; + + // this is needed to find the inviting player for Party response + // there can only be one active party request at once + private L2PcInstance _activeRequester; + private long _requestExpireTime = 0; + private L2ItemInstance _arrowItem; + + // Used for protection after teleport + private long _protectEndTime = 0; + + /** The fists L2Weapon of the L2PcInstance (used when no weapon is equiped) */ + private L2Weapon _fistsWeaponItem; + + private long _uptime; + private String _accountName; + + private final Map _chars = new FastMap(); + + public byte _updateKnownCounter = 0; + + /** The table containing all L2RecipeList of the L2PcInstance */ + private Map _dwarvenRecipeBook = new FastMap(); + private Map _commonRecipeBook = new FastMap(); + + private int _mountType; + + /** The current higher Expertise of the L2PcInstance (None=0, D=1, C=2, B=3, A=4, S=5)*/ + private int _expertiseIndex; // index in EXPERTISE_LEVELS + private int _expertisePenalty = 0; + + private L2ItemInstance _activeEnchantItem = null; + + private boolean _isOnline = false; + private boolean _isIn7sDungeon = false; + + protected boolean _inventoryDisable = false; + + protected Map _cubics = new FastMap(); + + /** The L2FolkInstance corresponding to the last Folk wich one the player talked. */ + private L2FolkInstance _lastFolkNpc = null; + + private boolean _isSilentMoving = false; + + protected Set _activeSoulShots = new FastSet(); + private boolean _isPathNodeMode; + private boolean _isPathNodesVisible; + private Map> _pathNodeMap; + private WayPointNode _selectedNode; + private int _clanPrivileges = 0; + private boolean _linkToggle = true; + + /** 1 if the player is invisible */ + private int _invisible = 0; + + /** Location before entering Observer Mode */ + private int _obsX; + private int _obsY; + private int _obsZ; + private boolean _observerMode = false; + + /** Event parameters */ + public int eventX; + public int eventY; + public int eventZ; + public int eventkarma; + public int eventpvpkills; + public int eventpkkills; + public String eventTitle; + public LinkedList kills = new LinkedList(); + public boolean eventSitForced = false; + public boolean atEvent = false; + + public int _telemode = 0; + + /** new loto ticket **/ + public int _loto[] = new int[5]; + //public static int _loto_nums[] = {0,1,2,3,4,5,6,7,8,9,}; + /** new race ticket **/ + public int _race[] = new int[2]; + + private final BlockList _blockList = new BlockList(); + private boolean _isConnected = true; + + private boolean _hero = false; + private int _team = 0; + private int _wantsPeace = 0; + + private boolean _noble = false; + private boolean _inOlympiadMode = false; + private int _olympiadGameId = -1; + private int _olympiadSide = -1; + + /** The list of sub-classes this character has. */ + private Map _subClasses; + protected int _baseClass; + protected int _activeClass; + protected int _classIndex = 0; + + private long _lastAccess; + private int _boatId; + + private L2Fishing _fish; + private boolean _fishing = false; + private int _fishx = 0; + private int _fishy = 0; + private int _fishz = 0; + + private ScheduledFuture _taskRentPet; + private ScheduledFuture _taskWater; + private L2BoatInstance _boat; + private Point3D _inBoatPosition; + + /** Stored from last ValidatePosition **/ + public Point3D _lastClientPosition = new Point3D(0, 0, 0); + public Point3D _lastServerPosition = new Point3D(0, 0, 0); + + /** Bypass validations */ + private List _validBypass = new FastList(); + private List _validBypass2 = new FastList(); + + private boolean _inCrystallize; + private boolean _inCraftMode; + private Forum _forumMail; + private Forum _forumMemo; + + /** Current skill in use */ + private SkillDat _currentSkill; + + /** Skills queued because a skill is already in progress */ + private SkillDat _queuedSkill; + + /** Store object used to summon the strider you are mounting **/ + private int _mountObjectID = 0; + + private boolean _inJail = false; + private long _jailTimer = 0; + + /** Flag to disable equipment/skills while wearing formal wear **/ + private boolean _IsWearingFormalWear = false; + + + /** Skill casting information (used to queue when several skills are cast in a short time) **/ + public class SkillDat + { + private L2Skill _skill; + private boolean _ctrlPressed; + private boolean _shiftPressed; + + protected SkillDat(L2Skill skill, boolean ctrlPressed, boolean shiftPressed) + { + _skill = skill; + _ctrlPressed = ctrlPressed; + _shiftPressed = shiftPressed; + } + + public boolean isCtrlPressed() + { + return _ctrlPressed; + } + + public boolean isShiftPressed() + { + return _shiftPressed; + } + + public L2Skill getSkill() + { + return _skill; + } + + public int getSkillId() + { + return (getSkill() != null) ? getSkill().getId() : -1; + } + } + + /** + * Create a new L2PcInstance and add it in the characters table of the database.

    + * + * Actions :

    + *
  • Create a new L2PcInstance with an account name
  • + *
  • Set the name, the Hair Style, the Hair Color and the Face type of the L2PcInstance
  • + *
  • Add the player in the characters table of the database


  • + * + * @param objectId Identifier of the object to initialized + * @param template The L2PcTemplate to apply to the L2PcInstance + * @param accountName The name of the L2PcInstance + * @param name The name of the L2PcInstance + * @param hairStyle The hair style Identifier of the L2PcInstance + * @param hairColor The hair color Identifier of the L2PcInstance + * @param face The face type Identifier of the L2PcInstance + * + * @return The L2PcInstance added to the database or null + * + */ + public static L2PcInstance create(int objectId, L2PcTemplate template, String accountName, + String name, int hairStyle, int hairColor, int face) + { + // Create a new L2PcInstance with an account name + L2PcInstance player = new L2PcInstance(objectId, template, accountName); + + // Set the name of the L2PcInstance + player.setName(name); + + // Set the Hair Style of the L2PcInstance + player.setHairStyle(hairStyle); + + // Set the Hair Color of the L2PcInstance + player.setHairColor(hairColor); + + // Set the Face type of the L2PcInstance + player.setFace(face); + + // Set the base class ID to that of the actual class ID. + player.setBaseClass(player.getClassId()); + + if (Config.ALT_GAME_NEW_CHAR_ALWAYS_IS_NEWBIE) + player.setNewbie(true); + + // Add the player in the characters table of the database + boolean ok = player.createDb(); + + if (!ok) + return null; + + return player; + } + + public static L2PcInstance createDummyPlayer(int objectId, String name) + { + // Create a new L2PcInstance with an account name + L2PcInstance player = new L2PcInstance(objectId); + player.setName(name); + + return player; + } + + public String getAccountName() + { + if (_connection == null) + return ""; + + return _connection.getClient().getLoginName(); + } + + public Map getAccountChars() + { + return _chars; + } + + /** + * Retrieve a L2PcInstance from the characters table of the database and add it in _allObjects of the L2world (call restore method).

    + * + * Actions :

    + *
  • Retrieve the L2PcInstance from the characters table of the database
  • + *
  • Add the L2PcInstance object in _allObjects
  • + *
  • Set the x,y,z position of the L2PcInstance and make it invisible
  • + *
  • Update the overloaded status of the L2PcInstance


  • + * + * @param objectId Identifier of the object to initialized + * + * @return The L2PcInstance loaded from the database + * + */ + public static L2PcInstance load(int objectId) + { + return restore(objectId); + } + + /** + * Constructor of L2PcInstance (use L2Character constructor).

    + * + * Actions :

    + *
  • Call the L2Character constructor to create an empty _skills slot and copy basic Calculator set to this L2PcInstance
  • + *
  • Set the name of the L2PcInstance


  • + * + * Caution : This method SET the level of the L2PcInstance to 1

    + * + * @param objectId Identifier of the object to initialized + * @param template The L2PcTemplate to apply to the L2PcInstance + * @param accountName The name of the account including this L2PcInstance + * + */ + private L2PcInstance(int objectId, L2PcTemplate template, String accountName) + { + super(objectId, template); + super.setKnownList(new PcKnownList(new L2PcInstance[] {this})); + super.setStat(new PcStat(new L2PcInstance[] {this})); + super.setStatus(new PcStatus(new L2PcInstance[] {this})); + + _accountName = accountName; + _nameColor = 0xFFFFFF; + _baseLoad = template.baseLoad; + + // Create an AI + _ai = new L2PlayerAI(new L2PcInstance.AIAccessor()); + + // Create a L2Radar object + _radar = new L2Radar(this); + + // Retrieve from the database all skills of this L2PcInstance and add them to _skills + // Retrieve from the database all items of this L2PcInstance and add them to _inventory + getInventory().restore(); + getWarehouse().restore(); + getFreight().restore(); + } + + private L2PcInstance(int objectId) + { + super(objectId, null); + super.setKnownList(new PcKnownList(new L2PcInstance[] {this})); + super.setStat(new PcStat(new L2PcInstance[] {this})); + super.setStatus(new PcStatus(new L2PcInstance[] {this})); + + _baseLoad = 0; + } + + public final PcKnownList getKnownList() { return (PcKnownList)super.getKnownList(); } + public final PcStat getStat() { return (PcStat)super.getStat(); } + public final PcStatus getStatus() { return (PcStatus)super.getStatus(); } + + /** + * Return the base L2PcTemplate link to the L2PcInstance.

    + */ + public final L2PcTemplate getBaseTemplate() + { + return CharTemplateTable.getInstance().getTemplate(_baseClass, getSex() == 1); + } + + /** Return the L2PcTemplate link to the L2PcInstance. */ + public final L2PcTemplate getTemplate() { return (L2PcTemplate)super.getTemplate(); } + + public void setTemplate(ClassId newclass, boolean female) { super.setTemplate(CharTemplateTable.getInstance().getTemplate(newclass, female)); } + + public void changeSex() { super.setTemplate(CharTemplateTable.getInstance().getTemplate(getClassId(), (getSex() == 1))); } + + /** + * Return the AI of the L2PcInstance (create it if necessary).

    + */ + public L2CharacterAI getAI() + { + if (_ai == null) + { + synchronized(this) + { + if (_ai == null) + _ai = new L2PlayerAI(new L2PcInstance.AIAccessor()); + } + } + + return _ai; + } + + + /** + * Calculate a destination to explore the area and set the AI Intension to AI_INTENTION_MOVE_TO.

    + */ + public void explore() + { + if (!_exploring) return; + + if(getMountType() == 2) + return; + + // Calculate the destination point (random) + + int x = getX()+Rnd.nextInt(6000)-3000; + int y = getY()+Rnd.nextInt(6000)-3000; + + if (x > Universe.MAX_X) x = Universe.MAX_X; + if (x < Universe.MIN_X) x = Universe.MIN_X; + if (y > Universe.MAX_Y) y = Universe.MAX_Y; + if (y < Universe.MIN_Y) y = Universe.MIN_Y; + + int z = getZ(); + + L2CharPosition pos = new L2CharPosition(x,y,z,0); + + // Set the AI Intention to AI_INTENTION_MOVE_TO + getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO,pos); + + } + + /** Return the Level of the L2PcInstance. */ + public final int getLevel() { return getStat().getLevel(); } + + /** + * Return the Sex of the L2PcInstance (Male=0, Female=1).

    + */ + public int getSex() { return getTemplate().isMale ? 0 : 1; } + + /** + * Return the Face type Identifier of the L2PcInstance.

    + */ + public int getFace() + { + return _face; + } + + /** + * Set the Face type of the L2PcInstance.

    + * + * @param face The Identifier of the Face type

    + * + */ + public void setFace(int face) + { + _face = face; + } + + /** + * Return the Hair Color Identifier of the L2PcInstance.

    + */ + public int getHairColor() + { + return _hairColor; + } + + /** + * Set the Hair Color of the L2PcInstance.

    + * + * @param hairColor The Identifier of the Hair Color

    + * + */ + public void setHairColor(int hairColor) + { + _hairColor = hairColor; + } + + /** + * Return the Hair Style Identifier of the L2PcInstance.

    + */ + public int getHairStyle() + { + return _hairStyle; + } + + /** + * Set the Hair Style of the L2PcInstance.

    + * + * @param hairStyle The Identifier of the Hair Style

    + * + */ + public void setHairStyle(int hairStyle) + { + _hairStyle = hairStyle; + } + + /** + * Return the _newbie state of the L2PcInstance.

    + */ + public boolean isNewbie() + { + return _newbie; + } + + /** + * Set the _newbie state of the L2PcInstance.

    + * + * @param isNewbie The Identifier of the _newbie state

    + * + */ + public void setNewbie(boolean isNewbie) + { + _newbie = isNewbie; + } + + + public void setBaseClass(int baseClass) + { + _baseClass = baseClass; + } + + public void setBaseClass(ClassId classId) + { + _baseClass = classId.ordinal(); + } + + public boolean isInStoreMode() { return (getPrivateStoreType() > 0); } +// public boolean isInCraftMode() { return (getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE); } + + public boolean isInCraftMode() + { + return _inCraftMode; + } + + public void isInCraftMode(boolean b) + { + _inCraftMode = b; + } + + /** + * Manage Logout Task.

    + */ + public void logout() + { + // Delete all Path Nodes + clearPathNodes(); + + // Close the connection with the client + if (_connection != null) + _connection.close(); + } + + /** + * Return a table containing all Common L2RecipeList of the L2PcInstance.

    + */ + public L2RecipeList[] getCommonRecipeBook() + { + return _commonRecipeBook.values().toArray(new L2RecipeList[_commonRecipeBook.values().size()]); + } + + /** + * Return a table containing all Dwarf L2RecipeList of the L2PcInstance.

    + */ + public L2RecipeList[] getDwarvenRecipeBook() + { + return _dwarvenRecipeBook.values().toArray(new L2RecipeList[_dwarvenRecipeBook.values().size()]); + } + + /** + * Add a new L2RecipList to the table _commonrecipebook containing all L2RecipeList of the L2PcInstance

    + * + * @param recipe The L2RecipeList to add to the _recipebook + * + */ + public void registerCommonRecipeList(L2RecipeList recipe) + { + _commonRecipeBook.put(recipe.getId(), recipe); + } + + /** + * Add a new L2RecipList to the table _recipebook containing all L2RecipeList of the L2PcInstance

    + * + * @param recipe The L2RecipeList to add to the _recipebook + * + */ + public void registerDwarvenRecipeList(L2RecipeList recipe) + { + _dwarvenRecipeBook.put(recipe.getId(), recipe); + } + + /** + * @param RecipeID The Identifier of the L2RecipeList to check in the player's recipe books + * + * @return + * TRUE if player has the recipe on Common or Dwarven Recipe book else returns FALSE + */ + public boolean hasRecipeList(int recipeId) + { + if (_dwarvenRecipeBook.containsKey(recipeId)) + return true; + else if(_commonRecipeBook.containsKey(recipeId)) + return true; + else + return false; + } + + /** + * Tries to remove a L2RecipList from the table _DwarvenRecipeBook or from table _CommonRecipeBook, those table contain all L2RecipeList of the L2PcInstance

    + * + * @param RecipeID The Identifier of the L2RecipeList to remove from the _recipebook + * + */ + public void unregisterRecipeList(int recipeId) + { + if (_dwarvenRecipeBook.containsKey(recipeId)) + _dwarvenRecipeBook.remove(recipeId); + else if(_commonRecipeBook.containsKey(recipeId)) + _commonRecipeBook.remove(recipeId); + else + _log.warning("Attempted to remove unknown RecipeList: "+recipeId); + } + + /** + * Returns the Id for the last talked quest NPC.

    + */ + public int getLastQuestNpcObject() + { + return _questNpcObject; + } + + public void setLastQuestNpcObject(int npcId) + { + _questNpcObject = npcId; + } + + /** + * Add Quest drops to the table containing all possible drops of a L2NpcInstance.

    + * + * @param npc The L2NpcInstance killed by the L2PcInstance + * @param drops The table containing all possible drops of the L2NpcInstance + * + */ + public void fillQuestDrops(L2NpcInstance npc, List drops) + { + for (QuestState qs : _quests.values()) + qs.fillQuestDrops(npc, drops); + } + + /** + * Return the QuestState object corresponding to the quest name.

    + * + * @param quest The name of the quest + * + */ + public QuestState getQuestState(String quest) + { + return _quests.get(quest); + } + + /** + * Add a QuestState to the table _quest containing all quests began by the L2PcInstance.

    + * + * @param qs The QuestState to add to _quest + * + */ + public void setQuestState(QuestState qs) + { + _quests.put(qs.getQuest().getName(), qs); + } + + + /** + * Remove a QuestState from the table _quest containing all quests began by the L2PcInstance.

    + * + * @param quest The name of the quest + * + */ + public void delQuestState(String quest) + { + _quests.remove(quest); + } + + private QuestState[] addToQuestStateArray(QuestState[] questStateArray, QuestState state) { + int len = questStateArray.length; + QuestState[] tmp = new QuestState[len+1]; + for (int i=0; i < len; i++) + tmp[i] = questStateArray[i]; + tmp[len] = state; + return tmp; + } + + /** + * Return a table containing all Quest in progress from the table _quests.

    + */ + public Quest[] getAllActiveQuests() + { + FastList quests = new FastList(); + + for (QuestState qs : _quests.values()) + { + if (qs.getQuest().getQuestIntId()>=1999) + continue; + + if (qs.isCompleted() && !Config.DEVELOPER) + continue; + + if (!qs.isStarted() && !Config.DEVELOPER) + continue; + + quests.add(qs.getQuest()); + } + + return quests.toArray(new Quest[quests.size()]); + } + + /** + * Return a table containing all QuestState to modify after a L2Attackable killing.

    + * + * @param npcId The Identifier of the L2Attackable attacked + * + */ + public QuestState[] getQuestsForAttacks(L2NpcInstance npc) + { + // Create a QuestState table that will contain all QuestState to modify + QuestState[] states = null; + + // Go through the QuestState of the L2PcInstance quests + for (QuestState qs : _quests.values()) + { + // Check if the Identifier of the L2Attackable attck is needed for the current quest + if (qs.waitsForAttack(npc)) + { + // Copy the current L2PcInstance QuestState in the QuestState table + if (states == null) + states = new QuestState[]{qs}; + else + states = addToQuestStateArray(states, qs); + } + } + + // Return a table containing all QuestState to modify + return states; + } + + /** + * Return a table containing all QuestState to modify after a L2Attackable killing.

    + * + * @param npcId The Identifier of the L2Attackable killed + * + */ + public QuestState[] getQuestsForKills(L2NpcInstance npc) + { + // Create a QuestState table that will contain all QuestState to modify + QuestState[] states = null; + + // Go through the QuestState of the L2PcInstance quests + for (QuestState qs : _quests.values()) + { + // Check if the Identifier of the L2Attackable killed is needed for the current quest + if (qs.waitsForKill(npc)) + { + // Copy the current L2PcInstance QuestState in the QuestState table + if (states == null) + states = new QuestState[]{qs}; + else + states = addToQuestStateArray(states, qs); + } + } + + // Return a table containing all QuestState to modify + return states; + } + + /** + * Return a table containing all QuestState from the table _quests in which the L2PcInstance must talk to the NPC.

    + * + * @param npcId The Identifier of the NPC + * + */ + public QuestState[] getQuestsForTalk(int npcId) + { + // Create a QuestState table that will contain all QuestState to modify + QuestState[] states = null; + + // Go through the QuestState of the L2PcInstance quests + for (QuestState qs : _quests.values()) + { + // Check if the Identifier of the L2Attackable talk is needed for the current quest + if (qs.waitsForTalk(npcId)) + { + // Copy the current L2PcInstance QuestState in the QuestState table + if (states == null) + states = new QuestState[]{qs}; + else + states = addToQuestStateArray(states, qs); + } + } + + // Return a table containing all QuestState to modify + return states; + } + + public QuestState processQuestEvent(String quest, String event) + { + QuestState retval = null; + if (event == null) + event = ""; + if (!_quests.containsKey(quest)) + return retval; + QuestState qs = getQuestState(quest); + if (qs == null && event.length() == 0) + return retval; + if (qs == null) { + Quest q = QuestManager.getInstance().getQuest(quest); + if (q == null) + return retval; + qs = q.newQuestState(this); + } + if (qs != null) { + if (getLastQuestNpcObject() > 0) + { + L2Object object = L2World.getInstance().findObject(getLastQuestNpcObject()); + if (object instanceof L2NpcInstance && isInsideRadius(object, L2NpcInstance.INTERACTION_DISTANCE, false, false)) + { + L2NpcInstance npc = (L2NpcInstance)object; + QuestState[] states = getQuestsForTalk(npc.getNpcId()); + + if (states != null) + { + for (QuestState state : states) + { + if ((state.getQuest().getQuestIntId() == qs.getQuest().getQuestIntId()) && !qs.isCompleted()) + { + if (qs.getQuest().notifyEvent(event, qs)) + showQuestWindow(quest, qs.getStateId()); + + retval = qs; + } + } + } + } + } + } + + return retval; + } + + private void showQuestWindow(String questId, String stateId) + { + String path = "data/jscript/quests/"+questId+"/"+stateId+".htm"; + String content = HtmCache.getInstance().getHtm(path); //TODO path for quests html + + if (content != null) + { + if (Config.DEBUG) + _log.fine("Showing quest window for quest "+questId+" state "+stateId+" html path: " + path); + + NpcHtmlMessage npcReply = new NpcHtmlMessage(5); + npcReply.setHtml(content); + sendPacket(npcReply); + } + + sendPacket( new ActionFailed() ); + } + + /** + * Return a table containing all L2ShortCut of the L2PcInstance.

    + */ + public L2ShortCut[] getAllShortCuts() + { + return _shortCuts.getAllShortCuts(); + } + + /** + * Return the L2ShortCut of the L2PcInstance corresponding to the position (page-slot).

    + * + * @param slot The slot in wich the shortCuts is equiped + * @param page The page of shortCuts containing the slot + * + */ + public L2ShortCut getShortCut(int slot, int page) + { + return _shortCuts.getShortCut(slot, page); + } + + /** + * Add a L2shortCut to the L2PcInstance _shortCuts

    + */ + public void registerShortCut(L2ShortCut shortcut) + { + _shortCuts.registerShortCut(shortcut); + } + + /** + * Delete the L2ShortCut corresponding to the position (page-slot) from the L2PcInstance _shortCuts.

    + */ + public void deleteShortCut(int slot, int page) + { + _shortCuts.deleteShortCut(slot, page); + } + + /** + * Add a L2Macro to the L2PcInstance _macroses

    + */ + public void registerMacro(L2Macro macro) + { + _macroses.registerMacro(macro); + } + + /** + * Delete the L2Macro corresponding to the Identifier from the L2PcInstance _macroses.

    + */ + public void deleteMacro(int id) + { + _macroses.deleteMacro(id); + } + + /** + * Return all L2Macro of the L2PcInstance.

    + */ + public MacroList getMacroses() + { + return _macroses; + } + + /** + * Set the PvP Flag of the L2PcInstance.

    + */ + public void setPvpFlag(int pvpFlag) + { + _pvpFlag = pvpFlag; + } + + public boolean getInPvpZone() + { + return _inPvpZone; + } + + /** + * Update the _inPvpZone flag and send a message to player.

    + * @param inPvpZone : true if player is in a pvp zone + * @see net.sf.l2j.gameserver.model.actor.instance.L2PcInstance.setInPvpZone(boolean, boolean) + */ + public void setInPvpZone(boolean inPvpZone) + { + setInPvpZone(inPvpZone, true); + } + /** + * Update the _inPvpZone flag.

    + * @param inPvpZone : true if player is in a pvp zone + * @param warnPlayer : true if a message should be send to player + */ + public void setInPvpZone(boolean inPvpZone, boolean warnPlayer) + { + if (_inPvpZone != inPvpZone) + { + _inPvpZone = inPvpZone; + + if (warnPlayer) + if (_inPvpZone) + sendPacket(new SystemMessage(283)); + else + sendPacket(new SystemMessage(284)); + } + } + + private void revalidateInPvpZone () + { + setInPvpZone(ZoneManager.getInstance().checkIfInZonePvP(this)); + } + + public void revalidateZone() + { + revalidateInPvpZone(); + } + + /** + * Return True if the L2PcInstance can Craft Dwarven Recipes.

    + */ + public boolean hasDwarvenCraft() + { + return getSkillLevel(L2Skill.SKILL_CREATE_DWARVEN) >= 1; + } + + public int getDwarvenCraft() + { + return getSkillLevel(L2Skill.SKILL_CREATE_DWARVEN); + } + + /** + * Return True if the L2PcInstance can Craft Dwarven Recipes.

    + */ + public boolean hasCommonCraft() + { + return getSkillLevel(L2Skill.SKILL_CREATE_COMMON) >= 1; + } + + public int getCommonCraft() + { + return getSkillLevel(L2Skill.SKILL_CREATE_COMMON); + } + + /** + * Return the PK counter of the L2PcInstance.

    + */ + public int getPkKills() + { + return _pkKills; + } + + /** + * Set the PK counter of the L2PcInstance.

    + */ + public void setPkKills(int pkKills) + { + _pkKills = pkKills; + } + + /** + * Return the _deleteTimer of the L2PcInstance.

    + */ + public int getDeleteTimer() + { + return _deleteTimer; + } + + /** + * Set the _deleteTimer of the L2PcInstance.

    + */ + public void setDeleteTimer(int deleteTimer) + { + _deleteTimer = deleteTimer; + } + + /** + * Return the current weight of the L2PcInstance.

    + */ + public int getCurrentLoad() + { + return _inventory.getTotalWeight(); + } + /** + * Return the number of recommandation obtained by the L2PcInstance.

    + */ + public int getRecomHave() + { + return _recomHave; + } + + /** + * Increment the number of recommandation obtained by the L2PcInstance (Max : 255).

    + */ + protected void incRecomHave() + { + if (_recomHave < 255) + _recomHave++; + } + + /** + * Set the number of recommandation obtained by the L2PcInstance (Max : 255).

    + */ + public void setRecomHave(int value) + { + if (value > 255) + _recomHave = 255; + else if (value < 0) + _recomHave = 0; + else + _recomHave = value; + } + + + + /** + * Return the number of recommandation that the L2PcInstance can give.

    + */ + public int getRecomLeft() + { + return _recomLeft; + } + + /** + * Increment the number of recommandation that the L2PcInstance can give.

    + */ + protected void decRecomLeft() + { + if (_recomLeft > 0) + _recomLeft--; + } + + public void giveRecom(L2PcInstance target) + { + target.incRecomHave(); + decRecomLeft(); + _recomChars.add(target.getName().hashCode()); + } + + public boolean canRecom(L2PcInstance target) + { + return !_recomChars.contains(target.getName().hashCode()); + } + + /** + * Return the Karma of the L2PcInstance.

    + */ + public int getKarma() + { + return _karma; + } + + /** + * Set the Karma of the L2PcInstance and send a Server->Client packet StatusUpdate (broadcast).

    + */ + public void setKarma(int karma) + { + if (karma < 0) karma = 0; + if (_karma == 0 && karma > 0) + { + for (L2Object object : getKnownList().getKnownObjects()) + { + if (object == null || !(object instanceof L2GuardInstance)) continue; + + if (((L2GuardInstance)object).getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE) + ((L2GuardInstance)object).getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE,null); + } + } + else if (_karma > 0 && karma == 0) + { + // Send a Server->Client StatusUpdate packet with Karma and PvP Flag to the L2PcInstance and all L2PcInstance to inform (broadcast) + setKarmaFlag(0); + } + + _karma = karma; + updateKarma(); + } + + /** + * Return the max weight that the L2PcInstance can load.

    + */ + public int getMaxLoad() + { + return (int)calcStat(Stats.MAX_LOAD, _baseLoad, this, null); + } + + public int getexpertisePenalty() + { + return _expertisePenalty; + } + + public int getWeightPenalty() + { + if (_dietMode) + return 0; + + return _curWeightPenalty; + } + + /** + * Update the overloaded status of the L2PcInstance.

    + */ + public void refreshOverloaded() + { + if (getMaxLoad() > 0 && !_dietMode) + { + setIsOverloaded(getCurrentLoad() > getMaxLoad()); + int weightproc = getCurrentLoad() * 1000 / getMaxLoad(); + int newWeightPenalty; + if ( weightproc < 500) newWeightPenalty = 0; + else if ( weightproc < 666) newWeightPenalty = 1; + else if ( weightproc < 800) newWeightPenalty = 2; + else if ( weightproc < 1000) newWeightPenalty = 3; + else newWeightPenalty = 4; + + if (_curWeightPenalty != newWeightPenalty) + { + _curWeightPenalty = newWeightPenalty; + if (newWeightPenalty > 0) + super.addSkill(SkillTable.getInstance().getInfo(4270,newWeightPenalty)); + else super.removeSkill(getKnownSkill(4270)); + + super.updateEffectIcons(); + } + } + } + + public void refreshExpertisePenalty() + { + int newPenalty = 0; + + for (L2ItemInstance item : getInventory().getItems()) + { + if (item.isEquipped()) + { + int crystaltype = item.getItem().getCrystalType(); + + if (crystaltype > newPenalty) + newPenalty = crystaltype; + } + } + + newPenalty = newPenalty - getExpertiseIndex(); + + if (newPenalty <= 0) + newPenalty = 0; + + if (getexpertisePenalty() != newPenalty) + { + _expertisePenalty = newPenalty; + + if (newPenalty > 0) + super.addSkill(SkillTable.getInstance().getInfo(4267, newPenalty)); + else + super.removeSkill(getKnownSkill(4267)); + + super.updateEffectIcons(); + } + } + + public void CheckIfWeaponIsAllowed() + { + // Override for Gamemasters + if (isGM()) + return; + + // Iterate through all effects currently on the character. + for (L2Effect currenteffect : this.getAllEffects()) + { + L2Skill effectSkill = currenteffect.getSkill(); + + // Ignore all buff skills that are party related (ie. songs, dances) while still remaining weapon dependant on cast though. + if (!(effectSkill.getTargetType() == SkillTargetType.TARGET_PARTY && effectSkill.getSkillType() == SkillType.BUFF)) + { + // Check to rest to assure current effect meets weapon requirements. + if (!effectSkill.getWeaponDependancy(this)) + { + sendMessage(effectSkill.getName() + " cannot be used with this weapon."); + + if (Config.DEBUG) + _log.info(" | Skill "+effectSkill.getName()+" has been disabled for ("+this.getName()+"); Reason: Incompatible Weapon Type."); + + currenteffect.exit(); + } + } + + continue; + } + } + + /** + * Return the the PvP Kills of the L2PcInstance (Number of player killed during a PvP).

    + */ + public int getPvpKills() + { + return _pvpKills; + } + + /** + * Set the the PvP Kills of the L2PcInstance (Number of player killed during a PvP).

    + */ + public void setPvpKills(int pvpKills) + { + _pvpKills = pvpKills; + } + + /** + * Return the ClassId object of the L2PcInstance contained in L2PcTemplate.

    + */ + public ClassId getClassId() + { + return getTemplate().classId; + } + + /** + * Set the template of the L2PcInstance.

    + * + * @param Id The Identifier of the L2PcTemplate to set to the L2PcInstance + * + */ + public void setClassId(int Id) + { + _activeClass = Id; + L2PcTemplate t = CharTemplateTable.getInstance().getTemplate(Id, getSex()==1); + + if (t == null) + { + _log.severe("Missing template for classId: "+Id); + throw new Error(); + } + + // Set the template of the L2PcInstance + setTemplate(t); + } + + /** Return the Experience of the L2PcInstance. */ + public int getExp() { return getStat().getExp(); } + + + public void setActiveEnchantItem(L2ItemInstance scroll) + { + _activeEnchantItem = scroll; + } + + public L2ItemInstance getActiveEnchantItem() + { + return _activeEnchantItem; + } + + /** + * Set the fists weapon of the L2PcInstance (used when no weapon is equiped).

    + * + * @param weaponItem The fists L2Weapon to set to the L2PcInstance + * + */ + public void setFistsWeaponItem(L2Weapon weaponItem) + { + _fistsWeaponItem = weaponItem; + } + + /** + * Return the fists weapon of the L2PcInstance (used when no weapon is equiped).

    + */ + public L2Weapon getFistsWeaponItem() + { + return _fistsWeaponItem; + } + + /** + * Return the fists weapon of the L2PcInstance Class (used when no weapon is equiped).

    + */ + public L2Weapon findFistsWeaponItem(int classId) + { + L2Weapon weaponItem = null; + if ((classId >= 0x00) && (classId <= 0x09)) + { + //human fighter fists + L2Item temp = ItemTable.getInstance().getTemplate(246); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x0a) && (classId <= 0x11)) + { + //human mage fists + L2Item temp = ItemTable.getInstance().getTemplate(251); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x12) && (classId <= 0x18)) + { + //elven fighter fists + L2Item temp = ItemTable.getInstance().getTemplate(244); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x19) && (classId <= 0x1e)) + { + //elven mage fists + L2Item temp = ItemTable.getInstance().getTemplate(249); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x1f) && (classId <= 0x25)) + { + //dark elven fighter fists + L2Item temp = ItemTable.getInstance().getTemplate(245); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x26) && (classId <= 0x2b)) + { + //dark elven mage fists + L2Item temp = ItemTable.getInstance().getTemplate(250); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x2c) && (classId <= 0x30)) + { + //orc fighter fists + L2Item temp = ItemTable.getInstance().getTemplate(248); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x31) && (classId <= 0x34)) + { + //orc mage fists + L2Item temp = ItemTable.getInstance().getTemplate(252); + weaponItem = (L2Weapon)temp; + } + else if ((classId >= 0x35) && (classId <= 0x39)) + { + //dwarven fists + L2Item temp = ItemTable.getInstance().getTemplate(247); + weaponItem = (L2Weapon)temp; + } + + return weaponItem; + } + + /** + * Give Expertise skill of this level and remove beginner Lucky skill.

    + * + * Actions :

    + *
  • Get the Level of the L2PcInstance
  • + *
  • If L2PcInstance Level is 5, remove beginner Lucky skill
  • + *
  • Add the Expertise skill corresponding to its Expertise level
  • + *
  • Update the overloaded status of the L2PcInstance


  • + * + * Caution : This method DOESN'T give other free skills (SP needed = 0)

    + * + */ + public void rewardSkills() + { + // Get the Level of the L2PcInstance + int lvl = getLevel(); + + // Remove beginner Lucky skill + if (lvl == 5) + { + L2Skill skill = SkillTable.getInstance().getInfo(194, 1); + skill = removeSkill(skill); + + if (Config.DEBUG && skill != null) _log.fine("removed skill 'Lucky' from "+getName()); + } + + // Calculate the current higher Expertise of the L2PcInstance + for (int i=0; i < EXPERTISE_LEVELS.length; i++) + { + if (lvl >= EXPERTISE_LEVELS[i]) + setExpertiseIndex(i); + } + + // Add the Expertise skill corresponding to its Expertise level + if (getExpertiseIndex() > 0) + { + L2Skill skill = SkillTable.getInstance().getInfo(239, getExpertiseIndex()); + addSkill(skill); + + if (Config.DEBUG) _log.fine("awarded "+getName()+" with new expertise."); + + } + else + { + if (Config.DEBUG) _log.fine("No skills awarded at lvl: "+lvl); + } + + //Active skill dwarven craft + + if (getSkillLevel(1321) < 1 && getRace() == Race.dwarf) + { + L2Skill skill = SkillTable.getInstance().getInfo(1321,1); + addSkill(skill); + } + + //Active skill common craft + if (getSkillLevel(1322) < 1) + { + L2Skill skill = SkillTable.getInstance().getInfo(1322,1); + addSkill(skill); + } + + for(int i = 0; i < COMMON_CRAFT_LEVELS.length; i++) + { + if(lvl >= COMMON_CRAFT_LEVELS[i] && getSkillLevel(1320) < (i+1)) + { + L2Skill skill = SkillTable.getInstance().getInfo(1320, (i+1)); + addSkill(skill); + } + } + + // This function gets called on login, so not such a bad place to check weight + refreshOverloaded(); // Update the overloaded status of the L2PcInstance + refreshExpertisePenalty(); // Update the expertise status of the L2PcInstance + } + + + /** Set the Experience value of the L2PcInstance. */ + public void setExp(int exp) { getStat().setExp(exp); } + + /** + * Return the Race object of the L2PcInstance.

    + */ + public Race getRace() + { + if (!isSubClassActive()) + return getTemplate().race; + + boolean isFemale = (getSex() == 1); + L2PcTemplate charTemp = CharTemplateTable.getInstance().getTemplate(_baseClass, isFemale); + + return charTemp.race; + } + + public L2Radar getRadar() + { + return _radar; + } + + /** Return the SP amount of the L2PcInstance. */ + public int getSp() { return getStat().getSp(); } + + /** Set the SP amount of the L2PcInstance. */ + public void setSp(int sp) { super.getStat().setSp(sp); } + + public int getPvpFlag() + { + return _pvpFlag; + } + + /** + * Return true if this L2PcInstance is a clan leader in + * ownership of the passed castle + */ + public boolean isCastleLord(int castleId) + { + L2Clan clan = getClan(); + + // player has clan and is the clan leader, check the castle info + if ((clan != null) && (clan.getLeader().getPlayerInstance() == this)) + { + // if the clan has a castle and it is actually the queried castle, return true + Castle castle = CastleManager.getInstance().getCastleByOwner(clan); + if ((castle != null) && (castle == CastleManager.getInstance().getCastle(castleId))) + return true; + } + + return false; + } + /** + * Return the Clan Identifier of the L2PcInstance.

    + */ + public int getClanId() + { + return _clanId; + } + + /** + * Return the Clan Crest Identifier of the L2PcInstance or 0.

    + */ + public int getClanCrestId() + { + if (_clan != null && _clan.hasCrest()) + return _clan.getCrestId(); + + return 0; + } + + /** + * @return The Clan CrestLarge Identifier or 0 + */ + public int getClanCrestLargeId() + { + if (_clan != null && _clan.hasCrestLarge()) + return _clan.getCrestLargeId(); + + return 0; + } + + public long getDeleteClanTime() + { + return _deleteClanTime; + } + + public void setDeleteClanTime(long time) + { + _deleteClanTime = time; + } + + public void setDeleteClanCurTime() + { + _deleteClanTime = System.currentTimeMillis(); + } + + public void setOnlineTime(long time) + { + _onlineTime = time; + _onlineBeginTime = System.currentTimeMillis(); + } + + public boolean canJoinClan() + { + return (_deleteClanTime == 0) || ((System.currentTimeMillis() - _deleteClanTime) >= Config.ALT_CLAN_JOIN_DAYS*24*60*60*1000); + } + + public boolean canCreateClan() + { + return (_deleteClanTime == 0) || ((System.currentTimeMillis() - _deleteClanTime) >= Config.ALT_CLAN_CREATE_DAYS*24*60*60*1000); + } + + /** + * Return the PcInventory Inventory of the L2PcInstance contained in _inventory.

    + */ + public PcInventory getInventory() + { + return _inventory; + } + + /** + * Delete a ShortCut of the L2PcInstance _shortCuts.

    + */ + public void removeItemFromShortCut(int objectId) + { + _shortCuts.deleteShortCutByObjectId(objectId); + } + + /** + * Return True if the L2PcInstance is sitting.

    + */ + public boolean isSitting() + { + return _waitTypeSitting; + } + + /** + * Sit down the L2PcInstance, set the AI Intention to AI_INTENTION_REST and send a Server->Client ChangeWaitType packet (broadcast)

    + */ + public void sitDown() + { + if (isCastingNow()) + { + sendMessage("Cannot sit while casting"); + return; + } + + if (!_waitTypeSitting && !isAttackingDisabled() && !isOutOfControl() && !isImobilised()) + { + breakAttack(); + + _waitTypeSitting = true; + getAI().setIntention(CtrlIntention.AI_INTENTION_REST); + broadcastPacket(new ChangeWaitType (this, ChangeWaitType.WT_SITTING)); + } + } + + /** + * Stand up the L2PcInstance, set the AI Intention to AI_INTENTION_IDLE and send a Server->Client ChangeWaitType packet (broadcast)

    + */ + public void standUp() + { + if (L2Event.active && eventSitForced) + { + sendMessage("A dark force beyond your mortal understanding makes your knees to shake when you try to stand up ..."); + } + else if (_waitTypeSitting && !isInStoreMode() && !isAlikeDead()) + { + if (_relax) + { + setRelax(false); + stopEffects(L2Effect.EffectType.RELAXING); + } + + _waitTypeSitting = false; + getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); + broadcastPacket(new ChangeWaitType (this, ChangeWaitType.WT_STANDING)); + } + } + + /** + * Set the value of the _relax value. Must be True if using skill Relax and False if not. + */ + public void setRelax(boolean val) + { + _relax = val; + } + + /** + * Return the PcWarehouse object of the L2PcInstance.

    + */ + public PcWarehouse getWarehouse() + { + return _warehouse; + } + + /** + * Return the PcFreight object of the L2PcInstance.

    + */ + public PcFreight getFreight() + { + return _freight; + } + + /** + * Return the Identifier of the L2PcInstance.

    + */ + public int getCharId() + { + return _charId; + } + + /** + * Set the Identifier of the L2PcInstance.

    + */ + public void setCharId(int charId) + { + _charId = charId; + } + + /** + * Return the Adena amount of the L2PcInstance.

    + */ + public int getAdena() + { + return _inventory.getAdena(); + } + + /** + * Return the Ancient Adena amount of the L2PcInstance.

    + */ + public int getAncientAdena() + { + return _inventory.getAncientAdena(); + } + + /** + * Add adena to Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param count : int Quantity of adena to be added + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + */ + public void addAdena(String process, int count, L2Object reference, boolean sendMessage) + { + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.EARNED_ADENA); + sm.addNumber(count); + sendPacket(sm); + } + + if (count > 0) + { + _inventory.addAdena(process, count, this, reference); + + // Send update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate iu = new InventoryUpdate(); + iu.addItem(_inventory.getAdenaInstance()); + sendPacket(iu); + } + else sendPacket(new ItemList(this, false)); + } + } + + /** + * Reduce adena in Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param count : int Quantity of adena to be reduced + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return boolean informing if the action was successfull + */ + public boolean reduceAdena(String process, int count, L2Object reference, boolean sendMessage) + { + if (count > getAdena()) + { + if (sendMessage) sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA)); + return false; + } + + if (count > 0) + { + L2ItemInstance adenaItem = _inventory.getAdenaInstance(); + _inventory.reduceAdena(process, count, this, reference); + + // Send update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate iu = new InventoryUpdate(); + iu.addItem(adenaItem); + sendPacket(iu); + } + else sendPacket(new ItemList(this, false)); + + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ADENA); + sm.addNumber(count); + sendPacket(sm); + } + } + + return true; + } + + /** + * Add ancient adena to Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * + * @param process : String Identifier of process triggering this action + * @param count : int Quantity of ancient adena to be added + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + */ + public void addAncientAdena(String process, int count, L2Object reference, boolean sendMessage) + { + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.EARNED_S2_S1_s); + sm.addItemName(PcInventory.ANCIENT_ADENA_ID); + sm.addNumber(count); + sendPacket(sm); + } + + if (count > 0) + { + _inventory.addAncientAdena(process, count, this, reference); + + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate iu = new InventoryUpdate(); + iu.addItem(_inventory.getAncientAdenaInstance()); + sendPacket(iu); + } + else sendPacket(new ItemList(this, false)); + } + } + + /** + * Reduce ancient adena in Inventory of the L2PcInstance and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param count : int Quantity of ancient adena to be reduced + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return boolean informing if the action was successfull + */ + public boolean reduceAncientAdena(String process, int count, L2Object reference, boolean sendMessage) + { + if (count > getAncientAdena()) + { + if (sendMessage) + sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA)); + + return false; + } + + if (count > 0) + { + L2ItemInstance ancientAdenaItem = _inventory.getAncientAdenaInstance(); + _inventory.reduceAncientAdena(process, count, this, reference); + + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate iu = new InventoryUpdate(); + iu.addItem(ancientAdenaItem); + sendPacket(iu); + } + else + { + sendPacket(new ItemList(this, false)); + } + + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); + sm.addNumber(count); + sm.addItemName(PcInventory.ANCIENT_ADENA_ID); + sendPacket(sm); + } + } + + return true; + } + + /** + * Adds item to inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param item : L2ItemInstance to be added + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + */ + public void addItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) + { + if (item.getCount() > 0) + { + // Sends message to client if requested + if (sendMessage) + { + if (item.getCount() > 1) + { + SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1_S2); + sm.addItemName(item.getItemId()); + sm.addNumber(item.getCount()); + sendPacket(sm); + } + else + { + SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1); + sm.addItemName(item.getItemId()); + sendPacket(sm); + } + } + + // Add the item to inventory + L2ItemInstance newitem = _inventory.addItem(process, item, this, reference); + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + playerIU.addItem(newitem); + sendPacket(playerIU); + } + else + { + sendPacket(new ItemList(this, false)); + } + + // Update current load as well + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // If over capacity, trop the item + if (!isGM() && !_inventory.validateCapacity(0)) + dropItem("InvDrop", item, null, true); + } + } + + /** + * Adds item to Inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param itemId : int Item Identifier of the item to be added + * @param count : int Quantity of items to be added + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + */ + public void addItem(String process, int itemId, int count, L2Object reference, boolean sendMessage) + { + if (count > 0) + { + // Sends message to client if requested + if (sendMessage) + { + if (count > 1) + { + if (process.equalsIgnoreCase("sweep") || process.equalsIgnoreCase("Quest")) + { + SystemMessage sm = new SystemMessage(SystemMessage.EARNED_S2_S1_s); + sm.addItemName(itemId); + sm.addNumber(count); + sendPacket(sm); + } + else + { + SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1_S2); + sm.addItemName(itemId); + sm.addNumber(count); + sendPacket(sm); + } + } + else + { + if (process.equalsIgnoreCase("sweep") || process.equalsIgnoreCase("Quest")) + { + SystemMessage sm = new SystemMessage(SystemMessage.EARNED_ITEM); + sm.addItemName(itemId); + sendPacket(sm); + } + else + { + SystemMessage sm = new SystemMessage(SystemMessage.YOU_PICKED_UP_S1); + sm.addItemName(itemId); + sendPacket(sm); + } + } + } + + // Add the item to inventory + L2ItemInstance item = _inventory.addItem(process, itemId, count, this, reference); + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + playerIU.addItem(item); + sendPacket(playerIU); + } + else sendPacket(new ItemList(this, false)); + + // Update current load as well + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // If over capacity, trop the item + if (!isGM() && !_inventory.validateCapacity(0)) dropItem("InvDrop", item, null, true); + } + } + + /** + * Destroy item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param item : L2ItemInstance to be destroyed + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return boolean informing if the action was successfull + */ + public boolean destroyItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) + { + int oldCount = item.getCount(); + item = _inventory.destroyItem(process, item, this, reference); + + if (item == null) + { + if (sendMessage) + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); + + return false; + } + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + playerIU.addItem(item); + sendPacket(playerIU); + } + else sendPacket(new ItemList(this, false)); + + // Update current load as well + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // Sends message to client if requested + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); + sm.addNumber(oldCount); + sm.addItemName(item.getItemId()); + sendPacket(sm); + } + + return true; + } + + /** + * Destroys item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param objectId : int Item Instance identifier of the item to be destroyed + * @param count : int Quantity of items to be destroyed + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return boolean informing if the action was successfull + */ + public boolean destroyItem(String process, int objectId, int count, L2Object reference, boolean sendMessage) + { + L2ItemInstance item = _inventory.getItemByObjectId(objectId); + + if (item == null || item.getCount() < count || _inventory.destroyItem(process, objectId, count, this, reference) == null) + { + if (sendMessage) + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); + + return false; + } + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + playerIU.addItem(item); + sendPacket(playerIU); + } + else sendPacket(new ItemList(this, false)); + + // Update current load as well + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // Sends message to client if requested + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); + sm.addNumber(count); + sm.addItemName(item.getItemId()); + sendPacket(sm); + } + + return true; + } + + /** + * Destroy item from inventory by using its itemId and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param itemId : int Item identifier of the item to be destroyed + * @param count : int Quantity of items to be destroyed + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return boolean informing if the action was successfull + */ + public boolean destroyItemByItemId(String process, int itemId, int count, L2Object reference, boolean sendMessage) + { + L2ItemInstance item = _inventory.getItemByItemId(itemId); + + if (item == null || item.getCount() < count || _inventory.destroyItemByItemId(process, itemId, count, this, reference) == null) + { + if (sendMessage) + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); + + return false; + } + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + playerIU.addItem(item); + sendPacket(playerIU); + } + else sendPacket(new ItemList(this, false)); + + // Update current load as well + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // Sends message to client if requested + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.DISSAPEARED_ITEM); + sm.addNumber(count); + sm.addItemName(itemId); + sendPacket(sm); + } + + return true; + } + + /** + * Destroy all weared items from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return boolean informing if the action was successfull + */ + public void destroyWearedItems(String process, L2Object reference, boolean sendMessage) + { + + // Go through all Items of the inventory + for (L2ItemInstance item : getInventory().getItems()) + { + // Check if the item is a Try On item in order to remove it + if (item.isWear()) + { + if (item.isEquipped()) + getInventory().unEquipItemInSlotAndRecord(item.getEquipSlot()); + + if (_inventory.destroyItem(process, item, this, reference) == null) + { + _log.warning("Player " + getName() + " can't destroy weared item: " + item.getName() + "[ " + item.getObjectId() + " ]"); + continue; + } + + // Send an Unequipped Message in system window of the player for each Item + SystemMessage sm = new SystemMessage(0x1a1); + sm.addItemName(item.getItemId()); + sendPacket(sm); + + } + } + + + // Send the StatusUpdate Server->Client Packet to the player with new CUR_LOAD (0x0e) information + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // Send the ItemList Server->Client Packet to the player in order to refresh its Inventory + ItemList il = new ItemList(getInventory().getItems(), true); + sendPacket(il); + + // Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers + broadcastUserInfo(); + + // Sends message to client if requested + sendMessage("Trying-on mode has ended."); + + } + + /** + * Transfers item to another ItemContainer and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param itemId : int Item Identifier of the item to be transfered + * @param count : int Quantity of items to be transfered + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @return L2ItemInstance corresponding to the new item or the updated item in inventory + */ + public L2ItemInstance transferItem(String process, int objectId, int count, Inventory target, L2Object reference) + { + L2ItemInstance oldItem = checkItemManipulation(objectId, count, "transfer"); + if (oldItem == null) return null; + L2ItemInstance newItem = getInventory().transferItem(process, objectId, count, target, this, reference); + if (newItem == null) return null; + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + + if (oldItem.getCount() > 0 && oldItem != newItem) + playerIU.addModifiedItem(oldItem); + else + playerIU.addRemovedItem(oldItem); + + sendPacket(playerIU); + } + else sendPacket(new ItemList(this, false)); + + // Update current load as well + StatusUpdate playerSU = new StatusUpdate(getObjectId()); + playerSU.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(playerSU); + + // Send target update packet + if (target instanceof PcInventory) + { + L2PcInstance targetPlayer = ((PcInventory)target).getOwner(); + + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + + if (newItem.getCount() > count) + playerIU.addModifiedItem(newItem); + else + playerIU.addNewItem(newItem); + + targetPlayer.sendPacket(playerIU); + } + else targetPlayer.sendPacket(new ItemList(targetPlayer, false)); + + // Update current load as well + playerSU = new StatusUpdate(targetPlayer.getObjectId()); + playerSU.addAttribute(StatusUpdate.CUR_LOAD, targetPlayer.getCurrentLoad()); + targetPlayer.sendPacket(playerSU); + } + else if (target instanceof PetInventory) + { + PetInventoryUpdate petIU = new PetInventoryUpdate(); + + if (newItem.getCount() > count) + petIU.addModifiedItem(newItem); + else + petIU.addNewItem(newItem); + + ((PetInventory)target).getOwner().getOwner().sendPacket(petIU); + } + + return newItem; + } + + /** + * Drop item from inventory and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param item : L2ItemInstance to be dropped + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return boolean informing if the action was successfull + */ + public boolean dropItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage) + { + item = _inventory.dropItem(process, item, this, reference); + + if (item == null) + { + if (sendMessage) + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); + + return false; + } + + item.dropMe(this, getClientX() + Rnd.get(50) - 25, getClientY() + Rnd.get(50) - 25, getClientZ() + 20); + // Avoids it from beeing removed by the auto item destroyer + item.setDropTime(0); + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + playerIU.addItem(item); + sendPacket(playerIU); + } + else sendPacket(new ItemList(this, false)); + + // Update current load as well + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // Sends message to client if requested + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.YOU_DROPPED_S1); + sm.addItemName(item.getItemId()); + sendPacket(sm); + } + + return true; + } + + /** + * Drop item from inventory by using its objectID and send a Server->Client InventoryUpdate packet to the L2PcInstance. + * @param process : String Identifier of process triggering this action + * @param objectId : int Item Instance identifier of the item to be dropped + * @param count : int Quantity of items to be dropped + * @param x : int coordinate for drop X + * @param y : int coordinate for drop Y + * @param z : int coordinate for drop Z + * @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation + * @param sendMessage : boolean Specifies whether to send message to Client about this action + * @return L2ItemInstance corresponding to the new item or the updated item in inventory + */ + public L2ItemInstance dropItem(String process, int objectId, int count, int x, int y, int z, L2Object reference, boolean sendMessage) + { + L2ItemInstance invitem = _inventory.getItemByObjectId(objectId); + L2ItemInstance item = _inventory.dropItem(process, objectId, count, this, reference); + + if (item == null) + { + if (sendMessage) + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); + + return null; + } + + item.dropMe(this, x, y, z); + // Avoids it from beeing removed by the auto item destroyer + item.setDropTime(0); + + // Send inventory update packet + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate playerIU = new InventoryUpdate(); + playerIU.addItem(invitem); + sendPacket(playerIU); + } + else + { + sendPacket(new ItemList(this, false)); + } + + // Update current load as well + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad()); + sendPacket(su); + + // Sends message to client if requested + if (sendMessage) + { + SystemMessage sm = new SystemMessage(SystemMessage.YOU_DROPPED_S1); + sm.addItemName(item.getItemId()); + sendPacket(sm); + } + + return item; + } + + public L2ItemInstance checkItemManipulation(int objectId, int count, String action) + { + //TODO: if we remove objects that are not visisble from the L2World, we'll have to remove this check + if (L2World.getInstance().findObject(objectId) == null) + { + _log.finest(getObjectId()+": player tried to " + action + " item not available in L2World"); + return null; + } + + L2ItemInstance item = getInventory().getItemByObjectId(objectId); + + if (item == null || item.getOwnerId() != getObjectId()) + { + _log.finest(getObjectId()+": player tried to " + action + " item he is not owner of"); + return null; + } + + if (count < 0 || (count > 1 && !item.isStackable())) + { + _log.finest(getObjectId()+": player tried to " + action + " item with invalid count: "+ count); + return null; + } + + if (count > item.getCount()) + { + _log.finest(getObjectId()+": player tried to " + action + " more items than he owns"); + return null; + } + + // Pet is summoned and not the item that summoned the pet AND not the buggle from strider you're mounting + if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId) + { + if (Config.DEBUG) + _log.finest(getObjectId()+": player tried to " + action + " item controling pet"); + + return null; + } + + if (getActiveEnchantItem() != null && getActiveEnchantItem().getObjectId() == objectId) + { + if (Config.DEBUG) + _log.finest(getObjectId()+":player tried to " + action + " an enchant scroll he was using"); + + return null; + } + + if (item.isWear()) + { + Util.handleIllegalPlayerAction(this, "Warning!! Character "+getName()+" tried to " + action + " weared item: "+item.getObjectId(),Config.DEFAULT_PUNISH); + return null; + } + + return item; + } + + /** + * Set _protectEndTime according settings. + */ + public void setProtection(boolean protect) + { + if (Config.DEVELOPER && (protect || _protectEndTime > 0)) + System.out.println(this.getName() + ": Protection " + (protect?"ON " + (GameTimeController.getGameTicks() + Config.PLAYER_SPAWN_PROTECTION * GameTimeController.TICKS_PER_SECOND) :"OFF") + " (currently " + GameTimeController.getGameTicks() + ")"); + + _protectEndTime = protect ? GameTimeController.getGameTicks() + Config.PLAYER_SPAWN_PROTECTION * GameTimeController.TICKS_PER_SECOND : 0; + } + + /** + * Return the active connection with the client.

    + */ + public Connection getNetConnection() + { + return _connection; + } + + /** + * Set the active connection with the client.

    + */ + public void setNetConnection(Connection connection) + { + _connection = connection; + } + + /** + * Close the active connection with the client.

    + */ + public void closeNetConnection() + { + if (getNetConnection() != null) + getNetConnection().close(); + } + + /** + * Manage actions when a player click on this L2PcInstance.

    + * + * Actions on first click on the L2PcInstance (Select it) :

    + *
  • Set the target of the player
  • + *
  • Send a Server->Client packet MyTargetSelected to the player (display the select window)


  • + * + * Actions on second click on the L2PcInstance (Follow it/Attack it/Intercat with it) :

    + *
  • Send a Server->Client packet MyTargetSelected to the player (display the select window)
  • + *
  • If this L2PcInstance has a Private Store, notify the player AI with AI_INTENTION_INTERACT
  • + *
  • If this L2PcInstance is autoAttackable, notify the player AI with AI_INTENTION_ATTACK


  • + *
  • If this L2PcInstance is NOT autoAttackable, notify the player AI with AI_INTENTION_FOLLOW


  • + * + * Example of use :

    + *
  • Client packet : Action, AttackRequest


  • + * + * @param player The player that start an action on this L2PcInstance + * + */ + public void onAction(L2PcInstance player) + { + // Check if the L2PcInstance is confused + if (player.isConfused()) + { + // Send a Server->Client packet ActionFailed to the player + ActionFailed af = new ActionFailed(); + player.sendPacket(af); + } + + // Check if the player already target this L2PcInstance + if (player.getTarget() != this) + { + // Set the target of the player + player.setTarget(this); + + // Send a Server->Client packet MyTargetSelected to the player + // The color to display in the select window is White + MyTargetSelected my = new MyTargetSelected(getObjectId(), 0); + player.sendPacket(my); + } + else + { + // Check if this L2PcInstance has a Private Store + if (getPrivateStoreType() != 0) + { + player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this); + } + else + { + // Check if this L2PcInstance is autoAttackable + if (isAutoAttackable(player)) + player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this); + else + player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this); + } + } + } + + /** + * Send packet StatusUpdate with current HP,MP and CP to the L2PcInstance and only current HP, MP and Level to all other L2PcInstance of the Party.

    + * + * Actions :

    + *
  • Send the Server->Client packet StatusUpdate with current HP, MP and CP to this L2PcInstance

  • + *
  • Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2PcInstance of the Party


  • + * + * Caution : This method DOESN'T SEND current HP and MP to all L2PcInstance of the _statusListener

    + * + */ + public void broadcastStatusUpdate() + { + //TODO We mustn't send these informations to other players + // Send the Server->Client packet StatusUpdate with current HP and MP to all L2PcInstance that must be informed of HP/MP updates of this L2PcInstance + //super.broadcastStatusUpdate(); + + // Send the Server->Client packet StatusUpdate with current HP, MP and CP to this L2PcInstance + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp()); + su.addAttribute(StatusUpdate.CUR_MP, (int) getCurrentMp()); + su.addAttribute(StatusUpdate.CUR_CP, (int) getCurrentCp()); + su.addAttribute(StatusUpdate.MAX_CP, getMaxCp()); + sendPacket(su); + + // Check if a party is in progress + if (isInParty()) + { + // Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2PcInstance of the Party + PartySmallWindowUpdate update = new PartySmallWindowUpdate(this); + getParty().broadcastToPartyMembers(this, update); + } + + if (isInOlympiadMode()) + { + if(Olympiad.getInstance().getSpectators(_olympiadGameId) != null) + { + for(L2PcInstance spectator : Olympiad.getInstance().getSpectators(_olympiadGameId)) + { + if (spectator == null) continue; + spectator.sendPacket(new ExOlympiadUserInfo(this, getOlympiadSide())); + } + } + } + } + + /** + * Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers.

    + * + * Concept :

    + * Others L2PcInstance in the detection area of the L2PcInstance are identified in _knownPlayers. + * In order to inform other players of this L2PcInstance state modifications, server just need to go through _knownPlayers to send Server->Client Packet

    + * + * Actions :

    + *
  • Send a Server->Client packet UserInfo to this L2PcInstance (Public and Private Data)
  • + *
  • Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance (Public data only)


  • + * + * Caution : DON'T SEND UserInfo packet to other players instead of CharInfo packet. + * Indeed, UserInfo packet contains PRIVATE DATA as MaxHP, STR, DEX...

    + * + */ + public final void broadcastUserInfo() + { + // Send a Server->Client packet UserInfo to this L2PcInstance + sendPacket(new UserInfo(this)); + + // Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance + if (Config.DEBUG) + _log.fine("players to notify:" + getKnownList().getKnownPlayers().size() + " packet: [S] 03 CharInfo"); + + Broadcast.toKnownPlayers(this, new CharInfo(this)); + } + + /** + * Return the Alliance Identifier of the L2PcInstance.

    + */ + public int getAllyId() + { + if (_clan == null) + return 0; + + return _clan.getAllyId(); + } + + public int getAllyCrestId() + { + if (getAllyId() == 0) + return 0; + + return _clan.getAllyCrestId(); + } + + /** + * Manage hit process (called by Hit Task of L2Character).

    + * + * Actions :

    + *
  • If the attacker/target is dead or use fake death, notify the AI with EVT_CANCEL and send a Server->Client packet ActionFailed (if attacker is a L2PcInstance)
  • + *
  • If attack isn't aborted, send a message system (critical hit, missed...) to attacker/target if they are L2PcInstance
  • + *
  • If attack isn't aborted and hit isn't missed, reduce HP of the target and calculate reflection damage to reduce HP of attacker if necessary
  • + *
  • if attack isn't aborted and hit isn't missed, manage attack or cast break of the target (calculating rate, sending message...)


  • + * + * @param target The L2Character targeted + * @param damage Nb of HP to reduce + * @param crit True if hit is critical + * @param miss True if hit is missed + * @param soulshot True if SoulShot are charged + * @param shld True if shield is efficient + * + */ + protected void onHitTimer(L2Character target, int damage, boolean crit, boolean miss, boolean soulshot, boolean shld) + { + super.onHitTimer(target, damage, crit, miss, soulshot, shld); + } + + /** + * Send a Server->Client packet StatusUpdate to the L2PcInstance.

    + */ + public void sendPacket(ServerBasePacket packet) + { + if(_isConnected) + { + try + { + if (_connection != null) + _connection.sendPacket(packet); + } + catch (Exception e) + { + _log.log(Level.INFO, "", e); + } + } + } + + /** + * Manage Interact Task with another L2PcInstance.

    + * + * Actions :

    + *
  • If the private store is a STORE_PRIVATE_SELL, send a Server->Client PrivateBuyListSell packet to the L2PcInstance
  • + *
  • If the private store is a STORE_PRIVATE_BUY, send a Server->Client PrivateBuyListBuy packet to the L2PcInstance
  • + *
  • If the private store is a STORE_PRIVATE_MANUFACTURE, send a Server->Client RecipeShopSellList packet to the L2PcInstance


  • + * + * @param target The L2Character targeted + * + */ + public void doInteract(L2Character target) + { + if (target instanceof L2PcInstance) + { + L2PcInstance temp = (L2PcInstance) target; + sendPacket(new ActionFailed()); + + if (temp.getPrivateStoreType() == STORE_PRIVATE_SELL) + sendPacket(new PrivateStoreListSell(this, temp)); + else if (temp.getPrivateStoreType() == STORE_PRIVATE_BUY) + sendPacket(new PrivateStoreListBuy(this, temp)); + else if (temp.getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE) + sendPacket(new RecipeShopSellList(this, temp)); + + } + else + { + // _interactTarget=null should never happen but one never knows ^^; + if (target != null) + target.onAction(this); + } + } + + /** + * Manage AutoLoot Task.

    + * + * Actions :

    + *
  • Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2
  • + *
  • Add the Item to the L2PcInstance inventory
  • + *
  • Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new slot) or ModifiedItem (increase amount)
  • + *
  • Send a Server->Client packet StatusUpdate to this L2PcInstance with current weight


  • + * + * Caution : If a Party is in progress, distribute Items between party members

    + * + * @param target The L2ItemInstance dropped + * + */ + public void doAutoLoot(L2Attackable target, L2Attackable.RewardItem item) + { + if (isInParty()) getParty().distributeItem(this, item, false); + else if (item.getItemId() == 57) addAdena("Loot", item.getCount(), target, true); + else addItem("Loot", item.getItemId(), item.getCount(), target, true); + } + + /** + * Manage Pickup Task.

    + * + * Actions :

    + *
  • Send a Server->Client packet StopMove to this L2PcInstance
  • + *
  • Remove the L2ItemInstance from the world and send server->client GetItem packets
  • + *
  • Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2
  • + *
  • Add the Item to the L2PcInstance inventory
  • + *
  • Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new slot) or ModifiedItem (increase amount)
  • + *
  • Send a Server->Client packet StatusUpdate to this L2PcInstance with current weight


  • + * + * Caution : If a Party is in progress, distribute Items between party members

    + * + * @param object The L2ItemInstance to pick up + * + */ + protected void doPickupItem(L2Object object) + { + if (isAlikeDead() || isFakeDeath()) return; + + // Set the AI Intention to AI_INTENTION_IDLE + getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); + + // Check if the L2Object to pick up is a L2ItemInstance + if (! (object instanceof L2ItemInstance)) + { + // dont try to pickup anything that is not an item :) + _log.warning("trying to pickup wrong target."+getTarget()); + return; + } + + L2ItemInstance target = (L2ItemInstance) object; + + // Send a Server->Client packet ActionFailed to this L2PcInstance + sendPacket(new ActionFailed()); + + // Send a Server->Client packet StopMove to this L2PcInstance + StopMove sm = new StopMove(getObjectId(), getX(), getY(), getZ(), getHeading()); + if (Config.DEBUG) _log.fine("pickup pos: "+ target.getX() + " "+target.getY()+ " "+target.getZ() ); + sendPacket(sm); + + synchronized (target) + { + // Check if the target to pick up is visible + if (!target.isVisible()) + { + // Send a Server->Client packet ActionFailed to this L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + if ( ((isInParty() && getParty().getLootDistribution() == L2Party.ITEM_LOOTER) || !isInParty()) && !_inventory.validateCapacity(target)) + { + sendPacket(new ActionFailed()); + sendPacket(new SystemMessage(SystemMessage.SLOTS_FULL)); + return; + } + + // Remove the L2ItemInstance from the world and send server->client GetItem packets + target.pickupMe(this); + } + + // Check if a Party is in progress + if (isInParty()) getParty().distributeItem(this, target); + // Target is adena + else if (target.getItemId() == 57 && getInventory().getAdenaInstance() != null) + { + addAdena("Pickup", target.getCount(), null, true); + ItemTable.getInstance().destroyItem("Pickup", target, this, null); + } + // Target is regular item + else addItem("Pickup", target, null, true); + } + + + /** + * Set a target.

    + * + * Actions :

    + *
  • Remove the L2PcInstance from the _statusListener of the old target if it was a L2Character
  • + *
  • Add the L2PcInstance to the _statusListener of the new target if it's a L2Character
  • + *
  • Target the new L2Object (add the target to the L2PcInstance _target, _knownObject and L2PcInstance to _KnownObject of the L2Object)


  • + * + * @param newTarget The L2Object to target + * + */ + public void setTarget(L2Object newTarget) + { + // Check if the new target is visible + if (newTarget != null && !newTarget.isVisible()) + newTarget = null; + + // Get the current target + L2Object oldTarget = getTarget(); + + if (oldTarget != null) + { + if (oldTarget.equals(newTarget)) + return; // no target change + + // Remove the L2PcInstance from the _statusListener of the old target if it was a L2Character + if (oldTarget instanceof L2Character) + ((L2Character) oldTarget).removeStatusListener(this); + } + + // Add the L2PcInstance to the _statusListener of the new target if it's a L2Character + if (newTarget != null && newTarget instanceof L2Character) + { + ((L2Character) newTarget).addStatusListener(this); + TargetSelected my = new TargetSelected(getObjectId(), newTarget.getObjectId(), getX(), getY(), getZ()); + broadcastPacket(my); + } + + // Target the new L2Object (add the target to the L2PcInstance _target, _knownObject and L2PcInstance to _KnownObject of the L2Object) + super.setTarget(newTarget); + } + + /** + * Return the active weapon instance (always equiped in the right hand).

    + */ + public L2ItemInstance getActiveWeaponInstance() + { + return getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND); + } + + /** + * Return the active weapon item (always equiped in the right hand).

    + */ + public L2Weapon getActiveWeaponItem() + { + L2ItemInstance weapon = getActiveWeaponInstance(); + + if (weapon == null) + return getFistsWeaponItem(); + + return (L2Weapon) weapon.getItem(); + } + + public L2ItemInstance getChestArmorInstance() + { + return getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST); + } + + public L2Armor getActiveChestArmorItem() + { + L2ItemInstance armor = getChestArmorInstance(); + + if (armor == null) + return null; + + return (L2Armor) armor.getItem(); + } + + public boolean isWearingHeavyArmor() + { + L2ItemInstance armor = getChestArmorInstance(); + + if ((L2ArmorType)armor.getItemType() == L2ArmorType.HEAVY) + return true; + + return false; + } + + public boolean isWearingLightArmor() + { + L2ItemInstance armor = getChestArmorInstance(); + + if ((L2ArmorType)armor.getItemType() == L2ArmorType.LIGHT) + return true; + + return false; + } + + public boolean isWearingMagicArmor() + { + L2ItemInstance armor = getChestArmorInstance(); + + if ((L2ArmorType)armor.getItemType() == L2ArmorType.MAGIC) + return true; + + return false; + } + + public boolean isWearingFormalWear() + { + return _IsWearingFormalWear; + } + + public void setIsWearingFormalWear(boolean value) { + _IsWearingFormalWear = value; + } + + /** + * Return the secondary weapon instance (always equiped in the left hand).

    + */ + public L2ItemInstance getSecondaryWeaponInstance() + { + return getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); + } + + /** + * Return the secondary weapon item (always equiped in the left hand) or the fists weapon.

    + */ + public L2Weapon getSecondaryWeaponItem() + { + L2ItemInstance weapon = getSecondaryWeaponInstance(); + + if (weapon == null) + return getFistsWeaponItem(); + + L2Item item = weapon.getItem(); + + if (item instanceof L2Weapon) + return (L2Weapon) item; + + return null; + } + + + /** + * Kill the L2Character, Apply Death Penalty, Manage gain/loss Karma and Item Drop.

    + * + * Actions :

    + *
  • Reduce the Experience of the L2PcInstance in function of the calculated Death Penalty
  • + *
  • If necessary, unsummon the Pet of the killed L2PcInstance
  • + *
  • Manage Karma gain for attacker and Karam loss for the killed L2PcInstance
  • + *
  • If the killed L2PcInstance has Karma, manage Drop Item
  • + *
  • Kill the L2PcInstance


  • + * + * + * @param i The HP decrease value + * @param attacker The L2Character who attacks + * + */ + public void doDie(L2Character killer) + { + // Kill the L2PcInstance + super.doDie(killer); + + if (killer != null) + { + if (atEvent && killer instanceof L2PcInstance) + { + L2PcInstance pk = (L2PcInstance) killer; + pk.kills.add(getName()); + } + + onDieDropItem(killer); // Check if any item should be dropped + + if (!ArenaManager.getInstance().checkIfInZone(this)) + { + if (Config.ALT_GAME_DELEVEL) + { + // Reduce the Experience of the L2PcInstance in function of the calculated Death Penalty + // NOTE: deathPenalty +- Exp will update karma + if (getSkillLevel(L2Skill.SKILL_LUCKY) < 0 || getStat().getLevel() > 4) + deathPenalty((killer instanceof L2PcInstance && this.getClan() != null && ((L2PcInstance)killer).getClan() != null && ((L2PcInstance)killer).getClan().isAtWarWith(this.getClanId()))); + } + else + onDieUpdateKarma(); // Update karma if delevel is not allowed + } + } + + setPvpFlag(0); // Clear the pvp flag + + // Unsummon the Pet + if (getPet() != null) + getPet().unSummon(this); + + // Unsummon Cubics + if (_cubics.size() > 0) + { + for (L2CubicInstance cubic : _cubics.values()) + { + cubic.stopAction(); + cubic.cancelDisappear(); + } + + _cubics.clear(); + } + + stopRentPet(); + stopWaterTask(); + } + + private void onDieDropItem(L2Character killer) + { + if (atEvent || killer == null) + return; + + if (getKarma()<=0 + && killer instanceof L2PcInstance + && ((L2PcInstance)killer).getClan()!=null + && this.getClan()!=null + && ( + ((L2PcInstance)killer).getClan().isAtWarWith(this.getClanId()) +// || this.getClan().isAtWarWith(((L2PcInstance)killer).getClanId()) + ) + ) + return; + + if (!ZoneManager.getInstance().checkIfInZonePvP(this) && (!isGM() || Config.KARMA_DROP_GM)) + { + boolean isKarmaDrop = false; + boolean isKillerNpc = (killer instanceof L2NpcInstance); + int pkLimit = Config.KARMA_PK_LIMIT;; + + int dropEquip = 0; + int dropEquipWeapon = 0; + int dropItem = 0; + int dropLimit = 0; + int dropPercent = 0; + + if (getKarma() > 0 && this.getPkKills() >= pkLimit) + { + isKarmaDrop = true; + dropPercent = Config.KARMA_RATE_DROP; + dropEquip = Config.KARMA_RATE_DROP_EQUIP; + dropEquipWeapon = Config.KARMA_RATE_DROP_EQUIP_WEAPON; + dropItem = Config.KARMA_RATE_DROP_ITEM; + dropLimit = Config.KARMA_DROP_LIMIT; + } + else if (isKillerNpc && getLevel() > 4 && !isFestivalParticipant()) + { + dropPercent = Config.PLAYER_RATE_DROP; + dropEquip = Config.PLAYER_RATE_DROP_EQUIP; + dropEquipWeapon = Config.PLAYER_RATE_DROP_EQUIP_WEAPON; + dropItem = Config.PLAYER_RATE_DROP_ITEM; + dropLimit = Config.PLAYER_DROP_LIMIT; + } + + if (dropPercent > 0 && Rnd.get(100) < dropPercent) + { + List nonDroppableList = new FastList(); + List nonDroppableListPet = new FastList(); + + nonDroppableList = Config.KARMA_LIST_NONDROPPABLE_ITEMS; + nonDroppableListPet = Config.KARMA_LIST_NONDROPPABLE_ITEMS; + + int dropCount = 0; + for (L2ItemInstance itemDrop : getInventory().getItems()) + { + // Don't drop + if ( + itemDrop.getItemId() == 57 || // Adena + itemDrop.getItem().getType2() == L2Item.TYPE2_QUEST || // Quest Items + nonDroppableList.contains(itemDrop.getItemId()) || // Item listed in the non droppable item list + nonDroppableListPet.contains(itemDrop.getItemId()) || // Item listed in the non droppable pet item list + getPet() != null && getPet().getControlItemId() == itemDrop.getItemId() // Control Item of active pet + ) continue; + + if (itemDrop.isEquipped()) + { + // Set proper chance according to Item type of equipped Item + dropPercent = itemDrop.getItem().getType2() == L2Item.TYPE2_WEAPON ? dropEquipWeapon : dropEquip; + getInventory().unEquipItemInSlotAndRecord(itemDrop.getEquipSlot()); + } + else dropPercent = dropItem; // Item in inventory + + // NOTE: Each time an item is dropped, the chance of another item being dropped gets lesser (dropCount * 2) + if (Rnd.get(100) < dropPercent - (dropCount * 2)) + { + dropItem("DieDrop", itemDrop, killer, true); + + if (isKarmaDrop) + _log.warning(getName() + " has karma and dropped id = " + itemDrop.getItemId() + ", count = " + itemDrop.getCount()); + else + _log.warning(getName() + " dropped id = " + itemDrop.getItemId() + ", count = " + itemDrop.getCount()); + + dropCount++; + if (dropCount >= dropLimit) break; + } + } + } + } + } + + private void onDieUpdateKarma() + { + // Karma lose for server that does not allow delevel + if ( getKarma() > 0 ) + { + // this formula seems to work relatively well: + // baseKarma * thisLVL * (thisLVL/100) + // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti + double karmaLost = Config.KARMA_LOST_BASE; + karmaLost *= getLevel(); // multiply by char lvl + karmaLost *= (getLevel() / 100); // divide by 0.charLVL + karmaLost = Math.round(karmaLost); + if ( karmaLost < 0 ) karmaLost = 1; + + // Decrease Karma of the L2PcInstance and Send it a Server->Client StatusUpdate packet with Karma and PvP Flag if necessary + setKarma(getKarma() - (int)karmaLost); + } + } + + public void onKillUpdatePvPKarma(L2Character target) + { + if (target == null) return; + if (!(target instanceof L2PlayableInstance)) return; + + L2PcInstance targetPlayer = null; + if (target instanceof L2PcInstance) + targetPlayer = (L2PcInstance)target; + else if (target instanceof L2Summon) + targetPlayer = ((L2Summon)target).getOwner(); + + if (targetPlayer == null) return; // Target player is null + if (targetPlayer == this) return; // Target player is self + + // If in Arena, do nothing + if (ArenaManager.getInstance().getArenaIndex(this.getX(),this.getY())!=-1 || + ArenaManager.getInstance().getArenaIndex(target.getX(),target.getY())!=-1) + return; + + // Check if it's pvp + if ( + ( + checkIfPvP(target) && // Can pvp and + targetPlayer.getPvpFlag() != 0 // Target player has pvp flag set + ) || // or + ( + ZoneManager.getInstance().checkIfInZonePvP(this) && // Player is inside pvp zone and + ZoneManager.getInstance().checkIfInZonePvP(target) // Target player is inside pvp zone + ) + ) + { + increasePvpKills(); + } + else // Target player doesn't have pvp flag set + { + // check about wars + if (targetPlayer.getClan() != null && this.getClan() != null) + { + if (this.getClan().isAtWarWith(targetPlayer.getClanId())) + { + if (targetPlayer.getClan().isAtWarWith(this.getClanId())) + { + // both way war + // Add a pvp kill + increasePvpKills(); + return; + } else + { + // one way war + increasePkKillsAndKarma(targetPlayer.getLevel()); + return; + } + } else + { + if (targetPlayer.getClan().isAtWarWith(this.getClanId())) + { + // one way war + increasePkKillsAndKarma(targetPlayer.getLevel()); + return; + } + } + } + + // not in war, normal PK + if (targetPlayer.getKarma() > 0) // Target player has karma + { + if ( Config.KARMA_AWARD_PK_KILL ) + { + increasePvpKills(); + } + } + else // Target player doesn't have karma + { + increasePkKillsAndKarma(targetPlayer.getLevel()); + } + } + } + + /** + * Increase the pvp kills count and send the info to the player + * + */ + public void increasePvpKills() + { + // Add karma to attacker and increase its PK counter + setPvpKills(getPvpKills() + 1); + + // Send a Server->Client UserInfo packet to attacker with its Karma and PK Counter + sendPacket(new UserInfo(this)); + } + + /** + * Increase pk count, karma and send the info to the player + * + * @param targLVL : level of the killed player + */ + public void increasePkKillsAndKarma(int targLVL) + { + int baseKarma = Config.KARMA_MIN_KARMA; + int newKarma = baseKarma; + int karmaLimit = Config.KARMA_MAX_KARMA; + + int pkLVL = getLevel(); + int pkPKCount = getPkKills(); + + int lvlDiffMulti = 0; + int pkCountMulti = 0; + + // Check if the attacker has a PK counter greater than 0 + if ( pkPKCount > 0 ) + pkCountMulti = pkPKCount / 2; + else + pkCountMulti = 1; + if ( pkCountMulti < 1 ) pkCountMulti = 1; + + // Calculate the level difference Multiplier between attacker and killed L2PcInstance + if ( pkLVL > targLVL ) + lvlDiffMulti = pkLVL / targLVL; + else + lvlDiffMulti = 1; + if ( lvlDiffMulti < 1 ) lvlDiffMulti = 1; + + // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti + newKarma *= pkCountMulti; + newKarma *= lvlDiffMulti; + + // Make sure newKarma is less than karmaLimit and higher than baseKarma + if ( newKarma < baseKarma ) newKarma = baseKarma; + if ( newKarma > karmaLimit ) newKarma = karmaLimit; + + // Fix to prevent overflow (=> karma has a max value of 2 147 483 647) + if (getKarma() > (Integer.MAX_VALUE - newKarma)) + newKarma = Integer.MAX_VALUE - getKarma(); + + // Add karma to attacker and increase its PK counter + setPkKills(getPkKills() + 1); + setKarma(getKarma() + newKarma); + + // Send a Server->Client UserInfo packet to attacker with its Karma and PK Counter + sendPacket(new UserInfo(this)); + } + + public int calculateKarmaLost(int exp) + { + // KARMA LOSS + // When a PKer gets killed by another player or a L2MonsterInstance, it loses a certain amount of Karma based on their level. + // this (with defaults) results in a level 1 losing about ~2 karma per death, and a lvl 70 loses about 11760 karma per death... + // You lose karma as long as you were not in a pvp zone and you did not kill urself. + // NOTE: exp for death (if delevel is allowed) is based on the players level + + int karmaLost = Math.abs(exp); + karmaLost /= Config.KARMA_XP_DIVIDER; + + if (karmaLost < Config.KARMA_LOST_BASE) karmaLost = Config.KARMA_LOST_BASE; + if (karmaLost > getKarma()) karmaLost = getKarma(); + + return karmaLost; + } + + public void updatePvPStatus() + { + if (getPvpFlag() == 0) startPvPFlag(); + if (getPvpFlag() != 0) setlastPvpAttack (System.currentTimeMillis()); //update last pvp ATTACK controller + } + + public void updatePvPStatus(L2Character target) + { + if ( + checkIfPvP(target) && + ( + !ZoneManager.getInstance().checkIfInZonePvP(this) || // Player is not inside pvp zone or + !ZoneManager.getInstance().checkIfInZonePvP(target) // Target player is not inside pvp zone + ) + ) updatePvPStatus(); + } + + /** + * Restore the specified % of experience this L2PcInstance has + * lost and sends a Server->Client StatusUpdate packet.

    + */ + public void restoreExp(double restorePercent) + { + if (_expBeforeDeath > 0) + { + // Restore the specified % of lost experience. + getStat().addExp((int)Math.round((_expBeforeDeath - getExp()) * restorePercent / 100)); + _expBeforeDeath = 0; + } + } + + /** + * Reduce the Experience (and level if necessary) of the L2PcInstance in function of the calculated Death Penalty.

    + * + * Actions :

    + *
  • Calculate the Experience loss
  • + *
  • Set the value of _expBeforeDeath
  • + *
  • Set the new Experience value of the L2PcInstance and Decrease its level if necessary
  • + *
  • Send a Server->Client StatusUpdate packet with its new Experience


  • + * + */ + public void deathPenalty(boolean atwar) + { + // TODO Need Correct Penalty + // Get the level of the L2PcInstance + final int lvl = getLevel(); + + //The death steal you some Exp + double percentLost = -0.07 * lvl + 6.5; + + if (getKarma() > 0) + percentLost *= Config.RATE_KARMA_EXP_LOST; + + if (isFestivalParticipant() || atwar || SiegeManager.getInstance().checkIfInZone(this)) + percentLost /= 4.0; + + // Calculate the Experience loss + int lostExp = (int) Math.round((getStat().getExpForLevel(lvl+1) - getStat().getExpForLevel(lvl)) * percentLost /100); + + if (atEvent) + lostExp = 0; + + // Get the Experience before applying penalty + _expBeforeDeath = getExp(); + + if (Config.DEBUG) + _log.fine(getName() + " died and lost " + lostExp + " experience."); + + // Set the new Experience value of the L2PcInstance + getStat().addExp(-lostExp); + } + + /** + * @param b + */ + public void setPartyMatchingAutomaticRegistration(boolean b) + { + _partyMatchingAutomaticRegistration = b; + } + + /** + * @param b + */ + public void setPartyMatchingShowLevel(boolean b) + { + _partyMatchingShowLevel = b; + } + + /** + * @param b + */ + public void setPartyMatchingShowClass(boolean b) + { + _partyMatchingShowClass = b; + } + + /** + * @param memo + */ + public void setPartyMatchingMemo(String memo) + { + _partyMatchingMemo = memo; + } + + public boolean isPartyMatchingAutomaticRegistration() + { + return _partyMatchingAutomaticRegistration; + } + + public String getPartyMatchingMemo() + { + return _partyMatchingMemo; + } + + public boolean isPartyMatchingShowClass() + { + return _partyMatchingShowClass; + } + + public boolean isPartyMatchingShowLevel() + { + return _partyMatchingShowLevel; + } + + /** + * Manage the increase level task of a L2PcInstance (Max MP, Max MP, Recommandation, Expertise and beginner skills...).

    + * + * Actions :

    + *
  • Send a Server->Client System Message to the L2PcInstance : YOU_INCREASED_YOUR_LEVEL
  • + *
  • Send a Server->Client packet StatusUpdate to the L2PcInstance with new LEVEL, MAX_HP and MAX_MP
  • + *
  • Set the current HP and MP of the L2PcInstance, Launch/Stop a HP/MP/CP Regeneration Task and send StatusUpdate packet to all other L2PcInstance to inform (exclusive broadcast)
  • + *
  • Recalculate the party level
  • + *
  • Recalculate the number of Recommandation that the L2PcInstance can give
  • + *
  • Give Expertise skill of this level and remove beginner Lucky skill


  • + * + */ + public void increaseLevel() + { + // Set the current HP and MP of the L2Character, Launch/Stop a HP/MP/CP Regeneration Task and send StatusUpdate packet to all other L2PcInstance to inform (exclusive broadcast) + setCurrentHpMp(getMaxHp(),getMaxMp()); + setCurrentCp(getMaxCp()); + } + + /** + * Stop the HP/MP/CP Regeneration task.

    + * + * Actions :

    + *
  • Set the RegenActive flag to False
  • + *
  • Stop the HP/MP/CP Regeneration task


  • + * + */ + public void stopAllTimers() + { + stopHpMpRegeneration(); + stopWarnUserTakeBreak(); + stopWaterTask(); + stopRentPet(); + stopJailTask(); + } + + /** + * Return the L2Summon of the L2PcInstance or null.

    + */ + public L2Summon getPet() + { + return _summon; + } + + /** + * Set the L2Summon of the L2PcInstance.

    + */ + public void setPet(L2Summon summon) + { + _summon = summon; + } + + /** + * Set the L2PcInstance requester of a transaction (ex : FriendInvite, JoinAlly, JoinParty...).

    + */ + public synchronized void setActiveRequester(L2PcInstance requester) + { + _activeRequester = requester; + } + + /** + * Return the L2PcInstance requester of a transaction (ex : FriendInvite, JoinAlly, JoinParty...).

    + */ + public L2PcInstance getActiveRequester() + { + return _activeRequester; + } + + /** + * Return True if a transaction is in progress.

    + */ + public boolean isProcessingRequest() + { + return _activeRequester != null || _requestExpireTime > GameTimeController.getGameTicks(); + } + + /** + * Return True if a transaction is in progress.

    + */ + public boolean isProcessingTransaction() { return _activeRequester != null || _activeTradeList != null || _requestExpireTime > GameTimeController.getGameTicks(); } + + /** + * Select the Warehouse to be used in next activity.

    + */ + public void onTransactionRequest(L2PcInstance partner) + { + _requestExpireTime = GameTimeController.getGameTicks() + REQUEST_TIMEOUT * GameTimeController.TICKS_PER_SECOND; + partner.setActiveRequester(this); + } + + /** + * Select the Warehouse to be used in next activity.

    + */ + public void onTransactionResponse() + { + _requestExpireTime = 0; + } + + /** + * Select the Warehouse to be used in next activity.

    + */ + public void setActiveWarehouse(ItemContainer warehouse) + { + _activeWarehouse = warehouse; + } + + /** + * Return active Warehouse.

    + */ + public ItemContainer getActiveWarehouse() + { + return _activeWarehouse; + } + + /** + * Select the TradeList to be used in next activity.

    + */ + public void setActiveTradeList(TradeList tradeList) + { + _activeTradeList = tradeList; + } + + /** + * Return active TradeList.

    + */ + public TradeList getActiveTradeList() + { + return _activeTradeList; + } + + public void onTradeStart(L2PcInstance partner) + { + _activeTradeList = new TradeList(this); + _activeTradeList.setPartner(partner); + + SystemMessage msg = new SystemMessage(SystemMessage.BEGIN_TRADE_WITH_S1); + msg.addString(partner.getName()); + sendPacket(msg); + sendPacket(new TradeStart(this)); + } + + public void onTradeConfirm(L2PcInstance partner) + { + SystemMessage msg = new SystemMessage(SystemMessage.S1_CONFIRMED_TRADE); + msg.addString(partner.getName()); + sendPacket(msg); + } + + public void onTradeCancel(L2PcInstance partner) + { + if (_activeTradeList == null) + return; + + _activeTradeList.Lock(); + _activeTradeList = null; + + sendPacket(new SendTradeDone(0)); + SystemMessage msg = new SystemMessage(SystemMessage.S1_CANCELED_TRADE); + msg.addString(partner.getName()); + sendPacket(msg); + } + + public void onTradeFinish(boolean successfull) + { + _activeTradeList = null; + sendPacket(new SendTradeDone(1)); + if (successfull) + sendPacket(new SystemMessage(SystemMessage.TRADE_SUCCESSFUL)); + } + + public void startTrade(L2PcInstance partner) + { + this.onTradeStart(partner); + partner.onTradeStart(this); + } + + public void cancelActiveTrade() + { + if (_activeTradeList == null) + return; + + L2PcInstance partner = _activeTradeList.getPartner(); + if (partner != null) partner.onTradeCancel(this); + onTradeCancel(this); + } + + /** + * Return the _createList object of the L2PcInstance.

    + */ + public L2ManufactureList getCreateList() + { + return _createList; + } + + /** + * Set the _createList object of the L2PcInstance.

    + */ + public void setCreateList(L2ManufactureList x) + { + _createList = x; + } + + /** + * Return the _buyList object of the L2PcInstance.

    + */ + public TradeList getSellList() + { + if (_sellList == null) _sellList = new TradeList(this); + return _sellList; + } + + /** + * Return the _buyList object of the L2PcInstance.

    + */ + public TradeList getBuyList() + { + if (_buyList == null) _buyList = new TradeList(this); + return _buyList; + } + + /** + * Set the Private Store type of the L2PcInstance.

    + * + * Values :

    + *
  • 0 : STORE_PRIVATE_NONE
  • + *
  • 1 : STORE_PRIVATE_SELL
  • + *
  • 2 : sellmanage

  • + *
  • 3 : STORE_PRIVATE_BUY

  • + *
  • 4 : buymanage

  • + *
  • 5 : STORE_PRIVATE_MANUFACTURE

  • + * + */ + public void setPrivateStoreType(int type) + { + _privatestore = type; + } + + /** + * Return the Private Store type of the L2PcInstance.

    + * + * Values :

    + *
  • 0 : STORE_PRIVATE_NONE
  • + *
  • 1 : STORE_PRIVATE_SELL
  • + *
  • 2 : sellmanage

  • + *
  • 3 : STORE_PRIVATE_BUY

  • + *
  • 4 : buymanage

  • + *
  • 5 : STORE_PRIVATE_MANUFACTURE

  • + * + */ + public int getPrivateStoreType() + { + return _privatestore; + } + + /** + * Set the _skillLearningClassId object of the L2PcInstance.

    + */ + public void setSkillLearningClassId(ClassId classId) + { + _skillLearningClassId = classId; + } + + /** + * Return the _skillLearningClassId object of the L2PcInstance.

    + */ + public ClassId getSkillLearningClassId() + { + return _skillLearningClassId; + } + + /** + * Set the _clan object, _clanId, _clanLeader Flag and title of the L2PcInstance.

    + */ + public void setClan(L2Clan clan) + { + _clan = clan; + + if (clan == null) + { + _clanId = 0; + _clanLeader = false; + _clanPrivileges = 0; + return; + } + + if (!clan.isMember(getName())) + { + // char has been kicked from clan + setClan(null); + setTitle(""); + return; + } + + _clanId = clan.getClanId(); + _clanLeader = getObjectId() == clan.getLeaderId(); + setTitle(""); + } + + /** + * Return the _clan object of the L2PcInstance.

    + */ + public L2Clan getClan() + { + return _clan; + } + + /** + * Return True if the L2PcInstance is the leader of its clan.

    + */ + public boolean isClanLeader() + { + return _clanLeader; + } + + /** + * Reduce the number of arrows owned by the L2PcInstance and send it Server->Client Packet InventoryUpdate or ItemList (to unequip if the last arrow was consummed).

    + */ + protected void reduceArrowCount() + { + L2ItemInstance arrows = getInventory().destroyItem("Consume", getInventory().getPaperdollObjectId(Inventory.PAPERDOLL_LHAND), 1, this, null); + + if (Config.DEBUG) _log.fine("arrow count:" + (arrows==null? 0 : arrows.getCount())); + + if (arrows == null || arrows.getCount() == 0) + { + getInventory().unEquipItemInSlot(Inventory.PAPERDOLL_LHAND); + _arrowItem = null; + + if (Config.DEBUG) _log.fine("removed arrows count"); + sendPacket(new ItemList(this,false)); + } + else + { + if (!Config.FORCE_INVENTORY_UPDATE) + { + InventoryUpdate iu = new InventoryUpdate(); + iu.addModifiedItem(arrows); + sendPacket(iu); + } + else sendPacket(new ItemList(this, false)); + } + } + + /** + * Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2PcINstance then return True.

    + */ + protected boolean checkAndEquipArrows() + { + // Check if nothing is equiped in left hand + if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null) + { + // Get the L2ItemInstance of the arrows needed for this bow + _arrowItem = getInventory().findArrowForBow(getActiveWeaponItem()); + + if (_arrowItem != null) + { + // Equip arrows needed in left hand + getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, _arrowItem); + + // Send a Server->Client packet ItemList to this L2PcINstance to update left hand equipement + ItemList il = new ItemList(this, false); + sendPacket(il); + } + } + else + { + // Get the L2ItemInstance of arrows equiped in left hand + _arrowItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); + } + + return _arrowItem != null; + } + + + /** + * Return True if the L2PcInstance use a dual weapon.

    + */ + public boolean isUsingDualWeapon() + { + L2Weapon weaponItem = getActiveWeaponItem(); + + if (weaponItem.getItemType() == L2WeaponType.DUAL) + return true; + else if (weaponItem.getItemType() == L2WeaponType.DUALFIST) + return true; + else if (weaponItem.getItemId() == 248) // orc fighter fists + return true; + else if (weaponItem.getItemId() == 252) // orc mage fists + return true; + else + return false; + } + + public void setUptime(long time) + { + _uptime = time; + } + + public long getUptime() + { + return System.currentTimeMillis()-_uptime; + } + + /** + * Set the invulnerability Flag of the L2PcInstance.

    + */ + public void setIsInvul(boolean b) + { + _isInvul = b; + } + + /** + * Return True if the L2PcInstance is invulnerable.

    + */ + public boolean isInvul() + { + return _isInvul || isTeleporting() || _protectEndTime > GameTimeController.getGameTicks(); + } + + /** + * Return True if the L2PcInstance has a Party in progress.

    + */ + public boolean isInParty() + { + return _party != null; + } + + /** + * Set the _party object of the L2PcInstance (without joining it).

    + */ + public void setParty(L2Party party) + { + _party = party; + } + + /** + * Set the _party object of the L2PcInstance AND join it.

    + */ + public void joinParty(L2Party party) + { + if (party != null) + { + // First set the party otherwise this wouldn't be considered + // as in a party into the L2Character.updateEffectIcons() call. + _party = party; + party.addPartyMember(this); + } + } + + + /** + * Manage the Leave Party task of the L2PcInstance.

    + */ + public void leaveParty() + { + if (isInParty()) + { + _party.removePartyMember(this); + _party = null; + } + } + + /** + * Return the _party object of the L2PcInstance.

    + */ + public L2Party getParty() + { + return _party; + } + + /** + * Set the _isGm Flag of the L2PcInstance.

    + */ + public void setIsGM(boolean status) + { + _isGm = status; + } + + /** + * Return True if the L2PcInstance is a GM.

    + */ + public boolean isGM() + { + return _isGm; + } + + /** + * Manage a cancel cast task for the L2PcInstance.

    + * + * Actions :

    + *
  • Set the Intention of the AI to AI_INTENTION_IDLE
  • + *
  • Enable all skills (set _allSkillsDisabled to False)
  • + *
  • Send a Server->Client Packet MagicSkillCanceld to the L2PcInstance and all L2PcInstance in the _KnownPlayers of the L2Character (broadcast)


  • + * + */ + public void cancelCastMagic() + { + // Set the Intention of the AI to AI_INTENTION_IDLE + getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); + + // Enable all skills (set _allSkillsDisabled to False) + enableAllSkills(); + + // Send a Server->Client Packet MagicSkillCanceld to the L2PcInstance and all L2PcInstance in the _KnownPlayers of the L2Character (broadcast) + MagicSkillCanceld msc = new MagicSkillCanceld(getObjectId()); + + // Broadcast the packet to self and known players. + Broadcast.toSelfAndKnownPlayersInRadius(this, msc, 810000/*900*/); + } + + /** + * Set the _accessLevel of the L2PcInstance.

    + */ + public void setAccessLevel(int level) + { + _accessLevel = level; + + if (_accessLevel > 0 || Config.EVERYBODY_HAS_ADMIN_RIGHTS) + setIsGM(true); + } + + public void setAccountAccesslevel(int level) + { + if (_connection != null) + LoginServerThread.getInstance().sendAccessLevel(getAccountName(),level); + else + _log.info("Couldnt set the player's account access level"); + } + + /** + * Return the _accessLevel of the L2PcInstance.

    + */ + public int getAccessLevel() + { + if (Config.EVERYBODY_HAS_ADMIN_RIGHTS && _accessLevel <= 200) + return 200; + + return _accessLevel; + } + + public double getLevelMod() + { + return (100.0 - 11 + getLevel()) / 100.0; + } + + /** + * Update Stats of the L2PcInstance client side by sending Server->Client packet UserInfo/StatusUpdate to this L2PcInstance and CharInfo/StatusUpdate to all L2PcInstance in its _KnownPlayers (broadcast).

    + */ + public void updateStats() + { + super.updateStats(); + refreshOverloaded(); + refreshExpertisePenalty(); + // Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers (broadcast) + broadcastUserInfo(); + + // Send a Server->Client StatusUpdate packet with Karma to the L2PcInstance and to all L2PcInstance in its _KnownPlayers (broadcast) + updateKarma(); + } + + /** + * Send a Server->Client StatusUpdate packet with Karma and PvP Flag to the L2PcInstance and all L2PcInstance to inform (broadcast).

    + */ + public void setKarmaFlag(int flag) + { + // Send a Server->Client StatusUpdate packet with Karma and PvP Flag to the L2PcInstance and all L2PcInstance to inform (broadcast) + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.KARMA, getKarma()); + su.addAttribute(StatusUpdate.PVP_FLAG, flag); + sendPacket(su); + broadcastPacket(su); + } + + /** + * Send a Server->Client StatusUpdate packet with Karma to the L2PcInstance and all L2PcInstance to inform (broadcast).

    + */ + public void updateKarma() + { + // Send a Server->Client StatusUpdate packet with Karma to the L2PcInstance + StatusUpdate su = new StatusUpdate(getObjectId()); + su.addAttribute(StatusUpdate.KARMA, getKarma()); + sendPacket(su); + broadcastPacket(su); + } + + /** + * Set the online Flag to True or False and update the characters table of the database with online status and lastAccess (called when login and logout).

    + */ + public void setOnlineStatus(boolean isOnline) + { + if (_isOnline != isOnline) + _isOnline = isOnline; + + // Update the characters table of the database with online status and lastAccess (called when login and logout) + updateOnlineStatus(); + } + + public void setIsIn7sDungeon(boolean isIn7sDungeon) + { + if (_isIn7sDungeon != isIn7sDungeon) + _isIn7sDungeon = isIn7sDungeon; + + updateIsIn7sDungeonStatus(); + } + + /** + * Update the characters table of the database with online status and lastAccess of this L2PcInstance (called when login and logout).

    + */ + public void updateOnlineStatus() + { + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement("UPDATE characters SET online=?, lastAccess=? WHERE obj_id=?"); + statement.setInt(1, isOnline()); + statement.setLong(2, System.currentTimeMillis()); + statement.setInt(3, getObjectId()); + statement.execute(); + statement.close(); + } + catch (Exception e) + { + _log.warning("could not set char online status:"+e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + } + + public void updateIsIn7sDungeonStatus() + { + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement("UPDATE characters SET isIn7sDungeon=?, lastAccess=? WHERE obj_id=?"); + statement.setInt(1, isIn7sDungeon() ? 1 : 0); + statement.setLong(2, System.currentTimeMillis()); + statement.setInt(3, getObjectId()); + statement.execute(); + statement.close(); + } + catch (Exception e) + { + _log.warning("could not set char isIn7sDungeon status:"+e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + } + + /** + * Create a new player in the characters table of the database.

    + */ + private boolean createDb() + { + java.sql.Connection con = null; + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + statement = con.prepareStatement( + "INSERT INTO characters " + + "(account_name,obj_Id,char_name,level,maxHp,curHp,maxCp,curCp,maxMp,curMp," + + "acc,crit,evasion,mAtk,mDef,mSpd,pAtk,pDef,pSpd,runSpd,walkSpd," + + "str,con,dex,_int,men,wit,face,hairStyle,hairColor,sex," + + "movement_multiplier,attack_speed_multiplier,colRad,colHeight," + + "exp,sp,karma,pvpkills,pkkills,clanid,maxload,race,classid,deletetime," + + "cancraft,title,allyId,accesslevel,online,isin7sdungeon,clan_privs,wantspeace,deleteclan," + + "base_class,newbie) " + + "values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); + statement.setString(1, _accountName); + statement.setInt(2, getObjectId()); + statement.setString(3, getName()); + statement.setInt(4, getLevel()); + statement.setInt(5, getMaxHp()); + statement.setDouble(6, getCurrentHp()); + statement.setInt(7, getMaxCp()); + statement.setDouble(8, getCurrentCp()); + statement.setInt(9, getMaxMp()); + statement.setDouble(10, getCurrentMp()); + statement.setInt(11, getAccuracy()); + statement.setInt(12, getCriticalHit(null, null)); + statement.setInt(13, getEvasionRate(null)); + statement.setInt(14, getMAtk(null, null)); + statement.setInt(15, getMDef(null, null)); + statement.setInt(16, getMAtkSpd()); + statement.setInt(17, getPAtk(null)); + statement.setInt(18, getPDef(null)); + statement.setInt(19, getPAtkSpd()); + statement.setInt(20, getRunSpeed()); + statement.setInt(21, getWalkSpeed()); + statement.setInt(22, getSTR()); + statement.setInt(23, getCON()); + statement.setInt(24, getDEX()); + statement.setInt(25, getINT()); + statement.setInt(26, getMEN()); + statement.setInt(27, getWIT()); + statement.setInt(28, getFace()); + statement.setInt(29, getHairStyle()); + statement.setInt(30, getHairColor()); + statement.setInt(31, getSex()); + statement.setDouble(32, 1/*getMovementMultiplier()*/); + statement.setDouble(33, 1/*getAttackSpeedMultiplier()*/); + statement.setDouble(34, getTemplate().collisionRadius/*getCollisionRadius()*/); + statement.setDouble(35, getTemplate().collisionHeight/*getCollisionHeight()*/); + statement.setInt(36, getExp()); + statement.setInt(37, getSp()); + statement.setInt(38, getKarma()); + statement.setInt(39, getPvpKills()); + statement.setInt(40, getPkKills()); + statement.setInt(41, getClanId()); + statement.setInt(42, getMaxLoad()); + statement.setInt(43, getRace().ordinal()); + statement.setInt(44, getClassId().getId()); + statement.setInt(45, getDeleteTimer()); + statement.setInt(46, hasDwarvenCraft() ? 1 : 0); + statement.setString(47, getTitle()); + statement.setInt(48, getAllyId()); + statement.setInt(49, getAccessLevel()); + statement.setInt(50, isOnline()); + statement.setInt(51, isIn7sDungeon() ? 1 : 0); + statement.setInt(52, getClanPrivileges()); + statement.setInt(53, getWantsPeace()); + statement.setLong(54, getDeleteClanTime()); + statement.setInt(55, getBaseClass()); + statement.setInt(56, isNewbie() ? 1 : 0); + statement.executeUpdate(); + statement.close(); + } + catch (Exception e) + { + _log.warning("Could not insert char data: " + e); + return false; + } + finally + { + try { con.close(); } catch (Exception e) {} + } + return true; + } + + /** + * Retrieve a L2PcInstance from the characters table of the database and add it in _allObjects of the L2world.

    + * + * Actions :

    + *
  • Retrieve the L2PcInstance from the characters table of the database
  • + *
  • Add the L2PcInstance object in _allObjects
  • + *
  • Set the x,y,z position of the L2PcInstance and make it invisible
  • + *
  • Update the overloaded status of the L2PcInstance


  • + * + * @param objectId Identifier of the object to initialized + * + * @return The L2PcInstance loaded from the database + * + */ + private static L2PcInstance restore(int objectId) + { + L2PcInstance player = null; + java.sql.Connection con = null; + + try + { + // Retrieve the L2PcInstance from the characters table of the database + con = L2DatabaseFactory.getInstance().getConnection(); + + PreparedStatement statement = con.prepareStatement(RESTORE_CHARACTER); + statement.setInt(1, objectId); + ResultSet rset = statement.executeQuery(); + + double currentCp = 0; + double currentHp = 0; + double currentMp = 0; + + while (rset.next()) + { + final int activeClassId = rset.getInt("classid"); + final boolean female = rset.getInt("sex")!=0; + final L2PcTemplate template = CharTemplateTable.getInstance().getTemplate(activeClassId, female); + + player = new L2PcInstance(objectId, template, rset.getString("account_name")); + player.setName(rset.getString("char_name")); + player._lastAccess = rset.getLong("lastAccess"); + + player._activeClass = activeClassId; + try { player.setBaseClass(rset.getInt("base_class")); } + catch (Exception e) { player.setBaseClass(activeClassId); } + + player._classIndex = 0; + player.getStat().setExp(rset.getInt("exp")); + player.getStat().setLevel(rset.getInt("level")); + player.getStat().setSp(rset.getInt("sp")); + + player.setFace(rset.getInt("face")); + player.setHairStyle(rset.getInt("hairStyle")); + player.setHairColor(rset.getInt("hairColor")); + player.setClanPrivileges(rset.getInt("clan_privs")); + player.setWantsPeace(rset.getInt("wantspeace")); + + player.setHeading(rset.getInt("heading")); + + player.setKarma(rset.getInt("karma")); + player.setPvpKills(rset.getInt("pvpkills")); + player.setPkKills(rset.getInt("pkkills")); + player.setDeleteClanTime(rset.getLong("deleteclan")); + player.setOnlineTime(rset.getLong("onlinetime")); + player.setNewbie(rset.getInt("newbie")==1); + + if (player.getDeleteClanTime() > 0 && player.canCreateClan()) + player.setDeleteClanTime(0); + + int clanId = rset.getInt("clanid"); + + if (clanId > 0) + player.setClan(ClanTable.getInstance().getClan(clanId)); + + player.setDeleteTimer(rset.getInt("deletetime")); + + player.setTitle(rset.getString("title")); + player.setAccessLevel(rset.getInt("accesslevel")); + player.setFistsWeaponItem(player.findFistsWeaponItem(activeClassId)); + player.setUptime(System.currentTimeMillis()); + + currentHp = rset.getDouble("curHp"); + player.setCurrentHp(rset.getDouble("curHp")); + currentCp = rset.getDouble("curCp"); + player.setCurrentCp(rset.getDouble("curCp")); + currentMp = rset.getDouble("curMp"); + player.setCurrentMp(rset.getDouble("curMp")); + + //Check recs + player.checkRecom(rset.getInt("rec_have"),rset.getInt("rec_left")); + + // Restore Subclass Data + if (restoreSubClassData(player)) + { + if (player.getActiveClass() != player.getBaseClass()) + { + for (SubClass subClass : player.getSubClasses().values()) + if (subClass.getClassId() == player.getActiveClass()) + player._classIndex = subClass.getClassIndex(); + } + } + + player.setIsIn7sDungeon((rset.getInt("isin7sdungeon")==1)? true : false); + player.setInJail((rset.getInt("in_jail")==1)? true : false); + player.setJailTimer(rset.getLong("jail_timer")); + + // Add the L2PcInstance object in _allObjects + //L2World.getInstance().storeObject(player); + + // Set the x,y,z position of the L2PcInstance and make it invisible + player.setXYZInvisible(rset.getInt("x"), rset.getInt("y"), rset.getInt("z")); + + // Retrieve the name and ID of the other characters assigned to this account. + PreparedStatement stmt = con.prepareStatement("SELECT obj_Id, char_name FROM characters WHERE account_name=? AND obj_Id<>?"); + stmt.setString(1, player._accountName); + stmt.setInt(2, objectId); + ResultSet chars = stmt.executeQuery(); + + while (chars.next()) + { + Integer charId = chars.getInt("obj_Id"); + String charName = chars.getString("char_name"); + player._chars.put(charId, charName); + } + + break; + } + + rset.close(); + statement.close(); + + // Retrieve from the database all secondary data of this L2PcInstance + // and reward expertise/lucky skills if necessary. + player.restoreCharData(); + player.rewardSkills(); + + // Restore current Cp, HP and MP values + player.setCurrentCp(currentCp); + player.setCurrentHp(currentHp); + player.setCurrentMp(currentMp); + + // Update the overloaded status of the L2PcInstance + player.refreshOverloaded(); + } + catch (Exception e) + { + _log.warning("Could not restore char data: " + e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + + return player; + } + + /** + * @return + */ + public Forum getMail() + { + if (_forumMail == null) + { + setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").GetChildByName(getName())); + + if (_forumMail == null) + { + ForumsBBSManager.getInstance().CreateNewForum(getName(),ForumsBBSManager.getInstance().getForumByName("MailRoot"),Forum.MAIL,Forum.OWNERONLY,getObjectId()); + setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").GetChildByName(getName())); + } + } + + return _forumMail; + } + + /** + * @param forum + */ + public void setMail(Forum forum) + { + _forumMail = forum; + } + + /** + * @return + */ + public Forum getMemo() + { + if (_forumMemo == null) + { + setMemo(ForumsBBSManager.getInstance().getForumByName("MemoRoot").GetChildByName(_accountName)); + + if (_forumMemo == null) + { + ForumsBBSManager.getInstance().CreateNewForum(_accountName,ForumsBBSManager.getInstance().getForumByName("MemoRoot"),Forum.MEMO,Forum.OWNERONLY,getObjectId()); + setMemo(ForumsBBSManager.getInstance().getForumByName("MemoRoot").GetChildByName(_accountName)); + } + } + + return _forumMemo; + } + + /** + * @param forum + */ + public void setMemo(Forum forum) + { + _forumMemo = forum; + } + + /** + * Restores sub-class data for the L2PcInstance, used to check the current + * class index for the character. + */ + private static boolean restoreSubClassData(L2PcInstance player) + { + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_SUBCLASSES); + statement.setInt(1, player.getObjectId()); + + ResultSet rset = statement.executeQuery(); + + while (rset.next()) + { + SubClass subClass = new SubClass(); + subClass.setClassId(rset.getInt("class_id")); + subClass.setLevel(rset.getInt("level")); + subClass.setExp(rset.getInt("exp")); + subClass.setSp(rset.getInt("sp")); + subClass.setClassIndex(rset.getInt("class_index")); + + // Enforce the correct indexing of _subClasses against their class indexes. + player.getSubClasses().put(subClass.getClassIndex(), subClass); + } + + statement.close(); + } + catch (Exception e) { + _log.warning("Could not restore classes for " + player.getName() + ": " + e); + e.printStackTrace(); + } + finally { + try { con.close(); } catch (Exception e) {} + } + + return true; + } + + /** + * Restores secondary data for the L2PcInstance, based on the current class index. + */ + private void restoreCharData() + { + // Retrieve from the database all skills of this L2PcInstance and add them to _skills. + restoreSkills(); + + // Retrieve from the database all macroses of this L2PcInstance and add them to _macroses. + _macroses.restore(); + + // Retrieve from the database all shortCuts of this L2PcInstance and add them to _shortCuts. + _shortCuts.restore(); + + // Retrieve from the database all henna of this L2PcInstance and add them to _henna. + restoreHenna(); + + // Retrieve from the database the recipe book of this L2PcInstance. + if (!isSubClassActive()) + restoreRecipeBook(); + } + + /** + * Store recipe book data for this L2PcInstance, if not on an active sub-class. + */ + private void storeRecipeBook() + { + // If the player is on a sub-class don't even attempt to store a recipe book. + if (isSubClassActive()) + return; + if (getCommonRecipeBook().length == 0 && getDwarvenRecipeBook().length == 0) + return; + + java.sql.Connection con = null; + + try { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement("DELETE FROM character_recipebook WHERE char_id=?"); + statement.setInt(1, getObjectId()); + statement.execute(); + statement.close(); + + L2RecipeList[] recipes = getCommonRecipeBook(); + + for (int count = 0; count < recipes.length; count++) + { + statement = con.prepareStatement("INSERT INTO character_recipebook (char_id, id, type) values(?,?,0)"); + statement.setInt(1, getObjectId()); + statement.setInt(2, recipes[count].getId()); + statement.execute(); + statement.close(); + } + + recipes = getDwarvenRecipeBook(); + for (int count = 0; count < recipes.length; count++) + { + statement = con.prepareStatement("INSERT INTO character_recipebook (char_id, id, type) values(?,?,1)"); + statement.setInt(1, getObjectId()); + statement.setInt(2, recipes[count].getId()); + statement.execute(); + statement.close(); + } + } + catch (Exception e) { + _log.warning("Could not store recipe book data: " + e); + } + finally { + try { con.close(); } catch (Exception e) {} + } + } + + /** + * Restore recipe book data for this L2PcInstance. + */ + private void restoreRecipeBook() + { + java.sql.Connection con = null; + + try { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement("SELECT id, type FROM character_recipebook WHERE char_id=?"); + statement.setInt(1, getObjectId()); + ResultSet rset = statement.executeQuery(); + + L2RecipeList recipe; + while (rset.next()) { + recipe = RecipeController.getInstance().getRecipeList(rset.getInt("id") - 1); + + if (rset.getInt("type") == 1) + registerDwarvenRecipeList(recipe); + else + registerCommonRecipeList(recipe); + } + + rset.close(); + statement.close(); + } + catch (Exception e) { + _log.warning("Could not restore recipe book data:" + e); + } + finally { + try { con.close(); } catch (Exception e) {} + } + } + + /** + * Update L2PcInstance stats in the characters table of the database.

    + */ + public void store() + { + //update client coords, if these look like true + if (isInsideRadius(getClientX(), getClientY(), 1000, true)) + setXYZ(getClientX(), getClientY(), getClientZ()); + + storeCharBase(); + storeCharSub(); + storeEffect(); + storeRecipeBook(); + } + + private void storeCharBase() + { + java.sql.Connection con = null; + + try + { + // Get the exp, level, and sp of base class to store in base table + int currentClassIndex = getClassIndex(); + _classIndex = 0; + int exp = getStat().getExp(); + int level = getStat().getLevel(); + int sp = getStat().getSp(); + _classIndex = currentClassIndex; + + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + + // Update base class + statement = con.prepareStatement(UPDATE_CHARACTER); + statement.setInt(1, level); + statement.setInt(2, getMaxHp()); + statement.setDouble(3, getCurrentHp()); + statement.setInt(4, getMaxCp()); + statement.setDouble(5, getCurrentCp()); + statement.setInt(6, getMaxMp()); + statement.setDouble(7, getCurrentMp()); + statement.setInt(8, getSTR()); + statement.setInt(9, getCON()); + statement.setInt(10, getDEX()); + statement.setInt(11, getINT()); + statement.setInt(12, getMEN()); + statement.setInt(13, getWIT()); + statement.setInt(14, getFace()); + statement.setInt(15, getHairStyle()); + statement.setInt(16, getHairColor()); + statement.setInt(17, getHeading()); + statement.setInt(18, getX()); + statement.setInt(19, getY()); + statement.setInt(20, getZ()); + statement.setInt(21, exp); + statement.setInt(22, sp); + statement.setInt(23, getKarma()); + statement.setInt(24, getPvpKills()); + statement.setInt(25, getPkKills()); + statement.setInt(26, getRecomHave()); + statement.setInt(27, getRecomLeft()); + statement.setInt(28, getClanId()); + statement.setInt(29, getMaxLoad()); + statement.setInt(30, getRace().ordinal()); + +// if (!isSubClassActive()) + +// else +// statement.setInt(30, getBaseTemplate().race.ordinal()); + + statement.setInt(31, getClassId().getId()); + statement.setInt(32, getDeleteTimer()); + statement.setString(33, getTitle()); + statement.setInt(34, getAllyId()); + statement.setInt(35, getAccessLevel()); + statement.setInt(36, isOnline()); + statement.setInt(37, isIn7sDungeon() ? 1 : 0); + statement.setInt(38, getClanPrivileges()); + statement.setInt(39, getWantsPeace()); + statement.setLong(40, getDeleteClanTime()); + statement.setInt(41, getBaseClass()); + + long totalOnlineTime = _onlineTime; + + if (_onlineBeginTime > 0) + totalOnlineTime += (System.currentTimeMillis()-_onlineBeginTime)/1000; + + statement.setLong(42, totalOnlineTime); + statement.setInt(43, isInJail() ? 1 : 0); + statement.setLong(44, getJailTimer()); + statement.setInt(45, isNewbie() ? 1 : 0); + statement.setInt(46, getObjectId()); + + statement.execute(); + statement.close(); + } + catch (Exception e) { _log.warning("Could not store char base data: "+ e); } + finally { try { con.close(); } catch (Exception e) {} } + } + + private void storeCharSub() + { + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + + if (getTotalSubClasses() > 0) + { + for (SubClass subClass : getSubClasses().values()) + { + statement = con.prepareStatement(UPDATE_CHAR_SUBCLASS); + statement.setInt(1, subClass.getExp()); + statement.setInt(2, subClass.getSp()); + statement.setInt(3, subClass.getLevel()); + statement.setInt(4, subClass.getClassId()); + statement.setInt(5, getObjectId()); + statement.setInt(6, subClass.getClassIndex()); + + statement.execute(); + statement.close(); + } + } + } + catch (Exception e) { + _log.warning("Could not store sub class data for " + getName() + ": "+ e); + } + finally { try { con.close(); } catch (Exception e) {} } + } + + private void storeEffect() + { + if (!Config.STORE_SKILL_COOLTIME) return; + + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + + // Delete all current stored effects for char to avoid dupe + statement = con.prepareStatement(DELETE_SKILL_SAVE); + statement.setInt(1, getObjectId()); + statement.setInt(2, getClassIndex()); + statement.execute(); + statement.close(); + + // Loop thru all effects for char and same them each to database + for (L2Effect effect : getAllEffects()) + { + if (effect != null && effect.getInUse() && !effect.getSkill().isToggle()) + { + statement = con.prepareStatement(ADD_SKILL_SAVE); + statement.setInt(1, getObjectId()); + statement.setInt(2, effect.getSkill().getId()); + statement.setInt(3, effect.getSkill().getLevel()); + statement.setInt(4, effect.getCount()); + statement.setInt(5, effect.getTime()); + statement.setInt(6, getClassIndex()); + statement.execute(); + statement.close(); + } + } + } + catch (Exception e) { _log.warning("Could not store char effect data: "+ e); } + finally { try { con.close(); } catch (Exception e) {} } + } + + /** + * Return True if the L2PcInstance is on line.

    + */ + public int isOnline() + { + return (_isOnline ? 1 : 0); + } + + public boolean isIn7sDungeon() + { + return _isIn7sDungeon; + } + + /** + * Add a skill to the L2PcInstance _skills and its Func objects to the calculator set of the L2PcInstance and save update in the character_skills table of the database.

    + * + * Concept :

    + * All skills own by a L2PcInstance are identified in _skills

    + * + * Actions :

    + *
  • Replace oldSkill by newSkill or Add the newSkill
  • + *
  • If an old skill has been replaced, remove all its Func objects of L2Character calculator set
  • + *
  • Add Func objects of newSkill to the calculator set of the L2Character


  • + * + * @param newSkill The L2Skill to add to the L2Character + * + * @return The L2Skill replaced or null if just added a new L2Skill + * + */ + public L2Skill addSkill(L2Skill newSkill) + { + // Add a skill to the L2PcInstance _skills and its Func objects to the calculator set of the L2PcInstance + L2Skill oldSkill = super.addSkill(newSkill); + + // Add or update a L2PcInstance skill in the character_skills table of the database + storeSkill(newSkill, oldSkill, -1); + + return oldSkill; + } + + /** + * Remove a skill from the L2Character and its Func objects from calculator set of the L2Character and save update in the character_skills table of the database.

    + * + * Concept :

    + * All skills own by a L2Character are identified in _skills

    + * + * Actions :

    + *
  • Remove the skill from the L2Character _skills
  • + *
  • Remove all its Func objects from the L2Character calculator set


  • + * + * Overriden in :

    + *
  • L2PcInstance : Save update in the character_skills table of the database


  • + * + * @param skill The L2Skill to remove from the L2Character + * + * @return The L2Skill removed + * + */ + public L2Skill removeSkill(L2Skill skill) + { + // Remove a skill from the L2Character and its Func objects from calculator set of the L2Character + L2Skill oldSkill = super.removeSkill(skill); + + java.sql.Connection con = null; + + try + { + // Remove or update a L2PcInstance skill from the character_skills table of the database + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + + if (oldSkill != null) + { + statement = con.prepareStatement(DELETE_SKILL_FROM_CHAR); + statement.setInt(1, oldSkill.getId()); + statement.setInt(2, getObjectId()); + statement.setInt(3, getClassIndex()); + statement.execute(); + statement.close(); + } + } + catch (Exception e) + { + _log.warning("Error could not delete skill: " + e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + + return oldSkill; + } + + /** + * Add or update a L2PcInstance skill in the character_skills table of the database. + *

    + * If newClassIndex > -1, the skill will be stored with that class index, not the current one. + */ + private void storeSkill(L2Skill newSkill, L2Skill oldSkill, int newClassIndex) + { + int classIndex = _classIndex; + + if (newClassIndex > -1) + classIndex = newClassIndex; + + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + + if (oldSkill != null && newSkill != null) + { + statement = con.prepareStatement(UPDATE_CHARACTER_SKILL_LEVEL); + statement.setInt(1, newSkill.getLevel()); + statement.setInt(2, oldSkill.getId()); + statement.setInt(3, getObjectId()); + statement.setInt(4, classIndex); + statement.execute(); + statement.close(); + } + else if (newSkill != null) + { + statement = con.prepareStatement(ADD_NEW_SKILL); + statement.setInt(1, getObjectId()); + statement.setInt(2, newSkill.getId()); + statement.setInt(3, newSkill.getLevel()); + statement.setString(4, newSkill.getName()); + statement.setInt(5, classIndex); + statement.execute(); + statement.close(); + } + else + { + _log.warning("could not store new skill. its NULL"); + } + } + catch (Exception e) + { + _log.warning("Error could not store char skills: " + e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + } + + /** + * Retrieve from the database all skills of this L2PcInstance and add them to _skills.

    + */ + private void restoreSkills() + { + java.sql.Connection con = null; + + try + { + // Retrieve all skills of this L2PcInstance from the database + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement(RESTORE_SKILLS_FOR_CHAR); + statement.setInt(1, getObjectId()); + statement.setInt(2, getClassIndex()); + ResultSet rset = statement.executeQuery(); + + // Go though the recordset of this SQL query + while (rset.next()) + { + int id = rset.getInt("skill_id"); + int level = rset.getInt("skill_level"); + + if (id > 9000) + continue; // fake skills for base stats + + // Create a L2Skill object for each record + L2Skill skill = SkillTable.getInstance().getInfo(id, level); + + // Add the L2Skill object to the L2Character _skills and its Func objects to the calculator set of the L2Character + super.addSkill(skill); + } + + rset.close(); + statement.close(); + } + catch (Exception e) + { + _log.warning("Could not restore character skills: " + e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + } + + /** + * HRetrieve from the database all skill effects of this L2PcInstance and add them to the player.

    + */ + public void restoreEffects() + { + L2Object[] targets = new L2Character[]{this}; + java.sql.Connection con = null; + + try { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + + statement = con.prepareStatement(RESTORE_SKILL_SAVE); + statement.setInt(1, getObjectId()); + statement.setInt(2, getClassIndex()); + + ResultSet rset = statement.executeQuery(); + + while (rset.next()) + { + int skillId = rset.getInt("skill_id"); + int skillLvl = rset.getInt("skill_level"); + int effectCount = rset.getInt("effect_count"); + int effectCurTime = rset.getInt("effect_cur_time"); + + L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl); + callSkill(skill, targets); + + for (L2Effect effect : getAllEffects()) + { + if (effect.getSkill().getId() == skillId) + { + effect.setCount(effectCount); + effect.setFirstTime(effectCurTime); + } + } + } + + statement = con.prepareStatement(DELETE_SKILL_SAVE); + statement.setInt(1, getObjectId()); + statement.setInt(2, getClassIndex()); + statement.executeUpdate(); + } + catch (Exception e) { + _log.warning("Could not restore active effect data: " + e); + } + finally { + try {con.close();} catch (Exception e) {} + } + + updateEffectIcons(); + } + + /** + * Retrieve from the database all Henna of this L2PcInstance, add them to _henna and calculate stats of the L2PcInstance.

    + */ + private void restoreHenna() + { + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_HENNAS); + statement.setInt(1, getObjectId()); + statement.setInt(2, getClassIndex()); + ResultSet rset = statement.executeQuery(); + + for (int i=0;i<3;i++) + _henna[i]=null; + + while (rset.next()) + { + int slot = rset.getInt("slot"); + + if (slot<1 || slot>3) + continue; + + int symbol_id = rset.getInt("symbol_id"); + + L2HennaInstance sym = null; + + if (symbol_id != 0) + { + L2Henna tpl = HennaTable.getInstance().getTemplate(symbol_id); + + if (tpl != null) + { + sym = new L2HennaInstance(tpl); + _henna[slot-1] = sym; + } + } + } + + rset.close(); + statement.close(); + } + catch (Exception e) + { + _log.warning("could not restore henna: "+e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + + // Calculate Henna modifiers of this L2PcInstance + recalcHennaStats(); + } + + /** + * Return the number of Henna empty slot of the L2PcInstance.

    + */ + public int getHennaEmptySlots() + { + int totalSlots = 1 + getClassId().level(); + + for (int i = 0; i < 3; i++) + if (_henna[i] != null) + totalSlots--; + + if (totalSlots <= 0) + return 0; + + return totalSlots; + } + + /** + * Remove a Henna of the L2PcInstance, save update in the character_hennas table of the database and send Server->Client HennaInfo/UserInfo packet to this L2PcInstance.

    + */ + public boolean removeHenna(int slot) + { + if (slot<1 || slot>3) + return false; + + slot--; + + if (_henna[slot]==null) + return false; + + L2HennaInstance henna = _henna[slot]; + _henna[slot] = null; + + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA); + statement.setInt(1, getObjectId()); + statement.setInt(2, slot+1); + statement.setInt(3, getClassIndex()); + statement.execute(); + statement.close(); + } + catch (Exception e) + { + _log.warning("could not remove char henna: "+e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + + // Calculate Henna modifiers of this L2PcInstance + recalcHennaStats(); + + // Send Server->Client HennaInfo packet to this L2PcInstance + sendPacket(new HennaInfo(this)); + + // Send Server->Client UserInfo packet to this L2PcInstance + sendPacket(new UserInfo(this)); + + // Add the recovered dyes to the player's inventory and notify them. + getInventory().addItem("Henna", henna.getItemIdDye(), henna.getAmountDyeRequire() / 2, this, null); + + SystemMessage sm = new SystemMessage(SystemMessage.EARNED_S2_S1_s); + sm.addItemName(henna.getItemIdDye()); + sm.addNumber(henna.getAmountDyeRequire() / 2); + sendPacket(sm); + + return true; + } + + /** + * Add a Henna to the L2PcInstance, save update in the character_hennas table of the database and send Server->Client HennaInfo/UserInfo packet to this L2PcInstance.

    + */ + public boolean addHenna(L2HennaInstance henna) + { + if (getHennaEmptySlots()==0) + { + this.sendMessage("You may not have more than three equipped symbols at a time."); + return false; + } + + // int slot = 0; + for (int i=0;i<3;i++) + { + if (_henna[i]==null) + { + _henna[i]=henna; + + // Calculate Henna modifiers of this L2PcInstance + recalcHennaStats(); + + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement(ADD_CHAR_HENNA); + statement.setInt(1, getObjectId()); + statement.setInt(2, henna.getSymbolId()); + statement.setInt(3, i+1); + statement.setInt(4, getClassIndex()); + statement.execute(); + statement.close(); + } + catch (Exception e) + { + _log.warning("could not save char henna: "+e); + } + finally + { + try { con.close(); } catch (Exception e) {} + } + + // Send Server->Client HennaInfo packet to this L2PcInstance + HennaInfo hi = new HennaInfo(this); + this.sendPacket(hi); + + // Send Server->Client UserInfo packet to this L2PcInstance + UserInfo ui = new UserInfo(this); + this.sendPacket(ui); + + return true; + } + } + + return false; + } + + /** + * Calculate Henna modifiers of this L2PcInstance.

    + */ + private void recalcHennaStats() + { + _hennaINT = 0; + _hennaSTR = 0; + _hennaCON = 0; + _hennaMEN = 0; + _hennaWIT = 0; + _hennaDEX = 0; + + for (int i=0;i<3;i++) + { + if (_henna[i]==null)continue; + _hennaINT += _henna[i].getStatINT(); + _hennaSTR += _henna[i].getStatSTR(); + _hennaMEN += _henna[i].getStatMEM(); + _hennaCON += _henna[i].getStatCON(); + _hennaWIT += _henna[i].getStatWIT(); + _hennaDEX += _henna[i].getStatDEX(); + } + + if (_hennaINT>5)_hennaINT=5; + if (_hennaSTR>5)_hennaSTR=5; + if (_hennaMEN>5)_hennaMEN=5; + if (_hennaCON>5)_hennaCON=5; + if (_hennaWIT>5)_hennaWIT=5; + if (_hennaDEX>5)_hennaDEX=5; + } + + /** + * Return the Henna of this L2PcInstance corresponding to the selected slot.

    + */ + public L2HennaInstance getHenna(int slot) + { + if (slot < 1 || slot > 3) + return null; + + return _henna[slot - 1]; + } + + /** + * Return the INT Henna modifier of this L2PcInstance.

    + */ + public int getHennaStatINT() + { + return _hennaINT; + } + + /** + * Return the STR Henna modifier of this L2PcInstance.

    + */ + public int getHennaStatSTR() + { + return _hennaSTR; + } + + /** + * Return the CON Henna modifier of this L2PcInstance.

    + */ + public int getHennaStatCON() + { + return _hennaCON; + } + + /** + * Return the MEN Henna modifier of this L2PcInstance.

    + */ + public int getHennaStatMEN() + { + return _hennaMEN; + } + + /** + * Return the WIT Henna modifier of this L2PcInstance.

    + */ + public int getHennaStatWIT() + { + return _hennaWIT; + } + + /** + * Return the DEX Henna modifier of this L2PcInstance.

    + */ + public int getHennaStatDEX() + { + return _hennaDEX; + } + + /** + * Return True if the L2PcInstance is autoAttackable.

    + * + * Actions :

    + *
  • Check if the attacker isn't the L2PcInstance Pet
  • + *
  • Check if the attacker is L2MonsterInstance
  • + *
  • If the attacker is a L2PcInstance, check if it is not in the same party
  • + *
  • Check if the L2PcInstance has Karma
  • + *
  • If the attacker is a L2PcInstance, check if it is not in the same siege clan (Attacker, Defender)


  • + * + */ + public boolean isAutoAttackable(L2Character attacker) + { + // Check if the attacker isn't the L2PcInstance Pet + if (attacker == this || attacker == this.getPet()) + return false; + + // TODO: check for friendly mobs + // Check if the attacker is a L2MonsterInstance + if (attacker instanceof L2MonsterInstance) + return true; + + // Check if the attacker is not in the same party + if (getParty() != null && getParty().getPartyMembers().contains(attacker)) + return false; + + // Check if the attacker is not in the same clan + if (getClan() != null && attacker != null && getClan().isMember(attacker.getName())) + return false; + + // Check if the L2PcInstance has Karma + if (getKarma() > 0 || getPvpFlag() > 0) + return true; + + // Check if the attacker is a L2PcInstance + if (attacker instanceof L2PcInstance) + { + // Check if the L2PcInstance is in an arena or a siege area + if (ZoneManager.getInstance().checkIfInZonePvP(this) && ZoneManager.getInstance().checkIfInZonePvP(attacker)) + return true; + + if (this.getClan() != null) + { + Siege siege = SiegeManager.getInstance().getSiege(getX(), getY()); + if (siege != null) + { + // Check if a siege is in progress and if attacker and the L2PcInstance aren't in the Defender clan + if (siege.checkIsDefender(((L2PcInstance)attacker).getClan()) && + siege.checkIsDefender(this.getClan())) + return false; + + // Check if a siege is in progress and if attacker and the L2PcInstance aren't in the Attacker clan + if (siege.checkIsAttacker(((L2PcInstance)attacker).getClan()) && + siege.checkIsAttacker(this.getClan())) + return false; + } + + // Check if clan is at war +// if (this.getClan() != null && ((L2PcInstance)attacker).getClan() != null && (this.getClan().isAtWarWith(((L2PcInstance)attacker).getClanId()) && this.getWantsPeace() == 0 && ((L2PcInstance)attacker).getWantsPeace() == 0)) +// return true; + } + } + else if (attacker instanceof L2SiegeGuardInstance) + { + if (this.getClan() != null) + { + Siege siege = SiegeManager.getInstance().getSiege(this); + return (siege != null && siege.checkIsAttacker(this.getClan())); + } + } + + return false; + } + + + /** + * Check if the active L2Skill can be casted.

    + * + * Actions :

    + *
  • Check if the skill isn't toggle and is offensive
  • + *
  • Check if the target is in the skill cast range
  • + *
  • Check if the skill is Spoil type and if the target isn't already spoiled
  • + *
  • Check if the caster owns enought consummed Item, enough HP and MP to cast the skill
  • + *
  • Check if the caster isn't sitting
  • + *
  • Check if all skills are enabled and this skill is enabled


  • + *
  • Check if the caster own the weapon needed


  • + *
  • Check if the skill is active


  • + *
  • Check if all casting conditions are completed


  • + *
  • Notify the AI with AI_INTENTION_CAST and target


  • + * + * @param skill The L2Skill to use + * @param forceUse used to force ATTACK on players + * @param dontMove used to prevent movement, if not in range + * + */ + public void useMagic(L2Skill skill, boolean forceUse, boolean dontMove) + { + if (isDead()) + { + abortCast(); + sendPacket(new ActionFailed()); + return; + } + + if (isWearingFormalWear() && !skill.isPotion()) + { + sendPacket(new SystemMessage(SystemMessage.CANNOT_USE_ITEMS_SKILLS_WITH_FORMALWEAR)); + + sendPacket(new ActionFailed()); + abortCast(); + return; + } + + if (inObserverMode()) + { + sendMessage("Cant use magic in observer mode"); + abortCast(); + sendPacket(new ActionFailed()); + return; + } + + + // Check if the skill type is TOGGLE + if (skill.isToggle()) + { + // Get effects of the skill + L2Effect effect = getEffect(skill); + + if (effect != null) + { + effect.exit(); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + } + + // Check if the skill is active + if (skill.isPassive()) + { + // just ignore the passive skill request. why does the client send it anyway ?? + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + + //************************************* Check Casting in Progress ******************************************* + + // If a skill is currently being used, queue this one if this is not the same + if (getCurrentSkill() != null && isCastingNow()) + { + // Check if new skill different from current skill in progress + if (skill.getId() == getCurrentSkill().getSkillId()) + return; + + if (Config.DEBUG && getQueuedSkill() != null) + _log.info(getQueuedSkill().getSkill().getName() + " is already queued for " + getName() + "."); + + //setCurrentSkill(null, false, false); + + // Create a new SkillDat object and queue it in the player _queuedSkill + setQueuedSkill(skill, forceUse, dontMove); + return; + } + + + + //************************************* Check Target ******************************************* + + // Create and set a L2Object containing the target of the skill + L2Object target = null; + + switch (skill.getTargetType()) + { + // Target the player if skill type is AURA, PARTY, CLAN or SELF + case TARGET_AURA: + case TARGET_PARTY: + case TARGET_ALLY: + case TARGET_CLAN: + case TARGET_SELF: + target = this; + break; + default: + target = getTarget(); + break; + } + + // Check the validity of the target + if (target == null) + { + sendPacket(new SystemMessage(SystemMessage.TARGET_CANT_FOUND)); + sendPacket(new ActionFailed()); + return; + } + + //Don't allow casting on players on different dungeon lvls etc + if ((Math.abs(target.getZ() - getZ()) > 1000)) + { + sendPacket(new SystemMessage(SystemMessage.CANT_SEE_TARGET)); + sendPacket(new ActionFailed()); + return; + } + + + + //************************************* Check skill availability ******************************************* + + // Check if this skill is enabled (ex : reuse time) + if (isSkillDisabled(skill.getId()) && (getAccessLevel() < Config.GM_PEACEATTACK)) + { + SystemMessage sm = new SystemMessage(SystemMessage.SKILL_NOT_AVAILABLE); + sm.addString(skill.getName()); + sendPacket(sm); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + // Check if all skills are disabled + if (isAllSkillsDisabled() && (getAccessLevel() < Config.GM_PEACEATTACK)) + { + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + + + //************************************* Check Consumables ******************************************* + + // Check if the caster has enough MP + if (getCurrentMp() < skill.getMpConsume()) + { + // Send a System Message to the caster + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + // Check if the caster has enough HP + if (getCurrentHp() <= skill.getHpConsume()) + { + // Send a System Message to the caster + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_HP)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + 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()) + { + // Send a System Message to the caster + sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_ITEMS)); + return; + } + } + + + + //************************************* 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(new ActionFailed()); + return; + } + + // Check if all casting conditions are completed + if (!skill.checkCondition(this)) + { + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + + + //************************************* Check Player State ******************************************* + + // Abnormal effects(ex : Stun, Sleep...) are checked in L2Character useMagic() + + // Check if the player use "Fake Death" skill + if (isAlikeDead()) + { + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + // Check if the caster is sitting + if (isSitting() && !skill.isPotion()) + { + // Send a System Message to the caster + sendPacket(new SystemMessage(SystemMessage.CANT_MOVE_SITTING)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + if (isFishing() && (skill.getSkillType() != SkillType.PUMPING && skill.getSkillType() != SkillType.REELING && skill.getSkillType() != SkillType.FISHING)) + { + //Only fishing skills are available + this.sendPacket(new SystemMessage(1448)); + return; + } + + + + //************************************* Check Skill Type ******************************************* + + // Check if this is offensive magic skill + if (skill.isOffensive()) + { + if ((isInsidePeaceZone(this, target)) && (getAccessLevel() < Config.GM_PEACEATTACK)) + { + // If L2Character or target is in a peace zone, send a system message TARGET_IN_PEACEZONE a Server->Client packet ActionFailed + sendPacket(new SystemMessage(SystemMessage.TARGET_IN_PEACEZONE)); + sendPacket(new ActionFailed()); + return; + } + + + // Check if the target is attackable + if (!target.isAttackable() && (getAccessLevel() < Config.GM_PEACEATTACK)) + { + // If target is not attackable, send a Server->Client packet ActionFailed + sendPacket(new ActionFailed()); + return; + } + + // Check if a Forced ATTACK is in progress on non-attackable target + if (!target.isAutoAttackable(this) && !forceUse && + skill.getTargetType() != SkillTargetType.TARGET_AURA && + skill.getTargetType() != SkillTargetType.TARGET_CLAN && + skill.getTargetType() != SkillTargetType.TARGET_ALLY && + skill.getTargetType() != SkillTargetType.TARGET_PARTY && + skill.getTargetType() != SkillTargetType.TARGET_SELF) + { + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + + // Check if the target is in the skill cast range + if (dontMove) + { + // Calculate the distance between the L2PcInstance and the target + if (skill.getCastRange() > 0 && !isInsideRadius(target, skill.getCastRange(), false, false)) + { + // Send a System Message to the caster + sendPacket(new SystemMessage(SystemMessage.TARGET_TOO_FAR)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + 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 + && (skill.getTargetType() != SkillTargetType.TARGET_PET) + && (skill.getTargetType() != SkillTargetType.TARGET_AURA) + && (skill.getTargetType() != SkillTargetType.TARGET_CLAN) + && (skill.getTargetType() != SkillTargetType.TARGET_SELF) + && (skill.getTargetType() != SkillTargetType.TARGET_PARTY) + && (skill.getTargetType() != SkillTargetType.TARGET_ALLY) + && (skill.getTargetType() != SkillTargetType.TARGET_CORPSE_MOB) + && (skill.getTargetType() != SkillTargetType.TARGET_AREA_CORPSE_MOB)) + { + // send the action failed so that the skill doens't go off. + sendPacket (new ActionFailed()); + return; + } + } + + // Check if the skill is Spoil type and if the target isn't already spoiled + if (skill.getSkillType() == SkillType.SPOIL) + { + if (target instanceof L2Attackable && ((L2Attackable)target).isSpoil()) + { + // Send a System Message to the caster + sendPacket(new SystemMessage(SystemMessage.ALREDAY_SPOILED)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + } + + // Check if the skill is Sweep type and if conditions not apply + if (skill.getSkillType() == SkillType.SWEEP && target instanceof L2Attackable) + { + int spoilerId = ((L2Attackable)target).getIsSpoiledBy(); + + if ((((L2Attackable)target).isDead() && !((L2Attackable)target).isSpoil()) || (getObjectId() != spoilerId && !isInSpoilerParty(spoilerId))) + { + // Send a System Message to the L2PcInstance + sendPacket(new SystemMessage(SystemMessage.SWEEPER_FAILED_TARGET_NOT_SPOILED)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + } + + // Check if the skill is Drain Soul (Soul Crystals) and if the target is a MOB + if (skill.getSkillType() == SkillType.DRAIN_SOUL) + { + if (!(target instanceof L2MonsterInstance)) + { + // Send a System Message to the L2PcInstance + sendPacket(new SystemMessage(SystemMessage.TARGET_IS_INCORRECT)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + } + + // Check if this is a Pvp skill and target isn't a non-flagged/non-karma player + switch (skill.getTargetType()) + { + 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: + break; + default: + if (!checkPvpSkill(target, skill) && (getAccessLevel() < Config.GM_PEACEATTACK)) + { + // Send a System Message to the L2PcInstance + sendPacket(new SystemMessage(SystemMessage.TARGET_IS_INCORRECT)); + + // Send a Server->Client packet ActionFailed to the L2PcInstance + sendPacket(new ActionFailed()); + return; + } + } + + if (skill.getTargetType() == SkillTargetType.TARGET_HOLY && !TakeCastle.checkIfOkToCastSealOfRule(this, false)) + { + sendPacket(new ActionFailed()); + abortCast(); + return; + } + + if (skill.getSkillType() == SkillType.SIEGEFLAG && !SiegeFlag.checkIfOkToPlaceFlag(this, false)) + { + sendPacket(new ActionFailed()); + abortCast(); + return; + } + + + + // If all conditions are checked, create a new SkillDat object and set the player _currentSkill + setCurrentSkill(skill, forceUse, dontMove); + + // Check if the active L2Skill can be casted (ex : not sleeping...), Check if the target is correct and Notify the AI with AI_INTENTION_CAST and target + super.useMagic(skill); + + } + + public boolean isInSpoilerParty(int SpoilerId) + { + L2PcInstance spoiler = (L2PcInstance)L2World.getInstance().findObject(SpoilerId); + + if (isInParty() && spoiler != null) + return getParty().getPartyMembers().contains(spoiler); + + return false; + } + + /** + * Check if the requested casting is a Pc->Pc skill cast and if it's a valid pvp condition + * @param target L2Object instance containing the target + * @param skill L2Skill instance with the skill being casted + * @return False if the skill is a pvpSkill and target is not a valid pvp target + */ + public boolean checkPvpSkill(L2Object target, L2Skill skill) + { + // check for PC->PC Pvp status + if ( + target != null && // target not null and + target != this && // target is not self and + target instanceof L2PcInstance && // target is L2PcInstance and + skill.isPvpSkill() && // pvp skill and + !ZoneManager.getInstance().checkIfInZonePvP(this) && // Pc is not in PvP zone + !ZoneManager.getInstance().checkIfInZonePvP(target) // target is not in PvP zone + ) + { + if ( + ((L2PcInstance)target).getPvpFlag() == 0 && // target's pvp flag is not set and + ((L2PcInstance)target).getKarma() == 0 // target has no karma + ) + return false; + } + return true; + } + + /** + * Reduce Item quantity of the L2PcInstance Inventory and send it a Server->Client packet InventoryUpdate.

    + */ + public void consumeItem(int itemConsumeId, int itemCount) + { + if (itemConsumeId != 0 && itemCount != 0) + destroyItemByItemId("Consume", itemConsumeId, itemCount, null, false); + } + + /** + * Return True if the L2PcInstance is a Mage.

    + */ + public boolean isMageClass() + { + L2CharTemplate template = CharTemplateTable.getInstance().getTemplate(getClassId(), getSex()!=0); + + if (template.baseMAtk > 3) + return true; + + return false; + } + + + public boolean isMounted() + { + return _mountType > 0; + } + + /** + * Set the type of Pet mounted (0 : none, 1 : Stridder, 2 : Wyvern) and send a Server->Client packet InventoryUpdate to the L2PcInstance.

    + */ + public boolean checkLandingState() + { + // Check if char is in a no landing zone + if (ZoneManager.getInstance().checkIfInZoneNoLanding(this)) + return true; + else + // if this is a castle that is currently being sieged, and the rider is NOT a castle owner + // he cannot land. + // castle owner is the leader of the clan that owns the castle where the pc is + if (SiegeManager.getInstance().checkIfInZone(this) && + !(getClan()!=null && + CastleManager.getInstance().getCastle(this) == CastleManager.getInstance().getCastleByOwner(getClan()) && + this == getClan().getLeader().getPlayerInstance())) + return true; + + return false; + } + + public void setMountType(int mountType) + { + if (checkLandingState() && mountType !=0) + return; + + switch(mountType) + { + case 0: + setIsFlying(false); + setIsRiding(false); + break; //Dismounted + case 1: + setIsRiding(true); + break; + case 2: + setIsFlying(true); + break; //Flying Wyvern + } + + _mountType = mountType; + + // Send a Server->Client packet InventoryUpdate to the L2PcInstance in order to update speed + UserInfo ui = new UserInfo(this); + sendPacket(ui); + + } + + /** + * Return the type of Pet mounted (0 : none, 1 : Stridder, 2 : Wyvern).

    + */ + public int getMountType() + { + return _mountType; + } + + /** + * Send a Server->Client packet UserInfo to this L2PcInstance and CharInfo to all L2PcInstance in its _KnownPlayers.

    + * + * Concept :

    + * Others L2PcInstance in the detection area of the L2PcInstance are identified in _knownPlayers. + * In order to inform other players of this L2PcInstance state modifications, server just need to go through _knownPlayers to send Server->Client Packet

    + * + * Actions :

    + *
  • Send a Server->Client packet UserInfo to this L2PcInstance (Public and Private Data)
  • + *
  • Send a Server->Client packet CharInfo to all L2PcInstance in _KnownPlayers of the L2PcInstance (Public data only)


  • + * + * Caution : DON'T SEND UserInfo packet to other players instead of CharInfo packet. + * Indeed, UserInfo packet contains PRIVATE DATA as MaxHP, STR, DEX...

    + * + */ + public void updateAbnormalEffect() + { + broadcastUserInfo(); + } + + /** + * Disable the Inventory and create a new task to enable it after 1.5s.

    + */ + public void tempInvetoryDisable() + { + _inventoryDisable = true; + + ThreadPoolManager.getInstance().scheduleGeneral(new InventoryEnable(), 1500); + } + + /** + * Return True if the Inventory is disabled.

    + */ + public boolean isInvetoryDisabled() + { + return _inventoryDisable; + } + + class InventoryEnable implements Runnable + { + public void run() + { + _inventoryDisable = false; + } + } + + public Map getCubics() + { + return _cubics; + } + + /** + * Add a L2CubicInstance to the L2PcInstance _cubics.

    + */ + public void addCubic(int id, int level) + { + L2CubicInstance cubic = new L2CubicInstance(this, id, level); + _cubics.put(id, cubic); + } + + /** + * Remove a L2CubicInstance from the L2PcInstance _cubics.

    + */ + public void delCubic(int id) + { + _cubics.remove(id); + } + + /** + * Return the L2CubicInstance corresponding to the Identifier of the L2PcInstance _cubics.

    + */ + public L2CubicInstance getCubic(int id) + { + return _cubics.get(id); + } + + public String toString() + { + return "player "+getName(); + } + + /** + * Return the modifier corresponding to the Enchant Effect of the Active Weapon (Min : 127).

    + */ + public int getEnchantEffect() + { + L2ItemInstance wpn = getActiveWeaponInstance(); + + if (wpn == null) + return 0; + + return Math.min(127, wpn.getEnchantLevel()); + } + + /** + * Set the _lastFolkNpc of the L2PcInstance corresponding to the last Folk wich one the player talked.

    + */ + public void setLastFolkNPC(L2FolkInstance folkNpc) + { + _lastFolkNpc = folkNpc; + } + + /** + * Return the _lastFolkNpc of the L2PcInstance corresponding to the last Folk wich one the player talked.

    + */ + public L2FolkInstance getLastFolkNPC() + { + return _lastFolkNpc; + } + + /** + * Set the Silent Moving mode Flag.

    + */ + public void setSilentMoving(boolean flag) + { + _isSilentMoving = flag; + } + + /** + * Return True if the Silent Moving mode is active.

    + */ + public boolean isSilentMoving() + { + return _isSilentMoving; + } + + /** + * Return True if L2PcInstance is a participant in the Festival of Darkness.

    + */ + public boolean isFestivalParticipant() + { + return SevenSignsFestival.getInstance().isParticipant(this); + } + + public void addAutoSoulShot(int itemId) + { + _activeSoulShots.add(itemId); + } + + public void removeAutoSoulShot(int itemId) + { + _activeSoulShots.remove(itemId); + } + + public Set getAutoSoulShot() + { + return _activeSoulShots; + } + + public void rechargeAutoSoulShot(boolean physical, boolean magic, boolean summon) + { + L2ItemInstance item; + IItemHandler handler; + + if (_activeSoulShots == null || _activeSoulShots.size() == 0) + return; + + for (int itemId : _activeSoulShots) + { + item = getInventory().getItemByItemId(itemId); + + if (item != null) + { + if (magic) + { + if (!summon) + { + if (itemId == 2509 || itemId == 2510 || itemId == 2511 || + itemId == 2512 || itemId == 2513 || itemId == 2514 || + itemId == 3947 || itemId == 3948 || itemId == 3949 || + itemId == 3950 || itemId == 3951 || itemId == 3952 || + itemId == 5790) + { + handler = ItemHandler.getInstance().getItemHandler(itemId); + + if (handler != null) + handler.useItem(this, item); + } + } else + { + if (itemId == 6646 || itemId == 6647) + { + handler = ItemHandler.getInstance().getItemHandler(itemId); + + if (handler != null) + handler.useItem(this, item); + } + } + } + + if (physical) + { + if (!summon) + { + if (itemId == 1463 || itemId == 1464 || itemId == 1465 || + itemId == 1466 || itemId == 1467 || itemId == 1835 || + itemId == 5789) + { + handler = ItemHandler.getInstance().getItemHandler(itemId); + + if (handler != null) + handler.useItem(this, item); + } + } else + { + if (itemId == 6645) + { + handler = ItemHandler.getInstance().getItemHandler(itemId); + + if (handler != null) + handler.useItem(this, item); + } + } + } + } + else + { + removeAutoSoulShot(itemId); + } + } + } + + + + private ScheduledFuture _taskWarnUserTakeBreak; + + class WarnUserTakeBreak implements Runnable + { + public void run() + { + if (L2PcInstance.this.isOnline() == 1) + { + SystemMessage msg = new SystemMessage(764); + L2PcInstance.this.sendPacket(msg); + } + else + stopWarnUserTakeBreak(); + } + } + + class RentPetTask implements Runnable + { + public void run() + { + stopRentPet(); + } + } + + private ScheduledFuture _taskforfish; + + class WaterTask implements Runnable + { + public void run() + { + double reduceHp = getMaxHp()/100; + + if (reduceHp < 1) + reduceHp = 1; + + reduceCurrentHp(reduceHp,L2PcInstance.this,false); + //reduced hp, becouse not rest + SystemMessage sm = new SystemMessage(297); + sm.addNumber((int)reduceHp); + sendPacket(sm); + + } + } + + class LokingForFishTask implements Runnable + { + public void run() + { + int rate = 90; //Only for now + int check = Rnd.get(100); + StopLookingForFishTask(); + if(rate > check) + { + StartFishCombat(); + } + else EndFishing(false); + } + } + + public void setInvisible() + { + _invisible = 1; + } + + public void setVisible() + { + _invisible = 0; + } + + public int getInvisible() + { + return _invisible; + } + + public void togglePathNodeMode() + { + _isPathNodeMode = !_isPathNodeMode; + } + + public void toggleViewPathNodes() + { + _isPathNodesVisible = !_isPathNodesVisible; + } + + public boolean isPathNodeModeActive() + { + return _isPathNodeMode; + } + + public boolean isPathNodeVisible() + { + return _isPathNodesVisible; + } + + public Map> getPathNodeMap() + { + if (_pathNodeMap == null) + _pathNodeMap = new FastMap>(); + + return _pathNodeMap; + } + + public void addPathNodePoint() + { + //add Node to Players PathNode List + //TODO: Addcheck for nearby point in radius + setSelectedNode(WayPointNode.spawn(this)); + getPathNodeMap().put(getSelectedNode(), new FastList()); + } + + /** + * Delete all Path Nodes.

    + */ + public void clearPathNodes() + { + if (getPathNodeMap() != null) + { + for (WayPointNode node : getPathNodeMap().keySet()) + removePathNodePoint(node); + + getPathNodeMap().clear(); + } + + setSelectedNode(null); + } + + public void setSelectedNode(WayPointNode decoInstance) + { + if (getSelectedNode() != null) + { + List linkedNodes = getPathNodeMap().get(getSelectedNode()); + + if (linkedNodes != null) + for (WayPointNode node : linkedNodes) + node.setNormal(); + + getSelectedNode().setNormal(); + } + + _selectedNode = decoInstance; + + if (_selectedNode != null) + { + _selectedNode.setSelected(); + + List linkedNodes = getPathNodeMap().get(_selectedNode); + + if (linkedNodes != null) + for (WayPointNode linked : linkedNodes) + linked.setLinked(); + } + } + + public WayPointNode getSelectedNode() + { + return _selectedNode; + } + + public void addLink(WayPointNode target) + { + if (getSelectedNode() != null) + { + List list = getPathNodeMap().get(getSelectedNode()); + + if (list == null) + list = new FastList(); + + list.add(target); + _pathNodeMap.put(getSelectedNode(), list); + + List list2 = getPathNodeMap().get(target); + + if (list2 == null) + list2 = new FastList(); + + list2.add(getSelectedNode()); + _pathNodeMap.put(target, list2); + + target.setLinked(); + WayPointNode.drawLine(target, getSelectedNode()); + } + } + + public void removeLink(WayPointNode target) + { + if (getSelectedNode() != null) + { + List list = getPathNodeMap().get(getSelectedNode()); + + if (list != null && list.contains(target)) + { + list.remove(target); + _pathNodeMap.put(getSelectedNode(), list); + + List list2 = getPathNodeMap().get(target); + + if (list2 != null && list2.contains(getSelectedNode())) + { + list2.remove(getSelectedNode()); + _pathNodeMap.put(target, list2); + } + + target.setNormal(); + WayPointNode.eraseLine(target, getSelectedNode()); + } + else + { + sendPacket(SystemMessage.sendString("Target not a Linked Node.")); + } + } + } + + public void removePathNodePoint() + { + removePathNodePoint(getSelectedNode()); + } + + public void removePathNodePoint(WayPointNode node) + { + if (node != null) + { + List list = getPathNodeMap().get(node); + + if (list != null) + { + synchronized (list) + { + try + { + for (WayPointNode link : list) + { + //WayPointNode.eraseLine(node, link); + removeLink(link); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + + node.decayMe(); + node = null; + } + } + + /** + * @param string + */ + public void savePathNodes(String fileName) + { + try + { + //File file = new File(Config.DATAPACK_ROOT, "pathnode/" + fileName + ".bin"); + FileOutputStream fos = new FileOutputStream("pathnode/" + fileName + ".bin"); // Save to file + GZIPOutputStream gzos = new GZIPOutputStream(fos); // Compressed + ObjectOutputStream out = new ObjectOutputStream(gzos); // Save objects + out.writeObject(getSaveList()); // Write the entire pathNodeMap of Positions + out.flush(); // Always flush the output. + out.close(); // And close the stream. + sendPacket(SystemMessage.sendString("Path Node table saved to: L2J/pathnode/"+fileName+".bin")); + } + catch (Exception e) + { + e.printStackTrace(); + sendPacket(SystemMessage.sendString("Could not Save Path Node Table.")); + } + } + + public Map> getSaveList() + { + Map> saveList = null; + + if (getPathNodeMap() != null) + { + saveList = Collections.synchronizedMap(new WeakHashMap>()); + + for (WayPointNode node : getPathNodeMap().keySet()) + { + Point3D nodePoint = Point3D.getPosition(node); + + List links = getPathNodeMap().get(node); + List linkPoints = null; + + if (links != null) + { + linkPoints = new FastList(); + + for (WayPointNode link : links) + linkPoints.add(Point3D.getPosition(link)); + } + + saveList.put(nodePoint, linkPoints); + } + } + + return saveList; + } + + /** + * @param string + */ + @SuppressWarnings(value = { "unchecked" }) + public void loadPathNodes(String fileName) + { + Map> newNodeMap = null; + + try + { + //Create necessary input streams + //File file = new File(Config.DATAPACK_ROOT, "pathnode/" + fileName + ".bin"); + FileInputStream fis = new FileInputStream("pathnode/" + fileName + ".bin"); // Read from file + GZIPInputStream gzis = new GZIPInputStream(fis); // Uncompress + ObjectInputStream in = new ObjectInputStream(gzis); // Read objects + // Read in an object. It should be a vector of scribbles + + newNodeMap = (FastMap>)in.readObject(); + in.close(); // Close the stream. + } + catch (Exception e) + { + sendPacket(SystemMessage.sendString("Could not Load Path Node Table from: L2J/pathnode/"+fileName+".bin")); + e.printStackTrace(); + return; + } + + clearPathNodes(); + loadNodeList(newNodeMap); + sendPacket(SystemMessage.sendString("Path Node table loaded from: L2J/pathnode/"+fileName+".bin")); + } + + /** + * @param newNodeMap + */ + private void loadNodeList(Map> newNodeMap) + { + _pathNodeMap = Collections.synchronizedMap(new WeakHashMap>()); + Map map = new FastMap(); + WayPointNode newNode = null; + + for (Point3D point : newNodeMap.keySet()) + { + newNode = WayPointNode.spawn(point); + newNode.setNormal(); + map.put(point, newNode); + } + + for (Point3D point : newNodeMap.keySet()) + { + WayPointNode node = map.get(point); + List links = newNodeMap.get(point); + List nodeLinks = null; + + if (links != null) + { + nodeLinks = new FastList(); + + for (Point3D link : links) + { + WayPointNode linkNode = map.get(link); + nodeLinks.add(linkNode); + + if (getPathNodeMap().get(linkNode) != null && + !getPathNodeMap().get(linkNode).contains(node)) + WayPointNode.drawLine(linkNode, node); + } + } + + _pathNodeMap.put(node, nodeLinks); + } + } + + public int getClanPrivileges() + { + return _clanPrivileges; + } + + public void setClanPrivileges(int n) + { + _clanPrivileges = n; + } + + public void refreshLinks() + { + if (_linkToggle) + { + for (WayPointNode node : getPathNodeMap().keySet()) + { + for (WayPointNode lineNode : node.getLineNodes()) + { + lineNode.decayMe(); + lineNode.refreshID(); + //lineNode.spawnMe(); + } + } + } + else + { + for (WayPointNode node : getPathNodeMap().keySet()) + { + for (WayPointNode lineNode : node.getLineNodes()) + { + //lineNode.decayMe(); + //lineNode.refreshID(); + lineNode.spawnMe(); + } + } + } + + _linkToggle = !_linkToggle; + } + + public void sendMessage(String message) + { + sendPacket(SystemMessage.sendString(message)); + } + + public void enterObserverMode(int x, int y, int z) + { + _obsX = getX(); + _obsY = getY(); + _obsZ = getZ(); + + setTarget(null); + stopMove(null); + setIsParalyzed(true); + setIsInvul(true); + setInvisible(); + sendPacket(new ObservationMode(x, y, z)); + setXYZ(x, y, z); + + _observerMode = true; + broadcastPacket(new CharInfo(this)); + } + + public void enterOlympiadObserverMode(int x, int y, int z, int id) + { + if (getPet() != null) + getPet().unSummon(this); + _olympiadGameId = id; + _obsX = getX(); + if (isSitting()) + standUp(); + _obsY = getY(); + _obsZ = getZ(); + setTarget(null); + setIsInvul(true); + setInvisible(); + teleToLocation(x, y, z); + sendPacket(new ExOlympiadMode(3)); + _observerMode = true; + } + + public void leaveObserverMode() + { + setTarget(null); + setXYZ(_obsX, _obsY, _obsZ); + setIsParalyzed(false); + setVisible(); + setIsInvul(false); + + if (getAI() != null) + getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); + + _observerMode = false; + sendPacket(new ObservationReturn(this)); + broadcastPacket(new CharInfo(this)); + } + + public void leaveOlympiadObserverMode() + { + setTarget(null); + sendPacket(new ExOlympiadMode(0)); + teleToLocation(_obsX, _obsY, _obsZ); + setVisible(); + setIsInvul(false); + if (getAI() != null) + { + getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); + } + Olympiad.getInstance().removeSpectator(_olympiadGameId, this); + _olympiadGameId = -1; + _observerMode = false; + broadcastPacket(new CharInfo(this)); + } + + public void setOlympiadSide(int i) + { + _olympiadSide = i; + } + + public int getOlympiadSide() + { + return _olympiadSide; + } + + public void setOlympiadGameId(int id) + { + _olympiadGameId = id; + } + + public int getOlympiadGameId() + { + return _olympiadGameId; + } + + public int getObsX() + { + return _obsX; + } + + public int getObsY() + { + return _obsY; + } + + public int getObsZ() + { + return _obsZ; + } + + public boolean inObserverMode() + { + return _observerMode; + } + + public int getTeleMode() + { + return _telemode; + } + + public void setTeleMode(int mode) + { + _telemode = mode; + } + + public void setLoto(int i, int val) + { + _loto[i] = val; + } + + public int getLoto(int i) + { + return _loto[i]; + } + + public void setRace(int i, int val) + { + _race[i] = val; + } + + public int getRace(int i) + { + return _race[i]; + } + + public void setChatBanned(boolean isBanned) + { + _chatBanned = isBanned; + + if (isChatBanned()) + sendMessage("You have been chat banned by a server admin."); + else + { + sendMessage("Your chat ban has been lifted."); + if (_chatUnbanTask != null) + _chatUnbanTask.cancel(false); + _chatUnbanTask = null; + } + } + + public boolean isChatBanned() + { + return _chatBanned; + } + + public void setChatUnbanTask(ScheduledFuture task) + { + _chatUnbanTask = task; + } + public ScheduledFuture getChatUnbanTask() + { + return _chatUnbanTask; + } + + public boolean getMessageRefusal() + { + return _messageRefusal; + } + + public void setMessageRefusal(boolean mode) + { + _messageRefusal = mode; + updateEffectIcons(); + } + + public void setDietMode(boolean mode) + { + _dietMode = mode; + } + + public boolean getDietMode() + { + return _dietMode; + } + + public void setTradeRefusal(boolean mode) + { + _tradeRefusal = mode; + } + + public boolean getTradeRefusal() + { + return _tradeRefusal; + } + + public void setExchangeRefusal(boolean mode) + { + _exchangeRefusal = mode; + } + + public boolean getExchangeRefusal() + { + return _exchangeRefusal; + } + + public BlockList getBlockList() + { + return _blockList; + } + + public void setConnected(boolean connected) + { + _isConnected = connected; + } + + public void setHero(boolean hero) + { + _hero = hero; + } + + public void setIsInOlympiadMode(boolean b) + { + _inOlympiadMode = b; + } + + public boolean isHero() + { + return _hero; + } + + public boolean isInOlympiadMode() + { + return _inOlympiadMode; + } + + public boolean isNoble() + { + _noble = false; + + if (isSubClassActive()) + { + if (getTotalSubClasses() > 1) + { + _noble = true; + return _noble; + } + if (getLevel() >= 75) + { + _noble = true; + return _noble; + } + } + else + { + if (getSubClasses() == null) + return _noble; + + if (getLevel() >= 76 && getClassId().getId() >= 88) + { + for (SubClass sub : getSubClasses().values()) + { + if (sub.getLevel() >= 75) + { + _noble = true; + return _noble; + } + } + } + } + + return _noble; + } + + public void setTeam(int team) + { + _team = team; + } + + public int getTeam() + { + return _team; + } + + public int getNameColor() + { + return _nameColor; + } + + public void setNameColor(int nameColor) + { + _nameColor = nameColor; + } + + public void setNameColor(int red, int green, int blue) + { + _nameColor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16); + } + + public void setWantsPeace(int wantsPeace) + { + _wantsPeace = wantsPeace; + } + + public int getWantsPeace() + { + return _wantsPeace; + } + + public boolean isFishing() + { + return _fishing; + } + + public void setFishing(boolean fishing) + { + _fishing = fishing; + } + + /** + * 1. Add the specified class ID as a subclass (up to the maximum number of three) + * for this character.
    + * 2. This method no longer changes the active _classIndex of the player. This is only + * done by the calling of setActiveClass() method as that should be the only way to do so. + * + * @param int classId + * @param int classIndex + * @return boolean subclassAdded + */ + public boolean addSubClass(int classId, int classIndex) + { + if (getTotalSubClasses() == 3 || classIndex == 0) + return false; + + if (getSubClasses().containsKey(classIndex)) + return false; + + // Note: Never change _classIndex in any method other than setActiveClass(). + + SubClass newClass = new SubClass(); + newClass.setClassId(classId); + newClass.setClassIndex(classIndex); + + java.sql.Connection con = null; + + try + { + // Store the basic info about this new sub-class. + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement = con.prepareStatement(ADD_CHAR_SUBCLASS); + statement.setInt(1, getObjectId()); + statement.setInt(2, newClass.getClassId()); + statement.setInt(3, newClass.getExp()); + statement.setInt(4, newClass.getSp()); + statement.setInt(5, newClass.getLevel()); + statement.setInt(6, newClass.getClassIndex()); // <-- Added + statement.execute(); + statement.close(); + } + catch (Exception e) { + _log.warning("WARNING: Could not add character sub class for " + getName() + ": " + e); + return false; + } + finally { + try { con.close(); } catch (Exception e) {} + } + + // Commit after database INSERT incase exception is thrown. + getSubClasses().put(newClass.getClassIndex(), newClass); + + if (Config.DEBUG) + _log.info(getName() + " added class ID " + classId + " as a sub class at index " + classIndex + "."); + + ClassId subTemplate = ClassId.values()[classId]; + List skillTree = SkillTreeTable.getInstance().getAllowedSkills(subTemplate); + + if (skillTree == null) + return true; + + Map prevSkillList = new FastMap(); + + for (L2SkillLearn skillInfo : skillTree) + { + if (skillInfo.getMinLevel() <= 40) + { + L2Skill prevSkill = prevSkillList.get(skillInfo.getId()); + L2Skill newSkill = SkillTable.getInstance().getInfo(skillInfo.getId(), skillInfo.getLevel()); + + if (prevSkill != null && (prevSkill.getLevel() > newSkill.getLevel())) + continue; + + prevSkillList.put(newSkill.getId(), newSkill); + storeSkill(newSkill, prevSkill, classIndex); + } + } + + if (Config.DEBUG) + _log.info(getName() + " was given " + getAllSkills().length + " skills for their new sub class."); + + return true; + } + + /** + * 1. Completely erase all existance of the subClass linked to the classIndex.
    + * 2. Send over the newClassId to addSubClass()to create a new instance on this classIndex.
    + * 3. Upon Exception, revert the player to their BaseClass to avoid further problems.
    + * + * @param int classIndex + * @param int newClassId + * @return boolean subclassAdded + */ + public boolean modifySubClass(int classIndex, int newClassId) + { + int oldClassId = getSubClasses().get(classIndex).getClassId(); + + if (Config.DEBUG) + _log.info(getName() + " has requested to modify sub class index " + classIndex + " from class ID " + oldClassId + " to " + newClassId + "."); + + java.sql.Connection con = null; + + try + { + con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement statement; + + // Remove all henna info stored for this sub-class. + statement = con.prepareStatement(DELETE_CHAR_HENNAS); + statement.setInt(1, getObjectId()); + statement.setInt(2, classIndex); + statement.execute(); + statement.close(); + + // Remove all shortcuts info stored for this sub-class. + statement = con.prepareStatement(DELETE_CHAR_SHORTCUTS); + statement.setInt(1, getObjectId()); + statement.setInt(2, classIndex); + statement.execute(); + statement.close(); + + // Remove all effects info stored for this sub-class. + statement = con.prepareStatement(DELETE_SKILL_SAVE); + statement.setInt(1, getObjectId()); + statement.setInt(2, classIndex); + statement.execute(); + statement.close(); + + // Remove all skill info stored for this sub-class. + statement = con.prepareStatement(DELETE_CHAR_SKILLS); + statement.setInt(1, getObjectId()); + statement.setInt(2, classIndex); + statement.execute(); + statement.close(); + + // Remove all basic info stored about this sub-class. + statement = con.prepareStatement(DELETE_CHAR_SUBCLASS); + statement.setInt(1, getObjectId()); + statement.setInt(2, classIndex); + statement.execute(); + statement.close(); + } + catch (Exception e) + { + _log.warning("Could not modify sub class for " + getName() + " to class index " + classIndex + ": " + e); + + // This must be done in order to maintain data consistency. + getSubClasses().remove(classIndex); + return false; + } + finally { + try { con.close(); } catch (Exception e) {} + } + + getSubClasses().remove(classIndex); + return addSubClass(newClassId, classIndex); + } + + public boolean isSubClassActive() + { + return _classIndex > 0; + } + + public Map getSubClasses() + { + if (_subClasses == null) + _subClasses = new FastMap(); + + return _subClasses; + } + + public int getTotalSubClasses() + { + return getSubClasses().size(); + } + + public int getBaseClass() + { + return _baseClass; + } + + public int getActiveClass() + { + return _activeClass; + } + + public int getClassIndex() + { + return _classIndex; + } + + /** + * Changes the character's class based on the given class index. + *

    + * An index of zero specifies the character's original (base) class, + * while indexes 1-3 specifies the character's sub-classes respectively. + * + * @param classIndex + */ + public boolean setActiveClass(int classIndex) + { + /* + * 1. Call store() before modifying _classIndex to avoid skill effects rollover. + * 2. Register the correct _classId against applied 'classIndex'. + */ + store(); + + if (classIndex == 0) + { + setClassId(getBaseClass()); + } + else + { + try { + setClassId(getSubClasses().get(classIndex).getClassId()); + } + catch (Exception e) { + _log.info("Could not switch " + getName() + "'s sub class to class index " + classIndex + ": " + e); + return false; + } + } + + _classIndex = classIndex; + + /* + * Update the character's change in class status. + * + * 1. Remove any active cubics from the player. + * 2. Renovate the characters table in the database with the new class info, storing also buff/effect data. + * 3. Remove all existing skills. + * 4. Restore all the learned skills for the current class from the database. + * 5. Restore effect/buff data for the new class. + * 6. Restore henna data for the class, applying the new stat modifiers while removing existing ones. + * 7. Reset HP/MP/CP stats and send Server->Client character status packet to reflect changes. + * 8. Restore shortcut data related to this class. + * 9. Resend a class change animation effect to broadcast to all nearby players. + */ + + if (getCubics().size() > 0) + { + for (L2CubicInstance cubic : getCubics().values()) + { + cubic.stopAction(); + cubic.cancelDisappear(); + } + + getCubics().clear(); + } + + for (L2Skill oldSkill : getAllSkills()) + super.removeSkill(oldSkill); + + for (L2Effect effect : getAllEffects()) + effect.exit(); + + if (isSubClassActive()) + { + _dwarvenRecipeBook.clear(); + _commonRecipeBook.clear(); + } + else + { + restoreRecipeBook(); + } + + restoreSkills(); + rewardSkills(); + restoreEffects(); + + for (int i = 0; i < 3; i++) + _henna[i] = null; + + restoreHenna(); + sendPacket(new HennaInfo(this)); + + setCurrentHpMp(getMaxHp(), getMaxMp()); + setCurrentCp(getMaxCp()); + updateStats(); + + //_macroses.restore(); + //_macroses.sendUpdate(); + _shortCuts.restore(); + sendPacket(new ShortCutInit(this)); + + broadcastPacket(new SocialAction(getObjectId(), 15)); + + //decayMe(); + //spawnMe(getX(), getY(), getZ()); + + return true; + } + + public void stopWarnUserTakeBreak() + { + if (_taskWarnUserTakeBreak != null) + { + _taskWarnUserTakeBreak.cancel(false); + _taskWarnUserTakeBreak = null; + } + } + + public void startWarnUserTakeBreak() + { + if (_taskWarnUserTakeBreak == null) + _taskWarnUserTakeBreak = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new WarnUserTakeBreak(), 7200000, 7200000); + } + + public void stopRentPet() + { + if (_taskRentPet != null) + { + // if the rent of a wyvern expires while over a flying zone, tp to down before unmounting + if (checkLandingState() && getMountType()==2) + teleToLocation(MapRegionTable.getInstance().getTeleToLocation(this, MapRegionTable.TeleportWhereType.Town)); + _taskRentPet.cancel(false); + Ride dismount = new Ride(getObjectId(), Ride.ACTION_DISMOUNT, 0); + sendPacket(dismount); + broadcastPacket(dismount); + _taskRentPet = null; + setMountType(0); + } + } + + public void startRentPet(int seconds) + { + if (_taskRentPet == null) + _taskRentPet = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new RentPetTask(), seconds * 1000, seconds * 1000); + } + + public boolean isRentedPet() + { + if (_taskRentPet != null) + return true; + + return false; + } + + public void stopWaterTask() + { + if (_taskWater != null) + { + _taskWater.cancel(false); + + _taskWater = null; + sendPacket(new SetupGauge(2, 0)); + } + } + + public void startWaterTask() + { + if (!isDead() && _taskWater == null) + { + int timeinwater = 86; + + sendPacket(new SetupGauge(2, timeinwater * 1000)); + _taskWater = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new WaterTask(), timeinwater * 1000, 1000); + } + } + + public boolean isInWater() + { + if (_taskWater != null) + return true; + + return false; + } + + public void checkWaterState() + { + //checking if char is over base level of water (sea, rivers) + if (getZ() > -3793) + { + stopWaterTask(); + return; + } + + // Check if char is in water or is underground and in water + int[] coord; + Zone zone = ZoneManager.getInstance().getZone(ZoneType.getZoneTypeName(ZoneType.ZoneTypeEnum.Water), getX(), getY()); //checking if char is in water zone + + if (zone == null) + zone = ZoneManager.getInstance().getZoneType(ZoneType.getZoneTypeName(ZoneType.ZoneTypeEnum.Underground)).getZone(getX(), getY()); //checking if char is in underground and in water + + if (zone != null) + { + coord = zone.getCoord(getX(), getY()); + + if (coord != null && getZ() > coord[4]) + { + stopWaterTask(); + return; + } + } + + startWaterTask(); + } + + public void onPlayerEnter() + { + startWarnUserTakeBreak(); + + if (SevenSigns.getInstance().isSealValidationPeriod() || SevenSigns.getInstance().isCompResultsPeriod()) + { + if (!isGM() && isIn7sDungeon() && SevenSigns.getInstance().getPlayerCabal(this) != SevenSigns.getInstance().getCabalHighestScore()) + { + teleToLocation(MapRegionTable.TeleportWhereType.Town); + setIsIn7sDungeon(false); + sendMessage("You have been teleported to the nearest town due to the beginning of the Seal Validation period."); + } + } + else + { + if (!isGM() && isIn7sDungeon() && SevenSigns.getInstance().getPlayerCabal(this) == SevenSigns.CABAL_NULL) + { + teleToLocation(MapRegionTable.TeleportWhereType.Town); + setIsIn7sDungeon(false); + sendMessage("You have been teleported to the nearest town because you have not signed for any cabal."); + } + } + + // jail task + updateJailState(); + + if (getInvisible() == 1) + sendMessage("Entering world in Invisible mode."); + if (getMessageRefusal()) + sendMessage("Entering world in Message Refusal mode."); + + // Reset Pvp Zone flag withour sending a message to the client + setInPvpZone(false, false); + revalidateInPvpZone(); + } + + public long getLastAccess() + { + return _lastAccess; + } + + private void checkRecom(int recsHave, int recsLeft) + { + Calendar check = Calendar.getInstance(); + check.setTimeInMillis(_lastAccess); + check.add(Calendar.DAY_OF_MONTH,1); + + Calendar min = Calendar.getInstance(); + min.set(Calendar.HOUR_OF_DAY, 13); + min.set(Calendar.MINUTE, 0); + + Calendar max = Calendar.getInstance(); + max.add(Calendar.DAY_OF_MONTH,1); + max.set(Calendar.HOUR_OF_DAY, 13); + max.set(Calendar.MINUTE, 0); + + if (getStat().getLevel() < 10 || !(check.after(min) && check.before(max)) ) + { + _recomHave = recsHave; + _recomLeft = recsLeft; + return; + } + + restartRecom(); + } + + public void restartRecom() + { + _recomChars.clear(); + + if (getStat().getLevel() < 20) + { + _recomLeft = 3; + _recomHave--; + } + else if (getStat().getLevel() < 40) + { + _recomLeft = 3; + _recomHave -= 2; + } + else + { + _recomLeft = 6; + _recomHave -= 3; + } + + if (_recomHave < 0) + _recomHave = 0; + } + + public int getBoatId() + { + return _boatId; + } + + public void setBoatId(int boatId) + { + _boatId = boatId; + } + + public void doRevive() + { + super.doRevive(); + updateEffectIcons(); + } + + public void doRevive(L2Skill skill) + { + // Restore the player's lost experience, + // depending on the % return of the skill used (based on its power). + restoreExp(skill.getPower()); + doRevive(); + } + + public void onActionRequest() + { + setProtection(false); + } + + /** + * @param expertiseIndex The expertiseIndex to set. + */ + public void setExpertiseIndex(int expertiseIndex) + { + _expertiseIndex = expertiseIndex; + } + + /** + * @return Returns the expertiseIndex. + */ + public int getExpertiseIndex() + { + return _expertiseIndex; + } + + public final void onTeleported() + { + super.onTeleported(); + + if (Config.PLAYER_SPAWN_PROTECTION > 0) + setProtection(true); + + if (Config.ALLOW_WATER) + checkWaterState(); + } + + public final boolean updatePosition(int gameTicks) + { + // Disables custom movement for L2PCInstance when Old Synchronization is selected + if (Config.COORD_SYNCHRONIZE == -1) + return super.updatePosition(gameTicks); + + // Get movement data + MoveData m = _move; + + if (_move == null) + return true; + + if (!isVisible()) + { + _move = null; + return true; + } + + // Check if the position has alreday be calculated + if (m._moveTimestamp == 0) + m._moveTimestamp = m._moveStartTime; + + // Check if the position has alreday be calculated + if (m._moveTimestamp == gameTicks) + return false; + + int dx = m._xDestination - getX(); + int dy = m._yDestination - getY(); + int dz = m._zDestination - getZ(); + int distPassed = (int)getStat().getMoveSpeed() * (gameTicks - m._moveTimestamp) / GameTimeController.TICKS_PER_SECOND; + double distFraction = (distPassed) / Math.sqrt(dx*dx + dy*dy + dz*dz); +// if (Config.DEVELOPER) System.out.println("Move Ticks:" + (gameTicks - m._moveTimestamp) + ", distPassed:" + distPassed + ", distFraction:" + distFraction); + + if (distFraction > 1) + { + // Set the position of the L2Character to the destination + super.setXYZ(m._xDestination, m._yDestination, m._zDestination); + + // Cancel the move action + _move = null; + } + else + { + // Set the position of the L2Character to estimated after parcial move + super.setXYZ(getX() + (int)(dx * distFraction + 0.5), getY() + (int)(dy * distFraction + 0.5), getZ() + (int)(dz * distFraction)); + } + + // Set the timer of last position update to now + m._moveTimestamp = gameTicks; + return (_move == null); + } + + public void setLastClientPosition(int x, int y, int z) + { + _lastClientPosition.setX(x); + _lastClientPosition.setY(y); + _lastClientPosition.setZ(z); + } + + public boolean checkLastClientPosition(int x, int y, int z) + { + return _lastClientPosition.getX() == x && _lastClientPosition.getY() == y && _lastClientPosition.getZ() == z; + } + + public int getLastClientDistance(int x, int y, int z) + { + int dx = (x - _lastClientPosition.getX()); + int dy = (y - _lastClientPosition.getY()); + int dz = (z - _lastClientPosition.getZ()); + + return (int)Math.sqrt(dx*dx + dy*dy + dz*dz); + } + + public void setLastServerPosition(int x, int y, int z) + { + _lastServerPosition.setX(x); + _lastServerPosition.setY(y); + _lastServerPosition.setZ(z); + } + + public boolean checkLastServerPosition(int x, int y, int z) + { + return _lastServerPosition.getX() == x && _lastServerPosition.getY() == y && _lastServerPosition.getZ() == z; + } + + public int getLastServerDistance(int x, int y, int z) + { + int dx = (x - _lastServerPosition.getX()); + int dy = (y - _lastServerPosition.getY()); + int dz = (z - _lastServerPosition.getZ()); + + return (int)Math.sqrt(dx*dx + dy*dy + dz*dz); + } + + public void addExpAndSp(int addToExp, int addToSp) { getStat().addExpAndSp(addToExp, addToSp); } + public void reduceCurrentHp(double i, L2Character attacker) { getStatus().reduceHp(i, attacker); } + public void reduceCurrentHp(double value, L2Character attacker, boolean awake) { getStatus().reduceHp(value, attacker, awake); } + + public void broadcastSnoop(int type, String name, String _text) + { + if(_SnoopListener.size() > 0) + { + Snoop sn = new Snoop(getObjectId(),getName(),type,name,_text); + + for (L2PcInstance pci : _SnoopListener) + if (pci != null) + pci.sendPacket(sn); + } + } + + public void addSnooper(L2PcInstance pci ) + { + if(!_SnoopListener.contains(pci)) + _SnoopListener.add(pci); + } + + public void removeSnooper(L2PcInstance pci ) + { + _SnoopListener.remove(pci); + } + + public void addSnooped(L2PcInstance pci ) + { + if(!_SnoopedPlayer.contains(pci)) + _SnoopedPlayer.add(pci); + } + + public void removeSnooped(L2PcInstance pci ) + { + _SnoopedPlayer.remove(pci); + } + + public void addBypass(String bypass) + { + _validBypass.add(bypass); + //_log.warning("[BypassAdd]"+getName()+" '"+bypass+"'"); + } + + public void addBypass2(String bypass) + { + _validBypass2.add(bypass); + //_log.warning("[BypassAdd]"+getName()+" '"+bypass+"'"); + } + + public boolean validateBypass(String cmd) + { + if (!Config.BYPASS_VALIDATION) + return true; + + for (String bp : _validBypass) + { + if (bp == null) + return false; + + //_log.warning("[BypassValidation]"+getName()+" '"+bp+"'"); + if (bp.equals(cmd)) + return true; + } + + for (String bp : _validBypass2) + { + if (bp == null) + return false; + + //_log.warning("[BypassValidation]"+getName()+" '"+bp+"'"); + if (cmd.startsWith(bp)) + return true; + } + + _log.warning("[L2PcInstance] player ["+getName()+"] sent invalid bypass '"+cmd+"', ban this player!"); + return false; + } + + public boolean validateItemManipulation(int objectId, String action) + { + L2ItemInstance item = getInventory().getItemByObjectId(objectId); + + if (item == null || item.getOwnerId() != getObjectId()) + { + _log.finest(getObjectId()+": player tried to " + action + " item he is not owner of"); + return false; + } + + // Pet is summoned and not the item that summoned the pet AND not the buggle from strider you're mounting + if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId) + { + if (Config.DEBUG) + _log.finest(getObjectId()+": player tried to " + action + " item controling pet"); + + return false; + } + + if(getActiveEnchantItem() != null && getActiveEnchantItem().getObjectId() == objectId) + { + if (Config.DEBUG) + _log.finest(getObjectId()+":player tried to " + action + " an enchant scroll he was using"); + + return false; + } + + if (item.isWear()) + { + Util.handleIllegalPlayerAction(this, "Warning!! Character "+getName()+" tried to "+action+" weared item: "+item.getObjectId(),Config.DEFAULT_PUNISH); + return false; + } + + return true; + } + + public void clearBypass() + { + synchronized (this) + { + _validBypass.clear(); + _validBypass2.clear(); + } + } + + /** + * @return Returns the inBoat. + */ + public boolean isInBoat() + { + return _inBoat; + } + + /** + * @param inBoat The inBoat to set. + */ + public void setInBoat(boolean inBoat) + { + _inBoat = inBoat; + } + + /** + * @return + */ + public L2BoatInstance getBoat() + { + return _boat; + } + + /** + * @param boat + */ + public void setBoat(L2BoatInstance boat) + { + _boat = boat; + } + + public void setInCrystallize(boolean inCrystallize) + { + _inCrystallize = inCrystallize; + } + + public boolean isInCrystallize() + { + return _inCrystallize; + } + + /** + * @return + */ + public Point3D getInBoatPosition() + { + return _inBoatPosition; + } + + public void setInBoatPosition(Point3D pt) + { + _inBoatPosition = pt; + } + + /** + * Manage the delete task of a L2PcInstance (Leave Party, Unsummon pet, Save its inventory in the database, Remove it from the world...).

    + * + * Actions :

    + *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • + *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • + *
  • Stop the HP/MP/CP Regeneration task
  • + *
  • Cancel Crafting, Attak or Cast
  • + *
  • Remove the L2PcInstance from the world
  • + *
  • Stop Party and Unsummon Pet
  • + *
  • Update database with items in its inventory and remove them from the world
  • + *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • + *
  • Close the connection with the client


  • + * + */ + public void deleteMe() + { + // Check if the L2PcInstance is in observer mode to set its position to its position before entering in observer mode + if (inObserverMode()) + setXYZ(_obsX, _obsY, _obsZ); + + // Set the online Flag to True or False and update the characters table of the database with online status and lastAccess (called when login and logout) + try { setOnlineStatus(false); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Stop the HP/MP/CP Regeneration task (scheduled tasks) + try { stopAllTimers(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Stop crafting, if in progress + try { RecipeController.getInstance().requestMakeItemAbort(this); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Cancel Attak or Cast + try { setTarget(null); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Remove the L2PcInstance from the world + if (isVisible()) + try { decayMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // If a Party is in progress, leave it + if (isInParty()) try { leaveParty(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // If the L2PcInstance has Pet, unsummon it + if (getPet() != null) + { + try { getPet().unSummon(this); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); }// returns pet to control item + } + + if (getClanId() != 0 && getClan() != null) + { + // set the status for pledge member list to OFFLINE + try + { + L2ClanMember clanMember = getClan().getClanMember(getName()); + if (clanMember != null) clanMember.setPlayerInstance(null); + } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + } + + if (getActiveRequester() != null) + { + // deals with sudden exit in the middle of transaction + setActiveRequester(null); + } + + // If the L2PcInstance is a GM, remove it from the GM List + if (isGM()) + { + try { GmListTable.getInstance().deleteGm(this); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + } + + // Update database with items in its inventory and remove them from the world + try { getInventory().deleteMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Update database with items in its warehouse and remove them from the world + try { getWarehouse().deleteMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Update database with items in its freight and remove them from the world + try { getFreight().deleteMe(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI + try { getKnownList().removeAllKnownObjects(); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + // Close the connection with the client + try { setNetConnection(null); } catch (Throwable t) {_log.log(Level.SEVERE, "deletedMe()", t); } + + clearPathNodes(); + + if (getClanId() > 0) + ClanTable.getInstance().getClan(getClanId()).broadcastToOnlineMembers(new PledgeShowMemberListAdd(this)); + + for(L2PcInstance player : _SnoopedPlayer) + player.removeSnooper(this); + + for(L2PcInstance player : _SnoopListener) + player.removeSnooped(this); + + // Remove L2Object object from _allObjects of L2World + L2World.getInstance().removeObject(this); + } + + public void StartFishing() + { + stopMove(null); + int rnd = Rnd.get(50) + 150; + double angle = Util.convertHeadingToDegree(getHeading()); + //this.sendMessage("Angel: "+angle+" Heading: "+getHeading()); + double radian = Math.toRadians(angle - 90); + double sin = Math.sin(radian); + double cos = Math.cos(radian); + int x1 = -(int)(sin * rnd); //Somthing wrong with L2j Heding calculation o_0? + int y1 = (int)(cos * rnd); //Somthing wrong with L2j Heding calculation o_0? + int x = getX()+x1; + int y = getY()+y1; + int z = getZ()-30; + _fishx = x; + _fishy = y; + _fishz = z; + + //check the fishing floats x,y,z is in a fishing zone + //if not the abort fishing mode else continue + if (!ZoneManager.getInstance().checkIfInZoneFishing(x,y)) + { + //abort fishing + this.sendMessage("Your Lure didnt land in a fishing zone."); + return; + } + this.sendMessage("Get Ready to Fish"); + this.setIsImobilised(true); + _fishing = true; + broadcastUserInfo(); + //Starts fishing + sendPacket(new SystemMessage(1461)); + ExFishingStart efs = new ExFishingStart(this,x,y,z); + broadcastPacket(efs); + StartLookingForFishTask(); + } + public void StopLookingForFishTask() + { + if (_taskforfish != null) + { + _taskforfish.cancel(false); + _taskforfish = null; + } + } + public void StartLookingForFishTask() + { + if (!isDead() && _taskforfish == null) + { + int waittime = 30; + //Time for fish is dependet to lure type + if (_lure != null) + { + int lureid = _lure.getItemId(); + if (lureid == 6519 || lureid == 6522 |lureid == 6525)//low grade + waittime = 25; + else if (lureid == 6520 || lureid == 6523 |lureid == 6526)//medium grade + waittime = 20; + else if (lureid == 6521 || lureid == 6524 |lureid == 6527)//high grade + waittime = 15; + } + _taskforfish = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new LokingForFishTask(), waittime * 1000, waittime * 1000); + } + } + public void StartFishCombat() + { + _fish = new L2Fishing (this); + } + public void EndFishing(boolean win) + { + if (win) + { + //Succeeded in fishing + sendPacket(new SystemMessage(1469)); + } + ExFishingEnd efe = new ExFishingEnd(win, this); + broadcastPacket(efe); + _fishing = false; + _fishx = 0; + _fishy = 0; + _fishz = 0; + broadcastUserInfo(); + _fish = null; + _lure = null; + //Ends fishing + sendPacket(new SystemMessage(1460)); + setIsImobilised(false); + StopLookingForFishTask(); + } + public L2Fishing GetFish() + { + return _fish; + } + public int GetFishx() + { + return _fishx; + } + public int GetFishy() + { + return _fishy; + } + public int GetFishz() + { + return _fishz; + } + public void SetLure (L2ItemInstance lure) + { + _lure = lure; + } + public L2ItemInstance GetLure() + { + return _lure; + } + public int GetInventoryLimit() + { + int ivlim; + if (isGM()) { + ivlim = Config.INVENTORY_MAXIMUM_GM; + } + else if (getRace() == Race.dwarf) + { + ivlim = Config.INVENTORY_MAXIMUM_DWARF; + } + else + { + ivlim = Config.INVENTORY_MAXIMUM_NO_DWARF; + } + ivlim += (int)getStat().calcStat(Stats.INV_LIM, 0, null, null); + + return ivlim; + } + public int GetWareHouseLimit() + { + int whlim; + if (getRace() == Race.dwarf){ + whlim = Config.WAREHOUSE_SLOTS_DWARF; + } + else{ + whlim = Config.WAREHOUSE_SLOTS_NO_DWARF; + } + whlim += (int)getStat().calcStat(Stats.WH_LIM, 0, null, null); + + return whlim; + } + public int GetPrivateSellStoreLimit() + { + int pslim; + if (getRace() == Race.dwarf){ + pslim = Config.MAX_PVTSTORE_SLOTS_DWARF; + } + else{ + pslim = Config.MAX_PVTSTORE_SLOTS_OTHER; + } + pslim += (int)getStat().calcStat(Stats.P_SELL_LIM, 0, null, null); + + return pslim; + } + public int GetPrivateBuyStoreLimit() + { + int pblim; + if (getRace() == Race.dwarf){ + pblim = Config.MAX_PVTSTORE_SLOTS_DWARF; + } + else + { + pblim = Config.MAX_PVTSTORE_SLOTS_OTHER; + } + pblim += (int)getStat().calcStat(Stats.P_BUY_LIM, 0, null, null); + + return pblim; + } + public int GetFreightLimit() + { + return Config.FREIGHT_SLOTS + (int)getStat().calcStat(Stats.FREIGHT_LIM, 0, null, null); + } + + public int GetDwarfRecipeLimit() + { + int recdlim = Config.DWARF_RECIPE_LIMIT; + recdlim += (int)getStat().calcStat(Stats.REC_D_LIM, 0, null, null); + return recdlim; + } + + public int GetCommonRecipeLimit() + { + int recclim = Config.COMMON_RECIPE_LIMIT; + recclim += (int)getStat().calcStat(Stats.REC_C_LIM, 0, null, null); + return recclim; + } + + public void setMountObjectID(int newID) + { + _mountObjectID = newID; + } + + public int getMountObjectID() + { + return _mountObjectID; + } + + private L2ItemInstance _lure = null; + + /** + * Get the current skill in use or return null.

    + * + */ + public SkillDat getCurrentSkill() + { + return _currentSkill; + } + + + /** + * Create a new SkillDat object and set the player _currentSkill.

    + * + */ + public void setCurrentSkill(L2Skill currentSkill, boolean ctrlPressed, + boolean shiftPressed) + { + if (currentSkill == null) + { + if (Config.DEBUG) + _log.info("Setting current skill: NULL for " + getName() + "."); + + _currentSkill = null; + return; + } + + if (Config.DEBUG) + _log.info("Setting current skill: " + currentSkill.getName() + " (ID: " + currentSkill.getId() + ") for " + getName() + "."); + + _currentSkill = new SkillDat(currentSkill, ctrlPressed, shiftPressed); + } + + public SkillDat getQueuedSkill() + { + return _queuedSkill; + } + + + /** + * Create a new SkillDat object and queue it in the player _queuedSkill.

    + * + */ + public void setQueuedSkill(L2Skill queuedSkill, boolean ctrlPressed, boolean shiftPressed) + { + if (queuedSkill == null) + { + if (Config.DEBUG) + _log.info("Setting queued skill: NULL for " + getName() + "."); + + _queuedSkill = null; + return; + } + + if (Config.DEBUG) + _log.info("Setting queued skill: " + queuedSkill.getName() + " (ID: " + queuedSkill.getId() + ") for " + getName() + "."); + + _queuedSkill = new SkillDat(queuedSkill, ctrlPressed, shiftPressed); + } + + public boolean isInJail() + { + return _inJail; + } + + public void setInJail(boolean state) + { + _inJail = state; + } + + public void setInJail(boolean state, int delayInMinutes) + { + _inJail = state; + _jailTimer = 0; + + if (_inJail) + { + if (delayInMinutes > 0) + { + _jailTimer = delayInMinutes * 60 * 1000; // in millisec + + // start the countdown + _jailTask = ThreadPoolManager.getInstance().scheduleGeneral(new JailTask(this), _jailTimer); + sendMessage("You are in jail for "+delayInMinutes+" minutes."); + } + + // Open a Html message to inform the player + NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0); + String jailInfos = HtmCache.getInstance().getHtm("data/html/jail_in.htm"); + if (jailInfos != null) + htmlMsg.setHtml(jailInfos); + else + htmlMsg.setHtml("You have been put in jail by an admin."); + sendPacket(htmlMsg); + + teleToLocation(-114356, -249645, -2984); // Jail + } else + { + // Open a Html message to inform the player + NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0); + String jailInfos = HtmCache.getInstance().getHtm("data/html/jail_out.htm"); + if (jailInfos != null) + htmlMsg.setHtml(jailInfos); + else + htmlMsg.setHtml("You are free for now, respect server rules!"); + sendPacket(htmlMsg); + + teleToLocation(17836, 170178, -3507); // Floran + } + + // store in database + storeCharBase(); + } + + public long getJailTimer() + { + return _jailTimer; + } + + public void setJailTimer(long time) + { + _jailTimer = time; + } + + private void updateJailState() + { + if (isInJail()) + { + // If jail time is elapsed, free the player + if (_jailTimer > 0) + { + // restart the countdown + _jailTask = ThreadPoolManager.getInstance().scheduleGeneral(new JailTask(this), _jailTimer); + sendMessage("You are still in jail for "+Math.round(_jailTimer/60000)+" minutes."); + } + + // If player escaped, put him back in jail + if (!ZoneManager.getInstance().checkIfInZone(ZoneType.getZoneTypeName(ZoneType.ZoneTypeEnum.Jail), this)) + teleToLocation(-114356,-249645,-2984); + } + } + + public void stopJailTask() + { + stopJailTask(true); + } + public void stopJailTask(boolean save) + { + if (_jailTask != null) + { + if (save) + setJailTimer(_jailTask.getDelay(TimeUnit.MILLISECONDS)); + _jailTask.cancel(false); + _jailTask = null; + } + } + + private ScheduledFuture _jailTask; + private class JailTask implements Runnable + { + L2PcInstance _player; + protected long _startedAt; + + protected JailTask(L2PcInstance player) + { + _player = player; + _startedAt = System.currentTimeMillis(); + } + + public void run() + { + _player.setInJail(false, 0); + } + } +} Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/knownlist/PcKnownList.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/knownlist/PcKnownList.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/knownlist/PcKnownList.java (working copy) @@ -1,223 +1,223 @@ -package net.sf.l2j.gameserver.model.actor.knownlist; - - -import net.sf.l2j.Config; -import net.sf.l2j.gameserver.model.L2Character; -import net.sf.l2j.gameserver.model.L2ItemInstance; -import net.sf.l2j.gameserver.model.L2Object; -import net.sf.l2j.gameserver.model.L2Summon; -import net.sf.l2j.gameserver.model.actor.instance.L2BoatInstance; -import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance; -import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance; -import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; -import net.sf.l2j.gameserver.model.actor.instance.L2PetInstance; -import net.sf.l2j.gameserver.model.actor.instance.L2StaticObjectInstance; -import net.sf.l2j.gameserver.serverpackets.CharInfo; -import net.sf.l2j.gameserver.serverpackets.DeleteObject; -import net.sf.l2j.gameserver.serverpackets.DoorInfo; -import net.sf.l2j.gameserver.serverpackets.DoorStatusUpdate; -import net.sf.l2j.gameserver.serverpackets.DropItem; -import net.sf.l2j.gameserver.serverpackets.GetOnVehicle; -import net.sf.l2j.gameserver.serverpackets.NpcInfo; -import net.sf.l2j.gameserver.serverpackets.PetInfo; -import net.sf.l2j.gameserver.serverpackets.PetItemList; -import net.sf.l2j.gameserver.serverpackets.PrivateStoreMsgSell; -import net.sf.l2j.gameserver.serverpackets.SpawnItem; -import net.sf.l2j.gameserver.serverpackets.SpawnItemPoly; -import net.sf.l2j.gameserver.serverpackets.StaticObject; -import net.sf.l2j.gameserver.serverpackets.VehicleInfo; - -public class PcKnownList extends PlayableKnownList -{ - // ========================================================= - // Data Field - - // ========================================================= - // Constructor - public PcKnownList(L2PcInstance[] activeChar) - { - super(activeChar); - } - - // ========================================================= - // Method - Public - /** - * Add a visible L2Object to L2PcInstance _knownObjects and _knownPlayer (if necessary) and send Server-Client Packets needed to inform the L2PcInstance of its state and actions in progress.

    - * - * object is a L2ItemInstance :

    - *
  • Send Server-Client Packet DropItem/SpawnItem to the L2PcInstance


  • - * - * object is a L2DoorInstance :

    - *
  • Send Server-Client Packets DoorInfo and DoorStatusUpdate to the L2PcInstance
  • - *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • - * - * object is a L2NpcInstance :

    - *
  • Send Server-Client Packet NpcInfo to the L2PcInstance
  • - *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • - * - * object is a L2Summon :

    - *
  • Send Server-Client Packet NpcInfo/PetItemList (if the L2PcInstance is the owner) to the L2PcInstance
  • - *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • - * - * object is a L2PcInstance :

    - *
  • Send Server-Client Packet CharInfo to the L2PcInstance
  • - *
  • If the object has a private store, Send Server-Client Packet PrivateStoreMsgSell to the L2PcInstance
  • - *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • - * - * @param object The L2Object to add to _knownObjects and _knownPlayer - * @param dropper The L2Character who dropped the L2Object - */ - public boolean addKnownObject(L2Object object) { return addKnownObject(object, null); } - public boolean addKnownObject(L2Object object, L2Character dropper) - { - if (!super.addKnownObject(object, dropper)) return false; - - if (object.getPoly().isMorphed() && object.getPoly().getPolyType().equals("item")) - { - //if (object.getPolytype().equals("item")) - getActiveChar().sendPacket(new SpawnItemPoly(object)); - //else if (object.getPolytype().equals("npc")) - // sendPacket(new NpcInfoPoly(object, this)); - - } - else - { - if (object instanceof L2ItemInstance) - { - if (dropper != null) - getActiveChar().sendPacket(new DropItem((L2ItemInstance) object, dropper.getObjectId())); - else - getActiveChar().sendPacket(new SpawnItem((L2ItemInstance) object)); - } - else if (object instanceof L2DoorInstance) - { - getActiveChar().sendPacket(new DoorInfo((L2DoorInstance) object)); - getActiveChar().sendPacket(new DoorStatusUpdate((L2DoorInstance) object)); - } - else if (object instanceof L2BoatInstance) - { - if(!getActiveChar().isInBoat()) - if(object != getActiveChar().getBoat()) - { - getActiveChar().sendPacket(new VehicleInfo((L2BoatInstance) object)); - ((L2BoatInstance) object).sendVehicleDeparture(getActiveChar()); - } - } - else if (object instanceof L2StaticObjectInstance) - { - getActiveChar().sendPacket(new StaticObject((L2StaticObjectInstance) object)); - } - else if (object instanceof L2NpcInstance) - { - if (Config.CHECK_KNOWN) getActiveChar().sendMessage("Added NPC: "+((L2NpcInstance) object).getName()); - getActiveChar().sendPacket(new NpcInfo((L2NpcInstance) object, getActiveChar())); - } - else if (object instanceof L2Summon) - { - L2Summon summon = (L2Summon) object; - - // Check if the L2PcInstance is the owner of the Pet - if (this.equals(summon.getOwner())) - { - getActiveChar().sendPacket(new PetInfo(summon)); - if (summon instanceof L2PetInstance) - { - getActiveChar().sendPacket(new PetItemList((L2PetInstance) summon)); - } - } - else - getActiveChar().sendPacket(new NpcInfo(summon, getActiveChar())); - } - else if (object instanceof L2PcInstance) - { - L2PcInstance otherPlayer = (L2PcInstance) object; - if(otherPlayer.isInBoat()) - { - otherPlayer.getPosition().setWorldPosition(otherPlayer.getBoat().getPosition().getWorldPosition()); - getActiveChar().sendPacket(new CharInfo(otherPlayer)); - getActiveChar().sendPacket(new GetOnVehicle(otherPlayer, otherPlayer.getBoat(), otherPlayer.getInBoatPosition().x, otherPlayer.getInBoatPosition().y, otherPlayer.getInBoatPosition().z)); - /*if(otherPlayer.getBoat().GetVehicleDeparture() == null) - { - - int xboat = otherPlayer.getBoat().getX(); - int yboat= otherPlayer.getBoat().getY(); - double modifier = Math.PI/2; - if (yboat == 0) - { - yboat = 1; - } - if(yboat < 0) - { - modifier = -modifier; - } - double angleboat = modifier - Math.atan(xboat/yboat); - int xp = otherPlayer.getX(); - int yp = otherPlayer.getY(); - modifier = Math.PI/2; - if (yp == 0) - { - yboat = 1; - } - if(yboat < 0) - { - modifier = -modifier; - } - double anglep = modifier - Math.atan(yp/xp); - - double finx = Math.cos(anglep - angleboat)*Math.sqrt(xp *xp +yp*yp ) + Math.cos(angleboat)*Math.sqrt(xboat *xboat +yboat*yboat ); - double finy = Math.sin(anglep - angleboat)*Math.sqrt(xp *xp +yp*yp ) + Math.sin(angleboat)*Math.sqrt(xboat *xboat +yboat*yboat ); - //otherPlayer.getPosition().setWorldPosition(otherPlayer.getBoat().getX() - otherPlayer.getInBoatPosition().x,otherPlayer.getBoat().getY() - otherPlayer.getInBoatPosition().y,otherPlayer.getBoat().getZ()- otherPlayer.getInBoatPosition().z); - otherPlayer.getPosition().setWorldPosition((int)finx,(int)finy,otherPlayer.getBoat().getZ()- otherPlayer.getInBoatPosition().z); - - }*/ - } - else - { - getActiveChar().sendPacket(new CharInfo(otherPlayer)); - } - - if (otherPlayer.getPrivateStoreType() == L2PcInstance.STORE_PRIVATE_BUY) - getActiveChar().sendPacket(new PrivateStoreMsgSell(otherPlayer)); - else if (otherPlayer.getPrivateStoreType() == L2PcInstance.STORE_PRIVATE_SELL) - getActiveChar().sendPacket(new PrivateStoreMsgSell(otherPlayer)); -// TODO: corrrect msg else if (otherPlayer.getPrivateStoreType() == L2PcInstance.STORE_PRIVATE_MANUFACTURE) -// getActiveChar().sendPacket(new PrivateStoreMsgSell(otherPlayer)); - } - - if (object instanceof L2Character) - { - // Update the state of the L2Character object client side by sending Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance - L2Character obj = (L2Character) object; - obj.getAI().describeStateToPlayer(getActiveChar()); - } - } - - return true; - } - - /** - * Remove a L2Object from L2PcInstance _knownObjects and _knownPlayer (if necessary) and send Server-Client Packet DeleteObject to the L2PcInstance.

    - * - * @param object The L2Object to remove from _knownObjects and _knownPlayer - * - */ - public boolean removeKnownObject(L2Object object) - { - if (!super.removeKnownObject(object)) return false; - // Send Server-Client Packet DeleteObject to the L2PcInstance - getActiveChar().sendPacket(new DeleteObject(object)); - if (Config.CHECK_KNOWN && object instanceof L2NpcInstance) getActiveChar().sendMessage("Removed NPC: "+((L2NpcInstance)object).getName()); - return true; - } - - // ========================================================= - // Method - Private - - // ========================================================= - // Property - Public - public final L2PcInstance getActiveChar() { return (L2PcInstance)super.getActiveChar(); } - - public int getDistanceToForgetObject(L2Object object) { return 6000; } - - public int getDistanceToWatchObject(L2Object object) { return 4000; } -} +package net.sf.l2j.gameserver.model.actor.knownlist; + + +import net.sf.l2j.Config; +import net.sf.l2j.gameserver.model.L2Character; +import net.sf.l2j.gameserver.model.L2ItemInstance; +import net.sf.l2j.gameserver.model.L2Object; +import net.sf.l2j.gameserver.model.L2Summon; +import net.sf.l2j.gameserver.model.actor.instance.L2BoatInstance; +import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance; +import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance; +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; +import net.sf.l2j.gameserver.model.actor.instance.L2PetInstance; +import net.sf.l2j.gameserver.model.actor.instance.L2StaticObjectInstance; +import net.sf.l2j.gameserver.serverpackets.CharInfo; +import net.sf.l2j.gameserver.serverpackets.DeleteObject; +import net.sf.l2j.gameserver.serverpackets.DoorInfo; +import net.sf.l2j.gameserver.serverpackets.DoorStatusUpdate; +import net.sf.l2j.gameserver.serverpackets.DropItem; +import net.sf.l2j.gameserver.serverpackets.GetOnVehicle; +import net.sf.l2j.gameserver.serverpackets.NpcInfo; +import net.sf.l2j.gameserver.serverpackets.PetInfo; +import net.sf.l2j.gameserver.serverpackets.PetItemList; +import net.sf.l2j.gameserver.serverpackets.PrivateStoreMsgSell; +import net.sf.l2j.gameserver.serverpackets.SpawnItem; +import net.sf.l2j.gameserver.serverpackets.SpawnItemPoly; +import net.sf.l2j.gameserver.serverpackets.StaticObject; +import net.sf.l2j.gameserver.serverpackets.VehicleInfo; + +public class PcKnownList extends PlayableKnownList +{ + // ========================================================= + // Data Field + + // ========================================================= + // Constructor + public PcKnownList(L2PcInstance[] activeChar) + { + super(activeChar); + } + + // ========================================================= + // Method - Public + /** + * Add a visible L2Object to L2PcInstance _knownObjects and _knownPlayer (if necessary) and send Server-Client Packets needed to inform the L2PcInstance of its state and actions in progress.

    + * + * object is a L2ItemInstance :

    + *
  • Send Server-Client Packet DropItem/SpawnItem to the L2PcInstance


  • + * + * object is a L2DoorInstance :

    + *
  • Send Server-Client Packets DoorInfo and DoorStatusUpdate to the L2PcInstance
  • + *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • + * + * object is a L2NpcInstance :

    + *
  • Send Server-Client Packet NpcInfo to the L2PcInstance
  • + *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • + * + * object is a L2Summon :

    + *
  • Send Server-Client Packet NpcInfo/PetItemList (if the L2PcInstance is the owner) to the L2PcInstance
  • + *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • + * + * object is a L2PcInstance :

    + *
  • Send Server-Client Packet CharInfo to the L2PcInstance
  • + *
  • If the object has a private store, Send Server-Client Packet PrivateStoreMsgSell to the L2PcInstance
  • + *
  • Send Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance


  • + * + * @param object The L2Object to add to _knownObjects and _knownPlayer + * @param dropper The L2Character who dropped the L2Object + */ + public boolean addKnownObject(L2Object object) { return addKnownObject(object, null); } + public boolean addKnownObject(L2Object object, L2Character dropper) + { + if (!super.addKnownObject(object, dropper)) return false; + + if (object.getPoly().isMorphed() && object.getPoly().getPolyType().equals("item")) + { + //if (object.getPolytype().equals("item")) + getActiveChar().sendPacket(new SpawnItemPoly(object)); + //else if (object.getPolytype().equals("npc")) + // sendPacket(new NpcInfoPoly(object, this)); + + } + else + { + if (object instanceof L2ItemInstance) + { + if (dropper != null) + getActiveChar().sendPacket(new DropItem((L2ItemInstance) object, dropper.getObjectId())); + else + getActiveChar().sendPacket(new SpawnItem((L2ItemInstance) object)); + } + else if (object instanceof L2DoorInstance) + { + getActiveChar().sendPacket(new DoorInfo((L2DoorInstance) object)); + getActiveChar().sendPacket(new DoorStatusUpdate((L2DoorInstance) object)); + } + else if (object instanceof L2BoatInstance) + { + if(!getActiveChar().isInBoat()) + if(object != getActiveChar().getBoat()) + { + getActiveChar().sendPacket(new VehicleInfo((L2BoatInstance) object)); + ((L2BoatInstance) object).sendVehicleDeparture(getActiveChar()); + } + } + else if (object instanceof L2StaticObjectInstance) + { + getActiveChar().sendPacket(new StaticObject((L2StaticObjectInstance) object)); + } + else if (object instanceof L2NpcInstance) + { + if (Config.CHECK_KNOWN) getActiveChar().sendMessage("Added NPC: "+((L2NpcInstance) object).getName()); + getActiveChar().sendPacket(new NpcInfo((L2NpcInstance) object, getActiveChar())); + } + else if (object instanceof L2Summon) + { + L2Summon summon = (L2Summon) object; + + // Check if the L2PcInstance is the owner of the Pet + if (this.equals(summon.getOwner())) + { + getActiveChar().sendPacket(new PetInfo(summon)); + if (summon instanceof L2PetInstance) + { + getActiveChar().sendPacket(new PetItemList((L2PetInstance) summon)); + } + } + else + getActiveChar().sendPacket(new NpcInfo(summon, getActiveChar())); + } + else if (object instanceof L2PcInstance) + { + L2PcInstance otherPlayer = (L2PcInstance) object; + if(otherPlayer.isInBoat()) + { + otherPlayer.getPosition().setWorldPosition(otherPlayer.getBoat().getPosition().getWorldPosition()); + getActiveChar().sendPacket(new CharInfo(otherPlayer)); + getActiveChar().sendPacket(new GetOnVehicle(otherPlayer, otherPlayer.getBoat(), otherPlayer.getInBoatPosition().getX(), otherPlayer.getInBoatPosition().getY(), otherPlayer.getInBoatPosition().getZ())); + /*if(otherPlayer.getBoat().GetVehicleDeparture() == null) + { + + int xboat = otherPlayer.getBoat().getX(); + int yboat= otherPlayer.getBoat().getY(); + double modifier = Math.PI/2; + if (yboat == 0) + { + yboat = 1; + } + if(yboat < 0) + { + modifier = -modifier; + } + double angleboat = modifier - Math.atan(xboat/yboat); + int xp = otherPlayer.getX(); + int yp = otherPlayer.getY(); + modifier = Math.PI/2; + if (yp == 0) + { + yboat = 1; + } + if(yboat < 0) + { + modifier = -modifier; + } + double anglep = modifier - Math.atan(yp/xp); + + double finx = Math.cos(anglep - angleboat)*Math.sqrt(xp *xp +yp*yp ) + Math.cos(angleboat)*Math.sqrt(xboat *xboat +yboat*yboat ); + double finy = Math.sin(anglep - angleboat)*Math.sqrt(xp *xp +yp*yp ) + Math.sin(angleboat)*Math.sqrt(xboat *xboat +yboat*yboat ); + //otherPlayer.getPosition().setWorldPosition(otherPlayer.getBoat().getX() - otherPlayer.getInBoatPosition().x,otherPlayer.getBoat().getY() - otherPlayer.getInBoatPosition().y,otherPlayer.getBoat().getZ()- otherPlayer.getInBoatPosition().z); + otherPlayer.getPosition().setWorldPosition((int)finx,(int)finy,otherPlayer.getBoat().getZ()- otherPlayer.getInBoatPosition().z); + + }*/ + } + else + { + getActiveChar().sendPacket(new CharInfo(otherPlayer)); + } + + if (otherPlayer.getPrivateStoreType() == L2PcInstance.STORE_PRIVATE_BUY) + getActiveChar().sendPacket(new PrivateStoreMsgSell(otherPlayer)); + else if (otherPlayer.getPrivateStoreType() == L2PcInstance.STORE_PRIVATE_SELL) + getActiveChar().sendPacket(new PrivateStoreMsgSell(otherPlayer)); +// TODO: corrrect msg else if (otherPlayer.getPrivateStoreType() == L2PcInstance.STORE_PRIVATE_MANUFACTURE) +// getActiveChar().sendPacket(new PrivateStoreMsgSell(otherPlayer)); + } + + if (object instanceof L2Character) + { + // Update the state of the L2Character object client side by sending Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance + L2Character obj = (L2Character) object; + obj.getAI().describeStateToPlayer(getActiveChar()); + } + } + + return true; + } + + /** + * Remove a L2Object from L2PcInstance _knownObjects and _knownPlayer (if necessary) and send Server-Client Packet DeleteObject to the L2PcInstance.

    + * + * @param object The L2Object to remove from _knownObjects and _knownPlayer + * + */ + public boolean removeKnownObject(L2Object object) + { + if (!super.removeKnownObject(object)) return false; + // Send Server-Client Packet DeleteObject to the L2PcInstance + getActiveChar().sendPacket(new DeleteObject(object)); + if (Config.CHECK_KNOWN && object instanceof L2NpcInstance) getActiveChar().sendMessage("Removed NPC: "+((L2NpcInstance)object).getName()); + return true; + } + + // ========================================================= + // Method - Private + + // ========================================================= + // Property - Public + public final L2PcInstance getActiveChar() { return (L2PcInstance)super.getActiveChar(); } + + public int getDistanceToForgetObject(L2Object object) { return 6000; } + + public int getDistanceToWatchObject(L2Object object) { return 4000; } +} Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/position/ObjectPosition.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/position/ObjectPosition.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/actor/position/ObjectPosition.java (working copy) @@ -1,155 +1,170 @@ -package net.sf.l2j.gameserver.model.actor.position; - -import java.util.logging.Logger; - -import net.sf.l2j.Config; -import net.sf.l2j.gameserver.model.L2Character; -import net.sf.l2j.gameserver.model.L2Object; -import net.sf.l2j.gameserver.model.L2World; -import net.sf.l2j.gameserver.model.L2WorldRegion; -import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; -import net.sf.l2j.util.Point3D; - -public class ObjectPosition -{ - private static final Logger _log = Logger.getLogger(ObjectPosition.class.getName()); - - // ========================================================= - // Data Field - private L2Object[] _ActiveObject; // Use array as a dirty trick to keep object as byref instead of byval - private int _Heading = 0; - private Point3D _WorldPosition; - private L2WorldRegion _WorldRegion; // Object localization : Used for items/chars that are seen in the world - - // ========================================================= - // Constructor - public ObjectPosition(L2Object[] activeObject) - { - _ActiveObject = activeObject; - setWorldRegion(L2World.getInstance().getRegion(getWorldPosition())); - } - - // ========================================================= - // Method - Public - /** - * Set the x,y,z position of the L2Object and if necessary modify its _worldRegion.

    - * - * Assert :

    - *
  • _worldRegion != null


  • - * - * Example of use :

    - *
  • Update position during and after movement, or after teleport

  • - */ - public final void setXYZ(int x, int y, int z) - { - if (Config.ASSERT) assert getWorldRegion() != null; - - setWorldPosition(x, y ,z); - - try - { - if (L2World.getInstance().getRegion(getWorldPosition()) != getWorldRegion()) - updateWorldRegion(); - } - catch (Exception e) - { - _log.warning("Object Id at bad coords: (x: " + getX() + ", y: " + getY() + ", z: " + getZ() + ")."); - if (getActiveObject() instanceof L2Character) - getActiveObject().decayMe(); - else if (getActiveObject() instanceof L2PcInstance) - { - //((L2PcInstance)obj).deleteMe(); - ((L2PcInstance)getActiveObject()).teleToLocation(0,0,0); - ((L2PcInstance)getActiveObject()).sendMessage("Error with your coords, Please ask a GM for help!"); - } - } - } - - /** - * Set the x,y,z position of the L2Object and make it invisible.

    - * - * Concept :

    - * A L2Object is invisble if _hidden=true or _worldregion==null

    - * - * Assert :

    - *
  • _worldregion==null (L2Object is invisible)


  • - * - * Example of use :

    - *
  • Create a Door
  • - *
  • Restore L2PcInstance

  • - */ - public final void setXYZInvisible(int x, int y, int z) - { - if (Config.ASSERT) assert getWorldRegion() == null; - if (x > L2World.MAP_MAX_X) x = L2World.MAP_MAX_X - 5000; - if (x < L2World.MAP_MIN_X) x = L2World.MAP_MIN_X + 5000; - if (y > L2World.MAP_MAX_Y) y = L2World.MAP_MAX_Y - 5000; - if (y < L2World.MAP_MIN_Y) y = L2World.MAP_MIN_Y + 5000; - - setWorldPosition(x, y ,z); - getActiveObject().setIsVisible(false); - } - - /** - * checks if current object changed its region, if so, update referencies - */ - public void updateWorldRegion() - { - if (!getActiveObject().isVisible()) return; - - L2WorldRegion newRegion = L2World.getInstance().getRegion(getWorldPosition()); - if (newRegion != getWorldRegion()) - { - getWorldRegion().removeVisibleObject(getActiveObject()); - - setWorldRegion(newRegion); - - // Add the L2Oject spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion - getWorldRegion().addVisibleObject(getActiveObject()); - } - } - - // ========================================================= - // Method - Private - - // ========================================================= - // Property - Public - public final L2Object getActiveObject() - { - if (_ActiveObject == null || _ActiveObject.length <= 0) return null; - return _ActiveObject[0]; - } - - public final int getHeading() { return _Heading; } - public final void setHeading(int value) { _Heading = value; } - - /** Return the x position of the L2Object. */ - public final int getX() { return getWorldPosition().x; } - public final void setX(int value) { getWorldPosition().x = value; } - - /** Return the y position of the L2Object. */ - public final int getY() { return getWorldPosition().y; } - public final void setY(int value) { getWorldPosition().y = value; } - - /** Return the z position of the L2Object. */ - public final int getZ() { return getWorldPosition().z; } - public final void setZ(int value) { getWorldPosition().z = value; } - - public final Point3D getWorldPosition() - { - if (_WorldPosition == null) _WorldPosition = new Point3D(0, 0, 0); - return _WorldPosition; - } - public final void setWorldPosition(int x, int y, int z) - { - getWorldPosition().x = x; - getWorldPosition().y = y; - getWorldPosition().z = z; - if (getActiveObject() != null && getActiveObject() instanceof L2PcInstance) - ((L2PcInstance)getActiveObject()).revalidateZone(); - } - public final void setWorldPosition(Point3D newPosition) { setWorldPosition(newPosition.x, newPosition.y, newPosition.z); } - - public final L2WorldRegion getWorldRegion() { return _WorldRegion; } - public final void setWorldRegion(L2WorldRegion value) { _WorldRegion = value; } -} +package net.sf.l2j.gameserver.model.actor.position; + +import java.util.logging.Logger; + +import net.sf.l2j.Config; +import net.sf.l2j.gameserver.model.L2Character; +import net.sf.l2j.gameserver.model.L2Object; +import net.sf.l2j.gameserver.model.L2World; +import net.sf.l2j.gameserver.model.L2WorldRegion; +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; +import net.sf.l2j.util.Point3D; + +public class ObjectPosition +{ + private static final Logger _log = Logger.getLogger(ObjectPosition.class.getName()); + + // ========================================================= + // Data Field + private L2Object[] _ActiveObject; // Use array as a dirty trick to keep object as byref instead of byval + private int _Heading = 0; + private Point3D _WorldPosition; + private L2WorldRegion _WorldRegion; // Object localization : Used for items/chars that are seen in the world + + // ========================================================= + // Constructor + public ObjectPosition(L2Object[] activeObject) + { + _WorldPosition = new Point3D(0,0,0); + _ActiveObject = activeObject; + _WorldRegion = L2World.getInstance().getRegion(_WorldPosition); + } + + // ========================================================= + // Method - Public + /** + * Set the x,y,z position of the L2Object and if necessary modify its _worldRegion.

    + * + * Assert :

    + *
  • _worldRegion != null


  • + * + * Example of use :

    + *
  • Update position during and after movement, or after teleport

  • + */ + public final void setXYZ(int x, int y, int z) + { + if (Config.ASSERT) assert getWorldRegion() != null; + + setWorldPosition(x, y ,z); + + try + { + if (L2World.getInstance().getRegion(getWorldPosition()) != getWorldRegion()) + updateWorldRegion(); + } + catch (Exception e) + { + _log.warning("Object Id at bad coords: (x: " + getX() + ", y: " + getY() + ", z: " + getZ() + ")."); + if (getActiveObject() instanceof L2Character) + getActiveObject().decayMe(); + else if (getActiveObject() instanceof L2PcInstance) + { + //((L2PcInstance)obj).deleteMe(); + ((L2PcInstance)getActiveObject()).teleToLocation(0,0,0); + ((L2PcInstance)getActiveObject()).sendMessage("Error with your coords, Please ask a GM for help!"); + } + } + } + + /** + * Set the x,y,z position of the L2Object and make it invisible.

    + * + * Concept :

    + * A L2Object is invisble if _hidden=true or _worldregion==null

    + * + * Assert :

    + *
  • _worldregion==null (L2Object is invisible)


  • + * + * Example of use :

    + *
  • Create a Door
  • + *
  • Restore L2PcInstance

  • + */ + public final void setXYZInvisible(int x, int y, int z) + { + if (Config.ASSERT) assert getWorldRegion() == null; + if (x > L2World.MAP_MAX_X) x = L2World.MAP_MAX_X - 5000; + if (x < L2World.MAP_MIN_X) x = L2World.MAP_MIN_X + 5000; + if (y > L2World.MAP_MAX_Y) y = L2World.MAP_MAX_Y - 5000; + if (y < L2World.MAP_MIN_Y) y = L2World.MAP_MIN_Y + 5000; + + setWorldPosition(x, y ,z); + getActiveObject().setIsVisible(false); + } + + /** + * checks if current object changed its region, if so, update referencies + */ + public void updateWorldRegion() + { + if (!getActiveObject().isVisible()) return; + + L2WorldRegion newRegion = L2World.getInstance().getRegion(getWorldPosition()); + if (newRegion != getWorldRegion()) + { + getWorldRegion().removeVisibleObject(getActiveObject()); + + setWorldRegion(newRegion); + + // Add the L2Oject spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion + getWorldRegion().addVisibleObject(getActiveObject()); + } + } + + // ========================================================= + // Method - Private + + // ========================================================= + // Property - Public + public synchronized final L2Object getActiveObject() + { + if (_ActiveObject == null || _ActiveObject.length <= 0) return null; + return _ActiveObject[0]; + } + + public synchronized final int getHeading() { + return _Heading; + } + public synchronized final void setHeading(int value) { + _Heading = value; + } + + /** Return the x position of the L2Object. */ + public final int getX() { return getWorldPosition().getX(); } + public final void setX(int value) { getWorldPosition().setX(value); } + + /** Return the y position of the L2Object. */ + public final int getY() { return getWorldPosition().getY(); } + public final void setY(int value) { getWorldPosition().setY(value); } + + /** Return the z position of the L2Object. */ + public final int getZ() { return getWorldPosition().getZ(); } + public final void setZ(int value) { getWorldPosition().setZ(value); } + + public synchronized final Point3D getWorldPosition() + { + if (_WorldPosition == null) + _WorldPosition = new Point3D(0, 0, 0); + return _WorldPosition; + } + public final void setWorldPosition(int x, int y, int z) + { + synchronized(this) { + getWorldPosition().setX(x); + getWorldPosition().setY(y); + getWorldPosition().setZ(z); + } + if (getActiveObject() != null && getActiveObject() instanceof L2PcInstance) + ((L2PcInstance)getActiveObject()).revalidateZone(); + } + public final void setWorldPosition(Point3D newPosition) { + setWorldPosition(newPosition.getX(), newPosition.getY(), newPosition.getZ()); + } + + public synchronized final L2WorldRegion getWorldRegion() { + return _WorldRegion; + } + + public synchronized final void setWorldRegion(L2WorldRegion value) { + _WorldRegion = value; + } +} Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/waypoint/WayPointNode.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/waypoint/WayPointNode.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/model/waypoint/WayPointNode.java (working copy) @@ -1,278 +1,278 @@ -/* - * $Header: WayPointNode.java, 20/07/2005 19:49:29 luisantonioa Exp $ - * - * $Author: luisantonioa $ - * $Date: 20/07/2005 19:49:29 $ - * $Revision: 1 $ - * $Log: WayPointNode.java,v $ - * Revision 1 20/07/2005 19:49:29 luisantonioa - * Added copyright notice - * - * - * 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 2, 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * http://www.gnu.org/copyleft/gpl.html - */ -package net.sf.l2j.gameserver.model.waypoint; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - -import javolution.util.FastList; -import net.sf.l2j.Config; -import net.sf.l2j.gameserver.idfactory.IdFactory; -import net.sf.l2j.gameserver.model.L2Character; -import net.sf.l2j.gameserver.model.L2Object; -import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; -import net.sf.l2j.gameserver.serverpackets.MyTargetSelected; -import net.sf.l2j.util.Point3D; - -/** - * This class ... - * - * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $ - */ - -public class WayPointNode extends L2Object -{ - private int _id; - private String _title, _type; - private static String NORMAL = "Node", SELECTED = "Selected", LINKED = "Linked"; - public static int LINE_ID = 5560; - private static String LINE_TYPE = "item"; - private Map> linkLists; - - /** - * @param objectId - */ - public WayPointNode(int objectId) - { - super(objectId); - linkLists = Collections.synchronizedMap(new WeakHashMap>()); - } - - /* (non-Javadoc) - * @see net.sf.l2j.gameserver.model.L2Object#isAutoAttackable(net.sf.l2j.gameserver.model.L2Character) - */ - public boolean isAutoAttackable(@SuppressWarnings("unused") - L2Character attacker) - { - return false; - } - - public static WayPointNode spawn(String type, int id, int x, int y, int z) - { - WayPointNode newNode = new WayPointNode(IdFactory.getInstance().getNextId()); - newNode.getPoly().setPolyInfo(type, id + ""); - newNode.spawnMe(x, y, z); - return newNode; - } - - public static WayPointNode spawn(boolean isItemId, int id, L2PcInstance player) - { - return spawn(isItemId ? "item" : "npc", id, player.getX(), player.getY(), player.getZ()); - } - - public static WayPointNode spawn(boolean isItemId, int id, Point3D point) - { - return spawn(isItemId ? "item" : "npc", id, point.x, point.y, point.z); - } - - public static WayPointNode spawn(Point3D point) - { - return spawn(Config.NEW_NODE_TYPE, Config.NEW_NODE_ID, point.x, point.y, point.z); - } - - public static WayPointNode spawn(L2PcInstance player) - { - return spawn(Config.NEW_NODE_TYPE, Config.NEW_NODE_ID, player.getX(), player.getY(), - player.getZ()); - } - - public void onAction(L2PcInstance player) - { - if (player.getTarget() != this) - { - player.setTarget(this); - MyTargetSelected my = new MyTargetSelected(getObjectId(), 0); - player.sendPacket(my); - } - } - - public void setNormalInfo(String type, int id, String title) - { - this._type = type; - changeID(id, title); - } - - public void setNormalInfo(String type, int id) - { - this._type = type; - changeID(id); - } - - private void changeID(int id) - { - this._id = id; - toggleVisible(); - toggleVisible(); - } - - private void changeID(int id, String title) - { - setName(title); - setTitle(title); - changeID(id); - } - - public void setLinked() - { - changeID(Config.LINKED_NODE_ID, LINKED); - } - - public void setNormal() - { - changeID(Config.NEW_NODE_ID, NORMAL); - } - - public void setSelected() - { - changeID(Config.SELECTED_NODE_ID, SELECTED); - } - - public boolean isMarker() - { - return true; - } - - public final String getTitle() - { - return _title; - } - - public final void setTitle(String title) - { - this._title = title; - } - - public int getId() - { - return _id; - } - - public String getType() - { - return _type; - } - - public void setType(String type) - { - this._type = type; - } - - /** - * @param target - * @param selectedNode - */ - public static void drawLine(WayPointNode nodeA, WayPointNode nodeB) - { - int x1 = nodeA.getX(), y1 = nodeA.getY(), z1 = nodeA.getZ(); - int x2 = nodeB.getX(), y2 = nodeB.getY(), z2 = nodeB.getZ(); - int modX = x1 - x2 > 0 ? -1 : 1; - int modY = y1 - y2 > 0 ? -1 : 1; - int modZ = z1 - z2 > 0 ? -1 : 1; - - int diffX = Math.abs(x1 - x2); - int diffY = Math.abs(y1 - y2); - int diffZ = Math.abs(z1 - z2); - - int distance = (int) Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); - - int steps = distance / 40; - - List lineNodes = new FastList(); - - for (int i = 0; i < steps; i++) - { - x1 = x1 + (modX * diffX / steps); - y1 = y1 + (modY * diffY / steps); - z1 = z1 + (modZ * diffZ / steps); - - lineNodes.add(WayPointNode.spawn(LINE_TYPE, LINE_ID, x1, y1, z1)); - } - - nodeA.addLineInfo(nodeB, lineNodes); - nodeB.addLineInfo(nodeA, lineNodes); - } - - public void addLineInfo(WayPointNode node, List line) - { - linkLists.put(node, line); - } - - /** - * @param target - * @param selectedNode - */ - public static void eraseLine(WayPointNode target, WayPointNode selectedNode) - { - List lineNodes = target.getLineInfo(selectedNode); - if (lineNodes == null) return; - for (WayPointNode node : lineNodes) - { - node.decayMe(); - } - target.eraseLine(selectedNode); - selectedNode.eraseLine(target); - } - - /** - * @param target - */ - public void eraseLine(WayPointNode target) - { - linkLists.remove(target); - } - - /** - * @param selectedNode - * @return - */ - private List getLineInfo(WayPointNode selectedNode) - { - return linkLists.get(selectedNode); - } - - public static void setLineId(int line_id) - { - LINE_ID = line_id; - } - - public List getLineNodes() - { - List list = new FastList(); - - for (List points : linkLists.values()) - { - list.addAll(points); - } - - return list; - } - -} +/* + * $Header: WayPointNode.java, 20/07/2005 19:49:29 luisantonioa Exp $ + * + * $Author: luisantonioa $ + * $Date: 20/07/2005 19:49:29 $ + * $Revision: 1 $ + * $Log: WayPointNode.java,v $ + * Revision 1 20/07/2005 19:49:29 luisantonioa + * Added copyright notice + * + * + * 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 2, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * http://www.gnu.org/copyleft/gpl.html + */ +package net.sf.l2j.gameserver.model.waypoint; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +import javolution.util.FastList; +import net.sf.l2j.Config; +import net.sf.l2j.gameserver.idfactory.IdFactory; +import net.sf.l2j.gameserver.model.L2Character; +import net.sf.l2j.gameserver.model.L2Object; +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; +import net.sf.l2j.gameserver.serverpackets.MyTargetSelected; +import net.sf.l2j.util.Point3D; + +/** + * This class ... + * + * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $ + */ + +public class WayPointNode extends L2Object +{ + private int _id; + private String _title, _type; + private static String NORMAL = "Node", SELECTED = "Selected", LINKED = "Linked"; + public static int LINE_ID = 5560; + private static String LINE_TYPE = "item"; + private Map> linkLists; + + /** + * @param objectId + */ + public WayPointNode(int objectId) + { + super(objectId); + linkLists = Collections.synchronizedMap(new WeakHashMap>()); + } + + /* (non-Javadoc) + * @see net.sf.l2j.gameserver.model.L2Object#isAutoAttackable(net.sf.l2j.gameserver.model.L2Character) + */ + public boolean isAutoAttackable(@SuppressWarnings("unused") + L2Character attacker) + { + return false; + } + + public static WayPointNode spawn(String type, int id, int x, int y, int z) + { + WayPointNode newNode = new WayPointNode(IdFactory.getInstance().getNextId()); + newNode.getPoly().setPolyInfo(type, id + ""); + newNode.spawnMe(x, y, z); + return newNode; + } + + public static WayPointNode spawn(boolean isItemId, int id, L2PcInstance player) + { + return spawn(isItemId ? "item" : "npc", id, player.getX(), player.getY(), player.getZ()); + } + + public static WayPointNode spawn(boolean isItemId, int id, Point3D point) + { + return spawn(isItemId ? "item" : "npc", id, point.getX(), point.getY(), point.getZ()); + } + + public static WayPointNode spawn(Point3D point) + { + return spawn(Config.NEW_NODE_TYPE, Config.NEW_NODE_ID, point.getX(), point.getY(), point.getZ()); + } + + public static WayPointNode spawn(L2PcInstance player) + { + return spawn(Config.NEW_NODE_TYPE, Config.NEW_NODE_ID, player.getX(), player.getY(), + player.getZ()); + } + + public void onAction(L2PcInstance player) + { + if (player.getTarget() != this) + { + player.setTarget(this); + MyTargetSelected my = new MyTargetSelected(getObjectId(), 0); + player.sendPacket(my); + } + } + + public void setNormalInfo(String type, int id, String title) + { + this._type = type; + changeID(id, title); + } + + public void setNormalInfo(String type, int id) + { + this._type = type; + changeID(id); + } + + private void changeID(int id) + { + this._id = id; + toggleVisible(); + toggleVisible(); + } + + private void changeID(int id, String title) + { + setName(title); + setTitle(title); + changeID(id); + } + + public void setLinked() + { + changeID(Config.LINKED_NODE_ID, LINKED); + } + + public void setNormal() + { + changeID(Config.NEW_NODE_ID, NORMAL); + } + + public void setSelected() + { + changeID(Config.SELECTED_NODE_ID, SELECTED); + } + + public boolean isMarker() + { + return true; + } + + public final String getTitle() + { + return _title; + } + + public final void setTitle(String title) + { + this._title = title; + } + + public int getId() + { + return _id; + } + + public String getType() + { + return _type; + } + + public void setType(String type) + { + this._type = type; + } + + /** + * @param target + * @param selectedNode + */ + public static void drawLine(WayPointNode nodeA, WayPointNode nodeB) + { + int x1 = nodeA.getX(), y1 = nodeA.getY(), z1 = nodeA.getZ(); + int x2 = nodeB.getX(), y2 = nodeB.getY(), z2 = nodeB.getZ(); + int modX = x1 - x2 > 0 ? -1 : 1; + int modY = y1 - y2 > 0 ? -1 : 1; + int modZ = z1 - z2 > 0 ? -1 : 1; + + int diffX = Math.abs(x1 - x2); + int diffY = Math.abs(y1 - y2); + int diffZ = Math.abs(z1 - z2); + + int distance = (int) Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); + + int steps = distance / 40; + + List lineNodes = new FastList(); + + for (int i = 0; i < steps; i++) + { + x1 = x1 + (modX * diffX / steps); + y1 = y1 + (modY * diffY / steps); + z1 = z1 + (modZ * diffZ / steps); + + lineNodes.add(WayPointNode.spawn(LINE_TYPE, LINE_ID, x1, y1, z1)); + } + + nodeA.addLineInfo(nodeB, lineNodes); + nodeB.addLineInfo(nodeA, lineNodes); + } + + public void addLineInfo(WayPointNode node, List line) + { + linkLists.put(node, line); + } + + /** + * @param target + * @param selectedNode + */ + public static void eraseLine(WayPointNode target, WayPointNode selectedNode) + { + List lineNodes = target.getLineInfo(selectedNode); + if (lineNodes == null) return; + for (WayPointNode node : lineNodes) + { + node.decayMe(); + } + target.eraseLine(selectedNode); + selectedNode.eraseLine(target); + } + + /** + * @param target + */ + public void eraseLine(WayPointNode target) + { + linkLists.remove(target); + } + + /** + * @param selectedNode + * @return + */ + private List getLineInfo(WayPointNode selectedNode) + { + return linkLists.get(selectedNode); + } + + public static void setLineId(int line_id) + { + LINE_ID = line_id; + } + + public List getLineNodes() + { + List list = new FastList(); + + for (List points : linkLists.values()) + { + list.addAll(points); + } + + return list; + } + +} Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/serverpackets/StopMoveInVehicle.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/serverpackets/StopMoveInVehicle.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/gameserver/serverpackets/StopMoveInVehicle.java (working copy) @@ -1,77 +1,77 @@ -/* - * 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 2, 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * http://www.gnu.org/copyleft/gpl.html - */ -package net.sf.l2j.gameserver.serverpackets; - -import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; - -/** - * @author Maktakien - * - */ -public class StopMoveInVehicle extends ServerBasePacket -{ - - private L2PcInstance _pci; - private int _boatid; - /** - * @param player - * @param boatid - */ - public StopMoveInVehicle(L2PcInstance player, int boatid) - { - _pci = player; - _boatid = boatid; - } - - /* (non-Javadoc) - * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#runImpl() - */ - @Override - void runImpl() - { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#writeImpl() - */ - @Override - void writeImpl() - { - writeC(0x72); - writeD(_pci.getObjectId()); - writeD(_boatid); - writeD(_pci.getInBoatPosition().x); - writeD(_pci.getInBoatPosition().y); - writeD(_pci.getInBoatPosition().z); - writeD(_pci.getPosition().getHeading()); - } - - /* (non-Javadoc) - * @see net.sf.l2j.gameserver.BasePacket#getType() - */ - @Override - public String getType() - { - // TODO Auto-generated method stub - return "[S] 72 StopMoveInVehicle"; - } - -} +/* + * 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 2, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * http://www.gnu.org/copyleft/gpl.html + */ +package net.sf.l2j.gameserver.serverpackets; + +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance; + +/** + * @author Maktakien + * + */ +public class StopMoveInVehicle extends ServerBasePacket +{ + + private L2PcInstance _pci; + private int _boatid; + /** + * @param player + * @param boatid + */ + public StopMoveInVehicle(L2PcInstance player, int boatid) + { + _pci = player; + _boatid = boatid; + } + + /* (non-Javadoc) + * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#runImpl() + */ + @Override + void runImpl() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#writeImpl() + */ + @Override + void writeImpl() + { + writeC(0x72); + writeD(_pci.getObjectId()); + writeD(_boatid); + writeD(_pci.getInBoatPosition().getX()); + writeD(_pci.getInBoatPosition().getY()); + writeD(_pci.getInBoatPosition().getZ()); + writeD(_pci.getPosition().getHeading()); + } + + /* (non-Javadoc) + * @see net.sf.l2j.gameserver.BasePacket#getType() + */ + @Override + public String getType() + { + // TODO Auto-generated method stub + return "[S] 72 StopMoveInVehicle"; + } + +} Index: /root/workspace/L2_GameServer_c4/java/net/sf/l2j/util/Point3D.java =================================================================== --- /root/workspace/L2_GameServer_c4/java/net/sf/l2j/util/Point3D.java (revision 2154) +++ /root/workspace/L2_GameServer_c4/java/net/sf/l2j/util/Point3D.java (working copy) @@ -1,142 +1,169 @@ -/* - * $Header: Point3D.java, 19/07/2005 21:33:07 luisantonioa Exp $ - * - * $Author: luisantonioa $ - * $Date: 19/07/2005 21:33:07 $ - * $Revision: 1 $ - * $Log: Point3D.java,v $ - * Revision 1 19/07/2005 21:33:07 luisantonioa - * Added copyright notice - * - * - * 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 2, 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * http://www.gnu.org/copyleft/gpl.html - */ -package net.sf.l2j.util; - -import java.io.Serializable; - -import net.sf.l2j.gameserver.model.waypoint.WayPointNode; - -/** - * This class ... - * - * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $ - */ -public class Point3D implements Serializable -{ - /** - * Comment for serialVersionUID - */ - private static final long serialVersionUID = 4638345252031872576L; - public int x, y, z; - - public Point3D(int pX, int pY, int pZ) - { - this.x = pX; - this.y = pY; - this.z = pZ; - } - - public Point3D(int pX, int pY) - { - this.x = pX; - this.y = pY; - this.z = 0; - } - - /** - * @param worldPosition - */ - public Point3D(Point3D worldPosition) - { - this.x = worldPosition.x; - this.y = worldPosition.y; - this.z = worldPosition.z; - } - - public static Point3D getPosition(WayPointNode node) - { - return new Point3D(node.getX(), node.getY(), node.getZ()); - } - - public void setTo(Point3D point) - { - this.x = point.x; - this.y = point.y; - this.z = point.z; - } - - public String toString() - { - return "(" + x + ", " + y + ", " + z + ")"; - } - - public int hashCode() - { - return x ^ y ^ z; - } - - public boolean equals(Object o) - { - if (o instanceof Point3D) - { - Point3D point3D = (Point3D) o; - return point3D.x == x && point3D.y == y && point3D.z == z; - } - return false; - } - - public long distanceSquaredTo(Point3D point) - { - long dx = x - point.x; - long dy = y - point.y; - - return (dx * dx) + (dy * dy); - } - - public static long distanceSquared(Point3D point1, Point3D point2) - { - long dx = point1.x - point2.x; - long dy = point1.y - point2.y; - - return (dx * dx) + (dy * dy); - } - - public static boolean distanceLessThan(Point3D point1, Point3D point2, double distance) - { - long dx = point1.x - point2.x; - long dy = point1.y - point2.y; - - return (dx * dx) + (dy * dy) < distance * distance; - } - - public int getX() - { - return x; - } - - public int getY() - { - return y; - } - - public int getZ() - { - return z; - } -} +/* + * $Header: Point3D.java, 19/07/2005 21:33:07 luisantonioa Exp $ + * + * $Author: luisantonioa $ + * $Date: 19/07/2005 21:33:07 $ + * $Revision: 1 $ + * $Log: Point3D.java,v $ + * Revision 1 19/07/2005 21:33:07 luisantonioa + * Added copyright notice + * + * + * 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 2, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * http://www.gnu.org/copyleft/gpl.html + */ +package net.sf.l2j.util; + +import java.io.Serializable; + +import net.sf.l2j.gameserver.model.waypoint.WayPointNode; + +/** + * This class ... + * + * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $ + */ +public class Point3D implements Serializable +{ + /** + * Comment for serialVersionUID + */ + private static final long serialVersionUID = 4638345252031872576L; + private int x, y, z; + + public Point3D(int pX, int pY, int pZ) + { + this.x = pX; + this.y = pY; + this.z = pZ; + } + + public Point3D(int pX, int pY) + { + this.x = pX; + this.y = pY; + this.z = 0; + } + + /** + * @param worldPosition + */ + public Point3D(Point3D worldPosition) + { + synchronized(worldPosition) { + this.x = worldPosition.getX(); + this.y = worldPosition.getY(); + this.z = worldPosition.getZ(); + } + } + + public static Point3D getPosition(WayPointNode node) + { + int x1,y1,z1; + synchronized(node) { + x1 = node.getX(); + y1 = node.getY(); + z1 = node.getZ(); + } + return new Point3D(x1,y1,z1); + } + + public void setTo(Point3D point) + { + int x1,y1,z1; + synchronized (point){ + x1=point.getX(); + y1=point.getY(); + z1=point.getZ(); + } + synchronized (this) { + this.x = x1; + this.y = y1; + this.z = z1; + } + + } + + public synchronized String toString() { return "(" + x + ", " + y + ", " + z + ")"; } + public synchronized int hashCode() { return x^y^z; } + + public boolean equals(Object o) + { + if (o instanceof Point3D) + { + boolean r; + Point3D point3D = (Point3D) o; + synchronized(point3D) { + synchronized(this) { + r=(point3D.getX() == x) && (point3D.getY()==y) && (point3D.getZ()==z); + } + } + return r; + } + return false; + } + + public long distanceSquaredTo(Point3D point) + { + long dx; + long dy; + synchronized(point) { + synchronized(this) { + dx = x - point.getX(); + dy = y - point.getY(); + } + } + return (dx * dx) + (dy * dy); + } + + public static long distanceSquared(Point3D point1, Point3D point2) + { + long dx; + long dy; + + synchronized(point1) { + synchronized(point2) { + dx = point1.getX() - point2.getX(); + dy = point1.getY() - point2.getY(); + } + } + return (dx * dx) + (dy * dy); + } + + public static boolean distanceLessThan(Point3D point1, Point3D point2, double distance) + { + long dx; + long dy; + + synchronized(point1) { + synchronized(point2) { + dx = point1.getX() - point2.getX(); + dy = point1.getY() - point2.getY(); + } + } + return (dx * dx) + (dy * dy) < distance * distance; + } + + public synchronized int getX() { return x; } + public synchronized int getY() { return y; } + public synchronized int getZ() { return z; } + + public synchronized void setX(int pX) { x=pX; } + public synchronized void setY(int pY) { y=pY; } + public synchronized void setZ(int pZ) { z=pZ; } + +}