Pauler

clanwarzone l2jpes

Sep 2nd, 2013
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 314.50 KB | None | 0 0
  1. /*
  2.  * This program is free software: you can redistribute it and/or modify it under
  3.  * the terms of the GNU General Public License as published by the Free Software
  4.  * Foundation, either version 3 of the License, or (at your option) any later
  5.  * version.
  6.  *
  7.  * This program is distributed in the hope that it will be useful, but WITHOUT
  8.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9.  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10.  * details.
  11.  *
  12.  * You should have received a copy of the GNU General Public License along with
  13.  * this program. If not, see <http://www.gnu.org/licenses/>.
  14.  */
  15. package com.l2jpes.gameserver.model.actor.instance;
  16.  
  17. import java.net.InetAddress;
  18. import java.sql.Connection;
  19. import java.sql.PreparedStatement;
  20. import java.sql.ResultSet;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.Calendar;
  24. import java.util.Collection;
  25. import java.util.HashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Set;
  29. import java.util.concurrent.CopyOnWriteArraySet;
  30. import java.util.concurrent.Future;
  31. import java.util.concurrent.ScheduledFuture;
  32. import java.util.concurrent.TimeUnit;
  33. import java.util.concurrent.atomic.AtomicInteger;
  34. import java.util.concurrent.locks.ReentrantLock;
  35. import java.util.logging.Level;
  36.  
  37. import javolution.util.FastMap;
  38.  
  39. import com.l2jpes.Config;
  40. import com.l2jpes.L2DatabaseFactory;
  41. import com.l2jpes.gameserver.GameTimeController;
  42. import com.l2jpes.gameserver.GeoData;
  43. import com.l2jpes.gameserver.ItemsAutoDestroy;
  44. import com.l2jpes.gameserver.LoginServerThread;
  45. import com.l2jpes.gameserver.RecipeController;
  46. import com.l2jpes.gameserver.SevenSigns;
  47. import com.l2jpes.gameserver.SevenSignsFestival;
  48. import com.l2jpes.gameserver.ThreadPoolManager;
  49. import com.l2jpes.gameserver.ai.CtrlIntention;
  50. import com.l2jpes.gameserver.ai.L2CharacterAI;
  51. import com.l2jpes.gameserver.ai.L2PlayerAI;
  52. import com.l2jpes.gameserver.ai.L2SummonAI;
  53. import com.l2jpes.gameserver.communitybbs.BB.Forum;
  54. import com.l2jpes.gameserver.communitybbs.Manager.ForumsBBSManager;
  55. import com.l2jpes.gameserver.datatables.GmListTable;
  56. import com.l2jpes.gameserver.datatables.sql.CharNameTable;
  57. import com.l2jpes.gameserver.datatables.sql.ClanTable;
  58. import com.l2jpes.gameserver.datatables.xml.AccessLevels;
  59. import com.l2jpes.gameserver.datatables.xml.CharTemplateTable;
  60. import com.l2jpes.gameserver.datatables.xml.FishTable;
  61. import com.l2jpes.gameserver.datatables.xml.HennaTable;
  62. import com.l2jpes.gameserver.datatables.xml.ItemTable;
  63. import com.l2jpes.gameserver.datatables.xml.MapRegionTable;
  64. import com.l2jpes.gameserver.datatables.xml.PetDataTable;
  65. import com.l2jpes.gameserver.datatables.xml.SkillTable;
  66. import com.l2jpes.gameserver.datatables.xml.SkillTable.FrequentSkill;
  67. import com.l2jpes.gameserver.datatables.xml.SkillTreeTable;
  68. import com.l2jpes.gameserver.events.EventCommons;
  69. import com.l2jpes.gameserver.events.EventTeam;
  70. import com.l2jpes.gameserver.handler.ItemHandler;
  71. import com.l2jpes.gameserver.handler.impl.IItemHandler;
  72. import com.l2jpes.gameserver.instancemanager.CastleManager;
  73. import com.l2jpes.gameserver.instancemanager.CoupleManager;
  74. import com.l2jpes.gameserver.instancemanager.CursedWeaponsManager;
  75. import com.l2jpes.gameserver.instancemanager.DimensionalRiftManager;
  76. import com.l2jpes.gameserver.instancemanager.DuelManager;
  77. import com.l2jpes.gameserver.instancemanager.GrandBossManager;
  78. import com.l2jpes.gameserver.instancemanager.ItemsOnGroundManager;
  79. import com.l2jpes.gameserver.instancemanager.QuestManager;
  80. import com.l2jpes.gameserver.instancemanager.SiegeManager;
  81. import com.l2jpes.gameserver.model.BlockList;
  82. import com.l2jpes.gameserver.model.CharEffectList;
  83. import com.l2jpes.gameserver.model.FishData;
  84. import com.l2jpes.gameserver.model.L2AccessLevel;
  85. import com.l2jpes.gameserver.model.L2Clan;
  86. import com.l2jpes.gameserver.model.L2ClanMember;
  87. import com.l2jpes.gameserver.model.L2Effect;
  88. import com.l2jpes.gameserver.model.L2Fishing;
  89. import com.l2jpes.gameserver.model.L2ItemInstance;
  90. import com.l2jpes.gameserver.model.L2Macro;
  91. import com.l2jpes.gameserver.model.L2ManufactureList;
  92. import com.l2jpes.gameserver.model.L2Object;
  93. import com.l2jpes.gameserver.model.L2Party;
  94. import com.l2jpes.gameserver.model.L2PetData;
  95. import com.l2jpes.gameserver.model.L2PetData.L2PetLevelData;
  96. import com.l2jpes.gameserver.model.L2Radar;
  97. import com.l2jpes.gameserver.model.L2RecipeList;
  98. import com.l2jpes.gameserver.model.L2Request;
  99. import com.l2jpes.gameserver.model.L2ShortCut;
  100. import com.l2jpes.gameserver.model.L2Skill;
  101. import com.l2jpes.gameserver.model.L2Skill.SkillTargetType;
  102. import com.l2jpes.gameserver.model.L2SkillLearn;
  103. import com.l2jpes.gameserver.model.L2World;
  104. import com.l2jpes.gameserver.model.L2WorldRegion;
  105. import com.l2jpes.gameserver.model.Location;
  106. import com.l2jpes.gameserver.model.MacroList;
  107. import com.l2jpes.gameserver.model.PartyMatchRoom;
  108. import com.l2jpes.gameserver.model.PartyMatchRoomList;
  109. import com.l2jpes.gameserver.model.PartyMatchWaitingList;
  110. import com.l2jpes.gameserver.model.ShortCuts;
  111. import com.l2jpes.gameserver.model.ShotType;
  112. import com.l2jpes.gameserver.model.TradeList;
  113. import com.l2jpes.gameserver.model.actor.L2Attackable;
  114. import com.l2jpes.gameserver.model.actor.L2Character;
  115. import com.l2jpes.gameserver.model.actor.L2Npc;
  116. import com.l2jpes.gameserver.model.actor.L2Playable;
  117. import com.l2jpes.gameserver.model.actor.L2Summon;
  118. import com.l2jpes.gameserver.model.actor.L2Vehicle;
  119. import com.l2jpes.gameserver.model.actor.appearance.PcAppearance;
  120. import com.l2jpes.gameserver.model.actor.knownlist.PlayerKnownList;
  121. import com.l2jpes.gameserver.model.actor.position.PlayerPosition;
  122. import com.l2jpes.gameserver.model.actor.stat.PlayerStat;
  123. import com.l2jpes.gameserver.model.actor.status.PlayerStatus;
  124. import com.l2jpes.gameserver.model.base.ClassId;
  125. import com.l2jpes.gameserver.model.base.ClassLevel;
  126. import com.l2jpes.gameserver.model.base.Experience;
  127. import com.l2jpes.gameserver.model.base.PlayerClass;
  128. import com.l2jpes.gameserver.model.base.Race;
  129. import com.l2jpes.gameserver.model.base.SubClass;
  130. import com.l2jpes.gameserver.model.entity.Castle;
  131. import com.l2jpes.gameserver.model.entity.Duel;
  132. import com.l2jpes.gameserver.model.entity.Hero;
  133. import com.l2jpes.gameserver.model.entity.Siege;
  134. import com.l2jpes.gameserver.model.itemcontainer.Inventory;
  135. import com.l2jpes.gameserver.model.itemcontainer.ItemContainer;
  136. import com.l2jpes.gameserver.model.itemcontainer.PetInventory;
  137. import com.l2jpes.gameserver.model.itemcontainer.PlayerFreight;
  138. import com.l2jpes.gameserver.model.itemcontainer.PlayerInventory;
  139. import com.l2jpes.gameserver.model.itemcontainer.PlayerWarehouse;
  140. import com.l2jpes.gameserver.model.olympiad.OlympiadGameManager;
  141. import com.l2jpes.gameserver.model.olympiad.OlympiadGameTask;
  142. import com.l2jpes.gameserver.model.olympiad.OlympiadManager;
  143. import com.l2jpes.gameserver.model.quest.Quest;
  144. import com.l2jpes.gameserver.model.quest.QuestEventType;
  145. import com.l2jpes.gameserver.model.quest.QuestState;
  146. import com.l2jpes.gameserver.model.zone.type.L2BossZone;
  147. import com.l2jpes.gameserver.network.L2GameClient;
  148. import com.l2jpes.gameserver.network.SystemMessageId;
  149. import com.l2jpes.gameserver.network.serverpackets.AbstractNpcInfo;
  150. import com.l2jpes.gameserver.network.serverpackets.ActionFailed;
  151. import com.l2jpes.gameserver.network.serverpackets.ChangeWaitType;
  152. import com.l2jpes.gameserver.network.serverpackets.CharInfo;
  153. import com.l2jpes.gameserver.network.serverpackets.ConfirmDlg;
  154. import com.l2jpes.gameserver.network.serverpackets.EtcStatusUpdate;
  155. import com.l2jpes.gameserver.network.serverpackets.ExAutoSoulShot;
  156. import com.l2jpes.gameserver.network.serverpackets.ExDuelUpdateUserInfo;
  157. import com.l2jpes.gameserver.network.serverpackets.ExFishingEnd;
  158. import com.l2jpes.gameserver.network.serverpackets.ExFishingStart;
  159. import com.l2jpes.gameserver.network.serverpackets.ExOlympiadMode;
  160. import com.l2jpes.gameserver.network.serverpackets.ExSetCompassZoneCode;
  161. import com.l2jpes.gameserver.network.serverpackets.ExStorageMaxCount;
  162. import com.l2jpes.gameserver.network.serverpackets.FriendList;
  163. import com.l2jpes.gameserver.network.serverpackets.GetOnVehicle;
  164. import com.l2jpes.gameserver.network.serverpackets.HennaInfo;
  165. import com.l2jpes.gameserver.network.serverpackets.InventoryUpdate;
  166. import com.l2jpes.gameserver.network.serverpackets.ItemList;
  167. import com.l2jpes.gameserver.network.serverpackets.L2GameServerPacket;
  168. import com.l2jpes.gameserver.network.serverpackets.LeaveWorld;
  169. import com.l2jpes.gameserver.network.serverpackets.MagicSkillUse;
  170. import com.l2jpes.gameserver.network.serverpackets.MoveToPawn;
  171. import com.l2jpes.gameserver.network.serverpackets.MyTargetSelected;
  172. import com.l2jpes.gameserver.network.serverpackets.NpcHtmlMessage;
  173. import com.l2jpes.gameserver.network.serverpackets.ObservationMode;
  174. import com.l2jpes.gameserver.network.serverpackets.ObservationReturn;
  175. import com.l2jpes.gameserver.network.serverpackets.PartySmallWindowUpdate;
  176. import com.l2jpes.gameserver.network.serverpackets.PetInventoryUpdate;
  177. import com.l2jpes.gameserver.network.serverpackets.PlaySound;
  178. import com.l2jpes.gameserver.network.serverpackets.PledgeShowMemberListDelete;
  179. import com.l2jpes.gameserver.network.serverpackets.PledgeShowMemberListUpdate;
  180. import com.l2jpes.gameserver.network.serverpackets.PrivateStoreListBuy;
  181. import com.l2jpes.gameserver.network.serverpackets.PrivateStoreListSell;
  182. import com.l2jpes.gameserver.network.serverpackets.PrivateStoreManageListBuy;
  183. import com.l2jpes.gameserver.network.serverpackets.PrivateStoreManageListSell;
  184. import com.l2jpes.gameserver.network.serverpackets.PrivateStoreMsgBuy;
  185. import com.l2jpes.gameserver.network.serverpackets.PrivateStoreMsgSell;
  186. import com.l2jpes.gameserver.network.serverpackets.RecipeShopManageList;
  187. import com.l2jpes.gameserver.network.serverpackets.RecipeShopMsg;
  188. import com.l2jpes.gameserver.network.serverpackets.RecipeShopSellList;
  189. import com.l2jpes.gameserver.network.serverpackets.RelationChanged;
  190. import com.l2jpes.gameserver.network.serverpackets.Ride;
  191. import com.l2jpes.gameserver.network.serverpackets.SendTradeDone;
  192. import com.l2jpes.gameserver.network.serverpackets.ServerClose;
  193. import com.l2jpes.gameserver.network.serverpackets.SetupGauge;
  194. import com.l2jpes.gameserver.network.serverpackets.ShortBuffStatusUpdate;
  195. import com.l2jpes.gameserver.network.serverpackets.ShortCutInit;
  196. import com.l2jpes.gameserver.network.serverpackets.SkillCoolTime;
  197. import com.l2jpes.gameserver.network.serverpackets.SkillList;
  198. import com.l2jpes.gameserver.network.serverpackets.Snoop;
  199. import com.l2jpes.gameserver.network.serverpackets.SocialAction;
  200. import com.l2jpes.gameserver.network.serverpackets.StatusUpdate;
  201. import com.l2jpes.gameserver.network.serverpackets.StopMove;
  202. import com.l2jpes.gameserver.network.serverpackets.SystemMessage;
  203. import com.l2jpes.gameserver.network.serverpackets.TargetSelected;
  204. import com.l2jpes.gameserver.network.serverpackets.TargetUnselected;
  205. import com.l2jpes.gameserver.network.serverpackets.TradePressOtherOk;
  206. import com.l2jpes.gameserver.network.serverpackets.TradePressOwnOk;
  207. import com.l2jpes.gameserver.network.serverpackets.TradeStart;
  208. import com.l2jpes.gameserver.network.serverpackets.UserInfo;
  209. import com.l2jpes.gameserver.plugin.Plugin;
  210. import com.l2jpes.gameserver.plugin.PluginListener;
  211. import com.l2jpes.gameserver.plugin.PluginLoader;
  212. import com.l2jpes.gameserver.skills.Env;
  213. import com.l2jpes.gameserver.skills.Formulas;
  214. import com.l2jpes.gameserver.skills.Stats;
  215. import com.l2jpes.gameserver.skills.effects.EffectTemplate;
  216. import com.l2jpes.gameserver.skills.funcs.FuncBowAtkRange;
  217. import com.l2jpes.gameserver.skills.funcs.FuncHennaCON;
  218. import com.l2jpes.gameserver.skills.funcs.FuncHennaDEX;
  219. import com.l2jpes.gameserver.skills.funcs.FuncHennaINT;
  220. import com.l2jpes.gameserver.skills.funcs.FuncHennaMEN;
  221. import com.l2jpes.gameserver.skills.funcs.FuncHennaSTR;
  222. import com.l2jpes.gameserver.skills.funcs.FuncHennaWIT;
  223. import com.l2jpes.gameserver.skills.funcs.FuncMaxCpAdd;
  224. import com.l2jpes.gameserver.skills.funcs.FuncMaxCpMul;
  225. import com.l2jpes.gameserver.skills.funcs.FuncMaxHpAdd;
  226. import com.l2jpes.gameserver.skills.funcs.FuncMaxMpAdd;
  227. import com.l2jpes.gameserver.skills.l2skills.L2SkillSiegeFlag;
  228. import com.l2jpes.gameserver.skills.l2skills.L2SkillSummon;
  229. import com.l2jpes.gameserver.taskmanager.AttackStanceTaskManager;
  230. import com.l2jpes.gameserver.taskmanager.PvpFlagTaskManager;
  231. import com.l2jpes.gameserver.taskmanager.TakeBreakTaskManager;
  232. import com.l2jpes.gameserver.taskmanager.WaterTaskManager;
  233. import com.l2jpes.gameserver.templates.chars.L2PlayerTemplate;
  234. import com.l2jpes.gameserver.templates.item.L2ActionType;
  235. import com.l2jpes.gameserver.templates.item.L2Armor;
  236. import com.l2jpes.gameserver.templates.item.L2ArmorType;
  237. import com.l2jpes.gameserver.templates.item.L2EtcItemType;
  238. import com.l2jpes.gameserver.templates.item.L2Henna;
  239. import com.l2jpes.gameserver.templates.item.L2Item;
  240. import com.l2jpes.gameserver.templates.item.L2Weapon;
  241. import com.l2jpes.gameserver.templates.item.L2WeaponType;
  242. import com.l2jpes.gameserver.templates.skills.L2EffectType;
  243. import com.l2jpes.gameserver.templates.skills.L2SkillType;
  244. import com.l2jpes.util.Broadcast;
  245. import com.l2jpes.util.Point3D;
  246. import com.l2jpes.util.Rnd;
  247. import com.l2jpes.util.Util;
  248. import com.l2jpes.util.floodprotector.FloodProtectors;
  249.  
  250. /**
  251.  * This class represents all player characters in the world. There is always a client-thread
  252.  * connected to this (except if a player-store is activated upon logout).
  253.  */
  254. public final class L2PlayerInstance extends L2Playable
  255. {
  256.     private EventTeam _eventTeam = null;
  257.    
  258.     public EventTeam getEventTeam()
  259.     {
  260.         return _eventTeam;
  261.     }
  262.    
  263.     public void setEventTeam(EventTeam val)
  264.     {
  265.         _eventTeam = val;
  266.     }
  267.    
  268.     // Character Skill SQL String Definitions:
  269.     private static final String RESTORE_SKILLS_FOR_CHAR =
  270.             "SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? AND class_index=?";
  271.     private static final String ADD_NEW_SKILL =
  272.             "INSERT INTO character_skills (char_obj_id,skill_id,skill_level,class_index) VALUES (?,?,?,?)";
  273.     private static final String UPDATE_CHARACTER_SKILL_LEVEL =
  274.             "UPDATE character_skills SET skill_level=? WHERE skill_id=? AND char_obj_id=? AND class_index=?";
  275.     private static final String DELETE_SKILL_FROM_CHAR =
  276.             "DELETE FROM character_skills WHERE skill_id=? AND char_obj_id=? AND class_index=?";
  277.     private static final String DELETE_CHAR_SKILLS =
  278.             "DELETE FROM character_skills WHERE char_obj_id=? AND class_index=?";
  279.    
  280.     // Character Skill Save SQL String Definitions:
  281.     private static final String ADD_SKILL_SAVE =
  282.             "INSERT INTO character_skills_save (char_obj_id,skill_id,skill_level,effect_count,effect_cur_time,reuse_delay,systime,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?,?)";
  283.     private static final String RESTORE_SKILL_SAVE =
  284.             "SELECT skill_id,skill_level,effect_count,effect_cur_time, reuse_delay, systime, restore_type FROM character_skills_save WHERE char_obj_id=? AND class_index=? ORDER BY buff_index ASC";
  285.     private static final String DELETE_SKILL_SAVE =
  286.             "DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=?";
  287.    
  288.     // Character SQL String Definitions:
  289.     private static final String INSERT_CHARACTER =
  290.             "INSERT INTO characters (account_name,obj_Id,char_name,level,maxHp,curHp,maxCp,curCp,maxMp,curMp,face,hairStyle,hairColor,sex,exp,sp,karma,pvpkills,pkkills,clanid,race,classid,deletetime,cancraft,title,accesslevel,online,isin7sdungeon,clan_privs,wantspeace,base_class,nobless,power_grade,last_recom_date) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
  291.     private static final String UPDATE_CHARACTER =
  292.             "UPDATE characters SET level=?,maxHp=?,curHp=?,maxCp=?,curCp=?,maxMp=?,curMp=?,face=?,hairStyle=?,hairColor=?,sex=?,heading=?,x=?,y=?,z=?,exp=?,expBeforeDeath=?,sp=?,karma=?,pvpkills=?,pkkills=?,rec_have=?,rec_left=?,clanid=?,race=?,classid=?,deletetime=?,title=?,accesslevel=?,online=?,isin7sdungeon=?,clan_privs=?,wantspeace=?,base_class=?,onlinetime=?,punish_level=?,punish_timer=?,nobless=?,power_grade=?,subpledge=?,last_recom_date=?,lvl_joined_academy=?,apprentice=?,sponsor=?,varka_ketra_ally=?,clan_join_expiry_time=?,clan_create_expiry_time=?,char_name=?,death_penalty_level=? WHERE obj_id=?";
  293.     private static final String RESTORE_CHARACTER =
  294.             "SELECT account_name, obj_Id, char_name, level, maxHp, curHp, maxCp, curCp, maxMp, curMp, face, hairStyle, hairColor, sex, heading, x, y, z, exp, expBeforeDeath, sp, karma, pvpkills, pkkills, clanid, race, classid, deletetime, cancraft, title, rec_have, rec_left, accesslevel, online, char_slot, lastAccess, clan_privs, wantspeace, base_class, onlinetime, isin7sdungeon, punish_level, punish_timer, nobless, power_grade, subpledge, last_recom_date, lvl_joined_academy, apprentice, sponsor, varka_ketra_ally,clan_join_expiry_time,clan_create_expiry_time,death_penalty_level FROM characters WHERE obj_id=?";
  295.    
  296.     // Character Subclass SQL String Definitions:
  297.     private static final String RESTORE_CHAR_SUBCLASSES =
  298.             "SELECT class_id,exp,sp,level,class_index FROM character_subclasses WHERE char_obj_id=? ORDER BY class_index ASC";
  299.     private static final String ADD_CHAR_SUBCLASS =
  300.             "INSERT INTO character_subclasses (char_obj_id,class_id,exp,sp,level,class_index) VALUES (?,?,?,?,?,?)";
  301.     private static final String UPDATE_CHAR_SUBCLASS =
  302.             "UPDATE character_subclasses SET exp=?,sp=?,level=?,class_id=? WHERE char_obj_id=? AND class_index =?";
  303.     private static final String DELETE_CHAR_SUBCLASS =
  304.             "DELETE FROM character_subclasses WHERE char_obj_id=? AND class_index=?";
  305.    
  306.     private static final String RESTORE_CHAR_HENNAS =
  307.             "SELECT slot,symbol_id FROM character_hennas WHERE char_obj_id=? AND class_index=?";
  308.     private static final String ADD_CHAR_HENNA =
  309.             "INSERT INTO character_hennas (char_obj_id,symbol_id,slot,class_index) VALUES (?,?,?,?)";
  310.     private static final String DELETE_CHAR_HENNA =
  311.             "DELETE FROM character_hennas WHERE char_obj_id=? AND slot=? AND class_index=?";
  312.     private static final String DELETE_CHAR_HENNAS =
  313.             "DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=?";
  314.     private static final String DELETE_CHAR_SHORTCUTS =
  315.             "DELETE FROM character_shortcuts WHERE char_obj_id=? AND class_index=?";
  316.    
  317.     private static final String RESTORE_CHAR_RECOMS =
  318.             "SELECT char_id,target_id FROM character_recommends WHERE char_id=?";
  319.     private static final String ADD_CHAR_RECOM = "INSERT INTO character_recommends (char_id,target_id) VALUES (?,?)";
  320.     private static final String DELETE_CHAR_RECOMS = "DELETE FROM character_recommends WHERE char_id=?";
  321.    
  322.     private static final String UPDATE_NOBLESS = "UPDATE characters SET nobless=? WHERE obj_Id=?";
  323.    
  324.     public static final int REQUEST_TIMEOUT = 15;
  325.     public static final int STORE_PRIVATE_NONE = 0;
  326.     public static final int STORE_PRIVATE_SELL = 1;
  327.     public static final int STORE_PRIVATE_BUY = 3;
  328.     public static final int STORE_PRIVATE_MANUFACTURE = 5;
  329.     public static final int STORE_PRIVATE_PACKAGE_SELL = 8;
  330.    
  331.     /** The table containing all minimum level needed for each Expertise (None, D, C, B, A, S) */
  332.     private static final int[] EXPERTISE_LEVELS = { SkillTreeTable.getInstance().getExpertiseLevel(0), // NONE
  333.             SkillTreeTable.getInstance().getExpertiseLevel(1), // D
  334.             SkillTreeTable.getInstance().getExpertiseLevel(2), // C
  335.             SkillTreeTable.getInstance().getExpertiseLevel(3), // B
  336.             SkillTreeTable.getInstance().getExpertiseLevel(4), // A
  337.             SkillTreeTable.getInstance().getExpertiseLevel(5), // S
  338.     };
  339.    
  340.     private static final int[] COMMON_CRAFT_LEVELS = { 5, 20, 28, 36, 43, 49, 55, 62 };
  341.    
  342.     public class AIAccessor extends L2Character.AIAccessor
  343.     {
  344.         protected AIAccessor()
  345.         {
  346.            
  347.         }
  348.        
  349.         public L2PlayerInstance getPlayer()
  350.         {
  351.             return L2PlayerInstance.this;
  352.         }
  353.        
  354.         public void doPickupItem(L2Object object)
  355.         {
  356.             L2PlayerInstance.this.doPickupItem(object);
  357.            
  358.             // Schedule a paralyzed task to wait for the animation to finish
  359.             ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
  360.                 @Override
  361.                 public void run()
  362.                 {
  363.                     setIsParalyzed(false);
  364.                 }
  365.             }, 500);
  366.             setIsParalyzed(true);
  367.         }
  368.        
  369.         public void doInteract(L2Character target)
  370.         {
  371.             L2PlayerInstance.this.doInteract(target);
  372.         }
  373.        
  374.         @Override
  375.         public void doAttack(L2Character target)
  376.         {
  377.             super.doAttack(target);
  378.            
  379.             // cancel the recent fake-death protection instantly if the player attacks or casts spells
  380.             getPlayer().setRecentFakeDeath(false);
  381.         }
  382.        
  383.         @Override
  384.         public void doCast(L2Skill skill)
  385.         {
  386.             super.doCast(skill);
  387.            
  388.             // cancel the recent fake-death protection instantly if the player attacks or casts spells
  389.             getPlayer().setRecentFakeDeath(false);
  390.         }
  391.     }
  392.    
  393.     private L2GameClient _client;
  394.    
  395.     private String _accountName;
  396.     private long _deleteTimer;
  397.    
  398.     private boolean _isOnline = false;
  399.     private long _onlineTime;
  400.     private long _onlineBeginTime;
  401.     private long _lastAccess;
  402.     private long _uptime;
  403.    
  404.     private final ReentrantLock _subclassLock = new ReentrantLock();
  405.     protected int _baseClass;
  406.     protected int _activeClass;
  407.     protected int _classIndex = 0;
  408.     private Map<Integer, SubClass> _subClasses;
  409.    
  410.     private PcAppearance _appearance;
  411.     private int _charId = 0x00030b7a;
  412.    
  413.     private long _expBeforeDeath;
  414.     private int _karma;
  415.     private int _pvpKills;
  416.     private int _pkKills;
  417.     private byte _pvpFlag;
  418.     private byte _siegeState = 0;
  419.     private int _curWeightPenalty = 0;
  420.    
  421.     private int _lastCompassZone; // the last compass zone update send to the client
  422.    
  423.     private boolean _isInWater;
  424.     private boolean _isIn7sDungeon = false;
  425.    
  426.     private PunishLevel _punishLevel = PunishLevel.NONE;
  427.     private long _punishTimer = 0;
  428.     private ScheduledFuture<?> _punishTask;
  429.    
  430.     public enum PunishLevel
  431.     {
  432.         NONE(0, ""),
  433.         CHAT(1, "chat banned"),
  434.         JAIL(2, "jailed"),
  435.         CHAR(3, "banned"),
  436.         ACC(4, "banned");
  437.        
  438.         private final int punValue;
  439.         private final String punString;
  440.        
  441.         PunishLevel(int value, String string)
  442.         {
  443.             punValue = value;
  444.             punString = string;
  445.         }
  446.        
  447.         public int value()
  448.         {
  449.             return punValue;
  450.         }
  451.        
  452.         public String string()
  453.         {
  454.             return punString;
  455.         }
  456.     }
  457.    
  458.     /** Olympiad */
  459.     private boolean _inOlympiadMode = false;
  460.     private boolean _OlympiadStart = false;
  461.     private int _olympiadGameId = -1;
  462.     private int _olympiadSide = -1;
  463.    
  464.     /** Duel */
  465.     private boolean _isInDuel = false;
  466.     private int _duelState = Duel.DUELSTATE_NODUEL;
  467.     private int _duelId = 0;
  468.     private SystemMessageId _noDuelReason = SystemMessageId.THERE_IS_NO_OPPONENT_TO_RECEIVE_YOUR_CHALLENGE_FOR_A_DUEL;
  469.    
  470.     /** Boat */
  471.     private L2Vehicle _vehicle = null;
  472.     private Point3D _inVehiclePosition;
  473.    
  474.     public ScheduledFuture<?> _taskforfish;
  475.    
  476.     private int _mountType;
  477.     private int _mountNpcId;
  478.     private int _mountLevel;
  479.     private int _mountObjectID = 0;
  480.    
  481.     public int _telemode = 0;
  482.     private boolean _inCrystallize;
  483.     private boolean _inCraftMode;
  484.    
  485.     /** The table containing all L2RecipeList of the L2PlayerInstance */
  486.     private final Map<Integer, L2RecipeList> _dwarvenRecipeBook = new HashMap<>();
  487.     private final Map<Integer, L2RecipeList> _commonRecipeBook = new HashMap<>();
  488.    
  489.     /** True if the L2PlayerInstance is sitting */
  490.     private boolean _waitTypeSitting;
  491.    
  492.     /** Location before entering Observer Mode */
  493.     private int _lastX;
  494.     private int _lastY;
  495.     private int _lastZ;
  496.     private boolean _observerMode = false;
  497.    
  498.     /** Stored from last ValidatePosition **/
  499.     private final Point3D _lastServerPosition = new Point3D(0, 0, 0);
  500.    
  501.     private int _recomHave; // how much I was recommended by others
  502.     private int _recomLeft; // how many recomendations I can give to others
  503.     private long _lastRecomUpdate;
  504.     private final List<Integer> _recomChars = new ArrayList<>();
  505.    
  506.     private final PlayerInventory _inventory = new PlayerInventory(this);
  507.     private PlayerWarehouse _warehouse;
  508.     private PlayerFreight _freight;
  509.     private List<PlayerFreight> _depositedFreight;
  510.    
  511.     /**
  512.      * The Private Store type of the L2PlayerInstance (STORE_PRIVATE_NONE=0, STORE_PRIVATE_SELL=1,
  513.      * sellmanage=2, STORE_PRIVATE_BUY=3, buymanage=4, STORE_PRIVATE_MANUFACTURE=5)
  514.      */
  515.     private int _privatestore;
  516.    
  517.     private TradeList _activeTradeList;
  518.     private ItemContainer _activeWarehouse;
  519.     private L2ManufactureList _createList;
  520.     private TradeList _sellList;
  521.     private TradeList _buyList;
  522.    
  523.     private boolean _noble = false;
  524.     private boolean _hero = false;
  525.    
  526.     /** The L2Npc corresponding to the current folk the player is talking with. */
  527.     private L2Npc _currentFolkNpc = null;
  528.    
  529.     /** Last NPC Id talked on a quest */
  530.     private int _questNpcObject = 0;
  531.    
  532.     /** The list containing all Quests began by the L2PlayerInstance */
  533.     private final List<QuestState> _quests = new ArrayList<>();
  534.    
  535.     /**
  536.      * List of all QuestState instance that needs to be notified of this L2PlayerInstance's or its
  537.      * pet's death
  538.      */
  539.     private final List<QuestState> _notifyQuestOfDeathList = new ArrayList<>();
  540.    
  541.     /** The list containing all shortCuts of this L2PlayerInstance */
  542.     private final ShortCuts _shortCuts = new ShortCuts(this);
  543.    
  544.     /** The list containing all macroses of this L2PlayerInstance */
  545.     private final MacroList _macroses = new MacroList(this);
  546.    
  547.     private final List<L2PlayerInstance> _snoopListener = new ArrayList<>();
  548.     private final List<L2PlayerInstance> _snoopedPlayer = new ArrayList<>();
  549.    
  550.     private ClassId _skillLearningClassId;
  551.    
  552.     // hennas
  553.     private final L2Henna[] _henna = new L2Henna[3];
  554.     private int _hennaSTR;
  555.     private int _hennaINT;
  556.     private int _hennaDEX;
  557.     private int _hennaMEN;
  558.     private int _hennaWIT;
  559.     private int _hennaCON;
  560.    
  561.     /** The L2Summon of the L2PlayerInstance */
  562.     private L2Summon _summon = null;
  563.     // apparently, a L2PlayerInstance CAN have both a summon AND a tamed beast at the same time!!
  564.     private L2TamedBeastInstance _tamedBeast = null;
  565.    
  566.     // client radar
  567.     // TODO: This needs to be better integrated and saved/loaded
  568.     private L2Radar _radar;
  569.    
  570.     // these values are only stored temporarily
  571.     private int _partyroom = 0;
  572.    
  573.     // Clan related attributes
  574.     /** The Clan Identifier of the L2PlayerInstance */
  575.     private int _clanId;
  576.    
  577.     /** The Clan object of the L2PlayerInstance */
  578.     private L2Clan _clan;
  579.    
  580.     /** Apprentice and Sponsor IDs */
  581.     private int _apprentice = 0;
  582.     private int _sponsor = 0;
  583.    
  584.     private long _clanJoinExpiryTime;
  585.     private long _clanCreateExpiryTime;
  586.    
  587.     private int _powerGrade = 0;
  588.     private int _clanPrivileges = 0;
  589.    
  590.     /** L2PlayerInstance's pledge class (knight, Baron, etc.) */
  591.     private int _pledgeClass = 0;
  592.     private int _pledgeType = 0;
  593.    
  594.     /** Level at which the player joined the clan as an academy member */
  595.     private int _lvlJoinedAcademy = 0;
  596.    
  597.     private int _wantsPeace = 0;
  598.    
  599.     // Death Penalty Buff Level
  600.     private int _deathPenaltyBuffLevel = 0;
  601.    
  602.     // charges
  603.     private final AtomicInteger _charges = new AtomicInteger();
  604.     private ScheduledFuture<?> _chargeTask = null;
  605.    
  606.     // WorldPosition used by TARGET_SIGNET_GROUND
  607.     private Point3D _currentSkillWorldPosition;
  608.    
  609.     private L2AccessLevel _accessLevel;
  610.    
  611.     private boolean _messageRefusal = false; // message refusal mode
  612.     private boolean _tradeRefusal = false; // Trade refusal
  613.     private boolean _exchangeRefusal = false; // Exchange refusal
  614.    
  615.     private L2Party _party;
  616.    
  617.     // this is needed to find the inviting player for Party response
  618.     // there can only be one active party request at once
  619.     private L2PlayerInstance _activeRequester;
  620.     private long _requestExpireTime = 0;
  621.     private final L2Request _request = new L2Request(this);
  622.     private L2ItemInstance _arrowItem;
  623.    
  624.     // Used for protection after teleport
  625.     private long _protectEndTime = 0;
  626.    
  627.     public boolean isSpawnProtected()
  628.     {
  629.         return _protectEndTime > GameTimeController.getGameTicks();
  630.     }
  631.    
  632.     // protects a char from agro mobs when getting up from fake death
  633.     private long _recentFakeDeathEndTime = 0;
  634.     private boolean _isFakeDeath;
  635.    
  636.     /** The fists L2Weapon of the L2PlayerInstance (used when no weapon is equipped) */
  637.     private L2Weapon _fistsWeaponItem;
  638.    
  639.     private final Map<Integer, String> _chars = new HashMap<>();
  640.    
  641.     /** The current higher Expertise of the L2PlayerInstance (None=0, D=1, C=2, B=3, A=4, S=5) */
  642.     private int _expertiseIndex; // index in EXPERTISE_LEVELS
  643.     private int _expertisePenalty = 0;
  644.    
  645.     private L2ItemInstance _activeEnchantItem = null;
  646.    
  647.     protected boolean _inventoryDisable = false;
  648.    
  649.     protected Map<Integer, L2CubicInstance> _cubics = new FastMap<Integer, L2CubicInstance>().shared();
  650.    
  651.     /**
  652.      * Active shots. A FastSet variable would actually suffice but this was changed to fix threading
  653.      * stability...
  654.      */
  655.     protected Set<Integer> _activeSoulShots = new CopyOnWriteArraySet<>();
  656.    
  657.     private final int _loto[] = new int[5];
  658.     private final int _race[] = new int[2];
  659.    
  660.     private final BlockList _blockList = new BlockList(this);
  661.    
  662.     private int _team = 0;
  663.    
  664.     /**
  665.      * lvl of alliance with ketra orcs or varka silenos, used in quests and aggro checks [-5,-1]
  666.      * varka, 0 neutral, [1,5] ketra
  667.      */
  668.     private int _alliedVarkaKetra = 0;
  669.    
  670.     private Location _fishingLoc;
  671.     private L2ItemInstance _lure = null;
  672.     private L2Fishing _fishCombat;
  673.     private FishData _fish;
  674.    
  675.     /** Bypass validations */
  676.     private final List<String> _validBypass = new ArrayList<>();
  677.     private final List<String> _validBypass2 = new ArrayList<>();
  678.    
  679.     private Forum _forumMail;
  680.     private Forum _forumMemo;
  681.    
  682.     /** data for mounted pets */
  683.     private boolean _canFeed;
  684.     private L2PetData _data;
  685.     private L2PetLevelData _leveldata;
  686.     private int _controlItemId;
  687.     private int _curFeed;
  688.     protected Future<?> _mountFeedTask;
  689.     private ScheduledFuture<?> _dismountTask;
  690.    
  691.     private boolean _isInSiege;
  692.    
  693.     private SkillDat _currentSkill;
  694.     private SkillDat _currentPetSkill;
  695.     private SkillDat _queuedSkill;
  696.    
  697.     private int _cursedWeaponEquippedId = 0;
  698.    
  699.     private int _reviveRequested = 0;
  700.     private double _revivePower = 0;
  701.     private boolean _revivePet = false;
  702.    
  703.     private double _cpUpdateIncCheck = .0;
  704.     private double _cpUpdateDecCheck = .0;
  705.     private double _cpUpdateInterval = .0;
  706.     private double _mpUpdateIncCheck = .0;
  707.     private double _mpUpdateDecCheck = .0;
  708.     private double _mpUpdateInterval = .0;
  709.    
  710.     /** Char Coords from Client */
  711.     private volatile int _clientX;
  712.     private volatile int _clientY;
  713.     private volatile int _clientZ;
  714.     private volatile int _clientHeading;
  715.    
  716.     private int _mailPosition;
  717.    
  718.     // during fall, validation will be disabled for 10 s.
  719.     private static final int FALLING_VALIDATION_DELAY = 10000;
  720.     private volatile long _fallingTimestamp = 0;
  721.    
  722.     private int _herbstask = 0;
  723.    
  724.     /** Task for Herbs */
  725.     private class HerbTask implements Runnable
  726.     {
  727.         private final String _process;
  728.         private final int _itemId;
  729.         private final int _count;
  730.         private final L2Object _reference;
  731.         private final boolean _sendMessage;
  732.        
  733.         HerbTask(String process, int itemId, int count, L2Object reference, boolean sendMessage)
  734.         {
  735.             _process = process;
  736.             _itemId = itemId;
  737.             _count = count;
  738.             _reference = reference;
  739.             _sendMessage = sendMessage;
  740.         }
  741.        
  742.         @Override
  743.         public void run()
  744.         {
  745.             addItem(_process, _itemId, _count, _reference, _sendMessage);
  746.         }
  747.     }
  748.    
  749.     /** ShortBuff clearing Task */
  750.     ScheduledFuture<?> _shortBuffTask = null;
  751.     public int _shortBuffTaskSkillId = 0;
  752.    
  753.     protected class ShortBuffTask implements Runnable
  754.     {
  755.         @Override
  756.         public void run()
  757.         {
  758.             L2PlayerInstance.this.sendPacket(new ShortBuffStatusUpdate(0, 0, 0));
  759.             setShortBuffTaskSkillId(0);
  760.         }
  761.     }
  762.    
  763.     // L2JMOD Wedding
  764.     private boolean _married = false;
  765.     private int _coupleId = 0;
  766.     private boolean _marryrequest = false;
  767.     private int _requesterId = 0;
  768.    
  769.     /** Skill casting information (used to queue when several skills are cast in a short time) **/
  770.     public static class SkillDat
  771.     {
  772.         private final L2Skill _skill;
  773.         private final boolean _ctrlPressed;
  774.         private final boolean _shiftPressed;
  775.        
  776.         protected SkillDat(L2Skill skill, boolean ctrlPressed, boolean shiftPressed)
  777.         {
  778.             _skill = skill;
  779.             _ctrlPressed = ctrlPressed;
  780.             _shiftPressed = shiftPressed;
  781.         }
  782.        
  783.         public boolean isCtrlPressed()
  784.         {
  785.             return _ctrlPressed;
  786.         }
  787.        
  788.         public boolean isShiftPressed()
  789.         {
  790.             return _shiftPressed;
  791.         }
  792.        
  793.         public L2Skill getSkill()
  794.         {
  795.             return _skill;
  796.         }
  797.        
  798.         public int getSkillId()
  799.         {
  800.             return (getSkill() != null) ? getSkill().getId() : -1;
  801.         }
  802.     }
  803.    
  804.     // summon friend
  805.     private final SummonRequest _summonRequest = new SummonRequest();
  806.    
  807.     protected static class SummonRequest
  808.     {
  809.         private L2PlayerInstance _target = null;
  810.         private L2Skill _skill = null;
  811.        
  812.         public void setTarget(L2PlayerInstance destination, L2Skill skill)
  813.         {
  814.             _target = destination;
  815.             _skill = skill;
  816.         }
  817.        
  818.         public L2PlayerInstance getTarget()
  819.         {
  820.             return _target;
  821.         }
  822.        
  823.         public L2Skill getSkill()
  824.         {
  825.             return _skill;
  826.         }
  827.     }
  828.    
  829.     // open/close gates
  830.     private final GatesRequest _gatesRequest = new GatesRequest();
  831.    
  832.     protected static class GatesRequest
  833.     {
  834.         private L2DoorInstance _target = null;
  835.        
  836.         public void setTarget(L2DoorInstance door)
  837.         {
  838.             _target = door;
  839.         }
  840.        
  841.         public L2DoorInstance getDoor()
  842.         {
  843.             return _target;
  844.         }
  845.     }
  846.    
  847.     public void gatesRequest(L2DoorInstance door)
  848.     {
  849.         _gatesRequest.setTarget(door);
  850.     }
  851.    
  852.     public void gatesAnswer(int answer, int type)
  853.     {
  854.         if (_gatesRequest.getDoor() == null)
  855.             return;
  856.        
  857.         if (answer == 1 && getTarget() == _gatesRequest.getDoor() && type == 1)
  858.             _gatesRequest.getDoor().openMe();
  859.         else if (answer == 1 && getTarget() == _gatesRequest.getDoor() && type == 0)
  860.             _gatesRequest.getDoor().closeMe();
  861.        
  862.         _gatesRequest.setTarget(null);
  863.     }
  864.    
  865.     /**
  866.      * Create a new L2PlayerInstance and add it in the characters table of the database.<BR>
  867.      * <BR>
  868.      * <B><U> Actions</U> :</B><BR>
  869.      * <BR>
  870.      * <li>Create a new L2PlayerInstance with an account name</li> <li>Set the name, the Hair Style,
  871.      * the Hair Color and the Face type of the L2PlayerInstance</li> <li>Add the player in the
  872.      * characters table of the database</li><BR>
  873.      * <BR>
  874.      *
  875.      * @param objectId Identifier of the object to initialized
  876.      * @param template The L2PlayerTemplate to apply to the L2PlayerInstance
  877.      * @param accountName The name of the L2PlayerInstance
  878.      * @param name The name of the L2PlayerInstance
  879.      * @param hairStyle The hair style Identifier of the L2PlayerInstance
  880.      * @param hairColor The hair color Identifier of the L2PlayerInstance
  881.      * @param face The face type Identifier of the L2PlayerInstance
  882.      * @param sex The sex type Identifier of the L2PlayerInstance
  883.      * @return The L2PlayerInstance added to the database or null
  884.      */
  885.     public static L2PlayerInstance create(int objectId, L2PlayerTemplate template, String accountName, String name,
  886.             byte hairStyle, byte hairColor, byte face, boolean sex)
  887.     {
  888.         // Create a new L2PlayerInstance with an account name
  889.         PcAppearance app = new PcAppearance(face, hairColor, hairStyle, sex);
  890.         L2PlayerInstance player = new L2PlayerInstance(objectId, template, accountName, app);
  891.        
  892.         // Set the name of the L2PlayerInstance
  893.         player.setName(name);
  894.        
  895.         // Set the base class ID to that of the actual class ID.
  896.         player.setBaseClass(player.getClassId());
  897.        
  898.         // Add the player in the characters table of the database
  899.         boolean ok = player.createDb();
  900.        
  901.         if (!ok)
  902.             return null;
  903.        
  904.         return player;
  905.     }
  906.    
  907.     public static L2PlayerInstance createDummyPlayer(int objectId, String name)
  908.     {
  909.         // Create a new L2PlayerInstance with an account name
  910.         L2PlayerInstance player = new L2PlayerInstance(objectId);
  911.         player.setName(name);
  912.        
  913.         return player;
  914.     }
  915.    
  916.     public String getAccountName()
  917.     {
  918.         return getClient().getAccountName();
  919.     }
  920.    
  921.     public Map<Integer, String> getAccountChars()
  922.     {
  923.         return _chars;
  924.     }
  925.    
  926.     public int getRelation(L2PlayerInstance target)
  927.     {
  928.         int result = 0;
  929.        
  930.         // karma and pvp may not be required
  931.         if (getPvpFlag() != 0)
  932.             result |= RelationChanged.RELATION_PVP_FLAG;
  933.         if (getKarma() > 0)
  934.             result |= RelationChanged.RELATION_HAS_KARMA;
  935.        
  936.         if (isClanLeader())
  937.             result |= RelationChanged.RELATION_LEADER;
  938.        
  939.         if (getSiegeState() != 0)
  940.         {
  941.             result |= RelationChanged.RELATION_INSIEGE;
  942.             if (getSiegeState() != target.getSiegeState())
  943.                 result |= RelationChanged.RELATION_ENEMY;
  944.             else
  945.                 result |= RelationChanged.RELATION_ALLY;
  946.             if (getSiegeState() == 1)
  947.                 result |= RelationChanged.RELATION_ATTACKER;
  948.         }
  949.        
  950.         if (getClan() != null && target.getClan() != null)
  951.         {
  952.             if (target.getPledgeType() != L2Clan.SUBUNIT_ACADEMY && getPledgeType() != L2Clan.SUBUNIT_ACADEMY
  953.                     && target.getClan().isAtWarWith(getClan().getClanId()))
  954.             {
  955.                 result |= RelationChanged.RELATION_1SIDED_WAR;
  956.                 if (getClan().isAtWarWith(target.getClan().getClanId()))
  957.                     result |= RelationChanged.RELATION_MUTUAL_WAR;
  958.             }
  959.         }
  960.         return result;
  961.     }
  962.    
  963.     /**
  964.      * Retrieve a L2PlayerInstance from the characters table of the database and add it in
  965.      * _allObjects of the L2world (call restore method).<BR>
  966.      * <BR>
  967.      * <B><U> Actions</U> :</B><BR>
  968.      * <BR>
  969.      * <li>Retrieve the L2PlayerInstance from the characters table of the database</li> <li>Add the
  970.      * L2PlayerInstance object in _allObjects</li> <li>Set the x,y,z position of the
  971.      * L2PlayerInstance and make it invisible</li> <li>Update the overloaded status of the
  972.      * L2PlayerInstance</li><BR>
  973.      * <BR>
  974.      *
  975.      * @param objectId Identifier of the object to initialized
  976.      * @return The L2PlayerInstance loaded from the database
  977.      */
  978.     public static L2PlayerInstance load(int objectId)
  979.     {
  980.         return restore(objectId);
  981.     }
  982.    
  983.     private void initPcStatusUpdateValues()
  984.     {
  985.         _cpUpdateInterval = getMaxCp() / 352.0;
  986.         _cpUpdateIncCheck = getMaxCp();
  987.         _cpUpdateDecCheck = getMaxCp() - _cpUpdateInterval;
  988.         _mpUpdateInterval = getMaxMp() / 352.0;
  989.         _mpUpdateIncCheck = getMaxMp();
  990.         _mpUpdateDecCheck = getMaxMp() - _mpUpdateInterval;
  991.     }
  992.    
  993.     /**
  994.      * Constructor of L2PlayerInstance (use L2Character constructor).<BR>
  995.      * <BR>
  996.      * <B><U> Actions</U> :</B><BR>
  997.      * <BR>
  998.      * <li>Call the L2Character constructor to create an empty _skills slot and copy basic
  999.      * Calculator set to this L2PlayerInstance</li> <li>Set the name of the L2PlayerInstance</li><BR>
  1000.      * <BR>
  1001.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method SET the level of the L2PlayerInstance to
  1002.      * 1</B></FONT><BR>
  1003.      * <BR>
  1004.      *
  1005.      * @param objectId Identifier of the object to initialized
  1006.      * @param template The L2PlayerTemplate to apply to the L2PlayerInstance
  1007.      * @param accountName The name of the account including this L2PlayerInstance
  1008.      * @param app The PcAppearance of the L2PlayerInstance
  1009.      */
  1010.     private L2PlayerInstance(int objectId, L2PlayerTemplate template, String accountName, PcAppearance app)
  1011.     {
  1012.         super(objectId, template);
  1013.         super.initCharStatusUpdateValues();
  1014.         initPcStatusUpdateValues();
  1015.        
  1016.         _accountName = accountName;
  1017.         _appearance = app;
  1018.        
  1019.         // Create an AI
  1020.         _ai = new L2PlayerAI(new L2PlayerInstance.AIAccessor());
  1021.        
  1022.         // Create a L2Radar object
  1023.         _radar = new L2Radar(this);
  1024.        
  1025.         // Retrieve from the database all items of this L2PlayerInstance and add them to _inventory
  1026.         getInventory().restore();
  1027.         getWarehouse();
  1028.         getFreight();
  1029.     }
  1030.    
  1031.     private L2PlayerInstance(int objectId)
  1032.     {
  1033.         super(objectId, null);
  1034.         super.initCharStatusUpdateValues();
  1035.         initPcStatusUpdateValues();
  1036.     }
  1037.    
  1038.     @Override
  1039.     public void addFuncsToNewCharacter()
  1040.     {
  1041.         // Add L2Character functionalities.
  1042.         super.addFuncsToNewCharacter();
  1043.        
  1044.         addStatFunc(FuncMaxCpAdd.getInstance());
  1045.         addStatFunc(FuncMaxCpMul.getInstance());
  1046.         addStatFunc(FuncMaxHpAdd.getInstance());
  1047.         addStatFunc(FuncMaxMpAdd.getInstance());
  1048.        
  1049.         addStatFunc(FuncBowAtkRange.getInstance());
  1050.        
  1051.         addStatFunc(FuncHennaSTR.getInstance());
  1052.         addStatFunc(FuncHennaDEX.getInstance());
  1053.         addStatFunc(FuncHennaINT.getInstance());
  1054.         addStatFunc(FuncHennaMEN.getInstance());
  1055.         addStatFunc(FuncHennaCON.getInstance());
  1056.         addStatFunc(FuncHennaWIT.getInstance());
  1057.     }
  1058.    
  1059.     @Override
  1060.     public void initKnownList()
  1061.     {
  1062.         setKnownList(new PlayerKnownList(this));
  1063.     }
  1064.    
  1065.     @Override
  1066.     public final PlayerKnownList getKnownList()
  1067.     {
  1068.         return (PlayerKnownList)super.getKnownList();
  1069.     }
  1070.    
  1071.     @Override
  1072.     public void initCharStat()
  1073.     {
  1074.         setStat(new PlayerStat(this));
  1075.     }
  1076.    
  1077.     @Override
  1078.     public final PlayerStat getStat()
  1079.     {
  1080.         return (PlayerStat)super.getStat();
  1081.     }
  1082.    
  1083.     @Override
  1084.     public void initCharStatus()
  1085.     {
  1086.         setStatus(new PlayerStatus(this));
  1087.     }
  1088.    
  1089.     @Override
  1090.     public final PlayerStatus getStatus()
  1091.     {
  1092.         return (PlayerStatus)super.getStatus();
  1093.     }
  1094.    
  1095.     @Override
  1096.     public void initPosition()
  1097.     {
  1098.         setObjectPosition(new PlayerPosition(this));
  1099.     }
  1100.    
  1101.     @Override
  1102.     public PlayerPosition getPosition()
  1103.     {
  1104.         return (PlayerPosition)super.getPosition();
  1105.     }
  1106.    
  1107.     public final PcAppearance getAppearance()
  1108.     {
  1109.         return _appearance;
  1110.     }
  1111.    
  1112.     /**
  1113.      * @return the base L2PlayerTemplate link to the L2PlayerInstance.
  1114.      */
  1115.     public final L2PlayerTemplate getBaseTemplate()
  1116.     {
  1117.         return CharTemplateTable.getInstance().getTemplate(_baseClass);
  1118.     }
  1119.    
  1120.     /** Return the L2PlayerTemplate link to the L2PlayerInstance. */
  1121.     @Override
  1122.     public final L2PlayerTemplate getTemplate()
  1123.     {
  1124.         return (L2PlayerTemplate)super.getTemplate();
  1125.     }
  1126.    
  1127.     public void setTemplate(ClassId newclass)
  1128.     {
  1129.         super.setTemplate(CharTemplateTable.getInstance().getTemplate(newclass));
  1130.     }
  1131.    
  1132.     /**
  1133.      * Return the AI of the L2PlayerInstance (create it if necessary).
  1134.      */
  1135.     @Override
  1136.     public L2CharacterAI getAI()
  1137.     {
  1138.         if (_ai == null)
  1139.         {
  1140.             synchronized (this)
  1141.             {
  1142.                 if (_ai == null)
  1143.                     _ai = new L2PlayerAI(new L2PlayerInstance.AIAccessor());
  1144.             }
  1145.         }
  1146.        
  1147.         return _ai;
  1148.     }
  1149.    
  1150.     /** Return the Level of the L2PlayerInstance. */
  1151.     @Override
  1152.     public final int getLevel()
  1153.     {
  1154.         return getStat().getLevel();
  1155.     }
  1156.    
  1157.     /**
  1158.      * A newbie is a player reaching level 6. He isn't considered newbie at lvl 25.<br>
  1159.      * Since IL newbie isn't anymore the first character of an account reaching that state, but any.
  1160.      *
  1161.      * @return True if newbie.
  1162.      */
  1163.     public boolean isNewbie()
  1164.     {
  1165.         return getClassId().level() <= 1 && getLevel() >= 6 && getLevel() <= 25;
  1166.     }
  1167.    
  1168.     public void setBaseClass(int baseClass)
  1169.     {
  1170.         _baseClass = baseClass;
  1171.     }
  1172.    
  1173.     public void setBaseClass(ClassId classId)
  1174.     {
  1175.         _baseClass = classId.ordinal();
  1176.     }
  1177.    
  1178.     public boolean isInStoreMode()
  1179.     {
  1180.         return (getPrivateStoreType() > 0);
  1181.     }
  1182.    
  1183.     public boolean isInCraftMode()
  1184.     {
  1185.         return _inCraftMode;
  1186.     }
  1187.    
  1188.     public void isInCraftMode(boolean b)
  1189.     {
  1190.         _inCraftMode = b;
  1191.     }
  1192.    
  1193.     /**
  1194.      * Manage Logout Task
  1195.      */
  1196.     public void logout()
  1197.     {
  1198.         logout(true);
  1199.     }
  1200.    
  1201.     /**
  1202.      * Manage Logout Task
  1203.      *
  1204.      * @param closeClient
  1205.      */
  1206.     public void logout(boolean closeClient)
  1207.     {
  1208.         try
  1209.         {
  1210.             closeNetConnection(closeClient);
  1211.         }
  1212.         catch (Exception e)
  1213.         {
  1214.             _log.log(Level.WARNING, "Exception on logout(): " + e.getMessage(), e);
  1215.         }
  1216.     }
  1217.    
  1218.     /**
  1219.      * @return a table containing all Common L2RecipeList of the L2PlayerInstance.
  1220.      */
  1221.     public L2RecipeList[] getCommonRecipeBook()
  1222.     {
  1223.         return _commonRecipeBook.values().toArray(new L2RecipeList[_commonRecipeBook.values().size()]);
  1224.     }
  1225.    
  1226.     /**
  1227.      * @return a table containing all Dwarf L2RecipeList of the L2PlayerInstance.
  1228.      */
  1229.     public L2RecipeList[] getDwarvenRecipeBook()
  1230.     {
  1231.         return _dwarvenRecipeBook.values().toArray(new L2RecipeList[_dwarvenRecipeBook.values().size()]);
  1232.     }
  1233.    
  1234.     /**
  1235.      * Add a new L2RecipList to the table _commonrecipebook containing all L2RecipeList of the
  1236.      * L2PlayerInstance.
  1237.      *
  1238.      * @param recipe The L2RecipeList to add to the _recipebook
  1239.      */
  1240.     public void registerCommonRecipeList(L2RecipeList recipe)
  1241.     {
  1242.         _commonRecipeBook.put(recipe.getId(), recipe);
  1243.     }
  1244.    
  1245.     /**
  1246.      * Add a new L2RecipList to the table _recipebook containing all L2RecipeList of the
  1247.      * L2PlayerInstance.
  1248.      *
  1249.      * @param recipe The L2RecipeList to add to the _recipebook
  1250.      */
  1251.     public void registerDwarvenRecipeList(L2RecipeList recipe)
  1252.     {
  1253.         _dwarvenRecipeBook.put(recipe.getId(), recipe);
  1254.     }
  1255.    
  1256.     /**
  1257.      * @param recipeId The Identifier of the L2RecipeList to check in the player's recipe books
  1258.      * @return <b>TRUE</b> if player has the recipe on Common or Dwarven Recipe book else returns
  1259.      *         <b>FALSE</b>
  1260.      */
  1261.     public boolean hasRecipeList(int recipeId)
  1262.     {
  1263.         if (_dwarvenRecipeBook.containsKey(recipeId))
  1264.             return true;
  1265.         else if (_commonRecipeBook.containsKey(recipeId))
  1266.             return true;
  1267.         else
  1268.             return false;
  1269.     }
  1270.    
  1271.     /**
  1272.      * Tries to remove a L2RecipList from the table _DwarvenRecipeBook or from table
  1273.      * _CommonRecipeBook, those table contain all L2RecipeList of the L2PlayerInstance.
  1274.      *
  1275.      * @param recipeId The Identifier of the L2RecipeList to remove from the _recipebook.
  1276.      */
  1277.     public void unregisterRecipeList(int recipeId)
  1278.     {
  1279.         if (_dwarvenRecipeBook.containsKey(recipeId))
  1280.             _dwarvenRecipeBook.remove(recipeId);
  1281.         else if (_commonRecipeBook.containsKey(recipeId))
  1282.             _commonRecipeBook.remove(recipeId);
  1283.         else
  1284.             _log.warning("Attempted to remove unknown RecipeList: " + recipeId);
  1285.        
  1286.         L2ShortCut[] allShortCuts = getAllShortCuts();
  1287.        
  1288.         for (L2ShortCut sc : allShortCuts)
  1289.         {
  1290.             if (sc != null && sc.getId() == recipeId && sc.getType() == L2ShortCut.TYPE_RECIPE)
  1291.                 deleteShortCut(sc.getSlot(), sc.getPage());
  1292.         }
  1293.     }
  1294.    
  1295.     /**
  1296.      * @return the Id for the last talked quest NPC.
  1297.      */
  1298.     public int getLastQuestNpcObject()
  1299.     {
  1300.         return _questNpcObject;
  1301.     }
  1302.    
  1303.     public void setLastQuestNpcObject(int npcId)
  1304.     {
  1305.         _questNpcObject = npcId;
  1306.     }
  1307.    
  1308.     /**
  1309.      * @param name The name of the quest.
  1310.      * @return The QuestState object corresponding to the quest name.
  1311.      */
  1312.     public QuestState getQuestState(String name)
  1313.     {
  1314.         for (QuestState qs : _quests)
  1315.         {
  1316.             if (name.equals(qs.getQuest().getName()))
  1317.                 return qs;
  1318.         }
  1319.         return null;
  1320.     }
  1321.    
  1322.     /**
  1323.      * Add a QuestState to the table _quest containing all quests began by the L2PlayerInstance.
  1324.      *
  1325.      * @param qs The QuestState to add to _quest.
  1326.      */
  1327.     public void setQuestState(QuestState qs)
  1328.     {
  1329.         _quests.add(qs);
  1330.     }
  1331.    
  1332.     /**
  1333.      * Remove a QuestState from the table _quest containing all quests began by the
  1334.      * L2PlayerInstance.
  1335.      *
  1336.      * @param qs : The QuestState to be removed from _quest.
  1337.      */
  1338.     public void delQuestState(QuestState qs)
  1339.     {
  1340.         _quests.remove(qs);
  1341.     }
  1342.    
  1343.     /**
  1344.      * @param completed : If true, include completed quests to the list.
  1345.      * @return list of started and eventually completed quests of the player.
  1346.      */
  1347.     public List<Quest> getAllQuests(boolean completed)
  1348.     {
  1349.         List<Quest> quests = new ArrayList<>();
  1350.        
  1351.         for (QuestState qs : _quests)
  1352.         {
  1353.             if (qs == null || completed && qs.isCreated() || !completed && !qs.isStarted())
  1354.                 continue;
  1355.            
  1356.             Quest quest = qs.getQuest();
  1357.             if (quest == null || !quest.isRealQuest())
  1358.                 continue;
  1359.            
  1360.             quests.add(quest);
  1361.         }
  1362.        
  1363.         return quests;
  1364.     }
  1365.    
  1366.     public void processQuestEvent(String questName, String event)
  1367.     {
  1368.         Quest quest = QuestManager.getInstance().getQuest(questName);
  1369.         if (quest == null)
  1370.             return;
  1371.        
  1372.         QuestState qs = getQuestState(questName);
  1373.         if (qs == null)
  1374.             return;
  1375.        
  1376.         L2Object object = L2World.getInstance().findObject(getLastQuestNpcObject());
  1377.         if (!(object instanceof L2Npc) || !isInsideRadius(object, L2Npc.INTERACTION_DISTANCE, false, false))
  1378.             return;
  1379.        
  1380.         L2Npc npc = (L2Npc)object;
  1381.         List<Quest> quests = npc.getTemplate().getEventQuests(QuestEventType.ON_TALK);
  1382.         if (quests != null)
  1383.         {
  1384.             for (Quest onTalk : quests)
  1385.             {
  1386.                 if (onTalk == null || onTalk != quest)
  1387.                     continue;
  1388.                
  1389.                 quest.notifyEvent(event, npc, this);
  1390.                 break;
  1391.             }
  1392.         }
  1393.     }
  1394.    
  1395.     /**
  1396.      * Add QuestState instance that is to be notified of L2PlayerInstance's death.
  1397.      *
  1398.      * @param qs The QuestState that subscribe to this event
  1399.      */
  1400.     public void addNotifyQuestOfDeath(QuestState qs)
  1401.     {
  1402.         if (qs == null)
  1403.             return;
  1404.        
  1405.         if (!_notifyQuestOfDeathList.contains(qs))
  1406.             _notifyQuestOfDeathList.add(qs);
  1407.     }
  1408.    
  1409.     /**
  1410.      * Remove QuestState instance that is to be notified of L2PlayerInstance's death.
  1411.      *
  1412.      * @param qs The QuestState that subscribe to this event
  1413.      */
  1414.     public void removeNotifyQuestOfDeath(QuestState qs)
  1415.     {
  1416.         if (qs == null)
  1417.             return;
  1418.        
  1419.         _notifyQuestOfDeathList.remove(qs);
  1420.     }
  1421.    
  1422.     /**
  1423.      * @return A list of QuestStates which registered for notify of death of this L2PlayerInstance.
  1424.      */
  1425.     public final List<QuestState> getNotifyQuestOfDeath()
  1426.     {
  1427.         return _notifyQuestOfDeathList;
  1428.     }
  1429.    
  1430.     /**
  1431.      * @return A table containing all L2ShortCut of the L2PlayerInstance.
  1432.      */
  1433.     public L2ShortCut[] getAllShortCuts()
  1434.     {
  1435.         return _shortCuts.getAllShortCuts();
  1436.     }
  1437.    
  1438.     /**
  1439.      * @param slot The slot in wich the shortCuts is equipped
  1440.      * @param page The page of shortCuts containing the slot
  1441.      * @return The L2ShortCut of the L2PlayerInstance corresponding to the position (page-slot).
  1442.      */
  1443.     public L2ShortCut getShortCut(int slot, int page)
  1444.     {
  1445.         return _shortCuts.getShortCut(slot, page);
  1446.     }
  1447.    
  1448.     /**
  1449.      * Add a L2shortCut to the L2PlayerInstance _shortCuts
  1450.      *
  1451.      * @param shortcut The shortcut to add.
  1452.      */
  1453.     public void registerShortCut(L2ShortCut shortcut)
  1454.     {
  1455.         _shortCuts.registerShortCut(shortcut);
  1456.     }
  1457.    
  1458.     /**
  1459.      * Delete the L2ShortCut corresponding to the position (page-slot) from the L2PlayerInstance
  1460.      * _shortCuts.
  1461.      *
  1462.      * @param slot
  1463.      * @param page
  1464.      */
  1465.     public void deleteShortCut(int slot, int page)
  1466.     {
  1467.         _shortCuts.deleteShortCut(slot, page);
  1468.     }
  1469.    
  1470.     /**
  1471.      * Add a L2Macro to the L2PlayerInstance _macroses.
  1472.      *
  1473.      * @param macro The Macro object to add.
  1474.      */
  1475.     public void registerMacro(L2Macro macro)
  1476.     {
  1477.         _macroses.registerMacro(macro);
  1478.     }
  1479.    
  1480.     /**
  1481.      * Delete the L2Macro corresponding to the Identifier from the L2PlayerInstance _macroses.
  1482.      *
  1483.      * @param id
  1484.      */
  1485.     public void deleteMacro(int id)
  1486.     {
  1487.         _macroses.deleteMacro(id);
  1488.     }
  1489.    
  1490.     /**
  1491.      * @return all L2Macro of the L2PlayerInstance.
  1492.      */
  1493.     public MacroList getMacroses()
  1494.     {
  1495.         return _macroses;
  1496.     }
  1497.    
  1498.     /**
  1499.      * Set the siege state of the L2PlayerInstance.
  1500.      *
  1501.      * @param siegeState 1 = attacker, 2 = defender, 0 = not involved
  1502.      */
  1503.     public void setSiegeState(byte siegeState)
  1504.     {
  1505.         _siegeState = siegeState;
  1506.     }
  1507.    
  1508.     /**
  1509.      * @return the siege state of the L2PlayerInstance.
  1510.      */
  1511.     public byte getSiegeState()
  1512.     {
  1513.         return _siegeState;
  1514.     }
  1515.    
  1516.     /**
  1517.      * Set the PvP Flag of the L2PlayerInstance.
  1518.      *
  1519.      * @param pvpFlag 0 or 1.
  1520.      */
  1521.     public void setPvpFlag(int pvpFlag)
  1522.     {
  1523.         _pvpFlag = (byte)pvpFlag;
  1524.     }
  1525.    
  1526.     @Override
  1527.     public byte getPvpFlag()
  1528.     {
  1529.         return _pvpFlag;
  1530.     }
  1531.    
  1532.     public void updatePvPFlag(int value)
  1533.     {
  1534.         if (getPvpFlag() == value)
  1535.             return;
  1536.        
  1537.         setPvpFlag(value);
  1538.         sendPacket(new UserInfo(this));
  1539.        
  1540.         if (getPet() != null)
  1541.             sendPacket(new RelationChanged(getPet(), getRelation(this), false));
  1542.        
  1543.         broadcastRelationsChanges();
  1544.     }
  1545.    
  1546.     @Override
  1547.     public void revalidateZone(boolean force)
  1548.     {
  1549.         // Cannot validate if not in a world region (happens during teleport)
  1550.         if (getWorldRegion() == null)
  1551.             return;
  1552.        
  1553.         // This function is called very often from movement code
  1554.         if (force)
  1555.             _zoneValidateCounter = 4;
  1556.         else
  1557.         {
  1558.             _zoneValidateCounter--;
  1559.             if (_zoneValidateCounter >= 0)
  1560.                 return;
  1561.            
  1562.             _zoneValidateCounter = 4;
  1563.         }
  1564.        
  1565.         getWorldRegion().revalidateZones(this);
  1566.        
  1567.         if (Config.ALLOW_WATER)
  1568.             checkWaterState();
  1569.        
  1570.         if (isInsideZone(ZONE_SIEGE))
  1571.         {
  1572.             if (_lastCompassZone == ExSetCompassZoneCode.SIEGEWARZONE2)
  1573.                 return;
  1574.            
  1575.             _lastCompassZone = ExSetCompassZoneCode.SIEGEWARZONE2;
  1576.             sendPacket(new ExSetCompassZoneCode(ExSetCompassZoneCode.SIEGEWARZONE2));
  1577.         }
  1578.         else if (isInsideZone(ZONE_PVP))
  1579.         {
  1580.             if (_lastCompassZone == ExSetCompassZoneCode.PVPZONE)
  1581.                 return;
  1582.            
  1583.             _lastCompassZone = ExSetCompassZoneCode.PVPZONE;
  1584.             sendPacket(new ExSetCompassZoneCode(ExSetCompassZoneCode.PVPZONE));
  1585.         }
  1586.         else if (isIn7sDungeon())
  1587.         {
  1588.             if (_lastCompassZone == ExSetCompassZoneCode.SEVENSIGNSZONE)
  1589.                 return;
  1590.            
  1591.             _lastCompassZone = ExSetCompassZoneCode.SEVENSIGNSZONE;
  1592.             sendPacket(new ExSetCompassZoneCode(ExSetCompassZoneCode.SEVENSIGNSZONE));
  1593.         }
  1594.         else if (isInsideZone(ZONE_PEACE))
  1595.         {
  1596.             if (_lastCompassZone == ExSetCompassZoneCode.PEACEZONE)
  1597.                 return;
  1598.            
  1599.             _lastCompassZone = ExSetCompassZoneCode.PEACEZONE;
  1600.             sendPacket(new ExSetCompassZoneCode(ExSetCompassZoneCode.PEACEZONE));
  1601.         }
  1602.         else
  1603.         {
  1604.             if (_lastCompassZone == ExSetCompassZoneCode.GENERALZONE)
  1605.                 return;
  1606.            
  1607.             if (_lastCompassZone == ExSetCompassZoneCode.SIEGEWARZONE2)
  1608.                 updatePvPStatus();
  1609.            
  1610.             _lastCompassZone = ExSetCompassZoneCode.GENERALZONE;
  1611.             sendPacket(new ExSetCompassZoneCode(ExSetCompassZoneCode.GENERALZONE));
  1612.         }
  1613.     }
  1614.    
  1615.     /**
  1616.      * @return True if the L2PlayerInstance can Craft Dwarven Recipes.
  1617.      */
  1618.     public boolean hasDwarvenCraft()
  1619.     {
  1620.         return getSkillLevel(L2Skill.SKILL_CREATE_DWARVEN) >= 1;
  1621.     }
  1622.    
  1623.     public int getDwarvenCraft()
  1624.     {
  1625.         return getSkillLevel(L2Skill.SKILL_CREATE_DWARVEN);
  1626.     }
  1627.    
  1628.     /**
  1629.      * @return True if the L2PlayerInstance can Craft Dwarven Recipes.
  1630.      */
  1631.     public boolean hasCommonCraft()
  1632.     {
  1633.         return getSkillLevel(L2Skill.SKILL_CREATE_COMMON) >= 1;
  1634.     }
  1635.    
  1636.     public int getCommonCraft()
  1637.     {
  1638.         return getSkillLevel(L2Skill.SKILL_CREATE_COMMON);
  1639.     }
  1640.    
  1641.     /**
  1642.      * @return the PK counter of the L2PlayerInstance.
  1643.      */
  1644.     public int getPkKills()
  1645.     {
  1646.         return _pkKills;
  1647.     }
  1648.    
  1649.     /**
  1650.      * Set the PK counter of the L2PlayerInstance.
  1651.      *
  1652.      * @param pkKills A number.
  1653.      */
  1654.     public void setPkKills(int pkKills)
  1655.     {
  1656.         _pkKills = pkKills;
  1657.     }
  1658.    
  1659.     /**
  1660.      * @return The _deleteTimer of the L2PlayerInstance.
  1661.      */
  1662.     public long getDeleteTimer()
  1663.     {
  1664.         return _deleteTimer;
  1665.     }
  1666.    
  1667.     /**
  1668.      * Set the _deleteTimer of the L2PlayerInstance.
  1669.      *
  1670.      * @param deleteTimer Time in ms.
  1671.      */
  1672.     public void setDeleteTimer(long deleteTimer)
  1673.     {
  1674.         _deleteTimer = deleteTimer;
  1675.     }
  1676.    
  1677.     /**
  1678.      * @return The current weight of the L2PlayerInstance.
  1679.      */
  1680.     public int getCurrentLoad()
  1681.     {
  1682.         return _inventory.getTotalWeight();
  1683.     }
  1684.    
  1685.     /**
  1686.      * @return The date of last update of recomPoints.
  1687.      */
  1688.     public long getLastRecomUpdate()
  1689.     {
  1690.         return _lastRecomUpdate;
  1691.     }
  1692.    
  1693.     public void setLastRecomUpdate(long date)
  1694.     {
  1695.         _lastRecomUpdate = date;
  1696.     }
  1697.    
  1698.     /**
  1699.      * @return The number of recommandation obtained by the L2PlayerInstance.
  1700.      */
  1701.     public int getRecomHave()
  1702.     {
  1703.         return _recomHave;
  1704.     }
  1705.    
  1706.     /**
  1707.      * Increment the number of recommandation obtained by the L2PlayerInstance (Max : 255).
  1708.      */
  1709.     protected void incRecomHave()
  1710.     {
  1711.         if (_recomHave < 255)
  1712.             _recomHave++;
  1713.     }
  1714.    
  1715.     /**
  1716.      * Set the number of recommandations obtained by the L2PlayerInstance (Max : 255).
  1717.      *
  1718.      * @param value Number of recommandations obtained.
  1719.      */
  1720.     public void setRecomHave(int value)
  1721.     {
  1722.         if (value > 255)
  1723.             _recomHave = 255;
  1724.         else if (value < 0)
  1725.             _recomHave = 0;
  1726.         else
  1727.             _recomHave = value;
  1728.     }
  1729.    
  1730.     /**
  1731.      * @return The number of recommandation that the L2PlayerInstance can give.
  1732.      */
  1733.     public int getRecomLeft()
  1734.     {
  1735.         return _recomLeft;
  1736.     }
  1737.    
  1738.     /**
  1739.      * Increment the number of recommandation that the L2PlayerInstance can give.
  1740.      */
  1741.     protected void decRecomLeft()
  1742.     {
  1743.         if (_recomLeft > 0)
  1744.             _recomLeft--;
  1745.     }
  1746.    
  1747.     public void giveRecom(L2PlayerInstance target)
  1748.     {
  1749.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  1750.         {
  1751.             PreparedStatement statement = con.prepareStatement(ADD_CHAR_RECOM);
  1752.             statement.setInt(1, getObjectId());
  1753.             statement.setInt(2, target.getObjectId());
  1754.             statement.execute();
  1755.             statement.close();
  1756.         }
  1757.         catch (Exception e)
  1758.         {
  1759.             _log.warning("Could not update char recommendations: " + e);
  1760.         }
  1761.        
  1762.         target.incRecomHave();
  1763.         decRecomLeft();
  1764.         _recomChars.add(target.getObjectId());
  1765.     }
  1766.    
  1767.     public boolean canRecom(L2PlayerInstance target)
  1768.     {
  1769.         return !_recomChars.contains(target.getObjectId());
  1770.     }
  1771.    
  1772.     /**
  1773.      * Set the exp of the L2PlayerInstance before a death
  1774.      *
  1775.      * @param exp
  1776.      */
  1777.     public void setExpBeforeDeath(long exp)
  1778.     {
  1779.         _expBeforeDeath = exp;
  1780.     }
  1781.    
  1782.     public long getExpBeforeDeath()
  1783.     {
  1784.         return _expBeforeDeath;
  1785.     }
  1786.    
  1787.     /**
  1788.      * Return the Karma of the L2PlayerInstance.
  1789.      */
  1790.     @Override
  1791.     public int getKarma()
  1792.     {
  1793.         return _karma;
  1794.     }
  1795.    
  1796.     /**
  1797.      * Set the Karma of the L2PlayerInstance and send StatusUpdate (broadcast).
  1798.      *
  1799.      * @param karma A value.
  1800.      */
  1801.     public void setKarma(int karma)
  1802.     {
  1803.         if (karma < 0)
  1804.             karma = 0;
  1805.        
  1806.         if (_karma > 0 && karma == 0)
  1807.         {
  1808.             sendPacket(new UserInfo(this));
  1809.             broadcastRelationsChanges();
  1810.         }
  1811.        
  1812.         // send message with new karma value
  1813.         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOUR_KARMA_HAS_BEEN_CHANGED_TO_S1).addNumber(karma));
  1814.        
  1815.         _karma = karma;
  1816.         broadcastKarma();
  1817.     }
  1818.    
  1819.     /**
  1820.      * Weight Limit = (CON Modifier*69000)*Skills
  1821.      *
  1822.      * @return The max weight that the L2PlayerInstance can load.
  1823.      */
  1824.     public int getMaxLoad()
  1825.     {
  1826.         int con = getCON();
  1827.         if (con < 1)
  1828.             return 31000;
  1829.        
  1830.         if (con > 59)
  1831.             return 176000;
  1832.        
  1833.         double baseLoad = Math.pow(1.029993928, con) * 30495.627366;
  1834.         return (int)calcStat(Stats.MAX_LOAD, baseLoad * Config.ALT_WEIGHT_LIMIT, this, null);
  1835.     }
  1836.    
  1837.     public int getExpertisePenalty()
  1838.     {
  1839.         return _expertisePenalty;
  1840.     }
  1841.    
  1842.     public int getWeightPenalty()
  1843.     {
  1844.         return _curWeightPenalty;
  1845.     }
  1846.    
  1847.     /**
  1848.      * Update the overloaded status of the L2PlayerInstance.
  1849.      */
  1850.     public void refreshOverloaded()
  1851.     {
  1852.         int maxLoad = getMaxLoad();
  1853.         if (maxLoad > 0)
  1854.         {
  1855.             int weightproc = getCurrentLoad() * 1000 / maxLoad;
  1856.             int newWeightPenalty;
  1857.            
  1858.             if (weightproc < 500)
  1859.                 newWeightPenalty = 0;
  1860.             else if (weightproc < 666)
  1861.                 newWeightPenalty = 1;
  1862.             else if (weightproc < 800)
  1863.                 newWeightPenalty = 2;
  1864.             else if (weightproc < 1000)
  1865.                 newWeightPenalty = 3;
  1866.             else
  1867.                 newWeightPenalty = 4;
  1868.            
  1869.             if (_curWeightPenalty != newWeightPenalty)
  1870.             {
  1871.                 _curWeightPenalty = newWeightPenalty;
  1872.                
  1873.                 if (newWeightPenalty > 0)
  1874.                 {
  1875.                     super.addSkill(SkillTable.getInstance().getInfo(4270, newWeightPenalty));
  1876.                     setIsOverloaded(getCurrentLoad() > maxLoad);
  1877.                 }
  1878.                 else
  1879.                 {
  1880.                     super.removeSkill(getKnownSkill(4270));
  1881.                     setIsOverloaded(false);
  1882.                 }
  1883.                
  1884.                 sendPacket(new UserInfo(this));
  1885.                 sendPacket(new EtcStatusUpdate(this));
  1886.                 broadcastCharInfo();
  1887.             }
  1888.         }
  1889.     }
  1890.    
  1891.     public void refreshExpertisePenalty()
  1892.     {
  1893.         int newPenalty = 0;
  1894.        
  1895.         for (L2ItemInstance item : getInventory().getItems())
  1896.         {
  1897.             if (item != null && item.isEquipped())
  1898.             {
  1899.                 int crystaltype = item.getItem().getCrystalType();
  1900.                
  1901.                 if (crystaltype > newPenalty)
  1902.                     newPenalty = crystaltype;
  1903.             }
  1904.         }
  1905.        
  1906.         newPenalty = newPenalty - getExpertiseIndex();
  1907.        
  1908.         if (newPenalty <= 0)
  1909.             newPenalty = 0;
  1910.        
  1911.         if (getExpertisePenalty() != newPenalty)
  1912.         {
  1913.             _expertisePenalty = newPenalty;
  1914.            
  1915.             if (newPenalty > 0)
  1916.                 super.addSkill(SkillTable.getInstance().getInfo(4267, 1)); // level used to be newPenalty
  1917.             else
  1918.                 super.removeSkill(getKnownSkill(4267));
  1919.            
  1920.             sendSkillList();
  1921.             sendPacket(new EtcStatusUpdate(this));
  1922.         }
  1923.     }
  1924.    
  1925.     /**
  1926.      * Equip or unequip the item.
  1927.      * <UL>
  1928.      * <LI>If item is equipped, shots are applied if automation is on.</LI>
  1929.      * <LI>If item is unequipped, shots are discharged.</LI>
  1930.      * </UL>
  1931.      *
  1932.      * @param item The item to charge/discharge.
  1933.      * @param abortAttack If true, the current attack will be aborted in order to equip the item.
  1934.      */
  1935.     public void useEquippableItem(L2ItemInstance item, boolean abortAttack)
  1936.     {
  1937.         L2ItemInstance[] items = null;
  1938.         final boolean isEquipped = item.isEquipped();
  1939.         final int oldInvLimit = getInventoryLimit();
  1940.         SystemMessage sm = null;
  1941.        
  1942.         if (item.getItem() instanceof L2Weapon)
  1943.             item.unChargeAllShots();
  1944.        
  1945.         if (isEquipped)
  1946.         {
  1947.             if (item.getEnchantLevel() > 0)
  1948.                 sm =
  1949.                         SystemMessage.getSystemMessage(SystemMessageId.EQUIPMENT_S1_S2_REMOVED)
  1950.                                 .addNumber(item.getEnchantLevel()).addItemName(item);
  1951.             else
  1952.                 sm = SystemMessage.getSystemMessage(SystemMessageId.S1_DISARMED).addItemName(item);
  1953.            
  1954.             sendPacket(sm);
  1955.            
  1956.             int slot = getInventory().getSlotFromItem(item);
  1957.             items = getInventory().unEquipItemInBodySlotAndRecord(slot);
  1958.         }
  1959.         else
  1960.         {
  1961.             items = getInventory().equipItemAndRecord(item);
  1962.            
  1963.             if (item.isEquipped())
  1964.             {
  1965.                 if (item.getEnchantLevel() > 0)
  1966.                     sm =
  1967.                             SystemMessage.getSystemMessage(SystemMessageId.S1_S2_EQUIPPED)
  1968.                                     .addNumber(item.getEnchantLevel()).addItemName(item);
  1969.                 else
  1970.                     sm = SystemMessage.getSystemMessage(SystemMessageId.S1_EQUIPPED).addItemName(item);
  1971.                
  1972.                 sendPacket(sm);
  1973.                
  1974.                 // Consume mana - will start a task if required; returns if item is not a shadow item
  1975.                 item.decreaseMana(false);
  1976.                
  1977.                 if ((item.getItem().getBodyPart() & L2Item.SLOT_ALLWEAPON) != 0)
  1978.                     rechargeShots(true, true);
  1979.             }
  1980.             else
  1981.                 sendPacket(SystemMessageId.CANNOT_EQUIP_ITEM_DUE_TO_BAD_CONDITION);
  1982.         }
  1983.         refreshExpertisePenalty();
  1984.         broadcastUserInfo();
  1985.        
  1986.         InventoryUpdate iu = new InventoryUpdate();
  1987.         iu.addItems(Arrays.asList(items));
  1988.         sendPacket(iu);
  1989.        
  1990.         if (abortAttack)
  1991.             abortAttack();
  1992.        
  1993.         if (getInventoryLimit() != oldInvLimit)
  1994.             sendPacket(new ExStorageMaxCount(this));
  1995.     }
  1996.    
  1997.     /**
  1998.      * @return PvP Kills of the L2PlayerInstance (number of player killed during a PvP).
  1999.      */
  2000.     public int getPvpKills()
  2001.     {
  2002.         return _pvpKills;
  2003.     }
  2004.    
  2005.     /**
  2006.      * Set PvP Kills of the L2PlayerInstance (number of player killed during a PvP).
  2007.      *
  2008.      * @param pvpKills A value.
  2009.      */
  2010.     public void setPvpKills(int pvpKills)
  2011.     {
  2012.         _pvpKills = pvpKills;
  2013.     }
  2014.    
  2015.     /**
  2016.      * @return The ClassId object of the L2PlayerInstance contained in L2PlayerTemplate.
  2017.      */
  2018.     public ClassId getClassId()
  2019.     {
  2020.         return getTemplate().classId;
  2021.     }
  2022.    
  2023.     /**
  2024.      * Set the template of the L2PlayerInstance.
  2025.      *
  2026.      * @param Id The Identifier of the L2PlayerTemplate to set to the L2PlayerInstance
  2027.      */
  2028.     public void setClassId(int Id)
  2029.     {
  2030.         if (!_subclassLock.tryLock())
  2031.             return;
  2032.        
  2033.         try
  2034.         {
  2035.             if (getLvlJoinedAcademy() != 0 && _clan != null && PlayerClass.values()[Id].getLevel() == ClassLevel.Third)
  2036.             {
  2037.                 if (getLvlJoinedAcademy() <= 16)
  2038.                     _clan.addReputationScore(400);
  2039.                 else if (getLvlJoinedAcademy() >= 39)
  2040.                     _clan.addReputationScore(170);
  2041.                 else
  2042.                     _clan.addReputationScore((400 - (getLvlJoinedAcademy() - 16) * 10));
  2043.                
  2044.                 setLvlJoinedAcademy(0);
  2045.                
  2046.                 // oust pledge member from the academy, cuz he has finished his 2nd class transfer
  2047.                 SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.CLAN_MEMBER_S1_EXPELLED);
  2048.                 msg.addString(getName());
  2049.                 _clan.broadcastToOnlineMembers(msg);
  2050.                 _clan.broadcastToOnlineMembers(new PledgeShowMemberListDelete(getName()));
  2051.                 _clan.removeClanMember(getObjectId(), 0);
  2052.                 sendPacket(SystemMessageId.ACADEMY_MEMBERSHIP_TERMINATED);
  2053.                
  2054.                 // receive graduation gift
  2055.                 getInventory().addItem("Gift", 8181, 1, this, null); // give academy circlet
  2056.             }
  2057.            
  2058.             if (isSubClassActive())
  2059.                 getSubClasses().get(_classIndex).setClassId(Id);
  2060.            
  2061.             broadcastPacket(new MagicSkillUse(this, this, 5103, 1, 1000, 0));
  2062.             setClassTemplate(Id);
  2063.            
  2064.             if (getClassId().level() == 3)
  2065.                 sendPacket(SystemMessageId.THIRD_CLASS_TRANSFER);
  2066.             else
  2067.                 sendPacket(SystemMessageId.CLASS_TRANSFER);
  2068.            
  2069.             // Update class icon in party and clan
  2070.             if (isInParty())
  2071.                 getParty().broadcastToPartyMembers(new PartySmallWindowUpdate(this));
  2072.            
  2073.             if (getClan() != null)
  2074.                 getClan().broadcastToOnlineMembers(new PledgeShowMemberListUpdate(this));
  2075.            
  2076.             if (Config.AUTO_LEARN_SKILLS)
  2077.                 rewardSkills();
  2078.         }
  2079.         finally
  2080.         {
  2081.             _subclassLock.unlock();
  2082.         }
  2083.     }
  2084.    
  2085.     /**
  2086.      * @return the Experience of the L2PlayerInstance.
  2087.      */
  2088.     public long getExp()
  2089.     {
  2090.         return getStat().getExp();
  2091.     }
  2092.    
  2093.     public void setActiveEnchantItem(L2ItemInstance scroll)
  2094.     {
  2095.         _activeEnchantItem = scroll;
  2096.     }
  2097.    
  2098.     public L2ItemInstance getActiveEnchantItem()
  2099.     {
  2100.         return _activeEnchantItem;
  2101.     }
  2102.    
  2103.     /**
  2104.      * Set the fists weapon of the L2PlayerInstance (used when no weapon is equipped).
  2105.      *
  2106.      * @param weaponItem The fists L2Weapon to set to the L2PlayerInstance
  2107.      */
  2108.     public void setFistsWeaponItem(L2Weapon weaponItem)
  2109.     {
  2110.         _fistsWeaponItem = weaponItem;
  2111.     }
  2112.    
  2113.     /**
  2114.      * @return The fists weapon of the L2PlayerInstance (used when no weapon is equipped).
  2115.      */
  2116.     public L2Weapon getFistsWeaponItem()
  2117.     {
  2118.         return _fistsWeaponItem;
  2119.     }
  2120.    
  2121.     /**
  2122.      * @param classId The classId to test.
  2123.      * @return The fists weapon of the L2PlayerInstance Class (used when no weapon is equipped).
  2124.      */
  2125.     public static L2Weapon findFistsWeaponItem(int classId)
  2126.     {
  2127.         L2Weapon weaponItem = null;
  2128.         if ((classId >= 0x00) && (classId <= 0x09))
  2129.         {
  2130.             // human fighter fists
  2131.             L2Item temp = ItemTable.getInstance().getTemplate(246);
  2132.             weaponItem = (L2Weapon)temp;
  2133.         }
  2134.         else if ((classId >= 0x0a) && (classId <= 0x11))
  2135.         {
  2136.             // human mage fists
  2137.             L2Item temp = ItemTable.getInstance().getTemplate(251);
  2138.             weaponItem = (L2Weapon)temp;
  2139.         }
  2140.         else if ((classId >= 0x12) && (classId <= 0x18))
  2141.         {
  2142.             // elven fighter fists
  2143.             L2Item temp = ItemTable.getInstance().getTemplate(244);
  2144.             weaponItem = (L2Weapon)temp;
  2145.         }
  2146.         else if ((classId >= 0x19) && (classId <= 0x1e))
  2147.         {
  2148.             // elven mage fists
  2149.             L2Item temp = ItemTable.getInstance().getTemplate(249);
  2150.             weaponItem = (L2Weapon)temp;
  2151.         }
  2152.         else if ((classId >= 0x1f) && (classId <= 0x25))
  2153.         {
  2154.             // dark elven fighter fists
  2155.             L2Item temp = ItemTable.getInstance().getTemplate(245);
  2156.             weaponItem = (L2Weapon)temp;
  2157.         }
  2158.         else if ((classId >= 0x26) && (classId <= 0x2b))
  2159.         {
  2160.             // dark elven mage fists
  2161.             L2Item temp = ItemTable.getInstance().getTemplate(250);
  2162.             weaponItem = (L2Weapon)temp;
  2163.         }
  2164.         else if ((classId >= 0x2c) && (classId <= 0x30))
  2165.         {
  2166.             // orc fighter fists
  2167.             L2Item temp = ItemTable.getInstance().getTemplate(248);
  2168.             weaponItem = (L2Weapon)temp;
  2169.         }
  2170.         else if ((classId >= 0x31) && (classId <= 0x34))
  2171.         {
  2172.             // orc mage fists
  2173.             L2Item temp = ItemTable.getInstance().getTemplate(252);
  2174.             weaponItem = (L2Weapon)temp;
  2175.         }
  2176.         else if ((classId >= 0x35) && (classId <= 0x39))
  2177.         {
  2178.             // dwarven fists
  2179.             L2Item temp = ItemTable.getInstance().getTemplate(247);
  2180.             weaponItem = (L2Weapon)temp;
  2181.         }
  2182.        
  2183.         return weaponItem;
  2184.     }
  2185.    
  2186.     /**
  2187.      * This method is kinda polymorph :<BR>
  2188.      * <BR>
  2189.      * <li>it gives proper Expertise, Dwarven && Common Craft skill level ;</li> <li>it controls the
  2190.      * Lucky skill (remove at lvl 10) ;</li> <li>it finally sends the skill list.</li>
  2191.      */
  2192.     public void rewardSkills()
  2193.     {
  2194.         // Get the Level of the L2PlayerInstance
  2195.         int lvl = getLevel();
  2196.        
  2197.         // Remove the Lucky skill once reached lvl 10.
  2198.         if (getSkillLevel(L2Skill.SKILL_LUCKY) > 0 && lvl >= 10)
  2199.             removeSkill(FrequentSkill.LUCKY.getSkill());
  2200.        
  2201.         // Calculate the current higher Expertise of the L2PlayerInstance
  2202.         for (int i = 0; i < EXPERTISE_LEVELS.length; i++)
  2203.         {
  2204.             if (lvl >= EXPERTISE_LEVELS[i])
  2205.                 setExpertiseIndex(i);
  2206.         }
  2207.        
  2208.         // Add the Expertise skill corresponding to its Expertise level
  2209.         if (getExpertiseIndex() > 0)
  2210.         {
  2211.             L2Skill skill = SkillTable.getInstance().getInfo(239, getExpertiseIndex());
  2212.             addSkill(skill, true);
  2213.         }
  2214.        
  2215.         // Active skill dwarven craft
  2216.         if (getSkillLevel(1321) < 1 && getClassId().equalsOrChildOf(ClassId.dwarvenFighter))
  2217.         {
  2218.             L2Skill skill = FrequentSkill.DWARVEN_CRAFT.getSkill();
  2219.             addSkill(skill, true);
  2220.         }
  2221.        
  2222.         // Active skill common craft
  2223.         if (getSkillLevel(1322) < 1)
  2224.         {
  2225.             L2Skill skill = FrequentSkill.COMMON_CRAFT.getSkill();
  2226.             addSkill(skill, true);
  2227.         }
  2228.        
  2229.         for (int i = 0; i < COMMON_CRAFT_LEVELS.length; i++)
  2230.         {
  2231.             if (lvl >= COMMON_CRAFT_LEVELS[i] && getSkillLevel(1320) < (i + 1))
  2232.             {
  2233.                 L2Skill skill = SkillTable.getInstance().getInfo(1320, (i + 1));
  2234.                 addSkill(skill, true);
  2235.             }
  2236.         }
  2237.        
  2238.         // Auto-Learn skills if activated
  2239.         if (Config.AUTO_LEARN_SKILLS)
  2240.             giveAvailableSkills();
  2241.        
  2242.         sendSkillList();
  2243.     }
  2244.    
  2245.     /**
  2246.      * Regive all skills which aren't saved to database, like Noble, Hero, Clan Skills
  2247.      */
  2248.     private void regiveTemporarySkills()
  2249.     {
  2250.         // Do not call this on enterworld or char load
  2251.        
  2252.         // Add noble skills if noble
  2253.         if (isNoble())
  2254.             setNoble(true, false);
  2255.        
  2256.         // Add Hero skills if hero
  2257.         if (isHero())
  2258.             setHero(true);
  2259.        
  2260.         // Add clan skills
  2261.         if (getClan() != null && getClan().getReputationScore() >= 0)
  2262.         {
  2263.             L2Skill[] skills = getClan().getAllSkills();
  2264.             for (L2Skill sk : skills)
  2265.             {
  2266.                 if (sk.getMinPledgeClass() <= getPledgeClass())
  2267.                     addSkill(sk, false);
  2268.             }
  2269.         }
  2270.        
  2271.         // Reload passive skills from armors / jewels / weapons
  2272.         getInventory().reloadEquippedItems();
  2273.        
  2274.         // Add Death Penalty Buff Level
  2275.         restoreDeathPenaltyBuffLevel();
  2276.     }
  2277.    
  2278.     /**
  2279.      * Give all available skills to the player.
  2280.      *
  2281.      * @return The number of given skills.
  2282.      */
  2283.     public int giveAvailableSkills()
  2284.     {
  2285.         int result = 0;
  2286.         for (L2SkillLearn sl : SkillTreeTable.getInstance().getAllAvailableSkills(this, getClassId()))
  2287.         {
  2288.             addSkill(SkillTable.getInstance().getInfo(sl.getId(), sl.getLevel()), true);
  2289.             result++;
  2290.         }
  2291.         return result;
  2292.     }
  2293.    
  2294.     /**
  2295.      * @return The Race object of the L2PlayerInstance.
  2296.      */
  2297.     public Race getRace()
  2298.     {
  2299.         if (!isSubClassActive())
  2300.             return getTemplate().race;
  2301.        
  2302.         L2PlayerTemplate charTemp = CharTemplateTable.getInstance().getTemplate(_baseClass);
  2303.         return charTemp.race;
  2304.     }
  2305.    
  2306.     public L2Radar getRadar()
  2307.     {
  2308.         return _radar;
  2309.     }
  2310.    
  2311.     /**
  2312.      * @return the SP amount of the L2PlayerInstance.
  2313.      */
  2314.     public int getSp()
  2315.     {
  2316.         return getStat().getSp();
  2317.     }
  2318.    
  2319.     /**
  2320.      * @param castleId The castle to check.
  2321.      * @return True if this L2PlayerInstance is a clan leader in ownership of the passed castle.
  2322.      */
  2323.     public boolean isCastleLord(int castleId)
  2324.     {
  2325.         L2Clan clan = getClan();
  2326.        
  2327.         // player has clan and is the clan leader, check the castle info
  2328.         if ((clan != null) && (clan.getLeader().getPlayerInstance() == this))
  2329.         {
  2330.             // if the clan has a castle and it is actually the queried castle, return true
  2331.             Castle castle = CastleManager.getInstance().getCastleByOwner(clan);
  2332.             if ((castle != null) && (castle == CastleManager.getInstance().getCastleById(castleId)))
  2333.                 return true;
  2334.         }
  2335.        
  2336.         return false;
  2337.     }
  2338.    
  2339.     /**
  2340.      * @return The Clan Identifier of the L2PlayerInstance.
  2341.      */
  2342.     public int getClanId()
  2343.     {
  2344.         return _clanId;
  2345.     }
  2346.    
  2347.     /**
  2348.      * @return The Clan Crest Identifier of the L2PlayerInstance or 0.
  2349.      */
  2350.     public int getClanCrestId()
  2351.     {
  2352.         if (_clan != null)
  2353.             return _clan.getCrestId();
  2354.        
  2355.         return 0;
  2356.     }
  2357.    
  2358.     /**
  2359.      * @return The Clan CrestLarge Identifier or 0
  2360.      */
  2361.     public int getClanCrestLargeId()
  2362.     {
  2363.         if (_clan != null)
  2364.             return _clan.getCrestLargeId();
  2365.        
  2366.         return 0;
  2367.     }
  2368.    
  2369.     public long getClanJoinExpiryTime()
  2370.     {
  2371.         return _clanJoinExpiryTime;
  2372.     }
  2373.    
  2374.     public void setClanJoinExpiryTime(long time)
  2375.     {
  2376.         _clanJoinExpiryTime = time;
  2377.     }
  2378.    
  2379.     public long getClanCreateExpiryTime()
  2380.     {
  2381.         return _clanCreateExpiryTime;
  2382.     }
  2383.    
  2384.     public void setClanCreateExpiryTime(long time)
  2385.     {
  2386.         _clanCreateExpiryTime = time;
  2387.     }
  2388.    
  2389.     public void setOnlineTime(long time)
  2390.     {
  2391.         _onlineTime = time;
  2392.         _onlineBeginTime = System.currentTimeMillis();
  2393.     }
  2394.    
  2395.     /**
  2396.      * Return the PlayerInventory Inventory of the L2PlayerInstance contained in _inventory.
  2397.      */
  2398.     @Override
  2399.     public PlayerInventory getInventory()
  2400.     {
  2401.         return _inventory;
  2402.     }
  2403.    
  2404.     /**
  2405.      * Delete a ShortCut of the L2PlayerInstance _shortCuts.
  2406.      *
  2407.      * @param objectId The shortcut id.
  2408.      */
  2409.     public void removeItemFromShortCut(int objectId)
  2410.     {
  2411.         _shortCuts.deleteShortCutByObjectId(objectId);
  2412.     }
  2413.    
  2414.     /**
  2415.      * @return True if the L2PlayerInstance is sitting.
  2416.      */
  2417.     public boolean isSitting()
  2418.     {
  2419.         return _waitTypeSitting;
  2420.     }
  2421.    
  2422.     /**
  2423.      * Set _waitTypeSitting to given value.
  2424.      *
  2425.      * @param state A boolean.
  2426.      */
  2427.     public void setIsSitting(boolean state)
  2428.     {
  2429.         _waitTypeSitting = state;
  2430.     }
  2431.    
  2432.     /**
  2433.      * Sit down the L2PlayerInstance, set the AI Intention to AI_INTENTION_REST and send a
  2434.      * Server->Client ChangeWaitType packet (broadcast)
  2435.      */
  2436.     public void sitDown()
  2437.     {
  2438.         sitDown(true);
  2439.     }
  2440.    
  2441.     public void sitDown(boolean checkCast)
  2442.     {
  2443.         if (checkCast && isCastingNow())
  2444.             return;
  2445.        
  2446.         if (!_waitTypeSitting && !isAttackingDisabled() && !isOutOfControl() && !isImmobilized())
  2447.         {
  2448.             breakAttack();
  2449.             setIsSitting(true);
  2450.             broadcastPacket(new ChangeWaitType(this, ChangeWaitType.WT_SITTING));
  2451.            
  2452.             // Schedule a sit down task to wait for the animation to finish
  2453.             getAI().setIntention(CtrlIntention.AI_INTENTION_REST);
  2454.             ThreadPoolManager.getInstance().scheduleGeneral(new SitDownTask(), 2500);
  2455.             setIsParalyzed(true);
  2456.         }
  2457.     }
  2458.    
  2459.     /**
  2460.      * Sit down Task
  2461.      */
  2462.     protected class SitDownTask implements Runnable
  2463.     {
  2464.         @Override
  2465.         public void run()
  2466.         {
  2467.             setIsParalyzed(false);
  2468.         }
  2469.     }
  2470.    
  2471.     /**
  2472.      * Stand up Task
  2473.      */
  2474.     protected class StandUpTask implements Runnable
  2475.     {
  2476.         @Override
  2477.         public void run()
  2478.         {
  2479.             setIsSitting(false);
  2480.             getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
  2481.         }
  2482.     }
  2483.    
  2484.     /**
  2485.      * Stand up the L2PlayerInstance, set the AI Intention to AI_INTENTION_IDLE and send a
  2486.      * Server->Client ChangeWaitType packet (broadcast)
  2487.      */
  2488.     public void standUp()
  2489.     {
  2490.         if (_waitTypeSitting && !isInStoreMode() && !isAlikeDead())
  2491.         {
  2492.             if (_effects.isAffected(CharEffectList.EFFECT_FLAG_RELAXING))
  2493.                 stopEffects(L2EffectType.RELAXING);
  2494.            
  2495.             broadcastPacket(new ChangeWaitType(this, ChangeWaitType.WT_STANDING));
  2496.             // Schedule a stand up task to wait for the animation to finish
  2497.             ThreadPoolManager.getInstance().scheduleGeneral(new StandUpTask(), 2500);
  2498.         }
  2499.     }
  2500.    
  2501.     /**
  2502.      * Stands up and close any opened shop window, if any.
  2503.      */
  2504.     public void forceStandUp()
  2505.     {
  2506.         // Cancels any shop types.
  2507.         if (getPrivateStoreType() != 0)
  2508.         {
  2509.             setPrivateStoreType(L2PlayerInstance.STORE_PRIVATE_NONE);
  2510.             broadcastUserInfo();
  2511.         }
  2512.        
  2513.         // Stand up.
  2514.         if (isSitting())
  2515.             standUp();
  2516.     }
  2517.    
  2518.     /**
  2519.      * @return The PlayerWarehouse object of the L2PlayerInstance.
  2520.      */
  2521.     public PlayerWarehouse getWarehouse()
  2522.     {
  2523.         if (_warehouse == null)
  2524.         {
  2525.             _warehouse = new PlayerWarehouse(this);
  2526.             _warehouse.restore();
  2527.         }
  2528.         return _warehouse;
  2529.     }
  2530.    
  2531.     /**
  2532.      * Free memory used by Warehouse
  2533.      */
  2534.     public void clearWarehouse()
  2535.     {
  2536.         if (_warehouse != null)
  2537.             _warehouse.deleteMe();
  2538.        
  2539.         _warehouse = null;
  2540.     }
  2541.    
  2542.     /**
  2543.      * @return The PlayerFreight object of the L2PlayerInstance.
  2544.      */
  2545.     public PlayerFreight getFreight()
  2546.     {
  2547.         if (_freight == null)
  2548.         {
  2549.             _freight = new PlayerFreight(this);
  2550.             _freight.restore();
  2551.         }
  2552.         return _freight;
  2553.     }
  2554.    
  2555.     /**
  2556.      * Free memory used by Freight
  2557.      */
  2558.     public void clearFreight()
  2559.     {
  2560.         if (_freight != null)
  2561.             _freight.deleteMe();
  2562.        
  2563.         _freight = null;
  2564.     }
  2565.    
  2566.     /**
  2567.      * @param objectId The id of the owner.
  2568.      * @return deposited PlayerFreight object for the objectId or create new if not existing.
  2569.      */
  2570.     public PlayerFreight getDepositedFreight(int objectId)
  2571.     {
  2572.         if (_depositedFreight == null)
  2573.             _depositedFreight = new ArrayList<>();
  2574.         else
  2575.         {
  2576.             for (PlayerFreight freight : _depositedFreight)
  2577.             {
  2578.                 if (freight != null && freight.getOwnerId() == objectId)
  2579.                     return freight;
  2580.             }
  2581.         }
  2582.        
  2583.         PlayerFreight freight = new PlayerFreight(null);
  2584.         freight.doQuickRestore(objectId);
  2585.         _depositedFreight.add(freight);
  2586.         return freight;
  2587.     }
  2588.    
  2589.     /**
  2590.      * Clear memory used by deposited freight
  2591.      */
  2592.     public void clearDepositedFreight()
  2593.     {
  2594.         if (_depositedFreight == null)
  2595.             return;
  2596.        
  2597.         for (PlayerFreight freight : _depositedFreight)
  2598.         {
  2599.             if (freight != null)
  2600.                 freight.deleteMe();
  2601.            
  2602.             _depositedFreight.clear();
  2603.             _depositedFreight = null;
  2604.         }
  2605.     }
  2606.    
  2607.     /**
  2608.      * @return The Identifier of the L2PlayerInstance.
  2609.      */
  2610.     public int getCharId()
  2611.     {
  2612.         return _charId;
  2613.     }
  2614.    
  2615.     /**
  2616.      * Set the Identifier of the L2PlayerInstance.
  2617.      *
  2618.      * @param charId The CharId.
  2619.      */
  2620.     public void setCharId(int charId)
  2621.     {
  2622.         _charId = charId;
  2623.     }
  2624.    
  2625.     /**
  2626.      * @return The Adena amount of the L2PlayerInstance.
  2627.      */
  2628.     public int getAdena()
  2629.     {
  2630.         return _inventory.getAdena();
  2631.     }
  2632.    
  2633.     /**
  2634.      * @return The Ancient Adena amount of the L2PlayerInstance.
  2635.      */
  2636.     public int getAncientAdena()
  2637.     {
  2638.         return _inventory.getAncientAdena();
  2639.     }
  2640.    
  2641.     /**
  2642.      * Add adena to Inventory of the L2PlayerInstance and send a Server->Client InventoryUpdate
  2643.      * packet to the L2PlayerInstance.
  2644.      *
  2645.      * @param process String Identifier of process triggering this action
  2646.      * @param count int Quantity of adena to be added
  2647.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2648.      *            item in transformation
  2649.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2650.      */
  2651.     public void addAdena(String process, int count, L2Object reference, boolean sendMessage)
  2652.     {
  2653.         if (sendMessage)
  2654.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.EARNED_S1_ADENA).addNumber(count));
  2655.        
  2656.         if (count > 0)
  2657.         {
  2658.             _inventory.addAdena(process, count, this, reference);
  2659.            
  2660.             InventoryUpdate iu = new InventoryUpdate();
  2661.             iu.addItem(_inventory.getAdenaInstance());
  2662.             sendPacket(iu);
  2663.         }
  2664.     }
  2665.    
  2666.     /**
  2667.      * Reduce adena in Inventory of the L2PlayerInstance and send a Server->Client InventoryUpdate
  2668.      * packet to the L2PlayerInstance.
  2669.      *
  2670.      * @param process String Identifier of process triggering this action
  2671.      * @param count int Quantity of adena to be reduced
  2672.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2673.      *            item in transformation
  2674.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2675.      * @return boolean informing if the action was successfull
  2676.      */
  2677.     public boolean reduceAdena(String process, int count, L2Object reference, boolean sendMessage)
  2678.     {
  2679.         if (count > getAdena())
  2680.         {
  2681.             if (sendMessage)
  2682.                 sendPacket(SystemMessageId.YOU_NOT_ENOUGH_ADENA);
  2683.            
  2684.             return false;
  2685.         }
  2686.        
  2687.         if (count > 0)
  2688.         {
  2689.             L2ItemInstance adenaItem = _inventory.getAdenaInstance();
  2690.             if (!_inventory.reduceAdena(process, count, this, reference))
  2691.                 return false;
  2692.            
  2693.             // Send update packet
  2694.             InventoryUpdate iu = new InventoryUpdate();
  2695.             iu.addItem(adenaItem);
  2696.             sendPacket(iu);
  2697.            
  2698.             if (sendMessage)
  2699.                 sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_DISAPPEARED_ADENA).addNumber(count));
  2700.         }
  2701.         return true;
  2702.     }
  2703.    
  2704.     /**
  2705.      * Add ancient adena to Inventory of the L2PlayerInstance and send a Server->Client
  2706.      * InventoryUpdate packet to the L2PlayerInstance.
  2707.      *
  2708.      * @param process String Identifier of process triggering this action
  2709.      * @param count int Quantity of ancient adena to be added
  2710.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2711.      *            item in transformation
  2712.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2713.      */
  2714.     public void addAncientAdena(String process, int count, L2Object reference, boolean sendMessage)
  2715.     {
  2716.         if (sendMessage)
  2717.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S)
  2718.                     .addItemName(PlayerInventory.ANCIENT_ADENA_ID).addNumber(count));
  2719.        
  2720.         if (count > 0)
  2721.         {
  2722.             _inventory.addAncientAdena(process, count, this, reference);
  2723.            
  2724.             InventoryUpdate iu = new InventoryUpdate();
  2725.             iu.addItem(_inventory.getAncientAdenaInstance());
  2726.             sendPacket(iu);
  2727.         }
  2728.     }
  2729.    
  2730.     /**
  2731.      * Reduce ancient adena in Inventory of the L2PlayerInstance and send a Server->Client
  2732.      * InventoryUpdate packet to the L2PlayerInstance.
  2733.      *
  2734.      * @param process String Identifier of process triggering this action
  2735.      * @param count int Quantity of ancient adena to be reduced
  2736.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2737.      *            item in transformation
  2738.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2739.      * @return boolean informing if the action was successfull
  2740.      */
  2741.     public boolean reduceAncientAdena(String process, int count, L2Object reference, boolean sendMessage)
  2742.     {
  2743.         if (count > getAncientAdena())
  2744.         {
  2745.             if (sendMessage)
  2746.                 sendPacket(SystemMessageId.YOU_NOT_ENOUGH_ADENA);
  2747.            
  2748.             return false;
  2749.         }
  2750.        
  2751.         if (count > 0)
  2752.         {
  2753.             L2ItemInstance ancientAdenaItem = _inventory.getAncientAdenaInstance();
  2754.             if (!_inventory.reduceAncientAdena(process, count, this, reference))
  2755.                 return false;
  2756.            
  2757.             InventoryUpdate iu = new InventoryUpdate();
  2758.             iu.addItem(ancientAdenaItem);
  2759.             sendPacket(iu);
  2760.            
  2761.             if (sendMessage)
  2762.             {
  2763.                 if (count > 1)
  2764.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED)
  2765.                             .addItemName(PlayerInventory.ANCIENT_ADENA_ID).addItemNumber(count));
  2766.                 else
  2767.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_DISAPPEARED).addItemName(
  2768.                             PlayerInventory.ANCIENT_ADENA_ID));
  2769.             }
  2770.         }
  2771.         return true;
  2772.     }
  2773.    
  2774.     /**
  2775.      * Adds item to inventory and send a Server->Client InventoryUpdate packet to the
  2776.      * L2PlayerInstance.
  2777.      *
  2778.      * @param process String Identifier of process triggering this action
  2779.      * @param item L2ItemInstance to be added
  2780.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2781.      *            item in transformation
  2782.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2783.      */
  2784.     public void addItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage)
  2785.     {
  2786.         if (item.getCount() > 0)
  2787.         {
  2788.             // Sends message to client if requested
  2789.             if (sendMessage)
  2790.             {
  2791.                 if (item.getCount() > 1)
  2792.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_PICKED_UP_S2_S1).addItemName(item)
  2793.                             .addNumber(item.getCount()));
  2794.                 else if (item.getEnchantLevel() > 0)
  2795.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_PICKED_UP_A_S1_S2)
  2796.                             .addNumber(item.getEnchantLevel()).addItemName(item));
  2797.                 else
  2798.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_PICKED_UP_S1).addItemName(item));
  2799.             }
  2800.            
  2801.             // Add the item to inventory
  2802.             L2ItemInstance newitem = _inventory.addItem(process, item, this, reference);
  2803.            
  2804.             // Send inventory update packet
  2805.             InventoryUpdate playerIU = new InventoryUpdate();
  2806.             playerIU.addItem(newitem);
  2807.             sendPacket(playerIU);
  2808.            
  2809.             // Update current load as well
  2810.             StatusUpdate su = new StatusUpdate(this);
  2811.             su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad());
  2812.             sendPacket(su);
  2813.            
  2814.             // If over capacity, drop the item
  2815.             if (!isGM() && !_inventory.validateCapacity(0, item.isQuestItem()) && newitem.isDropable()
  2816.                     && (!newitem.isStackable() || newitem.getLastChange() != L2ItemInstance.MODIFIED))
  2817.                 dropItem("InvDrop", newitem, null, true, true);
  2818.             // Cursed Weapon
  2819.             else if (CursedWeaponsManager.getInstance().isCursed(newitem.getItemId()))
  2820.                 CursedWeaponsManager.getInstance().activate(this, newitem);
  2821.            
  2822.             // If you pickup arrows.
  2823.             if (item.getItem().getItemType() == L2EtcItemType.ARROW)
  2824.             {
  2825.                 // If a bow is equipped, try to equip them if no arrows is currently equipped.
  2826.                 L2Weapon currentWeapon = getActiveWeaponItem();
  2827.                 if (currentWeapon != null && currentWeapon.getItemType() == L2WeaponType.BOW
  2828.                         && getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null)
  2829.                     checkAndEquipArrows();
  2830.             }
  2831.         }
  2832.     }
  2833.    
  2834.     /**
  2835.      * Adds item to Inventory and send a Server->Client InventoryUpdate packet to the
  2836.      * L2PlayerInstance.
  2837.      *
  2838.      * @param process String Identifier of process triggering this action
  2839.      * @param itemId int Item Identifier of the item to be added
  2840.      * @param count int Quantity of items to be added
  2841.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2842.      *            item in transformation
  2843.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2844.      * @return The created L2ItemInstance.
  2845.      */
  2846.     public L2ItemInstance addItem(String process, int itemId, int count, L2Object reference, boolean sendMessage)
  2847.     {
  2848.         if (count > 0)
  2849.         {
  2850.             L2ItemInstance item = null;
  2851.            
  2852.             if (ItemTable.getInstance().getTemplate(itemId) != null)
  2853.                 item = ItemTable.getInstance().createDummyItem(itemId);
  2854.             else
  2855.             {
  2856.                 _log.log(Level.SEVERE, "Item doesn't exist so cannot be added. Item ID: " + itemId);
  2857.                 return null;
  2858.             }
  2859.             // Sends message to client if requested
  2860.             if (sendMessage
  2861.                     && ((!isCastingNow() && item.getItemType() == L2EtcItemType.HERB) || item.getItemType() != L2EtcItemType.HERB))
  2862.             {
  2863.                 if (count > 1)
  2864.                 {
  2865.                     if (process.equalsIgnoreCase("sweep") || process.equalsIgnoreCase("Quest"))
  2866.                         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S).addItemName(itemId)
  2867.                                 .addItemNumber(count));
  2868.                     else
  2869.                         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_PICKED_UP_S2_S1)
  2870.                                 .addItemName(itemId).addItemNumber(count));
  2871.                 }
  2872.                 else
  2873.                 {
  2874.                     if (process.equalsIgnoreCase("sweep") || process.equalsIgnoreCase("Quest"))
  2875.                         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.EARNED_ITEM_S1).addItemName(itemId));
  2876.                     else
  2877.                         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_PICKED_UP_S1).addItemName(itemId));
  2878.                 }
  2879.             }
  2880.             // Auto use herbs - autoloot
  2881.             if (item.getItemType() == L2EtcItemType.HERB) // If item is herb dont add it to iv :]
  2882.             {
  2883.                 if (!isCastingNow())
  2884.                 {
  2885.                     L2ItemInstance herb = new L2ItemInstance(_charId, itemId);
  2886.                     IItemHandler handler = ItemHandler.getInstance().getItemHandler(herb.getEtcItem());
  2887.                     if (handler != null)
  2888.                     {
  2889.                         handler.useItem(this, herb, false);
  2890.                         if (_herbstask >= 100)
  2891.                             _herbstask -= 100;
  2892.                     }
  2893.                 }
  2894.                 else
  2895.                 {
  2896.                     _herbstask += 100;
  2897.                     ThreadPoolManager.getInstance().scheduleAi(
  2898.                             new HerbTask(process, itemId, count, reference, sendMessage), _herbstask);
  2899.                 }
  2900.             }
  2901.             else
  2902.             {
  2903.                 // Add the item to inventory
  2904.                 L2ItemInstance createdItem = _inventory.addItem(process, itemId, count, this, reference);
  2905.                
  2906.                 // If over capacity, drop the item
  2907.                 if (!isGM() && !_inventory.validateCapacity(0, item.isQuestItem()) && createdItem.isDropable()
  2908.                         && (!createdItem.isStackable() || createdItem.getLastChange() != L2ItemInstance.MODIFIED))
  2909.                     dropItem("InvDrop", createdItem, null, true);
  2910.                 // Cursed Weapon
  2911.                 else if (CursedWeaponsManager.getInstance().isCursed(createdItem.getItemId()))
  2912.                     CursedWeaponsManager.getInstance().activate(this, createdItem);
  2913.                
  2914.                 return createdItem;
  2915.             }
  2916.         }
  2917.         return null;
  2918.     }
  2919.    
  2920.     /**
  2921.      * Destroy item from inventory and send a Server->Client InventoryUpdate packet to the
  2922.      * L2PlayerInstance.
  2923.      *
  2924.      * @param process String Identifier of process triggering this action
  2925.      * @param item L2ItemInstance to be destroyed
  2926.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2927.      *            item in transformation
  2928.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2929.      * @return boolean informing if the action was successfull
  2930.      */
  2931.     public boolean destroyItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage)
  2932.     {
  2933.         return this.destroyItem(process, item, item.getCount(), reference, sendMessage);
  2934.     }
  2935.    
  2936.     /**
  2937.      * Destroy item from inventory and send a Server->Client InventoryUpdate packet to the
  2938.      * L2PlayerInstance.
  2939.      *
  2940.      * @param process String Identifier of process triggering this action
  2941.      * @param item L2ItemInstance to be destroyed
  2942.      * @param count int Quantity of ancient adena to be reduced
  2943.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2944.      *            item in transformation
  2945.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2946.      * @return boolean informing if the action was successfull
  2947.      */
  2948.     public boolean destroyItem(String process, L2ItemInstance item, int count, L2Object reference, boolean sendMessage)
  2949.     {
  2950.         item = _inventory.destroyItem(process, item, count, this, reference);
  2951.        
  2952.         if (item == null)
  2953.         {
  2954.             if (sendMessage)
  2955.                 sendPacket(SystemMessageId.NOT_ENOUGH_ITEMS);
  2956.            
  2957.             return false;
  2958.         }
  2959.        
  2960.         // Send inventory update packet
  2961.         InventoryUpdate playerIU = new InventoryUpdate();
  2962.         playerIU.addItem(item);
  2963.         sendPacket(playerIU);
  2964.        
  2965.         // Update current load as well
  2966.         StatusUpdate su = new StatusUpdate(this);
  2967.         su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad());
  2968.         sendPacket(su);
  2969.        
  2970.         // Sends message to client if requested
  2971.         if (sendMessage)
  2972.         {
  2973.             if (count > 1)
  2974.                 sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED).addItemName(item)
  2975.                         .addItemNumber(count));
  2976.             else
  2977.                 sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_DISAPPEARED).addItemName(item));
  2978.         }
  2979.         return true;
  2980.     }
  2981.    
  2982.     /**
  2983.      * Destroys item from inventory and send a Server->Client InventoryUpdate packet to the
  2984.      * L2PlayerInstance.
  2985.      *
  2986.      * @param process String Identifier of process triggering this action
  2987.      * @param objectId int Item Instance identifier of the item to be destroyed
  2988.      * @param count int Quantity of items to be destroyed
  2989.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  2990.      *            item in transformation
  2991.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  2992.      * @return boolean informing if the action was successfull
  2993.      */
  2994.     @Override
  2995.     public boolean destroyItem(String process, int objectId, int count, L2Object reference, boolean sendMessage)
  2996.     {
  2997.         L2ItemInstance item = _inventory.getItemByObjectId(objectId);
  2998.        
  2999.         if (item == null)
  3000.         {
  3001.             if (sendMessage)
  3002.                 sendPacket(SystemMessageId.NOT_ENOUGH_ITEMS);
  3003.            
  3004.             return false;
  3005.         }
  3006.         return this.destroyItem(process, item, count, reference, sendMessage);
  3007.     }
  3008.    
  3009.     /**
  3010.      * Destroys shots from inventory without logging and only occasional saving to database. Sends a
  3011.      * Server->Client InventoryUpdate packet to the L2PlayerInstance.
  3012.      *
  3013.      * @param process String Identifier of process triggering this action
  3014.      * @param objectId int Item Instance identifier of the item to be destroyed
  3015.      * @param count int Quantity of items to be destroyed
  3016.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  3017.      *            item in transformation
  3018.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  3019.      * @return boolean informing if the action was successfull
  3020.      */
  3021.     public boolean destroyItemWithoutTrace(String process, int objectId, int count, L2Object reference,
  3022.             boolean sendMessage)
  3023.     {
  3024.         L2ItemInstance item = _inventory.getItemByObjectId(objectId);
  3025.        
  3026.         if (item == null || item.getCount() < count)
  3027.         {
  3028.             if (sendMessage)
  3029.                 sendPacket(SystemMessageId.NOT_ENOUGH_ITEMS);
  3030.            
  3031.             return false;
  3032.         }
  3033.        
  3034.         return this.destroyItem(null, item, count, reference, sendMessage);
  3035.     }
  3036.    
  3037.     /**
  3038.      * Destroy item from inventory by using its <B>itemId</B> and send a Server->Client
  3039.      * InventoryUpdate packet to the L2PlayerInstance.
  3040.      *
  3041.      * @param process String Identifier of process triggering this action
  3042.      * @param itemId int Item identifier of the item to be destroyed
  3043.      * @param count int Quantity of items to be destroyed
  3044.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  3045.      *            item in transformation
  3046.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  3047.      * @return boolean informing if the action was successfull
  3048.      */
  3049.     @Override
  3050.     public boolean destroyItemByItemId(String process, int itemId, int count, L2Object reference, boolean sendMessage)
  3051.     {
  3052.         if (itemId == 57)
  3053.             return reduceAdena(process, count, reference, sendMessage);
  3054.        
  3055.         L2ItemInstance item = _inventory.getItemByItemId(itemId);
  3056.        
  3057.         if (item == null || item.getCount() < count
  3058.                 || _inventory.destroyItemByItemId(process, itemId, count, this, reference) == null)
  3059.         {
  3060.             if (sendMessage)
  3061.                 sendPacket(SystemMessageId.NOT_ENOUGH_ITEMS);
  3062.            
  3063.             return false;
  3064.         }
  3065.        
  3066.         // Send inventory update packet
  3067.         InventoryUpdate playerIU = new InventoryUpdate();
  3068.         playerIU.addItem(item);
  3069.         sendPacket(playerIU);
  3070.        
  3071.         // Update current load as well
  3072.         StatusUpdate su = new StatusUpdate(this);
  3073.         su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad());
  3074.         sendPacket(su);
  3075.        
  3076.         // Sends message to client if requested
  3077.         if (sendMessage)
  3078.         {
  3079.             if (count > 1)
  3080.                 sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED).addItemName(itemId)
  3081.                         .addItemNumber(count));
  3082.             else
  3083.                 sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_DISAPPEARED).addItemName(itemId));
  3084.         }
  3085.         return true;
  3086.     }
  3087.    
  3088.     /**
  3089.      * Transfers item to another ItemContainer and send a Server->Client InventoryUpdate packet to
  3090.      * the L2PlayerInstance.
  3091.      *
  3092.      * @param process String Identifier of process triggering this action
  3093.      * @param objectId int Item Identifier of the item to be transfered
  3094.      * @param count int Quantity of items to be transfered
  3095.      * @param target Inventory the Inventory target.
  3096.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  3097.      *            item in transformation
  3098.      * @return L2ItemInstance corresponding to the new item or the updated item in inventory
  3099.      */
  3100.     public L2ItemInstance transferItem(String process, int objectId, int count, Inventory target, L2Object reference)
  3101.     {
  3102.         final L2ItemInstance oldItem = checkItemManipulation(objectId, count);
  3103.         if (oldItem == null)
  3104.             return null;
  3105.        
  3106.         final L2ItemInstance newItem = getInventory().transferItem(process, objectId, count, target, this, reference);
  3107.         if (newItem == null)
  3108.             return null;
  3109.        
  3110.         // Send inventory update packet
  3111.         InventoryUpdate playerIU = new InventoryUpdate();
  3112.        
  3113.         if (oldItem.getCount() > 0 && oldItem != newItem)
  3114.             playerIU.addModifiedItem(oldItem);
  3115.         else
  3116.             playerIU.addRemovedItem(oldItem);
  3117.        
  3118.         sendPacket(playerIU);
  3119.        
  3120.         // Update current load as well
  3121.         StatusUpdate playerSU = new StatusUpdate(this);
  3122.         playerSU.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad());
  3123.         sendPacket(playerSU);
  3124.        
  3125.         // Send target update packet
  3126.         if (target instanceof PlayerInventory)
  3127.         {
  3128.             final L2PlayerInstance targetPlayer = ((PlayerInventory)target).getOwner();
  3129.            
  3130.             InventoryUpdate playerIU2 = new InventoryUpdate();
  3131.             if (newItem.getCount() > count)
  3132.                 playerIU2.addModifiedItem(newItem);
  3133.             else
  3134.                 playerIU2.addNewItem(newItem);
  3135.             targetPlayer.sendPacket(playerIU2);
  3136.            
  3137.             // Update current load as well
  3138.             playerSU = new StatusUpdate(targetPlayer);
  3139.             playerSU.addAttribute(StatusUpdate.CUR_LOAD, targetPlayer.getCurrentLoad());
  3140.             targetPlayer.sendPacket(playerSU);
  3141.         }
  3142.         else if (target instanceof PetInventory)
  3143.         {
  3144.             PetInventoryUpdate petIU = new PetInventoryUpdate();
  3145.             if (newItem.getCount() > count)
  3146.                 petIU.addModifiedItem(newItem);
  3147.             else
  3148.                 petIU.addNewItem(newItem);
  3149.             ((PetInventory)target).getOwner().getOwner().sendPacket(petIU);
  3150.         }
  3151.         return newItem;
  3152.     }
  3153.    
  3154.     /**
  3155.      * Drop item from inventory and send a Server->Client InventoryUpdate packet to the
  3156.      * L2PlayerInstance.
  3157.      *
  3158.      * @param process String Identifier of process triggering this action
  3159.      * @param item L2ItemInstance to be dropped
  3160.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  3161.      *            item in transformation
  3162.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  3163.      * @param protectItem whether or not dropped item must be protected temporary against other
  3164.      *            players
  3165.      * @return boolean informing if the action was successfull
  3166.      */
  3167.     public boolean dropItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage,
  3168.             boolean protectItem)
  3169.     {
  3170.         item = _inventory.dropItem(process, item, this, reference);
  3171.        
  3172.         if (item == null)
  3173.         {
  3174.             if (sendMessage)
  3175.                 sendPacket(SystemMessageId.NOT_ENOUGH_ITEMS);
  3176.            
  3177.             return false;
  3178.         }
  3179.        
  3180.         item.dropMe(this, getX() + Rnd.get(50) - 25, getY() + Rnd.get(50) - 25, getZ() + 20);
  3181.        
  3182.         if (Config.AUTODESTROY_ITEM_AFTER > 0 && Config.DESTROY_DROPPED_PLAYER_ITEM
  3183.                 && !Config.LIST_PROTECTED_ITEMS.contains(item.getItemId()))
  3184.         {
  3185.             if ((item.isEquipable() && Config.DESTROY_EQUIPABLE_PLAYER_ITEM) || !item.isEquipable())
  3186.                 ItemsAutoDestroy.getInstance().addItem(item);
  3187.         }
  3188.        
  3189.         if (Config.DESTROY_DROPPED_PLAYER_ITEM)
  3190.         {
  3191.             if (!item.isEquipable() || (item.isEquipable() && Config.DESTROY_EQUIPABLE_PLAYER_ITEM))
  3192.                 item.setProtected(false);
  3193.             else
  3194.                 item.setProtected(true);
  3195.         }
  3196.         else
  3197.             item.setProtected(true);
  3198.        
  3199.         // retail drop protection
  3200.         if (protectItem)
  3201.             item.getDropProtection().protect(this);
  3202.        
  3203.         // Send inventory update packet
  3204.         InventoryUpdate playerIU = new InventoryUpdate();
  3205.         playerIU.addItem(item);
  3206.         sendPacket(playerIU);
  3207.        
  3208.         // Update current load as well
  3209.         StatusUpdate su = new StatusUpdate(this);
  3210.         su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad());
  3211.         sendPacket(su);
  3212.        
  3213.         // Sends message to client if requested
  3214.         if (sendMessage)
  3215.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_DROPPED_S1).addItemName(item));
  3216.        
  3217.         return true;
  3218.     }
  3219.    
  3220.     public boolean dropItem(String process, L2ItemInstance item, L2Object reference, boolean sendMessage)
  3221.     {
  3222.         return dropItem(process, item, reference, sendMessage, false);
  3223.     }
  3224.    
  3225.     /**
  3226.      * Drop item from inventory by using its <B>objectID</B> and send a Server->Client
  3227.      * InventoryUpdate packet to the L2PlayerInstance.
  3228.      *
  3229.      * @param process String Identifier of process triggering this action
  3230.      * @param objectId int Item Instance identifier of the item to be dropped
  3231.      * @param count int Quantity of items to be dropped
  3232.      * @param x int coordinate for drop X
  3233.      * @param y int coordinate for drop Y
  3234.      * @param z int coordinate for drop Z
  3235.      * @param reference L2Object Object referencing current action like NPC selling item or previous
  3236.      *            item in transformation
  3237.      * @param sendMessage boolean Specifies whether to send message to Client about this action
  3238.      * @param protectItem boolean Activates drop protection on that item if true
  3239.      * @return L2ItemInstance corresponding to the new item or the updated item in inventory
  3240.      */
  3241.     public L2ItemInstance dropItem(String process, int objectId, int count, int x, int y, int z, L2Object reference,
  3242.             boolean sendMessage, boolean protectItem)
  3243.     {
  3244.         L2ItemInstance invitem = _inventory.getItemByObjectId(objectId);
  3245.         L2ItemInstance item = _inventory.dropItem(process, objectId, count, this, reference);
  3246.        
  3247.         if (item == null)
  3248.         {
  3249.             if (sendMessage)
  3250.                 sendPacket(SystemMessageId.NOT_ENOUGH_ITEMS);
  3251.            
  3252.             return null;
  3253.         }
  3254.        
  3255.         item.dropMe(this, x, y, z);
  3256.        
  3257.         if (Config.AUTODESTROY_ITEM_AFTER > 0 && Config.DESTROY_DROPPED_PLAYER_ITEM
  3258.                 && !Config.LIST_PROTECTED_ITEMS.contains(item.getItemId()))
  3259.         {
  3260.             if ((item.isEquipable() && Config.DESTROY_EQUIPABLE_PLAYER_ITEM) || !item.isEquipable())
  3261.                 ItemsAutoDestroy.getInstance().addItem(item);
  3262.         }
  3263.        
  3264.         if (Config.DESTROY_DROPPED_PLAYER_ITEM)
  3265.         {
  3266.             if (!item.isEquipable() || (item.isEquipable() && Config.DESTROY_EQUIPABLE_PLAYER_ITEM))
  3267.                 item.setProtected(false);
  3268.             else
  3269.                 item.setProtected(true);
  3270.         }
  3271.         else
  3272.             item.setProtected(true);
  3273.        
  3274.         // retail drop protection
  3275.         if (protectItem)
  3276.             item.getDropProtection().protect(this);
  3277.        
  3278.         // Send inventory update packet
  3279.         InventoryUpdate playerIU = new InventoryUpdate();
  3280.         playerIU.addItem(invitem);
  3281.         sendPacket(playerIU);
  3282.        
  3283.         // Update current load as well
  3284.         StatusUpdate su = new StatusUpdate(this);
  3285.         su.addAttribute(StatusUpdate.CUR_LOAD, getCurrentLoad());
  3286.         sendPacket(su);
  3287.        
  3288.         // Sends message to client if requested
  3289.         if (sendMessage)
  3290.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_DROPPED_S1).addItemName(item));
  3291.        
  3292.         return item;
  3293.     }
  3294.    
  3295.     public L2ItemInstance checkItemManipulation(int objectId, int count)
  3296.     {
  3297.         if (L2World.getInstance().findObject(objectId) == null)
  3298.             return null;
  3299.        
  3300.         final L2ItemInstance item = getInventory().getItemByObjectId(objectId);
  3301.        
  3302.         if (item == null || item.getOwnerId() != getObjectId())
  3303.             return null;
  3304.        
  3305.         if (count < 1 || (count > 1 && !item.isStackable()))
  3306.             return null;
  3307.        
  3308.         if (count > item.getCount())
  3309.             return null;
  3310.        
  3311.         // Pet is summoned and not the item that summoned the pet AND not the buggle from strider you're mounting
  3312.         if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId)
  3313.             return null;
  3314.        
  3315.         if (getActiveEnchantItem() != null && getActiveEnchantItem().getObjectId() == objectId)
  3316.             return null;
  3317.        
  3318.         // We cannot put a Weapon with Augmention in WH while casting (Possible Exploit)
  3319.         if (item.isAugmented() && (isCastingNow() || isCastingSimultaneouslyNow()))
  3320.             return null;
  3321.        
  3322.         return item;
  3323.     }
  3324.    
  3325.     /**
  3326.      * Set _protectEndTime according settings.
  3327.      *
  3328.      * @param protect boolean Drop timer or activate it.
  3329.      */
  3330.     public void setProtection(boolean protect)
  3331.     {
  3332.         _protectEndTime =
  3333.                 protect ? GameTimeController.getGameTicks() + Config.PLAYER_SPAWN_PROTECTION
  3334.                         * GameTimeController.TICKS_PER_SECOND : 0;
  3335.     }
  3336.    
  3337.     /**
  3338.      * Set protection from agro mobs when getting up from fake death, according settings.
  3339.      *
  3340.      * @param protect boolean Drop timer or activate it.
  3341.      */
  3342.     public void setRecentFakeDeath(boolean protect)
  3343.     {
  3344.         _recentFakeDeathEndTime =
  3345.                 protect ? GameTimeController.getGameTicks() + Config.PLAYER_FAKEDEATH_UP_PROTECTION
  3346.                         * GameTimeController.TICKS_PER_SECOND : 0;
  3347.     }
  3348.    
  3349.     public boolean isRecentFakeDeath()
  3350.     {
  3351.         return _recentFakeDeathEndTime > GameTimeController.getGameTicks();
  3352.     }
  3353.    
  3354.     public final boolean isFakeDeath()
  3355.     {
  3356.         return _isFakeDeath;
  3357.     }
  3358.    
  3359.     public final void setIsFakeDeath(boolean value)
  3360.     {
  3361.         _isFakeDeath = value;
  3362.     }
  3363.    
  3364.     @Override
  3365.     public final boolean isAlikeDead()
  3366.     {
  3367.         if (super.isAlikeDead())
  3368.             return true;
  3369.        
  3370.         return isFakeDeath();
  3371.     }
  3372.    
  3373.     /**
  3374.      * @return The client owner of this char.
  3375.      */
  3376.     public L2GameClient getClient()
  3377.     {
  3378.         return _client;
  3379.     }
  3380.    
  3381.     public void setClient(L2GameClient client)
  3382.     {
  3383.         _client = client;
  3384.     }
  3385.    
  3386.     /**
  3387.      * Close the active connection with the client.
  3388.      *
  3389.      * @param closeClient
  3390.      */
  3391.     private void closeNetConnection(boolean closeClient)
  3392.     {
  3393.         L2GameClient client = _client;
  3394.         if (client != null)
  3395.         {
  3396.             if (client.isDetached())
  3397.                 client.cleanMe(true);
  3398.             else
  3399.             {
  3400.                 if (!client.getConnection().isClosed())
  3401.                 {
  3402.                     if (closeClient)
  3403.                         client.close(LeaveWorld.STATIC_PACKET);
  3404.                     else
  3405.                         client.close(ServerClose.STATIC_PACKET);
  3406.                 }
  3407.             }
  3408.         }
  3409.     }
  3410.    
  3411.     public Point3D getCurrentSkillWorldPosition()
  3412.     {
  3413.         return _currentSkillWorldPosition;
  3414.     }
  3415.    
  3416.     public void setCurrentSkillWorldPosition(Point3D worldPosition)
  3417.     {
  3418.         _currentSkillWorldPosition = worldPosition;
  3419.     }
  3420.    
  3421.     /**
  3422.      * @see com.l2jpes.gameserver.model.actor.L2Character#enableSkill(com.l2jpes.gameserver.model.L2Skill)
  3423.      */
  3424.     @Override
  3425.     public void enableSkill(L2Skill skill)
  3426.     {
  3427.         super.enableSkill(skill);
  3428.         _reuseTimeStamps.remove(skill.getReuseHashCode());
  3429.     }
  3430.    
  3431.     /**
  3432.      * @see com.l2jpes.gameserver.model.actor.L2Character#checkDoCastConditions(com.l2jpes.gameserver.model.L2Skill)
  3433.      */
  3434.     @Override
  3435.     protected boolean checkDoCastConditions(L2Skill skill)
  3436.     {
  3437.         if (!super.checkDoCastConditions(skill))
  3438.             return false;
  3439.        
  3440.         if (skill.getSkillType() == L2SkillType.SUMMON)
  3441.         {
  3442.             if (!((L2SkillSummon)skill).isCubic() && (getPet() != null || isMounted()))
  3443.             {
  3444.                 sendPacket(SystemMessageId.SUMMON_ONLY_ONE);
  3445.                 return false;
  3446.             }
  3447.         }
  3448.        
  3449.         // Can't use Hero and resurrect skills during Olympiad
  3450.         if (isInOlympiadMode() && (skill.isHeroSkill() || skill.getSkillType() == L2SkillType.RESURRECT))
  3451.         {
  3452.             sendPacket(SystemMessage
  3453.                     .getSystemMessage(SystemMessageId.THIS_SKILL_IS_NOT_AVAILABLE_FOR_THE_OLYMPIAD_EVENT));
  3454.             return false;
  3455.         }
  3456.        
  3457.         // Check if the spell uses charges
  3458.         final int charges = getCharges();
  3459.         if (skill.getMaxCharges() == 0 && charges < skill.getNumCharges())
  3460.         {
  3461.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill));
  3462.             return false;
  3463.         }
  3464.        
  3465.         return true;
  3466.     }
  3467.    
  3468.     /**
  3469.      * Manage actions when a player click on this L2PlayerInstance.<BR>
  3470.      * <BR>
  3471.      * <B><U> Actions on first click on the L2PlayerInstance (Select it)</U> :</B><BR>
  3472.      * <BR>
  3473.      * <li>Set the target of the player</li> <li>Send MyTargetSelected to the player (display the
  3474.      * select window)</li><BR>
  3475.      * <BR>
  3476.      * <B><U> Actions on second click on the L2PlayerInstance (Follow it/Attack it/Intercat with
  3477.      * it)</U> :</B><BR>
  3478.      * <BR>
  3479.      * <li>Send MyTargetSelected to the player (display the select window)</li> <li>If this
  3480.      * L2PlayerInstance has a Private Store, notify the player AI with AI_INTENTION_INTERACT</li>
  3481.      * <li>If this L2PlayerInstance is autoAttackable, notify the player AI with AI_INTENTION_ATTACK
  3482.      * </li><BR>
  3483.      * <BR>
  3484.      * <li>If this L2PlayerInstance is NOT autoAttackable, notify the player AI with
  3485.      * AI_INTENTION_FOLLOW</li><BR>
  3486.      * <BR>
  3487.      * <B><U> Example of use </U> :</B><BR>
  3488.      * <BR>
  3489.      * <li>Client packet : Action, AttackRequest</li><BR>
  3490.      * <BR>
  3491.      *
  3492.      * @param player The player that start an action on this L2PlayerInstance
  3493.      */
  3494.     @Override
  3495.     public void onAction(L2PlayerInstance player)
  3496.     {
  3497.         if (!EventCommons.getInstance().canTarget(player, this))
  3498.         {
  3499.             return;
  3500.         }
  3501.        
  3502.         // Check if the player already target this L2PlayerInstance
  3503.         if (player.getTarget() != this)
  3504.         {
  3505.             // Set the target of the player
  3506.             player.setTarget(this);
  3507.            
  3508.             // Send MyTargetSelected to the player
  3509.             player.sendPacket(new MyTargetSelected(getObjectId(), 0));
  3510.         }
  3511.         else
  3512.         {
  3513.             // Check if this L2PlayerInstance has a Private Store
  3514.             if (getPrivateStoreType() != 0)
  3515.             {
  3516.                 player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
  3517.                 return;
  3518.             }
  3519.            
  3520.             // Check if this L2PlayerInstance is autoAttackable
  3521.             if (isAutoAttackable(player))
  3522.             {
  3523.                 // Player with lvl < 21 can't attack a cursed weapon holder and a cursed weapon holder can't attack players with lvl < 21
  3524.                 if ((isCursedWeaponEquipped() && player.getLevel() < 21)
  3525.                         || (player.isCursedWeaponEquipped() && getLevel() < 21))
  3526.                 {
  3527.                     player.sendPacket(ActionFailed.STATIC_PACKET);
  3528.                     return;
  3529.                 }
  3530.                
  3531.                 if (Config.GEODATA == 0 || GeoData.getInstance().canSeeTarget(player, this))
  3532.                 {
  3533.                     player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
  3534.                     player.onActionRequest();
  3535.                 }
  3536.             }
  3537.             else
  3538.             {
  3539.                 // avoids to stuck when clicking two or more times
  3540.                 player.sendPacket(ActionFailed.STATIC_PACKET);
  3541.                
  3542.                 if (Config.GEODATA == 0 || GeoData.getInstance().canSeeTarget(player, this))
  3543.                     player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this);
  3544.             }
  3545.         }
  3546.     }
  3547.    
  3548.     /**
  3549.      * @param barPixels
  3550.      * @return true if cp update should be done, false if not
  3551.      */
  3552.     private boolean needCpUpdate(int barPixels)
  3553.     {
  3554.         double currentCp = getCurrentCp();
  3555.        
  3556.         if (currentCp <= 1.0 || getMaxCp() < barPixels)
  3557.             return true;
  3558.        
  3559.         if (currentCp <= _cpUpdateDecCheck || currentCp >= _cpUpdateIncCheck)
  3560.         {
  3561.             if (currentCp == getMaxCp())
  3562.             {
  3563.                 _cpUpdateIncCheck = currentCp + 1;
  3564.                 _cpUpdateDecCheck = currentCp - _cpUpdateInterval;
  3565.             }
  3566.             else
  3567.             {
  3568.                 double doubleMulti = currentCp / _cpUpdateInterval;
  3569.                 int intMulti = (int)doubleMulti;
  3570.                
  3571.                 _cpUpdateDecCheck = _cpUpdateInterval * (doubleMulti < intMulti ? intMulti-- : intMulti);
  3572.                 _cpUpdateIncCheck = _cpUpdateDecCheck + _cpUpdateInterval;
  3573.             }
  3574.            
  3575.             return true;
  3576.         }
  3577.        
  3578.         return false;
  3579.     }
  3580.    
  3581.     /**
  3582.      * @param barPixels
  3583.      * @return true if mp update should be done, false if not
  3584.      */
  3585.     private boolean needMpUpdate(int barPixels)
  3586.     {
  3587.         double currentMp = getCurrentMp();
  3588.        
  3589.         if (currentMp <= 1.0 || getMaxMp() < barPixels)
  3590.             return true;
  3591.        
  3592.         if (currentMp <= _mpUpdateDecCheck || currentMp >= _mpUpdateIncCheck)
  3593.         {
  3594.             if (currentMp == getMaxMp())
  3595.             {
  3596.                 _mpUpdateIncCheck = currentMp + 1;
  3597.                 _mpUpdateDecCheck = currentMp - _mpUpdateInterval;
  3598.             }
  3599.             else
  3600.             {
  3601.                 double doubleMulti = currentMp / _mpUpdateInterval;
  3602.                 int intMulti = (int)doubleMulti;
  3603.                
  3604.                 _mpUpdateDecCheck = _mpUpdateInterval * (doubleMulti < intMulti ? intMulti-- : intMulti);
  3605.                 _mpUpdateIncCheck = _mpUpdateDecCheck + _mpUpdateInterval;
  3606.             }
  3607.            
  3608.             return true;
  3609.         }
  3610.        
  3611.         return false;
  3612.     }
  3613.    
  3614.     /**
  3615.      * Send packet StatusUpdate with current HP,MP and CP to the L2PlayerInstance and only current
  3616.      * HP, MP and Level to all other L2PlayerInstance of the Party.<BR>
  3617.      * <BR>
  3618.      * <B><U> Actions</U> :</B><BR>
  3619.      * <BR>
  3620.      * <li>Send the Server->Client packet StatusUpdate with current HP, MP and CP to this
  3621.      * L2PlayerInstance</li><BR>
  3622.      * <li>Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to
  3623.      * all other L2PlayerInstance of the Party</li><BR>
  3624.      * <BR>
  3625.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND current HP and MP to all
  3626.      * L2PlayerInstance of the _statusListener</B></FONT><BR>
  3627.      * <BR>
  3628.      */
  3629.     @Override
  3630.     public void broadcastStatusUpdate()
  3631.     {
  3632.         // Send the Server->Client packet StatusUpdate with current HP, MP and CP to this L2PlayerInstance
  3633.         StatusUpdate su = new StatusUpdate(this);
  3634.         su.addAttribute(StatusUpdate.CUR_HP, (int)getCurrentHp());
  3635.         su.addAttribute(StatusUpdate.CUR_MP, (int)getCurrentMp());
  3636.         su.addAttribute(StatusUpdate.CUR_CP, (int)getCurrentCp());
  3637.         su.addAttribute(StatusUpdate.MAX_CP, getMaxCp());
  3638.         sendPacket(su);
  3639.        
  3640.         final boolean needCpUpdate = needCpUpdate(352);
  3641.         final boolean needHpUpdate = needHpUpdate(352);
  3642.         // Check if a party is in progress and party window update is usefull
  3643.         L2Party party = _party;
  3644.         if (party != null && (needCpUpdate || needHpUpdate || needMpUpdate(352)))
  3645.         {
  3646.             // Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2PlayerInstance of the Party
  3647.             PartySmallWindowUpdate update = new PartySmallWindowUpdate(this);
  3648.             party.broadcastToPartyMembers(this, update);
  3649.         }
  3650.        
  3651.         if (isInOlympiadMode() && isOlympiadStart() && (needCpUpdate || needHpUpdate))
  3652.         {
  3653.             final OlympiadGameTask game = OlympiadGameManager.getInstance().getOlympiadTask(getOlympiadGameId());
  3654.             if (game != null && game.isBattleStarted())
  3655.                 game.getZone().broadcastStatusUpdate(this);
  3656.         }
  3657.        
  3658.         // In duel, MP updated only with CP or HP
  3659.         if (isInDuel() && (needCpUpdate || needHpUpdate))
  3660.         {
  3661.             ExDuelUpdateUserInfo update = new ExDuelUpdateUserInfo(this);
  3662.             DuelManager.getInstance().broadcastToOppositeTeam(this, update);
  3663.         }
  3664.     }
  3665.    
  3666.     /**
  3667.      * Broadcast informations from a user to himself and his knownlist.<BR>
  3668.      * If player is morphed, it sends informations from the template the player is using.<BR>
  3669.      * <BR>
  3670.      * <B><U> Actions</U> :</B><BR>
  3671.      * <li>Send a UserInfo packet (public and private data) to this L2PlayerInstance.</li> <li>Send
  3672.      * a CharInfo packet (public data only) to L2PlayerInstance's knownlist.</li>
  3673.      */
  3674.     public final void broadcastUserInfo()
  3675.     {
  3676.         sendPacket(new UserInfo(this));
  3677.        
  3678.         if (getPoly().isMorphed())
  3679.             Broadcast.toKnownPlayers(this, new AbstractNpcInfo.PcMorphInfo(this, getPoly().getNpcTemplate()));
  3680.         else
  3681.             broadcastCharInfo();
  3682.     }
  3683.    
  3684.     public final void broadcastCharInfo()
  3685.     {
  3686.         for (L2PlayerInstance player : getKnownList().getKnownPlayers())
  3687.         {
  3688.             player.sendPacket(new CharInfo(this));
  3689.            
  3690.             int relation = getRelation(player);
  3691.             Integer oldrelation = getKnownList().getKnownRelationsMap().get(player.getObjectId());
  3692.             if (oldrelation != null && oldrelation != relation)
  3693.             {
  3694.                 player.sendPacket(new RelationChanged(this, relation, isAutoAttackable(player)));
  3695.                 if (getPet() != null)
  3696.                     player.sendPacket(new RelationChanged(getPet(), relation, isAutoAttackable(player)));
  3697.             }
  3698.         }
  3699.     }
  3700.    
  3701.     /**
  3702.      * @return the Alliance Identifier of the L2PlayerInstance.
  3703.      */
  3704.     public int getAllyId()
  3705.     {
  3706.         if (_clan == null)
  3707.             return 0;
  3708.        
  3709.         return _clan.getAllyId();
  3710.     }
  3711.    
  3712.     public int getAllyCrestId()
  3713.     {
  3714.         if (getClanId() == 0)
  3715.             return 0;
  3716.        
  3717.         if (getClan().getAllyId() == 0)
  3718.             return 0;
  3719.        
  3720.         return getClan().getAllyCrestId();
  3721.     }
  3722.    
  3723.     /**
  3724.      * Send a packet to the L2PlayerInstance.
  3725.      */
  3726.     @Override
  3727.     public void sendPacket(L2GameServerPacket packet)
  3728.     {
  3729.         if (_client != null)
  3730.             _client.sendPacket(packet);
  3731.     }
  3732.    
  3733.     /**
  3734.      * Send SystemMessage packet.
  3735.      *
  3736.      * @param id SystemMessageId
  3737.      */
  3738.     @Override
  3739.     public void sendPacket(SystemMessageId id)
  3740.     {
  3741.         sendPacket(SystemMessage.getSystemMessage(id));
  3742.     }
  3743.    
  3744.     /**
  3745.      * Manage Interact Task with another L2PlayerInstance.<BR>
  3746.      * <BR>
  3747.      * Turn the character in front of the target.<BR>
  3748.      * In case of private stores, send the related packet.
  3749.      *
  3750.      * @param target The L2Character targeted
  3751.      */
  3752.     public void doInteract(L2Character target)
  3753.     {
  3754.         if (target instanceof L2PlayerInstance)
  3755.         {
  3756.             L2PlayerInstance temp = (L2PlayerInstance)target;
  3757.             sendPacket(new MoveToPawn(this, temp, L2Npc.INTERACTION_DISTANCE));
  3758.            
  3759.             switch (temp.getPrivateStoreType())
  3760.             {
  3761.                 case STORE_PRIVATE_SELL:
  3762.                 case STORE_PRIVATE_PACKAGE_SELL:
  3763.                     sendPacket(new PrivateStoreListSell(this, temp));
  3764.                     break;
  3765.                
  3766.                 case STORE_PRIVATE_BUY:
  3767.                     sendPacket(new PrivateStoreListBuy(this, temp));
  3768.                     break;
  3769.                
  3770.                 case STORE_PRIVATE_MANUFACTURE:
  3771.                     sendPacket(new RecipeShopSellList(this, temp));
  3772.                     break;
  3773.             }
  3774.         }
  3775.         else
  3776.         {
  3777.             // _interactTarget=null should never happen but one never knows ^^;
  3778.             if (target != null)
  3779.                 target.onAction(this);
  3780.         }
  3781.     }
  3782.    
  3783.     /**
  3784.      * Manage AutoLoot Task.<BR>
  3785.      * <BR>
  3786.      * <B><U> Actions</U> :</B><BR>
  3787.      * <BR>
  3788.      * <li>Send a System Message to the L2PlayerInstance : YOU_PICKED_UP_S1_ADENA or
  3789.      * YOU_PICKED_UP_S1_S2</li> <li>Add the Item to the L2PlayerInstance inventory</li> <li>Send
  3790.      * InventoryUpdate to this L2PlayerInstance with NewItem (use a new slot) or ModifiedItem
  3791.      * (increase amount)</li> <li>Send StatusUpdate to this L2PlayerInstance with current weight</li>
  3792.      * <BR>
  3793.      * <BR>
  3794.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : If a Party is in progress, distribute Items between
  3795.      * party members</B></FONT><BR>
  3796.      * <BR>
  3797.      *
  3798.      * @param target The reference Object.
  3799.      * @param item The dropped RewardItem.
  3800.      */
  3801.     public void doAutoLoot(L2Attackable target, L2Attackable.RewardItem item)
  3802.     {
  3803.         if (isInParty())
  3804.             getParty().distributeItem(this, item, false, target);
  3805.         else if (item.getItemId() == 57)
  3806.             addAdena("Loot", item.getCount(), target, true);
  3807.         else
  3808.             addItem("Loot", item.getItemId(), item.getCount(), target, true);
  3809.     }
  3810.    
  3811.     /**
  3812.      * Manage Pickup Task.<BR>
  3813.      * <BR>
  3814.      * <B><U> Actions</U> :</B><BR>
  3815.      * <BR>
  3816.      * <li>Send StopMove to this L2PlayerInstance</li> <li>Remove the L2ItemInstance from the world
  3817.      * and send server->client GetItem packets</li> <li>Send a System Message to the
  3818.      * L2PlayerInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2</li> <li>Add the Item to the
  3819.      * L2PlayerInstance inventory</li> <li>Send InventoryUpdate to this L2PlayerInstance with
  3820.      * NewItem (use a new slot) or ModifiedItem (increase amount)</li> <li>Send StatusUpdate to this
  3821.      * L2PlayerInstance with current weight</li><BR>
  3822.      * <BR>
  3823.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : If a Party is in progress, distribute Items between
  3824.      * party members</B></FONT><BR>
  3825.      * <BR>
  3826.      *
  3827.      * @param object The L2ItemInstance to pick up
  3828.      */
  3829.     protected void doPickupItem(L2Object object)
  3830.     {
  3831.         if (isAlikeDead() || isFakeDeath())
  3832.             return;
  3833.        
  3834.         // Set the AI Intention to AI_INTENTION_IDLE
  3835.         getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
  3836.        
  3837.         // Check if the L2Object to pick up is a L2ItemInstance
  3838.         if (!(object instanceof L2ItemInstance))
  3839.         {
  3840.             // dont try to pickup anything that is not an item :)
  3841.             _log.warning(getName() + " tried to pickup a wrong target: " + object);
  3842.             return;
  3843.         }
  3844.        
  3845.         L2ItemInstance target = (L2ItemInstance)object;
  3846.        
  3847.         // Send ActionFailed to this L2PlayerInstance
  3848.         sendPacket(ActionFailed.STATIC_PACKET);
  3849.         sendPacket(new StopMove(this));
  3850.        
  3851.         synchronized (target)
  3852.         {
  3853.             // Check if the target to pick up is visible
  3854.             if (!target.isVisible())
  3855.                 return;
  3856.            
  3857.             if (!target.getDropProtection().tryPickUp(this))
  3858.             {
  3859.                 sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FAILED_TO_PICKUP_S1).addItemName(
  3860.                         target.getItemId()));
  3861.                 return;
  3862.             }
  3863.            
  3864.             if (((isInParty() && getParty().getLootDistribution() == L2Party.ITEM_LOOTER) || !isInParty())
  3865.                     && !_inventory.validateCapacity(target))
  3866.             {
  3867.                 sendPacket(SystemMessageId.SLOTS_FULL);
  3868.                 return;
  3869.             }
  3870.            
  3871.             if (getActiveTradeList() != null)
  3872.             {
  3873.                 sendPacket(SystemMessageId.CANNOT_PICKUP_OR_USE_ITEM_WHILE_TRADING);
  3874.                 return;
  3875.             }
  3876.            
  3877.             if (target.getOwnerId() != 0 && target.getOwnerId() != getObjectId()
  3878.                     && !isInLooterParty(target.getOwnerId()))
  3879.             {
  3880.                 if (target.getItemId() == 57)
  3881.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FAILED_TO_PICKUP_S1_ADENA).addNumber(
  3882.                             target.getCount()));
  3883.                 else if (target.getCount() > 1)
  3884.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FAILED_TO_PICKUP_S2_S1_S)
  3885.                             .addItemName(target).addNumber(target.getCount()));
  3886.                 else
  3887.                     sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FAILED_TO_PICKUP_S1).addItemName(target));
  3888.                
  3889.                 return;
  3890.             }
  3891.            
  3892.             if (target.getItemLootShedule() != null
  3893.                     && (target.getOwnerId() == getObjectId() || isInLooterParty(target.getOwnerId())))
  3894.                 target.resetOwnerTimer();
  3895.            
  3896.             // Remove the L2ItemInstance from the world and send server->client GetItem packets
  3897.             target.pickupMe(this);
  3898.            
  3899.             if (Config.SAVE_DROPPED_ITEM) // item must be removed from ItemsOnGroundManager if is active
  3900.                 ItemsOnGroundManager.getInstance().removeObject(target);
  3901.         }
  3902.        
  3903.         // Auto use herbs - pick up
  3904.         if (target.getItemType() == L2EtcItemType.HERB)
  3905.         {
  3906.             IItemHandler handler = ItemHandler.getInstance().getItemHandler(target.getEtcItem());
  3907.             if (handler != null)
  3908.                 handler.useItem(this, target, false);
  3909.            
  3910.             ItemTable.getInstance().destroyItem("Consume", target, this, null);
  3911.         }
  3912.         // Cursed Weapons are not distributed
  3913.         else if (CursedWeaponsManager.getInstance().isCursed(target.getItemId()))
  3914.         {
  3915.             addItem("Pickup", target, null, true);
  3916.         }
  3917.         else
  3918.         {
  3919.             // if item is instance of L2ArmorType or L2WeaponType broadcast an "Attention" system message
  3920.             if (target.getItemType() instanceof L2ArmorType || target.getItemType() instanceof L2WeaponType)
  3921.             {
  3922.                 if (target.getEnchantLevel() > 0)
  3923.                 {
  3924.                     SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.ATTENTION_S1_PICKED_UP_S2_S3);
  3925.                     msg.addString(getName());
  3926.                     msg.addNumber(target.getEnchantLevel());
  3927.                     msg.addItemName(target.getItemId());
  3928.                     broadcastPacket(msg, 1400);
  3929.                 }
  3930.                 else
  3931.                 {
  3932.                     SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.ATTENTION_S1_PICKED_UP_S2);
  3933.                     msg.addString(getName());
  3934.                     msg.addItemName(target.getItemId());
  3935.                     broadcastPacket(msg, 1400);
  3936.                 }
  3937.             }
  3938.            
  3939.             // Check if a Party is in progress
  3940.             if (isInParty())
  3941.                 getParty().distributeItem(this, target);
  3942.             // Target is adena
  3943.             else if (target.getItemId() == 57 && getInventory().getAdenaInstance() != null)
  3944.             {
  3945.                 addAdena("Pickup", target.getCount(), null, true);
  3946.                 ItemTable.getInstance().destroyItem("Pickup", target, this, null);
  3947.             }
  3948.             // Target is regular item
  3949.             else
  3950.                 addItem("Pickup", target, null, true);
  3951.         }
  3952.     }
  3953.    
  3954.     public boolean canOpenPrivateStore()
  3955.     {
  3956.         return !isAlikeDead() && !isInOlympiadMode() && !isMounted() && !isInsideZone(ZONE_NOSTORE) && !isCastingNow();
  3957.     }
  3958.    
  3959.     public void tryOpenPrivateBuyStore()
  3960.     {
  3961.         if (canOpenPrivateStore())
  3962.         {
  3963.             if (getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_BUY
  3964.                     || getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_BUY + 1)
  3965.                 setPrivateStoreType(L2PlayerInstance.STORE_PRIVATE_NONE);
  3966.            
  3967.             if (getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_NONE)
  3968.             {
  3969.                 if (isSitting())
  3970.                     standUp();
  3971.                
  3972.                 setPrivateStoreType(L2PlayerInstance.STORE_PRIVATE_BUY + 1);
  3973.                 sendPacket(new PrivateStoreManageListBuy(this));
  3974.             }
  3975.         }
  3976.         else
  3977.         {
  3978.             if (isInsideZone(ZONE_NOSTORE))
  3979.                 sendPacket(SystemMessageId.NO_PRIVATE_STORE_HERE);
  3980.            
  3981.             sendPacket(ActionFailed.STATIC_PACKET);
  3982.         }
  3983.     }
  3984.    
  3985.     public void tryOpenPrivateSellStore(boolean isPackageSale)
  3986.     {
  3987.         if (canOpenPrivateStore())
  3988.         {
  3989.             if (getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_SELL
  3990.                     || getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_SELL + 1
  3991.                     || getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_PACKAGE_SELL)
  3992.                 setPrivateStoreType(L2PlayerInstance.STORE_PRIVATE_NONE);
  3993.            
  3994.             if (getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_NONE)
  3995.             {
  3996.                 if (isSitting())
  3997.                     standUp();
  3998.                
  3999.                 setPrivateStoreType(L2PlayerInstance.STORE_PRIVATE_SELL + 1);
  4000.                 sendPacket(new PrivateStoreManageListSell(this, isPackageSale));
  4001.             }
  4002.         }
  4003.         else
  4004.         {
  4005.             if (isInsideZone(ZONE_NOSTORE))
  4006.                 sendPacket(SystemMessageId.NO_PRIVATE_STORE_HERE);
  4007.            
  4008.             sendPacket(ActionFailed.STATIC_PACKET);
  4009.         }
  4010.     }
  4011.    
  4012.     public void tryOpenWorkshop(boolean isDwarven)
  4013.     {
  4014.         if (canOpenPrivateStore())
  4015.         {
  4016.             if (getPrivateStoreType() != 0)
  4017.                 setPrivateStoreType(L2PlayerInstance.STORE_PRIVATE_NONE);
  4018.            
  4019.             if (getPrivateStoreType() == L2PlayerInstance.STORE_PRIVATE_NONE)
  4020.             {
  4021.                 if (isSitting())
  4022.                     standUp();
  4023.                
  4024.                 if (getCreateList() == null)
  4025.                     setCreateList(new L2ManufactureList());
  4026.                
  4027.                 sendPacket(new RecipeShopManageList(this, isDwarven));
  4028.             }
  4029.         }
  4030.         else
  4031.         {
  4032.             if (isInsideZone(ZONE_NOSTORE))
  4033.                 sendPacket(SystemMessageId.NO_PRIVATE_WORKSHOP_HERE);
  4034.            
  4035.             sendPacket(ActionFailed.STATIC_PACKET);
  4036.         }
  4037.     }
  4038.    
  4039.     /**
  4040.      * Set a target.
  4041.      * <ul>
  4042.      * <li>Remove the L2PlayerInstance from the _statusListener of the old target if it was a
  4043.      * L2Character</li>
  4044.      * <li>Add the L2PlayerInstance to the _statusListener of the new target if it's a L2Character</li>
  4045.      * <li>Target the new L2Object (add the target to the L2PlayerInstance _target, _knownObject and
  4046.      * L2PlayerInstance to _KnownObject of the L2Object)</li>
  4047.      * </ul>
  4048.      *
  4049.      * @param newTarget The L2Object to target
  4050.      */
  4051.     @Override
  4052.     public void setTarget(L2Object newTarget)
  4053.     {
  4054.         if (newTarget != null)
  4055.         {
  4056.             boolean isParty =
  4057.                     (((newTarget instanceof L2PlayerInstance) && isInParty() && getParty().getPartyMembers().contains(
  4058.                             newTarget)));
  4059.            
  4060.             // Check if the new target is visible
  4061.             if (!isParty && (!newTarget.isVisible() || Math.abs(newTarget.getZ() - getZ()) > 1000))
  4062.                 newTarget = null;
  4063.         }
  4064.        
  4065.         // Can't target and attack festival monsters if not participant
  4066.         if ((newTarget instanceof L2FestivalMonsterInstance) && !isFestivalParticipant())
  4067.             newTarget = null;
  4068.         // Can't target and attack rift invaders if not in the same room
  4069.         else if (isInParty() && getParty().isInDimensionalRift())
  4070.         {
  4071.             byte riftType = getParty().getDimensionalRift().getType();
  4072.             byte riftRoom = getParty().getDimensionalRift().getCurrentRoom();
  4073.            
  4074.             if (newTarget != null
  4075.                     && !DimensionalRiftManager.getInstance().getRoom(riftType, riftRoom)
  4076.                             .checkIfInZone(newTarget.getX(), newTarget.getY(), newTarget.getZ()))
  4077.                 newTarget = null;
  4078.         }
  4079.        
  4080.         // Get the current target
  4081.         L2Object oldTarget = getTarget();
  4082.        
  4083.         if (oldTarget != null)
  4084.         {
  4085.             if (oldTarget.equals(newTarget))
  4086.                 return; // no target change
  4087.                
  4088.             // Remove the L2PlayerInstance from the _statusListener of the old target if it was a L2Character
  4089.             if (oldTarget instanceof L2Character)
  4090.                 ((L2Character)oldTarget).removeStatusListener(this);
  4091.         }
  4092.        
  4093.         // Add the L2PlayerInstance to the _statusListener of the new target if it's a L2Character
  4094.         if (newTarget instanceof L2Character)
  4095.         {
  4096.             ((L2Character)newTarget).addStatusListener(this);
  4097.             Broadcast.toKnownPlayers(this, new TargetSelected(getObjectId(), newTarget.getObjectId(), getX(), getY(),
  4098.                     getZ()));
  4099.         }
  4100.        
  4101.         if (newTarget == null && getTarget() != null)
  4102.         {
  4103.             broadcastPacket(new TargetUnselected(this));
  4104.             setCurrentFolkNPC(null);
  4105.         }
  4106.         else
  4107.         {
  4108.             // Rehabilitates that useful check.
  4109.             if (newTarget instanceof L2NpcInstance)
  4110.                 setCurrentFolkNPC((L2Npc)newTarget);
  4111.         }
  4112.        
  4113.         // Target the new L2Object (add the target to the L2PlayerInstance _target, _knownObject and L2PlayerInstance to _KnownObject of the L2Object)
  4114.         super.setTarget(newTarget);
  4115.     }
  4116.    
  4117.     /**
  4118.      * Return the active weapon instance (always equipped in the right hand).<BR>
  4119.      * <BR>
  4120.      */
  4121.     @Override
  4122.     public L2ItemInstance getActiveWeaponInstance()
  4123.     {
  4124.         return getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
  4125.     }
  4126.    
  4127.     /**
  4128.      * Return the active weapon item (always equipped in the right hand).<BR>
  4129.      * <BR>
  4130.      */
  4131.     @Override
  4132.     public L2Weapon getActiveWeaponItem()
  4133.     {
  4134.         L2ItemInstance weapon = getActiveWeaponInstance();
  4135.        
  4136.         if (weapon == null)
  4137.             return getFistsWeaponItem();
  4138.        
  4139.         return (L2Weapon)weapon.getItem();
  4140.     }
  4141.    
  4142.     public L2ItemInstance getChestArmorInstance()
  4143.     {
  4144.         return getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
  4145.     }
  4146.    
  4147.     public L2Armor getActiveChestArmorItem()
  4148.     {
  4149.         L2ItemInstance armor = getChestArmorInstance();
  4150.        
  4151.         if (armor == null)
  4152.             return null;
  4153.        
  4154.         return (L2Armor)armor.getItem();
  4155.     }
  4156.    
  4157.     public boolean isWearingHeavyArmor()
  4158.     {
  4159.         L2ItemInstance armor = getChestArmorInstance();
  4160.        
  4161.         if ((L2ArmorType)armor.getItemType() == L2ArmorType.HEAVY)
  4162.             return true;
  4163.        
  4164.         return false;
  4165.     }
  4166.    
  4167.     public boolean isWearingLightArmor()
  4168.     {
  4169.         L2ItemInstance armor = getChestArmorInstance();
  4170.        
  4171.         if ((L2ArmorType)armor.getItemType() == L2ArmorType.LIGHT)
  4172.             return true;
  4173.        
  4174.         return false;
  4175.     }
  4176.    
  4177.     public boolean isWearingMagicArmor()
  4178.     {
  4179.         L2ItemInstance armor = getChestArmorInstance();
  4180.        
  4181.         if ((L2ArmorType)armor.getItemType() == L2ArmorType.MAGIC)
  4182.             return true;
  4183.        
  4184.         return false;
  4185.     }
  4186.    
  4187.     public boolean isMarried()
  4188.     {
  4189.         return _married;
  4190.     }
  4191.    
  4192.     public void setMarried(boolean state)
  4193.     {
  4194.         _married = state;
  4195.     }
  4196.    
  4197.     public void setUnderMarryRequest(boolean state)
  4198.     {
  4199.         _marryrequest = state;
  4200.     }
  4201.    
  4202.     public boolean isUnderMarryRequest()
  4203.     {
  4204.         return _marryrequest;
  4205.     }
  4206.    
  4207.     public int getCoupleId()
  4208.     {
  4209.         return _coupleId;
  4210.     }
  4211.    
  4212.     public void setCoupleId(int coupleId)
  4213.     {
  4214.         _coupleId = coupleId;
  4215.     }
  4216.    
  4217.     public void setRequesterId(int requesterId)
  4218.     {
  4219.         _requesterId = requesterId;
  4220.     }
  4221.    
  4222.     public void EngageAnswer(int answer)
  4223.     {
  4224.         if (!_marryrequest || _requesterId == 0)
  4225.             return;
  4226.        
  4227.         L2PlayerInstance ptarget = L2World.getInstance().getPlayer(_requesterId);
  4228.         if (ptarget != null)
  4229.         {
  4230.             if (answer == 1)
  4231.             {
  4232.                 // Create the couple
  4233.                 CoupleManager.getInstance().createCouple(ptarget, L2PlayerInstance.this);
  4234.                
  4235.                 // Then "finish the job"
  4236.                 L2WeddingManagerInstance.justMarried(ptarget, L2PlayerInstance.this);
  4237.             }
  4238.             else
  4239.             {
  4240.                 setUnderMarryRequest(false);
  4241.                 sendMessage("You declined your partner's marriage request.");
  4242.                
  4243.                 ptarget.setUnderMarryRequest(false);
  4244.                 ptarget.sendMessage("Your partner declined your marriage request.");
  4245.             }
  4246.         }
  4247.     }
  4248.    
  4249.     /**
  4250.      * Return the secondary weapon instance (always equipped in the left hand).<BR>
  4251.      * <BR>
  4252.      */
  4253.     @Override
  4254.     public L2ItemInstance getSecondaryWeaponInstance()
  4255.     {
  4256.         return getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
  4257.     }
  4258.    
  4259.     /**
  4260.      * Return the secondary L2Item item (always equiped in the left hand).<BR>
  4261.      * Arrows, shield,...<BR>
  4262.      */
  4263.     @Override
  4264.     public L2Item getSecondaryWeaponItem()
  4265.     {
  4266.         L2ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
  4267.         if (item != null)
  4268.             return item.getItem();
  4269.        
  4270.         return null;
  4271.     }
  4272.    
  4273.     /**
  4274.      * Kill the L2Character, Apply Death Penalty, Manage gain/loss Karma and Item Drop.<BR>
  4275.      * <BR>
  4276.      * <B><U> Actions</U> :</B><BR>
  4277.      * <BR>
  4278.      * <li>Reduce the Experience of the L2PlayerInstance in function of the calculated Death Penalty
  4279.      * </li> <li>If necessary, unsummon the Pet of the killed L2PlayerInstance</li> <li>Manage Karma
  4280.      * gain for attacker and Karam loss for the killed L2PlayerInstance</li> <li>If the killed
  4281.      * L2PlayerInstance has Karma, manage Drop Item</li> <li>Kill the L2PlayerInstance</li><BR>
  4282.      * <BR>
  4283.      *
  4284.      * @param killer The L2Character who attacks
  4285.      */
  4286.     @Override
  4287.     public boolean doDie(L2Character killer)
  4288.     {
  4289.         // Kill the L2PlayerInstance
  4290.         if (!super.doDie(killer))
  4291.             return false;
  4292.        
  4293.         for (Plugin plugin : PluginLoader.getInstance().getPlugins())
  4294.         {
  4295.             for (PluginListener listener : plugin.getListeners())
  4296.             {
  4297.                 listener.onPlayerDeath(killer, this);
  4298.             }
  4299.         }
  4300.        
  4301.         if (isMounted())
  4302.             stopFeed();
  4303.        
  4304.         synchronized (this)
  4305.         {
  4306.             if (isFakeDeath())
  4307.                 stopFakeDeath(true);
  4308.         }
  4309.        
  4310.         EventCommons.getInstance().doDie(killer, this);
  4311.        
  4312.         if (killer != null)
  4313.         {
  4314.             L2PlayerInstance pk = killer.getActingPlayer();
  4315.            
  4316.             // Clear resurrect xp calculation
  4317.             setExpBeforeDeath(0);
  4318.            
  4319.             if (isCursedWeaponEquipped())
  4320.                 CursedWeaponsManager.getInstance().drop(_cursedWeaponEquippedId, killer);
  4321.             else
  4322.             {
  4323.                 if (pk == null || !pk.isCursedWeaponEquipped())
  4324.                 {
  4325.                     onDieDropItem(killer); // Check if any item should be dropped
  4326.                    
  4327.                     // if the area isn't a pvp zone or a siege zone
  4328.                     if (!(isInsideZone(ZONE_PVP) && !isInsideZone(ZONE_SIEGE)))
  4329.                     {
  4330.                         // if both victim and attacker got clans & aren't academicians
  4331.                         if (pk != null && pk.getClan() != null && getClan() != null && !isAcademyMember()
  4332.                                 && !pk.isAcademyMember())
  4333.                         {
  4334.                             // if clans got mutual war, then use the reputation calcul
  4335.                             if (_clan.isAtWarWith(pk.getClanId()) && pk.getClan().isAtWarWith(_clan.getClanId()))
  4336.                             {
  4337.                                 // when your reputation score is 0 or below, the other clan cannot acquire any reputation points
  4338.                                 if (getClan().getReputationScore() > 0)
  4339.                                     pk.getClan().addReputationScore(1);
  4340.                                 // when the opposing sides reputation score is 0 or below, your clans reputation score doesn't decrease
  4341.                                 if (pk.getClan().getReputationScore() > 0)
  4342.                                     _clan.takeReputationScore(1);
  4343.                             }
  4344.                         }
  4345.                     }
  4346.                    
  4347.                     if (Config.ALT_GAME_DELEVEL)
  4348.                     {
  4349.                         // Reduce the Experience of the L2PlayerInstance in function of the calculated Death Penalty
  4350.                         // NOTE: deathPenalty +- Exp will update karma
  4351.                         if (getSkillLevel(L2Skill.SKILL_LUCKY) < 0 || getStat().getLevel() > 9)
  4352.                             deathPenalty((pk != null && getClan() != null && pk.getClan() != null && pk.getClan()
  4353.                                     .isAtWarWith(getClanId())));
  4354.                     }
  4355.                     else
  4356.                     {
  4357.                         if (!(isInsideZone(ZONE_PVP) && !isInSiege()) || pk == null)
  4358.                             onDieUpdateKarma(); // Update karma if delevel is not allowed
  4359.                     }
  4360.                 }
  4361.             }
  4362.         }
  4363.        
  4364.         // Unsummon Cubics
  4365.         if (!_cubics.isEmpty())
  4366.         {
  4367.             for (L2CubicInstance cubic : _cubics.values())
  4368.             {
  4369.                 cubic.stopAction();
  4370.                 cubic.cancelDisappear();
  4371.             }
  4372.            
  4373.             _cubics.clear();
  4374.         }
  4375.        
  4376.         if (_fusionSkill != null)
  4377.             abortCast();
  4378.        
  4379.         for (L2Character character : getKnownList().getKnownType(L2Character.class))
  4380.             if (character.getFusionSkill() != null && character.getFusionSkill().getTarget() == this)
  4381.                 character.abortCast();
  4382.        
  4383.         if (isInParty() && getParty().isInDimensionalRift())
  4384.             getParty().getDimensionalRift().getDeadMemberList().add(this);
  4385.        
  4386.         // calculate death penalty buff
  4387.         calculateDeathPenaltyBuffLevel(killer);
  4388.        
  4389.         stopWaterTask();
  4390.        
  4391.         if (isPhoenixBlessed())
  4392.             reviveRequest(this, null, false);
  4393.         else if (isAffected(CharEffectList.EFFECT_FLAG_CHARM_OF_COURAGE) && isInSiege())
  4394.             reviveRequest(this, null, false);
  4395.        
  4396.         // Icons update in order to get retained buffs list
  4397.         updateEffectIcons();
  4398.        
  4399.         return true;
  4400.     }
  4401.    
  4402.     private void onDieDropItem(L2Character killer)
  4403.     {
  4404.         if (killer == null)
  4405.             return;
  4406.        
  4407.         L2PlayerInstance pk = killer.getActingPlayer();
  4408.         if (getKarma() <= 0 && pk != null && pk.getClan() != null && getClan() != null
  4409.                 && pk.getClan().isAtWarWith(getClanId()))
  4410.             return;
  4411.        
  4412.         if ((!isInsideZone(ZONE_PVP) || pk == null) && (!isGM() || Config.KARMA_DROP_GM))
  4413.         {
  4414.             boolean isKillerNpc = (killer instanceof L2Npc);
  4415.             int pkLimit = Config.KARMA_PK_LIMIT;
  4416.            
  4417.             int dropEquip = 0;
  4418.             int dropEquipWeapon = 0;
  4419.             int dropItem = 0;
  4420.             int dropLimit = 0;
  4421.             int dropPercent = 0;
  4422.            
  4423.             if (getKarma() > 0 && getPkKills() >= pkLimit)
  4424.             {
  4425.                 dropPercent = Config.KARMA_RATE_DROP;
  4426.                 dropEquip = Config.KARMA_RATE_DROP_EQUIP;
  4427.                 dropEquipWeapon = Config.KARMA_RATE_DROP_EQUIP_WEAPON;
  4428.                 dropItem = Config.KARMA_RATE_DROP_ITEM;
  4429.                 dropLimit = Config.KARMA_DROP_LIMIT;
  4430.             }
  4431.             else if (isKillerNpc && getLevel() > 4 && !isFestivalParticipant())
  4432.             {
  4433.                 dropPercent = Config.PLAYER_RATE_DROP;
  4434.                 dropEquip = Config.PLAYER_RATE_DROP_EQUIP;
  4435.                 dropEquipWeapon = Config.PLAYER_RATE_DROP_EQUIP_WEAPON;
  4436.                 dropItem = Config.PLAYER_RATE_DROP_ITEM;
  4437.                 dropLimit = Config.PLAYER_DROP_LIMIT;
  4438.             }
  4439.            
  4440.             if (dropPercent > 0 && Rnd.get(100) < dropPercent)
  4441.             {
  4442.                 int dropCount = 0;
  4443.                 int itemDropPercent = 0;
  4444.                
  4445.                 for (L2ItemInstance itemDrop : getInventory().getItems())
  4446.                 {
  4447.                     // Don't drop those following things
  4448.                     if (!itemDrop.isDropable() || itemDrop.isShadowItem() || itemDrop.getItemId() == 57
  4449.                             || itemDrop.getItem().getType2() == L2Item.TYPE2_QUEST || getPet() != null
  4450.                             && getPet().getControlItemId() == itemDrop.getItemId()
  4451.                             || Arrays.binarySearch(Config.KARMA_LIST_NONDROPPABLE_ITEMS, itemDrop.getItemId()) >= 0
  4452.                             || Arrays.binarySearch(Config.KARMA_LIST_NONDROPPABLE_PET_ITEMS, itemDrop.getItemId()) >= 0)
  4453.                         continue;
  4454.                    
  4455.                     if (itemDrop.isEquipped())
  4456.                     {
  4457.                         // Set proper chance according to Item type of equipped Item
  4458.                         itemDropPercent =
  4459.                                 itemDrop.getItem().getType2() == L2Item.TYPE2_WEAPON ? dropEquipWeapon : dropEquip;
  4460.                         getInventory().unEquipItemInSlot(itemDrop.getLocationSlot());
  4461.                     }
  4462.                     else
  4463.                         itemDropPercent = dropItem; // Item in inventory
  4464.                        
  4465.                     // NOTE: Each time an item is dropped, the chance of another item being dropped gets lesser (dropCount * 2)
  4466.                     if (Rnd.get(100) < itemDropPercent)
  4467.                     {
  4468.                         dropItem("DieDrop", itemDrop, killer, true);
  4469.                        
  4470.                         if (++dropCount >= dropLimit)
  4471.                             break;
  4472.                     }
  4473.                 }
  4474.             }
  4475.         }
  4476.     }
  4477.    
  4478.     private void onDieUpdateKarma()
  4479.     {
  4480.         // Karma lose for server that does not allow delevel
  4481.         if (getKarma() > 0)
  4482.         {
  4483.             // this formula seems to work relatively well:
  4484.             // baseKarma * thisLVL * (thisLVL/100)
  4485.             // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
  4486.             double karmaLost = Config.KARMA_LOST_BASE;
  4487.             karmaLost *= getLevel(); // multiply by char lvl
  4488.             karmaLost *= (getLevel() / 100.0); // divide by 0.charLVL
  4489.             karmaLost = Math.round(karmaLost);
  4490.             if (karmaLost < 0)
  4491.                 karmaLost = 1;
  4492.            
  4493.             // Decrease Karma of the L2PlayerInstance and Send it a Server->Client StatusUpdate packet with Karma and PvP Flag if necessary
  4494.             setKarma(getKarma() - (int)karmaLost);
  4495.         }
  4496.     }
  4497.    
  4498.     public void onKillUpdatePvPKarma(L2Character target)
  4499.     {
  4500.         if (!(target instanceof L2Playable))
  4501.             return;
  4502.        
  4503.         final L2PlayerInstance targetPlayer = target.getActingPlayer();
  4504.         if (targetPlayer == null || targetPlayer == this)
  4505.             return;
  4506.        
  4507.         // Don't rank up the CW if it was a summon.
  4508.         if (isCursedWeaponEquipped() && target instanceof L2PlayerInstance)
  4509.         {
  4510.             CursedWeaponsManager.getInstance().increaseKills(_cursedWeaponEquippedId);
  4511.             return;
  4512.         }
  4513.        
  4514.         // If in duel and you kill (only can kill l2summon), do nothing
  4515.         if (isInDuel() && targetPlayer.isInDuel())
  4516.             return;
  4517.        
  4518.         if (isInsideClanwarZone() && targetPlayer.isInsideClanwarZone() && (getClan() != null)
  4519.                 && (targetPlayer.getClan() != null) && (getClanId() != targetPlayer.getClanId()))
  4520.         {
  4521.             getClan().addReputationScore(100);
  4522.             getClan().broadcastClanStatus();
  4523.             sendMessage("You killed someone from an enemy clan. Your clan gets rewarded with 100 rep points!");
  4524.         }
  4525.        
  4526.         // If in Arena, do nothing
  4527.         if (isInsideZone(ZONE_PVP) || targetPlayer.isInsideZone(ZONE_PVP))
  4528.             return;
  4529.        
  4530.         // Check if it's pvp
  4531.         if ((checkIfPvP(target) && targetPlayer.getPvpFlag() != 0)
  4532.                 || (isInsideZone(ZONE_PVP) && targetPlayer.isInsideZone(ZONE_PVP)))
  4533.             increasePvpKills();
  4534.         // Target player doesn't have pvp flag set
  4535.         else
  4536.         {
  4537.             // check about wars
  4538.             if (targetPlayer.getClan() != null && getClan() != null && getClan().isAtWarWith(targetPlayer.getClanId())
  4539.                     && targetPlayer.getClan().isAtWarWith(getClanId())
  4540.                     && targetPlayer.getPledgeType() != L2Clan.SUBUNIT_ACADEMY
  4541.                     && getPledgeType() != L2Clan.SUBUNIT_ACADEMY)
  4542.             {
  4543.                 // 'Both way war' -> 'PvP Kill'
  4544.                 increasePvpKills();
  4545.                 return;
  4546.             }
  4547.            
  4548.             // 'No war' or 'One way war' -> 'Normal PK'
  4549.             if (targetPlayer.getKarma() > 0)
  4550.             {
  4551.                 if (Config.KARMA_AWARD_PK_KILL)
  4552.                     increasePvpKills();
  4553.             }
  4554.             else if (targetPlayer.getPvpFlag() == 0)
  4555.                 increasePkKillsAndKarma(targetPlayer.getLevel());
  4556.         }
  4557.     }
  4558.    
  4559.     /**
  4560.      * Increase the pvp kills count and send the info to the player
  4561.      */
  4562.     public void increasePvpKills()
  4563.     {
  4564.         // Add karma to attacker and increase its PK counter
  4565.         setPvpKills(getPvpKills() + 1);
  4566.        
  4567.         // Send a Server->Client UserInfo packet to attacker with its Karma and PK Counter
  4568.         sendPacket(new UserInfo(this));
  4569.     }
  4570.    
  4571.     /**
  4572.      * Increase pk count, karma and send the info to the player
  4573.      *
  4574.      * @param targLVL : level of the killed player
  4575.      */
  4576.     public void increasePkKillsAndKarma(int targLVL)
  4577.     {
  4578.         int baseKarma = Config.KARMA_MIN_KARMA;
  4579.         int newKarma = baseKarma;
  4580.         int karmaLimit = Config.KARMA_MAX_KARMA;
  4581.        
  4582.         int pkLVL = getLevel();
  4583.         int pkPKCount = getPkKills();
  4584.        
  4585.         int lvlDiffMulti = 0;
  4586.         int pkCountMulti = 0;
  4587.        
  4588.         // Check if the attacker has a PK counter greater than 0
  4589.         if (pkPKCount > 0)
  4590.             pkCountMulti = pkPKCount / 2;
  4591.         else
  4592.             pkCountMulti = 1;
  4593.        
  4594.         if (pkCountMulti < 1)
  4595.             pkCountMulti = 1;
  4596.        
  4597.         // Calculate the level difference Multiplier between attacker and killed L2PlayerInstance
  4598.         if (pkLVL > targLVL)
  4599.             lvlDiffMulti = pkLVL / targLVL;
  4600.         else
  4601.             lvlDiffMulti = 1;
  4602.        
  4603.         if (lvlDiffMulti < 1)
  4604.             lvlDiffMulti = 1;
  4605.        
  4606.         // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
  4607.         newKarma *= pkCountMulti;
  4608.         newKarma *= lvlDiffMulti;
  4609.        
  4610.         // Make sure newKarma is less than karmaLimit and higher than baseKarma
  4611.         if (newKarma < baseKarma)
  4612.             newKarma = baseKarma;
  4613.        
  4614.         if (newKarma > karmaLimit)
  4615.             newKarma = karmaLimit;
  4616.        
  4617.         // Fix to prevent overflow (=> karma has a max value of 2 147 483 647)
  4618.         if (getKarma() > (Integer.MAX_VALUE - newKarma))
  4619.             newKarma = Integer.MAX_VALUE - getKarma();
  4620.        
  4621.         // Add karma to attacker and increase its PK counter
  4622.         setPkKills(getPkKills() + 1);
  4623.         setKarma(getKarma() + newKarma);
  4624.        
  4625.         // Send a Server->Client UserInfo packet to attacker with its Karma and PK Counter
  4626.         sendPacket(new UserInfo(this));
  4627.     }
  4628.    
  4629.     public int calculateKarmaLost(long exp)
  4630.     {
  4631.         // KARMA LOSS
  4632.         // When a PKer gets killed by another player or a L2MonsterInstance, it loses a certain amount of Karma based on their level.
  4633.         // this (with defaults) results in a level 1 losing about ~2 karma per death, and a lvl 70 loses about 11760 karma per death...
  4634.         // You lose karma as long as you were not in a pvp zone and you did not kill urself.
  4635.         // NOTE: exp for death (if delevel is allowed) is based on the players level
  4636.        
  4637.         long expGained = Math.abs(exp);
  4638.         expGained /= Config.KARMA_XP_DIVIDER;
  4639.        
  4640.         // FIXME Micht : Maybe this code should be fixed and karma set to a long value
  4641.         int karmaLost = 0;
  4642.         if (expGained > Integer.MAX_VALUE)
  4643.             karmaLost = Integer.MAX_VALUE;
  4644.         else
  4645.             karmaLost = (int)expGained;
  4646.        
  4647.         if (karmaLost < Config.KARMA_LOST_BASE)
  4648.             karmaLost = Config.KARMA_LOST_BASE;
  4649.         if (karmaLost > getKarma())
  4650.             karmaLost = getKarma();
  4651.        
  4652.         return karmaLost;
  4653.     }
  4654.    
  4655.     public void updatePvPStatus()
  4656.     {
  4657.         if (isInsideZone(ZONE_PVP))
  4658.             return;
  4659.        
  4660.         PvpFlagTaskManager.getInstance().addPvpFlagTask(this, System.currentTimeMillis() + Config.PVP_NORMAL_TIME);
  4661.        
  4662.         if (getPvpFlag() == 0)
  4663.             updatePvPFlag(1);
  4664.     }
  4665.    
  4666.     public void updatePvPStatus(L2Character target)
  4667.     {
  4668.         final L2PlayerInstance player = target.getActingPlayer();
  4669.         if (player == null)
  4670.             return;
  4671.        
  4672.         if ((isInDuel() && player.getDuelId() == getDuelId()))
  4673.             return;
  4674.        
  4675.         if ((!isInsideZone(ZONE_PVP) || !player.isInsideZone(ZONE_PVP)) && player.getKarma() == 0)
  4676.         {
  4677.             if (checkIfPvP(player))
  4678.                 PvpFlagTaskManager.getInstance().addPvpFlagTask(this, System.currentTimeMillis() + Config.PVP_PVP_TIME);
  4679.             else
  4680.                 PvpFlagTaskManager.getInstance().addPvpFlagTask(this,
  4681.                         System.currentTimeMillis() + Config.PVP_NORMAL_TIME);
  4682.            
  4683.             if (getPvpFlag() == 0)
  4684.                 updatePvPFlag(1);
  4685.         }
  4686.     }
  4687.    
  4688.     /**
  4689.      * Restore the experience this L2PlayerInstance has lost and sends a Server->Client StatusUpdate
  4690.      * packet.
  4691.      *
  4692.      * @param restorePercent The specified % of restored experience.
  4693.      */
  4694.     public void restoreExp(double restorePercent)
  4695.     {
  4696.         if (getExpBeforeDeath() > 0)
  4697.         {
  4698.             getStat().addExp((int)Math.round((getExpBeforeDeath() - getExp()) * restorePercent / 100));
  4699.             setExpBeforeDeath(0);
  4700.         }
  4701.     }
  4702.    
  4703.     /**
  4704.      * Reduce the Experience (and level if necessary) of the L2PlayerInstance in function of the
  4705.      * calculated Death Penalty.<BR>
  4706.      * <BR>
  4707.      * <B><U> Actions</U> :</B><BR>
  4708.      * <BR>
  4709.      * <li>Calculate the Experience loss</li> <li>Set the value of _expBeforeDeath</li> <li>Set the
  4710.      * new Experience value of the L2PlayerInstance and Decrease its level if necessary</li> <li>
  4711.      * Send a Server->Client StatusUpdate packet with its new Experience</li><BR>
  4712.      * <BR>
  4713.      *
  4714.      * @param atwar If true, use clan war penalty system instead of regular system.
  4715.      */
  4716.     public void deathPenalty(boolean atwar)
  4717.     {
  4718.         // Get the level of the L2PlayerInstance
  4719.         final int lvl = getLevel();
  4720.        
  4721.         // The death steal you some Exp
  4722.         double percentLost = 7.0;
  4723.         if (getLevel() >= 76)
  4724.             percentLost = 2.0;
  4725.         else if (getLevel() >= 40)
  4726.             percentLost = 4.0;
  4727.        
  4728.         if (getKarma() > 0)
  4729.             percentLost *= Config.RATE_KARMA_EXP_LOST;
  4730.        
  4731.         if (isFestivalParticipant() || atwar || isInsideZone(ZONE_SIEGE))
  4732.             percentLost /= 4.0;
  4733.        
  4734.         // Calculate the Experience loss
  4735.         long lostExp = 0;
  4736.        
  4737.         if (lvl < Experience.MAX_LEVEL)
  4738.             lostExp =
  4739.                     Math.round((getStat().getExpForLevel(lvl + 1) - getStat().getExpForLevel(lvl)) * percentLost / 100);
  4740.         else
  4741.             lostExp =
  4742.                     Math.round((getStat().getExpForLevel(Experience.MAX_LEVEL) - getStat().getExpForLevel(
  4743.                             Experience.MAX_LEVEL - 1))
  4744.                             * percentLost / 100);
  4745.        
  4746.         // Get the Experience before applying penalty
  4747.         setExpBeforeDeath(getExp());
  4748.        
  4749.         // Set the new Experience value of the L2PlayerInstance
  4750.         getStat().addExp(-lostExp);
  4751.     }
  4752.    
  4753.     public boolean isPartyWaiting()
  4754.     {
  4755.         return PartyMatchWaitingList.getInstance().getPlayers().contains(this);
  4756.     }
  4757.    
  4758.     public void setPartyRoom(int id)
  4759.     {
  4760.         _partyroom = id;
  4761.     }
  4762.    
  4763.     public int getPartyRoom()
  4764.     {
  4765.         return _partyroom;
  4766.     }
  4767.    
  4768.     public boolean isInPartyMatchRoom()
  4769.     {
  4770.         return _partyroom > 0;
  4771.     }
  4772.    
  4773.     /**
  4774.      * Manage the increase level task of a L2PlayerInstance (Max MP, Max MP, Recommandation,
  4775.      * Expertise and beginner skills...).<BR>
  4776.      * <BR>
  4777.      * <B><U> Actions</U> :</B><BR>
  4778.      * <BR>
  4779.      * <li>Send a Server->Client System Message to the L2PlayerInstance : YOU_INCREASED_YOUR_LEVEL</li>
  4780.      * <li>Send StatusUpdate to the L2PlayerInstance with new LEVEL, MAX_HP and MAX_MP</li> <li>Set
  4781.      * the current HP and MP of the L2PlayerInstance, Launch/Stop a HP/MP/CP Regeneration Task and
  4782.      * send StatusUpdate packet to all other L2PlayerInstance to inform (exclusive broadcast)</li>
  4783.      * <li>Recalculate the party level</li> <li>Recalculate the number of Recommandation that the
  4784.      * L2PlayerInstance can give</li> <li>Give Expertise skill of this level and remove beginner
  4785.      * Lucky skill</li><BR>
  4786.      * <BR>
  4787.      */
  4788.     public void increaseLevel()
  4789.     {
  4790.         // Set the current HP and MP of the L2Character, Launch/Stop a HP/MP/CP Regeneration Task and send StatusUpdate packet to all other L2PlayerInstance to inform (exclusive broadcast)
  4791.         setCurrentHpMp(getMaxHp(), getMaxMp());
  4792.         setCurrentCp(getMaxCp());
  4793.     }
  4794.    
  4795.     /**
  4796.      * Stop the HP/MP/CP Regeneration task.<BR>
  4797.      * <BR>
  4798.      * <B><U> Actions</U> :</B><BR>
  4799.      * <BR>
  4800.      * <li>Set the RegenActive flag to False</li> <li>Stop the HP/MP/CP Regeneration task</li><BR>
  4801.      * <BR>
  4802.      */
  4803.     public void stopAllTimers()
  4804.     {
  4805.         stopHpMpRegeneration();
  4806.         stopWaterTask();
  4807.         stopFeed();
  4808.         clearPetData();
  4809.         storePetFood(_mountNpcId);
  4810.         stopPunishTask(true);
  4811.         stopChargeTask();
  4812.        
  4813.         AttackStanceTaskManager.getInstance().removeAttackStanceTask(this);
  4814.         PvpFlagTaskManager.getInstance().removePvpFlagTask(this);
  4815.         TakeBreakTaskManager.getInstance().removeTakeBreakTask(this);
  4816.     }
  4817.    
  4818.     /**
  4819.      * Return the L2Summon of the L2PlayerInstance or null.
  4820.      */
  4821.     @Override
  4822.     public L2Summon getPet()
  4823.     {
  4824.         return _summon;
  4825.     }
  4826.    
  4827.     /**
  4828.      * @return {@code true} if the player has a pet, {@code false} otherwise
  4829.      */
  4830.     public boolean hasPet()
  4831.     {
  4832.         return _summon != null && _summon instanceof L2PetInstance;
  4833.     }
  4834.    
  4835.     /**
  4836.      * @return {@code true} if the player has a summon, {@code false} otherwise
  4837.      */
  4838.     public boolean hasServitor()
  4839.     {
  4840.         return _summon != null && _summon instanceof L2SummonInstance;
  4841.     }
  4842.    
  4843.     /**
  4844.      * Set the L2Summon of the L2PlayerInstance.
  4845.      *
  4846.      * @param summon The Object.
  4847.      */
  4848.     public void setPet(L2Summon summon)
  4849.     {
  4850.         _summon = summon;
  4851.     }
  4852.    
  4853.     /**
  4854.      * @return the L2TamedBeast of the L2PlayerInstance or null.
  4855.      */
  4856.     public L2TamedBeastInstance getTrainedBeast()
  4857.     {
  4858.         return _tamedBeast;
  4859.     }
  4860.    
  4861.     /**
  4862.      * Set the L2TamedBeast of the L2PlayerInstance.
  4863.      *
  4864.      * @param tamedBeast The Object.
  4865.      */
  4866.     public void setTrainedBeast(L2TamedBeastInstance tamedBeast)
  4867.     {
  4868.         _tamedBeast = tamedBeast;
  4869.     }
  4870.    
  4871.     /**
  4872.      * @return the L2PlayerInstance requester of a transaction (ex : FriendInvite, JoinAlly,
  4873.      *         JoinParty...).
  4874.      */
  4875.     public L2Request getRequest()
  4876.     {
  4877.         return _request;
  4878.     }
  4879.    
  4880.     /**
  4881.      * Set the L2PlayerInstance requester of a transaction (ex : FriendInvite, JoinAlly,
  4882.      * JoinParty...).
  4883.      *
  4884.      * @param requester
  4885.      */
  4886.     public void setActiveRequester(L2PlayerInstance requester)
  4887.     {
  4888.         _activeRequester = requester;
  4889.     }
  4890.    
  4891.     /**
  4892.      * @return the L2PlayerInstance requester of a transaction (ex : FriendInvite, JoinAlly,
  4893.      *         JoinParty...).
  4894.      */
  4895.     public L2PlayerInstance getActiveRequester()
  4896.     {
  4897.         L2PlayerInstance requester = _activeRequester;
  4898.         if (requester != null)
  4899.         {
  4900.             if (requester.isRequestExpired() && _activeTradeList == null)
  4901.                 _activeRequester = null;
  4902.         }
  4903.         return _activeRequester;
  4904.     }
  4905.    
  4906.     /**
  4907.      * @return True if a request is in progress.
  4908.      */
  4909.     public boolean isProcessingRequest()
  4910.     {
  4911.         return getActiveRequester() != null || _requestExpireTime > GameTimeController.getGameTicks();
  4912.     }
  4913.    
  4914.     /**
  4915.      * @return True if a transaction <B>(trade OR request)</B> is in progress.
  4916.      */
  4917.     public boolean isProcessingTransaction()
  4918.     {
  4919.         return getActiveRequester() != null || _activeTradeList != null
  4920.                 || _requestExpireTime > GameTimeController.getGameTicks();
  4921.     }
  4922.    
  4923.     /**
  4924.      * Set the _requestExpireTime of that L2PlayerInstance, and set his partner as the active
  4925.      * requester.
  4926.      *
  4927.      * @param partner The partner to make checks on.
  4928.      */
  4929.     public void onTransactionRequest(L2PlayerInstance partner)
  4930.     {
  4931.         _requestExpireTime = GameTimeController.getGameTicks() + REQUEST_TIMEOUT * GameTimeController.TICKS_PER_SECOND;
  4932.         partner.setActiveRequester(this);
  4933.     }
  4934.    
  4935.     /**
  4936.      * @return true if last request is expired.
  4937.      */
  4938.     public boolean isRequestExpired()
  4939.     {
  4940.         return !(_requestExpireTime > GameTimeController.getGameTicks());
  4941.     }
  4942.    
  4943.     /**
  4944.      * Select the Warehouse to be used in next activity.
  4945.      */
  4946.     public void onTransactionResponse()
  4947.     {
  4948.         _requestExpireTime = 0;
  4949.     }
  4950.    
  4951.     /**
  4952.      * Select the Warehouse to be used in next activity.
  4953.      *
  4954.      * @param warehouse An active warehouse.
  4955.      */
  4956.     public void setActiveWarehouse(ItemContainer warehouse)
  4957.     {
  4958.         _activeWarehouse = warehouse;
  4959.     }
  4960.    
  4961.     /**
  4962.      * @return The active Warehouse.
  4963.      */
  4964.     public ItemContainer getActiveWarehouse()
  4965.     {
  4966.         return _activeWarehouse;
  4967.     }
  4968.    
  4969.     /**
  4970.      * Set the TradeList to be used in next activity.
  4971.      *
  4972.      * @param tradeList The TradeList to be used.
  4973.      */
  4974.     public void setActiveTradeList(TradeList tradeList)
  4975.     {
  4976.         _activeTradeList = tradeList;
  4977.     }
  4978.    
  4979.     /**
  4980.      * @return The active TradeList.
  4981.      */
  4982.     public TradeList getActiveTradeList()
  4983.     {
  4984.         return _activeTradeList;
  4985.     }
  4986.    
  4987.     public void onTradeStart(L2PlayerInstance partner)
  4988.     {
  4989.         _activeTradeList = new TradeList(this);
  4990.         _activeTradeList.setPartner(partner);
  4991.        
  4992.         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.BEGIN_TRADE_WITH_S1).addString(partner.getName()));
  4993.         sendPacket(new TradeStart(this));
  4994.     }
  4995.    
  4996.     public void onTradeConfirm(L2PlayerInstance partner)
  4997.     {
  4998.         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_CONFIRMED_TRADE).addString(partner.getName()));
  4999.        
  5000.         partner.sendPacket(TradePressOwnOk.STATIC_PACKET);
  5001.         sendPacket(TradePressOtherOk.STATIC_PACKET);
  5002.     }
  5003.    
  5004.     public void onTradeCancel(L2PlayerInstance partner)
  5005.     {
  5006.         if (_activeTradeList == null)
  5007.             return;
  5008.        
  5009.         _activeTradeList.lock();
  5010.         _activeTradeList = null;
  5011.        
  5012.         sendPacket(new SendTradeDone(0));
  5013.         SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANCELED_TRADE);
  5014.         msg.addString(partner.getName());
  5015.         sendPacket(msg);
  5016.     }
  5017.    
  5018.     public void onTradeFinish(boolean successfull)
  5019.     {
  5020.         _activeTradeList = null;
  5021.         sendPacket(new SendTradeDone(1));
  5022.         if (successfull)
  5023.             sendPacket(SystemMessageId.TRADE_SUCCESSFUL);
  5024.     }
  5025.    
  5026.     public void startTrade(L2PlayerInstance partner)
  5027.     {
  5028.         onTradeStart(partner);
  5029.         partner.onTradeStart(this);
  5030.     }
  5031.    
  5032.     public void cancelActiveTrade()
  5033.     {
  5034.         if (_activeTradeList == null)
  5035.             return;
  5036.        
  5037.         L2PlayerInstance partner = _activeTradeList.getPartner();
  5038.         if (partner != null)
  5039.             partner.onTradeCancel(this);
  5040.        
  5041.         onTradeCancel(this);
  5042.     }
  5043.    
  5044.     /**
  5045.      * @return The _createList object of the L2PlayerInstance.
  5046.      */
  5047.     public L2ManufactureList getCreateList()
  5048.     {
  5049.         return _createList;
  5050.     }
  5051.    
  5052.     /**
  5053.      * Set the _createList object of the L2PlayerInstance.
  5054.      *
  5055.      * @param list
  5056.      */
  5057.     public void setCreateList(L2ManufactureList list)
  5058.     {
  5059.         _createList = list;
  5060.     }
  5061.    
  5062.     /**
  5063.      * @return The _sellList object of the L2PlayerInstance.
  5064.      */
  5065.     public TradeList getSellList()
  5066.     {
  5067.         if (_sellList == null)
  5068.             _sellList = new TradeList(this);
  5069.        
  5070.         return _sellList;
  5071.     }
  5072.    
  5073.     /**
  5074.      * @return the _buyList object of the L2PlayerInstance.
  5075.      */
  5076.     public TradeList getBuyList()
  5077.     {
  5078.         if (_buyList == null)
  5079.             _buyList = new TradeList(this);
  5080.        
  5081.         return _buyList;
  5082.     }
  5083.    
  5084.     /**
  5085.      * Set the Private Store type of the L2PlayerInstance.
  5086.      *
  5087.      * @param type The value : 0 = none, 1 = sell, 2 = sellmanage, 3 = buy, 4 = buymanage, 5 =
  5088.      *            manufacture.
  5089.      */
  5090.     public void setPrivateStoreType(int type)
  5091.     {
  5092.         _privatestore = type;
  5093.     }
  5094.    
  5095.     /**
  5096.      * @return The Private Store type of the L2PlayerInstance.
  5097.      */
  5098.     public int getPrivateStoreType()
  5099.     {
  5100.         return _privatestore;
  5101.     }
  5102.    
  5103.     /**
  5104.      * Set the _skillLearningClassId object of the L2PlayerInstance.
  5105.      *
  5106.      * @param classId The parameter.
  5107.      */
  5108.     public void setSkillLearningClassId(ClassId classId)
  5109.     {
  5110.         _skillLearningClassId = classId;
  5111.     }
  5112.    
  5113.     /**
  5114.      * @return The _skillLearningClassId object of the L2PlayerInstance.
  5115.      */
  5116.     public ClassId getSkillLearningClassId()
  5117.     {
  5118.         return _skillLearningClassId;
  5119.     }
  5120.    
  5121.     /**
  5122.      * Set the _clan object, _clanId, _clanLeader Flag and title of the L2PlayerInstance.
  5123.      *
  5124.      * @param clan The Clan object which is used to feed L2PlayerInstance values.
  5125.      */
  5126.     public void setClan(L2Clan clan)
  5127.     {
  5128.         _clan = clan;
  5129.         setTitle("");
  5130.        
  5131.         if (clan == null)
  5132.         {
  5133.             _clanId = 0;
  5134.             _clanPrivileges = 0;
  5135.             _pledgeType = 0;
  5136.             _powerGrade = 0;
  5137.             _lvlJoinedAcademy = 0;
  5138.             _apprentice = 0;
  5139.             _sponsor = 0;
  5140.             return;
  5141.         }
  5142.        
  5143.         if (!clan.isMember(getObjectId()))
  5144.         {
  5145.             // char has been kicked from clan
  5146.             setClan(null);
  5147.             return;
  5148.         }
  5149.        
  5150.         _clanId = clan.getClanId();
  5151.     }
  5152.    
  5153.     /**
  5154.      * @return The _clan object of the L2PlayerInstance.
  5155.      */
  5156.     public L2Clan getClan()
  5157.     {
  5158.         return _clan;
  5159.     }
  5160.    
  5161.     /**
  5162.      * @return True if the L2PlayerInstance is the leader of its clan.
  5163.      */
  5164.     public boolean isClanLeader()
  5165.     {
  5166.         if (getClan() == null)
  5167.             return false;
  5168.        
  5169.         return getObjectId() == getClan().getLeaderId();
  5170.     }
  5171.    
  5172.     /**
  5173.      * Reduce the number of arrows owned by the L2PlayerInstance and send it Server->Client Packet
  5174.      * InventoryUpdate or ItemList (to unequip if the last arrow was consummed).<BR>
  5175.      * <BR>
  5176.      */
  5177.     @Override
  5178.     protected void reduceArrowCount()
  5179.     {
  5180.         L2ItemInstance arrows = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
  5181.        
  5182.         if (arrows == null)
  5183.         {
  5184.             getInventory().unEquipItemInSlot(Inventory.PAPERDOLL_LHAND);
  5185.             _arrowItem = null;
  5186.             sendPacket(new ItemList(this, false));
  5187.             return;
  5188.         }
  5189.        
  5190.         // Adjust item quantity
  5191.         if (arrows.getCount() > 1)
  5192.         {
  5193.             synchronized (arrows)
  5194.             {
  5195.                 arrows.changeCountWithoutTrace(-1, this, null);
  5196.                 arrows.setLastChange(L2ItemInstance.MODIFIED);
  5197.                
  5198.                 // could do also without saving, but let's save approx 1 of 10
  5199.                 if (GameTimeController.getGameTicks() % 10 == 0)
  5200.                     arrows.updateDatabase();
  5201.                 _inventory.refreshWeight();
  5202.             }
  5203.         }
  5204.         else
  5205.         {
  5206.             // Destroy entire item and save to database
  5207.             _inventory.destroyItem("Consume", arrows, this, null);
  5208.            
  5209.             getInventory().unEquipItemInSlot(Inventory.PAPERDOLL_LHAND);
  5210.             _arrowItem = null;
  5211.            
  5212.             sendPacket(new ItemList(this, false));
  5213.             return;
  5214.         }
  5215.        
  5216.         InventoryUpdate iu = new InventoryUpdate();
  5217.         iu.addModifiedItem(arrows);
  5218.         sendPacket(iu);
  5219.     }
  5220.    
  5221.     /**
  5222.      * Equip arrows needed in left hand and send ItemList to the L2PcINstance then return True.<BR>
  5223.      * <BR>
  5224.      */
  5225.     @Override
  5226.     protected boolean checkAndEquipArrows()
  5227.     {
  5228.         // Check if nothing is equipped in left hand
  5229.         if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null)
  5230.         {
  5231.             // Get the L2ItemInstance of the arrows needed for this bow
  5232.             _arrowItem = getInventory().findArrowForBow(getActiveWeaponItem());
  5233.            
  5234.             if (_arrowItem != null)
  5235.             {
  5236.                 // Equip arrows needed in left hand
  5237.                 getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, _arrowItem);
  5238.                
  5239.                 // Send ItemList to this L2PcINstance to update left hand equipement
  5240.                 ItemList il = new ItemList(this, false);
  5241.                 sendPacket(il);
  5242.             }
  5243.         }
  5244.         else
  5245.         {
  5246.             // Get the L2ItemInstance of arrows equipped in left hand
  5247.             _arrowItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
  5248.         }
  5249.        
  5250.         return _arrowItem != null;
  5251.     }
  5252.    
  5253.     /**
  5254.      * Disarm the player's weapon and shield.
  5255.      *
  5256.      * @return true if successful, false otherwise.
  5257.      */
  5258.     public boolean disarmWeapons()
  5259.     {
  5260.         // Don't allow disarming a cursed weapon
  5261.         if (isCursedWeaponEquipped())
  5262.             return false;
  5263.        
  5264.         // Unequip the weapon
  5265.         L2ItemInstance wpn = getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
  5266.         if (wpn != null)
  5267.         {
  5268.             L2ItemInstance[] unequipped = getInventory().unEquipItemInBodySlotAndRecord(wpn.getItem().getBodyPart());
  5269.             InventoryUpdate iu = new InventoryUpdate();
  5270.             for (L2ItemInstance itm : unequipped)
  5271.                 iu.addModifiedItem(itm);
  5272.             sendPacket(iu);
  5273.            
  5274.             abortAttack();
  5275.             broadcastUserInfo();
  5276.            
  5277.             // this can be 0 if the user pressed the right mousebutton twice very fast
  5278.             if (unequipped.length > 0)
  5279.             {
  5280.                 SystemMessage sm;
  5281.                 if (unequipped[0].getEnchantLevel() > 0)
  5282.                     sm =
  5283.                             SystemMessage.getSystemMessage(SystemMessageId.EQUIPMENT_S1_S2_REMOVED)
  5284.                                     .addNumber(unequipped[0].getEnchantLevel()).addItemName(unequipped[0]);
  5285.                 else
  5286.                     sm = SystemMessage.getSystemMessage(SystemMessageId.S1_DISARMED).addItemName(unequipped[0]);
  5287.                
  5288.                 sendPacket(sm);
  5289.             }
  5290.         }
  5291.        
  5292.         // Unequip the shield
  5293.         L2ItemInstance sld = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
  5294.         if (sld != null)
  5295.         {
  5296.             L2ItemInstance[] unequipped = getInventory().unEquipItemInBodySlotAndRecord(sld.getItem().getBodyPart());
  5297.             InventoryUpdate iu = new InventoryUpdate();
  5298.             for (L2ItemInstance itm : unequipped)
  5299.                 iu.addModifiedItem(itm);
  5300.             sendPacket(iu);
  5301.            
  5302.             abortAttack();
  5303.             broadcastUserInfo();
  5304.            
  5305.             // this can be 0 if the user pressed the right mousebutton twice very fast
  5306.             if (unequipped.length > 0)
  5307.             {
  5308.                 SystemMessage sm;
  5309.                 if (unequipped[0].getEnchantLevel() > 0)
  5310.                     sm =
  5311.                             SystemMessage.getSystemMessage(SystemMessageId.EQUIPMENT_S1_S2_REMOVED)
  5312.                                     .addNumber(unequipped[0].getEnchantLevel()).addItemName(unequipped[0]);
  5313.                 else
  5314.                     sm = SystemMessage.getSystemMessage(SystemMessageId.S1_DISARMED).addItemName(unequipped[0]);
  5315.                
  5316.                 sendPacket(sm);
  5317.             }
  5318.         }
  5319.         return true;
  5320.     }
  5321.    
  5322.     public boolean mount(L2Summon pet)
  5323.     {
  5324.         if (!disarmWeapons())
  5325.             return false;
  5326.        
  5327.         stopAllToggles();
  5328.         Ride mount = new Ride(getObjectId(), Ride.ACTION_MOUNT, pet.getTemplate().getNpcId());
  5329.         setMount(pet.getNpcId(), pet.getLevel(), mount.getMountType());
  5330.         setMountObjectID(pet.getControlItemId());
  5331.         clearPetData();
  5332.         startFeed(pet.getNpcId());
  5333.         broadcastPacket(mount);
  5334.        
  5335.         // Notify self and others about speed change
  5336.         broadcastUserInfo();
  5337.        
  5338.         pet.unSummon(this);
  5339.         return true;
  5340.     }
  5341.    
  5342.     public boolean mount(int npcId, int controlItemId, boolean useFood)
  5343.     {
  5344.         if (!disarmWeapons())
  5345.             return false;
  5346.        
  5347.         stopAllToggles();
  5348.         Ride mount = new Ride(getObjectId(), Ride.ACTION_MOUNT, npcId);
  5349.         if (setMount(npcId, getLevel(), mount.getMountType()))
  5350.         {
  5351.             clearPetData();
  5352.             setMountObjectID(controlItemId);
  5353.             broadcastPacket(mount);
  5354.            
  5355.             // Notify self and others about speed change
  5356.             broadcastUserInfo();
  5357.            
  5358.             if (useFood)
  5359.                 startFeed(npcId);
  5360.            
  5361.             return true;
  5362.         }
  5363.         return false;
  5364.     }
  5365.    
  5366.     public boolean mountPlayer(L2Summon summon)
  5367.     {
  5368.         if (summon != null && summon.isMountable() && !isMounted() && !isBetrayed())
  5369.         {
  5370.             if (isDead()) // A strider cannot be ridden when dead.
  5371.             {
  5372.                 sendPacket(SystemMessageId.STRIDER_CANT_BE_RIDDEN_WHILE_DEAD);
  5373.                 return false;
  5374.             }
  5375.            
  5376.             if (summon.isDead()) // A dead strider cannot be ridden.
  5377.             {
  5378.                 sendPacket(SystemMessageId.DEAD_STRIDER_CANT_BE_RIDDEN);
  5379.                 return false;
  5380.             }
  5381.            
  5382.             if (summon.isInCombat() || summon.isRooted()) // A strider in battle cannot be ridden.
  5383.             {
  5384.                 sendPacket(SystemMessageId.STRIDER_IN_BATLLE_CANT_BE_RIDDEN);
  5385.                 return false;
  5386.             }
  5387.            
  5388.             if (isInCombat()) // A strider cannot be ridden while in battle
  5389.             {
  5390.                 sendPacket(SystemMessageId.STRIDER_CANT_BE_RIDDEN_WHILE_IN_BATTLE);
  5391.                 return false;
  5392.             }
  5393.            
  5394.             if (isSitting()) // A strider can be ridden only when standing
  5395.             {
  5396.                 sendPacket(SystemMessageId.STRIDER_CAN_BE_RIDDEN_ONLY_WHILE_STANDING);
  5397.                 return false;
  5398.             }
  5399.            
  5400.             if (isFishing()) // You can't mount, dismount, break and drop items while fishing
  5401.             {
  5402.                 sendPacket(SystemMessageId.CANNOT_DO_WHILE_FISHING_2);
  5403.                 return false;
  5404.             }
  5405.            
  5406.             if (isCursedWeaponEquipped()) // You can't mount, dismount, break and drop items while weilding a cursed weapon
  5407.             {
  5408.                 sendPacket(SystemMessageId.STRIDER_CANT_BE_RIDDEN_WHILE_IN_BATTLE);
  5409.                 return false;
  5410.             }
  5411.            
  5412.             if (!Util.checkIfInRange(200, this, summon, true))
  5413.             {
  5414.                 sendPacket(SystemMessageId.TOO_FAR_AWAY_FROM_STRIDER_TO_MOUNT);
  5415.                 return false;
  5416.             }
  5417.            
  5418.             if (summon.isHungry())
  5419.             {
  5420.                 sendPacket(SystemMessageId.HUNGRY_STRIDER_NOT_MOUNT);
  5421.                 return false;
  5422.             }
  5423.            
  5424.             if (!summon.isDead() && !isMounted())
  5425.                 mount(summon);
  5426.         }
  5427.         else if (isMounted())
  5428.         {
  5429.             if (getMountType() == 2 && isInsideZone(L2Character.ZONE_NOLANDING))
  5430.             {
  5431.                 sendPacket(SystemMessageId.NO_DISMOUNT_HERE);
  5432.                 return false;
  5433.             }
  5434.            
  5435.             if (isHungry())
  5436.             {
  5437.                 sendPacket(SystemMessageId.HUNGRY_STRIDER_NOT_MOUNT);
  5438.                 return false;
  5439.             }
  5440.            
  5441.             dismount();
  5442.         }
  5443.         return true;
  5444.     }
  5445.    
  5446.     public boolean dismount()
  5447.     {
  5448.         sendPacket(new SetupGauge(3, 0, 0));
  5449.         int petId = _mountNpcId;
  5450.         if (setMount(0, 0, 0))
  5451.         {
  5452.             stopFeed();
  5453.             clearPetData();
  5454.            
  5455.             broadcastPacket(new Ride(getObjectId(), Ride.ACTION_DISMOUNT, 0));
  5456.            
  5457.             setMountObjectID(0);
  5458.             storePetFood(petId);
  5459.            
  5460.             // Notify self and others about speed change
  5461.             broadcastUserInfo();
  5462.             return true;
  5463.         }
  5464.         return false;
  5465.     }
  5466.    
  5467.     public void storePetFood(int petId)
  5468.     {
  5469.         if (_controlItemId != 0 && petId != 0)
  5470.         {
  5471.             try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  5472.             {
  5473.                 PreparedStatement statement = con.prepareStatement("UPDATE pets SET fed=? WHERE item_obj_id = ?");
  5474.                 statement.setInt(1, getCurrentFeed());
  5475.                 statement.setInt(2, _controlItemId);
  5476.                 statement.executeUpdate();
  5477.                 statement.close();
  5478.                 _controlItemId = 0;
  5479.             }
  5480.             catch (Exception e)
  5481.             {
  5482.                 _log.log(Level.SEVERE, "Failed to store Pet [NpcId: " + petId + "] data", e);
  5483.             }
  5484.         }
  5485.     }
  5486.    
  5487.     protected class FeedTask implements Runnable
  5488.     {
  5489.         @Override
  5490.         public void run()
  5491.         {
  5492.             try
  5493.             {
  5494.                 if (!isMounted())
  5495.                 {
  5496.                     stopFeed();
  5497.                     return;
  5498.                 }
  5499.                
  5500.                 if (getCurrentFeed() > getFeedConsume())
  5501.                 {
  5502.                     // eat
  5503.                     setCurrentFeed(getCurrentFeed() - getFeedConsume());
  5504.                 }
  5505.                 else
  5506.                 {
  5507.                     // go back to pet control item, or simply said, unsummon it
  5508.                     setCurrentFeed(0);
  5509.                     stopFeed();
  5510.                     dismount();
  5511.                     sendPacket(SystemMessageId.OUT_OF_FEED_MOUNT_CANCELED);
  5512.                 }
  5513.                
  5514.                 int[] foodIds = getPetData(getMountNpcId()).getFood();
  5515.                 if (foodIds.length == 0)
  5516.                     return;
  5517.                
  5518.                 L2ItemInstance food = null;
  5519.                 for (int id : foodIds)
  5520.                 {
  5521.                     food = getInventory().getItemByItemId(id);
  5522.                     if (food != null)
  5523.                         break;
  5524.                 }
  5525.                
  5526.                 if (food != null && isHungry())
  5527.                 {
  5528.                     IItemHandler handler = ItemHandler.getInstance().getItemHandler(food.getEtcItem());
  5529.                     if (handler != null)
  5530.                     {
  5531.                         handler.useItem(L2PlayerInstance.this, food, false);
  5532.                         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.PET_TOOK_S1_BECAUSE_HE_WAS_HUNGRY)
  5533.                                 .addItemName(food));
  5534.                     }
  5535.                 }
  5536.             }
  5537.             catch (Exception e)
  5538.             {
  5539.                 _log.log(Level.SEVERE, "Mounted Pet [NpcId: " + getMountNpcId() + "] a feed task error has occurred", e);
  5540.             }
  5541.         }
  5542.     }
  5543.    
  5544.     protected synchronized void startFeed(int npcId)
  5545.     {
  5546.         _canFeed = npcId > 0;
  5547.         if (!isMounted())
  5548.             return;
  5549.        
  5550.         if (getPet() != null)
  5551.         {
  5552.             setCurrentFeed(((L2PetInstance)getPet()).getCurrentFed());
  5553.             _controlItemId = getPet().getControlItemId();
  5554.             sendPacket(new SetupGauge(3, getCurrentFeed() * 10000 / getFeedConsume(), getMaxFeed() * 10000
  5555.                     / getFeedConsume()));
  5556.             if (!isDead())
  5557.                 _mountFeedTask =
  5558.                         ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new FeedTask(), 10000, 10000);
  5559.         }
  5560.         else if (_canFeed)
  5561.         {
  5562.             setCurrentFeed(getMaxFeed());
  5563.             sendPacket(new SetupGauge(3, getCurrentFeed() * 10000 / getFeedConsume(), getMaxFeed() * 10000
  5564.                     / getFeedConsume()));
  5565.             if (!isDead())
  5566.                 _mountFeedTask =
  5567.                         ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new FeedTask(), 10000, 10000);
  5568.         }
  5569.     }
  5570.    
  5571.     protected synchronized void stopFeed()
  5572.     {
  5573.         if (_mountFeedTask != null)
  5574.         {
  5575.             _mountFeedTask.cancel(false);
  5576.             _mountFeedTask = null;
  5577.         }
  5578.     }
  5579.    
  5580.     private final void clearPetData()
  5581.     {
  5582.         _data = null;
  5583.     }
  5584.    
  5585.     protected final L2PetData getPetData(int npcId)
  5586.     {
  5587.         if (_data == null)
  5588.             _data = PetDataTable.getInstance().getPetData(npcId);
  5589.         return _data;
  5590.     }
  5591.    
  5592.     private final L2PetLevelData getPetLevelData(int npcId)
  5593.     {
  5594.         if (_leveldata == null)
  5595.             _leveldata = PetDataTable.getInstance().getPetData(npcId).getPetLevelData(getMountLevel());
  5596.         return _leveldata;
  5597.     }
  5598.    
  5599.     public int getCurrentFeed()
  5600.     {
  5601.         return _curFeed;
  5602.     }
  5603.    
  5604.     protected int getFeedConsume()
  5605.     {
  5606.         return (isAttackingNow()) ? getPetLevelData(_mountNpcId).getPetFeedBattle() : getPetLevelData(_mountNpcId)
  5607.                 .getPetFeedNormal();
  5608.     }
  5609.    
  5610.     public void setCurrentFeed(int num)
  5611.     {
  5612.         _curFeed = (num > getMaxFeed()) ? getMaxFeed() : num;
  5613.         sendPacket(new SetupGauge(3, getCurrentFeed() * 10000 / getFeedConsume(), getMaxFeed() * 10000
  5614.                 / getFeedConsume()));
  5615.     }
  5616.    
  5617.     private int getMaxFeed()
  5618.     {
  5619.         return getPetLevelData(_mountNpcId).getPetMaxFeed();
  5620.     }
  5621.    
  5622.     protected boolean isHungry()
  5623.     {
  5624.         return _canFeed ? (getCurrentFeed() < (getPetLevelData(getMountNpcId()).getPetMaxFeed() * 0.55)) : false;
  5625.     }
  5626.    
  5627.     /**
  5628.      * Return True if the L2PlayerInstance use a dual weapon.<BR>
  5629.      * <BR>
  5630.      */
  5631.     @Override
  5632.     public boolean isUsingDualWeapon()
  5633.     {
  5634.         L2Weapon weaponItem = getActiveWeaponItem();
  5635.         if (weaponItem == null)
  5636.             return false;
  5637.        
  5638.         if (weaponItem.getItemType() == L2WeaponType.DUAL)
  5639.             return true;
  5640.         else if (weaponItem.getItemType() == L2WeaponType.DUALFIST)
  5641.             return true;
  5642.         else
  5643.             return false;
  5644.     }
  5645.    
  5646.     public void setUptime(long time)
  5647.     {
  5648.         _uptime = time;
  5649.     }
  5650.    
  5651.     public long getUptime()
  5652.     {
  5653.         return System.currentTimeMillis() - _uptime;
  5654.     }
  5655.    
  5656.     /**
  5657.      * Return True if the L2PlayerInstance is invulnerable.
  5658.      */
  5659.     @Override
  5660.     public boolean isInvul()
  5661.     {
  5662.         return super.isInvul() || _protectEndTime > GameTimeController.getGameTicks();
  5663.     }
  5664.    
  5665.     /**
  5666.      * Return True if the L2PlayerInstance has a Party in progress.
  5667.      */
  5668.     @Override
  5669.     public boolean isInParty()
  5670.     {
  5671.         return _party != null;
  5672.     }
  5673.    
  5674.     /**
  5675.      * Set the _party object of the L2PlayerInstance (without joining it).
  5676.      *
  5677.      * @param party The object.
  5678.      */
  5679.     public void setParty(L2Party party)
  5680.     {
  5681.         _party = party;
  5682.     }
  5683.    
  5684.     /**
  5685.      * Set the _party object of the L2PlayerInstance AND join it.
  5686.      *
  5687.      * @param party
  5688.      */
  5689.     public void joinParty(L2Party party)
  5690.     {
  5691.         if (party != null)
  5692.         {
  5693.             _party = party;
  5694.             party.addPartyMember(this);
  5695.         }
  5696.     }
  5697.    
  5698.     /**
  5699.      * Manage the Leave Party task of the L2PlayerInstance.
  5700.      */
  5701.     public void leaveParty()
  5702.     {
  5703.         if (isInParty())
  5704.         {
  5705.             _party.removePartyMember(this);
  5706.             _party = null;
  5707.         }
  5708.     }
  5709.    
  5710.     /**
  5711.      * Return the _party object of the L2PlayerInstance.
  5712.      */
  5713.     @Override
  5714.     public L2Party getParty()
  5715.     {
  5716.         return _party;
  5717.     }
  5718.    
  5719.     /**
  5720.      * Return True if the L2PlayerInstance is a GM.
  5721.      */
  5722.     @Override
  5723.     public boolean isGM()
  5724.     {
  5725.         return getAccessLevel().isGm();
  5726.     }
  5727.    
  5728.     /**
  5729.      * Set the _accessLevel of the L2PlayerInstance.
  5730.      *
  5731.      * @param level
  5732.      */
  5733.     public void setAccessLevel(int level)
  5734.     {
  5735.         if (level == AccessLevels._masterAccessLevelNum)
  5736.         {
  5737.             _log.warning(getName() + " has logged in with Master access level.");
  5738.             _accessLevel = AccessLevels._masterAccessLevel;
  5739.         }
  5740.         else if (level == AccessLevels._userAccessLevelNum)
  5741.             _accessLevel = AccessLevels._userAccessLevel;
  5742.         else
  5743.         {
  5744.             L2AccessLevel accessLevel = AccessLevels.getInstance().getAccessLevel(level);
  5745.            
  5746.             if (accessLevel == null)
  5747.             {
  5748.                 if (level < 0)
  5749.                 {
  5750.                     AccessLevels.getInstance().addBanAccessLevel(level);
  5751.                     _accessLevel = AccessLevels.getInstance().getAccessLevel(level);
  5752.                 }
  5753.                 else
  5754.                 {
  5755.                     _log.warning("Server tried to set unregistered access level " + level + " to " + getName()
  5756.                             + ". His access level have been reseted to user level.");
  5757.                     _accessLevel = AccessLevels._userAccessLevel;
  5758.                 }
  5759.             }
  5760.             else
  5761.             {
  5762.                 _accessLevel = accessLevel;
  5763.                 setTitle(_accessLevel.getName());
  5764.             }
  5765.         }
  5766.        
  5767.         getAppearance().setNameColor(_accessLevel.getNameColor());
  5768.         getAppearance().setTitleColor(_accessLevel.getTitleColor());
  5769.         broadcastUserInfo();
  5770.        
  5771.         CharNameTable.getInstance().addName(this);
  5772.     }
  5773.    
  5774.     public void setAccountAccesslevel(int level)
  5775.     {
  5776.         LoginServerThread.getInstance().sendAccessLevel(getAccountName(), level);
  5777.     }
  5778.    
  5779.     /**
  5780.      * @return the _accessLevel of the L2PlayerInstance.
  5781.      */
  5782.     public L2AccessLevel getAccessLevel()
  5783.     {
  5784.         if (Config.EVERYBODY_HAS_ADMIN_RIGHTS)
  5785.             return AccessLevels._masterAccessLevel;
  5786.         else if (_accessLevel == null) /* This is here because inventory etc. is loaded before access level on login, so it is not null */
  5787.             setAccessLevel(AccessLevels._userAccessLevelNum);
  5788.        
  5789.         return _accessLevel;
  5790.     }
  5791.    
  5792.     /**
  5793.      * Update Stats of the L2PlayerInstance client side by sending Server->Client packet
  5794.      * UserInfo/StatusUpdate to this L2PlayerInstance and CharInfo/StatusUpdate to all
  5795.      * L2PlayerInstance in its _KnownPlayers (broadcast).
  5796.      *
  5797.      * @param broadcastType
  5798.      */
  5799.     public void updateAndBroadcastStatus(int broadcastType)
  5800.     {
  5801.         refreshOverloaded();
  5802.         refreshExpertisePenalty();
  5803.        
  5804.         if (broadcastType == 1)
  5805.             sendPacket(new UserInfo(this));
  5806.         else if (broadcastType == 2)
  5807.             broadcastUserInfo();
  5808.     }
  5809.    
  5810.     /**
  5811.      * Send a Server->Client StatusUpdate packet with Karma to the L2PlayerInstance and all
  5812.      * L2PlayerInstance to inform (broadcast).
  5813.      */
  5814.     public void broadcastKarma()
  5815.     {
  5816.         StatusUpdate su = new StatusUpdate(this);
  5817.         su.addAttribute(StatusUpdate.KARMA, getKarma());
  5818.         sendPacket(su);
  5819.        
  5820.         if (getPet() != null)
  5821.             sendPacket(new RelationChanged(getPet(), getRelation(this), false));
  5822.        
  5823.         broadcastRelationsChanges();
  5824.     }
  5825.    
  5826.     /**
  5827.      * Set the online Flag to True or False and update the characters table of the database with
  5828.      * online status and lastAccess (called when login and logout).
  5829.      *
  5830.      * @param isOnline
  5831.      * @param updateInDb
  5832.      */
  5833.     public void setOnlineStatus(boolean isOnline, boolean updateInDb)
  5834.     {
  5835.         if (_isOnline != isOnline)
  5836.             _isOnline = isOnline;
  5837.        
  5838.         // Update the characters table of the database with online status and lastAccess (called when login and logout)
  5839.         if (updateInDb)
  5840.             updateOnlineStatus();
  5841.     }
  5842.    
  5843.     public void setIsIn7sDungeon(boolean isIn7sDungeon)
  5844.     {
  5845.         _isIn7sDungeon = isIn7sDungeon;
  5846.     }
  5847.    
  5848.     /**
  5849.      * Update the characters table of the database with online status and lastAccess of this
  5850.      * L2PlayerInstance (called when login and logout).
  5851.      */
  5852.     public void updateOnlineStatus()
  5853.     {
  5854.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  5855.         {
  5856.             PreparedStatement statement =
  5857.                     con.prepareStatement("UPDATE characters SET online=?, lastAccess=? WHERE obj_id=?");
  5858.             statement.setInt(1, isOnlineInt());
  5859.             statement.setLong(2, System.currentTimeMillis());
  5860.             statement.setInt(3, getObjectId());
  5861.             statement.execute();
  5862.             statement.close();
  5863.         }
  5864.         catch (Exception e)
  5865.         {
  5866.             _log.warning("could not set char online status:" + e);
  5867.         }
  5868.     }
  5869.    
  5870.     /**
  5871.      * Create a new player in the characters table of the database.
  5872.      *
  5873.      * @return true if successful.
  5874.      */
  5875.     private boolean createDb()
  5876.     {
  5877.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  5878.         {
  5879.             PreparedStatement statement = con.prepareStatement(INSERT_CHARACTER);
  5880.             statement.setString(1, _accountName);
  5881.             statement.setInt(2, getObjectId());
  5882.             statement.setString(3, getName());
  5883.             statement.setInt(4, getLevel());
  5884.             statement.setInt(5, getMaxHp());
  5885.             statement.setDouble(6, getCurrentHp());
  5886.             statement.setInt(7, getMaxCp());
  5887.             statement.setDouble(8, getCurrentCp());
  5888.             statement.setInt(9, getMaxMp());
  5889.             statement.setDouble(10, getCurrentMp());
  5890.             statement.setInt(11, getAppearance().getFace());
  5891.             statement.setInt(12, getAppearance().getHairStyle());
  5892.             statement.setInt(13, getAppearance().getHairColor());
  5893.             statement.setInt(14, getAppearance().getSex() ? 1 : 0);
  5894.             statement.setLong(15, getExp());
  5895.             statement.setInt(16, getSp());
  5896.             statement.setInt(17, getKarma());
  5897.             statement.setInt(18, getPvpKills());
  5898.             statement.setInt(19, getPkKills());
  5899.             statement.setInt(20, getClanId());
  5900.             statement.setInt(21, getRace().ordinal());
  5901.             statement.setInt(22, getClassId().getId());
  5902.             statement.setLong(23, getDeleteTimer());
  5903.             statement.setInt(24, hasDwarvenCraft() ? 1 : 0);
  5904.             statement.setString(25, getTitle());
  5905.             statement.setInt(26, getAccessLevel().getLevel());
  5906.             statement.setInt(27, isOnlineInt());
  5907.             statement.setInt(28, isIn7sDungeon() ? 1 : 0);
  5908.             statement.setInt(29, getClanPrivileges());
  5909.             statement.setInt(30, getWantsPeace());
  5910.             statement.setInt(31, getBaseClass());
  5911.             statement.setInt(32, isNoble() ? 1 : 0);
  5912.             statement.setLong(33, 0);
  5913.             statement.setLong(34, System.currentTimeMillis());
  5914.             statement.executeUpdate();
  5915.             statement.close();
  5916.         }
  5917.         catch (Exception e)
  5918.         {
  5919.             _log.severe("Could not insert char data: " + e);
  5920.             return false;
  5921.         }
  5922.         return true;
  5923.     }
  5924.    
  5925.     /**
  5926.      * Retrieve a L2PlayerInstance from the characters table of the database and add it in
  5927.      * _allObjects of the L2world.<BR>
  5928.      * <BR>
  5929.      * <B><U> Actions</U> :</B><BR>
  5930.      * <BR>
  5931.      * <li>Retrieve the L2PlayerInstance from the characters table of the database</li> <li>Add the
  5932.      * L2PlayerInstance object in _allObjects</li> <li>Set the x,y,z position of the
  5933.      * L2PlayerInstance and make it invisible</li> <li>Update the overloaded status of the
  5934.      * L2PlayerInstance</li><BR>
  5935.      * <BR>
  5936.      *
  5937.      * @param objectId Identifier of the object to initialized
  5938.      * @return The L2PlayerInstance loaded from the database
  5939.      */
  5940.     private static L2PlayerInstance restore(int objectId)
  5941.     {
  5942.         L2PlayerInstance player = null;
  5943.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  5944.         {
  5945.             PreparedStatement statement = con.prepareStatement(RESTORE_CHARACTER);
  5946.             statement.setInt(1, objectId);
  5947.             ResultSet rset = statement.executeQuery();
  5948.            
  5949.             double currentCp = 0;
  5950.             double currentHp = 0;
  5951.             double currentMp = 0;
  5952.            
  5953.             while (rset.next())
  5954.             {
  5955.                 final int activeClassId = rset.getInt("classid");
  5956.                 final L2PlayerTemplate template = CharTemplateTable.getInstance().getTemplate(activeClassId);
  5957.                 PcAppearance app =
  5958.                         new PcAppearance(rset.getByte("face"), rset.getByte("hairColor"), rset.getByte("hairStyle"),
  5959.                                 rset.getInt("sex") != 0);
  5960.                
  5961.                 player = new L2PlayerInstance(objectId, template, rset.getString("account_name"), app);
  5962.                 player.setName(rset.getString("char_name"));
  5963.                 player._lastAccess = rset.getLong("lastAccess");
  5964.                
  5965.                 player.getStat().setExp(rset.getLong("exp"));
  5966.                 player.setExpBeforeDeath(rset.getLong("expBeforeDeath"));
  5967.                 player.getStat().setLevel(rset.getByte("level"));
  5968.                 player.getStat().setSp(rset.getInt("sp"));
  5969.                
  5970.                 player.setWantsPeace(rset.getInt("wantspeace"));
  5971.                
  5972.                 player.setHeading(rset.getInt("heading"));
  5973.                
  5974.                 player.setKarma(rset.getInt("karma"));
  5975.                 player.setPvpKills(rset.getInt("pvpkills"));
  5976.                 player.setPkKills(rset.getInt("pkkills"));
  5977.                 player.setOnlineTime(rset.getLong("onlinetime"));
  5978.                 player.setNoble(rset.getInt("nobless") == 1, false);
  5979.                
  5980.                 player.setClanJoinExpiryTime(rset.getLong("clan_join_expiry_time"));
  5981.                 if (player.getClanJoinExpiryTime() < System.currentTimeMillis())
  5982.                     player.setClanJoinExpiryTime(0);
  5983.                
  5984.                 player.setClanCreateExpiryTime(rset.getLong("clan_create_expiry_time"));
  5985.                 if (player.getClanCreateExpiryTime() < System.currentTimeMillis())
  5986.                     player.setClanCreateExpiryTime(0);
  5987.                
  5988.                 player.setPowerGrade((int)rset.getLong("power_grade"));
  5989.                 player.setPledgeType(rset.getInt("subpledge"));
  5990.                 player.setLastRecomUpdate(rset.getLong("last_recom_date"));
  5991.                
  5992.                 int clanId = rset.getInt("clanid");
  5993.                 if (clanId > 0)
  5994.                     player.setClan(ClanTable.getInstance().getClan(clanId));
  5995.                
  5996.                 if (player.getClan() != null)
  5997.                 {
  5998.                     if (player.getClan().getLeaderId() != player.getObjectId())
  5999.                     {
  6000.                         if (player.getPowerGrade() == 0)
  6001.                             player.setPowerGrade(5);
  6002.                        
  6003.                         player.setClanPrivileges(player.getClan().getRankPrivs(player.getPowerGrade()));
  6004.                     }
  6005.                     else
  6006.                     {
  6007.                         player.setClanPrivileges(L2Clan.CP_ALL);
  6008.                         player.setPowerGrade(1);
  6009.                     }
  6010.                 }
  6011.                 else
  6012.                     player.setClanPrivileges(L2Clan.CP_NOTHING);
  6013.                
  6014.                 player.setPledgeClass(L2ClanMember.calculatePledgeClass(player));
  6015.                 player.setDeleteTimer(rset.getLong("deletetime"));
  6016.                
  6017.                 player.setTitle(rset.getString("title"));
  6018.                 player.setAccessLevel(rset.getInt("accesslevel"));
  6019.                 player.setFistsWeaponItem(findFistsWeaponItem(activeClassId));
  6020.                 player.setUptime(System.currentTimeMillis());
  6021.                
  6022.                 currentHp = rset.getDouble("curHp");
  6023.                 currentCp = rset.getDouble("curCp");
  6024.                 currentMp = rset.getDouble("curMp");
  6025.                
  6026.                 // Check recs
  6027.                 player.checkRecom(rset.getInt("rec_have"), rset.getInt("rec_left"));
  6028.                
  6029.                 player._classIndex = 0;
  6030.                 try
  6031.                 {
  6032.                     player.setBaseClass(rset.getInt("base_class"));
  6033.                 }
  6034.                 catch (Exception e)
  6035.                 {
  6036.                     player.setBaseClass(activeClassId);
  6037.                 }
  6038.                
  6039.                 // Restore Subclass Data (cannot be done earlier in function)
  6040.                 if (restoreSubClassData(player))
  6041.                 {
  6042.                     if (activeClassId != player.getBaseClass())
  6043.                     {
  6044.                         for (SubClass subClass : player.getSubClasses().values())
  6045.                             if (subClass.getClassId() == activeClassId)
  6046.                                 player._classIndex = subClass.getClassIndex();
  6047.                     }
  6048.                 }
  6049.                 if (player.getClassIndex() == 0 && activeClassId != player.getBaseClass())
  6050.                 {
  6051.                     // Subclass in use but doesn't exist in DB -
  6052.                     // a possible restart-while-modifysubclass cheat has been attempted.
  6053.                     // Switching to use base class
  6054.                     player.setClassId(player.getBaseClass());
  6055.                     _log.warning("Player " + player.getName()
  6056.                             + " reverted to base class. Possibly has tried a relogin exploit while subclassing.");
  6057.                 }
  6058.                 else
  6059.                     player._activeClass = activeClassId;
  6060.                
  6061.                 player.setApprentice(rset.getInt("apprentice"));
  6062.                 player.setSponsor(rset.getInt("sponsor"));
  6063.                 player.setLvlJoinedAcademy(rset.getInt("lvl_joined_academy"));
  6064.                 player.setIsIn7sDungeon(rset.getInt("isin7sdungeon") == 1);
  6065.                 player.setPunishLevel(rset.getInt("punish_level"));
  6066.                 if (player.getPunishLevel() != PunishLevel.NONE)
  6067.                     player.setPunishTimer(rset.getLong("punish_timer"));
  6068.                 else
  6069.                     player.setPunishTimer(0);
  6070.                
  6071.                 CursedWeaponsManager.getInstance().checkPlayer(player);
  6072.                
  6073.                 player.setAllianceWithVarkaKetra(rset.getInt("varka_ketra_ally"));
  6074.                
  6075.                 player.setDeathPenaltyBuffLevel(rset.getInt("death_penalty_level"));
  6076.                
  6077.                 // Set the x,y,z position of the L2PlayerInstance and make it invisible
  6078.                 player.setXYZInvisible(rset.getInt("x"), rset.getInt("y"), rset.getInt("z"));
  6079.                
  6080.                 // Set Hero status if it applies
  6081.                 if (Hero.getInstance().isActiveHero(objectId))
  6082.                     player.setHero(true);
  6083.                
  6084.                 // Retrieve from the database all secondary data of this L2PlayerInstance and reward expertise/lucky skills if necessary.
  6085.                 // Note that Clan, Noblesse and Hero skills are given separately and not here.
  6086.                 player.restoreCharData();
  6087.                 player.rewardSkills();
  6088.                
  6089.                 // Restore current Cp, HP and MP values
  6090.                 player.setCurrentCp(currentCp);
  6091.                 player.setCurrentHp(currentHp);
  6092.                 player.setCurrentMp(currentMp);
  6093.                
  6094.                 if (currentHp < 0.5)
  6095.                 {
  6096.                     player.setIsDead(true);
  6097.                     player.stopHpMpRegeneration();
  6098.                 }
  6099.                
  6100.                 // Restore pet if exists in the world
  6101.                 player.setPet(L2World.getInstance().getPet(player.getObjectId()));
  6102.                 if (player.getPet() != null)
  6103.                     player.getPet().setOwner(player);
  6104.                
  6105.                 player.refreshOverloaded();
  6106.                 player.refreshExpertisePenalty();
  6107.                
  6108.                 player.restoreFriendList();
  6109.                
  6110.                 // Retrieve the name and ID of the other characters assigned to this account.
  6111.                 PreparedStatement stmt =
  6112.                         con.prepareStatement("SELECT obj_Id, char_name FROM characters WHERE account_name=? AND obj_Id<>?");
  6113.                 stmt.setString(1, player._accountName);
  6114.                 stmt.setInt(2, objectId);
  6115.                 ResultSet chars = stmt.executeQuery();
  6116.                
  6117.                 while (chars.next())
  6118.                     player._chars.put(chars.getInt("obj_Id"), chars.getString("char_name"));
  6119.                
  6120.                 chars.close();
  6121.                 stmt.close();
  6122.                 break;
  6123.             }
  6124.            
  6125.             rset.close();
  6126.             statement.close();
  6127.         }
  6128.         catch (Exception e)
  6129.         {
  6130.             _log.severe("Could not restore char data: " + e);
  6131.         }
  6132.        
  6133.         return player;
  6134.     }
  6135.    
  6136.     /**
  6137.      * @return
  6138.      */
  6139.     public Forum getMail()
  6140.     {
  6141.         if (_forumMail == null)
  6142.         {
  6143.             setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").getChildByName(getName()));
  6144.            
  6145.             if (_forumMail == null)
  6146.             {
  6147.                 ForumsBBSManager.getInstance().createNewForum(getName(),
  6148.                         ForumsBBSManager.getInstance().getForumByName("MailRoot"), Forum.MAIL, Forum.OWNERONLY,
  6149.                         getObjectId());
  6150.                 setMail(ForumsBBSManager.getInstance().getForumByName("MailRoot").getChildByName(getName()));
  6151.             }
  6152.         }
  6153.        
  6154.         return _forumMail;
  6155.     }
  6156.    
  6157.     /**
  6158.      * @param forum
  6159.      */
  6160.     public void setMail(Forum forum)
  6161.     {
  6162.         _forumMail = forum;
  6163.     }
  6164.    
  6165.     /**
  6166.      * @return
  6167.      */
  6168.     public Forum getMemo()
  6169.     {
  6170.         if (_forumMemo == null)
  6171.         {
  6172.             setMemo(ForumsBBSManager.getInstance().getForumByName("MemoRoot").getChildByName(_accountName));
  6173.            
  6174.             if (_forumMemo == null)
  6175.             {
  6176.                 ForumsBBSManager.getInstance().createNewForum(_accountName,
  6177.                         ForumsBBSManager.getInstance().getForumByName("MemoRoot"), Forum.MEMO, Forum.OWNERONLY,
  6178.                         getObjectId());
  6179.                 setMemo(ForumsBBSManager.getInstance().getForumByName("MemoRoot").getChildByName(_accountName));
  6180.             }
  6181.         }
  6182.        
  6183.         return _forumMemo;
  6184.     }
  6185.    
  6186.     /**
  6187.      * @param forum
  6188.      */
  6189.     public void setMemo(Forum forum)
  6190.     {
  6191.         _forumMemo = forum;
  6192.     }
  6193.    
  6194.     /**
  6195.      * Restores sub-class data for the L2PlayerInstance, used to check the current class index for
  6196.      * the character.
  6197.      *
  6198.      * @param player The player to make checks on.
  6199.      * @return true if successful.
  6200.      */
  6201.     private static boolean restoreSubClassData(L2PlayerInstance player)
  6202.     {
  6203.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6204.         {
  6205.             PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_SUBCLASSES);
  6206.             statement.setInt(1, player.getObjectId());
  6207.            
  6208.             ResultSet rset = statement.executeQuery();
  6209.            
  6210.             while (rset.next())
  6211.             {
  6212.                 SubClass subClass = new SubClass();
  6213.                 subClass.setClassId(rset.getInt("class_id"));
  6214.                 subClass.setLevel(rset.getByte("level"));
  6215.                 subClass.setExp(rset.getLong("exp"));
  6216.                 subClass.setSp(rset.getInt("sp"));
  6217.                 subClass.setClassIndex(rset.getInt("class_index"));
  6218.                
  6219.                 // Enforce the correct indexing of _subClasses against their class indexes.
  6220.                 player.getSubClasses().put(subClass.getClassIndex(), subClass);
  6221.             }
  6222.            
  6223.             statement.close();
  6224.         }
  6225.         catch (Exception e)
  6226.         {
  6227.             _log.warning("Could not restore classes for " + player.getName() + ": " + e);
  6228.             e.printStackTrace();
  6229.         }
  6230.        
  6231.         return true;
  6232.     }
  6233.    
  6234.     /**
  6235.      * Restores secondary data for the L2PlayerInstance, based on the current class index.
  6236.      */
  6237.     private void restoreCharData()
  6238.     {
  6239.         // Retrieve from the database all skills of this L2PlayerInstance and add them to _skills.
  6240.         restoreSkills();
  6241.        
  6242.         // Retrieve from the database all macroses of this L2PlayerInstance and add them to _macroses.
  6243.         _macroses.restore();
  6244.        
  6245.         // Retrieve from the database all shortCuts of this L2PlayerInstance and add them to _shortCuts.
  6246.         _shortCuts.restore();
  6247.        
  6248.         // Retrieve from the database all henna of this L2PlayerInstance and add them to _henna.
  6249.         restoreHenna();
  6250.        
  6251.         // Retrieve from the database all recom data of this L2PlayerInstance and add to _recomChars.
  6252.         restoreRecom();
  6253.        
  6254.         // Retrieve from the database the recipe book of this L2PlayerInstance.
  6255.         if (!isSubClassActive())
  6256.             restoreRecipeBook();
  6257.     }
  6258.    
  6259.     /**
  6260.      * Store recipe book data for this L2PlayerInstance, if not on an active sub-class.
  6261.      */
  6262.     private void storeRecipeBook()
  6263.     {
  6264.         // If the player is on a sub-class don't even attempt to store a recipe book.
  6265.         if (isSubClassActive())
  6266.             return;
  6267.         if (getCommonRecipeBook().length == 0 && getDwarvenRecipeBook().length == 0)
  6268.             return;
  6269.        
  6270.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6271.         {
  6272.             PreparedStatement statement = con.prepareStatement("DELETE FROM character_recipebook WHERE char_id=?");
  6273.             statement.setInt(1, getObjectId());
  6274.             statement.execute();
  6275.             statement.close();
  6276.            
  6277.             L2RecipeList[] recipes = getCommonRecipeBook();
  6278.            
  6279.             for (L2RecipeList recipe : recipes)
  6280.             {
  6281.                 statement = con.prepareStatement("INSERT INTO character_recipebook (char_id, id, type) values(?,?,0)");
  6282.                 statement.setInt(1, getObjectId());
  6283.                 statement.setInt(2, recipe.getId());
  6284.                 statement.execute();
  6285.                 statement.close();
  6286.             }
  6287.            
  6288.             recipes = getDwarvenRecipeBook();
  6289.             for (L2RecipeList recipe : recipes)
  6290.             {
  6291.                 statement = con.prepareStatement("INSERT INTO character_recipebook (char_id, id, type) values(?,?,1)");
  6292.                 statement.setInt(1, getObjectId());
  6293.                 statement.setInt(2, recipe.getId());
  6294.                 statement.execute();
  6295.                 statement.close();
  6296.             }
  6297.         }
  6298.         catch (Exception e)
  6299.         {
  6300.             _log.warning("Could not store recipe book data: " + e);
  6301.         }
  6302.     }
  6303.    
  6304.     /**
  6305.      * Restore recipe book data for this L2PlayerInstance.
  6306.      */
  6307.     private void restoreRecipeBook()
  6308.     {
  6309.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6310.         {
  6311.             PreparedStatement statement =
  6312.                     con.prepareStatement("SELECT id, type FROM character_recipebook WHERE char_id=?");
  6313.             statement.setInt(1, getObjectId());
  6314.             ResultSet rset = statement.executeQuery();
  6315.            
  6316.             L2RecipeList recipe;
  6317.             while (rset.next())
  6318.             {
  6319.                 recipe = RecipeController.getInstance().getRecipeList(rset.getInt("id"));
  6320.                
  6321.                 if (rset.getInt("type") == 1)
  6322.                     registerDwarvenRecipeList(recipe);
  6323.                 else
  6324.                     registerCommonRecipeList(recipe);
  6325.             }
  6326.            
  6327.             rset.close();
  6328.             statement.close();
  6329.         }
  6330.         catch (Exception e)
  6331.         {
  6332.             _log.warning("Could not restore recipe book data:" + e);
  6333.         }
  6334.     }
  6335.    
  6336.     /**
  6337.      * Update L2PlayerInstance stats in the characters table of the database.
  6338.      *
  6339.      * @param storeActiveEffects
  6340.      */
  6341.     public synchronized void store(boolean storeActiveEffects)
  6342.     {
  6343.         // update client coords, if these look like true
  6344.         if (isInsideRadius(getClientX(), getClientY(), 1000, true))
  6345.             setXYZ(getClientX(), getClientY(), getClientZ());
  6346.        
  6347.         storeCharBase();
  6348.         storeCharSub();
  6349.         storeEffect(storeActiveEffects);
  6350.         storeRecipeBook();
  6351.         SevenSigns.getInstance().saveSevenSignsData(getObjectId());
  6352.     }
  6353.    
  6354.     public void store()
  6355.     {
  6356.         store(true);
  6357.     }
  6358.    
  6359.     private void storeCharBase()
  6360.     {
  6361.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6362.         {
  6363.             // Get the exp, level, and sp of base class to store in base table
  6364.             int currentClassIndex = getClassIndex();
  6365.             _classIndex = 0;
  6366.             long exp = getStat().getExp();
  6367.             int level = getStat().getLevel();
  6368.             int sp = getStat().getSp();
  6369.             _classIndex = currentClassIndex;
  6370.            
  6371.             PreparedStatement statement = con.prepareStatement(UPDATE_CHARACTER);
  6372.            
  6373.             statement.setInt(1, level);
  6374.             statement.setInt(2, getMaxHp());
  6375.             statement.setDouble(3, getCurrentHp());
  6376.             statement.setInt(4, getMaxCp());
  6377.             statement.setDouble(5, getCurrentCp());
  6378.             statement.setInt(6, getMaxMp());
  6379.             statement.setDouble(7, getCurrentMp());
  6380.             statement.setInt(8, getAppearance().getFace());
  6381.             statement.setInt(9, getAppearance().getHairStyle());
  6382.             statement.setInt(10, getAppearance().getHairColor());
  6383.             statement.setInt(11, getAppearance().getSex() ? 1 : 0);
  6384.             statement.setInt(12, getHeading());
  6385.             statement.setInt(13, _observerMode ? _lastX : getX());
  6386.             statement.setInt(14, _observerMode ? _lastY : getY());
  6387.             statement.setInt(15, _observerMode ? _lastZ : getZ());
  6388.             statement.setLong(16, exp);
  6389.             statement.setLong(17, getExpBeforeDeath());
  6390.             statement.setInt(18, sp);
  6391.             statement.setInt(19, getKarma());
  6392.             statement.setInt(20, getPvpKills());
  6393.             statement.setInt(21, getPkKills());
  6394.             statement.setInt(22, getRecomHave());
  6395.             statement.setInt(23, getRecomLeft());
  6396.             statement.setInt(24, getClanId());
  6397.             statement.setInt(25, getRace().ordinal());
  6398.             statement.setInt(26, getClassId().getId());
  6399.             statement.setLong(27, getDeleteTimer());
  6400.             statement.setString(28, getTitle());
  6401.             statement.setInt(29, getAccessLevel().getLevel());
  6402.             statement.setInt(30, isOnlineInt());
  6403.             statement.setInt(31, isIn7sDungeon() ? 1 : 0);
  6404.             statement.setInt(32, getClanPrivileges());
  6405.             statement.setInt(33, getWantsPeace());
  6406.             statement.setInt(34, getBaseClass());
  6407.            
  6408.             long totalOnlineTime = _onlineTime;
  6409.             if (_onlineBeginTime > 0)
  6410.                 totalOnlineTime += (System.currentTimeMillis() - _onlineBeginTime) / 1000;
  6411.            
  6412.             statement.setLong(35, totalOnlineTime);
  6413.             statement.setInt(36, getPunishLevel().value());
  6414.             statement.setLong(37, getPunishTimer());
  6415.             statement.setInt(38, isNoble() ? 1 : 0);
  6416.             statement.setLong(39, getPowerGrade());
  6417.             statement.setInt(40, getPledgeType());
  6418.             statement.setLong(41, getLastRecomUpdate());
  6419.             statement.setInt(42, getLvlJoinedAcademy());
  6420.             statement.setLong(43, getApprentice());
  6421.             statement.setLong(44, getSponsor());
  6422.             statement.setInt(45, getAllianceWithVarkaKetra());
  6423.             statement.setLong(46, getClanJoinExpiryTime());
  6424.             statement.setLong(47, getClanCreateExpiryTime());
  6425.             statement.setString(48, getName());
  6426.             statement.setLong(49, getDeathPenaltyBuffLevel());
  6427.             statement.setInt(50, getObjectId());
  6428.            
  6429.             statement.execute();
  6430.             statement.close();
  6431.         }
  6432.         catch (Exception e)
  6433.         {
  6434.             _log.warning("Could not store char base data: " + e);
  6435.         }
  6436.     }
  6437.    
  6438.     private void storeCharSub()
  6439.     {
  6440.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6441.         {
  6442.             PreparedStatement statement = con.prepareStatement(UPDATE_CHAR_SUBCLASS);
  6443.            
  6444.             if (getTotalSubClasses() > 0)
  6445.             {
  6446.                 for (SubClass subClass : getSubClasses().values())
  6447.                 {
  6448.                     statement.setLong(1, subClass.getExp());
  6449.                     statement.setInt(2, subClass.getSp());
  6450.                     statement.setInt(3, subClass.getLevel());
  6451.                     statement.setInt(4, subClass.getClassId());
  6452.                     statement.setInt(5, getObjectId());
  6453.                     statement.setInt(6, subClass.getClassIndex());
  6454.                    
  6455.                     statement.execute();
  6456.                 }
  6457.             }
  6458.             statement.close();
  6459.         }
  6460.         catch (Exception e)
  6461.         {
  6462.             _log.warning("Could not store sub class data for " + getName() + ": " + e);
  6463.         }
  6464.     }
  6465.    
  6466.     private void storeEffect(boolean storeEffects)
  6467.     {
  6468.         if (!Config.STORE_SKILL_COOLTIME)
  6469.             return;
  6470.        
  6471.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6472.         {
  6473.             // Delete all current stored effects for char to avoid dupe
  6474.             PreparedStatement statement = con.prepareStatement(DELETE_SKILL_SAVE);
  6475.            
  6476.             statement.setInt(1, getObjectId());
  6477.             statement.setInt(2, getClassIndex());
  6478.             statement.execute();
  6479.             statement.close();
  6480.            
  6481.             int buff_index = 0;
  6482.            
  6483.             final List<Integer> storedSkills = new ArrayList<>();
  6484.            
  6485.             // Store all effect data along with calulated remaining
  6486.             // reuse delays for matching skills. 'restore_type'= 0.
  6487.             statement = con.prepareStatement(ADD_SKILL_SAVE);
  6488.            
  6489.             if (storeEffects)
  6490.             {
  6491.                 for (L2Effect effect : getAllEffects())
  6492.                 {
  6493.                     if (effect == null)
  6494.                         continue;
  6495.                    
  6496.                     switch (effect.getEffectType())
  6497.                     {
  6498.                         case HEAL_OVER_TIME:
  6499.                         case COMBAT_POINT_HEAL_OVER_TIME:
  6500.                             continue;
  6501.                         default:
  6502.                             break;
  6503.                     }
  6504.                    
  6505.                     L2Skill skill = effect.getSkill();
  6506.                     if (storedSkills.contains(skill.getReuseHashCode()))
  6507.                         continue;
  6508.                    
  6509.                     storedSkills.add(skill.getReuseHashCode());
  6510.                    
  6511.                     if (!effect.isHerbEffect() && effect.getInUse() && !skill.isToggle())
  6512.                     {
  6513.                         statement.setInt(1, getObjectId());
  6514.                         statement.setInt(2, skill.getId());
  6515.                         statement.setInt(3, skill.getLevel());
  6516.                         statement.setInt(4, effect.getCount());
  6517.                         statement.setInt(5, effect.getTime());
  6518.                        
  6519.                         if (_reuseTimeStamps.containsKey(skill.getReuseHashCode()))
  6520.                         {
  6521.                             TimeStamp t = _reuseTimeStamps.get(skill.getReuseHashCode());
  6522.                             statement.setLong(6, t.hasNotPassed() ? t.getReuse() : 0);
  6523.                             statement.setDouble(7, t.hasNotPassed() ? t.getStamp() : 0);
  6524.                         }
  6525.                         else
  6526.                         {
  6527.                             statement.setLong(6, 0);
  6528.                             statement.setDouble(7, 0);
  6529.                         }
  6530.                        
  6531.                         statement.setInt(8, 0);
  6532.                         statement.setInt(9, getClassIndex());
  6533.                         statement.setInt(10, ++buff_index);
  6534.                         statement.execute();
  6535.                     }
  6536.                 }
  6537.             }
  6538.            
  6539.             // Store the reuse delays of remaining skills which
  6540.             // lost effect but still under reuse delay. 'restore_type' 1.
  6541.             for (int hash : _reuseTimeStamps.keySet())
  6542.             {
  6543.                 if (storedSkills.contains(hash))
  6544.                     continue;
  6545.                
  6546.                 TimeStamp t = _reuseTimeStamps.get(hash);
  6547.                 if (t != null && t.hasNotPassed())
  6548.                 {
  6549.                     storedSkills.add(hash);
  6550.                    
  6551.                     statement.setInt(1, getObjectId());
  6552.                     statement.setInt(2, t.getSkillId());
  6553.                     statement.setInt(3, t.getSkillLvl());
  6554.                     statement.setInt(4, -1);
  6555.                     statement.setInt(5, -1);
  6556.                     statement.setLong(6, t.getReuse());
  6557.                     statement.setDouble(7, t.getStamp());
  6558.                     statement.setInt(8, 1);
  6559.                     statement.setInt(9, getClassIndex());
  6560.                     statement.setInt(10, ++buff_index);
  6561.                     statement.execute();
  6562.                 }
  6563.             }
  6564.             statement.close();
  6565.         }
  6566.         catch (Exception e)
  6567.         {
  6568.             _log.log(Level.WARNING, "Could not store char effect data: ", e);
  6569.         }
  6570.     }
  6571.    
  6572.     /**
  6573.      * @return True if the L2PlayerInstance is online.
  6574.      */
  6575.     public boolean isOnline()
  6576.     {
  6577.         return _isOnline;
  6578.     }
  6579.    
  6580.     /**
  6581.      * @return an int interpretation of online status.
  6582.      */
  6583.     public int isOnlineInt()
  6584.     {
  6585.         if (_isOnline && getClient() != null)
  6586.             return getClient().isDetached() ? 2 : 1;
  6587.        
  6588.         return 0;
  6589.     }
  6590.    
  6591.     public boolean isIn7sDungeon()
  6592.     {
  6593.         return _isIn7sDungeon;
  6594.     }
  6595.    
  6596.     /**
  6597.      * Add a skill to the L2PlayerInstance _skills and its Func objects to the calculator set of the
  6598.      * L2PlayerInstance and save update in the character_skills table of the database.<BR>
  6599.      * <BR>
  6600.      * <B><U> Concept</U> :</B><BR>
  6601.      * <BR>
  6602.      * All skills own by a L2PlayerInstance are identified in <B>_skills</B><BR>
  6603.      * <BR>
  6604.      * <B><U> Actions</U> :</B><BR>
  6605.      * <BR>
  6606.      * <li>Replace oldSkill by newSkill or Add the newSkill</li> <li>If an old skill has been
  6607.      * replaced, remove all its Func objects of L2Character calculator set</li> <li>Add Func objects
  6608.      * of newSkill to the calculator set of the L2Character</li><BR>
  6609.      * <BR>
  6610.      *
  6611.      * @param newSkill The L2Skill to add to the L2Character
  6612.      * @param store
  6613.      * @return The L2Skill replaced or null if just added a new L2Skill
  6614.      */
  6615.     public L2Skill addSkill(L2Skill newSkill, boolean store)
  6616.     {
  6617.         // Add a skill to the L2PlayerInstance _skills and its Func objects to the calculator set of the L2PlayerInstance
  6618.         L2Skill oldSkill = super.addSkill(newSkill);
  6619.        
  6620.         // Add or update a L2PlayerInstance skill in the character_skills table of the database
  6621.         if (store)
  6622.             storeSkill(newSkill, oldSkill, -1);
  6623.        
  6624.         return oldSkill;
  6625.     }
  6626.    
  6627.     @Override
  6628.     public L2Skill removeSkill(L2Skill skill, boolean store)
  6629.     {
  6630.         if (store)
  6631.             return removeSkill(skill);
  6632.        
  6633.         return super.removeSkill(skill, true);
  6634.     }
  6635.    
  6636.     public L2Skill removeSkill(L2Skill skill, boolean store, boolean cancelEffect)
  6637.     {
  6638.         if (store)
  6639.             return removeSkill(skill);
  6640.        
  6641.         return super.removeSkill(skill, cancelEffect);
  6642.     }
  6643.    
  6644.     /**
  6645.      * Remove a skill from the L2Character and its Func objects from calculator set of the
  6646.      * L2Character and save update in the character_skills table of the database.<BR>
  6647.      * <BR>
  6648.      * <B><U> Concept</U> :</B><BR>
  6649.      * <BR>
  6650.      * All skills own by a L2Character are identified in <B>_skills</B><BR>
  6651.      * <BR>
  6652.      * <B><U> Actions</U> :</B><BR>
  6653.      * <BR>
  6654.      * <li>Remove the skill from the L2Character _skills</li> <li>Remove all its Func objects from
  6655.      * the L2Character calculator set</li><BR>
  6656.      * <BR>
  6657.      * <B><U> Overriden in </U> :</B><BR>
  6658.      * <BR>
  6659.      * <li>L2PlayerInstance : Save update in the character_skills table of the database</li><BR>
  6660.      * <BR>
  6661.      *
  6662.      * @param skill The L2Skill to remove from the L2Character
  6663.      * @return The L2Skill removed
  6664.      */
  6665.     @Override
  6666.     public L2Skill removeSkill(L2Skill skill)
  6667.     {
  6668.         // Remove a skill from the L2Character and its Func objects from calculator set of the L2Character
  6669.         L2Skill oldSkill = super.removeSkill(skill);
  6670.        
  6671.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6672.         {
  6673.             PreparedStatement statement = con.prepareStatement(DELETE_SKILL_FROM_CHAR);
  6674.            
  6675.             if (oldSkill != null)
  6676.             {
  6677.                 statement.setInt(1, oldSkill.getId());
  6678.                 statement.setInt(2, getObjectId());
  6679.                 statement.setInt(3, getClassIndex());
  6680.                 statement.execute();
  6681.             }
  6682.             statement.close();
  6683.         }
  6684.         catch (Exception e)
  6685.         {
  6686.             _log.warning("Error could not delete skill: " + e);
  6687.         }
  6688.        
  6689.         // Don't busy with shortcuts if skill was a passive skill.
  6690.         if (skill != null && !skill.isPassive())
  6691.         {
  6692.             L2ShortCut[] allShortCuts = getAllShortCuts();
  6693.            
  6694.             for (L2ShortCut sc : allShortCuts)
  6695.             {
  6696.                 if (sc != null && sc.getId() == skill.getId() && sc.getType() == L2ShortCut.TYPE_SKILL)
  6697.                     deleteShortCut(sc.getSlot(), sc.getPage());
  6698.             }
  6699.         }
  6700.        
  6701.         return oldSkill;
  6702.     }
  6703.    
  6704.     /**
  6705.      * Add or update a L2PlayerInstance skill in the character_skills table of the database. <BR>
  6706.      * <BR>
  6707.      * If newClassIndex > -1, the skill will be stored with that class index, not the current one.
  6708.      *
  6709.      * @param newSkill
  6710.      * @param oldSkill
  6711.      * @param newClassIndex
  6712.      */
  6713.     private void storeSkill(L2Skill newSkill, L2Skill oldSkill, int newClassIndex)
  6714.     {
  6715.         int classIndex = _classIndex;
  6716.        
  6717.         if (newClassIndex > -1)
  6718.             classIndex = newClassIndex;
  6719.        
  6720.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6721.         {
  6722.             PreparedStatement statement;
  6723.            
  6724.             if (oldSkill != null && newSkill != null)
  6725.             {
  6726.                 statement = con.prepareStatement(UPDATE_CHARACTER_SKILL_LEVEL);
  6727.                 statement.setInt(1, newSkill.getLevel());
  6728.                 statement.setInt(2, oldSkill.getId());
  6729.                 statement.setInt(3, getObjectId());
  6730.                 statement.setInt(4, classIndex);
  6731.                 statement.execute();
  6732.                 statement.close();
  6733.             }
  6734.             else if (newSkill != null)
  6735.             {
  6736.                 statement = con.prepareStatement(ADD_NEW_SKILL);
  6737.                 statement.setInt(1, getObjectId());
  6738.                 statement.setInt(2, newSkill.getId());
  6739.                 statement.setInt(3, newSkill.getLevel());
  6740.                 statement.setInt(4, classIndex);
  6741.                 statement.execute();
  6742.                 statement.close();
  6743.             }
  6744.             else
  6745.             {
  6746.                 _log.warning("storeSkill() couldn't store new skill. It's null type.");
  6747.             }
  6748.         }
  6749.         catch (Exception e)
  6750.         {
  6751.             _log.warning("Error could not store char skills: " + e);
  6752.         }
  6753.     }
  6754.    
  6755.     /**
  6756.      * Retrieve from the database all skills of this L2PlayerInstance and add them to _skills.
  6757.      */
  6758.     private void restoreSkills()
  6759.     {
  6760.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6761.         {
  6762.             PreparedStatement statement = con.prepareStatement(RESTORE_SKILLS_FOR_CHAR);
  6763.             statement.setInt(1, getObjectId());
  6764.             statement.setInt(2, getClassIndex());
  6765.             ResultSet rset = statement.executeQuery();
  6766.            
  6767.             // Go though the recordset of this SQL query
  6768.             while (rset.next())
  6769.             {
  6770.                 int id = rset.getInt("skill_id");
  6771.                 int level = rset.getInt("skill_level");
  6772.                
  6773.                 if (id > 9000)
  6774.                     continue; // fake skills for base stats
  6775.                    
  6776.                 // Create a L2Skill object for each record
  6777.                 L2Skill skill = SkillTable.getInstance().getInfo(id, level);
  6778.                
  6779.                 // Add the L2Skill object to the L2Character _skills and its Func objects to the calculator set of the L2Character
  6780.                 super.addSkill(skill);
  6781.             }
  6782.            
  6783.             rset.close();
  6784.             statement.close();
  6785.         }
  6786.         catch (Exception e)
  6787.         {
  6788.             _log.warning("Could not restore character skills: " + e);
  6789.         }
  6790.     }
  6791.    
  6792.     /**
  6793.      * Retrieve from the database all skill effects of this L2PlayerInstance and add them to the
  6794.      * player.
  6795.      */
  6796.     public void restoreEffects()
  6797.     {
  6798.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6799.         {
  6800.             PreparedStatement statement = con.prepareStatement(RESTORE_SKILL_SAVE);
  6801.             statement.setInt(1, getObjectId());
  6802.             statement.setInt(2, getClassIndex());
  6803.             ResultSet rset = statement.executeQuery();
  6804.            
  6805.             while (rset.next())
  6806.             {
  6807.                 int effectCount = rset.getInt("effect_count");
  6808.                 int effectCurTime = rset.getInt("effect_cur_time");
  6809.                 long reuseDelay = rset.getLong("reuse_delay");
  6810.                 long systime = rset.getLong("systime");
  6811.                 int restoreType = rset.getInt("restore_type");
  6812.                
  6813.                 final L2Skill skill =
  6814.                         SkillTable.getInstance().getInfo(rset.getInt("skill_id"), rset.getInt("skill_level"));
  6815.                 if (skill == null)
  6816.                     continue;
  6817.                
  6818.                 final long remainingTime = systime - System.currentTimeMillis();
  6819.                 if (remainingTime > 10)
  6820.                 {
  6821.                     disableSkill(skill, remainingTime);
  6822.                     addTimeStamp(skill, reuseDelay, systime);
  6823.                 }
  6824.                
  6825.                 /**
  6826.                  * Restore Type 1 The remaning skills lost effect upon logout but were still under a
  6827.                  * high reuse delay.
  6828.                  */
  6829.                 if (restoreType > 0)
  6830.                     continue;
  6831.                
  6832.                 /**
  6833.                  * Restore Type 0 These skills were still in effect on the character upon logout.
  6834.                  * Some of which were self casted and might still have a long reuse delay which also
  6835.                  * is restored.
  6836.                  */
  6837.                 if (skill.hasEffects())
  6838.                 {
  6839.                     Env env = new Env();
  6840.                     env.player = this;
  6841.                     env.target = this;
  6842.                     env.skill = skill;
  6843.                     L2Effect ef;
  6844.                     for (EffectTemplate et : skill.getEffectTemplates())
  6845.                     {
  6846.                         ef = et.getEffect(env);
  6847.                         if (ef != null)
  6848.                         {
  6849.                             ef.setCount(effectCount);
  6850.                             ef.setFirstTime(effectCurTime);
  6851.                             ef.scheduleEffect();
  6852.                         }
  6853.                     }
  6854.                 }
  6855.             }
  6856.            
  6857.             rset.close();
  6858.             statement.close();
  6859.            
  6860.             statement = con.prepareStatement(DELETE_SKILL_SAVE);
  6861.             statement.setInt(1, getObjectId());
  6862.             statement.setInt(2, getClassIndex());
  6863.             statement.executeUpdate();
  6864.             statement.close();
  6865.         }
  6866.         catch (Exception e)
  6867.         {
  6868.             _log.log(Level.WARNING, "Could not restore " + this + " active effect data: " + e.getMessage(), e);
  6869.         }
  6870.     }
  6871.    
  6872.     /**
  6873.      * Retrieve from the database all Henna of this L2PlayerInstance, add them to _henna and
  6874.      * calculate stats of the L2PlayerInstance.
  6875.      */
  6876.     private void restoreHenna()
  6877.     {
  6878.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6879.         {
  6880.             PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_HENNAS);
  6881.             statement.setInt(1, getObjectId());
  6882.             statement.setInt(2, getClassIndex());
  6883.             ResultSet rset = statement.executeQuery();
  6884.            
  6885.             for (int i = 0; i < 3; i++)
  6886.                 _henna[i] = null;
  6887.            
  6888.             while (rset.next())
  6889.             {
  6890.                 int slot = rset.getInt("slot");
  6891.                
  6892.                 if (slot < 1 || slot > 3)
  6893.                     continue;
  6894.                
  6895.                 int symbolId = rset.getInt("symbol_id");
  6896.                 if (symbolId != 0)
  6897.                 {
  6898.                     L2Henna tpl = HennaTable.getInstance().getTemplate(symbolId);
  6899.                     if (tpl != null)
  6900.                         _henna[slot - 1] = tpl;
  6901.                 }
  6902.             }
  6903.            
  6904.             rset.close();
  6905.             statement.close();
  6906.         }
  6907.         catch (Exception e)
  6908.         {
  6909.             _log.warning("could not restore henna: " + e);
  6910.         }
  6911.        
  6912.         // Calculate Henna modifiers of this L2PlayerInstance
  6913.         recalcHennaStats();
  6914.     }
  6915.    
  6916.     /**
  6917.      * Retrieve from the database all Recommendation data of this L2PlayerInstance, add to
  6918.      * _recomChars and calculate stats of the L2PlayerInstance.
  6919.      */
  6920.     private void restoreRecom()
  6921.     {
  6922.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6923.         {
  6924.             PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_RECOMS);
  6925.             statement.setInt(1, getObjectId());
  6926.             ResultSet rset = statement.executeQuery();
  6927.             while (rset.next())
  6928.                 _recomChars.add(rset.getInt("target_id"));
  6929.            
  6930.             rset.close();
  6931.             statement.close();
  6932.         }
  6933.         catch (Exception e)
  6934.         {
  6935.             _log.warning("could not restore recommendations: " + e);
  6936.         }
  6937.     }
  6938.    
  6939.     /**
  6940.      * @return the number of Henna empty slot of the L2PlayerInstance.
  6941.      */
  6942.     public int getHennaEmptySlots()
  6943.     {
  6944.         int totalSlots = 0;
  6945.         if (getClassId().level() == 1)
  6946.             totalSlots = 2;
  6947.         else
  6948.             totalSlots = 3;
  6949.        
  6950.         for (int i = 0; i < 3; i++)
  6951.         {
  6952.             if (_henna[i] != null)
  6953.                 totalSlots--;
  6954.         }
  6955.        
  6956.         if (totalSlots <= 0)
  6957.             return 0;
  6958.        
  6959.         return totalSlots;
  6960.     }
  6961.    
  6962.     /**
  6963.      * Remove a Henna of the L2PlayerInstance, save update in the character_hennas table of the
  6964.      * database and send Server->Client HennaInfo/UserInfo packet to this L2PlayerInstance.
  6965.      *
  6966.      * @param slot The slot number to make checks on.
  6967.      * @return true if successful.
  6968.      */
  6969.     public boolean removeHenna(int slot)
  6970.     {
  6971.         if (slot < 1 || slot > 3)
  6972.             return false;
  6973.        
  6974.         slot--;
  6975.        
  6976.         if (_henna[slot] == null)
  6977.             return false;
  6978.        
  6979.         L2Henna henna = _henna[slot];
  6980.         _henna[slot] = null;
  6981.        
  6982.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  6983.         {
  6984.             PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA);
  6985.            
  6986.             statement.setInt(1, getObjectId());
  6987.             statement.setInt(2, slot + 1);
  6988.             statement.setInt(3, getClassIndex());
  6989.            
  6990.             statement.execute();
  6991.             statement.close();
  6992.         }
  6993.         catch (Exception e)
  6994.         {
  6995.             _log.warning("could not remove char henna: " + e);
  6996.         }
  6997.        
  6998.         // Calculate Henna modifiers of this L2PlayerInstance
  6999.         recalcHennaStats();
  7000.        
  7001.         // Send Server->Client HennaInfo packet to this L2PlayerInstance
  7002.         sendPacket(new HennaInfo(this));
  7003.        
  7004.         // Send Server->Client UserInfo packet to this L2PlayerInstance
  7005.         sendPacket(new UserInfo(this));
  7006.        
  7007.         // Add the recovered dyes to the player's inventory and notify them.
  7008.         getInventory().addItem("Henna", henna.getDyeId(), L2Henna.getAmountDyeRequire() / 2, this, null);
  7009.         reduceAdena("Henna", henna.getPrice() / 5, this, false);
  7010.        
  7011.         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S).addItemName(henna.getDyeId())
  7012.                 .addNumber(L2Henna.getAmountDyeRequire() / 2));
  7013.         sendPacket(SystemMessageId.SYMBOL_DELETED);
  7014.         return true;
  7015.     }
  7016.    
  7017.     /**
  7018.      * Add a Henna to the L2PlayerInstance, save update in the character_hennas table of the
  7019.      * database and send Server->Client HennaInfo/UserInfo packet to this L2PlayerInstance.
  7020.      *
  7021.      * @param henna The Henna template to add.
  7022.      */
  7023.     public void addHenna(L2Henna henna)
  7024.     {
  7025.         for (int i = 0; i < 3; i++)
  7026.         {
  7027.             if (_henna[i] == null)
  7028.             {
  7029.                 _henna[i] = henna;
  7030.                
  7031.                 // Calculate Henna modifiers of this L2PlayerInstance
  7032.                 recalcHennaStats();
  7033.                
  7034.                 try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  7035.                 {
  7036.                     PreparedStatement statement = con.prepareStatement(ADD_CHAR_HENNA);
  7037.                    
  7038.                     statement.setInt(1, getObjectId());
  7039.                     statement.setInt(2, henna.getSymbolId());
  7040.                     statement.setInt(3, i + 1);
  7041.                     statement.setInt(4, getClassIndex());
  7042.                    
  7043.                     statement.execute();
  7044.                     statement.close();
  7045.                 }
  7046.                 catch (Exception e)
  7047.                 {
  7048.                     _log.warning("could not save char henna: " + e);
  7049.                 }
  7050.                
  7051.                 sendPacket(new HennaInfo(this));
  7052.                 sendPacket(new UserInfo(this));
  7053.                 sendPacket(SystemMessageId.SYMBOL_ADDED);
  7054.                 return;
  7055.             }
  7056.         }
  7057.     }
  7058.    
  7059.     /**
  7060.      * Calculate Henna modifiers of this L2PlayerInstance.<BR>
  7061.      * <BR>
  7062.      */
  7063.     private void recalcHennaStats()
  7064.     {
  7065.         _hennaINT = 0;
  7066.         _hennaSTR = 0;
  7067.         _hennaCON = 0;
  7068.         _hennaMEN = 0;
  7069.         _hennaWIT = 0;
  7070.         _hennaDEX = 0;
  7071.        
  7072.         for (int i = 0; i < 3; i++)
  7073.         {
  7074.             if (_henna[i] == null)
  7075.                 continue;
  7076.            
  7077.             _hennaINT += _henna[i].getStatINT();
  7078.             _hennaSTR += _henna[i].getStatSTR();
  7079.             _hennaMEN += _henna[i].getStatMEN();
  7080.             _hennaCON += _henna[i].getStatCON();
  7081.             _hennaWIT += _henna[i].getStatWIT();
  7082.             _hennaDEX += _henna[i].getStatDEX();
  7083.         }
  7084.        
  7085.         if (_hennaINT > 5)
  7086.             _hennaINT = 5;
  7087.        
  7088.         if (_hennaSTR > 5)
  7089.             _hennaSTR = 5;
  7090.        
  7091.         if (_hennaMEN > 5)
  7092.             _hennaMEN = 5;
  7093.        
  7094.         if (_hennaCON > 5)
  7095.             _hennaCON = 5;
  7096.        
  7097.         if (_hennaWIT > 5)
  7098.             _hennaWIT = 5;
  7099.        
  7100.         if (_hennaDEX > 5)
  7101.             _hennaDEX = 5;
  7102.     }
  7103.    
  7104.     /**
  7105.      * @param slot A slot to check.
  7106.      * @return the Henna of this L2PlayerInstance corresponding to the selected slot.
  7107.      */
  7108.     public L2Henna getHenna(int slot)
  7109.     {
  7110.         if (slot < 1 || slot > 3)
  7111.             return null;
  7112.        
  7113.         return _henna[slot - 1];
  7114.     }
  7115.    
  7116.     public int getHennaStatINT()
  7117.     {
  7118.         return _hennaINT;
  7119.     }
  7120.    
  7121.     public int getHennaStatSTR()
  7122.     {
  7123.         return _hennaSTR;
  7124.     }
  7125.    
  7126.     public int getHennaStatCON()
  7127.     {
  7128.         return _hennaCON;
  7129.     }
  7130.    
  7131.     public int getHennaStatMEN()
  7132.     {
  7133.         return _hennaMEN;
  7134.     }
  7135.    
  7136.     public int getHennaStatWIT()
  7137.     {
  7138.         return _hennaWIT;
  7139.     }
  7140.    
  7141.     public int getHennaStatDEX()
  7142.     {
  7143.         return _hennaDEX;
  7144.     }
  7145.    
  7146.     /**
  7147.      * Return True if the L2PlayerInstance is autoAttackable.
  7148.      * <ul>
  7149.      * <li>Check if the attacker isn't the L2PlayerInstance Pet</li>
  7150.      * <li>Check if the attacker is L2MonsterInstance</li>
  7151.      * <li>If the attacker is a L2PlayerInstance, check if it is not in the same party</li>
  7152.      * <li>Check if the L2PlayerInstance has Karma</li>
  7153.      * <li>If the attacker is a L2PlayerInstance, check if it is not in the same siege clan
  7154.      * (Attacker, Defender)</li>
  7155.      * </ul>
  7156.      */
  7157.     @Override
  7158.     public boolean isAutoAttackable(L2Character attacker)
  7159.     {
  7160.         // Check if the attacker isn't the L2PlayerInstance Pet
  7161.         if (attacker == this || attacker == getPet())
  7162.             return false;
  7163.        
  7164.         // Check if the attacker is a L2MonsterInstance
  7165.         if (attacker instanceof L2MonsterInstance)
  7166.             return true;
  7167.        
  7168.         // Check if the attacker is not in the same party
  7169.         if (getParty() != null && getParty().getPartyMembers().contains(attacker))
  7170.             return false;
  7171.        
  7172.         // Check if the attacker is in olympia and olympia start
  7173.         if (attacker instanceof L2PlayerInstance && ((L2PlayerInstance)attacker).isInOlympiadMode())
  7174.         {
  7175.             if (isInOlympiadMode() && isOlympiadStart()
  7176.                     && ((L2PlayerInstance)attacker).getOlympiadGameId() == getOlympiadGameId())
  7177.                 return true;
  7178.            
  7179.             return false;
  7180.         }
  7181.        
  7182.         // Check if the attacker is not in the same clan
  7183.         if (getClan() != null && attacker != null && getClan().isMember(attacker.getObjectId()))
  7184.             return false;
  7185.        
  7186.         if (attacker instanceof L2Playable && isInsideZone(ZONE_PEACE))
  7187.             return false;
  7188.        
  7189.         // Check if the L2PlayerInstance has Karma
  7190.         if (getKarma() > 0 || getPvpFlag() > 0)
  7191.             return true;
  7192.        
  7193.         // Check if the attacker is a L2Playable
  7194.         if (attacker instanceof L2Playable)
  7195.         {
  7196.             // Get L2PlayerInstance
  7197.             L2PlayerInstance cha = attacker.getActingPlayer();
  7198.            
  7199.             // is AutoAttackable if both players are in the same duel and the duel is still going on
  7200.             if (getDuelState() == Duel.DUELSTATE_DUELLING && getDuelId() == cha.getDuelId())
  7201.                 return true;
  7202.            
  7203.             // Check if the L2PlayerInstance is in an arena or a siege area
  7204.             if (isInsideZone(ZONE_PVP) && cha.isInsideZone(ZONE_PVP))
  7205.                 return true;
  7206.            
  7207.             if (getClan() != null)
  7208.             {
  7209.                 Siege siege = SiegeManager.getSiege(getX(), getY(), getZ());
  7210.                 if (siege != null)
  7211.                 {
  7212.                     // Check if a siege is in progress and if attacker and the L2PlayerInstance aren't in the Defender clan
  7213.                     if (siege.checkIsDefender(cha.getClan()) && siege.checkIsDefender(getClan()))
  7214.                         return false;
  7215.                    
  7216.                     // Check if a siege is in progress and if attacker and the L2PlayerInstance aren't in the Attacker clan
  7217.                     if (siege.checkIsAttacker(cha.getClan()) && siege.checkIsAttacker(getClan()))
  7218.                         return false;
  7219.                 }
  7220.                
  7221.                 // Check if clan is at war
  7222.                 if (getClan() != null && cha.getClan() != null && getClan().isAtWarWith(cha.getClanId())
  7223.                         && cha.getClan().isAtWarWith(getClanId()) && getWantsPeace() == 0 && cha.getWantsPeace() == 0
  7224.                         && !isAcademyMember())
  7225.                     return true;
  7226.             }
  7227.         }
  7228.         else if (attacker instanceof L2SiegeGuardInstance)
  7229.         {
  7230.             if (getClan() != null)
  7231.             {
  7232.                 Siege siege = SiegeManager.getSiege(this);
  7233.                 return (siege != null && siege.checkIsAttacker(getClan()));
  7234.             }
  7235.         }
  7236.         return false;
  7237.     }
  7238.    
  7239.     /**
  7240.      * Check if the active L2Skill can be casted.<BR>
  7241.      * <BR>
  7242.      * <B><U> Actions</U> :</B><BR>
  7243.      * <BR>
  7244.      * <li>Check if the skill isn't toggle and is offensive</li> <li>Check if the target is in the
  7245.      * skill cast range</li> <li>Check if the skill is Spoil type and if the target isn't already
  7246.      * spoiled</li> <li>Check if the caster owns enought consummed Item, enough HP and MP to cast
  7247.      * the skill</li> <li>
  7248.      * Check if the caster isn't sitting</li> <li>Check if all skills are enabled and this skill is
  7249.      * enabled</li><BR>
  7250.      * <BR>
  7251.      * <li>Check if the caster own the weapon needed</li><BR>
  7252.      * <BR>
  7253.      * <li>Check if the skill is active</li><BR>
  7254.      * <BR>
  7255.      * <li>Check if all casting conditions are completed</li><BR>
  7256.      * <BR>
  7257.      * <li>Notify the AI with AI_INTENTION_CAST and target</li><BR>
  7258.      * <BR>
  7259.      *
  7260.      * @param skill The L2Skill to use
  7261.      * @param forceUse used to force ATTACK on players
  7262.      * @param dontMove used to prevent movement, if not in range
  7263.      */
  7264.     @Override
  7265.     public boolean useMagic(L2Skill skill, boolean forceUse, boolean dontMove)
  7266.     {
  7267.         // Cancels the use of skills when player uses a cursed weapon or is flying.
  7268.         if ((isCursedWeaponEquipped() && !skill.isDemonicSkill()) // If CW, allow ONLY demonic skills.
  7269.                 || (getMountType() == 1 && !skill.isStriderSkill()) // If mounted, allow ONLY Strider skills.
  7270.                 || (getMountType() == 2 && !skill.isFlyingSkill())) // If flying, allow ONLY Wyvern skills.
  7271.         {
  7272.             sendPacket(ActionFailed.STATIC_PACKET);
  7273.             return false;
  7274.         }
  7275.        
  7276.         // Check if the skill is active
  7277.         if (skill.isPassive())
  7278.         {
  7279.             sendPacket(ActionFailed.STATIC_PACKET);
  7280.             return false;
  7281.         }
  7282.        
  7283.         // ************************************* Check Casting in Progress *******************************************
  7284.        
  7285.         // If a skill is currently being used, queue this one if this is not the same
  7286.         if (isCastingNow())
  7287.         {
  7288.             SkillDat currentSkill = getCurrentSkill();
  7289.             // Check if new skill different from current skill in progress
  7290.             if (currentSkill != null && skill.getId() == currentSkill.getSkillId())
  7291.             {
  7292.                 sendPacket(ActionFailed.STATIC_PACKET);
  7293.                 return false;
  7294.             }
  7295.            
  7296.             // Create a new SkillDat object and queue it in the player _queuedSkill
  7297.             setQueuedSkill(skill, forceUse, dontMove);
  7298.             sendPacket(ActionFailed.STATIC_PACKET);
  7299.             return false;
  7300.         }
  7301.         setIsCastingNow(true);
  7302.        
  7303.         // Create a new SkillDat object and set the player _currentSkill
  7304.         setCurrentSkill(skill, forceUse, dontMove);
  7305.        
  7306.         if (getQueuedSkill() != null) // wiping out previous values, after casting has been aborted
  7307.             setQueuedSkill(null, false, false);
  7308.        
  7309.         if (!checkUseMagicConditions(skill, forceUse, dontMove))
  7310.         {
  7311.             setIsCastingNow(false);
  7312.             return false;
  7313.         }
  7314.        
  7315.         // Check if the target is correct and Notify the AI with AI_INTENTION_CAST and target
  7316.         L2Object target = null;
  7317.        
  7318.         switch (skill.getTargetType())
  7319.         {
  7320.             case TARGET_AURA: // AURA, SELF should be cast even if no target has been found
  7321.             case TARGET_FRONT_AURA:
  7322.             case TARGET_BEHIND_AURA:
  7323.             case TARGET_GROUND:
  7324.             case TARGET_SELF:
  7325.             case TARGET_AURA_UNDEAD:
  7326.                 target = this;
  7327.                 break;
  7328.             default:
  7329.                
  7330.                 // Get the first target of the list
  7331.                 target = skill.getFirstOfTargetList(this);
  7332.                 break;
  7333.         }
  7334.        
  7335.         // Notify the AI with AI_INTENTION_CAST and target
  7336.         getAI().setIntention(CtrlIntention.AI_INTENTION_CAST, skill, target);
  7337.         return true;
  7338.     }
  7339.    
  7340.     private boolean checkUseMagicConditions(L2Skill skill, boolean forceUse, boolean dontMove)
  7341.     {
  7342.         L2SkillType sklType = skill.getSkillType();
  7343.        
  7344.         // ************************************* Check Player State *******************************************
  7345.        
  7346.         // Abnormal effects(ex : Stun, Sleep...) are checked in L2Character useMagic()
  7347.        
  7348.         if (isOutOfControl() || isParalyzed() || isStunned() || isSleeping())
  7349.         {
  7350.             sendPacket(ActionFailed.STATIC_PACKET);
  7351.             return false;
  7352.         }
  7353.        
  7354.         // Check if the player is dead
  7355.         if (isDead())
  7356.         {
  7357.             // Send ActionFailed to the L2PlayerInstance
  7358.             sendPacket(ActionFailed.STATIC_PACKET);
  7359.             return false;
  7360.         }
  7361.        
  7362.         if (isFishing()
  7363.                 && (sklType != L2SkillType.PUMPING && sklType != L2SkillType.REELING && sklType != L2SkillType.FISHING))
  7364.         {
  7365.             // Only fishing skills are available
  7366.             sendPacket(SystemMessageId.ONLY_FISHING_SKILLS_NOW);
  7367.             return false;
  7368.         }
  7369.        
  7370.         if (inObserverMode())
  7371.         {
  7372.             sendPacket(SystemMessageId.OBSERVERS_CANNOT_PARTICIPATE);
  7373.             abortCast();
  7374.             sendPacket(ActionFailed.STATIC_PACKET);
  7375.             return false;
  7376.         }
  7377.        
  7378.         // Check if the caster is sitted. Toggle skills can be only removed, not activated.
  7379.         if (isSitting())
  7380.         {
  7381.             if (skill.isToggle())
  7382.             {
  7383.                 // Get effects of the skill
  7384.                 L2Effect effect = getFirstEffect(skill.getId());
  7385.                 if (effect != null)
  7386.                 {
  7387.                     effect.exit();
  7388.                    
  7389.                     // Send ActionFailed to the L2PlayerInstance
  7390.                     sendPacket(ActionFailed.STATIC_PACKET);
  7391.                     return false;
  7392.                 }
  7393.             }
  7394.            
  7395.             // Send a System Message to the caster
  7396.             sendPacket(SystemMessageId.CANT_MOVE_SITTING);
  7397.            
  7398.             // Send ActionFailed to the L2PlayerInstance
  7399.             sendPacket(ActionFailed.STATIC_PACKET);
  7400.             return false;
  7401.         }
  7402.        
  7403.         // Check if the skill type is TOGGLE
  7404.         if (skill.isToggle())
  7405.         {
  7406.             // Get effects of the skill
  7407.             L2Effect effect = getFirstEffect(skill.getId());
  7408.            
  7409.             if (effect != null)
  7410.             {
  7411.                 // If the toggle is different of FakeDeath, you can de-activate it clicking on it.
  7412.                 if (skill.getId() != 60)
  7413.                     effect.exit();
  7414.                
  7415.                 // Send ActionFailed to the L2PlayerInstance
  7416.                 sendPacket(ActionFailed.STATIC_PACKET);
  7417.                 return false;
  7418.             }
  7419.         }
  7420.        
  7421.         // Check if the player uses "Fake Death" skill
  7422.         if (isFakeDeath())
  7423.         {
  7424.             // Send ActionFailed to the L2PlayerInstance
  7425.             sendPacket(ActionFailed.STATIC_PACKET);
  7426.             return false;
  7427.         }
  7428.        
  7429.         // ************************************* Check Target *******************************************
  7430.         // Create and set a L2Object containing the target of the skill
  7431.         L2Object target = null;
  7432.         SkillTargetType sklTargetType = skill.getTargetType();
  7433.         Point3D worldPosition = getCurrentSkillWorldPosition();
  7434.        
  7435.         if (sklTargetType == SkillTargetType.TARGET_GROUND && worldPosition == null)
  7436.         {
  7437.             _log.info("WorldPosition is null for skill: " + skill.getName() + ", player: " + getName() + ".");
  7438.             sendPacket(ActionFailed.STATIC_PACKET);
  7439.             return false;
  7440.         }
  7441.        
  7442.         switch (sklTargetType)
  7443.         {
  7444.         // Target the player if skill type is AURA, PARTY, CLAN or SELF
  7445.             case TARGET_AURA:
  7446.             case TARGET_FRONT_AURA:
  7447.             case TARGET_BEHIND_AURA:
  7448.             case TARGET_AURA_UNDEAD:
  7449.             case TARGET_PARTY:
  7450.             case TARGET_ALLY:
  7451.             case TARGET_CLAN:
  7452.             case TARGET_GROUND:
  7453.             case TARGET_SELF:
  7454.             case TARGET_AREA_SUMMON:
  7455.                 target = this;
  7456.                 break;
  7457.             case TARGET_PET:
  7458.             case TARGET_SUMMON:
  7459.                 target = getPet();
  7460.                 break;
  7461.             default:
  7462.                 target = getTarget();
  7463.                 break;
  7464.         }
  7465.        
  7466.         // Check the validity of the target
  7467.         if (target == null)
  7468.         {
  7469.             sendPacket(ActionFailed.STATIC_PACKET);
  7470.             return false;
  7471.         }
  7472.        
  7473.         if (target instanceof L2DoorInstance)
  7474.         {
  7475.             if (!((L2DoorInstance)target).isAttackable(this) // Siege doors only hittable during siege
  7476.                     || (((L2DoorInstance)target).isUnlockable() && skill.getSkillType() != L2SkillType.UNLOCK)) // unlockable doors
  7477.             {
  7478.                 sendPacket(SystemMessageId.INCORRECT_TARGET);
  7479.                 sendPacket(ActionFailed.STATIC_PACKET);
  7480.                 return false;
  7481.             }
  7482.         }
  7483.        
  7484.         // Are the target and the player in the same duel?
  7485.         if (isInDuel())
  7486.         {
  7487.             if (target instanceof L2Playable)
  7488.             {
  7489.                 // Get L2PlayerInstance
  7490.                 L2PlayerInstance cha = target.getActingPlayer();
  7491.                 if (cha.getDuelId() != getDuelId())
  7492.                 {
  7493.                     sendPacket(SystemMessageId.INCORRECT_TARGET);
  7494.                     sendPacket(ActionFailed.STATIC_PACKET);
  7495.                     return false;
  7496.                 }
  7497.             }
  7498.         }
  7499.        
  7500.         // ************************************* Check skill availability *******************************************
  7501.        
  7502.         // Siege summon checks. Both checks send a message to the player if it return false.
  7503.         if (skill.isSiegeSummonSkill()
  7504.                 && (!SiegeManager.checkIfOkToSummon(this) || !SevenSigns.getInstance().checkSummonConditions(this)))
  7505.             return false;
  7506.        
  7507.         // Check if this skill is enabled (ex : reuse time)
  7508.         if (isSkillDisabled(skill))
  7509.         {
  7510.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_PREPARED_FOR_REUSE).addSkillName(skill));
  7511.             return false;
  7512.         }
  7513.        
  7514.         // ************************************* Check casting conditions *******************************************
  7515.        
  7516.         // Check if all casting conditions are completed
  7517.         if (!skill.checkCondition(this, target, false))
  7518.         {
  7519.             // Send ActionFailed to the L2PlayerInstance
  7520.             sendPacket(ActionFailed.STATIC_PACKET);
  7521.             return false;
  7522.         }
  7523.        
  7524.         // ************************************* Check Skill Type *******************************************
  7525.        
  7526.         // Check if this is offensive magic skill
  7527.         if (skill.isOffensive())
  7528.         {
  7529.             if ((isInsidePeaceZone(this, target)) && !getAccessLevel().allowPeaceAttack())
  7530.             {
  7531.                 // If L2Character or target is in a peace zone, send a system message TARGET_IN_PEACEZONE ActionFailed
  7532.                 sendPacket(SystemMessageId.TARGET_IN_PEACEZONE);
  7533.                 sendPacket(ActionFailed.STATIC_PACKET);
  7534.                 return false;
  7535.             }
  7536.            
  7537.             if (isInOlympiadMode() && !isOlympiadStart())
  7538.             {
  7539.                 // if L2PlayerInstance is in Olympia and the match isn't already start, send ActionFailed
  7540.                 sendPacket(ActionFailed.STATIC_PACKET);
  7541.                 return false;
  7542.             }
  7543.            
  7544.             // Check if the target is attackable
  7545.             if (!target.isAttackable() && !getAccessLevel().allowPeaceAttack())
  7546.             {
  7547.                 // If target is not attackable, send ActionFailed
  7548.                 sendPacket(ActionFailed.STATIC_PACKET);
  7549.                 return false;
  7550.             }
  7551.            
  7552.             // Check if a Forced ATTACK is in progress on non-attackable target
  7553.             if (!target.isAutoAttackable(this) && !forceUse)
  7554.             {
  7555.                 switch (sklTargetType)
  7556.                 {
  7557.                     case TARGET_AURA:
  7558.                     case TARGET_FRONT_AURA:
  7559.                     case TARGET_BEHIND_AURA:
  7560.                     case TARGET_AURA_UNDEAD:
  7561.                     case TARGET_CLAN:
  7562.                     case TARGET_ALLY:
  7563.                     case TARGET_PARTY:
  7564.                     case TARGET_SELF:
  7565.                     case TARGET_GROUND:
  7566.                     case TARGET_AREA_SUMMON:
  7567.                         break;
  7568.                     default: // Send ActionFailed to the L2PlayerInstance
  7569.                         sendPacket(ActionFailed.STATIC_PACKET);
  7570.                         return false;
  7571.                 }
  7572.             }
  7573.            
  7574.             // Check if the target is in the skill cast range
  7575.             if (dontMove)
  7576.             {
  7577.                 // Calculate the distance between the L2PlayerInstance and the target
  7578.                 if (sklTargetType == SkillTargetType.TARGET_GROUND)
  7579.                 {
  7580.                     if (!isInsideRadius(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(),
  7581.                             skill.getCastRange() + getTemplate().getCollisionRadius(), false, false))
  7582.                     {
  7583.                         // Send a System Message to the caster
  7584.                         sendPacket(SystemMessageId.TARGET_TOO_FAR);
  7585.                        
  7586.                         // Send ActionFailed to the L2PlayerInstance
  7587.                         sendPacket(ActionFailed.STATIC_PACKET);
  7588.                         return false;
  7589.                     }
  7590.                 }
  7591.                 else if (skill.getCastRange() > 0
  7592.                         && !isInsideRadius(target, skill.getCastRange() + getTemplate().getCollisionRadius(), false,
  7593.                                 false))
  7594.                 {
  7595.                     // Send a System Message to the caster
  7596.                     sendPacket(SystemMessageId.TARGET_TOO_FAR);
  7597.                    
  7598.                     // Send ActionFailed to the L2PlayerInstance
  7599.                     sendPacket(ActionFailed.STATIC_PACKET);
  7600.                     return false;
  7601.                 }
  7602.             }
  7603.         }
  7604.        
  7605.         // Check if the skill is defensive
  7606.         if (!skill.isOffensive() && target instanceof L2MonsterInstance && !forceUse)
  7607.         {
  7608.             // check if the target is a monster and if force attack is set.. if not then we don't want to cast.
  7609.             switch (sklTargetType)
  7610.             {
  7611.                 case TARGET_PET:
  7612.                 case TARGET_SUMMON:
  7613.                 case TARGET_AURA:
  7614.                 case TARGET_FRONT_AURA:
  7615.                 case TARGET_BEHIND_AURA:
  7616.                 case TARGET_AURA_UNDEAD:
  7617.                 case TARGET_CLAN:
  7618.                 case TARGET_SELF:
  7619.                 case TARGET_PARTY:
  7620.                 case TARGET_ALLY:
  7621.                 case TARGET_CORPSE_MOB:
  7622.                 case TARGET_AREA_CORPSE_MOB:
  7623.                 case TARGET_GROUND:
  7624.                     break;
  7625.                 default:
  7626.                 {
  7627.                     switch (sklType)
  7628.                     {
  7629.                         case BEAST_FEED:
  7630.                         case DELUXE_KEY_UNLOCK:
  7631.                         case UNLOCK:
  7632.                             break;
  7633.                         default:
  7634.                             sendPacket(ActionFailed.STATIC_PACKET);
  7635.                             return false;
  7636.                     }
  7637.                     break;
  7638.                 }
  7639.             }
  7640.         }
  7641.        
  7642.         // Check if the skill is Spoil type and if the target isn't already spoiled
  7643.         if (sklType == L2SkillType.SPOIL)
  7644.         {
  7645.             if (!(target instanceof L2MonsterInstance))
  7646.             {
  7647.                 // Send a System Message to the L2PlayerInstance
  7648.                 sendPacket(SystemMessageId.INCORRECT_TARGET);
  7649.                
  7650.                 // Send ActionFailed to the L2PlayerInstance
  7651.                 sendPacket(ActionFailed.STATIC_PACKET);
  7652.                 return false;
  7653.             }
  7654.         }
  7655.        
  7656.         // Check if the skill is Sweep type and if conditions not apply
  7657.         if (sklType == L2SkillType.SWEEP && target instanceof L2Attackable)
  7658.         {
  7659.             if (((L2Attackable)target).isDead())
  7660.             {
  7661.                 final int spoilerId = ((L2Attackable)target).getIsSpoiledBy();
  7662.                 if (spoilerId == 0)
  7663.                 {
  7664.                     // Send a System Message to the L2PlayerInstance
  7665.                     sendPacket(SystemMessageId.SWEEPER_FAILED_TARGET_NOT_SPOILED);
  7666.                    
  7667.                     // Send ActionFailed to the L2PlayerInstance
  7668.                     sendPacket(ActionFailed.STATIC_PACKET);
  7669.                     return false;
  7670.                 }
  7671.                
  7672.                 if (getObjectId() != spoilerId && !isInLooterParty(spoilerId))
  7673.                 {
  7674.                     // Send a System Message to the L2PlayerInstance
  7675.                     sendPacket(SystemMessageId.SWEEP_NOT_ALLOWED);
  7676.                    
  7677.                     // Send ActionFailed to the L2PlayerInstance
  7678.                     sendPacket(ActionFailed.STATIC_PACKET);
  7679.                     return false;
  7680.                 }
  7681.             }
  7682.         }
  7683.        
  7684.         // Check if the skill is Drain Soul (Soul Crystals) and if the target is a MOB
  7685.         if (sklType == L2SkillType.DRAIN_SOUL)
  7686.         {
  7687.             if (!(target instanceof L2MonsterInstance))
  7688.             {
  7689.                 // Send a System Message to the L2PlayerInstance
  7690.                 sendPacket(SystemMessageId.INCORRECT_TARGET);
  7691.                
  7692.                 // Send ActionFailed to the L2PlayerInstance
  7693.                 sendPacket(ActionFailed.STATIC_PACKET);
  7694.                 return false;
  7695.             }
  7696.         }
  7697.        
  7698.         // Check if this is a Pvp skill and target isn't a non-flagged/non-karma player
  7699.         switch (sklTargetType)
  7700.         {
  7701.             case TARGET_PARTY:
  7702.             case TARGET_ALLY: // For such skills, checkPvpSkill() is called from L2Skill.getTargetList()
  7703.             case TARGET_CLAN: // For such skills, checkPvpSkill() is called from L2Skill.getTargetList()
  7704.             case TARGET_AURA:
  7705.             case TARGET_FRONT_AURA:
  7706.             case TARGET_BEHIND_AURA:
  7707.             case TARGET_AURA_UNDEAD:
  7708.             case TARGET_GROUND:
  7709.             case TARGET_SELF:
  7710.                 break;
  7711.             default:
  7712.                 if (!checkPvpSkill(target, skill) && !getAccessLevel().allowPeaceAttack())
  7713.                 {
  7714.                     // Send a System Message to the L2PlayerInstance
  7715.                     sendPacket(SystemMessageId.TARGET_IS_INCORRECT);
  7716.                    
  7717.                     // Send ActionFailed to the L2PlayerInstance
  7718.                     sendPacket(ActionFailed.STATIC_PACKET);
  7719.                     return false;
  7720.                 }
  7721.         }
  7722.        
  7723.         if ((sklTargetType == SkillTargetType.TARGET_HOLY && !checkIfOkToCastSealOfRule(CastleManager.getInstance()
  7724.                 .getCastle(this), false, skill, target))
  7725.                 || (sklType == L2SkillType.SIEGEFLAG && !L2SkillSiegeFlag.checkIfOkToPlaceFlag(this, false))
  7726.                 || (sklType == L2SkillType.STRSIEGEASSAULT && !checkIfOkToUseStriderSiegeAssault(skill))
  7727.                 || (sklType == L2SkillType.SUMMON_FRIEND && !(checkSummonerStatus(this) && checkSummonTargetStatus(
  7728.                         target, this))))
  7729.         {
  7730.             sendPacket(ActionFailed.STATIC_PACKET);
  7731.             abortCast();
  7732.             return false;
  7733.         }
  7734.        
  7735.         // GeoData Los Check here
  7736.         if (skill.getCastRange() > 0)
  7737.         {
  7738.             if (sklTargetType == SkillTargetType.TARGET_GROUND)
  7739.             {
  7740.                 if (!GeoData.getInstance().canSeeTarget(this, worldPosition))
  7741.                 {
  7742.                     sendPacket(SystemMessageId.CANT_SEE_TARGET);
  7743.                     sendPacket(ActionFailed.STATIC_PACKET);
  7744.                     return false;
  7745.                 }
  7746.             }
  7747.             else if (!GeoData.getInstance().canSeeTarget(this, target))
  7748.             {
  7749.                 sendPacket(SystemMessageId.CANT_SEE_TARGET);
  7750.                 sendPacket(ActionFailed.STATIC_PACKET);
  7751.                 return false;
  7752.             }
  7753.         }
  7754.         // finally, after passing all conditions
  7755.         return true;
  7756.     }
  7757.    
  7758.     public boolean checkIfOkToUseStriderSiegeAssault(L2Skill skill)
  7759.     {
  7760.         SystemMessage sm;
  7761.         Castle castle = CastleManager.getInstance().getCastle(this);
  7762.        
  7763.         if (!isRiding())
  7764.             sm = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill);
  7765.         else if (!(getTarget() instanceof L2DoorInstance))
  7766.             sm = SystemMessage.getSystemMessage(SystemMessageId.INCORRECT_TARGET);
  7767.         else if (castle == null || castle.getCastleId() <= 0)
  7768.             sm = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill);
  7769.         else if (!castle.getSiege().getIsInProgress() || castle.getSiege().getAttackerClan(getClan()) == null)
  7770.             sm = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill);
  7771.         else
  7772.             return true;
  7773.        
  7774.         sendPacket(sm);
  7775.         return false;
  7776.     }
  7777.    
  7778.     public boolean checkIfOkToCastSealOfRule(Castle castle, boolean isCheckOnly, L2Skill skill, L2Object target)
  7779.     {
  7780.         SystemMessage sm;
  7781.        
  7782.         if (castle == null || castle.getCastleId() <= 0)
  7783.             sm = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill);
  7784.         else if (!castle.getArtefacts().contains(target))
  7785.             sm = SystemMessage.getSystemMessage(SystemMessageId.INCORRECT_TARGET);
  7786.         else if (!castle.getSiege().getIsInProgress())
  7787.             sm = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill);
  7788.         else if (!Util.checkIfInRange(200, this, target, true))
  7789.             sm = SystemMessage.getSystemMessage(SystemMessageId.DIST_TOO_FAR_CASTING_STOPPED);
  7790.         else if (!isInsideZone(L2Character.ZONE_CASTONARTIFACT))
  7791.             sm = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill);
  7792.         else if (castle.getSiege().getAttackerClan(getClan()) == null)
  7793.             sm = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED).addSkillName(skill);
  7794.         else
  7795.         {
  7796.             if (!isCheckOnly)
  7797.             {
  7798.                 sm = SystemMessage.getSystemMessage(SystemMessageId.OPPONENT_STARTED_ENGRAVING);
  7799.                 castle.getSiege().announceToPlayer(sm, false);
  7800.             }
  7801.             return true;
  7802.         }
  7803.         sendPacket(sm);
  7804.         return false;
  7805.     }
  7806.    
  7807.     public boolean isInLooterParty(int LooterId)
  7808.     {
  7809.         L2PlayerInstance looter = L2World.getInstance().getPlayer(LooterId);
  7810.        
  7811.         // if L2PlayerInstance is in a CommandChannel
  7812.         if (isInParty() && getParty().isInCommandChannel() && looter != null)
  7813.             return getParty().getCommandChannel().getMembers().contains(looter);
  7814.        
  7815.         if (isInParty() && looter != null)
  7816.             return getParty().getPartyMembers().contains(looter);
  7817.        
  7818.         return false;
  7819.     }
  7820.    
  7821.     /**
  7822.      * Check if the requested casting is a Pc->Pc skill cast and if it's a valid pvp condition
  7823.      *
  7824.      * @param target L2Object instance containing the target
  7825.      * @param skill L2Skill instance with the skill being casted
  7826.      * @return False if the skill is a pvpSkill and target is not a valid pvp target
  7827.      */
  7828.     public boolean checkPvpSkill(L2Object target, L2Skill skill)
  7829.     {
  7830.         return checkPvpSkill(target, skill, false);
  7831.     }
  7832.    
  7833.     /**
  7834.      * Check if the requested casting is a Pc->Pc skill cast and if it's a valid pvp condition
  7835.      *
  7836.      * @param target L2Object instance containing the target
  7837.      * @param skill L2Skill instance with the skill being casted
  7838.      * @param srcIsSummon is L2Summon - caster?
  7839.      * @return False if the skill is a pvpSkill and target is not a valid pvp target
  7840.      */
  7841.     public boolean checkPvpSkill(L2Object target, L2Skill skill, boolean srcIsSummon)
  7842.     {
  7843.         // check for PC->PC Pvp status
  7844.         if (target instanceof L2Summon)
  7845.             target = target.getActingPlayer();
  7846.        
  7847.         if (target != null && target != this && target instanceof L2PlayerInstance
  7848.                 && !(isInDuel() && ((L2PlayerInstance)target).getDuelId() == getDuelId()) && !isInsideZone(ZONE_PVP)
  7849.                 && !((L2PlayerInstance)target).isInsideZone(ZONE_PVP))
  7850.         {
  7851.             SkillDat skilldat = getCurrentSkill();
  7852.             SkillDat skilldatpet = getCurrentPetSkill();
  7853.            
  7854.             if (skill.isPvpSkill()) // pvp skill
  7855.             {
  7856.                 // in clan war player can attack whites even with sleep etc.
  7857.                 if (getClan() != null && ((L2PlayerInstance)target).getClan() != null)
  7858.                 {
  7859.                     if (getClan().isAtWarWith(((L2PlayerInstance)target).getClan().getClanId()))
  7860.                         return true;
  7861.                 }
  7862.                
  7863.                 // target's pvp flag is not set and target has no karma
  7864.                 if (((L2PlayerInstance)target).getPvpFlag() == 0 && ((L2PlayerInstance)target).getKarma() == 0)
  7865.                     return false;
  7866.             }
  7867.             else if ((skilldat != null && !skilldat.isCtrlPressed() && skill.isOffensive() && !srcIsSummon)
  7868.                     || (skilldatpet != null && !skilldatpet.isCtrlPressed() && skill.isOffensive() && srcIsSummon))
  7869.             {
  7870.                 // in clan war player can attack whites even with sleep etc.
  7871.                 if (getClan() != null && ((L2PlayerInstance)target).getClan() != null)
  7872.                 {
  7873.                     if (getClan().isAtWarWith(((L2PlayerInstance)target).getClan().getClanId()))
  7874.                         return true;
  7875.                 }
  7876.                
  7877.                 // target's pvp flag is not set and target has no karma
  7878.                 if (((L2PlayerInstance)target).getPvpFlag() == 0 && ((L2PlayerInstance)target).getKarma() == 0)
  7879.                     return false;
  7880.             }
  7881.         }
  7882.         return true;
  7883.     }
  7884.    
  7885.     /**
  7886.      * @return True if the L2PlayerInstance is a Mage (based on class templates).
  7887.      */
  7888.     public boolean isMageClass()
  7889.     {
  7890.         return getClassId().isMage();
  7891.     }
  7892.    
  7893.     public boolean isMounted()
  7894.     {
  7895.         return _mountType > 0;
  7896.     }
  7897.    
  7898.     /**
  7899.      * This method allows to :<br>
  7900.      * - change isRiding/isFlying flags;<br>
  7901.      * - gift player with Wyvern Breath skill if mount is a wyvern;;<br>
  7902.      * - send the skillList (faded icons update)
  7903.      *
  7904.      * @param npcId the npcId of the mount
  7905.      * @param npcLevel The level of the mount
  7906.      * @param mountType 0, 1 or 2 (dismount, strider or wyvern).
  7907.      * @return always true.
  7908.      */
  7909.     public boolean setMount(int npcId, int npcLevel, int mountType)
  7910.     {
  7911.         switch (mountType)
  7912.         {
  7913.             case 0: // Dismounted
  7914.                 if (isFlying())
  7915.                     removeSkill(FrequentSkill.WYVERN_BREATH.getSkill());
  7916.                 setIsFlying(false);
  7917.                 setIsRiding(false);
  7918.                 break;
  7919.             case 1: // Strider
  7920.                 setIsFlying(false);
  7921.                 setIsRiding(true);
  7922.                 break;
  7923.             case 2: // Flying Wyvern
  7924.                 setIsFlying(true);
  7925.                 setIsRiding(false);
  7926.                 addSkill(FrequentSkill.WYVERN_BREATH.getSkill(), false); // not saved to DB
  7927.                 break;
  7928.         }
  7929.        
  7930.         _mountNpcId = npcId;
  7931.         _mountType = mountType;
  7932.         _mountLevel = npcLevel;
  7933.        
  7934.         sendSkillList(); // Update faded icons && eventual added skills.
  7935.         return true;
  7936.     }
  7937.    
  7938.     /**
  7939.      * @return the type of Pet mounted (0 : none, 1 : Strider, 2 : Wyvern).
  7940.      */
  7941.     public int getMountType()
  7942.     {
  7943.         return _mountType;
  7944.     }
  7945.    
  7946.     @Override
  7947.     public final void stopAllEffects()
  7948.     {
  7949.         super.stopAllEffects();
  7950.         updateAndBroadcastStatus(2);
  7951.     }
  7952.    
  7953.     @Override
  7954.     public final void stopAllEffectsExceptThoseThatLastThroughDeath()
  7955.     {
  7956.         super.stopAllEffectsExceptThoseThatLastThroughDeath();
  7957.         updateAndBroadcastStatus(2);
  7958.     }
  7959.    
  7960.     /**
  7961.      * Stop all toggle-type effects
  7962.      */
  7963.     public final void stopAllToggles()
  7964.     {
  7965.         _effects.stopAllToggles();
  7966.     }
  7967.    
  7968.     public final void stopCubics()
  7969.     {
  7970.         if (getCubics() != null)
  7971.         {
  7972.             boolean removed = false;
  7973.             for (L2CubicInstance cubic : getCubics().values())
  7974.             {
  7975.                 cubic.stopAction();
  7976.                 delCubic(cubic.getId());
  7977.                 removed = true;
  7978.             }
  7979.             if (removed)
  7980.                 broadcastUserInfo();
  7981.         }
  7982.     }
  7983.    
  7984.     public final void stopCubicsByOthers()
  7985.     {
  7986.         if (getCubics() != null)
  7987.         {
  7988.             boolean removed = false;
  7989.             for (L2CubicInstance cubic : getCubics().values())
  7990.             {
  7991.                 if (cubic.givenByOther())
  7992.                 {
  7993.                     cubic.stopAction();
  7994.                     delCubic(cubic.getId());
  7995.                     removed = true;
  7996.                 }
  7997.             }
  7998.             if (removed)
  7999.                 broadcastUserInfo();
  8000.         }
  8001.     }
  8002.    
  8003.     /**
  8004.      * Send UserInfo to this L2PlayerInstance and CharInfo to all L2PlayerInstance in its
  8005.      * _KnownPlayers.<BR>
  8006.      * <BR>
  8007.      * <B><U> Concept</U> :</B><BR>
  8008.      * <BR>
  8009.      * Others L2PlayerInstance in the detection area of the L2PlayerInstance are identified in
  8010.      * <B>_knownPlayers</B>. In order to inform other players of this L2PlayerInstance state
  8011.      * modifications, server just need to go through _knownPlayers to send Server->Client Packet<BR>
  8012.      * <BR>
  8013.      * <B><U> Actions</U> :</B><BR>
  8014.      * <BR>
  8015.      * <li>Send UserInfo to this L2PlayerInstance (Public and Private Data)</li> <li>Send CharInfo
  8016.      * to all L2PlayerInstance in _KnownPlayers of the L2PlayerInstance (Public data only)</li><BR>
  8017.      * <BR>
  8018.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : DON'T SEND UserInfo packet to other players instead
  8019.      * of CharInfo packet. Indeed, UserInfo packet contains PRIVATE DATA as MaxHP, STR,
  8020.      * DEX...</B></FONT><BR>
  8021.      * <BR>
  8022.      */
  8023.     @Override
  8024.     public void updateAbnormalEffect()
  8025.     {
  8026.         broadcastUserInfo();
  8027.     }
  8028.    
  8029.     /**
  8030.      * Disable the Inventory and create a new task to enable it after 1.5s.
  8031.      */
  8032.     public void tempInventoryDisable()
  8033.     {
  8034.         _inventoryDisable = true;
  8035.        
  8036.         ThreadPoolManager.getInstance().scheduleGeneral(new InventoryEnable(), 1500);
  8037.     }
  8038.    
  8039.     /**
  8040.      * @return True if the Inventory is disabled.
  8041.      */
  8042.     public boolean isInventoryDisabled()
  8043.     {
  8044.         return _inventoryDisable;
  8045.     }
  8046.    
  8047.     protected class InventoryEnable implements Runnable
  8048.     {
  8049.         @Override
  8050.         public void run()
  8051.         {
  8052.             _inventoryDisable = false;
  8053.         }
  8054.     }
  8055.    
  8056.     public Map<Integer, L2CubicInstance> getCubics()
  8057.     {
  8058.         return _cubics;
  8059.     }
  8060.    
  8061.     /**
  8062.      * Add a L2CubicInstance to the L2PlayerInstance _cubics.
  8063.      *
  8064.      * @param id
  8065.      * @param level
  8066.      * @param matk
  8067.      * @param activationtime
  8068.      * @param activationchance
  8069.      * @param totalLifetime
  8070.      * @param givenByOther
  8071.      */
  8072.     public void addCubic(int id, int level, double matk, int activationtime, int activationchance, int totalLifetime,
  8073.             boolean givenByOther)
  8074.     {
  8075.         L2CubicInstance cubic =
  8076.                 new L2CubicInstance(this, id, level, (int)matk, activationtime, activationchance, totalLifetime,
  8077.                         givenByOther);
  8078.         _cubics.put(id, cubic);
  8079.     }
  8080.    
  8081.     /**
  8082.      * Remove a L2CubicInstance from the L2PlayerInstance _cubics.
  8083.      *
  8084.      * @param id
  8085.      */
  8086.     public void delCubic(int id)
  8087.     {
  8088.         _cubics.remove(id);
  8089.     }
  8090.    
  8091.     /**
  8092.      * @param id
  8093.      * @return the L2CubicInstance corresponding to the Identifier of the L2PlayerInstance _cubics.
  8094.      */
  8095.     public L2CubicInstance getCubic(int id)
  8096.     {
  8097.         return _cubics.get(id);
  8098.     }
  8099.    
  8100.     @Override
  8101.     public String toString()
  8102.     {
  8103.         return "player " + getName();
  8104.     }
  8105.    
  8106.     /**
  8107.      * @return the modifier corresponding to the Enchant Effect of the Active Weapon (Min : 127).
  8108.      */
  8109.     public int getEnchantEffect()
  8110.     {
  8111.         L2ItemInstance wpn = getActiveWeaponInstance();
  8112.        
  8113.         if (wpn == null)
  8114.             return 0;
  8115.        
  8116.         return Math.min(127, wpn.getEnchantLevel());
  8117.     }
  8118.    
  8119.     /**
  8120.      * Set the _currentFolkNpc of the player.
  8121.      *
  8122.      * @param npc
  8123.      */
  8124.     public void setCurrentFolkNPC(L2Npc npc)
  8125.     {
  8126.         _currentFolkNpc = npc;
  8127.     }
  8128.    
  8129.     /**
  8130.      * @return the _currentFolkNpc of the player.
  8131.      */
  8132.     public L2Npc getCurrentFolkNPC()
  8133.     {
  8134.         return _currentFolkNpc;
  8135.     }
  8136.    
  8137.     /**
  8138.      * @return True if L2PlayerInstance is a participant in the Festival of Darkness.
  8139.      */
  8140.     public boolean isFestivalParticipant()
  8141.     {
  8142.         return SevenSignsFestival.getInstance().isParticipant(this);
  8143.     }
  8144.    
  8145.     public void addAutoSoulShot(int itemId)
  8146.     {
  8147.         _activeSoulShots.add(itemId);
  8148.     }
  8149.    
  8150.     public boolean removeAutoSoulShot(int itemId)
  8151.     {
  8152.         return _activeSoulShots.remove(itemId);
  8153.     }
  8154.    
  8155.     public Set<Integer> getAutoSoulShot()
  8156.     {
  8157.         return _activeSoulShots;
  8158.     }
  8159.    
  8160.     @Override
  8161.     public boolean isChargedShot(ShotType type)
  8162.     {
  8163.         L2ItemInstance weapon = getActiveWeaponInstance();
  8164.         return weapon != null && weapon.isChargedShot(type);
  8165.     }
  8166.    
  8167.     @Override
  8168.     public void setChargedShot(ShotType type, boolean charged)
  8169.     {
  8170.         L2ItemInstance weapon = getActiveWeaponInstance();
  8171.         if (weapon != null)
  8172.             weapon.setChargedShot(type, charged);
  8173.     }
  8174.    
  8175.     @Override
  8176.     public void rechargeShots(boolean physical, boolean magic)
  8177.     {
  8178.         if (_activeSoulShots == null || _activeSoulShots.isEmpty())
  8179.             return;
  8180.        
  8181.         for (int itemId : _activeSoulShots)
  8182.         {
  8183.             L2ItemInstance item = getInventory().getItemByItemId(itemId);
  8184.             if (item != null)
  8185.             {
  8186.                 if (magic && item.getItem().getDefaultAction() == L2ActionType.spiritshot)
  8187.                 {
  8188.                     IItemHandler handler = ItemHandler.getInstance().getItemHandler(item.getEtcItem());
  8189.                     if (handler != null)
  8190.                         handler.useItem(this, item, false);
  8191.                 }
  8192.                
  8193.                 if (physical && item.getItem().getDefaultAction() == L2ActionType.soulshot)
  8194.                 {
  8195.                     IItemHandler handler = ItemHandler.getInstance().getItemHandler(item.getEtcItem());
  8196.                     if (handler != null)
  8197.                         handler.useItem(this, item, false);
  8198.                 }
  8199.             }
  8200.             else
  8201.                 removeAutoSoulShot(itemId);
  8202.         }
  8203.     }
  8204.    
  8205.     /**
  8206.      * Cancel autoshot use for shot itemId
  8207.      *
  8208.      * @param itemId int id to disable
  8209.      * @return true if canceled.
  8210.      */
  8211.     public boolean disableAutoShot(int itemId)
  8212.     {
  8213.         if (_activeSoulShots.contains(itemId))
  8214.         {
  8215.             removeAutoSoulShot(itemId);
  8216.             sendPacket(new ExAutoSoulShot(itemId, 0));
  8217.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.AUTO_USE_OF_S1_CANCELLED).addItemName(itemId));
  8218.             return true;
  8219.         }
  8220.        
  8221.         return false;
  8222.     }
  8223.    
  8224.     /**
  8225.      * Cancel all autoshots for player
  8226.      */
  8227.     public void disableAutoShotsAll()
  8228.     {
  8229.         for (int itemId : _activeSoulShots)
  8230.         {
  8231.             sendPacket(new ExAutoSoulShot(itemId, 0));
  8232.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.AUTO_USE_OF_S1_CANCELLED).addItemName(itemId));
  8233.         }
  8234.         _activeSoulShots.clear();
  8235.     }
  8236.    
  8237.     class LookingForFishTask implements Runnable
  8238.     {
  8239.         boolean _isNoob, _isUpperGrade;
  8240.         int _fishType, _fishGutsCheck;
  8241.         long _endTaskTime;
  8242.        
  8243.         protected LookingForFishTask(int fishWaitTime, int fishGutsCheck, int fishType, boolean isNoob,
  8244.                 boolean isUpperGrade)
  8245.         {
  8246.             _fishGutsCheck = fishGutsCheck;
  8247.             _endTaskTime = System.currentTimeMillis() + fishWaitTime + 10000;
  8248.             _fishType = fishType;
  8249.             _isNoob = isNoob;
  8250.             _isUpperGrade = isUpperGrade;
  8251.         }
  8252.        
  8253.         @Override
  8254.         public void run()
  8255.         {
  8256.             if (System.currentTimeMillis() >= _endTaskTime)
  8257.             {
  8258.                 endFishing(false);
  8259.                 return;
  8260.             }
  8261.            
  8262.             if (_fishType == -1)
  8263.                 return;
  8264.            
  8265.             int check = Rnd.get(1000);
  8266.             if (_fishGutsCheck > check)
  8267.             {
  8268.                 stopLookingForFishTask();
  8269.                 startFishCombat(_isNoob, _isUpperGrade);
  8270.             }
  8271.         }
  8272.     }
  8273.    
  8274.     public int getClanPrivileges()
  8275.     {
  8276.         return _clanPrivileges;
  8277.     }
  8278.    
  8279.     public void setClanPrivileges(int n)
  8280.     {
  8281.         _clanPrivileges = n;
  8282.     }
  8283.    
  8284.     // baron etc
  8285.     public void setPledgeClass(int classId)
  8286.     {
  8287.         _pledgeClass = classId;
  8288.     }
  8289.    
  8290.     public int getPledgeClass()
  8291.     {
  8292.         return _pledgeClass;
  8293.     }
  8294.    
  8295.     public void setPledgeType(int typeId)
  8296.     {
  8297.         _pledgeType = typeId;
  8298.     }
  8299.    
  8300.     public int getPledgeType()
  8301.     {
  8302.         return _pledgeType;
  8303.     }
  8304.    
  8305.     public int getApprentice()
  8306.     {
  8307.         return _apprentice;
  8308.     }
  8309.    
  8310.     public void setApprentice(int apprentice_id)
  8311.     {
  8312.         _apprentice = apprentice_id;
  8313.     }
  8314.    
  8315.     public int getSponsor()
  8316.     {
  8317.         return _sponsor;
  8318.     }
  8319.    
  8320.     public void setSponsor(int sponsor_id)
  8321.     {
  8322.         _sponsor = sponsor_id;
  8323.     }
  8324.    
  8325.     @Override
  8326.     public void sendMessage(String message)
  8327.     {
  8328.         sendPacket(SystemMessage.sendString(message));
  8329.     }
  8330.    
  8331.     /**
  8332.      * Unsummon all types of summons : pets, cubics, normal summons and trained beasts.
  8333.      */
  8334.     public void dropAllSummons()
  8335.     {
  8336.         // Delete summons and pets
  8337.         if (getPet() != null)
  8338.             getPet().unSummon(this);
  8339.        
  8340.         // Delete trained beasts
  8341.         if (getTrainedBeast() != null)
  8342.             getTrainedBeast().deleteMe();
  8343.        
  8344.         // Delete any form of cubics
  8345.         stopCubics();
  8346.     }
  8347.    
  8348.     public void enterObserverMode(int x, int y, int z)
  8349.     {
  8350.         _lastX = getX();
  8351.         _lastY = getY();
  8352.         _lastZ = getZ();
  8353.        
  8354.         _observerMode = true;
  8355.        
  8356.         if (isSitting())
  8357.             standUp();
  8358.        
  8359.         dropAllSummons();
  8360.         setTarget(null);
  8361.         setIsParalyzed(true);
  8362.         startParalyze();
  8363.         setIsInvul(true);
  8364.         getAppearance().setInvisible();
  8365.        
  8366.         sendPacket(new ObservationMode(x, y, z));
  8367.         getKnownList().removeAllKnownObjects(); // reinit knownlist
  8368.         setXYZ(x, y, z);
  8369.        
  8370.         broadcastUserInfo();
  8371.     }
  8372.    
  8373.     public void setLastCords(int x, int y, int z)
  8374.     {
  8375.         _lastX = getX();
  8376.         _lastY = getY();
  8377.         _lastZ = getZ();
  8378.     }
  8379.    
  8380.     public void enterOlympiadObserverMode(Location loc, int id)
  8381.     {
  8382.         dropAllSummons();
  8383.        
  8384.         if (getParty() != null)
  8385.             getParty().removePartyMember(this, true);
  8386.        
  8387.         _olympiadGameId = id;
  8388.        
  8389.         if (isSitting())
  8390.             standUp();
  8391.        
  8392.         if (!_observerMode)
  8393.         {
  8394.             _lastX = getX();
  8395.             _lastY = getY();
  8396.             _lastZ = getZ();
  8397.         }
  8398.        
  8399.         _observerMode = true;
  8400.         setTarget(null);
  8401.         setIsInvul(true);
  8402.         getAppearance().setInvisible();
  8403.         teleToLocation(loc, 0);
  8404.         sendPacket(new ExOlympiadMode(3));
  8405.         broadcastUserInfo();
  8406.     }
  8407.    
  8408.     public void leaveObserverMode()
  8409.     {
  8410.         setTarget(null);
  8411.         getKnownList().removeAllKnownObjects(); // reinit knownlist
  8412.         setXYZ(_lastX, _lastY, _lastZ);
  8413.         setIsParalyzed(false);
  8414.         stopParalyze(false);
  8415.         getAppearance().setVisible();
  8416.         setIsInvul(false);
  8417.        
  8418.         if (hasAI())
  8419.             getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
  8420.        
  8421.         // prevent receive falling damage
  8422.         setFalling();
  8423.        
  8424.         _observerMode = false;
  8425.         setLastCords(0, 0, 0);
  8426.         sendPacket(new ObservationReturn(this));
  8427.         broadcastUserInfo();
  8428.     }
  8429.    
  8430.     public void leaveOlympiadObserverMode()
  8431.     {
  8432.         if (_olympiadGameId == -1)
  8433.             return;
  8434.        
  8435.         _olympiadGameId = -1;
  8436.         _observerMode = false;
  8437.        
  8438.         setTarget(null);
  8439.         sendPacket(new ExOlympiadMode(0));
  8440.         teleToLocation(_lastX, _lastY, _lastZ, 20);
  8441.         getAppearance().setVisible();
  8442.         setIsInvul(false);
  8443.        
  8444.         if (hasAI())
  8445.             getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
  8446.        
  8447.         setLastCords(0, 0, 0);
  8448.         broadcastUserInfo();
  8449.     }
  8450.    
  8451.     public void setOlympiadSide(int i)
  8452.     {
  8453.         _olympiadSide = i;
  8454.     }
  8455.    
  8456.     public int getOlympiadSide()
  8457.     {
  8458.         return _olympiadSide;
  8459.     }
  8460.    
  8461.     public void setOlympiadGameId(int id)
  8462.     {
  8463.         _olympiadGameId = id;
  8464.     }
  8465.    
  8466.     public int getOlympiadGameId()
  8467.     {
  8468.         return _olympiadGameId;
  8469.     }
  8470.    
  8471.     public int getLastX()
  8472.     {
  8473.         return _lastX;
  8474.     }
  8475.    
  8476.     public int getLastY()
  8477.     {
  8478.         return _lastY;
  8479.     }
  8480.    
  8481.     public int getLastZ()
  8482.     {
  8483.         return _lastZ;
  8484.     }
  8485.    
  8486.     public boolean inObserverMode()
  8487.     {
  8488.         return _observerMode;
  8489.     }
  8490.    
  8491.     public int getTeleMode()
  8492.     {
  8493.         return _telemode;
  8494.     }
  8495.    
  8496.     public void setTeleMode(int mode)
  8497.     {
  8498.         _telemode = mode;
  8499.     }
  8500.    
  8501.     public void setLoto(int i, int val)
  8502.     {
  8503.         _loto[i] = val;
  8504.     }
  8505.    
  8506.     public int getLoto(int i)
  8507.     {
  8508.         return _loto[i];
  8509.     }
  8510.    
  8511.     public void setRace(int i, int val)
  8512.     {
  8513.         _race[i] = val;
  8514.     }
  8515.    
  8516.     public int getRace(int i)
  8517.     {
  8518.         return _race[i];
  8519.     }
  8520.    
  8521.     public boolean isInRefusalMode()
  8522.     {
  8523.         return _messageRefusal;
  8524.     }
  8525.    
  8526.     public void setInRefusalMode(boolean mode)
  8527.     {
  8528.         _messageRefusal = mode;
  8529.         sendPacket(new EtcStatusUpdate(this));
  8530.     }
  8531.    
  8532.     public void setTradeRefusal(boolean mode)
  8533.     {
  8534.         _tradeRefusal = mode;
  8535.     }
  8536.    
  8537.     public boolean getTradeRefusal()
  8538.     {
  8539.         return _tradeRefusal;
  8540.     }
  8541.    
  8542.     public void setExchangeRefusal(boolean mode)
  8543.     {
  8544.         _exchangeRefusal = mode;
  8545.     }
  8546.    
  8547.     public boolean getExchangeRefusal()
  8548.     {
  8549.         return _exchangeRefusal;
  8550.     }
  8551.    
  8552.     public BlockList getBlockList()
  8553.     {
  8554.         return _blockList;
  8555.     }
  8556.    
  8557.     public void setHero(boolean hero)
  8558.     {
  8559.         if (hero && _baseClass == _activeClass)
  8560.         {
  8561.             for (L2Skill s : SkillTable.getHeroSkills())
  8562.                 addSkill(s, false); // Dont Save Hero skills to database
  8563.         }
  8564.         else
  8565.         {
  8566.             for (L2Skill s : SkillTable.getHeroSkills())
  8567.                 super.removeSkill(s); // Just Remove skills from nonHero characters
  8568.         }
  8569.         _hero = hero;
  8570.        
  8571.         sendSkillList();
  8572.     }
  8573.    
  8574.     public void setIsInOlympiadMode(boolean b)
  8575.     {
  8576.         _inOlympiadMode = b;
  8577.     }
  8578.    
  8579.     public void setIsOlympiadStart(boolean b)
  8580.     {
  8581.         _OlympiadStart = b;
  8582.     }
  8583.    
  8584.     public boolean isOlympiadStart()
  8585.     {
  8586.         return _OlympiadStart;
  8587.     }
  8588.    
  8589.     public boolean isHero()
  8590.     {
  8591.         return _hero;
  8592.     }
  8593.    
  8594.     public boolean isInOlympiadMode()
  8595.     {
  8596.         return _inOlympiadMode;
  8597.     }
  8598.    
  8599.     public boolean isInDuel()
  8600.     {
  8601.         return _isInDuel;
  8602.     }
  8603.    
  8604.     public int getDuelId()
  8605.     {
  8606.         return _duelId;
  8607.     }
  8608.    
  8609.     public void setDuelState(int mode)
  8610.     {
  8611.         _duelState = mode;
  8612.     }
  8613.    
  8614.     public int getDuelState()
  8615.     {
  8616.         return _duelState;
  8617.     }
  8618.    
  8619.     /**
  8620.      * Sets up the duel state using a non 0 duelId.
  8621.      *
  8622.      * @param duelId 0=not in a duel
  8623.      */
  8624.     public void setIsInDuel(int duelId)
  8625.     {
  8626.         if (duelId > 0)
  8627.         {
  8628.             _isInDuel = true;
  8629.             _duelState = Duel.DUELSTATE_DUELLING;
  8630.             _duelId = duelId;
  8631.         }
  8632.         else
  8633.         {
  8634.             if (_duelState == Duel.DUELSTATE_DEAD)
  8635.             {
  8636.                 enableAllSkills();
  8637.                 getStatus().startHpMpRegeneration();
  8638.             }
  8639.             _isInDuel = false;
  8640.             _duelState = Duel.DUELSTATE_NODUEL;
  8641.             _duelId = 0;
  8642.         }
  8643.     }
  8644.    
  8645.     /**
  8646.      * This returns a SystemMessage stating why the player is not available for duelling.
  8647.      *
  8648.      * @return S1_CANNOT_DUEL... message
  8649.      */
  8650.     public SystemMessage getNoDuelReason()
  8651.     {
  8652.         SystemMessage sm = SystemMessage.getSystemMessage(_noDuelReason);
  8653.         sm.addPcName(this);
  8654.         _noDuelReason = SystemMessageId.THERE_IS_NO_OPPONENT_TO_RECEIVE_YOUR_CHALLENGE_FOR_A_DUEL;
  8655.         return sm;
  8656.     }
  8657.    
  8658.     /**
  8659.      * Checks if this player might join / start a duel. To get the reason use getNoDuelReason()
  8660.      * after calling this function.
  8661.      *
  8662.      * @return true if the player might join/start a duel.
  8663.      */
  8664.     public boolean canDuel()
  8665.     {
  8666.         if (isInCombat() || getPunishLevel() == PunishLevel.JAIL)
  8667.             _noDuelReason = SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_IS_CURRENTLY_ENGAGED_IN_BATTLE;
  8668.         else if (isDead() || isAlikeDead() || (getCurrentHp() < getMaxHp() / 2 || getCurrentMp() < getMaxMp() / 2))
  8669.             _noDuelReason = SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_HP_OR_MP_IS_BELOW_50_PERCENT;
  8670.         else if (isInDuel())
  8671.             _noDuelReason = SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_IS_ALREADY_ENGAGED_IN_A_DUEL;
  8672.         else if (isInOlympiadMode())
  8673.             _noDuelReason = SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_IS_PARTICIPATING_IN_THE_OLYMPIAD;
  8674.         else if (isCursedWeaponEquipped())
  8675.             _noDuelReason = SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_IS_IN_A_CHAOTIC_STATE;
  8676.         else if (getPrivateStoreType() != STORE_PRIVATE_NONE)
  8677.             _noDuelReason =
  8678.                     SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_IS_CURRENTLY_ENGAGED_IN_A_PRIVATE_STORE_OR_MANUFACTURE;
  8679.         else if (isMounted() || isInBoat())
  8680.             _noDuelReason = SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_IS_CURRENTLY_RIDING_A_BOAT_WYVERN_OR_STRIDER;
  8681.         else if (isFishing())
  8682.             _noDuelReason = SystemMessageId.S1_CANNOT_DUEL_BECAUSE_S1_IS_CURRENTLY_FISHING;
  8683.         else if (isInsideZone(ZONE_PVP) || isInsideZone(ZONE_PEACE) || isInsideZone(ZONE_SIEGE))
  8684.             _noDuelReason =
  8685.                     SystemMessageId.S1_CANNOT_MAKE_A_CHALLANGE_TO_A_DUEL_BECAUSE_S1_IS_CURRENTLY_IN_A_DUEL_PROHIBITED_AREA;
  8686.         else
  8687.             return true;
  8688.        
  8689.         return false;
  8690.     }
  8691.    
  8692.     public boolean isNoble()
  8693.     {
  8694.         return _noble;
  8695.     }
  8696.    
  8697.     /**
  8698.      * Set Noblesse Status, and reward with nobles' skills.
  8699.      *
  8700.      * @param val Add skills if setted to true, else remove skills.
  8701.      * @param store Store the status directly in the db if setted to true.
  8702.      */
  8703.     public void setNoble(boolean val, boolean store)
  8704.     {
  8705.         if (val)
  8706.             for (L2Skill s : SkillTable.getNobleSkills())
  8707.                 addSkill(s, false); // Dont Save Noble skills to Sql
  8708.         else
  8709.             for (L2Skill s : SkillTable.getNobleSkills())
  8710.                 super.removeSkill(s); // Just Remove skills without deleting from Sql
  8711.            
  8712.         _noble = val;
  8713.        
  8714.         sendSkillList();
  8715.        
  8716.         if (store)
  8717.         {
  8718.             try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  8719.             {
  8720.                 PreparedStatement statement = con.prepareStatement(UPDATE_NOBLESS);
  8721.                 statement.setBoolean(1, val);
  8722.                 statement.setInt(2, getObjectId());
  8723.                 statement.executeUpdate();
  8724.                 statement.close();
  8725.             }
  8726.             catch (Exception e)
  8727.             {
  8728.                 _log.log(Level.WARNING, "Could not update " + getName() + " nobless status: " + e.getMessage(), e);
  8729.             }
  8730.         }
  8731.     }
  8732.    
  8733.     public void setLvlJoinedAcademy(int lvl)
  8734.     {
  8735.         _lvlJoinedAcademy = lvl;
  8736.     }
  8737.    
  8738.     public int getLvlJoinedAcademy()
  8739.     {
  8740.         return _lvlJoinedAcademy;
  8741.     }
  8742.    
  8743.     public boolean isAcademyMember()
  8744.     {
  8745.         return _lvlJoinedAcademy > 0;
  8746.     }
  8747.    
  8748.     public void setTeam(int team)
  8749.     {
  8750.         _team = team;
  8751.     }
  8752.    
  8753.     public int getTeam()
  8754.     {
  8755.         return _team;
  8756.     }
  8757.    
  8758.     public void setWantsPeace(int wantsPeace)
  8759.     {
  8760.         _wantsPeace = wantsPeace;
  8761.     }
  8762.    
  8763.     public int getWantsPeace()
  8764.     {
  8765.         return _wantsPeace;
  8766.     }
  8767.    
  8768.     public boolean isFishing()
  8769.     {
  8770.         return _fishingLoc != null;
  8771.     }
  8772.    
  8773.     public void setAllianceWithVarkaKetra(int sideAndLvlOfAlliance)
  8774.     {
  8775.         _alliedVarkaKetra = sideAndLvlOfAlliance;
  8776.     }
  8777.    
  8778.     /**
  8779.      * [-5,-1] varka, 0 neutral, [1,5] ketra
  8780.      *
  8781.      * @return the side faction.
  8782.      */
  8783.     public int getAllianceWithVarkaKetra()
  8784.     {
  8785.         return _alliedVarkaKetra;
  8786.     }
  8787.    
  8788.     public boolean isAlliedWithVarka()
  8789.     {
  8790.         return (_alliedVarkaKetra < 0);
  8791.     }
  8792.    
  8793.     public boolean isAlliedWithKetra()
  8794.     {
  8795.         return (_alliedVarkaKetra > 0);
  8796.     }
  8797.    
  8798.     public void sendSkillList()
  8799.     {
  8800.         boolean isDisabled = false;
  8801.         SkillList sl = new SkillList();
  8802.         for (L2Skill s : getAllSkills())
  8803.         {
  8804.             if (s == null)
  8805.                 continue;
  8806.            
  8807.             if (s.getId() > 9000 && s.getId() < 9007)
  8808.                 continue; // Fake skills to change base stats
  8809.                
  8810.             if (getClan() != null)
  8811.                 isDisabled = s.isClanSkill() && getClan().getReputationScore() < 0;
  8812.            
  8813.             if (isCursedWeaponEquipped()) // Only Demonic skills are available
  8814.                 isDisabled = !s.isDemonicSkill();
  8815.             else if (isMounted()) // else if, because only ONE state is possible
  8816.             {
  8817.                 if (getMountType() == 1) // Only Strider skills are available
  8818.                     isDisabled = !s.isStriderSkill();
  8819.                 else if (getMountType() == 2) // Only Wyvern skills are available
  8820.                     isDisabled = !s.isFlyingSkill();
  8821.             }
  8822.            
  8823.             sl.addSkill(s.getId(), s.getLevel(), s.isPassive(), isDisabled);
  8824.         }
  8825.         sendPacket(sl);
  8826.     }
  8827.    
  8828.     /**
  8829.      * 1. Add the specified class ID as a subclass (up to the maximum number of <b>three</b>) for
  8830.      * this character.<BR>
  8831.      * 2. This method no longer changes the active _classIndex of the player. This is only done by
  8832.      * the calling of setActiveClass() method as that should be the only way to do so.
  8833.      *
  8834.      * @param classId
  8835.      * @param classIndex
  8836.      * @return boolean subclassAdded
  8837.      */
  8838.     public boolean addSubClass(int classId, int classIndex)
  8839.     {
  8840.         if (!_subclassLock.tryLock())
  8841.             return false;
  8842.        
  8843.         try
  8844.         {
  8845.             if (getTotalSubClasses() == 3 || classIndex == 0)
  8846.                 return false;
  8847.            
  8848.             if (getSubClasses().containsKey(classIndex))
  8849.                 return false;
  8850.            
  8851.             // Note: Never change _classIndex in any method other than setActiveClass().
  8852.            
  8853.             SubClass newClass = new SubClass();
  8854.             newClass.setClassId(classId);
  8855.             newClass.setClassIndex(classIndex);
  8856.            
  8857.             try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  8858.             {
  8859.                 PreparedStatement statement = con.prepareStatement(ADD_CHAR_SUBCLASS);
  8860.                 statement.setInt(1, getObjectId());
  8861.                 statement.setInt(2, newClass.getClassId());
  8862.                 statement.setLong(3, newClass.getExp());
  8863.                 statement.setInt(4, newClass.getSp());
  8864.                 statement.setInt(5, newClass.getLevel());
  8865.                 statement.setInt(6, newClass.getClassIndex()); // <-- Added
  8866.                
  8867.                 statement.execute();
  8868.                 statement.close();
  8869.             }
  8870.             catch (Exception e)
  8871.             {
  8872.                 _log.warning("WARNING: Could not add character sub class for " + getName() + ": " + e);
  8873.                 return false;
  8874.             }
  8875.            
  8876.             // Commit after database INSERT incase exception is thrown.
  8877.             getSubClasses().put(newClass.getClassIndex(), newClass);
  8878.            
  8879.             ClassId subTemplate = ClassId.values()[classId];
  8880.             Collection<L2SkillLearn> skillTree = SkillTreeTable.getInstance().getAllowedSkills(subTemplate);
  8881.            
  8882.             if (skillTree == null)
  8883.                 return true;
  8884.            
  8885.             Map<Integer, L2Skill> prevSkillList = new HashMap<>();
  8886.            
  8887.             for (L2SkillLearn skillInfo : skillTree)
  8888.             {
  8889.                 if (skillInfo.getMinLevel() <= 40)
  8890.                 {
  8891.                     L2Skill prevSkill = prevSkillList.get(skillInfo.getId());
  8892.                     L2Skill newSkill = SkillTable.getInstance().getInfo(skillInfo.getId(), skillInfo.getLevel());
  8893.                    
  8894.                     if (prevSkill != null && (prevSkill.getLevel() > newSkill.getLevel()))
  8895.                         continue;
  8896.                    
  8897.                     prevSkillList.put(newSkill.getId(), newSkill);
  8898.                     storeSkill(newSkill, prevSkill, classIndex);
  8899.                 }
  8900.             }
  8901.            
  8902.             return true;
  8903.         }
  8904.         finally
  8905.         {
  8906.             _subclassLock.unlock();
  8907.         }
  8908.     }
  8909.    
  8910.     /**
  8911.      * 1. Completely erase all existance of the subClass linked to the classIndex.<BR>
  8912.      * 2. Send over the newClassId to addSubClass()to create a new instance on this classIndex.<BR>
  8913.      * 3. Upon Exception, revert the player to their BaseClass to avoid further problems.<BR>
  8914.      *
  8915.      * @param classIndex
  8916.      * @param newClassId
  8917.      * @return boolean subclassAdded
  8918.      */
  8919.     public boolean modifySubClass(int classIndex, int newClassId)
  8920.     {
  8921.         if (!_subclassLock.tryLock())
  8922.             return false;
  8923.        
  8924.         try
  8925.         {
  8926.             try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  8927.             {
  8928.                 // Remove all henna info stored for this sub-class.
  8929.                 PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNAS);
  8930.                 statement.setInt(1, getObjectId());
  8931.                 statement.setInt(2, classIndex);
  8932.                 statement.execute();
  8933.                 statement.close();
  8934.                
  8935.                 // Remove all shortcuts info stored for this sub-class.
  8936.                 statement = con.prepareStatement(DELETE_CHAR_SHORTCUTS);
  8937.                 statement.setInt(1, getObjectId());
  8938.                 statement.setInt(2, classIndex);
  8939.                 statement.execute();
  8940.                 statement.close();
  8941.                
  8942.                 // Remove all effects info stored for this sub-class.
  8943.                 statement = con.prepareStatement(DELETE_SKILL_SAVE);
  8944.                 statement.setInt(1, getObjectId());
  8945.                 statement.setInt(2, classIndex);
  8946.                 statement.execute();
  8947.                 statement.close();
  8948.                
  8949.                 // Remove all skill info stored for this sub-class.
  8950.                 statement = con.prepareStatement(DELETE_CHAR_SKILLS);
  8951.                 statement.setInt(1, getObjectId());
  8952.                 statement.setInt(2, classIndex);
  8953.                 statement.execute();
  8954.                 statement.close();
  8955.                
  8956.                 // Remove all basic info stored about this sub-class.
  8957.                 statement = con.prepareStatement(DELETE_CHAR_SUBCLASS);
  8958.                 statement.setInt(1, getObjectId());
  8959.                 statement.setInt(2, classIndex);
  8960.                 statement.execute();
  8961.                 statement.close();
  8962.             }
  8963.             catch (Exception e)
  8964.             {
  8965.                 _log.warning("Could not modify subclass for " + getName() + " to class index " + classIndex + ": " + e);
  8966.                
  8967.                 // This must be done in order to maintain data consistency.
  8968.                 getSubClasses().remove(classIndex);
  8969.                 return false;
  8970.             }
  8971.            
  8972.             getSubClasses().remove(classIndex);
  8973.         }
  8974.         finally
  8975.         {
  8976.             _subclassLock.unlock();
  8977.         }
  8978.        
  8979.         return addSubClass(newClassId, classIndex);
  8980.     }
  8981.    
  8982.     public boolean isSubClassActive()
  8983.     {
  8984.         return _classIndex > 0;
  8985.     }
  8986.    
  8987.     public Map<Integer, SubClass> getSubClasses()
  8988.     {
  8989.         if (_subClasses == null)
  8990.             _subClasses = new HashMap<>();
  8991.        
  8992.         return _subClasses;
  8993.     }
  8994.    
  8995.     public int getTotalSubClasses()
  8996.     {
  8997.         return getSubClasses().size();
  8998.     }
  8999.    
  9000.     public int getBaseClass()
  9001.     {
  9002.         return _baseClass;
  9003.     }
  9004.    
  9005.     public int getActiveClass()
  9006.     {
  9007.         return _activeClass;
  9008.     }
  9009.    
  9010.     public int getClassIndex()
  9011.     {
  9012.         return _classIndex;
  9013.     }
  9014.    
  9015.     private void setClassTemplate(int classId)
  9016.     {
  9017.         _activeClass = classId;
  9018.        
  9019.         L2PlayerTemplate t = CharTemplateTable.getInstance().getTemplate(classId);
  9020.        
  9021.         if (t == null)
  9022.         {
  9023.             _log.severe("Missing template for classId: " + classId);
  9024.             throw new Error();
  9025.         }
  9026.        
  9027.         // Set the template of the L2PlayerInstance
  9028.         setTemplate(t);
  9029.     }
  9030.    
  9031.     /**
  9032.      * Changes the character's class based on the given class index. <BR>
  9033.      * <BR>
  9034.      * An index of zero specifies the character's original (base) class, while indexes 1-3 specifies
  9035.      * the character's sub-classes respectively.
  9036.      *
  9037.      * @param classIndex
  9038.      * @return true if successful.
  9039.      */
  9040.     public boolean setActiveClass(int classIndex)
  9041.     {
  9042.         if (!_subclassLock.tryLock())
  9043.             return false;
  9044.        
  9045.         try
  9046.         {
  9047.             // Remove active item skills before saving char to database because next time when choosing this class, worn items can be different
  9048.             for (L2ItemInstance item : getInventory().getAugmentedItems())
  9049.             {
  9050.                 if (item != null && item.isEquipped())
  9051.                     item.getAugmentation().removeBonus(this);
  9052.             }
  9053.            
  9054.             // abort any kind of cast.
  9055.             abortCast();
  9056.            
  9057.             // Stop casting for any player that may be casting a force buff on this l2pcinstance.
  9058.             for (L2Character character : getKnownList().getKnownType(L2Character.class))
  9059.                 if (character.getFusionSkill() != null && character.getFusionSkill().getTarget() == this)
  9060.                     character.abortCast();
  9061.            
  9062.             /*
  9063.              * 1. Call store() before modifying _classIndex to avoid skill effects rollover. 2. Register the correct _classId against applied 'classIndex'.
  9064.              */
  9065.             store();
  9066.             _reuseTimeStamps.clear();
  9067.            
  9068.             // clear charges
  9069.             _charges.set(0);
  9070.             stopChargeTask();
  9071.            
  9072.             if (classIndex == 0)
  9073.                 setClassTemplate(getBaseClass());
  9074.             else
  9075.             {
  9076.                 try
  9077.                 {
  9078.                     setClassTemplate(getSubClasses().get(classIndex).getClassId());
  9079.                 }
  9080.                 catch (Exception e)
  9081.                 {
  9082.                     _log.info("Could not switch " + getName() + "'s sub class to class index " + classIndex + ": " + e);
  9083.                     return false;
  9084.                 }
  9085.             }
  9086.             _classIndex = classIndex;
  9087.            
  9088.             if (isInParty())
  9089.                 getParty().recalculatePartyLevel();
  9090.            
  9091.             /*
  9092.              * 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
  9093.              * 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
  9094.              * related to this class. 9. Resend a class change animation effect to broadcast to all nearby players. 10.Unsummon any active servitor from the player.
  9095.              */
  9096.            
  9097.             if (getPet() instanceof L2SummonInstance)
  9098.                 getPet().unSummon(this);
  9099.            
  9100.             for (L2Skill oldSkill : getAllSkills())
  9101.                 super.removeSkill(oldSkill);
  9102.            
  9103.             stopAllEffectsExceptThoseThatLastThroughDeath();
  9104.             stopCubics();
  9105.            
  9106.             if (isSubClassActive())
  9107.             {
  9108.                 _dwarvenRecipeBook.clear();
  9109.                 _commonRecipeBook.clear();
  9110.             }
  9111.             else
  9112.             {
  9113.                 restoreRecipeBook();
  9114.             }
  9115.            
  9116.             // Restore any Death Penalty Buff
  9117.             restoreDeathPenaltyBuffLevel();
  9118.            
  9119.             restoreSkills();
  9120.             rewardSkills();
  9121.             regiveTemporarySkills();
  9122.            
  9123.             // Prevents some issues when changing between subclases that shares skills
  9124.             if (_disabledSkills != null && !_disabledSkills.isEmpty())
  9125.                 _disabledSkills.clear();
  9126.            
  9127.             restoreEffects();
  9128.             updateEffectIcons();
  9129.             sendPacket(new EtcStatusUpdate(this));
  9130.            
  9131.             // If player has quest "Repent Your Sins", remove it
  9132.             QuestState st = getQuestState("Q422_RepentYourSins");
  9133.             if (st != null)
  9134.                 st.exitQuest(true);
  9135.            
  9136.             for (int i = 0; i < 3; i++)
  9137.                 _henna[i] = null;
  9138.            
  9139.             restoreHenna();
  9140.             sendPacket(new HennaInfo(this));
  9141.            
  9142.             if (getCurrentHp() > getMaxHp())
  9143.                 setCurrentHp(getMaxHp());
  9144.             if (getCurrentMp() > getMaxMp())
  9145.                 setCurrentMp(getMaxMp());
  9146.             if (getCurrentCp() > getMaxCp())
  9147.                 setCurrentCp(getMaxCp());
  9148.            
  9149.             refreshOverloaded();
  9150.             refreshExpertisePenalty();
  9151.             broadcastUserInfo();
  9152.            
  9153.             // Clear resurrect xp calculation
  9154.             setExpBeforeDeath(0);
  9155.            
  9156.             _shortCuts.restore();
  9157.             sendPacket(new ShortCutInit(this));
  9158.            
  9159.             broadcastPacket(new SocialAction(this, 15));
  9160.             sendPacket(new SkillCoolTime(this));
  9161.             return true;
  9162.         }
  9163.         finally
  9164.         {
  9165.             _subclassLock.unlock();
  9166.         }
  9167.     }
  9168.    
  9169.     public boolean isLocked()
  9170.     {
  9171.         return _subclassLock.isLocked();
  9172.     }
  9173.    
  9174.     public void stopWaterTask()
  9175.     {
  9176.         if (_isInWater)
  9177.         {
  9178.             _isInWater = false;
  9179.             sendPacket(new SetupGauge(2, 0));
  9180.             WaterTaskManager.getInstance().removeWaterTask(this);
  9181.         }
  9182.     }
  9183.    
  9184.     public void startWaterTask()
  9185.     {
  9186.         if (!isDead() && !_isInWater)
  9187.         {
  9188.             _isInWater = true;
  9189.             int time = (int)calcStat(Stats.BREATH, 60000, this, null);
  9190.            
  9191.             sendPacket(new SetupGauge(2, time));
  9192.             WaterTaskManager.getInstance().addWaterTask(this, System.currentTimeMillis() + time);
  9193.         }
  9194.     }
  9195.    
  9196.     public void checkWaterState()
  9197.     {
  9198.         if (isInsideZone(ZONE_WATER))
  9199.             startWaterTask();
  9200.         else
  9201.             stopWaterTask();
  9202.     }
  9203.    
  9204.     public void onPlayerEnter()
  9205.     {
  9206.         if (isCursedWeaponEquipped())
  9207.             CursedWeaponsManager.getInstance().getCursedWeapon(getCursedWeaponEquippedId()).cursedOnLogin();
  9208.        
  9209.         // Add a task for the "Take Break" message.
  9210.         TakeBreakTaskManager.getInstance().addTakeBreakTask(this);
  9211.        
  9212.         // Teleport player if the Seven Signs period isn't the good one, or if the player isn't in a cabal.
  9213.         if (isIn7sDungeon() && !isGM())
  9214.         {
  9215.             if (SevenSigns.getInstance().isSealValidationPeriod() || SevenSigns.getInstance().isCompResultsPeriod())
  9216.             {
  9217.                 if (SevenSigns.getInstance().getPlayerCabal(getObjectId()) != SevenSigns.getInstance()
  9218.                         .getCabalHighestScore())
  9219.                 {
  9220.                     teleToLocation(MapRegionTable.TeleportWhereType.Town);
  9221.                     setIsIn7sDungeon(false);
  9222.                 }
  9223.             }
  9224.             else if (SevenSigns.getInstance().getPlayerCabal(getObjectId()) == SevenSigns.CABAL_NULL)
  9225.             {
  9226.                 teleToLocation(MapRegionTable.TeleportWhereType.Town);
  9227.                 setIsIn7sDungeon(false);
  9228.             }
  9229.         }
  9230.        
  9231.         // Jail task
  9232.         updatePunishState();
  9233.        
  9234.         if (isGM())
  9235.         {
  9236.             if (isInvul())
  9237.                 sendMessage("Entering world in Invulnerable mode.");
  9238.             if (getAppearance().getInvisible())
  9239.                 sendMessage("Entering world in Invisible mode.");
  9240.             if (isInRefusalMode())
  9241.                 sendMessage("Entering world in Message Refusal mode.");
  9242.         }
  9243.        
  9244.         revalidateZone(true);
  9245.         notifyFriends(true);
  9246.     }
  9247.    
  9248.     public long getLastAccess()
  9249.     {
  9250.         return _lastAccess;
  9251.     }
  9252.    
  9253.     private void checkRecom(int recsHave, int recsLeft)
  9254.     {
  9255.         Calendar check = Calendar.getInstance();
  9256.         check.setTimeInMillis(_lastRecomUpdate);
  9257.         check.add(Calendar.DAY_OF_MONTH, 1);
  9258.        
  9259.         Calendar min = Calendar.getInstance();
  9260.        
  9261.         _recomHave = recsHave;
  9262.         _recomLeft = recsLeft;
  9263.        
  9264.         if (getStat().getLevel() < 10 || check.after(min))
  9265.             return;
  9266.        
  9267.         restartRecom();
  9268.     }
  9269.    
  9270.     public void restartRecom()
  9271.     {
  9272.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  9273.         {
  9274.             PreparedStatement statement = con.prepareStatement(DELETE_CHAR_RECOMS);
  9275.             statement.setInt(1, getObjectId());
  9276.             statement.execute();
  9277.             statement.close();
  9278.            
  9279.             _recomChars.clear();
  9280.         }
  9281.         catch (Exception e)
  9282.         {
  9283.             _log.warning("could not clear char recommendations: " + e);
  9284.         }
  9285.        
  9286.         if (getStat().getLevel() < 20)
  9287.         {
  9288.             _recomLeft = 3;
  9289.             _recomHave--;
  9290.         }
  9291.         else if (getStat().getLevel() < 40)
  9292.         {
  9293.             _recomLeft = 6;
  9294.             _recomHave -= 2;
  9295.         }
  9296.         else
  9297.         {
  9298.             _recomLeft = 9;
  9299.             _recomHave -= 3;
  9300.         }
  9301.        
  9302.         if (_recomHave < 0)
  9303.             _recomHave = 0;
  9304.        
  9305.         // If we have to update last update time, but it's now before 13, we should set it to yesterday
  9306.         Calendar update = Calendar.getInstance();
  9307.         if (update.get(Calendar.HOUR_OF_DAY) < 13)
  9308.             update.add(Calendar.DAY_OF_MONTH, -1);
  9309.        
  9310.         update.set(Calendar.HOUR_OF_DAY, 13);
  9311.         _lastRecomUpdate = update.getTimeInMillis();
  9312.     }
  9313.    
  9314.     @Override
  9315.     public void doRevive()
  9316.     {
  9317.         super.doRevive();
  9318.         stopEffects(L2EffectType.CHARMOFCOURAGE);
  9319.         sendPacket(new EtcStatusUpdate(this));
  9320.         _reviveRequested = 0;
  9321.         _revivePower = 0;
  9322.        
  9323.         if (isMounted())
  9324.             startFeed(_mountNpcId);
  9325.        
  9326.         if (isInParty() && getParty().isInDimensionalRift())
  9327.         {
  9328.             if (!DimensionalRiftManager.getInstance().checkIfInPeaceZone(getX(), getY(), getZ()))
  9329.                 getParty().getDimensionalRift().memberRessurected(this);
  9330.         }
  9331.     }
  9332.    
  9333.     @Override
  9334.     public void doRevive(double revivePower)
  9335.     {
  9336.         // Restore the player's lost experience,
  9337.         // depending on the % return of the skill used (based on its power).
  9338.         restoreExp(revivePower);
  9339.         doRevive();
  9340.     }
  9341.    
  9342.     public void reviveRequest(L2PlayerInstance Reviver, L2Skill skill, boolean Pet)
  9343.     {
  9344.         if (_reviveRequested == 1)
  9345.         {
  9346.             // Resurrection has already been proposed.
  9347.             if (_revivePet == Pet)
  9348.                 Reviver.sendPacket(SystemMessageId.RES_HAS_ALREADY_BEEN_PROPOSED);
  9349.             else
  9350.             {
  9351.                 if (Pet)
  9352.                     // A pet cannot be resurrected while it's owner is in the process of resurrecting.
  9353.                     Reviver.sendPacket(SystemMessageId.CANNOT_RES_PET2);
  9354.                 else
  9355.                     // While a pet is attempting to resurrect, it cannot help in resurrecting its master.
  9356.                     Reviver.sendPacket(SystemMessageId.MASTER_CANNOT_RES);
  9357.             }
  9358.             return;
  9359.         }
  9360.        
  9361.         if ((Pet && getPet() != null && getPet().isDead()) || (!Pet && isDead()))
  9362.         {
  9363.             _reviveRequested = 1;
  9364.            
  9365.             if (isPhoenixBlessed())
  9366.                 _revivePower = 100;
  9367.             else if (isAffected(CharEffectList.EFFECT_FLAG_CHARM_OF_COURAGE))
  9368.                 _revivePower = 0;
  9369.             else
  9370.                 _revivePower = Formulas.calculateSkillResurrectRestorePercent(skill.getPower(), Reviver);
  9371.            
  9372.             _revivePet = Pet;
  9373.            
  9374.             if (isAffected(CharEffectList.EFFECT_FLAG_CHARM_OF_COURAGE))
  9375.             {
  9376.                 sendPacket(new ConfirmDlg(SystemMessageId.DO_YOU_WANT_TO_BE_RESTORED).addTime(60000));
  9377.                 return;
  9378.             }
  9379.            
  9380.             sendPacket(new ConfirmDlg(SystemMessageId.RESSURECTION_REQUEST_BY_S1).addPcName(Reviver));
  9381.         }
  9382.     }
  9383.    
  9384.     public void reviveAnswer(int answer)
  9385.     {
  9386.         if (_reviveRequested != 1 || (!isDead() && !_revivePet)
  9387.                 || (_revivePet && getPet() != null && !getPet().isDead()))
  9388.             return;
  9389.        
  9390.         if (answer == 0 && isPhoenixBlessed())
  9391.             stopPhoenixBlessing(null);
  9392.         else if (answer == 1)
  9393.         {
  9394.             if (!_revivePet)
  9395.             {
  9396.                 if (_revivePower != 0)
  9397.                     doRevive(_revivePower);
  9398.                 else
  9399.                     doRevive();
  9400.             }
  9401.             else if (getPet() != null)
  9402.             {
  9403.                 if (_revivePower != 0)
  9404.                     getPet().doRevive(_revivePower);
  9405.                 else
  9406.                     getPet().doRevive();
  9407.             }
  9408.         }
  9409.         _reviveRequested = 0;
  9410.         _revivePower = 0;
  9411.     }
  9412.    
  9413.     public boolean isReviveRequested()
  9414.     {
  9415.         return (_reviveRequested == 1);
  9416.     }
  9417.    
  9418.     public boolean isRevivingPet()
  9419.     {
  9420.         return _revivePet;
  9421.     }
  9422.    
  9423.     public void removeReviving()
  9424.     {
  9425.         _reviveRequested = 0;
  9426.         _revivePower = 0;
  9427.     }
  9428.    
  9429.     public void onActionRequest()
  9430.     {
  9431.         if (isSpawnProtected())
  9432.             sendMessage("As you acted, you are no longer under teleport protection.");
  9433.         setProtection(false);
  9434.     }
  9435.    
  9436.     /**
  9437.      * @param expertiseIndex The expertiseIndex to set.
  9438.      */
  9439.     public void setExpertiseIndex(int expertiseIndex)
  9440.     {
  9441.         _expertiseIndex = expertiseIndex;
  9442.     }
  9443.    
  9444.     /**
  9445.      * @return Returns the expertiseIndex.
  9446.      */
  9447.     public int getExpertiseIndex()
  9448.     {
  9449.         return _expertiseIndex;
  9450.     }
  9451.    
  9452.     @Override
  9453.     public final void onTeleported()
  9454.     {
  9455.         super.onTeleported();
  9456.        
  9457.         // Force a revalidation
  9458.         revalidateZone(true);
  9459.        
  9460.         if (Config.PLAYER_SPAWN_PROTECTION > 0)
  9461.             setProtection(true);
  9462.        
  9463.         // Modify the position of the tamed beast if necessary
  9464.         if (getTrainedBeast() != null)
  9465.         {
  9466.             getTrainedBeast().getAI().stopFollow();
  9467.             getTrainedBeast().teleToLocation(getPosition().getX(), getPosition().getY(), getPosition().getZ(), 0);
  9468.             getTrainedBeast().getAI().startFollow(this);
  9469.         }
  9470.        
  9471.         // Modify the position of the pet if necessary
  9472.         L2Summon pet = getPet();
  9473.         if (pet != null)
  9474.         {
  9475.             pet.setFollowStatus(false);
  9476.             pet.teleToLocation(getPosition().getX(), getPosition().getY(), getPosition().getZ(), 0);
  9477.             ((L2SummonAI)pet.getAI()).setStartFollowController(true);
  9478.             pet.setFollowStatus(true);
  9479.         }
  9480.     }
  9481.    
  9482.     public void setLastServerPosition(int x, int y, int z)
  9483.     {
  9484.         _lastServerPosition.setXYZ(x, y, z);
  9485.     }
  9486.    
  9487.     public boolean checkLastServerPosition(int x, int y, int z)
  9488.     {
  9489.         return _lastServerPosition.equals(x, y, z);
  9490.     }
  9491.    
  9492.     public int getLastServerDistance(int x, int y, int z)
  9493.     {
  9494.         double dx = (x - _lastServerPosition.getX());
  9495.         double dy = (y - _lastServerPosition.getY());
  9496.         double dz = (z - _lastServerPosition.getZ());
  9497.        
  9498.         return (int)Math.sqrt(dx * dx + dy * dy + dz * dz);
  9499.     }
  9500.    
  9501.     @Override
  9502.     public void addExpAndSp(long addToExp, int addToSp)
  9503.     {
  9504.         getStat().addExpAndSp(addToExp, addToSp);
  9505.     }
  9506.    
  9507.     public void removeExpAndSp(long removeExp, int removeSp)
  9508.     {
  9509.         getStat().removeExpAndSp(removeExp, removeSp);
  9510.     }
  9511.    
  9512.     @Override
  9513.     public void reduceCurrentHp(double value, L2Character attacker, boolean awake, boolean isDOT, L2Skill skill)
  9514.     {
  9515.         if (skill != null)
  9516.             getStatus().reduceHp(value, attacker, awake, isDOT, skill.isToggle(), skill.getDmgDirectlyToHP());
  9517.         else
  9518.             getStatus().reduceHp(value, attacker, awake, isDOT, false, false);
  9519.        
  9520.         // notify the tamed beast of attacks
  9521.         if (getTrainedBeast() != null)
  9522.             getTrainedBeast().onOwnerGotAttacked(attacker);
  9523.     }
  9524.    
  9525.     public void broadcastSnoop(int type, String name, String _text)
  9526.     {
  9527.         if (_snoopListener.size() > 0)
  9528.         {
  9529.             Snoop sn = new Snoop(getObjectId(), getName(), type, name, _text);
  9530.            
  9531.             for (L2PlayerInstance pci : _snoopListener)
  9532.                 if (pci != null)
  9533.                     pci.sendPacket(sn);
  9534.         }
  9535.     }
  9536.    
  9537.     public void addSnooper(L2PlayerInstance pci)
  9538.     {
  9539.         if (!_snoopListener.contains(pci))
  9540.             _snoopListener.add(pci);
  9541.     }
  9542.    
  9543.     public void removeSnooper(L2PlayerInstance pci)
  9544.     {
  9545.         _snoopListener.remove(pci);
  9546.     }
  9547.    
  9548.     public void addSnooped(L2PlayerInstance pci)
  9549.     {
  9550.         if (!_snoopedPlayer.contains(pci))
  9551.             _snoopedPlayer.add(pci);
  9552.     }
  9553.    
  9554.     public void removeSnooped(L2PlayerInstance pci)
  9555.     {
  9556.         _snoopedPlayer.remove(pci);
  9557.     }
  9558.    
  9559.     public synchronized void addBypass(String bypass)
  9560.     {
  9561.         if (bypass == null)
  9562.             return;
  9563.        
  9564.         _validBypass.add(bypass);
  9565.     }
  9566.    
  9567.     public synchronized void addBypass2(String bypass)
  9568.     {
  9569.         if (bypass == null)
  9570.             return;
  9571.        
  9572.         _validBypass2.add(bypass);
  9573.     }
  9574.    
  9575.     public synchronized boolean validateBypass(String cmd)
  9576.     {
  9577.         for (String bp : _validBypass)
  9578.         {
  9579.             if (bp == null)
  9580.                 continue;
  9581.            
  9582.             if (bp.equals(cmd))
  9583.                 return true;
  9584.         }
  9585.        
  9586.         for (String bp : _validBypass2)
  9587.         {
  9588.             if (bp == null)
  9589.                 continue;
  9590.            
  9591.             if (cmd.startsWith(bp))
  9592.                 return true;
  9593.         }
  9594.        
  9595.         return false;
  9596.     }
  9597.    
  9598.     public boolean validateItemManipulation(int objectId, String action)
  9599.     {
  9600.         L2ItemInstance item = getInventory().getItemByObjectId(objectId);
  9601.        
  9602.         if (item == null || item.getOwnerId() != getObjectId())
  9603.         {
  9604.             _log.finest(getObjectId() + ": player tried to " + action + " item he is not owner of");
  9605.             return false;
  9606.         }
  9607.        
  9608.         // Pet is summoned and not the item that summoned the pet AND not the buggle from strider you're mounting
  9609.         if (getPet() != null && getPet().getControlItemId() == objectId || getMountObjectID() == objectId)
  9610.         {
  9611.             return false;
  9612.         }
  9613.        
  9614.         if (getActiveEnchantItem() != null && getActiveEnchantItem().getObjectId() == objectId)
  9615.         {
  9616.             return false;
  9617.         }
  9618.        
  9619.         if (CursedWeaponsManager.getInstance().isCursed(item.getItemId()))
  9620.         {
  9621.             // can not trade a cursed weapon
  9622.             return false;
  9623.         }
  9624.        
  9625.         return true;
  9626.     }
  9627.    
  9628.     public synchronized void clearBypass()
  9629.     {
  9630.         _validBypass.clear();
  9631.         _validBypass2.clear();
  9632.     }
  9633.    
  9634.     /**
  9635.      * @return Returns the inBoat.
  9636.      */
  9637.     public boolean isInBoat()
  9638.     {
  9639.         return _vehicle != null && _vehicle.isBoat();
  9640.     }
  9641.    
  9642.     /**
  9643.      * @return
  9644.      */
  9645.     public L2BoatInstance getBoat()
  9646.     {
  9647.         return (L2BoatInstance)_vehicle;
  9648.     }
  9649.    
  9650.     public L2Vehicle getVehicle()
  9651.     {
  9652.         return _vehicle;
  9653.     }
  9654.    
  9655.     public void setVehicle(L2Vehicle v)
  9656.     {
  9657.         if (v == null && _vehicle != null)
  9658.             _vehicle.removePassenger(this);
  9659.        
  9660.         _vehicle = v;
  9661.     }
  9662.    
  9663.     public void setInCrystallize(boolean inCrystallize)
  9664.     {
  9665.         _inCrystallize = inCrystallize;
  9666.     }
  9667.    
  9668.     public boolean isInCrystallize()
  9669.     {
  9670.         return _inCrystallize;
  9671.     }
  9672.    
  9673.     /**
  9674.      * @return
  9675.      */
  9676.     public Point3D getInVehiclePosition()
  9677.     {
  9678.         return _inVehiclePosition;
  9679.     }
  9680.    
  9681.     public void setInVehiclePosition(Point3D pt)
  9682.     {
  9683.         _inVehiclePosition = pt;
  9684.     }
  9685.    
  9686.     /**
  9687.      * Manage the delete task of a L2PlayerInstance (Leave Party, Unsummon pet, Save its inventory
  9688.      * in the database, Remove it from the world...).<BR>
  9689.      * <BR>
  9690.      * <B><U> Actions</U> :</B><BR>
  9691.      * <BR>
  9692.      * <li>If the L2PlayerInstance is in observer mode, set its position to its position before
  9693.      * entering in observer mode</li> <li>Set the online Flag to True or False and update the
  9694.      * characters table of the database with online status and lastAccess</li> <li>Stop the HP/MP/CP
  9695.      * Regeneration task</li> <li>
  9696.      * Cancel Crafting, Attak or Cast</li> <li>Remove the L2PlayerInstance from the world</li> <li>
  9697.      * Stop Party and Unsummon Pet</li> <li>Update database with items in its inventory and remove
  9698.      * them from the world</li> <li>Remove all L2Object from _knownObjects and _knownPlayer of the
  9699.      * L2Character then cancel Attak or Cast and notify AI</li> <li>Close the connection with the
  9700.      * client</li><BR>
  9701.      * <BR>
  9702.      */
  9703.     @Override
  9704.     public void deleteMe()
  9705.     {
  9706.         cleanup();
  9707.         store();
  9708.         super.deleteMe();
  9709.     }
  9710.    
  9711.     private synchronized void cleanup()
  9712.     {
  9713.         try
  9714.         {
  9715.             if (!isOnline())
  9716.                 _log.log(Level.SEVERE, "deleteMe() called on offline character " + this, new RuntimeException());
  9717.            
  9718.             // Put the online status to false
  9719.             setOnlineStatus(false, true);
  9720.            
  9721.             // abort cast & attack and remove the target. Cancels movement aswell.
  9722.             abortAttack();
  9723.             abortCast();
  9724.             stopMove(null);
  9725.             setTarget(null);
  9726.            
  9727.             PartyMatchWaitingList.getInstance().removePlayer(this);
  9728.             if (_partyroom != 0)
  9729.             {
  9730.                 PartyMatchRoom room = PartyMatchRoomList.getInstance().getRoom(_partyroom);
  9731.                 if (room != null)
  9732.                     room.deleteMember(this);
  9733.             }
  9734.            
  9735.             if (isFlying())
  9736.                 removeSkill(SkillTable.getInstance().getInfo(4289, 1));
  9737.            
  9738.             // Stop all scheduled tasks
  9739.             stopAllTimers();
  9740.            
  9741.             // Cancel the cast of eventual fusion skill users on this target.
  9742.             for (L2Character character : getKnownList().getKnownType(L2Character.class))
  9743.                 if (character.getFusionSkill() != null && character.getFusionSkill().getTarget() == this)
  9744.                     character.abortCast();
  9745.            
  9746.             // Stop signets & toggles effects.
  9747.             for (L2Effect effect : getAllEffects())
  9748.             {
  9749.                 if (effect.getSkill().isToggle())
  9750.                 {
  9751.                     effect.exit();
  9752.                     continue;
  9753.                 }
  9754.                
  9755.                 switch (effect.getEffectType())
  9756.                 {
  9757.                     case SIGNET_GROUND:
  9758.                     case SIGNET_EFFECT:
  9759.                         effect.exit();
  9760.                         break;
  9761.                     default:
  9762.                         break;
  9763.                 }
  9764.             }
  9765.            
  9766.             // Remove the L2PlayerInstance from the world
  9767.             decayMe();
  9768.            
  9769.             // Remove from world regions zones
  9770.             L2WorldRegion oldRegion = getWorldRegion();
  9771.             if (oldRegion != null)
  9772.                 oldRegion.removeFromZones(this);
  9773.            
  9774.             // If a party is in progress, leave it
  9775.             if (isInParty())
  9776.                 leaveParty();
  9777.            
  9778.             // If the L2PlayerInstance has Pet, unsummon it
  9779.             if (getPet() != null)
  9780.                 getPet().unSummon(this);
  9781.            
  9782.             // Handle removal from olympiad game
  9783.             if (OlympiadManager.getInstance().isRegistered(this) || getOlympiadGameId() != -1)
  9784.                 OlympiadManager.getInstance().removeDisconnectedCompetitor(this);
  9785.            
  9786.             // set the status for pledge member list to OFFLINE
  9787.             if (getClan() != null)
  9788.             {
  9789.                 L2ClanMember clanMember = getClan().getClanMember(getName());
  9790.                 if (clanMember != null)
  9791.                     clanMember.setPlayerInstance(null);
  9792.             }
  9793.            
  9794.             // deals with sudden exit in the middle of transaction
  9795.             if (getActiveRequester() != null)
  9796.             {
  9797.                 setActiveRequester(null);
  9798.                 cancelActiveTrade();
  9799.             }
  9800.            
  9801.             // If the L2PlayerInstance is a GM, remove it from the GM List
  9802.             if (isGM())
  9803.                 GmListTable.getInstance().deleteGm(this);
  9804.            
  9805.             // Check if the L2PlayerInstance is in observer mode to set its position to its position
  9806.             // before entering in observer mode
  9807.             if (inObserverMode())
  9808.                 setXYZInvisible(_lastX, _lastY, _lastZ);
  9809.            
  9810.             // Oust player from boat
  9811.             if (getVehicle() != null)
  9812.                 getVehicle().oustPlayer(this);
  9813.            
  9814.             // Update inventory and remove them from the world
  9815.             getInventory().deleteMe();
  9816.            
  9817.             // Update warehouse and remove them from the world
  9818.             clearWarehouse();
  9819.            
  9820.             // Update freight and remove them from the world
  9821.             clearFreight();
  9822.             clearDepositedFreight();
  9823.            
  9824.             if (isCursedWeaponEquipped())
  9825.                 CursedWeaponsManager.getInstance().getCursedWeapon(_cursedWeaponEquippedId).setPlayer(null);
  9826.            
  9827.             // Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  9828.             getKnownList().removeAllKnownObjects();
  9829.            
  9830.             if (getClanId() > 0)
  9831.                 getClan().broadcastToOtherOnlineMembers(new PledgeShowMemberListUpdate(this), this);
  9832.            
  9833.             for (L2PlayerInstance player : _snoopedPlayer)
  9834.                 player.removeSnooper(this);
  9835.            
  9836.             for (L2PlayerInstance player : _snoopListener)
  9837.                 player.removeSnooped(this);
  9838.            
  9839.             // Remove L2Object object from _allObjects of L2World
  9840.             L2World.getInstance().removeObject(this);
  9841.             L2World.getInstance().removeFromAllPlayers(this); // force remove in case of crash during teleport
  9842.            
  9843.             // friends & blocklist update
  9844.             notifyFriends(false);
  9845.             getBlockList().playerLogout();
  9846.         }
  9847.         catch (Exception e)
  9848.         {
  9849.             _log.log(Level.WARNING, "Exception on deleteMe()" + e.getMessage(), e);
  9850.         }
  9851.     }
  9852.    
  9853.     public void startFishing(Location loc)
  9854.     {
  9855.         stopMove(null);
  9856.         setIsImmobilized(true);
  9857.        
  9858.         _fishingLoc = loc;
  9859.        
  9860.         // Starts fishing
  9861.         int group = getRandomGroup();
  9862.        
  9863.         _fish = FishTable.getFish(getRandomFishLvl(), getRandomFishType(group), group);
  9864.         if (_fish == null)
  9865.         {
  9866.             endFishing(false);
  9867.             return;
  9868.         }
  9869.        
  9870.         sendPacket(SystemMessageId.CAST_LINE_AND_START_FISHING);
  9871.        
  9872.         broadcastPacket(new ExFishingStart(this, _fish.getType(_lure.isNightLure()), loc, _lure.isNightLure()));
  9873.         sendPacket(new PlaySound(1, "SF_P_01", 0, 0, 0, 0, 0));
  9874.         startLookingForFishTask();
  9875.     }
  9876.    
  9877.     public void stopLookingForFishTask()
  9878.     {
  9879.         if (_taskforfish != null)
  9880.         {
  9881.             _taskforfish.cancel(false);
  9882.             _taskforfish = null;
  9883.         }
  9884.     }
  9885.    
  9886.     public void startLookingForFishTask()
  9887.     {
  9888.         if (!isDead() && _taskforfish == null)
  9889.         {
  9890.             int checkDelay = 0;
  9891.             boolean isNoob = false;
  9892.             boolean isUpperGrade = false;
  9893.            
  9894.             if (_lure != null)
  9895.             {
  9896.                 int lureid = _lure.getItemId();
  9897.                 isNoob = _fish.getGroup() == 0;
  9898.                 isUpperGrade = _fish.getGroup() == 2;
  9899.                 if (lureid == 6519 || lureid == 6522 || lureid == 6525 || lureid == 8505 || lureid == 8508
  9900.                         || lureid == 8511) // low grade
  9901.                     checkDelay = Math.round((float)(_fish.getGutsCheckTime() * (1.33)));
  9902.                 else if (lureid == 6520 || lureid == 6523 || lureid == 6526 || (lureid >= 8505 && lureid <= 8513)
  9903.                         || (lureid >= 7610 && lureid <= 7613) || (lureid >= 7807 && lureid <= 7809)
  9904.                         || (lureid >= 8484 && lureid <= 8486)) // medium grade, beginner, prize-winning & quest special bait
  9905.                     checkDelay = Math.round((float)(_fish.getGutsCheckTime() * (1.00)));
  9906.                 else if (lureid == 6521 || lureid == 6524 || lureid == 6527 || lureid == 8507 || lureid == 8510
  9907.                         || lureid == 8513) // high grade
  9908.                     checkDelay = Math.round((float)(_fish.getGutsCheckTime() * (0.66)));
  9909.             }
  9910.             _taskforfish =
  9911.                     ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(
  9912.                             new LookingForFishTask(_fish.getWaitTime(), _fish.getFishGuts(), _fish.getType(_lure
  9913.                                     .isNightLure()), isNoob, isUpperGrade), 10000, checkDelay);
  9914.         }
  9915.     }
  9916.    
  9917.     private int getRandomGroup()
  9918.     {
  9919.         switch (_lure.getItemId())
  9920.         {
  9921.             case 7807: // green for beginners
  9922.             case 7808: // purple for beginners
  9923.             case 7809: // yellow for beginners
  9924.             case 8486: // prize-winning for beginners
  9925.                 return 0;
  9926.                
  9927.             case 8485: // prize-winning luminous
  9928.             case 8506: // green luminous
  9929.             case 8509: // purple luminous
  9930.             case 8512: // yellow luminous
  9931.                 return 2;
  9932.                
  9933.             default:
  9934.                 return 1;
  9935.         }
  9936.     }
  9937.    
  9938.     private int getRandomFishType(int group)
  9939.     {
  9940.         int check = Rnd.get(100);
  9941.         int type = 1;
  9942.         switch (group)
  9943.         {
  9944.             case 0: // fish for novices
  9945.                 switch (_lure.getItemId())
  9946.                 {
  9947.                     case 7807: // green lure, preferred by fast-moving (nimble) fish (type 5)
  9948.                         if (check <= 54)
  9949.                             type = 5;
  9950.                         else if (check <= 77)
  9951.                             type = 4;
  9952.                         else
  9953.                             type = 6;
  9954.                         break;
  9955.                    
  9956.                     case 7808: // purple lure, preferred by fat fish (type 4)
  9957.                         if (check <= 54)
  9958.                             type = 4;
  9959.                         else if (check <= 77)
  9960.                             type = 6;
  9961.                         else
  9962.                             type = 5;
  9963.                         break;
  9964.                    
  9965.                     case 7809: // yellow lure, preferred by ugly fish (type 6)
  9966.                         if (check <= 54)
  9967.                             type = 6;
  9968.                         else if (check <= 77)
  9969.                             type = 5;
  9970.                         else
  9971.                             type = 4;
  9972.                         break;
  9973.                    
  9974.                     case 8486: // prize-winning fishing lure for beginners
  9975.                         if (check <= 33)
  9976.                             type = 4;
  9977.                         else if (check <= 66)
  9978.                             type = 5;
  9979.                         else
  9980.                             type = 6;
  9981.                         break;
  9982.                 }
  9983.                 break;
  9984.            
  9985.             case 1: // normal fish
  9986.                 switch (_lure.getItemId())
  9987.                 {
  9988.                     case 7610:
  9989.                     case 7611:
  9990.                     case 7612:
  9991.                     case 7613:
  9992.                         type = 3;
  9993.                         break;
  9994.                    
  9995.                     case 6519: // all theese lures (green) are prefered by fast-moving (nimble) fish (type 1)
  9996.                     case 8505:
  9997.                     case 6520:
  9998.                     case 6521:
  9999.                     case 8507:
  10000.                         if (check <= 54)
  10001.                             type = 1;
  10002.                         else if (check <= 74)
  10003.                             type = 0;
  10004.                         else if (check <= 94)
  10005.                             type = 2;
  10006.                         else
  10007.                             type = 3;
  10008.                         break;
  10009.                    
  10010.                     case 6522: // all theese lures (purple) are prefered by fat fish (type 0)
  10011.                     case 8508:
  10012.                     case 6523:
  10013.                     case 6524:
  10014.                     case 8510:
  10015.                         if (check <= 54)
  10016.                             type = 0;
  10017.                         else if (check <= 74)
  10018.                             type = 1;
  10019.                         else if (check <= 94)
  10020.                             type = 2;
  10021.                         else
  10022.                             type = 3;
  10023.                         break;
  10024.                    
  10025.                     case 6525: // all theese lures (yellow) are prefered by ugly fish (type 2)
  10026.                     case 8511:
  10027.                     case 6526:
  10028.                     case 6527:
  10029.                     case 8513:
  10030.                         if (check <= 55)
  10031.                             type = 2;
  10032.                         else if (check <= 74)
  10033.                             type = 1;
  10034.                         else if (check <= 94)
  10035.                             type = 0;
  10036.                         else
  10037.                             type = 3;
  10038.                         break;
  10039.                     case 8484: // prize-winning fishing lure
  10040.                         if (check <= 33)
  10041.                             type = 0;
  10042.                         else if (check <= 66)
  10043.                             type = 1;
  10044.                         else
  10045.                             type = 2;
  10046.                         break;
  10047.                 }
  10048.                 break;
  10049.            
  10050.             case 2: // upper grade fish, luminous lure
  10051.                 switch (_lure.getItemId())
  10052.                 {
  10053.                     case 8506: // green lure, preferred by fast-moving (nimble) fish (type 8)
  10054.                         if (check <= 54)
  10055.                             type = 8;
  10056.                         else if (check <= 77)
  10057.                             type = 7;
  10058.                         else
  10059.                             type = 9;
  10060.                         break;
  10061.                    
  10062.                     case 8509: // purple lure, preferred by fat fish (type 7)
  10063.                         if (check <= 54)
  10064.                             type = 7;
  10065.                         else if (check <= 77)
  10066.                             type = 9;
  10067.                         else
  10068.                             type = 8;
  10069.                         break;
  10070.                    
  10071.                     case 8512: // yellow lure, preferred by ugly fish (type 9)
  10072.                         if (check <= 54)
  10073.                             type = 9;
  10074.                         else if (check <= 77)
  10075.                             type = 8;
  10076.                         else
  10077.                             type = 7;
  10078.                         break;
  10079.                    
  10080.                     case 8485: // prize-winning fishing lure
  10081.                         if (check <= 33)
  10082.                             type = 7;
  10083.                         else if (check <= 66)
  10084.                             type = 8;
  10085.                         else
  10086.                             type = 9;
  10087.                         break;
  10088.                 }
  10089.         }
  10090.         return type;
  10091.     }
  10092.    
  10093.     private int getRandomFishLvl()
  10094.     {
  10095.         int skilllvl = getSkillLevel(1315);
  10096.        
  10097.         final L2Effect e = getFirstEffect(2274);
  10098.         if (e != null)
  10099.             skilllvl = (int)e.getSkill().getPower();
  10100.        
  10101.         if (skilllvl <= 0)
  10102.             return 1;
  10103.        
  10104.         int randomlvl;
  10105.        
  10106.         final int check = Rnd.get(100);
  10107.         if (check <= 50)
  10108.             randomlvl = skilllvl;
  10109.         else if (check <= 85)
  10110.         {
  10111.             randomlvl = skilllvl - 1;
  10112.             if (randomlvl <= 0)
  10113.                 randomlvl = 1;
  10114.         }
  10115.         else
  10116.         {
  10117.             randomlvl = skilllvl + 1;
  10118.             if (randomlvl > 27)
  10119.                 randomlvl = 27;
  10120.         }
  10121.         return randomlvl;
  10122.     }
  10123.    
  10124.     public void startFishCombat(boolean isNoob, boolean isUpperGrade)
  10125.     {
  10126.         _fishCombat = new L2Fishing(this, _fish, isNoob, isUpperGrade, _lure.getItemId());
  10127.     }
  10128.    
  10129.     public void endFishing(boolean win)
  10130.     {
  10131.         if (_fishCombat == null)
  10132.             sendPacket(SystemMessageId.BAIT_LOST_FISH_GOT_AWAY);
  10133.         else
  10134.             _fishCombat = null;
  10135.        
  10136.         _lure = null;
  10137.         _fishingLoc = null;
  10138.        
  10139.         // Ends fishing
  10140.         broadcastPacket(new ExFishingEnd(win, this));
  10141.         sendPacket(SystemMessageId.REEL_LINE_AND_STOP_FISHING);
  10142.         setIsImmobilized(false);
  10143.         stopLookingForFishTask();
  10144.     }
  10145.    
  10146.     public L2Fishing getFishCombat()
  10147.     {
  10148.         return _fishCombat;
  10149.     }
  10150.    
  10151.     public Location getFishingLoc()
  10152.     {
  10153.         return _fishingLoc;
  10154.     }
  10155.    
  10156.     public void setLure(L2ItemInstance lure)
  10157.     {
  10158.         _lure = lure;
  10159.     }
  10160.    
  10161.     public L2ItemInstance getLure()
  10162.     {
  10163.         return _lure;
  10164.     }
  10165.    
  10166.     public int getInventoryLimit()
  10167.     {
  10168.         int ivlim;
  10169.         if (getRace() == Race.Dwarf)
  10170.             ivlim = Config.INVENTORY_MAXIMUM_DWARF;
  10171.         else
  10172.             ivlim = Config.INVENTORY_MAXIMUM_NO_DWARF;
  10173.        
  10174.         ivlim += (int)getStat().calcStat(Stats.INV_LIM, 0, null, null);
  10175.        
  10176.         return ivlim;
  10177.     }
  10178.    
  10179.     /**
  10180.      * @return
  10181.      */
  10182.     public static int getQuestInventoryLimit()
  10183.     {
  10184.         return Config.INVENTORY_MAXIMUM_QUEST_ITEMS;
  10185.     }
  10186.    
  10187.     public int getWareHouseLimit()
  10188.     {
  10189.         int whlim;
  10190.         if (getRace() == Race.Dwarf)
  10191.             whlim = Config.WAREHOUSE_SLOTS_DWARF;
  10192.         else
  10193.             whlim = Config.WAREHOUSE_SLOTS_NO_DWARF;
  10194.         whlim += (int)getStat().calcStat(Stats.WH_LIM, 0, null, null);
  10195.        
  10196.         return whlim;
  10197.     }
  10198.    
  10199.     public int getPrivateSellStoreLimit()
  10200.     {
  10201.         int pslim;
  10202.         if (getRace() == Race.Dwarf)
  10203.             pslim = Config.MAX_PVTSTORE_SLOTS_DWARF;
  10204.         else
  10205.             pslim = Config.MAX_PVTSTORE_SLOTS_OTHER;
  10206.        
  10207.         pslim += (int)getStat().calcStat(Stats.P_SELL_LIM, 0, null, null);
  10208.        
  10209.         return pslim;
  10210.     }
  10211.    
  10212.     public int getPrivateBuyStoreLimit()
  10213.     {
  10214.         int pblim;
  10215.         if (getRace() == Race.Dwarf)
  10216.             pblim = Config.MAX_PVTSTORE_SLOTS_DWARF;
  10217.         else
  10218.             pblim = Config.MAX_PVTSTORE_SLOTS_OTHER;
  10219.        
  10220.         pblim += (int)getStat().calcStat(Stats.P_BUY_LIM, 0, null, null);
  10221.        
  10222.         return pblim;
  10223.     }
  10224.    
  10225.     public int getFreightLimit()
  10226.     {
  10227.         return Config.FREIGHT_SLOTS + (int)getStat().calcStat(Stats.FREIGHT_LIM, 0, null, null);
  10228.     }
  10229.    
  10230.     public int getDwarfRecipeLimit()
  10231.     {
  10232.         int recdlim = Config.DWARF_RECIPE_LIMIT;
  10233.         recdlim += (int)getStat().calcStat(Stats.REC_D_LIM, 0, null, null);
  10234.         return recdlim;
  10235.     }
  10236.    
  10237.     public int getCommonRecipeLimit()
  10238.     {
  10239.         int recclim = Config.COMMON_RECIPE_LIMIT;
  10240.         recclim += (int)getStat().calcStat(Stats.REC_C_LIM, 0, null, null);
  10241.         return recclim;
  10242.     }
  10243.    
  10244.     public int getMountNpcId()
  10245.     {
  10246.         return _mountNpcId;
  10247.     }
  10248.    
  10249.     public int getMountLevel()
  10250.     {
  10251.         return _mountLevel;
  10252.     }
  10253.    
  10254.     public void setMountObjectID(int newID)
  10255.     {
  10256.         _mountObjectID = newID;
  10257.     }
  10258.    
  10259.     public int getMountObjectID()
  10260.     {
  10261.         return _mountObjectID;
  10262.     }
  10263.    
  10264.     /**
  10265.      * @return the current skill in use or return null.
  10266.      */
  10267.     public SkillDat getCurrentSkill()
  10268.     {
  10269.         return _currentSkill;
  10270.     }
  10271.    
  10272.     /**
  10273.      * Create a new SkillDat object and set the player _currentSkill.
  10274.      *
  10275.      * @param currentSkill
  10276.      * @param ctrlPressed
  10277.      * @param shiftPressed
  10278.      */
  10279.     public void setCurrentSkill(L2Skill currentSkill, boolean ctrlPressed, boolean shiftPressed)
  10280.     {
  10281.         if (currentSkill == null)
  10282.         {
  10283.             _currentSkill = null;
  10284.             return;
  10285.         }
  10286.         _currentSkill = new SkillDat(currentSkill, ctrlPressed, shiftPressed);
  10287.     }
  10288.    
  10289.     /**
  10290.      * @return the current pet skill in use or return null.
  10291.      */
  10292.     public SkillDat getCurrentPetSkill()
  10293.     {
  10294.         return _currentPetSkill;
  10295.     }
  10296.    
  10297.     /**
  10298.      * Create a new SkillDat object and set the player _currentPetSkill.
  10299.      *
  10300.      * @param currentSkill
  10301.      * @param ctrlPressed
  10302.      * @param shiftPressed
  10303.      */
  10304.     public void setCurrentPetSkill(L2Skill currentSkill, boolean ctrlPressed, boolean shiftPressed)
  10305.     {
  10306.         if (currentSkill == null)
  10307.         {
  10308.             _currentPetSkill = null;
  10309.             return;
  10310.         }
  10311.         _currentPetSkill = new SkillDat(currentSkill, ctrlPressed, shiftPressed);
  10312.     }
  10313.    
  10314.     public SkillDat getQueuedSkill()
  10315.     {
  10316.         return _queuedSkill;
  10317.     }
  10318.    
  10319.     /**
  10320.      * Create a new SkillDat object and queue it in the player _queuedSkill.
  10321.      *
  10322.      * @param queuedSkill
  10323.      * @param ctrlPressed
  10324.      * @param shiftPressed
  10325.      */
  10326.     public void setQueuedSkill(L2Skill queuedSkill, boolean ctrlPressed, boolean shiftPressed)
  10327.     {
  10328.         if (queuedSkill == null)
  10329.         {
  10330.             _queuedSkill = null;
  10331.             return;
  10332.         }
  10333.         _queuedSkill = new SkillDat(queuedSkill, ctrlPressed, shiftPressed);
  10334.     }
  10335.    
  10336.     /**
  10337.      * @return the timer to delay animation tasks, based on run speed.
  10338.      */
  10339.     public int getAnimationTimer()
  10340.     {
  10341.         int timer = 5000 - getRunSpeed() * 20;
  10342.         if (timer < 1000)
  10343.             timer = 1000;
  10344.        
  10345.         return timer;
  10346.     }
  10347.    
  10348.     /**
  10349.      * @return punishment level of player
  10350.      */
  10351.     public PunishLevel getPunishLevel()
  10352.     {
  10353.         return _punishLevel;
  10354.     }
  10355.    
  10356.     /**
  10357.      * @return True if player is jailed
  10358.      */
  10359.     public boolean isInJail()
  10360.     {
  10361.         return _punishLevel == PunishLevel.JAIL;
  10362.     }
  10363.    
  10364.     /**
  10365.      * @return True if player is chat banned
  10366.      */
  10367.     public boolean isChatBanned()
  10368.     {
  10369.         return _punishLevel == PunishLevel.CHAT;
  10370.     }
  10371.    
  10372.     public void setPunishLevel(int state)
  10373.     {
  10374.         switch (state)
  10375.         {
  10376.             case 0:
  10377.                 _punishLevel = PunishLevel.NONE;
  10378.                 break;
  10379.             case 1:
  10380.                 _punishLevel = PunishLevel.CHAT;
  10381.                 break;
  10382.             case 2:
  10383.                 _punishLevel = PunishLevel.JAIL;
  10384.                 break;
  10385.             case 3:
  10386.                 _punishLevel = PunishLevel.CHAR;
  10387.                 break;
  10388.             case 4:
  10389.                 _punishLevel = PunishLevel.ACC;
  10390.                 break;
  10391.         }
  10392.     }
  10393.    
  10394.     /**
  10395.      * Sets punish level for player based on delay
  10396.      *
  10397.      * @param state
  10398.      * @param delayInMinutes -- 0 for infinite
  10399.      */
  10400.     public void setPunishLevel(PunishLevel state, int delayInMinutes)
  10401.     {
  10402.         long delayInMilliseconds = delayInMinutes * 60000L;
  10403.         switch (state)
  10404.         {
  10405.             case NONE: // Remove Punishments
  10406.             {
  10407.                 switch (_punishLevel)
  10408.                 {
  10409.                     case CHAT:
  10410.                     {
  10411.                         _punishLevel = state;
  10412.                         stopPunishTask(true);
  10413.                         sendPacket(new EtcStatusUpdate(this));
  10414.                         sendMessage("Chatting is now available.");
  10415.                         sendPacket(new PlaySound("systemmsg_e.345"));
  10416.                         break;
  10417.                     }
  10418.                     case JAIL:
  10419.                     {
  10420.                         _punishLevel = state;
  10421.                        
  10422.                         // Open a Html message to inform the player
  10423.                         NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0);
  10424.                         htmlMsg.setFile("data/html/jail_out.htm");
  10425.                         sendPacket(htmlMsg);
  10426.                         stopPunishTask(true);
  10427.                         teleToLocation(17836, 170178, -3507, 20); // Floran village
  10428.                         break;
  10429.                     }
  10430.                     default:
  10431.                         break;
  10432.                 }
  10433.                 break;
  10434.             }
  10435.             case CHAT: // Chat ban
  10436.             {
  10437.                 // not allow player to escape jail using chat ban
  10438.                 if (_punishLevel == PunishLevel.JAIL)
  10439.                     break;
  10440.                
  10441.                 _punishLevel = state;
  10442.                 _punishTimer = 0;
  10443.                 sendPacket(new EtcStatusUpdate(this));
  10444.                
  10445.                 // Remove the task if any
  10446.                 stopPunishTask(false);
  10447.                
  10448.                 if (delayInMinutes > 0)
  10449.                 {
  10450.                     _punishTimer = delayInMilliseconds;
  10451.                    
  10452.                     // start the countdown
  10453.                     _punishTask = ThreadPoolManager.getInstance().scheduleGeneral(new PunishTask(), _punishTimer);
  10454.                     sendMessage("Chatting has been suspended for " + delayInMinutes + " minute(s).");
  10455.                 }
  10456.                 else
  10457.                     sendMessage("Chatting has been suspended.");
  10458.                
  10459.                 // Send same sound packet in both "delay" cases.
  10460.                 sendPacket(new PlaySound("systemmsg_e.346"));
  10461.                 break;
  10462.                
  10463.             }
  10464.             case JAIL: // Jail Player
  10465.             {
  10466.                 _punishLevel = state;
  10467.                 _punishTimer = 0;
  10468.                
  10469.                 // Remove the task if any
  10470.                 stopPunishTask(false);
  10471.                
  10472.                 if (delayInMinutes > 0)
  10473.                 {
  10474.                     _punishTimer = delayInMilliseconds;
  10475.                    
  10476.                     // start the countdown
  10477.                     _punishTask = ThreadPoolManager.getInstance().scheduleGeneral(new PunishTask(), _punishTimer);
  10478.                     sendMessage("You are jailed for " + delayInMinutes + " minutes.");
  10479.                 }
  10480.                
  10481.                 if (OlympiadManager.getInstance().isRegisteredInComp(this))
  10482.                     OlympiadManager.getInstance().removeDisconnectedCompetitor(this);
  10483.                
  10484.                 // Open a Html message to inform the player
  10485.                 NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0);
  10486.                 htmlMsg.setFile("data/html/jail_in.htm");
  10487.                 sendPacket(htmlMsg);
  10488.                 setIsIn7sDungeon(false);
  10489.                
  10490.                 teleToLocation(-114356, -249645, -2984, 0); // Jail
  10491.                 break;
  10492.             }
  10493.             case CHAR: // Ban Character
  10494.             {
  10495.                 setAccessLevel(-100);
  10496.                 logout();
  10497.                 break;
  10498.             }
  10499.             case ACC: // Ban Account
  10500.             {
  10501.                 setAccountAccesslevel(-100);
  10502.                 logout();
  10503.                 break;
  10504.             }
  10505.             default:
  10506.             {
  10507.                 _punishLevel = state;
  10508.                 break;
  10509.             }
  10510.         }
  10511.        
  10512.         // store in database
  10513.         storeCharBase();
  10514.     }
  10515.    
  10516.     public long getPunishTimer()
  10517.     {
  10518.         return _punishTimer;
  10519.     }
  10520.    
  10521.     public void setPunishTimer(long time)
  10522.     {
  10523.         _punishTimer = time;
  10524.     }
  10525.    
  10526.     private void updatePunishState()
  10527.     {
  10528.         if (getPunishLevel() != PunishLevel.NONE)
  10529.         {
  10530.             // If punish timer exists, restart punishtask.
  10531.             if (_punishTimer > 0)
  10532.             {
  10533.                 _punishTask = ThreadPoolManager.getInstance().scheduleGeneral(new PunishTask(), _punishTimer);
  10534.                 sendMessage("You are still " + getPunishLevel().string() + " for " + Math.round(_punishTimer / 60000f)
  10535.                         + " minutes.");
  10536.             }
  10537.             if (getPunishLevel() == PunishLevel.JAIL)
  10538.             {
  10539.                 // If player escaped, put him back in jail
  10540.                 if (!isInsideZone(ZONE_JAIL))
  10541.                     teleToLocation(-114356, -249645, -2984, 20);
  10542.             }
  10543.         }
  10544.     }
  10545.    
  10546.     public void stopPunishTask(boolean save)
  10547.     {
  10548.         if (_punishTask != null)
  10549.         {
  10550.             if (save)
  10551.             {
  10552.                 long delay = _punishTask.getDelay(TimeUnit.MILLISECONDS);
  10553.                 if (delay < 0)
  10554.                     delay = 0;
  10555.                 setPunishTimer(delay);
  10556.             }
  10557.             _punishTask.cancel(false);
  10558.             _punishTask = null;
  10559.         }
  10560.     }
  10561.    
  10562.     protected class PunishTask implements Runnable
  10563.     {
  10564.         @Override
  10565.         public void run()
  10566.         {
  10567.             L2PlayerInstance.this.setPunishLevel(PunishLevel.NONE, 0);
  10568.         }
  10569.     }
  10570.    
  10571.     public int getPowerGrade()
  10572.     {
  10573.         return _powerGrade;
  10574.     }
  10575.    
  10576.     public void setPowerGrade(int power)
  10577.     {
  10578.         _powerGrade = power;
  10579.     }
  10580.    
  10581.     public boolean isCursedWeaponEquipped()
  10582.     {
  10583.         return _cursedWeaponEquippedId != 0;
  10584.     }
  10585.    
  10586.     public void setCursedWeaponEquippedId(int value)
  10587.     {
  10588.         _cursedWeaponEquippedId = value;
  10589.     }
  10590.    
  10591.     public int getCursedWeaponEquippedId()
  10592.     {
  10593.         return _cursedWeaponEquippedId;
  10594.     }
  10595.    
  10596.     public void shortBuffStatusUpdate(int magicId, int level, int time)
  10597.     {
  10598.         if (_shortBuffTask != null)
  10599.         {
  10600.             _shortBuffTask.cancel(false);
  10601.             _shortBuffTask = null;
  10602.         }
  10603.         _shortBuffTask = ThreadPoolManager.getInstance().scheduleGeneral(new ShortBuffTask(), time * 1000);
  10604.         setShortBuffTaskSkillId(magicId);
  10605.        
  10606.         sendPacket(new ShortBuffStatusUpdate(magicId, level, time));
  10607.     }
  10608.    
  10609.     public void setShortBuffTaskSkillId(int id)
  10610.     {
  10611.         _shortBuffTaskSkillId = id;
  10612.     }
  10613.    
  10614.     public int getDeathPenaltyBuffLevel()
  10615.     {
  10616.         return _deathPenaltyBuffLevel;
  10617.     }
  10618.    
  10619.     public void setDeathPenaltyBuffLevel(int level)
  10620.     {
  10621.         _deathPenaltyBuffLevel = level;
  10622.     }
  10623.    
  10624.     public void calculateDeathPenaltyBuffLevel(L2Character killer)
  10625.     {
  10626.         if ((getKarma() > 0 || Rnd.get(1, 100) <= Config.DEATH_PENALTY_CHANCE) && !(killer instanceof L2PlayerInstance)
  10627.                 && !(isGM()) && !(getCharmOfLuck() && killer.isRaid()) && !isPhoenixBlessed()
  10628.                 && !(isInsideZone(L2Character.ZONE_PVP) || isInsideZone(L2Character.ZONE_SIEGE)))
  10629.            
  10630.             increaseDeathPenaltyBuffLevel();
  10631.     }
  10632.    
  10633.     public void increaseDeathPenaltyBuffLevel()
  10634.     {
  10635.         if (getDeathPenaltyBuffLevel() >= 15) // maximum level reached
  10636.             return;
  10637.        
  10638.         if (getDeathPenaltyBuffLevel() != 0)
  10639.         {
  10640.             L2Skill skill = SkillTable.getInstance().getInfo(5076, getDeathPenaltyBuffLevel());
  10641.            
  10642.             if (skill != null)
  10643.                 removeSkill(skill, true);
  10644.         }
  10645.        
  10646.         _deathPenaltyBuffLevel++;
  10647.        
  10648.         addSkill(SkillTable.getInstance().getInfo(5076, getDeathPenaltyBuffLevel()), false);
  10649.         sendPacket(new EtcStatusUpdate(this));
  10650.         sendPacket(SystemMessage.getSystemMessage(SystemMessageId.DEATH_PENALTY_LEVEL_S1_ADDED).addNumber(
  10651.                 getDeathPenaltyBuffLevel()));
  10652.     }
  10653.    
  10654.     public void reduceDeathPenaltyBuffLevel()
  10655.     {
  10656.         if (getDeathPenaltyBuffLevel() <= 0)
  10657.             return;
  10658.        
  10659.         L2Skill skill = SkillTable.getInstance().getInfo(5076, getDeathPenaltyBuffLevel());
  10660.        
  10661.         if (skill != null)
  10662.             removeSkill(skill, true);
  10663.        
  10664.         _deathPenaltyBuffLevel--;
  10665.        
  10666.         if (getDeathPenaltyBuffLevel() > 0)
  10667.         {
  10668.             addSkill(SkillTable.getInstance().getInfo(5076, getDeathPenaltyBuffLevel()), false);
  10669.             sendPacket(new EtcStatusUpdate(this));
  10670.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.DEATH_PENALTY_LEVEL_S1_ADDED).addNumber(
  10671.                     getDeathPenaltyBuffLevel()));
  10672.         }
  10673.         else
  10674.         {
  10675.             sendPacket(new EtcStatusUpdate(this));
  10676.             sendPacket(SystemMessageId.DEATH_PENALTY_LIFTED);
  10677.         }
  10678.     }
  10679.    
  10680.     public void restoreDeathPenaltyBuffLevel()
  10681.     {
  10682.         if (getDeathPenaltyBuffLevel() > 0)
  10683.             addSkill(SkillTable.getInstance().getInfo(5076, getDeathPenaltyBuffLevel()), false);
  10684.     }
  10685.    
  10686.     private final Map<Integer, TimeStamp> _reuseTimeStamps = new FastMap<Integer, TimeStamp>().shared();
  10687.    
  10688.     public Collection<TimeStamp> getReuseTimeStamps()
  10689.     {
  10690.         return _reuseTimeStamps.values();
  10691.     }
  10692.    
  10693.     public Map<Integer, TimeStamp> getReuseTimeStamp()
  10694.     {
  10695.         return _reuseTimeStamps;
  10696.     }
  10697.    
  10698.     /**
  10699.      * Simple class containing all neccessary information to maintain valid timestamps and reuse for
  10700.      * skills upon relog. Filter this carefully as it becomes redundant to store reuse for small
  10701.      * delays.
  10702.      *
  10703.      * @author Yesod
  10704.      */
  10705.     public static class TimeStamp
  10706.     {
  10707.         private final int _skillId;
  10708.         private final int _skillLvl;
  10709.         private final long _reuse;
  10710.         private final long _stamp;
  10711.        
  10712.         public TimeStamp(L2Skill skill, long reuse)
  10713.         {
  10714.             _skillId = skill.getId();
  10715.             _skillLvl = skill.getLevel();
  10716.             _reuse = reuse;
  10717.             _stamp = System.currentTimeMillis() + reuse;
  10718.         }
  10719.        
  10720.         public TimeStamp(L2Skill skill, long reuse, long systime)
  10721.         {
  10722.             _skillId = skill.getId();
  10723.             _skillLvl = skill.getLevel();
  10724.             _reuse = reuse;
  10725.             _stamp = systime;
  10726.         }
  10727.        
  10728.         public long getStamp()
  10729.         {
  10730.             return _stamp;
  10731.         }
  10732.        
  10733.         public int getSkillId()
  10734.         {
  10735.             return _skillId;
  10736.         }
  10737.        
  10738.         public int getSkillLvl()
  10739.         {
  10740.             return _skillLvl;
  10741.         }
  10742.        
  10743.         public long getReuse()
  10744.         {
  10745.             return _reuse;
  10746.         }
  10747.        
  10748.         public long getRemaining()
  10749.         {
  10750.             return Math.max(_stamp - System.currentTimeMillis(), 0);
  10751.         }
  10752.        
  10753.         /*
  10754.          * Check if the reuse delay has passed and if it has not then update the stored reuse time according to what is currently remaining on the delay.
  10755.          */
  10756.         public boolean hasNotPassed()
  10757.         {
  10758.             return System.currentTimeMillis() < _stamp;
  10759.         }
  10760.     }
  10761.    
  10762.     /**
  10763.      * Index according to skill id the current timestamp of use.
  10764.      *
  10765.      * @param skill
  10766.      * @param reuse delay
  10767.      */
  10768.     @Override
  10769.     public void addTimeStamp(L2Skill skill, long reuse)
  10770.     {
  10771.         _reuseTimeStamps.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse));
  10772.     }
  10773.    
  10774.     /**
  10775.      * Index according to skill this TimeStamp instance for restoration purposes only.
  10776.      *
  10777.      * @param skill
  10778.      * @param reuse
  10779.      * @param systime
  10780.      */
  10781.     public void addTimeStamp(L2Skill skill, long reuse, long systime)
  10782.     {
  10783.         _reuseTimeStamps.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse, systime));
  10784.     }
  10785.    
  10786.     @Override
  10787.     public L2PlayerInstance getActingPlayer()
  10788.     {
  10789.         return this;
  10790.     }
  10791.    
  10792.     @Override
  10793.     public final void sendDamageMessage(L2Character target, int damage, boolean mcrit, boolean pcrit, boolean miss)
  10794.     {
  10795.         // Check if hit is missed
  10796.         if (miss)
  10797.         {
  10798.             sendPacket(SystemMessageId.MISSED_TARGET);
  10799.             return;
  10800.         }
  10801.        
  10802.         // Check if hit is critical
  10803.         if (pcrit)
  10804.             sendPacket(SystemMessageId.CRITICAL_HIT);
  10805.         if (mcrit)
  10806.             sendPacket(SystemMessageId.CRITICAL_HIT_MAGIC);
  10807.        
  10808.         if (target.isInvul())
  10809.         {
  10810.             if (target.isParalyzed())
  10811.                 sendPacket(SystemMessageId.OPPONENT_PETRIFIED);
  10812.             else
  10813.                 sendPacket(SystemMessageId.ATTACK_WAS_BLOCKED);
  10814.         }
  10815.         else
  10816.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_DID_S1_DMG).addNumber(damage));
  10817.        
  10818.         if (isInOlympiadMode() && target instanceof L2PlayerInstance && ((L2PlayerInstance)target).isInOlympiadMode()
  10819.                 && ((L2PlayerInstance)target).getOlympiadGameId() == getOlympiadGameId())
  10820.             OlympiadGameManager.getInstance().notifyCompetitorDamage(this, damage);
  10821.     }
  10822.    
  10823.     public void checkItemRestriction()
  10824.     {
  10825.         for (int i = 0; i < Inventory.PAPERDOLL_TOTALSLOTS; i++)
  10826.         {
  10827.             L2ItemInstance equippedItem = getInventory().getPaperdollItem(i);
  10828.             if (equippedItem != null && !equippedItem.getItem().checkCondition(this, this, false))
  10829.             {
  10830.                 getInventory().unEquipItemInSlot(i);
  10831.                
  10832.                 InventoryUpdate iu = new InventoryUpdate();
  10833.                 iu.addModifiedItem(equippedItem);
  10834.                 sendPacket(iu);
  10835.                
  10836.                 SystemMessage sm = null;
  10837.                 if (equippedItem.getEnchantLevel() > 0)
  10838.                 {
  10839.                     sm = SystemMessage.getSystemMessage(SystemMessageId.EQUIPMENT_S1_S2_REMOVED);
  10840.                     sm.addNumber(equippedItem.getEnchantLevel());
  10841.                     sm.addItemName(equippedItem);
  10842.                 }
  10843.                 else
  10844.                 {
  10845.                     sm = SystemMessage.getSystemMessage(SystemMessageId.S1_DISARMED);
  10846.                     sm.addItemName(equippedItem);
  10847.                 }
  10848.                 sendPacket(sm);
  10849.             }
  10850.         }
  10851.     }
  10852.    
  10853.     protected class Dismount implements Runnable
  10854.     {
  10855.         @Override
  10856.         public void run()
  10857.         {
  10858.             try
  10859.             {
  10860.                 dismount();
  10861.             }
  10862.             catch (Exception e)
  10863.             {
  10864.                 _log.log(Level.WARNING, "Exception on dismount(): " + e.getMessage(), e);
  10865.             }
  10866.         }
  10867.     }
  10868.    
  10869.     public void enteredNoLanding(int delay)
  10870.     {
  10871.         _dismountTask = ThreadPoolManager.getInstance().scheduleGeneral(new L2PlayerInstance.Dismount(), delay * 1000);
  10872.     }
  10873.    
  10874.     public void exitedNoLanding()
  10875.     {
  10876.         if (_dismountTask != null)
  10877.         {
  10878.             _dismountTask.cancel(true);
  10879.             _dismountTask = null;
  10880.         }
  10881.     }
  10882.    
  10883.     public void setIsInSiege(boolean b)
  10884.     {
  10885.         _isInSiege = b;
  10886.     }
  10887.    
  10888.     public boolean isInSiege()
  10889.     {
  10890.         return _isInSiege;
  10891.     }
  10892.    
  10893.     public FloodProtectors getFloodProtectors()
  10894.     {
  10895.         return getClient().getFloodProtectors();
  10896.     }
  10897.    
  10898.     /**
  10899.      * Remove player from BossZones (used on char logout/exit)
  10900.      */
  10901.     public void removeFromBossZone()
  10902.     {
  10903.         try
  10904.         {
  10905.             for (L2BossZone _zone : GrandBossManager.getInstance().getZones())
  10906.                 _zone.removePlayer(this);
  10907.         }
  10908.         catch (Exception e)
  10909.         {
  10910.             _log.log(Level.WARNING, "Exception on removeFromBossZone(): " + e.getMessage(), e);
  10911.         }
  10912.     }
  10913.    
  10914.     /**
  10915.      * Returns the Number of Charges this L2PlayerInstance got.
  10916.      *
  10917.      * @return
  10918.      */
  10919.     public int getCharges()
  10920.     {
  10921.         return _charges.get();
  10922.     }
  10923.    
  10924.     public synchronized void increaseCharges(int count, int max)
  10925.     {
  10926.         if (_charges.get() >= max)
  10927.         {
  10928.             sendPacket(SystemMessageId.FORCE_MAXLEVEL_REACHED);
  10929.             return;
  10930.         }
  10931.        
  10932.         // if no charges - start clear task
  10933.         if (_charges.get() == 0)
  10934.             restartChargeTask();
  10935.        
  10936.         if (_charges.addAndGet(count) >= max)
  10937.         {
  10938.             _charges.set(max);
  10939.             sendPacket(SystemMessageId.FORCE_MAXLEVEL_REACHED);
  10940.         }
  10941.         else
  10942.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FORCE_INCREASED_TO_S1).addNumber(_charges.get()));
  10943.        
  10944.         sendPacket(new EtcStatusUpdate(this));
  10945.     }
  10946.    
  10947.     public synchronized boolean decreaseCharges(int count)
  10948.     {
  10949.         if (_charges.get() < count)
  10950.             return false;
  10951.        
  10952.         if (_charges.addAndGet(-count) == 0)
  10953.             stopChargeTask();
  10954.        
  10955.         sendPacket(new EtcStatusUpdate(this));
  10956.         return true;
  10957.     }
  10958.    
  10959.     public void clearCharges()
  10960.     {
  10961.         _charges.set(0);
  10962.         sendPacket(new EtcStatusUpdate(this));
  10963.     }
  10964.    
  10965.     /**
  10966.      * Starts/Restarts the ChargeTask to Clear Charges after 10 Mins.
  10967.      */
  10968.     private void restartChargeTask()
  10969.     {
  10970.         if (_chargeTask != null)
  10971.         {
  10972.             _chargeTask.cancel(false);
  10973.             _chargeTask = null;
  10974.         }
  10975.         _chargeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChargeTask(), 600000);
  10976.     }
  10977.    
  10978.     /**
  10979.      * Stops the Charges Clearing Task.
  10980.      */
  10981.     public void stopChargeTask()
  10982.     {
  10983.         if (_chargeTask != null)
  10984.         {
  10985.             _chargeTask.cancel(false);
  10986.             _chargeTask = null;
  10987.         }
  10988.     }
  10989.    
  10990.     protected class ChargeTask implements Runnable
  10991.     {
  10992.         @Override
  10993.         public void run()
  10994.         {
  10995.             clearCharges();
  10996.         }
  10997.     }
  10998.    
  10999.     /**
  11000.      * Signets check used to valid who is affected when he entered in the aoe effect.
  11001.      *
  11002.      * @param cha The target to make checks on.
  11003.      * @return true if player can attack the target.
  11004.      */
  11005.     public boolean canAttackCharacter(L2Character cha)
  11006.     {
  11007.         if (cha instanceof L2Attackable)
  11008.             return true;
  11009.         else if (cha instanceof L2Playable)
  11010.         {
  11011.             if (cha.isInsideZone(L2Character.ZONE_PVP) && !cha.isInsideZone(L2Character.ZONE_SIEGE))
  11012.                 return true;
  11013.            
  11014.             L2PlayerInstance target;
  11015.             if (cha instanceof L2Summon)
  11016.                 target = ((L2Summon)cha).getOwner();
  11017.             else
  11018.                 target = (L2PlayerInstance)cha;
  11019.            
  11020.             if (isInDuel() && target.isInDuel() && (target.getDuelId() == getDuelId()))
  11021.                 return true;
  11022.             else if (isInParty() && target.isInParty())
  11023.             {
  11024.                 if (getParty() == target.getParty())
  11025.                     return false;
  11026.                
  11027.                 if ((getParty().getCommandChannel() != null || target.getParty().getCommandChannel() != null)
  11028.                         && (getParty().getCommandChannel() == target.getParty().getCommandChannel()))
  11029.                     return false;
  11030.             }
  11031.             else if (getClan() != null && target.getClan() != null)
  11032.             {
  11033.                 if (getClanId() == target.getClanId())
  11034.                     return false;
  11035.                
  11036.                 if ((getAllyId() > 0 || target.getAllyId() > 0) && (getAllyId() == target.getAllyId()))
  11037.                     return false;
  11038.                
  11039.                 if (getClan().isAtWarWith(target.getClan().getClanId())
  11040.                         && target.getClan().isAtWarWith(getClan().getClanId()))
  11041.                     return true;
  11042.             }
  11043.             else if (getClan() == null || target.getClan() == null)
  11044.             {
  11045.                 if (target.getPvpFlag() == 0 && target.getKarma() == 0)
  11046.                     return false;
  11047.             }
  11048.         }
  11049.         return true;
  11050.     }
  11051.    
  11052.     /**
  11053.      * Request Teleport
  11054.      *
  11055.      * @param requester The player who requested the teleport.
  11056.      * @param skill The used skill.
  11057.      * @return true if successful.
  11058.      **/
  11059.     public boolean teleportRequest(L2PlayerInstance requester, L2Skill skill)
  11060.     {
  11061.         if (_summonRequest.getTarget() != null && requester != null)
  11062.             return false;
  11063.        
  11064.         _summonRequest.setTarget(requester, skill);
  11065.         return true;
  11066.     }
  11067.    
  11068.     /**
  11069.      * Action teleport
  11070.      *
  11071.      * @param answer
  11072.      * @param requesterId
  11073.      **/
  11074.     public void teleportAnswer(int answer, int requesterId)
  11075.     {
  11076.         if (_summonRequest.getTarget() == null)
  11077.             return;
  11078.        
  11079.         if (answer == 1 && _summonRequest.getTarget().getObjectId() == requesterId)
  11080.             teleToTarget(this, _summonRequest.getTarget(), _summonRequest.getSkill());
  11081.        
  11082.         _summonRequest.setTarget(null, null);
  11083.     }
  11084.    
  11085.     public static void teleToTarget(L2PlayerInstance targetChar, L2PlayerInstance summonerChar, L2Skill summonSkill)
  11086.     {
  11087.         if (targetChar == null || summonerChar == null || summonSkill == null)
  11088.             return;
  11089.        
  11090.         if (!checkSummonerStatus(summonerChar))
  11091.             return;
  11092.         if (!checkSummonTargetStatus(targetChar, summonerChar))
  11093.             return;
  11094.        
  11095.         int itemConsumeId = summonSkill.getTargetConsumeId();
  11096.         int itemConsumeCount = summonSkill.getTargetConsume();
  11097.         if (itemConsumeId != 0 && itemConsumeCount != 0)
  11098.         {
  11099.             // Delete by rocknow
  11100.             if (targetChar.getInventory().getInventoryItemCount(itemConsumeId, 0) < itemConsumeCount)
  11101.             {
  11102.                 targetChar.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_REQUIRED_FOR_SUMMONING)
  11103.                         .addItemName(summonSkill.getTargetConsumeId()));
  11104.                 return;
  11105.             }
  11106.             targetChar.getInventory().destroyItemByItemId("Consume", itemConsumeId, itemConsumeCount, summonerChar,
  11107.                     targetChar);
  11108.             targetChar.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_DISAPPEARED).addItemName(
  11109.                     summonSkill.getTargetConsumeId()));
  11110.         }
  11111.         targetChar.teleToLocation(summonerChar.getX(), summonerChar.getY(), summonerChar.getZ(), 20);
  11112.     }
  11113.    
  11114.     public static boolean checkSummonerStatus(L2PlayerInstance summonerChar)
  11115.     {
  11116.         if (summonerChar == null)
  11117.             return false;
  11118.        
  11119.         if (summonerChar.isInOlympiadMode() || summonerChar.inObserverMode()
  11120.                 || summonerChar.isInsideZone(L2Character.ZONE_NOSUMMONFRIEND) || summonerChar.isMounted())
  11121.             return false;
  11122.        
  11123.         return true;
  11124.     }
  11125.    
  11126.     public static boolean checkSummonTargetStatus(L2Object target, L2PlayerInstance summonerChar)
  11127.     {
  11128.         if (target == null || !(target instanceof L2PlayerInstance))
  11129.             return false;
  11130.        
  11131.         L2PlayerInstance targetChar = (L2PlayerInstance)target;
  11132.        
  11133.         if (targetChar.isAlikeDead())
  11134.         {
  11135.             summonerChar.sendPacket(SystemMessage.getSystemMessage(
  11136.                     SystemMessageId.S1_IS_DEAD_AT_THE_MOMENT_AND_CANNOT_BE_SUMMONED).addPcName(targetChar));
  11137.             return false;
  11138.         }
  11139.        
  11140.         if (targetChar.isInStoreMode())
  11141.         {
  11142.             summonerChar.sendPacket(SystemMessage.getSystemMessage(
  11143.                     SystemMessageId.S1_CURRENTLY_TRADING_OR_OPERATING_PRIVATE_STORE_AND_CANNOT_BE_SUMMONED).addPcName(
  11144.                     targetChar));
  11145.             return false;
  11146.         }
  11147.        
  11148.         if (targetChar.isRooted() || targetChar.isInCombat())
  11149.         {
  11150.             summonerChar.sendPacket(SystemMessage.getSystemMessage(
  11151.                     SystemMessageId.S1_IS_ENGAGED_IN_COMBAT_AND_CANNOT_BE_SUMMONED).addPcName(targetChar));
  11152.             return false;
  11153.         }
  11154.        
  11155.         if (targetChar.isInOlympiadMode())
  11156.         {
  11157.             summonerChar.sendPacket(SystemMessageId.YOU_CANNOT_SUMMON_PLAYERS_WHO_ARE_IN_OLYMPIAD);
  11158.             return false;
  11159.         }
  11160.        
  11161.         if (targetChar.isFestivalParticipant() || targetChar.isMounted())
  11162.         {
  11163.             summonerChar.sendPacket(SystemMessageId.YOUR_TARGET_IS_IN_AN_AREA_WHICH_BLOCKS_SUMMONING);
  11164.             return false;
  11165.         }
  11166.        
  11167.         if (targetChar.inObserverMode() || targetChar.isInsideZone(L2Character.ZONE_NOSUMMONFRIEND))
  11168.         {
  11169.             summonerChar.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_IN_SUMMON_BLOCKING_AREA)
  11170.                     .addCharName(targetChar));
  11171.             return false;
  11172.         }
  11173.        
  11174.         return true;
  11175.     }
  11176.    
  11177.     public final int getClientX()
  11178.     {
  11179.         return _clientX;
  11180.     }
  11181.    
  11182.     public final int getClientY()
  11183.     {
  11184.         return _clientY;
  11185.     }
  11186.    
  11187.     public final int getClientZ()
  11188.     {
  11189.         return _clientZ;
  11190.     }
  11191.    
  11192.     public final int getClientHeading()
  11193.     {
  11194.         return _clientHeading;
  11195.     }
  11196.    
  11197.     public final void setClientX(int val)
  11198.     {
  11199.         _clientX = val;
  11200.     }
  11201.    
  11202.     public final void setClientY(int val)
  11203.     {
  11204.         _clientY = val;
  11205.     }
  11206.    
  11207.     public final void setClientZ(int val)
  11208.     {
  11209.         _clientZ = val;
  11210.     }
  11211.    
  11212.     public final void setClientHeading(int val)
  11213.     {
  11214.         _clientHeading = val;
  11215.     }
  11216.    
  11217.     /**
  11218.      * @return the mailPosition.
  11219.      */
  11220.     public int getMailPosition()
  11221.     {
  11222.         return _mailPosition;
  11223.     }
  11224.    
  11225.     /**
  11226.      * @param mailPosition The mailPosition to set.
  11227.      */
  11228.     public void setMailPosition(int mailPosition)
  11229.     {
  11230.         _mailPosition = mailPosition;
  11231.     }
  11232.    
  11233.     /**
  11234.      * @param z
  11235.      * @return true if character falling now On the start of fall return false for correct coord
  11236.      *         sync !
  11237.      */
  11238.     public final boolean isFalling(int z)
  11239.     {
  11240.         if (isDead() || isFlying() || isInsideZone(ZONE_WATER))
  11241.             return false;
  11242.        
  11243.         if (System.currentTimeMillis() < _fallingTimestamp)
  11244.             return true;
  11245.        
  11246.         final int deltaZ = getZ() - z;
  11247.         if (deltaZ <= getBaseTemplate().getFallHeight())
  11248.             return false;
  11249.        
  11250.         final int damage = (int)Formulas.calcFallDam(this, deltaZ);
  11251.         if (damage > 0)
  11252.         {
  11253.             reduceCurrentHp(Math.min(damage, getCurrentHp() - 1), null, false, true, null);
  11254.             sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FALL_DAMAGE_S1).addNumber(damage));
  11255.         }
  11256.        
  11257.         setFalling();
  11258.        
  11259.         return false;
  11260.     }
  11261.    
  11262.     /**
  11263.      * Set falling timestamp
  11264.      */
  11265.     public final void setFalling()
  11266.     {
  11267.         _fallingTimestamp = System.currentTimeMillis() + FALLING_VALIDATION_DELAY;
  11268.     }
  11269.    
  11270.     public boolean isAllowedToEnchantSkills()
  11271.     {
  11272.         if (isLocked())
  11273.             return false;
  11274.        
  11275.         if (AttackStanceTaskManager.getInstance().getAttackStanceTask(this))
  11276.             return false;
  11277.        
  11278.         if (isCastingNow() || isCastingSimultaneouslyNow())
  11279.             return false;
  11280.        
  11281.         if (isInBoat())
  11282.             return false;
  11283.        
  11284.         return true;
  11285.     }
  11286.    
  11287.     /**
  11288.      * Friendlist / selected Friendlist (for community board)
  11289.      */
  11290.     private final List<Integer> _friendList = new ArrayList<>();
  11291.     private final List<Integer> _selectedFriendList = new ArrayList<>();
  11292.    
  11293.     public List<Integer> getFriendList()
  11294.     {
  11295.         return _friendList;
  11296.     }
  11297.    
  11298.     public void selectFriend(Integer friendId)
  11299.     {
  11300.         _selectedFriendList.add(friendId);
  11301.     }
  11302.    
  11303.     public void deselectFriend(Integer friendId)
  11304.     {
  11305.         _selectedFriendList.remove(friendId);
  11306.     }
  11307.    
  11308.     public List<Integer> getSelectedFriendList()
  11309.     {
  11310.         return _selectedFriendList;
  11311.     }
  11312.    
  11313.     private void restoreFriendList()
  11314.     {
  11315.         _friendList.clear();
  11316.        
  11317.         try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  11318.         {
  11319.             PreparedStatement statement =
  11320.                     con.prepareStatement("SELECT friend_id FROM character_friends WHERE char_id = ? AND relation = 0");
  11321.             statement.setInt(1, getObjectId());
  11322.             ResultSet rset = statement.executeQuery();
  11323.            
  11324.             int friendId;
  11325.             while (rset.next())
  11326.             {
  11327.                 friendId = rset.getInt("friend_id");
  11328.                 if (friendId == getObjectId())
  11329.                     continue;
  11330.                
  11331.                 _friendList.add(friendId);
  11332.             }
  11333.            
  11334.             rset.close();
  11335.             statement.close();
  11336.         }
  11337.         catch (Exception e)
  11338.         {
  11339.             _log.log(Level.WARNING, "Error found in " + getName() + "'s friendlist: " + e.getMessage(), e);
  11340.         }
  11341.     }
  11342.    
  11343.     public InetAddress getIpAddress()
  11344.     {
  11345.         return getClient().getConnection().getInetAddress();
  11346.     }
  11347.    
  11348.     private void notifyFriends(boolean login)
  11349.     {
  11350.         for (int id : _friendList)
  11351.         {
  11352.             L2PlayerInstance friend = L2World.getInstance().getPlayer(id);
  11353.             if (friend != null)
  11354.             {
  11355.                 friend.sendPacket(new FriendList(friend));
  11356.                
  11357.                 if (login)
  11358.                     friend.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FRIEND_S1_HAS_LOGGED_IN)
  11359.                             .addPcName(this));
  11360.             }
  11361.         }
  11362.     }
  11363.    
  11364.     /**
  11365.      * Test if player inventory is under 80% capaity
  11366.      *
  11367.      * @param includeQuestInv check also quest inventory
  11368.      * @return
  11369.      */
  11370.     public boolean isInventoryUnder80(boolean includeQuestInv)
  11371.     {
  11372.         if (getInventory().getSize(false) <= (getInventoryLimit() * 0.8))
  11373.         {
  11374.             if (includeQuestInv)
  11375.             {
  11376.                 if (getInventory().getSize(true) <= (getQuestInventoryLimit() * 0.8))
  11377.                     return true;
  11378.             }
  11379.             else
  11380.                 return true;
  11381.         }
  11382.         return false;
  11383.     }
  11384.    
  11385.     @Override
  11386.     public void broadcastRelationsChanges()
  11387.     {
  11388.         for (L2PlayerInstance player : getKnownList().getKnownPlayers())
  11389.         {
  11390.             player.sendPacket(new RelationChanged(this, getRelation(player), isAutoAttackable(player)));
  11391.             if (getPet() != null)
  11392.                 player.sendPacket(new RelationChanged(getPet(), getRelation(player), isAutoAttackable(player)));
  11393.         }
  11394.     }
  11395.    
  11396.     @Override
  11397.     public void sendInfo(L2PlayerInstance activeChar)
  11398.     {
  11399.         if (isInBoat())
  11400.             getPosition().setWorldPosition(getBoat().getPosition().getWorldPosition());
  11401.        
  11402.         if (getPoly().isMorphed())
  11403.             activeChar.sendPacket(new AbstractNpcInfo.PcMorphInfo(this, getPoly().getNpcTemplate()));
  11404.         else
  11405.             activeChar.sendPacket(new CharInfo(this));
  11406.        
  11407.         int relation1 = getRelation(activeChar);
  11408.         int relation2 = activeChar.getRelation(this);
  11409.        
  11410.         Integer oldrelation = getKnownList().getKnownRelationsMap().get(activeChar.getObjectId());
  11411.         if (oldrelation != null && oldrelation != relation1)
  11412.         {
  11413.             activeChar.sendPacket(new RelationChanged(this, relation1, isAutoAttackable(activeChar)));
  11414.             if (getPet() != null)
  11415.                 activeChar.sendPacket(new RelationChanged(getPet(), relation1, isAutoAttackable(activeChar)));
  11416.         }
  11417.        
  11418.         oldrelation = activeChar.getKnownList().getKnownRelationsMap().get(getObjectId());
  11419.         if (oldrelation != null && oldrelation != relation2)
  11420.         {
  11421.             sendPacket(new RelationChanged(activeChar, relation2, activeChar.isAutoAttackable(this)));
  11422.             if (activeChar.getPet() != null)
  11423.                 sendPacket(new RelationChanged(activeChar.getPet(), relation2, activeChar.isAutoAttackable(this)));
  11424.         }
  11425.        
  11426.         if (isInBoat())
  11427.             activeChar.sendPacket(new GetOnVehicle(getObjectId(), getBoat().getObjectId(), getInVehiclePosition()));
  11428.        
  11429.         // No reason to try to broadcast shop message if player isn't in store mode
  11430.         if (getPrivateStoreType() != STORE_PRIVATE_NONE)
  11431.         {
  11432.             switch (getPrivateStoreType())
  11433.             {
  11434.                 case L2PlayerInstance.STORE_PRIVATE_SELL:
  11435.                 case L2PlayerInstance.STORE_PRIVATE_PACKAGE_SELL:
  11436.                     activeChar.sendPacket(new PrivateStoreMsgSell(this));
  11437.                     break;
  11438.                 case L2PlayerInstance.STORE_PRIVATE_BUY:
  11439.                     activeChar.sendPacket(new PrivateStoreMsgBuy(this));
  11440.                     break;
  11441.                 case L2PlayerInstance.STORE_PRIVATE_MANUFACTURE:
  11442.                     activeChar.sendPacket(new RecipeShopMsg(this));
  11443.                     break;
  11444.             }
  11445.         }
  11446.     }
  11447. }
Advertisement
Add Comment
Please, Sign In to add comment