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