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