· 8 years ago · Nov 21, 2017, 08:06 PM
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 public 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 pk.assasins++;
4332
4333 switch(pk.assasins) {
4334 case 1:
4335 Announcements.getInstance().announceToAll("FIRST KILL VARIABLE FOR TEST: " + assasins);
4336 break;
4337 case 2:
4338 Announcements.getInstance().announceToAll("SECOND KILL VARIABLE FOR TEST: " + assasins);
4339 break;
4340 case 3:
4341 Announcements.getInstance().announceToAll("THIRD KILL VARIABLE FOR TEST: " + assasins);
4342 break;
4343 case 4:
4344 Announcements.getInstance().announceToAll("FOUR KILL VARIABLE FOR TEST: " + assasins);
4345 break;
4346 default:
4347 Announcements.getInstance().announceToAll("DEFAULT KILL++ VARIABLE FOR TEST: " + 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 boolean checkPvp = true;
4545 if (Config.ALLOW_CURSED_WEAPONS)
4546 {
4547 if (isCursedWeaponEquipped())
4548 {
4549 CursedWeaponsManager.getInstance().dropPlayer(this);
4550 checkPvp = false;
4551 }
4552 else if ((killer != null) && killer.isPlayer() && killer.isCursedWeaponEquipped())
4553 {
4554 CursedWeaponsManager.getInstance().increaseKills(((Player) killer).getCursedWeaponEquippedId());
4555 checkPvp = false;
4556 }
4557 }
4558
4559 if (checkPvp)
4560 {
4561 doPKPVPManage(killer);
4562 //killingspree
4563 assasins = 0;
4564 Announcements.getInstance().announceToAll("LOG: doPKPVPManage(killer): " + assasins);
4565
4566 altDeathPenalty(killer);
4567 }
4568
4569 // And in the end of process notify death penalty that owner died :)
4570 getDeathPenalty().notifyDead(killer);
4571
4572 if (_event != null)
4573 {
4574 _event.doDie(killer, this);
4575 }
4576
4577 setIncreasedForce(0);
4578
4579 if (isInParty() && getParty().isInReflection() && (getParty().getReflection() instanceof DimensionalRift))
4580 {
4581 ((DimensionalRift) getParty().getReflection()).memberDead(this);
4582 }
4583
4584 stopWaterTask();
4585
4586 if (!isSalvation() && isOnSiegeField() && isCharmOfCourage())
4587 {
4588 ask(new ConfirmDlg(SystemMsg.YOUR_CHARM_OF_COURAGE_IS_TRYING_TO_RESURRECT_YOU, 60000), new ReviveAnswerListener(this, 100, false));
4589 setCharmOfCourage(false);
4590 }
4591
4592 if (getLevel() < 6)
4593 {
4594 Quest q = QuestManager.getQuest(255);
4595 if (q != null)
4596 {
4597 processQuestEvent(q.getName(), "CE30", null);
4598 }
4599 }
4600
4601 if (isInOlympiadMode() && (killer.isPlayable() && killer.getPlayer().isInOlympiadMode()))
4602 {
4603 _log.warn("Player: " + getName() + " DIED in olympiad from: " + killer.getName());
4604 Thread.dumpStack();
4605 }
4606
4607 // Prims - Call the gm event manager due to this death
4608 GmEventManager.getInstance().onPlayerKill(this, killer);
4609
4610 super.onDeath(killer);
4611 }
4612
4613 public void restoreExp()
4614 {
4615 restoreExp(100.);
4616 }
4617
4618 public void restoreExp(double percent)
4619 {
4620 if (percent == 0)
4621 {
4622 return;
4623 }
4624
4625 int lostexp = 0;
4626
4627 String lostexps = getVar("lostexp");
4628 if (lostexps != null)
4629 {
4630 lostexp = Integer.parseInt(lostexps);
4631 unsetVar("lostexp");
4632 }
4633
4634 if (lostexp != 0)
4635 {
4636 addExpAndSp((long) ((lostexp * percent) / 100), 0);
4637 }
4638 }
4639
4640 public void deathPenalty(Creature killer)
4641 {
4642 if (killer == null || isInFightClub())
4643 {
4644 return;
4645 }
4646 final boolean atwar = (killer.getPlayer() != null) && atWarWith(killer.getPlayer());
4647
4648 double deathPenaltyBonus = getDeathPenalty().getLevel() * Config.ALT_DEATH_PENALTY_C5_EXPERIENCE_PENALTY;
4649 if (deathPenaltyBonus < 2)
4650 {
4651 deathPenaltyBonus = 1;
4652 }
4653 else
4654 {
4655 deathPenaltyBonus = deathPenaltyBonus / 2;
4656 }
4657
4658 // The death steal you some Exp: 10-40 lvl 8% loose
4659 double percentLost = 8.0;
4660
4661 int level = getLevel();
4662 if (level >= 79)
4663 {
4664 percentLost = 1.0;
4665 }
4666 else if (level >= 78)
4667 {
4668 percentLost = 1.5;
4669 }
4670 else if (level >= 76)
4671 {
4672 percentLost = 2.0;
4673 }
4674 else if (level >= 40)
4675 {
4676 percentLost = 4.0;
4677 }
4678
4679 if (Config.ALT_DEATH_PENALTY)
4680 {
4681 percentLost = (percentLost * Config.RATE_XP) + (_pkKills * Config.ALT_PK_DEATH_RATE);
4682 }
4683
4684 if (isFestivalParticipant() || atwar)
4685 {
4686 percentLost = percentLost / 4.0;
4687 }
4688
4689 // Calculate the Experience loss
4690 int lostexp = (int) Math.round(((Experience.LEVEL[level + 1] - Experience.LEVEL[level]) * percentLost) / 100);
4691 lostexp *= deathPenaltyBonus;
4692
4693 lostexp = (int) calcStat(Stats.EXP_LOST, lostexp, killer, null);
4694
4695 if (isOnSiegeField())
4696 {
4697 SiegeEvent<?, ?> siegeEvent = getEvent(SiegeEvent.class);
4698 if (siegeEvent != null)
4699 {
4700 lostexp = 0;
4701 }
4702
4703 if (siegeEvent != null)
4704 {
4705 List<Effect> effect = getEffectList().getEffectsBySkillId(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
4706 if (effect != null)
4707 {
4708 int syndromeLvl = effect.get(0).getSkill().getLevel();
4709 if (syndromeLvl < 5)
4710 {
4711 getEffectList().stopEffect(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
4712 Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, syndromeLvl + 1);
4713 skill.getEffects(this, this, false, false);
4714 }
4715 else if (syndromeLvl == 5)
4716 {
4717 getEffectList().stopEffect(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
4718 Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, 5);
4719 skill.getEffects(this, this, false, false);
4720 }
4721 }
4722 else
4723 {
4724 Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, 1);
4725 if (skill != null)
4726 {
4727 skill.getEffects(this, this, false, false);
4728 }
4729 }
4730 }
4731 }
4732
4733 if (getNevitSystem().isBlessingActive())
4734 {
4735 return;
4736 }
4737
4738 if ((_event != null) && !_event.canLostExpOnDie())
4739 {
4740 return;
4741 }
4742
4743 long before = getExp();
4744 addExpAndSp(-lostexp, 0);
4745 long lost = before - getExp();
4746
4747 if (lost > 0)
4748 {
4749 setVar("lostexp", String.valueOf(lost), -1);
4750 }
4751 }
4752
4753 public void setRequest(Request transaction)
4754 {
4755 _request = transaction;
4756 }
4757
4758 public Request getRequest()
4759 {
4760 return _request;
4761 }
4762
4763 public boolean isBusy()
4764 {
4765 return isProcessingRequest() || isOutOfControl() || isInOlympiadMode() || (getTeam() != TeamType.NONE) || isInStoreMode() || isInDuel() || getMessageRefusal() || isBlockAll() || isInvisible();
4766 }
4767
4768 public boolean isProcessingRequest()
4769 {
4770 if (_request == null)
4771 {
4772 return false;
4773 }
4774 if (!_request.isInProgress())
4775 {
4776 return false;
4777 }
4778 return true;
4779 }
4780
4781 public boolean isInTrade()
4782 {
4783 return isProcessingRequest() && getRequest().isTypeOf(L2RequestType.TRADE);
4784 }
4785
4786 public boolean isInPost()
4787 {
4788 return isProcessingRequest() && getRequest().isTypeOf(L2RequestType.POST);
4789 }
4790
4791 public List<L2GameServerPacket> addVisibleObject(GameObject object, Creature dropper)
4792 {
4793 if (isLogoutStarted() || (object == null) || (object.getObjectId() == getObjectId()) || !object.isVisible())
4794 {
4795 return Collections.emptyList();
4796 }
4797
4798 return object.addPacketList(this, dropper);
4799 }
4800
4801 @Override
4802 public List<L2GameServerPacket> addPacketList(Player forPlayer, Creature dropper)
4803 {
4804 if (getPrivateStoreType() != STORE_PRIVATE_NONE && !isInBuffStore() && forPlayer.getVarB("notraders"))
4805 {
4806 return Collections.emptyList();
4807 }
4808
4809 // If this is fake an Observer - do not show.
4810 if (isInObserverMode() && (getCurrentRegion() != getObserverRegion()) && (getObserverRegion() == forPlayer.getCurrentRegion()))
4811 {
4812 return Collections.emptyList();
4813 }
4814
4815 List<L2GameServerPacket> list = new ArrayList<>();
4816 if (forPlayer.getObjectId() != getObjectId())
4817 {
4818 list.add(isPolymorphed() ? new NpcInfoPoly(this) : new CharInfo(this, forPlayer));
4819 }
4820
4821 list.add(new ExBR_ExtraUserInfo(this));
4822
4823 if (isSitting() && (_sittingObject != null))
4824 {
4825 list.add(new ChairSit(this, _sittingObject));
4826 }
4827
4828 if (getPrivateStoreType() != STORE_PRIVATE_NONE)
4829 {
4830 if (getPrivateStoreType() == STORE_PRIVATE_BUY)
4831 {
4832 list.add(new PrivateStoreMsgBuy(this));
4833 }
4834 else if ((getPrivateStoreType() == STORE_PRIVATE_SELL) || (getPrivateStoreType() == STORE_PRIVATE_SELL_PACKAGE))
4835 {
4836 list.add(new PrivateStoreMsgSell(this));
4837 }
4838 else if (getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE)
4839 {
4840 list.add(new RecipeShopMsg(this));
4841 }
4842 if (forPlayer.isInZonePeace())
4843 {
4844 return list;
4845 }
4846 }
4847
4848 if (isCastingNow())
4849 {
4850 Creature castingTarget = getCastingTarget();
4851 Skill castingSkill = getCastingSkill();
4852 long animationEndTime = getAnimationEndTime();
4853 if ((castingSkill != null) && (castingTarget != null) && castingTarget.isCreature() && (getAnimationEndTime() > 0))
4854 {
4855 list.add(new MagicSkillUse(this, castingTarget, castingSkill.getId(), castingSkill.getLevel(), (int) (animationEndTime - System.currentTimeMillis()), 0));
4856 }
4857 }
4858
4859 if (isInCombat())
4860 {
4861 list.add(new AutoAttackStart(getObjectId()));
4862 }
4863
4864 list.add(RelationChanged.update(forPlayer, this, forPlayer));
4865 DominionSiegeEvent dominionSiegeEvent = getEvent(DominionSiegeEvent.class);
4866 if (dominionSiegeEvent != null)
4867 {
4868 list.add(new ExDominionWarStart(this));
4869 }
4870
4871 if (isInBoat())
4872 {
4873 list.add(getBoat().getOnPacket(this, getInBoatPosition()));
4874 }
4875 else
4876 {
4877 if (isMoving || isFollow)
4878 {
4879 list.add(movePacket());
4880 }
4881 }
4882 return list;
4883 }
4884
4885 public List<L2GameServerPacket> removeVisibleObject(GameObject object, List<L2GameServerPacket> list)
4886 {
4887 if (isLogoutStarted() || (object == null) || (object.getObjectId() == getObjectId()))
4888 {
4889 return null;
4890 }
4891
4892 List<L2GameServerPacket> result = list == null ? object.deletePacketList() : list;
4893
4894 getAI().notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
4895 return result;
4896 }
4897
4898 public void levelSet(int levels)
4899 {
4900 if (levels > 0)
4901 {
4902 sendPacket(Msg.YOU_HAVE_INCREASED_YOUR_LEVEL);
4903 broadcastPacket(new SocialAction(getObjectId(), SocialAction.LEVEL_UP));
4904
4905 setCurrentHpMp(getMaxHp(), getMaxMp());
4906 setCurrentCp(getMaxCp());
4907
4908 Quest q = QuestManager.getQuest(255);
4909 if (q != null)
4910 {
4911 processQuestEvent(q.getName(), "CE40", null);
4912 processQuestEvent(q.getName(), "OpenClassMaster", null);
4913 }
4914 }
4915 else if (levels < 0)
4916 {
4917 if (Config.ALT_REMOVE_SKILLS_ON_DELEVEL)
4918 {
4919 checkSkills();
4920 }
4921 }
4922
4923 // Recalculate the party level
4924 if (isInParty())
4925 {
4926 getParty().recalculatePartyData();
4927 }
4928
4929 if (_clan != null)
4930 {
4931 _clan.broadcastToOnlineMembers(new PledgeShowMemberListUpdate(this));
4932 }
4933
4934 if (_matchingRoom != null)
4935 {
4936 _matchingRoom.broadcastPlayerUpdate(this);
4937 }
4938
4939 // Give Expertise skill of this level
4940 rewardSkills(true);
4941 }
4942
4943 public void checkSkills()
4944 {
4945 for (Skill sk : getAllSkillsArray())
4946 {
4947 SkillTreeTable.checkSkill(this, sk);
4948 }
4949 }
4950
4951 public void startTimers()
4952 {
4953 startAutoSaveTask();
4954 startPcBangPointsTask();
4955 startHourlyTask();
4956 PremiumStart.getInstance().start(this);
4957 //startBonusTask();
4958 getInventory().startTimers();
4959 resumeQuestTimers();
4960 }
4961
4962 public void stopAllTimers()
4963 {
4964 setAgathion(0);
4965 stopWaterTask();
4966 stopBonusTask();
4967 stopHourlyTask();
4968 stopKickTask();
4969 stopVitalityTask();
4970 stopPcBangPointsTask();
4971 stopAutoSaveTask();
4972 stopRecomBonusTask(true);
4973 getInventory().stopAllTimers();
4974 stopQuestTimers();
4975 getNevitSystem().stopTasksOnLogout();
4976 }
4977
4978 @Override
4979 public Summon getPet()
4980 {
4981 return _summon;
4982 }
4983
4984 public void setPet(Summon summon)
4985 {
4986 boolean isPet = false;
4987 if ((_summon != null) && _summon.isPet())
4988 {
4989 isPet = true;
4990 }
4991 unsetVar("pet");
4992 _summon = summon;
4993 autoShot();
4994 if (summon == null)
4995 {
4996 if (isPet)
4997 {
4998 if (isLogoutStarted())
4999 {
5000 if (getPetControlItem() != null)
5001 {
5002 setVar("pet", String.valueOf(getPetControlItem().getObjectId()), -1);
5003 }
5004 }
5005 setPetControlItem(null);
5006 }
5007 getEffectList().stopEffect(4140);
5008 }
5009 }
5010
5011 public void scheduleDelete()
5012 {
5013 long time = 0;
5014
5015 if (Config.SERVICES_ENABLE_NO_CARRIER)
5016 {
5017 time = NumberUtils.toInt(getVar("noCarrier"), Config.SERVICES_NO_CARRIER_DEFAULT_TIME);
5018 }
5019 scheduleDelete(time * 1000);
5020 }
5021
5022 /**
5023 * 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>
5024 * <br>
5025 * a minute to make him invulnerable. <br>
5026 * 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>
5027 * <br>
5028 * @param time
5029 */
5030 public void scheduleDelete(long time)
5031 {
5032 if (isInOfflineMode())
5033 {
5034 return;
5035 }
5036 broadcastCharInfo();
5037
5038 ThreadPoolManager.getInstance().schedule(new RunnableImpl()
5039 {
5040 @Override
5041 public void runImpl()
5042 {
5043 if (!isConnected())
5044 {
5045 prepareToLogout();
5046 deleteMe();
5047 }
5048 }
5049 }, time);
5050 }
5051
5052 @Override
5053 protected void onDelete()
5054 {
5055 super.onDelete();
5056
5057 // Remove the fake at the observation point
5058 WorldRegion observerRegion = getObserverRegion();
5059 if (observerRegion != null)
5060 {
5061 observerRegion.removeObject(this);
5062 }
5063
5064 // Send friendlists to friends that this player has logged off
5065 _friendList.notifyFriends(false);
5066
5067 bookmarks.clear();
5068
5069 _inventory.clear();
5070 _warehouse.clear();
5071 _summon = null;
5072 _arrowItem = null;
5073 _fistsWeaponItem = null;
5074 _chars = null;
5075 _enchantScroll = null;
5076 _lastNpc = HardReferences.emptyRef();
5077 _observerRegion = null;
5078 }
5079
5080 public void setTradeList(List<TradeItem> list)
5081 {
5082 _tradeList = list;
5083 }
5084
5085 public List<TradeItem> getTradeList()
5086 {
5087 return _tradeList;
5088 }
5089
5090 public String getSellStoreName()
5091 {
5092 return _sellStoreName;
5093 }
5094
5095 public void setSellStoreName(String name)
5096 {
5097 _sellStoreName = Strings.stripToSingleLine(name);
5098 }
5099
5100 public void setSellList(boolean packageSell, List<TradeItem> list)
5101 {
5102 if (packageSell)
5103 {
5104 _packageSellList = list;
5105 }
5106 else
5107 {
5108 _sellList = list;
5109 }
5110 }
5111
5112 public List<TradeItem> getSellList()
5113 {
5114 return getSellList(_privatestore == STORE_PRIVATE_SELL_PACKAGE);
5115 }
5116
5117 public List<TradeItem> getSellList(boolean packageSell)
5118 {
5119 return packageSell ? _packageSellList : _sellList;
5120 }
5121
5122 public String getBuyStoreName()
5123 {
5124 return _buyStoreName;
5125 }
5126
5127 public void setBuyStoreName(String name)
5128 {
5129 _buyStoreName = Strings.stripToSingleLine(name);
5130 }
5131
5132 public void setBuyList(List<TradeItem> list)
5133 {
5134 _buyList = list;
5135 }
5136
5137 public List<TradeItem> getBuyList()
5138 {
5139 return _buyList;
5140 }
5141
5142 public void setManufactureName(String name)
5143 {
5144 _manufactureName = Strings.stripToSingleLine(name);
5145 }
5146
5147 public String getManufactureName()
5148 {
5149 return _manufactureName;
5150 }
5151
5152 public List<ManufactureItem> getCreateList()
5153 {
5154 return _createList;
5155 }
5156
5157 public void setCreateList(List<ManufactureItem> list)
5158 {
5159 _createList = list;
5160 }
5161
5162 public void setPrivateStoreType(final int type)
5163 {
5164 _privatestore = type;
5165 if (type != STORE_PRIVATE_NONE)
5166 {
5167 setVar("storemode", String.valueOf(type), -1);
5168 }
5169 else
5170 {
5171 for (TradeItem item : _sellList)
5172 AuctionManager.getInstance().removeStore(this, item.getAuctionId());
5173 unsetVar("storemode");
5174 }
5175 }
5176
5177 public boolean isInStoreMode()
5178 {
5179 return _privatestore != STORE_PRIVATE_NONE;
5180 }
5181
5182 public boolean isInBuffStore()
5183 {
5184 return (getPrivateStoreType() == STORE_PRIVATE_BUFF);
5185 }
5186
5187 public int getPrivateStoreType()
5188 {
5189 return _privatestore;
5190 }
5191
5192 /**
5193 * Set the _clan object, _clanId, _clanLeader Flag and title of the L2Player.<BR>
5194 * <BR>
5195 * @param clan the clat to set
5196 */
5197 public void setClan(Clan clan)
5198 {
5199 if ((_clan != clan) && (_clan != null))
5200 {
5201 unsetVar("canWhWithdraw");
5202 }
5203
5204 Clan oldClan = _clan;
5205 if ((oldClan != null) && (clan == null))
5206 {
5207 // Remove clan skills
5208 for (Skill skill : oldClan.getSkills())
5209 {
5210 removeSkill(skill, false);
5211 }
5212
5213 // Also remove subunit skills
5214 for (SubUnit subUnit : oldClan.getAllSubUnits())
5215 {
5216 for (Skill sk : subUnit.getSkills())
5217 {
5218 removeSkill(sk, false);
5219 }
5220 }
5221 }
5222
5223 _clan = clan;
5224
5225 if (clan == null)
5226 {
5227 _pledgeType = Clan.SUBUNIT_NONE;
5228 _pledgeClass = 0;
5229 _powerGrade = 0;
5230 _apprentice = 0;
5231 _inventory.validateItems();
5232
5233 if (getEvent(CastleSiegeEvent.class) != null)
5234 removeEvent(getEvent(CastleSiegeEvent.class));
5235 return;
5236 }
5237
5238 if (!clan.isAnyMember(getObjectId()))
5239 {
5240 clan.restartMembers();
5241 }
5242
5243 if (!clan.isAnyMember(getObjectId()))
5244 {
5245 setClan(null);
5246 if (!_noble)
5247 {
5248 setTitle("");
5249 }
5250 }
5251 }
5252
5253 @Override
5254 public Clan getClan()
5255 {
5256 return _clan;
5257 }
5258
5259 public SubUnit getSubUnit()
5260 {
5261 return _clan == null ? null : _clan.getSubUnit(_pledgeType);
5262 }
5263
5264 public ClanHall getClanHall()
5265 {
5266 int id = _clan != null ? _clan.getHasHideout() : 0;
5267 return ResidenceHolder.getInstance().getResidence(ClanHall.class, id);
5268 }
5269
5270 public Castle getCastle()
5271 {
5272 int id = _clan != null ? _clan.getCastle() : 0;
5273 return ResidenceHolder.getInstance().getResidence(Castle.class, id);
5274 }
5275
5276 public Fortress getFortress()
5277 {
5278 int id = _clan != null ? _clan.getHasFortress() : 0;
5279 return ResidenceHolder.getInstance().getResidence(Fortress.class, id);
5280 }
5281
5282 public Alliance getAlliance()
5283 {
5284 return _clan == null ? null : _clan.getAlliance();
5285 }
5286
5287 public boolean isClanLeader()
5288 {
5289 return (_clan != null) && (getObjectId() == _clan.getLeaderId());
5290 }
5291
5292 public boolean isAllyLeader()
5293 {
5294 return (getAlliance() != null) && (getAlliance().getLeader().getLeaderId() == getObjectId());
5295 }
5296
5297 @Override
5298 public void reduceArrowCount()
5299 {
5300 sendPacket(SystemMsg.YOU_CAREFULLY_NOCK_AN_ARROW);
5301 if ((_arrowItem != null) && !Config.ALLOW_ARROW_INFINITELY)
5302 {
5303 if (!getInventory().destroyItemByObjectId(getInventory().getPaperdollObjectId(Inventory.PAPERDOLL_LHAND), 1L, null, null))
5304 {
5305 getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, null);
5306 _arrowItem = null;
5307 }
5308 }
5309 }
5310
5311 /**
5312 * Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2Player then return True.
5313 * @return
5314 */
5315 protected boolean checkAndEquipArrows()
5316 {
5317 // Check if nothing is equipped in left hand
5318 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null)
5319 {
5320 ItemInstance activeWeapon = getActiveWeaponInstance();
5321 if (activeWeapon != null)
5322 {
5323 if (activeWeapon.getItemType() == WeaponType.BOW)
5324 {
5325 _arrowItem = getInventory().findArrowForBow(activeWeapon.getTemplate());
5326 }
5327 else if (activeWeapon.getItemType() == WeaponType.CROSSBOW)
5328 {
5329 getInventory().findArrowForCrossbow(activeWeapon.getTemplate());
5330 }
5331 }
5332
5333 // Equip arrows needed in left hand
5334 if (_arrowItem != null)
5335 {
5336 getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, _arrowItem);
5337 }
5338 }
5339 else
5340 {
5341 // Get the L2ItemInstance of arrows equipped in left hand
5342 _arrowItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
5343 }
5344
5345 return _arrowItem != null;
5346 }
5347
5348 public void setUptime(final long time)
5349 {
5350 _uptime = time;
5351 }
5352
5353 public long getUptime()
5354 {
5355 return _uptime == 0L ? 0L : System.currentTimeMillis() - _uptime;
5356 }
5357
5358 public boolean isInParty()
5359 {
5360 return _party != null;
5361 }
5362
5363 public void setParty(final Party party)
5364 {
5365 _party = party;
5366 }
5367
5368 public void joinParty(final Party party)
5369 {
5370 if (party != null)
5371 {
5372 party.addPartyMember(this);
5373 for (Player member : party.getMembers())
5374 {
5375 if (PartyMatchingBBSManager.getInstance().partyMatchingPlayersList.contains(member))
5376 {
5377 PartyMatchingBBSManager.getInstance().partyMatchingPlayersList.remove(member);
5378 PartyMatchingBBSManager.getInstance().partyMatchingDescriptionList.remove(member.getObjectId());
5379 member.sendMessage("Now that you have found a party, you've been removed from the Party Matching list.");
5380 }
5381 }
5382
5383 }
5384 }
5385
5386 public void leaveParty()
5387 {
5388 if (isInParty())
5389 {
5390 _party.removePartyMember(this, false);
5391 }
5392 }
5393
5394 public Party getParty()
5395 {
5396 return _party;
5397 }
5398
5399 public void setLastPartyPosition(Location loc)
5400 {
5401 _lastPartyPosition = loc;
5402 }
5403
5404 public Location getLastPartyPosition()
5405 {
5406 return _lastPartyPosition;
5407 }
5408
5409 public boolean isGM()
5410 {
5411 return _playerAccess == null ? false : _playerAccess.IsGM;
5412 }
5413
5414 public void setAccessLevel(final int level)
5415 {
5416 _accessLevel = level;
5417 }
5418
5419 @Override
5420 public int getAccessLevel()
5421 {
5422 return _accessLevel;
5423 }
5424
5425 public void setPlayerAccess(final PlayerAccess pa)
5426 {
5427 if (pa != null)
5428 {
5429 _playerAccess = pa;
5430 }
5431 else
5432 {
5433 _playerAccess = new PlayerAccess();
5434 }
5435
5436 setAccessLevel(isGM() || _playerAccess.Menu ? 100 : 0);
5437 }
5438
5439 public PlayerAccess getPlayerAccess()
5440 {
5441 return _playerAccess;
5442 }
5443
5444 @Override
5445 public double getLevelMod()
5446 {
5447 return (89. + getLevel()) / 100.0;
5448 }
5449
5450 /**
5451 * 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>
5452 * <BR>
5453 */
5454 @Override
5455 public void updateStats()
5456 {
5457 if (entering || isLogoutStarted())
5458 {
5459 return;
5460 }
5461
5462 refreshOverloaded();
5463 if (Config.EXPERTISE_PENALTY)
5464 {
5465 refreshExpertisePenalty();
5466 }
5467 super.updateStats();
5468 }
5469
5470 @Override
5471 public void sendChanges()
5472 {
5473 if (entering || isLogoutStarted())
5474 {
5475 return;
5476 }
5477 super.sendChanges();
5478 }
5479
5480 /**
5481 * Send a Server->Client StatusUpdate packet with Karma to the L2Player and all L2Player to inform (broadcast).
5482 * @param flagChanged
5483 */
5484 public void updateKarma(boolean flagChanged)
5485 {
5486 sendStatusUpdate(true, true, StatusUpdate.KARMA);
5487 if (flagChanged)
5488 broadcastRelationChanged();
5489 }
5490
5491 public boolean isOnline()
5492 {
5493 return _isOnline;
5494 }
5495
5496 public void setIsOnline(boolean isOnline)
5497 {
5498 _isOnline = isOnline;
5499 }
5500
5501 public void setOnlineStatus(boolean isOnline)
5502 {
5503 _isOnline = isOnline;
5504 updateOnlineStatus();
5505 }
5506
5507 public void updateOnlineStatus()
5508 {
5509 try (Connection con = DatabaseFactory.getInstance().getConnection();
5510 PreparedStatement statement = con.prepareStatement("UPDATE characters SET online=?, lastAccess=? WHERE obj_id=?"))
5511 {
5512 statement.setInt(1, (isOnline() && !isInOfflineMode()) || (isInOfflineMode() && Config.SHOW_OFFLINE_MODE_IN_ONLINE) ? 1 : 0);
5513 statement.setLong(2, System.currentTimeMillis() / 1000L);
5514 statement.setInt(3, getObjectId());
5515 statement.execute();
5516 }
5517 catch (SQLException e)
5518 {
5519 _log.error("Error while updating Online Status", e);
5520 }
5521 }
5522
5523 /**
5524 * Decrease Karma of the L2Player and Send it StatusUpdate packet with Karma and PvP Flag (broadcast).
5525 * @param add_karma
5526 */
5527 public void increaseKarma(final long add_karma)
5528 {
5529 boolean flagChanged = _karma == 0;
5530 long newKarma = _karma + add_karma;
5531
5532 if (newKarma > Integer.MAX_VALUE)
5533 {
5534 newKarma = Integer.MAX_VALUE;
5535 }
5536
5537 if ((_karma == 0) && (newKarma > 0))
5538 {
5539 if (_pvpFlag > 0)
5540 {
5541 _pvpFlag = 0;
5542 if (_PvPRegTask != null)
5543 {
5544 _PvPRegTask.cancel(true);
5545 _PvPRegTask = null;
5546 }
5547 sendStatusUpdate(true, true, StatusUpdate.PVP_FLAG);
5548 }
5549
5550 _karma = (int) newKarma;
5551 }
5552 else
5553 {
5554 _karma = (int) newKarma;
5555 }
5556
5557 if (getCounters().highestKarma < newKarma)
5558 getCounters().highestKarma = (int) newKarma;
5559
5560 updateKarma(flagChanged);
5561 }
5562
5563 /**
5564 * Decrease Karma of the L2Player and Send it StatusUpdate packet with Karma and PvP Flag (broadcast).
5565 * @param i
5566 */
5567 public void decreaseKarma(final int i)
5568 {
5569 boolean flagChanged = _karma > 0;
5570 _karma -= i;
5571 if (_karma <= 0)
5572 {
5573 _karma = 0;
5574 updateKarma(flagChanged);
5575 }
5576 else
5577 {
5578 updateKarma(false);
5579 }
5580 }
5581
5582 /**
5583 * Create a new L2Player and add it in the characters table of the database.<BR>
5584 * <BR>
5585 * <p/>
5586 * <B><U> Actions</U> :</B><BR>
5587 * <BR>
5588 * <li>Create a new L2Player with an account name</li>
5589 * <li>Set the name, the Hair Style, the Hair Color and the Face type of the L2Player</li>
5590 * <li>Add the player in the characters table of the database</li><BR>
5591 * <BR>
5592 * @param classId
5593 * @param sex
5594 * @param accountName The name of the L2Player
5595 * @param name The name of the L2Player
5596 * @param hairStyle The hair style Identifier of the L2Player
5597 * @param hairColor The hair color Identifier of the L2Player
5598 * @param face The face type Identifier of the L2Player
5599 * @return The L2Player added to the database or null
5600 */
5601 public static Player create(int classId, int sex, String accountName, final String name, final int hairStyle, final int hairColor, final int face)
5602 {
5603 PlayerTemplate template = CharTemplateHolder.getInstance().getTemplate(classId, sex != 0);
5604
5605 // Create a new L2Player with an account name
5606 Player player = new Player(IdFactory.getInstance().getNextId(), template, accountName);
5607
5608 player.setName(name);
5609 player.setTitle("");
5610 player.setHairStyle(hairStyle);
5611 player.setHairColor(hairColor);
5612 player.setFace(face);
5613 player.setCreateTime(System.currentTimeMillis());
5614
5615 // Add the player in the characters table of the database
5616 if (!CharacterDAO.getInstance().insert(player))
5617 {
5618 return null;
5619 }
5620
5621 return player;
5622 }
5623
5624 /**
5625 * Retrieve a L2Player from the characters table of the database and add it in _allObjects of the L2World
5626 * @param objectId
5627 * @return The L2Player loaded from the database
5628 */
5629 public static Player restore(final int objectId)
5630 {
5631 Player player = null;
5632
5633 try (Connection con = DatabaseFactory.getInstance().getConnection();
5634 Statement statement = con.createStatement();
5635 Statement statement2 = con.createStatement();
5636 ResultSet rset = statement.executeQuery("SELECT * FROM `characters` WHERE `obj_Id`=" + objectId + " LIMIT 1");
5637 ResultSet rset2 = statement2.executeQuery("SELECT `class_id` FROM `character_subclasses` WHERE `char_obj_id`=" + objectId + " AND `isBase`=1 LIMIT 1"))
5638 {
5639 if (rset.next() && rset2.next())
5640 {
5641 final int classId = rset2.getInt("class_id");
5642 final boolean female = rset.getInt("sex") == 1;
5643 final PlayerTemplate template = CharTemplateHolder.getInstance().getTemplate(classId, female);
5644
5645 player = new Player(objectId, template);
5646
5647 player.loadVariables(con);
5648 player.loadInstanceReuses(con);
5649 player.loadPremiumItemList(con);
5650 player.bookmarks.setCapacity(rset.getInt("bookmarks"));
5651 player.bookmarks.restore(con);
5652 player._friendList.restore(con);
5653 player._postFriends = CharacterPostFriendDAO.select(player, con);
5654 CharacterGroupReuseDAO.select(player, con);
5655
5656 player._baseClass = classId;
5657 player._login = rset.getString("account_name");
5658 player.setName(rset.getString("char_name"));
5659
5660 player._face = rset.getInt("face");
5661 player._hairStyle = rset.getInt("hairStyle");
5662 player._hairColor = rset.getInt("hairColor");
5663 player.setHeading(0);
5664
5665 player.setKarma(rset.getInt("karma"));
5666 player._pvpKills = rset.getInt("pvpkills");
5667 player._pkKills = rset.getInt("pkkills");
5668 player.raids = rset.getInt("raidkills");
5669 player.soloInstance = rset.getInt("soloinstance");
5670 player.partyInstance = rset.getInt("partyinstance");
5671 player.setLeaveClanTime(rset.getLong("leaveclan") * 1000L);
5672 if (player.getLeaveClanTime() > 0 && player.canJoinClan())
5673 {
5674 player.setLeaveClanTime(0);
5675 }
5676 player.setDeleteClanTime(rset.getLong("deleteclan") * 1000L);
5677 if (player.getDeleteClanTime() > 0 && player.canCreateClan())
5678 {
5679 player.setDeleteClanTime(0);
5680 }
5681 player.setNoChannel(rset.getLong("nochannel") * 1000L);
5682 if ((player._NoChannel > 0L) && (player.getNoChannelRemained() < 0L))
5683 {
5684 player.setNoChannel(0L);
5685 }
5686 player._hwidLock = rset.getString("hwid_lock");
5687 if (player._hwidLock != null && player._hwidLock.isEmpty())
5688 player._hwidLock = null;
5689
5690 if (!player.isInOfflineMode() || !player.isInBuffStore())
5691 {
5692 player.setOnlineTime(rset.getLong("onlinetime") * 1000L);
5693 }
5694
5695 final int clanId = rset.getInt("clanid");
5696 if (clanId > 0)
5697 {
5698 player.setClan(ClanTable.getInstance().getClan(clanId));
5699 player._pledgeType = rset.getInt("pledge_type");
5700 player._powerGrade = rset.getInt("pledge_rank");
5701 player._lvlJoinedAcademy = rset.getInt("lvl_joined_academy");
5702 player._apprentice = rset.getInt("apprentice");
5703 }
5704
5705 player._createTime = rset.getLong("createtime") * 1000L;
5706 player._deleteTimer = rset.getInt("deletetime");
5707
5708 SchemeBufferInstance.loadSchemes(player, con);
5709
5710 player.setTitle(rset.getString("title"));
5711
5712 if (player.getVar("titlecolor") != null)
5713 {
5714 player.setTitleColor(Integer.decode("0x" + player.getVar("titlecolor")).intValue());
5715 }
5716
5717 if (player.getVar("namecolor") == null)
5718 {
5719 if (player.isGM())
5720 {
5721 player.setNameColor(Config.GM_NAME_COLOUR);
5722 }
5723 else if ((player._clan != null) && (player._clan.getLeaderId() == player.getObjectId()))
5724 {
5725 player.setNameColor(Config.CLANLEADER_NAME_COLOUR);
5726 }
5727 else
5728 {
5729 player.setNameColor(Config.NORMAL_NAME_COLOUR);
5730 }
5731 }
5732 else
5733 {
5734 player.setNameColor(Integer.decode("0x" + player.getVar("namecolor")).intValue());
5735 }
5736
5737 if (Config.AUTO_LOOT_INDIVIDUAL)
5738 {
5739 player._autoLoot = player.getVarB("AutoLoot", Config.AUTO_LOOT);
5740 player.AutoLootHerbs = player.getVarB("AutoLootHerbs", Config.AUTO_LOOT_HERBS);
5741 player.AutoLootOnlyAdena = player.getVarB("AutoLootOnlyAdena", Config.AUTO_LOOT_ONLY_ADENA);
5742 }
5743
5744 player._fistsWeaponItem = player.findFistsWeaponItem(classId);
5745 player._uptime = System.currentTimeMillis();
5746 player._lastAccess = rset.getLong("lastAccess");
5747
5748 player.setRecomHave(rset.getInt("rec_have"));
5749 player.setRecomLeft(rset.getInt("rec_left"));
5750 player._recomBonusTime = rset.getInt("rec_bonus_time");
5751
5752 if (player.getVar("recLeftToday") != null)
5753 {
5754 player._recomLeftToday = Integer.parseInt(player.getVar("recLeftToday"));
5755 }
5756 else
5757 {
5758 player._recomLeftToday = 0;
5759 }
5760
5761 player._nevitSystem.setPoints(rset.getInt("hunt_points"), rset.getInt("hunt_time"));
5762
5763 player.setKeyBindings(rset.getBytes("key_bindings"));
5764 player._pcBangPoints = rset.getInt("pcBangPoints");
5765
5766 player._fame = rset.getInt("fame");
5767
5768 player.restoreRecipeBook(con);
5769
5770 if (Config.ENABLE_OLYMPIAD)
5771 {
5772 player._hero = Hero.getInstance().isHero(player.getObjectId());
5773 player._noble = Olympiad.isNoble(player.getObjectId());
5774 }
5775
5776 player.setHwidLock(rset.getString("hwid_lock"));
5777
5778 player.updatePledgeClass();
5779
5780 int reflection = 0;
5781
5782 if (player.isInJail())
5783 {
5784 // randomly spawn in prison
5785 player.setXYZ(Rnd.get(-114936, -114136), Rnd.get(-249768, -248952), -2984);
5786
5787 long period = player.getVarTimeToExpire("jailed");
5788 player.updateNoChannel(period);
5789 player.sitDown(null);
5790 player.block();
5791
5792 if (period != -1)
5793 {
5794 player._unjailTask = ThreadPoolManager.getInstance().schedule(new UnJailTask(player, true), period);
5795 }
5796 }
5797 else if (player.getVar("jailedFrom") != null)
5798 {
5799 String[] re = player.getVar("jailedFrom").split(";");
5800
5801 player.setXYZ(Integer.parseInt(re[0]), Integer.parseInt(re[1]), Integer.parseInt(re[2]));
5802 player.setReflection(re.length > 3 ? Integer.parseInt(re[3]) : 0);
5803
5804 player.unsetVar("jailedFrom");
5805 }
5806 else
5807 {
5808 player.setXYZ(rset.getInt("x"), rset.getInt("y"), rset.getInt("z"));
5809 String ref = player.getVar("reflection");
5810 if (ref != null && Integer.parseInt(ref) != ReflectionManager.JAIL.getId())
5811 {
5812 reflection = Integer.parseInt(ref);
5813 if (reflection > 0) // not the portal back of the GC Parnassus, Gila
5814 {
5815 String back = player.getVar("backCoords");
5816 if (back != null)
5817 {
5818 player.setLoc(Location.parseLoc(back));
5819 player.unsetVar("backCoords");
5820 }
5821 reflection = 0;
5822 }
5823 }
5824 }
5825
5826 player.setReflection(reflection);
5827
5828 EventHolder.getInstance().findEvent(player);
5829
5830 Quest.restoreQuestStates(player, con);
5831
5832 player._inventory.restore();
5833
5834 player.isntAfk();
5835
5836 restoreCharSubClasses(player, con);
5837
5838 //4 points per minute based casino
5839 player.setVitality(rset.getInt("vitality") + (int) (((System.currentTimeMillis() / 1000L) -
5840 rset.getLong("lastAccess")) / 15.));
5841
5842 try
5843 {
5844 String var = player.getVar("ExpandInventory");
5845 if (var != null)
5846 {
5847 player._expandInventory = Integer.parseInt(var);
5848 }
5849 }
5850 catch (NumberFormatException e)
5851 {
5852 _log.error("Error while restoring Expand Inventory ", e);
5853 }
5854
5855 try
5856 {
5857 String var = player.getVar("ExpandWarehouse");
5858 if (var != null)
5859 {
5860 player._expandWarehouse = Integer.parseInt(var);
5861 }
5862 }
5863 catch (NumberFormatException e)
5864 {
5865 _log.error("Error while restoring Expand Warehouse", e);
5866 }
5867
5868 try
5869 {
5870 String var = player.getVar(NO_ANIMATION_OF_CAST_VAR);
5871 if (var != null)
5872 {
5873 player._notShowBuffAnim = Boolean.parseBoolean(var);
5874 }
5875 }
5876 catch (RuntimeException e)
5877 {
5878 _log.error("Error while restoring No Animation Player Config ", e);
5879 }
5880
5881 try
5882 {
5883 String var = player.getVar(NO_TRADERS_VAR);
5884 if (var != null)
5885 {
5886 player._notShowTraders = Boolean.parseBoolean(var);
5887 }
5888 }
5889 catch (RuntimeException e)
5890 {
5891 _log.error("Error while restoring Not Show Traders Player Config", e);
5892 }
5893
5894 try
5895 {
5896 String var = player.getVar("pet");
5897 if (var != null)
5898 {
5899 player.setPetControlItem(Integer.parseInt(var));
5900 }
5901 }
5902 catch (NumberFormatException e)
5903 {
5904 _log.error("Error while restoring Pet Control Item ", e);
5905 }
5906
5907 try
5908 {
5909 String var = player.getVar("isPvPevents");
5910 if (var != null)
5911 {
5912 player.unsetVar("isPvPevents");
5913 }
5914 }
5915 catch (RuntimeException e)
5916 {
5917 _log.error("Error while restoring some strange thing ", e);
5918 }
5919
5920 try (PreparedStatement statement3 = con.prepareStatement("SELECT obj_Id, char_name FROM characters WHERE account_name=? AND obj_Id!=?"))
5921 {
5922 statement3.setString(1, player._login);
5923 statement3.setInt(2, objectId);
5924 try (ResultSet rset3 = statement3.executeQuery())
5925 {
5926 while (rset3.next())
5927 {
5928 final Integer charId = rset3.getInt("obj_Id");
5929 final String charName = rset3.getString("char_name");
5930 player._chars.put(charId, charName);
5931 }
5932 }
5933 }
5934
5935 // if (!player.isGM())
5936 {
5937 ArrayList<Zone> zones = new ArrayList<>();
5938
5939 World.getZones(zones, player.getLoc(), player.getReflection());
5940
5941 if (!zones.isEmpty())
5942 {
5943 for (Zone zone : zones)
5944 {
5945 if (zone.getType() == ZoneType.no_restart)
5946 {
5947 if (((System.currentTimeMillis() / 1000L) - player.getLastAccess()) > zone.getRestartTime())
5948 {
5949 player.sendMessage(new CustomMessage("l2ro.gameserver.clientpackets.EnterWorld.TeleportedReasonNoRestart", player));
5950 player.setLoc(TeleportUtils.getRestartLocation(player, RestartType.TO_VILLAGE));
5951 }
5952 }
5953 else if (zone.getType() == ZoneType.SIEGE)
5954 {
5955 SiegeEvent<?, ?> siegeEvent = player.getEvent(SiegeEvent.class);
5956 if (siegeEvent != null)
5957 {
5958 player.setLoc(siegeEvent.getEnterLoc(player));
5959 }
5960 else
5961 {
5962 Residence r = ResidenceHolder.getInstance().getResidence(zone.getParams().getInteger("residence"));
5963 player.setLoc(r.getNotOwnerRestartPoint(player));
5964 }
5965 }
5966 }
5967 }
5968
5969 if (DimensionalRiftManager.getInstance().checkIfInRiftZone(player.getLoc(), false))
5970 {
5971 player.setLoc(DimensionalRiftManager.getInstance().getRoom(0, 0).getTeleportCoords());
5972 }
5973 }
5974
5975 player.restoreBlockList(con);
5976 player._macroses.restore(con);
5977
5978 player.refreshExpertisePenalty();
5979 player.refreshOverloaded();
5980
5981 player._warehouse.restore();
5982 player._freight.restore();
5983
5984 player.restoreTradeList();
5985 if (player.getVar("storemode") != null)
5986 {
5987 player.setPrivateStoreType(Integer.parseInt(player.getVar("storemode")));
5988 player._isSitting = true;
5989
5990 if (Config.AUCTION_PRIVATE_STORE_AUTO_ADDED)
5991 {
5992 if (player._privatestore == STORE_PRIVATE_SELL)
5993 {
5994 if (player.getVar("offline") != null)
5995 {
5996 AuctionManager.getInstance().removePlayerStores(player);
5997 }
5998 for (TradeItem item : player._sellList)
5999 {
6000 ItemInstance itemToSell = player._inventory.getItemByItemId(item.getItemId());
6001 Auction a = AuctionManager.getInstance().addNewStore(player, itemToSell, item.getOwnersPrice(), item.getCount());
6002 item.setAuctionId(a.getAuctionId());
6003 }
6004 }
6005 }
6006 }
6007
6008 try
6009 {
6010 String var = player.getVar("FightClubRate");
6011 if (var != null)
6012 {
6013 RestoreFightClub(player);
6014 }
6015 }
6016 catch (RuntimeException e)
6017 {
6018 _log.error("Error while restoring FightClubRate", e);
6019 }
6020
6021 try
6022 {
6023 String var = player.getVar("EnItemOlyRec");
6024 if (Config.OLY_ENCH_LIMIT_ENABLE && (var != null))
6025 {
6026 FixEnchantOlympiad.restoreEnchantItemsOly(player);
6027 }
6028 }
6029 catch (RuntimeException e)
6030 {
6031 _log.error("Error while restoring EnItemOlyRec", e);
6032 }
6033 player.updateKetraVarka();
6034 player.updateRam();
6035 player.checkRecom();
6036 if (player.isCursedWeaponEquipped())
6037 {
6038 player.restoreCursedWeapon();
6039 }
6040
6041 // player.getCounters().load();
6042
6043 if (Config.ENABLE_ACHIEVEMENTS)
6044 player.loadAchivements();
6045
6046 // Synerge - Get dinamically characters values getting names from the ranking
6047// for (Ranking top : Ranking.values())
6048// {
6049// if (top.getDbLocation().equalsIgnoreCase("characters"))
6050// {
6051// player.getStats().setPlayerStats(top, rset.getLong(top.getDbName()));
6052// }
6053// }
6054 }
6055 }
6056 catch (IllegalArgumentException | SQLException e)
6057 {
6058 _log.error("Could not restore char data! ", e);
6059 }
6060
6061 // Synerge - Now we must get all the stats from the alternative table, using the ranking values
6062// try (Connection conEl = DatabaseFactory.getInstance().getConnection();
6063// PreparedStatement statementEl = conEl.prepareStatement("SELECT variable,value FROM character_stats WHERE charId=?"))
6064// {
6065// statementEl.setInt(1, objectId);
6066// try (ResultSet rsetEl = statementEl.executeQuery())
6067// {
6068// while (rsetEl.next())
6069// {
6070// // Obtengo dinamicamente cada ranking perteneciente a esta tabla con su valor correspondiente
6071// for (Ranking top : Ranking.values())
6072// {
6073// if (player != null && top.getDbName().equalsIgnoreCase(rsetEl.getString("variable")) && top.getDbLocation().equalsIgnoreCase("character_stats"))
6074// {
6075// player.getStats().setPlayerStats(top, rsetEl.getLong("value"));
6076// }
6077// }
6078// }
6079// }
6080// }
6081// catch (Exception e)
6082// {
6083// _log.error("Failed loading character stats", e);
6084// }
6085 return player;
6086 }
6087
6088 private void loadPremiumItemList(Connection con)
6089 {
6090 try (PreparedStatement statement = con.prepareStatement("SELECT itemNum, itemId, itemCount, itemSender FROM character_premium_items WHERE charId=?"))
6091 {
6092 statement.setInt(1, getObjectId());
6093
6094 try (ResultSet rs = statement.executeQuery())
6095 {
6096 while (rs.next())
6097 {
6098 int itemNum = rs.getInt("itemNum");
6099 int itemId = rs.getInt("itemId");
6100 long itemCount = rs.getLong("itemCount");
6101 String itemSender = rs.getString("itemSender");
6102 PremiumItem item = new PremiumItem(itemId, itemCount, itemSender);
6103 _premiumItems.put(itemNum, item);
6104 }
6105 }
6106 }
6107 catch (SQLException e)
6108 {
6109 _log.error("Error while loading Premium Item List for Id "+getObjectId(), e);
6110 }
6111 }
6112
6113 public void updatePremiumItem(int itemNum, long newcount)
6114 {
6115 try (Connection con = DatabaseFactory.getInstance().getConnection();
6116 PreparedStatement statement = con.prepareStatement("UPDATE character_premium_items SET itemCount=? WHERE charId=? AND itemNum=?"))
6117 {
6118 statement.setLong(1, newcount);
6119 statement.setInt(2, getObjectId());
6120 statement.setInt(3, itemNum);
6121 statement.execute();
6122 }
6123 catch (SQLException e)
6124 {
6125 _log.error("Error while updating Premium Items", e);
6126 }
6127 }
6128
6129 public void deletePremiumItem(int itemNum)
6130 {
6131 try (Connection con = DatabaseFactory.getInstance().getConnection();
6132 PreparedStatement statement = con.prepareStatement("DELETE FROM character_premium_items WHERE charId=? AND itemNum=?"))
6133 {
6134 statement.setInt(1, getObjectId());
6135 statement.setInt(2, itemNum);
6136 statement.execute();
6137 }
6138 catch (SQLException e)
6139 {
6140 _log.error("Error while deleting Premium Item", e);
6141 }
6142 }
6143
6144 public Map<Integer, PremiumItem> getPremiumItemList()
6145 {
6146 return _premiumItems;
6147 }
6148
6149 /**
6150 * Update L2Player stats in the characters table of the database.
6151 * @param fast
6152 */
6153 public void store(boolean fast)
6154 {
6155 if (!_storeLock.tryLock())
6156 {
6157 return;
6158 }
6159
6160 try
6161 {
6162 try (Connection con = DatabaseFactory.getInstance().getConnection();
6163 PreparedStatement statement = con.prepareStatement(//
6164 "UPDATE characters SET face=?,hairStyle=?,hairColor=?,x=?,y=?,z=?" + //
6165 ",karma=?,pvpkills=?,pkkills=?,rec_have=?,rec_left=?,rec_bonus_time=?,hunt_points=?,hunt_time=?,clanid=?,deletetime=?," + //
6166 "title=?,accesslevel=?,online=?,leaveclan=?,deleteclan=?,nochannel=?," + //
6167 "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");)
6168 {
6169 statement.setInt(1, getFace());
6170 statement.setInt(2, getHairStyle());
6171 statement.setInt(3, getHairColor());
6172 if (_stablePoint == null)
6173 {
6174 statement.setInt(4, getX());
6175 statement.setInt(5, getY());
6176 statement.setInt(6, getZ());
6177 }
6178 else
6179 {
6180 statement.setInt(4, _stablePoint.x);
6181 statement.setInt(5, _stablePoint.y);
6182 statement.setInt(6, _stablePoint.z);
6183 }
6184 statement.setInt(7, getKarma());
6185 statement.setInt(8, getPvpKills());
6186 statement.setInt(9, getPkKills());
6187 statement.setInt(10, getRecomHave());
6188 statement.setInt(11, getRecomLeft());
6189 statement.setInt(12, getRecomBonusTime());
6190 statement.setInt(13, getNevitSystem().getPoints());
6191 statement.setInt(14, getNevitSystem().getTime());
6192 statement.setInt(15, getClanId());
6193 statement.setInt(16, getDeleteTimer());
6194 statement.setString(17, _title);
6195 statement.setInt(18, _accessLevel);
6196 statement.setInt(19, (isOnline() && !isInOfflineMode()) || (isInOfflineMode() && Config.SHOW_OFFLINE_MODE_IN_ONLINE) ? 1 : 0);
6197 statement.setLong(20, getLeaveClanTime() / 1000L);
6198 statement.setLong(21, getDeleteClanTime() / 1000L);
6199 statement.setLong(22, _NoChannel > 0 ? getNoChannelRemained() / 1000 : _NoChannel);
6200 statement.setInt(23, (int)(getOnlineTime() / 1000L));
6201 statement.setInt(24, getPledgeType());
6202 statement.setInt(25, getPowerGrade());
6203 statement.setInt(26, getLvlJoinedAcademy());
6204 statement.setInt(27, getApprentice());
6205 statement.setBytes(28, getKeyBindings());
6206 statement.setInt(29, getPcBangPoints());
6207 statement.setString(30, getName());
6208 statement.setInt(31, (int) getVitality());
6209 statement.setInt(32, getFame());
6210 statement.setInt(33, bookmarks.getCapacity());
6211 statement.setString(34, getHwidLock());
6212 statement.setInt(35, getRaidKills());
6213 statement.setInt(36, getSoloInstance());
6214 statement.setInt(37, getPartyInstance());
6215 statement.setInt(38, getObjectId());
6216
6217 statement.executeUpdate();
6218 if (Config.RATE_DROP_ADENA < 20)
6219 {
6220 GameStats.increaseUpdatePlayerBase();
6221 }
6222
6223 if (!fast)
6224 {
6225 EffectsDAO.getInstance().insert(this);
6226 CharacterGroupReuseDAO.getInstance().insert(this);
6227 storeDisableSkills();
6228 storeBlockList();
6229 }
6230
6231 storeCharSubClasses();
6232 bookmarks.store();
6233
6234 //getCounters().save();
6235
6236 if (Config.ENABLE_ACHIEVEMENTS)
6237 saveAchivements();
6238
6239 // Synerge - When closing character, we must add the online value to the stats for it to be saved
6240// addPlayerStats(Ranking.STAT_TOP_ONLINE, getOnlineTime());
6241
6242 // Synerge - The same for the longest online time, we must calculate it on exit
6243// addPlayerStats(Ranking.STAT_TOP_LONGEST_ONLINE_TIME, Math.max(Math.round((System.currentTimeMillis() - _onlineBeginTime) / 60000), getStats().getPlayerStats(Ranking.STAT_TOP_LONGEST_ONLINE_TIME)));
6244
6245 // Synerge - We create a dynamic query to update the stats based on the ranking values that use the character_stats table
6246// try (PreparedStatement statementEl = con.prepareStatement("REPLACE INTO character_stats VALUES (?, ?, ?)"))
6247// {
6248// // Agrego dinamicamente cada ranking perteneciente a esta tabla con su valor correspondiente, para lograr un update totalmente dinamico
6249// for (Ranking top : Ranking.values())
6250// {
6251// if (top.getDbLocation().equalsIgnoreCase("character_stats"))
6252// {
6253// // Solo lo salvamos si el cantidad es mayor a 0, sino creamos celdas en la db al pedo, el default es 0
6254// if (getStats().getPlayerStats(top) > 0)
6255// {
6256// statementEl.setInt(1, getObjectId());
6257// statementEl.setString(2, top.getDbName());
6258// statementEl.setLong(3, getStats().getPlayerStats(top));
6259// statementEl.execute();
6260// }
6261// }
6262// }
6263// }
6264 }
6265 catch (SQLException e)
6266 {
6267 _log.error("Could not store char data: " + this + '!', e);
6268 }
6269 }
6270 finally
6271 {
6272 _storeLock.unlock();
6273 }
6274 }
6275
6276 private int raids;
6277
6278 public void updateRaidKills()
6279 {
6280 this.raids++;
6281 }
6282
6283 public int getRaidKills()
6284 {
6285 return raids;
6286 }
6287 /**
6288 * 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.
6289 * @param newSkill
6290 * @param store
6291 * @return The L2Skill replaced or null if just added a new L2Skill
6292 */
6293 public Skill addSkill(final Skill newSkill, final boolean store)
6294 {
6295 if (newSkill == null)
6296 {
6297 return null;
6298 }
6299
6300 // 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
6301 if (getKnownSkill(newSkill.getId()) != null)
6302 {
6303 disableSkillByNewLvl(SkillTable.getInstance().getInfo(newSkill.getId(), getKnownSkill(newSkill.getId()).getLevel()).hashCode(),
6304 SkillTable.getInstance().getInfo(newSkill.getId(), newSkill.getLevel()).hashCode());
6305 }
6306 // Add a skill to the L2Player _skills and its Func objects to the calculator set of the L2Player
6307 Skill oldSkill = super.addSkill(newSkill);
6308
6309 if (newSkill.equals(oldSkill))
6310 {
6311 return oldSkill;
6312 }
6313
6314 // Add or update a L2Player skill in the character_skills table of the database
6315 if (store)
6316 {
6317 storeSkill(newSkill, oldSkill);
6318 }
6319
6320 return oldSkill;
6321 }
6322
6323 public Skill removeSkill(Skill skill, boolean fromDB)
6324 {
6325 if (skill == null)
6326 {
6327 return null;
6328 }
6329 return removeSkill(skill.getId(), fromDB);
6330 }
6331
6332 /**
6333 * 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.
6334 * @param id
6335 * @param fromDB
6336 * @return The L2Skill removed
6337 */
6338 public Skill removeSkill(int id, boolean fromDB)
6339 {
6340 // Remove a skill from the L2Character and its Func objects from calculator set of the L2Character
6341 Skill oldSkill = super.removeSkillById(id);
6342
6343 if (!fromDB)
6344 {
6345 return oldSkill;
6346 }
6347
6348 if (oldSkill != null)
6349 {
6350 try (Connection con = DatabaseFactory.getInstance().getConnection();
6351 PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills WHERE skill_id=? AND char_obj_id=? AND class_index=?"))
6352 {
6353 // Remove or update a L2Player skill from the character_skills table of the database
6354 statement.setInt(1, oldSkill.getId());
6355 statement.setInt(2, getObjectId());
6356 statement.setInt(3, getActiveClassId());
6357 statement.execute();
6358 }
6359 catch (final Exception e)
6360 {
6361 _log.error("Could not delete skill!", e);
6362 }
6363 }
6364
6365 return oldSkill;
6366 }
6367
6368 /**
6369 * Add or update a L2Player skill in the character_skills table of the database.
6370 * @param newSkill
6371 * @param oldSkill
6372 */
6373 private void storeSkill(final Skill newSkill, final Skill oldSkill)
6374 {
6375 if (newSkill == null)
6376 {
6377 _log.warn("could not store new skill. its NULL");
6378 return;
6379 }
6380
6381 try (Connection con = DatabaseFactory.getInstance().getConnection();
6382 PreparedStatement statement = con.prepareStatement("REPLACE INTO character_skills (char_obj_id,skill_id,skill_level,class_index) values(?,?,?,?)"))
6383 {
6384 statement.setInt(1, getObjectId());
6385 statement.setInt(2, newSkill.getId());
6386 statement.setInt(3, newSkill.getLevel());
6387 statement.setInt(4, getActiveClassId());
6388 statement.execute();
6389 }
6390 catch (SQLException e)
6391 {
6392 _log.error("Error could not store skills!", e);
6393 }
6394 }
6395
6396 /**
6397 * Retrieve from the database all skills of this L2Player and add them to _skills.
6398 */
6399 private void restoreSkills()
6400 {
6401 PreparedStatement statement = null;
6402 try (Connection con = DatabaseFactory.getInstance().getConnection())
6403 {
6404 // Retrieve all skills of this L2Player from the database
6405 // Send the SQL query : SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? to the database
6406 if (Config.ALT_ENABLE_MULTI_PROFA)
6407 {
6408 statement = con.prepareStatement("SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=?");
6409 statement.setInt(1, getObjectId());
6410 }
6411 else
6412 {
6413 statement = con.prepareStatement("SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? AND class_index=?");
6414 statement.setInt(1, getObjectId());
6415 statement.setInt(2, getActiveClassId());
6416 }
6417
6418 try (ResultSet rset = statement.executeQuery())
6419 {
6420 // Go though the recordset of this SQL query
6421 while (rset.next())
6422 {
6423 final int id = rset.getInt("skill_id");
6424 final int level = rset.getInt("skill_level");
6425
6426 // Create a L2Skill object for each record
6427 final Skill skill = SkillTable.getInstance().getInfo(id, level);
6428
6429 if (skill == null)
6430 {
6431 continue;
6432 }
6433
6434 // Remove skill if not possible
6435 if (!isGM() && !SkillAcquireHolder.getInstance().isSkillPossible(this, skill))
6436 {
6437 // int ReturnSP = SkillTreeTable.getInstance().getSkillCost(this, skill);
6438 // if (ReturnSP == Integer.MAX_VALUE || ReturnSP < 0)
6439 // ReturnSP = 0;
6440 removeSkill(skill, true);
6441 removeSkillFromShortCut(skill.getId());
6442 // if (ReturnSP > 0)
6443 // setSp(getSp() + ReturnSP);
6444 continue;
6445 }
6446
6447 super.addSkill(skill);
6448 }
6449 }
6450
6451 // Restore noble skills
6452 if (isNoble())
6453 {
6454 updateNobleSkills();
6455 }
6456
6457 // Restore Hero skills at main class only
6458 if (_hero && (getBaseClassId() == getActiveClassId()))
6459 {
6460 Hero.addSkills(this);
6461 }
6462
6463 // Restore clan skills
6464 if (_clan != null)
6465 {
6466 _clan.addSkillsQuietly(this);
6467
6468 // Restore clan leader siege skills
6469 if ((_clan.getLeaderId() == getObjectId()) && (_clan.getLevel() >= 5))
6470 {
6471 SiegeUtils.addSiegeSkills(this);
6472 }
6473 }
6474
6475 // Give dwarven craft skill
6476 if (((getActiveClassId() >= 53) && (getActiveClassId() <= 57)) || (getActiveClassId() == 117) || (getActiveClassId() == 118))
6477 {
6478 super.addSkill(SkillTable.getInstance().getInfo(1321, 1));
6479 }
6480
6481 super.addSkill(SkillTable.getInstance().getInfo(1322, 1));
6482
6483 if (Config.UNSTUCK_SKILL && (getSkillLevel(1050) < 0))
6484 {
6485 super.addSkill(SkillTable.getInstance().getInfo(2099, 1));
6486 }
6487 }
6488 catch (SQLException e)
6489 {
6490 _log.warn("Could not restore skills for player objId: " + getObjectId(), e);
6491 }
6492 finally
6493 {
6494 DbUtils.closeQuietly(statement);
6495 }
6496 }
6497
6498 public void storeDisableSkills()
6499 {
6500 try (Connection con = DatabaseFactory.getInstance().getConnection();
6501 Statement statement = con.createStatement())
6502 {
6503 statement.executeUpdate("DELETE FROM character_skills_save WHERE char_obj_id = " + getObjectId() + " AND class_index=" + getActiveClassId() + " AND `end_time` < " + System.currentTimeMillis());
6504
6505 if (_skillReuses.isEmpty())
6506 {
6507 return;
6508 }
6509
6510 SqlBatch b = new SqlBatch("REPLACE INTO `character_skills_save` (`char_obj_id`,`skill_id`,`skill_level`,`class_index`,`end_time`,`reuse_delay_org`) VALUES");
6511 synchronized (_skillReuses)
6512 {
6513 StringBuilder sb;
6514 for (TimeStamp timeStamp : _skillReuses.values())
6515 {
6516 if (timeStamp.hasNotPassed())
6517 {
6518 sb = new StringBuilder("(");
6519 sb.append(getObjectId()).append(",");
6520 sb.append(timeStamp.getId()).append(",");
6521 sb.append(timeStamp.getLevel()).append(",");
6522 sb.append(getActiveClassId()).append(",");
6523 sb.append(timeStamp.getEndTime()).append(",");
6524 sb.append(timeStamp.getReuseBasic()).append(")");
6525 b.write(sb.toString());
6526 }
6527 }
6528 }
6529 if (!b.isEmpty())
6530 {
6531 statement.executeUpdate(b.close());
6532 }
6533 }
6534 catch (final Exception e)
6535 {
6536 _log.warn("Could not store disable skills data: " + e);
6537 }
6538 }
6539
6540 public void restoreDisableSkills()
6541 {
6542 _skillReuses.clear();
6543
6544 try (Connection con = DatabaseFactory.getInstance().getConnection();
6545 Statement statement = con.createStatement();)
6546 {
6547
6548 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()))
6549 {
6550 while (rset.next())
6551 {
6552 int skillId = rset.getInt("skill_id");
6553 int skillLevel = rset.getInt("skill_level");
6554 long endTime = rset.getLong("end_time");
6555 long rDelayOrg = rset.getLong("reuse_delay_org");
6556 long curTime = System.currentTimeMillis();
6557
6558 Skill skill = SkillTable.getInstance().getInfo(skillId, skillLevel);
6559
6560 if ((skill != null) && ((endTime - curTime) > 500))
6561 {
6562 _skillReuses.put(skill.hashCode(), new TimeStamp(skill, endTime, rDelayOrg));
6563 }
6564 }
6565 }
6566
6567 statement.executeUpdate("DELETE FROM character_skills_save WHERE char_obj_id = " + getObjectId() + " AND class_index=" + getActiveClassId() + " AND `end_time` < " + System.currentTimeMillis());
6568 }
6569 catch (Exception e)
6570 {
6571 _log.error("Could not restore active skills data!", e);
6572 }
6573 }
6574
6575 /**
6576 * Retrieve from the database all Henna of this L2Player, add them to _henna and calculate stats of the L2Player.<BR>
6577 * <BR>
6578 */
6579 private void restoreHenna()
6580 {
6581 try (Connection con = DatabaseFactory.getInstance().getConnection();
6582 PreparedStatement statement = con.prepareStatement("select slot, symbol_id from character_hennas where char_obj_id=? AND class_index=?"))
6583 {
6584 statement.setInt(1, getObjectId());
6585 statement.setInt(2, getActiveClassId());
6586
6587 try (ResultSet rset = statement.executeQuery())
6588 {
6589 for (int i = 0; i < 3; i++)
6590 {
6591 _henna[i] = null;
6592 }
6593
6594 while (rset.next())
6595 {
6596 final int slot = rset.getInt("slot");
6597 if ((slot < 1) || (slot > 3))
6598 {
6599 continue;
6600 }
6601
6602 final int symbol_id = rset.getInt("symbol_id");
6603
6604 if (symbol_id != 0)
6605 {
6606 final Henna tpl = HennaHolder.getInstance().getHenna(symbol_id);
6607 if (tpl != null)
6608 {
6609 _henna[slot - 1] = tpl;
6610 }
6611 }
6612 }
6613 }
6614 }
6615 catch (final Exception e)
6616 {
6617 _log.warn("could not restore henna: " + e);
6618 }
6619
6620 // Calculate Henna modifiers of this L2Player
6621 recalcHennaStats();
6622
6623 }
6624
6625 public int getHennaEmptySlots()
6626 {
6627 int totalSlots = 1 + getClassId().level();
6628 for (int i = 0; i < 3; i++)
6629 {
6630 if (_henna[i] != null)
6631 {
6632 totalSlots--;
6633 }
6634 }
6635
6636 if (totalSlots <= 0)
6637 {
6638 return 0;
6639 }
6640
6641 return totalSlots;
6642
6643 }
6644
6645 /**
6646 * 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>
6647 * <BR>
6648 * @param slot
6649 * @return
6650 */
6651 public boolean removeHenna(int slot)
6652 {
6653 if ((slot < 1) || (slot > 3))
6654 {
6655 return false;
6656 }
6657
6658 slot--;
6659
6660 if (_henna[slot] == null)
6661 {
6662 return false;
6663 }
6664
6665 final Henna henna = _henna[slot];
6666 final int dyeID = henna.getDyeId();
6667
6668 _henna[slot] = null;
6669
6670 try (Connection con = DatabaseFactory.getInstance().getConnection();
6671 PreparedStatement statement = con.prepareStatement("DELETE FROM character_hennas where char_obj_id=? and slot=? and class_index=?"))
6672 {
6673 statement.setInt(1, getObjectId());
6674 statement.setInt(2, slot + 1);
6675 statement.setInt(3, getActiveClassId());
6676 statement.execute();
6677 }
6678 catch (final Exception e)
6679 {
6680 _log.warn("could not remove char henna: " + e, e);
6681 }
6682
6683 // Calculate Henna modifiers of this L2Player
6684 recalcHennaStats();
6685
6686 // Send Server->Client HennaInfo packet to this L2Player
6687 sendPacket(new HennaInfo(this));
6688 // Send Server->Client UserInfo packet to this L2Player
6689 sendUserInfo(true);
6690
6691 // Add the recovered dyes to the player's inventory and notify them.
6692 ItemFunctions.addItem(this, dyeID, henna.getDrawCount() / 2, true, "removeHenna");
6693
6694 return true;
6695 }
6696
6697 /**
6698 * 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>
6699 * @param henna
6700 * @return
6701 */
6702 public boolean addHenna(Henna henna)
6703 {
6704 if (getHennaEmptySlots() == 0)
6705 {
6706 sendPacket(SystemMsg.NO_SLOT_EXISTS_TO_DRAW_THE_SYMBOL);
6707 return false;
6708 }
6709
6710 // int slot = 0;
6711 for (int i = 0; i < 3; i++)
6712 {
6713 if (_henna[i] == null)
6714 {
6715 _henna[i] = henna;
6716
6717 // Calculate Henna modifiers of this L2Player
6718 recalcHennaStats();
6719
6720 try (Connection con = DatabaseFactory.getInstance().getConnection();
6721 PreparedStatement statement = con.prepareStatement("INSERT INTO `character_hennas` (char_obj_id, symbol_id, slot, class_index) VALUES (?,?,?,?)"))
6722 {
6723 statement.setInt(1, getObjectId());
6724 statement.setInt(2, henna.getSymbolId());
6725 statement.setInt(3, i + 1);
6726 statement.setInt(4, getActiveClassId());
6727 statement.execute();
6728 }
6729 catch (Exception e)
6730 {
6731 _log.warn("could not save char henna: " + e);
6732 }
6733
6734 sendPacket(new HennaInfo(this));
6735 sendUserInfo(true);
6736
6737 return true;
6738 }
6739 }
6740
6741 return false;
6742 }
6743
6744 /**
6745 * Calculate Henna modifiers of this L2Player.
6746 */
6747 private void recalcHennaStats()
6748 {
6749 _hennaINT = 0;
6750 _hennaSTR = 0;
6751 _hennaCON = 0;
6752 _hennaMEN = 0;
6753 _hennaWIT = 0;
6754 _hennaDEX = 0;
6755
6756 for (int i = 0; i < 3; i++)
6757 {
6758 Henna henna = _henna[i];
6759 if (henna == null)
6760 {
6761 continue;
6762 }
6763 if (!henna.isForThisClass(this))
6764 {
6765 continue;
6766 }
6767
6768 _hennaINT += henna.getStatINT();
6769 _hennaSTR += henna.getStatSTR();
6770 _hennaMEN += henna.getStatMEN();
6771 _hennaCON += henna.getStatCON();
6772 _hennaWIT += henna.getStatWIT();
6773 _hennaDEX += henna.getStatDEX();
6774 }
6775
6776 if (_hennaINT > Config.HENNA_STATS)
6777 {
6778 _hennaINT = Config.HENNA_STATS;
6779 }
6780 if (_hennaSTR > Config.HENNA_STATS)
6781 {
6782 _hennaSTR = Config.HENNA_STATS;
6783 }
6784 if (_hennaMEN > Config.HENNA_STATS)
6785 {
6786 _hennaMEN = Config.HENNA_STATS;
6787 }
6788 if (_hennaCON > Config.HENNA_STATS)
6789 {
6790 _hennaCON = Config.HENNA_STATS;
6791 }
6792 if (_hennaWIT > Config.HENNA_STATS)
6793 {
6794 _hennaWIT = Config.HENNA_STATS;
6795 }
6796 if (_hennaDEX > Config.HENNA_STATS)
6797 {
6798 _hennaDEX = Config.HENNA_STATS;
6799 }
6800 }
6801
6802 /**
6803 * @param slot
6804 * @return the Henna of this L2Player corresponding to the selected slot.<BR>
6805 * <BR>
6806 */
6807 public Henna getHenna(final int slot)
6808 {
6809 if ((slot < 1) || (slot > 3))
6810 {
6811 return null;
6812 }
6813 return _henna[slot - 1];
6814 }
6815
6816 public int getHennaStatINT()
6817 {
6818 return _hennaINT;
6819 }
6820
6821 public int getHennaStatSTR()
6822 {
6823 return _hennaSTR;
6824 }
6825
6826 public int getHennaStatCON()
6827 {
6828 return _hennaCON;
6829 }
6830
6831 public int getHennaStatMEN()
6832 {
6833 return _hennaMEN;
6834 }
6835
6836 public int getHennaStatWIT()
6837 {
6838 return _hennaWIT;
6839 }
6840
6841 public int getHennaStatDEX()
6842 {
6843 return _hennaDEX;
6844 }
6845
6846 @Override
6847 public boolean consumeItem(int itemConsumeId, long itemCount)
6848 {
6849 if (getInventory().destroyItemByItemId(itemConsumeId, itemCount, "Consume"))
6850 {
6851 sendPacket(SystemMessage2.removeItems(itemConsumeId, itemCount));
6852 return true;
6853 }
6854 return false;
6855 }
6856
6857 @Override
6858 public boolean consumeItemMp(int itemId, int mp)
6859 {
6860 for (ItemInstance item : getInventory().getPaperdollItems())
6861 {
6862 if ((item != null) && (item.getItemId() == itemId))
6863 {
6864 final int newMp = item.getLifeTime() - mp;
6865 if (newMp >= 0)
6866 {
6867 item.setLifeTime(newMp);
6868 sendPacket(new InventoryUpdate().addModifiedItem(item));
6869 return true;
6870 }
6871 break;
6872 }
6873 }
6874 return false;
6875 }
6876
6877 /**
6878 * @return True if the L2Player is a Mage.<BR>
6879 * <BR>
6880 */
6881 @Override
6882 public boolean isMageClass()
6883 {
6884 return _template.baseMAtk > 3;
6885 }
6886
6887 public boolean isMounted()
6888 {
6889 return _mountNpcId > 0;
6890 }
6891
6892 public final boolean isRiding()
6893 {
6894 return _riding;
6895 }
6896
6897 public final void setRiding(boolean mode)
6898 {
6899 _riding = mode;
6900 }
6901
6902 public boolean checkLandingState()
6903 {
6904 if (isInZone(ZoneType.no_landing))
6905 {
6906 return false;
6907 }
6908
6909 SiegeEvent<?, ?> siege = getEvent(SiegeEvent.class);
6910 if (siege != null)
6911 {
6912 Residence unit = siege.getResidence();
6913 if ((unit != null) && (getClan() != null) && isClanLeader() && ((getClan().getCastle() == unit.getId()) || (getClan().getHasFortress() == unit.getId())))
6914 {
6915 return true;
6916 }
6917 return false;
6918 }
6919
6920 return true;
6921 }
6922
6923 public void dismount()
6924 {
6925 setMount(0, 0, 0);
6926 }
6927
6928 public void setMount(int npcId, int obj_id, int level)
6929 {
6930 if (isCursedWeaponEquipped())
6931 {
6932 return;
6933 }
6934
6935 switch (npcId)
6936 {
6937 case 0: // Dismount
6938 setFlying(false);
6939 setRiding(false);
6940 if (getTransformation() > 0)
6941 {
6942 setTransformation(0);
6943 }
6944 removeSkillById(Skill.SKILL_STRIDER_ASSAULT);
6945 removeSkillById(Skill.SKILL_WYVERN_BREATH);
6946 getEffectList().stopEffect(Skill.SKILL_HINDER_STRIDER);
6947 break;
6948 case PetDataTable.STRIDER_WIND_ID:
6949 case PetDataTable.STRIDER_STAR_ID:
6950 case PetDataTable.STRIDER_TWILIGHT_ID:
6951 case PetDataTable.RED_STRIDER_WIND_ID:
6952 case PetDataTable.RED_STRIDER_STAR_ID:
6953 case PetDataTable.RED_STRIDER_TWILIGHT_ID:
6954 case PetDataTable.GUARDIANS_STRIDER_ID:
6955 setRiding(true);
6956 if (isNoble())
6957 {
6958 addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_STRIDER_ASSAULT, 1), false);
6959 }
6960 break;
6961 case PetDataTable.WYVERN_ID:
6962 setFlying(true);
6963 setLoc(getLoc().changeZ(32));
6964 addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_WYVERN_BREATH, 1), false);
6965 break;
6966 case PetDataTable.WGREAT_WOLF_ID:
6967 case PetDataTable.FENRIR_WOLF_ID:
6968 case PetDataTable.WFENRIR_WOLF_ID:
6969 setRiding(true);
6970 break;
6971 }
6972
6973 if (npcId > 0)
6974 {
6975 unEquipWeapon();
6976 }
6977
6978 _mountNpcId = npcId;
6979 _mountObjId = obj_id;
6980 _mountLevel = level;
6981
6982 broadcastUserInfo(true);
6983 broadcastPacket(new Ride(this));
6984 broadcastUserInfo(true);
6985
6986 sendPacket(new SkillList(this));
6987 }
6988
6989 public void unEquipWeapon()
6990 {
6991 ItemInstance wpn = getSecondaryWeaponInstance();
6992 if (wpn != null)
6993 {
6994 sendDisarmMessage(wpn);
6995 getInventory().unEquipItem(wpn);
6996 }
6997
6998 wpn = getActiveWeaponInstance();
6999 if (wpn != null)
7000 {
7001 sendDisarmMessage(wpn);
7002 getInventory().unEquipItem(wpn);
7003 }
7004
7005 abortAttack(true, true);
7006 abortCast(true, true);
7007 }
7008
7009 @Override
7010 public int getSpeed(int baseSpeed)
7011 {
7012 if (isMounted())
7013 {
7014 PetData petData = PetDataTable.getInstance().getInfo(_mountNpcId, _mountLevel);
7015 int speed = 187;
7016 if (petData != null)
7017 {
7018 speed = petData.getSpeed();
7019 }
7020 double mod = 1.;
7021 int level = getLevel();
7022 if ((_mountLevel > level) && ((level - _mountLevel) > 10))
7023 {
7024 mod = 0.5;
7025 }
7026 baseSpeed = (int) (mod * speed);
7027 }
7028 return super.getSpeed(baseSpeed);
7029 }
7030
7031 private int _mountNpcId;
7032 private int _mountObjId;
7033 private int _mountLevel;
7034
7035 public int getMountNpcId()
7036 {
7037 return _mountNpcId;
7038 }
7039
7040 public int getMountObjId()
7041 {
7042 return _mountObjId;
7043 }
7044
7045 public int getMountLevel()
7046 {
7047 return _mountLevel;
7048 }
7049
7050 public void sendDisarmMessage(ItemInstance wpn)
7051 {
7052 if (wpn.getEnchantLevel() > 0)
7053 {
7054 SystemMessage sm = new SystemMessage(SystemMessage.EQUIPMENT_OF__S1_S2_HAS_BEEN_REMOVED);
7055 sm.addNumber(wpn.getEnchantLevel());
7056 sm.addItemName(wpn.getItemId());
7057 sendPacket(sm);
7058 }
7059 else
7060 {
7061 SystemMessage sm = new SystemMessage(SystemMessage.S1__HAS_BEEN_DISARMED);
7062 sm.addItemName(wpn.getItemId());
7063 sendPacket(sm);
7064 }
7065 }
7066
7067 public void setUsingWarehouseType(final WarehouseType type)
7068 {
7069 _usingWHType = type;
7070 }
7071
7072 public WarehouseType getUsingWarehouseType()
7073 {
7074 return _usingWHType;
7075 }
7076
7077 public Warehouse getWithdrawWarehouse()
7078 {
7079 return _withdrawWarehouse;
7080 }
7081
7082 public void setWithdrawWarehouse(Warehouse withdrawWarehouse)
7083 {
7084 _withdrawWarehouse = withdrawWarehouse;
7085 }
7086
7087 public Collection<EffectCubic> getCubics()
7088 {
7089 return _cubics == null ? Collections.<EffectCubic> emptyList() : _cubics.values();
7090 }
7091
7092 public void addCubic(EffectCubic cubic)
7093 {
7094 if (_cubics == null)
7095 {
7096 _cubics = new ConcurrentHashMap<>(3);
7097 }
7098 _cubics.put(cubic.getId(), cubic);
7099 }
7100
7101 public void removeCubic(int id)
7102 {
7103 if (_cubics != null)
7104 {
7105 _cubics.remove(id);
7106 }
7107 }
7108
7109 public EffectCubic getCubic(int id)
7110 {
7111 return _cubics == null ? null : _cubics.get(id);
7112 }
7113
7114 @Override
7115 public String toString()
7116 {
7117 return getName() + "[" + getObjectId() + "]";
7118 }
7119
7120 /**
7121 * @return the modifier corresponding to the Enchant Effect of the Active Weapon (Min : 127).<BR>
7122 * <BR>
7123 */
7124 public int getEnchantEffect()
7125 {
7126 final ItemInstance wpn = getActiveWeaponInstance();
7127
7128 if (wpn == null)
7129 {
7130 return 0;
7131 }
7132
7133 return Math.min(127, wpn.getEnchantLevel());
7134 }
7135
7136 /**
7137 * Set the _lastFolkNpc of the L2Player corresponding to the last Folk witch one the player talked.<BR>
7138 * <BR>
7139 * @param npc
7140 */
7141 public void setLastNpc(final NpcInstance npc)
7142 {
7143 if (npc == null)
7144 {
7145 _lastNpc = HardReferences.emptyRef();
7146 }
7147 else
7148 {
7149 _lastNpc = npc.getRef();
7150 }
7151 }
7152
7153 /**
7154 * @return the _lastFolkNpc of the L2Player corresponding to the last Folk witch one the player talked.<BR>
7155 * <BR>
7156 */
7157 public NpcInstance getLastNpc()
7158 {
7159 return _lastNpc.get();
7160 }
7161
7162 public void setMultisell(MultiSellListContainer multisell)
7163 {
7164 _multisell = multisell;
7165 }
7166
7167 public MultiSellListContainer getMultisell()
7168 {
7169 return _multisell;
7170 }
7171
7172 /**
7173 * @return True if L2Player is a participant in the Festival of Darkness.<BR>
7174 * <BR>
7175 */
7176 public boolean isFestivalParticipant()
7177 {
7178 return getReflection() instanceof DarknessFestival;
7179 }
7180
7181 @Override
7182 public boolean unChargeShots(boolean spirit)
7183 {
7184 ItemInstance weapon = getActiveWeaponInstance();
7185 if (weapon == null)
7186 {
7187 return false;
7188 }
7189
7190 if (spirit)
7191 {
7192 weapon.setChargedSpiritshot(ItemInstance.CHARGED_NONE);
7193 }
7194 else
7195 {
7196 weapon.setChargedSoulshot(ItemInstance.CHARGED_NONE);
7197 }
7198
7199 autoShot();
7200 return true;
7201 }
7202
7203 public boolean unChargeFishShot()
7204 {
7205 ItemInstance weapon = getActiveWeaponInstance();
7206 if (weapon == null)
7207 {
7208 return false;
7209 }
7210 weapon.setChargedFishshot(false);
7211 autoShot();
7212 return true;
7213 }
7214
7215 public void autoShot()
7216 {
7217 for (Integer shotId : _activeSoulShots)
7218 {
7219 ItemInstance item = getInventory().getItemByItemId(shotId);
7220 if (item == null)
7221 {
7222 removeAutoSoulShot(shotId);
7223 continue;
7224 }
7225 IItemHandler handler = item.getTemplate().getHandler();
7226 if (handler == null)
7227 {
7228 continue;
7229 }
7230 handler.useItem(this, item, false);
7231 }
7232 }
7233
7234 public boolean getChargedFishShot()
7235 {
7236 ItemInstance weapon = getActiveWeaponInstance();
7237 return (weapon != null) && weapon.getChargedFishshot();
7238 }
7239
7240 @Override
7241 public boolean getChargedSoulShot()
7242 {
7243 ItemInstance weapon = getActiveWeaponInstance();
7244 return (weapon != null) && (weapon.getChargedSoulshot() == ItemInstance.CHARGED_SOULSHOT);
7245 }
7246
7247 @Override
7248 public int getChargedSpiritShot()
7249 {
7250 ItemInstance weapon = getActiveWeaponInstance();
7251 if (weapon == null)
7252 {
7253 return 0;
7254 }
7255 return weapon.getChargedSpiritshot();
7256 }
7257
7258 public void addAutoSoulShot(Integer itemId)
7259 {
7260 _activeSoulShots.add(itemId);
7261 }
7262
7263 public void removeAutoSoulShot(Integer itemId)
7264 {
7265 _activeSoulShots.remove(itemId);
7266 }
7267
7268 public Set<Integer> getAutoSoulShot()
7269 {
7270 return _activeSoulShots;
7271 }
7272
7273 public void setInvisibleType(InvisibleType vis)
7274 {
7275 _invisibleType = vis;
7276 }
7277
7278 @Override
7279 public InvisibleType getInvisibleType()
7280 {
7281 return _invisibleType;
7282 }
7283
7284 public int getClanPrivileges()
7285 {
7286 if (_clan == null)
7287 {
7288 return 0;
7289 }
7290 if (isClanLeader())
7291 {
7292 return Clan.CP_ALL;
7293 }
7294 if ((_powerGrade < 1) || (_powerGrade > 9))
7295 {
7296 return 0;
7297 }
7298 RankPrivs privs = _clan.getRankPrivs(_powerGrade);
7299 if (privs != null)
7300 {
7301 return privs.getPrivs();
7302 }
7303 return 0;
7304 }
7305
7306 public void teleToClosestTown()
7307 {
7308 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_VILLAGE), ReflectionManager.DEFAULT);
7309 }
7310
7311 public void teleToCastle()
7312 {
7313 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_CASTLE), ReflectionManager.DEFAULT);
7314 }
7315
7316 public void teleToFortress()
7317 {
7318 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_FORTRESS), ReflectionManager.DEFAULT);
7319 }
7320
7321 public void teleToClanhall()
7322 {
7323 teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_CLANHALL), ReflectionManager.DEFAULT);
7324 }
7325
7326 @Override
7327 public void sendMessage(CustomMessage message)
7328 {
7329 sendMessage(message.toString());
7330 }
7331
7332 @Override
7333 public void sendChatMessage(int objectId, int messageType, String charName, String text)
7334 {
7335 sendPacket(new CreatureSay(objectId, messageType, charName, text));
7336 }
7337
7338 @Override
7339 public void teleToLocation(int x, int y, int z, int refId)
7340 {
7341 if (isDeleted())
7342 {
7343 return;
7344 }
7345
7346 super.teleToLocation(x, y, z, refId);
7347 }
7348
7349 @Override
7350 public boolean onTeleported()
7351 {
7352 if (!super.onTeleported())
7353 {
7354 return false;
7355 }
7356
7357 if (isFakeDeath())
7358 {
7359 breakFakeDeath();
7360 }
7361
7362 if (isInBoat())
7363 {
7364 setLoc(getBoat().getLoc());
7365 }
7366
7367 // 15 seconds after teleport the character does not cast agr
7368 setNonAggroTime(System.currentTimeMillis() + Config.NONAGGRO_TIME_ONTELEPORT);
7369
7370 spawnMe();
7371
7372 setLastClientPosition(getLoc());
7373 setLastServerPosition(getLoc());
7374
7375 if (isPendingRevive())
7376 {
7377 doRevive();
7378 }
7379
7380 sendActionFailed();
7381
7382 getAI().notifyEvent(CtrlEvent.EVT_TELEPORTED);
7383
7384 if (isLockedTarget() && (getTarget() != null))
7385 {
7386 sendPacket(new MyTargetSelected(getTarget().getObjectId(), 0));
7387 }
7388
7389 sendUserInfo(true);
7390 if (getPet() != null)
7391 {
7392 if (!getPet().isInRange(getLoc(), Config.FOLLOW_RANGE))
7393 {
7394 getPet().teleportToOwner();
7395 }
7396 }
7397
7398 return true;
7399 }
7400
7401 private boolean _partyMatchingVisible = true;
7402
7403 public void setPartyMatchingVisible()
7404 {
7405 _partyMatchingVisible = (!(_partyMatchingVisible));
7406 }
7407
7408 public boolean isPartyMatchingVisible()
7409 {
7410 return _partyMatchingVisible;
7411 }
7412
7413 public boolean enterObserverMode(Location loc)
7414 {
7415 WorldRegion observerRegion = World.getRegion(loc);
7416 if (observerRegion == null)
7417 {
7418 return false;
7419 }
7420 if (!_observerMode.compareAndSet(OBSERVER_NONE, OBSERVER_STARTING))
7421 {
7422 return false;
7423 }
7424
7425 setTarget(null);
7426 stopMove();
7427 sitDown(null);
7428 setFlying(true);
7429
7430 World.removeObjectsFromPlayer(this);
7431
7432 _observerRegion = observerRegion;
7433
7434 broadcastCharInfo();
7435
7436 sendPacket(new ObserverStart(loc));
7437
7438 return true;
7439 }
7440
7441 public void appearObserverMode()
7442 {
7443 if (!_observerMode.compareAndSet(OBSERVER_STARTING, OBSERVER_STARTED))
7444 {
7445 return;
7446 }
7447
7448 WorldRegion currentRegion = getCurrentRegion();
7449
7450 // Add a fake to the point of observation
7451 if (!_observerRegion.equals(currentRegion))
7452 {
7453 _observerRegion.addObject(this);
7454 }
7455
7456 World.showObjectsToPlayer(this);
7457
7458 if (_olympiadObserveGame != null)
7459 {
7460 _olympiadObserveGame.addSpectator(this);
7461 _olympiadObserveGame.broadcastInfo(null, this, true);
7462 }
7463 }
7464
7465 public void leaveObserverMode()
7466 {
7467 if (!_observerMode.compareAndSet(OBSERVER_STARTED, OBSERVER_LEAVING))
7468 {
7469 return;
7470 }
7471
7472 WorldRegion currentRegion = getCurrentRegion();
7473
7474 if (!_observerRegion.equals(currentRegion))
7475 {
7476 _observerRegion.removeObject(this);
7477 }
7478
7479 // Clear all visible objects
7480 World.removeObjectsFromPlayer(this);
7481
7482 _observerRegion = null;
7483
7484 setTarget(null);
7485 stopMove();
7486
7487 // Exit the mode observing
7488 sendPacket(new ObserverEnd(getLoc()));
7489 }
7490
7491 public void returnFromObserverMode()
7492 {
7493 if (!_observerMode.compareAndSet(OBSERVER_LEAVING, OBSERVER_NONE))
7494 {
7495 return;
7496 }
7497
7498 // It is necessary when teleport from a higher point to a lower, or harmed by the "fall"
7499 _lastClientPosition = null;
7500 _lastServerPosition = null;
7501
7502 unblock();
7503 standUp();
7504 setFlying(false);
7505
7506 broadcastCharInfo();
7507
7508 World.showObjectsToPlayer(this);
7509 }
7510
7511 public void enterOlympiadObserverMode(Location loc, OlympiadGame game, Reflection reflect)
7512 {
7513 WorldRegion observerRegion = World.getRegion(loc);
7514 //WorldRegion currentRegion = getCurrentRegion();
7515 WorldRegion oldObserver = _observerRegion;
7516 if (observerRegion == null)
7517 {
7518 return;
7519 }
7520 OlympiadGame oldGame = _olympiadObserveGame;
7521 if (!_observerMode.compareAndSet(oldGame != null ? OBSERVER_STARTED : OBSERVER_NONE, OBSERVER_STARTING))
7522 {
7523 return;
7524 }
7525
7526 setTarget(null);
7527 stopMove();
7528
7529 World.removeObjectsFromPlayer(this);
7530 _observerRegion = observerRegion;
7531
7532 if (oldGame != null)
7533 {
7534 if (isInObserverMode() && (oldObserver != null))
7535 oldObserver.removeObject(this);
7536 oldGame.removeSpectator(this);
7537 sendPacket(ExOlympiadMatchEnd.STATIC);
7538 }
7539 else
7540 {
7541 block();
7542
7543 broadcastCharInfo();
7544
7545 sendPacket(new ExOlympiadMode(3));
7546 }
7547
7548 _olympiadObserveGame = game;
7549
7550 setReflection(reflect);
7551 sendPacket(new TeleportToLocation(this, loc));
7552 }
7553
7554 public void leaveOlympiadObserverMode(boolean removeFromGame)
7555 {
7556 if (_olympiadObserveGame == null)
7557 return;
7558
7559 if (!_observerMode.compareAndSet(OBSERVER_STARTED, OBSERVER_LEAVING))
7560 {
7561 return;
7562 }
7563
7564 if (removeFromGame)
7565 {
7566 _olympiadObserveGame.removeSpectator(this);
7567 }
7568 _olympiadObserveGame = null;
7569
7570 WorldRegion currentRegion = getCurrentRegion();
7571
7572 if ((_observerRegion != null) && (currentRegion != null) && !_observerRegion.equals(currentRegion))
7573 {
7574 _observerRegion.removeObject(this);
7575 }
7576
7577 World.removeObjectsFromPlayer(this);
7578
7579 _observerRegion = null;
7580
7581 setTarget(null);
7582 stopMove();
7583
7584 sendPacket(new ExOlympiadMode(0));
7585 sendPacket(ExOlympiadMatchEnd.STATIC);
7586
7587 setReflection(ReflectionManager.DEFAULT);
7588
7589 sendPacket(new TeleportToLocation(this, getLoc()));
7590 }
7591
7592 public void setOlympiadSide(final int i)
7593 {
7594 _olympiadSide = i;
7595 }
7596
7597 public int getOlympiadSide()
7598 {
7599 return _olympiadSide;
7600 }
7601
7602 @Override
7603 public boolean isInObserverMode()
7604 {
7605 return _observerMode.get() > OBSERVER_NONE;//So it can be OBSERVER_STARTING(1), OBSERVER_LEAVING(2) or OBSERVER_STARTED(3)
7606 }
7607
7608 public int getObserverMode()
7609 {
7610 return _observerMode.get();
7611 }
7612
7613 public WorldRegion getObserverRegion()
7614 {
7615 return _observerRegion;
7616 }
7617
7618 public void setObserverRegion(WorldRegion region)
7619 {
7620 _observerRegion = region;
7621 }
7622
7623 public int getTeleMode()
7624 {
7625 return _telemode;
7626 }
7627
7628 public void setTeleMode(final int mode)
7629 {
7630 _telemode = mode;
7631 }
7632
7633 public void setLoto(final int i, final int val)
7634 {
7635 _loto[i] = val;
7636 }
7637
7638 public int getLoto(final int i)
7639 {
7640 return _loto[i];
7641 }
7642
7643 public void setRace(final int i, final int val)
7644 {
7645 _race[i] = val;
7646 }
7647
7648 public int getRace(final int i)
7649 {
7650 return _race[i];
7651 }
7652
7653 public boolean getMessageRefusal()
7654 {
7655 return _messageRefusal;
7656 }
7657
7658 public void setMessageRefusal(final boolean mode)
7659 {
7660 _messageRefusal = mode;
7661 }
7662
7663 public void setTradeRefusal(final boolean mode)
7664 {
7665 _tradeRefusal = mode;
7666 }
7667
7668 public boolean getTradeRefusal()
7669 {
7670 return _tradeRefusal;
7671 }
7672
7673 public void addToBlockList(final String charName)
7674 {
7675 if ((charName == null) || charName.equalsIgnoreCase(getName()) || isInBlockList(charName))
7676 {
7677 sendPacket(Msg.YOU_HAVE_FAILED_TO_REGISTER_THE_USER_TO_YOUR_IGNORE_LIST);
7678 return;
7679 }
7680
7681 Player block_target = World.getPlayer(charName);
7682
7683 if (block_target != null)
7684 {
7685 if (block_target.isGM())
7686 {
7687 sendPacket(Msg.YOU_MAY_NOT_IMPOSE_A_BLOCK_ON_A_GM);
7688 return;
7689 }
7690 _blockList.put(block_target.getObjectId(), block_target.getName());
7691 sendPacket(new SystemMessage(SystemMessage.S1_HAS_BEEN_ADDED_TO_YOUR_IGNORE_LIST).addString(block_target.getName()));
7692 block_target.sendPacket(new SystemMessage(SystemMessage.S1__HAS_PLACED_YOU_ON_HIS_HER_IGNORE_LIST).addString(getName()));
7693 return;
7694 }
7695
7696 int charId = CharacterDAO.getInstance().getObjectIdByName(charName);
7697
7698 if (charId == 0)
7699 {
7700 sendPacket(Msg.YOU_HAVE_FAILED_TO_REGISTER_THE_USER_TO_YOUR_IGNORE_LIST);
7701 return;
7702 }
7703
7704 if (Config.gmlist.containsKey(charId) && Config.gmlist.get(charId).IsGM)
7705 {
7706 sendPacket(Msg.YOU_MAY_NOT_IMPOSE_A_BLOCK_ON_A_GM);
7707 return;
7708 }
7709 _blockList.put(charId, charName);
7710 sendPacket(new SystemMessage(SystemMessage.S1_HAS_BEEN_ADDED_TO_YOUR_IGNORE_LIST).addString(charName));
7711 }
7712
7713 public void removeFromBlockList(final String charName)
7714 {
7715 int charId = 0;
7716 for (int blockId : _blockList.keySet())
7717 {
7718 if (charName.equalsIgnoreCase(_blockList.get(blockId)))
7719 {
7720 charId = blockId;
7721 break;
7722 }
7723 }
7724 if (charId == 0)
7725 {
7726 sendPacket(Msg.YOU_HAVE_FAILED_TO_DELETE_THE_CHARACTER_FROM_IGNORE_LIST);
7727 return;
7728 }
7729 sendPacket(new SystemMessage(SystemMessage.S1_HAS_BEEN_REMOVED_FROM_YOUR_IGNORE_LIST).addString(_blockList.remove(charId)));
7730 Player block_target = GameObjectsStorage.getPlayer(charId);
7731 if (block_target != null)
7732 {
7733 block_target.sendMessage(getName() + " has removed you from his/her Ignore List.");
7734 }
7735 }
7736
7737 public boolean isInBlockList(final Player player)
7738 {
7739 return isInBlockList(player.getObjectId());
7740 }
7741
7742 public boolean isInBlockList(final int charId)
7743 {
7744 return (_blockList != null) && _blockList.containsKey(charId);
7745 }
7746
7747 public boolean isInBlockList(final String charName)
7748 {
7749 for (int blockId : _blockList.keySet())
7750 {
7751 if (charName.equalsIgnoreCase(_blockList.get(blockId)))
7752 {
7753 return true;
7754 }
7755 }
7756 return false;
7757 }
7758
7759 private void restoreBlockList(Connection con)
7760 {
7761 _blockList.clear();
7762
7763 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 = ?"))
7764 {
7765 statement.setInt(1, getObjectId());
7766
7767 try (ResultSet rs = statement.executeQuery())
7768 {
7769 while (rs.next())
7770 {
7771 int targetId = rs.getInt("target_Id");
7772 String name = rs.getString("char_name");
7773 if (name == null)
7774 {
7775 continue;
7776 }
7777 _blockList.put(targetId, name);
7778 }
7779 }
7780 }
7781 catch (SQLException e)
7782 {
7783 _log.warn("Can't restore player blocklist " + e, e);
7784 }
7785 }
7786
7787 private void storeBlockList()
7788 {
7789 try (Connection con = DatabaseFactory.getInstance().getConnection();
7790 Statement statement = con.createStatement())
7791 {
7792 statement.executeUpdate("DELETE FROM character_blocklist WHERE obj_Id=" + getObjectId());
7793
7794 if (_blockList.isEmpty())
7795 {
7796 return;
7797 }
7798
7799 SqlBatch b = new SqlBatch("INSERT IGNORE INTO `character_blocklist` (`obj_Id`,`target_Id`) VALUES");
7800
7801 synchronized (_blockList)
7802 {
7803 StringBuilder sb;
7804 for (Entry<Integer, String> e : _blockList.entrySet())
7805 {
7806 sb = new StringBuilder("(");
7807 sb.append(getObjectId()).append(",");
7808 sb.append(e.getKey()).append(")");
7809 b.write(sb.toString());
7810 }
7811 }
7812 if (!b.isEmpty())
7813 {
7814 statement.executeUpdate(b.close());
7815 }
7816 }
7817 catch (Exception e)
7818 {
7819 _log.warn("Can't store player blocklist " + e);
7820 }
7821 }
7822
7823 public boolean isBlockAll()
7824 {
7825 return _blockAll;
7826 }
7827
7828 public void setBlockAll(final boolean state)
7829 {
7830 _blockAll = state;
7831 }
7832
7833 public Collection<String> getBlockList()
7834 {
7835 return _blockList.values();
7836 }
7837
7838 public Map<Integer, String> getBlockListMap()
7839 {
7840 return _blockList;
7841 }
7842
7843 public void setHeroAura(boolean heroAura)
7844 {
7845 _heroAura = heroAura;
7846 }
7847
7848 public boolean isHeroAura()
7849 {
7850 return (_hero) || (_heroAura) || (isFakeHero());
7851 }
7852
7853 public boolean isFakeHero()
7854 {
7855 if (getVarB("hasFakeHero"))
7856 {
7857 return true;
7858 }
7859 return false;
7860 }
7861
7862 public boolean FakeHeroEquip()
7863 {
7864 if ((isFakeHero() && (Config.SERVICES_HERO_SELL_ITEMS)) || (getVarB("hasFakeHeroItems")))
7865 {
7866 return true;
7867 }
7868 return false;
7869 }
7870
7871 public boolean FakeHeroChat()
7872 {
7873 if ((isFakeHero() && (Config.SERVICES_HERO_SELL_CHAT)) || (getVarB("hasFakeHeroChat")))
7874 {
7875 return true;
7876 }
7877 return false;
7878 }
7879
7880 public boolean FakeHeroSkill()
7881 {
7882 if ((isFakeHero() && (Config.SERVICES_HERO_SELL_SKILL)) || (getVarB("hasFakeHeroSkills")))
7883 {
7884 return true;
7885 }
7886 return false;
7887 }
7888 public void setHero(final boolean hero)
7889 {
7890 _hero = hero;
7891 }
7892
7893 @Override
7894 public boolean isHero()
7895 {
7896 return _hero;
7897 }
7898
7899 public void setHero(Player player)
7900 {
7901 StatsSet hero = new StatsSet();
7902 hero.set(Olympiad.CLASS_ID, player.getBaseClassId());
7903 hero.set(Olympiad.CHAR_ID, player.getObjectId());
7904 hero.set(Olympiad.CHAR_NAME, player.getName());
7905 hero.set(Hero.ACTIVE, 1);
7906
7907 List<StatsSet> heroesToBe = new ArrayList<StatsSet>();
7908 heroesToBe.add(hero);
7909
7910 Hero.getInstance().computeNewHeroes(heroesToBe);
7911 player.setHero(true);
7912 Hero.addSkills(player);
7913 player.updatePledgeClass();
7914 if (player.isHero())
7915 {
7916 player.broadcastPacket(new SocialAction(player.getObjectId(), 16));
7917 }
7918 player.broadcastUserInfo(true);
7919 }
7920
7921 public int getPing()
7922 {
7923 return _ping;
7924 }
7925
7926 public void setPing(int ping)
7927 {
7928 _ping = ping;
7929 }
7930
7931 public void setIsInOlympiadMode(final boolean b)
7932 {
7933 _inOlympiadMode = b;
7934 }
7935
7936 @Override
7937 public boolean isInOlympiadMode()
7938 {
7939 return _inOlympiadMode;
7940 }
7941
7942 public void setOlympiadCompStarted(final boolean b)
7943 {
7944 _isOlympiadCompStarted = b;
7945 }
7946
7947 public boolean isOlympiadCompStarted()
7948 {
7949 return _isOlympiadCompStarted;
7950 }
7951
7952 public void updateNobleSkills()
7953 {
7954 if (isNoble())
7955 {
7956 if (isClanLeader() && (getClan().getCastle() > 0))
7957 {
7958 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_WYVERN_AEGIS, 1));
7959 }
7960 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_NOBLESSE_BLESSING, 1));
7961 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_SUMMON_CP_POTION, 1));
7962 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_FORTUNE_OF_NOBLESSE, 1));
7963 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_HARMONY_OF_NOBLESSE, 1));
7964 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_SYMPHONY_OF_NOBLESSE, 1));
7965 }
7966 else
7967 {
7968 super.removeSkillById(Skill.SKILL_WYVERN_AEGIS);
7969 super.removeSkillById(Skill.SKILL_NOBLESSE_BLESSING);
7970 super.removeSkillById(Skill.SKILL_SUMMON_CP_POTION);
7971 super.removeSkillById(Skill.SKILL_FORTUNE_OF_NOBLESSE);
7972 super.removeSkillById(Skill.SKILL_HARMONY_OF_NOBLESSE);
7973 super.removeSkillById(Skill.SKILL_SYMPHONY_OF_NOBLESSE);
7974 }
7975 }
7976
7977 public void setNoble(boolean noble)
7978 {
7979 if (noble)
7980 {
7981 broadcastPacket(new MagicSkillUse(this, this, 6673, 1, 1000, 0));
7982 }
7983 _noble = noble;
7984 }
7985
7986 public boolean isNoble()
7987 {
7988 return _noble;
7989 }
7990
7991 public int getSubLevel()
7992 {
7993 return isSubClassActive() ? getLevel() : 0;
7994 }
7995
7996 /* varka silenos and ketra orc quests related functions */
7997 public void updateKetraVarka()
7998 {
7999 if (ItemFunctions.getItemCount(this, 7215) > 0)
8000 {
8001 _ketra = 5;
8002 }
8003 else if (ItemFunctions.getItemCount(this, 7214) > 0)
8004 {
8005 _ketra = 4;
8006 }
8007 else if (ItemFunctions.getItemCount(this, 7213) > 0)
8008 {
8009 _ketra = 3;
8010 }
8011 else if (ItemFunctions.getItemCount(this, 7212) > 0)
8012 {
8013 _ketra = 2;
8014 }
8015 else if (ItemFunctions.getItemCount(this, 7211) > 0)
8016 {
8017 _ketra = 1;
8018 }
8019 else if (ItemFunctions.getItemCount(this, 7225) > 0)
8020 {
8021 _varka = 5;
8022 }
8023 else if (ItemFunctions.getItemCount(this, 7224) > 0)
8024 {
8025 _varka = 4;
8026 }
8027 else if (ItemFunctions.getItemCount(this, 7223) > 0)
8028 {
8029 _varka = 3;
8030 }
8031 else if (ItemFunctions.getItemCount(this, 7222) > 0)
8032 {
8033 _varka = 2;
8034 }
8035 else if (ItemFunctions.getItemCount(this, 7221) > 0)
8036 {
8037 _varka = 1;
8038 }
8039 else
8040 {
8041 _varka = 0;
8042 _ketra = 0;
8043 }
8044 }
8045
8046 public int getVarka()
8047 {
8048 return _varka;
8049 }
8050
8051 public int getKetra()
8052 {
8053 return _ketra;
8054 }
8055
8056 public void updateRam()
8057 {
8058 if (ItemFunctions.getItemCount(this, 7247) > 0)
8059 {
8060 _ram = 2;
8061 }
8062 else if (ItemFunctions.getItemCount(this, 7246) > 0)
8063 {
8064 _ram = 1;
8065 }
8066 else
8067 {
8068 _ram = 0;
8069 }
8070 }
8071
8072 public int getRam()
8073 {
8074 return _ram;
8075 }
8076
8077 public void setPledgeType(final int typeId)
8078 {
8079 _pledgeType = typeId;
8080 }
8081
8082 public int getPledgeType()
8083 {
8084 return _pledgeType;
8085 }
8086
8087 public void setLvlJoinedAcademy(int lvl)
8088 {
8089 _lvlJoinedAcademy = lvl;
8090 }
8091
8092 public int getLvlJoinedAcademy()
8093 {
8094 return _lvlJoinedAcademy;
8095 }
8096
8097 public int getPledgeClass()
8098 {
8099 return _pledgeClass;
8100 }
8101
8102 public void updatePledgeClass()
8103 {
8104 int clanLevel = _clan == null ? -1 : _clan.getLevel();
8105 boolean inAcademy = (_clan != null) && Clan.isAcademy(_pledgeType);
8106 boolean isGuard = (_clan != null) && Clan.isRoyalGuard(_pledgeType);
8107 boolean isKnight = (_clan != null) && Clan.isOrderOfKnights(_pledgeType);
8108
8109 boolean isGuardCaptain = false, isKnightCommander = false, isLeader = false;
8110
8111 SubUnit unit = getSubUnit();
8112 if (unit != null)
8113 {
8114 UnitMember unitMember = unit.getUnitMember(getObjectId());
8115 if (unitMember == null)
8116 {
8117 _log.warn("Player: unitMember null, clan: " + _clan.getClanId() + "; pledgeType: " + unit.getType());
8118 return;
8119 }
8120 isGuardCaptain = Clan.isRoyalGuard(unitMember.getLeaderOf());
8121 isKnightCommander = Clan.isOrderOfKnights(unitMember.getLeaderOf());
8122 isLeader = unitMember.getLeaderOf() == Clan.SUBUNIT_MAIN_CLAN;
8123 }
8124
8125 switch (clanLevel)
8126 {
8127 case -1:
8128 _pledgeClass = RANK_VAGABOND;
8129 break;
8130 case 0:
8131 case 1:
8132 case 2:
8133 case 3:
8134 if (isLeader)
8135 {
8136 _pledgeClass = RANK_HEIR;
8137 }
8138 else
8139 {
8140 _pledgeClass = RANK_VASSAL;
8141 }
8142 break;
8143 case 4:
8144 if (isLeader)
8145 {
8146 _pledgeClass = RANK_KNIGHT;
8147 }
8148 else
8149 {
8150 _pledgeClass = RANK_HEIR;
8151 }
8152 break;
8153 case 5:
8154 if (isLeader)
8155 {
8156 _pledgeClass = RANK_WISEMAN;
8157 }
8158 else if (inAcademy)
8159 {
8160 _pledgeClass = RANK_VASSAL;
8161 }
8162 else
8163 {
8164 _pledgeClass = RANK_HEIR;
8165 }
8166 break;
8167 case 6:
8168 if (isLeader)
8169 {
8170 _pledgeClass = RANK_BARON;
8171 }
8172 else if (inAcademy)
8173 {
8174 _pledgeClass = RANK_VASSAL;
8175 }
8176 else if (isGuardCaptain)
8177 {
8178 _pledgeClass = RANK_WISEMAN;
8179 }
8180 else if (isGuard)
8181 {
8182 _pledgeClass = RANK_HEIR;
8183 }
8184 else
8185 {
8186 _pledgeClass = RANK_KNIGHT;
8187 }
8188 break;
8189 case 7:
8190 if (isLeader)
8191 {
8192 _pledgeClass = RANK_COUNT;
8193 }
8194 else if (inAcademy)
8195 {
8196 _pledgeClass = RANK_VASSAL;
8197 }
8198 else if (isGuardCaptain)
8199 {
8200 _pledgeClass = RANK_VISCOUNT;
8201 }
8202 else if (isGuard)
8203 {
8204 _pledgeClass = RANK_KNIGHT;
8205 }
8206 else if (isKnightCommander)
8207 {
8208 _pledgeClass = RANK_BARON;
8209 }
8210 else if (isKnight)
8211 {
8212 _pledgeClass = RANK_HEIR;
8213 }
8214 else
8215 {
8216 _pledgeClass = RANK_WISEMAN;
8217 }
8218 break;
8219 case 8:
8220 if (isLeader)
8221 {
8222 _pledgeClass = RANK_MARQUIS;
8223 }
8224 else if (inAcademy)
8225 {
8226 _pledgeClass = RANK_VASSAL;
8227 }
8228 else if (isGuardCaptain)
8229 {
8230 _pledgeClass = RANK_COUNT;
8231 }
8232 else if (isGuard)
8233 {
8234 _pledgeClass = RANK_WISEMAN;
8235 }
8236 else if (isKnightCommander)
8237 {
8238 _pledgeClass = RANK_VISCOUNT;
8239 }
8240 else if (isKnight)
8241 {
8242 _pledgeClass = RANK_KNIGHT;
8243 }
8244 else
8245 {
8246 _pledgeClass = RANK_BARON;
8247 }
8248 break;
8249 case 9:
8250 if (isLeader)
8251 {
8252 _pledgeClass = RANK_DUKE;
8253 }
8254 else if (inAcademy)
8255 {
8256 _pledgeClass = RANK_VASSAL;
8257 }
8258 else if (isGuardCaptain)
8259 {
8260 _pledgeClass = RANK_MARQUIS;
8261 }
8262 else if (isGuard)
8263 {
8264 _pledgeClass = RANK_BARON;
8265 }
8266 else if (isKnightCommander)
8267 {
8268 _pledgeClass = RANK_COUNT;
8269 }
8270 else if (isKnight)
8271 {
8272 _pledgeClass = RANK_WISEMAN;
8273 }
8274 else
8275 {
8276 _pledgeClass = RANK_VISCOUNT;
8277 }
8278 break;
8279 case 10:
8280 if (isLeader)
8281 {
8282 _pledgeClass = RANK_GRAND_DUKE;
8283 }
8284 else if (inAcademy)
8285 {
8286 _pledgeClass = RANK_VASSAL;
8287 }
8288 else if (isGuard)
8289 {
8290 _pledgeClass = RANK_VISCOUNT;
8291 }
8292 else if (isKnight)
8293 {
8294 _pledgeClass = RANK_BARON;
8295 }
8296 else if (isGuardCaptain)
8297 {
8298 _pledgeClass = RANK_DUKE;
8299 }
8300 else if (isKnightCommander)
8301 {
8302 _pledgeClass = RANK_MARQUIS;
8303 }
8304 else
8305 {
8306 _pledgeClass = RANK_COUNT;
8307 }
8308 break;
8309 case 11:
8310 if (isLeader)
8311 {
8312 _pledgeClass = RANK_DISTINGUISHED_KING;
8313 }
8314 else if (inAcademy)
8315 {
8316 _pledgeClass = RANK_VASSAL;
8317 }
8318 else if (isGuard)
8319 {
8320 _pledgeClass = RANK_COUNT;
8321 }
8322 else if (isKnight)
8323 {
8324 _pledgeClass = RANK_VISCOUNT;
8325 }
8326 else if (isGuardCaptain)
8327 {
8328 _pledgeClass = RANK_GRAND_DUKE;
8329 }
8330 else if (isKnightCommander)
8331 {
8332 _pledgeClass = RANK_DUKE;
8333 }
8334 else
8335 {
8336 _pledgeClass = RANK_MARQUIS;
8337 }
8338 break;
8339 }
8340
8341 if (_hero && (_pledgeClass < RANK_MARQUIS))
8342 {
8343 _pledgeClass = RANK_MARQUIS;
8344 }
8345 else if (_noble && (_pledgeClass < RANK_BARON))
8346 {
8347 _pledgeClass = RANK_BARON;
8348 }
8349 }
8350
8351 public void setPowerGrade(final int grade)
8352 {
8353 _powerGrade = grade;
8354 }
8355
8356 public int getPowerGrade()
8357 {
8358 return _powerGrade;
8359 }
8360
8361 public void setApprentice(final int apprentice)
8362 {
8363 _apprentice = apprentice;
8364 }
8365
8366 public int getApprentice()
8367 {
8368 return _apprentice;
8369 }
8370
8371 public int getSponsor()
8372 {
8373 return _clan == null ? 0 : _clan.getAnyMember(getObjectId()).getSponsor();
8374 }
8375
8376 public int getNameColor()
8377 {
8378 if (isInObserverMode())
8379 {
8380 return Color.black.getRGB();
8381 }
8382
8383 return _nameColor;
8384 }
8385
8386 public void setNameColor(final int nameColor)
8387 {
8388 if ((nameColor != Config.NORMAL_NAME_COLOUR) && (nameColor != Config.CLANLEADER_NAME_COLOUR) && (nameColor != Config.GM_NAME_COLOUR) && (nameColor != Config.SERVICES_OFFLINE_TRADE_NAME_COLOR))
8389 {
8390 setVar("namecolor", Integer.toHexString(nameColor), -1);
8391 }
8392 else if (nameColor == Config.NORMAL_NAME_COLOUR)
8393 {
8394 unsetVar("namecolor");
8395 }
8396 _nameColor = nameColor;
8397 }
8398
8399 public void setNameColor(final int red, final int green, final int blue)
8400 {
8401 _nameColor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16);
8402 if ((_nameColor != Config.NORMAL_NAME_COLOUR) && (_nameColor != Config.CLANLEADER_NAME_COLOUR) && (_nameColor != Config.GM_NAME_COLOUR) && (_nameColor != Config.SERVICES_OFFLINE_TRADE_NAME_COLOR))
8403 {
8404 setVar("namecolor", Integer.toHexString(_nameColor), -1);
8405 }
8406 else
8407 {
8408 unsetVar("namecolor");
8409 }
8410 }
8411
8412 public void setNameColor(String RGB)
8413 {
8414 if (RGB.length() == 6)
8415 {
8416 RGB = RGB.substring(4, 6) + RGB.substring(2, 4) + RGB.substring(0, 2);
8417 }
8418 setNameColor(Integer.decode("0x" + RGB));
8419 }
8420
8421 private final Map<String, PlayerVar> user_variables = new ConcurrentHashMap<String, PlayerVar>();
8422
8423 public static void setVarOffline(int playerObjId, String name, String value, long expireDate)
8424 {
8425 Player player = World.getPlayer(playerObjId);
8426 if (player != null)
8427 player.setVar(name, value, expireDate);
8428 else
8429 mysql.set("REPLACE INTO character_variables (obj_id, type, name, value, expire_time) VALUES (?,'user-var',?,?,?)", playerObjId, name, value, expireDate);
8430 }
8431
8432 public static void setVarOffline(int playerObjId, String name, int value, long expireDate)
8433 {
8434 setVarOffline(playerObjId, name, String.valueOf(value), expireDate);
8435 }
8436
8437 public static void setVarOffline(int playerObjId, String name, int value)
8438 {
8439 setVarOffline(playerObjId, name, String.valueOf(value), -1);
8440 }
8441
8442 public static void setVarOffline(int playerObjId, String name, long value, long expireDate)
8443 {
8444 setVarOffline(playerObjId, name, String.valueOf(value), expireDate);
8445 }
8446
8447 public static void setVarOffline(int playerObjId, String name, long value)
8448 {
8449 setVarOffline(playerObjId, name, String.valueOf(value), -1);
8450 }
8451
8452 public static void unsetVarOffline(int playerObjId, String name)
8453 {
8454 Player player = World.getPlayer(playerObjId);
8455 if (player != null)
8456 player.unsetVar(name);
8457 else
8458 mysql.set("DELETE FROM `character_variables` WHERE `obj_id`=? AND `type`='user-var' AND `name`=? LIMIT 1", playerObjId, name);
8459 }
8460
8461 public void setVar(String name, String value, long expireDate)
8462 {
8463 if (user_variables.containsKey(name))
8464 {
8465 getVarObject(name).stopExpireTask();
8466 }
8467
8468 user_variables.put(name, new PlayerVar(this, name, value, expireDate));
8469 mysql.set("REPLACE INTO character_variables (obj_id, type, name, value, expire_time) VALUES (?,'user-var',?,?,?)", getObjectId(), name, value, expireDate);
8470 }
8471
8472 public void setVar(String name, String value)
8473 {
8474 setVar(name, value, -1);
8475 }
8476
8477 public void setVar(String name, int value, long expireDate)
8478 {
8479 setVar(name, String.valueOf(value), expireDate);
8480 }
8481
8482 public void setVar(String name, int value)
8483 {
8484 setVar(name, String.valueOf(value), -1);
8485 }
8486
8487 public void setVar(String name, long value, long expireDate)
8488 {
8489 setVar(name, String.valueOf(value), expireDate);
8490 }
8491
8492 public void setVar(String name, long value)
8493 {
8494 setVar(name, String.valueOf(value), -1);
8495 }
8496
8497 public void unsetVar(String name)
8498 {
8499 if (name == null)
8500 return;
8501
8502 PlayerVar pv = user_variables.remove(name);
8503
8504 if (pv != null)
8505 {
8506 pv.stopExpireTask();
8507 mysql.set("DELETE FROM `character_variables` WHERE `obj_id`=? AND `type`='user-var' AND `name`=? LIMIT 1", getObjectId(), name);
8508 }
8509 }
8510
8511 public String getVar(String name)
8512 {
8513 PlayerVar pv = getVarObject(name);
8514
8515 if (pv == null)
8516 {
8517 return null;
8518 }
8519
8520 return pv.getValue();
8521 }
8522
8523 public long getVarTimeToExpire(String name)
8524 {
8525 try
8526 {
8527 return getVarObject(name).getTimeToExpire();
8528 }
8529 catch (NullPointerException npe)
8530 {
8531
8532 }
8533
8534 return 0;
8535 }
8536
8537 public PlayerVar getVarObject(String name)
8538 {
8539 return user_variables.get(name);
8540 }
8541
8542 public boolean getVarB(String name, boolean defaultVal)
8543 {
8544 PlayerVar pv = getVarObject(name);
8545
8546 if (pv == null)
8547 {
8548 return defaultVal;
8549 }
8550
8551 return pv.getValueBoolean();
8552 }
8553
8554 public boolean getVarB(String name)
8555 {
8556 return getVarB(name, false);
8557 }
8558
8559 public long getVarLong(String name)
8560 {
8561 return getVarLong(name, 0L);
8562 }
8563
8564 public long getVarLong(String name, long defaultVal)
8565 {
8566 long result = defaultVal;
8567 String var = getVar(name);
8568 if (var != null)
8569 {
8570 result = Long.parseLong(var);
8571 }
8572 return result;
8573 }
8574
8575 public int getVarInt(String name)
8576 {
8577 return getVarInt(name, 0);
8578 }
8579
8580 public int getVarInt(String name, int defaultVal)
8581 {
8582 int result = defaultVal;
8583 String var = getVar(name);
8584 if (var != null)
8585 {
8586 result = Integer.parseInt(var);
8587 }
8588 return result;
8589 }
8590
8591 public Map<String, PlayerVar> getVars()
8592 {
8593 return user_variables;
8594 }
8595
8596 private void loadVariables(Connection con)
8597 {
8598 try (PreparedStatement offline = con.prepareStatement("SELECT * FROM character_variables WHERE obj_id = ?"))
8599 {
8600 offline.setInt(1, getObjectId());
8601
8602 try (ResultSet rs = offline.executeQuery())
8603 {
8604 while (rs.next())
8605 {
8606 String name = rs.getString("name");
8607 String value = Strings.stripSlashes(rs.getString("value"));
8608 long expire_time = rs.getLong("expire_time");
8609 long curtime = System.currentTimeMillis();
8610
8611 if ((expire_time <= curtime) && (expire_time > 0))
8612 {
8613 continue;
8614 }
8615
8616 user_variables.put(name, new PlayerVar(this, name, value, expire_time));
8617 }
8618 }
8619 }
8620 catch (SQLException e)
8621 {
8622 _log.error("Error while loading Character_variables for Id "+getObjectId(), e);
8623 }
8624 }
8625
8626 public static String getVarFromPlayer(int objId, String var)
8627 {
8628 String value = null;
8629
8630 try (Connection con = DatabaseFactory.getInstance().getConnection();
8631 PreparedStatement offline = con.prepareStatement("SELECT value FROM character_variables WHERE obj_id = ? AND name = ?"))
8632 {
8633 offline.setInt(1, objId);
8634 offline.setString(2, var);
8635
8636 try (ResultSet rs = offline.executeQuery())
8637 {
8638 if (rs.next())
8639 {
8640 value = Strings.stripSlashes(rs.getString("value"));
8641 }
8642 }
8643 }
8644 catch (Exception e)
8645 {
8646 _log.error("Error while getting Variable from Player", e);
8647 }
8648 return value;
8649 }
8650
8651 /**
8652 * Adding Variable to Map<Name, Value>. It's not saved to database.
8653 * Value can be taken back by {@link #getQuickVarO(String, Object...)} method.
8654 * @param name key
8655 * @param value value
8656 */
8657 public void addQuickVar(String name, Object value)
8658 {
8659 if (quickVars.containsKey(name))
8660 quickVars.remove(name);
8661 quickVars.put(name, value);
8662 }
8663
8664 /**
8665 * Getting back String Value located in quickVars Map<Name, Value>.
8666 * If value doesn't exist, defaultValue is returned.
8667 * If value isn't String type, throws Error
8668 * @param name key
8669 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8670 * @return value
8671 */
8672 public String getQuickVarS(String name, String... defaultValue)
8673 {
8674 if (!quickVars.containsKey(name))
8675 {
8676 if (defaultValue.length > 0)
8677 return defaultValue[0];
8678 return null;
8679 }
8680 return (String) quickVars.get(name);
8681 }
8682
8683 /**
8684 * Getting back String Value located in quickVars Map<Name, Value>.
8685 * If value doesn't exist, defaultValue is returned.
8686 * If value isn't Boolean type, throws Error
8687 * @param name key
8688 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8689 * @return value
8690 */
8691 public boolean getQuickVarB(String name, boolean... defaultValue)
8692 {
8693 if (!quickVars.containsKey(name))
8694 {
8695 if (defaultValue.length > 0)
8696 return defaultValue[0];
8697 return false;
8698 }
8699 return ((Boolean) quickVars.get(name)).booleanValue();
8700 }
8701
8702 /**
8703 * Getting back Integer Value located in quickVars Map<Name, Value>.
8704 * If value doesn't exist, defaultValue is returned.
8705 * If value isn't Integer type, throws Error
8706 * @param name key
8707 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8708 * @return value
8709 */
8710 public int getQuickVarI(String name, int... defaultValue)
8711 {
8712 if (!quickVars.containsKey(name))
8713 {
8714 if (defaultValue.length > 0)
8715 return defaultValue[0];
8716 return -1;
8717 }
8718 return ((Integer) quickVars.get(name)).intValue();
8719 }
8720
8721 /**
8722 * Getting back Long Value located in quickVars Map<Name, Value>.
8723 * If value doesn't exist, defaultValue is returned.
8724 * If value isn't Long type, throws Error
8725 * @param name key
8726 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8727 * @return value
8728 */
8729 public long getQuickVarL(String name, long... defaultValue)
8730 {
8731 if (!quickVars.containsKey(name))
8732 {
8733 if (defaultValue.length > 0)
8734 return defaultValue[0];
8735 return -1L;
8736 }
8737 return ((Long) quickVars.get(name)).longValue();
8738 }
8739
8740 /**
8741 * Getting back Object Value located in quickVars Map<Name, Value>.
8742 * If value doesn't exist, defaultValue is returned.
8743 * @param name key
8744 * @param defaultValue Value returned when <code>name</code> key doesn't exist
8745 * @return value
8746 */
8747 public Object getQuickVarO(String name, Object... defaultValue)
8748 {
8749 if (!quickVars.containsKey(name))
8750 {
8751 if (defaultValue.length > 0)
8752 return defaultValue[0];
8753 return null;
8754 }
8755 return quickVars.get(name);
8756 }
8757
8758 /**
8759 * Checking if quickVars Map<Name, Value> contains a name as a Key
8760 * @param name key
8761 * @return contains name
8762 */
8763 public boolean containsQuickVar(String name)
8764 {
8765 return quickVars.containsKey(name);
8766 }
8767
8768 /**
8769 * Removing Key from quickVars Map
8770 * @param name - key
8771 */
8772 public void deleteQuickVar(String name)
8773 {
8774 quickVars.remove(name);
8775 }
8776
8777 /**
8778 * Adding new Image Id to List of Images loaded by Game Client of this plater
8779 * @param id of the image
8780 */
8781 public void addLoadedImage(int id)
8782 {
8783 loadedImages.add(id);
8784 }
8785
8786 /**
8787 * Did Game Client already receive Custom Image from the server?
8788 * @param id of the image
8789 * @return client received image
8790 */
8791 public boolean wasImageLoaded(int id)
8792 {
8793 return loadedImages.contains(id);
8794 }
8795
8796 /**
8797 * @return Number of Custom Images sent from Server to the Player
8798 */
8799 public int getLoadedImagesSize()
8800 {
8801 return loadedImages.size();
8802 }
8803
8804 public String getLang()
8805 {
8806 return "en";
8807 }
8808
8809 public int getLangId()
8810 {
8811 String lang = getLang();
8812 if (lang.equalsIgnoreCase("en") || lang.equalsIgnoreCase("e") || lang.equalsIgnoreCase("eng"))
8813 {
8814 return LANG_ENG;
8815 }
8816 if (lang.equalsIgnoreCase("ru") || lang.equalsIgnoreCase("r") || lang.equalsIgnoreCase("rus"))
8817 {
8818 return LANG_RUS;
8819 }
8820 return LANG_UNK;
8821 }
8822
8823 public Language getLanguage()
8824 {
8825 String lang = getLang();
8826 if ((lang == null) || lang.equalsIgnoreCase("en") || lang.equalsIgnoreCase("e") || lang.equalsIgnoreCase("eng"))
8827 {
8828 return Language.ENGLISH;
8829 }
8830 if (lang.equalsIgnoreCase("ru") || lang.equalsIgnoreCase("r") || lang.equalsIgnoreCase("rus"))
8831 {
8832 return Language.RUSSIAN;
8833 }
8834 return Language.ENGLISH;
8835 }
8836
8837 public boolean isLangRus()
8838 {
8839 return getLangId() == LANG_RUS;
8840 }
8841
8842 public int isAtWarWith(final Integer id)
8843 {
8844 return (_clan == null) || !_clan.isAtWarWith(id) ? 0 : 1;
8845 }
8846
8847 public int isAtWar()
8848 {
8849 return (_clan == null) || (_clan.isAtWarOrUnderAttack() <= 0) ? 0 : 1;
8850 }
8851
8852 public void stopWaterTask()
8853 {
8854 if (_taskWater != null)
8855 {
8856 _taskWater.cancel(false);
8857 _taskWater = null;
8858 sendPacket(new SetupGauge(this, SetupGauge.CYAN, 0));
8859 sendChanges();
8860 }
8861 }
8862
8863 public void startWaterTask()
8864 {
8865 if (isDead())
8866 {
8867 stopWaterTask();
8868 }
8869 else if (Config.ALLOW_WATER && (_taskWater == null))
8870 {
8871 int timeinwater = (int) (calcStat(Stats.BREATH, 86, null, null) * 1000L);
8872 sendPacket(new SetupGauge(this, SetupGauge.CYAN, timeinwater));
8873 if ((getTransformation() > 0) && (getTransformationTemplate() > 0) && !isCursedWeaponEquipped())
8874 {
8875 setTransformation(0);
8876 }
8877 _taskWater = ThreadPoolManager.getInstance().scheduleAtFixedRate(new WaterTask(this), timeinwater, 1000L);
8878 sendChanges();
8879 }
8880 }
8881
8882 public void doRevive(double percent)
8883 {
8884 restoreExp(percent);
8885 doRevive();
8886 }
8887
8888 @Override
8889 public void doRevive()
8890 {
8891 super.doRevive();
8892 setAgathionRes(false);
8893 unsetVar("lostexp");
8894 updateEffectIcons();
8895 autoShot();
8896
8897 // Prims - Block the community buffer 10 seconds so the player cannot buff when resurrected
8898 _resurrectionBuffBlockedTime = System.currentTimeMillis() + 10 * 1000;
8899 }
8900
8901 public void reviveRequest(Player reviver, double percent, boolean pet)
8902 {
8903 ReviveAnswerListener reviveAsk = (_askDialog != null) && (_askDialog.getValue() instanceof ReviveAnswerListener) ? (ReviveAnswerListener) _askDialog.getValue() : null;
8904 if (reviveAsk != null)
8905 {
8906 if ((reviveAsk.isForPet() == pet) && (reviveAsk.getPower() >= percent))
8907 {
8908 reviver.sendPacket(Msg.BETTER_RESURRECTION_HAS_BEEN_ALREADY_PROPOSED);
8909 return;
8910 }
8911 if (pet && !reviveAsk.isForPet())
8912 {
8913 reviver.sendPacket(Msg.SINCE_THE_MASTER_WAS_IN_THE_PROCESS_OF_BEING_RESURRECTED_THE_ATTEMPT_TO_RESURRECT_THE_PET_HAS_BEEN_CANCELLED);
8914 return;
8915 }
8916 if (pet && isDead())
8917 {
8918 reviver.sendPacket(Msg.WHILE_A_PET_IS_ATTEMPTING_TO_RESURRECT_IT_CANNOT_HELP_IN_RESURRECTING_ITS_MASTER);
8919 return;
8920 }
8921 }
8922
8923 if ((pet && getPet() != null && getPet().isDead()) || (!pet && isDead()))
8924 {
8925 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));
8926 pkt.addName(reviver).addString(Math.round(percent) + " percent");
8927
8928 if (!isDualbox(reviver))
8929 reviver.getCounters().playersRessurected++;
8930
8931 ask(pkt, new ReviveAnswerListener(this, percent, pet));
8932 }
8933 }
8934
8935 /**
8936 * @return Prims - Max time for the player to accept the resurrection request
8937 */
8938 public long getResurrectionMaxTime()
8939 {
8940 return _resurrectionMaxTime;
8941 }
8942
8943 /**
8944 * @return Prims - Block time that the player cannot use the community buffer
8945 */
8946 public long getResurrectionBuffBlockedTime()
8947 {
8948 return _resurrectionBuffBlockedTime;
8949 }
8950
8951 public void summonCharacterRequest(final Creature summoner, final Location loc, final int summonConsumeCrystal)
8952 {
8953 ConfirmDlg cd = new ConfirmDlg(SystemMsg.C1_WISHES_TO_SUMMON_YOU_FROM_S2, 60000);
8954 cd.addName(summoner).addZoneName(loc);
8955
8956 ask(cd, new SummonAnswerListener(this, loc, summonConsumeCrystal));
8957 }
8958
8959 public void scriptRequest(String text, String scriptName, Object[] args)
8960 {
8961 ask(new ConfirmDlg(SystemMsg.S1, 30000).addString(text), new ScriptAnswerListener(this, scriptName, args));
8962 }
8963
8964 public void updateNoChannel(final long time)
8965 {
8966 setNoChannel(time);
8967
8968 final String stmt = "UPDATE characters SET nochannel = ? WHERE obj_Id=?";
8969
8970 try (Connection con = DatabaseFactory.getInstance().getConnection();
8971 PreparedStatement statement = con.prepareStatement(stmt))
8972 {
8973 statement.setLong(1, _NoChannel > 0 ? _NoChannel / 1000 : _NoChannel);
8974 statement.setInt(2, getObjectId());
8975 statement.executeUpdate();
8976 }
8977 catch (final Exception e)
8978 {
8979 _log.warn("Could not activate nochannel:" + e);
8980 }
8981
8982 sendPacket(new EtcStatusUpdate(this));
8983 }
8984
8985 public boolean isJailed()
8986 {
8987 return getVar("jailed") != null;
8988 }
8989
8990 private void checkRecom()
8991 {
8992 Calendar temp = Calendar.getInstance();
8993 temp.set(Calendar.HOUR_OF_DAY, 6);
8994 temp.set(Calendar.MINUTE, 30);
8995 temp.set(Calendar.SECOND, 0);
8996 temp.set(Calendar.MILLISECOND, 0);
8997 long count = Math.round(((System.currentTimeMillis() / 1000) - _lastAccess) / 86400);
8998 if ((count == 0) && (_lastAccess < (temp.getTimeInMillis() / 1000)) && (System.currentTimeMillis() > temp.getTimeInMillis()))
8999 {
9000 count++;
9001 }
9002
9003 for (int i = 1; i < count; i++)
9004 {
9005 setRecomHave(getRecomHave() - 20);
9006 }
9007
9008 if (count > 0)
9009 {
9010 restartRecom();
9011 }
9012 }
9013
9014 public void restartRecom()
9015 {
9016 setRecomBonusTime(3600);
9017 setRecomLeftToday(0);
9018 setRecomLeft(20);
9019 setRecomHave(getRecomHave() - 20);
9020 stopRecomBonusTask(false);
9021 startRecomBonusTask();
9022 sendUserInfo(true);
9023 sendVoteSystemInfo();
9024 }
9025
9026 @Override
9027 public boolean isInBoat()
9028 {
9029 return _boat != null;
9030 }
9031
9032 public Boat getBoat()
9033 {
9034 return _boat;
9035 }
9036
9037 public void setBoat(Boat boat)
9038 {
9039 _boat = boat;
9040 }
9041
9042 public Location getInBoatPosition()
9043 {
9044 return _inBoatPosition;
9045 }
9046
9047 public void setInBoatPosition(Location loc)
9048 {
9049 _inBoatPosition = loc;
9050 }
9051
9052 public Map<Integer, SubClass> getSubClasses()
9053 {
9054 return _classlist;
9055 }
9056
9057 public void setBaseClass(final int baseClass)
9058 {
9059 _baseClass = baseClass;
9060 }
9061
9062 public int getBaseClassId()
9063 {
9064 return _baseClass;
9065 }
9066
9067 public void setActiveClass(SubClass activeClass)
9068 {
9069 _activeClass = activeClass;
9070 }
9071
9072 public SubClass getActiveClass()
9073 {
9074 return _activeClass;
9075 }
9076
9077 public int getActiveClassId()
9078 {
9079 if (getActiveClass() == null)
9080 return -1;
9081
9082 return getActiveClass().getClassId();
9083 }
9084
9085 /**
9086 * Changing index of class in DB, used for changing class when finished professional quests
9087 * @param oldclass
9088 * @param newclass
9089 */
9090 public synchronized void changeClassInDb(final int oldclass, final int newclass)
9091 {
9092 try (Connection con = DatabaseFactory.getInstance().getConnection())
9093 {
9094 try (PreparedStatement statement = con.prepareStatement("UPDATE character_subclasses SET class_id=? WHERE char_obj_id=? AND class_id=?"))
9095 {
9096 statement.setInt(1, newclass);
9097 statement.setInt(2, getObjectId());
9098 statement.setInt(3, oldclass);
9099 statement.executeUpdate();
9100 }
9101
9102 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=?"))
9103 {
9104 statement.setInt(1, getObjectId());
9105 statement.setInt(2, newclass);
9106 statement.executeUpdate();
9107 }
9108
9109 try (PreparedStatement statement = con.prepareStatement("UPDATE character_hennas SET class_index=? WHERE char_obj_id=? AND class_index=?"))
9110 {
9111 statement.setInt(1, newclass);
9112 statement.setInt(2, getObjectId());
9113 statement.setInt(3, oldclass);
9114 statement.executeUpdate();
9115 }
9116
9117 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE object_id=? AND class_index=?"))
9118 {
9119 statement.setInt(1, getObjectId());
9120 statement.setInt(2, newclass);
9121 statement.executeUpdate();
9122 }
9123
9124 try (PreparedStatement statement = con.prepareStatement("UPDATE character_shortcuts SET class_index=? WHERE object_id=? AND class_index=?"))
9125 {
9126 statement.setInt(1, newclass);
9127 statement.setInt(2, getObjectId());
9128 statement.setInt(3, oldclass);
9129 statement.executeUpdate();
9130 }
9131
9132 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=? AND class_index=?"))
9133 {
9134 statement.setInt(1, getObjectId());
9135 statement.setInt(2, newclass);
9136 statement.executeUpdate();
9137 }
9138
9139 try (PreparedStatement statement = con.prepareStatement("UPDATE character_skills SET class_index=? WHERE char_obj_id=? AND class_index=?"))
9140 {
9141 statement.setInt(1, newclass);
9142 statement.setInt(2, getObjectId());
9143 statement.setInt(3, oldclass);
9144 statement.executeUpdate();
9145 }
9146
9147 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_effects_save WHERE object_id=? AND id=?"))
9148 {
9149 statement.setInt(1, getObjectId());
9150 statement.setInt(2, newclass);
9151 statement.executeUpdate();
9152 }
9153
9154 try (PreparedStatement statement = con.prepareStatement("UPDATE character_effects_save SET id=? WHERE object_id=? AND id=?"))
9155 {
9156 statement.setInt(1, newclass);
9157 statement.setInt(2, getObjectId());
9158 statement.setInt(3, oldclass);
9159 statement.executeUpdate();
9160 }
9161
9162 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=?"))
9163 {
9164 statement.setInt(1, getObjectId());
9165 statement.setInt(2, newclass);
9166 statement.executeUpdate();
9167 }
9168
9169 try (PreparedStatement statement = con.prepareStatement("UPDATE character_skills_save SET class_index=? WHERE char_obj_id=? AND class_index=?"))
9170 {
9171 statement.setInt(1, newclass);
9172 statement.setInt(2, getObjectId());
9173 statement.setInt(3, oldclass);
9174 statement.executeUpdate();
9175 }
9176 }
9177 catch (final SQLException e)
9178 {
9179 _log.error("Error while changing Class in Database", e);
9180 }
9181 }
9182
9183 public void storeCharSubClasses()
9184 {
9185 SubClass main = getActiveClass();
9186 if (main != null)
9187 {
9188 main.setCp(getCurrentCp());
9189 // main.setExp(getExp());
9190 // main.setLevel(getLevel());
9191 // main.setSp(getSp());
9192 main.setHp(getCurrentHp());
9193 main.setMp(getCurrentMp());
9194 main.setActive(true);
9195 getSubClasses().put(getActiveClassId(), main);
9196 }
9197 else
9198 {
9199 _log.warn("Could not store char sub data, main class " + getActiveClassId() + " not found for " + this);
9200 }
9201
9202 try (Connection con = DatabaseFactory.getInstance().getConnection();
9203 Statement statement = con.createStatement())
9204 {
9205
9206 StringBuilder sb;
9207 for (SubClass subClass : getSubClasses().values())
9208 {
9209 sb = new StringBuilder("UPDATE character_subclasses SET ");
9210 sb.append("exp=").append(subClass.getExp()).append(",");
9211 sb.append("sp=").append(subClass.getSp()).append(",");
9212 sb.append("curHp=").append(subClass.getHp()).append(",");
9213 sb.append("curMp=").append(subClass.getMp()).append(",");
9214 sb.append("curCp=").append(subClass.getCp()).append(",");
9215 sb.append("level=").append(subClass.getLevel()).append(",");
9216 sb.append("active=").append(subClass.isActive() ? 1 : 0).append(",");
9217 sb.append("isBase=").append(subClass.isBase() ? 1 : 0).append(",");
9218 sb.append("death_penalty=").append(subClass.getDeathPenalty(this).getLevelOnSaveDB()).append(",");
9219 sb.append("certification='").append(subClass.getCertification()).append("'");
9220 sb.append(" WHERE char_obj_id=").append(getObjectId()).append(" AND class_id=").append(subClass.getClassId()).append(" LIMIT 1");
9221 statement.executeUpdate(sb.toString());
9222 }
9223
9224 sb = new StringBuilder("UPDATE character_subclasses SET ");
9225 sb.append("maxHp=").append(getMaxHp()).append(",");
9226 sb.append("maxMp=").append(getMaxMp()).append(",");
9227 sb.append("maxCp=").append(getMaxCp());
9228 sb.append(" WHERE char_obj_id=").append(getObjectId()).append(" AND active=1 LIMIT 1");
9229 statement.executeUpdate(sb.toString());
9230 }
9231 catch (SQLException e)
9232 {
9233 _log.warn("Error while storing Char Subclasses", e);
9234 }
9235 }
9236
9237 /**
9238 * Restore list of character professions and set up active proof Used when character is loading
9239 * @param player
9240 * @param con
9241 */
9242 public static void restoreCharSubClasses(final Player player, Connection con)
9243 {
9244 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=?"))
9245 {
9246 statement.setInt(1, player.getObjectId());
9247 SubClass activeSubclass = null;
9248
9249 try (ResultSet rset = statement.executeQuery())
9250 {
9251 while (rset.next())
9252 {
9253 final SubClass subClass = new SubClass();
9254 subClass.setBase(rset.getInt("isBase") != 0);
9255 subClass.setClassId(rset.getInt("class_id"));
9256 subClass.setExp(rset.getLong("exp"));
9257 subClass.setSp(rset.getInt("sp"));
9258 subClass.setHp(rset.getDouble("curHp"));
9259 subClass.setMp(rset.getDouble("curMp"));
9260 subClass.setCp(rset.getDouble("curCp"));
9261 subClass.setDeathPenalty(new DeathPenalty(player, rset.getInt("death_penalty")));
9262 subClass.setCertification(rset.getInt("certification"));
9263
9264 boolean active = rset.getInt("active") != 0;
9265 if (active)
9266 {
9267 activeSubclass = subClass;
9268 }
9269 player._classlist.put(subClass.getClassId(), subClass);
9270 }
9271 }
9272 if (player._classlist.isEmpty())
9273 {
9274 _log.error("Error! There are no subclasses for player: " + player);
9275 return;
9276 }
9277
9278 int baseClassId = player._baseClass;
9279 if (baseClassId == -1)
9280 {
9281 _log.error("Error! There is no base class for player: " + player);
9282 return;
9283 }
9284
9285 if (activeSubclass != null)
9286 {
9287 player.setActiveSubClass(activeSubclass.getClassId(), false);
9288 }
9289
9290 if (player._activeClass == null)
9291 {
9292 final SubClass subClass = player._classlist.get(baseClassId);
9293 subClass.setActive(true);
9294 player.setActiveSubClass(subClass.getClassId(), false);
9295 }
9296 }
9297 catch (SQLException e)
9298 {
9299 _log.warn("Could not restore char sub-classes: ", e);
9300 }
9301 }
9302
9303 public boolean addSubClass(final int classId, boolean storeOld, int certification)
9304 {
9305 if (_classlist.size() >= (4 + Config.ALT_GAME_SUB_ADD))
9306 {
9307 return false;
9308 }
9309
9310 final ClassId newId = ClassId.VALUES[classId];
9311
9312 final SubClass newClass = new SubClass();
9313 newClass.setBase(false);
9314 if (newId.getRace() == null)
9315 {
9316 return false;
9317 }
9318
9319 newClass.setClassId(classId);
9320 newClass.setCertification(certification);
9321
9322 _classlist.put(classId, newClass);
9323
9324 try (Connection con = DatabaseFactory.getInstance().getConnection();
9325 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 (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"))
9326 {
9327 // Store the basic info about this new sub-class.
9328 statement.setInt(1, getObjectId());
9329 statement.setInt(2, newClass.getClassId());
9330 statement.setLong(3, Experience.LEVEL[40]);
9331 statement.setInt(4, 0);
9332 statement.setDouble(5, getCurrentHp());
9333 statement.setDouble(6, getCurrentMp());
9334 statement.setDouble(7, getCurrentCp());
9335 statement.setDouble(8, getCurrentHp());
9336 statement.setDouble(9, getCurrentMp());
9337 statement.setDouble(10, getCurrentCp());
9338 statement.setInt(11, 40);
9339 statement.setInt(12, 0);
9340 statement.setInt(13, 0);
9341 statement.setInt(14, 0);
9342 statement.setInt(15, certification);
9343 statement.execute();
9344 }
9345 catch (final Exception e)
9346 {
9347 _log.warn("Could not add character sub-class: " + e, e);
9348 return false;
9349 }
9350
9351 setActiveSubClass(classId, storeOld);
9352
9353 boolean countUnlearnable = true;
9354 int unLearnable = 0;
9355
9356 Collection<SkillLearn> skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
9357 while (skills.size() > unLearnable)
9358 {
9359 for (final SkillLearn s : skills)
9360 {
9361 final Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
9362 if ((sk == null) || !sk.getCanLearn(newId))
9363 {
9364 if (countUnlearnable)
9365 {
9366 unLearnable++;
9367 }
9368 continue;
9369 }
9370 addSkill(sk, true);
9371 }
9372 countUnlearnable = false;
9373 skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
9374 }
9375
9376 sendPacket(new SkillList(this));
9377 setCurrentHpMp(getMaxHp(), getMaxMp(), true);
9378 setCurrentCp(getMaxCp());
9379 return true;
9380 }
9381
9382 public boolean modifySubClass(final int oldClassId, final int newClassId)
9383 {
9384 final SubClass originalClass = _classlist.get(oldClassId);
9385 if ((originalClass == null) || originalClass.isBase())
9386 {
9387 return false;
9388 }
9389
9390 final int certification = originalClass.getCertification();
9391
9392 try (Connection con = DatabaseFactory.getInstance().getConnection())
9393 {
9394
9395 // Remove all basic info stored about this sub-class.
9396 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_subclasses WHERE char_obj_id=? AND class_id=? AND isBase = 0"))
9397 {
9398 statement.setInt(1, getObjectId());
9399 statement.setInt(2, oldClassId);
9400 statement.execute();
9401 }
9402
9403 // Remove all skill info stored for this sub-class.
9404 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=? AND class_index=? "))
9405 {
9406 statement.setInt(1, getObjectId());
9407 statement.setInt(2, oldClassId);
9408 statement.execute();
9409 }
9410
9411 // Remove all saved skills info stored for this sub-class.
9412 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=? "))
9413 {
9414 statement.setInt(1, getObjectId());
9415 statement.setInt(2, oldClassId);
9416 statement.execute();
9417 }
9418
9419 // Remove all saved effects stored for this sub-class.
9420 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_effects_save WHERE object_id=? AND id=? "))
9421 {
9422 statement.setInt(1, getObjectId());
9423 statement.setInt(2, oldClassId);
9424 statement.execute();
9425 }
9426
9427 // Remove all henna info stored for this sub-class.
9428 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=? "))
9429 {
9430 statement.setInt(1, getObjectId());
9431 statement.setInt(2, oldClassId);
9432 statement.execute();
9433 }
9434
9435 // Remove all shortcuts info stored for this sub-class.
9436 try (PreparedStatement statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE object_id=? AND class_index=? "))
9437 {
9438 statement.setInt(1, getObjectId());
9439 statement.setInt(2, oldClassId);
9440 statement.execute();
9441 }
9442 }
9443 catch (final Exception e)
9444 {
9445 _log.warn("Error while deleting char sub-class", e);
9446 }
9447
9448 _classlist.remove(oldClassId);
9449
9450 return (newClassId <= 0) || addSubClass(newClassId, false, certification);
9451 }
9452
9453 public void setActiveSubClass(final int subId, final boolean store)
9454 {
9455 final SubClass sub = _classlist.get(subId);
9456 if (sub == null)
9457 {
9458 return;
9459 }
9460
9461 if (isInDuel())
9462 {
9463 sendMessage("Unable to perform during a duel!");
9464 return;
9465 }
9466
9467 //Fix for Cancel exploit
9468 CancelTaskManager.getInstance().cancelPlayerTasks(this);
9469
9470 if (_activeClass != null)
9471 {
9472 EffectsDAO.getInstance().insert(this);
9473 storeDisableSkills();
9474
9475 if (QuestManager.getQuest(422) != null)
9476 {
9477 String qn = QuestManager.getQuest(422).getName();
9478 if (qn != null)
9479 {
9480 QuestState qs = getQuestState(qn);
9481 if (qs != null)
9482 {
9483 qs.exitCurrentQuest(true);
9484 }
9485 }
9486 }
9487 }
9488
9489 if (store)
9490 {
9491 final SubClass oldsub = _activeClass;
9492 oldsub.setCp(getCurrentCp());
9493 // oldsub.setExp(getExp());
9494 // oldsub.setLevel(getLevel());
9495 // oldsub.setSp(getSp());
9496 oldsub.setHp(getCurrentHp());
9497 oldsub.setMp(getCurrentMp());
9498 oldsub.setActive(false);
9499 _classlist.put(getActiveClassId(), oldsub);
9500 }
9501
9502 sub.setActive(true);
9503 _activeClass = sub;
9504 _classlist.put(getActiveClassId(), sub);
9505
9506 setClassId(subId, false, false);
9507
9508 removeAllSkills();
9509
9510 getEffectList().stopAllEffects();
9511
9512 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())))))
9513 {
9514 _summon.unSummon();
9515 }
9516
9517 setAgathion(0);
9518
9519 restoreSkills();
9520 rewardSkills(false);
9521 checkSkills();
9522 sendPacket(new ExStorageMaxCount(this));
9523
9524 refreshExpertisePenalty();
9525
9526 sendPacket(new SkillList(this));
9527
9528 _inventory.refreshEquip();
9529 _inventory.validateItems();
9530
9531 for (int i = 0; i < 3; i++)
9532 {
9533 _henna[i] = null;
9534 }
9535
9536 restoreHenna();
9537 sendPacket(new HennaInfo(this));
9538
9539 EffectsDAO.getInstance().restoreEffects(this, true, sub.getHp(), sub.getCp(), sub.getMp());
9540 restoreDisableSkills();
9541
9542 setCurrentHpMp(sub.getHp(), sub.getMp());
9543 setCurrentCp(sub.getCp());
9544
9545 _shortCuts.restore();
9546 sendPacket(new ShortCutInit(this));
9547 for (int shotId : _activeSoulShots)
9548 {
9549 sendPacket(new ExAutoSoulShot(shotId, true));
9550 }
9551 sendPacket(new SkillCoolTime(this));
9552
9553 broadcastPacket(new SocialAction(getObjectId(), SocialAction.LEVEL_UP));
9554
9555 getDeathPenalty().restore(this);
9556
9557 setIncreasedForce(0);
9558
9559 startHourlyTask();
9560
9561 broadcastCharInfo();
9562 updateEffectIcons();
9563 updateStats();
9564 }
9565
9566 public void startKickTask(long delayMillis)
9567 {
9568 stopKickTask();
9569 _kickTask = ThreadPoolManager.getInstance().schedule(new KickTask(this), delayMillis);
9570 }
9571
9572 public void stopKickTask()
9573 {
9574 if (_kickTask != null)
9575 {
9576 _kickTask.cancel(false);
9577 _kickTask = null;
9578 }
9579 }
9580
9581 public Future<?> getExpiration()
9582 {
9583 return _bonusExpiration;
9584 }
9585
9586 public void setExpiration(Future<?> expiration)
9587 {
9588 _bonusExpiration = expiration;
9589 }
9590
9591 public void stopBonusTask(boolean silence)
9592 {
9593 PremiumEnd.getInstance().stopBonusTask(this, silence);
9594 }
9595 public void startBonusTask()
9596 {
9597 if (Config.SERVICES_RATE_TYPE != Bonus.NO_BONUS)
9598 {
9599 int bonusExpire = _connection.getBonusExpire();
9600 double bonus = _connection.getBonus();
9601 if (bonusExpire > (System.currentTimeMillis() / 1000L))
9602 {
9603 _bonus.setRateXp(Config.SERVICES_BONUS_XP * bonus);
9604 _bonus.setRateSp(Config.SERVICES_BONUS_SP * bonus);
9605 _bonus.setDropAdena(Config.SERVICES_BONUS_ADENA * bonus);
9606 _bonus.setDropItems(Config.SERVICES_BONUS_ITEMS * bonus);
9607 _bonus.setDropSpoil(Config.SERVICES_BONUS_SPOIL * bonus);
9608 _bonus.setBonusExpire(bonusExpire);
9609
9610 if (_bonusExpiration == null)
9611 {
9612 _bonusExpiration = LazyPrecisionTaskManager.getInstance().startBonusExpirationTask(this);
9613 }
9614 }
9615 }
9616 }
9617
9618 public void stopBonusTask()
9619 {
9620 if (_bonusExpiration != null)
9621 {
9622 _bonusExpiration.cancel(false);
9623 _bonusExpiration = null;
9624 }
9625 }
9626
9627 @Override
9628 public int getInventoryLimit()
9629 {
9630 return (int) calcStat(Stats.INVENTORY_LIMIT, 0.0, null, null);
9631 }
9632
9633 public int getWarehouseLimit()
9634 {
9635 return (int) calcStat(Stats.STORAGE_LIMIT, 0.0, null, null);
9636 }
9637
9638 public int getTradeLimit()
9639 {
9640 return (int) calcStat(Stats.TRADE_LIMIT, 0.0, null, null);
9641 }
9642
9643 public int getDwarvenRecipeLimit()
9644 {
9645 return (int) calcStat(Stats.DWARVEN_RECIPE_LIMIT, 50.0, null, null) + Config.ALT_ADD_RECIPES;
9646 }
9647
9648 public int getCommonRecipeLimit()
9649 {
9650 return (int) calcStat(Stats.COMMON_RECIPE_LIMIT, 50.0, null, null) + Config.ALT_ADD_RECIPES;
9651 }
9652
9653 public Element getAttackElement()
9654 {
9655 return Formulas.getAttackElement(this, null);
9656 }
9657
9658 public int getAttack(Element element)
9659 {
9660 if (element == Element.NONE)
9661 {
9662 return 0;
9663 }
9664 return (int) calcStat(element.getAttack(), 0., null, null);
9665 }
9666
9667 public int getDefence(Element element)
9668 {
9669 if (element == Element.NONE)
9670 {
9671 return 0;
9672 }
9673 return (int) calcStat(element.getDefence(), 0., null, null);
9674 }
9675
9676 public boolean getAndSetLastItemAuctionRequest()
9677 {
9678 if ((_lastItemAuctionInfoRequest + 2000L) < System.currentTimeMillis())
9679 {
9680 _lastItemAuctionInfoRequest = System.currentTimeMillis();
9681 return true;
9682 }
9683 else
9684 {
9685 _lastItemAuctionInfoRequest = System.currentTimeMillis();
9686 return false;
9687 }
9688 }
9689
9690 @Override
9691 public int getNpcId()
9692 {
9693 return -2;
9694 }
9695
9696 public GameObject getVisibleObject(int id)
9697 {
9698 if (getObjectId() == id)
9699 {
9700 return this;
9701 }
9702
9703 GameObject target = null;
9704
9705 if (getTargetId() == id)
9706 {
9707 target = getTarget();
9708 }
9709
9710 if ((target == null) && (_party != null))
9711 {
9712 for (Player p : _party.getMembers())
9713 {
9714 if ((p != null) && (p.getObjectId() == id))
9715 {
9716 target = p;
9717 break;
9718 }
9719 }
9720 }
9721
9722 if (target == null)
9723 {
9724 target = World.getAroundObjectById(this, id);
9725 }
9726
9727 return (target == null) || target.isInvisible() ? null : target;
9728 }
9729
9730 @Override
9731 public int getPAtk(final Creature target)
9732 {
9733 double init = getActiveWeaponInstance() == null ? (isMageClass() ? 3 : 4) : 0;
9734 return (int) calcStat(Stats.POWER_ATTACK, init, target, null);
9735 }
9736
9737 @Override
9738 public int getPDef(final Creature target)
9739 {
9740 double init = 4.; // empty cloak and underwear slots
9741
9742 final ItemInstance chest = getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
9743 if (chest == null)
9744 {
9745 init += isMageClass() ? ArmorTemplate.EMPTY_BODY_MYSTIC : ArmorTemplate.EMPTY_BODY_FIGHTER;
9746 }
9747 if ((getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS) == null) && ((chest == null) || (chest.getBodyPart() != ItemTemplate.SLOT_FULL_ARMOR)))
9748 {
9749 init += isMageClass() ? ArmorTemplate.EMPTY_LEGS_MYSTIC : ArmorTemplate.EMPTY_LEGS_FIGHTER;
9750 }
9751
9752 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_HEAD) == null)
9753 {
9754 init += ArmorTemplate.EMPTY_HELMET;
9755 }
9756 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_GLOVES) == null)
9757 {
9758 init += ArmorTemplate.EMPTY_GLOVES;
9759 }
9760 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_FEET) == null)
9761 {
9762 init += ArmorTemplate.EMPTY_BOOTS;
9763 }
9764
9765 return (int) calcStat(Stats.POWER_DEFENCE, init, target, null);
9766 }
9767
9768 @Override
9769 public int getMDef(final Creature target, final Skill skill)
9770 {
9771 double init = 0.;
9772
9773 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEAR) == null)
9774 {
9775 init += ArmorTemplate.EMPTY_EARRING;
9776 }
9777 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_REAR) == null)
9778 {
9779 init += ArmorTemplate.EMPTY_EARRING;
9780 }
9781 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_NECK) == null)
9782 {
9783 init += ArmorTemplate.EMPTY_NECKLACE;
9784 }
9785 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LFINGER) == null)
9786 {
9787 init += ArmorTemplate.EMPTY_RING;
9788 }
9789 if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_RFINGER) == null)
9790 {
9791 init += ArmorTemplate.EMPTY_RING;
9792 }
9793
9794 return (int) calcStat(Stats.MAGIC_DEFENCE, init, target, skill);
9795 }
9796
9797 public boolean isSubClassActive()
9798 {
9799 return getBaseClassId() != getActiveClassId();
9800 }
9801
9802 @Override
9803 public String getTitle()
9804 {
9805 return super.getTitle();
9806 }
9807
9808 public int getTitleColor()
9809 {
9810 return _titlecolor;
9811 }
9812
9813 public void setTitleColor(final int titlecolor)
9814 {
9815 if (titlecolor != DEFAULT_TITLE_COLOR)
9816 {
9817 setVar("titlecolor", Integer.toHexString(titlecolor), -1);
9818 }
9819 else
9820 {
9821 unsetVar("titlecolor");
9822 }
9823 _titlecolor = titlecolor;
9824 }
9825
9826 @Override
9827 public boolean isCursedWeaponEquipped()
9828 {
9829 return _cursedWeaponEquippedId != 0;
9830 }
9831
9832 public void setCursedWeaponEquippedId(int value)
9833 {
9834 _cursedWeaponEquippedId = value;
9835 }
9836
9837 public int getCursedWeaponEquippedId()
9838 {
9839 return _cursedWeaponEquippedId;
9840 }
9841
9842 @Override
9843 public boolean isImmobilized()
9844 {
9845 return super.isImmobilized() || isOverloaded() || isSitting() || isFishing();
9846 }
9847
9848 @Override
9849 public boolean isBlocked()
9850 {
9851 return super.isBlocked() || isInMovie() || isInObserverMode() || isTeleporting() || isLogoutStarted();
9852 }
9853
9854 @Override
9855 public boolean isInvul()
9856 {
9857 return super.isInvul() || isInMovie();
9858 }
9859
9860 /**
9861 * if True, the L2Player can't take more item
9862 * @param overloaded
9863 */
9864 public void setOverloaded(boolean overloaded)
9865 {
9866 _overloaded = overloaded;
9867 }
9868
9869 public boolean isOverloaded()
9870 {
9871 return _overloaded;
9872 }
9873
9874 public boolean isFishing()
9875 {
9876 return _isFishing;
9877 }
9878
9879 public Fishing getFishing()
9880 {
9881 return _fishing;
9882 }
9883
9884 public void setFishing(boolean value)
9885 {
9886 _isFishing = value;
9887 }
9888
9889 public void startFishing(FishTemplate fish, int lureId)
9890 {
9891 _fishing.setFish(fish);
9892 _fishing.setLureId(lureId);
9893 _fishing.startFishing();
9894 }
9895
9896 public void stopFishing()
9897 {
9898 _fishing.stopFishing();
9899 }
9900
9901 public Location getFishLoc()
9902 {
9903 return _fishing.getFishLoc();
9904 }
9905
9906 public Bonus getBonus()
9907 {
9908 return _bonus;
9909 }
9910
9911 public boolean hasBonus()
9912 {
9913 return _bonus.getBonusExpire() > (System.currentTimeMillis() / 1000L);
9914 }
9915
9916 @Override
9917 public double getRateAdena()
9918 {
9919 return _party == null ? _bonus.getDropAdena() : _party._rateAdena;
9920 }
9921
9922 @Override
9923 public double getRateItems()
9924 {
9925 return _party == null ? _bonus.getDropItems() : _party._rateDrop;
9926 }
9927
9928 @Override
9929 public double getRateExp()
9930 {
9931 return calcStat(Stats.EXP, (_party == null ? _bonus.getRateXp() : _party._rateExp), null, null);
9932 }
9933
9934 @Override
9935 public double getRateSp()
9936 {
9937 return calcStat(Stats.SP, (_party == null ? _bonus.getRateSp() : _party._rateSp), null, null);
9938 }
9939
9940 @Override
9941 public double getRateSpoil()
9942 {
9943 return _party == null ? _bonus.getDropSpoil() : _party._rateSpoil;
9944 }
9945
9946 private boolean _maried = false;
9947 private int _partnerId = 0;
9948 private int _coupleId = 0;
9949 private boolean _maryrequest = false;
9950 private boolean _maryaccepted = false;
9951
9952 public boolean isMaried()
9953 {
9954 return _maried;
9955 }
9956
9957 public void setMaried(boolean state)
9958 {
9959 _maried = state;
9960 }
9961
9962 public void setMaryRequest(boolean state)
9963 {
9964 _maryrequest = state;
9965 }
9966
9967 public boolean isMaryRequest()
9968 {
9969 return _maryrequest;
9970 }
9971
9972 public void setMaryAccepted(boolean state)
9973 {
9974 _maryaccepted = state;
9975 }
9976
9977 public boolean isMaryAccepted()
9978 {
9979 return _maryaccepted;
9980 }
9981
9982 public int getPartnerId()
9983 {
9984 return _partnerId;
9985 }
9986
9987 public void setPartnerId(int partnerid)
9988 {
9989 _partnerId = partnerid;
9990 }
9991
9992 public int getCoupleId()
9993 {
9994 return _coupleId;
9995 }
9996
9997 public void setCoupleId(int coupleId)
9998 {
9999 _coupleId = coupleId;
10000 }
10001
10002 public void setUndying(boolean val)
10003 {
10004 if (!isGM())
10005 {
10006 return;
10007 }
10008 _isUndying = val;
10009 }
10010
10011 public boolean isUndying()
10012 {
10013 return _isUndying;
10014 }
10015
10016 private final GArray<Player> _snoopListener = new GArray<Player>();
10017 private final GArray<Player> _snoopedPlayer = new GArray<Player>();
10018
10019 public void broadcastSnoop(int type, String name, String _text)
10020 {
10021 if (_snoopListener.size() > 0)
10022 {
10023 Snoop sn = new Snoop(getObjectId(), getName(), type, name, _text);
10024 for (Player pci : _snoopListener)
10025 {
10026 if (pci != null)
10027 {
10028 pci.sendPacket(sn);
10029 }
10030 }
10031 }
10032 }
10033
10034 public void addSnooper(Player pci)
10035 {
10036 if (!_snoopListener.contains(pci))
10037 {
10038 _snoopListener.add(pci);
10039 }
10040 }
10041
10042 public void removeSnooper(Player pci)
10043 {
10044 _snoopListener.remove(pci);
10045 }
10046
10047 public void addSnooped(Player pci)
10048 {
10049 if (!_snoopedPlayer.contains(pci))
10050 {
10051 _snoopedPlayer.add(pci);
10052 }
10053 }
10054
10055 public void removeSnooped(Player pci)
10056 {
10057 _snoopedPlayer.remove(pci);
10058 }
10059
10060 public void resetReuse()
10061 {
10062 _skillReuses.clear();
10063 _sharedGroupReuses.clear();
10064 }
10065
10066 public DeathPenalty getDeathPenalty()
10067 {
10068 return _activeClass == null ? null : _activeClass.getDeathPenalty(this);
10069 }
10070
10071 private boolean _charmOfCourage = false;
10072
10073 public boolean isCharmOfCourage()
10074 {
10075 return _charmOfCourage;
10076 }
10077
10078 public void setCharmOfCourage(boolean val)
10079 {
10080 _charmOfCourage = val;
10081
10082 if (!val)
10083 {
10084 getEffectList().stopEffect(Skill.SKILL_CHARM_OF_COURAGE);
10085 }
10086
10087 sendEtcStatusUpdate();
10088 }
10089
10090 private int _increasedForce = 0;
10091 private int _consumedSouls = 0;
10092
10093 @Override
10094 public int getIncreasedForce()
10095 {
10096 return _increasedForce;
10097 }
10098
10099 @Override
10100 public int getConsumedSouls()
10101 {
10102 return _consumedSouls;
10103 }
10104
10105 @Override
10106 public void setConsumedSouls(int i, NpcInstance monster)
10107 {
10108 if (i == _consumedSouls)
10109 {
10110 return;
10111 }
10112
10113 int max = (int) calcStat(Stats.SOULS_LIMIT, 0, monster, null);
10114
10115 if (i > max)
10116 {
10117 i = max;
10118 }
10119
10120 if (i <= 0)
10121 {
10122 _consumedSouls = 0;
10123 sendEtcStatusUpdate();
10124 return;
10125 }
10126
10127 if (_consumedSouls != i)
10128 {
10129 int diff = i - _consumedSouls;
10130 if (diff > 0)
10131 {
10132 SystemMessage sm = new SystemMessage(SystemMessage.YOUR_SOUL_HAS_INCREASED_BY_S1_SO_IT_IS_NOW_AT_S2);
10133 sm.addNumber(diff);
10134 sm.addNumber(i);
10135 sendPacket(sm);
10136 }
10137 }
10138 else if (max == i)
10139 {
10140 sendPacket(Msg.SOUL_CANNOT_BE_ABSORBED_ANY_MORE);
10141 return;
10142 }
10143
10144 _consumedSouls = i;
10145 sendPacket(new EtcStatusUpdate(this));
10146 }
10147
10148 @Override
10149 public void setIncreasedForce(int i)
10150 {
10151 i = Math.min(i, Charge.MAX_CHARGE);
10152 i = Math.max(i, 0);
10153
10154 if ((i != 0) && (i > _increasedForce))
10155 {
10156 sendPacket(new SystemMessage(SystemMessage.YOUR_FORCE_HAS_INCREASED_TO_S1_LEVEL).addNumber(i));
10157 }
10158
10159 _increasedForce = i;
10160 sendEtcStatusUpdate();
10161 }
10162
10163 private long _lastFalling;
10164
10165 public boolean isFalling()
10166 {
10167 return (System.currentTimeMillis() - _lastFalling) < 5000;
10168 }
10169
10170 public void falling(int height)
10171 {
10172 if (!Config.DAMAGE_FROM_FALLING || isDead() || isFlying() || isInWater() || isInBoat())
10173 {
10174 return;
10175 }
10176 _lastFalling = System.currentTimeMillis();
10177 int damage = (int) calcStat(Stats.FALL, (getMaxHp() / 2000) * height, null, null);
10178 if (damage > 0)
10179 {
10180 int curHp = (int) getCurrentHp();
10181 if ((curHp - damage) < 1)
10182 {
10183 setCurrentHp(1, false);
10184 }
10185 else
10186 {
10187 setCurrentHp(curHp - damage, false);
10188 }
10189 sendPacket(new SystemMessage(SystemMessage.YOU_RECEIVED_S1_DAMAGE_FROM_TAKING_A_HIGH_FALL).addNumber(damage));
10190 }
10191 }
10192
10193 @Override
10194 public void checkHpMessages(double curHp, double newHp)
10195 {
10196 int[] _hp =
10197 {
10198 30,
10199 30
10200 };
10201 int[] skills =
10202 {
10203 290,
10204 291
10205 };
10206
10207 int[] _effects_skills_id =
10208 {
10209 139,
10210 176,
10211 292,
10212 292,
10213 420
10214 };
10215 int[] _effects_hp =
10216 {
10217 30,
10218 30,
10219 30,
10220 60,
10221 30
10222 };
10223
10224 double percent = getMaxHp() / 100;
10225 double _curHpPercent = curHp / percent;
10226 double _newHpPercent = newHp / percent;
10227 boolean needsUpdate = false;
10228
10229 // check for passive skills
10230 for (int i = 0; i < skills.length; i++)
10231 {
10232 int level = getSkillLevel(skills[i]);
10233 if (level > 0)
10234 {
10235 if ((_curHpPercent > _hp[i]) && (_newHpPercent <= _hp[i]))
10236 {
10237 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_DECREASED_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(skills[i], level));
10238 needsUpdate = true;
10239 }
10240 else if ((_curHpPercent <= _hp[i]) && (_newHpPercent > _hp[i]))
10241 {
10242 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_INCREASED_THE_EFFECT_OF_S1_WILL_DISAPPEAR).addSkillName(skills[i], level));
10243 needsUpdate = true;
10244 }
10245 }
10246 }
10247
10248 // check for active effects
10249 for (Integer i = 0; i < _effects_skills_id.length; i++)
10250 {
10251 if (getEffectList().getEffectsBySkillId(_effects_skills_id[i]) != null)
10252 {
10253 if ((_curHpPercent > _effects_hp[i]) && (_newHpPercent <= _effects_hp[i]))
10254 {
10255 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_DECREASED_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(_effects_skills_id[i], 1));
10256 needsUpdate = true;
10257 }
10258 else if ((_curHpPercent <= _effects_hp[i]) && (_newHpPercent > _effects_hp[i]))
10259 {
10260 sendPacket(new SystemMessage(SystemMessage.SINCE_HP_HAS_INCREASED_THE_EFFECT_OF_S1_WILL_DISAPPEAR).addSkillName(_effects_skills_id[i], 1));
10261 needsUpdate = true;
10262 }
10263 }
10264 }
10265
10266 if (needsUpdate)
10267 {
10268 sendChanges();
10269 }
10270 }
10271
10272 public void checkDayNightMessages()
10273 {
10274 int level = getSkillLevel(294);
10275 if (level > 0)
10276 {
10277 if (GameTimeController.getInstance().isNowNight())
10278 {
10279 sendPacket(new SystemMessage(SystemMessage.IT_IS_NOW_MIDNIGHT_AND_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(294, level));
10280 }
10281 else
10282 {
10283 sendPacket(new SystemMessage(SystemMessage.IT_IS_DAWN_AND_THE_EFFECT_OF_S1_WILL_NOW_DISAPPEAR).addSkillName(294, level));
10284 }
10285 }
10286 sendChanges();
10287 }
10288
10289 public int getZoneMask()
10290 {
10291 return _zoneMask;
10292 }
10293
10294 @Override
10295 protected void onUpdateZones(List<Zone> leaving, List<Zone> entering)
10296 {
10297 super.onUpdateZones(leaving, entering);
10298
10299 if (((leaving == null) || leaving.isEmpty()) && ((entering == null) || entering.isEmpty()))
10300 {
10301 return;
10302 }
10303
10304 boolean lastInCombatZone = (_zoneMask & ZONE_PVP_FLAG) == ZONE_PVP_FLAG;
10305 boolean lastInDangerArea = (_zoneMask & ZONE_ALTERED_FLAG) == ZONE_ALTERED_FLAG;
10306 boolean lastOnSiegeField = (_zoneMask & ZONE_SIEGE_FLAG) == ZONE_SIEGE_FLAG;
10307 boolean lastInPeaceZone = (_zoneMask & ZONE_PEACE_FLAG) == ZONE_PEACE_FLAG;
10308 @SuppressWarnings("unused")
10309 boolean lastInSSQZone = (_zoneMask & ZONE_SSQ_FLAG) == ZONE_SSQ_FLAG;
10310
10311 boolean isInCombatZone = isInCombatZone();
10312 boolean isInDangerArea = isInDangerArea();
10313 boolean isOnSiegeField = isOnSiegeField();
10314 boolean isInPeaceZone = isInPeaceZone();
10315 boolean isInSSQZone = isInSSQZone();
10316
10317 // update the compass, only if the character in the world
10318 int lastZoneMask = _zoneMask;
10319 _zoneMask = 0;
10320
10321 if (isInCombatZone)
10322 {
10323 _zoneMask |= ZONE_PVP_FLAG;
10324 }
10325 if (isInDangerArea)
10326 {
10327 _zoneMask |= ZONE_ALTERED_FLAG;
10328 }
10329 if (isOnSiegeField)
10330 {
10331 _zoneMask |= ZONE_SIEGE_FLAG;
10332 }
10333 if (isInPeaceZone)
10334 {
10335 _zoneMask |= ZONE_PEACE_FLAG;
10336 }
10337 if (isInSSQZone)
10338 {
10339 _zoneMask |= ZONE_SSQ_FLAG;
10340 }
10341
10342 if (lastZoneMask != _zoneMask)
10343 {
10344 sendPacket(new ExSetCompassZoneCode(this));
10345 }
10346
10347 if (lastInCombatZone != isInCombatZone)
10348 {
10349 broadcastRelationChanged();
10350 }
10351
10352 if (lastInDangerArea != isInDangerArea)
10353 {
10354 sendPacket(new EtcStatusUpdate(this));
10355 }
10356
10357 if (lastOnSiegeField != isOnSiegeField)
10358 {
10359 broadcastRelationChanged();
10360 if (isOnSiegeField)
10361 {
10362 sendPacket(Msg.YOU_HAVE_ENTERED_A_COMBAT_ZONE);
10363 }
10364 else
10365 {
10366 sendPacket(Msg.YOU_HAVE_LEFT_A_COMBAT_ZONE);
10367 if (!isTeleporting() && (getPvpFlag() == 0))
10368 {
10369 startPvPFlag(null);
10370 }
10371 }
10372 }
10373
10374 if (lastInPeaceZone != isInPeaceZone)
10375 {
10376 if (isInPeaceZone)
10377 {
10378 setRecomTimerActive(false);
10379 if (getNevitSystem().isActive())
10380 {
10381 getNevitSystem().stopAdventTask(true);
10382 }
10383 startVitalityTask();
10384 }
10385 else
10386 {
10387 stopVitalityTask();
10388 }
10389 }
10390
10391 if (isInWater())
10392 {
10393 startWaterTask();
10394 }
10395 else
10396 {
10397 stopWaterTask();
10398 }
10399 }
10400
10401 public void startAutoSaveTask()
10402 {
10403 if (!Config.AUTOSAVE)
10404 {
10405 return;
10406 }
10407 if (_autoSaveTask == null)
10408 {
10409 _autoSaveTask = AutoSaveManager.getInstance().addAutoSaveTask(this);
10410 }
10411 }
10412
10413 public void stopAutoSaveTask()
10414 {
10415 if (_autoSaveTask != null)
10416 {
10417 _autoSaveTask.cancel(false);
10418 }
10419 _autoSaveTask = null;
10420 }
10421
10422 public void startVitalityTask()
10423 {
10424 if (!Config.ALT_VITALITY_ENABLED)
10425 {
10426 return;
10427 }
10428 if (_vitalityTask == null)
10429 {
10430 _vitalityTask = LazyPrecisionTaskManager.getInstance().addVitalityRegenTask(this);
10431 }
10432 }
10433
10434 public void stopVitalityTask()
10435 {
10436 if (_vitalityTask != null)
10437 {
10438 _vitalityTask.cancel(false);
10439 }
10440 _vitalityTask = null;
10441 }
10442
10443 public void startPcBangPointsTask()
10444 {
10445 if (!Config.ALT_PCBANG_POINTS_ENABLED || (Config.ALT_PCBANG_POINTS_DELAY <= 0))
10446 {
10447 return;
10448 }
10449 if (_pcCafePointsTask == null)
10450 {
10451 _pcCafePointsTask = LazyPrecisionTaskManager.getInstance().addPCCafePointsTask(this);
10452 }
10453 }
10454
10455 public void stopPcBangPointsTask()
10456 {
10457 if (_pcCafePointsTask != null)
10458 {
10459 _pcCafePointsTask.cancel(false);
10460 }
10461 _pcCafePointsTask = null;
10462 }
10463
10464 public final boolean isInJail()
10465 {
10466 return getVarB("jailed");
10467 }
10468
10469 @Override
10470 public void sendMessage(String message)
10471 {
10472 sendPacket(new SystemMessage(message));
10473 }
10474
10475 private Location _lastClientPosition;
10476 private Location _lastServerPosition;
10477
10478 public void setLastClientPosition(Location position)
10479 {
10480 _lastClientPosition = position;
10481 }
10482
10483 public Location getLastClientPosition()
10484 {
10485 return _lastClientPosition;
10486 }
10487
10488 public void setLastServerPosition(Location position)
10489 {
10490 _lastServerPosition = position;
10491 }
10492
10493 public Location getLastServerPosition()
10494 {
10495 return _lastServerPosition;
10496 }
10497
10498 public ClickersDetector getClickersDetector()
10499 {
10500 if (_detector == null)
10501 _detector = new ClickersDetector(this);
10502 return _detector;
10503 }
10504
10505 public void setHwidLock(String hwid)
10506 {
10507 _hwidLock = hwid;
10508 }
10509
10510 public String getHwidLock()
10511 {
10512 return _hwidLock;
10513 }
10514
10515 private int _useSeed = 0;
10516
10517 public void setUseSeed(int id)
10518 {
10519 _useSeed = id;
10520 }
10521
10522 public int getUseSeed()
10523 {
10524 return _useSeed;
10525 }
10526
10527 public int getFriendRelation()
10528 {
10529 int result = 0;
10530
10531 result |= RelationChanged.RELATION_CLAN_MEMBER;
10532 result |= RelationChanged.RELATION_CLAN_MATE;
10533
10534 return result;
10535 }
10536
10537 public int getWarRelation()
10538 {
10539 int result = 0;
10540
10541 result |= RelationChanged.RELATION_CLAN_MEMBER;
10542 result |= RelationChanged.RELATION_1SIDED_WAR;
10543 result |= RelationChanged.RELATION_MUTUAL_WAR;
10544
10545 return result;
10546 }
10547
10548 public int getRelation(Player target)
10549 {
10550 if (getTeam() != TeamType.NONE && target.getTeam() != TeamType.NONE)
10551 return getTeam() == target.getTeam() ? getFriendRelation() : getWarRelation();
10552
10553 int result = 0;
10554
10555 if (getClan() != null)
10556 {
10557 result |= RelationChanged.RELATION_CLAN_MEMBER;
10558 if (getClan() == target.getClan())
10559 {
10560 result |= RelationChanged.RELATION_CLAN_MATE;
10561 }
10562 if (getClan().getAllyId() != 0)
10563 {
10564 result |= RelationChanged.RELATION_ALLY_MEMBER;
10565 }
10566 }
10567
10568 if (isClanLeader())
10569 {
10570 result |= RelationChanged.RELATION_LEADER;
10571 }
10572
10573 Party party = getParty();
10574 if ((party != null) && (party == target.getParty()))
10575 {
10576 result |= RelationChanged.RELATION_HAS_PARTY;
10577
10578 switch (party.getMembers().indexOf(this))
10579 {
10580 case 0:
10581 result |= RelationChanged.RELATION_PARTYLEADER; // 0x10
10582 break;
10583 case 1:
10584 result |= RelationChanged.RELATION_PARTY4; // 0x8
10585 break;
10586 case 2:
10587 result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY2 + RelationChanged.RELATION_PARTY1; // 0x7
10588 break;
10589 case 3:
10590 result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY2; // 0x6
10591 break;
10592 case 4:
10593 result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY1; // 0x5
10594 break;
10595 case 5:
10596 result |= RelationChanged.RELATION_PARTY3; // 0x4
10597 break;
10598 case 6:
10599 result |= RelationChanged.RELATION_PARTY2 + RelationChanged.RELATION_PARTY1; // 0x3
10600 break;
10601 case 7:
10602 result |= RelationChanged.RELATION_PARTY2; // 0x2
10603 break;
10604 case 8:
10605 result |= RelationChanged.RELATION_PARTY1; // 0x1
10606 break;
10607 }
10608 }
10609
10610 Clan clan1 = getClan();
10611 Clan clan2 = target.getClan();
10612 if ((clan1 != null) && (clan2 != null))
10613 {
10614 if ((target.getPledgeType() != Clan.SUBUNIT_ACADEMY) && (getPledgeType() != Clan.SUBUNIT_ACADEMY))
10615 {
10616 if (clan2.isAtWarWith(clan1.getClanId()))
10617 {
10618 result |= RelationChanged.RELATION_1SIDED_WAR;
10619 if (clan1.isAtWarWith(clan2.getClanId()))
10620 {
10621 result |= RelationChanged.RELATION_MUTUAL_WAR;
10622 }
10623 }
10624 }
10625 if (getBlockCheckerArena() != -1)
10626 {
10627 result |= RelationChanged.RELATION_INSIEGE;
10628 ArenaParticipantsHolder holder = HandysBlockCheckerManager.getInstance().getHolder(getBlockCheckerArena());
10629 if (holder.getPlayerTeam(this) == 0)
10630 {
10631 result |= RelationChanged.RELATION_ENEMY;
10632 }
10633 else
10634 {
10635 result |= RelationChanged.RELATION_ALLY;
10636 }
10637 result |= RelationChanged.RELATION_ATTACKER;
10638 }
10639 }
10640
10641 for (GlobalEvent e : getEvents())
10642 {
10643 result = e.getRelation(this, target, result);
10644 }
10645
10646 return result;
10647 }
10648
10649 /**
10650 * 0=White, 1=Purple, 2=PurpleBlink
10651 */
10652 protected int _pvpFlag;
10653
10654 private ScheduledFuture<?> _PvPRegTask;
10655 private long _lastPvpAttack;
10656
10657 public long getlastPvpAttack()
10658 {
10659 return _lastPvpAttack;
10660 }
10661
10662 @Override
10663 public void startPvPFlag(Creature target)
10664 {
10665 if (_karma > 0)
10666 return;
10667
10668 long startTime = System.currentTimeMillis();
10669 if (target != null && (target.getPvpFlag() != 0 || target.isMonster()))
10670 startTime -= Config.PVP_TIME / 2;
10671
10672 if (_pvpFlag != 0 && _lastPvpAttack > startTime)
10673 return;
10674
10675 _lastPvpAttack = startTime;
10676
10677 updatePvPFlag(1);
10678
10679 if (_PvPRegTask == null)
10680 _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
10681 }
10682
10683 public void stopPvPFlag()
10684 {
10685 if (_PvPRegTask != null)
10686 {
10687 _PvPRegTask.cancel(false);
10688 _PvPRegTask = null;
10689 }
10690 updatePvPFlag(0);
10691 }
10692
10693 public void updatePvPFlag(int value)
10694 {
10695 if (_handysBlockCheckerEventArena != -1)
10696 {
10697 return;
10698 }
10699 if (_pvpFlag == value)
10700 {
10701 return;
10702 }
10703
10704 setPvpFlag(value);
10705
10706 sendStatusUpdate(true, true, StatusUpdate.PVP_FLAG);
10707
10708 broadcastRelationChanged();
10709 }
10710
10711 public void setPvpFlag(int pvpFlag)
10712 {
10713 _pvpFlag = pvpFlag;
10714 }
10715
10716 /**
10717 * @return The remaning time of the pvp flag in miliseconds.
10718 */
10719 public int getPvpFlagRemaningTime()
10720 {
10721 if (_PvPRegTask == null || _PvPRegTask.isDone())
10722 return 0;
10723
10724 return (int) _PvPRegTask.getDelay(TimeUnit.MILLISECONDS);
10725 }
10726
10727 @Override
10728 public int getPvpFlag()
10729 {
10730 return _pvpFlag;
10731 }
10732
10733 public boolean isInDuel()
10734 {
10735 return getEvent(DuelEvent.class) != null;
10736 }
10737
10738 public boolean isRegisteredInFightClub()
10739 {
10740 return getEvent(AbstractFightClub.class) != null;
10741 }
10742
10743 public boolean isInFightClub()
10744 {
10745 try
10746 {
10747 if (getEvent(AbstractFightClub.class) == null)
10748 return false;
10749
10750 return getEvent(AbstractFightClub.class).getFightClubPlayer(this) != null;
10751 }
10752 catch (NullPointerException e)
10753 {
10754 return false;
10755 }
10756 }
10757
10758 public FightClubGameRoom getFightClubGameRoom()
10759 {
10760 return _fightClubGameRoom;
10761 }
10762
10763 public void setFightClubGameRoom(FightClubGameRoom room)
10764 {
10765 _fightClubGameRoom = room;
10766 }
10767
10768 public AbstractFightClub getFightClubEvent()
10769 {
10770 return getEvent(AbstractFightClub.class);
10771 }
10772
10773 private final Map<Integer, TamedBeastInstance> _tamedBeasts = new ConcurrentHashMap<Integer, TamedBeastInstance>();
10774
10775 public Map<Integer, TamedBeastInstance> getTrainedBeasts()
10776 {
10777 return _tamedBeasts;
10778 }
10779
10780 public void addTrainedBeast(TamedBeastInstance tamedBeast)
10781 {
10782 _tamedBeasts.put(tamedBeast.getObjectId(), tamedBeast);
10783 }
10784
10785 public void removeTrainedBeast(int npcId)
10786 {
10787 _tamedBeasts.remove(npcId);
10788 }
10789
10790 private long _lastAttackPacket = 0;
10791
10792 public long getLastAttackPacket()
10793 {
10794 return _lastAttackPacket;
10795 }
10796
10797 public void setLastAttackPacket()
10798 {
10799 _lastAttackPacket = System.currentTimeMillis();
10800 }
10801
10802 private long _lastMovePacket = 0;
10803
10804 public long getLastMovePacket()
10805 {
10806 return _lastMovePacket;
10807 }
10808
10809 public void setLastMovePacket()
10810 {
10811 _lastMovePacket = System.currentTimeMillis();
10812 }
10813
10814 public byte[] getKeyBindings()
10815 {
10816 return _keyBindings;
10817 }
10818
10819 public void setKeyBindings(byte[] keyBindings)
10820 {
10821 if (keyBindings == null)
10822 {
10823 _keyBindings = ArrayUtils.EMPTY_BYTE_ARRAY;
10824 }
10825 else
10826 {
10827 _keyBindings = keyBindings;
10828 }
10829 }
10830
10831 public void setTransformation(int transformationId)
10832 {
10833 if ((transformationId == _transformationId) || ((_transformationId != 0) && (transformationId != 0)))
10834 {
10835 return;
10836 }
10837
10838 if (transformationId == 0)
10839 {
10840 for (Effect effect : getEffectList().getAllEffects())
10841 {
10842 if ((effect != null) && (effect.getEffectType() == EffectType.Transformation))
10843 {
10844 if (effect.calc() == 0)
10845 {
10846 continue;
10847 }
10848 effect.exit();
10849 preparateToTransform(effect.getSkill());
10850 break;
10851 }
10852 }
10853
10854 if (!_transformationSkills.isEmpty())
10855 {
10856 for (Skill s : _transformationSkills.values())
10857 {
10858 if (!s.isCommon() && !SkillAcquireHolder.getInstance().isSkillPossible(this, s) && !s.isHeroic())
10859 {
10860 super.removeSkill(s);
10861 }
10862 }
10863 _transformationSkills.clear();
10864 }
10865 }
10866 else
10867 {
10868 int _id = 0;
10869 int _level = 1;
10870 switch (getBaseClassId())
10871 {
10872 case 97:// Cardinal
10873 _id = 24001;
10874 break;
10875 case 98:// Hierophant
10876 _id = 24002;
10877 break;
10878 case 100:// SwordMuse
10879 _id = 24003;
10880 break;
10881 case 105:// EvaSaint
10882 _id = 24004;
10883 break;
10884 case 107:// SpectralDancer
10885 _id = 24005;
10886 break;
10887 case 112:// ShillienSaint
10888 _id = 24006;
10889 break;
10890 case 115:// Dominator
10891 _id = 24007;
10892 break;
10893 case 116:// Doomcryer
10894 _id = 24008;
10895 break;
10896 }
10897
10898 Skill _skill = SkillTable.getInstance().getInfo(_id, _level);
10899 if (_skill != null)
10900 {
10901 super.removeSkill(_skill);
10902 removeSkillFromShortCut(_skill.getId());
10903 }
10904
10905 if (!isCursedWeaponEquipped())
10906 {
10907 for (Effect effect : getEffectList().getAllEffects())
10908 {
10909 if ((effect != null) && (effect.getEffectType() == EffectType.Transformation))
10910 {
10911 if ((effect.getSkill() instanceof Transformation) && ((Transformation) effect.getSkill()).isDisguise)
10912 {
10913 for (Skill s : getAllSkills())
10914 {
10915 if ((s != null) && (s.isActive() || s.isToggle()))
10916 {
10917 _transformationSkills.put(s.getId(), s);
10918 }
10919 }
10920 }
10921 else
10922 {
10923 for (AddedSkill s : effect.getSkill().getAddedSkills())
10924 {
10925 if (s.level == 0)
10926 {
10927 int s2 = getSkillLevel(s.id);
10928 if (s2 > 0)
10929 {
10930 _transformationSkills.put(s.id, SkillTable.getInstance().getInfo(s.id, s2));
10931 }
10932 }
10933 else if (s.level == -2) // XXX: wild heartburn for skills depending on the player's level
10934 {
10935 int learnLevel = Math.max(effect.getSkill().getMagicLevel(), 40);
10936 int maxLevel = SkillTable.getInstance().getBaseLevel(s.id);
10937 int curSkillLevel = 1;
10938 if (maxLevel > 3)
10939 {
10940 curSkillLevel += getLevel() - learnLevel;
10941 }
10942 else
10943 {
10944 curSkillLevel += (getLevel() - learnLevel) / ((76 - learnLevel) / maxLevel);
10945 }
10946 curSkillLevel = Math.min(Math.max(curSkillLevel, 1), maxLevel);
10947 _transformationSkills.put(s.id, SkillTable.getInstance().getInfo(s.id, curSkillLevel));
10948 }
10949 else
10950 {
10951 _transformationSkills.put(s.id, s.getSkill());
10952 }
10953 }
10954 }
10955 preparateToTransform(effect.getSkill());
10956 break;
10957 }
10958 }
10959 }
10960 else
10961 {
10962 preparateToTransform(null);
10963 }
10964
10965 if (!isInOlympiadMode() && !isCursedWeaponEquipped() && _hero && (getBaseClassId() == getActiveClassId()))
10966 {
10967 _transformationSkills.put(395, SkillTable.getInstance().getInfo(395, 1));
10968 _transformationSkills.put(396, SkillTable.getInstance().getInfo(396, 1));
10969 _transformationSkills.put(1374, SkillTable.getInstance().getInfo(1374, 1));
10970 _transformationSkills.put(1375, SkillTable.getInstance().getInfo(1375, 1));
10971 _transformationSkills.put(1376, SkillTable.getInstance().getInfo(1376, 1));
10972 }
10973
10974 for (Skill s : _transformationSkills.values())
10975 {
10976 addSkill(s, false);
10977 }
10978 }
10979
10980 _transformationId = transformationId;
10981
10982 sendPacket(new ExBasicActionList(this));
10983 sendPacket(new SkillList(this));
10984 sendPacket(new ShortCutInit(this));
10985 for (int shotId : getAutoSoulShot())
10986 {
10987 sendPacket(new ExAutoSoulShot(shotId, true));
10988 }
10989 broadcastUserInfo(true);
10990 }
10991
10992 private void preparateToTransform(Skill transSkill)
10993 {
10994 if ((transSkill == null) || !transSkill.isBaseTransformation())
10995 {
10996 for (Effect effect : getEffectList().getAllEffects())
10997 {
10998 if ((effect != null) && effect.getSkill().isToggle())
10999 {
11000 effect.exit();
11001 }
11002 }
11003 }
11004 }
11005
11006 public boolean isInFlyingTransform()
11007 {
11008 return (_transformationId == 8) || (_transformationId == 9) || (_transformationId == 260);
11009 }
11010
11011 public boolean isInMountTransform()
11012 {
11013 return (_transformationId == 106) || (_transformationId == 109) || (_transformationId == 110) || (_transformationId == 20001);
11014 }
11015
11016 public int getTransformation()
11017 {
11018 return _transformationId;
11019 }
11020
11021 public String getTransformationName()
11022 {
11023 return _transformationName;
11024 }
11025
11026 public void setTransformationName(String name)
11027 {
11028 _transformationName = name;
11029 }
11030
11031 public void setTransformationTemplate(int template)
11032 {
11033 _transformationTemplate = template;
11034 }
11035
11036 public int getTransformationTemplate()
11037 {
11038 return _transformationTemplate;
11039 }
11040
11041 @Override
11042 public final Collection<Skill> getAllSkills()
11043 {
11044 if (_transformationId == 0)
11045 {
11046 return super.getAllSkills();
11047 }
11048
11049 Map<Integer, Skill> tempSkills = new HashMap<Integer, Skill>();
11050 for (Skill s : super.getAllSkills())
11051 {
11052 if ((s != null) && !s.isActive() && !s.isToggle())
11053 {
11054 tempSkills.put(s.getId(), s);
11055 }
11056 }
11057 tempSkills.putAll(_transformationSkills);
11058 return tempSkills.values();
11059 }
11060
11061 public void setAgathion(int id)
11062 {
11063 if (_agathionId == id)
11064 {
11065 return;
11066 }
11067
11068 _agathionId = id;
11069 broadcastCharInfo();
11070 }
11071
11072 public int getAgathionId()
11073 {
11074 return _agathionId;
11075 }
11076
11077 public int getPcBangPoints()
11078 {
11079 return _pcBangPoints;
11080 }
11081
11082 public void setPcBangPoints(int val)
11083 {
11084 _pcBangPoints = val;
11085 }
11086
11087 public void addPcBangPoints(int count, boolean doublePoints)
11088 {
11089 if (doublePoints)
11090 {
11091 count *= 2;
11092 }
11093
11094 _pcBangPoints += count;
11095
11096 sendPacket(new SystemMessage(doublePoints ? SystemMessage.DOUBLE_POINTS_YOU_AQUIRED_S1_PC_BANG_POINT : SystemMessage.YOU_ACQUIRED_S1_PC_BANG_POINT).addNumber(count));
11097 sendPacket(new ExPCCafePointInfo(this, count, 1, 2, 12));
11098 }
11099
11100 public boolean reducePcBangPoints(int count)
11101 {
11102 if (_pcBangPoints < count)
11103 {
11104 return false;
11105 }
11106
11107 _pcBangPoints -= count;
11108 sendPacket(new SystemMessage(SystemMessage.YOU_ARE_USING_S1_POINT).addNumber(count));
11109 sendPacket(new ExPCCafePointInfo(this, 0, 1, 2, 12));
11110 return true;
11111 }
11112
11113 private Location _groundSkillLoc;
11114
11115 public void setGroundSkillLoc(Location location)
11116 {
11117 _groundSkillLoc = location;
11118 }
11119
11120 public Location getGroundSkillLoc()
11121 {
11122 return _groundSkillLoc;
11123 }
11124
11125 public boolean isLogoutStarted()
11126 {
11127 return _isLogout.get();
11128 }
11129
11130 public void setOfflineMode(boolean val)
11131 {
11132 if (!val)
11133 {
11134 unsetVar("offline");
11135 }
11136 _offline = val;
11137 }
11138
11139 public boolean isInOfflineMode()
11140 {
11141 return _offline;
11142 }
11143
11144 public void saveTradeList()
11145 {
11146 StringBuilder tradeListBuilder = new StringBuilder();
11147
11148 if ((_sellList == null) || _sellList.isEmpty())
11149 {
11150 unsetVar("selllist");
11151 }
11152 else
11153 {
11154 for (TradeItem i : _sellList)
11155 {
11156 tradeListBuilder.append(i.getObjectId()).append(";").append(i.getCount()).append(";").append(i.getOwnersPrice()).append(":");
11157 }
11158 setVar("selllist", tradeListBuilder.toString(), -1);
11159 tradeListBuilder.delete(0, tradeListBuilder.length());
11160 if ((_tradeList != null) && (getSellStoreName() != null))
11161 {
11162 setVar("sellstorename", getSellStoreName(), -1);
11163 }
11164 }
11165
11166 if ((_packageSellList == null) || _packageSellList.isEmpty())
11167 {
11168 unsetVar("packageselllist");
11169 }
11170 else
11171 {
11172 for (TradeItem i : _packageSellList)
11173 {
11174 tradeListBuilder.append(i.getObjectId()).append(";").append(i.getCount()).append(";").append(i.getOwnersPrice()).append(":");
11175 }
11176 setVar("packageselllist", tradeListBuilder.toString(), -1);
11177 tradeListBuilder.delete(0, tradeListBuilder.length());
11178 if ((_tradeList != null) && (getSellStoreName() != null))
11179 {
11180 setVar("sellstorename", getSellStoreName(), -1);
11181 }
11182 }
11183
11184 if ((_buyList == null) || _buyList.isEmpty())
11185 {
11186 unsetVar("buylist");
11187 }
11188 else
11189 {
11190 for (TradeItem i : _buyList)
11191 {
11192 tradeListBuilder.append(i.getItemId()).append(";").append(i.getCount()).append(";").append(i.getOwnersPrice()).append(":");
11193 }
11194 setVar("buylist", tradeListBuilder.toString(), -1);
11195 tradeListBuilder.delete(0, tradeListBuilder.length());
11196 if ((_tradeList != null) && (getBuyStoreName() != null))
11197 {
11198 setVar("buystorename", getBuyStoreName(), -1);
11199 }
11200 }
11201
11202 if ((_createList == null) || _createList.isEmpty())
11203 {
11204 unsetVar("createlist");
11205 }
11206 else
11207 {
11208 for (ManufactureItem i : _createList)
11209 {
11210 tradeListBuilder.append(i.getRecipeId()).append(";").append(i.getCost()).append(":");
11211 }
11212 setVar("createlist", tradeListBuilder.toString(), -1);
11213 if (getManufactureName() != null)
11214 {
11215 setVar("manufacturename", getManufactureName(), -1);
11216 }
11217 }
11218 }
11219
11220 public void restoreTradeList()
11221 {
11222 String var;
11223 var = getVar("selllist");
11224 if (var != null)
11225 {
11226 _sellList = new CopyOnWriteArrayList<TradeItem>();
11227 String[] items = var.split(":");
11228 for (String item : items)
11229 {
11230 if (item.equals(""))
11231 {
11232 continue;
11233 }
11234 String[] values = item.split(";");
11235 if (values.length < 3)
11236 {
11237 continue;
11238 }
11239
11240 int oId = Integer.parseInt(values[0]);
11241 long count = Long.parseLong(values[1]);
11242 long price = Long.parseLong(values[2]);
11243
11244 ItemInstance itemToSell = getInventory().getItemByObjectId(oId);
11245
11246 if ((count < 1) || (itemToSell == null))
11247 {
11248 continue;
11249 }
11250
11251 if (count > itemToSell.getCount())
11252 {
11253 count = itemToSell.getCount();
11254 }
11255
11256 TradeItem i = new TradeItem(itemToSell);
11257 i.setCount(count);
11258 i.setOwnersPrice(price);
11259
11260 _sellList.add(i);
11261 }
11262 var = getVar("sellstorename");
11263 if (var != null)
11264 {
11265 setSellStoreName(var);
11266 }
11267 }
11268 var = getVar("packageselllist");
11269 if (var != null)
11270 {
11271 _packageSellList = new CopyOnWriteArrayList<TradeItem>();
11272 String[] items = var.split(":");
11273 for (String item : items)
11274 {
11275 if (item.equals(""))
11276 {
11277 continue;
11278 }
11279 String[] values = item.split(";");
11280 if (values.length < 3)
11281 {
11282 continue;
11283 }
11284
11285 int oId = Integer.parseInt(values[0]);
11286 long count = Long.parseLong(values[1]);
11287 long price = Long.parseLong(values[2]);
11288
11289 ItemInstance itemToSell = getInventory().getItemByObjectId(oId);
11290
11291 if ((count < 1) || (itemToSell == null))
11292 {
11293 continue;
11294 }
11295
11296 if (count > itemToSell.getCount())
11297 {
11298 count = itemToSell.getCount();
11299 }
11300
11301 TradeItem i = new TradeItem(itemToSell);
11302 i.setCount(count);
11303 i.setOwnersPrice(price);
11304
11305 _packageSellList.add(i);
11306 }
11307 var = getVar("sellstorename");
11308 if (var != null)
11309 {
11310 setSellStoreName(var);
11311 }
11312 }
11313 var = getVar("buylist");
11314 if (var != null)
11315 {
11316 _buyList = new CopyOnWriteArrayList<TradeItem>();
11317 String[] items = var.split(":");
11318 for (String item : items)
11319 {
11320 if (item.equals(""))
11321 {
11322 continue;
11323 }
11324 String[] values = item.split(";");
11325 if (values.length < 3)
11326 {
11327 continue;
11328 }
11329 TradeItem i = new TradeItem();
11330 i.setItemId(Integer.parseInt(values[0]));
11331 i.setCount(Long.parseLong(values[1]));
11332 i.setOwnersPrice(Long.parseLong(values[2]));
11333 _buyList.add(i);
11334 }
11335 var = getVar("buystorename");
11336 if (var != null)
11337 {
11338 setBuyStoreName(var);
11339 }
11340 }
11341 var = getVar("createlist");
11342 if (var != null)
11343 {
11344 _createList = new CopyOnWriteArrayList<ManufactureItem>();
11345 String[] items = var.split(":");
11346 for (String item : items)
11347 {
11348 if (item.equals(""))
11349 {
11350 continue;
11351 }
11352 String[] values = item.split(";");
11353 if (values.length < 2)
11354 {
11355 continue;
11356 }
11357 int recId = Integer.parseInt(values[0]);
11358 long price = Long.parseLong(values[1]);
11359 if (findRecipe(recId))
11360 {
11361 _createList.add(new ManufactureItem(recId, price));
11362 }
11363 }
11364 var = getVar("manufacturename");
11365 if (var != null)
11366 {
11367 setManufactureName(var);
11368 }
11369 }
11370 }
11371
11372 public void restoreRecipeBook(Connection con)
11373 {
11374 try (PreparedStatement statement = con.prepareStatement("SELECT id FROM character_recipebook WHERE char_id=?"))
11375 {
11376 statement.setInt(1, getObjectId());
11377
11378 try (ResultSet rset = statement.executeQuery())
11379 {
11380 while (rset.next())
11381 {
11382 int id = rset.getInt("id");
11383 Recipe recipe = RecipeHolder.getInstance().getRecipeByRecipeId(id);
11384 registerRecipe(recipe, false);
11385 }
11386 }
11387 }
11388 catch (SQLException e)
11389 {
11390 _log.error("Error while restoring Recipe Book for Id "+getObjectId(), e);
11391 }
11392 }
11393
11394 public DecoyInstance getDecoy()
11395 {
11396 return _decoy;
11397 }
11398
11399 public void setDecoy(DecoyInstance decoy)
11400 {
11401 _decoy = decoy;
11402 }
11403
11404 public int getMountType()
11405 {
11406 switch (getMountNpcId())
11407 {
11408 case PetDataTable.STRIDER_WIND_ID:
11409 case PetDataTable.STRIDER_STAR_ID:
11410 case PetDataTable.STRIDER_TWILIGHT_ID:
11411 case PetDataTable.RED_STRIDER_WIND_ID:
11412 case PetDataTable.RED_STRIDER_STAR_ID:
11413 case PetDataTable.RED_STRIDER_TWILIGHT_ID:
11414 case PetDataTable.GUARDIANS_STRIDER_ID:
11415 return 1;
11416 case PetDataTable.WYVERN_ID:
11417 return 2;
11418 case PetDataTable.WGREAT_WOLF_ID:
11419 case PetDataTable.FENRIR_WOLF_ID:
11420 case PetDataTable.WFENRIR_WOLF_ID:
11421 return 3;
11422 }
11423 return 0;
11424 }
11425
11426 @Override
11427 public double getColRadius()
11428 {
11429 if (getTransformation() != 0)
11430 {
11431 if (getTransformationTemplate() == 32)
11432 {
11433 setTransformation(0);
11434 }
11435 else
11436 {
11437 final int template = getTransformationTemplate();
11438 if (template != 0)
11439 {
11440 final NpcTemplate npcTemplate = NpcHolder.getInstance().getTemplate(template);
11441 if (npcTemplate != null)
11442 {
11443 return npcTemplate.collisionRadius;
11444 }
11445 }
11446 }
11447 }
11448 else if (isMounted())
11449 {
11450 final int mountTemplate = getMountNpcId();
11451 if (mountTemplate != 0)
11452 {
11453 final NpcTemplate mountNpcTemplate = NpcHolder.getInstance().getTemplate(mountTemplate);
11454 if (mountNpcTemplate != null)
11455 {
11456 return mountNpcTemplate.collisionRadius;
11457 }
11458 }
11459 }
11460 return getBaseTemplate().collisionRadius;
11461 }
11462
11463 @Override
11464 public double getColHeight()
11465 {
11466 if (getTransformation() != 0)
11467 {
11468 if (getTransformationTemplate() == 32)
11469 {
11470 setTransformation(0);
11471 }
11472 else
11473 {
11474 final int template = getTransformationTemplate();
11475 if (template != 0)
11476 {
11477 final NpcTemplate npcTemplate = NpcHolder.getInstance().getTemplate(template);
11478 if (npcTemplate != null)
11479 {
11480 return npcTemplate.collisionHeight;
11481 }
11482 }
11483 }
11484 }
11485 else if (isMounted())
11486 {
11487 final int mountTemplate = getMountNpcId();
11488 if (mountTemplate != 0)
11489 {
11490 final NpcTemplate mountNpcTemplate = NpcHolder.getInstance().getTemplate(mountTemplate);
11491 if (mountNpcTemplate != null)
11492 {
11493 return mountNpcTemplate.collisionHeight;
11494 }
11495 }
11496 }
11497 return getBaseTemplate().collisionHeight;
11498 }
11499
11500 @Override
11501 public void setReflection(Reflection reflection)
11502 {
11503 if (getReflection() == reflection)
11504 {
11505 return;
11506 }
11507
11508 super.setReflection(reflection);
11509
11510 if ((_summon != null) && !_summon.isDead())
11511 {
11512 _summon.setReflection(reflection);
11513 }
11514
11515 if (reflection != ReflectionManager.DEFAULT)
11516 {
11517 String var = getVar("reflection");
11518 if ((var == null) || !var.equals(String.valueOf(reflection.getId())))
11519 {
11520 setVar("reflection", String.valueOf(reflection.getId()), -1);
11521 }
11522 }
11523 else
11524 {
11525 unsetVar("reflection");
11526 }
11527
11528 if (getActiveClass() != null)
11529 {
11530 getInventory().validateItems();
11531 //_129_PailakaDevilsLegacy
11532 if ((getPet() != null) && ((getPet().getNpcId() == 14916) || (getPet().getNpcId() == 14917)))
11533 {
11534 getPet().unSummon();
11535 }
11536 }
11537 }
11538
11539 public boolean isTerritoryFlagEquipped()
11540 {
11541 ItemInstance weapon = getActiveWeaponInstance();
11542 return (weapon != null) && weapon.getTemplate().isTerritoryFlag();
11543 }
11544
11545 private int _buyListId;
11546
11547 public void setBuyListId(int listId)
11548 {
11549 _buyListId = listId;
11550 }
11551
11552 public int getBuyListId()
11553 {
11554 return _buyListId;
11555 }
11556
11557 public int getFame()
11558 {
11559 return _fame;
11560 }
11561
11562 public void setFame(int fame, String log)
11563 {
11564 fame = Math.min(Config.LIM_FAME, fame);
11565 if ((log != null) && !log.isEmpty())
11566 {
11567 Log.add(_name + "|" + (fame - _fame) + "|" + fame + "|" + log, "fame");
11568 }
11569 if (fame > _fame)
11570 {
11571 int added = fame - _fame;
11572 getCounters().fameAcquired += added;
11573 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_ACQUIRED_S1_REPUTATION_SCORE).addNumber(added));
11574 }
11575
11576
11577 // Synerge - Add the fame acquired to the stats
11578// if (fame > _fame)
11579// addPlayerStats(Ranking.STAT_TOP_FAME_ACQUIRED, fame - _fame);
11580
11581 _fame = fame;
11582 sendChanges();
11583 }
11584
11585 public void setFame(int fame)
11586 {
11587 fame = Math.min(Config.LIM_FAME, fame);
11588 if (fame > _fame)
11589 {
11590 sendPacket(new SystemMessage(SystemMessage.YOU_HAVE_ACQUIRED_S1_REPUTATION_SCORE).addNumber(fame - _fame));
11591 }
11592
11593 // Synerge - Add the fame acquired to the stats
11594// if (fame > _fame)
11595// addPlayerStats(Ranking.STAT_TOP_FAME_ACQUIRED, fame - _fame);
11596
11597 _fame = fame;
11598 sendChanges();
11599 }
11600
11601 public int getVitalityLevel(boolean blessActive)
11602 {
11603 return Config.ALT_VITALITY_ENABLED ? (blessActive ? 4 : _vitalityLevel) : 0;
11604 }
11605
11606 public double getVitality()
11607 {
11608 return Config.ALT_VITALITY_ENABLED ? _vitality : 0;
11609 }
11610
11611 public void addVitality(double val)
11612 {
11613 setVitality(getVitality() + val);
11614 }
11615
11616 public void setVitality(double newVitality)
11617 {
11618 if (!Config.ALT_VITALITY_ENABLED)
11619 {
11620 return;
11621 }
11622
11623 newVitality = Math.max(Math.min(newVitality, Config.VITALITY_LEVELS[4]), 0);
11624
11625 if ((newVitality >= _vitality) || (getLevel() >= 10))
11626 {
11627 if (newVitality != _vitality)
11628 {
11629 if (newVitality == 0)
11630 {
11631 sendPacket(Msg.VITALITY_IS_FULLY_EXHAUSTED);
11632 }
11633 else if (newVitality == Config.VITALITY_LEVELS[4])
11634 {
11635 sendPacket(Msg.YOUR_VITALITY_IS_AT_MAXIMUM);
11636 }
11637 }
11638
11639 _vitality = newVitality;
11640 }
11641
11642 int newLevel = 0;
11643 if (_vitality >= Config.VITALITY_LEVELS[3])
11644 {
11645 newLevel = 4;
11646 }
11647 else if (_vitality >= Config.VITALITY_LEVELS[2])
11648 {
11649 newLevel = 3;
11650 }
11651 else if (_vitality >= Config.VITALITY_LEVELS[1])
11652 {
11653 newLevel = 2;
11654 }
11655 else if (_vitality >= Config.VITALITY_LEVELS[0])
11656 {
11657 newLevel = 1;
11658 }
11659
11660 if (_vitalityLevel > newLevel)
11661 {
11662 getNevitSystem().addPoints(1500);
11663 }
11664
11665 if (_vitalityLevel != newLevel)
11666 {
11667 if (_vitalityLevel != -1)
11668 {
11669 sendPacket(newLevel < _vitalityLevel ? Msg.VITALITY_HAS_DECREASED : Msg.VITALITY_HAS_INCREASED);
11670 }
11671 _vitalityLevel = newLevel;
11672 }
11673
11674 sendPacket(new ExVitalityPointInfo((int) _vitality));
11675 }
11676
11677 private final int _incorrectValidateCount = 0;
11678
11679 public int getIncorrectValidateCount()
11680 {
11681 return _incorrectValidateCount;
11682 }
11683
11684 public int setIncorrectValidateCount(int count)
11685 {
11686 return _incorrectValidateCount;
11687 }
11688
11689 public int getExpandInventory()
11690 {
11691 return _expandInventory;
11692 }
11693
11694 public void setExpandInventory(int inventory)
11695 {
11696 _expandInventory = inventory;
11697 }
11698
11699 public int getExpandWarehouse()
11700 {
11701 return _expandWarehouse;
11702 }
11703
11704 public void setExpandWarehouse(int warehouse)
11705 {
11706 _expandWarehouse = warehouse;
11707 }
11708
11709 public boolean isNotShowBuffAnim()
11710 {
11711 return _notShowBuffAnim;
11712 }
11713
11714 public void setNotShowBuffAnim(boolean value)
11715 {
11716 _notShowBuffAnim = value;
11717 }
11718
11719 public List<SchemeBufferInstance.PlayerScheme> getBuffSchemes()
11720 {
11721 return buffSchemes;
11722 }
11723
11724 public SchemeBufferInstance.PlayerScheme getBuffSchemeById(int id)
11725 {
11726 for (SchemeBufferInstance.PlayerScheme scheme : buffSchemes)
11727 if (scheme.schemeId == id)
11728 return scheme;
11729 return null;
11730 }
11731
11732 public SchemeBufferInstance.PlayerScheme getBuffSchemeByName(String name)
11733 {
11734 for (SchemeBufferInstance.PlayerScheme scheme : buffSchemes)
11735 if (scheme.schemeName.equals(name))
11736 return scheme;
11737 return null;
11738 }
11739
11740 public void enterMovieMode()
11741 {
11742 if (isInMovie())
11743 {
11744 return;
11745 }
11746
11747 setTarget(null);
11748 stopMove();
11749 setIsInMovie(true);
11750 sendPacket(new CameraMode(1));
11751 }
11752
11753 public void leaveMovieMode()
11754 {
11755 setIsInMovie(false);
11756 sendPacket(new CameraMode(0));
11757 broadcastCharInfo();
11758 }
11759
11760 public void specialCamera(GameObject target, int dist, int yaw, int pitch, int time, int duration)
11761 {
11762 sendPacket(new SpecialCamera(target.getObjectId(), dist, yaw, pitch, time, duration));
11763 }
11764
11765 public void specialCamera(GameObject target, int dist, int yaw, int pitch, int time, int duration, int turn, int rise, int widescreen, int unk)
11766 {
11767 sendPacket(new SpecialCamera(target.getObjectId(), dist, yaw, pitch, time, duration, turn, rise, widescreen, unk));
11768 }
11769
11770 private int _movieId = 0;
11771 private boolean _isInMovie;
11772
11773 public void setMovieId(int id)
11774 {
11775 _movieId = id;
11776 }
11777
11778 public int getMovieId()
11779 {
11780 return _movieId;
11781 }
11782
11783 public boolean isInMovie()
11784 {
11785 return _isInMovie;
11786 }
11787
11788 public void setIsInMovie(boolean state)
11789 {
11790 _isInMovie = state;
11791 }
11792
11793 public void showQuestMovie(SceneMovie movie)
11794 {
11795 if (isInMovie())
11796 {
11797 return;
11798 }
11799
11800 sendActionFailed();
11801 setTarget(null);
11802 stopMove();
11803 setMovieId(movie.getId());
11804 setIsInMovie(true);
11805 sendPacket(movie.packet(this));
11806 }
11807
11808 public void showQuestMovie(int movieId)
11809 {
11810 if (isInMovie())
11811 {
11812 return;
11813 }
11814
11815 sendActionFailed();
11816 setTarget(null);
11817 stopMove();
11818 setMovieId(movieId);
11819 setIsInMovie(true);
11820 sendPacket(new ExStartScenePlayer(movieId));
11821 }
11822
11823 public void setAutoLoot(boolean enable)
11824 {
11825 if (Config.AUTO_LOOT_INDIVIDUAL)
11826 {
11827 _autoLoot = enable;
11828 setVar("AutoLoot", String.valueOf(enable), -1);
11829 }
11830 }
11831
11832 public void setAutoLootHerbs(boolean enable)
11833 {
11834 if (Config.AUTO_LOOT_INDIVIDUAL)
11835 {
11836 AutoLootHerbs = enable;
11837 setVar("AutoLootHerbs", String.valueOf(enable), -1);
11838 }
11839 }
11840
11841 public void setAutoLootOnlyAdena(boolean enable)
11842 {
11843 if (Config.AUTO_LOOT_INDIVIDUAL)
11844 {
11845 AutoLootOnlyAdena = enable;
11846 setVar("AutoLootOnlyAdena", String.valueOf(enable), -1);
11847 }
11848 }
11849
11850 public boolean isAutoLootEnabled()
11851 {
11852 return _autoLoot;
11853 }
11854
11855 public boolean isAutoLootHerbsEnabled()
11856 {
11857 return AutoLootHerbs;
11858 }
11859
11860 public boolean isAutoLootOnlyAdenaEnabled()
11861 {
11862 return AutoLootOnlyAdena;
11863 }
11864
11865 public final void reName(String name, boolean saveToDB)
11866 {
11867 setName(name);
11868 if (saveToDB)
11869 {
11870 saveNameToDB();
11871 }
11872 broadcastCharInfo();
11873 }
11874
11875 public final void reName(String name)
11876 {
11877 reName(name, false);
11878 }
11879
11880 public final void saveNameToDB()
11881 {
11882 try (Connection con = DatabaseFactory.getInstance().getConnection();
11883 PreparedStatement st = con.prepareStatement("UPDATE characters SET char_name = ? WHERE obj_Id = ?"))
11884 {
11885 st.setString(1, getName());
11886 st.setInt(2, getObjectId());
11887 st.executeUpdate();
11888 }
11889 catch (SQLException e)
11890 {
11891 _log.error("Error while saving Char Name", e);
11892 }
11893 }
11894
11895 @Override
11896 public Player getPlayer()
11897 {
11898 return this;
11899 }
11900
11901 private List<String> getStoredBypasses(boolean bbs)
11902 {
11903 if (bbs)
11904 {
11905 if (bypasses_bbs == null)
11906 {
11907 bypasses_bbs = new ArrayList<>();
11908 }
11909 return bypasses_bbs;
11910 }
11911 if (bypasses == null)
11912 {
11913 bypasses = new ArrayList<>();
11914 }
11915 return bypasses;
11916 }
11917
11918 public void cleanBypasses(boolean bbs)
11919 {
11920 List<String> bypassStorage = getStoredBypasses(bbs);
11921 synchronized (bypassStorage)
11922 {
11923 bypassStorage.clear();
11924 }
11925 }
11926
11927 public String encodeBypasses(String htmlCode, boolean bbs)
11928 {
11929 List<String> bypassStorage = getStoredBypasses(bbs);
11930 synchronized (bypassStorage)
11931 {
11932 return BypassManager.encode(htmlCode, bypassStorage, bbs);
11933 }
11934 }
11935
11936 public DecodedBypass decodeBypass(String bypass)
11937 {
11938 BypassType bpType = BypassManager.getBypassType(bypass);
11939 boolean bbs = (bpType == BypassType.ENCODED_BBS) || (bpType == BypassType.SIMPLE_BBS);
11940 List<String> bypassStorage = getStoredBypasses(bbs);
11941 if ((bpType == BypassType.ENCODED) || (bpType == BypassType.ENCODED_BBS))
11942 {
11943 return BypassManager.decode(bypass, bypassStorage, bbs, this);
11944 }
11945 if (bpType == BypassType.SIMPLE)
11946 {
11947 return new DecodedBypass(bypass, false).trim();
11948 }
11949 if ((bpType == BypassType.SIMPLE_BBS) && !bypass.startsWith("_bbsscripts"))
11950 {
11951 return new DecodedBypass(bypass, true).trim();
11952 }
11953
11954 ICommunityBoardHandler handler = CommunityBoardManager.getInstance().getCommunityHandler(bypass);
11955 if (handler != null)
11956 {
11957 return new DecodedBypass(bypass, handler).trim();
11958 }
11959
11960 _log.warn("Direct access to bypass: " + bypass + " / Player: " + getName());
11961 return null;
11962 }
11963
11964 public int getTalismanCount()
11965 {
11966 return (int) calcStat(Stats.TALISMANS_LIMIT, 0, null, null);
11967 }
11968
11969 public boolean getOpenCloak()
11970 {
11971 if (Config.ALT_OPEN_CLOAK_SLOT || isGM())
11972 {
11973 return true;
11974 }
11975 return (int) calcStat(Stats.CLOAK_SLOT, 0, null, null) > 0;
11976 }
11977
11978 public final void disableDrop(int time)
11979 {
11980 _dropDisabled = System.currentTimeMillis() + time;
11981 }
11982
11983 public final boolean isDropDisabled()
11984 {
11985 return _dropDisabled > System.currentTimeMillis();
11986 }
11987
11988 private ItemInstance _petControlItem = null;
11989
11990 public void setPetControlItem(int itemObjId)
11991 {
11992 setPetControlItem(getInventory().getItemByObjectId(itemObjId));
11993 }
11994
11995 public void setPetControlItem(ItemInstance item)
11996 {
11997 _petControlItem = item;
11998 }
11999
12000 public ItemInstance getPetControlItem()
12001 {
12002 return _petControlItem;
12003 }
12004
12005 private long _lastNotAfkTime = 0;
12006
12007 public void isntAfk()
12008 {
12009 _lastNotAfkTime = System.currentTimeMillis();
12010 }
12011
12012 public long getLastNotAfkTime()
12013 {
12014 return _lastNotAfkTime;
12015 }
12016
12017 private final AtomicBoolean isActive = new AtomicBoolean();
12018
12019 public long lastActive = 0;
12020
12021 public boolean isActive()
12022 {
12023 return isActive.get();
12024 }
12025
12026 public void setActive()
12027 {
12028 setNonAggroTime(0);
12029
12030 isntAfk();
12031
12032 lastActive = System.currentTimeMillis();
12033
12034 if (isActive.getAndSet(true))
12035 {
12036 return;
12037 }
12038
12039 onActive();
12040 }
12041
12042 private void onActive()
12043 {
12044 setNonAggroTime(0L);
12045
12046 if (!isRegisteredInFightClub())
12047 {
12048 sendPacket(Msg.YOU_ARE_PROTECTED_AGGRESSIVE_MONSTERS);
12049 }
12050
12051 if (getPetControlItem() != null)
12052 {
12053 ThreadPoolManager.getInstance().execute(new RunnableImpl()
12054 {
12055 @Override
12056 public void runImpl()
12057 {
12058 if (getPetControlItem() != null)
12059 {
12060 summonPet();
12061 }
12062 }
12063
12064 });
12065 }
12066 }
12067
12068 public void summonPet()
12069 {
12070 if (getPet() != null)
12071 {
12072 return;
12073 }
12074
12075 ItemInstance controlItem = getPetControlItem();
12076 if (controlItem == null)
12077 {
12078 return;
12079 }
12080
12081 int npcId = PetDataTable.getSummonId(controlItem);
12082 if (npcId == 0)
12083 {
12084 return;
12085 }
12086
12087 NpcTemplate petTemplate = NpcHolder.getInstance().getTemplate(npcId);
12088 if (petTemplate == null)
12089 {
12090 return;
12091 }
12092
12093 PetInstance pet = PetInstance.restore(controlItem, petTemplate, this);
12094 if (pet == null)
12095 {
12096 return;
12097 }
12098
12099 setPet(pet);
12100 pet.setTitle(getName());
12101
12102 if (!pet.isRespawned())
12103 {
12104 pet.setCurrentHp(pet.getMaxHp(), false);
12105 pet.setCurrentMp(pet.getMaxMp());
12106 pet.setCurrentFed(pet.getMaxFed());
12107 pet.updateControlItem();
12108 pet.store();
12109 }
12110
12111 pet.getInventory().restore();
12112
12113 pet.setReflection(getReflection());
12114 pet.spawnMe(Location.findPointToStay(this, 50, 70));
12115 pet.setRunning();
12116 pet.setFollowMode(true);
12117 pet.getInventory().validateItems();
12118
12119 if (pet instanceof PetBabyInstance)
12120 {
12121 ((PetBabyInstance) pet).startBuffTask();
12122 }
12123 }
12124
12125 private Map<Integer, Long> _traps;
12126
12127 public Collection<TrapInstance> getTraps()
12128 {
12129 if (_traps == null)
12130 {
12131 return null;
12132 }
12133 Collection<TrapInstance> result = new ArrayList<TrapInstance>(getTrapsCount());
12134 TrapInstance trap;
12135 for (Integer trapId : _traps.keySet())
12136 {
12137 if ((trap = (TrapInstance) GameObjectsStorage.get(_traps.get(trapId))) != null)
12138 {
12139 result.add(trap);
12140 }
12141 else
12142 {
12143 _traps.remove(trapId);
12144 }
12145 }
12146 return result;
12147 }
12148
12149 public int getTrapsCount()
12150 {
12151 return _traps == null ? 0 : _traps.size();
12152 }
12153
12154 public void addTrap(TrapInstance trap)
12155 {
12156 if (_traps == null)
12157 {
12158 _traps = new HashMap<Integer, Long>();
12159 }
12160 _traps.put(trap.getObjectId(), trap.getStoredId());
12161 }
12162
12163 public void removeTrap(TrapInstance trap)
12164 {
12165 Map<Integer, Long> traps = _traps;
12166 if ((traps == null) || traps.isEmpty())
12167 {
12168 return;
12169 }
12170 traps.remove(trap.getObjectId());
12171 }
12172
12173 public void destroyFirstTrap()
12174 {
12175 Map<Integer, Long> traps = _traps;
12176 if ((traps == null) || traps.isEmpty())
12177 {
12178 return;
12179 }
12180 TrapInstance trap;
12181 for (Integer trapId : traps.keySet())
12182 {
12183 if ((trap = (TrapInstance) GameObjectsStorage.get(traps.get(trapId))) != null)
12184 {
12185 trap.deleteMe();
12186 return;
12187 }
12188 return;
12189 }
12190 }
12191
12192 public void destroyAllTraps()
12193 {
12194 Map<Integer, Long> traps = _traps;
12195 if ((traps == null) || traps.isEmpty())
12196 {
12197 return;
12198 }
12199 List<TrapInstance> toRemove = new ArrayList<TrapInstance>();
12200 for (Integer trapId : traps.keySet())
12201 {
12202 toRemove.add((TrapInstance) GameObjectsStorage.get(traps.get(trapId)));
12203 }
12204 for (TrapInstance t : toRemove)
12205 {
12206 if (t != null)
12207 {
12208 t.deleteMe();
12209 }
12210 }
12211 }
12212
12213 public void setBlockCheckerArena(byte arena)
12214 {
12215 _handysBlockCheckerEventArena = arena;
12216 }
12217
12218 public int getBlockCheckerArena()
12219 {
12220 return _handysBlockCheckerEventArena;
12221 }
12222
12223 @Override
12224 public PlayerListenerList getListeners()
12225 {
12226 if (listeners == null)
12227 {
12228 synchronized (this)
12229 {
12230 if (listeners == null)
12231 {
12232 listeners = new PlayerListenerList(this);
12233 }
12234 }
12235 }
12236 return (PlayerListenerList) listeners;
12237 }
12238
12239 @Override
12240 public PlayerStatsChangeRecorder getStatsRecorder()
12241 {
12242 if (_statsRecorder == null)
12243 {
12244 synchronized (this)
12245 {
12246 if (_statsRecorder == null)
12247 {
12248 _statsRecorder = new PlayerStatsChangeRecorder(this);
12249 }
12250 }
12251 }
12252 return (PlayerStatsChangeRecorder) _statsRecorder;
12253 }
12254
12255 private Future<?> _hourlyTask;
12256 private int _hoursInGame = 0;
12257
12258 public int getHoursInGame()
12259 {
12260 _hoursInGame++;
12261 return _hoursInGame;
12262 }
12263
12264 public int getHoursInGames()
12265 {
12266 return _hoursInGame;
12267 }
12268
12269 public void startHourlyTask()
12270 {
12271 _hourlyTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new HourlyTask(this), 3600000L, 3600000L);
12272 }
12273
12274 public void stopHourlyTask()
12275 {
12276 if (_hourlyTask != null)
12277 {
12278 _hourlyTask.cancel(false);
12279 _hourlyTask = null;
12280 }
12281 }
12282 @Override
12283 public void setTeam(TeamType t)
12284 {
12285 super.setTeam(t);
12286
12287 if (getPet() != null)
12288 getPet().sendChanges();
12289 }
12290 private int _team = 0;
12291 @SuppressWarnings("unused")
12292 private boolean _checksForTeam = false;
12293
12294 public void setTeamEvents(final int team, boolean checksForTeam)
12295 {
12296 _checksForTeam = checksForTeam;
12297 if (_team != team)
12298 {
12299 _team = team;
12300
12301 broadcastUserInfo(true);
12302 if (getPet() != null)
12303 {
12304 getPet().broadcastCharInfo();
12305 }
12306 }
12307 }
12308
12309 public int getTeamEvents()
12310 {
12311 return _team;
12312 }
12313
12314 public long getPremiumPoints()
12315 {
12316 if (Config.GAME_POINT_ITEM_ID != -1)
12317 {
12318 return ItemFunctions.getItemCount(this, Config.GAME_POINT_ITEM_ID);
12319 }
12320 return 0;
12321 }
12322
12323 public void reducePremiumPoints(final int val)
12324 {
12325 if (Config.GAME_POINT_ITEM_ID != -1)
12326 {
12327 ItemFunctions.removeItem(this, Config.GAME_POINT_ITEM_ID, val, true, "PremiumPoints");
12328 }
12329 }
12330
12331 public void addPremiumPoints(final int val)
12332 {
12333 if (Config.GAME_POINT_ITEM_ID != -1)
12334 {
12335 ItemFunctions.addItem(this, Config.GAME_POINT_ITEM_ID, val, true, "PremiumPoints");
12336 }
12337 }
12338
12339 private boolean _agathionResAvailable = false;
12340
12341 public boolean isAgathionResAvailable()
12342 {
12343 return _agathionResAvailable;
12344 }
12345
12346 public void setAgathionRes(boolean val)
12347 {
12348 _agathionResAvailable = val;
12349 }
12350
12351 public boolean isClanAirShipDriver()
12352 {
12353 return isInBoat() && getBoat().isClanAirShip() && (((ClanAirShip) getBoat()).getDriver() == this);
12354 }
12355
12356 private Map<String, String> _userSession;
12357
12358 public String getSessionVar(String key)
12359 {
12360 if (_userSession == null)
12361 {
12362 return null;
12363 }
12364 return _userSession.get(key);
12365 }
12366
12367 public void setSessionVar(String key, String val)
12368 {
12369 if (_userSession == null)
12370 {
12371 _userSession = new ConcurrentHashMap<String, String>();
12372 }
12373
12374 if ((val == null) || val.isEmpty())
12375 {
12376 _userSession.remove(key);
12377 }
12378 else
12379 {
12380 _userSession.put(key, val);
12381 }
12382 }
12383
12384 public FriendList getFriendList()
12385 {
12386 return _friendList;
12387 }
12388
12389 public boolean isNotShowTraders()
12390 {
12391 return _notShowTraders;
12392 }
12393
12394 public void setNotShowTraders(boolean notShowTraders)
12395 {
12396 _notShowTraders = notShowTraders;
12397 }
12398
12399 public boolean isDebug()
12400 {
12401 return _debug;
12402 }
12403
12404 public void setDebug(boolean b)
12405 {
12406 _debug = b;
12407 }
12408
12409 public void sendItemList(boolean show)
12410 {
12411 ItemInstance[] items = getInventory().getItems();
12412 LockType lockType = getInventory().getLockType();
12413 int[] lockItems = getInventory().getLockItems();
12414
12415 int allSize = items.length;
12416 int questItemsSize = 0;
12417 int agathionItemsSize = 0;
12418 for (ItemInstance item : items)
12419 {
12420 if (item.getTemplate().isQuest())
12421 {
12422 questItemsSize++;
12423 }
12424 if (item.getTemplate().getAgathionEnergy() > 0)
12425 {
12426 agathionItemsSize++;
12427 }
12428 }
12429
12430 sendPacket(new ItemList(allSize - questItemsSize, items, show, lockType, lockItems));
12431 if (questItemsSize > 0)
12432 {
12433 sendPacket(new ExQuestItemList(questItemsSize, items, lockType, lockItems));
12434 }
12435 if (agathionItemsSize > 0)
12436 {
12437 sendPacket(new ExBR_AgathionEnergyInfo(agathionItemsSize, items));
12438 }
12439 }
12440
12441 public int getBeltInventoryIncrease()
12442 {
12443 ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_BELT);
12444 if ((item != null) && (item.getTemplate().getAttachedSkills() != null))
12445 {
12446 for (Skill skill : item.getTemplate().getAttachedSkills())
12447 {
12448 for (FuncTemplate func : skill.getAttachedFuncs())
12449 {
12450 if (func._stat == Stats.INVENTORY_LIMIT)
12451 {
12452 return (int) func._value;
12453 }
12454 }
12455 }
12456 }
12457 return 0;
12458 }
12459
12460 @Override
12461 public boolean isPlayer()
12462 {
12463 return true;
12464 }
12465
12466 public boolean checkCoupleAction(Player target)
12467 {
12468 if (target.getPrivateStoreType() != Player.STORE_PRIVATE_NONE)
12469 {
12470 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IN_PRIVATE_STORE).addName(target));
12471 return false;
12472 }
12473 if (target.isFishing())
12474 {
12475 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_FISHING).addName(target));
12476 return false;
12477 }
12478 if (target.isInCombat())
12479 {
12480 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_COMBAT).addName(target));
12481 return false;
12482 }
12483 if (target.isCursedWeaponEquipped())
12484 {
12485 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_CURSED_WEAPON_EQUIPED).addName(target));
12486 return false;
12487 }
12488 if (target.isInOlympiadMode())
12489 {
12490 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_OLYMPIAD).addName(target));
12491 return false;
12492 }
12493 if (target.isOnSiegeField())
12494 {
12495 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_SIEGE).addName(target));
12496 return false;
12497 }
12498 if (target.isInBoat() || (target.getMountNpcId() != 0))
12499 {
12500 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_VEHICLE_MOUNT_OTHER).addName(target));
12501 return false;
12502 }
12503 if (target.isTeleporting())
12504 {
12505 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_TELEPORTING).addName(target));
12506 return false;
12507 }
12508 if (target.getTransformation() != 0)
12509 {
12510 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_TRANSFORM).addName(target));
12511 return false;
12512 }
12513 if (target.isDead())
12514 {
12515 sendPacket(new SystemMessage(SystemMessage.COUPLE_ACTION_CANNOT_C1_TARGET_IS_DEAD).addName(target));
12516 return false;
12517 }
12518 if (isInFightClub() && !getFightClubEvent().isFriend(this, target))
12519 {
12520 sendMessage("You cannot request couple action while player is your enemy!");
12521 return false;
12522 }
12523 return true;
12524 }
12525
12526 @Override
12527 public void startAttackStanceTask()
12528 {
12529 startAttackStanceTask0();
12530 Summon summon = getPet();
12531 if (summon != null)
12532 {
12533 summon.startAttackStanceTask0();
12534 }
12535 }
12536
12537 @Override
12538 public void displayGiveDamageMessage(Creature target, int damage, boolean crit, boolean miss, boolean shld, boolean magic)
12539 {
12540 super.displayGiveDamageMessage(target, damage, crit, miss, shld, magic);
12541 if (crit)
12542 {
12543 if (magic)
12544 {
12545 getCounters().mcritsDone++;
12546 sendPacket(new SystemMessage(SystemMessage.MAGIC_CRITICAL_HIT).addName(this));
12547 }
12548 else
12549 {
12550 getCounters().critsDone++;
12551 sendPacket(new SystemMessage(SystemMessage.C1_HAD_A_CRITICAL_HIT).addName(this));
12552 }
12553 }
12554
12555 if (miss)
12556 {
12557 sendPacket(new SystemMessage(SystemMessage.C1S_ATTACK_WENT_ASTRAY).addName(this));
12558 }
12559 else if (!target.isDamageBlocked())
12560 {
12561 sendPacket(new SystemMessage(SystemMessage.C1_HAS_GIVEN_C2_DAMAGE_OF_S3).addName(this).addName(target).addNumber(damage));
12562 }
12563
12564 if (target.isPlayer())
12565 {
12566 if (shld && (damage > 1))
12567 {
12568 target.sendPacket(SystemMsg.YOUR_SHIELD_DEFENSE_HAS_SUCCEEDED);
12569 }
12570 else if (shld && (damage == 1))
12571 {
12572 target.sendPacket(SystemMsg.YOUR_EXCELLENT_SHIELD_DEFENSE_WAS_A_SUCCESS);
12573 }
12574 }
12575 }
12576
12577 @Override
12578 public void displayReceiveDamageMessage(Creature attacker, int damage)
12579 {
12580 if (attacker != this)
12581 {
12582 sendPacket(new SystemMessage(SystemMessage.C1_HAS_RECEIVED_DAMAGE_OF_S3_FROM_C2).addString(getVisibleName()).addString(attacker.getVisibleName()).addNumber((long) damage));
12583 }
12584 }
12585
12586 public IntObjectMap<String> getPostFriends()
12587 {
12588 return _postFriends;
12589 }
12590
12591 public boolean isSharedGroupDisabled(int groupId)
12592 {
12593 TimeStamp sts = _sharedGroupReuses.get(groupId);
12594 if (sts == null)
12595 {
12596 return false;
12597 }
12598 if (sts.hasNotPassed())
12599 {
12600 return true;
12601 }
12602 _sharedGroupReuses.remove(groupId);
12603 return false;
12604 }
12605
12606 public TimeStamp getSharedGroupReuse(int groupId)
12607 {
12608 return _sharedGroupReuses.get(groupId);
12609 }
12610
12611 public void addSharedGroupReuse(int group, TimeStamp stamp)
12612 {
12613 _sharedGroupReuses.put(group, stamp);
12614 }
12615
12616 public Collection<IntObjectMap.Entry<TimeStamp>> getSharedGroupReuses()
12617 {
12618 return _sharedGroupReuses.entrySet();
12619 }
12620
12621 public void sendReuseMessage(ItemInstance item)
12622 {
12623 TimeStamp sts = getSharedGroupReuse(item.getTemplate().getReuseGroup());
12624 if ((sts == null) || !sts.hasNotPassed())
12625 {
12626 return;
12627 }
12628
12629 long timeleft = sts.getReuseCurrent();
12630 long hours = timeleft / 3600000;
12631 long minutes = (timeleft - (hours * 3600000)) / 60000;
12632 long seconds = (long) Math.ceil((timeleft - (hours * 3600000) - (minutes * 60000)) / 1000.);
12633
12634 if (hours > 0)
12635 {
12636 sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[2]).addItemName(item.getTemplate().getItemId()).addInteger(hours).addInteger(minutes).addInteger(seconds));
12637 }
12638 else if (minutes > 0)
12639 {
12640 sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[1]).addItemName(item.getTemplate().getItemId()).addInteger(minutes).addInteger(seconds));
12641 }
12642 else
12643 {
12644 sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[0]).addItemName(item.getTemplate().getItemId()).addInteger(seconds));
12645 }
12646 }
12647
12648 public NevitSystem getNevitSystem()
12649 {
12650 return _nevitSystem;
12651 }
12652
12653 public void ask(ConfirmDlg dlg, OnAnswerListener listener)
12654 {
12655 if (_askDialog != null)
12656 return;
12657
12658 int rnd = Rnd.nextInt();
12659 _askDialog = new ImmutablePair<Integer, OnAnswerListener>(rnd, listener);
12660 dlg.setRequestId(rnd);
12661 sendPacket(dlg);
12662
12663 // Prims - Set the resurrection max time to accept it to 5 minutes. After that it will be rejected. Only for players
12664 if (listener instanceof ReviveAnswerListener && !((ReviveAnswerListener)listener).isForPet())
12665 _resurrectionMaxTime = System.currentTimeMillis() + 5 * 60 * 1000;
12666 }
12667
12668 public Pair<Integer, OnAnswerListener> getAskListener(boolean clear)
12669 {
12670 if (!clear)
12671 {
12672 return _askDialog;
12673 }
12674 else
12675 {
12676 Pair<Integer, OnAnswerListener> ask = _askDialog;
12677 _askDialog = null;
12678 return ask;
12679 }
12680 }
12681
12682 public boolean hasDialogAskActive()
12683 {
12684 return _askDialog != null;
12685 }
12686
12687 @Override
12688 public boolean isDead()
12689 {
12690 return (isInOlympiadMode() || isInDuel()) ? getCurrentHp() <= 1. : super.isDead();
12691 }
12692
12693 @Override
12694 public int getAgathionEnergy()
12695 {
12696 ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LBRACELET);
12697 return item == null ? 0 : item.getAgathionEnergy();
12698 }
12699
12700 @Override
12701 public void setAgathionEnergy(int val)
12702 {
12703 ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LBRACELET);
12704 if (item == null)
12705 {
12706 return;
12707 }
12708 item.setAgathionEnergy(val);
12709 item.setJdbcState(JdbcEntityState.UPDATED);
12710
12711 sendPacket(new ExBR_AgathionEnergyInfo(1, item));
12712 }
12713
12714 public boolean hasPrivilege(Privilege privilege)
12715 {
12716 return (_clan != null) && ((getClanPrivileges() & privilege.mask()) == privilege.mask());
12717 }
12718
12719 public MatchingRoom getMatchingRoom()
12720 {
12721 return _matchingRoom;
12722 }
12723
12724 public void setMatchingRoom(MatchingRoom matchingRoom)
12725 {
12726 _matchingRoom = matchingRoom;
12727 }
12728
12729 public void dispelBuffs()
12730 {
12731 for (Effect e : getEffectList().getAllEffects())
12732 {
12733 if (!e.getSkill().isOffensive() && !e.getSkill().isNewbie() && e.isCancelable() && !e.getSkill().isPreservedOnDeath())
12734 {
12735 sendPacket(new SystemMessage(SystemMessage.THE_EFFECT_OF_S1_HAS_BEEN_REMOVED).addSkillName(e.getSkill().getId(), e.getSkill().getLevel()));
12736 e.exit();
12737 }
12738 }
12739 if (getPet() != null)
12740 {
12741 for (Effect e : getPet().getEffectList().getAllEffects())
12742 {
12743 if (!e.getSkill().isOffensive() && !e.getSkill().isNewbie() && e.isCancelable() && !e.getSkill().isPreservedOnDeath())
12744 {
12745 e.exit();
12746 }
12747 }
12748 }
12749 }
12750
12751 public void setInstanceReuse(int id, long time)
12752 {
12753 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());
12754 sendPacket(msg);
12755 _instancesReuses.put(id, time);
12756 mysql.set("REPLACE INTO character_instances (obj_id, id, reuse) VALUES (?,?,?)", getObjectId(), id, time);
12757 }
12758
12759 public void removeInstanceReuse(int id)
12760 {
12761 if (_instancesReuses.remove(id) != null)
12762 {
12763 mysql.set("DELETE FROM `character_instances` WHERE `obj_id`=? AND `id`=? LIMIT 1", getObjectId(), id);
12764 }
12765 }
12766
12767 public void removeAllInstanceReuses()
12768 {
12769 _instancesReuses.clear();
12770 mysql.set("DELETE FROM `character_instances` WHERE `obj_id`=?", getObjectId());
12771 }
12772
12773 public void removeInstanceReusesByGroupId(int groupId)
12774 {
12775 for (int i : InstantZoneHolder.getInstance().getSharedReuseInstanceIdsByGroup(groupId))
12776 {
12777 if (getInstanceReuse(i) != null)
12778 {
12779 removeInstanceReuse(i);
12780 }
12781 }
12782 }
12783
12784 public Long getInstanceReuse(int id)
12785 {
12786 return _instancesReuses.get(id);
12787 }
12788
12789 public Map<Integer, Long> getInstanceReuses()
12790 {
12791 return _instancesReuses;
12792 }
12793
12794 private void loadInstanceReuses(Connection con)
12795 {
12796 try (PreparedStatement offline = con.prepareStatement("SELECT * FROM character_instances WHERE obj_id = ?"))
12797 {
12798 offline.setInt(1, getObjectId());
12799
12800 try (ResultSet rs = offline.executeQuery())
12801 {
12802 while (rs.next())
12803 {
12804 int id = rs.getInt("id");
12805 long reuse = rs.getLong("reuse");
12806 _instancesReuses.put(id, reuse);
12807 }
12808 }
12809 }
12810 catch (SQLException e)
12811 {
12812 _log.error("Error while loading Instance Reuses for Id "+getObjectId(), e);
12813 }
12814 }
12815
12816 public Reflection getActiveReflection()
12817 {
12818 for (Reflection r : ReflectionManager.getInstance().getAll())
12819 {
12820 if ((r != null) && ArrayUtils.contains(r.getVisitors(), getObjectId()))
12821 {
12822 return r;
12823 }
12824 }
12825 return null;
12826 }
12827
12828 public boolean canEnterInstance(int instancedZoneId)
12829 {
12830 InstantZone iz = InstantZoneHolder.getInstance().getInstantZone(instancedZoneId);
12831
12832 if (isDead())
12833 {
12834 return false;
12835 }
12836
12837 if (!Config.ALLOW_ENTER_INSTANCE)
12838 {
12839 sendMessage("Instances cannot be entered at the time!");
12840 return false;
12841 }
12842
12843 if (ReflectionManager.getInstance().size() > Config.MAX_REFLECTIONS_COUNT)
12844 {
12845 sendPacket(SystemMsg.THE_MAXIMUM_NUMBER_OF_INSTANCE_ZONES_HAS_BEEN_EXCEEDED);
12846 return false;
12847 }
12848
12849 if (iz == null)
12850 {
12851 sendPacket(SystemMsg.SYSTEM_ERROR);
12852 return false;
12853 }
12854
12855 if (ReflectionManager.getInstance().getCountByIzId(instancedZoneId) >= iz.getMaxChannels())
12856 {
12857 sendPacket(SystemMsg.THE_MAXIMUM_NUMBER_OF_INSTANCE_ZONES_HAS_BEEN_EXCEEDED);
12858 return false;
12859 }
12860
12861 return iz.getEntryType().canEnter(this, iz);
12862 }
12863
12864 public boolean canReenterInstance(int instancedZoneId)
12865 {
12866 InstantZone iz = InstantZoneHolder.getInstance().getInstantZone(instancedZoneId);
12867
12868 if (!Config.ALLOW_ENTER_INSTANCE)
12869 {
12870 sendMessage("Instances cannot be entered at the time!");
12871 return false;
12872 }
12873
12874 if ((getActiveReflection() != null) && (getActiveReflection().getInstancedZoneId() != instancedZoneId))
12875 {
12876 sendPacket(SystemMsg.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
12877 return false;
12878 }
12879 if (iz.isDispelBuffs())
12880 {
12881 dispelBuffs();
12882 }
12883 return iz.getEntryType().canReEnter(this, iz);
12884 }
12885
12886 public int getBattlefieldChatId()
12887 {
12888 return _battlefieldChatId;
12889 }
12890
12891 public void setBattlefieldChatId(int battlefieldChatId)
12892 {
12893 _battlefieldChatId = battlefieldChatId;
12894 }
12895
12896 @Override
12897 public Iterator<Player> iterator()
12898 {
12899 return Collections.singleton(this).iterator();
12900 }
12901
12902 public PlayerGroup getPlayerGroup()
12903 {
12904 if (getParty() != null)
12905 {
12906 if (getParty().getCommandChannel() != null)
12907 {
12908 return getParty().getCommandChannel();
12909 }
12910 else
12911 {
12912 return getParty();
12913 }
12914 }
12915 else
12916 {
12917 return this;
12918 }
12919 }
12920
12921 @Override
12922 public int size()
12923 {
12924 return 1;
12925 }
12926
12927 @Override
12928 public Player getLeader()
12929 {
12930 return this;
12931 }
12932
12933 @Override
12934 public List<Player> getMembers(Player... excluded)
12935 {
12936 if (Util.arrayContains(excluded, this))
12937 return Collections.emptyList();
12938
12939 return Collections.singletonList(this);
12940 }
12941
12942 @Override
12943 public boolean containsMember(Player player)
12944 {
12945 return this == player;
12946 }
12947
12948 public boolean isActionBlocked(String action)
12949 {
12950 return _blockedActions.contains(action);
12951 }
12952
12953 public void blockActions(String... actions)
12954 {
12955 Collections.addAll(_blockedActions, actions);
12956 }
12957
12958 public void unblockActions(String... actions)
12959 {
12960 for (String action : actions)
12961 {
12962 _blockedActions.remove(action);
12963 }
12964 }
12965
12966 public OlympiadGame getOlympiadGame()
12967 {
12968 return _olympiadGame;
12969 }
12970
12971 public void setOlympiadGame(OlympiadGame olympiadGame)
12972 {
12973 _olympiadGame = olympiadGame;
12974 }
12975
12976 public boolean isInOlympiadObserverMode()
12977 {
12978 return _olympiadObserveGame != null;
12979 }
12980
12981 public OlympiadGame getOlympiadObserveGame()
12982 {
12983 return _olympiadObserveGame;
12984 }
12985
12986 public void setOlympiadObserveGame(OlympiadGame olympiadObserveGame)
12987 {
12988 _olympiadObserveGame = olympiadObserveGame;
12989 }
12990
12991 public void addRadar(int x, int y, int z)
12992 {
12993 sendPacket(new RadarControl(0, 1, x, y, z));
12994 }
12995
12996 public void addRadarWithMap(int x, int y, int z)
12997 {
12998 sendPacket(new RadarControl(0, 2, x, y, z));
12999 }
13000
13001 public PetitionMainGroup getPetitionGroup()
13002 {
13003 return _petitionGroup;
13004 }
13005
13006 public void setPetitionGroup(PetitionMainGroup petitionGroup)
13007 {
13008 _petitionGroup = petitionGroup;
13009 }
13010
13011 public int getLectureMark()
13012 {
13013 return _lectureMark;
13014 }
13015
13016 public void setLectureMark(int lectureMark)
13017 {
13018 _lectureMark = lectureMark;
13019 }
13020
13021 class TeleportPoints
13022 {
13023 private final String _name;
13024 private final Location _xyz;
13025 private final long _prace;
13026 private final int _itemId;
13027 private final int _id;
13028
13029 public TeleportPoints(String name, Location xyz, int id, int itemId, long price)
13030 {
13031 _id = id;
13032 _name = name;
13033 _xyz = xyz;
13034 _itemId = itemId;
13035 _prace = price;
13036 }
13037
13038 public int getId()
13039 {
13040 return _id;
13041 }
13042
13043 public String getName()
13044 {
13045 return _name;
13046 }
13047
13048 public long getPrice()
13049 {
13050 return _prace;
13051 }
13052
13053 public int getItemId()
13054 {
13055 return _itemId;
13056 }
13057
13058 public Location getXYZ()
13059 {
13060 return _xyz;
13061 }
13062 }
13063
13064 public TeleportPoints getTeleportPoint(String name)
13065 {
13066 for (TeleportPoints point : _teleportPoints)
13067 {
13068 if (point.getName().equalsIgnoreCase(name))
13069 {
13070 return point;
13071 }
13072 }
13073 return null;
13074 }
13075
13076 public void addTeleportPoint(String name, int id, int itemId, long price)
13077 {
13078 _teleportPoints.add(new TeleportPoints(name, new Location(getX(), getY(), getZ()), id, itemId, price));
13079 }
13080
13081 public void delTeleportPoint(String name)
13082 {
13083 for (TeleportPoints point : _teleportPoints)
13084 {
13085 if (point.getName().equals(name))
13086 {
13087 _teleportPoints.remove(point);
13088 }
13089 }
13090 }
13091
13092 public void setLastHeroTrue(boolean value)
13093 {
13094 setHero(value);
13095 }
13096
13097 private boolean is_bbs_use = false;
13098
13099 public void setIsBBSUse(boolean value)
13100 {
13101 is_bbs_use = value;
13102 }
13103
13104 public boolean isBBSUse()
13105 {
13106 return is_bbs_use;
13107 }
13108
13109 public void setAccountAccesslevel(final int level, final String comments, int banTime)
13110 {
13111 AuthServerCommunication.getInstance().sendPacket(new ChangeAccessLevel(getAccountName(), level, banTime));
13112 }
13113
13114 private static void RestoreFightClub(Player player)
13115 {
13116 String[] values = player.getVar("FightClubRate").split(";");
13117 int id = Integer.parseInt(values[0]);
13118 int count = Integer.parseInt(values[1]);
13119 ItemFunctions.addItem(player, id, count, true, "RestoreFightClub");
13120 player.unsetVar("FightClubRate");
13121 player.unsetVar("isPvPevents");
13122 }
13123
13124 private static boolean _isNoAttackEvents = false;
13125
13126 public static void setNoAttackEvents(boolean set)
13127 {
13128 _isNoAttackEvents = set;
13129 }
13130
13131 public boolean isNoAttackEvents()
13132 {
13133 return _isNoAttackEvents;
13134 }
13135
13136 private void restoreCursedWeapon()
13137 {
13138 for (ItemInstance item : getInventory().getItems())
13139 {
13140 if (item.isCursed())
13141 {
13142 int skillLvl = CursedWeaponsManager.getInstance().getLevel(item.getItemId());
13143 if (item.getItemId() == 8190)
13144 {
13145 addSkill(SkillTable.getInstance().getInfo(3603, skillLvl), false);
13146 }
13147 else if (item.getItemId() == 8689)
13148 {
13149 addSkill(SkillTable.getInstance().getInfo(3629, skillLvl), false);
13150 }
13151 }
13152 }
13153 updateStats();
13154 }
13155
13156 private int _pvp_team = 0;
13157
13158 public void setPvPTeam(final int team)
13159 {
13160 if (_pvp_team != team)
13161 {
13162 _pvp_team = team;
13163 broadcastUserInfo(true);
13164 if (getPet() != null)
13165 {
13166 getPet().broadcastCharInfo();
13167 }
13168 }
13169 }
13170
13171 public void allowPvPTeam()
13172 {
13173 if (_pvp_team == 0)
13174 {
13175 setTeam(TeamType.NONE);
13176 }
13177 else if (_pvp_team == 2)
13178 {
13179 setTeam(TeamType.RED);
13180 }
13181 else if (_pvp_team == 1)
13182 {
13183 setTeam(TeamType.BLUE);
13184 }
13185 }
13186
13187 public int getPvPTeam()
13188 {
13189 return _pvp_team;
13190 }
13191
13192 public void startUnjailTask(Player player, long time, boolean msg)
13193 {
13194 if (time < 1)
13195 {
13196 return;
13197 }
13198
13199 if (_unjailTask != null)
13200 {
13201 _unjailTask.cancel(false);
13202 }
13203
13204 _unjailTask = ThreadPoolManager.getInstance().schedule(new UnJailTask(player, msg), time);
13205 }
13206
13207 public void stopUnjailTask()
13208 {
13209 if (_unjailTask != null)
13210 {
13211 _unjailTask.cancel(false);
13212 }
13213 _unjailTask = null;
13214 }
13215
13216 private AutoHuntingPunish _AutoHuntingPunish = null;
13217
13218 /**
13219 * Initializes his _botPunish object with the specified punish and for the specified time
13220 * @param punishType
13221 * @param minsOfPunish
13222 */
13223 public synchronized void setPunishDueBotting(AutoHuntingPunish.Punish punishType, int minsOfPunish)
13224 {
13225 if (_AutoHuntingPunish == null)
13226 {
13227 _AutoHuntingPunish = new AutoHuntingPunish(punishType, minsOfPunish);
13228 }
13229 }
13230
13231 /**
13232 * Returns the current object-representative player punish
13233 * @return
13234 */
13235 public AutoHuntingPunish getPlayerPunish()
13236 {
13237 return _AutoHuntingPunish;
13238 }
13239
13240 /**
13241 * Returns the type of punish being applied
13242 * @return
13243 */
13244 public AutoHuntingPunish.Punish getBotPunishType()
13245 {
13246 return _AutoHuntingPunish.getBotPunishType();
13247 }
13248
13249 /**
13250 * Will return true if the player has any bot punishment active
13251 * @return
13252 */
13253 public boolean isBeingPunished()
13254 {
13255 return _AutoHuntingPunish != null;
13256 }
13257
13258 public long _firstExp;
13259 public AccountReportDAO _account = null;
13260
13261 /**
13262 * Sets exp holded by the character on log in
13263 * @param value
13264 */
13265 public void setFirstExp(long value)
13266 {
13267 _firstExp = value;
13268 }
13269
13270 /**
13271 * Will return true if the player has gained exp since logged in
13272 * @return
13273 */
13274 public boolean hasEarnedExp()
13275 {
13276 if ((getExp() - _firstExp) != 0)
13277 {
13278 return true;
13279 }
13280 return false;
13281 }
13282
13283 /**
13284 * Will end the punishment once a player attempt to perform any forbid action and his punishment has expired
13285 */
13286 public void endPunishment()
13287 {
13288
13289 _AutoHuntingPunish = null;
13290 this.sendMessage("Your punishment has expired. Do not bot again!");
13291 }
13292
13293 private boolean _InTvT = false;
13294 private boolean _inCtF = false;
13295 private boolean _inLastHero = false;
13296 private boolean _isVoting = false;
13297 public boolean isInSameParty(Player target)
13298 {
13299 return ((getParty() != null) && (target.getParty() != null) && (getParty() == target.getParty()));
13300 }
13301
13302 public boolean isInSameChannel(Player target)
13303 {
13304 Party activeCharP = getParty();
13305 Party targetP = target.getParty();
13306 if ((activeCharP == null) || (targetP == null))
13307 return false;
13308 CommandChannel chan = activeCharP.getCommandChannel();
13309
13310 return chan != null && chan == targetP.getCommandChannel();
13311 }
13312
13313 public boolean isInSameClan(Player target)
13314 {
13315 return getClanId() != 0 && getClanId() == target.getClanId();
13316 }
13317
13318 public final boolean isInSameAlly(Player target)
13319 {
13320 return getAllyId() != 0 && getAllyId() == target.getAllyId();
13321 }
13322
13323 public boolean isInTvT()
13324 {
13325 return _InTvT;
13326 }
13327
13328 public boolean isInCtF()
13329 {
13330 return _inCtF;
13331 }
13332
13333 public boolean isInLastHero()
13334 {
13335 return _inLastHero;
13336 }
13337
13338 public boolean isInPvPEvent()
13339 {
13340 return !_InTvT && !_inCtF && !_inLastHero ? false : true;
13341 }
13342
13343 public void setIsInTvT(boolean param)
13344 {
13345 _InTvT = param;
13346 }
13347
13348 public boolean isVoting()
13349 {
13350 return _isVoting;
13351 }
13352
13353 public void setIsVoting(boolean value)
13354 {
13355 _isVoting = value;
13356 }
13357
13358 public void setIsInCtF(boolean param)
13359 {
13360 _inCtF = param;
13361 }
13362
13363 public void setIsInLastHero(boolean param)
13364 {
13365 _inLastHero = param;
13366 }
13367
13368 public void setMacroSkill(Skill skill)
13369 {
13370 _macroSkill = skill;
13371 }
13372
13373 public Skill getMacroSkill()
13374 {
13375 return _macroSkill;
13376 }
13377
13378 // Prims - Support for visible non permanent colors
13379 private int _visibleNameColor = 0;
13380
13381 public int getVisibleNameColor()
13382 {
13383 if (_visibleNameColor != 0)
13384 return _visibleNameColor;
13385
13386 return getNameColor();
13387 }
13388
13389 public void setVisibleNameColor(final int nameColor)
13390 {
13391 _visibleNameColor = nameColor;
13392 }
13393
13394 private int _visibleTitleColor = 0;
13395
13396 public int getVisibleTitleColor()
13397 {
13398 if (_visibleTitleColor != 0)
13399 return _visibleTitleColor;
13400
13401 return getTitleColor();
13402 }
13403
13404 public void setVisibleTitleColor(final int nameColor)
13405 {
13406 _visibleTitleColor = nameColor;
13407 }
13408
13409 public void setLastAugmentNpc(NpcInstance npc)
13410 {
13411 lastAugmentNpc = npc;
13412 }
13413
13414 public boolean checkLastAugmentNpc()
13415 {
13416 if (lastAugmentNpc == null)
13417 return false;
13418
13419 if (!PositionUtils.checkIfInRange(300, this, lastAugmentNpc, true))
13420 {
13421 lastAugmentNpc = null;
13422 return false;
13423 }
13424
13425 return true;
13426 }
13427 // Support for visible non permanent name and title
13428 private String _visibleName = null;
13429
13430 @Override
13431 public String getVisibleName()
13432 {
13433 if (_visibleName != null)
13434 return _visibleName;
13435
13436 return getName();
13437 }
13438
13439 public void setVisibleName(final String name)
13440 {
13441 _visibleName = name;
13442 }
13443
13444 private String _visibleTitle = null;
13445
13446 public String getVisibleTitle()
13447 {
13448 if (_visibleTitle != null)
13449 return _visibleTitle;
13450
13451 return getTitle();
13452 }
13453
13454 public void setVisibleTitle(final String title)
13455 {
13456 _visibleTitle = title;
13457 }
13458
13459 // Offline buff store function
13460 public void offlineBuffStore()
13461 {
13462 if (getHwidGamer() != null)
13463 getHwidGamer().removePlayer(this);
13464
13465 if (_connection != null)
13466 {
13467 _connection.setActiveChar(null);
13468 _connection.close(ServerClose.STATIC);
13469 setNetConnection(null);
13470 }
13471 setOnlineTime(getOnlineTime());
13472 setUptime(0);
13473 setOfflineMode(true);
13474
13475 Party party = getParty();
13476 if (party != null)
13477 {
13478 if (isFestivalParticipant())
13479 {
13480 party.sendMessage(getName() + " has been removed from the upcoming festival.");
13481 }
13482 leaveParty();
13483 }
13484
13485 if (getPet() != null)
13486 {
13487 getPet().unSummon();
13488 }
13489
13490 CursedWeaponsManager.getInstance().doLogout(this);
13491
13492 if (isInOlympiadMode() || (getOlympiadGame() != null))
13493 {
13494 Olympiad.logoutPlayer(this);
13495 }
13496
13497 if (isInObserverMode())
13498 {
13499 if (getOlympiadObserveGame() == null)
13500 {
13501 leaveObserverMode();
13502 }
13503 else
13504 {
13505 leaveOlympiadObserverMode(true);
13506 }
13507 _observerMode.set(OBSERVER_NONE);
13508 }
13509
13510 setVisibleNameColor(Config.BUFF_STORE_OFFLINE_NAME_COLOR);
13511 broadcastCharInfo();
13512
13513 // Guardamos el offline buffer en la db al salir
13514 OfflineBuffersTable.getInstance().onLogout(this);
13515
13516 // Stop all tasks
13517 stopWaterTask();
13518 stopBonusTask();
13519 stopHourlyTask();
13520 stopVitalityTask();
13521 stopPcBangPointsTask();
13522 stopAutoSaveTask();
13523 stopRecomBonusTask(true);
13524 stopQuestTimers();
13525 getNevitSystem().stopTasksOnLogout();
13526
13527 try
13528 {
13529 getInventory().store();
13530 }
13531 catch (Throwable t)
13532 {
13533 _log.error("Error while storing Player Inventory", t);
13534 }
13535
13536 try
13537 {
13538 store(false);
13539 }
13540 catch (Throwable t)
13541 {
13542 _log.error("Error while storing Player", t);
13543 }
13544 }
13545
13546
13547 @Override
13548 public boolean isInZoneBattle()
13549 {
13550 // Prims - If the player is in a Gm Event and is a pvp event, then its in a zone battle also
13551 if (GmEventManager.getInstance().isParticipating(this) && GmEventManager.getInstance().isPvPEvent())
13552 return true;
13553
13554 return super.isInZoneBattle();
13555 }
13556
13557 @Override
13558 public boolean isInZonePeace()
13559 {
13560 // Prims - If the player is in a Gm Event and is a peace event, then its in a peace zone
13561 if (GmEventManager.getInstance().isParticipating(this) && GmEventManager.getInstance().isPeaceEvent())
13562 return true;
13563
13564 return super.isInZonePeace();
13565 }
13566 /** ----------------- Hit Man System ------------------- */
13567 public int _ordered;
13568 public int getOrdered()
13569 {
13570 return _ordered;
13571 }
13572
13573 public void setOrdered(int ordered)
13574 {
13575 _ordered = ordered;
13576 broadcastUserInfo(true);
13577 }
13578 /** ----------------- End Hit Man System -------------------
13579
13580 * @return
13581 * */
13582 public boolean isInAwayingMode()
13583 {
13584 return _awaying;
13585 }
13586
13587 public void setAwayingMode(boolean awaying)
13588 {
13589 _awaying = awaying;
13590 }
13591 /**
13592 * 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
13593 *
13594 * @param oldSkillReuseHashCode
13595 * @param newSkillReuseHashCode
13596 */
13597 public void disableSkillByNewLvl(Integer oldSkillReuseHashCode, Integer newSkillReuseHashCode)
13598 {
13599 if (oldSkillReuseHashCode == newSkillReuseHashCode)
13600 return;
13601
13602 if (_skillReuses == null)
13603 return;
13604
13605 final TimeStamp timeStamp = _skillReuses.get(oldSkillReuseHashCode);
13606 if (timeStamp == null)
13607 return;
13608
13609 _skillReuses.remove(oldSkillReuseHashCode);
13610
13611 if (timeStamp.getEndTime() <= 0 || timeStamp.getEndTime() < System.currentTimeMillis())
13612 return;
13613
13614 _skillReuses.put(newSkillReuseHashCode, timeStamp);
13615 }
13616
13617 // Synerge - Support for being able to enchant a weapon/armor using all attribute stones available
13618 private boolean _isEnchantAllAttribute = false;
13619
13620 public void setIsEnchantAllAttribute(boolean isEnchantAllAttribute)
13621 {
13622 _isEnchantAllAttribute = isEnchantAllAttribute;
13623 }
13624
13625 public boolean isEnchantAllAttribute()
13626 {
13627 return _isEnchantAllAttribute;
13628 }
13629
13630 public boolean isDualbox(Player ... players)
13631 {
13632 return isDualbox(0, false, Arrays.asList(players));
13633 }
13634
13635 public boolean isDualbox(Iterable<Player> players)
13636 {
13637 return isDualbox(0, false, players);
13638 }
13639
13640 public boolean isDualbox(int maxBoxesAllowed, boolean hwidOnly, Player ... players)
13641 {
13642 if (maxBoxesAllowed < 0)
13643 return false;
13644
13645 return isDualbox(maxBoxesAllowed, hwidOnly, Arrays.asList(players));
13646 }
13647
13648 public boolean isDualbox(int maxBoxesAllowed, boolean hwidOnly, Iterable<Player> players)
13649 {
13650 if (maxBoxesAllowed < 0)
13651 return false;
13652
13653 for (Player player : players)
13654 {
13655 if (player == null || player.getNetConnection() == null || player == this)
13656 continue;
13657
13658 if (!hwidOnly && getIP().equalsIgnoreCase(player.getIP()))
13659 {
13660 maxBoxesAllowed--;
13661 }
13662 else if (getHWID().equalsIgnoreCase(player.getHWID()))
13663 {
13664 maxBoxesAllowed--;
13665 }
13666
13667 if (maxBoxesAllowed < 0)
13668 return true;
13669 }
13670
13671 return false;
13672 }
13673
13674 private final Map<Integer, Integer> _achievementLevels = new FastMap<>();
13675
13676 public boolean achievement_nf_open;
13677
13678 public Map<Integer, Integer> getAchievements(int category)
13679 {
13680 Map<Integer, Integer> result = new FastMap<>();
13681 for(Entry<Integer, Integer> entry : _achievementLevels.entrySet())
13682 {
13683 int achievementId = entry.getKey();
13684 int achievementLevel = entry.getValue();
13685 Achievement ach = Achievements.getInstance().getAchievement(achievementId, Math.max(1, achievementLevel));
13686 if (ach != null && ach.getCategoryId() == category)
13687 result.put(achievementId, achievementLevel);
13688 }
13689 return result;
13690 }
13691
13692 public Map<Integer, Integer> getAchievements()
13693 {
13694 return _achievementLevels;
13695 }
13696
13697 private void loadAchivements()
13698 {
13699 String achievements = getVar("achievements");
13700 if (achievements != null && !achievements.isEmpty())
13701 {
13702 String[] levels = achievements.split(";");
13703 for(String ach : levels)
13704 {
13705 String[] lvl = ach.split(",");
13706
13707 // Check if achievement exists.
13708 if (Achievements.getInstance().getMaxLevel(Integer.parseInt(lvl[0])) > 0)
13709 _achievementLevels.put(Integer.parseInt(lvl[0]), Integer.parseInt(lvl[1]));
13710 }
13711 }
13712
13713 for(int achievementId : Achievements.getInstance().getAchievementIds())
13714 if (!_achievementLevels.containsKey(achievementId))
13715 _achievementLevels.put(achievementId, 0);
13716 }
13717
13718 private void saveAchivements()
13719 {
13720 String str = "";
13721 for(Entry<Integer, Integer> a : _achievementLevels.entrySet())
13722 str += a.getKey() + "," + a.getValue() + ";";
13723
13724 setVar("achievements", str);
13725 }
13726
13727 private PlayerCounters _playerCountersExtension = null;
13728
13729 public PlayerCounters getCounters()
13730 {
13731 //if (!Config.ENABLE_PLAYER_COUNTERS) // Return Dummy counters when achievements arent enabled.
13732 // return PlayerCounters.DUMMY_COUNTER;
13733
13734 if (_playerCountersExtension == null)
13735 {
13736 synchronized (this)
13737 {
13738 if (_playerCountersExtension == null)
13739 _playerCountersExtension = new PlayerCounters(this);
13740 }
13741 }
13742 return _playerCountersExtension;
13743 }
13744
13745 // Synerge - Custom stats holder
13746// private PcStats _stats;
13747//
13748// public final PcStats getStats()
13749// {
13750// return _stats;
13751// }
13752//
13753// public final void addPlayerStats(Ranking rank)
13754// {
13755// getStats().addPlayerStats(rank);
13756// }
13757//
13758// public final void addPlayerStats(Ranking rank, long points)
13759// {
13760// getStats().addPlayerStats(rank, points);
13761// }
13762
13763 public void broadcastSkillOrSocialAnimation(int id, int level, int hitTime, int lockActivityTime)
13764 {
13765 if (isAlikeDead())
13766 return;
13767
13768 boolean performSocialAction = (level < 1);
13769
13770 if (!performSocialAction)
13771 broadcastPacket(new MagicSkillUse(this, this, id, level, hitTime, 0));
13772 else
13773 broadcastPacket(new SocialAction(getObjectId(), id));
13774 }
13775
13776 private int soloInstance;
13777
13778 public void updateSoloInstance()
13779 {
13780 this.soloInstance++;
13781 }
13782
13783 public int getSoloInstance()
13784 {
13785 return soloInstance;
13786 }
13787
13788 private int partyInstance;
13789
13790 public void updatePartyInstance()
13791 {
13792 this.partyInstance++;
13793 }
13794
13795 public int getPartyInstance()
13796 {
13797 return partyInstance;
13798 }
13799
13800 // Captcha
13801 private int _capchaCount = 0;
13802
13803 public int getCapchaCount()
13804 {
13805 return _capchaCount;
13806 }
13807
13808 public void updateCapchaCount(int count)
13809 {
13810 _capchaCount = count;
13811 }
13812
13813 // Synerge - Used for catpcha system, sets when was the last time that this player did damage to a monster
13814 private long _lastMonsterDamageTime = 0;
13815
13816 public long getLastMonsterDamageTime()
13817 {
13818 return _lastMonsterDamageTime;
13819 }
13820
13821 public void setLastMonsterDamageTime()
13822 {
13823 _lastMonsterDamageTime = System.currentTimeMillis();
13824 }
13825}