Advertisement
Guest User

L2PcInstance.java

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