· 6 years ago · Dec 08, 2019, 01:58 PM
1package l2f.gameserver.model;
2
3import static l2f.gameserver.network.serverpackets.ExSetCompassZoneCode.ZONE_ALTERED_FLAG;
4import static l2f.gameserver.network.serverpackets.ExSetCompassZoneCode.ZONE_PEACE_FLAG;
5import static l2f.gameserver.network.serverpackets.ExSetCompassZoneCode.ZONE_PVP_FLAG;
6import static l2f.gameserver.network.serverpackets.ExSetCompassZoneCode.ZONE_SIEGE_FLAG;
7import static l2f.gameserver.network.serverpackets.ExSetCompassZoneCode.ZONE_SSQ_FLAG;
8
9import java.awt.Color;
10import java.sql.Connection;
11import java.sql.PreparedStatement;
12import java.sql.ResultSet;
13import java.sql.SQLException;
14import java.sql.Statement;
15import java.util.ArrayList;
16import java.util.Arrays;
17import java.util.Calendar;
18import java.util.Collection;
19import java.util.Collections;
20import java.util.HashMap;
21import java.util.Iterator;
22import java.util.List;
23import java.util.Map;
24import java.util.Map.Entry;
25import java.util.Set;
26import java.util.TreeMap;
27import java.util.concurrent.ConcurrentHashMap;
28import java.util.concurrent.ConcurrentSkipListMap;
29import java.util.concurrent.CopyOnWriteArrayList;
30import java.util.concurrent.CopyOnWriteArraySet;
31import java.util.concurrent.Future;
32import java.util.concurrent.ScheduledFuture;
33import java.util.concurrent.TimeUnit;
34import java.util.concurrent.atomic.AtomicBoolean;
35import java.util.concurrent.atomic.AtomicInteger;
36import java.util.concurrent.locks.Lock;
37import java.util.concurrent.locks.ReentrantLock;
38
39import org.apache.commons.lang3.ArrayUtils;
40import org.apache.commons.lang3.tuple.ImmutablePair;
41import org.apache.commons.lang3.tuple.Pair;
42import org.napile.primitive.Containers;
43import org.napile.primitive.maps.IntObjectMap;
44import org.napile.primitive.maps.impl.CHashIntObjectMap;
45import org.slf4j.Logger;
46import org.slf4j.LoggerFactory;
47
48import Elemental.datatables.OfflineBuffersTable;
49import Elemental.managers.GmEventManager;
50import Elemental.managers.OfflineBufferManager;
51import Elemental.pc.PcStats;
52import Elemental.templates.Ranking;
53import javolution.util.FastMap;
54import l2f.commons.dao.JdbcEntityState;
55import l2f.commons.dbutils.DbUtils;
56import l2f.commons.lang.reference.HardReference;
57import l2f.commons.lang.reference.HardReferences;
58import l2f.commons.threading.RunnableImpl;
59import l2f.commons.util.Rnd;
60import l2f.gameserver.Announcements;
61import l2f.gameserver.Config;
62import l2f.gameserver.GameTimeController;
63import l2f.gameserver.PartyMatchingBBSManager;
64import l2f.gameserver.ThreadPoolManager;
65import l2f.gameserver.ai.CtrlEvent;
66import l2f.gameserver.ai.CtrlIntention;
67import l2f.gameserver.ai.PlayableAI.nextAction;
68import l2f.gameserver.ai.PlayerAI;
69import l2f.gameserver.cache.Msg;
70import l2f.gameserver.dao.AccountReportDAO;
71import l2f.gameserver.dao.CharacterDAO;
72import l2f.gameserver.model.entity.SpreeHandler;
73import l2f.gameserver.dao.CharacterGroupReuseDAO;
74import l2f.gameserver.dao.CharacterPostFriendDAO;
75import l2f.gameserver.dao.EffectsDAO;
76import l2f.gameserver.data.xml.holder.CharTemplateHolder;
77import l2f.gameserver.data.xml.holder.EventHolder;
78import l2f.gameserver.data.xml.holder.HennaHolder;
79import l2f.gameserver.data.xml.holder.InstantZoneHolder;
80import l2f.gameserver.data.xml.holder.ItemHolder;
81import l2f.gameserver.data.xml.holder.MultiSellHolder.MultiSellListContainer;
82import l2f.gameserver.data.xml.holder.NpcHolder;
83import l2f.gameserver.data.xml.holder.RecipeHolder;
84import l2f.gameserver.data.xml.holder.ResidenceHolder;
85import l2f.gameserver.data.xml.holder.SkillAcquireHolder;
86import l2f.gameserver.database.DatabaseFactory;
87import l2f.gameserver.database.mysql;
88import l2f.gameserver.handler.bbs.CommunityBoardManager;
89import l2f.gameserver.handler.bbs.ICommunityBoardHandler;
90import l2f.gameserver.handler.items.IItemHandler;
91import l2f.gameserver.hwid.ClickersDetector;
92import l2f.gameserver.hwid.HwidGamer;
93import l2f.gameserver.idfactory.IdFactory;
94import l2f.gameserver.instancemanager.BypassManager;
95import l2f.gameserver.instancemanager.BypassManager.BypassType;
96import l2f.gameserver.instancemanager.BypassManager.DecodedBypass;
97import l2f.gameserver.instancemanager.CursedWeaponsManager;
98import l2f.gameserver.instancemanager.DimensionalRiftManager;
99import l2f.gameserver.instancemanager.MatchingRoomManager;
100import l2f.gameserver.instancemanager.QuestManager;
101import l2f.gameserver.instancemanager.ReflectionManager;
102import l2f.gameserver.instancemanager.games.HandysBlockCheckerManager;
103import l2f.gameserver.instancemanager.games.HandysBlockCheckerManager.ArenaParticipantsHolder;
104import l2f.gameserver.listener.actor.player.OnAnswerListener;
105import l2f.gameserver.listener.actor.player.impl.ReviveAnswerListener;
106import l2f.gameserver.listener.actor.player.impl.ScriptAnswerListener;
107import l2f.gameserver.listener.actor.player.impl.SummonAnswerListener;
108import l2f.gameserver.model.GameObjectTasks.EndSitDownTask;
109import l2f.gameserver.model.GameObjectTasks.EndStandUpTask;
110import l2f.gameserver.model.GameObjectTasks.HourlyTask;
111import l2f.gameserver.model.GameObjectTasks.KickTask;
112import l2f.gameserver.model.GameObjectTasks.PvPFlagTask;
113import l2f.gameserver.model.GameObjectTasks.RecomBonusTask;
114import l2f.gameserver.model.GameObjectTasks.UnJailTask;
115import l2f.gameserver.model.GameObjectTasks.WaterTask;
116import l2f.gameserver.model.Request.L2RequestType;
117import l2f.gameserver.model.Skill.AddedSkill;
118import l2f.gameserver.model.Zone.ZoneType;
119import l2f.gameserver.model.actor.instances.player.Bonus;
120import l2f.gameserver.model.actor.instances.player.BookMarkList;
121import l2f.gameserver.model.actor.instances.player.FriendList;
122import l2f.gameserver.model.actor.instances.player.Macro;
123import l2f.gameserver.model.actor.instances.player.MacroList;
124import l2f.gameserver.model.actor.instances.player.NevitSystem;
125import l2f.gameserver.model.actor.instances.player.RecomBonus;
126import l2f.gameserver.model.actor.instances.player.ShortCut;
127import l2f.gameserver.model.actor.instances.player.ShortCutList;
128import l2f.gameserver.model.actor.listener.PlayerListenerList;
129import l2f.gameserver.model.actor.recorder.PlayerStatsChangeRecorder;
130import l2f.gameserver.model.base.AcquireType;
131import l2f.gameserver.model.base.ClassId;
132import l2f.gameserver.model.base.Element;
133import l2f.gameserver.model.base.Experience;
134import l2f.gameserver.model.base.InvisibleType;
135import l2f.gameserver.model.base.PlayerAccess;
136import l2f.gameserver.model.base.Race;
137import l2f.gameserver.model.base.RestartType;
138import l2f.gameserver.model.base.TeamType;
139import l2f.gameserver.model.entity.DimensionalRift;
140import l2f.gameserver.model.entity.Hero;
141import l2f.gameserver.model.entity.Reflection;
142import l2f.gameserver.model.entity.CCPHelpers.itemLogs.ItemActionType;
143import l2f.gameserver.model.entity.CCPHelpers.itemLogs.ItemLogHandler;
144import l2f.gameserver.model.entity.SevenSignsFestival.DarknessFestival;
145import l2f.gameserver.model.entity.achievements.Achievement;
146import l2f.gameserver.model.entity.achievements.Achievements;
147import l2f.gameserver.model.entity.achievements.PlayerCounters;
148import l2f.gameserver.model.entity.auction.Auction;
149import l2f.gameserver.model.entity.auction.AuctionManager;
150import l2f.gameserver.model.entity.boat.Boat;
151import l2f.gameserver.model.entity.boat.ClanAirShip;
152import l2f.gameserver.model.entity.events.GameEvent;
153import l2f.gameserver.model.entity.events.GlobalEvent;
154import l2f.gameserver.model.entity.events.fightclubmanager.FightClubGameRoom;
155import l2f.gameserver.model.entity.events.impl.AbstractFightClub;
156import l2f.gameserver.model.entity.events.impl.CastleSiegeEvent;
157import l2f.gameserver.model.entity.events.impl.ClanHallSiegeEvent;
158import l2f.gameserver.model.entity.events.impl.DominionSiegeEvent;
159import l2f.gameserver.model.entity.events.impl.DuelEvent;
160import l2f.gameserver.model.entity.events.impl.FortressSiegeEvent;
161import l2f.gameserver.model.entity.events.impl.SiegeEvent;
162import l2f.gameserver.model.entity.olympiad.CompType;
163import l2f.gameserver.model.entity.olympiad.Olympiad;
164import l2f.gameserver.model.entity.olympiad.OlympiadGame;
165import l2f.gameserver.model.entity.residence.Castle;
166import l2f.gameserver.model.entity.residence.ClanHall;
167import l2f.gameserver.model.entity.residence.Fortress;
168import l2f.gameserver.model.entity.residence.Residence;
169import l2f.gameserver.model.instances.DecoyInstance;
170import l2f.gameserver.model.instances.FestivalMonsterInstance;
171import l2f.gameserver.model.instances.GuardInstance;
172import l2f.gameserver.model.instances.MonsterInstance;
173import l2f.gameserver.model.instances.NpcInstance;
174import l2f.gameserver.model.instances.PetBabyInstance;
175import l2f.gameserver.model.instances.PetInstance;
176import l2f.gameserver.model.instances.ReflectionBossInstance;
177import l2f.gameserver.model.instances.SchemeBufferInstance;
178import l2f.gameserver.model.instances.StaticObjectInstance;
179import l2f.gameserver.model.instances.TamedBeastInstance;
180import l2f.gameserver.model.instances.TrapInstance;
181import l2f.gameserver.model.items.Inventory;
182import l2f.gameserver.model.items.ItemContainer;
183import l2f.gameserver.model.items.ItemInstance;
184import l2f.gameserver.model.items.LockType;
185import l2f.gameserver.model.items.ManufactureItem;
186import l2f.gameserver.model.items.PcFreight;
187import l2f.gameserver.model.items.PcInventory;
188import l2f.gameserver.model.items.PcRefund;
189import l2f.gameserver.model.items.PcWarehouse;
190import l2f.gameserver.model.items.TradeItem;
191import l2f.gameserver.model.items.Warehouse;
192import l2f.gameserver.model.items.Warehouse.WarehouseType;
193import l2f.gameserver.model.items.attachment.FlagItemAttachment;
194import l2f.gameserver.model.items.attachment.PickableAttachment;
195import l2f.gameserver.model.matching.MatchingRoom;
196import l2f.gameserver.model.petition.PetitionMainGroup;
197import l2f.gameserver.model.pledge.Alliance;
198import l2f.gameserver.model.pledge.Clan;
199import l2f.gameserver.model.pledge.Privilege;
200import l2f.gameserver.model.pledge.RankPrivs;
201import l2f.gameserver.model.pledge.SubUnit;
202import l2f.gameserver.model.pledge.UnitMember;
203import l2f.gameserver.model.premium.PremiumEnd;
204import l2f.gameserver.model.premium.PremiumStart;
205import l2f.gameserver.model.quest.Quest;
206import l2f.gameserver.model.quest.QuestEventType;
207import l2f.gameserver.model.quest.QuestState;
208import l2f.gameserver.network.GameClient;
209import l2f.gameserver.network.loginservercon.AuthServerCommunication;
210import l2f.gameserver.network.loginservercon.gspackets.ChangeAccessLevel;
211import l2f.gameserver.network.serverpackets.AbnormalStatusUpdate;
212import l2f.gameserver.network.serverpackets.ActionFail;
213import l2f.gameserver.network.serverpackets.AutoAttackStart;
214import l2f.gameserver.network.serverpackets.CameraMode;
215import l2f.gameserver.network.serverpackets.ChairSit;
216import l2f.gameserver.network.serverpackets.ChangeWaitType;
217import l2f.gameserver.network.serverpackets.CharInfo;
218import l2f.gameserver.network.serverpackets.ConfirmDlg;
219import l2f.gameserver.network.serverpackets.CreatureSay;
220import l2f.gameserver.network.serverpackets.EtcStatusUpdate;
221import l2f.gameserver.network.serverpackets.ExAutoSoulShot;
222import l2f.gameserver.network.serverpackets.ExBR_AgathionEnergyInfo;
223import l2f.gameserver.network.serverpackets.ExBR_ExtraUserInfo;
224import l2f.gameserver.network.serverpackets.ExBasicActionList;
225import l2f.gameserver.network.serverpackets.ExDominionWarStart;
226import l2f.gameserver.network.serverpackets.ExDuelUpdateUserInfo;
227import l2f.gameserver.network.serverpackets.ExOlympiadMatchEnd;
228import l2f.gameserver.network.serverpackets.ExOlympiadMode;
229import l2f.gameserver.network.serverpackets.ExOlympiadSpelledInfo;
230import l2f.gameserver.network.serverpackets.ExPCCafePointInfo;
231import l2f.gameserver.network.serverpackets.ExQuestItemList;
232import l2f.gameserver.network.serverpackets.ExSetCompassZoneCode;
233import l2f.gameserver.network.serverpackets.ExStartScenePlayer;
234import l2f.gameserver.network.serverpackets.ExStorageMaxCount;
235import l2f.gameserver.network.serverpackets.ExVitalityPointInfo;
236import l2f.gameserver.network.serverpackets.ExVoteSystemInfo;
237import l2f.gameserver.network.serverpackets.GetItem;
238import l2f.gameserver.network.serverpackets.HennaInfo;
239import l2f.gameserver.network.serverpackets.InventoryUpdate;
240import l2f.gameserver.network.serverpackets.ItemList;
241import l2f.gameserver.network.serverpackets.L2GameServerPacket;
242import l2f.gameserver.network.serverpackets.LeaveWorld;
243import l2f.gameserver.network.serverpackets.MagicSkillLaunched;
244import l2f.gameserver.network.serverpackets.MagicSkillUse;
245import l2f.gameserver.network.serverpackets.MyTargetSelected;
246import l2f.gameserver.network.serverpackets.NpcInfoPoly;
247import l2f.gameserver.network.serverpackets.ObserverEnd;
248import l2f.gameserver.network.serverpackets.ObserverStart;
249import l2f.gameserver.network.serverpackets.PartySmallWindowUpdate;
250import l2f.gameserver.network.serverpackets.PartySpelled;
251import l2f.gameserver.network.serverpackets.PlaySound;
252import l2f.gameserver.network.serverpackets.PledgeShowMemberListDelete;
253import l2f.gameserver.network.serverpackets.PledgeShowMemberListDeleteAll;
254import l2f.gameserver.network.serverpackets.PledgeShowMemberListUpdate;
255import l2f.gameserver.network.serverpackets.PrivateStoreListBuy;
256import l2f.gameserver.network.serverpackets.PrivateStoreListSell;
257import l2f.gameserver.network.serverpackets.PrivateStoreMsgBuy;
258import l2f.gameserver.network.serverpackets.PrivateStoreMsgSell;
259import l2f.gameserver.network.serverpackets.QuestList;
260import l2f.gameserver.network.serverpackets.RadarControl;
261import l2f.gameserver.network.serverpackets.RecipeShopMsg;
262import l2f.gameserver.network.serverpackets.RecipeShopSellList;
263import l2f.gameserver.network.serverpackets.RelationChanged;
264import l2f.gameserver.network.serverpackets.Revive;
265import l2f.gameserver.handler.voicecommands.IVoicedCommandHandler;
266import l2f.gameserver.handler.voicecommands.VoicedCommandHandler;
267import l2f.gameserver.handler.voicecommands.impl.StreamPersonal;
268import l2f.gameserver.network.serverpackets.Ride;
269import l2f.gameserver.network.serverpackets.SendTradeDone;
270import l2f.gameserver.network.serverpackets.ServerClose;
271import l2f.gameserver.network.serverpackets.SetupGauge;
272import l2f.gameserver.network.serverpackets.ShortBuffStatusUpdate;
273import l2f.gameserver.network.serverpackets.ShortCutInit;
274import l2f.gameserver.network.serverpackets.ShortCutRegister;
275import l2f.gameserver.network.serverpackets.SkillCoolTime;
276import l2f.gameserver.network.serverpackets.SkillList;
277import l2f.gameserver.network.serverpackets.Snoop;
278import l2f.gameserver.network.serverpackets.SocialAction;
279import l2f.gameserver.network.serverpackets.SpawnEmitter;
280import l2f.gameserver.network.serverpackets.SpecialCamera;
281import l2f.gameserver.network.serverpackets.StatusUpdate;
282import l2f.gameserver.network.serverpackets.SystemMessage;
283import l2f.gameserver.network.serverpackets.SystemMessage2;
284import l2f.gameserver.network.serverpackets.TargetSelected;
285import l2f.gameserver.network.serverpackets.TargetUnselected;
286import l2f.gameserver.network.serverpackets.TeleportToLocation;
287import l2f.gameserver.network.serverpackets.UserInfo;
288import l2f.gameserver.network.serverpackets.ValidateLocation;
289import l2f.gameserver.network.serverpackets.components.CustomMessage;
290import l2f.gameserver.network.serverpackets.components.IStaticPacket;
291import l2f.gameserver.network.serverpackets.components.SceneMovie;
292import l2f.gameserver.network.serverpackets.components.SystemMsg;
293import l2f.gameserver.scripts.Events;
294import l2f.gameserver.skills.AbnormalEffect;
295import l2f.gameserver.skills.EffectType;
296import l2f.gameserver.skills.TimeStamp;
297import l2f.gameserver.skills.effects.EffectCubic;
298import l2f.gameserver.skills.effects.EffectTemplate;
299import l2f.gameserver.skills.skillclasses.Charge;
300import l2f.gameserver.skills.skillclasses.Transformation;
301import l2f.gameserver.stats.Formulas;
302import l2f.gameserver.stats.Stats;
303import l2f.gameserver.stats.funcs.FuncClassesBalancer;
304import l2f.gameserver.stats.funcs.FuncTemplate;
305import l2f.gameserver.tables.ClanTable;
306import l2f.gameserver.tables.PetDataTable;
307import l2f.gameserver.tables.SkillTable;
308import l2f.gameserver.tables.SkillTreeTable;
309import l2f.gameserver.taskmanager.AutoRechargeManager;
310import l2f.gameserver.taskmanager.AutoSaveManager;
311import l2f.gameserver.taskmanager.CancelTaskManager;
312import l2f.gameserver.taskmanager.LazyPrecisionTaskManager;
313import l2f.gameserver.templates.FishTemplate;
314import l2f.gameserver.templates.Henna;
315import l2f.gameserver.templates.InstantZone;
316import l2f.gameserver.templates.PlayerTemplate;
317import l2f.gameserver.templates.StatsSet;
318import l2f.gameserver.templates.item.ArmorTemplate;
319import l2f.gameserver.templates.item.ArmorTemplate.ArmorType;
320import l2f.gameserver.templates.item.ItemTemplate;
321import l2f.gameserver.templates.item.WeaponTemplate;
322import l2f.gameserver.templates.item.WeaponTemplate.WeaponType;
323import l2f.gameserver.templates.npc.NpcTemplate;
324import l2f.gameserver.utils.AntiFlood;
325import l2f.gameserver.utils.AutoHuntingPunish;
326import l2f.gameserver.utils.EffectsComparator;
327import l2f.gameserver.utils.FixEnchantOlympiad;
328import l2f.gameserver.utils.GArray;
329import l2f.gameserver.utils.GameStats;
330import l2f.gameserver.utils.ItemFunctions;
331import l2f.gameserver.utils.Language;
332import l2f.gameserver.utils.Location;
333import l2f.gameserver.utils.Log;
334import l2f.gameserver.utils.PositionUtils;
335import l2f.gameserver.utils.SiegeUtils;
336import l2f.gameserver.utils.SqlBatch;
337import l2f.gameserver.utils.Strings;
338import l2f.gameserver.utils.TeleportUtils;
339import l2f.gameserver.utils.Util;
340
341@SuppressWarnings("serial")
342public final class Player extends Playable implements PlayerGroup
343{
344 public static final int DEFAULT_TITLE_COLOR = 0xFFFF77;
345 public static final int MAX_POST_FRIEND_SIZE = 100;
346 public static final int MAX_FRIEND_SIZE = 128;
347
348 private static final Logger _log = LoggerFactory.getLogger(Player.class);
349
350 public static final String NO_TRADERS_VAR = "notraders";
351 public static final String NO_ANIMATION_OF_CAST_VAR = "notShowBuffAnim";
352 public static final String MY_BIRTHDAY_RECEIVE_YEAR = "MyBirthdayReceiveYear";
353 public static final String NOT_CONNECTED = "<not connected>";
354
355 public Map<Integer, SubClass> _classlist = new HashMap<Integer, SubClass>(4);
356
357 public final static int OBSERVER_NONE = 0;
358 public final static int OBSERVER_STARTING = 1;
359 public final static int OBSERVER_STARTED = 3;
360 public final static int OBSERVER_LEAVING = 2;
361
362 public static final int STORE_PRIVATE_NONE = 0;
363 public static final int STORE_PRIVATE_SELL = 1;
364 public static final int STORE_PRIVATE_BUY = 3;
365 public static final int STORE_PRIVATE_MANUFACTURE = 5;
366 public static final int STORE_OBSERVING_GAMES = 7;
367 public static final int STORE_PRIVATE_SELL_PACKAGE = 8;
368 public static final int STORE_PRIVATE_BUFF = 20;
369
370 public static final int RANK_VAGABOND = 0;
371 public static final int RANK_VASSAL = 1;
372 public static final int RANK_HEIR = 2;
373 public static final int RANK_KNIGHT = 3;
374 public static final int RANK_WISEMAN = 4;
375 public static final int RANK_BARON = 5;
376 public static final int RANK_VISCOUNT = 6;
377 public static final int RANK_COUNT = 7;
378 public static final int RANK_MARQUIS = 8;
379 public static final int RANK_DUKE = 9;
380 public static final int RANK_GRAND_DUKE = 10;
381 public static final int RANK_DISTINGUISHED_KING = 11;
382 public static final int RANK_EMPEROR = 12; // unused
383
384 public static final int LANG_ENG = 0;
385 public static final int LANG_RUS = 1;
386 public static final int LANG_UNK = -1;
387
388 public static final int[] EXPERTISE_LEVELS =
389 {
390 0,
391 20,
392 40,
393 52,
394 61,
395 76,
396 80,
397 84,
398 Integer.MAX_VALUE
399 };
400
401 private GameClient _connection;
402 private String _login;
403
404 private HwidGamer _gamer;
405 private String _hwidLock;
406
407 private int _karma, _pkKills, _pvpKills;
408 private int _face, _hairStyle, _hairColor;
409 private int _recomHave, _recomLeftToday, _fame;
410 private int _recomLeft = 20;
411 private int _recomBonusTime = 3600;
412 private boolean _isHourglassEffected, _isRecomTimerActive;
413 private boolean _isUndying = false;
414 private int _deleteTimer;
415
416 private NpcInstance lastAugmentNpc = null;
417
418 private ClickersDetector _detector;
419
420 private int _ping = -1;
421 private int spreeKills = 0;
422
423 private long _onlineBeginTime = System.currentTimeMillis();
424 private long _createTime,
425 _onlineTime,
426// _onlineBeginTime, Made the one above to calculate good.
427 _leaveClanTime,
428 _deleteClanTime,
429 _NoChannel,
430 _NoChannelBegin;
431
432 private long _uptime;
433 /**
434 * Time on login in game
435 */
436 private long _lastAccess;
437
438 /**
439 * The Color of players name / title (white is 0xFFFFFF)
440 */
441 private int _nameColor, _titlecolor;
442
443 private int _vitalityLevel = -1;
444 private double _vitality = Config.VITALITY_LEVELS[4];
445 private boolean _overloaded;
446
447 public boolean sittingTaskLaunched;
448
449 /**
450 * Time counter when L2Player is sitting
451 */
452 private int _waitTimeWhenSit;
453
454 private boolean _autoLoot = Config.AUTO_LOOT, AutoLootHerbs = Config.AUTO_LOOT_HERBS, AutoLootOnlyAdena = Config.AUTO_LOOT_ONLY_ADENA;
455
456 private final PcInventory _inventory = new PcInventory(this);
457 private final Warehouse _warehouse = new PcWarehouse(this);
458 private Warehouse _withdrawWarehouse = null; // Used for GMs withdrawing from CWH or other player warehouses
459 private final ItemContainer _refund = new PcRefund(this);
460 private final PcFreight _freight = new PcFreight(this);
461
462 public final BookMarkList bookmarks = new BookMarkList(this, 0);
463
464 public final AntiFlood antiFlood = new AntiFlood();
465
466 /**
467 * The table containing all l2fecipeList of the L2Player
468 */
469 private final Map<Integer, Recipe> _recipebook = new TreeMap<Integer, Recipe>();
470 private final Map<Integer, Recipe> _commonrecipebook = new TreeMap<Integer, Recipe>();
471
472 private final Map<String, Object> quickVars = new ConcurrentHashMap<>();
473 private final List<Integer> loadedImages = new ArrayList<>();
474
475 /**
476 * Premium Items
477 */
478 private final Map<Integer, PremiumItem> _premiumItems = new TreeMap<Integer, PremiumItem>();
479
480 /**
481 * The table containing all Quests began by the L2Player
482 */
483 private final Map<String, QuestState> _quests = new HashMap<String, QuestState>();
484
485 /**
486 * The list containing all shortCuts of this L2Player
487 */
488 private final ShortCutList _shortCuts = new ShortCutList(this);
489
490 /**
491 * The list containing all macroses of this L2Player
492 */
493 private final MacroList _macroses = new MacroList(this);
494
495 /**
496 * The Private Store type of the L2Player (STORE_PRIVATE_NONE=0, STORE_PRIVATE_SELL=1, sellmanage=2, STORE_PRIVATE_BUY=3, buymanage=4, STORE_PRIVATE_MANUFACTURE=5)
497 */
498 private int _privatestore;
499 private String _manufactureName;
500 private List<ManufactureItem> _createList = Collections.emptyList();
501 private String _sellStoreName;
502 private List<TradeItem> _sellList = Collections.emptyList();
503 private List<TradeItem> _packageSellList = Collections.emptyList();
504 private String _buyStoreName;
505 private List<TradeItem> _buyList = Collections.emptyList();
506 private List<TradeItem> _tradeList = Collections.emptyList();
507
508 /**
509 * hennas
510 */
511 private final Henna[] _henna = new Henna[3];
512 private int _hennaSTR, _hennaINT, _hennaDEX, _hennaMEN, _hennaWIT, _hennaCON;
513
514 private Party _party;
515 private Location _lastPartyPosition;
516
517 private Clan _clan;
518 private int _pledgeClass = 0, _pledgeType = Clan.SUBUNIT_NONE, _powerGrade = 0, _lvlJoinedAcademy = 0, _apprentice = 0;
519
520 /**
521 * GM Stuff
522 */
523 private int _accessLevel;
524 private PlayerAccess _playerAccess = new PlayerAccess();
525 public boolean _gmVisible = false;
526
527 private boolean _messageRefusal = false, _tradeRefusal = false, _partyinviteRefusal = false, _friendinviteRefusal = false, _blockAll = false;
528 private boolean _isPendingOlyEnd = false;
529
530 private Skill _macroSkill = null;
531
532 private boolean _isFakePlayer = false;
533 /**
534 * The L2Summon of the L2Player
535 */
536 private Summon _summon = null;
537 private boolean _riding;
538
539 private DecoyInstance _decoy = null;
540
541 private Map<Integer, EffectCubic> _cubics = null;
542 private int _agathionId = 0;
543
544 private Request _request;
545
546 private ItemInstance _arrowItem;
547
548 /**
549 * The fists L2Weapon of the L2Player (used when no weapon is equipped)
550 */
551 private WeaponTemplate _fistsWeaponItem;
552
553 private Map<Integer, String> _chars = new HashMap<Integer, String>(8);
554
555 /**
556 * The current higher Expertise of the L2Player (None=0, D=1, C=2, B=3, A=4, S=5, S80=6, S84=7)
557 */
558 public int expertiseIndex = 0;
559
560 private ItemInstance _enchantScroll = null;
561
562 private WarehouseType _usingWHType;
563
564 private boolean _isOnline = false;
565
566 private final AtomicBoolean _isLogout = new AtomicBoolean();
567
568 public boolean _autoMp;
569 public boolean _autoCp;
570 public boolean _autoHp;
571 public final static int autoMp = 728;
572 public final static int autoCp = 5592;
573 public final static int autoHp = 1539;
574
575 /**
576 * The L2NpcInstance corresponding to the last Folk which one the player talked.
577 */
578 private HardReference<NpcInstance> _lastNpc = HardReferences.emptyRef();
579 private MultiSellListContainer _multisell = null;
580
581 private final Set<Integer> _activeSoulShots = new CopyOnWriteArraySet<Integer>();
582
583 private WorldRegion _observerRegion;
584 private final AtomicInteger _observerMode = new AtomicInteger(0);
585
586 public int _telemode = 0;
587
588 private int _handysBlockCheckerEventArena = -1;
589
590 public boolean entering = true;
591
592 public Location _stablePoint = null;
593
594 /**
595 * new loto ticket *
596 */
597 public int _loto[] = new int[5];
598 /**
599 * new race ticket *
600 */
601 public int _race[] = new int[2];
602
603 private final Map<Integer, String> _blockList = new ConcurrentSkipListMap<Integer, String>(); // characters blocked with '/block <charname>' cmd
604 private final FriendList _friendList = new FriendList(this);
605
606 private boolean _hero = false;
607 private boolean _heroAura = false;
608
609 /**
610 * True if the L2Player is in a boat
611 */
612 private Boat _boat;
613 private Location _inBoatPosition;
614
615 protected int _baseClass = -1;
616 protected SubClass _activeClass = null;
617
618 private final Bonus _bonus = new Bonus();
619
620 private Future<?> _bonusExpiration;
621
622 private boolean _isSitting;
623 private StaticObjectInstance _sittingObject;
624
625 private boolean _noble = false;
626
627 private boolean _inOlympiadMode;
628 private boolean _isOlympiadCompStarted = false;
629 private OlympiadGame _olympiadGame;
630 private OlympiadGame _olympiadObserveGame;
631
632 private int _olympiadSide = -1;
633
634 /**
635 * ally with ketra or varka related wars
636 */
637 private int _varka = 0;
638 private int _ketra = 0;
639 private int _ram = 0;
640
641 private byte[] _keyBindings = ArrayUtils.EMPTY_BYTE_ARRAY;
642
643 private int _cursedWeaponEquippedId = 0;
644
645 private final Fishing _fishing = new Fishing(this);
646 private boolean _isFishing;
647
648 private Future<?> _taskWater;
649 private Future<?> _autoSaveTask;
650 private Future<?> _autoChargeTask;
651 private Future<?> _kickTask;
652
653 private Future<?> _vitalityTask;
654 private Future<?> _pcCafePointsTask;
655 private Future<?> _unjailTask;
656
657 private final Lock _storeLock = new ReentrantLock();
658
659 private int _zoneMask;
660
661 private boolean _offline = false;
662 private boolean _awaying = false;
663
664 private int _transformationId;
665 private int _transformationTemplate;
666 private String _transformationName;
667
668// private boolean _registeredInEvent;
669
670 private int _pcBangPoints;
671
672 Map<Integer, Skill> _transformationSkills = new HashMap<Integer, Skill>();
673
674 private int _expandInventory = 0;
675 private int _expandWarehouse = 0;
676 private int _battlefieldChatId;
677 private int _lectureMark;
678 private InvisibleType _invisibleType = InvisibleType.NONE;
679
680 private List<String> bypasses = null, bypasses_bbs = null;
681 private IntObjectMap<String> _postFriends = Containers.emptyIntObjectMap();
682
683 private final List<String> _blockedActions = new ArrayList<String>();
684
685 private boolean _notShowBuffAnim = false;
686 private boolean _notShowTraders = false;
687 private boolean _debug = false;
688
689 private final List<SchemeBufferInstance.PlayerScheme> buffSchemes;
690
691 private long _dropDisabled;
692 private long _lastItemAuctionInfoRequest;
693
694 private final IntObjectMap<TimeStamp> _sharedGroupReuses = new CHashIntObjectMap<TimeStamp>();
695 private Pair<Integer, OnAnswerListener> _askDialog = null;
696
697 // High Five: Navit's Bonus System
698 private final NevitSystem _nevitSystem = new NevitSystem(this);
699 private final StreamPersonal _streamPersonal = new StreamPersonal();
700
701 private MatchingRoom _matchingRoom;
702 private PetitionMainGroup _petitionGroup;
703 private final Map<Integer, Long> _instancesReuses = new ConcurrentHashMap<Integer, Long>();
704
705 public List<TeleportPoints> _teleportPoints = new ArrayList<TeleportPoints>();
706
707 public GameEvent _event = null;
708 private FightClubGameRoom _fightClubGameRoom = null;
709
710 // Ady
711 private long _resurrectionMaxTime = 0;
712 private long _resurrectionBuffBlockedTime = 0;
713
714 private long _petSummonBlockedTime = 0;
715
716 public boolean isFakePlayer()
717 {
718 return _isFakePlayer;
719 }
720
721 public void setPetSummonBlockedTime(long time)
722 {
723 this._petSummonBlockedTime = time;
724 }
725
726 public void setFakePlayer()
727 {
728 _isFakePlayer = true;
729 }
730
731 public Player(final int objectId, final PlayerTemplate template, final String accountName)
732 {
733 super(objectId, template);
734
735 _login = accountName;
736 _nameColor = 0xFFFFFF;
737 _titlecolor = 0xFFFF77;
738 _baseClass = getClassId().getId();
739 buffSchemes = new CopyOnWriteArrayList<>();
740
741 for (Stats st : Stats.values())
742 addStatFunc(FuncClassesBalancer.getInstance(st, this));
743
744 // Alexander - Create the statics holder for this pc
745 _stats = new PcStats(getObjectId());
746 }
747
748 /**
749 * Constructor<?> of L2Player (use L2Character constructor).<BR>
750 * <BR>
751 * <p/>
752 * <B><U> Actions</U> :</B><BR>
753 * <BR>
754 * <li>Call the L2Character constructor to create an empty _skills slot and copy basic Calculator set to this L2Player</li>
755 * <li>Create a l2fadar object</li>
756 * <li>Retrieve from the database all items of this L2Player and add them to _inventory</li>
757 * <p/>
758 * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SET the account name of the L2Player</B></FONT><BR>
759 * <BR>
760 * @param objectId Identifier of the object to initialized
761 * @param template The L2PlayerTemplate to apply to the L2Player
762 */
763 private Player(final int objectId, final PlayerTemplate template)
764 {
765 this(objectId, template, null);
766
767 _ai = new PlayerAI(this);
768
769 if (!Config.EVERYBODY_HAS_ADMIN_RIGHTS)
770 {
771 setPlayerAccess(Config.gmlist.get(objectId));
772 }
773 else
774 {
775 setPlayerAccess(Config.gmlist.get(0));
776 }
777 }
778
779 @SuppressWarnings("unchecked")
780 @Override
781 public HardReference<Player> getRef()
782 {
783 return (HardReference<Player>) super.getRef();
784 }
785
786 public String getAccountName()
787 {
788 if (_connection == null)
789 {
790 return _login;
791 }
792 return _connection.getLogin();
793 }
794
795 public String getIP()
796 {
797 if (_connection == null)
798 {
799 return NOT_CONNECTED;
800 }
801 return _connection.getIpAddr();
802 }
803
804 public String getHWID()
805 {
806 if (_connection == null)
807 {
808 return NOT_CONNECTED;
809 }
810 return _connection.getHWID();
811 }
812
813 public HwidGamer getHwidGamer()
814 {
815 return _gamer;
816 }
817
818 public void setHwidGamer(HwidGamer gamer)
819 {
820 _gamer = gamer;
821 }
822
823 public Map<Integer, String> getAccountChars()
824 {
825 return _chars;
826 }
827
828 @Override
829 public final PlayerTemplate getTemplate()
830 {
831 return (PlayerTemplate) _template;
832 }
833
834 @Override
835 public PlayerTemplate getBaseTemplate()
836 {
837 return (PlayerTemplate) _baseTemplate;
838 }
839
840 public void changeSex()
841 {
842 setTransformation(251);
843
844 if (getSex() == 1)
845 {
846 _template = CharTemplateHolder.getInstance().getTemplate(getClassId(), false);
847 setSex(0);
848 } else
849 {
850 _template = CharTemplateHolder.getInstance().getTemplate(getClassId(), true);
851 setSex(1);
852 }
853
854 setTransformation(0);
855 this.sendPacket(new UserInfo(this));
856 }
857
858 @Override
859 public PlayerAI getAI()
860 {
861 return (PlayerAI) _ai;
862 }
863
864 @Override
865 public void doCast(final Skill skill, final Creature target, boolean forceUse)
866 {
867 if (skill == null)
868 {
869 return;
870 }
871
872 if ((_event != null) && !_event.canUseSkill(this, target, skill))
873 {
874 sendActionFailed();
875 return;
876 }
877
878 super.doCast(skill, target, forceUse);
879
880// if (getUseSeed() != 0 && skill.getSkillType() == SkillType.SOWING)
881// sendPacket(new ExUseSharedGroupItem(getUseSeed(), getUseSeed(), 5000, 5000));
882 }
883
884 @Override
885 public void doAttack(Creature target)
886 {
887 if ((_event != null) && !_event.canAttack(this, target))
888 {
889 sendActionFailed();
890 return;
891 }
892 super.doAttack(target);
893 }
894
895 @Override
896 public void sendReuseMessage(Skill skill)
897 {
898 if (isCastingNow())
899 {
900 return;
901 }
902 TimeStamp sts = getSkillReuse(skill);
903 if ((sts == null) || !sts.hasNotPassed())
904 {
905 return;
906 }
907 long timeleft = sts.getReuseCurrent();
908 if ((!Config.ALT_SHOW_REUSE_MSG && (timeleft < 10000)) || (timeleft < 500))
909 {
910 return;
911 }
912 long hours = timeleft / 3600000;
913 long minutes = (timeleft - (hours * 3600000)) / 60000;
914 long seconds = (long) Math.ceil((timeleft - (hours * 3600000) - (minutes * 60000)) / 1000.);
915 if (hours > 0)
916 {
917 sendPacket(new SystemMessage(SystemMessage.THERE_ARE_S2_HOURS_S3_MINUTES_AND_S4_SECONDS_REMAINING_IN_S1S_REUSE_TIME).addSkillName(skill.getId(), skill.getDisplayLevel()).addNumber(hours).addNumber(minutes).addNumber(seconds));
918 }
919 else if (minutes > 0)
920 {
921 sendPacket(new SystemMessage(SystemMessage.THERE_ARE_S2_MINUTES_S3_SECONDS_REMAINING_IN_S1S_REUSE_TIME).addSkillName(skill.getId(), skill.getDisplayLevel()).addNumber(minutes).addNumber(seconds));
922 }
923 else
924 {
925 sendPacket(new SystemMessage(SystemMessage.THERE_ARE_S2_SECONDS_REMAINING_IN_S1S_REUSE_TIME).addSkillName(skill.getId(), skill.getDisplayLevel()).addNumber(seconds));
926 }
927 }
928
929 @Override
930 public final int getLevel()
931 {
932 return _activeClass == null ? 1 : _activeClass.getLevel();
933 }
934
935 public int getSex()
936 {
937 return getTemplate().isMale ? 0 : 1;
938 }
939
940 public int getFace()
941 {
942 return _face;
943 }
944
945 public void setFace(int face)
946 {
947 _face = face;
948 }
949
950 public int getHairColor()
951 {
952 return _hairColor;
953 }
954
955 public void setHairColor(int hairColor)
956 {
957 _hairColor = hairColor;
958 }
959
960 public int getHairStyle()
961 {
962 return _hairStyle;
963 }
964
965 public void setHairStyle(int hairStyle)
966 {
967 _hairStyle = hairStyle;
968 }
969
970 public void offline()
971 {
972 if (getHwidGamer() != null)
973 getHwidGamer().removePlayer(this);
974 if (_connection != null)
975 {
976 _connection.setActiveChar(null);
977 _connection.close(ServerClose.STATIC);
978 setNetConnection(null);
979 }
980
981 setNameColor(Config.SERVICES_OFFLINE_TRADE_NAME_COLOR);
982 setOnlineTime(getOnlineTime());
983 setUptime(0L);
984 setOfflineMode(true);
985
986 setVar("offline", String.valueOf(System.currentTimeMillis() / 1000L), -1);
987
988 Party party = getParty();
989 if (party != null)
990 {
991 if (isFestivalParticipant())
992 {
993 party.sendMessage(getName() + " has been removed from the upcoming festival.");
994 }
995 leaveParty();
996 }
997
998 if (getPet() != null)
999 {
1000 getPet().unSummon();
1001 }
1002
1003 CursedWeaponsManager.getInstance().doLogout(this);
1004
1005 if (isInOlympiadMode() || (getOlympiadGame() != null))
1006 {
1007 Olympiad.logoutPlayer(this);
1008 }
1009
1010 if (isInObserverMode())
1011 {
1012 if (getOlympiadObserveGame() == null)
1013 {
1014 leaveObserverMode();
1015 }
1016 else
1017 {
1018 leaveOlympiadObserverMode(true);
1019 }
1020 _observerMode.set(OBSERVER_NONE);
1021 }
1022
1023 broadcastCharInfo();
1024 stopWaterTask();
1025 stopBonusTask();
1026 stopHourlyTask();
1027 stopVitalityTask();
1028 stopPcBangPointsTask();
1029 stopAutoSaveTask();
1030 stopRecomBonusTask(true);
1031 stopQuestTimers();
1032 getNevitSystem().stopTasksOnLogout();
1033
1034 try
1035 {
1036 getInventory().store();
1037 }
1038 catch (Throwable t)
1039 {
1040 _log.error("Error while storing Player Inventory", t);
1041 }
1042
1043 try
1044 {
1045 store(false);
1046 }
1047 catch (Throwable t)
1048 {
1049 _log.error("Error while storing Player", t);
1050 }
1051 }
1052 public void kick()
1053 {
1054 if (_connection != null)
1055 {
1056 this.getStreamPersonal().OnLogout(this);
1057 _connection.close(LeaveWorld.STATIC);
1058 setNetConnection(null);
1059 Log.LogToPlayerCommunity(getHwidGamer(), this, "Kicked from game!");
1060 }
1061 stopAbnormalEffect(AbnormalEffect.FIREROOT_STUN);
1062 prepareToLogout();
1063 deleteMe();
1064 }
1065
1066 public void restart()
1067 {
1068 if (_connection != null)
1069 {
1070 this.getStreamPersonal().OnLogout(this);
1071 _connection.setActiveChar(null);
1072 setNetConnection(null);
1073 Log.LogToPlayerCommunity(getHwidGamer(), this, "Restarting character!");
1074 }
1075 prepareToLogout();
1076 deleteMe();
1077 }
1078
1079 /**
1080 * The connection is closed, the client does not close, the character is saved and removed from the game Writing an inscription NO CARRIER
1081 */
1082 public void logout()
1083 {
1084 if (_connection != null)
1085 {
1086 this.getStreamPersonal().OnLogout(this);
1087 _connection.close(ServerClose.STATIC);
1088 setNetConnection(null);
1089 Log.LogToPlayerCommunity(getHwidGamer(), this, "Logging Off!");
1090 }
1091 prepareToLogout();
1092 deleteMe();
1093 }
1094
1095 private void prepareToLogout()
1096 {
1097 if (_isLogout.getAndSet(true))
1098 {
1099 return;
1100 }
1101
1102 if (getHwidGamer() != null)
1103 getHwidGamer().removePlayer(this);
1104
1105 setNetConnection(null);
1106 setIsOnline(false);
1107
1108 getListeners().onExit();
1109
1110 if (this.spreeKills > 0)
1111 {
1112 this.spreeKills = 0;
1113 if ((this.getNameColor() == Config.NAME_COLOR_1) || (this.getNameColor() == Config.NAME_COLOR_2) || (this.getNameColor() == Config.NAME_COLOR_3) || (this.getNameColor() == Config.NAME_COLOR_4) || (this.getNameColor() == Config.NAME_COLOR_5) || (this.getNameColor() == Config.NAME_COLOR_6 || (this.getNameColor() == Config.NAME_COLOR_7) || (this.getNameColor() == Config.NAME_COLOR_8) || (this.getNameColor() == Config.NAME_COLOR_9) || (this.getNameColor() == Config.NAME_COLOR_10)))
1114 {
1115 this.setNameColor(Config.NORMAL_NAME_COLOUR);
1116 this.broadcastUserInfo(true);
1117 }
1118 }
1119
1120 if (isFlying() && !checkLandingState())
1121 {
1122 _stablePoint = TeleportUtils.getRestartLocation(this, RestartType.TO_VILLAGE);
1123 }
1124
1125 if (isCastingNow())
1126 {
1127 abortCast(true, true);
1128 }
1129
1130 if (!isInOfflineMode() && getPrivateStoreType() == STORE_PRIVATE_SELL && isSitting())
1131 {
1132 for (TradeItem item : _sellList)
1133 AuctionManager.getInstance().removeStore(this, item.getAuctionId());
1134 }
1135
1136 Party party = getParty();
1137
1138 if ((party != null))
1139 {
1140 if (isFestivalParticipant())
1141 {
1142 party.sendMessage(getName() + " has been removed from the upcoming festival.");
1143 }
1144 leaveParty();
1145 }
1146
1147 if (isInFightClub())
1148 getFightClubEvent().loggedOut(this);
1149
1150 CursedWeaponsManager.getInstance().doLogout(this);
1151
1152 if (_olympiadObserveGame != null)
1153 {
1154 _olympiadObserveGame.removeSpectator(this);
1155 }
1156
1157 if (isInOlympiadMode() || (getOlympiadGame() != null))
1158 {
1159 Olympiad.logoutPlayer(this);
1160 }
1161
1162 stopFishing();
1163
1164 if (isInObserverMode())
1165 {
1166 if (getOlympiadObserveGame() == null)
1167 {
1168 leaveObserverMode();
1169 }
1170 else
1171 {
1172 leaveOlympiadObserverMode(true);
1173 }
1174 _observerMode.set(OBSERVER_NONE);
1175 }
1176
1177 if (_stablePoint != null)
1178 {
1179 teleToLocation(_stablePoint);
1180 }
1181
1182 Summon pet = getPet();
1183 if (pet != null)
1184 {
1185 pet.saveEffects();
1186 pet.unSummon();
1187 }
1188
1189 _friendList.notifyFriends(false);
1190
1191 if (isProcessingRequest())
1192 {
1193 getRequest().cancel();
1194 }
1195
1196 stopAllTimers();
1197
1198 if (isInBoat())
1199 {
1200 getBoat().removePlayer(this);
1201 }
1202
1203 SubUnit unit = getSubUnit();
1204 UnitMember member = unit == null ? null : unit.getUnitMember(getObjectId());
1205 if (member != null)
1206 {
1207 int sponsor = member.getSponsor();
1208 int apprentice = getApprentice();
1209 PledgeShowMemberListUpdate memberUpdate = new PledgeShowMemberListUpdate(this);
1210 for (Player clanMember : _clan.getOnlineMembers(getObjectId()))
1211 {
1212 clanMember.sendPacket(memberUpdate);
1213 if (clanMember.getObjectId() == sponsor)
1214 {
1215 clanMember.sendPacket(new SystemMessage(SystemMessage.S1_YOUR_CLAN_ACADEMYS_APPRENTICE_HAS_LOGGED_OUT).addString(_name));
1216 }
1217 else if (clanMember.getObjectId() == apprentice)
1218 {
1219 clanMember.sendPacket(new SystemMessage(SystemMessage.S1_YOUR_CLAN_ACADEMYS_SPONSOR_HAS_LOGGED_OUT).addString(_name));
1220 }
1221 }
1222 member.setPlayerInstance(this, true);
1223 }
1224
1225 FlagItemAttachment attachment = getActiveWeaponFlagAttachment();
1226 if (attachment != null)
1227 {
1228 attachment.onLogout(this);
1229 }
1230
1231 if (CursedWeaponsManager.getInstance().getCursedWeapon(getCursedWeaponEquippedId()) != null)
1232 {
1233 CursedWeaponsManager.getInstance().getCursedWeapon(getCursedWeaponEquippedId()).setPlayer(null);
1234 }
1235
1236 MatchingRoom room = getMatchingRoom();
1237 if (room != null)
1238 {
1239 if (room.getLeader() == this)
1240 {
1241 room.disband();
1242 }
1243 else
1244 {
1245 room.removeMember(this, false);
1246 }
1247 }
1248 setMatchingRoom(null);
1249
1250 MatchingRoomManager.getInstance().removeFromWaitingList(this);
1251
1252 destroyAllTraps();
1253
1254 if (_decoy != null)
1255 {
1256 _decoy.unSummon();
1257 _decoy = null;
1258 }
1259
1260 stopPvPFlag();
1261
1262 if (_event != null)
1263 {
1264 _event.onLogout(this);
1265 }
1266
1267 Reflection ref = getReflection();
1268
1269 if (ref != ReflectionManager.DEFAULT)
1270 {
1271 if (ref.getReturnLoc() != null)
1272 {
1273 _stablePoint = ref.getReturnLoc();
1274 }
1275
1276 ref.removeObject(this);
1277 }
1278
1279 try
1280 {
1281 getInventory().store();
1282 getRefund().clear();
1283 }
1284 catch (Throwable t)
1285 {
1286 _log.error("Error while storing Inventory and Refund", t);
1287 }
1288
1289 try
1290 {
1291 store(false);
1292 }
1293 catch (Throwable t)
1294 {
1295 _log.error("Error while storing Player", t);
1296 }
1297 }
1298
1299 /**
1300 * @return a table containing all l2fecipeList of the L2Player.<BR>
1301 * <BR>
1302 */
1303 public Collection<Recipe> getDwarvenRecipeBook()
1304 {
1305 return _recipebook.values();
1306 }
1307
1308 public Collection<Recipe> getCommonRecipeBook()
1309 {
1310 return _commonrecipebook.values();
1311 }
1312
1313 public int recipesCount()
1314 {
1315 return _commonrecipebook.size() + _recipebook.size();
1316 }
1317
1318 public boolean hasRecipe(final Recipe id)
1319 {
1320 return _recipebook.containsValue(id) || _commonrecipebook.containsValue(id);
1321 }
1322
1323 public boolean findRecipe(final int id)
1324 {
1325 return _recipebook.containsKey(id) || _commonrecipebook.containsKey(id);
1326 }
1327
1328 /**
1329 * Add a new l2fecipList to the table _recipebook containing all l2fecipeList of the L2Player
1330 * @param recipe
1331 * @param saveDB
1332 */
1333 public void registerRecipe(final Recipe recipe, boolean saveDB)
1334 {
1335 if (recipe == null)
1336 {
1337 return;
1338 }
1339 if (recipe.isDwarvenRecipe())
1340 {
1341 _recipebook.put(recipe.getId(), recipe);
1342 }
1343 else
1344 {
1345 _commonrecipebook.put(recipe.getId(), recipe);
1346 }
1347 if (saveDB)
1348 {
1349 mysql.set("REPLACE INTO character_recipebook (char_id, id) VALUES(?,?)", getObjectId(), recipe.getId());
1350 }
1351 }
1352
1353 /**
1354 * Remove a l2fecipList from the table _recipebook containing all l2fecipeList of the L2Player
1355 * @param RecipeID
1356 */
1357 public void unregisterRecipe(final int RecipeID)
1358 {
1359 if (_recipebook.containsKey(RecipeID))
1360 {
1361 mysql.set("DELETE FROM `character_recipebook` WHERE `char_id`=? AND `id`=? LIMIT 1", getObjectId(), RecipeID);
1362 _recipebook.remove(RecipeID);
1363 }
1364 else if (_commonrecipebook.containsKey(RecipeID))
1365 {
1366 mysql.set("DELETE FROM `character_recipebook` WHERE `char_id`=? AND `id`=? LIMIT 1", getObjectId(), RecipeID);
1367 _commonrecipebook.remove(RecipeID);
1368 }
1369 else
1370 {
1371 _log.warn("Attempted to remove unknown RecipeList" + RecipeID);
1372 }
1373 }
1374
1375 // ------------------- Quest Engine ----------------------
1376
1377 public QuestState getQuestState(String quest)
1378 {
1379 questRead.lock();
1380 try
1381 {
1382 return _quests.get(quest);
1383 }
1384 finally
1385 {
1386 questRead.unlock();
1387 }
1388 }
1389
1390 public QuestState getQuestState(Class<?> quest)
1391 {
1392 return getQuestState(quest.getSimpleName());
1393 }
1394
1395 public boolean isQuestCompleted(String quest)
1396 {
1397 QuestState q = getQuestState(quest);
1398 return (q != null) && q.isCompleted();
1399 }
1400
1401 public boolean isQuestCompleted(Class<?> quest)
1402 {
1403 QuestState q = getQuestState(quest);
1404 return (q != null) && q.isCompleted();
1405 }
1406
1407 public void setQuestState(QuestState qs)
1408 {
1409 questWrite.lock();
1410 try
1411 {
1412 _quests.put(qs.getQuest().getName(), qs);
1413 }
1414 finally
1415 {
1416 questWrite.unlock();
1417 }
1418 }
1419
1420 public void removeQuestState(String quest)
1421 {
1422 questWrite.lock();
1423 try
1424 {
1425 _quests.remove(quest);
1426 }
1427 finally
1428 {
1429 questWrite.unlock();
1430 }
1431 }
1432
1433 public Quest[] getAllActiveQuests()
1434 {
1435 List<Quest> quests = new ArrayList<Quest>(_quests.size());
1436 questRead.lock();
1437 try
1438 {
1439 for (final QuestState qs : _quests.values())
1440 {
1441 if (qs.isStarted())
1442 {
1443 quests.add(qs.getQuest());
1444 }
1445 }
1446 }
1447 finally
1448 {
1449 questRead.unlock();
1450 }
1451 return quests.toArray(new Quest[quests.size()]);
1452 }
1453
1454 public QuestState[] getAllQuestsStates()
1455 {
1456 questRead.lock();
1457 try
1458 {
1459 return _quests.values().toArray(new QuestState[_quests.size()]);
1460 }
1461 finally
1462 {
1463 questRead.unlock();
1464 }
1465 }
1466
1467 public List<QuestState> getQuestsForEvent(NpcInstance npc, QuestEventType event)
1468 {
1469 List<QuestState> states = new ArrayList<QuestState>();
1470 Quest[] quests = npc.getTemplate().getEventQuests(event);
1471 QuestState qs;
1472 if (quests != null)
1473 {
1474 for (Quest quest : quests)
1475 {
1476 qs = getQuestState(quest.getName());
1477 if ((qs != null) && !qs.isCompleted())
1478 {
1479 states.add(getQuestState(quest.getName()));
1480 }
1481 }
1482 }
1483 return states;
1484 }
1485
1486 public void processQuestEvent(String quest, String event, NpcInstance npc, boolean... sendPacket)
1487 {
1488 if (event == null)
1489 {
1490 event = "";
1491 }
1492 QuestState qs = getQuestState(quest);
1493 if (qs == null)
1494 {
1495 Quest q = QuestManager.getQuest(quest);
1496 if (q == null)
1497 {
1498 _log.warn("Quest " + quest + " not found!");
1499 return;
1500 }
1501 qs = q.newQuestState(this, Quest.CREATED);
1502 }
1503 if ((qs == null) || qs.isCompleted())
1504 {
1505 return;
1506 }
1507 qs.getQuest().notifyEvent(event, qs, npc);
1508 if (sendPacket.length == 0 || sendPacket[0])
1509 sendPacket(new QuestList(this));
1510 }
1511
1512 public boolean isQuestContinuationPossible(boolean msg)
1513 {
1514 if ((getWeightPenalty() >= 3) || ((getInventoryLimit() * 0.9) < getInventory().getSize()) || ((Config.QUEST_INVENTORY_MAXIMUM * 0.9) < getInventory().getQuestSize()))
1515 {
1516 if (msg)
1517 {
1518 sendPacket(Msg.PROGRESS_IN_A_QUEST_IS_POSSIBLE_ONLY_WHEN_YOUR_INVENTORYS_WEIGHT_AND_VOLUME_ARE_LESS_THAN_80_PERCENT_OF_CAPACITY);
1519 }
1520 return false;
1521 }
1522 return true;
1523 }
1524
1525 public void stopQuestTimers()
1526 {
1527 for (QuestState qs : getAllQuestsStates())
1528 {
1529 if (qs.isStarted())
1530 {
1531 qs.pauseQuestTimers();
1532 }
1533 else
1534 {
1535 qs.stopQuestTimers();
1536 }
1537 }
1538 }
1539
1540 public void resumeQuestTimers()
1541 {
1542 for (QuestState qs : getAllQuestsStates())
1543 {
1544 qs.resumeQuestTimers();
1545 }
1546 }
1547
1548 // ----------------- End of Quest Engine -------------------
1549
1550 public Collection<ShortCut> getAllShortCuts()
1551 {
1552 return _shortCuts.getAllShortCuts();
1553 }
1554
1555 public ShortCut getShortCut(int slot, int page)
1556 {
1557 return _shortCuts.getShortCut(slot, page);
1558 }
1559
1560 public void registerShortCut(ShortCut shortcut)
1561 {
1562 _shortCuts.registerShortCut(shortcut);
1563 }
1564
1565 public void deleteShortCut(int slot, int page)
1566 {
1567 _shortCuts.deleteShortCut(slot, page);
1568 }
1569
1570 public void registerMacro(Macro macro)
1571 {
1572 _macroses.registerMacro(macro);
1573 }
1574
1575 public void deleteMacro(int id)
1576 {
1577 _macroses.deleteMacro(id);
1578 }
1579
1580 public MacroList getMacroses()
1581 {
1582 return _macroses;
1583 }
1584
1585 public boolean isCastleLord(int castleId)
1586 {
1587 return (_clan != null) && isClanLeader() && (_clan.getCastle() == castleId);
1588 }
1589
1590 public boolean isFortressLord(int fortressId)
1591 {
1592 return (_clan != null) && isClanLeader() && (_clan.getHasFortress() == fortressId);
1593 }
1594
1595 public int getPkKills()
1596 {
1597 return _pkKills;
1598 }
1599
1600 public void setPkKills(final int pkKills)
1601 {
1602 _pkKills = pkKills;
1603 }
1604
1605 public long getCreateTime()
1606 {
1607 return _createTime;
1608 }
1609
1610 public void setCreateTime(final long createTime)
1611 {
1612 _createTime = createTime;
1613 }
1614
1615 public int getDeleteTimer()
1616 {
1617 return _deleteTimer;
1618 }
1619
1620 public void setDeleteTimer(final int deleteTimer)
1621 {
1622 _deleteTimer = deleteTimer;
1623 }
1624
1625 public int getCurrentLoad()
1626 {
1627 return getInventory().getTotalWeight();
1628 }
1629
1630 public long getLastAccess()
1631 {
1632 return _lastAccess;
1633 }
1634
1635 public void setLastAccess(long value)
1636 {
1637 _lastAccess = value;
1638 }
1639
1640 public int getRecomHave()
1641 {
1642 return _recomHave;
1643 }
1644
1645 public void setRecomHave(int value)
1646 {
1647 if (value > 255)
1648 {
1649 _recomHave = 255;
1650 }
1651 else if (value < 0)
1652 {
1653 _recomHave = 0;
1654 }
1655 else
1656 {
1657 _recomHave = value;
1658 }
1659 }
1660
1661 public int getRecomBonusTime()
1662 {
1663 if (_recomBonusTask != null)
1664 {
1665 return (int) Math.max(0, _recomBonusTask.getDelay(TimeUnit.SECONDS));
1666 }
1667 return _recomBonusTime;
1668 }
1669
1670 public void setRecomBonusTime(int val)
1671 {
1672 _recomBonusTime = val;
1673 }
1674
1675 public int getRecomLeft()
1676 {
1677 return _recomLeft;
1678 }
1679
1680 public void setRecomLeft(final int value)
1681 {
1682 _recomLeft = Math.min(999, value);
1683 }
1684
1685 public boolean isHourglassEffected()
1686 {
1687 return _isHourglassEffected;
1688 }
1689
1690 public void setHourlassEffected(boolean val)
1691 {
1692 _isHourglassEffected = val;
1693 }
1694
1695 public void startHourglassEffect()
1696 {
1697 setHourlassEffected(true);
1698 stopRecomBonusTask(true);
1699 sendVoteSystemInfo();
1700 }
1701
1702 public void stopHourglassEffect()
1703 {
1704 setHourlassEffected(false);
1705 startRecomBonusTask();
1706 sendVoteSystemInfo();
1707 }
1708
1709 public int addRecomLeft()
1710 {
1711 int recoms = 0;
1712 if (getRecomLeftToday() < 20)
1713 {
1714 recoms = 10;
1715 }
1716 else
1717 {
1718 recoms = 1;
1719 }
1720 setRecomLeft(getRecomLeft() + recoms);
1721 setRecomLeftToday(getRecomLeftToday() + recoms);
1722 sendUserInfo(true);
1723 return recoms;
1724 }
1725
1726 public int getRecomLeftToday()
1727 {
1728 return _recomLeftToday;
1729 }
1730
1731 public void setRecomLeftToday(final int value)
1732 {
1733 _recomLeftToday = value;
1734 setVar("recLeftToday", String.valueOf(_recomLeftToday), -1);
1735 }
1736
1737 public void giveRecom(final Player target)
1738 {
1739 int targetRecom = target.getRecomHave();
1740 if (targetRecom < 255)
1741 {
1742 target.addRecomHave(1);
1743 }
1744 if (getRecomLeft() > 0)
1745 {
1746 setRecomLeft(getRecomLeft() - 1);
1747 }
1748
1749 sendUserInfo(true);
1750 }
1751
1752 public void addRecomHave(final int val)
1753 {
1754 setRecomHave(getRecomHave() + val);
1755 broadcastUserInfo(true);
1756 sendVoteSystemInfo();
1757 }
1758
1759 public int getRecomBonus()
1760 {
1761 if ((getRecomBonusTime() > 0) || isHourglassEffected())
1762 {
1763 return RecomBonus.getRecoBonus(this);
1764 }
1765 return 0;
1766 }
1767
1768 public double getRecomBonusMul()
1769 {
1770 if ((getRecomBonusTime() > 0) || isHourglassEffected())
1771 {
1772 return RecomBonus.getRecoMultiplier(this);
1773 }
1774 return 1;
1775 }
1776
1777 public void sendVoteSystemInfo()
1778 {
1779 sendPacket(new ExVoteSystemInfo(this));
1780 }
1781
1782 public boolean isRecomTimerActive()
1783 {
1784 return _isRecomTimerActive;
1785 }
1786
1787 public void setRecomTimerActive(boolean val)
1788 {
1789 if (_isRecomTimerActive == val)
1790 {
1791 return;
1792 }
1793
1794 _isRecomTimerActive = val;
1795
1796 if (val)
1797 {
1798 startRecomBonusTask();
1799 }
1800 else
1801 {
1802 stopRecomBonusTask(true);
1803 }
1804
1805 sendVoteSystemInfo();
1806 }
1807
1808 private ScheduledFuture<?> _recomBonusTask;
1809
1810 public void startRecomBonusTask()
1811 {
1812 if ((_recomBonusTask == null) && (getRecomBonusTime() > 0) && isRecomTimerActive() && !isHourglassEffected())
1813 {
1814 _recomBonusTask = ThreadPoolManager.getInstance().schedule(new RecomBonusTask(this), getRecomBonusTime() * 1000);
1815 }
1816 }
1817
1818 public void stopRecomBonusTask(boolean saveTime)
1819 {
1820 if (_recomBonusTask != null)
1821 {
1822 if (saveTime)
1823 {
1824 setRecomBonusTime((int) Math.max(0, _recomBonusTask.getDelay(TimeUnit.SECONDS)));
1825 }
1826 _recomBonusTask.cancel(false);
1827 _recomBonusTask = null;
1828 }
1829 }
1830
1831 @Override
1832 public int getKarma()
1833 {
1834 return _karma;
1835 }
1836
1837 public void setKarma(int karma)
1838 {
1839 if (karma < 0)
1840 {
1841 karma = 0;
1842 }
1843
1844 if (_karma == karma)
1845 {
1846 return;
1847 }
1848
1849 _karma = karma;
1850
1851 sendChanges();
1852
1853 if (getPet() != null)
1854 {
1855 getPet().broadcastCharInfo();
1856 }
1857 }
1858
1859 @Override
1860 public int getMaxLoad()
1861 {
1862 // Weight Limit = (CON Modifier*69000)*Skills
1863 // Source http://l2f.bravehost.com/weightlimit.html (May 2007)
1864 // Fitted exponential curve to the data
1865 int con = getCON();
1866 if (con < 1)
1867 {
1868 return (int) (31000 * Config.MAXLOAD_MODIFIER);
1869 }
1870 else if (con > 59)
1871 {
1872 return (int) (176000 * Config.MAXLOAD_MODIFIER);
1873 }
1874 else
1875 {
1876 return (int) calcStat(Stats.MAX_LOAD, Math.pow(1.029993928, con) * 30495.627366 * Config.MAXLOAD_MODIFIER, this, null);
1877 }
1878 }
1879
1880 private Future<?> _updateEffectIconsTask;
1881
1882 private class UpdateEffectIcons extends RunnableImpl
1883 {
1884 @Override
1885 public void runImpl()
1886 {
1887 updateEffectIconsImpl();
1888 _updateEffectIconsTask = null;
1889 }
1890 }
1891
1892 @Override
1893 public void updateEffectIcons()
1894 {
1895 if (entering || isLogoutStarted())
1896 {
1897 return;
1898 }
1899
1900 if (Config.USER_INFO_INTERVAL == 0)
1901 {
1902 if (_updateEffectIconsTask != null)
1903 {
1904 _updateEffectIconsTask.cancel(false);
1905 _updateEffectIconsTask = null;
1906 }
1907 updateEffectIconsImpl();
1908 return;
1909 }
1910
1911 if (_updateEffectIconsTask != null)
1912 {
1913 return;
1914 }
1915
1916 _updateEffectIconsTask = ThreadPoolManager.getInstance().schedule(new UpdateEffectIcons(), Config.USER_INFO_INTERVAL);
1917 }
1918
1919 public void updateEffectIconsImpl()
1920 {
1921 Effect[] effects = getEffectList().getAllFirstEffects();
1922 Arrays.sort(effects, EffectsComparator.getInstance());
1923
1924 PartySpelled ps = new PartySpelled(this, false);
1925 AbnormalStatusUpdate mi = new AbnormalStatusUpdate();
1926
1927 for (Effect effect : effects)
1928 {
1929 if (effect.isInUse())
1930 {
1931 if (effect.getStackType().equals(EffectTemplate.HP_RECOVER_CAST))
1932 {
1933 sendPacket(new ShortBuffStatusUpdate(effect));
1934 }
1935 else
1936 {
1937 effect.addIcon(mi);
1938 }
1939 if (_party != null)
1940 {
1941 effect.addPartySpelledIcon(ps);
1942 }
1943 }
1944 }
1945
1946 sendPacket(mi);
1947 if (_party != null)
1948 {
1949 _party.sendPacket(ps);
1950 }
1951
1952 if (isInOlympiadMode() && isOlympiadCompStarted())
1953 {
1954 OlympiadGame olymp_game = _olympiadGame;
1955 if (olymp_game != null)
1956 {
1957 ExOlympiadSpelledInfo olympiadSpelledInfo = new ExOlympiadSpelledInfo();
1958
1959 for (Effect effect : effects)
1960 {
1961 if ((effect != null) && effect.isInUse())
1962 {
1963 effect.addOlympiadSpelledIcon(this, olympiadSpelledInfo);
1964 }
1965 }
1966
1967 if ((olymp_game.getType() == CompType.CLASSED) || (olymp_game.getType() == CompType.NON_CLASSED))
1968 {
1969 for (Player member : olymp_game.getTeamMembers(this))
1970 {
1971 member.sendPacket(olympiadSpelledInfo);
1972 }
1973 }
1974
1975 for (Player member : olymp_game.getSpectators())
1976 {
1977 member.sendPacket(olympiadSpelledInfo);
1978 }
1979 }
1980 }
1981 }
1982
1983 public int getWeightPenalty()
1984 {
1985 return getSkillLevel(4270, 0);
1986 }
1987
1988 public void refreshOverloaded()
1989 {
1990 if (isLogoutStarted() || (getMaxLoad() <= 0))
1991 {
1992 return;
1993 }
1994
1995 setOverloaded(getCurrentLoad() > getMaxLoad());
1996 double weightproc = (100. * (getCurrentLoad() - calcStat(Stats.MAX_NO_PENALTY_LOAD, 0, this, null))) / getMaxLoad();
1997 int newWeightPenalty = 0;
1998
1999 if (weightproc < 50)
2000 {
2001 newWeightPenalty = 0;
2002 }
2003 else if (weightproc < 66.6)
2004 {
2005 newWeightPenalty = 1;
2006 }
2007 else if (weightproc < 80)
2008 {
2009 newWeightPenalty = 2;
2010 }
2011 else if (weightproc < 100)
2012 {
2013 newWeightPenalty = 3;
2014 }
2015 else
2016 {
2017 newWeightPenalty = 4;
2018 }
2019
2020 int current = getWeightPenalty();
2021 if (current == newWeightPenalty)
2022 {
2023 return;
2024 }
2025
2026 if (newWeightPenalty > 0)
2027 {
2028 super.addSkill(SkillTable.getInstance().getInfo(4270, newWeightPenalty));
2029 }
2030 else
2031 {
2032 super.removeSkill(getKnownSkill(4270));
2033 }
2034
2035 sendPacket(new SkillList(this));
2036 sendEtcStatusUpdate();
2037 updateStats();
2038 }
2039
2040 public int getArmorsExpertisePenalty()
2041 {
2042 return getSkillLevel(6213, 0);
2043 }
2044
2045 public int getWeaponsExpertisePenalty()
2046 {
2047 return getSkillLevel(6209, 0);
2048 }
2049
2050 public int getExpertisePenalty(ItemInstance item)
2051 {
2052 if (item.getTemplate().getType2() == ItemTemplate.TYPE2_WEAPON)
2053 {
2054 return getWeaponsExpertisePenalty();
2055 }
2056 else if ((item.getTemplate().getType2() == ItemTemplate.TYPE2_SHIELD_ARMOR) || (item.getTemplate().getType2() == ItemTemplate.TYPE2_ACCESSORY))
2057 {
2058 return getArmorsExpertisePenalty();
2059 }
2060 return 0;
2061 }
2062
2063 public void refreshExpertisePenalty()
2064 {
2065 if (isLogoutStarted())
2066 {
2067 return;
2068 }
2069
2070 boolean skillUpdate = false;
2071
2072 int level = (int) calcStat(Stats.GRADE_EXPERTISE_LEVEL, getLevel(), null, null);
2073 int i = 0;
2074 for (i = 0; (i < EXPERTISE_LEVELS.length) && (level >= EXPERTISE_LEVELS[(i + 1)]); i++)
2075 {
2076 ;
2077 }
2078 if (expertiseIndex != i)
2079 {
2080 expertiseIndex = i;
2081 if ((expertiseIndex > 0) && Config.EXPERTISE_PENALTY) // TODO who to do? No need here! redo with a check for an item epic! added Config.EPIC_EXPERTISE_PENALTY
2082 {
2083 addSkill(SkillTable.getInstance().getInfo(239, expertiseIndex), false);
2084 skillUpdate = true;
2085 }
2086 }
2087
2088 int newWeaponPenalty = 0;
2089 int newArmorPenalty = 0;
2090 ItemInstance[] items = getInventory().getPaperdollItems();
2091 for (ItemInstance item : items)
2092 {
2093 if (item != null)
2094 {
2095 int crystaltype = item.getTemplate().getCrystalType().ordinal();
2096 if (item.getTemplate().getType2() == ItemTemplate.TYPE2_WEAPON)
2097 {
2098 if (crystaltype > newWeaponPenalty)
2099 {
2100 newWeaponPenalty = crystaltype;
2101 }
2102 }
2103 else if ((item.getTemplate().getType2() == ItemTemplate.TYPE2_SHIELD_ARMOR) || (item.getTemplate().getType2() == ItemTemplate.TYPE2_ACCESSORY))
2104 {
2105 if (crystaltype > newArmorPenalty)
2106 {
2107 newArmorPenalty = crystaltype;
2108 }
2109 }
2110 }
2111 }
2112
2113 newWeaponPenalty = newWeaponPenalty - expertiseIndex;
2114 if (newWeaponPenalty <= 0)
2115 {
2116 newWeaponPenalty = 0;
2117 }
2118 else if (newWeaponPenalty >= 4)
2119 {
2120 newWeaponPenalty = 4;
2121 }
2122
2123 newArmorPenalty = newArmorPenalty - expertiseIndex;
2124 if (newArmorPenalty <= 0)
2125 {
2126 newArmorPenalty = 0;
2127 }
2128 else if (newArmorPenalty >= 4)
2129 {
2130 newArmorPenalty = 4;
2131 }
2132
2133 int weaponExpertise = getWeaponsExpertisePenalty();
2134 int armorExpertise = getArmorsExpertisePenalty();
2135
2136 if (weaponExpertise != newWeaponPenalty)
2137 {
2138 weaponExpertise = newWeaponPenalty;
2139 if ((newWeaponPenalty > 0) && Config.EXPERTISE_PENALTY)
2140 {
2141 addSkill(SkillTable.getInstance().getInfo(6209, weaponExpertise));
2142 }
2143 else
2144 {
2145 removeSkill(getKnownSkill(6209));
2146 }
2147 skillUpdate = true;
2148 }
2149 if (armorExpertise != newArmorPenalty)
2150 {
2151 armorExpertise = newArmorPenalty;
2152 if ((newArmorPenalty > 0) && Config.EXPERTISE_PENALTY)
2153 {
2154 addSkill(SkillTable.getInstance().getInfo(6213, armorExpertise));
2155 }
2156 else
2157 {
2158 removeSkill(getKnownSkill(6213));
2159 }
2160 skillUpdate = true;
2161 }
2162
2163 if (skillUpdate)
2164 {
2165 _inventory.validateItemsSkills();
2166
2167 sendPacket(new SkillList(this));
2168 sendEtcStatusUpdate();
2169 updateStats();
2170 }
2171 }
2172
2173 public int getPvpKills()
2174 {
2175 return _pvpKills;
2176 }
2177
2178 public void setPvpKills(int pvpKills)
2179 {
2180 _pvpKills = pvpKills;
2181 }
2182
2183 public ClassId getClassId()
2184 {
2185 return getTemplate().classId;
2186 }
2187
2188 public boolean isPendingOlyEnd()
2189 {
2190 return _isPendingOlyEnd;
2191 }
2192
2193 public void setPendingOlyEnd(boolean val)
2194 {
2195 _isPendingOlyEnd = val;
2196 }
2197
2198 public void addClanPointsOnProfession(final int id)
2199 {
2200 if ((getLvlJoinedAcademy() != 0) && (_clan != null) && (_clan.getLevel() >= 5) && (ClassId.VALUES[id].getLevel() == 2))
2201 {
2202 _clan.incReputation(100, true, "Academy");
2203 }
2204 else if ((getLvlJoinedAcademy() != 0) && (_clan != null) && (_clan.getLevel() >= 5) && (ClassId.VALUES[id].getLevel() == 3))
2205 {
2206 int earnedPoints = 0;
2207 if (getLvlJoinedAcademy() <= 16)
2208 {
2209 earnedPoints = Config.MAX_ACADEM_POINT;
2210 }
2211 else if (getLvlJoinedAcademy() >= 39)
2212 {
2213 earnedPoints = Config.MIN_ACADEM_POINT;
2214 }
2215 else
2216 {
2217 earnedPoints = Config.MAX_ACADEM_POINT - ((getLvlJoinedAcademy() - 16) * 20);
2218 }
2219
2220 _clan.removeClanMember(getObjectId());
2221
2222 SystemMessage sm = new SystemMessage(SystemMessage.CLAN_ACADEMY_MEMBER_S1_HAS_SUCCESSFULLY_COMPLETED_THE_2ND_CLASS_TRANSFER_AND_OBTAINED_S2_CLAN_REPUTATION_POINTS);
2223 sm.addString(getName());
2224 sm.addNumber(_clan.incReputation(earnedPoints, true, "Academy"));
2225 _clan.broadcastToOnlineMembers(sm);
2226 _clan.broadcastToOtherOnlineMembers(new PledgeShowMemberListDelete(getName()), this);
2227
2228 setClan(null);
2229 setTitle("");
2230 sendPacket(Msg.CONGRATULATIONS_YOU_WILL_NOW_GRADUATE_FROM_THE_CLAN_ACADEMY_AND_LEAVE_YOUR_CURRENT_CLAN_AS_A_GRADUATE_OF_THE_ACADEMY_YOU_CAN_IMMEDIATELY_JOIN_A_CLAN_AS_A_REGULAR_MEMBER_WITHOUT_BEING_SUBJECT_TO_ANY_PENALTIES);
2231 setLeaveClanTime(0);
2232
2233 broadcastCharInfo();
2234
2235 sendPacket(PledgeShowMemberListDeleteAll.STATIC);
2236
2237 ItemFunctions.addItem(this, 8181, 1, true, "Academy");
2238 }
2239 }
2240
2241 /**
2242 * Set the template of the L2Player.
2243 * @param id The Identifier of the L2PlayerTemplate to set to the L2Player
2244 * @param noban
2245 * @param fromQuest
2246 */
2247 public synchronized void setClassId(final int id, boolean noban, boolean fromQuest)
2248 {
2249 boolean cannotChangeClass = !getPlayerAccess().CanChangeClass && !Config.EVERYBODY_HAS_ADMIN_RIGHTS;
2250 if (!noban && !ClassId.VALUES[id].equalsOrChildOf(ClassId.VALUES[getActiveClassId()]) && cannotChangeClass)
2251 {
2252 _log.error("Error while setting new class as :" + id + " Player:" + getName() + " current Class:" + getActiveClassId() + "|cannot change class? " + cannotChangeClass);
2253 Thread.dumpStack();
2254 return;
2255 }
2256
2257 if (!getSubClasses().containsKey(id))
2258 {
2259 final SubClass cclass = getActiveClass();
2260 getSubClasses().remove(getActiveClassId());
2261 changeClassInDb(cclass.getClassId(), id);
2262 if (cclass.isBase())
2263 {
2264 setBaseClass(id);
2265 addClanPointsOnProfession(id);
2266 ItemInstance coupons = null;
2267 if (ClassId.VALUES[id].getLevel() == 2)
2268 {
2269 if (fromQuest && Config.ALT_ALLOW_SHADOW_WEAPONS)
2270 {
2271 coupons = ItemFunctions.createItem(8869);
2272 }
2273 unsetVar("newbieweapon");
2274 unsetVar("p1q2");
2275 unsetVar("p1q3");
2276 unsetVar("p1q4");
2277 unsetVar("prof1");
2278 unsetVar("ng1");
2279 unsetVar("ng2");
2280 unsetVar("ng3");
2281 unsetVar("ng4");
2282 }
2283 else if (ClassId.VALUES[id].getLevel() == 3)
2284 {
2285 if (fromQuest && Config.ALT_ALLOW_SHADOW_WEAPONS)
2286 {
2287 coupons = ItemFunctions.createItem(8870);
2288 }
2289 unsetVar("newbiearmor");
2290 unsetVar("dd1");
2291 unsetVar("dd2");
2292 unsetVar("dd3");
2293 unsetVar("prof2.1");
2294 unsetVar("prof2.2");
2295 unsetVar("prof2.3");
2296 }
2297
2298 if (coupons != null)
2299 {
2300 coupons.setCount(15);
2301 sendPacket(SystemMessage2.obtainItems(coupons));
2302 getInventory().addItem(coupons, "Class Change");
2303 }
2304 }
2305
2306 //Holy Pomander
2307 switch (ClassId.VALUES[id])
2308 {
2309 case cardinal:
2310 ItemFunctions.addItem(this, 15307, 1, true, "Class Change");
2311 break;
2312 case evaSaint:
2313 ItemFunctions.addItem(this, 15308, 1, true, "Class Change");
2314 break;
2315 case shillienSaint:
2316 ItemFunctions.addItem(this, 15309, 4, true, "Class Change");
2317 break;
2318 }
2319
2320 cclass.setClassId(id);
2321 getSubClasses().put(id, cclass);
2322 rewardSkills(true);
2323 storeCharSubClasses();
2324
2325 if (fromQuest)
2326 {
2327 broadcastPacket(new MagicSkillUse(this, this, 5103, 1, 1000, 0));
2328 sendPacket(new PlaySound("ItemSound.quest_fanfare_2"));
2329 }
2330 broadcastCharInfo();
2331 }
2332
2333 PlayerTemplate t = CharTemplateHolder.getInstance().getTemplate(id, getSex() == 1);
2334 if (t == null)
2335 {
2336 _log.error("Missing template for classId: " + id);
2337 // do not throw error - only print error
2338 return;
2339 }
2340
2341 // Set the template of the L2Player
2342 _template = t;
2343
2344 // Update class icon in party and clan
2345 if (isInParty())
2346 {
2347 _party.sendPacket(new PartySmallWindowUpdate(this));
2348 }
2349 if (_clan != null)
2350 {
2351 _clan.broadcastToOnlineMembers(new PledgeShowMemberListUpdate(this));
2352 }
2353 if (_matchingRoom != null)
2354 {
2355 _matchingRoom.broadcastPlayerUpdate(this);
2356 }
2357 }
2358
2359 public long getExp()
2360 {
2361 return _activeClass == null ? 0 : _activeClass.getExp();
2362 }
2363
2364 public long getMaxExp()
2365 {
2366 return _activeClass == null ? Experience.LEVEL[Experience.getMaxLevel() + 1] : _activeClass.getMaxExp();
2367 }
2368
2369 public void setEnchantScroll(final ItemInstance scroll)
2370 {
2371 _enchantScroll = scroll;
2372 }
2373
2374 public ItemInstance getEnchantScroll()
2375 {
2376 return _enchantScroll;
2377 }
2378
2379 public void setFistsWeaponItem(final WeaponTemplate weaponItem)
2380 {
2381 _fistsWeaponItem = weaponItem;
2382 }
2383
2384 public WeaponTemplate getFistsWeaponItem()
2385 {
2386 return _fistsWeaponItem;
2387 }
2388
2389 public WeaponTemplate findFistsWeaponItem(final int classId)
2390 {
2391 // human fighter fists
2392 if ((classId >= 0x00) && (classId <= 0x09))
2393 {
2394 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(246);
2395 }
2396
2397 // human mage fists
2398 if ((classId >= 0x0a) && (classId <= 0x11))
2399 {
2400 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(251);
2401 }
2402
2403 // elven fighter fists
2404 if ((classId >= 0x12) && (classId <= 0x18))
2405 {
2406 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(244);
2407 }
2408
2409 // elven mage fists
2410 if ((classId >= 0x19) && (classId <= 0x1e))
2411 {
2412 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(249);
2413 }
2414
2415 // dark elven fighter fists
2416 if ((classId >= 0x1f) && (classId <= 0x25))
2417 {
2418 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(245);
2419 }
2420
2421 // dark elven mage fists
2422 if ((classId >= 0x26) && (classId <= 0x2b))
2423 {
2424 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(250);
2425 }
2426
2427 // orc fighter fists
2428 if ((classId >= 0x2c) && (classId <= 0x30))
2429 {
2430 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(248);
2431 }
2432
2433 // orc mage fists
2434 if ((classId >= 0x31) && (classId <= 0x34))
2435 {
2436 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(252);
2437 }
2438
2439 // dwarven fists
2440 if ((classId >= 0x35) && (classId <= 0x39))
2441 {
2442 return (WeaponTemplate) ItemHolder.getInstance().getTemplate(247);
2443 }
2444
2445 return null;
2446 }
2447
2448 public void addExpAndCheckBonus(MonsterInstance mob, final double noRateExp, double noRateSp, double partyVitalityMod)
2449 {
2450 if (_activeClass == null || getVarB("NoExp"))
2451 {
2452 return;
2453 }
2454
2455 double neededExp = calcStat(Stats.SOULS_CONSUME_EXP, 0.0D, mob, null);
2456 if ((neededExp > 0.0D) && (noRateExp > neededExp))
2457 {
2458 mob.broadcastPacket(new L2GameServerPacket[]
2459 {
2460 new SpawnEmitter(mob, this)
2461 });
2462 ThreadPoolManager.getInstance().schedule(new GameObjectTasks.SoulConsumeTask(this), 1000L);
2463 }
2464
2465 double vitalityBonus = 0.0D;
2466 int npcLevel = mob.getLevel();
2467 if (Config.ALT_VITALITY_ENABLED)
2468 {
2469 boolean blessActive = getNevitSystem().isBlessingActive();
2470 vitalityBonus = mob.isRaid() ? 0.0D : getVitalityLevel(blessActive) / 2.0D;
2471 vitalityBonus *= Config.ALT_VITALITY_RATE;
2472
2473 if (noRateExp > 0.0D)
2474 {
2475 if (!mob.isRaid())
2476 {
2477 if ((blessActive) && ((!getVarB("NoExp")) || (getExp() != (l2f.gameserver.model.base.Experience.LEVEL[(getLevel() + 1)] - 1L))))
2478 {
2479 double points = ((noRateExp / (npcLevel * npcLevel)) * 100.0D) / 9.0D;
2480 points *= Config.ALT_VITALITY_CONSUME_RATE;
2481 vitalityBonus = 4.0D * Config.ALT_VITALITY_RATE;
2482 setVitality(getVitality() + (points * partyVitalityMod));
2483 }
2484 else if ((!blessActive) && ((!getVarB("NoExp")) || (getExp() != (l2f.gameserver.model.base.Experience.LEVEL[(getLevel() + 1)] - 1L))))
2485 {
2486 double points = ((noRateExp / (npcLevel * npcLevel)) * 100.0D) / 9.0D;
2487 points *= Config.ALT_VITALITY_CONSUME_RATE;
2488
2489 if (getEffectList().getEffectByType(EffectType.Vitality) != null)
2490 {
2491 points *= -1.0D;
2492 }
2493 if (getEffectList().getEffectByType(EffectType.VitalityMaintenance) == null)
2494 {
2495 setVitality(getVitality() - (points * partyVitalityMod));
2496 }
2497 }
2498 }
2499 else
2500 {
2501 setVitality(getVitality() + Config.ALT_VITALITY_RAID_BONUS);
2502 }
2503 }
2504 }
2505
2506 // In the first call, activate the timer bonuses.
2507 if (!isInPeaceZone())
2508 {
2509 setRecomTimerActive(true);
2510 getNevitSystem().startAdventTask();
2511 if ((getLevel() - npcLevel) <= 9)
2512 {
2513 int nevitPoints = (int) Math.round(((noRateExp / (npcLevel * npcLevel)) * 100) / 20); // TODO: Formula from the bulldozer.
2514 getNevitSystem().addPoints(nevitPoints);
2515 }
2516 }
2517
2518 long normalExp = (long) (noRateExp * (((Config.RATE_XP * getRateExp()) + vitalityBonus) * getRecomBonusMul()));
2519 long normalSp = (long) (noRateSp * ((Config.RATE_SP * getRateSp()) + vitalityBonus));
2520
2521 long expWithoutBonus = (long) (noRateExp * Config.RATE_XP * getRateExp());
2522 long spWithoutBonus = (long) (noRateSp * Config.RATE_SP * getRateSp());
2523
2524 // Alexander - Add the exp acquired to the stats
2525 if (normalExp > 0)
2526 addPlayerStats(Ranking.STAT_TOP_EXP_ACQUIRED, normalExp);
2527
2528 addExpAndSp(normalExp, normalSp, normalExp - expWithoutBonus, normalSp - spWithoutBonus, false, true);
2529 }
2530
2531 private boolean _isVitalityStop = false;
2532
2533 public void VitalityStop(boolean stop)
2534 {
2535 _isVitalityStop = stop;
2536 }
2537
2538 @SuppressWarnings("unused")
2539 private boolean isVitalityStop()
2540 {
2541 return _isVitalityStop;
2542 }
2543
2544 public void setExp(long exp)
2545 {
2546 int oldLvl = _activeClass.getLevel();
2547
2548 _activeClass.setExp(exp);
2549
2550 int level = _activeClass.getLevel();
2551 if (level != oldLvl)
2552 {
2553 int levels = level - oldLvl;
2554 if (levels > 0)
2555 getNevitSystem().addPoints(1950);
2556 levelSet(levels);
2557 }
2558
2559 updateStats();
2560 }
2561
2562 @Override
2563 public void addExpAndSp(long exp, long sp)
2564 {
2565 addExpAndSp(exp, sp, 0, 0, false, false);
2566 }
2567
2568 public void addExpAndSp(long addToExp, long addToSp, long bonusAddExp, long bonusAddSp, boolean applyRate, boolean applyToPet)
2569 {
2570 if (_activeClass == null || getVarB("NoExp"))
2571 {
2572 return;
2573 }
2574
2575 if (applyRate)
2576 {
2577 addToExp *= Config.RATE_XP * getRateExp();
2578 addToSp *= Config.RATE_SP * getRateSp();
2579 }
2580
2581 Summon pet = getPet();
2582 if (addToExp > 0)
2583 {
2584 if (applyToPet)
2585 {
2586 if ((pet != null) && !pet.isDead() && !PetDataTable.isVitaminPet(pet.getNpcId()))
2587 {
2588 if (pet.getNpcId() == PetDataTable.SIN_EATER_ID)
2589 {
2590 pet.addExpAndSp(addToExp, 0);
2591 addToExp = 0;
2592 }
2593 else if (pet.isPet() && (pet.getExpPenalty() > 0f))
2594 {
2595 if ((pet.getLevel() > (getLevel() - 20)) && (pet.getLevel() < (getLevel() + 5)))
2596 {
2597 pet.addExpAndSp((long) (addToExp * pet.getExpPenalty()), 0);
2598 addToExp *= 1. - pet.getExpPenalty();
2599 }
2600 else
2601 {
2602 pet.addExpAndSp((long) ((addToExp * pet.getExpPenalty()) / 5.), 0);
2603 addToExp *= 1. - (pet.getExpPenalty() / 5.);
2604 }
2605 }
2606 else if (pet.isSummon())
2607 {
2608 addToExp *= 1. - pet.getExpPenalty();
2609 }
2610 }
2611 }
2612
2613 // Ady fix - establish if karma had before
2614 boolean hadKarma = _karma > 0;
2615
2616 // Remove Karma when the player kills L2MonsterInstance
2617 if (!isCursedWeaponEquipped() && (addToSp > 0) && (_karma > 0))
2618 {
2619 long toDecrease = Config.KARMA_MIN_KARMA / 10 + getPkKills() * Config.KARMA_SP_DIVIDER;
2620 setKarma(_karma - (int)Rnd.get(toDecrease / 2, toDecrease * 2));
2621 }
2622
2623 // Ady PK fix
2624 if (_karma <= 0)
2625 {
2626 _karma = 0;
2627 if (hadKarma)
2628 startPvPFlag(this);
2629 }
2630
2631 getCounters().expAcquired += addToExp;
2632
2633 long max_xp = getVarB("NoExp") ? Experience.LEVEL[getLevel() + 1] - 1 : getMaxExp();
2634 addToExp = Math.min(addToExp, max_xp - getExp());
2635 }
2636
2637 int oldLvl = _activeClass.getLevel();
2638 long oldExp = _activeClass.getExp();
2639
2640 _activeClass.addExp(addToExp);
2641 _activeClass.addSp(addToSp);
2642
2643 // Alexander - Add the exp lost to the player stats
2644 if (addToExp < 0)
2645 addPlayerStats(Ranking.STAT_TOP_EXP_LOST, -addToExp);
2646
2647 if ((addToExp > 0) && (addToSp > 0) && ((bonusAddExp > 0) || (bonusAddSp > 0)))
2648 {
2649 sendPacket(new SystemMessage2(SystemMsg.YOU_HAVE_ACQUIRED_S1_EXP_BONUS_S2_AND_S3_SP_BONUS_S4).addLong(addToExp).addLong(bonusAddExp).addInteger(addToSp).addInteger((int) bonusAddSp));
2650 }
2651 else if ((addToSp > 0) && (addToExp == 0))
2652 {
2653 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_ACQUIRED_S1_SP).addNumber(addToSp));
2654 }
2655 else if ((addToSp > 0) && (addToExp > 0))
2656 {
2657 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_EARNED_S1_EXPERIENCE_AND_S2_SP).addNumber(addToExp).addNumber(addToSp));
2658 }
2659 else if ((addToSp == 0) && (addToExp > 0))
2660 {
2661 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_EARNED_S1_EXPERIENCE).addNumber(addToExp));
2662 }
2663
2664 // Alexander - Custom tutorial event for the first exp got and then in lvl 6
2665 if (addToExp > 0 && (oldExp < 100 || (_activeClass.getLevel() >= 6 && _activeClass.getLevel() <= 10)))
2666 {
2667 Quest q = QuestManager.getQuest(255);
2668 if (q != null)
2669 {
2670 processQuestEvent(q.getName(), "CE41", null);
2671 }
2672 }
2673
2674 int level = _activeClass.getLevel();
2675 if (level != oldLvl)
2676 {
2677 int levels = level - oldLvl;
2678 if (levels > 0)
2679 {
2680 getNevitSystem().addPoints(1950);
2681 }
2682 levelSet(levels);
2683 }
2684 // Custom Level Up Soul Crystals
2685 if (Config.AUTO_SOUL_CRYSTAL_QUEST)
2686 {
2687 Quest q = QuestManager.getQuest(350);
2688 if (level >= 45 && q != null && getQuestState(q.getName()) == null)
2689 processQuestEvent(q.getName(), "30115-04.htm", null, false);
2690 }
2691
2692 if ((pet != null) && pet.isPet() && PetDataTable.isVitaminPet(pet.getNpcId()))
2693 {
2694 PetInstance _pet = (PetInstance) pet;
2695 _pet.setLevel(getLevel());
2696 _pet.setExp(_pet.getExpForNextLevel());
2697 _pet.broadcastStatusUpdate();
2698 }
2699
2700 if (getNevitSystem().isBlessingActive())
2701 {
2702 addVitality(Config.ALT_VITALITY_NEVIT_POINT);
2703 }
2704
2705 updateStats();
2706 }
2707
2708 /**
2709 * Give Expertise skill of this level.<BR>
2710 * <BR>
2711 * <B><U> Actions</U> :</B><BR>
2712 * <BR>
2713 * <li>Get the Level of the L2Player</li> <li>Add the Expertise skill corresponding to its Expertise level</li> <li>Update the overloaded status of the L2Player</li><BR>
2714 * <BR>
2715 * <p/>
2716 * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T give other free skills (SP needed = 0)</B></FONT><BR>
2717 * <BR>
2718 * @param send
2719 */
2720 private void rewardSkills(boolean send)
2721 {
2722 boolean update = false;
2723 if (Config.AUTO_LEARN_SKILLS)
2724 {
2725 int unLearnable = 0;
2726 Collection<SkillLearn> skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
2727 while (skills.size() > unLearnable)
2728 {
2729 unLearnable = 0;
2730 for (SkillLearn s : skills)
2731 {
2732 Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
2733 if ((sk == null) || !sk.getCanLearn(getClassId()) || (!Config.AUTO_LEARN_FORGOTTEN_SKILLS && s.isClicked()))
2734 {
2735 unLearnable++;
2736 continue;
2737 }
2738 addSkill(sk, true);
2739 }
2740 skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
2741 }
2742 update = true;
2743 }
2744 else
2745 {
2746 // Skills gives subscription-free does not need to be studied
2747 for (SkillLearn skill : SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL))
2748 {
2749 if ((skill.getCost() == 0) && (skill.getItemId() == 0))
2750 {
2751 Skill sk = SkillTable.getInstance().getInfo(skill.getId(), skill.getLevel());
2752 addSkill(sk, true);
2753 if ((getAllShortCuts().size() > 0) && (sk.getLevel() > 1))
2754 {
2755 for (ShortCut sc : getAllShortCuts())
2756 {
2757 if ((sc.getId() == sk.getId()) && (sc.getType() == ShortCut.TYPE_SKILL))
2758 {
2759 ShortCut newsc = new ShortCut(sc.getSlot(), sc.getPage(), sc.getType(), sc.getId(), sk.getLevel(), 1);
2760 sendPacket(new ShortCutRegister(this, newsc));
2761 registerShortCut(newsc);
2762 }
2763 }
2764 }
2765 update = true;
2766 }
2767 }
2768 }
2769
2770 if (send && update)
2771 {
2772 sendPacket(new SkillList(this));
2773 }
2774
2775 updateStats();
2776 }
2777
2778 public Race getRace()
2779 {
2780 return getBaseTemplate().race;
2781 }
2782
2783 public int getIntSp()
2784 {
2785 return (int) getSp();
2786 }
2787
2788 public long getSp()
2789 {
2790 return _activeClass == null ? 0 : _activeClass.getSp();
2791 }
2792
2793 public void setSp(long sp)
2794 {
2795 if (_activeClass != null)
2796 {
2797 _activeClass.setSp(sp);
2798 }
2799 }
2800
2801 public int getClanId()
2802 {
2803 return _clan == null ? 0 : _clan.getClanId();
2804 }
2805
2806 public long getLeaveClanTime()
2807 {
2808 return _leaveClanTime;
2809 }
2810
2811 public long getDeleteClanTime()
2812 {
2813 return _deleteClanTime;
2814 }
2815
2816 public void setLeaveClanTime(final long time)
2817 {
2818 _leaveClanTime = time;
2819 }
2820
2821 public void setDeleteClanTime(final long time)
2822 {
2823 _deleteClanTime = time;
2824 }
2825
2826 public void setOnlineTime(final long time)
2827 {
2828 _onlineTime = time;
2829 _onlineBeginTime = System.currentTimeMillis();
2830 }
2831
2832 public long getOnlineTime()
2833 {
2834 return _onlineTime + getUptime();
2835 }
2836 /**
2837 * @return Time since logging in in seconds
2838 */
2839 public long getOnlineBeginTime()
2840 {
2841 return _onlineBeginTime / 1000L;
2842 }
2843
2844 public void setNoChannel(final long time)
2845 {
2846 _NoChannel = time;
2847 if ((_NoChannel > 2145909600000L) || (_NoChannel < 0))
2848 {
2849 _NoChannel = -1;
2850 }
2851
2852 if (_NoChannel > 0)
2853 {
2854 _NoChannelBegin = System.currentTimeMillis();
2855 }
2856 else
2857 {
2858 _NoChannelBegin = 0;
2859 }
2860 }
2861
2862 public long getNoChannel()
2863 {
2864 return _NoChannel;
2865 }
2866
2867 public long getNoChannelRemained()
2868 {
2869 if (_NoChannel == 0)
2870 {
2871 return 0;
2872 }
2873 else if (_NoChannel < 0)
2874 {
2875 return -1;
2876 }
2877 else
2878 {
2879 long remained = (_NoChannel - System.currentTimeMillis()) + _NoChannelBegin;
2880 if (remained < 0)
2881 {
2882 return 0;
2883 }
2884
2885 return remained;
2886 }
2887 }
2888
2889 public void setLeaveClanCurTime()
2890 {
2891 if (Config.CLAN_LEAVE_PENALTY == 0)
2892 return;
2893
2894 _leaveClanTime = System.currentTimeMillis();
2895 }
2896
2897 public void setDeleteClanCurTime()
2898 {
2899 _deleteClanTime = System.currentTimeMillis();
2900 }
2901
2902 public boolean canJoinClan()
2903 {
2904 if (_leaveClanTime == 0)
2905 {
2906 return true;
2907 }
2908 if (System.currentTimeMillis() - _leaveClanTime >= Config.CLAN_LEAVE_PENALTY * 60 * 60 * 1000L)
2909 {
2910 _leaveClanTime = 0;
2911 return true;
2912 }
2913 return false;
2914 }
2915
2916 public boolean canCreateClan()
2917 {
2918 if (_deleteClanTime == 0)
2919 {
2920 return true;
2921 }
2922 if (System.currentTimeMillis() - _deleteClanTime >= 10 * 24 * 60 * 60 * 1000L)
2923 {
2924 _deleteClanTime = 0;
2925 return true;
2926 }
2927 return false;
2928 }
2929
2930 public IStaticPacket canJoinParty(Player inviter)
2931 {
2932 Request request = getRequest();
2933 if ((request != null) && request.isInProgress() && (request.getOtherPlayer(this) != inviter))
2934 {
2935 return SystemMsg.WAITING_FOR_ANOTHER_REPLY.packet(inviter);
2936 }
2937 if (isBlockAll() || getMessageRefusal())
2938 {
2939 return SystemMsg.THAT_PERSON_IS_IN_MESSAGE_REFUSAL_MODE.packet(inviter);
2940 }
2941 if (isInParty())
2942 {
2943 return new SystemMessage2(SystemMsg.C1_IS_A_MEMBER_OF_ANOTHER_PARTY_AND_CANNOT_BE_INVITED).addName(this);
2944 }
2945 if (inviter.getReflection() != getReflection())
2946 {
2947 if ((inviter.getReflection() != ReflectionManager.DEFAULT) && (getReflection() != ReflectionManager.DEFAULT))
2948 {
2949 return SystemMsg.INVALID_TARGET.packet(inviter);
2950 }
2951 }
2952 if (isCursedWeaponEquipped() || inviter.isCursedWeaponEquipped())
2953 {
2954 return SystemMsg.INVALID_TARGET.packet(inviter);
2955 }
2956 if (inviter.isInOlympiadMode() || isInOlympiadMode())
2957 {
2958 return SystemMsg.A_USER_CURRENTLY_PARTICIPATING_IN_THE_OLYMPIAD_CANNOT_SEND_PARTY_AND_FRIEND_INVITATIONS.packet(inviter);
2959 }
2960 if (!inviter.getPlayerAccess().CanJoinParty || !getPlayerAccess().CanJoinParty)
2961 {
2962 return SystemMsg.INVALID_TARGET.packet(inviter);
2963 }
2964 if (getTeam() != TeamType.NONE)
2965 {
2966 return SystemMsg.INVALID_TARGET.packet(inviter);
2967 }
2968 if (isInFightClub() && !getFightClubEvent().canJoinParty(inviter, this))
2969 {
2970 return SystemMsg.INVALID_TARGET.packet(inviter);
2971 }
2972 return null;
2973 }
2974
2975 @Override
2976 public PcInventory getInventory()
2977 {
2978 return _inventory;
2979 }
2980
2981 @Override
2982 public long getWearedMask()
2983 {
2984 return _inventory.getWearedMask();
2985 }
2986
2987 public PcFreight getFreight()
2988 {
2989 return _freight;
2990 }
2991
2992 public void removeItemFromShortCut(final int objectId)
2993 {
2994 _shortCuts.deleteShortCutByObjectId(objectId);
2995 }
2996
2997 public void removeSkillFromShortCut(final int skillId)
2998 {
2999 _shortCuts.deleteShortCutBySkillId(skillId);
3000 }
3001
3002 public boolean isSitting()
3003 {
3004 return _isSitting;
3005 }
3006
3007 public void setSitting(boolean val)
3008 {
3009 _isSitting = val;
3010 }
3011
3012 public void setSex(int m)
3013 {
3014 if (getTemplate().isMale)
3015 {
3016 m = 0;
3017 } else
3018 {
3019 // female = 1
3020 m = 1;
3021 }
3022 }
3023 public boolean getSittingTask()
3024 {
3025 return sittingTaskLaunched;
3026 }
3027
3028 @Override
3029 public void sitDown(StaticObjectInstance throne, boolean... force)
3030 {
3031 if (isSitting() || sittingTaskLaunched || isAlikeDead())
3032 {
3033 return;
3034 }
3035 if (force.length == 0 || !force[0])
3036 {
3037 if (sittingTaskLaunched || isAlikeDead())
3038 {
3039 return;
3040 }
3041
3042 if (isStunned() || isSleeping() || isParalyzed() || isAttackingNow() || isCastingNow() || isMoving)
3043 {
3044 getAI().setNextAction(nextAction.REST, null, null, false, false);
3045 return;
3046 }
3047 }
3048
3049 resetWaitSitTime();
3050 getAI().setIntention(CtrlIntention.AI_INTENTION_REST, null, null);
3051
3052 if (throne == null)
3053 {
3054 broadcastPacket(new ChangeWaitType(this, ChangeWaitType.WT_SITTING));
3055 }
3056 else
3057 {
3058 broadcastPacket(new ChairSit(this, throne));
3059 }
3060
3061 _sittingObject = throne;
3062 setSitting(true);
3063 sittingTaskLaunched = true;
3064 ThreadPoolManager.getInstance().schedule(new EndSitDownTask(this), 2500);
3065 }
3066
3067 @Override
3068 public void standUp()
3069 {
3070 if (!isSitting() || sittingTaskLaunched || isInStoreMode() || isAlikeDead())
3071 {
3072 return;
3073 }
3074 if (isInFightClub() && !getFightClubEvent().canStandUp(this))
3075 return;
3076
3077 getEffectList().stopAllSkillEffects(EffectType.Relax);
3078
3079 getEffectList().stopAllSkillEffects(EffectType.SilentMove);
3080
3081 getAI().clearNextAction();
3082 broadcastPacket(new ChangeWaitType(this, ChangeWaitType.WT_STANDING));
3083
3084 _sittingObject = null;
3085 sittingTaskLaunched = true;
3086 ThreadPoolManager.getInstance().schedule(new EndStandUpTask(this), 2500);
3087 }
3088
3089 public void updateWaitSitTime()
3090 {
3091 if (_waitTimeWhenSit < 200)
3092 {
3093 _waitTimeWhenSit += 2;
3094 }
3095 }
3096
3097 public int getWaitSitTime()
3098 {
3099 return _waitTimeWhenSit;
3100 }
3101
3102 public void resetWaitSitTime()
3103 {
3104 _waitTimeWhenSit = 0;
3105 }
3106
3107 public Warehouse getWarehouse()
3108 {
3109 return _warehouse;
3110 }
3111
3112 public ItemContainer getRefund()
3113 {
3114 return _refund;
3115 }
3116
3117 public long getAdena()
3118 {
3119 return getInventory().getAdena();
3120 }
3121 public long getDP()
3122 {
3123 return getInventory().getDP();
3124 }
3125
3126 public boolean reduceAdena(long adena, String log)
3127 {
3128 return reduceAdena(adena, false, log);
3129 }
3130
3131 public boolean reduceAdena(long adena, boolean notify, String log)
3132 {
3133 if (adena < 0)
3134 {
3135 return false;
3136 }
3137 if (adena == 0)
3138 {
3139 return true;
3140 }
3141 boolean result = getInventory().reduceAdena(adena, log);
3142 if (notify && result)
3143 {
3144 sendPacket(SystemMessage2.removeItems(ItemTemplate.ITEM_ID_ADENA, adena));
3145 }
3146 return result;
3147 }
3148
3149 public ItemInstance addAdena(long adena, String log)
3150 {
3151 return addAdena(adena, false, log);
3152 }
3153
3154 public ItemInstance addAdena(long adena, boolean notify, String log)
3155 {
3156 if (adena < 1)
3157 {
3158 return null;
3159 }
3160 ItemInstance item = getInventory().addAdena(adena, log);
3161 if ((item != null) && notify)
3162 {
3163 sendPacket(SystemMessage2.obtainItems(ItemTemplate.ITEM_ID_ADENA, adena, 0));
3164 }
3165 return item;
3166 }
3167
3168 public ItemInstance addDP(long dp, boolean notify, String log)
3169 {
3170 if (dp < 1)
3171 {
3172 return null;
3173 }
3174 ItemInstance item = getInventory().addDP(dp, log);
3175 if ((item != null) && notify)
3176 {
3177 sendPacket(SystemMessage2.obtainItems(ItemTemplate.ITEM_ID_DP, dp, 0));
3178 }
3179 return item;
3180 }
3181
3182
3183 public GameClient getNetConnection()
3184 {
3185 return _connection;
3186 }
3187
3188 public int getRevision()
3189 {
3190 return _connection == null ? 0 : _connection.getRevision();
3191 }
3192
3193 public void setNetConnection(final GameClient connection)
3194 {
3195 _connection = connection;
3196 }
3197
3198 public boolean isConnected()
3199 {
3200 return (_connection != null) && _connection.isConnected();
3201 }
3202
3203 @Override
3204 public void onAction(final Player player, boolean shift)
3205 {
3206 if (isFrozen())
3207 {
3208 player.sendPacket(ActionFail.STATIC);
3209 return;
3210 }
3211
3212 if (Events.onAction(player, this, shift))
3213 {
3214 player.sendPacket(ActionFail.STATIC);
3215 return;
3216 }
3217 // Check if the other player already target this L2Player
3218 if (player.getTarget() != this)
3219 {
3220 player.setTarget(this);
3221 if (player.getTarget() == this)
3222 {
3223 player.sendPacket(new MyTargetSelected(getObjectId(), 0)); // The color to display in the select window is White
3224 }
3225 else
3226 {
3227 player.sendPacket(ActionFail.STATIC);
3228 }
3229 }
3230 else if (getPrivateStoreType() != Player.STORE_PRIVATE_NONE)
3231 {
3232 if ((getDistance(player) > INTERACTION_DISTANCE) && (player.getAI().getIntention() != CtrlIntention.AI_INTENTION_INTERACT))
3233 {
3234 if (!shift)
3235 {
3236 player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this, null);
3237 }
3238 else
3239 {
3240 player.sendPacket(ActionFail.STATIC);
3241 }
3242 }
3243 else
3244 {
3245 player.doInteract(this);
3246 }
3247 }
3248 else if (isAutoAttackable(player))
3249 {
3250 player.getAI().Attack(this, false, shift);
3251 }
3252 else if (player != this)
3253 {
3254 if (player.getAI().getIntention() != CtrlIntention.AI_INTENTION_FOLLOW)
3255 {
3256 if (!shift)
3257 {
3258 player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this, Config.FOLLOW_RANGE);
3259 }
3260 else
3261 {
3262 player.sendPacket(ActionFail.STATIC);
3263 }
3264 }
3265 else
3266 {
3267 player.sendPacket(ActionFail.STATIC);
3268 }
3269 }
3270 else
3271 {
3272 player.sendPacket(ActionFail.STATIC);
3273 }
3274 }
3275
3276 @Override
3277 public void broadcastStatusUpdate()
3278 {
3279 if (!needStatusUpdate())
3280 {
3281 return;
3282 }
3283
3284 StatusUpdate su = makeStatusUpdate(StatusUpdate.MAX_HP, StatusUpdate.MAX_MP, StatusUpdate.MAX_CP, StatusUpdate.CUR_HP, StatusUpdate.CUR_MP, StatusUpdate.CUR_CP);
3285 sendPacket(su);
3286
3287 // Check if a party is in progress
3288 if (isInParty())
3289 {
3290 // Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2Player of the Party
3291 getParty().sendPacket(this, new PartySmallWindowUpdate(this));
3292 }
3293
3294 DuelEvent duelEvent = getEvent(DuelEvent.class);
3295 if (duelEvent != null)
3296 {
3297 duelEvent.sendPacket(new ExDuelUpdateUserInfo(this), getTeam().revert().name());
3298 }
3299
3300 if (isInOlympiadMode() && isOlympiadCompStarted())
3301 {
3302 if (_olympiadGame != null)
3303 {
3304 _olympiadGame.broadcastInfo(this, null, false);
3305 }
3306 }
3307 }
3308
3309 private ScheduledFuture<?> _broadcastCharInfoTask;
3310
3311 public class BroadcastCharInfoTask extends RunnableImpl
3312 {
3313 @Override
3314 public void runImpl()
3315 {
3316 broadcastCharInfoImpl();
3317 _broadcastCharInfoTask = null;
3318 }
3319 }
3320
3321 @Override
3322 public void broadcastCharInfo()
3323 {
3324 broadcastUserInfo(false);
3325 }
3326
3327 public void broadcastUserInfo(boolean force)
3328 {
3329 sendUserInfo(force);
3330
3331 if (Config.BROADCAST_CHAR_INFO_INTERVAL == 0)
3332 {
3333 force = true;
3334 }
3335
3336 if (force)
3337 {
3338 if (_broadcastCharInfoTask != null)
3339 {
3340 _broadcastCharInfoTask.cancel(false);
3341 _broadcastCharInfoTask = null;
3342 }
3343 broadcastCharInfoImpl();
3344 return;
3345 }
3346
3347 if (_broadcastCharInfoTask != null)
3348 {
3349 return;
3350 }
3351
3352 _broadcastCharInfoTask = ThreadPoolManager.getInstance().schedule(new BroadcastCharInfoTask(), Config.BROADCAST_CHAR_INFO_INTERVAL);
3353 }
3354
3355 private int _polyNpcId;
3356
3357 public void setPolyId(int polyid)
3358 {
3359 _polyNpcId = polyid;
3360
3361 teleToLocation(getLoc());
3362 broadcastUserInfo(true);
3363 }
3364
3365 public boolean isPolymorphed()
3366 {
3367 return _polyNpcId != 0;
3368 }
3369
3370 public int getPolyId()
3371 {
3372 return _polyNpcId;
3373 }
3374
3375 private void broadcastCharInfoImpl()
3376 {
3377 L2GameServerPacket exCi = new ExBR_ExtraUserInfo(this);
3378 L2GameServerPacket dominion = getEvent(DominionSiegeEvent.class) != null ? new ExDominionWarStart(this) : null;
3379 for(Player player : World.getAroundPlayers(this))
3380 {
3381 player.sendPacket(isPolymorphed() ? new NpcInfoPoly(this) : new CharInfo(this, player), exCi);
3382 player.sendPacket(RelationChanged.update(player, this, player));
3383 if (dominion != null)
3384 {
3385 player.sendPacket(dominion);
3386 }
3387 }
3388 }
3389
3390 public void broadcastRelationChanged()
3391 {
3392 for (Player player : World.getAroundPlayers(this))
3393 {
3394 player.sendPacket(RelationChanged.update(player, this, player));
3395 }
3396 }
3397
3398 public void sendEtcStatusUpdate()
3399 {
3400 if (!isVisible())
3401 {
3402 return;
3403 }
3404
3405 sendPacket(new EtcStatusUpdate(this));
3406 }
3407
3408 private Future<?> _userInfoTask;
3409
3410 private class UserInfoTask extends RunnableImpl
3411 {
3412 @Override
3413 public void runImpl()
3414 {
3415 sendUserInfoImpl();
3416 _userInfoTask = null;
3417 }
3418 }
3419
3420 private void sendUserInfoImpl()
3421 {
3422 sendPacket(new UserInfo(this), new ExBR_ExtraUserInfo(this));
3423 DominionSiegeEvent siegeEvent = getEvent(DominionSiegeEvent.class);
3424 if (siegeEvent != null)
3425 {
3426 sendPacket(new ExDominionWarStart(this));
3427 }
3428 }
3429
3430 public void sendUserInfo()
3431 {
3432 sendUserInfo(false);
3433 }
3434
3435 public void sendUserInfo(boolean force)
3436 {
3437 if (!isVisible() || entering || isLogoutStarted())
3438 {
3439 return;
3440 }
3441
3442 if ((Config.USER_INFO_INTERVAL == 0) || force)
3443 {
3444 if (_userInfoTask != null)
3445 {
3446 _userInfoTask.cancel(false);
3447 _userInfoTask = null;
3448 }
3449 sendUserInfoImpl();
3450 return;
3451 }
3452
3453 if (_userInfoTask != null)
3454 {
3455 return;
3456 }
3457
3458 _userInfoTask = ThreadPoolManager.getInstance().schedule(new UserInfoTask(), Config.USER_INFO_INTERVAL);
3459 }
3460
3461 @Override
3462 public StatusUpdate makeStatusUpdate(int... fields)
3463 {
3464 StatusUpdate su = new StatusUpdate(getObjectId());
3465 for (int field : fields)
3466 {
3467 switch (field)
3468 {
3469 case StatusUpdate.CUR_HP:
3470 su.addAttribute(field, (int) getCurrentHp());
3471 break;
3472 case StatusUpdate.MAX_HP:
3473 su.addAttribute(field, getMaxHp());
3474 break;
3475 case StatusUpdate.CUR_MP:
3476 su.addAttribute(field, (int) getCurrentMp());
3477 break;
3478 case StatusUpdate.MAX_MP:
3479 su.addAttribute(field, getMaxMp());
3480 break;
3481 case StatusUpdate.CUR_LOAD:
3482 su.addAttribute(field, getCurrentLoad());
3483 break;
3484 case StatusUpdate.MAX_LOAD:
3485 su.addAttribute(field, getMaxLoad());
3486 break;
3487 case StatusUpdate.PVP_FLAG:
3488 su.addAttribute(field, _pvpFlag);
3489 break;
3490 case StatusUpdate.KARMA:
3491 su.addAttribute(field, getKarma());
3492 break;
3493 case StatusUpdate.CUR_CP:
3494 su.addAttribute(field, (int) getCurrentCp());
3495 break;
3496 case StatusUpdate.MAX_CP:
3497 su.addAttribute(field, getMaxCp());
3498 break;
3499 }
3500 }
3501 return su;
3502 }
3503
3504 public void sendStatusUpdate(boolean broadCast, boolean withPet, int... fields)
3505 {
3506 if ((fields.length == 0) || (entering && !broadCast))
3507 {
3508 return;
3509 }
3510
3511 StatusUpdate su = makeStatusUpdate(fields);
3512 if (!su.hasAttributes())
3513 {
3514 return;
3515 }
3516
3517 List<L2GameServerPacket> packets = new ArrayList<L2GameServerPacket>(withPet ? 2 : 1);
3518 if (withPet && (getPet() != null))
3519 {
3520 packets.add(getPet().makeStatusUpdate(fields));
3521 }
3522
3523 packets.add(su);
3524
3525 if (!broadCast)
3526 {
3527 sendPacket(packets);
3528 }
3529 else if (entering)
3530 {
3531 broadcastPacketToOthers(packets);
3532 }
3533 else
3534 {
3535 broadcastPacket(packets);
3536 }
3537 }
3538
3539 /**
3540 * @return the Alliance Identifier of the L2Player.<BR>
3541 * <BR>
3542 */
3543 public int getAllyId()
3544 {
3545 return _clan == null ? 0 : _clan.getAllyId();
3546 }
3547
3548 @Override
3549 public void sendPacket(IStaticPacket p)
3550 {
3551 if (!isConnected())
3552 {
3553 return;
3554 }
3555
3556 if (isPacketIgnored(p.packet(this)))
3557 {
3558 return;
3559 }
3560
3561 _connection.sendPacket(p.packet(this));
3562 }
3563
3564 @Override
3565 public void sendPacket(IStaticPacket... packets)
3566 {
3567 if (!isConnected())
3568 {
3569 return;
3570 }
3571
3572 for (IStaticPacket p : packets)
3573 {
3574 if (isPacketIgnored(p))
3575 {
3576 continue;
3577 }
3578
3579 _connection.sendPacket(p.packet(this));
3580 }
3581 }
3582
3583 private boolean isPacketIgnored(IStaticPacket p)
3584 {
3585 if (p == null)
3586 {
3587 return true;
3588 }
3589 if (_notShowBuffAnim && (/*(p.getClass() == MagicSkillUse.class) || */(p.getClass() == MagicSkillLaunched.class) || (p.getClass() == SocialAction.class)))
3590 {
3591 return true;
3592 }
3593
3594 if (_notShowTraders && (p.getClass() == PrivateStoreMsgBuy.class || p.getClass() == PrivateStoreMsgSell.class || p.getClass() == RecipeShopMsg.class))
3595 return true;
3596
3597 return false;
3598 }
3599
3600 @Override
3601 public void sendPacket(List<? extends IStaticPacket> packets)
3602 {
3603 if (!isConnected())
3604 {
3605 return;
3606 }
3607
3608 for (IStaticPacket p : packets)
3609 {
3610 _connection.sendPacket(p.packet(this));
3611 }
3612 }
3613
3614 public void doInteract(GameObject target)
3615 {
3616 if ((target == null) || isActionsDisabled())
3617 {
3618 sendActionFailed();
3619 return;
3620 }
3621 if (target.isPlayer())
3622 {
3623 if (target.getDistance(this) <= INTERACTION_DISTANCE)
3624 {
3625 Player temp = (Player) target;
3626
3627 if ((temp.getPrivateStoreType() == STORE_PRIVATE_SELL) || (temp.getPrivateStoreType() == STORE_PRIVATE_SELL_PACKAGE))
3628 {
3629 sendPacket(new PrivateStoreListSell(this, temp));
3630 }
3631 else if (temp.getPrivateStoreType() == STORE_PRIVATE_BUY)
3632 {
3633 sendPacket(new PrivateStoreListBuy(this, temp));
3634 }
3635 else if (temp.getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE)
3636 {
3637 sendPacket(new RecipeShopSellList(this, temp));
3638 }
3639 // Ady - Support for buff stores
3640 else if (temp.getPrivateStoreType() == STORE_PRIVATE_BUFF)
3641 {
3642 OfflineBufferManager.getInstance().processBypass(this, "BuffStore bufflist " + temp.getObjectId());
3643 }
3644 sendActionFailed();
3645 }
3646 else if (getAI().getIntention() != CtrlIntention.AI_INTENTION_INTERACT)
3647 {
3648 getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this, null);
3649 }
3650 }
3651 else
3652 {
3653 target.onAction(this, false);
3654 }
3655 }
3656
3657 public void doAutoLootOrDrop(ItemInstance item, NpcInstance fromNpc)
3658 {
3659 boolean forceAutoloot = fromNpc.isFlying() || getReflection().isAutolootForced();
3660
3661 if ((fromNpc.isRaid() || (fromNpc instanceof ReflectionBossInstance)) && !Config.AUTO_LOOT_FROM_RAIDS && !item.isHerb() && !forceAutoloot)
3662 {
3663 item.dropToTheGround(this, fromNpc);
3664 return;
3665 }
3666
3667 if (!item.isAdena())
3668 {
3669 if ((item.isHerb() && !AutoLootHerbs && AutoLootOnlyAdena) || (!item.isHerb() && AutoLootOnlyAdena))
3670 {
3671 item.dropToTheGround(this, fromNpc);
3672 return;
3673 }
3674 }
3675 // Champion mob drop
3676 if (!item.isAdena() && fromNpc.isChampion() && Config.CHAMPION_DROP_ONLY_ADENA)
3677 {
3678 item.deleteMe();
3679 return;
3680 }
3681 // Herbs
3682 if (item.isHerb())
3683 {
3684 if (fromNpc.isChampion() && !Config.ALT_CHAMPION_DROP_HERBS)
3685 {
3686 item.deleteMe();
3687 return;
3688 }
3689
3690 if (!AutoLootHerbs && !forceAutoloot)
3691 {
3692 item.dropToTheGround(this, fromNpc);
3693 return;
3694 }
3695 Skill[] skills = item.getTemplate().getAttachedSkills();
3696 if (skills.length > 0)
3697 {
3698 for (Skill skill : skills)
3699 {
3700 altUseSkill(skill, this);
3701 if ((getPet() != null) && getPet().isSummon() && !getPet().isDead())
3702 {
3703 getPet().altUseSkill(skill, getPet());
3704 }
3705 }
3706 }
3707 item.deleteMe();
3708 return;
3709 }
3710
3711 if (!_autoLoot && !forceAutoloot)
3712 {
3713 item.dropToTheGround(this, fromNpc);
3714 return;
3715 }
3716
3717 if (Config.AUTO_LOOT_PA)
3718 {
3719 if (!(_bonusExpiration != null))
3720 {
3721 item.dropToTheGround(this, fromNpc);
3722 sendMessage("Need buy Premium Account");
3723 return;
3724 }
3725 }
3726
3727 // Check if the L2Player is in a Party
3728 if (!isInParty() || item.isCursed())
3729 {
3730 if (!pickupItem(item, Log.Pickup))
3731 {
3732 item.dropToTheGround(this, fromNpc);
3733 return;
3734 }
3735 }
3736 else
3737 {
3738 getParty().distributeItem(this, item, fromNpc);
3739 }
3740
3741 broadcastPickUpMsg(item);
3742 }
3743
3744 @Override
3745 public void doPickupItem(final GameObject object)
3746 {
3747 // Check if the L2Object to pick up is a L2ItemInstance
3748 if (!object.isItem())
3749 {
3750 _log.warn("trying to pickup wrong target." + getTarget());
3751 return;
3752 }
3753
3754 sendActionFailed();
3755 stopMove();
3756
3757 ItemInstance item = (ItemInstance) object;
3758
3759 synchronized (item)
3760 {
3761 if (!item.isVisible())
3762 {
3763 return;
3764 }
3765
3766 // Check if me not owner of item and, if in party, not in owner party and nonowner pickup delay still active
3767 if (!ItemFunctions.checkIfCanPickup(this, item))
3768 {
3769 SystemMessage sm;
3770 if (item.getItemId() == 57)
3771 {
3772 sm = new SystemMessage(SystemMessage.YOU_HAVE_FAILED_TO_PICK_UP_S1_ADENA);
3773 sm.addNumber(item.getCount());
3774 }
3775 else
3776 {
3777 sm = new SystemMessage(SystemMessage.YOU_HAVE_FAILED_TO_PICK_UP_S1);
3778 sm.addItemName(item.getItemId());
3779 }
3780 sendPacket(sm);
3781 return;
3782 }
3783
3784 // Herbs
3785 if (item.isHerb())
3786 {
3787 Skill[] skills = item.getTemplate().getAttachedSkills();
3788 if (skills.length > 0)
3789 {
3790 for (Skill skill : skills)
3791 {
3792 altUseSkill(skill, this);
3793 if ((getPet() != null) && getPet().isSummon() && !getPet().isDead())
3794 {
3795 getPet().altUseSkill(skill, getPet());
3796 }
3797 }
3798 }
3799
3800 broadcastPacket(new GetItem(item, getObjectId()));
3801 item.deleteMe();
3802 return;
3803 }
3804
3805 FlagItemAttachment attachment = item.getAttachment() instanceof FlagItemAttachment ? (FlagItemAttachment) item.getAttachment() : null;
3806
3807 if (!isInParty() || (attachment != null) || item.isCursed())
3808 {
3809 if (pickupItem(item, Log.Pickup))
3810 {
3811 broadcastPacket(new GetItem(item, getObjectId()));
3812 broadcastPickUpMsg(item);
3813 item.pickupMe();
3814 }
3815 }
3816 else
3817 {
3818 getParty().distributeItem(this, item, null);
3819 }
3820 }
3821 }
3822
3823 public boolean pickupItem(ItemInstance item, String log)
3824 {
3825 PickableAttachment attachment = item.getAttachment() instanceof PickableAttachment ? (PickableAttachment) item.getAttachment() : null;
3826
3827 if (!ItemFunctions.canAddItem(this, item))
3828 {
3829 return false;
3830 }
3831
3832 if ((item.getItemId() == ItemTemplate.ITEM_ID_ADENA) || (item.getItemId() == 6353))
3833 {
3834 Quest q = QuestManager.getQuest(255);
3835 if (q != null)
3836 {
3837 processQuestEvent(q.getName(), "CE" + item.getItemId(), null);
3838 }
3839 }
3840
3841 sendPacket(SystemMessage2.obtainItems(item));
3842 getInventory().addItem(item, log);
3843
3844 if (attachment != null)
3845 {
3846 attachment.pickUp(this);
3847 }
3848
3849 sendChanges();
3850 return true;
3851 }
3852
3853 public void setObjectTarget(GameObject target)
3854 {
3855 setTarget(target);
3856 if (target == null)
3857 {
3858 return;
3859 }
3860
3861 if (target == getTarget())
3862 {
3863 if (target.isNpc())
3864 {
3865 NpcInstance npc = (NpcInstance) target;
3866 sendPacket(new MyTargetSelected(npc.getObjectId(), getLevel() - npc.getLevel()));
3867 sendPacket(npc.makeStatusUpdate(StatusUpdate.CUR_HP, StatusUpdate.MAX_HP));
3868 sendPacket(new ValidateLocation(npc), ActionFail.STATIC);
3869 }
3870 else
3871 {
3872 sendPacket(new MyTargetSelected(target.getObjectId(), 0));
3873 }
3874 }
3875 }
3876
3877 @Override
3878 public void setTarget(GameObject newTarget)
3879 {
3880 // Check if the new target is visible
3881 if ((newTarget != null) && !newTarget.isVisible())
3882 {
3883 newTarget = null;
3884 }
3885
3886 // Can't target and attack festival monsters if not participant
3887 if ((newTarget instanceof FestivalMonsterInstance) && !isFestivalParticipant())
3888 {
3889 newTarget = null;
3890 }
3891
3892 Party party = getParty();
3893
3894 // Can't target and attack rift invaders if not in the same room
3895 if ((party != null) && party.isInDimensionalRift())
3896 {
3897 int riftType = party.getDimensionalRift().getType();
3898 int riftRoom = party.getDimensionalRift().getCurrentRoom();
3899 if ((newTarget != null) && !DimensionalRiftManager.getInstance().getRoom(riftType, riftRoom).checkIfInZone(newTarget.getX(), newTarget.getY(), newTarget.getZ()))
3900 {
3901 newTarget = null;
3902 }
3903 }
3904
3905 GameObject oldTarget = getTarget();
3906
3907 if (oldTarget != null)
3908 {
3909 if (oldTarget.equals(newTarget))
3910 {
3911 return;
3912 }
3913
3914 // Remove the L2Player from the _statusListener of the old target if it was a L2Character
3915 if (oldTarget.isCreature())
3916 {
3917 ((Creature) oldTarget).removeStatusListener(this);
3918 }
3919
3920 if(newTarget == null)
3921 {
3922 broadcastPacket(new TargetUnselected(this));
3923 }
3924 broadcastPacket(new TargetUnselected(this));
3925 }
3926
3927 if (newTarget != null)
3928 {
3929 // Add the L2Player to the _statusListener of the new target if it's a L2Character
3930 if (newTarget.isCreature())
3931 {
3932 ((Creature) newTarget).addStatusListener(this);
3933 }
3934
3935 broadcastPacketToOthers(new TargetSelected(getObjectId(), newTarget.getObjectId(), getLoc()));
3936 broadcastPacket(new TargetSelected(getObjectId(), newTarget.getObjectId(), getLoc()));
3937 }
3938
3939 super.setTarget(newTarget);
3940 }
3941
3942 /**
3943 * @return the active weapon instance (always equipped in the right hand).<BR>
3944 * <BR>
3945 */
3946 @Override
3947 public ItemInstance getActiveWeaponInstance()
3948 {
3949 return getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
3950 }
3951
3952 /**
3953 * @return the active weapon item (always equipped in the right hand).<BR>
3954 * <BR>
3955 */
3956 @Override
3957 public WeaponTemplate getActiveWeaponItem()
3958 {
3959 final ItemInstance weapon = getActiveWeaponInstance();
3960
3961 if (weapon == null)
3962 {
3963 return getFistsWeaponItem();
3964 }
3965
3966 return (WeaponTemplate) weapon.getTemplate();
3967 }
3968
3969 /**
3970 * @return the secondary weapon instance (always equipped in the left hand).<BR>
3971 * <BR>
3972 */
3973 @Override
3974 public ItemInstance getSecondaryWeaponInstance()
3975 {
3976 return getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
3977 }
3978
3979 /**
3980 * @return the secondary weapon item (always equipped in the left hand) or the fists weapon.<BR>
3981 * <BR>
3982 */
3983 @Override
3984 public WeaponTemplate getSecondaryWeaponItem()
3985 {
3986 final ItemInstance weapon = getSecondaryWeaponInstance();
3987
3988 if (weapon == null)
3989 {
3990 return getFistsWeaponItem();
3991 }
3992
3993 final ItemTemplate item = weapon.getTemplate();
3994
3995 if (item instanceof WeaponTemplate)
3996 {
3997 return (WeaponTemplate) item;
3998 }
3999
4000 return null;
4001 }
4002
4003 public boolean isWearingArmor(final ArmorType armorType)
4004 {
4005 final ItemInstance chest = getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
4006
4007 if (chest == null)
4008 {
4009 return armorType == ArmorType.NONE;
4010 }
4011
4012 if (chest.getItemType() != armorType)
4013 {
4014 return false;
4015 }
4016
4017 if (chest.getBodyPart() == ItemTemplate.SLOT_FULL_ARMOR)
4018 {
4019 return true;
4020 }
4021
4022 final ItemInstance legs = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS);
4023
4024 return legs == null ? armorType == ArmorType.NONE : legs.getItemType() == armorType;
4025 }
4026
4027 @Override
4028 public void reduceCurrentHp(double damage, Creature attacker, Skill skill, boolean awake, boolean standUp, boolean directHp, boolean canReflect, boolean transferDamage, boolean isDot, boolean sendMessage)
4029 {
4030 if ((attacker == null) || isDead() || (attacker.isDead() && !isDot))
4031 {
4032 return;
4033 }
4034
4035 // 5182 = Blessing of protection
4036 if (attacker.isPlayer() && (Math.abs(attacker.getLevel() - getLevel()) > 10))
4037 {
4038 if ((attacker.getKarma() > 0) && (getEffectList().getEffectsBySkillId(5182) != null) && !isInZone(ZoneType.SIEGE))
4039 {
4040 return;
4041 }
4042
4043 if ((getKarma() > 0) && (attacker.getEffectList().getEffectsBySkillId(5182) != null) && !attacker.isInZone(ZoneType.SIEGE))
4044 {
4045 return;
4046 }
4047 }
4048
4049 // Reduce the current HP of the L2Player
4050 super.reduceCurrentHp(damage, attacker, skill, awake, standUp, directHp, canReflect, transferDamage, isDot, sendMessage);
4051 }
4052
4053 private Creature lastAttacker = null;
4054 private long lastAttackDate = 0L;
4055
4056 public Creature getLastAttacker()
4057 {
4058 return lastAttacker;
4059 }
4060
4061 public long getLastAttackDate()
4062 {
4063 return lastAttackDate;
4064 }
4065
4066 @Override
4067 protected void onReduceCurrentHp(double damage, Creature attacker, Skill skill, boolean awake, boolean standUp, boolean directHp)
4068 {
4069 if (standUp && !isInTvT())
4070 {
4071 standUp();
4072 if (isFakeDeath())
4073 {
4074 breakFakeDeath();
4075 }
4076 }
4077
4078 lastAttacker = attacker;
4079 lastAttackDate = System.currentTimeMillis();
4080
4081 if (attacker.isPlayable())
4082 {
4083 if (!directHp && (getCurrentCp() > 0))
4084 {
4085 double cp = getCurrentCp();
4086 if (isInOlympiadMode())
4087 {
4088 addDamageOnOlympiad(attacker, skill, damage, cp);
4089 }
4090
4091 if (cp >= damage)
4092 {
4093 cp -= damage;
4094 damage = 0;
4095 }
4096 else
4097 {
4098 damage -= cp;
4099 cp = 0;
4100 }
4101
4102 setCurrentCp(cp);
4103 }
4104 }
4105
4106 double hp = getCurrentHp();
4107
4108 DuelEvent duelEvent = getEvent(DuelEvent.class);
4109 if (duelEvent != null)
4110 {
4111 if (hp <= damage)
4112 {
4113 setCurrentHp(1, true);
4114 duelEvent.onDie(this);
4115 return;
4116 }
4117 }
4118
4119 if ((getPvPTeam() != 0) && (_event != null))
4120 {
4121 if (hp <= damage) // if x <= 1 - killed
4122 {
4123 setCurrentHp(1, true);
4124 _event.doDie(attacker, this);
4125 return;
4126 }
4127 }
4128
4129 if (isInOlympiadMode())
4130 {
4131 addDamageOnOlympiad(attacker, skill, damage, hp);
4132
4133 if (hp <= damage) // it was if (hp + 0.5 <= damage)
4134 {
4135 if (_olympiadGame.getType() != CompType.TEAM)
4136 {
4137 damage = 0;
4138 setCurrentHp(1, true);
4139 _olympiadGame.setWinner(getOlympiadSide() == 1 ? 2 : 1);
4140 _olympiadGame.endGame(20, false);
4141 attacker.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
4142 attacker.sendActionFailed();
4143 return;
4144 }
4145 else if (_olympiadGame.doDie(this))
4146 {
4147 _olympiadGame.setWinner(getOlympiadSide() == 1 ? 2 : 1);
4148 _olympiadGame.endGame(20, false);
4149 }
4150 }
4151 }
4152
4153 super.onReduceCurrentHp(damage, attacker, skill, awake, standUp, directHp);
4154 }
4155
4156 public void addDamageOnOlympiad(Creature attacker, Skill skill, double damage, double hpcp)
4157 {
4158 if ((this != attacker) && ((skill == null) || skill.isOffensive()))
4159 {
4160 _olympiadGame.addDamage(this, Math.min(hpcp, damage));
4161 }
4162 }
4163
4164 private void altDeathPenalty(final Creature killer)
4165 {
4166 // Reduce the Experience of the L2Player in function of the calculated Death Penalty
4167 if (!Config.ALT_GAME_DELEVEL)
4168 {
4169 return;
4170 }
4171 if (isInZoneBattle())
4172 {
4173 return;
4174 }
4175 if (isInZonePvP())
4176 {
4177 return;
4178 }
4179 if (getNevitSystem().isBlessingActive())
4180 {
4181 return;
4182 }
4183 deathPenalty(killer);
4184 }
4185
4186 public final boolean atWarWith(final Player player)
4187 {
4188 return (_clan != null) && (player.getClan() != null) && (getPledgeType() != -1) && (player.getPledgeType() != -1) && _clan.isAtWarWith(player.getClan().getClanId());
4189 }
4190
4191 public boolean atMutualWarWith(Player player)
4192 {
4193 return (_clan != null) && (player.getClan() != null) && (getPledgeType() != -1) && (player.getPledgeType() != -1) && _clan.isAtWarWith(player.getClan().getClanId()) && player.getClan().isAtWarWith(_clan.getClanId());
4194 }
4195
4196 public final void doPurePk(final Player killer)
4197 {
4198 if (killer.getKarma() > 0)
4199 killer.getCounters().pkInARowKills++;
4200 else
4201 killer.getCounters().pkInARowKills = 1;
4202
4203 // Check if the attacker has a PK counter greater than 0
4204 final int pkCountMulti = Math.max(killer.getPkKills() / 2, 1);
4205
4206 // Calculate the level difference Multiplier between attacker and killed L2Player
4207 final int lvlDiffMulti = Math.max(killer.getLevel() / getLevel(), 1);
4208
4209 // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
4210 // Add karma to attacker and increase its PK counter
4211 killer.increaseKarma(Config.KARMA_MIN_KARMA * pkCountMulti); // * lvlDiffMulti);
4212 killer.setPkKills(killer.getPkKills() + 1);
4213
4214 }
4215
4216 public final void doKillInPeace(final Player killer) // Check if the L2Player killed haven't Karma
4217 {
4218 if ((_karma <= 0) && ((_event == null) || _event.checkPvP(killer, this)))
4219 {
4220 if (Config.SERVICES_PK_PVP_KILL_ENABLE)
4221 {
4222 if (Config.SERVICES_PK_PVP_TIE_IF_SAME_IP)
4223 {
4224 if (getIP() != killer.getIP())
4225 {
4226 if (Config.SERVICES_ANNOUNCE_PK_ENABLED)
4227 {
4228 Announcements.getInstance().announceToAll("Player " + killer.getName() + " has pk" + killer.getTarget().getName());
4229 }
4230 ItemFunctions.addItem(killer, Config.SERVICES_PK_KILL_REWARD_ITEM, Config.SERVICES_PK_KILL_REWARD_COUNT, true, "Pk");
4231 }
4232 }
4233 else
4234 {
4235 if (Config.SERVICES_ANNOUNCE_PK_ENABLED)
4236 {
4237 Announcements.getInstance().announceToAll("Player " + killer.getName() + " has pk" + killer.getTarget().getName());
4238 }
4239 ItemFunctions.addItem(killer, Config.SERVICES_PK_KILL_REWARD_ITEM, Config.SERVICES_PK_KILL_REWARD_COUNT, true, "Pk");
4240 }
4241 }
4242 doPurePk(killer);
4243 }
4244 else
4245 {
4246 killer.setPvpKills(killer.getPvpKills() + 1);
4247 }
4248 }
4249
4250 public void checkAddItemToDrop(List<ItemInstance> array, List<ItemInstance> items, int maxCount)
4251 {
4252 for (int i = 0; (i < maxCount) && !items.isEmpty(); i++)
4253 {
4254 array.add(items.remove(Rnd.get(items.size())));
4255 }
4256 }
4257
4258 public FlagItemAttachment getActiveWeaponFlagAttachment()
4259 {
4260 ItemInstance item = getActiveWeaponInstance();
4261 if ((item == null) || !(item.getAttachment() instanceof FlagItemAttachment))
4262 {
4263 return null;
4264 }
4265 return (FlagItemAttachment) item.getAttachment();
4266 }
4267
4268 protected void doPKPVPManage(Creature killer)
4269 {
4270 FlagItemAttachment attachment = getActiveWeaponFlagAttachment();
4271 if (attachment != null)
4272 {
4273 attachment.onDeath(this, killer);
4274 }
4275
4276 if ((killer == null) || (killer == _summon) || (killer == this))
4277 {
4278 return;
4279 }
4280
4281 if ((isInZoneBattle() || killer.isInZoneBattle()) && !Config.ZONE_PVP_COUNT)
4282 {
4283 // Alexander - Add the arena kill to the stats
4284 if (killer.isPlayer())
4285 {
4286 addPlayerStats(Ranking.STAT_TOP_ARENA_DEATHS);
4287
4288 killer.getPlayer().addPlayerStats(Ranking.STAT_TOP_ARENA_KILLS);
4289 }
4290
4291 return;
4292 }
4293
4294 if ((killer instanceof Summon) && ((killer = killer.getPlayer()) == null))
4295 {
4296 return;
4297 }
4298
4299 if (isInFightClub() || killer.isPlayable() && killer.getPlayer().isInFightClub())
4300 {
4301 return;
4302 }
4303
4304 // Processing Karma/PKCount/PvPCount for killer
4305 if (killer.isPlayer())
4306 {
4307 Player pk = (Player) killer;
4308 int repValue = (getLevel() - pk.getLevel()) >= 20 ? 2 : 1;
4309 boolean war = atMutualWarWith(pk);
4310
4311 if ((war) && (pk.getClan().getReputationScore() > 0) && (_clan.getLevel() >= 5) && (_clan.getReputationScore() > 0) && (pk.getClan().getLevel() >= 5))
4312 {
4313 _clan.broadcastToOtherOnlineMembers(new SystemMessage(1782).addString(getName()).addNumber(-_clan.incReputation(-repValue, true, "ClanWar")), this);
4314 pk.getClan().broadcastToOtherOnlineMembers(new SystemMessage(1783).addNumber(pk.getClan().incReputation(repValue, true, "ClanWar")), pk);
4315 }
4316
4317 CastleSiegeEvent siegeEvent = getEvent(CastleSiegeEvent.class);
4318 CastleSiegeEvent siegeEventPk = pk.getEvent(CastleSiegeEvent.class);
4319 if (siegeEvent != null && (siegeEvent == siegeEventPk))
4320 {
4321 pk.getClan().incSiegeKills();
4322 if (((siegeEventPk.getSiegeClan("defenders", pk.getClan()) != siegeEvent.getSiegeClan("attackers", getClan())) || (siegeEventPk.getSiegeClan("attackers", pk.getClan()) != siegeEvent.getSiegeClan("defenders", getClan()))) && (pk.getClan().getReputationScore() > 0) && (_clan.getLevel() >= 5) && (_clan.getReputationScore() > 0) && (pk.getClan().getLevel() >= 5))
4323 {
4324 _clan.broadcastToOtherOnlineMembers(new SystemMessage(1782).addString(getName()).addNumber(-_clan.incReputation(-repValue, true, "ClanWar")), this);
4325 pk.getClan().broadcastToOtherOnlineMembers(new SystemMessage(1783).addNumber(pk.getClan().incReputation(repValue, true, "ClanWar")), pk);
4326 }
4327 }
4328 DominionSiegeEvent dominionEvent = getEvent(DominionSiegeEvent.class);
4329 DominionSiegeEvent dominionEventPk = pk.getEvent(DominionSiegeEvent.class);
4330 if ((dominionEvent != null) && (dominionEventPk != null))
4331 {
4332 pk.getClan().incSiegeKills();
4333 }
4334 FortressSiegeEvent fsiegeEvent = getEvent(FortressSiegeEvent.class);
4335 FortressSiegeEvent fsiegeEventPk = pk.getEvent(FortressSiegeEvent.class);
4336 if ((fsiegeEvent != null) && (fsiegeEvent == fsiegeEventPk) && (pk.getClan() != null) && (_clan != null) && ((fsiegeEventPk.getSiegeClan("defenders", pk.getClan()) != fsiegeEvent.getSiegeClan("attackers", getClan())) || (fsiegeEventPk.getSiegeClan("attackers", pk.getClan()) != fsiegeEvent.getSiegeClan("defenders", getClan()))) && (pk.getClan().getReputationScore() > 0) && (_clan.getLevel() >= 5) && (_clan.getReputationScore() > 0) && (pk.getClan().getLevel() >= 5))
4337 {
4338 _clan.broadcastToOtherOnlineMembers(new SystemMessage(1782).addString(getName()).addNumber(-_clan.incReputation(-repValue, true, "ClanWar")), this);
4339 pk.getClan().broadcastToOtherOnlineMembers(new SystemMessage(1783).addNumber(pk.getClan().incReputation(repValue, true, "ClanWar")), pk);
4340 }
4341 ClanHallSiegeEvent chsiegeEvent = getEvent(ClanHallSiegeEvent.class);
4342 ClanHallSiegeEvent chsiegeEventPk = pk.getEvent(ClanHallSiegeEvent.class);
4343 if ((chsiegeEvent != null) && (chsiegeEvent == chsiegeEventPk) && ((chsiegeEventPk.getSiegeClan("defenders", pk.getClan()) != chsiegeEvent.getSiegeClan("attackers", getClan())) || (chsiegeEventPk.getSiegeClan("attackers", pk.getClan()) != chsiegeEvent.getSiegeClan("defenders", getClan()))) && (pk.getClan().getReputationScore() > 0) && (_clan.getLevel() >= 5) && (_clan.getReputationScore() > 0) && (pk.getClan().getLevel() >= 5))
4344 {
4345 _clan.broadcastToOtherOnlineMembers(new SystemMessage(1782).addString(getName()).addNumber(-_clan.incReputation(-repValue, true, "ClanWar")), this);
4346 pk.getClan().broadcastToOtherOnlineMembers(new SystemMessage(1783).addNumber(pk.getClan().incReputation(repValue, true, "ClanWar")), pk);
4347 }
4348 if ((isOnSiegeField()) && (!Config.SIEGE_PVP_COUNT))
4349 {
4350 // Alexander - Add the siege kill to the stats
4351 if (killer.isPlayer())
4352 {
4353 addPlayerStats(Ranking.STAT_TOP_SIEGE_DEATHS);
4354
4355 killer.getPlayer().addPlayerStats(Ranking.STAT_TOP_SIEGE_KILLS);
4356 }
4357 return;
4358 }
4359 if ((_pvpFlag > 0) || (war) || (Config.SIEGE_PVP_COUNT) || (Config.ZONE_PVP_COUNT) || isInZonePvP())
4360 {
4361 if (Config.SERVICES_PK_PVP_KILL_ENABLE)
4362 {
4363 if (Config.SERVICES_PK_PVP_TIE_IF_SAME_IP)
4364 {
4365 if (getIP() != pk.getIP())
4366 {
4367 if (Config.SERVICES_ANNOUNCE_PVP_ENABLED)
4368 {
4369 Announcements.getInstance().announceToAll("Player " + pk.getName() + " has killed" + pk.getTarget().getName());
4370 }
4371 if (pk.isInZoneBattle() && pk.isInZone(ZoneType.epic)) // only if killer is in both epic and battle zone
4372 {
4373 ItemFunctions.addItem(pk, Config.SERVICES_PVP_KILL_REWARD_ITEM, Config.SERVICES_PVP_KILL_REWARD_COUNT, true, "PvP");
4374 }
4375 if (Config.ALLOW_PVP_SPREE_REWARD && !isInSameParty(killer.getPlayer()))
4376 {
4377 ++pk.spreeKills;
4378 SpreeHandler.getInstance().spreeSystem(pk, pk.spreeKills);
4379 }
4380 }
4381 }
4382 else
4383 {
4384 if (Config.SERVICES_ANNOUNCE_PVP_ENABLED)
4385 {
4386 Announcements.getInstance().announceToAll("Player " + pk.getName() + " has killed" + pk.getTarget().getName());
4387 }
4388 if (pk.isInZoneBattle() && pk.isInZone(ZoneType.epic)) // only if killer is in both epic and battle zone
4389 {
4390 ItemFunctions.addItem(pk, Config.SERVICES_PVP_KILL_REWARD_ITEM, Config.SERVICES_PVP_KILL_REWARD_COUNT, true, "PvP");
4391 }
4392 if (Config.ALLOW_PVP_SPREE_REWARD && !isInSameParty(killer.getPlayer()))
4393 {
4394 ++pk.spreeKills;
4395 SpreeHandler.getInstance().spreeSystem(pk, pk.spreeKills);
4396 }
4397 }
4398 }
4399 pk.setPvpKills(pk.getPvpKills() + 1);
4400
4401 // Alexander - Add the pvp kill to the stats
4402 if (killer.isPlayer())
4403 {
4404 addPlayerStats(Ranking.STAT_TOP_PVP_DEATHS);
4405
4406 killer.getPlayer().addPlayerStats(Ranking.STAT_TOP_PVP_KILLS);
4407
4408 // Alexander - If the player has a clan, then we must add a new pvp kill to the clan stats
4409 if (killer.getPlayer().getClan() != null)
4410 killer.getPlayer().getClan().getStats().addClanStats(Ranking.STAT_TOP_CLAN_PVP_KILLS);
4411 }
4412 }
4413 else
4414 {
4415 doKillInPeace(pk);
4416
4417 // Alexander - Add the pk kill to the stats
4418 if (killer.isPlayer())
4419 {
4420 addPlayerStats(Ranking.STAT_TOP_PK_DEATHS);
4421
4422 killer.getPlayer().addPlayerStats(Ranking.STAT_TOP_PK_KILLS);
4423 }
4424 }
4425
4426 // Achievement system, increase pvp kills! Not sure if here is the place...
4427 if (getCounters().pvpKills < getPvpKills() && getHWID() != null && !getHWID().equalsIgnoreCase(pk.getHWID()))
4428 getCounters().pvpKills = getPvpKills();
4429
4430 pk.sendChanges();
4431 }
4432
4433 int karma = _karma;
4434 decreaseKarma(Config.KARMA_LOST_BASE);
4435
4436 // under normal conditions, things are lost with the death of the guard tower or player
4437 // In addition, the loss of viola at things smetri can lose things in the monster smteri
4438 boolean isPvP = killer.isPlayable() || (killer instanceof GuardInstance);
4439
4440 if ((killer.isMonster() && !Config.DROP_ITEMS_ON_DIE // if you kill the monster and viola off
4441 ) || (isPvP // if you kill a player or the Guard and
4442 && ((_pkKills < Config.MIN_PK_TO_ITEMS_DROP // number of PCs too little
4443 ) || ((karma == 0) && Config.KARMA_NEEDED_TO_DROP)) // karma is not
4444 ) || isFestivalParticipant() // the festival things are not lost
4445 || (!killer.isMonster() && !isPvP))
4446 {
4447 return;
4448 }
4449
4450 // No drop from GM's
4451 if (!Config.KARMA_DROP_GM && isGM())
4452 {
4453 return;
4454 }
4455
4456 final int max_drop_count = isPvP ? Config.KARMA_DROP_ITEM_LIMIT : 1;
4457
4458 double dropRate; // base percentage chance
4459 if (isPvP)
4460 {
4461 dropRate = (_pkKills * Config.KARMA_DROPCHANCE_MOD) + Config.KARMA_DROPCHANCE_BASE;
4462 }
4463 else
4464 {
4465 dropRate = Config.NORMAL_DROPCHANCE_BASE;
4466 }
4467
4468 int dropEquipCount = 0, dropWeaponCount = 0, dropItemCount = 0;
4469
4470 for (int i = 0; (i < Math.ceil(dropRate / 100)) && (i < max_drop_count); i++)
4471 {
4472 if (Rnd.chance(dropRate))
4473 {
4474 int rand = Rnd.get(Config.DROPCHANCE_EQUIPPED_WEAPON + Config.DROPCHANCE_EQUIPMENT + Config.DROPCHANCE_ITEM) + 1;
4475 if (rand > (Config.DROPCHANCE_EQUIPPED_WEAPON + Config.DROPCHANCE_EQUIPMENT))
4476 {
4477 dropItemCount++;
4478 }
4479 else if (rand > Config.DROPCHANCE_EQUIPPED_WEAPON)
4480 {
4481 dropEquipCount++;
4482 }
4483 else
4484 {
4485 dropWeaponCount++;
4486 }
4487 }
4488 }
4489
4490 List<ItemInstance> drop = new ArrayList<ItemInstance>(), // total array with the results of the choice
4491 dropItem = new ArrayList<ItemInstance>(), dropEquip = new ArrayList<ItemInstance>(), dropWeapon = new ArrayList<ItemInstance>();
4492
4493 getInventory().writeLock();
4494 try
4495 {
4496 for (ItemInstance item : getInventory().getItems())
4497 {
4498 if (!item.canBeDropped(this, true) || Config.KARMA_LIST_NONDROPPABLE_ITEMS.contains(item.getItemId()))
4499 {
4500 continue;
4501 }
4502
4503 if (item.getTemplate().getType2() == ItemTemplate.TYPE2_WEAPON)
4504 {
4505 dropWeapon.add(item);
4506 }
4507 else if ((item.getTemplate().getType2() == ItemTemplate.TYPE2_SHIELD_ARMOR) || (item.getTemplate().getType2() == ItemTemplate.TYPE2_ACCESSORY))
4508 {
4509 dropEquip.add(item);
4510 }
4511 else if (item.getTemplate().getType2() == ItemTemplate.TYPE2_OTHER)
4512 {
4513 dropItem.add(item);
4514 }
4515 }
4516
4517 checkAddItemToDrop(drop, dropWeapon, dropWeaponCount);
4518 checkAddItemToDrop(drop, dropEquip, dropEquipCount);
4519 checkAddItemToDrop(drop, dropItem, dropItemCount);
4520
4521 // Dropping items, if present
4522 if (drop.isEmpty())
4523 {
4524 return;
4525 }
4526
4527 for (ItemInstance item : drop)
4528 {
4529 if (item.isAugmented() && !Config.ALT_ALLOW_DROP_AUGMENTED)
4530 {
4531 item.setAugmentationId(0);
4532 }
4533
4534 item = getInventory().removeItem(item, "Karma Drop");
4535
4536 if (item.getEnchantLevel() > 0)
4537 {
4538 sendPacket(new SystemMessage(SystemMessage.DROPPED__S1_S2).addNumber(item.getEnchantLevel()).addItemName(item.getItemId()));
4539 }
4540 else
4541 {
4542 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_DROPPED_S1).addItemName(item.getItemId()));
4543 }
4544
4545 if (killer.isPlayable() && ((Config.AUTO_LOOT && Config.AUTO_LOOT_PK) || isInFlyingTransform()))
4546 {
4547 killer.getPlayer().getInventory().addItem(item, Log.Pickup);
4548
4549 killer.getPlayer().sendPacket(SystemMessage2.obtainItems(item));
4550 }
4551 else
4552 {
4553 item.dropToTheGround(this, Location.findAroundPosition(this, Config.KARMA_RANDOM_DROP_LOCATION_LIMIT));
4554 }
4555 }
4556
4557 ItemLogHandler.getInstance().addLog(this, drop, ItemActionType.DROPPED_BY_KARMA);
4558 }
4559 finally
4560 {
4561 getInventory().writeUnlock();
4562 }
4563 }
4564
4565 @Override
4566 protected void onDeath(Creature killer)
4567 {
4568 // Check for active charm of luck for death penalty
4569 getDeathPenalty().checkCharmOfLuck();
4570
4571 if (Config.ALLOW_PVP_SPREE_REWARD)
4572 {
4573 this.spreeKills = 0;
4574 if ((this.getNameColor() == Config.NAME_COLOR_1) || (this.getNameColor() == Config.NAME_COLOR_2) || (this.getNameColor() == Config.NAME_COLOR_3) || (this.getNameColor() == Config.NAME_COLOR_4) || (this.getNameColor() == Config.NAME_COLOR_5) || (this.getNameColor() == Config.NAME_COLOR_6 || (this.getNameColor() == Config.NAME_COLOR_7) || (this.getNameColor() == Config.NAME_COLOR_8) || (this.getNameColor() == Config.NAME_COLOR_9) || (this.getNameColor() == Config.NAME_COLOR_10)))
4575 {
4576 this.setNameColor(Config.NORMAL_NAME_COLOUR);
4577 this.broadcastUserInfo(true);
4578 }
4579// if ((this.getTitleColor() == Config.TITLE_COLOR_1) || (this.getTitleColor() == Config.TITLE_COLOR_2) || (this.getTitleColor() == Config.TITLE_COLOR_3) || (this.getTitleColor() == Config.TITLE_COLOR_4) || (this.getTitleColor() == Config.TITLE_COLOR_5) || (this.getTitleColor() == Config.TITLE_COLOR_6 || (this.getTitleColor() == Config.TITLE_COLOR_7) || (this.getTitleColor() == Config.TITLE_COLOR_8) || (this.getTitleColor() == Config.TITLE_COLOR_9) || (this.getTitleColor() == Config.TITLE_COLOR_10)))
4580// {
4581// this.setTitleColor(Config.NORMAL_TITLE_COLOUR);
4582// this.broadcastUserInfo(true);
4583// }
4584 }
4585 if (isInStoreMode())
4586 {
4587 setPrivateStoreType(Player.STORE_PRIVATE_NONE);
4588 }
4589 if (isProcessingRequest())
4590 {
4591 Request request = getRequest();
4592 if (isInTrade())
4593 {
4594 Player parthner = request.getOtherPlayer(this);
4595 sendPacket(SendTradeDone.FAIL);
4596 parthner.sendPacket(SendTradeDone.FAIL);
4597 }
4598 request.cancel();
4599 }
4600
4601 if (_cubics != null)
4602 {
4603 getEffectList().stopAllSkillEffects(EffectType.Cubic);
4604 }
4605
4606 setAgathion(0);
4607
4608 boolean checkPvp = true;
4609 if (Config.ALLOW_CURSED_WEAPONS)
4610 {
4611 if (isCursedWeaponEquipped())
4612 {
4613 CursedWeaponsManager.getInstance().dropPlayer(this);
4614 checkPvp = false;
4615 }
4616 else if ((killer != null) && killer.isPlayer() && killer.isCursedWeaponEquipped())
4617 {
4618 CursedWeaponsManager.getInstance().increaseKills(((Player) killer).getCursedWeaponEquippedId());
4619 checkPvp = false;
4620 }
4621 }
4622
4623 if (checkPvp)
4624 {
4625 doPKPVPManage(killer);
4626
4627 altDeathPenalty(killer);
4628 }
4629
4630 // And in the end of process notify death penalty that owner died :)
4631 getDeathPenalty().notifyDead(killer);
4632
4633 if (_event != null)
4634 {
4635 _event.doDie(killer, this);
4636 }
4637
4638 setIncreasedForce(0);
4639
4640 if (isInParty() && getParty().isInReflection() && (getParty().getReflection() instanceof DimensionalRift))
4641 {
4642 ((DimensionalRift) getParty().getReflection()).memberDead(this);
4643 }
4644
4645 stopWaterTask();
4646
4647 if (!isSalvation() && isOnSiegeField() && isCharmOfCourage())
4648 {
4649 ask(new ConfirmDlg(SystemMsg.YOUR_CHARM_OF_COURAGE_IS_TRYING_TO_RESURRECT_YOU, 60000), new ReviveAnswerListener(this, 100, false));
4650 setCharmOfCourage(false);
4651 }
4652
4653 if (getLevel() < 6)
4654 {
4655 Quest q = QuestManager.getQuest(255);
4656 if (q != null)
4657 {
4658 processQuestEvent(q.getName(), "CE30", null);
4659 }
4660 }
4661
4662 if (isInOlympiadMode() && (killer.isPlayable() && killer.getPlayer().isInOlympiadMode()))
4663 {
4664 _log.warn("Player: " + getName() + " DIED in olympiad from: " + killer.getName());
4665 Thread.dumpStack();
4666 }
4667
4668 // Ady - Call the gm event manager due to this death
4669 GmEventManager.getInstance().onPlayerKill(this, killer);
4670
4671 super.onDeath(killer);
4672 }
4673
4674 public void restoreExp()
4675 {
4676 restoreExp(100.);
4677 }
4678
4679 public void restoreExp(double percent)
4680 {
4681 if (percent == 0)
4682 {
4683 return;
4684 }
4685
4686 int lostexp = 0;
4687
4688 String lostexps = getVar("lostexp");
4689 if (lostexps != null)
4690 {
4691 lostexp = Integer.parseInt(lostexps);
4692 unsetVar("lostexp");
4693 }
4694
4695 if (lostexp != 0)
4696 {
4697 addExpAndSp((long) ((lostexp * percent) / 100), 0);
4698 }
4699 }
4700
4701 public void deathPenalty(Creature killer)
4702 {
4703 if (killer == null || isInFightClub())
4704 {
4705 return;
4706 }
4707 final boolean atwar = (killer.getPlayer() != null) && atWarWith(killer.getPlayer());
4708
4709 double deathPenaltyBonus = getDeathPenalty().getLevel() * Config.ALT_DEATH_PENALTY_C5_EXPERIENCE_PENALTY;
4710 if (deathPenaltyBonus < 2)
4711 {
4712 deathPenaltyBonus = 1;
4713 }
4714 else
4715 {
4716 deathPenaltyBonus = deathPenaltyBonus / 2;
4717 }
4718
4719 // The death steal you some Exp: 10-40 lvl 8% loose
4720 double percentLost = 8.0;
4721
4722 int level = getLevel();
4723 if (level >= 79)
4724 {
4725 percentLost = 1.0;
4726 }
4727 else if (level >= 78)
4728 {
4729 percentLost = 1.5;
4730 }
4731 else if (level >= 76)
4732 {
4733 percentLost = 2.0;
4734 }
4735 else if (level >= 40)
4736 {
4737 percentLost = 4.0;
4738 }
4739
4740 if (Config.ALT_DEATH_PENALTY)
4741 {
4742 percentLost = (percentLost * Config.RATE_XP) + (_pkKills * Config.ALT_PK_DEATH_RATE);
4743 }
4744
4745 if (isFestivalParticipant() || atwar)
4746 {
4747 percentLost = percentLost / 4.0;
4748 }
4749
4750 // Calculate the Experience loss
4751 int lostexp = (int) Math.round(((Experience.LEVEL[level + 1] - Experience.LEVEL[level]) * percentLost) / 100);
4752 lostexp *= deathPenaltyBonus;
4753
4754 lostexp = (int) calcStat(Stats.EXP_LOST, lostexp, killer, null);
4755
4756 if (isOnSiegeField())
4757 {
4758 SiegeEvent<?, ?> siegeEvent = getEvent(SiegeEvent.class);
4759 if (siegeEvent != null)
4760 {
4761 lostexp = 0;
4762 }
4763
4764 if (siegeEvent != null)
4765 {
4766 List<Effect> effect = getEffectList().getEffectsBySkillId(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
4767 if (effect != null)
4768 {
4769 int syndromeLvl = effect.get(0).getSkill().getLevel();
4770 if (syndromeLvl < 5)
4771 {
4772 getEffectList().stopEffect(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
4773 Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, syndromeLvl + 1);
4774 skill.getEffects(this, this, false, false);
4775 }
4776 else if (syndromeLvl == 5)
4777 {
4778 getEffectList().stopEffect(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
4779 Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, 5);
4780 skill.getEffects(this, this, false, false);
4781 }
4782 }
4783 else
4784 {
4785 Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, 1);
4786 if (skill != null)
4787 {
4788 skill.getEffects(this, this, false, false);
4789 }
4790 }
4791 }
4792 }
4793
4794 if (getNevitSystem().isBlessingActive())
4795 {
4796 return;
4797 }
4798
4799 if ((_event != null) && !_event.canLostExpOnDie())
4800 {
4801 return;
4802 }
4803
4804 long before = getExp();
4805 addExpAndSp(-lostexp, 0);
4806 long lost = before - getExp();
4807
4808 if (lost > 0)
4809 {
4810 setVar("lostexp", String.valueOf(lost), -1);
4811 }
4812 }
4813
4814 public void setRequest(Request transaction)
4815 {
4816 _request = transaction;
4817 }
4818
4819 public Request getRequest()
4820 {
4821 return _request;
4822 }
4823
4824 public boolean isBusy()
4825 {
4826 return isProcessingRequest() || isOutOfControl() || isInOlympiadMode() || (getTeam() != TeamType.NONE) || isInStoreMode() || isInDuel() || getMessageRefusal() || isBlockAll() || isInvisible();
4827 }
4828
4829 public boolean isProcessingRequest()
4830 {
4831 if (_request == null)
4832 {
4833 return false;
4834 }
4835 if (!_request.isInProgress())
4836 {
4837 return false;
4838 }
4839 return true;
4840 }
4841
4842 public boolean isInTrade()
4843 {
4844 return isProcessingRequest() && getRequest().isTypeOf(L2RequestType.TRADE);
4845 }
4846
4847 public boolean isInPost()
4848 {
4849 return isProcessingRequest() && getRequest().isTypeOf(L2RequestType.POST);
4850 }
4851
4852 public List<L2GameServerPacket> addVisibleObject(GameObject object, Creature dropper)
4853 {
4854 if (isLogoutStarted() || (object == null) || (object.getObjectId() == getObjectId()) || !object.isVisible())
4855 {
4856 return Collections.emptyList();
4857 }
4858
4859 return object.addPacketList(this, dropper);
4860 }
4861
4862 @Override
4863 public List<L2GameServerPacket> addPacketList(Player forPlayer, Creature dropper)
4864 {
4865 if (getPrivateStoreType() != STORE_PRIVATE_NONE && !isInBuffStore() && forPlayer.getVarB("notraders"))
4866 {
4867 return Collections.emptyList();
4868 }
4869
4870 // If this is fake an Observer - do not show.
4871 if (isInObserverMode() && (getCurrentRegion() != getObserverRegion()) && (getObserverRegion() == forPlayer.getCurrentRegion()))
4872 {
4873 return Collections.emptyList();
4874 }
4875
4876 List<L2GameServerPacket> list = new ArrayList<>();
4877 if (forPlayer.getObjectId() != getObjectId())
4878 {
4879 list.add(isPolymorphed() ? new NpcInfoPoly(this) : new CharInfo(this, forPlayer));
4880 }
4881
4882 list.add(new ExBR_ExtraUserInfo(this));
4883
4884 if (isSitting() && (_sittingObject != null))
4885 {
4886 list.add(new ChairSit(this, _sittingObject));
4887 }
4888
4889 if (getPrivateStoreType() != STORE_PRIVATE_NONE)
4890 {
4891 if (getPrivateStoreType() == STORE_PRIVATE_BUY)
4892 {
4893 list.add(new PrivateStoreMsgBuy(this));
4894 }
4895 else if ((getPrivateStoreType() == STORE_PRIVATE_SELL) || (getPrivateStoreType() == STORE_PRIVATE_SELL_PACKAGE))
4896 {
4897 list.add(new PrivateStoreMsgSell(this));
4898 }
4899 else if (getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE)
4900 {
4901 list.add(new RecipeShopMsg(this));
4902 }
4903 if (forPlayer.isInZonePeace())
4904 {
4905 return list;
4906 }
4907 }
4908
4909 if (isCastingNow())
4910 {
4911 Creature castingTarget = getCastingTarget();
4912 Skill castingSkill = getCastingSkill();
4913 long animationEndTime = getAnimationEndTime();
4914 if ((castingSkill != null) && (castingTarget != null) && castingTarget.isCreature() && (getAnimationEndTime() > 0))
4915 {
4916 list.add(new MagicSkillUse(this, castingTarget, castingSkill.getId(), castingSkill.getLevel(), (int) (animationEndTime - System.currentTimeMillis()), 0));
4917 }
4918 }
4919
4920 if (isInCombat())
4921 {
4922 list.add(new AutoAttackStart(getObjectId()));
4923 }
4924
4925 list.add(RelationChanged.update(forPlayer, this, forPlayer));
4926 DominionSiegeEvent dominionSiegeEvent = getEvent(DominionSiegeEvent.class);
4927 if (dominionSiegeEvent != null)
4928 {
4929 list.add(new ExDominionWarStart(this));
4930 }
4931
4932 if (isInBoat())
4933 {
4934 list.add(getBoat().getOnPacket(this, getInBoatPosition()));
4935 }
4936 else
4937 {
4938 if (isMoving || isFollow)
4939 {
4940 list.add(movePacket());
4941 }
4942 }
4943 return list;
4944 }
4945
4946 public List<L2GameServerPacket> removeVisibleObject(GameObject object, List<L2GameServerPacket> list)
4947 {
4948 if (isLogoutStarted() || (object == null) || (object.getObjectId() == getObjectId()))
4949 {
4950 return null;
4951 }
4952
4953 List<L2GameServerPacket> result = list == null ? object.deletePacketList() : list;
4954
4955 getAI().notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
4956 return result;
4957 }
4958
4959 public void levelSet(int levels)
4960 {
4961 if (levels > 0)
4962 {
4963 sendPacket(Msg.YOU_HAVE_INCREASED_YOUR_LEVEL);
4964 broadcastPacket(new SocialAction(getObjectId(), SocialAction.LEVEL_UP));
4965
4966 setCurrentHpMp(getMaxHp(), getMaxMp());
4967 setCurrentCp(getMaxCp());
4968
4969 Quest q = QuestManager.getQuest(255);
4970 if (q != null)
4971 {
4972 processQuestEvent(q.getName(), "CE40", null);
4973 processQuestEvent(q.getName(), "OpenClassMaster", null);
4974 }
4975 }
4976 else if (levels < 0)
4977 {
4978 if (Config.ALT_REMOVE_SKILLS_ON_DELEVEL)
4979 {
4980 checkSkills();
4981 }
4982 }
4983
4984 // Recalculate the party level
4985 if (isInParty())
4986 {
4987 getParty().recalculatePartyData();
4988 }
4989
4990 if (_clan != null)
4991 {
4992 _clan.broadcastToOnlineMembers(new PledgeShowMemberListUpdate(this));
4993 }
4994
4995 if (_matchingRoom != null)
4996 {
4997 _matchingRoom.broadcastPlayerUpdate(this);
4998 }
4999
5000 // Give Expertise skill of this level
5001 rewardSkills(true);
5002 }
5003
5004 public void checkSkills()
5005 {
5006 for (Skill sk : getAllSkillsArray())
5007 {
5008 SkillTreeTable.checkSkill(this, sk);
5009 }
5010 }
5011
5012 public void startTimers()
5013 {
5014 startAutoSaveTask();
5015 startAutoChargeTask();
5016 startPcBangPointsTask();
5017 startHourlyTask();
5018 PremiumStart.getInstance().start(this);
5019 startBonusTask();
5020 getInventory().startTimers();
5021 resumeQuestTimers();
5022 }
5023
5024 public void stopAllTimers()
5025 {
5026 setAgathion(0);
5027 stopWaterTask();
5028 stopBonusTask();
5029 stopHourlyTask();
5030 stopKickTask();
5031 stopVitalityTask();
5032 stopPcBangPointsTask();
5033 stopAutoSaveTask();
5034 stopRecomBonusTask(true);
5035 getInventory().stopAllTimers();
5036 stopQuestTimers();
5037 getNevitSystem().stopTasksOnLogout();
5038 }
5039
5040 @Override
5041 public Summon getPet()
5042 {
5043 return _summon;
5044 }
5045
5046 public void setPet(Summon summon)
5047 {
5048 boolean isPet = false;
5049 if ((_summon != null) && _summon.isPet())
5050 {
5051 isPet = true;
5052 }
5053 unsetVar("pet");
5054 _summon = summon;
5055 autoShot();
5056 if (summon == null)
5057 {
5058 if (isPet)
5059 {
5060 if (isLogoutStarted())
5061 {
5062 if (getPetControlItem() != null)
5063 {
5064 setVar("pet", String.valueOf(getPetControlItem().getObjectId()), -1);
5065 }
5066 }
5067 setPetControlItem(null);
5068 }
5069 getEffectList().stopEffect(4140);
5070 }
5071 }
5072
5073 public void scheduleDelete()
5074 {
5075 long time = 0;
5076
5077 if(Config.SERVICES_ENABLE_NO_CARRIER && !isOnSiegeField())
5078 {
5079 time = 180;
5080 setNonAggroTime(System.currentTimeMillis() + time * 1000L);
5081 setIsInvul(true);
5082 }
5083 scheduleDelete(time * 1000);
5084 }
5085
5086 /**
5087 * Removes the character of the world in the specified time, if at the time of the expiry of the time it will not be connected. <br>
5088 * <br>
5089 * a minute to make him invulnerable. <br>
5090 * make a binding time to the context for areas with a time limit to leave the game on all the time in the zone. <br>
5091 * <br>
5092 * @param time
5093 */
5094 public void scheduleDelete(long time)
5095 {
5096 if (isInOfflineMode())
5097 {
5098 return;
5099 }
5100 broadcastCharInfo();
5101
5102 ThreadPoolManager.getInstance().schedule(new RunnableImpl()
5103 {
5104 @Override
5105 public void runImpl()
5106 {
5107 if (!isConnected())
5108 {
5109 prepareToLogout();
5110 deleteMe();
5111 }
5112 }
5113 }, time);
5114 }
5115
5116 @Override
5117 protected void onDelete()
5118 {
5119 super.onDelete();
5120
5121 // Remove the fake at the observation point
5122 WorldRegion observerRegion = getObserverRegion();
5123 if (observerRegion != null)
5124 {
5125 observerRegion.removeObject(this);
5126 }
5127
5128 // Send friendlists to friends that this player has logged off
5129 _friendList.notifyFriends(false);
5130
5131 bookmarks.clear();
5132
5133 _inventory.clear();
5134 _warehouse.clear();
5135 _summon = null;
5136 _arrowItem = null;
5137 _fistsWeaponItem = null;
5138 _chars = null;
5139 _enchantScroll = null;
5140 _lastNpc = HardReferences.emptyRef();
5141 _observerRegion = null;
5142 }
5143
5144 public void setTradeList(List<TradeItem> list)
5145 {
5146 _tradeList = list;
5147 }
5148
5149 public List<TradeItem> getTradeList()
5150 {
5151 return _tradeList;
5152 }
5153
5154 public String getSellStoreName()
5155 {
5156 return _sellStoreName;
5157 }
5158
5159 public void setSellStoreName(String name)
5160 {
5161 _sellStoreName = Strings.stripToSingleLine(name);
5162 }
5163
5164 public void setSellList(boolean packageSell, List<TradeItem> list)
5165 {
5166 if (packageSell)
5167 {
5168 _packageSellList = list;
5169 }
5170 else
5171 {
5172 _sellList = list;
5173 }
5174 }
5175
5176 public List<TradeItem> getSellList()
5177 {
5178 return getSellList(_privatestore == STORE_PRIVATE_SELL_PACKAGE);
5179 }
5180
5181 public List<TradeItem> getSellList(boolean packageSell)
5182 {
5183 return packageSell ? _packageSellList : _sellList;
5184 }
5185
5186 public String getBuyStoreName()
5187 {
5188 return _buyStoreName;
5189 }
5190
5191 public void setBuyStoreName(String name)
5192 {
5193 _buyStoreName = Strings.stripToSingleLine(name);
5194 }
5195
5196 public void setBuyList(List<TradeItem> list)
5197 {
5198 _buyList = list;
5199 }
5200
5201 public List<TradeItem> getBuyList()
5202 {
5203 return _buyList;
5204 }
5205
5206 public void setManufactureName(String name)
5207 {
5208 _manufactureName = Strings.stripToSingleLine(name);
5209 }
5210
5211 public String getManufactureName()
5212 {
5213 return _manufactureName;
5214 }
5215
5216 public List<ManufactureItem> getCreateList()
5217 {
5218 return _createList;
5219 }
5220
5221 public void setCreateList(List<ManufactureItem> list)
5222 {
5223 _createList = list;
5224 }
5225
5226 public void setPrivateStoreType(final int type)
5227 {
5228 _privatestore = type;
5229 if (type != STORE_PRIVATE_NONE)
5230 {
5231 setVar("storemode", String.valueOf(type), -1);
5232 }
5233 else
5234 {
5235 for (TradeItem item : _sellList)
5236 AuctionManager.getInstance().removeStore(this, item.getAuctionId());
5237 unsetVar("storemode");
5238 }
5239 }
5240
5241 public boolean isInStoreMode()
5242 {
5243 return _privatestore != STORE_PRIVATE_NONE;
5244 }
5245
5246 public boolean isInBuffStore()
5247 {
5248 return (getPrivateStoreType() == STORE_PRIVATE_BUFF);
5249 }
5250
5251 public int getPrivateStoreType()
5252 {
5253 return _privatestore;
5254 }
5255
5256 /**
5257 * Set the _clan object, _clanId, _clanLeader Flag and title of the L2Player.<BR>
5258 * <BR>
5259 * @param clan the clat to set
5260 */
5261 public void setClan(Clan clan)
5262 {
5263 if ((_clan != clan) && (_clan != null))
5264 {
5265 unsetVar("canWhWithdraw");
5266 }
5267
5268 Clan oldClan = _clan;
5269 if ((oldClan != null) && (clan == null))
5270 {
5271 // Remove clan skills
5272 for (Skill skill : oldClan.getSkills())
5273 {
5274 removeSkill(skill, false);
5275 }
5276
5277 // Also remove subunit skills
5278 for (SubUnit subUnit : oldClan.getAllSubUnits())
5279 {
5280 for (Skill sk : subUnit.getSkills())
5281 {
5282 removeSkill(sk, false);
5283 }
5284 }
5285 }
5286
5287 _clan = clan;
5288
5289 if (clan == null)
5290 {
5291 _pledgeType = Clan.SUBUNIT_NONE;
5292 _pledgeClass = 0;
5293 _powerGrade = 0;
5294 _apprentice = 0;
5295 _inventory.validateItems();
5296
5297 if (getEvent(CastleSiegeEvent.class) != null)
5298 removeEvent(getEvent(CastleSiegeEvent.class));
5299 return;
5300 }
5301
5302 if (!clan.isAnyMember(getObjectId()))
5303 {
5304 clan.restartMembers();
5305 }
5306
5307 if (!clan.isAnyMember(getObjectId()))
5308 {
5309 setClan(null);
5310 if (!_noble)
5311 {
5312 setTitle("");
5313 }
5314 }
5315 }
5316
5317 @Override
5318 public Clan getClan()
5319 {
5320 return _clan;
5321 }
5322
5323 public SubUnit getSubUnit()
5324 {
5325 return _clan == null ? null : _clan.getSubUnit(_pledgeType);
5326 }
5327
5328 public ClanHall getClanHall()
5329 {
5330 int id = _clan != null ? _clan.getHasHideout() : 0;
5331 return ResidenceHolder.getInstance().getResidence(ClanHall.class, id);
5332 }
5333
5334 public Castle getCastle()
5335 {
5336 int id = _clan != null ? _clan.getCastle() : 0;
5337 return ResidenceHolder.getInstance().getResidence(Castle.class, id);
5338 }
5339
5340 public Fortress getFortress()
5341 {
5342 int id = _clan != null ? _clan.getHasFortress() : 0;
5343 return ResidenceHolder.getInstance().getResidence(Fortress.class, id);
5344 }
5345
5346 public Alliance getAlliance()
5347 {
5348 return _clan == null ? null : _clan.getAlliance();
5349 }
5350
5351 public boolean isClanLeader()
5352 {
5353 return (_clan != null) && (getObjectId() == _clan.getLeaderId());
5354 }
5355
5356 public boolean isAllyLeader()
5357 {
5358 return (getAlliance() != null) && (getAlliance().getLeader().getLeaderId() == getObjectId());
5359 }
5360
5361 @Override
5362 public void reduceArrowCount()
5363 {
5364 sendPacket(SystemMsg.YOU_CAREFULLY_NOCK_AN_ARROW);
5365 if ((_arrowItem != null) && !Config.ALLOW_ARROW_INFINITELY)
5366 {
5367 if (!getInventory().destroyItemByObjectId(getInventory().getPaperdollObjectId(Inventory.PAPERDOLL_LHAND), 1L, null, null))
5368 {
5369 getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, null);
5370 _arrowItem = null;
5371 }
5372 }
5373 }
5374
5375 /**
5376 * Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2Player then return True.
5377 * @return
5378 */
5379 protected boolean checkAndEquipArrows()
5380 {
5381 // Check if nothing is equipped in left hand
5382 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null)
5383 {
5384 ItemInstance activeWeapon = getActiveWeaponInstance();
5385 if (activeWeapon != null)
5386 {
5387 if (activeWeapon.getItemType() == WeaponType.BOW)
5388 {
5389 _arrowItem = getInventory().findArrowForBow(activeWeapon.getTemplate());
5390 }
5391 else if (activeWeapon.getItemType() == WeaponType.CROSSBOW)
5392 {
5393 getInventory().findArrowForCrossbow(activeWeapon.getTemplate());
5394 }
5395 }
5396
5397 // Equip arrows needed in left hand
5398 if (_arrowItem != null)
5399 {
5400 getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, _arrowItem);
5401 }
5402 }
5403 else
5404 {
5405 // Get the L2ItemInstance of arrows equipped in left hand
5406 _arrowItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
5407 }
5408
5409 return _arrowItem != null;
5410 }
5411
5412 public void setUptime(final long time)
5413 {
5414 _uptime = time;
5415 }
5416
5417 public long getUptime()
5418 {
5419 return _uptime == 0L ? 0L : System.currentTimeMillis() - _uptime;
5420 }
5421
5422 public boolean isInParty()
5423 {
5424 return _party != null;
5425 }
5426
5427 public void setParty(final Party party)
5428 {
5429 _party = party;
5430 }
5431
5432 public void joinParty(final Party party)
5433 {
5434 if (party != null)
5435 {
5436 party.addPartyMember(this);
5437 for (Player member : party.getMembers())
5438 {
5439 if (PartyMatchingBBSManager.getInstance().partyMatchingPlayersList.contains(member))
5440 {
5441 PartyMatchingBBSManager.getInstance().partyMatchingPlayersList.remove(member);
5442 PartyMatchingBBSManager.getInstance().partyMatchingDescriptionList.remove(member.getObjectId());
5443 member.sendMessage("Now that you have found a party, you've been removed from the Party Matching list.");
5444 }
5445 }
5446
5447 }
5448 }
5449
5450 public void leaveParty()
5451 {
5452 if (isInParty())
5453 {
5454 _party.removePartyMember(this, false);
5455 }
5456 }
5457
5458 public Party getParty()
5459 {
5460 return _party;
5461 }
5462
5463 public void setLastPartyPosition(Location loc)
5464 {
5465 _lastPartyPosition = loc;
5466 }
5467
5468 public void setGMVisible(boolean flag)
5469 {
5470 _gmVisible = flag;
5471 }
5472
5473 public boolean isGMVisible()
5474 {
5475 return _gmVisible;
5476 }
5477
5478 public Location getLastPartyPosition()
5479 {
5480 return _lastPartyPosition;
5481 }
5482
5483 public boolean isGM()
5484 {
5485 return _playerAccess == null ? false : _playerAccess.IsGM;
5486 }
5487
5488 public void setAccessLevel(final int level)
5489 {
5490 _accessLevel = level;
5491 }
5492
5493 @Override
5494 public int getAccessLevel()
5495 {
5496 return _accessLevel;
5497 }
5498
5499 public void setPlayerAccess(final PlayerAccess pa)
5500 {
5501 if (pa != null)
5502 {
5503 _playerAccess = pa;
5504 }
5505 else
5506 {
5507 _playerAccess = new PlayerAccess();
5508 }
5509
5510 setAccessLevel(isGM() || _playerAccess.Menu ? 100 : 0);
5511 }
5512
5513 public PlayerAccess getPlayerAccess()
5514 {
5515 return _playerAccess;
5516 }
5517
5518 @Override
5519 public double getLevelMod()
5520 {
5521 return (89. + getLevel()) / 100.0;
5522 }
5523
5524 /**
5525 * Update Stats of the Player client side by sending Server->Client packet UserInfo/StatusUpdate to this L2Player and CharInfo/StatusUpdate to all players around (broadcast).<BR>
5526 * <BR>
5527 */
5528 @Override
5529 public void updateStats()
5530 {
5531 if (entering || isLogoutStarted())
5532 {
5533 return;
5534 }
5535
5536 refreshOverloaded();
5537 if (Config.EXPERTISE_PENALTY)
5538 {
5539 refreshExpertisePenalty();
5540 }
5541 super.updateStats();
5542 }
5543
5544 @Override
5545 public void sendChanges()
5546 {
5547 if (entering || isLogoutStarted())
5548 {
5549 return;
5550 }
5551 super.sendChanges();
5552 }
5553
5554 /**
5555 * Send a Server->Client StatusUpdate packet with Karma to the L2Player and all L2Player to inform (broadcast).
5556 * @param flagChanged
5557 */
5558 public void updateKarma(boolean flagChanged)
5559 {
5560 sendStatusUpdate(true, true, StatusUpdate.KARMA);
5561 if (flagChanged)
5562 broadcastRelationChanged();
5563 }
5564
5565 public boolean isOnline()
5566 {
5567 return _isOnline;
5568 }
5569
5570 public void setIsOnline(boolean isOnline)
5571 {
5572 _isOnline = isOnline;
5573 }
5574
5575 public void setOnlineStatus(boolean isOnline)
5576 {
5577 _isOnline = isOnline;
5578 updateOnlineStatus();
5579 }
5580
5581 public void updateOnlineStatus()
5582 {
5583 try (Connection con = DatabaseFactory.getInstance().getConnection();
5584 PreparedStatement statement = con.prepareStatement("UPDATE characters SET online=?, lastAccess=? WHERE obj_id=?"))
5585 {
5586 statement.setInt(1, (isOnline() && !isInOfflineMode()) || (isInOfflineMode() && Config.SHOW_OFFLINE_MODE_IN_ONLINE) ? 1 : 0);
5587 statement.setLong(2, System.currentTimeMillis() / 1000L);
5588 statement.setInt(3, getObjectId());
5589 statement.execute();
5590 }
5591 catch (SQLException e)
5592 {
5593 _log.error("Error while updating Online Status", e);
5594 }
5595 }
5596
5597 /**
5598 * Decrease Karma of the L2Player and Send it StatusUpdate packet with Karma and PvP Flag (broadcast).
5599 * @param add_karma
5600 */
5601 public void increaseKarma(final long add_karma)
5602 {
5603 boolean flagChanged = _karma == 0;
5604 long newKarma = _karma + add_karma;
5605
5606 if (newKarma > Integer.MAX_VALUE)
5607 {
5608 newKarma = Integer.MAX_VALUE;
5609 }
5610
5611 if ((_karma == 0) && (newKarma > 0))
5612 {
5613 if (_pvpFlag > 0)
5614 {
5615 _pvpFlag = 0;
5616 if (_PvPRegTask != null)
5617 {
5618 _PvPRegTask.cancel(true);
5619 _PvPRegTask = null;
5620 }
5621 sendStatusUpdate(true, true, StatusUpdate.PVP_FLAG);
5622 }
5623
5624 _karma = (int) newKarma;
5625 }
5626 else
5627 {
5628 _karma = (int) newKarma;
5629 }
5630
5631 if (getCounters().highestKarma < newKarma)
5632 getCounters().highestKarma = (int) newKarma;
5633
5634 updateKarma(flagChanged);
5635 }
5636
5637 /**
5638 * Decrease Karma of the L2Player and Send it StatusUpdate packet with Karma and PvP Flag (broadcast).
5639 * @param i
5640 */
5641 public void decreaseKarma(final int i)
5642 {
5643 boolean flagChanged = _karma > 0;
5644 _karma -= i;
5645 if (_karma <= 0)
5646 {
5647 _karma = 0;
5648 updateKarma(flagChanged);
5649 }
5650 else
5651 {
5652 updateKarma(false);
5653 }
5654 }
5655
5656 /**
5657 * Create a new L2Player and add it in the characters table of the database.<BR>
5658 * <BR>
5659 * <p/>
5660 * <B><U> Actions</U> :</B><BR>
5661 * <BR>
5662 * <li>Create a new L2Player with an account name</li>
5663 * <li>Set the name, the Hair Style, the Hair Color and the Face type of the L2Player</li>
5664 * <li>Add the player in the characters table of the database</li><BR>
5665 * <BR>
5666 * @param classId
5667 * @param sex
5668 * @param accountName The name of the L2Player
5669 * @param name The name of the L2Player
5670 * @param hairStyle The hair style Identifier of the L2Player
5671 * @param hairColor The hair color Identifier of the L2Player
5672 * @param face The face type Identifier of the L2Player
5673 * @return The L2Player added to the database or null
5674 */
5675 public static Player create(int classId, int sex, String accountName, final String name, final int hairStyle, final int hairColor, final int face)
5676 {
5677 PlayerTemplate template = CharTemplateHolder.getInstance().getTemplate(classId, sex != 0);
5678
5679 // Create a new L2Player with an account name
5680 Player player = new Player(IdFactory.getInstance().getNextId(), template, accountName);
5681
5682 player.setName(name);
5683 player.setTitle("");
5684 player.setHairStyle(hairStyle);
5685 player.setHairColor(hairColor);
5686 player.setFace(face);
5687 player.setCreateTime(System.currentTimeMillis());
5688
5689 // Add the player in the characters table of the database
5690 if (!CharacterDAO.getInstance().insert(player))
5691 {
5692 return null;
5693 }
5694
5695 return player;
5696 }
5697
5698 /**
5699 * Retrieve a L2Player from the characters table of the database and add it in _allObjects of the L2World
5700 * @param objectId
5701 * @return The L2Player loaded from the database
5702 */
5703 public static Player restore(final int objectId)
5704 {
5705 Player player = null;
5706
5707 try (Connection con = DatabaseFactory.getInstance().getConnection();
5708 Statement statement = con.createStatement();
5709 Statement statement2 = con.createStatement();
5710 ResultSet rset = statement.executeQuery("SELECT * FROM `characters` WHERE `obj_Id`=" + objectId + " LIMIT 1");
5711 ResultSet rset2 = statement2.executeQuery("SELECT `class_id` FROM `character_subclasses` WHERE `char_obj_id`=" + objectId + " AND `isBase`=1 LIMIT 1"))
5712 {
5713 if (rset.next() && rset2.next())
5714 {
5715 final int classId = rset2.getInt("class_id");
5716 final boolean female = rset.getInt("sex") == 1;
5717 final PlayerTemplate template = CharTemplateHolder.getInstance().getTemplate(classId, female);
5718
5719 player = new Player(objectId, template);
5720
5721 player.loadVariables(con);
5722 player.loadInstanceReuses(con);
5723 player.loadPremiumItemList(con);
5724 player.bookmarks.setCapacity(rset.getInt("bookmarks"));
5725 player.bookmarks.restore(con);
5726 player._friendList.restore(con);
5727 player._postFriends = CharacterPostFriendDAO.select(player, con);
5728 CharacterGroupReuseDAO.select(player, con);
5729
5730 player._baseClass = classId;
5731 player._login = rset.getString("account_name");
5732 player.setName(rset.getString("char_name"));
5733
5734 player._face = rset.getInt("face");
5735 player._hairStyle = rset.getInt("hairStyle");
5736 player._hairColor = rset.getInt("hairColor");
5737 player.setHeading(0);
5738
5739 player.setKarma(rset.getInt("karma"));
5740 player._pvpKills = rset.getInt("pvpkills");
5741 player._pkKills = rset.getInt("pkkills");
5742 player.raids = rset.getInt("raidkills");
5743 player.soloInstance = rset.getInt("soloinstance");
5744 player.partyInstance = rset.getInt("partyinstance");
5745 player.setLeaveClanTime(rset.getLong("leaveclan") * 1000L);
5746 if (player.getLeaveClanTime() > 0 && player.canJoinClan())
5747 {
5748 player.setLeaveClanTime(0);
5749 }
5750 player.setDeleteClanTime(rset.getLong("deleteclan") * 1000L);
5751 if (player.getDeleteClanTime() > 0 && player.canCreateClan())
5752 {
5753 player.setDeleteClanTime(0);
5754 }
5755 player.setNoChannel(rset.getLong("nochannel") * 1000L);
5756 if ((player._NoChannel > 0L) && (player.getNoChannelRemained() < 0L))
5757 {
5758 player.setNoChannel(0L);
5759 }
5760 player._hwidLock = rset.getString("hwid_lock");
5761 if (player._hwidLock != null && player._hwidLock.isEmpty())
5762 player._hwidLock = null;
5763
5764 if (!player.isInOfflineMode() || !player.isInBuffStore())
5765 {
5766 player.setOnlineTime(rset.getLong("onlinetime") * 1000L);
5767 }
5768
5769 final int clanId = rset.getInt("clanid");
5770 if (clanId > 0)
5771 {
5772 player.setClan(ClanTable.getInstance().getClan(clanId));
5773 player._pledgeType = rset.getInt("pledge_type");
5774 player._powerGrade = rset.getInt("pledge_rank");
5775 player._lvlJoinedAcademy = rset.getInt("lvl_joined_academy");
5776 player._apprentice = rset.getInt("apprentice");
5777 }
5778
5779 player._createTime = rset.getLong("createtime") * 1000L;
5780 player._deleteTimer = rset.getInt("deletetime");
5781
5782 SchemeBufferInstance.loadSchemes(player, con);
5783
5784 player.setTitle(rset.getString("title"));
5785
5786 if (player.getVar("titlecolor") != null)
5787 {
5788 player.setTitleColor(Integer.decode("0x" + player.getVar("titlecolor")).intValue());
5789 }
5790
5791 if (player.getVar("namecolor") == null)
5792 {
5793 if (player.isGM())
5794 {
5795 player.setNameColor(Config.GM_NAME_COLOUR);
5796 }
5797 else if ((player._clan != null) && (player._clan.getLeaderId() == player.getObjectId()))
5798 {
5799 player.setNameColor(Config.CLANLEADER_NAME_COLOUR);
5800 }
5801 else
5802 {
5803 player.setNameColor(Config.NORMAL_NAME_COLOUR);
5804 }
5805 }
5806 else
5807 {
5808 player.setNameColor(Integer.decode("0x" + player.getVar("namecolor")).intValue());
5809 }
5810
5811 if (Config.AUTO_LOOT_INDIVIDUAL)
5812 {
5813 player._autoLoot = player.getVarB("AutoLoot", Config.AUTO_LOOT);
5814 player.AutoLootHerbs = player.getVarB("AutoLootHerbs", Config.AUTO_LOOT_HERBS);
5815 player.AutoLootOnlyAdena = player.getVarB("AutoLootOnlyAdena", Config.AUTO_LOOT_ONLY_ADENA);
5816 }
5817
5818 player._fistsWeaponItem = player.findFistsWeaponItem(classId);
5819 player._uptime = System.currentTimeMillis();
5820 player._lastAccess = rset.getLong("lastAccess");
5821
5822 player.setRecomHave(rset.getInt("rec_have"));
5823 player.setRecomLeft(rset.getInt("rec_left"));
5824 player._recomBonusTime = rset.getInt("rec_bonus_time");
5825
5826 if (player.getVar("recLeftToday") != null)
5827 {
5828 player._recomLeftToday = Integer.parseInt(player.getVar("recLeftToday"));
5829 }
5830 else
5831 {
5832 player._recomLeftToday = 0;
5833 }
5834
5835 player._nevitSystem.setPoints(rset.getInt("hunt_points"), rset.getInt("hunt_time"));
5836
5837 player.setKeyBindings(rset.getBytes("key_bindings"));
5838 player._pcBangPoints = rset.getInt("pcBangPoints");
5839
5840 player._fame = rset.getInt("fame");
5841
5842 player.restoreRecipeBook(con);
5843
5844 if (Config.ENABLE_OLYMPIAD)
5845 {
5846 player._hero = Hero.getInstance().isHero(player.getObjectId());
5847 player._noble = Olympiad.isNoble(player.getObjectId());
5848 }
5849
5850 player.setHwidLock(rset.getString("hwid_lock"));
5851
5852 player.updatePledgeClass();
5853
5854 int reflection = 0;
5855
5856 if (player.isInJail())
5857 {
5858 // randomly spawn in prison
5859 player.setXYZ(Rnd.get(-114936, -114136), Rnd.get(-249768, -248952), -2984);
5860
5861 long period = player.getVarTimeToExpire("jailed");
5862 player.updateNoChannel(period);
5863 player.sitDown(null);
5864 player.block();
5865
5866 if (period != -1)
5867 {
5868 player._unjailTask = ThreadPoolManager.getInstance().schedule(new UnJailTask(player, true), period);
5869 }
5870 }
5871 else if (player.getVar("jailedFrom") != null)
5872 {
5873 String[] re = player.getVar("jailedFrom").split(";");
5874
5875 player.setXYZ(Integer.parseInt(re[0]), Integer.parseInt(re[1]), Integer.parseInt(re[2]));
5876 player.setReflection(re.length > 3 ? Integer.parseInt(re[3]) : 0);
5877
5878 player.unsetVar("jailedFrom");
5879 }
5880 else
5881 {
5882 player.setXYZ(rset.getInt("x"), rset.getInt("y"), rset.getInt("z"));
5883 String ref = player.getVar("reflection");
5884 if (ref != null && Integer.parseInt(ref) != ReflectionManager.JAIL.getId())
5885 {
5886 reflection = Integer.parseInt(ref);
5887 if (reflection > 0) // not the portal back of the GC Parnassus, Gila
5888 {
5889 String back = player.getVar("backCoords");
5890 if (back != null)
5891 {
5892 player.setLoc(Location.parseLoc(back));
5893 player.unsetVar("backCoords");
5894 }
5895 reflection = 0;
5896 }
5897 }
5898 }
5899
5900 player.setReflection(reflection);
5901
5902 EventHolder.getInstance().findEvent(player);
5903
5904 Quest.restoreQuestStates(player, con);
5905
5906 player._inventory.restore();
5907
5908 player.isntAfk();
5909
5910 restoreCharSubClasses(player, con);
5911
5912 //4 points per minute based casino
5913 player.setVitality(rset.getInt("vitality") + (int) (((System.currentTimeMillis() / 1000L) -
5914 rset.getLong("lastAccess")) / 15.));
5915
5916 try
5917 {
5918 String var = player.getVar("ExpandInventory");
5919 if (var != null)
5920 {
5921 player._expandInventory = Integer.parseInt(var);
5922 }
5923 }
5924 catch (NumberFormatException e)
5925 {
5926 _log.error("Error while restoring Expand Inventory ", e);
5927 }
5928
5929 try
5930 {
5931 String var = player.getVar("ExpandWarehouse");
5932 if (var != null)
5933 {
5934 player._expandWarehouse = Integer.parseInt(var);
5935 }
5936 }
5937 catch (NumberFormatException e)
5938 {
5939 _log.error("Error while restoring Expand Warehouse", e);
5940 }
5941
5942 try
5943 {
5944 String var = player.getVar(NO_ANIMATION_OF_CAST_VAR);
5945 if (var != null)
5946 {
5947 player._notShowBuffAnim = Boolean.parseBoolean(var);
5948 }
5949 }
5950 catch (RuntimeException e)
5951 {
5952 _log.error("Error while restoring No Animation Player Config ", e);
5953 }
5954
5955 try
5956 {
5957 String var = player.getVar(NO_TRADERS_VAR);
5958 if (var != null)
5959 {
5960 player._notShowTraders = Boolean.parseBoolean(var);
5961 }
5962 }
5963 catch (RuntimeException e)
5964 {
5965 _log.error("Error while restoring Not Show Traders Player Config", e);
5966 }
5967
5968 try
5969 {
5970 String var = player.getVar("pet");
5971 if (var != null)
5972 {
5973 player.setPetControlItem(Integer.parseInt(var));
5974 }
5975 }
5976 catch (NumberFormatException e)
5977 {
5978 _log.error("Error while restoring Pet Control Item ", e);
5979 }
5980
5981 try
5982 {
5983 String var = player.getVar("isPvPevents");
5984 if (var != null)
5985 {
5986 player.unsetVar("isPvPevents");
5987 }
5988 }
5989 catch (RuntimeException e)
5990 {
5991 _log.error("Error while restoring some strange thing ", e);
5992 }
5993
5994 try (PreparedStatement statement3 = con.prepareStatement("SELECT obj_Id, char_name FROM characters WHERE account_name=? AND obj_Id!=?"))
5995 {
5996 statement3.setString(1, player._login);
5997 statement3.setInt(2, objectId);
5998 try (ResultSet rset3 = statement3.executeQuery())
5999 {
6000 while (rset3.next())
6001 {
6002 final Integer charId = rset3.getInt("obj_Id");
6003 final String charName = rset3.getString("char_name");
6004 player._chars.put(charId, charName);
6005 }
6006 }
6007 }
6008
6009 if (!player.isGM())
6010 {
6011 ArrayList<Zone> zones = new ArrayList<>();
6012
6013 World.getZones(zones, player.getLoc(), player.getReflection());
6014
6015 if (!zones.isEmpty())
6016 {
6017 for (Zone zone : zones)
6018 {
6019 if (zone.getType() == ZoneType.no_restart)
6020 {
6021 if (((System.currentTimeMillis() / 1000L) - player.getLastAccess()) > zone.getRestartTime())
6022 {
6023 player.sendMessage(new CustomMessage("l2f.gameserver.clientpackets.EnterWorld.TeleportedReasonNoRestart", player));
6024 player.setLoc(TeleportUtils.getRestartLocation(player, RestartType.TO_VILLAGE));
6025 }
6026 }
6027 else if (zone.getType() == ZoneType.SIEGE)
6028 {
6029 SiegeEvent<?, ?> siegeEvent = player.getEvent(SiegeEvent.class);
6030 if (siegeEvent != null)
6031 {
6032 player.setLoc(siegeEvent.getEnterLoc(player));
6033 }
6034 else
6035 {
6036 Residence r = ResidenceHolder.getInstance().getResidence(zone.getParams().getInteger("residence"));
6037 player.setLoc(r.getNotOwnerRestartPoint(player));
6038 }
6039 }
6040 }
6041 }
6042
6043 if (DimensionalRiftManager.getInstance().checkIfInRiftZone(player.getLoc(), false))
6044 {
6045 player.setLoc(DimensionalRiftManager.getInstance().getRoom(0, 0).getTeleportCoords());
6046 }
6047 }
6048
6049 player.restoreBlockList(con);
6050 player._macroses.restore(con);
6051
6052 player.refreshExpertisePenalty();
6053 player.refreshOverloaded();
6054
6055 player._warehouse.restore();
6056 player._freight.restore();
6057
6058 player.restoreTradeList();
6059 if (player.getVar("storemode") != null)
6060 {
6061 player.setPrivateStoreType(Integer.parseInt(player.getVar("storemode")));
6062 player._isSitting = true;
6063
6064 if (Config.AUCTION_PRIVATE_STORE_AUTO_ADDED)
6065 {
6066 if (player._privatestore == STORE_PRIVATE_SELL)
6067 {
6068 if (player.getVar("offline") != null)
6069 {
6070 AuctionManager.getInstance().removePlayerStores(player);
6071 }
6072 for (TradeItem item : player._sellList)
6073 {
6074 ItemInstance itemToSell = player._inventory.getItemByItemId(item.getItemId());
6075 Auction a = AuctionManager.getInstance().addNewStore(player, itemToSell, item.getOwnersPrice(), item.getCount());
6076 item.setAuctionId(a.getAuctionId());
6077 }
6078 }
6079 }
6080 }
6081
6082 try
6083 {
6084 String var = player.getVar("FightClubRate");
6085 if (var != null)
6086 {
6087 RestoreFightClub(player);
6088 }
6089 }
6090 catch (RuntimeException e)
6091 {
6092 _log.error("Error while restoring FightClubRate", e);
6093 }
6094
6095 try
6096 {
6097 String var = player.getVar("EnItemOlyRec");
6098 if (Config.OLY_ENCH_LIMIT_ENABLE && (var != null))
6099 {
6100 FixEnchantOlympiad.restoreEnchantItemsOly(player);
6101 }
6102 }
6103 catch (RuntimeException e)
6104 {
6105 _log.error("Error while restoring EnItemOlyRec", e);
6106 }
6107 player.updateKetraVarka();
6108 player.updateRam();
6109 player.checkRecom();
6110 if (player.isCursedWeaponEquipped())
6111 {
6112 player.restoreCursedWeapon();
6113 }
6114
6115 if (Config.ENABLE_PLAYER_COUNTERS)
6116 {
6117 player.getCounters().load();
6118
6119 if (Config.ENABLE_ACHIEVEMENTS)
6120 player.loadAchivements();
6121 }
6122
6123 // Alexander - Get dinamically characters values getting names from the ranking
6124 for (Ranking top : Ranking.values())
6125 {
6126 if (top.getDbLocation().equalsIgnoreCase("characters"))
6127 {
6128 player.getStats().setPlayerStats(top, rset.getLong(top.getDbName()));
6129 }
6130 }
6131 }
6132 }
6133 catch (IllegalArgumentException | SQLException e)
6134 {
6135 _log.error("Could not restore char data! ", e);
6136 }
6137
6138 // Alexander - Now we must get all the stats from the alternative table, using the ranking values
6139 try (Connection conEl = DatabaseFactory.getInstance().getConnection();
6140 PreparedStatement statementEl = conEl.prepareStatement("SELECT variable,value FROM character_stats WHERE charId=?"))
6141 {
6142 statementEl.setInt(1, objectId);
6143 try (ResultSet rsetEl = statementEl.executeQuery())
6144 {
6145 while (rsetEl.next())
6146 {
6147 // Obtengo dinamicamente cada ranking perteneciente a esta tabla con su valor correspondiente
6148 for (Ranking top : Ranking.values())
6149 {
6150 if (player != null && top.getDbName().equalsIgnoreCase(rsetEl.getString("variable")) && top.getDbLocation().equalsIgnoreCase("character_stats"))
6151 {
6152 player.getStats().setPlayerStats(top, rsetEl.getLong("value"));
6153 }
6154 }
6155 }
6156 }
6157 }
6158 catch (Exception e)
6159 {
6160 _log.error("Failed loading character stats", e);
6161 }
6162 return player;
6163 }
6164
6165 private void loadPremiumItemList(Connection con)
6166 {
6167 try (PreparedStatement statement = con.prepareStatement("SELECT itemNum, itemId, itemCount, itemSender FROM character_premium_items WHERE charId=?"))
6168 {
6169 statement.setInt(1, getObjectId());
6170
6171 try (ResultSet rs = statement.executeQuery())
6172 {
6173 while (rs.next())
6174 {
6175 int itemNum = rs.getInt("itemNum");
6176 int itemId = rs.getInt("itemId");
6177 long itemCount = rs.getLong("itemCount");
6178 String itemSender = rs.getString("itemSender");
6179 PremiumItem item = new PremiumItem(itemId, itemCount, itemSender);
6180 _premiumItems.put(itemNum, item);
6181 }
6182 }
6183 }
6184 catch (SQLException e)
6185 {
6186 _log.error("Error while loading Premium Item List for Id "+getObjectId(), e);
6187 }
6188 }
6189
6190 public void updatePremiumItem(int itemNum, long newcount)
6191 {
6192 try (Connection con = DatabaseFactory.getInstance().getConnection();
6193 PreparedStatement statement = con.prepareStatement("UPDATE character_premium_items SET itemCount=? WHERE charId=? AND itemNum=?"))
6194 {
6195 statement.setLong(1, newcount);
6196 statement.setInt(2, getObjectId());
6197 statement.setInt(3, itemNum);
6198 statement.execute();
6199 }
6200 catch (SQLException e)
6201 {
6202 _log.error("Error while updating Premium Items", e);
6203 }
6204 }
6205
6206 public void deletePremiumItem(int itemNum)
6207 {
6208 try (Connection con = DatabaseFactory.getInstance().getConnection();
6209 PreparedStatement statement = con.prepareStatement("DELETE FROM character_premium_items WHERE charId=? AND itemNum=?"))
6210 {
6211 statement.setInt(1, getObjectId());
6212 statement.setInt(2, itemNum);
6213 statement.execute();
6214 }
6215 catch (SQLException e)
6216 {
6217 _log.error("Error while deleting Premium Item", e);
6218 }
6219 }
6220
6221 public Map<Integer, PremiumItem> getPremiumItemList()
6222 {
6223 return _premiumItems;
6224 }
6225
6226 /**
6227 * Update L2Player stats in the characters table of the database.
6228 * @param fast
6229 */
6230 public void store(boolean fast)
6231 {
6232 if (!_storeLock.tryLock())
6233 {
6234 return;
6235 }
6236
6237 try
6238 {
6239 try (Connection con = DatabaseFactory.getInstance().getConnection();
6240 PreparedStatement statement = con.prepareStatement(//
6241 "UPDATE characters SET face=?,hairStyle=?,hairColor=?,x=?,y=?,z=?" + //
6242 ",karma=?,pvpkills=?,pkkills=?,rec_have=?,rec_left=?,rec_bonus_time=?,hunt_points=?,hunt_time=?,clanid=?,deletetime=?," + //
6243 "title=?,accesslevel=?,online=?,leaveclan=?,deleteclan=?,nochannel=?," + //
6244 "onlinetime=?,pledge_type=?,pledge_rank=?,lvl_joined_academy=?,apprentice=?,key_bindings=?,pcBangPoints=?,char_name=?,vitality=?,fame=?,bookmarks=?,hwid_lock=?,raidkills=?,soloinstance=?,partyinstance=? WHERE obj_Id=? LIMIT 1");)
6245 {
6246 statement.setInt(1, getFace());
6247 statement.setInt(2, getHairStyle());
6248 statement.setInt(3, getHairColor());
6249 if (_stablePoint == null)
6250 {
6251 statement.setInt(4, getX());
6252 statement.setInt(5, getY());
6253 statement.setInt(6, getZ());
6254 }
6255 else
6256 {
6257 statement.setInt(4, _stablePoint.x);
6258 statement.setInt(5, _stablePoint.y);
6259 statement.setInt(6, _stablePoint.z);
6260 }
6261 statement.setInt(7, getKarma());
6262 statement.setInt(8, getPvpKills());
6263 statement.setInt(9, getPkKills());
6264 statement.setInt(10, getRecomHave());
6265 statement.setInt(11, getRecomLeft());
6266 statement.setInt(12, getRecomBonusTime());
6267 statement.setInt(13, getNevitSystem().getPoints());
6268 statement.setInt(14, getNevitSystem().getTime());
6269 statement.setInt(15, getClanId());
6270 statement.setInt(16, getDeleteTimer());
6271 statement.setString(17, _title);
6272 statement.setInt(18, _accessLevel);
6273 statement.setInt(19, (isOnline() && !isInOfflineMode()) || (isInOfflineMode() && Config.SHOW_OFFLINE_MODE_IN_ONLINE) ? 1 : 0);
6274 statement.setLong(20, getLeaveClanTime() / 1000L);
6275 statement.setLong(21, getDeleteClanTime() / 1000L);
6276 statement.setLong(22, _NoChannel > 0 ? getNoChannelRemained() / 1000 : _NoChannel);
6277 statement.setInt(23, (int)(getOnlineTime() / 1000L));
6278 statement.setInt(24, getPledgeType());
6279 statement.setInt(25, getPowerGrade());
6280 statement.setInt(26, getLvlJoinedAcademy());
6281 statement.setInt(27, getApprentice());
6282 statement.setBytes(28, getKeyBindings());
6283 statement.setInt(29, getPcBangPoints());
6284 statement.setString(30, getName());
6285 statement.setInt(31, (int) getVitality());
6286 statement.setInt(32, getFame());
6287 statement.setInt(33, bookmarks.getCapacity());
6288 statement.setString(34, getHwidLock());
6289 statement.setInt(35, getRaidKills());
6290 statement.setInt(36, getSoloInstance());
6291 statement.setInt(37, getPartyInstance());
6292 statement.setInt(38, getObjectId());
6293
6294 statement.executeUpdate();
6295 if (Config.RATE_DROP_ADENA < 20)
6296 {
6297 GameStats.increaseUpdatePlayerBase();
6298 }
6299
6300 if (!fast)
6301 {
6302 EffectsDAO.getInstance().insert(this);
6303 CharacterGroupReuseDAO.getInstance().insert(this);
6304 storeDisableSkills();
6305 storeBlockList();
6306 }
6307
6308 storeCharSubClasses();
6309 bookmarks.store();
6310
6311 if (Config.ENABLE_PLAYER_COUNTERS)
6312 {
6313 getCounters().save();
6314
6315 if (Config.ENABLE_ACHIEVEMENTS)
6316 saveAchivements();
6317 }
6318
6319 // Alexander - When closing character, we must add the online value to the stats for it to be saved
6320// addPlayerStats(Ranking.STAT_TOP_ONLINE, getOnlineTime());
6321 if (!isInOfflineMode() || !isInBuffStore()) {
6322 addPlayerStats(Ranking.STAT_TOP_ONLINE, Math.max(Math.round(getOnlineTime() / 1000), getStats().getPlayerStats(Ranking.STAT_TOP_ONLINE)));
6323 }
6324 // Alexander - The same for the longest online time, we must calculate it on exit
6325 if (!isInOfflineMode() || !isInBuffStore()) {
6326 addPlayerStats(Ranking.STAT_TOP_LONGEST_ONLINE_TIME, Math.max(Math.round((System.currentTimeMillis() - _onlineBeginTime) / 60000), getStats().getPlayerStats(Ranking.STAT_TOP_LONGEST_ONLINE_TIME)));
6327 }
6328 // Alexander - We create a dynamic query to update the stats based on the ranking values that use the character_stats table
6329 try (PreparedStatement statementEl = con.prepareStatement("REPLACE INTO character_stats VALUES (?, ?, ?)"))
6330 {
6331 // Agrego dinamicamente cada ranking perteneciente a esta tabla con su valor correspondiente, para lograr un update totalmente dinamico
6332 for (Ranking top : Ranking.values())
6333 {
6334 if (top.getDbLocation().equalsIgnoreCase("character_stats"))
6335 {
6336 // Solo lo salvamos si el cantidad es mayor a 0, sino creamos celdas en la db al pedo, el default es 0
6337 if (getStats().getPlayerStats(top) > 0)
6338 {
6339 statementEl.setInt(1, getObjectId());
6340 statementEl.setString(2, top.getDbName());
6341 statementEl.setLong(3, getStats().getPlayerStats(top));
6342 statementEl.execute();
6343 }
6344 }
6345 }
6346 }
6347 }
6348 catch (SQLException e)
6349 {
6350 _log.error("Could not store char data: " + this + '!', e);
6351 }
6352 }
6353 finally
6354 {
6355 _storeLock.unlock();
6356 }
6357 }
6358
6359 private int raids;
6360
6361 public void updateRaidKills()
6362 {
6363 this.raids++;
6364 }
6365
6366 public int getRaidKills()
6367 {
6368 return raids;
6369 }
6370 /**
6371 * Add a skill to the L2Player _skills and its Func objects to the calculator set of the L2Player and save update in the character_skills table of the database.
6372 * @param newSkill
6373 * @param store
6374 * @return The L2Skill replaced or null if just added a new L2Skill
6375 */
6376 public Skill addSkill(final Skill newSkill, final boolean store)
6377 {
6378 if (newSkill == null)
6379 {
6380 return null;
6381 }
6382
6383 // Fix If the skill existed before, then we must transfer its reuse to the new level. Its a known exploit of enchant a skill to reset its reuse
6384 if (getKnownSkill(newSkill.getId()) != null)
6385 {
6386 disableSkillByNewLvl(SkillTable.getInstance().getInfo(newSkill.getId(), getKnownSkill(newSkill.getId()).getLevel()).hashCode(),
6387 SkillTable.getInstance().getInfo(newSkill.getId(), newSkill.getLevel()).hashCode());
6388 }
6389 // Add a skill to the L2Player _skills and its Func objects to the calculator set of the L2Player
6390 Skill oldSkill = super.addSkill(newSkill);
6391
6392 if (newSkill.equals(oldSkill))
6393 {
6394 return oldSkill;
6395 }
6396
6397 // Add or update a L2Player skill in the character_skills table of the database
6398 if (store)
6399 {
6400 storeSkill(newSkill, oldSkill);
6401 }
6402
6403 return oldSkill;
6404 }
6405
6406 public Skill removeSkill(Skill skill, boolean fromDB)
6407 {
6408 if (skill == null)
6409 {
6410 return null;
6411 }
6412 return removeSkill(skill.getId(), fromDB);
6413 }
6414
6415 /**
6416 * 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.
6417 * @param id
6418 * @param fromDB
6419 * @return The L2Skill removed
6420 */
6421 public Skill removeSkill(int id, boolean fromDB)
6422 {
6423 // Remove a skill from the L2Character and its Func objects from calculator set of the L2Character
6424 Skill oldSkill = super.removeSkillById(id);
6425
6426 if (!fromDB)
6427 {
6428 return oldSkill;
6429 }
6430
6431 if (oldSkill != null)
6432 {
6433 try (Connection con = DatabaseFactory.getInstance().getConnection();
6434 PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills WHERE skill_id=? AND char_obj_id=? AND class_index=?"))
6435 {
6436 // Remove or update a L2Player skill from the character_skills table of the database
6437 statement.setInt(1, oldSkill.getId());
6438 statement.setInt(2, getObjectId());
6439 statement.setInt(3, getActiveClassId());
6440 statement.execute();
6441 }
6442 catch (final Exception e)
6443 {
6444 _log.error("Could not delete skill!", e);
6445 }
6446 }
6447
6448 return oldSkill;
6449 }
6450
6451 /**
6452 * Add or update a L2Player skill in the character_skills table of the database.
6453 * @param newSkill
6454 * @param oldSkill
6455 */
6456 private void storeSkill(final Skill newSkill, final Skill oldSkill)
6457 {
6458 if (newSkill == null)
6459 {
6460 _log.warn("could not store new skill. its NULL");
6461 return;
6462 }
6463
6464 try (Connection con = DatabaseFactory.getInstance().getConnection();
6465 PreparedStatement statement = con.prepareStatement("REPLACE INTO character_skills (char_obj_id,skill_id,skill_level,class_index) values(?,?,?,?)"))
6466 {
6467 statement.setInt(1, getObjectId());
6468 statement.setInt(2, newSkill.getId());
6469 statement.setInt(3, newSkill.getLevel());
6470 statement.setInt(4, getActiveClassId());
6471 statement.execute();
6472 }
6473 catch (SQLException e)
6474 {
6475 _log.error("Error could not store skills!", e);
6476 }
6477 }
6478
6479 /**
6480 * Retrieve from the database all skills of this L2Player and add them to _skills.
6481 */
6482 private void restoreSkills()
6483 {
6484 PreparedStatement statement = null;
6485 try (Connection con = DatabaseFactory.getInstance().getConnection())
6486 {
6487 // Retrieve all skills of this L2Player from the database
6488 // Send the SQL query : SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? to the database
6489 if (Config.ALT_ENABLE_MULTI_PROFA)
6490 {
6491 statement = con.prepareStatement("SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=?");
6492 statement.setInt(1, getObjectId());
6493 }
6494 else
6495 {
6496 statement = con.prepareStatement("SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? AND class_index=?");
6497 statement.setInt(1, getObjectId());
6498 statement.setInt(2, getActiveClassId());
6499 }
6500
6501 try (ResultSet rset = statement.executeQuery())
6502 {
6503 // Go though the recordset of this SQL query
6504 while (rset.next())
6505 {
6506 final int id = rset.getInt("skill_id");
6507 final int level = rset.getInt("skill_level");
6508
6509 // Create a L2Skill object for each record
6510 final Skill skill = SkillTable.getInstance().getInfo(id, level);
6511
6512 if (skill == null)
6513 {
6514 continue;
6515 }
6516
6517 // Remove skill if not possible
6518 if (!isGM() && !SkillAcquireHolder.getInstance().isSkillPossible(this, skill))
6519 {
6520 // int ReturnSP = SkillTreeTable.getInstance().getSkillCost(this, skill);
6521 // if (ReturnSP == Integer.MAX_VALUE || ReturnSP < 0)
6522 // ReturnSP = 0;
6523 removeSkill(skill, true);
6524 removeSkillFromShortCut(skill.getId());
6525 // if (ReturnSP > 0)
6526 // setSp(getSp() + ReturnSP);
6527 continue;
6528 }
6529
6530 super.addSkill(skill);
6531 }
6532 }
6533
6534 // Restore noble skills
6535 if (isNoble())
6536 {
6537 updateNobleSkills();
6538 }
6539
6540 // Restore Hero skills at main class only
6541 if (_hero && (getBaseClassId() == getActiveClassId()))
6542 {
6543 Hero.addSkills(this);
6544 }
6545
6546 // Restore clan skills
6547 if (_clan != null)
6548 {
6549 _clan.addSkillsQuietly(this);
6550
6551 // Restore clan leader siege skills
6552 if ((_clan.getLeaderId() == getObjectId()) && (_clan.getLevel() >= 5))
6553 {
6554 SiegeUtils.addSiegeSkills(this);
6555 }
6556 }
6557
6558 // Give dwarven craft skill
6559 if (((getActiveClassId() >= 53) && (getActiveClassId() <= 57)) || (getActiveClassId() == 117) || (getActiveClassId() == 118))
6560 {
6561 super.addSkill(SkillTable.getInstance().getInfo(1321, 1));
6562 }
6563
6564 super.addSkill(SkillTable.getInstance().getInfo(1322, 1));
6565
6566 if (Config.UNSTUCK_SKILL && (getSkillLevel(1050) < 0))
6567 {
6568 super.addSkill(SkillTable.getInstance().getInfo(2099, 1));
6569 }
6570 }
6571 catch (SQLException e)
6572 {
6573 _log.warn("Could not restore skills for player objId: " + getObjectId(), e);
6574 }
6575 finally
6576 {
6577 DbUtils.closeQuietly(statement);
6578 }
6579 }
6580
6581 public void storeDisableSkills()
6582 {
6583 try (Connection con = DatabaseFactory.getInstance().getConnection();
6584 Statement statement = con.createStatement())
6585 {
6586 statement.executeUpdate("DELETE FROM character_skills_save WHERE char_obj_id = " + getObjectId() + " AND class_index=" + getActiveClassId() + " AND `end_time` < " + System.currentTimeMillis());
6587
6588 if (_skillReuses.isEmpty())
6589 {
6590 return;
6591 }
6592
6593 SqlBatch b = new SqlBatch("REPLACE INTO `character_skills_save` (`char_obj_id`,`skill_id`,`skill_level`,`class_index`,`end_time`,`reuse_delay_org`) VALUES");
6594 synchronized (_skillReuses)
6595 {
6596 StringBuilder sb;
6597 for (TimeStamp timeStamp : _skillReuses.values())
6598 {
6599 if (timeStamp.hasNotPassed())
6600 {
6601 sb = new StringBuilder("(");
6602 sb.append(getObjectId()).append(",");
6603 sb.append(timeStamp.getId()).append(",");
6604 sb.append(timeStamp.getLevel()).append(",");
6605 sb.append(getActiveClassId()).append(",");
6606 sb.append(timeStamp.getEndTime()).append(",");
6607 sb.append(timeStamp.getReuseBasic()).append(")");
6608 b.write(sb.toString());
6609 }
6610 }
6611 }
6612 if (!b.isEmpty())
6613 {
6614 statement.executeUpdate(b.close());
6615 }
6616 }
6617 catch (final Exception e)
6618 {
6619 _log.warn("Could not store disable skills data: " + e);
6620 }
6621 }
6622
6623 public void restoreDisableSkills()
6624 {
6625 _skillReuses.clear();
6626
6627 try (Connection con = DatabaseFactory.getInstance().getConnection();
6628 Statement statement = con.createStatement();)
6629 {
6630
6631 try (ResultSet rset = statement.executeQuery("SELECT skill_id,skill_level,end_time,reuse_delay_org FROM character_skills_save WHERE char_obj_id=" + getObjectId() + " AND class_index=" + getActiveClassId()))
6632 {
6633 while (rset.next())
6634 {
6635 int skillId = rset.getInt("skill_id");
6636 int skillLevel = rset.getInt("skill_level");
6637 long endTime = rset.getLong("end_time");
6638 long rDelayOrg = rset.getLong("reuse_delay_org");
6639 long curTime = System.currentTimeMillis();
6640
6641 Skill skill = SkillTable.getInstance().getInfo(skillId, skillLevel);
6642
6643 if ((skill != null) && ((endTime - curTime) > 500))
6644 {
6645 _skillReuses.put(skill.hashCode(), new TimeStamp(skill, endTime, rDelayOrg));
6646 }
6647 }
6648 }
6649
6650 statement.executeUpdate("DELETE FROM character_skills_save WHERE char_obj_id = " + getObjectId() + " AND class_index=" + getActiveClassId() + " AND `end_time` < " + System.currentTimeMillis());
6651 }
6652 catch (Exception e)
6653 {
6654 _log.error("Could not restore active skills data!", e);
6655 }
6656 }
6657
6658 /**
6659 * Retrieve from the database all Henna of this L2Player, add them to _henna and calculate stats of the L2Player.<BR>
6660 * <BR>
6661 */
6662 private void restoreHenna()
6663 {
6664 try (Connection con = DatabaseFactory.getInstance().getConnection();
6665 PreparedStatement statement = con.prepareStatement("select slot, symbol_id from character_hennas where char_obj_id=? AND class_index=?"))
6666 {
6667 statement.setInt(1, getObjectId());
6668 statement.setInt(2, getActiveClassId());
6669
6670 try (ResultSet rset = statement.executeQuery())
6671 {
6672 for (int i = 0; i < 3; i++)
6673 {
6674 _henna[i] = null;
6675 }
6676
6677 while (rset.next())
6678 {
6679 final int slot = rset.getInt("slot");
6680 if ((slot < 1) || (slot > 3))
6681 {
6682 continue;
6683 }
6684
6685 final int symbol_id = rset.getInt("symbol_id");
6686
6687 if (symbol_id != 0)
6688 {
6689 final Henna tpl = HennaHolder.getInstance().getHenna(symbol_id);
6690 if (tpl != null)
6691 {
6692 _henna[slot - 1] = tpl;
6693 }
6694 }
6695 }
6696 }
6697 }
6698 catch (final Exception e)
6699 {
6700 _log.warn("could not restore henna: " + e);
6701 }
6702
6703 // Calculate Henna modifiers of this L2Player
6704 recalcHennaStats();
6705
6706 }
6707
6708 public int getHennaEmptySlots()
6709 {
6710 int totalSlots = 1 + getClassId().level();
6711 for (int i = 0; i < 3; i++)
6712 {
6713 if (_henna[i] != null)
6714 {
6715 totalSlots--;
6716 }
6717 }
6718
6719 if (totalSlots <= 0)
6720 {
6721 return 0;
6722 }
6723
6724 return totalSlots;
6725
6726 }
6727
6728 /**
6729 * Remove a Henna of the L2Player, save update in the character_hennas table of the database and send Server->Client HennaInfo/UserInfo packet to this L2Player.<BR>
6730 * <BR>
6731 * @param slot
6732 * @return
6733 */
6734 public boolean removeHenna(int slot)
6735 {
6736 if ((slot < 1) || (slot > 3))
6737 {
6738 return false;
6739 }
6740
6741 slot--;
6742
6743 if (_henna[slot] == null)
6744 {
6745 return false;
6746 }
6747
6748 final Henna henna = _henna[slot];
6749 final int dyeID = henna.getDyeId();
6750
6751 _henna[slot] = null;
6752
6753 try (Connection con = DatabaseFactory.getInstance().getConnection();
6754 PreparedStatement statement = con.prepareStatement("DELETE FROM character_hennas where char_obj_id=? and slot=? and class_index=?"))
6755 {
6756 statement.setInt(1, getObjectId());
6757 statement.setInt(2, slot + 1);
6758 statement.setInt(3, getActiveClassId());
6759 statement.execute();
6760 }
6761 catch (final Exception e)
6762 {
6763 _log.warn("could not remove char henna: " + e, e);
6764 }
6765
6766 // Calculate Henna modifiers of this L2Player
6767 recalcHennaStats();
6768
6769 // Send Server->Client HennaInfo packet to this L2Player
6770 sendPacket(new HennaInfo(this));
6771 // Send Server->Client UserInfo packet to this L2Player
6772 sendUserInfo(true);
6773
6774 // Add the recovered dyes to the player's inventory and notify them.
6775 ItemFunctions.addItem(this, dyeID, henna.getDrawCount() / 2, true, "removeHenna");
6776
6777 return true;
6778 }
6779
6780 /**
6781 * Add a Henna to the L2Player, save update in the character_hennas table of the database and send Server->Client HennaInfo/UserInfo packet to this L2Player.<BR>
6782 * @param henna
6783 * @return
6784 */
6785 public boolean addHenna(Henna henna)
6786 {
6787 if (getHennaEmptySlots() == 0)
6788 {
6789 sendPacket(SystemMsg.NO_SLOT_EXISTS_TO_DRAW_THE_SYMBOL);
6790 return false;
6791 }
6792
6793 int slot = 0;
6794 for (int i = 0; i < 3; i++)
6795 {
6796 if (_henna[i] == null)
6797 {
6798 _henna[i] = henna;
6799
6800 // Calculate Henna modifiers of this L2Player
6801 recalcHennaStats();
6802
6803 try (Connection con = DatabaseFactory.getInstance().getConnection();
6804 PreparedStatement statement = con.prepareStatement("INSERT INTO `character_hennas` (char_obj_id, symbol_id, slot, class_index) VALUES (?,?,?,?)"))
6805 {
6806 statement.setInt(1, getObjectId());
6807 statement.setInt(2, henna.getSymbolId());
6808 statement.setInt(3, i + 1);
6809 statement.setInt(4, getActiveClassId());
6810 statement.execute();
6811 }
6812 catch (Exception e)
6813 {
6814 _log.warn("could not save char henna: " + e);
6815 }
6816
6817 sendPacket(new HennaInfo(this));
6818 sendUserInfo(true);
6819
6820 return true;
6821 }
6822 }
6823
6824 return false;
6825 }
6826
6827 /**
6828 * Calculate Henna modifiers of this L2Player.
6829 */
6830 private void recalcHennaStats()
6831 {
6832 _hennaINT = 0;
6833 _hennaSTR = 0;
6834 _hennaCON = 0;
6835 _hennaMEN = 0;
6836 _hennaWIT = 0;
6837 _hennaDEX = 0;
6838
6839 for (int i = 0; i < 3; i++)
6840 {
6841 Henna henna = _henna[i];
6842 if (henna == null)
6843 {
6844 continue;
6845 }
6846 if (!henna.isForThisClass(this))
6847 {
6848 continue;
6849 }
6850
6851 _hennaINT += henna.getStatINT();
6852 _hennaSTR += henna.getStatSTR();
6853 _hennaMEN += henna.getStatMEN();
6854 _hennaCON += henna.getStatCON();
6855 _hennaWIT += henna.getStatWIT();
6856 _hennaDEX += henna.getStatDEX();
6857 }
6858
6859 if (_hennaINT > Config.HENNA_STATS)
6860 {
6861 _hennaINT = Config.HENNA_STATS;
6862 }
6863 if (_hennaSTR > Config.HENNA_STATS)
6864 {
6865 _hennaSTR = Config.HENNA_STATS;
6866 }
6867 if (_hennaMEN > Config.HENNA_STATS)
6868 {
6869 _hennaMEN = Config.HENNA_STATS;
6870 }
6871 if (_hennaCON > Config.HENNA_STATS)
6872 {
6873 _hennaCON = Config.HENNA_STATS;
6874 }
6875 if (_hennaWIT > Config.HENNA_STATS)
6876 {
6877 _hennaWIT = Config.HENNA_STATS;
6878 }
6879 if (_hennaDEX > Config.HENNA_STATS)
6880 {
6881 _hennaDEX = Config.HENNA_STATS;
6882 }
6883 }
6884
6885 /**
6886 * @param slot
6887 * @return the Henna of this L2Player corresponding to the selected slot.<BR>
6888 * <BR>
6889 */
6890 public Henna getHenna(final int slot)
6891 {
6892 if ((slot < 1) || (slot > 3))
6893 {
6894 return null;
6895 }
6896 return _henna[slot - 1];
6897 }
6898
6899 public int getHennaStatINT()
6900 {
6901 return _hennaINT;
6902 }
6903
6904 public int getHennaStatSTR()
6905 {
6906 return _hennaSTR;
6907 }
6908
6909 public int getHennaStatCON()
6910 {
6911 return _hennaCON;
6912 }
6913
6914 public int getHennaStatMEN()
6915 {
6916 return _hennaMEN;
6917 }
6918
6919 public int getHennaStatWIT()
6920 {
6921 return _hennaWIT;
6922 }
6923
6924 public int getHennaStatDEX()
6925 {
6926 return _hennaDEX;
6927 }
6928
6929 @Override
6930 public boolean consumeItem(int itemConsumeId, long itemCount)
6931 {
6932 if (getInventory().destroyItemByItemId(itemConsumeId, itemCount, "Consume"))
6933 {
6934 sendPacket(SystemMessage2.removeItems(itemConsumeId, itemCount));
6935 return true;
6936 }
6937 return false;
6938 }
6939
6940 @Override
6941 public boolean consumeItemMp(int itemId, int mp)
6942 {
6943 for (ItemInstance item : getInventory().getPaperdollItems())
6944 {
6945 if ((item != null) && (item.getItemId() == itemId))
6946 {
6947 final int newMp = item.getLifeTime() - mp;
6948 if (newMp >= 0)
6949 {
6950 item.setLifeTime(newMp);
6951 sendPacket(new InventoryUpdate().addModifiedItem(item));
6952 return true;
6953 }
6954 break;
6955 }
6956 }
6957 return false;
6958 }
6959
6960 /**
6961 * @return True if the L2Player is a Mage.<BR>
6962 * <BR>
6963 */
6964 @Override
6965 public boolean isMageClass()
6966 {
6967 return _template.baseMAtk > 3;
6968 }
6969
6970 public boolean isMounted()
6971 {
6972 return _mountNpcId > 0;
6973 }
6974
6975 public final boolean isRiding()
6976 {
6977 return _riding;
6978 }
6979
6980 public final void setRiding(boolean mode)
6981 {
6982 _riding = mode;
6983 }
6984
6985 public boolean checkLandingState()
6986 {
6987 if (isInZone(ZoneType.no_landing))
6988 {
6989 return false;
6990 }
6991
6992 SiegeEvent<?, ?> siege = getEvent(SiegeEvent.class);
6993 if (siege != null)
6994 {
6995 Residence unit = siege.getResidence();
6996 if ((unit != null) && (getClan() != null) && isClanLeader() && ((getClan().getCastle() == unit.getId()) || (getClan().getHasFortress() == unit.getId())))
6997 {
6998 return true;
6999 }
7000 return false;
7001 }
7002
7003 return true;
7004 }
7005
7006 public void dismount()
7007 {
7008 setMount(0, 0, 0);
7009 }
7010
7011 public void setMount(int npcId, int obj_id, int level)
7012 {
7013 if (isCursedWeaponEquipped())
7014 {
7015 return;
7016 }
7017
7018 switch (npcId)
7019 {
7020 case 0: // Dismount
7021 setFlying(false);
7022 setRiding(false);
7023 if (getTransformation() > 0)
7024 {
7025 setTransformation(0);
7026 }
7027 removeSkillById(Skill.SKILL_STRIDER_ASSAULT);
7028 removeSkillById(Skill.SKILL_WYVERN_BREATH);
7029 getEffectList().stopEffect(Skill.SKILL_HINDER_STRIDER);
7030 break;
7031 case PetDataTable.STRIDER_WIND_ID:
7032 case PetDataTable.STRIDER_STAR_ID:
7033 case PetDataTable.STRIDER_TWILIGHT_ID:
7034 case PetDataTable.RED_STRIDER_WIND_ID:
7035 case PetDataTable.RED_STRIDER_STAR_ID:
7036 case PetDataTable.RED_STRIDER_TWILIGHT_ID:
7037 case PetDataTable.GUARDIANS_STRIDER_ID:
7038 setRiding(true);
7039 if (isNoble())
7040 {
7041 addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_STRIDER_ASSAULT, 1), false);
7042 }
7043 break;
7044 case PetDataTable.WYVERN_ID:
7045 setFlying(true);
7046 setLoc(getLoc().changeZ(32));
7047 addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_WYVERN_BREATH, 1), false);
7048 break;
7049 case PetDataTable.WGREAT_WOLF_ID:
7050 case PetDataTable.FENRIR_WOLF_ID:
7051 case PetDataTable.WFENRIR_WOLF_ID:
7052 setRiding(true);
7053 break;
7054 }
7055
7056 if (npcId > 0)
7057 {
7058 unEquipWeapon();
7059 }
7060
7061 _mountNpcId = npcId;
7062 _mountObjId = obj_id;
7063 _mountLevel = level;
7064
7065 broadcastUserInfo(true);
7066 broadcastPacket(new Ride(this));
7067 broadcastUserInfo(true);
7068
7069 sendPacket(new SkillList(this));
7070 }
7071
7072 public void unEquipWeapon()
7073 {
7074 ItemInstance wpn = getSecondaryWeaponInstance();
7075 if (wpn != null)
7076 {
7077 sendDisarmMessage(wpn);
7078 getInventory().unEquipItem(wpn);
7079 }
7080
7081 wpn = getActiveWeaponInstance();
7082 if (wpn != null)
7083 {
7084 sendDisarmMessage(wpn);
7085 getInventory().unEquipItem(wpn);
7086 }
7087
7088 abortAttack(true, true);
7089 abortCast(true, true);
7090 }
7091
7092 @Override
7093 public int getSpeed(int baseSpeed)
7094 {
7095 if (isMounted())
7096 {
7097 PetData petData = PetDataTable.getInstance().getInfo(_mountNpcId, _mountLevel);
7098 int speed = 187;
7099 if (petData != null)
7100 {
7101 speed = petData.getSpeed();
7102 }
7103 double mod = 1.;
7104 int level = getLevel();
7105 if ((_mountLevel > level) && ((level - _mountLevel) > 10))
7106 {
7107 mod = 0.5;
7108 }
7109 baseSpeed = (int) (mod * speed);
7110 }
7111 return super.getSpeed(baseSpeed);
7112 }
7113
7114 private int _mountNpcId;
7115 private int _mountObjId;
7116 private int _mountLevel;
7117
7118 public int getMountNpcId()
7119 {
7120 return _mountNpcId;
7121 }
7122
7123 public int getMountObjId()
7124 {
7125 return _mountObjId;
7126 }
7127
7128 public int getMountLevel()
7129 {
7130 return _mountLevel;
7131 }
7132
7133 public void sendDisarmMessage(ItemInstance wpn)
7134 {
7135 if (wpn.getEnchantLevel() > 0)
7136 {
7137 SystemMessage sm = new SystemMessage(SystemMessage.EQUIPMENT_OF__S1_S2_HAS_BEEN_REMOVED);
7138 sm.addNumber(wpn.getEnchantLevel());
7139 sm.addItemName(wpn.getItemId());
7140 sendPacket(sm);
7141 }
7142 else
7143 {
7144 SystemMessage sm = new SystemMessage(SystemMessage.S1__HAS_BEEN_DISARMED);
7145 sm.addItemName(wpn.getItemId());
7146 sendPacket(sm);
7147 }
7148 }
7149
7150 public void setUsingWarehouseType(final WarehouseType type)
7151 {
7152 _usingWHType = type;
7153 }
7154
7155 public WarehouseType getUsingWarehouseType()
7156 {
7157 return _usingWHType;
7158 }
7159
7160 public Warehouse getWithdrawWarehouse()
7161 {
7162 return _withdrawWarehouse;
7163 }
7164
7165 public void setWithdrawWarehouse(Warehouse withdrawWarehouse)
7166 {
7167 _withdrawWarehouse = withdrawWarehouse;
7168 }
7169
7170 public Collection<EffectCubic> getCubics()
7171 {
7172 return _cubics == null ? Collections.<EffectCubic> emptyList() : _cubics.values();
7173 }
7174
7175 public void addCubic(EffectCubic cubic)
7176 {
7177 if (_cubics == null)
7178 {
7179 _cubics = new ConcurrentHashMap<>(3);
7180 }
7181 _cubics.put(cubic.getId(), cubic);
7182 }
7183
7184 public void removeCubic(int id)
7185 {
7186 if (_cubics != null)
7187 {
7188 _cubics.remove(id);
7189 }
7190 }
7191
7192 public EffectCubic getCubic(int id)
7193 {
7194 return _cubics == null ? null : _cubics.get(id);
7195 }
7196
7197 @Override
7198 public String toString()
7199 {
7200 return getName() + "[" + getObjectId() + "]";
7201 }
7202
7203 /**
7204 * @return the modifier corresponding to the Enchant Effect of the Active Weapon (Min : 127).<BR>
7205 * <BR>
7206 */
7207 public int getEnchantEffect()
7208 {
7209 final ItemInstance wpn = getActiveWeaponInstance();
7210
7211 if (wpn == null)
7212 {
7213 return 0;
7214 }
7215
7216 return Math.min(127, wpn.getEnchantLevel());
7217 }
7218
7219 /**
7220 * Set the _lastFolkNpc of the L2Player corresponding to the last Folk witch one the player talked.<BR>
7221 * <BR>
7222 * @param npc
7223 */
7224 public void setLastNpc(final NpcInstance npc)
7225 {
7226 if (npc == null)
7227 {
7228 _lastNpc = HardReferences.emptyRef();
7229 }
7230 else
7231 {
7232 _lastNpc = npc.getRef();
7233 }
7234 }
7235
7236 /**
7237 * @return the _lastFolkNpc of the L2Player corresponding to the last Folk witch one the player talked.<BR>
7238 * <BR>
7239 */
7240 public NpcInstance getLastNpc()
7241 {
7242 return _lastNpc.get();
7243 }
7244
7245 public void setMultisell(MultiSellListContainer multisell)
7246 {
7247 _multisell = multisell;
7248 }
7249
7250 public MultiSellListContainer getMultisell()
7251 {
7252 return _multisell;
7253 }
7254
7255 /**
7256 * @return True if L2Player is a participant in the Festival of Darkness.<BR>
7257 * <BR>
7258 */
7259 public boolean isFestivalParticipant()
7260 {
7261 return getReflection() instanceof DarknessFestival;
7262 }
7263
7264 @Override
7265 public boolean unChargeShots(boolean spirit)
7266 {
7267 ItemInstance weapon = getActiveWeaponInstance();
7268 if (weapon == null)
7269 {
7270 return false;
7271 }
7272
7273 if (spirit)
7274 {
7275 weapon.setChargedSpiritshot(ItemInstance.CHARGED_NONE);
7276 }
7277 else
7278 {
7279 weapon.setChargedSoulshot(ItemInstance.CHARGED_NONE);
7280 }
7281
7282 autoShot();
7283 return true;
7284 }
7285
7286 public boolean unChargeFishShot()
7287 {
7288 ItemInstance weapon = getActiveWeaponInstance();
7289 if (weapon == null)
7290 {
7291 return false;
7292 }
7293 weapon.setChargedFishshot(false);
7294 autoShot();
7295 return true;
7296 }
7297
7298 public void autoShot()
7299 {
7300 for (Integer shotId : _activeSoulShots)
7301 {
7302 ItemInstance item = getInventory().getItemByItemId(shotId);
7303 if (item == null)
7304 {
7305 removeAutoSoulShot(shotId);
7306 continue;
7307 }
7308 IItemHandler handler = item.getTemplate().getHandler();
7309 if (handler == null)
7310 {
7311 continue;
7312 }
7313 handler.useItem(this, item, false);
7314 }
7315 }
7316
7317 public boolean getChargedFishShot()
7318 {
7319 ItemInstance weapon = getActiveWeaponInstance();
7320 return (weapon != null) && weapon.getChargedFishshot();
7321 }
7322
7323 @Override
7324 public boolean getChargedSoulShot()
7325 {
7326 ItemInstance weapon = getActiveWeaponInstance();
7327 return (weapon != null) && (weapon.getChargedSoulshot() == ItemInstance.CHARGED_SOULSHOT);
7328 }
7329
7330 @Override
7331 public int getChargedSpiritShot()
7332 {
7333 ItemInstance weapon = getActiveWeaponInstance();
7334 if (weapon == null)
7335 {
7336 return 0;
7337 }
7338 return weapon.getChargedSpiritshot();
7339 }
7340
7341 public void addAutoSoulShot(Integer itemId)
7342 {
7343 _activeSoulShots.add(itemId);
7344 }
7345
7346 public void removeAutoSoulShot(Integer itemId)
7347 {
7348 _activeSoulShots.remove(itemId);
7349 }
7350
7351 public Set<Integer> getAutoSoulShot()
7352 {
7353 return _activeSoulShots;
7354 }
7355
7356 public void setInvisibleType(InvisibleType vis)
7357 {
7358 _invisibleType = vis;
7359 }
7360
7361 @Override
7362 public InvisibleType getInvisibleType()
7363 {
7364 return _invisibleType;
7365 }
7366
7367 public int getClanPrivileges()
7368 {
7369 if (_clan == null)
7370 {
7371 return 0;
7372 }
7373 if (isClanLeader())
7374 {
7375 return Clan.CP_ALL;
7376 }
7377 if ((_powerGrade < 1) || (_powerGrade > 9))
7378 {
7379 return 0;
7380 }
7381 RankPrivs privs = _clan.getRankPrivs(_powerGrade);
7382 if (privs != null)
7383 {
7384 return privs.getPrivs();
7385 }
7386 return 0;
7387 }
7388
7389 public void teleToClosestTown()
7390 {
7391 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_VILLAGE), ReflectionManager.DEFAULT);
7392 }
7393
7394 public void teleToCastle()
7395 {
7396 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_CASTLE), ReflectionManager.DEFAULT);
7397 }
7398
7399 public void teleToFortress()
7400 {
7401 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_FORTRESS), ReflectionManager.DEFAULT);
7402 }
7403
7404 public void teleToClanhall()
7405 {
7406 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_CLANHALL), ReflectionManager.DEFAULT);
7407 }
7408
7409 @Override
7410 public void sendMessage(CustomMessage message)
7411 {
7412 sendMessage(message.toString());
7413 }
7414
7415 @Override
7416 public void sendChatMessage(int objectId, int messageType, String charName, String text)
7417 {
7418 sendPacket(new CreatureSay(objectId, messageType, charName, text));
7419 }
7420
7421 @Override
7422 public void teleToLocation(int x, int y, int z, int refId)
7423 {
7424 if (isDeleted())
7425 {
7426 return;
7427 }
7428
7429 super.teleToLocation(x, y, z, refId);
7430 }
7431
7432 @Override
7433 public boolean onTeleported()
7434 {
7435 if (!super.onTeleported())
7436 {
7437 return false;
7438 }
7439
7440 if (isFakeDeath())
7441 {
7442 breakFakeDeath();
7443 }
7444
7445 if (isInBoat())
7446 {
7447 setLoc(getBoat().getLoc());
7448 }
7449
7450 // 15 seconds after teleport the character does not cast agr
7451 setNonAggroTime(System.currentTimeMillis() + Config.NONAGGRO_TIME_ONTELEPORT);
7452
7453 spawnMe();
7454
7455 setLastClientPosition(getLoc());
7456 setLastServerPosition(getLoc());
7457
7458 if (isPendingRevive())
7459 {
7460 doRevive();
7461 }
7462
7463 sendActionFailed();
7464
7465 getAI().notifyEvent(CtrlEvent.EVT_TELEPORTED);
7466
7467 if (isLockedTarget() && (getTarget() != null))
7468 {
7469 sendPacket(new MyTargetSelected(getTarget().getObjectId(), 0));
7470 }
7471
7472 sendUserInfo(true);
7473 if (getPet() != null)
7474 {
7475 if (!getPet().isInRange(getLoc(), Config.FOLLOW_RANGE))
7476 {
7477 getPet().teleportToOwner();
7478 }
7479 }
7480
7481 return true;
7482 }
7483
7484 private boolean _partyMatchingVisible = true;
7485
7486 public void setPartyMatchingVisible()
7487 {
7488 _partyMatchingVisible = (!(_partyMatchingVisible));
7489 }
7490
7491 public boolean isPartyMatchingVisible()
7492 {
7493 return _partyMatchingVisible;
7494 }
7495
7496 public boolean enterObserverMode(Location loc)
7497 {
7498 WorldRegion observerRegion = World.getRegion(loc);
7499 if (observerRegion == null)
7500 {
7501 return false;
7502 }
7503 if (!_observerMode.compareAndSet(OBSERVER_NONE, OBSERVER_STARTING))
7504 {
7505 return false;
7506 }
7507
7508 setTarget(null);
7509 stopMove();
7510 sitDown(null);
7511 setFlying(true);
7512
7513 World.removeObjectsFromPlayer(this);
7514
7515 _observerRegion = observerRegion;
7516
7517 broadcastCharInfo();
7518
7519 sendPacket(new ObserverStart(loc));
7520
7521 return true;
7522 }
7523
7524 public void appearObserverMode()
7525 {
7526 if (!_observerMode.compareAndSet(OBSERVER_STARTING, OBSERVER_STARTED))
7527 {
7528 return;
7529 }
7530
7531 WorldRegion currentRegion = getCurrentRegion();
7532
7533 // Add a fake to the point of observation
7534 if (!_observerRegion.equals(currentRegion))
7535 {
7536 _observerRegion.addObject(this);
7537 }
7538
7539 World.showObjectsToPlayer(this);
7540
7541 if (_olympiadObserveGame != null)
7542 {
7543 _olympiadObserveGame.addSpectator(this);
7544 _olympiadObserveGame.broadcastInfo(null, this, true);
7545 }
7546 }
7547
7548 public void leaveObserverMode()
7549 {
7550 if (!_observerMode.compareAndSet(OBSERVER_STARTED, OBSERVER_LEAVING))
7551 {
7552 return;
7553 }
7554
7555 WorldRegion currentRegion = getCurrentRegion();
7556
7557 if (!_observerRegion.equals(currentRegion))
7558 {
7559 _observerRegion.removeObject(this);
7560 }
7561
7562 // Clear all visible objects
7563 World.removeObjectsFromPlayer(this);
7564
7565 _observerRegion = null;
7566
7567 setTarget(null);
7568 stopMove();
7569
7570 // Exit the mode observing
7571 sendPacket(new ObserverEnd(getLoc()));
7572 }
7573
7574 public void returnFromObserverMode()
7575 {
7576 if (!_observerMode.compareAndSet(OBSERVER_LEAVING, OBSERVER_NONE))
7577 {
7578 return;
7579 }
7580
7581 // It is necessary when teleport from a higher point to a lower, or harmed by the "fall"
7582 _lastClientPosition = null;
7583 _lastServerPosition = null;
7584
7585 unblock();
7586 standUp();
7587 setFlying(false);
7588
7589 broadcastCharInfo();
7590
7591 World.showObjectsToPlayer(this);
7592 }
7593
7594 public void enterOlympiadObserverMode(Location loc, OlympiadGame game, Reflection reflect)
7595 {
7596 WorldRegion observerRegion = World.getRegion(loc);
7597 WorldRegion currentRegion = getCurrentRegion();
7598 WorldRegion oldObserver = _observerRegion;
7599 if (observerRegion == null)
7600 {
7601 return;
7602 }
7603 OlympiadGame oldGame = _olympiadObserveGame;
7604 if (!_observerMode.compareAndSet(oldGame != null ? OBSERVER_STARTED : OBSERVER_NONE, OBSERVER_STARTING))
7605 {
7606 return;
7607 }
7608
7609 setTarget(null);
7610 stopMove();
7611
7612 World.removeObjectsFromPlayer(this);
7613 _observerRegion = observerRegion;
7614
7615 if (oldGame != null)
7616 {
7617 if (isInObserverMode() && (oldObserver != null))
7618 oldObserver.removeObject(this);
7619 oldGame.removeSpectator(this);
7620 sendPacket(ExOlympiadMatchEnd.STATIC);
7621 }
7622 else
7623 {
7624 block();
7625
7626 broadcastCharInfo();
7627
7628 sendPacket(new ExOlympiadMode(3));
7629 }
7630
7631 _olympiadObserveGame = game;
7632
7633 setReflection(reflect);
7634 sendPacket(new TeleportToLocation(this, loc));
7635 }
7636
7637 public void leaveOlympiadObserverMode(boolean removeFromGame)
7638 {
7639 if (_olympiadObserveGame == null)
7640 return;
7641
7642 if (!_observerMode.compareAndSet(OBSERVER_STARTED, OBSERVER_LEAVING))
7643 {
7644 return;
7645 }
7646
7647 if (removeFromGame)
7648 {
7649 _olympiadObserveGame.removeSpectator(this);
7650 }
7651 _olympiadObserveGame = null;
7652
7653 WorldRegion currentRegion = getCurrentRegion();
7654
7655 if ((_observerRegion != null) && (currentRegion != null) && !_observerRegion.equals(currentRegion))
7656 {
7657 _observerRegion.removeObject(this);
7658 }
7659
7660 World.removeObjectsFromPlayer(this);
7661
7662 _observerRegion = null;
7663
7664 setTarget(null);
7665 stopMove();
7666
7667 sendPacket(new ExOlympiadMode(0));
7668 sendPacket(ExOlympiadMatchEnd.STATIC);
7669
7670 setReflection(ReflectionManager.DEFAULT);
7671
7672 sendPacket(new TeleportToLocation(this, getLoc()));
7673 }
7674
7675 public void setOlympiadSide(final int i)
7676 {
7677 _olympiadSide = i;
7678 }
7679
7680 public int getOlympiadSide()
7681 {
7682 return _olympiadSide;
7683 }
7684
7685 @Override
7686 public boolean isInObserverMode()
7687 {
7688 return _observerMode.get() > OBSERVER_NONE;//So it can be OBSERVER_STARTING(1), OBSERVER_LEAVING(2) or OBSERVER_STARTED(3)
7689 }
7690
7691 public int getObserverMode()
7692 {
7693 return _observerMode.get();
7694 }
7695
7696 public WorldRegion getObserverRegion()
7697 {
7698 return _observerRegion;
7699 }
7700
7701 public void setObserverRegion(WorldRegion region)
7702 {
7703 _observerRegion = region;
7704 }
7705
7706 public int getTeleMode()
7707 {
7708 return _telemode;
7709 }
7710
7711 public void setTeleMode(final int mode)
7712 {
7713 _telemode = mode;
7714 }
7715
7716 public void setLoto(final int i, final int val)
7717 {
7718 _loto[i] = val;
7719 }
7720
7721 public int getLoto(final int i)
7722 {
7723 return _loto[i];
7724 }
7725
7726 public void setRace(final int i, final int val)
7727 {
7728 _race[i] = val;
7729 }
7730
7731 public int getRace(final int i)
7732 {
7733 return _race[i];
7734 }
7735
7736 public boolean getMessageRefusal()
7737 {
7738 return _messageRefusal;
7739 }
7740
7741 public void setMessageRefusal(final boolean mode)
7742 {
7743 _messageRefusal = mode;
7744 }
7745
7746 public void setTradeRefusal(final boolean mode)
7747 {
7748 _tradeRefusal = mode;
7749 }
7750
7751 public boolean getTradeRefusal()
7752 {
7753 return _tradeRefusal;
7754 }
7755
7756 public void setPartyInviteRefusal(final boolean mode)
7757 {
7758 _partyinviteRefusal = mode;
7759 }
7760
7761 public boolean getPartyInviteRefusal()
7762 {
7763 return _partyinviteRefusal;
7764 }
7765
7766 public void setFriendInviteRefusal(final boolean mode)
7767 {
7768 _friendinviteRefusal = mode;
7769 }
7770
7771 public boolean getFriendInviteRefusal()
7772 {
7773 return _friendinviteRefusal;
7774 }
7775
7776 public void addToBlockList(final String charName)
7777 {
7778 if ((charName == null) || charName.equalsIgnoreCase(getName()) || isInBlockList(charName))
7779 {
7780 sendPacket(Msg.YOU_HAVE_FAILED_TO_REGISTER_THE_USER_TO_YOUR_IGNORE_LIST);
7781 return;
7782 }
7783
7784 Player block_target = World.getPlayer(charName);
7785
7786 if (block_target != null)
7787 {
7788 if (block_target.isGM())
7789 {
7790 sendPacket(Msg.YOU_MAY_NOT_IMPOSE_A_BLOCK_ON_A_GM);
7791 return;
7792 }
7793 _blockList.put(block_target.getObjectId(), block_target.getName());
7794 sendPacket(new SystemMessage(SystemMessage.S1_HAS_BEEN_ADDED_TO_YOUR_IGNORE_LIST).addString(block_target.getName()));
7795 block_target.sendPacket(new SystemMessage(SystemMessage.S1__HAS_PLACED_YOU_ON_HIS_HER_IGNORE_LIST).addString(getName()));
7796 return;
7797 }
7798
7799 int charId = CharacterDAO.getInstance().getObjectIdByName(charName);
7800
7801 if (charId == 0)
7802 {
7803 sendPacket(Msg.YOU_HAVE_FAILED_TO_REGISTER_THE_USER_TO_YOUR_IGNORE_LIST);
7804 return;
7805 }
7806
7807 if (Config.gmlist.containsKey(charId) && Config.gmlist.get(charId).IsGM)
7808 {
7809 sendPacket(Msg.YOU_MAY_NOT_IMPOSE_A_BLOCK_ON_A_GM);
7810 return;
7811 }
7812 _blockList.put(charId, charName);
7813 sendPacket(new SystemMessage(SystemMessage.S1_HAS_BEEN_ADDED_TO_YOUR_IGNORE_LIST).addString(charName));
7814 }
7815
7816 public void removeFromBlockList(final String charName)
7817 {
7818 int charId = 0;
7819 for (int blockId : _blockList.keySet())
7820 {
7821 if (charName.equalsIgnoreCase(_blockList.get(blockId)))
7822 {
7823 charId = blockId;
7824 break;
7825 }
7826 }
7827 if (charId == 0)
7828 {
7829 sendPacket(Msg.YOU_HAVE_FAILED_TO_DELETE_THE_CHARACTER_FROM_IGNORE_LIST);
7830 return;
7831 }
7832 sendPacket(new SystemMessage(SystemMessage.S1_HAS_BEEN_REMOVED_FROM_YOUR_IGNORE_LIST).addString(_blockList.remove(charId)));
7833 Player block_target = GameObjectsStorage.getPlayer(charId);
7834 if (block_target != null)
7835 {
7836 block_target.sendMessage(getName() + " has removed you from his/her Ignore List.");
7837 }
7838 }
7839
7840 public boolean isInBlockList(final Player player)
7841 {
7842 return isInBlockList(player.getObjectId());
7843 }
7844
7845 public boolean isInBlockList(final int charId)
7846 {
7847 return (_blockList != null) && _blockList.containsKey(charId);
7848 }
7849
7850 public boolean isInBlockList(final String charName)
7851 {
7852 for (int blockId : _blockList.keySet())
7853 {
7854 if (charName.equalsIgnoreCase(_blockList.get(blockId)))
7855 {
7856 return true;
7857 }
7858 }
7859 return false;
7860 }
7861
7862 private void restoreBlockList(Connection con)
7863 {
7864 _blockList.clear();
7865
7866 try (PreparedStatement statement = con.prepareStatement("SELECT target_Id, char_name FROM character_blocklist LEFT JOIN characters ON ( character_blocklist.target_Id = characters.obj_Id ) WHERE character_blocklist.obj_Id = ?"))
7867 {
7868 statement.setInt(1, getObjectId());
7869
7870 try (ResultSet rs = statement.executeQuery())
7871 {
7872 while (rs.next())
7873 {
7874 int targetId = rs.getInt("target_Id");
7875 String name = rs.getString("char_name");
7876 if (name == null)
7877 {
7878 continue;
7879 }
7880 _blockList.put(targetId, name);
7881 }
7882 }
7883 }
7884 catch (SQLException e)
7885 {
7886 _log.warn("Can't restore player blocklist " + e, e);
7887 }
7888 }
7889
7890 private void storeBlockList()
7891 {
7892 try (Connection con = DatabaseFactory.getInstance().getConnection();
7893 Statement statement = con.createStatement())
7894 {
7895 statement.executeUpdate("DELETE FROM character_blocklist WHERE obj_Id=" + getObjectId());
7896
7897 if (_blockList.isEmpty())
7898 {
7899 return;
7900 }
7901
7902 SqlBatch b = new SqlBatch("INSERT IGNORE INTO `character_blocklist` (`obj_Id`,`target_Id`) VALUES");
7903
7904 synchronized (_blockList)
7905 {
7906 StringBuilder sb;
7907 for (Entry<Integer, String> e : _blockList.entrySet())
7908 {
7909 sb = new StringBuilder("(");
7910 sb.append(getObjectId()).append(",");
7911 sb.append(e.getKey()).append(")");
7912 b.write(sb.toString());
7913 }
7914 }
7915 if (!b.isEmpty())
7916 {
7917 statement.executeUpdate(b.close());
7918 }
7919 }
7920 catch (Exception e)
7921 {
7922 _log.warn("Can't store player blocklist " + e);
7923 }
7924 }
7925
7926 public boolean isBlockAll()
7927 {
7928 return _blockAll;
7929 }
7930
7931 public void setBlockAll(final boolean state)
7932 {
7933 _blockAll = state;
7934 }
7935
7936 public Collection<String> getBlockList()
7937 {
7938 return _blockList.values();
7939 }
7940
7941 public Map<Integer, String> getBlockListMap()
7942 {
7943 return _blockList;
7944 }
7945
7946 public void setHeroAura(boolean heroAura)
7947 {
7948 _heroAura = heroAura;
7949 }
7950
7951 public boolean isHeroAura()
7952 {
7953 return (_hero) || (_heroAura) || (isFakeHero());
7954 }
7955
7956 public boolean isFakeHero()
7957 {
7958 if (getVarB("hasFakeHero"))
7959 {
7960 return true;
7961 }
7962 return false;
7963 }
7964
7965 public boolean FakeHeroEquip()
7966 {
7967 if ((isFakeHero() && (Config.SERVICES_HERO_SELL_ITEMS)) || (getVarB("hasFakeHeroItems")))
7968 {
7969 return true;
7970 }
7971 return false;
7972 }
7973
7974 public boolean FakeHeroChat()
7975 {
7976 if ((isFakeHero() && (Config.SERVICES_HERO_SELL_CHAT)) || (getVarB("hasFakeHeroChat")))
7977 {
7978 return true;
7979 }
7980 return false;
7981 }
7982
7983 public boolean FakeHeroSkill()
7984 {
7985 if ((isFakeHero() && (Config.SERVICES_HERO_SELL_SKILL)) || (getVarB("hasFakeHeroSkills")))
7986 {
7987 return true;
7988 }
7989 return false;
7990 }
7991 public void setHero(final boolean hero)
7992 {
7993 _hero = hero;
7994 }
7995
7996 @Override
7997 public boolean isHero()
7998 {
7999 return _hero;
8000 }
8001
8002 public void setHero(Player player)
8003 {
8004 StatsSet hero = new StatsSet();
8005 hero.set(Olympiad.CLASS_ID, player.getBaseClassId());
8006 hero.set(Olympiad.CHAR_ID, player.getObjectId());
8007 hero.set(Olympiad.CHAR_NAME, player.getName());
8008 hero.set(Hero.ACTIVE, 1);
8009
8010 List<StatsSet> heroesToBe = new ArrayList<StatsSet>();
8011 heroesToBe.add(hero);
8012
8013 Hero.getInstance().computeNewHeroes(heroesToBe);
8014 player.setHero(true);
8015 Hero.addSkills(player);
8016 player.updatePledgeClass();
8017 if (player.isHero())
8018 {
8019 player.broadcastPacket(new SocialAction(player.getObjectId(), 16));
8020 }
8021 player.broadcastUserInfo(true);
8022 }
8023
8024 public int getPing()
8025 {
8026 return _ping;
8027 }
8028
8029 public void setPing(int ping)
8030 {
8031 _ping = ping;
8032 }
8033
8034 public void setIsInOlympiadMode(final boolean b)
8035 {
8036 _inOlympiadMode = b;
8037 }
8038
8039 @Override
8040 public boolean isInOlympiadMode()
8041 {
8042 return _inOlympiadMode;
8043 }
8044
8045 public void setOlympiadCompStarted(final boolean b)
8046 {
8047 _isOlympiadCompStarted = b;
8048 }
8049
8050 public boolean isOlympiadCompStarted()
8051 {
8052 return _isOlympiadCompStarted;
8053 }
8054
8055 public void updateNobleSkills()
8056 {
8057 if (isNoble())
8058 {
8059 if (isClanLeader() && (getClan().getCastle() > 0))
8060 {
8061 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_WYVERN_AEGIS, 1));
8062 }
8063 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_NOBLESSE_BLESSING, 1));
8064 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_SUMMON_CP_POTION, 1));
8065 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_FORTUNE_OF_NOBLESSE, 1));
8066 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_HARMONY_OF_NOBLESSE, 1));
8067 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_SYMPHONY_OF_NOBLESSE, 1));
8068 }
8069 else
8070 {
8071 super.removeSkillById(Skill.SKILL_WYVERN_AEGIS);
8072 super.removeSkillById(Skill.SKILL_NOBLESSE_BLESSING);
8073 super.removeSkillById(Skill.SKILL_SUMMON_CP_POTION);
8074 super.removeSkillById(Skill.SKILL_FORTUNE_OF_NOBLESSE);
8075 super.removeSkillById(Skill.SKILL_HARMONY_OF_NOBLESSE);
8076 super.removeSkillById(Skill.SKILL_SYMPHONY_OF_NOBLESSE);
8077 }
8078 }
8079
8080 public void setNoble(boolean noble)
8081 {
8082 if (noble)
8083 {
8084 broadcastPacket(new MagicSkillUse(this, this, 6673, 1, 1000, 0));
8085 }
8086 _noble = noble;
8087 }
8088
8089 public boolean isNoble()
8090 {
8091 return _noble;
8092 }
8093
8094 public int getSubLevel()
8095 {
8096 return isSubClassActive() ? getLevel() : 0;
8097 }
8098
8099 /* varka silenos and ketra orc quests related functions */
8100 public void updateKetraVarka()
8101 {
8102 if (ItemFunctions.getItemCount(this, 7215) > 0)
8103 {
8104 _ketra = 5;
8105 }
8106 else if (ItemFunctions.getItemCount(this, 7214) > 0)
8107 {
8108 _ketra = 4;
8109 }
8110 else if (ItemFunctions.getItemCount(this, 7213) > 0)
8111 {
8112 _ketra = 3;
8113 }
8114 else if (ItemFunctions.getItemCount(this, 7212) > 0)
8115 {
8116 _ketra = 2;
8117 }
8118 else if (ItemFunctions.getItemCount(this, 7211) > 0)
8119 {
8120 _ketra = 1;
8121 }
8122 else if (ItemFunctions.getItemCount(this, 7225) > 0)
8123 {
8124 _varka = 5;
8125 }
8126 else if (ItemFunctions.getItemCount(this, 7224) > 0)
8127 {
8128 _varka = 4;
8129 }
8130 else if (ItemFunctions.getItemCount(this, 7223) > 0)
8131 {
8132 _varka = 3;
8133 }
8134 else if (ItemFunctions.getItemCount(this, 7222) > 0)
8135 {
8136 _varka = 2;
8137 }
8138 else if (ItemFunctions.getItemCount(this, 7221) > 0)
8139 {
8140 _varka = 1;
8141 }
8142 else
8143 {
8144 _varka = 0;
8145 _ketra = 0;
8146 }
8147 }
8148
8149 public int getVarka()
8150 {
8151 return _varka;
8152 }
8153
8154 public int getKetra()
8155 {
8156 return _ketra;
8157 }
8158
8159 public void updateRam()
8160 {
8161 if (ItemFunctions.getItemCount(this, 7247) > 0)
8162 {
8163 _ram = 2;
8164 }
8165 else if (ItemFunctions.getItemCount(this, 7246) > 0)
8166 {
8167 _ram = 1;
8168 }
8169 else
8170 {
8171 _ram = 0;
8172 }
8173 }
8174
8175 public int getRam()
8176 {
8177 return _ram;
8178 }
8179
8180 public void setPledgeType(final int typeId)
8181 {
8182 _pledgeType = typeId;
8183 }
8184
8185 public int getPledgeType()
8186 {
8187 return _pledgeType;
8188 }
8189
8190 public void setLvlJoinedAcademy(int lvl)
8191 {
8192 _lvlJoinedAcademy = lvl;
8193 }
8194
8195 public int getLvlJoinedAcademy()
8196 {
8197 return _lvlJoinedAcademy;
8198 }
8199
8200 public int getPledgeClass()
8201 {
8202 return _pledgeClass;
8203 }
8204
8205 public void updatePledgeClass()
8206 {
8207 int clanLevel = _clan == null ? -1 : _clan.getLevel();
8208 boolean inAcademy = (_clan != null) && Clan.isAcademy(_pledgeType);
8209 boolean isGuard = (_clan != null) && Clan.isRoyalGuard(_pledgeType);
8210 boolean isKnight = (_clan != null) && Clan.isOrderOfKnights(_pledgeType);
8211
8212 boolean isGuardCaptain = false, isKnightCommander = false, isLeader = false;
8213
8214 SubUnit unit = getSubUnit();
8215 if (unit != null)
8216 {
8217 UnitMember unitMember = unit.getUnitMember(getObjectId());
8218 if (unitMember == null)
8219 {
8220 _log.warn("Player: unitMember null, clan: " + _clan.getClanId() + "; pledgeType: " + unit.getType());
8221 return;
8222 }
8223 isGuardCaptain = Clan.isRoyalGuard(unitMember.getLeaderOf());
8224 isKnightCommander = Clan.isOrderOfKnights(unitMember.getLeaderOf());
8225 isLeader = unitMember.getLeaderOf() == Clan.SUBUNIT_MAIN_CLAN;
8226 }
8227
8228 switch (clanLevel)
8229 {
8230 case -1:
8231 _pledgeClass = RANK_VAGABOND;
8232 break;
8233 case 0:
8234 case 1:
8235 case 2:
8236 case 3:
8237 if (isLeader)
8238 {
8239 _pledgeClass = RANK_HEIR;
8240 }
8241 else
8242 {
8243 _pledgeClass = RANK_VASSAL;
8244 }
8245 break;
8246 case 4:
8247 if (isLeader)
8248 {
8249 _pledgeClass = RANK_KNIGHT;
8250 }
8251 else
8252 {
8253 _pledgeClass = RANK_HEIR;
8254 }
8255 break;
8256 case 5:
8257 if (isLeader)
8258 {
8259 _pledgeClass = RANK_WISEMAN;
8260 }
8261 else if (inAcademy)
8262 {
8263 _pledgeClass = RANK_VASSAL;
8264 }
8265 else
8266 {
8267 _pledgeClass = RANK_HEIR;
8268 }
8269 break;
8270 case 6:
8271 if (isLeader)
8272 {
8273 _pledgeClass = RANK_BARON;
8274 }
8275 else if (inAcademy)
8276 {
8277 _pledgeClass = RANK_VASSAL;
8278 }
8279 else if (isGuardCaptain)
8280 {
8281 _pledgeClass = RANK_WISEMAN;
8282 }
8283 else if (isGuard)
8284 {
8285 _pledgeClass = RANK_HEIR;
8286 }
8287 else
8288 {
8289 _pledgeClass = RANK_KNIGHT;
8290 }
8291 break;
8292 case 7:
8293 if (isLeader)
8294 {
8295 _pledgeClass = RANK_COUNT;
8296 }
8297 else if (inAcademy)
8298 {
8299 _pledgeClass = RANK_VASSAL;
8300 }
8301 else if (isGuardCaptain)
8302 {
8303 _pledgeClass = RANK_VISCOUNT;
8304 }
8305 else if (isGuard)
8306 {
8307 _pledgeClass = RANK_KNIGHT;
8308 }
8309 else if (isKnightCommander)
8310 {
8311 _pledgeClass = RANK_BARON;
8312 }
8313 else if (isKnight)
8314 {
8315 _pledgeClass = RANK_HEIR;
8316 }
8317 else
8318 {
8319 _pledgeClass = RANK_WISEMAN;
8320 }
8321 break;
8322 case 8:
8323 if (isLeader)
8324 {
8325 _pledgeClass = RANK_MARQUIS;
8326 }
8327 else if (inAcademy)
8328 {
8329 _pledgeClass = RANK_VASSAL;
8330 }
8331 else if (isGuardCaptain)
8332 {
8333 _pledgeClass = RANK_COUNT;
8334 }
8335 else if (isGuard)
8336 {
8337 _pledgeClass = RANK_WISEMAN;
8338 }
8339 else if (isKnightCommander)
8340 {
8341 _pledgeClass = RANK_VISCOUNT;
8342 }
8343 else if (isKnight)
8344 {
8345 _pledgeClass = RANK_KNIGHT;
8346 }
8347 else
8348 {
8349 _pledgeClass = RANK_BARON;
8350 }
8351 break;
8352 case 9:
8353 if (isLeader)
8354 {
8355 _pledgeClass = RANK_DUKE;
8356 }
8357 else if (inAcademy)
8358 {
8359 _pledgeClass = RANK_VASSAL;
8360 }
8361 else if (isGuardCaptain)
8362 {
8363 _pledgeClass = RANK_MARQUIS;
8364 }
8365 else if (isGuard)
8366 {
8367 _pledgeClass = RANK_BARON;
8368 }
8369 else if (isKnightCommander)
8370 {
8371 _pledgeClass = RANK_COUNT;
8372 }
8373 else if (isKnight)
8374 {
8375 _pledgeClass = RANK_WISEMAN;
8376 }
8377 else
8378 {
8379 _pledgeClass = RANK_VISCOUNT;
8380 }
8381 break;
8382 case 10:
8383 if (isLeader)
8384 {
8385 _pledgeClass = RANK_GRAND_DUKE;
8386 }
8387 else if (inAcademy)
8388 {
8389 _pledgeClass = RANK_VASSAL;
8390 }
8391 else if (isGuard)
8392 {
8393 _pledgeClass = RANK_VISCOUNT;
8394 }
8395 else if (isKnight)
8396 {
8397 _pledgeClass = RANK_BARON;
8398 }
8399 else if (isGuardCaptain)
8400 {
8401 _pledgeClass = RANK_DUKE;
8402 }
8403 else if (isKnightCommander)
8404 {
8405 _pledgeClass = RANK_MARQUIS;
8406 }
8407 else
8408 {
8409 _pledgeClass = RANK_COUNT;
8410 }
8411 break;
8412 case 11:
8413 if (isLeader)
8414 {
8415 _pledgeClass = RANK_DISTINGUISHED_KING;
8416 }
8417 else if (inAcademy)
8418 {
8419 _pledgeClass = RANK_VASSAL;
8420 }
8421 else if (isGuard)
8422 {
8423 _pledgeClass = RANK_COUNT;
8424 }
8425 else if (isKnight)
8426 {
8427 _pledgeClass = RANK_VISCOUNT;
8428 }
8429 else if (isGuardCaptain)
8430 {
8431 _pledgeClass = RANK_GRAND_DUKE;
8432 }
8433 else if (isKnightCommander)
8434 {
8435 _pledgeClass = RANK_DUKE;
8436 }
8437 else
8438 {
8439 _pledgeClass = RANK_MARQUIS;
8440 }
8441 break;
8442 }
8443
8444 if (_hero && (_pledgeClass < RANK_MARQUIS))
8445 {
8446 _pledgeClass = RANK_MARQUIS;
8447 }
8448 else if (_noble && (_pledgeClass < RANK_BARON))
8449 {
8450 _pledgeClass = RANK_BARON;
8451 }
8452 }
8453
8454 public void setPowerGrade(final int grade)
8455 {
8456 _powerGrade = grade;
8457 }
8458
8459 public int getPowerGrade()
8460 {
8461 return _powerGrade;
8462 }
8463
8464 public void setApprentice(final int apprentice)
8465 {
8466 _apprentice = apprentice;
8467 }
8468
8469 public int getApprentice()
8470 {
8471 return _apprentice;
8472 }
8473
8474 public int getSponsor()
8475 {
8476 return _clan == null ? 0 : _clan.getAnyMember(getObjectId()).getSponsor();
8477 }
8478
8479 public int getNameColor()
8480 {
8481 if (isInObserverMode())
8482 {
8483 return Color.black.getRGB();
8484 }
8485
8486 return _nameColor;
8487 }
8488
8489 public void setNameColor(final int nameColor)
8490 {
8491 if ((nameColor != Config.NORMAL_NAME_COLOUR) && (nameColor != Config.CLANLEADER_NAME_COLOUR) && (nameColor != Config.GM_NAME_COLOUR) && (nameColor != Config.SERVICES_OFFLINE_TRADE_NAME_COLOR))
8492 {
8493 setVar("namecolor", Integer.toHexString(nameColor), -1);
8494 }
8495 else if (nameColor == Config.NORMAL_NAME_COLOUR)
8496 {
8497 unsetVar("namecolor");
8498 }
8499 _nameColor = nameColor;
8500 }
8501
8502 public void setNameColor(final int red, final int green, final int blue)
8503 {
8504 _nameColor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16);
8505 if ((_nameColor != Config.NORMAL_NAME_COLOUR) && (_nameColor != Config.CLANLEADER_NAME_COLOUR) && (_nameColor != Config.GM_NAME_COLOUR) && (_nameColor != Config.SERVICES_OFFLINE_TRADE_NAME_COLOR))
8506 {
8507 setVar("namecolor", Integer.toHexString(_nameColor), -1);
8508 }
8509 else
8510 {
8511 unsetVar("namecolor");
8512 }
8513 }
8514
8515 public void setNameColor(String RGB)
8516 {
8517 if (RGB.length() == 6)
8518 {
8519 RGB = RGB.substring(4, 6) + RGB.substring(2, 4) + RGB.substring(0, 2);
8520 }
8521 setNameColor(Integer.decode("0x" + RGB));
8522 }
8523
8524 private final Map<String, PlayerVar> user_variables = new ConcurrentHashMap<String, PlayerVar>();
8525
8526 public static void setVarOffline(int playerObjId, String name, String value, long expireDate)
8527 {
8528 Player player = World.getPlayer(playerObjId);
8529 if (player != null)
8530 player.setVar(name, value, expireDate);
8531 else
8532 mysql.set("REPLACE INTO character_variables (obj_id, type, name, value, expire_time) VALUES (?,'user-var',?,?,?)", playerObjId, name, value, expireDate);
8533 }
8534
8535 public static void setVarOffline(int playerObjId, String name, int value, long expireDate)
8536 {
8537 setVarOffline(playerObjId, name, String.valueOf(value), expireDate);
8538 }
8539
8540 public static void setVarOffline(int playerObjId, String name, int value)
8541 {
8542 setVarOffline(playerObjId, name, String.valueOf(value), -1);
8543 }
8544
8545 public static void setVarOffline(int playerObjId, String name, long value, long expireDate)
8546 {
8547 setVarOffline(playerObjId, name, String.valueOf(value), expireDate);
8548 }
8549
8550 public static void setVarOffline(int playerObjId, String name, long value)
8551 {
8552 setVarOffline(playerObjId, name, String.valueOf(value), -1);
8553 }
8554
8555 public static void unsetVarOffline(int playerObjId, String name)
8556 {
8557 Player player = World.getPlayer(playerObjId);
8558 if (player != null)
8559 player.unsetVar(name);
8560 else
8561 mysql.set("DELETE FROM `character_variables` WHERE `obj_id`=? AND `type`='user-var' AND `name`=? LIMIT 1", playerObjId, name);
8562 }
8563
8564 public void setVar(String name, String value, long expireDate)
8565 {
8566 if (user_variables.containsKey(name))
8567 {
8568 getVarObject(name).stopExpireTask();
8569 }
8570
8571 user_variables.put(name, new PlayerVar(this, name, value, expireDate));
8572 mysql.set("REPLACE INTO character_variables (obj_id, type, name, value, expire_time) VALUES (?,'user-var',?,?,?)", getObjectId(), name, value, expireDate);
8573 }
8574
8575 public void setVar(String name, String value)
8576 {
8577 setVar(name, value, -1);
8578 }
8579
8580 public void setVar(String name, int value, long expireDate)
8581 {
8582 setVar(name, String.valueOf(value), expireDate);
8583 }
8584
8585 public void setVar(String name, int value)
8586 {
8587 setVar(name, String.valueOf(value), -1);
8588 }
8589
8590 public void setVar(String name, long value, long expireDate)
8591 {
8592 setVar(name, String.valueOf(value), expireDate);
8593 }
8594
8595 public void setVar(String name, long value)
8596 {
8597 setVar(name, String.valueOf(value), -1);
8598 }
8599
8600 public void unsetVar(String name)
8601 {
8602 if (name == null)
8603 return;
8604
8605 PlayerVar pv = user_variables.remove(name);
8606
8607 if (pv != null)
8608 {
8609 pv.stopExpireTask();
8610 mysql.set("DELETE FROM `character_variables` WHERE `obj_id`=? AND `type`='user-var' AND `name`=? LIMIT 1", getObjectId(), name);
8611 }
8612 }
8613
8614 public String getVar(String name)
8615 {
8616 PlayerVar pv = getVarObject(name);
8617
8618 if (pv == null)
8619 {
8620 return null;
8621 }
8622
8623 return pv.getValue();
8624 }
8625
8626 public long getVarTimeToExpire(String name)
8627 {
8628 try
8629 {
8630 return getVarObject(name).getTimeToExpire();
8631 }
8632 catch (NullPointerException npe)
8633 {
8634
8635 }
8636
8637 return 0;
8638 }
8639
8640 public PlayerVar getVarObject(String name)
8641 {
8642 return user_variables.get(name);
8643 }
8644
8645 public boolean getVarB(String name, boolean defaultVal)
8646 {
8647 PlayerVar pv = getVarObject(name);
8648
8649 if (pv == null)
8650 {
8651 return defaultVal;
8652 }
8653
8654 return pv.getValueBoolean();
8655 }
8656
8657 public boolean getVarB(String name)
8658 {
8659 return getVarB(name, false);
8660 }
8661
8662 public long getVarLong(String name)
8663 {
8664 return getVarLong(name, 0L);
8665 }
8666
8667 public long getVarLong(String name, long defaultVal)
8668 {
8669 long result = defaultVal;
8670 String var = getVar(name);
8671 if (var != null)
8672 {
8673 result = Long.parseLong(var);
8674 }
8675 return result;
8676 }
8677
8678 public int getVarInt(String name)
8679 {
8680 return getVarInt(name, 0);
8681 }
8682
8683 public int getVarInt(String name, int defaultVal)
8684 {
8685 int result = defaultVal;
8686 String var = getVar(name);
8687 if (var != null)
8688 {
8689 result = Integer.parseInt(var);
8690 }
8691 return result;
8692 }
8693
8694 public Map<String, PlayerVar> getVars()
8695 {
8696 return user_variables;
8697 }
8698
8699 private void loadVariables(Connection con)
8700 {
8701 try (PreparedStatement offline = con.prepareStatement("SELECT * FROM character_variables WHERE obj_id = ?"))
8702 {
8703 offline.setInt(1, getObjectId());
8704
8705 try (ResultSet rs = offline.executeQuery())
8706 {
8707 while (rs.next())
8708 {
8709 String name = rs.getString("name");
8710 String value = Strings.stripSlashes(rs.getString("value"));
8711 long expire_time = rs.getLong("expire_time");
8712 long curtime = System.currentTimeMillis();
8713
8714 if ((expire_time <= curtime) && (expire_time > 0))
8715 {
8716 continue;
8717 }
8718
8719 user_variables.put(name, new PlayerVar(this, name, value, expire_time));
8720 }
8721 }
8722 }
8723 catch (SQLException e)
8724 {
8725 _log.error("Error while loading Character_variables for Id "+getObjectId(), e);
8726 }
8727 }
8728
8729 public static String getVarFromPlayer(int objId, String var)
8730 {
8731 String value = null;
8732
8733 try (Connection con = DatabaseFactory.getInstance().getConnection();
8734 PreparedStatement offline = con.prepareStatement("SELECT value FROM character_variables WHERE obj_id = ? AND name = ?"))
8735 {
8736 offline.setInt(1, objId);
8737 offline.setString(2, var);
8738
8739 try (ResultSet rs = offline.executeQuery())
8740 {
8741 if (rs.next())
8742 {
8743 value = Strings.stripSlashes(rs.getString("value"));
8744 }
8745 }
8746 }
8747 catch (Exception e)
8748 {
8749 _log.error("Error while getting Variable from Player", e);
8750 }
8751 return value;
8752 }
8753
8754 /**
8755 * Adding Variable to Map<Name, Value>. It's not saved to database.
8756 * Value can be taken back by {@link #getQuickVarO(String, Object...)} method.
8757 * @param name key
8758 * @param value value
8759 */
8760 public void addQuickVar(String name, Object value)
8761 {
8762 if (quickVars.containsKey(name))
8763 quickVars.remove(name);
8764 quickVars.put(name, value);
8765 }
8766
8767 /**
8768 * Getting back String Value located in quickVars Map<Name, Value>.
8769 * If value doesn't exist, defaultValue is returned.
8770 * If value isn't String type, throws Error
8771 * @param name key
8772 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8773 * @return value
8774 */
8775 public String getQuickVarS(String name, String... defaultValue)
8776 {
8777 if (!quickVars.containsKey(name))
8778 {
8779 if (defaultValue.length > 0)
8780 return defaultValue[0];
8781 return null;
8782 }
8783 return (String) quickVars.get(name);
8784 }
8785
8786 /**
8787 * Getting back String Value located in quickVars Map<Name, Value>.
8788 * If value doesn't exist, defaultValue is returned.
8789 * If value isn't Boolean type, throws Error
8790 * @param name key
8791 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8792 * @return value
8793 */
8794 public boolean getQuickVarB(String name, boolean... defaultValue)
8795 {
8796 if (!quickVars.containsKey(name))
8797 {
8798 if (defaultValue.length > 0)
8799 return defaultValue[0];
8800 return false;
8801 }
8802 return ((Boolean) quickVars.get(name)).booleanValue();
8803 }
8804
8805 /**
8806 * Getting back Integer Value located in quickVars Map<Name, Value>.
8807 * If value doesn't exist, defaultValue is returned.
8808 * If value isn't Integer type, throws Error
8809 * @param name key
8810 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8811 * @return value
8812 */
8813 public int getQuickVarI(String name, int... defaultValue)
8814 {
8815 if (!quickVars.containsKey(name))
8816 {
8817 if (defaultValue.length > 0)
8818 return defaultValue[0];
8819 return -1;
8820 }
8821 return ((Integer) quickVars.get(name)).intValue();
8822 }
8823
8824 /**
8825 * Getting back Long Value located in quickVars Map<Name, Value>.
8826 * If value doesn't exist, defaultValue is returned.
8827 * If value isn't Long type, throws Error
8828 * @param name key
8829 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8830 * @return value
8831 */
8832 public long getQuickVarL(String name, long... defaultValue)
8833 {
8834 if (!quickVars.containsKey(name))
8835 {
8836 if (defaultValue.length > 0)
8837 return defaultValue[0];
8838 return -1L;
8839 }
8840 return ((Long) quickVars.get(name)).longValue();
8841 }
8842
8843 /**
8844 * Getting back Object Value located in quickVars Map<Name, Value>.
8845 * If value doesn't exist, defaultValue is returned.
8846 * @param name key
8847 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8848 * @return value
8849 */
8850 public Object getQuickVarO(String name, Object... defaultValue)
8851 {
8852 if (!quickVars.containsKey(name))
8853 {
8854 if (defaultValue.length > 0)
8855 return defaultValue[0];
8856 return null;
8857 }
8858 return quickVars.get(name);
8859 }
8860
8861 /**
8862 * Checking if quickVars Map<Name, Value> contains a name as a Key
8863 * @param name key
8864 * @return contains name
8865 */
8866 public boolean containsQuickVar(String name)
8867 {
8868 return quickVars.containsKey(name);
8869 }
8870
8871 /**
8872 * Removing Key from quickVars Map
8873 * @param name - key
8874 */
8875 public void deleteQuickVar(String name)
8876 {
8877 quickVars.remove(name);
8878 }
8879
8880 /**
8881 * Adding new Image Id to List of Images loaded by Game Client of this plater
8882 * @param id of the image
8883 */
8884 public void addLoadedImage(int id)
8885 {
8886 loadedImages.add(id);
8887 }
8888
8889 /**
8890 * Did Game Client already receive Custom Image from the server?
8891 * @param id of the image
8892 * @return client received image
8893 */
8894 public boolean wasImageLoaded(int id)
8895 {
8896 return loadedImages.contains(id);
8897 }
8898
8899 /**
8900 * @return Number of Custom Images sent from Server to the Player
8901 */
8902 public int getLoadedImagesSize()
8903 {
8904 return loadedImages.size();
8905 }
8906
8907 public String getLang()
8908 {
8909 return "en";
8910 }
8911
8912 public int getLangId()
8913 {
8914 String lang = getLang();
8915 if (lang.equalsIgnoreCase("en") || lang.equalsIgnoreCase("e") || lang.equalsIgnoreCase("eng"))
8916 {
8917 return LANG_ENG;
8918 }
8919 if (lang.equalsIgnoreCase("ru") || lang.equalsIgnoreCase("r") || lang.equalsIgnoreCase("rus"))
8920 {
8921 return LANG_RUS;
8922 }
8923 return LANG_UNK;
8924 }
8925
8926 public Language getLanguage()
8927 {
8928 String lang = getLang();
8929 if ((lang == null) || lang.equalsIgnoreCase("en") || lang.equalsIgnoreCase("e") || lang.equalsIgnoreCase("eng"))
8930 {
8931 return Language.ENGLISH;
8932 }
8933 if (lang.equalsIgnoreCase("ru") || lang.equalsIgnoreCase("r") || lang.equalsIgnoreCase("rus"))
8934 {
8935 return Language.RUSSIAN;
8936 }
8937 return Language.ENGLISH;
8938 }
8939
8940 public boolean isLangRus()
8941 {
8942 return getLangId() == LANG_RUS;
8943 }
8944
8945 public int isAtWarWith(final Integer id)
8946 {
8947 return (_clan == null) || !_clan.isAtWarWith(id) ? 0 : 1;
8948 }
8949
8950 public int isAtWar()
8951 {
8952 return (_clan == null) || (_clan.isAtWarOrUnderAttack() <= 0) ? 0 : 1;
8953 }
8954
8955 public void stopWaterTask()
8956 {
8957 if (_taskWater != null)
8958 {
8959 _taskWater.cancel(false);
8960 _taskWater = null;
8961 sendPacket(new SetupGauge(this, SetupGauge.CYAN, 0));
8962 sendChanges();
8963 }
8964 }
8965
8966 public void startWaterTask()
8967 {
8968 if (isDead())
8969 {
8970 stopWaterTask();
8971 }
8972 else if (Config.ALLOW_WATER && (_taskWater == null))
8973 {
8974 int timeinwater = (int) (calcStat(Stats.BREATH, 86, null, null) * 1000L);
8975 sendPacket(new SetupGauge(this, SetupGauge.CYAN, timeinwater));
8976 if ((getTransformation() > 0) && (getTransformationTemplate() > 0) && !isCursedWeaponEquipped())
8977 {
8978 setTransformation(0);
8979 }
8980 _taskWater = ThreadPoolManager.getInstance().scheduleAtFixedRate(new WaterTask(this), timeinwater, 1000L);
8981 sendChanges();
8982 }
8983 }
8984
8985 public void doRevive(double percent)
8986 {
8987 restoreExp(percent);
8988 doRevive();
8989 }
8990
8991 @Override
8992 public void doRevive()
8993 {
8994 super.doRevive();
8995 setAgathionRes(false);
8996 unsetVar("lostexp");
8997 updateEffectIcons();
8998 autoShot();
8999
9000 // Ady - Block the community buffer 10 seconds so the player cannot buff when resurrected
9001 _resurrectionBuffBlockedTime = System.currentTimeMillis() + 10 * 1000;
9002 }
9003
9004 public void reviveRequest(Player reviver, double percent, boolean pet)
9005 {
9006 ReviveAnswerListener reviveAsk = (_askDialog != null) && (_askDialog.getValue() instanceof ReviveAnswerListener) ? (ReviveAnswerListener) _askDialog.getValue() : null;
9007 if (reviveAsk != null)
9008 {
9009 if ((reviveAsk.isForPet() == pet) && (reviveAsk.getPower() >= percent))
9010 {
9011 reviver.sendPacket(Msg.BETTER_RESURRECTION_HAS_BEEN_ALREADY_PROPOSED);
9012 return;
9013 }
9014 if (pet && !reviveAsk.isForPet())
9015 {
9016 reviver.sendPacket(Msg.SINCE_THE_MASTER_WAS_IN_THE_PROCESS_OF_BEING_RESURRECTED_THE_ATTEMPT_TO_RESURRECT_THE_PET_HAS_BEEN_CANCELLED);
9017 return;
9018 }
9019 if (pet && isDead())
9020 {
9021 reviver.sendPacket(Msg.WHILE_A_PET_IS_ATTEMPTING_TO_RESURRECT_IT_CANNOT_HELP_IN_RESURRECTING_ITS_MASTER);
9022 return;
9023 }
9024 }
9025
9026 if ((pet && getPet() != null && getPet().isDead()) || (!pet && isDead()))
9027 {
9028 ConfirmDlg pkt = new ConfirmDlg(SystemMsg.C1_IS_MAKING_AN_ATTEMPT_TO_RESURRECT_YOU_IF_YOU_CHOOSE_THIS_PATH_S2_EXPERIENCE_WILL_BE_RETURNED_FOR_YOU, (pet ? 0 : 5 * 60 * 1000));
9029 pkt.addName(reviver).addString(Math.round(percent) + " percent");
9030
9031 if (!isDualbox(reviver))
9032 reviver.getCounters().playersRessurected++;
9033
9034 ask(pkt, new ReviveAnswerListener(this, percent, pet));
9035 }
9036 }
9037
9038 /**
9039 * @return Ady - Max time for the player to accept the resurrection request
9040 */
9041 public long getResurrectionMaxTime()
9042 {
9043 return _resurrectionMaxTime;
9044 }
9045
9046 /**
9047 * @return Ady - Block time that the player cannot use the community buffer
9048 */
9049 public long getResurrectionBuffBlockedTime()
9050 {
9051 return _resurrectionBuffBlockedTime;
9052 }
9053
9054 // /**
9055 // * Block time that the player cannot summon a pet
9056 // * @return
9057 // */
9058 public long getPetSummonBlockedTime()
9059 {
9060 return _petSummonBlockedTime;
9061 }
9062
9063 public void summonCharacterRequest(final Creature summoner, final Location loc, final int summonConsumeCrystal)
9064 {
9065 ConfirmDlg cd = new ConfirmDlg(SystemMsg.C1_WISHES_TO_SUMMON_YOU_FROM_S2, 60000);
9066 cd.addName(summoner).addZoneName(loc);
9067
9068 ask(cd, new SummonAnswerListener(this, loc, summonConsumeCrystal));
9069 }
9070
9071 public void scriptRequest(String text, String scriptName, Object[] args)
9072 {
9073 ask(new ConfirmDlg(SystemMsg.S1, 30000).addString(text), new ScriptAnswerListener(this, scriptName, args));
9074 }
9075
9076 public void updateNoChannel(final long time)
9077 {
9078 setNoChannel(time);
9079
9080 final String stmt = "UPDATE characters SET nochannel = ? WHERE obj_Id=?";
9081
9082 try (Connection con = DatabaseFactory.getInstance().getConnection();
9083 PreparedStatement statement = con.prepareStatement(stmt))
9084 {
9085 statement.setLong(1, _NoChannel > 0 ? _NoChannel / 1000 : _NoChannel);
9086 statement.setInt(2, getObjectId());
9087 statement.executeUpdate();
9088 }
9089 catch (final Exception e)
9090 {
9091 _log.warn("Could not activate nochannel:" + e);
9092 }
9093
9094 sendPacket(new EtcStatusUpdate(this));
9095 }
9096
9097 public boolean isJailed()
9098 {
9099 return getVar("jailed") != null;
9100 }
9101
9102 private void checkRecom()
9103 {
9104 Calendar temp = Calendar.getInstance();
9105 temp.set(Calendar.HOUR_OF_DAY, 6);
9106 temp.set(Calendar.MINUTE, 30);
9107 temp.set(Calendar.SECOND, 0);
9108 temp.set(Calendar.MILLISECOND, 0);
9109 long count = Math.round(((System.currentTimeMillis() / 1000) - _lastAccess) / 86400);
9110 if ((count == 0) && (_lastAccess < (temp.getTimeInMillis() / 1000)) && (System.currentTimeMillis() > temp.getTimeInMillis()))
9111 {
9112 count++;
9113 }
9114
9115 for (int i = 1; i < count; i++)
9116 {
9117 setRecomHave(getRecomHave() - 20);
9118 }
9119
9120 if (count > 0)
9121 {
9122 restartRecom();
9123 }
9124 }
9125
9126 public void restartRecom()
9127 {
9128 setRecomBonusTime(3600);
9129 setRecomLeftToday(0);
9130 setRecomLeft(20);
9131 setRecomHave(getRecomHave() - 20);
9132 stopRecomBonusTask(false);
9133 startRecomBonusTask();
9134 sendUserInfo(true);
9135 sendVoteSystemInfo();
9136 }
9137
9138 @Override
9139 public boolean isInBoat()
9140 {
9141 return _boat != null;
9142 }
9143
9144 public Boat getBoat()
9145 {
9146 return _boat;
9147 }
9148
9149 public void setBoat(Boat boat)
9150 {
9151 _boat = boat;
9152 }
9153
9154 public Location getInBoatPosition()
9155 {
9156 return _inBoatPosition;
9157 }
9158
9159 public void setInBoatPosition(Location loc)
9160 {
9161 _inBoatPosition = loc;
9162 }
9163
9164 public Map<Integer, SubClass> getSubClasses()
9165 {
9166 return _classlist;
9167 }
9168
9169 public void setBaseClass(final int baseClass)
9170 {
9171 _baseClass = baseClass;
9172 }
9173
9174 public int getBaseClassId()
9175 {
9176 return _baseClass;
9177 }
9178
9179 public void setActiveClass(SubClass activeClass)
9180 {
9181 _activeClass = activeClass;
9182 }
9183
9184 public SubClass getActiveClass()
9185 {
9186 return _activeClass;
9187 }
9188
9189 public int getActiveClassId()
9190 {
9191 if (getActiveClass() == null)
9192 return -1;
9193
9194 return getActiveClass().getClassId();
9195 }
9196
9197 /**
9198 * Changing index of class in DB, used for changing class when finished professional quests
9199 * @param oldclass
9200 * @param newclass
9201 */
9202 public synchronized void changeClassInDb(final int oldclass, final int newclass)
9203 {
9204 try (Connection con = DatabaseFactory.getInstance().getConnection())
9205 {
9206 try (PreparedStatement statement = con.prepareStatement("UPDATE character_subclasses SET class_id=? WHERE char_obj_id=? AND class_id=?"))
9207 {
9208 statement.setInt(1, newclass);
9209 statement.setInt(2, getObjectId());
9210 statement.setInt(3, oldclass);
9211 statement.executeUpdate();
9212 }
9213
9214 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=?"))
9215 {
9216 statement.setInt(1, getObjectId());
9217 statement.setInt(2, newclass);
9218 statement.executeUpdate();
9219 }
9220
9221 try (PreparedStatement statement = con.prepareStatement("UPDATE character_hennas SET class_index=? WHERE char_obj_id=? AND class_index=?"))
9222 {
9223 statement.setInt(1, newclass);
9224 statement.setInt(2, getObjectId());
9225 statement.setInt(3, oldclass);
9226 statement.executeUpdate();
9227 }
9228
9229 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE object_id=? AND class_index=?"))
9230 {
9231 statement.setInt(1, getObjectId());
9232 statement.setInt(2, newclass);
9233 statement.executeUpdate();
9234 }
9235
9236 try (PreparedStatement statement = con.prepareStatement("UPDATE character_shortcuts SET class_index=? WHERE object_id=? AND class_index=?"))
9237 {
9238 statement.setInt(1, newclass);
9239 statement.setInt(2, getObjectId());
9240 statement.setInt(3, oldclass);
9241 statement.executeUpdate();
9242 }
9243
9244 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=? AND class_index=?"))
9245 {
9246 statement.setInt(1, getObjectId());
9247 statement.setInt(2, newclass);
9248 statement.executeUpdate();
9249 }
9250
9251 try (PreparedStatement statement = con.prepareStatement("UPDATE character_skills SET class_index=? WHERE char_obj_id=? AND class_index=?"))
9252 {
9253 statement.setInt(1, newclass);
9254 statement.setInt(2, getObjectId());
9255 statement.setInt(3, oldclass);
9256 statement.executeUpdate();
9257 }
9258
9259 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_effects_save WHERE object_id=? AND id=?"))
9260 {
9261 statement.setInt(1, getObjectId());
9262 statement.setInt(2, newclass);
9263 statement.executeUpdate();
9264 }
9265
9266 try (PreparedStatement statement = con.prepareStatement("UPDATE character_effects_save SET id=? WHERE object_id=? AND id=?"))
9267 {
9268 statement.setInt(1, newclass);
9269 statement.setInt(2, getObjectId());
9270 statement.setInt(3, oldclass);
9271 statement.executeUpdate();
9272 }
9273
9274 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=?"))
9275 {
9276 statement.setInt(1, getObjectId());
9277 statement.setInt(2, newclass);
9278 statement.executeUpdate();
9279 }
9280
9281 try (PreparedStatement statement = con.prepareStatement("UPDATE character_skills_save SET class_index=? WHERE char_obj_id=? AND class_index=?"))
9282 {
9283 statement.setInt(1, newclass);
9284 statement.setInt(2, getObjectId());
9285 statement.setInt(3, oldclass);
9286 statement.executeUpdate();
9287 }
9288 }
9289 catch (final SQLException e)
9290 {
9291 _log.error("Error while changing Class in Database", e);
9292 }
9293 }
9294
9295 public void storeCharSubClasses()
9296 {
9297 SubClass main = getActiveClass();
9298 if (main != null)
9299 {
9300 main.setCp(getCurrentCp());
9301// main.setExp(getExp());
9302// main.setLevel(getLevel());
9303// main.setSp(getSp());
9304 main.setHp(getCurrentHp());
9305 main.setMp(getCurrentMp());
9306 main.setActive(true);
9307 getSubClasses().put(getActiveClassId(), main);
9308 }
9309 else
9310 {
9311 _log.warn("Could not store char sub data, main class " + getActiveClassId() + " not found for " + this);
9312 }
9313
9314 try (Connection con = DatabaseFactory.getInstance().getConnection();
9315 Statement statement = con.createStatement())
9316 {
9317
9318 StringBuilder sb;
9319 for (SubClass subClass : getSubClasses().values())
9320 {
9321 sb = new StringBuilder("UPDATE character_subclasses SET ");
9322 sb.append("exp=").append(subClass.getExp()).append(",");
9323 sb.append("sp=").append(subClass.getSp()).append(",");
9324 sb.append("curHp=").append(subClass.getHp()).append(",");
9325 sb.append("curMp=").append(subClass.getMp()).append(",");
9326 sb.append("curCp=").append(subClass.getCp()).append(",");
9327 sb.append("level=").append(subClass.getLevel()).append(",");
9328 sb.append("active=").append(subClass.isActive() ? 1 : 0).append(",");
9329 sb.append("isBase=").append(subClass.isBase() ? 1 : 0).append(",");
9330 sb.append("death_penalty=").append(subClass.getDeathPenalty(this).getLevelOnSaveDB()).append(",");
9331 sb.append("certification='").append(subClass.getCertification()).append("'");
9332 sb.append(" WHERE char_obj_id=").append(getObjectId()).append(" AND class_id=").append(subClass.getClassId()).append(" LIMIT 1");
9333 statement.executeUpdate(sb.toString());
9334 }
9335
9336 sb = new StringBuilder("UPDATE character_subclasses SET ");
9337 sb.append("maxHp=").append(getMaxHp()).append(",");
9338 sb.append("maxMp=").append(getMaxMp()).append(",");
9339 sb.append("maxCp=").append(getMaxCp());
9340 sb.append(" WHERE char_obj_id=").append(getObjectId()).append(" AND active=1 LIMIT 1");
9341 statement.executeUpdate(sb.toString());
9342 }
9343 catch (SQLException e)
9344 {
9345 _log.warn("Error while storing Char Subclasses", e);
9346 }
9347 }
9348
9349 /**
9350 * Restore list of character professions and set up active proof Used when character is loading
9351 * @param player
9352 * @param con
9353 */
9354 public static void restoreCharSubClasses(final Player player, Connection con)
9355 {
9356 try (PreparedStatement statement = con.prepareStatement("SELECT class_id,exp,sp,curHp,curCp,curMp,active,isBase,death_penalty,certification FROM character_subclasses WHERE char_obj_id=?"))
9357 {
9358 statement.setInt(1, player.getObjectId());
9359 SubClass activeSubclass = null;
9360
9361 try (ResultSet rset = statement.executeQuery())
9362 {
9363 while (rset.next())
9364 {
9365 final SubClass subClass = new SubClass();
9366 subClass.setBase(rset.getInt("isBase") != 0);
9367 subClass.setClassId(rset.getInt("class_id"));
9368 subClass.setExp(rset.getLong("exp"));
9369 subClass.setSp(rset.getInt("sp"));
9370 subClass.setHp(rset.getDouble("curHp"));
9371 subClass.setMp(rset.getDouble("curMp"));
9372 subClass.setCp(rset.getDouble("curCp"));
9373 subClass.setDeathPenalty(new DeathPenalty(player, rset.getInt("death_penalty")));
9374 subClass.setCertification(rset.getInt("certification"));
9375
9376 boolean active = rset.getInt("active") != 0;
9377 if (active)
9378 {
9379 activeSubclass = subClass;
9380 }
9381 player._classlist.put(subClass.getClassId(), subClass);
9382 }
9383 }
9384 if (player._classlist.isEmpty())
9385 {
9386 _log.error("Error! There are no subclasses for player: " + player);
9387 return;
9388 }
9389
9390 int baseClassId = player._baseClass;
9391 if (baseClassId == -1)
9392 {
9393 _log.error("Error! There is no base class for player: " + player);
9394 return;
9395 }
9396
9397 if (activeSubclass != null)
9398 {
9399 player.setActiveSubClass(activeSubclass.getClassId(), false);
9400 }
9401
9402 if (player._activeClass == null)
9403 {
9404 final SubClass subClass = player._classlist.get(baseClassId);
9405 subClass.setActive(true);
9406 player.setActiveSubClass(subClass.getClassId(), false);
9407 }
9408 }
9409 catch (SQLException e)
9410 {
9411 _log.warn("Could not restore char sub-classes: ", e);
9412 }
9413 }
9414
9415 public boolean addSubClass(final int classId, boolean storeOld, int certification)
9416 {
9417 if (_classlist.size() >= (4 + Config.ALT_GAME_SUB_ADD))
9418 {
9419 return false;
9420 }
9421
9422 final ClassId newId = ClassId.VALUES[classId];
9423
9424 final SubClass newClass = new SubClass();
9425 newClass.setBase(false);
9426 if (newId.getRace() == null)
9427 {
9428 return false;
9429 }
9430
9431 newClass.setClassId(classId);
9432 newClass.setCertification(certification);
9433
9434 _classlist.put(classId, newClass);
9435
9436 try (Connection con = DatabaseFactory.getInstance().getConnection();
9437 PreparedStatement statement = con.prepareStatement("INSERT INTO character_subclasses (char_obj_id, class_id, exp, sp, curHp, curMp, curCp, maxHp, maxMp, maxCp, level, active, isBase, death_penalty, certification) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"))
9438 {
9439 // Store the basic info about this new sub-class.
9440 statement.setInt(1, getObjectId());
9441 statement.setInt(2, newClass.getClassId());
9442 statement.setLong(3, Experience.LEVEL[40]);
9443 statement.setInt(4, 0);
9444 statement.setDouble(5, getCurrentHp());
9445 statement.setDouble(6, getCurrentMp());
9446 statement.setDouble(7, getCurrentCp());
9447 statement.setDouble(8, getCurrentHp());
9448 statement.setDouble(9, getCurrentMp());
9449 statement.setDouble(10, getCurrentCp());
9450 statement.setInt(11, 40);
9451 statement.setInt(12, 0);
9452 statement.setInt(13, 0);
9453 statement.setInt(14, 0);
9454 statement.setInt(15, certification);
9455 statement.execute();
9456 }
9457 catch (final Exception e)
9458 {
9459 _log.warn("Could not add character sub-class: " + e, e);
9460 return false;
9461 }
9462
9463 setActiveSubClass(classId, storeOld);
9464
9465 boolean countUnlearnable = true;
9466 int unLearnable = 0;
9467
9468 Collection<SkillLearn> skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
9469 while (skills.size() > unLearnable)
9470 {
9471 for (final SkillLearn s : skills)
9472 {
9473 final Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
9474 if ((sk == null) || !sk.getCanLearn(newId))
9475 {
9476 if (countUnlearnable)
9477 {
9478 unLearnable++;
9479 }
9480 continue;
9481 }
9482 addSkill(sk, true);
9483 }
9484 countUnlearnable = false;
9485 skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
9486 }
9487
9488 sendPacket(new SkillList(this));
9489 setCurrentHpMp(getMaxHp(), getMaxMp(), true);
9490 setCurrentCp(getMaxCp());
9491 return true;
9492 }
9493
9494 public boolean modifySubClass(final int oldClassId, final int newClassId)
9495 {
9496 final SubClass originalClass = _classlist.get(oldClassId);
9497 if ((originalClass == null) || originalClass.isBase())
9498 {
9499 return false;
9500 }
9501
9502 final int certification = originalClass.getCertification();
9503
9504 try (Connection con = DatabaseFactory.getInstance().getConnection())
9505 {
9506
9507 // Remove all basic info stored about this sub-class.
9508 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_subclasses WHERE char_obj_id=? AND class_id=? AND isBase = 0"))
9509 {
9510 statement.setInt(1, getObjectId());
9511 statement.setInt(2, oldClassId);
9512 statement.execute();
9513 }
9514
9515 // Remove all skill info stored for this sub-class.
9516 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=? AND class_index=? "))
9517 {
9518 statement.setInt(1, getObjectId());
9519 statement.setInt(2, oldClassId);
9520 statement.execute();
9521 }
9522
9523 // Remove all saved skills info stored for this sub-class.
9524 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=? "))
9525 {
9526 statement.setInt(1, getObjectId());
9527 statement.setInt(2, oldClassId);
9528 statement.execute();
9529 }
9530
9531 // Remove all saved effects stored for this sub-class.
9532 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_effects_save WHERE object_id=? AND id=? "))
9533 {
9534 statement.setInt(1, getObjectId());
9535 statement.setInt(2, oldClassId);
9536 statement.execute();
9537 }
9538
9539 // Remove all henna info stored for this sub-class.
9540 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=? "))
9541 {
9542 statement.setInt(1, getObjectId());
9543 statement.setInt(2, oldClassId);
9544 statement.execute();
9545 }
9546
9547 // Remove all shortcuts info stored for this sub-class.
9548 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE object_id=? AND class_index=? "))
9549 {
9550 statement.setInt(1, getObjectId());
9551 statement.setInt(2, oldClassId);
9552 statement.execute();
9553 }
9554 }
9555 catch (final Exception e)
9556 {
9557 _log.warn("Error while deleting char sub-class", e);
9558 }
9559
9560 _classlist.remove(oldClassId);
9561
9562 return (newClassId <= 0) || addSubClass(newClassId, false, certification);
9563 }
9564
9565 public void setActiveSubClass(final int subId, final boolean store)
9566 {
9567 final SubClass sub = _classlist.get(subId);
9568 if (sub == null)
9569 {
9570 return;
9571 }
9572
9573 if (isInDuel())
9574 {
9575 sendMessage("Unable to perform during a duel!");
9576 return;
9577 }
9578
9579 //Fix for Cancel exploit
9580 CancelTaskManager.getInstance().cancelPlayerTasks(this);
9581
9582 if (_activeClass != null)
9583 {
9584 EffectsDAO.getInstance().insert(this);
9585 storeDisableSkills();
9586
9587 if (QuestManager.getQuest(422) != null)
9588 {
9589 String qn = QuestManager.getQuest(422).getName();
9590 if (qn != null)
9591 {
9592 QuestState qs = getQuestState(qn);
9593 if (qs != null)
9594 {
9595 qs.exitCurrentQuest(true);
9596 }
9597 }
9598 }
9599 }
9600
9601 if (store)
9602 {
9603 final SubClass oldsub = _activeClass;
9604 oldsub.setCp(getCurrentCp());
9605// oldsub.setExp(getExp());
9606// oldsub.setLevel(getLevel());
9607// oldsub.setSp(getSp());
9608 oldsub.setHp(getCurrentHp());
9609 oldsub.setMp(getCurrentMp());
9610 oldsub.setActive(false);
9611 _classlist.put(getActiveClassId(), oldsub);
9612 }
9613
9614 sub.setActive(true);
9615 _activeClass = sub;
9616 _classlist.put(getActiveClassId(), sub);
9617
9618 setClassId(subId, false, false);
9619
9620 removeAllSkills();
9621
9622 getEffectList().stopAllEffects();
9623
9624 if ((_summon != null) && (_summon.isSummon() || (Config.ALT_IMPROVED_PETS_LIMITED_USE && (((_summon.getNpcId() == PetDataTable.IMPROVED_BABY_KOOKABURRA_ID) && !isMageClass()) || ((_summon.getNpcId() == PetDataTable.IMPROVED_BABY_BUFFALO_ID) && isMageClass())))))
9625 {
9626 _summon.unSummon();
9627 }
9628
9629 setAgathion(0);
9630
9631 restoreSkills();
9632 rewardSkills(false);
9633 checkSkills();
9634 sendPacket(new ExStorageMaxCount(this));
9635
9636 refreshExpertisePenalty();
9637
9638 sendPacket(new SkillList(this));
9639
9640 _inventory.refreshEquip();
9641 _inventory.validateItems();
9642
9643 for (int i = 0; i < 3; i++)
9644 {
9645 _henna[i] = null;
9646 }
9647
9648 restoreHenna();
9649 sendPacket(new HennaInfo(this));
9650
9651 EffectsDAO.getInstance().restoreEffects(this, true, sub.getHp(), sub.getCp(), sub.getMp());
9652 restoreDisableSkills();
9653
9654 setCurrentHpMp(sub.getHp(), sub.getMp());
9655 setCurrentCp(sub.getCp());
9656
9657 _shortCuts.restore();
9658 sendPacket(new ShortCutInit(this));
9659 for (int shotId : _activeSoulShots)
9660 {
9661 sendPacket(new ExAutoSoulShot(shotId, true));
9662 }
9663 sendPacket(new SkillCoolTime(this));
9664
9665 broadcastPacket(new SocialAction(getObjectId(), SocialAction.LEVEL_UP));
9666
9667 getDeathPenalty().restore(this);
9668
9669 setIncreasedForce(0);
9670
9671 startHourlyTask();
9672
9673 broadcastCharInfo();
9674 updateEffectIcons();
9675 updateStats();
9676 }
9677
9678 public void startKickTask(long delayMillis)
9679 {
9680 stopKickTask();
9681 _kickTask = ThreadPoolManager.getInstance().schedule(new KickTask(this), delayMillis);
9682 }
9683
9684 public void stopKickTask()
9685 {
9686 if (_kickTask != null)
9687 {
9688 _kickTask.cancel(false);
9689 _kickTask = null;
9690 }
9691 }
9692
9693 public Future<?> getExpiration()
9694 {
9695 return _bonusExpiration;
9696 }
9697
9698 public void setExpiration(Future<?> expiration)
9699 {
9700 _bonusExpiration = expiration;
9701 }
9702
9703 public void stopBonusTask(boolean silence)
9704 {
9705 PremiumEnd.getInstance().stopBonusTask(this, silence);
9706 }
9707 public void startBonusTask()
9708 {
9709 if (Config.SERVICES_RATE_TYPE != Bonus.NO_BONUS)
9710 {
9711 int bonusExpire = _connection.getBonusExpire();
9712// double bonus = _connection.getBonus();
9713 double bonus = 1;
9714 if (bonusExpire > (System.currentTimeMillis() / 1000L))
9715 {
9716 _bonus.setRateXp(Config.SERVICES_BONUS_XP * bonus);
9717 _bonus.setRateSp(Config.SERVICES_BONUS_SP * bonus);
9718 _bonus.setDropAdena(Config.SERVICES_BONUS_ADENA * bonus);
9719 _bonus.setDropItems(Config.SERVICES_BONUS_ITEMS * bonus);
9720 _bonus.setDropSpoil(Config.SERVICES_BONUS_SPOIL * bonus);
9721 _bonus.setBonusExpire(bonusExpire);
9722
9723 if (_bonusExpiration == null)
9724 {
9725 _bonusExpiration = LazyPrecisionTaskManager.getInstance().startBonusExpirationTask(this);
9726 }
9727 }
9728 }
9729 }
9730
9731 public void stopBonusTask()
9732 {
9733 if (_bonusExpiration != null)
9734 {
9735 _bonusExpiration.cancel(false);
9736 _bonusExpiration = null;
9737 }
9738 }
9739
9740 @Override
9741 public int getInventoryLimit()
9742 {
9743 return (int) calcStat(Stats.INVENTORY_LIMIT, 0.0, null, null);
9744 }
9745
9746 public int getWarehouseLimit()
9747 {
9748 return (int) calcStat(Stats.STORAGE_LIMIT, 0.0, null, null);
9749 }
9750
9751 public int getTradeLimit()
9752 {
9753 return (int) calcStat(Stats.TRADE_LIMIT, 0.0, null, null);
9754 }
9755
9756 public int getDwarvenRecipeLimit()
9757 {
9758 return (int) calcStat(Stats.DWARVEN_RECIPE_LIMIT, 50.0, null, null) + Config.ALT_ADD_RECIPES;
9759 }
9760
9761 public int getCommonRecipeLimit()
9762 {
9763 return (int) calcStat(Stats.COMMON_RECIPE_LIMIT, 50.0, null, null) + Config.ALT_ADD_RECIPES;
9764 }
9765
9766 public Element getAttackElement()
9767 {
9768 return Formulas.getAttackElement(this, null);
9769 }
9770
9771 public int getAttack(Element element)
9772 {
9773 if (element == Element.NONE)
9774 {
9775 return 0;
9776 }
9777 return (int) calcStat(element.getAttack(), 0., null, null);
9778 }
9779
9780 public int getDefence(Element element)
9781 {
9782 if (element == Element.NONE)
9783 {
9784 return 0;
9785 }
9786 return (int) calcStat(element.getDefence(), 0., null, null);
9787 }
9788
9789 public boolean getAndSetLastItemAuctionRequest()
9790 {
9791 if ((_lastItemAuctionInfoRequest + 2000L) < System.currentTimeMillis())
9792 {
9793 _lastItemAuctionInfoRequest = System.currentTimeMillis();
9794 return true;
9795 }
9796 else
9797 {
9798 _lastItemAuctionInfoRequest = System.currentTimeMillis();
9799 return false;
9800 }
9801 }
9802
9803 @Override
9804 public int getNpcId()
9805 {
9806 return -2;
9807 }
9808
9809 public GameObject getVisibleObject(int id)
9810 {
9811 if (getObjectId() == id)
9812 {
9813 return this;
9814 }
9815
9816 GameObject target = null;
9817
9818 if (getTargetId() == id)
9819 {
9820 target = getTarget();
9821 }
9822
9823 if ((target == null) && (_party != null))
9824 {
9825 for (Player p : _party.getMembers())
9826 {
9827 if ((p != null) && (p.getObjectId() == id))
9828 {
9829 target = p;
9830 break;
9831 }
9832 }
9833 }
9834
9835 if (target == null)
9836 {
9837 target = World.getAroundObjectById(this, id);
9838 }
9839
9840 return (target == null) || target.isInvisible() ? null : target;
9841 }
9842
9843 @Override
9844 public int getPAtk(final Creature target)
9845 {
9846 double init = getActiveWeaponInstance() == null ? (isMageClass() ? 3 : 4) : 0;
9847 return (int) calcStat(Stats.POWER_ATTACK, init, target, null);
9848 }
9849
9850 @Override
9851 public int getPDef(final Creature target)
9852 {
9853 double init = 4.; // empty cloak and underwear slots
9854
9855 final ItemInstance chest = getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
9856 if (chest == null)
9857 {
9858 init += isMageClass() ? ArmorTemplate.EMPTY_BODY_MYSTIC : ArmorTemplate.EMPTY_BODY_FIGHTER;
9859 }
9860 if ((getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS) == null) && ((chest == null) || (chest.getBodyPart() != ItemTemplate.SLOT_FULL_ARMOR)))
9861 {
9862 init += isMageClass() ? ArmorTemplate.EMPTY_LEGS_MYSTIC : ArmorTemplate.EMPTY_LEGS_FIGHTER;
9863 }
9864
9865 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_HEAD) == null)
9866 {
9867 init += ArmorTemplate.EMPTY_HELMET;
9868 }
9869 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_GLOVES) == null)
9870 {
9871 init += ArmorTemplate.EMPTY_GLOVES;
9872 }
9873 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_FEET) == null)
9874 {
9875 init += ArmorTemplate.EMPTY_BOOTS;
9876 }
9877
9878 return (int) calcStat(Stats.POWER_DEFENCE, init, target, null);
9879 }
9880
9881 @Override
9882 public int getMDef(final Creature target, final Skill skill)
9883 {
9884 double init = 0.;
9885
9886 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEAR) == null)
9887 {
9888 init += ArmorTemplate.EMPTY_EARRING;
9889 }
9890 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_REAR) == null)
9891 {
9892 init += ArmorTemplate.EMPTY_EARRING;
9893 }
9894 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_NECK) == null)
9895 {
9896 init += ArmorTemplate.EMPTY_NECKLACE;
9897 }
9898 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LFINGER) == null)
9899 {
9900 init += ArmorTemplate.EMPTY_RING;
9901 }
9902 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_RFINGER) == null)
9903 {
9904 init += ArmorTemplate.EMPTY_RING;
9905 }
9906
9907 return (int) calcStat(Stats.MAGIC_DEFENCE, init, target, skill);
9908 }
9909
9910 public boolean isSubClassActive()
9911 {
9912 return getBaseClassId() != getActiveClassId();
9913 }
9914
9915 @Override
9916 public String getTitle()
9917 {
9918 return super.getTitle();
9919 }
9920
9921 public int getTitleColor()
9922 {
9923 return _titlecolor;
9924 }
9925
9926 public void setTitleColor(final int titlecolor)
9927 {
9928 if (titlecolor != DEFAULT_TITLE_COLOR)
9929 {
9930 setVar("titlecolor", Integer.toHexString(titlecolor), -1);
9931 }
9932 else
9933 {
9934 unsetVar("titlecolor");
9935 }
9936 _titlecolor = titlecolor;
9937 }
9938
9939 @Override
9940 public boolean isCursedWeaponEquipped()
9941 {
9942 return _cursedWeaponEquippedId != 0;
9943 }
9944
9945 public void setCursedWeaponEquippedId(int value)
9946 {
9947 _cursedWeaponEquippedId = value;
9948 }
9949
9950 public int getCursedWeaponEquippedId()
9951 {
9952 return _cursedWeaponEquippedId;
9953 }
9954
9955 @Override
9956 public boolean isImmobilized()
9957 {
9958 return super.isImmobilized() || isOverloaded() || isSitting() || isFishing();
9959 }
9960
9961 @Override
9962 public boolean isBlocked()
9963 {
9964 return super.isBlocked() || isInMovie() || isInObserverMode() || isTeleporting() || isLogoutStarted();
9965 }
9966
9967 @Override
9968 public boolean isInvul()
9969 {
9970 return super.isInvul() || isInMovie();
9971 }
9972
9973 /**
9974 * if True, the L2Player can't take more item
9975 * @param overloaded
9976 */
9977 public void setOverloaded(boolean overloaded)
9978 {
9979 _overloaded = overloaded;
9980 }
9981
9982 public boolean isOverloaded()
9983 {
9984 return _overloaded;
9985 }
9986
9987 public boolean isFishing()
9988 {
9989 return _isFishing;
9990 }
9991
9992 public Fishing getFishing()
9993 {
9994 return _fishing;
9995 }
9996
9997 public void setFishing(boolean value)
9998 {
9999 _isFishing = value;
10000 }
10001
10002 public void startFishing(FishTemplate fish, int lureId)
10003 {
10004 _fishing.setFish(fish);
10005 _fishing.setLureId(lureId);
10006 _fishing.startFishing();
10007 }
10008
10009 public void stopFishing()
10010 {
10011 _fishing.stopFishing();
10012 }
10013
10014 public Location getFishLoc()
10015 {
10016 return _fishing.getFishLoc();
10017 }
10018
10019 public Bonus getBonus()
10020 {
10021 return _bonus;
10022 }
10023
10024 public boolean hasBonus()
10025 {
10026 return _bonus.getBonusExpire() > (System.currentTimeMillis() / 1000L);
10027 }
10028
10029 @Override
10030 public double getRateAdena()
10031 {
10032 return _party == null ? _bonus.getDropAdena() : _party._rateAdena;
10033 }
10034
10035 @Override
10036 public double getRateItems()
10037 {
10038 return _party == null ? _bonus.getDropItems() : _party._rateDrop;
10039 }
10040
10041 @Override
10042 public double getRateExp()
10043 {
10044 return calcStat(Stats.EXP, (_party == null ? _bonus.getRateXp() : _party._rateExp), null, null);
10045 }
10046
10047 @Override
10048 public double getRateSp()
10049 {
10050 return calcStat(Stats.SP, (_party == null ? _bonus.getRateSp() : _party._rateSp), null, null);
10051 }
10052
10053 @Override
10054 public double getRateSpoil()
10055 {
10056 return _party == null ? _bonus.getDropSpoil() : _party._rateSpoil;
10057 }
10058
10059 private boolean _maried = false;
10060 private int _partnerId = 0;
10061 private int _coupleId = 0;
10062 private boolean _maryrequest = false;
10063 private boolean _maryaccepted = false;
10064
10065 public boolean isMaried()
10066 {
10067 return _maried;
10068 }
10069
10070 public void setMaried(boolean state)
10071 {
10072 _maried = state;
10073 }
10074
10075 public void setMaryRequest(boolean state)
10076 {
10077 _maryrequest = state;
10078 }
10079
10080 public boolean isMaryRequest()
10081 {
10082 return _maryrequest;
10083 }
10084
10085 public void setMaryAccepted(boolean state)
10086 {
10087 _maryaccepted = state;
10088 }
10089
10090 public boolean isMaryAccepted()
10091 {
10092 return _maryaccepted;
10093 }
10094
10095 public int getPartnerId()
10096 {
10097 return _partnerId;
10098 }
10099
10100 public void setPartnerId(int partnerid)
10101 {
10102 _partnerId = partnerid;
10103 }
10104
10105 public int getCoupleId()
10106 {
10107 return _coupleId;
10108 }
10109
10110 public void setCoupleId(int coupleId)
10111 {
10112 _coupleId = coupleId;
10113 }
10114
10115 public void setUndying(boolean val)
10116 {
10117 if (!isGM())
10118 {
10119 return;
10120 }
10121 _isUndying = val;
10122 }
10123
10124 public boolean isUndying()
10125 {
10126 return _isUndying;
10127 }
10128
10129 private final GArray<Player> _snoopListener = new GArray<Player>();
10130 private final GArray<Player> _snoopedPlayer = new GArray<Player>();
10131
10132 public void broadcastSnoop(int type, String name, String _text)
10133 {
10134 if (_snoopListener.size() > 0)
10135 {
10136 Snoop sn = new Snoop(getObjectId(), getName(), type, name, _text);
10137 for (Player pci : _snoopListener)
10138 {
10139 if (pci != null)
10140 {
10141 pci.sendPacket(sn);
10142 }
10143 }
10144 }
10145 }
10146
10147 public void addSnooper(Player pci)
10148 {
10149 if (!_snoopListener.contains(pci))
10150 {
10151 _snoopListener.add(pci);
10152 }
10153 }
10154
10155 public void removeSnooper(Player pci)
10156 {
10157 _snoopListener.remove(pci);
10158 }
10159
10160 public void addSnooped(Player pci)
10161 {
10162 if (!_snoopedPlayer.contains(pci))
10163 {
10164 _snoopedPlayer.add(pci);
10165 }
10166 }
10167
10168 public void removeSnooped(Player pci)
10169 {
10170 _snoopedPlayer.remove(pci);
10171 }
10172
10173 public void resetReuse()
10174 {
10175 _skillReuses.clear();
10176 _sharedGroupReuses.clear();
10177 }
10178
10179 public DeathPenalty getDeathPenalty()
10180 {
10181 return _activeClass == null ? null : _activeClass.getDeathPenalty(this);
10182 }
10183
10184 private boolean _charmOfCourage = false;
10185
10186 public boolean isCharmOfCourage()
10187 {
10188 return _charmOfCourage;
10189 }
10190
10191 public void setCharmOfCourage(boolean val)
10192 {
10193 _charmOfCourage = val;
10194
10195 if (!val)
10196 {
10197 getEffectList().stopEffect(Skill.SKILL_CHARM_OF_COURAGE);
10198 }
10199
10200 sendEtcStatusUpdate();
10201 }
10202
10203 private int _increasedForce = 0;
10204 private int _consumedSouls = 0;
10205
10206 @Override
10207 public int getIncreasedForce()
10208 {
10209 return _increasedForce;
10210 }
10211
10212 @Override
10213 public int getConsumedSouls()
10214 {
10215 return _consumedSouls;
10216 }
10217
10218 @Override
10219 public void setConsumedSouls(int i, NpcInstance monster)
10220 {
10221 if (i == _consumedSouls)
10222 {
10223 return;
10224 }
10225
10226 int max = (int) calcStat(Stats.SOULS_LIMIT, 0, monster, null);
10227
10228 if (i > max)
10229 {
10230 i = max;
10231 }
10232
10233 if (i <= 0)
10234 {
10235 _consumedSouls = 0;
10236 sendEtcStatusUpdate();
10237 return;
10238 }
10239
10240 if (_consumedSouls != i)
10241 {
10242 int diff = i - _consumedSouls;
10243 if (diff > 0)
10244 {
10245 SystemMessage sm = new SystemMessage(SystemMessage.YOUR_SOUL_HAS_INCREASED_BY_S1_SO_IT_IS_NOW_AT_S2);
10246 sm.addNumber(diff);
10247 sm.addNumber(i);
10248 sendPacket(sm);
10249 }
10250 }
10251 else if (max == i)
10252 {
10253 sendPacket(Msg.SOUL_CANNOT_BE_ABSORBED_ANY_MORE);
10254 return;
10255 }
10256
10257 _consumedSouls = i;
10258 sendPacket(new EtcStatusUpdate(this));
10259 }
10260
10261 @Override
10262 public void setIncreasedForce(int i)
10263 {
10264 i = Math.min(i, Charge.MAX_CHARGE);
10265 i = Math.max(i, 0);
10266
10267 if ((i != 0) && (i > _increasedForce))
10268 {
10269 sendPacket(new SystemMessage(SystemMessage.YOUR_FORCE_HAS_INCREASED_TO_S1_LEVEL).addNumber(i));
10270 }
10271
10272 _increasedForce = i;
10273 sendEtcStatusUpdate();
10274 }
10275
10276 private long _lastFalling;
10277
10278 public boolean isFalling()
10279 {
10280 return (System.currentTimeMillis() - _lastFalling) < 5000;
10281 }
10282
10283 public void falling(int height)
10284 {
10285 if (!Config.DAMAGE_FROM_FALLING || isDead() || isFlying() || isInWater() || isInBoat())
10286 {
10287 return;
10288 }
10289 _lastFalling = System.currentTimeMillis();
10290 int damage = (int) calcStat(Stats.FALL, (getMaxHp() / 2000) * height, null, null);
10291 if (damage > 0)
10292 {
10293 int curHp = (int) getCurrentHp();
10294 if ((curHp - damage) < 1)
10295 {
10296 setCurrentHp(1, false);
10297 }
10298 else
10299 {
10300 setCurrentHp(curHp - damage, false);
10301 }
10302 sendPacket(new SystemMessage(SystemMessage.YOU_RECEIVED_S1_DAMAGE_FROM_TAKING_A_HIGH_FALL).addNumber(damage));
10303 }
10304 }
10305
10306 @Override
10307 public void checkHpMessages(double curHp, double newHp)
10308 {
10309 int[] _hp =
10310 {
10311 30,
10312 30
10313 };
10314 int[] skills =
10315 {
10316 290,
10317 291
10318 };
10319
10320 int[] _effects_skills_id =
10321 {
10322 139,
10323 176,
10324 292,
10325 292,
10326 420
10327 };
10328 int[] _effects_hp =
10329 {
10330 30,
10331 30,
10332 30,
10333 60,
10334 30
10335 };
10336
10337 double percent = getMaxHp() / 100;
10338 double _curHpPercent = curHp / percent;
10339 double _newHpPercent = newHp / percent;
10340 boolean needsUpdate = false;
10341
10342 // check for passive skills
10343 for (int i = 0; i < skills.length; i++)
10344 {
10345 int level = getSkillLevel(skills[i]);
10346 if (level > 0)
10347 {
10348 if ((_curHpPercent > _hp[i]) && (_newHpPercent <= _hp[i]))
10349 {
10350 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_DECREASED_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(skills[i], level));
10351 needsUpdate = true;
10352 }
10353 else if ((_curHpPercent <= _hp[i]) && (_newHpPercent > _hp[i]))
10354 {
10355 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_INCREASED_THE_EFFECT_OF_S1_WILL_DISAPPEAR).addSkillName(skills[i], level));
10356 needsUpdate = true;
10357 }
10358 }
10359 }
10360
10361 // check for active effects
10362 for (Integer i = 0; i < _effects_skills_id.length; i++)
10363 {
10364 if (getEffectList().getEffectsBySkillId(_effects_skills_id[i]) != null)
10365 {
10366 if ((_curHpPercent > _effects_hp[i]) && (_newHpPercent <= _effects_hp[i]))
10367 {
10368 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_DECREASED_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(_effects_skills_id[i], 1));
10369 needsUpdate = true;
10370 }
10371 else if ((_curHpPercent <= _effects_hp[i]) && (_newHpPercent > _effects_hp[i]))
10372 {
10373 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_INCREASED_THE_EFFECT_OF_S1_WILL_DISAPPEAR).addSkillName(_effects_skills_id[i], 1));
10374 needsUpdate = true;
10375 }
10376 }
10377 }
10378
10379 if (needsUpdate)
10380 {
10381 sendChanges();
10382 }
10383 }
10384
10385 public void checkDayNightMessages()
10386 {
10387 int level = getSkillLevel(294);
10388 if (level > 0)
10389 {
10390 if (GameTimeController.getInstance().isNowNight())
10391 {
10392 sendPacket(new SystemMessage(SystemMessage.IT_IS_NOW_MIDNIGHT_AND_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(294, level));
10393 }
10394 else
10395 {
10396 sendPacket(new SystemMessage(SystemMessage.IT_IS_DAWN_AND_THE_EFFECT_OF_S1_WILL_NOW_DISAPPEAR).addSkillName(294, level));
10397 }
10398 }
10399 sendChanges();
10400 }
10401
10402 public int getZoneMask()
10403 {
10404 return _zoneMask;
10405 }
10406
10407 @Override
10408 protected void onUpdateZones(List<Zone> leaving, List<Zone> entering)
10409 {
10410 super.onUpdateZones(leaving, entering);
10411
10412 if (((leaving == null) || leaving.isEmpty()) && ((entering == null) || entering.isEmpty()))
10413 {
10414 return;
10415 }
10416
10417 boolean lastInCombatZone = (_zoneMask & ZONE_PVP_FLAG) == ZONE_PVP_FLAG;
10418 boolean lastInDangerArea = (_zoneMask & ZONE_ALTERED_FLAG) == ZONE_ALTERED_FLAG;
10419 boolean lastOnSiegeField = (_zoneMask & ZONE_SIEGE_FLAG) == ZONE_SIEGE_FLAG;
10420 boolean lastInPeaceZone = (_zoneMask & ZONE_PEACE_FLAG) == ZONE_PEACE_FLAG;
10421 @SuppressWarnings("unused")
10422 boolean lastInSSQZone = (_zoneMask & ZONE_SSQ_FLAG) == ZONE_SSQ_FLAG;
10423
10424 boolean isInCombatZone = isInCombatZone();
10425 boolean isInDangerArea = isInDangerArea();
10426 boolean isOnSiegeField = isOnSiegeField();
10427 boolean isInPeaceZone = isInPeaceZone();
10428 boolean isInSSQZone = isInSSQZone();
10429
10430 // update the compass, only if the character in the world
10431 int lastZoneMask = _zoneMask;
10432 _zoneMask = 0;
10433
10434 if (isInCombatZone)
10435 {
10436 _zoneMask |= ZONE_PVP_FLAG;
10437 }
10438 if (isInDangerArea)
10439 {
10440 _zoneMask |= ZONE_ALTERED_FLAG;
10441 }
10442 if (isOnSiegeField)
10443 {
10444 _zoneMask |= ZONE_SIEGE_FLAG;
10445 }
10446 if (isInPeaceZone)
10447 {
10448 _zoneMask |= ZONE_PEACE_FLAG;
10449 }
10450 if (isInSSQZone)
10451 {
10452 _zoneMask |= ZONE_SSQ_FLAG;
10453 }
10454
10455 if (lastZoneMask != _zoneMask)
10456 {
10457 sendPacket(new ExSetCompassZoneCode(this));
10458 }
10459
10460 if (lastInCombatZone != isInCombatZone)
10461 {
10462 broadcastRelationChanged();
10463 }
10464
10465 if (lastInDangerArea != isInDangerArea)
10466 {
10467 sendPacket(new EtcStatusUpdate(this));
10468 }
10469
10470 if (lastOnSiegeField != isOnSiegeField)
10471 {
10472 broadcastRelationChanged();
10473 if (isOnSiegeField)
10474 {
10475 sendPacket(Msg.YOU_HAVE_ENTERED_A_COMBAT_ZONE);
10476 }
10477 else
10478 {
10479 sendPacket(Msg.YOU_HAVE_LEFT_A_COMBAT_ZONE);
10480 if (!isTeleporting() && (getPvpFlag() == 0))
10481 {
10482 startPvPFlag(null);
10483 }
10484 }
10485 }
10486
10487 if (lastInPeaceZone != isInPeaceZone)
10488 {
10489 if (isInPeaceZone)
10490 {
10491 setRecomTimerActive(false);
10492 if (getNevitSystem().isActive())
10493 {
10494 getNevitSystem().stopAdventTask(true);
10495 }
10496 startVitalityTask();
10497 }
10498 else
10499 {
10500 stopVitalityTask();
10501 }
10502 }
10503
10504 if (isInWater())
10505 {
10506 startWaterTask();
10507 }
10508 else
10509 {
10510 stopWaterTask();
10511 }
10512 }
10513
10514 public void startAutoSaveTask()
10515 {
10516 if (!Config.AUTOSAVE)
10517 {
10518 return;
10519 }
10520 if (_autoSaveTask == null)
10521 {
10522 _autoSaveTask = AutoSaveManager.getInstance().addAutoSaveTask(this);
10523 }
10524 }
10525
10526 public void stopAutoSaveTask()
10527 {
10528 if (_autoSaveTask != null)
10529 {
10530 _autoSaveTask.cancel(false);
10531 }
10532 _autoSaveTask = null;
10533 }
10534
10535 public void startAutoChargeTask()
10536 {
10537 if (_autoChargeTask == null)
10538 {
10539 _autoChargeTask = AutoRechargeManager.getInstance().addAutoChargeTask(this);
10540 }
10541 }
10542
10543 public void stopAutoChargeTask()
10544 {
10545 if (_autoChargeTask != null)
10546 {
10547 _autoChargeTask.cancel(false);
10548 }
10549 _autoChargeTask = null;
10550 }
10551
10552 public void startVitalityTask()
10553 {
10554 if (!Config.ALT_VITALITY_ENABLED)
10555 {
10556 return;
10557 }
10558 if (_vitalityTask == null)
10559 {
10560 _vitalityTask = LazyPrecisionTaskManager.getInstance().addVitalityRegenTask(this);
10561 }
10562 }
10563
10564 public void stopVitalityTask()
10565 {
10566 if (_vitalityTask != null)
10567 {
10568 _vitalityTask.cancel(false);
10569 }
10570 _vitalityTask = null;
10571 }
10572
10573 public void startPcBangPointsTask()
10574 {
10575 if (!Config.ALT_PCBANG_POINTS_ENABLED || (Config.ALT_PCBANG_POINTS_DELAY <= 0))
10576 {
10577 return;
10578 }
10579 if (_pcCafePointsTask == null)
10580 {
10581 _pcCafePointsTask = LazyPrecisionTaskManager.getInstance().addPCCafePointsTask(this);
10582 }
10583 }
10584
10585 public void stopPcBangPointsTask()
10586 {
10587 if (_pcCafePointsTask != null)
10588 {
10589 _pcCafePointsTask.cancel(false);
10590 }
10591 _pcCafePointsTask = null;
10592 }
10593
10594 public final boolean isInJail()
10595 {
10596 return getVarB("jailed");
10597 }
10598
10599 @Override
10600 public void sendMessage(String message)
10601 {
10602 sendPacket(new SystemMessage(message));
10603 }
10604
10605 private Location _lastClientPosition;
10606 private Location _lastServerPosition;
10607
10608 public void setLastClientPosition(Location position)
10609 {
10610 _lastClientPosition = position;
10611 }
10612
10613 public Location getLastClientPosition()
10614 {
10615 return _lastClientPosition;
10616 }
10617
10618 public void setLastServerPosition(Location position)
10619 {
10620 _lastServerPosition = position;
10621 }
10622
10623 public Location getLastServerPosition()
10624 {
10625 return _lastServerPosition;
10626 }
10627
10628 public ClickersDetector getClickersDetector()
10629 {
10630 if (_detector == null)
10631 _detector = new ClickersDetector(this);
10632 return _detector;
10633 }
10634
10635 public void setHwidLock(String hwid)
10636 {
10637 _hwidLock = hwid;
10638 }
10639
10640 public String getHwidLock()
10641 {
10642 return _hwidLock;
10643 }
10644
10645 private int _useSeed = 0;
10646
10647 public void setUseSeed(int id)
10648 {
10649 _useSeed = id;
10650 }
10651
10652 public int getUseSeed()
10653 {
10654 return _useSeed;
10655 }
10656
10657 public int getFriendRelation()
10658 {
10659 int result = 0;
10660
10661 result |= RelationChanged.RELATION_CLAN_MEMBER;
10662 result |= RelationChanged.RELATION_CLAN_MATE;
10663
10664 return result;
10665 }
10666
10667 public int getWarRelation()
10668 {
10669 int result = 0;
10670
10671 result |= RelationChanged.RELATION_CLAN_MEMBER;
10672 result |= RelationChanged.RELATION_1SIDED_WAR;
10673 result |= RelationChanged.RELATION_MUTUAL_WAR;
10674
10675 return result;
10676 }
10677
10678 public int getRelation(Player target)
10679 {
10680 if (getTeam() != TeamType.NONE && target.getTeam() != TeamType.NONE)
10681 return getTeam() == target.getTeam() ? getFriendRelation() : getWarRelation();
10682
10683 int result = 0;
10684
10685 if (getClan() != null)
10686 {
10687 result |= RelationChanged.RELATION_CLAN_MEMBER;
10688 if (getClan() == target.getClan())
10689 {
10690 result |= RelationChanged.RELATION_CLAN_MATE;
10691 }
10692 if (getClan().getAllyId() != 0)
10693 {
10694 result |= RelationChanged.RELATION_ALLY_MEMBER;
10695 }
10696 }
10697
10698 if (isClanLeader())
10699 {
10700 result |= RelationChanged.RELATION_LEADER;
10701 }
10702
10703 Party party = getParty();
10704 if ((party != null) && (party == target.getParty()))
10705 {
10706 result |= RelationChanged.RELATION_HAS_PARTY;
10707
10708 switch (party.getMembers().indexOf(this))
10709 {
10710 case 0:
10711 result |= RelationChanged.RELATION_PARTYLEADER; // 0x10
10712 break;
10713 case 1:
10714 result |= RelationChanged.RELATION_PARTY4; // 0x8
10715 break;
10716 case 2:
10717 result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY2 + RelationChanged.RELATION_PARTY1; // 0x7
10718 break;
10719 case 3:
10720 result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY2; // 0x6
10721 break;
10722 case 4:
10723 result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY1; // 0x5
10724 break;
10725 case 5:
10726 result |= RelationChanged.RELATION_PARTY3; // 0x4
10727 break;
10728 case 6:
10729 result |= RelationChanged.RELATION_PARTY2 + RelationChanged.RELATION_PARTY1; // 0x3
10730 break;
10731 case 7:
10732 result |= RelationChanged.RELATION_PARTY2; // 0x2
10733 break;
10734 case 8:
10735 result |= RelationChanged.RELATION_PARTY1; // 0x1
10736 break;
10737 }
10738 }
10739
10740 Clan clan1 = getClan();
10741 Clan clan2 = target.getClan();
10742 if ((clan1 != null) && (clan2 != null))
10743 {
10744 if ((target.getPledgeType() != Clan.SUBUNIT_ACADEMY) && (getPledgeType() != Clan.SUBUNIT_ACADEMY))
10745 {
10746 if (clan2.isAtWarWith(clan1.getClanId()))
10747 {
10748 result |= RelationChanged.RELATION_1SIDED_WAR;
10749 if (clan1.isAtWarWith(clan2.getClanId()))
10750 {
10751 result |= RelationChanged.RELATION_MUTUAL_WAR;
10752 }
10753 }
10754 }
10755 if (getBlockCheckerArena() != -1)
10756 {
10757 result |= RelationChanged.RELATION_INSIEGE;
10758 ArenaParticipantsHolder holder = HandysBlockCheckerManager.getInstance().getHolder(getBlockCheckerArena());
10759 if (holder.getPlayerTeam(this) == 0)
10760 {
10761 result |= RelationChanged.RELATION_ENEMY;
10762 }
10763 else
10764 {
10765 result |= RelationChanged.RELATION_ALLY;
10766 }
10767 result |= RelationChanged.RELATION_ATTACKER;
10768 }
10769 }
10770
10771 for (GlobalEvent e : getEvents())
10772 {
10773 result = e.getRelation(this, target, result);
10774 }
10775
10776 return result;
10777 }
10778
10779 /**
10780 * 0=White, 1=Purple, 2=PurpleBlink
10781 */
10782 protected int _pvpFlag;
10783
10784 private ScheduledFuture<?> _PvPRegTask;
10785 private long _lastPvpAttack;
10786
10787 public long getlastPvpAttack()
10788 {
10789 return _lastPvpAttack;
10790 }
10791
10792 @Override
10793 public void startPvPFlag(Creature target)
10794 {
10795 if (_karma > 0)
10796 return;
10797
10798 long startTime = System.currentTimeMillis();
10799 if (target != null && (target.getPvpFlag() != 0 || target.isMonster()))
10800 startTime -= Config.PVP_TIME / 2;
10801
10802 if (_pvpFlag != 0 && _lastPvpAttack > startTime)
10803 return;
10804
10805 _lastPvpAttack = startTime;
10806
10807 updatePvPFlag(1);
10808
10809 if (_PvPRegTask == null)
10810 _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
10811 }
10812
10813 public void stopPvPFlag()
10814 {
10815 if (_PvPRegTask != null)
10816 {
10817 _PvPRegTask.cancel(false);
10818 _PvPRegTask = null;
10819 }
10820 updatePvPFlag(0);
10821 }
10822
10823 public void updatePvPFlag(int value)
10824 {
10825 if (_handysBlockCheckerEventArena != -1)
10826 {
10827 return;
10828 }
10829 if (_pvpFlag == value)
10830 {
10831 return;
10832 }
10833
10834 setPvpFlag(value);
10835
10836 sendStatusUpdate(true, true, StatusUpdate.PVP_FLAG);
10837
10838 broadcastRelationChanged();
10839 }
10840
10841 public void setPvpFlag(int pvpFlag)
10842 {
10843 _pvpFlag = pvpFlag;
10844 }
10845
10846 /**
10847 * @return The remaning time of the pvp flag in miliseconds.
10848 */
10849 public int getPvpFlagRemaningTime()
10850 {
10851 if (_PvPRegTask == null || _PvPRegTask.isDone())
10852 return 0;
10853
10854 return (int) _PvPRegTask.getDelay(TimeUnit.MILLISECONDS);
10855 }
10856
10857 @Override
10858 public int getPvpFlag()
10859 {
10860 return _pvpFlag;
10861 }
10862
10863 public boolean isInDuel()
10864 {
10865 return getEvent(DuelEvent.class) != null;
10866 }
10867
10868 public boolean isRegisteredInFightClub()
10869 {
10870 return getEvent(AbstractFightClub.class) != null;
10871 }
10872
10873 public boolean isInFightClub()
10874 {
10875 try
10876 {
10877 if (getEvent(AbstractFightClub.class) == null)
10878 return false;
10879
10880 return getEvent(AbstractFightClub.class).getFightClubPlayer(this) != null;
10881 }
10882 catch (NullPointerException e)
10883 {
10884 return false;
10885 }
10886 }
10887
10888 public FightClubGameRoom getFightClubGameRoom()
10889 {
10890 return _fightClubGameRoom;
10891 }
10892
10893 public void setFightClubGameRoom(FightClubGameRoom room)
10894 {
10895 _fightClubGameRoom = room;
10896 }
10897
10898 public AbstractFightClub getFightClubEvent()
10899 {
10900 return getEvent(AbstractFightClub.class);
10901 }
10902
10903 private final Map<Integer, TamedBeastInstance> _tamedBeasts = new ConcurrentHashMap<Integer, TamedBeastInstance>();
10904
10905 public Map<Integer, TamedBeastInstance> getTrainedBeasts()
10906 {
10907 return _tamedBeasts;
10908 }
10909
10910 public void addTrainedBeast(TamedBeastInstance tamedBeast)
10911 {
10912 _tamedBeasts.put(tamedBeast.getObjectId(), tamedBeast);
10913 }
10914
10915 public void removeTrainedBeast(int npcId)
10916 {
10917 _tamedBeasts.remove(npcId);
10918 }
10919
10920 private long _lastAttackPacket = 0;
10921
10922 public long getLastAttackPacket()
10923 {
10924 return _lastAttackPacket;
10925 }
10926
10927 public void setLastAttackPacket()
10928 {
10929 _lastAttackPacket = System.currentTimeMillis();
10930 }
10931
10932 private long _lastMovePacket = 0;
10933
10934 public long getLastMovePacket()
10935 {
10936 return _lastMovePacket;
10937 }
10938
10939 public void setLastMovePacket()
10940 {
10941 _lastMovePacket = System.currentTimeMillis();
10942 }
10943
10944 public byte[] getKeyBindings()
10945 {
10946 return _keyBindings;
10947 }
10948
10949 public void setKeyBindings(byte[] keyBindings)
10950 {
10951 if (keyBindings == null)
10952 {
10953 _keyBindings = ArrayUtils.EMPTY_BYTE_ARRAY;
10954 }
10955 else
10956 {
10957 _keyBindings = keyBindings;
10958 }
10959 }
10960
10961 public void setTransformation(int transformationId)
10962 {
10963 if ((transformationId == _transformationId) || ((_transformationId != 0) && (transformationId != 0)))
10964 {
10965 return;
10966 }
10967
10968 if (transformationId == 0)
10969 {
10970 for (Effect effect : getEffectList().getAllEffects())
10971 {
10972 if ((effect != null) && (effect.getEffectType() == EffectType.Transformation))
10973 {
10974 if (effect.calc() == 0)
10975 {
10976 continue;
10977 }
10978 effect.exit();
10979 preparateToTransform(effect.getSkill());
10980 break;
10981 }
10982 }
10983
10984 if (!_transformationSkills.isEmpty())
10985 {
10986 for (Skill s : _transformationSkills.values())
10987 {
10988 if (!s.isCommon() && !SkillAcquireHolder.getInstance().isSkillPossible(this, s) && !s.isHeroic())
10989 {
10990 super.removeSkill(s);
10991 }
10992 }
10993 _transformationSkills.clear();
10994 }
10995 }
10996 else
10997 {
10998 int _id = 0;
10999 int _level = 1;
11000 switch (getBaseClassId())
11001 {
11002 case 97:// Cardinal
11003 _id = 24001;
11004 break;
11005 case 98:// Hierophant
11006 _id = 24002;
11007 break;
11008 case 100:// SwordMuse
11009 _id = 24003;
11010 break;
11011 case 105:// EvaSaint
11012 _id = 24004;
11013 break;
11014 case 107:// SpectralDancer
11015 _id = 24005;
11016 break;
11017 case 112:// ShillienSaint
11018 _id = 24006;
11019 break;
11020 case 115:// Dominator
11021 _id = 24007;
11022 break;
11023 case 116:// Doomcryer
11024 _id = 24008;
11025 break;
11026 }
11027
11028 Skill _skill = SkillTable.getInstance().getInfo(_id, _level);
11029 if (_skill != null)
11030 {
11031 super.removeSkill(_skill);
11032 removeSkillFromShortCut(_skill.getId());
11033 }
11034
11035 if (!isCursedWeaponEquipped())
11036 {
11037 for (Effect effect : getEffectList().getAllEffects())
11038 {
11039 if ((effect != null) && (effect.getEffectType() == EffectType.Transformation))
11040 {
11041 if ((effect.getSkill() instanceof Transformation) && ((Transformation) effect.getSkill()).isDisguise)
11042 {
11043 for (Skill s : getAllSkills())
11044 {
11045 if ((s != null) && (s.isActive() || s.isToggle()))
11046 {
11047 _transformationSkills.put(s.getId(), s);
11048 }
11049 }
11050 }
11051 else
11052 {
11053 for (AddedSkill s : effect.getSkill().getAddedSkills())
11054 {
11055 if (s.level == 0)
11056 {
11057 int s2 = getSkillLevel(s.id);
11058 if (s2 > 0)
11059 {
11060 _transformationSkills.put(s.id, SkillTable.getInstance().getInfo(s.id, s2));
11061 }
11062 }
11063 else if (s.level == -2) // XXX: wild heartburn for skills depending on the player's level
11064 {
11065 int learnLevel = Math.max(effect.getSkill().getMagicLevel(), 40);
11066 int maxLevel = SkillTable.getInstance().getBaseLevel(s.id);
11067 int curSkillLevel = 1;
11068 if (maxLevel > 3)
11069 {
11070 curSkillLevel += getLevel() - learnLevel;
11071 }
11072 else
11073 {
11074 curSkillLevel += (getLevel() - learnLevel) / ((76 - learnLevel) / maxLevel);
11075 }
11076 curSkillLevel = Math.min(Math.max(curSkillLevel, 1), maxLevel);
11077 _transformationSkills.put(s.id, SkillTable.getInstance().getInfo(s.id, curSkillLevel));
11078 }
11079 else
11080 {
11081 _transformationSkills.put(s.id, s.getSkill());
11082 }
11083 }
11084 }
11085 preparateToTransform(effect.getSkill());
11086 break;
11087 }
11088 }
11089 }
11090 else
11091 {
11092 preparateToTransform(null);
11093 }
11094
11095 if (!isInOlympiadMode() && !isCursedWeaponEquipped() && _hero && (getBaseClassId() == getActiveClassId()))
11096 {
11097 _transformationSkills.put(395, SkillTable.getInstance().getInfo(395, 1));
11098 _transformationSkills.put(396, SkillTable.getInstance().getInfo(396, 1));
11099 _transformationSkills.put(1374, SkillTable.getInstance().getInfo(1374, 1));
11100 _transformationSkills.put(1375, SkillTable.getInstance().getInfo(1375, 1));
11101 _transformationSkills.put(1376, SkillTable.getInstance().getInfo(1376, 1));
11102 }
11103
11104 for (Skill s : _transformationSkills.values())
11105 {
11106 addSkill(s, false);
11107 }
11108 }
11109
11110 _transformationId = transformationId;
11111
11112 sendPacket(new ExBasicActionList(this));
11113 sendPacket(new SkillList(this));
11114 sendPacket(new ShortCutInit(this));
11115 for (int shotId : getAutoSoulShot())
11116 {
11117 sendPacket(new ExAutoSoulShot(shotId, true));
11118 }
11119 broadcastUserInfo(true);
11120 }
11121
11122 private void preparateToTransform(Skill transSkill)
11123 {
11124 if ((transSkill == null) || !transSkill.isBaseTransformation())
11125 {
11126 for (Effect effect : getEffectList().getAllEffects())
11127 {
11128 if ((effect != null) && effect.getSkill().isToggle())
11129 {
11130 effect.exit();
11131 }
11132 }
11133 }
11134 }
11135
11136 public boolean isInFlyingTransform()
11137 {
11138 return (_transformationId == 8) || (_transformationId == 9) || (_transformationId == 260);
11139 }
11140
11141 public boolean isInMountTransform()
11142 {
11143 return (_transformationId == 106) || (_transformationId == 109) || (_transformationId == 110) || (_transformationId == 20001);
11144 }
11145
11146 public int getTransformation()
11147 {
11148 return _transformationId;
11149 }
11150
11151 public String getTransformationName()
11152 {
11153 return _transformationName;
11154 }
11155
11156 public void setTransformationName(String name)
11157 {
11158 _transformationName = name;
11159 }
11160
11161 public void setTransformationTemplate(int template)
11162 {
11163 _transformationTemplate = template;
11164 }
11165
11166 public int getTransformationTemplate()
11167 {
11168 return _transformationTemplate;
11169 }
11170
11171 @Override
11172 public final Collection<Skill> getAllSkills()
11173 {
11174 if (_transformationId == 0)
11175 {
11176 return super.getAllSkills();
11177 }
11178
11179 Map<Integer, Skill> tempSkills = new HashMap<Integer, Skill>();
11180 for (Skill s : super.getAllSkills())
11181 {
11182 if ((s != null) && !s.isActive() && !s.isToggle())
11183 {
11184 tempSkills.put(s.getId(), s);
11185 }
11186 }
11187 tempSkills.putAll(_transformationSkills);
11188 return tempSkills.values();
11189 }
11190
11191 public void setAgathion(int id)
11192 {
11193 if (_agathionId == id)
11194 {
11195 return;
11196 }
11197
11198 _agathionId = id;
11199 broadcastCharInfo();
11200 }
11201
11202 public int getAgathionId()
11203 {
11204 return _agathionId;
11205 }
11206
11207 public int getPcBangPoints()
11208 {
11209 return _pcBangPoints;
11210 }
11211
11212 public void setPcBangPoints(int val)
11213 {
11214 _pcBangPoints = val;
11215 }
11216
11217 public void addPcBangPoints(int count, boolean doublePoints)
11218 {
11219 if (doublePoints)
11220 {
11221 count *= 2;
11222 }
11223
11224 _pcBangPoints += count;
11225
11226 sendPacket(new SystemMessage(doublePoints ? SystemMessage.DOUBLE_POINTS_YOU_AQUIRED_S1_PC_BANG_POINT : SystemMessage.YOU_ACQUIRED_S1_PC_BANG_POINT).addNumber(count));
11227 sendPacket(new ExPCCafePointInfo(this, count, 1, 2, 12));
11228 }
11229
11230 public boolean reducePcBangPoints(int count)
11231 {
11232 if (_pcBangPoints < count)
11233 {
11234 return false;
11235 }
11236
11237 _pcBangPoints -= count;
11238 sendPacket(new SystemMessage(SystemMessage.YOU_ARE_USING_S1_POINT).addNumber(count));
11239 sendPacket(new ExPCCafePointInfo(this, 0, 1, 2, 12));
11240 return true;
11241 }
11242
11243 private Location _groundSkillLoc;
11244
11245 public void setGroundSkillLoc(Location location)
11246 {
11247 _groundSkillLoc = location;
11248 }
11249
11250 public Location getGroundSkillLoc()
11251 {
11252 return _groundSkillLoc;
11253 }
11254
11255 public boolean isLogoutStarted()
11256 {
11257 return _isLogout.get();
11258 }
11259
11260 public void setOfflineMode(boolean val)
11261 {
11262 if (!val)
11263 {
11264 unsetVar("offline");
11265 }
11266 _offline = val;
11267 }
11268
11269 public boolean isInOfflineMode()
11270 {
11271 return _offline;
11272 }
11273
11274 public void saveTradeList()
11275 {
11276 StringBuilder tradeListBuilder = new StringBuilder();
11277
11278 if ((_sellList == null) || _sellList.isEmpty())
11279 {
11280 unsetVar("selllist");
11281 }
11282 else
11283 {
11284 for (TradeItem i : _sellList)
11285 {
11286 tradeListBuilder.append(i.getObjectId()).append(";").append(i.getCount()).append(";").append(i.getOwnersPrice()).append(":");
11287 }
11288 setVar("selllist", tradeListBuilder.toString(), -1);
11289 tradeListBuilder.delete(0, tradeListBuilder.length());
11290 if ((_tradeList != null) && (getSellStoreName() != null))
11291 {
11292 setVar("sellstorename", getSellStoreName(), -1);
11293 }
11294 }
11295
11296 if ((_packageSellList == null) || _packageSellList.isEmpty())
11297 {
11298 unsetVar("packageselllist");
11299 }
11300 else
11301 {
11302 for (TradeItem i : _packageSellList)
11303 {
11304 tradeListBuilder.append(i.getObjectId()).append(";").append(i.getCount()).append(";").append(i.getOwnersPrice()).append(":");
11305 }
11306 setVar("packageselllist", tradeListBuilder.toString(), -1);
11307 tradeListBuilder.delete(0, tradeListBuilder.length());
11308 if ((_tradeList != null) && (getSellStoreName() != null))
11309 {
11310 setVar("sellstorename", getSellStoreName(), -1);
11311 }
11312 }
11313
11314 if ((_buyList == null) || _buyList.isEmpty())
11315 {
11316 unsetVar("buylist");
11317 }
11318 else
11319 {
11320 for (TradeItem i : _buyList)
11321 {
11322 tradeListBuilder.append(i.getItemId()).append(";").append(i.getCount()).append(";").append(i.getOwnersPrice()).append(":");
11323 }
11324 setVar("buylist", tradeListBuilder.toString(), -1);
11325 tradeListBuilder.delete(0, tradeListBuilder.length());
11326 if ((_tradeList != null) && (getBuyStoreName() != null))
11327 {
11328 setVar("buystorename", getBuyStoreName(), -1);
11329 }
11330 }
11331
11332 if ((_createList == null) || _createList.isEmpty())
11333 {
11334 unsetVar("createlist");
11335 }
11336 else
11337 {
11338 for (ManufactureItem i : _createList)
11339 {
11340 tradeListBuilder.append(i.getRecipeId()).append(";").append(i.getCost()).append(":");
11341 }
11342 setVar("createlist", tradeListBuilder.toString(), -1);
11343 if (getManufactureName() != null)
11344 {
11345 setVar("manufacturename", getManufactureName(), -1);
11346 }
11347 }
11348 }
11349
11350 public void restoreTradeList()
11351 {
11352 String var;
11353 var = getVar("selllist");
11354 if (var != null)
11355 {
11356 _sellList = new CopyOnWriteArrayList<TradeItem>();
11357 String[] items = var.split(":");
11358 for (String item : items)
11359 {
11360 if (item.equals(""))
11361 {
11362 continue;
11363 }
11364 String[] values = item.split(";");
11365 if (values.length < 3)
11366 {
11367 continue;
11368 }
11369
11370 int oId = Integer.parseInt(values[0]);
11371 long count = Long.parseLong(values[1]);
11372 long price = Long.parseLong(values[2]);
11373
11374 ItemInstance itemToSell = getInventory().getItemByObjectId(oId);
11375
11376 if ((count < 1) || (itemToSell == null))
11377 {
11378 continue;
11379 }
11380
11381 if (count > itemToSell.getCount())
11382 {
11383 count = itemToSell.getCount();
11384 }
11385
11386 TradeItem i = new TradeItem(itemToSell);
11387 i.setCount(count);
11388 i.setOwnersPrice(price);
11389
11390 _sellList.add(i);
11391 }
11392 var = getVar("sellstorename");
11393 if (var != null)
11394 {
11395 setSellStoreName(var);
11396 }
11397 }
11398 var = getVar("packageselllist");
11399 if (var != null)
11400 {
11401 _packageSellList = new CopyOnWriteArrayList<TradeItem>();
11402 String[] items = var.split(":");
11403 for (String item : items)
11404 {
11405 if (item.equals(""))
11406 {
11407 continue;
11408 }
11409 String[] values = item.split(";");
11410 if (values.length < 3)
11411 {
11412 continue;
11413 }
11414
11415 int oId = Integer.parseInt(values[0]);
11416 long count = Long.parseLong(values[1]);
11417 long price = Long.parseLong(values[2]);
11418
11419 ItemInstance itemToSell = getInventory().getItemByObjectId(oId);
11420
11421 if ((count < 1) || (itemToSell == null))
11422 {
11423 continue;
11424 }
11425
11426 if (count > itemToSell.getCount())
11427 {
11428 count = itemToSell.getCount();
11429 }
11430
11431 TradeItem i = new TradeItem(itemToSell);
11432 i.setCount(count);
11433 i.setOwnersPrice(price);
11434
11435 _packageSellList.add(i);
11436 }
11437 var = getVar("sellstorename");
11438 if (var != null)
11439 {
11440 setSellStoreName(var);
11441 }
11442 }
11443 var = getVar("buylist");
11444 if (var != null)
11445 {
11446 _buyList = new CopyOnWriteArrayList<TradeItem>();
11447 String[] items = var.split(":");
11448 for (String item : items)
11449 {
11450 if (item.equals(""))
11451 {
11452 continue;
11453 }
11454 String[] values = item.split(";");
11455 if (values.length < 3)
11456 {
11457 continue;
11458 }
11459 TradeItem i = new TradeItem();
11460 i.setItemId(Integer.parseInt(values[0]));
11461 i.setCount(Long.parseLong(values[1]));
11462 i.setOwnersPrice(Long.parseLong(values[2]));
11463 _buyList.add(i);
11464 }
11465 var = getVar("buystorename");
11466 if (var != null)
11467 {
11468 setBuyStoreName(var);
11469 }
11470 }
11471 var = getVar("createlist");
11472 if (var != null)
11473 {
11474 _createList = new CopyOnWriteArrayList<ManufactureItem>();
11475 String[] items = var.split(":");
11476 for (String item : items)
11477 {
11478 if (item.equals(""))
11479 {
11480 continue;
11481 }
11482 String[] values = item.split(";");
11483 if (values.length < 2)
11484 {
11485 continue;
11486 }
11487 int recId = Integer.parseInt(values[0]);
11488 long price = Long.parseLong(values[1]);
11489 if (findRecipe(recId))
11490 {
11491 _createList.add(new ManufactureItem(recId, price));
11492 }
11493 }
11494 var = getVar("manufacturename");
11495 if (var != null)
11496 {
11497 setManufactureName(var);
11498 }
11499 }
11500 }
11501
11502 public void restoreRecipeBook(Connection con)
11503 {
11504 try (PreparedStatement statement = con.prepareStatement("SELECT id FROM character_recipebook WHERE char_id=?"))
11505 {
11506 statement.setInt(1, getObjectId());
11507
11508 try (ResultSet rset = statement.executeQuery())
11509 {
11510 while (rset.next())
11511 {
11512 int id = rset.getInt("id");
11513 Recipe recipe = RecipeHolder.getInstance().getRecipeByRecipeId(id);
11514 registerRecipe(recipe, false);
11515 }
11516 }
11517 }
11518 catch (SQLException e)
11519 {
11520 _log.error("Error while restoring Recipe Book for Id "+getObjectId(), e);
11521 }
11522 }
11523
11524 public DecoyInstance getDecoy()
11525 {
11526 return _decoy;
11527 }
11528
11529 public void setDecoy(DecoyInstance decoy)
11530 {
11531 _decoy = decoy;
11532 }
11533
11534 public int getMountType()
11535 {
11536 switch (getMountNpcId())
11537 {
11538 case PetDataTable.STRIDER_WIND_ID:
11539 case PetDataTable.STRIDER_STAR_ID:
11540 case PetDataTable.STRIDER_TWILIGHT_ID:
11541 case PetDataTable.RED_STRIDER_WIND_ID:
11542 case PetDataTable.RED_STRIDER_STAR_ID:
11543 case PetDataTable.RED_STRIDER_TWILIGHT_ID:
11544 case PetDataTable.GUARDIANS_STRIDER_ID:
11545 return 1;
11546 case PetDataTable.WYVERN_ID:
11547 return 2;
11548 case PetDataTable.WGREAT_WOLF_ID:
11549 case PetDataTable.FENRIR_WOLF_ID:
11550 case PetDataTable.WFENRIR_WOLF_ID:
11551 return 3;
11552 }
11553 return 0;
11554 }
11555
11556 @Override
11557 public double getColRadius()
11558 {
11559 if (getTransformation() != 0)
11560 {
11561 if (getTransformationTemplate() == 32)
11562 {
11563 setTransformation(0);
11564 }
11565 else
11566 {
11567 final int template = getTransformationTemplate();
11568 if (template != 0)
11569 {
11570 final NpcTemplate npcTemplate = NpcHolder.getInstance().getTemplate(template);
11571 if (npcTemplate != null)
11572 {
11573 return npcTemplate.collisionRadius;
11574 }
11575 }
11576 }
11577 }
11578 else if (isMounted())
11579 {
11580 final int mountTemplate = getMountNpcId();
11581 if (mountTemplate != 0)
11582 {
11583 final NpcTemplate mountNpcTemplate = NpcHolder.getInstance().getTemplate(mountTemplate);
11584 if (mountNpcTemplate != null)
11585 {
11586 return mountNpcTemplate.collisionRadius;
11587 }
11588 }
11589 }
11590 return getBaseTemplate().collisionRadius;
11591 }
11592
11593 @Override
11594 public double getColHeight()
11595 {
11596 if (getTransformation() != 0)
11597 {
11598 if (getTransformationTemplate() == 32)
11599 {
11600 setTransformation(0);
11601 }
11602 else
11603 {
11604 final int template = getTransformationTemplate();
11605 if (template != 0)
11606 {
11607 final NpcTemplate npcTemplate = NpcHolder.getInstance().getTemplate(template);
11608 if (npcTemplate != null)
11609 {
11610 return npcTemplate.collisionHeight;
11611 }
11612 }
11613 }
11614 }
11615 else if (isMounted())
11616 {
11617 final int mountTemplate = getMountNpcId();
11618 if (mountTemplate != 0)
11619 {
11620 final NpcTemplate mountNpcTemplate = NpcHolder.getInstance().getTemplate(mountTemplate);
11621 if (mountNpcTemplate != null)
11622 {
11623 return mountNpcTemplate.collisionHeight;
11624 }
11625 }
11626 }
11627 return getBaseTemplate().collisionHeight;
11628 }
11629
11630 @Override
11631 public void setReflection(Reflection reflection)
11632 {
11633 if (getReflection() == reflection)
11634 {
11635 return;
11636 }
11637
11638 super.setReflection(reflection);
11639
11640 if ((_summon != null) && !_summon.isDead())
11641 {
11642 _summon.setReflection(reflection);
11643 }
11644
11645 if (reflection != ReflectionManager.DEFAULT)
11646 {
11647 String var = getVar("reflection");
11648 if ((var == null) || !var.equals(String.valueOf(reflection.getId())))
11649 {
11650 setVar("reflection", String.valueOf(reflection.getId()), -1);
11651 }
11652 }
11653 else
11654 {
11655 unsetVar("reflection");
11656 }
11657
11658 if (getActiveClass() != null)
11659 {
11660 getInventory().validateItems();
11661 //_129_PailakaDevilsLegacy
11662 if ((getPet() != null) && ((getPet().getNpcId() == 14916) || (getPet().getNpcId() == 14917)))
11663 {
11664 getPet().unSummon();
11665 }
11666 }
11667 }
11668
11669 public boolean isTerritoryFlagEquipped()
11670 {
11671 ItemInstance weapon = getActiveWeaponInstance();
11672 return (weapon != null) && weapon.getTemplate().isTerritoryFlag();
11673 }
11674
11675 private int _buyListId;
11676
11677 public void setBuyListId(int listId)
11678 {
11679 _buyListId = listId;
11680 }
11681
11682 public int getBuyListId()
11683 {
11684 return _buyListId;
11685 }
11686
11687 public int getFame()
11688 {
11689 return _fame;
11690 }
11691
11692 public void setFame(int fame, String log)
11693 {
11694 fame = Math.min(Config.LIM_FAME, fame);
11695 if ((log != null) && !log.isEmpty())
11696 {
11697 Log.add(_name + "|" + (fame - _fame) + "|" + fame + "|" + log, "fame");
11698 }
11699 if (fame > _fame)
11700 {
11701 int added = fame - _fame;
11702 getCounters().fameAcquired += added;
11703 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_ACQUIRED_S1_REPUTATION_SCORE).addNumber(added));
11704 }
11705
11706
11707 // Alexander - Add the fame acquired to the stats
11708 if (fame > _fame)
11709 addPlayerStats(Ranking.STAT_TOP_FAME_ACQUIRED, fame - _fame);
11710
11711 _fame = fame;
11712 sendChanges();
11713 }
11714
11715 public void setFame(int fame)
11716 {
11717 fame = Math.min(Config.LIM_FAME, fame);
11718 if (fame > _fame)
11719 {
11720 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_ACQUIRED_S1_REPUTATION_SCORE).addNumber(fame - _fame));
11721 }
11722
11723 // Alexander - Add the fame acquired to the stats
11724 if (fame > _fame)
11725 addPlayerStats(Ranking.STAT_TOP_FAME_ACQUIRED, fame - _fame);
11726
11727 _fame = fame;
11728 sendChanges();
11729 }
11730
11731 public int getVitalityLevel(boolean blessActive)
11732 {
11733 return Config.ALT_VITALITY_ENABLED ? (blessActive ? 4 : _vitalityLevel) : 0;
11734 }
11735
11736 public double getVitality()
11737 {
11738 return Config.ALT_VITALITY_ENABLED ? _vitality : 0;
11739 }
11740
11741 public void addVitality(double val)
11742 {
11743 setVitality(getVitality() + val);
11744 }
11745
11746 public void setVitality(double newVitality)
11747 {
11748 if (!Config.ALT_VITALITY_ENABLED)
11749 {
11750 return;
11751 }
11752
11753 newVitality = Math.max(Math.min(newVitality, Config.VITALITY_LEVELS[4]), 0);
11754
11755 if ((newVitality >= _vitality) || (getLevel() >= 10))
11756 {
11757 if (newVitality != _vitality)
11758 {
11759 if (newVitality == 0)
11760 {
11761 sendPacket(Msg.VITALITY_IS_FULLY_EXHAUSTED);
11762 }
11763 else if (newVitality == Config.VITALITY_LEVELS[4])
11764 {
11765 sendPacket(Msg.YOUR_VITALITY_IS_AT_MAXIMUM);
11766 }
11767 }
11768
11769 _vitality = newVitality;
11770 }
11771
11772 int newLevel = 0;
11773 if (_vitality >= Config.VITALITY_LEVELS[3])
11774 {
11775 newLevel = 4;
11776 }
11777 else if (_vitality >= Config.VITALITY_LEVELS[2])
11778 {
11779 newLevel = 3;
11780 }
11781 else if (_vitality >= Config.VITALITY_LEVELS[1])
11782 {
11783 newLevel = 2;
11784 }
11785 else if (_vitality >= Config.VITALITY_LEVELS[0])
11786 {
11787 newLevel = 1;
11788 }
11789
11790 if (_vitalityLevel > newLevel)
11791 {
11792 getNevitSystem().addPoints(1500);
11793 }
11794
11795 if (_vitalityLevel != newLevel)
11796 {
11797 if (_vitalityLevel != -1)
11798 {
11799 sendPacket(newLevel < _vitalityLevel ? Msg.VITALITY_HAS_DECREASED : Msg.VITALITY_HAS_INCREASED);
11800 }
11801 _vitalityLevel = newLevel;
11802 }
11803
11804 sendPacket(new ExVitalityPointInfo((int) _vitality));
11805 }
11806
11807 private final int _incorrectValidateCount = 0;
11808
11809 public int getIncorrectValidateCount()
11810 {
11811 return _incorrectValidateCount;
11812 }
11813
11814 public int setIncorrectValidateCount(int count)
11815 {
11816 return _incorrectValidateCount;
11817 }
11818
11819 public int getExpandInventory()
11820 {
11821 return _expandInventory;
11822 }
11823
11824 public void setExpandInventory(int inventory)
11825 {
11826 _expandInventory = inventory;
11827 }
11828
11829 public int getExpandWarehouse()
11830 {
11831 return _expandWarehouse;
11832 }
11833
11834 public void setExpandWarehouse(int warehouse)
11835 {
11836 _expandWarehouse = warehouse;
11837 }
11838
11839 public boolean isNotShowBuffAnim()
11840 {
11841 return _notShowBuffAnim;
11842 }
11843
11844 public void setNotShowBuffAnim(boolean value)
11845 {
11846 _notShowBuffAnim = value;
11847 }
11848
11849 public List<SchemeBufferInstance.PlayerScheme> getBuffSchemes()
11850 {
11851 return buffSchemes;
11852 }
11853
11854 public SchemeBufferInstance.PlayerScheme getBuffSchemeById(int id)
11855 {
11856 for (SchemeBufferInstance.PlayerScheme scheme : buffSchemes)
11857 if (scheme.schemeId == id)
11858 return scheme;
11859 return null;
11860 }
11861
11862 public SchemeBufferInstance.PlayerScheme getBuffSchemeByName(String name)
11863 {
11864 for (SchemeBufferInstance.PlayerScheme scheme : buffSchemes)
11865 if (scheme.schemeName.equals(name))
11866 return scheme;
11867 return null;
11868 }
11869
11870 public void enterMovieMode()
11871 {
11872 if (isInMovie())
11873 {
11874 return;
11875 }
11876
11877 setTarget(null);
11878 stopMove();
11879 setIsInMovie(true);
11880 sendPacket(new CameraMode(1));
11881 }
11882
11883 public void leaveMovieMode()
11884 {
11885 setIsInMovie(false);
11886 sendPacket(new CameraMode(0));
11887 sendPacket(new ShortCutInit(this));
11888 broadcastCharInfo();
11889 }
11890
11891 public void specialCamera(GameObject target, int dist, int yaw, int pitch, int time, int duration)
11892 {
11893 sendPacket(new SpecialCamera(target.getObjectId(), dist, yaw, pitch, time, duration));
11894 }
11895
11896 public void specialCamera(GameObject target, int dist, int yaw, int pitch, int time, int duration, int turn, int rise, int widescreen, int unk)
11897 {
11898 sendPacket(new SpecialCamera(target.getObjectId(), dist, yaw, pitch, time, duration, turn, rise, widescreen, unk));
11899 }
11900
11901 private int _movieId = 0;
11902 private boolean _isInMovie;
11903
11904 public void setMovieId(int id)
11905 {
11906 _movieId = id;
11907 }
11908
11909 public int getMovieId()
11910 {
11911 return _movieId;
11912 }
11913
11914 public boolean isInMovie()
11915 {
11916 return _isInMovie;
11917 }
11918
11919 public void setIsInMovie(boolean state)
11920 {
11921 _isInMovie = state;
11922 }
11923
11924 public void showQuestMovie(SceneMovie movie)
11925 {
11926 if (isInMovie())
11927 {
11928 return;
11929 }
11930
11931 sendActionFailed();
11932 setTarget(null);
11933 stopMove();
11934 setMovieId(movie.getId());
11935 setIsInMovie(true);
11936 sendPacket(movie.packet(this));
11937 }
11938
11939 public void showQuestMovie(int movieId)
11940 {
11941 if (isInMovie())
11942 {
11943 return;
11944 }
11945
11946 sendActionFailed();
11947 setTarget(null);
11948 stopMove();
11949 setMovieId(movieId);
11950 setIsInMovie(true);
11951 sendPacket(new ExStartScenePlayer(movieId));
11952 }
11953
11954 public void setAutoLoot(boolean enable)
11955 {
11956 if (Config.AUTO_LOOT_INDIVIDUAL)
11957 {
11958 _autoLoot = enable;
11959 setVar("AutoLoot", String.valueOf(enable), -1);
11960 }
11961 }
11962
11963 public void setAutoLootHerbs(boolean enable)
11964 {
11965 if (Config.AUTO_LOOT_INDIVIDUAL)
11966 {
11967 AutoLootHerbs = enable;
11968 setVar("AutoLootHerbs", String.valueOf(enable), -1);
11969 }
11970 }
11971
11972 public void setAutoLootOnlyAdena(boolean enable)
11973 {
11974 if (Config.AUTO_LOOT_INDIVIDUAL)
11975 {
11976 AutoLootOnlyAdena = enable;
11977 setVar("AutoLootOnlyAdena", String.valueOf(enable), -1);
11978 }
11979 }
11980
11981 public boolean isAutoLootEnabled()
11982 {
11983 return _autoLoot;
11984 }
11985
11986 public boolean isAutoLootHerbsEnabled()
11987 {
11988 return AutoLootHerbs;
11989 }
11990
11991 public boolean isAutoLootOnlyAdenaEnabled()
11992 {
11993 return AutoLootOnlyAdena;
11994 }
11995
11996 public final void reName(String name, boolean saveToDB)
11997 {
11998 setName(name);
11999 if (saveToDB)
12000 {
12001 saveNameToDB();
12002 }
12003 broadcastCharInfo();
12004 }
12005
12006 public final void reName(String name)
12007 {
12008 reName(name, false);
12009 }
12010
12011 public final void saveNameToDB()
12012 {
12013 try (Connection con = DatabaseFactory.getInstance().getConnection();
12014 PreparedStatement st = con.prepareStatement("UPDATE characters SET char_name = ? WHERE obj_Id = ?"))
12015 {
12016 st.setString(1, getName());
12017 st.setInt(2, getObjectId());
12018 st.executeUpdate();
12019 }
12020 catch (SQLException e)
12021 {
12022 _log.error("Error while saving Char Name", e);
12023 }
12024 }
12025
12026 @Override
12027 public Player getPlayer()
12028 {
12029 return this;
12030 }
12031
12032 private List<String> getStoredBypasses(boolean bbs)
12033 {
12034 if (bbs)
12035 {
12036 if (bypasses_bbs == null)
12037 {
12038 bypasses_bbs = new ArrayList<>();
12039 }
12040 return bypasses_bbs;
12041 }
12042 if (bypasses == null)
12043 {
12044 bypasses = new ArrayList<>();
12045 }
12046 return bypasses;
12047 }
12048
12049 public void cleanBypasses(boolean bbs)
12050 {
12051 List<String> bypassStorage = getStoredBypasses(bbs);
12052 synchronized (bypassStorage)
12053 {
12054 bypassStorage.clear();
12055 }
12056 }
12057
12058 public String encodeBypasses(String htmlCode, boolean bbs)
12059 {
12060 List<String> bypassStorage = getStoredBypasses(bbs);
12061 synchronized (bypassStorage)
12062 {
12063 return BypassManager.encode(htmlCode, bypassStorage, bbs);
12064 }
12065 }
12066
12067 public DecodedBypass decodeBypass(String bypass)
12068 {
12069 BypassType bpType = BypassManager.getBypassType(bypass);
12070 boolean bbs = (bpType == BypassType.ENCODED_BBS) || (bpType == BypassType.SIMPLE_BBS);
12071 List<String> bypassStorage = getStoredBypasses(bbs);
12072 if ((bpType == BypassType.ENCODED) || (bpType == BypassType.ENCODED_BBS))
12073 {
12074 return BypassManager.decode(bypass, bypassStorage, bbs, this);
12075 }
12076 if (bpType == BypassType.SIMPLE)
12077 {
12078 return new DecodedBypass(bypass, false).trim();
12079 }
12080 if ((bpType == BypassType.SIMPLE_BBS) && !bypass.startsWith("_bbsscripts"))
12081 {
12082 return new DecodedBypass(bypass, true).trim();
12083 }
12084
12085 ICommunityBoardHandler handler = CommunityBoardManager.getInstance().getCommunityHandler(bypass);
12086 if (handler != null)
12087 {
12088 return new DecodedBypass(bypass, handler).trim();
12089 }
12090
12091 _log.warn("Direct access to bypass: " + bypass + " / Player: " + getName());
12092 return null;
12093 }
12094
12095 public int getTalismanCount()
12096 {
12097 return (int) calcStat(Stats.TALISMANS_LIMIT, 0, null, null);
12098 }
12099
12100 public boolean getOpenCloak()
12101 {
12102 if (Config.ALT_OPEN_CLOAK_SLOT || isGM())
12103 {
12104 return true;
12105 }
12106 return (int) calcStat(Stats.CLOAK_SLOT, 0, null, null) > 0;
12107 }
12108
12109 public final void disableDrop(int time)
12110 {
12111 _dropDisabled = System.currentTimeMillis() + time;
12112 }
12113
12114 public final boolean isDropDisabled()
12115 {
12116 return _dropDisabled > System.currentTimeMillis();
12117 }
12118
12119 private ItemInstance _petControlItem = null;
12120
12121 public void setPetControlItem(int itemObjId)
12122 {
12123 setPetControlItem(getInventory().getItemByObjectId(itemObjId));
12124 }
12125
12126 public void setPetControlItem(ItemInstance item)
12127 {
12128 _petControlItem = item;
12129 }
12130
12131 public ItemInstance getPetControlItem()
12132 {
12133 return _petControlItem;
12134 }
12135
12136 private long _lastNotAfkTime = 0;
12137
12138 public void isntAfk()
12139 {
12140 _lastNotAfkTime = System.currentTimeMillis();
12141 }
12142
12143 public long getLastNotAfkTime()
12144 {
12145 return _lastNotAfkTime;
12146 }
12147
12148 private final AtomicBoolean isActive = new AtomicBoolean();
12149
12150 public long lastActive = 0;
12151
12152 public boolean isActive()
12153 {
12154 return isActive.get();
12155 }
12156
12157 public void setActive()
12158 {
12159 setNonAggroTime(0);
12160
12161 isntAfk();
12162
12163 lastActive = System.currentTimeMillis();
12164
12165 if (isActive.getAndSet(true))
12166 {
12167 return;
12168 }
12169
12170 onActive();
12171 }
12172
12173 private void onActive()
12174 {
12175 setNonAggroTime(0L);
12176
12177 if (!isRegisteredInFightClub())
12178 {
12179 sendPacket(Msg.YOU_ARE_PROTECTED_AGGRESSIVE_MONSTERS);
12180 }
12181
12182 if (getPetControlItem() != null)
12183 {
12184 ThreadPoolManager.getInstance().execute(new RunnableImpl()
12185 {
12186 @Override
12187 public void runImpl()
12188 {
12189 if (getPetControlItem() != null)
12190 {
12191 summonPet();
12192 }
12193 }
12194
12195 });
12196 }
12197 }
12198
12199 public void summonPet()
12200 {
12201 if (getPet() != null)
12202 {
12203 return;
12204 }
12205
12206 ItemInstance controlItem = getPetControlItem();
12207 if (controlItem == null)
12208 {
12209 return;
12210 }
12211
12212 int npcId = PetDataTable.getSummonId(controlItem);
12213 if (npcId == 0)
12214 {
12215 return;
12216 }
12217
12218 NpcTemplate petTemplate = NpcHolder.getInstance().getTemplate(npcId);
12219 if (petTemplate == null)
12220 {
12221 return;
12222 }
12223
12224 PetInstance pet = PetInstance.restore(controlItem, petTemplate, this);
12225 if (pet == null)
12226 {
12227 return;
12228 }
12229
12230 setPet(pet);
12231 pet.setTitle(getName());
12232
12233 if (!pet.isRespawned())
12234 {
12235 pet.setCurrentHp(pet.getMaxHp(), false);
12236 pet.setCurrentMp(pet.getMaxMp());
12237 pet.setCurrentFed(pet.getMaxFed());
12238 pet.updateControlItem();
12239 pet.store();
12240 }
12241
12242 pet.getInventory().restore();
12243
12244 pet.setReflection(getReflection());
12245 pet.spawnMe(Location.findPointToStay(this, 50, 70));
12246 pet.setRunning();
12247 pet.setFollowMode(true);
12248 pet.getInventory().validateItems();
12249
12250 if (pet instanceof PetBabyInstance)
12251 {
12252 ((PetBabyInstance) pet).startBuffTask();
12253 }
12254 }
12255
12256 private Map<Integer, Long> _traps;
12257
12258 public Collection<TrapInstance> getTraps()
12259 {
12260 if (_traps == null)
12261 {
12262 return null;
12263 }
12264 Collection<TrapInstance> result = new ArrayList<TrapInstance>(getTrapsCount());
12265 TrapInstance trap;
12266 for (Integer trapId : _traps.keySet())
12267 {
12268 if ((trap = (TrapInstance) GameObjectsStorage.get(_traps.get(trapId))) != null)
12269 {
12270 result.add(trap);
12271 }
12272 else
12273 {
12274 _traps.remove(trapId);
12275 }
12276 }
12277 return result;
12278 }
12279
12280 public int getTrapsCount()
12281 {
12282 return _traps == null ? 0 : _traps.size();
12283 }
12284
12285 public void addTrap(TrapInstance trap)
12286 {
12287 if (_traps == null)
12288 {
12289 _traps = new HashMap<Integer, Long>();
12290 }
12291 _traps.put(trap.getObjectId(), trap.getStoredId());
12292 }
12293
12294 public void removeTrap(TrapInstance trap)
12295 {
12296 Map<Integer, Long> traps = _traps;
12297 if ((traps == null) || traps.isEmpty())
12298 {
12299 return;
12300 }
12301 traps.remove(trap.getObjectId());
12302 }
12303
12304 public void destroyFirstTrap()
12305 {
12306 Map<Integer, Long> traps = _traps;
12307 if ((traps == null) || traps.isEmpty())
12308 {
12309 return;
12310 }
12311 TrapInstance trap;
12312 for (Integer trapId : traps.keySet())
12313 {
12314 if ((trap = (TrapInstance) GameObjectsStorage.get(traps.get(trapId))) != null)
12315 {
12316 trap.deleteMe();
12317 return;
12318 }
12319 return;
12320 }
12321 }
12322
12323 public void destroyAllTraps()
12324 {
12325 Map<Integer, Long> traps = _traps;
12326 if ((traps == null) || traps.isEmpty())
12327 {
12328 return;
12329 }
12330 List<TrapInstance> toRemove = new ArrayList<TrapInstance>();
12331 for (Integer trapId : traps.keySet())
12332 {
12333 toRemove.add((TrapInstance) GameObjectsStorage.get(traps.get(trapId)));
12334 }
12335 for (TrapInstance t : toRemove)
12336 {
12337 if (t != null)
12338 {
12339 t.deleteMe();
12340 }
12341 }
12342 }
12343
12344 public void setBlockCheckerArena(byte arena)
12345 {
12346 _handysBlockCheckerEventArena = arena;
12347 }
12348
12349 public int getBlockCheckerArena()
12350 {
12351 return _handysBlockCheckerEventArena;
12352 }
12353
12354 @Override
12355 public PlayerListenerList getListeners()
12356 {
12357 if (listeners == null)
12358 {
12359 synchronized (this)
12360 {
12361 if (listeners == null)
12362 {
12363 listeners = new PlayerListenerList(this);
12364 }
12365 }
12366 }
12367 return (PlayerListenerList) listeners;
12368 }
12369
12370 @Override
12371 public PlayerStatsChangeRecorder getStatsRecorder()
12372 {
12373 if (_statsRecorder == null)
12374 {
12375 synchronized (this)
12376 {
12377 if (_statsRecorder == null)
12378 {
12379 _statsRecorder = new PlayerStatsChangeRecorder(this);
12380 }
12381 }
12382 }
12383 return (PlayerStatsChangeRecorder) _statsRecorder;
12384 }
12385
12386 private Future<?> _hourlyTask;
12387 private int _hoursInGame = 0;
12388
12389 public int getHoursInGame()
12390 {
12391 _hoursInGame++;
12392 return _hoursInGame;
12393 }
12394
12395 public int getHoursInGames()
12396 {
12397 return _hoursInGame;
12398 }
12399
12400 public void startHourlyTask()
12401 {
12402 _hourlyTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new HourlyTask(this), 3600000L, 3600000L);
12403 }
12404
12405 public void stopHourlyTask()
12406 {
12407 if (_hourlyTask != null)
12408 {
12409 _hourlyTask.cancel(false);
12410 _hourlyTask = null;
12411 }
12412 }
12413 @Override
12414 public void setTeam(TeamType t)
12415 {
12416 super.setTeam(t);
12417
12418 if (getPet() != null)
12419 getPet().sendChanges();
12420 }
12421 private int _team = 0;
12422 @SuppressWarnings("unused")
12423 private boolean _checksForTeam = false;
12424
12425 public void setTeamEvents(final int team, boolean checksForTeam)
12426 {
12427 _checksForTeam = checksForTeam;
12428 if (_team != team)
12429 {
12430 _team = team;
12431
12432 broadcastUserInfo(true);
12433 if (getPet() != null)
12434 {
12435 getPet().broadcastCharInfo();
12436 }
12437 }
12438 }
12439
12440 public int getTeamEvents()
12441 {
12442 return _team;
12443 }
12444
12445 public long getPremiumPoints()
12446 {
12447 if (Config.GAME_POINT_ITEM_ID != -1)
12448 {
12449 return ItemFunctions.getItemCount(this, Config.GAME_POINT_ITEM_ID);
12450 }
12451 return 0;
12452 }
12453
12454 public void reducePremiumPoints(final int val)
12455 {
12456 if (Config.GAME_POINT_ITEM_ID != -1)
12457 {
12458 ItemFunctions.removeItem(this, Config.GAME_POINT_ITEM_ID, val, true, "PremiumPoints");
12459 }
12460 }
12461
12462 public void addPremiumPoints(final int val)
12463 {
12464 if (Config.GAME_POINT_ITEM_ID != -1)
12465 {
12466 ItemFunctions.addItem(this, Config.GAME_POINT_ITEM_ID, val, true, "PremiumPoints");
12467 }
12468 }
12469
12470 private boolean _agathionResAvailable = false;
12471
12472 public boolean isAgathionResAvailable()
12473 {
12474 return _agathionResAvailable;
12475 }
12476
12477 public void setAgathionRes(boolean val)
12478 {
12479 _agathionResAvailable = val;
12480 }
12481
12482 public boolean isClanAirShipDriver()
12483 {
12484 return isInBoat() && getBoat().isClanAirShip() && (((ClanAirShip) getBoat()).getDriver() == this);
12485 }
12486
12487 private Map<String, String> _userSession;
12488
12489 public String getSessionVar(String key)
12490 {
12491 if (_userSession == null)
12492 {
12493 return null;
12494 }
12495 return _userSession.get(key);
12496 }
12497
12498 public void setSessionVar(String key, String val)
12499 {
12500 if (_userSession == null)
12501 {
12502 _userSession = new ConcurrentHashMap<String, String>();
12503 }
12504
12505 if ((val == null) || val.isEmpty())
12506 {
12507 _userSession.remove(key);
12508 }
12509 else
12510 {
12511 _userSession.put(key, val);
12512 }
12513 }
12514
12515 public FriendList getFriendList()
12516 {
12517 return _friendList;
12518 }
12519
12520 public boolean isNotShowTraders()
12521 {
12522 return _notShowTraders;
12523 }
12524
12525 public void setNotShowTraders(boolean notShowTraders)
12526 {
12527 _notShowTraders = notShowTraders;
12528 }
12529
12530 public boolean isDebug()
12531 {
12532 return _debug;
12533 }
12534
12535 public void setDebug(boolean b)
12536 {
12537 _debug = b;
12538 }
12539
12540 public void sendItemList(boolean show)
12541 {
12542 ItemInstance[] items = getInventory().getItems();
12543 LockType lockType = getInventory().getLockType();
12544 int[] lockItems = getInventory().getLockItems();
12545
12546 int allSize = items.length;
12547 int questItemsSize = 0;
12548 int agathionItemsSize = 0;
12549 for (ItemInstance item : items)
12550 {
12551 if (item.getTemplate().isQuest())
12552 {
12553 questItemsSize++;
12554 }
12555 if (item.getTemplate().getAgathionEnergy() > 0)
12556 {
12557 agathionItemsSize++;
12558 }
12559 }
12560
12561 sendPacket(new ItemList(allSize - questItemsSize, items, show, lockType, lockItems));
12562 if (questItemsSize > 0)
12563 {
12564 sendPacket(new ExQuestItemList(questItemsSize, items, lockType, lockItems));
12565 }
12566 if (agathionItemsSize > 0)
12567 {
12568 sendPacket(new ExBR_AgathionEnergyInfo(agathionItemsSize, items));
12569 }
12570 }
12571
12572 public int getBeltInventoryIncrease()
12573 {
12574 ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_BELT);
12575 if ((item != null) && (item.getTemplate().getAttachedSkills() != null))
12576 {
12577 for (Skill skill : item.getTemplate().getAttachedSkills())
12578 {
12579 for (FuncTemplate func : skill.getAttachedFuncs())
12580 {
12581 if (func._stat == Stats.INVENTORY_LIMIT)
12582 {
12583 return (int) func._value;
12584 }
12585 }
12586 }
12587 }
12588 return 0;
12589 }
12590
12591 @Override
12592 public boolean isPlayer()
12593 {
12594 return true;
12595 }
12596
12597 public boolean checkCoupleAction(Player target)
12598 {
12599 if (target.getPrivateStoreType() != Player.STORE_PRIVATE_NONE)
12600 {
12601 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IN_PRIVATE_STORE).addName(target));
12602 return false;
12603 }
12604 if (target.isFishing())
12605 {
12606 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_FISHING).addName(target));
12607 return false;
12608 }
12609 if (target.isInCombat())
12610 {
12611 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_COMBAT).addName(target));
12612 return false;
12613 }
12614 if (target.isCursedWeaponEquipped())
12615 {
12616 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_CURSED_WEAPON_EQUIPED).addName(target));
12617 return false;
12618 }
12619 if (target.isInOlympiadMode())
12620 {
12621 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_OLYMPIAD).addName(target));
12622 return false;
12623 }
12624 if (target.isOnSiegeField())
12625 {
12626 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_SIEGE).addName(target));
12627 return false;
12628 }
12629 if (target.isInBoat() || (target.getMountNpcId() != 0))
12630 {
12631 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_VEHICLE_MOUNT_OTHER).addName(target));
12632 return false;
12633 }
12634 if (target.isTeleporting())
12635 {
12636 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_TELEPORTING).addName(target));
12637 return false;
12638 }
12639 if (target.getTransformation() != 0)
12640 {
12641 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_TRANSFORM).addName(target));
12642 return false;
12643 }
12644 if (target.isDead())
12645 {
12646 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_DEAD).addName(target));
12647 return false;
12648 }
12649 if (isInFightClub() && !getFightClubEvent().isFriend(this, target))
12650 {
12651 sendMessage("You cannot request couple action while player is your enemy!");
12652 return false;
12653 }
12654 return true;
12655 }
12656
12657 @Override
12658 public void startAttackStanceTask()
12659 {
12660 startAttackStanceTask0();
12661 Summon summon = getPet();
12662 if (summon != null)
12663 {
12664 summon.startAttackStanceTask0();
12665 }
12666 }
12667
12668 @Override
12669 public void displayGiveDamageMessage(Creature target, int damage, boolean crit, boolean miss, boolean shld, boolean magic)
12670 {
12671 super.displayGiveDamageMessage(target, damage, crit, miss, shld, magic);
12672 if (crit)
12673 {
12674 if (magic)
12675 {
12676 getCounters().mcritsDone++;
12677 sendPacket(new SystemMessage(SystemMessage.MAGIC_CRITICAL_HIT).addName(this));
12678 }
12679 else
12680 {
12681 getCounters().critsDone++;
12682 sendPacket(new SystemMessage(SystemMessage.C1_HAD_A_CRITICAL_HIT).addName(this));
12683 }
12684 }
12685
12686 if (miss)
12687 {
12688 sendPacket(new SystemMessage(SystemMessage.C1S_ATTACK_WENT_ASTRAY).addName(this));
12689 }
12690 else if (!target.isDamageBlocked())
12691 {
12692 sendPacket(new SystemMessage(SystemMessage.C1_HAS_GIVEN_C2_DAMAGE_OF_S3).addName(this).addName(target).addNumber(damage));
12693 }
12694
12695 if (target.isPlayer())
12696 {
12697 if (shld && (damage > 1))
12698 {
12699 target.sendPacket(SystemMsg.YOUR_SHIELD_DEFENSE_HAS_SUCCEEDED);
12700 }
12701 else if (shld && (damage == 1))
12702 {
12703 target.sendPacket(SystemMsg.YOUR_EXCELLENT_SHIELD_DEFENSE_WAS_A_SUCCESS);
12704 }
12705 }
12706 }
12707
12708 @Override
12709 public void displayReceiveDamageMessage(Creature attacker, int damage)
12710 {
12711 if (attacker != this)
12712 {
12713 sendPacket(new SystemMessage(SystemMessage.C1_HAS_RECEIVED_DAMAGE_OF_S3_FROM_C2).addString(getVisibleName()).addString(attacker.getVisibleName()).addNumber((long) damage));
12714 }
12715 }
12716
12717 public IntObjectMap<String> getPostFriends()
12718 {
12719 return _postFriends;
12720 }
12721
12722 public boolean isSharedGroupDisabled(int groupId)
12723 {
12724 TimeStamp sts = _sharedGroupReuses.get(groupId);
12725 if (sts == null)
12726 {
12727 return false;
12728 }
12729 if (sts.hasNotPassed())
12730 {
12731 return true;
12732 }
12733 _sharedGroupReuses.remove(groupId);
12734 return false;
12735 }
12736
12737 public TimeStamp getSharedGroupReuse(int groupId)
12738 {
12739 return _sharedGroupReuses.get(groupId);
12740 }
12741
12742 public void addSharedGroupReuse(int group, TimeStamp stamp)
12743 {
12744 _sharedGroupReuses.put(group, stamp);
12745 }
12746
12747 public Collection<IntObjectMap.Entry<TimeStamp>> getSharedGroupReuses()
12748 {
12749 return _sharedGroupReuses.entrySet();
12750 }
12751
12752 public void sendReuseMessage(ItemInstance item)
12753 {
12754 TimeStamp sts = getSharedGroupReuse(item.getTemplate().getReuseGroup());
12755 if ((sts == null) || !sts.hasNotPassed())
12756 {
12757 return;
12758 }
12759
12760 long timeleft = sts.getReuseCurrent();
12761 long hours = timeleft / 3600000;
12762 long minutes = (timeleft - (hours * 3600000)) / 60000;
12763 long seconds = (long) Math.ceil((timeleft - (hours * 3600000) - (minutes * 60000)) / 1000.);
12764
12765 if (hours > 0)
12766 {
12767 sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[2]).addItemName(item.getTemplate().getItemId()).addInteger(hours).addInteger(minutes).addInteger(seconds));
12768 }
12769 else if (minutes > 0)
12770 {
12771 sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[1]).addItemName(item.getTemplate().getItemId()).addInteger(minutes).addInteger(seconds));
12772 }
12773 else
12774 {
12775 sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[0]).addItemName(item.getTemplate().getItemId()).addInteger(seconds));
12776 }
12777 }
12778
12779 public NevitSystem getNevitSystem()
12780 {
12781 return _nevitSystem;
12782 }
12783 public StreamPersonal getStreamPersonal()
12784 {
12785 return _streamPersonal;
12786 }
12787
12788 public void ask(ConfirmDlg dlg, OnAnswerListener listener)
12789 {
12790 if (_askDialog != null)
12791 return;
12792
12793 int rnd = Rnd.nextInt();
12794 _askDialog = new ImmutablePair<Integer, OnAnswerListener>(rnd, listener);
12795 dlg.setRequestId(rnd);
12796 sendPacket(dlg);
12797
12798 // Ady - Set the resurrection max time to accept it to 5 minutes. After that it will be rejected. Only for players
12799 if (listener instanceof ReviveAnswerListener && !((ReviveAnswerListener)listener).isForPet())
12800 _resurrectionMaxTime = System.currentTimeMillis() + 5 * 60 * 1000;
12801 }
12802
12803 public Pair<Integer, OnAnswerListener> getAskListener(boolean clear)
12804 {
12805 if (!clear)
12806 {
12807 return _askDialog;
12808 }
12809 else
12810 {
12811 Pair<Integer, OnAnswerListener> ask = _askDialog;
12812 _askDialog = null;
12813 return ask;
12814 }
12815 }
12816
12817 public boolean hasDialogAskActive()
12818 {
12819 return _askDialog != null;
12820 }
12821
12822 @Override
12823 public boolean isDead()
12824 {
12825 return (isInOlympiadMode() || isInDuel()) ? getCurrentHp() <= 1. : super.isDead();
12826 }
12827
12828 @Override
12829 public int getAgathionEnergy()
12830 {
12831 ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LBRACELET);
12832 return item == null ? 0 : item.getAgathionEnergy();
12833 }
12834
12835 @Override
12836 public void setAgathionEnergy(int val)
12837 {
12838 ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LBRACELET);
12839 if (item == null)
12840 {
12841 return;
12842 }
12843 item.setAgathionEnergy(val);
12844 item.setJdbcState(JdbcEntityState.UPDATED);
12845
12846 sendPacket(new ExBR_AgathionEnergyInfo(1, item));
12847 }
12848
12849 public boolean hasPrivilege(Privilege privilege)
12850 {
12851 return (_clan != null) && ((getClanPrivileges() & privilege.mask()) == privilege.mask());
12852 }
12853
12854 public MatchingRoom getMatchingRoom()
12855 {
12856 return _matchingRoom;
12857 }
12858
12859 public void setMatchingRoom(MatchingRoom matchingRoom)
12860 {
12861 _matchingRoom = matchingRoom;
12862 }
12863
12864 public void dispelBuffs()
12865 {
12866 for (Effect e : getEffectList().getAllEffects())
12867 {
12868 if (!e.getSkill().isOffensive() && !e.getSkill().isNewbie() && e.isCancelable() && !e.getSkill().isPreservedOnDeath())
12869 {
12870 sendPacket(new SystemMessage(SystemMessage.THE_EFFECT_OF_S1_HAS_BEEN_REMOVED).addSkillName(e.getSkill().getId(), e.getSkill().getLevel()));
12871 e.exit();
12872 }
12873 }
12874 if (getPet() != null)
12875 {
12876 for (Effect e : getPet().getEffectList().getAllEffects())
12877 {
12878 if (!e.getSkill().isOffensive() && !e.getSkill().isNewbie() && e.isCancelable() && !e.getSkill().isPreservedOnDeath())
12879 {
12880 e.exit();
12881 }
12882 }
12883 }
12884 }
12885
12886 public void setInstanceReuse(int id, long time)
12887 {
12888 final SystemMessage msg = new SystemMessage(SystemMessage.INSTANT_ZONE_FROM_HERE__S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_ENTRY_POSSIBLE).addString(getName());
12889 sendPacket(msg);
12890 _instancesReuses.put(id, time);
12891 mysql.set("REPLACE INTO character_instances (obj_id, id, reuse) VALUES (?,?,?)", getObjectId(), id, time);
12892 }
12893
12894 public void removeInstanceReuse(int id)
12895 {
12896 if (_instancesReuses.remove(id) != null)
12897 {
12898 mysql.set("DELETE FROM `character_instances` WHERE `obj_id`=? AND `id`=? LIMIT 1", getObjectId(), id);
12899 }
12900 }
12901
12902 public void removeAllInstanceReuses()
12903 {
12904 _instancesReuses.clear();
12905 mysql.set("DELETE FROM `character_instances` WHERE `obj_id`=?", getObjectId());
12906 }
12907
12908 public void removeInstanceReusesByGroupId(int groupId)
12909 {
12910 for (int i : InstantZoneHolder.getInstance().getSharedReuseInstanceIdsByGroup(groupId))
12911 {
12912 if (getInstanceReuse(i) != null)
12913 {
12914 removeInstanceReuse(i);
12915 }
12916 }
12917 }
12918
12919 public Long getInstanceReuse(int id)
12920 {
12921 return _instancesReuses.get(id);
12922 }
12923
12924 public Map<Integer, Long> getInstanceReuses()
12925 {
12926 return _instancesReuses;
12927 }
12928
12929 private void loadInstanceReuses(Connection con)
12930 {
12931 try (PreparedStatement offline = con.prepareStatement("SELECT * FROM character_instances WHERE obj_id = ?"))
12932 {
12933 offline.setInt(1, getObjectId());
12934
12935 try (ResultSet rs = offline.executeQuery())
12936 {
12937 while (rs.next())
12938 {
12939 int id = rs.getInt("id");
12940 long reuse = rs.getLong("reuse");
12941 _instancesReuses.put(id, reuse);
12942 }
12943 }
12944 }
12945 catch (SQLException e)
12946 {
12947 _log.error("Error while loading Instance Reuses for Id "+getObjectId(), e);
12948 }
12949 }
12950
12951 public Reflection getActiveReflection()
12952 {
12953 for (Reflection r : ReflectionManager.getInstance().getAll())
12954 {
12955 if ((r != null) && ArrayUtils.contains(r.getVisitors(), getObjectId()))
12956 {
12957 return r;
12958 }
12959 }
12960 return null;
12961 }
12962
12963 public boolean canEnterInstance(int instancedZoneId)
12964 {
12965 InstantZone iz = InstantZoneHolder.getInstance().getInstantZone(instancedZoneId);
12966
12967 if (isDead())
12968 {
12969 return false;
12970 }
12971
12972 if (!Config.ALLOW_ENTER_INSTANCE)
12973 {
12974 sendMessage("Instances cannot be entered at the time!");
12975 return false;
12976 }
12977
12978 if (ReflectionManager.getInstance().size() > Config.MAX_REFLECTIONS_COUNT)
12979 {
12980 sendPacket(SystemMsg.THE_MAXIMUM_NUMBER_OF_INSTANCE_ZONES_HAS_BEEN_EXCEEDED);
12981 return false;
12982 }
12983
12984 if (iz == null)
12985 {
12986 sendPacket(SystemMsg.SYSTEM_ERROR);
12987 return false;
12988 }
12989
12990 if (ReflectionManager.getInstance().getCountByIzId(instancedZoneId) >= iz.getMaxChannels())
12991 {
12992 sendPacket(SystemMsg.THE_MAXIMUM_NUMBER_OF_INSTANCE_ZONES_HAS_BEEN_EXCEEDED);
12993 return false;
12994 }
12995
12996 return iz.getEntryType().canEnter(this, iz);
12997 }
12998
12999 public boolean canReenterInstance(int instancedZoneId)
13000 {
13001 InstantZone iz = InstantZoneHolder.getInstance().getInstantZone(instancedZoneId);
13002
13003 if (!Config.ALLOW_ENTER_INSTANCE)
13004 {
13005 sendMessage("Instances cannot be entered at the time!");
13006 return false;
13007 }
13008
13009 if ((getActiveReflection() != null) && (getActiveReflection().getInstancedZoneId() != instancedZoneId))
13010 {
13011 sendPacket(SystemMsg.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
13012 return false;
13013 }
13014 if (iz.isDispelBuffs())
13015 {
13016 dispelBuffs();
13017 }
13018 return iz.getEntryType().canReEnter(this, iz);
13019 }
13020
13021 public int getBattlefieldChatId()
13022 {
13023 return _battlefieldChatId;
13024 }
13025
13026 public void setBattlefieldChatId(int battlefieldChatId)
13027 {
13028 _battlefieldChatId = battlefieldChatId;
13029 }
13030
13031 @Override
13032 public Iterator<Player> iterator()
13033 {
13034 return Collections.singleton(this).iterator();
13035 }
13036
13037 public PlayerGroup getPlayerGroup()
13038 {
13039 if (getParty() != null)
13040 {
13041 if (getParty().getCommandChannel() != null)
13042 {
13043 return getParty().getCommandChannel();
13044 }
13045 else
13046 {
13047 return getParty();
13048 }
13049 }
13050 else
13051 {
13052 return this;
13053 }
13054 }
13055
13056 @Override
13057 public int size()
13058 {
13059 return 1;
13060 }
13061
13062 @Override
13063 public Player getLeader()
13064 {
13065 return this;
13066 }
13067
13068 @Override
13069 public List<Player> getMembers(Player... excluded)
13070 {
13071 if (Util.arrayContains(excluded, this))
13072 return Collections.emptyList();
13073
13074 return Collections.singletonList(this);
13075 }
13076
13077 @Override
13078 public boolean containsMember(Player player)
13079 {
13080 return this == player;
13081 }
13082
13083 public boolean isActionBlocked(String action)
13084 {
13085 return _blockedActions.contains(action);
13086 }
13087
13088 public void blockActions(String... actions)
13089 {
13090 Collections.addAll(_blockedActions, actions);
13091 }
13092
13093 public void unblockActions(String... actions)
13094 {
13095 for (String action : actions)
13096 {
13097 _blockedActions.remove(action);
13098 }
13099 }
13100
13101 public OlympiadGame getOlympiadGame()
13102 {
13103 return _olympiadGame;
13104 }
13105
13106 public void setOlympiadGame(OlympiadGame olympiadGame)
13107 {
13108 _olympiadGame = olympiadGame;
13109 }
13110
13111 public boolean isInOlympiadObserverMode()
13112 {
13113 return _olympiadObserveGame != null;
13114 }
13115
13116 public OlympiadGame getOlympiadObserveGame()
13117 {
13118 return _olympiadObserveGame;
13119 }
13120
13121 public void setOlympiadObserveGame(OlympiadGame olympiadObserveGame)
13122 {
13123 _olympiadObserveGame = olympiadObserveGame;
13124 }
13125
13126 public void addRadar(int x, int y, int z)
13127 {
13128 sendPacket(new RadarControl(0, 1, x, y, z));
13129 }
13130
13131 public void addRadarWithMap(int x, int y, int z)
13132 {
13133 sendPacket(new RadarControl(0, 2, x, y, z));
13134 }
13135
13136 public PetitionMainGroup getPetitionGroup()
13137 {
13138 return _petitionGroup;
13139 }
13140
13141 public void setPetitionGroup(PetitionMainGroup petitionGroup)
13142 {
13143 _petitionGroup = petitionGroup;
13144 }
13145
13146 public int getLectureMark()
13147 {
13148 return _lectureMark;
13149 }
13150
13151 public void setLectureMark(int lectureMark)
13152 {
13153 _lectureMark = lectureMark;
13154 }
13155
13156 class TeleportPoints
13157 {
13158 private final String _name;
13159 private final Location _xyz;
13160 private final long _prace;
13161 private final int _itemId;
13162 private final int _id;
13163
13164 public TeleportPoints(String name, Location xyz, int id, int itemId, long price)
13165 {
13166 _id = id;
13167 _name = name;
13168 _xyz = xyz;
13169 _itemId = itemId;
13170 _prace = price;
13171 }
13172
13173 public int getId()
13174 {
13175 return _id;
13176 }
13177
13178 public String getName()
13179 {
13180 return _name;
13181 }
13182
13183 public long getPrice()
13184 {
13185 return _prace;
13186 }
13187
13188 public int getItemId()
13189 {
13190 return _itemId;
13191 }
13192
13193 public Location getXYZ()
13194 {
13195 return _xyz;
13196 }
13197 }
13198
13199 public TeleportPoints getTeleportPoint(String name)
13200 {
13201 for (TeleportPoints point : _teleportPoints)
13202 {
13203 if (point.getName().equalsIgnoreCase(name))
13204 {
13205 return point;
13206 }
13207 }
13208 return null;
13209 }
13210
13211 public void addTeleportPoint(String name, int id, int itemId, long price)
13212 {
13213 _teleportPoints.add(new TeleportPoints(name, new Location(getX(), getY(), getZ()), id, itemId, price));
13214 }
13215
13216 public void delTeleportPoint(String name)
13217 {
13218 for (TeleportPoints point : _teleportPoints)
13219 {
13220 if (point.getName().equals(name))
13221 {
13222 _teleportPoints.remove(point);
13223 }
13224 }
13225 }
13226
13227 public void setLastHeroTrue(boolean value)
13228 {
13229 setHero(value);
13230 }
13231
13232 private boolean is_bbs_use = false;
13233
13234 public void setIsBBSUse(boolean value)
13235 {
13236 is_bbs_use = value;
13237 }
13238
13239 public boolean isBBSUse()
13240 {
13241 return is_bbs_use;
13242 }
13243
13244 public void setAccountAccesslevel(final int level, final String comments, int banTime)
13245 {
13246 AuthServerCommunication.getInstance().sendPacket(new ChangeAccessLevel(getAccountName(), level, banTime));
13247 }
13248
13249 private static void RestoreFightClub(Player player)
13250 {
13251 String[] values = player.getVar("FightClubRate").split(";");
13252 int id = Integer.parseInt(values[0]);
13253 int count = Integer.parseInt(values[1]);
13254 ItemFunctions.addItem(player, id, count, true, "RestoreFightClub");
13255 player.unsetVar("FightClubRate");
13256 player.unsetVar("isPvPevents");
13257 }
13258
13259 private static boolean _isNoAttackEvents = false;
13260
13261 public static void setNoAttackEvents(boolean set)
13262 {
13263 _isNoAttackEvents = set;
13264 }
13265
13266 public boolean isNoAttackEvents()
13267 {
13268 return _isNoAttackEvents;
13269 }
13270
13271 private void restoreCursedWeapon()
13272 {
13273 for (ItemInstance item : getInventory().getItems())
13274 {
13275 if (item.isCursed())
13276 {
13277 int skillLvl = CursedWeaponsManager.getInstance().getLevel(item.getItemId());
13278 if (item.getItemId() == 8190)
13279 {
13280 addSkill(SkillTable.getInstance().getInfo(3603, skillLvl), false);
13281 }
13282 else if (item.getItemId() == 8689)
13283 {
13284 addSkill(SkillTable.getInstance().getInfo(3629, skillLvl), false);
13285 }
13286 }
13287 }
13288 updateStats();
13289 }
13290
13291 private int _pvp_team = 0;
13292
13293 public void setPvPTeam(final int team)
13294 {
13295 if (_pvp_team != team)
13296 {
13297 _pvp_team = team;
13298 broadcastUserInfo(true);
13299 if (getPet() != null)
13300 {
13301 getPet().broadcastCharInfo();
13302 }
13303 }
13304 }
13305
13306 public void allowPvPTeam()
13307 {
13308 if (_pvp_team == 0)
13309 {
13310 setTeam(TeamType.NONE);
13311 }
13312 else if (_pvp_team == 2)
13313 {
13314 setTeam(TeamType.RED);
13315 }
13316 else if (_pvp_team == 1)
13317 {
13318 setTeam(TeamType.BLUE);
13319 }
13320 }
13321
13322 public int getPvPTeam()
13323 {
13324 return _pvp_team;
13325 }
13326
13327 public void startUnjailTask(Player player, long time, boolean msg)
13328 {
13329 if (time < 1)
13330 {
13331 return;
13332 }
13333
13334 if (_unjailTask != null)
13335 {
13336 _unjailTask.cancel(false);
13337 }
13338
13339 _unjailTask = ThreadPoolManager.getInstance().schedule(new UnJailTask(player, msg), time);
13340 }
13341
13342 public void stopUnjailTask()
13343 {
13344 if (_unjailTask != null)
13345 {
13346 _unjailTask.cancel(false);
13347 }
13348 _unjailTask = null;
13349 }
13350
13351 private AutoHuntingPunish _AutoHuntingPunish = null;
13352
13353 /**
13354 * Initializes his _botPunish object with the specified punish and for the specified time
13355 * @param punishType
13356 * @param minsOfPunish
13357 */
13358 public synchronized void setPunishDueBotting(AutoHuntingPunish.Punish punishType, int minsOfPunish)
13359 {
13360 if (_AutoHuntingPunish == null)
13361 {
13362 _AutoHuntingPunish = new AutoHuntingPunish(punishType, minsOfPunish);
13363 }
13364 }
13365
13366 /**
13367 * Returns the current object-representative player punish
13368 * @return
13369 */
13370 public AutoHuntingPunish getPlayerPunish()
13371 {
13372 return _AutoHuntingPunish;
13373 }
13374
13375 /**
13376 * Returns the type of punish being applied
13377 * @return
13378 */
13379 public AutoHuntingPunish.Punish getBotPunishType()
13380 {
13381 return _AutoHuntingPunish.getBotPunishType();
13382 }
13383
13384 /**
13385 * Will return true if the player has any bot punishment active
13386 * @return
13387 */
13388 public boolean isBeingPunished()
13389 {
13390 return _AutoHuntingPunish != null;
13391 }
13392
13393 public long _firstExp;
13394 public AccountReportDAO _account = null;
13395
13396 /**
13397 * Sets exp holded by the character on log in
13398 * @param value
13399 */
13400 public void setFirstExp(long value)
13401 {
13402 _firstExp = value;
13403 }
13404
13405 /**
13406 * Will return true if the player has gained exp since logged in
13407 * @return
13408 */
13409 public boolean hasEarnedExp()
13410 {
13411 if ((getExp() - _firstExp) != 0)
13412 {
13413 return true;
13414 }
13415 return false;
13416 }
13417
13418 /**
13419 * Will end the punishment once a player attempt to perform any forbid action and his punishment has expired
13420 */
13421 public void endPunishment()
13422 {
13423
13424 _AutoHuntingPunish = null;
13425 this.sendMessage("Your punishment has expired. Do not bot again!");
13426 }
13427
13428 private boolean _InTvT = false;
13429 private boolean _inCtF = false;
13430 private boolean _inLastHero = false;
13431 private boolean _isVoting = false;
13432 public boolean isInSameParty(Player target)
13433 {
13434 return ((getParty() != null) && (target.getParty() != null) && (getParty() == target.getParty()));
13435 }
13436
13437 public boolean isInSameChannel(Player target)
13438 {
13439 Party activeCharP = getParty();
13440 Party targetP = target.getParty();
13441 if ((activeCharP == null) || (targetP == null))
13442 return false;
13443 CommandChannel chan = activeCharP.getCommandChannel();
13444
13445 return chan != null && chan == targetP.getCommandChannel();
13446 }
13447
13448 public boolean isInSameClan(Player target)
13449 {
13450 return getClanId() != 0 && getClanId() == target.getClanId();
13451 }
13452
13453 public final boolean isInSameAlly(Player target)
13454 {
13455 return getAllyId() != 0 && getAllyId() == target.getAllyId();
13456 }
13457
13458 public boolean isInTvT()
13459 {
13460 return _InTvT;
13461 }
13462
13463 public boolean isInCtF()
13464 {
13465 return _inCtF;
13466 }
13467
13468// public void setRegisteredInEvent(boolean inEvent)
13469// {
13470// _registeredInEvent = inEvent;
13471// }
13472//
13473// public boolean isRegisteredInEvent()
13474// {
13475// return _registeredInEvent;
13476// }
13477
13478 public boolean isInLastHero()
13479 {
13480 return _inLastHero;
13481 }
13482
13483 public boolean isInPvPEvent()
13484 {
13485 return !_InTvT && !_inCtF && !_inLastHero ? false : true;
13486 }
13487
13488 public void setIsInTvT(boolean param)
13489 {
13490 _InTvT = param;
13491 }
13492
13493 public boolean isVoting()
13494 {
13495 return _isVoting;
13496 }
13497
13498 public void setIsVoting(boolean value)
13499 {
13500 _isVoting = value;
13501 }
13502
13503 public void setIsInCtF(boolean param)
13504 {
13505 _inCtF = param;
13506 }
13507
13508 public void setIsInLastHero(boolean param)
13509 {
13510 _inLastHero = param;
13511 }
13512
13513 public void setMacroSkill(Skill skill)
13514 {
13515 _macroSkill = skill;
13516 }
13517
13518 public Skill getMacroSkill()
13519 {
13520 return _macroSkill;
13521 }
13522
13523 // Ady - Support for visible non permanent colors
13524 private int _visibleNameColor = 0;
13525
13526 public int getVisibleNameColor()
13527 {
13528 if (_visibleNameColor != 0)
13529 return _visibleNameColor;
13530
13531 return getNameColor();
13532 }
13533
13534 public void setVisibleNameColor(final int nameColor)
13535 {
13536 _visibleNameColor = nameColor;
13537 }
13538
13539 private int _visibleTitleColor = 0;
13540
13541 public int getVisibleTitleColor()
13542 {
13543 if (_visibleTitleColor != 0)
13544 return _visibleTitleColor;
13545
13546 return getTitleColor();
13547 }
13548
13549 public void setVisibleTitleColor(final int nameColor)
13550 {
13551 _visibleTitleColor = nameColor;
13552 }
13553
13554 public void setLastAugmentNpc(NpcInstance npc)
13555 {
13556 lastAugmentNpc = npc;
13557 }
13558
13559 public boolean checkLastAugmentNpc()
13560 {
13561 if (lastAugmentNpc == null)
13562 return false;
13563
13564 if (!PositionUtils.checkIfInRange(300, this, lastAugmentNpc, true))
13565 {
13566 lastAugmentNpc = null;
13567 return false;
13568 }
13569
13570 return true;
13571 }
13572 // Support for visible non permanent name and title
13573 private String _visibleName = null;
13574
13575 @Override
13576 public String getVisibleName()
13577 {
13578 if (_visibleName != null)
13579 return _visibleName;
13580
13581 return getName();
13582 }
13583
13584 public void setVisibleName(final String name)
13585 {
13586 _visibleName = name;
13587 }
13588
13589 private String _visibleTitle = null;
13590
13591 public String getVisibleTitle()
13592 {
13593 if (_visibleTitle != null)
13594 return _visibleTitle;
13595
13596 return getTitle();
13597 }
13598
13599 public void setVisibleTitle(final String title)
13600 {
13601 _visibleTitle = title;
13602 }
13603
13604 // Offline buff store function
13605 public void offlineBuffStore()
13606 {
13607 if (getHwidGamer() != null)
13608 getHwidGamer().removePlayer(this);
13609
13610 if (_connection != null)
13611 {
13612 _connection.setActiveChar(null);
13613 _connection.close(ServerClose.STATIC);
13614 setNetConnection(null);
13615 }
13616 setOnlineTime(getOnlineTime());
13617 setUptime(0);
13618 setOfflineMode(true);
13619
13620 Party party = getParty();
13621 if (party != null)
13622 {
13623 if (isFestivalParticipant())
13624 {
13625 party.sendMessage(getName() + " has been removed from the upcoming festival.");
13626 }
13627 leaveParty();
13628 }
13629
13630 if (getPet() != null)
13631 {
13632 getPet().unSummon();
13633 }
13634
13635 CursedWeaponsManager.getInstance().doLogout(this);
13636
13637 if (isInOlympiadMode() || (getOlympiadGame() != null))
13638 {
13639 Olympiad.logoutPlayer(this);
13640 }
13641
13642 if (isInObserverMode())
13643 {
13644 if (getOlympiadObserveGame() == null)
13645 {
13646 leaveObserverMode();
13647 }
13648 else
13649 {
13650 leaveOlympiadObserverMode(true);
13651 }
13652 _observerMode.set(OBSERVER_NONE);
13653 }
13654
13655 setVisibleNameColor(Config.BUFF_STORE_OFFLINE_NAME_COLOR);
13656 broadcastCharInfo();
13657
13658 // Guardamos el offline buffer en la db al salir
13659 OfflineBuffersTable.getInstance().onLogout(this);
13660
13661 // Stop all tasks
13662 stopWaterTask();
13663 stopBonusTask();
13664 stopHourlyTask();
13665 stopVitalityTask();
13666 stopPcBangPointsTask();
13667 stopAutoSaveTask();
13668 stopAutoChargeTask();
13669 stopRecomBonusTask(true);
13670 stopQuestTimers();
13671 getNevitSystem().stopTasksOnLogout();
13672
13673 try
13674 {
13675 getInventory().store();
13676 }
13677 catch (Throwable t)
13678 {
13679 _log.error("Error while storing Player Inventory", t);
13680 }
13681
13682 try
13683 {
13684 store(false);
13685 }
13686 catch (Throwable t)
13687 {
13688 _log.error("Error while storing Player", t);
13689 }
13690 }
13691
13692
13693 @Override
13694 public boolean isInZoneBattle()
13695 {
13696 // Ady - If the player is in a Gm Event and is a pvp event, then its in a zone battle also
13697 if (GmEventManager.getInstance().isParticipating(this) && GmEventManager.getInstance().isPvPEvent())
13698 return true;
13699
13700 return super.isInZoneBattle();
13701 }
13702
13703 @Override
13704 public boolean isInZonePeace()
13705 {
13706 // Ady - If the player is in a Gm Event and is a peace event, then its in a peace zone
13707 if (GmEventManager.getInstance().isParticipating(this) && GmEventManager.getInstance().isPeaceEvent())
13708 return true;
13709
13710 return super.isInZonePeace();
13711 }
13712 /** ----------------- Hit Man System ------------------- */
13713 public int _ordered;
13714 public int getOrdered()
13715 {
13716 return _ordered;
13717 }
13718
13719 public void setOrdered(int ordered)
13720 {
13721 _ordered = ordered;
13722 broadcastUserInfo(true);
13723 }
13724 /** ----------------- End Hit Man System -------------------
13725
13726 * @return
13727 * */
13728 public boolean isInAwayingMode()
13729 {
13730 return _awaying;
13731 }
13732
13733 public void setAwayingMode(boolean awaying)
13734 {
13735 _awaying = awaying;
13736 }
13737 /**
13738 * Alexander - This is used to transfer the skill reuse to a new skill. This happens when a player level up or enchants an skill, its reused is lost due to its hashCode
13739 *
13740 * @param oldSkillReuseHashCode
13741 * @param newSkillReuseHashCode
13742 */
13743 public void disableSkillByNewLvl(Integer oldSkillReuseHashCode, Integer newSkillReuseHashCode)
13744 {
13745 if (oldSkillReuseHashCode == newSkillReuseHashCode)
13746 return;
13747
13748 if (_skillReuses == null)
13749 return;
13750
13751 final TimeStamp timeStamp = _skillReuses.get(oldSkillReuseHashCode);
13752 if (timeStamp == null)
13753 return;
13754
13755 _skillReuses.remove(oldSkillReuseHashCode);
13756
13757 if (timeStamp.getEndTime() <= 0 || timeStamp.getEndTime() < System.currentTimeMillis())
13758 return;
13759
13760 _skillReuses.put(newSkillReuseHashCode, timeStamp);
13761 }
13762
13763 // Alexander - Support for being able to enchant a weapon/armor using all attribute stones available
13764 private boolean _isEnchantAllAttribute = false;
13765
13766 public void setIsEnchantAllAttribute(boolean isEnchantAllAttribute)
13767 {
13768 _isEnchantAllAttribute = isEnchantAllAttribute;
13769 }
13770
13771 public boolean isEnchantAllAttribute()
13772 {
13773 return _isEnchantAllAttribute;
13774 }
13775
13776 public boolean isDualbox(Player ... players)
13777 {
13778 return isDualbox(0, false, Arrays.asList(players));
13779 }
13780
13781 public boolean isDualbox(Iterable<Player> players)
13782 {
13783 return isDualbox(0, false, players);
13784 }
13785
13786 public boolean isDualbox(int maxBoxesAllowed, boolean hwidOnly, Player ... players)
13787 {
13788 if (maxBoxesAllowed < 0)
13789 return false;
13790
13791 return isDualbox(maxBoxesAllowed, hwidOnly, Arrays.asList(players));
13792 }
13793
13794 public boolean isDualbox(int maxBoxesAllowed, boolean hwidOnly, Iterable<Player> players)
13795 {
13796 if (maxBoxesAllowed < 0)
13797 return false;
13798
13799 for (Player player : players)
13800 {
13801 if (player == null || player.getNetConnection() == null || player == this)
13802 continue;
13803
13804 if (!hwidOnly && getIP().equalsIgnoreCase(player.getIP()))
13805 {
13806 maxBoxesAllowed--;
13807 }
13808 else if (getHWID().equalsIgnoreCase(player.getHWID()))
13809 {
13810 maxBoxesAllowed--;
13811 }
13812
13813 if (maxBoxesAllowed < 0)
13814 return true;
13815 }
13816
13817 return false;
13818 }
13819
13820 private final Map<Integer, Integer> _achievementLevels = new FastMap<>();
13821
13822 public boolean achievement_nf_open;
13823
13824 public Map<Integer, Integer> getAchievements(int category)
13825 {
13826 Map<Integer, Integer> result = new FastMap<>();
13827 for(Entry<Integer, Integer> entry : _achievementLevels.entrySet())
13828 {
13829 int achievementId = entry.getKey();
13830 int achievementLevel = entry.getValue();
13831 Achievement ach = Achievements.getInstance().getAchievement(achievementId, Math.max(1, achievementLevel));
13832 if (ach != null && ach.getCategoryId() == category)
13833 result.put(achievementId, achievementLevel);
13834 }
13835 return result;
13836 }
13837
13838 public Map<Integer, Integer> getAchievements()
13839 {
13840 return _achievementLevels;
13841 }
13842
13843 private void loadAchivements()
13844 {
13845 String achievements = getVar("achievements");
13846 if (achievements != null && !achievements.isEmpty())
13847 {
13848 String[] levels = achievements.split(";");
13849 for(String ach : levels)
13850 {
13851 String[] lvl = ach.split(",");
13852
13853 // Check if achievement exists.
13854 if (Achievements.getInstance().getMaxLevel(Integer.parseInt(lvl[0])) > 0)
13855 _achievementLevels.put(Integer.parseInt(lvl[0]), Integer.parseInt(lvl[1]));
13856 }
13857 }
13858
13859 for(int achievementId : Achievements.getInstance().getAchievementIds())
13860 if (!_achievementLevels.containsKey(achievementId))
13861 _achievementLevels.put(achievementId, 0);
13862 }
13863
13864 private void saveAchivements()
13865 {
13866 String str = "";
13867 for(Entry<Integer, Integer> a : _achievementLevels.entrySet())
13868 str += a.getKey() + "," + a.getValue() + ";";
13869
13870 setVar("achievements", str);
13871 }
13872
13873 private PlayerCounters _playerCountersExtension = null;
13874
13875 public PlayerCounters getCounters()
13876 {
13877 if (!Config.ENABLE_PLAYER_COUNTERS)
13878 return PlayerCounters.DUMMY_COUNTER;
13879
13880 if (_playerCountersExtension == null)
13881 {
13882 synchronized (this)
13883 {
13884 if (_playerCountersExtension == null)
13885 _playerCountersExtension = new PlayerCounters(this);
13886 }
13887 }
13888 return _playerCountersExtension;
13889 }
13890
13891 // Alexander - Custom stats holder
13892 private final PcStats _stats;
13893
13894 public final PcStats getStats()
13895 {
13896 return _stats;
13897 }
13898
13899 public final void addPlayerStats(Ranking rank)
13900 {
13901 getStats().addPlayerStats(rank);
13902 }
13903
13904 public final void addPlayerStats(Ranking rank, long points)
13905 {
13906 getStats().addPlayerStats(rank, points);
13907 }
13908
13909 public void broadcastSkillOrSocialAnimation(int id, int level, int hitTime, int lockActivityTime)
13910 {
13911 if (isAlikeDead())
13912 return;
13913
13914 boolean performSocialAction = (level < 1);
13915
13916 if (!performSocialAction)
13917 broadcastPacket(new MagicSkillUse(this, this, id, level, hitTime, 0));
13918 else
13919 broadcastPacket(new SocialAction(getObjectId(), id));
13920 }
13921
13922 private int soloInstance;
13923
13924 public void updateSoloInstance()
13925 {
13926 this.soloInstance++;
13927 }
13928
13929 public int getSoloInstance()
13930 {
13931 return soloInstance;
13932 }
13933
13934 private int partyInstance;
13935
13936 public void updatePartyInstance()
13937 {
13938 this.partyInstance++;
13939 }
13940
13941 public int getPartyInstance()
13942 {
13943 return partyInstance;
13944 }
13945
13946 //automp
13947 public void AutoMp(boolean flag)
13948 {
13949 _autoMp = flag;
13950 sendPacket(new ExAutoSoulShot(autoMp, flag));
13951 }
13952
13953 public void AutoCp(boolean flag)
13954 {
13955 _autoCp = flag;
13956 sendPacket(new ExAutoSoulShot(autoCp, flag));
13957 }
13958
13959 public void AutoHp(boolean flag)
13960 {
13961 _autoHp = flag;
13962 sendPacket(new ExAutoSoulShot(autoHp, flag));
13963 }
13964
13965 // Captcha
13966 private int _capchaCount = 0;
13967
13968 public int getCapchaCount()
13969 {
13970 return _capchaCount;
13971 }
13972
13973 public void updateCapchaCount(int count)
13974 {
13975 _capchaCount = count;
13976 }
13977
13978 // Alexander - Used for catpcha system, sets when was the last time that this player did damage to a monster
13979 private long _lastMonsterDamageTime = 0;
13980
13981 public long getLastMonsterDamageTime()
13982 {
13983 return _lastMonsterDamageTime;
13984 }
13985
13986 public void setLastMonsterDamageTime()
13987 {
13988 _lastMonsterDamageTime = System.currentTimeMillis();
13989 }
13990}