Guest User

Untitled

a guest
Sep 29th, 2013
540
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 286.29 KB | None | 0 0
  1. package l2r.gameserver.model;
  2.  
  3. import l2r.commons.collections.LazyArrayList;
  4. import l2r.commons.dao.JdbcEntityState;
  5. import l2r.commons.dbutils.DbUtils;
  6. import l2r.commons.lang.reference.HardReference;
  7. import l2r.commons.lang.reference.HardReferences;
  8. import l2r.commons.threading.RunnableImpl;
  9. import l2r.commons.util.Rnd;
  10. import l2r.gameserver.Config;
  11. import l2r.gameserver.GameTimeController;
  12. import l2r.gameserver.ThreadPoolManager;
  13. import l2r.gameserver.ai.CtrlEvent;
  14. import l2r.gameserver.ai.CtrlIntention;
  15. import l2r.gameserver.ai.PlayableAI.nextAction;
  16. import l2r.gameserver.ai.PlayerAI;
  17. import l2r.gameserver.dao.*;
  18. import l2r.gameserver.data.xml.holder.*;
  19. import l2r.gameserver.data.xml.holder.MultiSellHolder.MultiSellListContainer;
  20. import l2r.gameserver.database.DatabaseFactory;
  21. import l2r.gameserver.database.mysql;
  22. import l2r.gameserver.gve.GveConfig;
  23. import l2r.gameserver.gve.managers.FactionManager;
  24. import l2r.gameserver.handler.bbs.CommunityBoardManager;
  25. import l2r.gameserver.handler.bbs.ICommunityBoardHandler;
  26. import l2r.gameserver.handler.items.IItemHandler;
  27. import l2r.gameserver.handler.voicecommands.impl.RefferalSystem;
  28. import l2r.gameserver.idfactory.IdFactory;
  29. import l2r.gameserver.instancemanager.*;
  30. import l2r.gameserver.instancemanager.BypassManager.BypassType;
  31. import l2r.gameserver.instancemanager.BypassManager.DecodedBypass;
  32. import l2r.gameserver.instancemanager.games.HandysBlockCheckerManager;
  33. import l2r.gameserver.instancemanager.games.HandysBlockCheckerManager.ArenaParticipantsHolder;
  34. import l2r.gameserver.listener.actor.player.OnAnswerListener;
  35. import l2r.gameserver.listener.actor.player.impl.ReviveAnswerListener;
  36. import l2r.gameserver.listener.actor.player.impl.ScriptAnswerListener;
  37. import l2r.gameserver.listener.actor.player.impl.SummonAnswerListener;
  38. import l2r.gameserver.model.GameObjectTasks.*;
  39. import l2r.gameserver.model.Request.L2RequestType;
  40. import l2r.gameserver.model.Skill.AddedSkill;
  41. import l2r.gameserver.model.Zone.ZoneType;
  42. import l2r.gameserver.model.actor.instances.player.*;
  43. import l2r.gameserver.model.actor.instances.player.FriendList;
  44. import l2r.gameserver.model.actor.listener.PlayerListenerList;
  45. import l2r.gameserver.model.actor.recorder.PlayerStatsChangeRecorder;
  46. import l2r.gameserver.model.base.*;
  47. import l2r.gameserver.model.entity.DimensionalRift;
  48. import l2r.gameserver.model.entity.Hero;
  49. import l2r.gameserver.model.entity.Reflection;
  50. import l2r.gameserver.model.entity.SevenSignsFestival.DarknessFestival;
  51. import l2r.gameserver.model.entity.boat.Boat;
  52. import l2r.gameserver.model.entity.boat.ClanAirShip;
  53. import l2r.gameserver.model.entity.events.GlobalEvent;
  54. import l2r.gameserver.model.entity.events.impl.DominionSiegeEvent;
  55. import l2r.gameserver.model.entity.events.impl.DuelEvent;
  56. import l2r.gameserver.model.entity.events.impl.SiegeEvent;
  57. import l2r.gameserver.model.entity.olympiad.CompType;
  58. import l2r.gameserver.model.entity.olympiad.Olympiad;
  59. import l2r.gameserver.model.entity.olympiad.OlympiadGame;
  60. import l2r.gameserver.model.entity.residence.Castle;
  61. import l2r.gameserver.model.entity.residence.ClanHall;
  62. import l2r.gameserver.model.entity.residence.Fortress;
  63. import l2r.gameserver.model.entity.residence.Residence;
  64. import l2r.gameserver.model.instances.*;
  65. import l2r.gameserver.model.items.*;
  66. import l2r.gameserver.model.items.Warehouse.WarehouseType;
  67. import l2r.gameserver.model.items.attachment.FlagItemAttachment;
  68. import l2r.gameserver.model.items.attachment.PickableAttachment;
  69. import l2r.gameserver.model.matching.MatchingRoom;
  70. import l2r.gameserver.model.petition.PetitionMainGroup;
  71. import l2r.gameserver.model.pledge.*;
  72. import l2r.gameserver.model.quest.Quest;
  73. import l2r.gameserver.model.quest.QuestEventType;
  74. import l2r.gameserver.model.quest.QuestState;
  75. import l2r.gameserver.network.GameClient;
  76. import l2r.gameserver.network.serverpackets.*;
  77. import l2r.gameserver.network.serverpackets.components.CustomMessage;
  78. import l2r.gameserver.network.serverpackets.components.IStaticPacket;
  79. import l2r.gameserver.network.serverpackets.components.SceneMovie;
  80. import l2r.gameserver.network.serverpackets.components.SystemMsg;
  81. import l2r.gameserver.scripts.Events;
  82. import l2r.gameserver.skills.EffectType;
  83. import l2r.gameserver.skills.TimeStamp;
  84. import l2r.gameserver.skills.effects.EffectCubic;
  85. import l2r.gameserver.skills.effects.EffectTemplate;
  86. import l2r.gameserver.skills.skillclasses.Charge;
  87. import l2r.gameserver.skills.skillclasses.Transformation;
  88. import l2r.gameserver.stats.Formulas;
  89. import l2r.gameserver.stats.Stats;
  90. import l2r.gameserver.stats.funcs.FuncTemplate;
  91. import l2r.gameserver.tables.*;
  92. import l2r.gameserver.taskmanager.AutoSaveManager;
  93. import l2r.gameserver.taskmanager.LazyPrecisionTaskManager;
  94. import l2r.gameserver.templates.FishTemplate;
  95. import l2r.gameserver.templates.Henna;
  96. import l2r.gameserver.templates.InstantZone;
  97. import l2r.gameserver.templates.PlayerTemplate;
  98. import l2r.gameserver.templates.item.ArmorTemplate;
  99. import l2r.gameserver.templates.item.ArmorTemplate.ArmorType;
  100. import l2r.gameserver.templates.item.ItemTemplate;
  101. import l2r.gameserver.templates.item.WeaponTemplate;
  102. import l2r.gameserver.templates.item.WeaponTemplate.WeaponType;
  103. import l2r.gameserver.templates.npc.NpcTemplate;
  104. import l2r.gameserver.utils.*;
  105. import l2r.loginserver.database.L2DatabaseFactory;
  106. import org.apache.commons.lang3.ArrayUtils;
  107. import org.apache.commons.lang3.tuple.ImmutablePair;
  108. import org.apache.commons.lang3.tuple.Pair;
  109. import org.napile.primitive.Containers;
  110. import org.napile.primitive.maps.IntObjectMap;
  111. import org.napile.primitive.maps.impl.CHashIntObjectMap;
  112. import org.slf4j.Logger;
  113. import org.slf4j.LoggerFactory;
  114.  
  115. import java.awt.*;
  116. import java.sql.*;
  117. import java.util.*;
  118. import java.util.List;
  119. import java.util.Map.Entry;
  120. import java.util.concurrent.*;
  121. import java.util.concurrent.atomic.AtomicBoolean;
  122. import java.util.concurrent.atomic.AtomicInteger;
  123. import java.util.concurrent.locks.Lock;
  124. import java.util.concurrent.locks.ReentrantLock;
  125.  
  126. import static l2r.gameserver.network.serverpackets.ExSetCompassZoneCode.*;
  127.  
  128. public final class Player extends Playable implements PlayerGroup
  129. {
  130.     private static final long serialVersionUID = -4408842247140935625L;
  131.     public static final int DEFAULT_TITLE_COLOR = 0xFFFF77;
  132.     public static final int MAX_POST_FRIEND_SIZE = 100;
  133.     public static final int MAX_FRIEND_SIZE = 128;
  134.  
  135.     private static final Logger _log = LoggerFactory.getLogger(Player.class);
  136.  
  137.     public static final String NO_TRADERS_VAR = "notraders";
  138.     public static final String NO_ANIMATION_OF_CAST_VAR = "notShowBuffAnim";
  139.     public static final String MY_BIRTHDAY_RECEIVE_YEAR = "MyBirthdayReceiveYear";
  140.     private static final String NOT_CONNECTED = "<not connected>";
  141.  
  142.     public Map<Integer, SubClass> _classlist = new HashMap<Integer, SubClass>(4);
  143.  
  144.     public final static int OBSERVER_NONE = 0;
  145.     public final static int OBSERVER_STARTING = 1;
  146.     public final static int OBSERVER_STARTED = 3;
  147.     public final static int OBSERVER_LEAVING = 2;
  148.  
  149.     public static final int STORE_PRIVATE_NONE = 0;
  150.     public static final int STORE_PRIVATE_SELL = 1;
  151.     public static final int STORE_PRIVATE_BUY = 3;
  152.     public static final int STORE_PRIVATE_MANUFACTURE = 5;
  153.     public static final int STORE_OBSERVING_GAMES = 7;
  154.     public static final int STORE_PRIVATE_SELL_PACKAGE = 8;
  155.  
  156.     public static final int RANK_VAGABOND = 0;
  157.     public static final int RANK_VASSAL = 1;
  158.     public static final int RANK_HEIR = 2;
  159.     public static final int RANK_KNIGHT = 3;
  160.     public static final int RANK_WISEMAN = 4;
  161.     public static final int RANK_BARON = 5;
  162.     public static final int RANK_VISCOUNT = 6;
  163.     public static final int RANK_COUNT = 7;
  164.     public static final int RANK_MARQUIS = 8;
  165.     public static final int RANK_DUKE = 9;
  166.     public static final int RANK_GRAND_DUKE = 10;
  167.     public static final int RANK_DISTINGUISHED_KING = 11;
  168.     public static final int RANK_EMPEROR = 12; // unused
  169.  
  170.     public static final int LANG_ENG = 0;
  171.     public static final int LANG_RUS = 1;
  172.     public static final int LANG_UNK = -1;
  173.  
  174.     public static final int[] EXPERTISE_LEVELS =
  175.     {
  176.             0,
  177.             20,
  178.             40,
  179.             52,
  180.             61,
  181.             76,
  182.             80,
  183.             84,
  184.             Integer.MAX_VALUE
  185.     };
  186.  
  187.     private GameClient _connection;
  188.     private String _login;
  189.    
  190.     /** The player's bot punishment */
  191.     private AutoHuntingPunish _AutoHuntingPunish = null;
  192.     public AccountReportDAO _account = null;
  193.     /** Used to check if the player has gained exp since log in */
  194.     public long _firstExp;
  195.  
  196.     private int _karma, _pkKills, _pvpKills;
  197.     private int _face, _hairStyle, _hairColor;
  198.     private int _recomHave, _recomLeftToday, _fame;
  199.     private int _recomLeft = 20;
  200.     private int _recomBonusTime = 3600;
  201.     private boolean _isHourglassEffected, _isRecomTimerActive;
  202.     private boolean _isUndying = false;
  203.     private int _deleteTimer;
  204.  
  205.     private long _createTime, _onlineTime, _onlineBeginTime, _leaveClanTime, _deleteClanTime, _NoChannel, _NoChannelBegin;
  206.     private long _uptime;
  207.     /**
  208.      * Time on login in game
  209.      */
  210.     private long _lastAccess;
  211.  
  212.     /**
  213.      * The Color of players name / title (white is 0xFFFFFF)
  214.      */
  215.     private int _nameColor, _titlecolor;
  216.  
  217.     private int _vitalityLevel = -1;
  218.     private double _vitality = Config.VITALITY_LEVELS[4];
  219.     private boolean _overloaded;
  220.  
  221.     boolean sittingTaskLaunched;
  222.  
  223.     /**
  224.      * Time counter when L2Player is sitting
  225.      */
  226.     private int _waitTimeWhenSit;
  227.  
  228.     private boolean _autoLoot = Config.AUTO_LOOT, AutoLootHerbs = Config.AUTO_LOOT_HERBS;
  229.  
  230.     private final PcInventory _inventory = new PcInventory(this);
  231.     private final Warehouse _warehouse = new PcWarehouse(this);
  232.     private final ItemContainer _refund = new PcRefund(this);
  233.     private final PcFreight _freight = new PcFreight(this);
  234.  
  235.     public final BookMarkList bookmarks = new BookMarkList(this, 0);
  236.  
  237.     public final AntiFlood antiFlood = new AntiFlood();
  238.  
  239.     /**
  240.      * The table containing all L2RecipeList of the L2Player
  241.      */
  242.     private final Map<Integer, Recipe> _recipebook = new TreeMap<Integer, Recipe>();
  243.     private final Map<Integer, Recipe> _commonrecipebook = new TreeMap<Integer, Recipe>();
  244.  
  245.     /**
  246.      * Premium Items
  247.      */
  248.     private Map<Integer, PremiumItem> _premiumItems = new TreeMap<Integer, PremiumItem>();
  249.  
  250.     /**
  251.      * The table containing all Quests began by the L2Player
  252.      */
  253.     private final Map<String, QuestState> _quests = new HashMap<String, QuestState>();
  254.  
  255.     /**
  256.      * The list containing all shortCuts of this L2Player
  257.      */
  258.     private final ShortCutList _shortCuts = new ShortCutList(this);
  259.  
  260.     /**
  261.      * The list containing all macroses of this L2Player
  262.      */
  263.     private final MacroList _macroses = new MacroList(this);
  264.  
  265.     /**
  266.      * 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)
  267.      */
  268.     private int _privatestore;
  269.     /**
  270.      * Данные для магазина рецептов
  271.      */
  272.     private String _manufactureName;
  273.     private List<ManufactureItem> _createList = Collections.emptyList();
  274.     /**
  275.      * Данные для магазина продажи
  276.      */
  277.     private String _sellStoreName;
  278.     private List<TradeItem> _sellList = Collections.emptyList();
  279.     private List<TradeItem> _packageSellList = Collections.emptyList();
  280.     /**
  281.      * Данные для магазина покупки
  282.      */
  283.     private String _buyStoreName;
  284.     private List<TradeItem> _buyList = Collections.emptyList();
  285.     /**
  286.      * Данные для обмена
  287.      */
  288.     private List<TradeItem> _tradeList = Collections.emptyList();
  289.  
  290.     // gve
  291.     private int _price;
  292.     private int famePoints;
  293.  
  294.     public FactionManager.Rank getRank()
  295.     {
  296.         return _rank;
  297.     }
  298.  
  299.     public void setRank(FactionManager.Rank _rank)
  300.     {
  301.         this._rank = _rank;
  302.         broadcastCharInfo();
  303.     }
  304.  
  305.     private FactionManager.Rank _rank = FactionManager.Rank.soldier9;
  306.  
  307.     public void updateRank()
  308.     {
  309.         FactionManager.Rank rank = FactionManager.Rank.getRankForPlayer(this);
  310.         if(rank != _rank)
  311.         {
  312.             _rank = rank;
  313.             updatePrice();
  314.         }
  315.     }
  316.  
  317.     /**
  318.      * hennas
  319.      */
  320.     private final Henna[] _henna = new Henna[3];
  321.     private int _hennaSTR, _hennaINT, _hennaDEX, _hennaMEN, _hennaWIT, _hennaCON;
  322.  
  323.     private Party _party;
  324.     private Location _lastPartyPosition;
  325.  
  326.     private Clan _clan;
  327.     private int _pledgeClass = 0, _pledgeType = Clan.SUBUNIT_NONE, _powerGrade = 0, _lvlJoinedAcademy = 0, _apprentice = 0;
  328.  
  329.     /**
  330.      * GM Stuff
  331.      */
  332.     private int _accessLevel;
  333.     private PlayerAccess _playerAccess = new PlayerAccess();
  334.  
  335.     private boolean _messageRefusal = false, _tradeRefusal = false, _blockAll = false;
  336.  
  337.     /**
  338.      * The L2Summon of the L2Player
  339.      */
  340.     private Summon _summon = null;
  341.     private boolean _riding;
  342.  
  343.     private DecoyInstance _decoy = null;
  344.  
  345.     private Map<Integer, EffectCubic> _cubics = null;
  346.     private int _agathionId = 0;
  347.  
  348.     private Request _request;
  349.  
  350.     private ItemInstance _arrowItem;
  351.  
  352.     /**
  353.      * The fists L2Weapon of the L2Player (used when no weapon is equipped)
  354.      */
  355.     private WeaponTemplate _fistsWeaponItem;
  356.  
  357.     private Map<Integer, String> _chars = new HashMap<Integer, String>(8);
  358.  
  359.     /**
  360.      * The current higher Expertise of the L2Player (None=0, D=1, C=2, B=3, A=4, S=5, S80=6, S84=7)
  361.      */
  362.     public int expertiseIndex = 0;
  363.  
  364.     private ItemInstance _enchantScroll = null;
  365.  
  366.     private WarehouseType _usingWHType;
  367.  
  368.     private boolean _isOnline = false;
  369.  
  370.     private AtomicBoolean _isLogout = new AtomicBoolean();
  371.  
  372.     /**
  373.      * The L2NpcInstance corresponding to the last Folk which one the player talked.
  374.      */
  375.     private HardReference<NpcInstance> _lastNpc = HardReferences.emptyRef();
  376.     /**
  377.      * тут храним мультиселл с которым работаем
  378.      */
  379.     private MultiSellListContainer _multisell = null;
  380.  
  381.     private Set<Integer> _activeSoulShots = new CopyOnWriteArraySet<Integer>();
  382.  
  383.     private WorldRegion _observerRegion;
  384.     private AtomicInteger _observerMode = new AtomicInteger(0);
  385.  
  386.     public int _telemode = 0;
  387.  
  388.     private int _handysBlockCheckerEventArena = -1;
  389.  
  390.     public boolean entering = true;
  391.  
  392.     /**
  393.      * Эта точка проверяется при нештатном выходе чара, и если не равна null чар возвращается в нее
  394.      * Используется например для возвращения при падении с виверны
  395.      * Поле heading используется для хранения денег возвращаемых при сбое
  396.      */
  397.     public Location _stablePoint = null;
  398.  
  399.     /**
  400.      * new loto ticket *
  401.      */
  402.     public int _loto[] = new int[5];
  403.     /**
  404.      * new race ticket *
  405.      */
  406.     public int _race[] = new int[2];
  407.  
  408.     private final Map<Integer, String> _blockList = new ConcurrentSkipListMap<Integer, String>(); // characters blocked with '/block <charname>' cmd
  409.     private final FriendList _friendList = new FriendList(this);
  410.  
  411.     private boolean _hero = false;
  412.  
  413.     /**
  414.      * True if the L2Player is in a boat
  415.      */
  416.     private Boat _boat;
  417.     private Location _inBoatPosition;
  418.  
  419.     protected int _baseClass = -1;
  420.     protected SubClass _activeClass = null;
  421.  
  422.     private Bonus _bonus = new Bonus();
  423.     private Future<?> _bonusExpiration;
  424.  
  425.     private boolean _isSitting;
  426.     private StaticObjectInstance _sittingObject;
  427.  
  428.     private boolean _noble = false;
  429.  
  430.     private boolean _inOlympiadMode;
  431.     private OlympiadGame _olympiadGame;
  432.     private OlympiadGame _olympiadObserveGame;
  433.  
  434.     private int _olympiadSide = -1;
  435.  
  436.     /**
  437.      * ally with ketra or varka related wars
  438.      */
  439.     private int _varka = 0;
  440.     private int _ketra = 0;
  441.     private int _ram = 0;
  442.  
  443.     private byte[] _keyBindings = ArrayUtils.EMPTY_BYTE_ARRAY;
  444.  
  445.     private int _cursedWeaponEquippedId = 0;
  446.  
  447.     private final Fishing _fishing = new Fishing(this);
  448.     private boolean _isFishing;
  449.  
  450.     private Future<?> _taskWater;
  451.     private Future<?> _autoSaveTask;
  452.     private Future<?> _kickTask;
  453.  
  454.     private Future<?> _vitalityTask;
  455.     private Future<?> _pcCafePointsTask;
  456.     private Future<?> _unjailTask;
  457.  
  458.     private final Lock _storeLock = new ReentrantLock();
  459.  
  460.     private int _zoneMask;
  461.  
  462.     private boolean _offline = false;
  463.  
  464.     private int _transformationId;
  465.     private int _transformationTemplate;
  466.     private String _transformationName;
  467.  
  468.     private int _pcBangPoints;
  469.  
  470.     Map<Integer, Skill> _transformationSkills = new HashMap<Integer, Skill>();
  471.  
  472.     private int _expandInventory = 0;
  473.     private int _expandWarehouse = 0;
  474.     private int _battlefieldChatId;
  475.     private int _lectureMark;
  476.     private InvisibleType _invisibleType = InvisibleType.NONE;
  477.  
  478.     private List<String> bypasses = null, bypasses_bbs = null;
  479.     private IntObjectMap<String> _postFriends = Containers.emptyIntObjectMap();
  480.  
  481.     private List<String> _blockedActions = new ArrayList<String>();
  482.  
  483.     private boolean _notShowBuffAnim = false;
  484.     private boolean _notShowTraders = false;
  485.     private boolean _debug = false;
  486.  
  487.     private long _dropDisabled;
  488.     private long _lastItemAuctionInfoRequest;
  489.  
  490.     private IntObjectMap<TimeStamp> _sharedGroupReuses = new CHashIntObjectMap<TimeStamp>();
  491.     private Pair<Integer, OnAnswerListener> _askDialog = null;
  492.  
  493.     // High Five: Navit's Bonus System
  494.     private NevitSystem _nevitSystem = new NevitSystem(this);
  495.  
  496.     private MatchingRoom _matchingRoom;
  497.     private PetitionMainGroup _petitionGroup;
  498.     private final Map<Integer, Long> _instancesReuses = new ConcurrentHashMap<Integer, Long>();
  499.  
  500.     private Skill _macroSkill = null;
  501.     /**
  502.      * Конструктор для L2Player. Напрямую не вызывается, для создания игрока используется PlayerManager.create
  503.      */
  504.     public Player(final int objectId, final PlayerTemplate template, final String accountName)
  505.     {
  506.         super(objectId, template);
  507.  
  508.         _login = accountName;
  509.         _nameColor = 0xFFFFFF;
  510.         _titlecolor = 0xFFFF77;
  511.         _baseClass = getClassId().getId();
  512.     }
  513.  
  514.     /**
  515.      * Constructor<?> of L2Player (use L2Character constructor).<BR><BR>
  516.      * <p/>
  517.      * <B><U> Actions</U> :</B><BR><BR>
  518.      * <li>Call the L2Character constructor to create an empty _skills slot and copy basic Calculator set to this L2Player </li>
  519.      * <li>Create a L2Radar object</li>
  520.      * <li>Retrieve from the database all items of this L2Player and add them to _inventory </li>
  521.      * <p/>
  522.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SET the account name of the L2Player</B></FONT><BR><BR>
  523.      *
  524.      * @param objectId Identifier of the object to initialized
  525.      * @param template The L2PlayerTemplate to apply to the L2Player
  526.      */
  527.     private Player(final int objectId, final PlayerTemplate template)
  528.     {
  529.         this(objectId, template, null);
  530.  
  531.         _ai = new PlayerAI(this);
  532.  
  533.         if(!Config.EVERYBODY_HAS_ADMIN_RIGHTS)
  534.             setPlayerAccess(Config.gmlist.get(objectId));
  535.         else
  536.             setPlayerAccess(Config.gmlist.get(0));
  537.     }
  538.  
  539.     @SuppressWarnings("unchecked")
  540.     @Override
  541.     public HardReference<Player> getRef()
  542.     {
  543.         return (HardReference<Player>) super.getRef();
  544.     }
  545.  
  546.     public String getAccountName()
  547.     {
  548.         if(_connection == null)
  549.             return _login;
  550.         return _connection.getLogin();
  551.     }
  552.  
  553.     public String getIP()
  554.     {
  555.         if(_connection == null)
  556.             return NOT_CONNECTED;
  557.         return _connection.getIpAddr();
  558.     }
  559.  
  560.     /**
  561.      * Возвращает список персонажей на аккаунте, за исключением текущего
  562.      *
  563.      * @return Список персонажей
  564.      */
  565.     public Map<Integer, String> getAccountChars()
  566.     {
  567.         return _chars;
  568.     }
  569.  
  570.     @Override
  571.     public final PlayerTemplate getTemplate()
  572.     {
  573.         return (PlayerTemplate) _template;
  574.     }
  575.  
  576.     @Override
  577.     public PlayerTemplate getBaseTemplate()
  578.     {
  579.         return (PlayerTemplate) _baseTemplate;
  580.     }
  581.  
  582.     public void changeSex()
  583.     {
  584.         boolean male = true;
  585.         if(getSex() == 1)
  586.             male = false;
  587.         _template = CharTemplateTable.getInstance().getTemplate(getClassId(), !male);
  588.     }
  589.  
  590.     @Override
  591.     public PlayerAI getAI()
  592.     {
  593.         return (PlayerAI) _ai;
  594.     }
  595.  
  596.     @Override
  597.     public void doAttack(final Creature target)
  598.     {
  599.         if (getFaction() != FactionManager.Faction.ADMIN && target.getPlayer() != null && target.getFaction() == getFaction())
  600.         {
  601.             return;
  602.         }
  603.  
  604.         super.doAttack(target);
  605.     }
  606.  
  607.     @Override
  608.     public void doCast(final Skill skill, final Creature target, boolean forceUse)
  609.     {
  610.         if(skill == null)
  611.             return;
  612.  
  613.         if (skill.getSkillType() == Skill.SkillType.HEAL || skill.getSkillType() == Skill.SkillType.BUFF)
  614.         {
  615.             if (getFaction() != FactionManager.Faction.ADMIN && getFaction() != target.getFaction()/* || target.isFlag*/)
  616.             {
  617.                 return;
  618.             }
  619.         }
  620.  
  621.         super.doCast(skill, target, forceUse);
  622.     }
  623.  
  624.     @Override
  625.     public void setFaction(FactionManager.Faction f)
  626.     {
  627.         super.setFaction(f);
  628.  
  629.         switch (getFaction())
  630.         {
  631.             case EVIL:
  632.                 setTitleColor(255, 62, 44); // red
  633.                 setNameColor(255, 62, 44); // red
  634.                 break;
  635.  
  636.             case GOOD:
  637.                 setTitleColor(99, 240, 79);
  638.                 setNameColor(99, 240, 79); // green
  639.                 break;
  640.  
  641.             case ADMIN:
  642.                 setTitleColor(248, 175, 0); // orange
  643.                 break;
  644.  
  645.             default:
  646.                 setTitleColor(Config.NORMAL_NAME_COLOUR);
  647.         }
  648.     }
  649.  
  650.     @Override
  651.     public void sendReuseMessage(Skill skill)
  652.     {
  653.         if(isCastingNow())
  654.             return;
  655.         TimeStamp sts = getSkillReuse(skill);
  656.         if(sts == null || !sts.hasNotPassed())
  657.             return;
  658.         long timeleft = sts.getReuseCurrent();
  659.         if(!Config.ALT_SHOW_REUSE_MSG && timeleft < 10000 || timeleft < 500)
  660.             return;
  661.         long hours = timeleft / 3600000;
  662.         long minutes = (timeleft - hours * 3600000) / 60000;
  663.         long seconds = (long) Math.ceil((timeleft - hours * 3600000 - minutes * 60000) / 1000.);
  664.         if(hours > 0)
  665.             sendPacket(new SystemMessage2(SystemMsg.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));
  666.         else if(minutes > 0)
  667.             sendPacket(new SystemMessage2(SystemMsg.THERE_ARE_S2_MINUTES_S3_SECONDS_REMAINING_IN_S1S_REUSE_TIME).addSkillName(skill.getId(), skill.getDisplayLevel()).addNumber(minutes).addNumber(seconds));
  668.         else
  669.             sendPacket(new SystemMessage2(SystemMsg.THERE_ARE_S2_SECONDS_REMAINING_IN_S1S_REUSE_TIME).addSkillName(skill.getId(), skill.getDisplayLevel()).addNumber(seconds));
  670.     }
  671.  
  672.     @Override
  673.     public final int getLevel()
  674.     {
  675.         return _activeClass == null ? 1 : _activeClass.getLevel();
  676.     }
  677.  
  678.     public int getSex()
  679.     {
  680.         return getTemplate().isMale ? 0 : 1;
  681.     }
  682.  
  683.     public int getFace()
  684.     {
  685.         return _face;
  686.     }
  687.  
  688.     public void setFace(int face)
  689.     {
  690.         _face = face;
  691.     }
  692.  
  693.     public int getHairColor()
  694.     {
  695.         return _hairColor;
  696.     }
  697.  
  698.     public void setHairColor(int hairColor)
  699.     {
  700.         _hairColor = hairColor;
  701.     }
  702.  
  703.     public int getHairStyle()
  704.     {
  705.         return _hairStyle;
  706.     }
  707.  
  708.     public void setHairStyle(int hairStyle)
  709.     {
  710.         _hairStyle = hairStyle;
  711.     }
  712.  
  713.     public void offline()
  714.     {
  715.         if(isInObserverMode())
  716.         {
  717.             if(getOlympiadObserveGame() == null)
  718.             {
  719.                 leaveObserverMode();
  720.             }
  721.             else
  722.             {
  723.                 leaveOlympiadObserverMode(true);
  724.             }
  725.  
  726.             _observerMode.set(OBSERVER_NONE);
  727.         }
  728.  
  729.         if(isInOlympiadMode() || getOlympiadGame() != null)
  730.         {
  731.             Olympiad.logoutPlayer(this);
  732.         }
  733.  
  734.         if(_connection != null)
  735.         {
  736.             _connection.setActiveChar(null);
  737.             _connection.close(ServerClose.STATIC);
  738.             setNetConnection(null);
  739.         }
  740.  
  741.         if(_nameColor == Config.NORMAL_NAME_COLOUR)
  742.             setNameColor(Config.SERVICES_OFFLINE_TRADE_NAME_COLOR);
  743.         setOfflineMode(true);
  744.  
  745.         setVar("offline", String.valueOf(System.currentTimeMillis() / 1000L), -1);
  746.  
  747.         if(Config.SERVICES_OFFLINE_TRADE_SECONDS_TO_KICK > 0)
  748.             startKickTask(Config.SERVICES_OFFLINE_TRADE_SECONDS_TO_KICK * 1000L);
  749.  
  750.         Party party = getParty();
  751.         if(party != null)
  752.         {
  753.             if(isFestivalParticipant())
  754.                 party.broadcastMessageToPartyMembers(getName() + " has been removed from the upcoming festival.");
  755.             leaveParty();
  756.         }
  757.  
  758.         if(getPet() != null)
  759.             getPet().unSummon();
  760.  
  761.         CursedWeaponsManager.getInstance().doLogout(this);
  762.  
  763.         if(isInObserverMode())
  764.         {
  765.             if(getOlympiadObserveGame() == null)
  766.                 leaveObserverMode();
  767.             else
  768.                 leaveOlympiadObserverMode(true);
  769.             _observerMode.set(OBSERVER_NONE);
  770.         }
  771.  
  772.         if(isInOlympiadMode() || getOlympiadGame() != null)
  773.             Olympiad.logoutPlayer(this);
  774.  
  775.         broadcastCharInfo();
  776.         stopWaterTask();
  777.         stopBonusTask();
  778.         stopHourlyTask();
  779.         stopVitalityTask();
  780.         stopPcBangPointsTask();
  781.         stopAutoSaveTask();
  782.         stopRecomBonusTask(true);
  783.         stopQuestTimers();
  784.         getNevitSystem().stopTasksOnLogout();
  785.  
  786.         try
  787.         {
  788.             getInventory().store();
  789.         }
  790.         catch(Throwable t)
  791.         {
  792.             _log.error("", t);
  793.         }
  794.  
  795.         try
  796.         {
  797.             store(false);
  798.         }
  799.         catch(Throwable t)
  800.         {
  801.             _log.error("", t);
  802.         }
  803.     }
  804.  
  805.     /**
  806.      * Соединение закрывается, клиент закрывается, персонаж сохраняется и удаляется из игры
  807.      */
  808.     public void kick()
  809.     {
  810.         if(_connection != null)
  811.         {
  812.             _connection.close(LeaveWorld.STATIC);
  813.             setNetConnection(null);
  814.         }
  815.         prepareToLogout();
  816.         deleteMe();
  817.     }
  818.  
  819.     /**
  820.      * Соединение не закрывается, клиент не закрывается, персонаж сохраняется и удаляется из игры
  821.      */
  822.     public void restart()
  823.     {
  824.         if(_connection != null)
  825.         {
  826.             _connection.setActiveChar(null);
  827.             setNetConnection(null);
  828.         }
  829.         prepareToLogout();
  830.         deleteMe();
  831.     }
  832.  
  833.     /**
  834.      * Соединение закрывается, клиент не закрывается, персонаж сохраняется и удаляется из игры
  835.      */
  836.     public void logout()
  837.     {
  838.         if(_connection != null)
  839.         {
  840.             _connection.close(ServerClose.STATIC);
  841.             setNetConnection(null);
  842.         }
  843.         prepareToLogout();
  844.         deleteMe();
  845.     }
  846.  
  847.     private void prepareToLogout()
  848.     {
  849.         if(_isLogout.getAndSet(true))
  850.             return;
  851.        
  852.         if(isInObserverMode())
  853.         {
  854.             if(getOlympiadObserveGame() == null)
  855.             {
  856.                 leaveObserverMode();
  857.             }
  858.             else
  859.             {
  860.                 leaveOlympiadObserverMode(true);
  861.             }
  862.  
  863.             _observerMode.set(OBSERVER_NONE);
  864.         }
  865.  
  866.         if(isInOlympiadMode() || getOlympiadGame() != null)
  867.         {
  868.             Olympiad.logoutPlayer(this);
  869.         }
  870.  
  871.        
  872.         setNetConnection(null);
  873.         setIsOnline(false);
  874.  
  875.         getListeners().onExit();
  876.  
  877.         if(isFlying() && !checkLandingState())
  878.             _stablePoint = TeleportUtils.getRestartLocation(this, RestartType.TO_VILLAGE);
  879.  
  880.         if(isCastingNow())
  881.             abortCast(true, true);
  882.  
  883.         Party party = getParty();
  884.         if(party != null)
  885.         {
  886.             if(isFestivalParticipant())
  887.                 party.broadcastMessageToPartyMembers("l2r.gameserver.Config.RemovedFromFestival");
  888.             leaveParty();
  889.         }
  890.  
  891.         CursedWeaponsManager.getInstance().doLogout(this);
  892.  
  893.         if(_olympiadObserveGame != null)
  894.             _olympiadObserveGame.removeSpectator(this);
  895.        
  896.         if(isInObserverMode())
  897.         {
  898.             if(getOlympiadObserveGame() == null)
  899.                 leaveObserverMode();
  900.             else
  901.                 leaveOlympiadObserverMode(true);
  902.             _observerMode.set(OBSERVER_NONE);
  903.         }
  904.  
  905.         if(isInOlympiadMode() || getOlympiadGame() != null)
  906.             Olympiad.logoutPlayer(this);
  907.  
  908.         stopFishing();
  909.  
  910.         if(_stablePoint != null)
  911.             teleToLocation(_stablePoint);
  912.  
  913.         Summon pet = getPet();
  914.         if(pet != null)
  915.         {
  916.             pet.saveEffects();
  917.             pet.unSummon();
  918.         }
  919.  
  920.         _friendList.notifyFriends(false);
  921.  
  922.         if(isProcessingRequest())
  923.             getRequest().cancel();
  924.  
  925.         stopAllTimers();
  926.  
  927.         if(isInBoat())
  928.             getBoat().removePlayer(this);
  929.  
  930.         SubUnit unit = getSubUnit();
  931.         UnitMember member = unit == null ? null : unit.getUnitMember(getObjectId());
  932.         if(member != null)
  933.         {
  934.             int sponsor = member.getSponsor();
  935.             int apprentice = getApprentice();
  936.             PledgeShowMemberListUpdate memberUpdate = new PledgeShowMemberListUpdate(this);
  937.             for(Player clanMember : _clan.getOnlineMembers(getObjectId()))
  938.             {
  939.                 clanMember.sendPacket(memberUpdate);
  940.                 if(clanMember.getObjectId() == sponsor)
  941.                     clanMember.sendPacket(new SystemMessage2(SystemMsg.YOUR_APPRENTICE_C1_HAS_LOGGED_OUT).addString(_name));
  942.                 else if(clanMember.getObjectId() == apprentice)
  943.                     clanMember.sendPacket(new SystemMessage2(SystemMsg.YOUR_SPONSOR_C1_HAS_LOGGED_OUT).addString(_name));
  944.             }
  945.             member.setPlayerInstance(this, true);
  946.         }
  947.  
  948.         FlagItemAttachment attachment = getActiveWeaponFlagAttachment();
  949.         if(attachment != null)
  950.             attachment.onLogout(this);
  951.  
  952.         if(CursedWeaponsManager.getInstance().getCursedWeapon(getCursedWeaponEquippedId()) != null)
  953.             CursedWeaponsManager.getInstance().getCursedWeapon(getCursedWeaponEquippedId()).setPlayer(null);
  954.  
  955.         MatchingRoom room = getMatchingRoom();
  956.         if(room != null)
  957.         {
  958.             if(room.getLeader() == this)
  959.                 room.disband();
  960.             else
  961.                 room.removeMember(this, false);
  962.         }
  963.         setMatchingRoom(null);
  964.  
  965.         MatchingRoomManager.getInstance().removeFromWaitingList(this);
  966.  
  967.         destroyAllTraps();
  968.  
  969.         if(_decoy != null)
  970.         {
  971.             _decoy.unSummon();
  972.             _decoy = null;
  973.         }
  974.  
  975.         //stopPvPFlag();
  976.  
  977.         Reflection ref = getReflection();
  978.  
  979.         if(ref != ReflectionManager.DEFAULT)
  980.         {
  981.             if(ref.getReturnLoc() != null)
  982.                 _stablePoint = ref.getReturnLoc();
  983.  
  984.             ref.removeObject(this);
  985.         }
  986.        
  987.         // Bot punishment
  988.         if(Config.ENABLE_AUTO_HUNTING_REPORT)      
  989.         {
  990.             // Save punish
  991.             if(isBeingPunished())
  992.             {
  993.                 try
  994.                 {
  995.                     AutoHuntingManager.getInstance().savePlayerPunish(this);
  996.                 }
  997.                 catch(Exception e)
  998.                 {
  999.                     _log.warn("deleteMe()", e);
  1000.                 }
  1001.             }
  1002.             // Save report points left
  1003.             if(_account != null)
  1004.             {
  1005.                 try
  1006.                 {
  1007.                     _account.updatePoints(this._login);
  1008.                 }
  1009.                 catch(Exception e)
  1010.                 {
  1011.                     e.printStackTrace();
  1012.                 }
  1013.             }
  1014.         }
  1015.  
  1016.         try
  1017.         {
  1018.             getInventory().store();
  1019.             getRefund().clear();
  1020.         }
  1021.         catch(Throwable t)
  1022.         {
  1023.             _log.error("", t);
  1024.         }
  1025.  
  1026.         try
  1027.         {
  1028.             store(false);
  1029.         }
  1030.         catch(Throwable t)
  1031.         {
  1032.             _log.error("", t);
  1033.         }
  1034.     }
  1035.  
  1036.     /**
  1037.      * @return a table containing all L2RecipeList of the L2Player.<BR><BR>
  1038.      */
  1039.     public Collection<Recipe> getDwarvenRecipeBook()
  1040.     {
  1041.         return _recipebook.values();
  1042.     }
  1043.  
  1044.     public Collection<Recipe> getCommonRecipeBook()
  1045.     {
  1046.         return _commonrecipebook.values();
  1047.     }
  1048.  
  1049.     public int recipesCount()
  1050.     {
  1051.         return _commonrecipebook.size() + _recipebook.size();
  1052.     }
  1053.  
  1054.     public boolean hasRecipe(final Recipe id)
  1055.     {
  1056.         return _recipebook.containsValue(id) || _commonrecipebook.containsValue(id);
  1057.     }
  1058.  
  1059.     public boolean findRecipe(final int id)
  1060.     {
  1061.         return _recipebook.containsKey(id) || _commonrecipebook.containsKey(id);
  1062.     }
  1063.  
  1064.     /**
  1065.      * Add a new L2RecipList to the table _recipebook containing all L2RecipeList of the L2Player
  1066.      */
  1067.     public void registerRecipe(final Recipe recipe, boolean saveDB)
  1068.     {
  1069.         if(recipe == null)
  1070.             return;
  1071.         if(recipe.isDwarvenRecipe())
  1072.             _recipebook.put(recipe.getId(), recipe);
  1073.         else
  1074.             _commonrecipebook.put(recipe.getId(), recipe);
  1075.         if(saveDB)
  1076.             mysql.set("REPLACE INTO character_recipebook (char_id, id) VALUES(?,?)", getObjectId(), recipe.getId());
  1077.     }
  1078.  
  1079.     /**
  1080.      * Remove a L2RecipList from the table _recipebook containing all L2RecipeList of the L2Player
  1081.      */
  1082.     public void unregisterRecipe(final int RecipeID)
  1083.     {
  1084.         if(_recipebook.containsKey(RecipeID))
  1085.         {
  1086.             mysql.set("DELETE FROM `character_recipebook` WHERE `char_id`=? AND `id`=? LIMIT 1", getObjectId(), RecipeID);
  1087.             _recipebook.remove(RecipeID);
  1088.         }
  1089.         else if(_commonrecipebook.containsKey(RecipeID))
  1090.         {
  1091.             mysql.set("DELETE FROM `character_recipebook` WHERE `char_id`=? AND `id`=? LIMIT 1", getObjectId(), RecipeID);
  1092.             _commonrecipebook.remove(RecipeID);
  1093.         }
  1094.         else
  1095.             _log.warn("Attempted to remove unknown RecipeList" + RecipeID);
  1096.     }
  1097.  
  1098.     // ------------------- Quest Engine ----------------------
  1099.  
  1100.     public QuestState getQuestState(String quest)
  1101.     {
  1102.         questRead.lock();
  1103.         try
  1104.         {
  1105.             return _quests.get(quest);
  1106.         }
  1107.         finally
  1108.         {
  1109.             questRead.unlock();
  1110.         }
  1111.     }
  1112.  
  1113.     public QuestState getQuestState(Class<?> quest)
  1114.     {
  1115.         return getQuestState(quest.getSimpleName());
  1116.     }
  1117.  
  1118.     public boolean isQuestCompleted(String quest)
  1119.     {
  1120.         QuestState q = getQuestState(quest);
  1121.         return q != null && q.isCompleted();
  1122.     }
  1123.  
  1124.     public boolean isQuestCompleted(Class<?> quest)
  1125.     {
  1126.         QuestState q = getQuestState(quest);
  1127.         return q != null && q.isCompleted();
  1128.     }
  1129.  
  1130.     public void setQuestState(QuestState qs)
  1131.     {
  1132.         questWrite.lock();
  1133.         try
  1134.         {
  1135.             _quests.put(qs.getQuest().getName(), qs);
  1136.         }
  1137.         finally
  1138.         {
  1139.             questWrite.unlock();
  1140.         }
  1141.     }
  1142.  
  1143.     public void removeQuestState(String quest)
  1144.     {
  1145.         questWrite.lock();
  1146.         try
  1147.         {
  1148.             _quests.remove(quest);
  1149.         }
  1150.         finally
  1151.         {
  1152.             questWrite.unlock();
  1153.         }
  1154.     }
  1155.  
  1156.     public Quest[] getAllActiveQuests()
  1157.     {
  1158.         List<Quest> quests = new ArrayList<Quest>(_quests.size());
  1159.         questRead.lock();
  1160.         try
  1161.         {
  1162.             for(final QuestState qs : _quests.values())
  1163.                 if(qs.isStarted())
  1164.                     quests.add(qs.getQuest());
  1165.         }
  1166.         finally
  1167.         {
  1168.             questRead.unlock();
  1169.         }
  1170.         return quests.toArray(new Quest[quests.size()]);
  1171.     }
  1172.  
  1173.     public QuestState[] getAllQuestsStates()
  1174.     {
  1175.         questRead.lock();
  1176.         try
  1177.         {
  1178.             return _quests.values().toArray(new QuestState[_quests.size()]);
  1179.         }
  1180.         finally
  1181.         {
  1182.             questRead.unlock();
  1183.         }
  1184.     }
  1185.  
  1186.     public List<QuestState> getQuestsForEvent(NpcInstance npc, QuestEventType event)
  1187.     {
  1188.         List<QuestState> states = new ArrayList<QuestState>();
  1189.         Quest[] quests = npc.getTemplate().getEventQuests(event);
  1190.         QuestState qs;
  1191.         if(quests != null)
  1192.             for(Quest quest : quests)
  1193.             {
  1194.                 qs = getQuestState(quest.getName());
  1195.                 if(qs != null && !qs.isCompleted())
  1196.                     states.add(getQuestState(quest.getName()));
  1197.             }
  1198.         return states;
  1199.     }
  1200.  
  1201.     public void processQuestEvent(String quest, String event, NpcInstance npc)
  1202.     {
  1203.         if(event == null)
  1204.             event = "";
  1205.         QuestState qs = getQuestState(quest);
  1206.         if(qs == null)
  1207.         {
  1208.             Quest q = QuestManager.getQuest(quest);
  1209.             if(q == null)
  1210.             {
  1211.                 _log.warn("Quest " + quest + " not found!");
  1212.                 return;
  1213.             }
  1214.             qs = q.newQuestState(this, Quest.CREATED);
  1215.         }
  1216.         if(qs == null || qs.isCompleted())
  1217.             return;
  1218.         qs.getQuest().notifyEvent(event, qs, npc);
  1219.         sendPacket(new QuestList(this));
  1220.     }
  1221.  
  1222.     /**
  1223.      * Проверка на переполнение инвентаря и перебор в весе для квестов и эвентов
  1224.      *
  1225.      * @return true если ве проверки прошли успешно
  1226.      */
  1227.     public boolean isQuestContinuationPossible(boolean msg)
  1228.     {
  1229.         if(getWeightPenalty() >= 3 || getInventoryLimit() * 0.9 < getInventory().getSize() || Config.QUEST_INVENTORY_MAXIMUM * 0.9 < getInventory().getQuestSize())
  1230.         {
  1231.             if(msg)
  1232.                 sendPacket(SystemMsg.PROGRESS_IN_A_QUEST_IS_POSSIBLE_ONLY_WHEN_YOUR_INVENTORYS_WEIGHT_AND_VOLUME_ARE_LESS_THAN_80_PERCENT_OF_CAPACITY);
  1233.             return false;
  1234.         }
  1235.         return true;
  1236.     }
  1237.  
  1238.     /**
  1239.      * Останавливаем и запоминаем все квестовые таймеры
  1240.      */
  1241.     public void stopQuestTimers()
  1242.     {
  1243.         for(QuestState qs : getAllQuestsStates())
  1244.             if(qs.isStarted())
  1245.                 qs.pauseQuestTimers();
  1246.             else
  1247.                 qs.stopQuestTimers();
  1248.     }
  1249.  
  1250.     /**
  1251.      * Восстанавливаем все квестовые таймеры
  1252.      */
  1253.     public void resumeQuestTimers()
  1254.     {
  1255.         for(QuestState qs : getAllQuestsStates())
  1256.             qs.resumeQuestTimers();
  1257.     }
  1258.  
  1259.     // ----------------- End of Quest Engine -------------------
  1260.  
  1261.     public Collection<ShortCut> getAllShortCuts()
  1262.     {
  1263.         return _shortCuts.getAllShortCuts();
  1264.     }
  1265.  
  1266.     public ShortCut getShortCut(int slot, int page)
  1267.     {
  1268.         return _shortCuts.getShortCut(slot, page);
  1269.     }
  1270.  
  1271.     public void registerShortCut(ShortCut shortcut)
  1272.     {
  1273.         _shortCuts.registerShortCut(shortcut);
  1274.     }
  1275.  
  1276.     public void deleteShortCut(int slot, int page)
  1277.     {
  1278.         _shortCuts.deleteShortCut(slot, page);
  1279.     }
  1280.  
  1281.     public void registerMacro(Macro macro)
  1282.     {
  1283.         _macroses.registerMacro(macro);
  1284.     }
  1285.  
  1286.     public void deleteMacro(int id)
  1287.     {
  1288.         _macroses.deleteMacro(id);
  1289.     }
  1290.  
  1291.     public MacroList getMacroses()
  1292.     {
  1293.         return _macroses;
  1294.     }
  1295.  
  1296.     public boolean isCastleLord(int castleId)
  1297.     {
  1298.         return _clan != null && isClanLeader() && _clan.getCastle() == castleId;
  1299.     }
  1300.  
  1301.     /**
  1302.      * Проверяет является ли этот персонаж владельцем крепости
  1303.      *
  1304.      * @param fortressId
  1305.      * @return true если владелец
  1306.      */
  1307.     public boolean isFortressLord(int fortressId)
  1308.     {
  1309.         return _clan != null && isClanLeader() && _clan.getHasFortress() == fortressId;
  1310.     }
  1311.  
  1312.     public int getPkKills()
  1313.     {
  1314.         return _pkKills;
  1315.     }
  1316.  
  1317.     public void setPkKills(final int pkKills)
  1318.     {
  1319.         _pkKills = pkKills;
  1320.     }
  1321.  
  1322.     public long getCreateTime()
  1323.     {
  1324.         return _createTime;
  1325.     }
  1326.  
  1327.     public void setCreateTime(final long createTime)
  1328.     {
  1329.         _createTime = createTime;
  1330.     }
  1331.  
  1332.     public int getDeleteTimer()
  1333.     {
  1334.         return _deleteTimer;
  1335.     }
  1336.  
  1337.     public void setDeleteTimer(final int deleteTimer)
  1338.     {
  1339.         _deleteTimer = deleteTimer;
  1340.     }
  1341.  
  1342.     public int getCurrentLoad()
  1343.     {
  1344.         return getInventory().getTotalWeight();
  1345.     }
  1346.  
  1347.     public long getLastAccess()
  1348.     {
  1349.         return _lastAccess;
  1350.     }
  1351.  
  1352.     public void setLastAccess(long value)
  1353.     {
  1354.         _lastAccess = value;
  1355.     }
  1356.  
  1357.     public int getRecomHave()
  1358.     {
  1359.         return _recomHave;
  1360.     }
  1361.  
  1362.     public void setRecomHave(int value)
  1363.     {
  1364.         if(value > 255)
  1365.             _recomHave = 255;
  1366.         else if(value < 0)
  1367.             _recomHave = 0;
  1368.         else
  1369.             _recomHave = value;
  1370.     }
  1371.  
  1372.     public int getRecomBonusTime()
  1373.     {
  1374.         if(_recomBonusTask != null)
  1375.             return (int) Math.max(0, _recomBonusTask.getDelay(TimeUnit.SECONDS));
  1376.         return _recomBonusTime;
  1377.     }
  1378.  
  1379.     public void setRecomBonusTime(int val)
  1380.     {
  1381.         _recomBonusTime = val;
  1382.     }
  1383.  
  1384.     public int getRecomLeft()
  1385.     {
  1386.         return _recomLeft;
  1387.     }
  1388.  
  1389.     public void setRecomLeft(final int value)
  1390.     {
  1391.         _recomLeft = value;
  1392.     }
  1393.  
  1394.     public boolean isHourglassEffected()
  1395.     {
  1396.         return _isHourglassEffected;
  1397.     }
  1398.  
  1399.     public void setHourlassEffected(boolean val)
  1400.     {
  1401.         _isHourglassEffected = val;
  1402.     }
  1403.  
  1404.     public void startHourglassEffect()
  1405.     {
  1406.         setHourlassEffected(true);
  1407.         stopRecomBonusTask(true);
  1408.         sendVoteSystemInfo();
  1409.     }
  1410.  
  1411.     public void stopHourglassEffect()
  1412.     {
  1413.         setHourlassEffected(false);
  1414.         startRecomBonusTask();
  1415.         sendVoteSystemInfo();
  1416.     }
  1417.  
  1418.     public int addRecomLeft()
  1419.     {
  1420.         int recoms;
  1421.         if(getRecomLeftToday() < 20)
  1422.             recoms = 10;
  1423.         else
  1424.             recoms = 1;
  1425.         setRecomLeft(getRecomLeft() + recoms);
  1426.         setRecomLeftToday(getRecomLeftToday() + recoms);
  1427.         sendUserInfo(true);
  1428.         return recoms;
  1429.     }
  1430.  
  1431.     public int getRecomLeftToday()
  1432.     {
  1433.         return _recomLeftToday;
  1434.     }
  1435.  
  1436.     public void setRecomLeftToday(final int value)
  1437.     {
  1438.         _recomLeftToday = value;
  1439.         setVar("recLeftToday", String.valueOf(_recomLeftToday), -1);
  1440.     }
  1441.  
  1442.     public void giveRecom(final Player target)
  1443.     {
  1444.         int targetRecom = target.getRecomHave();
  1445.         if(targetRecom < 255)
  1446.             target.addRecomHave(1);
  1447.         if(getRecomLeft() > 0)
  1448.             setRecomLeft(getRecomLeft() - 1);
  1449.  
  1450.         sendUserInfo(true);
  1451.     }
  1452.  
  1453.     public void addRecomHave(final int val)
  1454.     {
  1455.         setRecomHave(getRecomHave() + val);
  1456.         broadcastUserInfo(true);
  1457.         sendVoteSystemInfo();
  1458.     }
  1459.  
  1460.     public int getRecomBonus()
  1461.     {
  1462.         if(getRecomBonusTime() > 0 || isHourglassEffected())
  1463.             return RecomBonus.getRecoBonus(this);
  1464.         return 0;
  1465.     }
  1466.  
  1467.     public double getRecomBonusMul()
  1468.     {
  1469.         if(getRecomBonusTime() > 0 || isHourglassEffected())
  1470.             return RecomBonus.getRecoMultiplier(this);
  1471.         return 1;
  1472.     }
  1473.  
  1474.     public void sendVoteSystemInfo()
  1475.     {
  1476.         sendPacket(new ExVoteSystemInfo(this));
  1477.     }
  1478.  
  1479.     public boolean isRecomTimerActive()
  1480.     {
  1481.         return _isRecomTimerActive;
  1482.     }
  1483.  
  1484.     public void setRecomTimerActive(boolean val)
  1485.     {
  1486.         if(_isRecomTimerActive == val)
  1487.             return;
  1488.  
  1489.         _isRecomTimerActive = val;
  1490.  
  1491.         if(val)
  1492.             startRecomBonusTask();
  1493.         else
  1494.             stopRecomBonusTask(true);
  1495.  
  1496.         sendVoteSystemInfo();
  1497.     }
  1498.  
  1499.     private ScheduledFuture<?> _recomBonusTask;
  1500.  
  1501.     public void startRecomBonusTask()
  1502.     {
  1503.         if(_recomBonusTask == null && getRecomBonusTime() > 0 && isRecomTimerActive() && !isHourglassEffected())
  1504.             _recomBonusTask = ThreadPoolManager.getInstance().schedule(new RecomBonusTask(this), getRecomBonusTime() * 1000);
  1505.     }
  1506.  
  1507.     public void stopRecomBonusTask(boolean saveTime)
  1508.     {
  1509.         if(_recomBonusTask != null)
  1510.         {
  1511.             if(saveTime)
  1512.                 setRecomBonusTime((int) Math.max(0, _recomBonusTask.getDelay(TimeUnit.SECONDS)));
  1513.             _recomBonusTask.cancel(false);
  1514.             _recomBonusTask = null;
  1515.         }
  1516.     }
  1517.  
  1518.     @Override
  1519.     public int getKarma()
  1520.     {
  1521.         return _karma;
  1522.     }
  1523.  
  1524.     public void setKarma(int karma)
  1525.     {
  1526.         if(karma < 0)
  1527.             karma = 0;
  1528.  
  1529.         if(_karma == karma)
  1530.             return;
  1531.  
  1532.         _karma = karma;
  1533.  
  1534.         sendChanges();
  1535.  
  1536.         if(getPet() != null)
  1537.             getPet().broadcastCharInfo();
  1538.     }
  1539.  
  1540.     @Override
  1541.     public int getMaxLoad()
  1542.     {
  1543.         // Weight Limit = (CON Modifier*69000)*Skills
  1544.         // Source http://l2r.bravehost.com/weightlimit.html (May 2007)
  1545.         // Fitted exponential curve to the data
  1546.         int con = getCON();
  1547.         if(con < 1)
  1548.             return (int) (31000 * Config.MAXLOAD_MODIFIER);
  1549.         else if(con > 59)
  1550.             return (int) (176000 * Config.MAXLOAD_MODIFIER);
  1551.         else
  1552.             return (int) calcStat(Stats.MAX_LOAD, Math.pow(1.029993928, con) * 30495.627366 * Config.MAXLOAD_MODIFIER, this, null);
  1553.     }
  1554.  
  1555.     private Future<?> _updateEffectIconsTask;
  1556.  
  1557.     private class UpdateEffectIcons extends RunnableImpl
  1558.     {
  1559.         @Override
  1560.         public void runImpl() throws Exception
  1561.         {
  1562.             updateEffectIconsImpl();
  1563.             _updateEffectIconsTask = null;
  1564.         }
  1565.     }
  1566.  
  1567.     @Override
  1568.     public void updateEffectIcons()
  1569.     {
  1570.         if(entering || isLogoutStarted())
  1571.             return;
  1572.  
  1573.         if(Config.USER_INFO_INTERVAL == 0)
  1574.         {
  1575.             if(_updateEffectIconsTask != null)
  1576.             {
  1577.                 _updateEffectIconsTask.cancel(false);
  1578.                 _updateEffectIconsTask = null;
  1579.             }
  1580.             updateEffectIconsImpl();
  1581.             return;
  1582.         }
  1583.  
  1584.         if(_updateEffectIconsTask != null)
  1585.             return;
  1586.  
  1587.         _updateEffectIconsTask = ThreadPoolManager.getInstance().schedule(new UpdateEffectIcons(), Config.USER_INFO_INTERVAL);
  1588.     }
  1589.  
  1590.     private void updateEffectIconsImpl()
  1591.     {
  1592.         Effect[] effects = getEffectList().getAllFirstEffects();
  1593.         Arrays.sort(effects, EffectsComparator.getInstance());
  1594.  
  1595.         PartySpelled ps = new PartySpelled(this, false);
  1596.         AbnormalStatusUpdate mi = new AbnormalStatusUpdate();
  1597.  
  1598.         for(Effect effect : effects)
  1599.             if(effect.isInUse())
  1600.             {
  1601.                 if(effect.getStackType().equals(EffectTemplate.HP_RECOVER_CAST))
  1602.                     sendPacket(new ShortBuffStatusUpdate(effect));
  1603.                 else
  1604.                     effect.addIcon(mi);
  1605.                 if(_party != null)
  1606.                     effect.addPartySpelledIcon(ps);
  1607.             }
  1608.  
  1609.         sendPacket(mi);
  1610.         if(_party != null)
  1611.             _party.broadCast(ps);
  1612.  
  1613.         if(isInOlympiadMode() && isOlympiadCompStart())
  1614.         {
  1615.             OlympiadGame olymp_game = _olympiadGame;
  1616.             if(olymp_game != null)
  1617.             {
  1618.                 ExOlympiadSpelledInfo olympiadSpelledInfo = new ExOlympiadSpelledInfo();
  1619.  
  1620.                 for(Effect effect : effects)
  1621.                     if(effect != null && effect.isInUse())
  1622.                         effect.addOlympiadSpelledIcon(this, olympiadSpelledInfo);
  1623.  
  1624.                 if(olymp_game.getType() == CompType.CLASSED || olymp_game.getType() == CompType.NON_CLASSED)
  1625.                     for(Player member : olymp_game.getTeamMembers(this))
  1626.                         member.sendPacket(olympiadSpelledInfo);
  1627.  
  1628.                 for(Player member : olymp_game.getSpectators())
  1629.                     member.sendPacket(olympiadSpelledInfo);
  1630.             }
  1631.         }
  1632.     }
  1633.  
  1634.     public int getWeightPenalty()
  1635.     {
  1636.         return getSkillLevel(4270, 0);
  1637.     }
  1638.  
  1639.     public void refreshOverloaded()
  1640.     {
  1641.         if(isLogoutStarted() || getMaxLoad() <= 0)
  1642.             return;
  1643.  
  1644.         setOverloaded(getCurrentLoad() > getMaxLoad());
  1645.         double weightproc = 100. * (getCurrentLoad() - calcStat(Stats.MAX_NO_PENALTY_LOAD, 0, this, null)) / getMaxLoad();
  1646.         int newWeightPenalty;
  1647.  
  1648.         if(weightproc < 50)
  1649.             newWeightPenalty = 0;
  1650.         else if(weightproc < 66.6)
  1651.             newWeightPenalty = 1;
  1652.         else if(weightproc < 80)
  1653.             newWeightPenalty = 2;
  1654.         else if(weightproc < 100)
  1655.             newWeightPenalty = 3;
  1656.         else
  1657.             newWeightPenalty = 4;
  1658.  
  1659.         int current = getWeightPenalty();
  1660.         if(current == newWeightPenalty)
  1661.             return;
  1662.  
  1663.         if(newWeightPenalty > 0)
  1664.             super.addSkill(SkillTable.getInstance().getInfo(4270, newWeightPenalty));
  1665.         else
  1666.             super.removeSkill(getKnownSkill(4270));
  1667.  
  1668.         sendPacket(new SkillList(this));
  1669.         sendEtcStatusUpdate();
  1670.         updateStats();
  1671.     }
  1672.  
  1673.     public int getArmorsExpertisePenalty()
  1674.     {
  1675.         return getSkillLevel(6213, 0);
  1676.     }
  1677.  
  1678.     public int getWeaponsExpertisePenalty()
  1679.     {
  1680.         return getSkillLevel(6209, 0);
  1681.     }
  1682.  
  1683.     public int getExpertisePenalty(ItemInstance item)
  1684.     {
  1685.         if(item.getTemplate().getType2() == ItemTemplate.TYPE2_WEAPON)
  1686.             return getWeaponsExpertisePenalty();
  1687.         else if(item.getTemplate().getType2() == ItemTemplate.TYPE2_SHIELD_ARMOR || item.getTemplate().getType2() == ItemTemplate.TYPE2_ACCESSORY)
  1688.             return getArmorsExpertisePenalty();
  1689.         return 0;
  1690.     }
  1691.  
  1692.     public void refreshExpertisePenalty()
  1693.     {
  1694.         if(isLogoutStarted())
  1695.             return;
  1696.  
  1697.         // Calculate the current higher Expertise of the L2Player
  1698.         int level = (int) calcStat(Stats.GRADE_EXPERTISE_LEVEL, getLevel(), null, null);
  1699.         int i;
  1700.         for(i = 0; i < EXPERTISE_LEVELS.length; i++)
  1701.             if(level < EXPERTISE_LEVELS[i + 1])
  1702.                 break;
  1703.  
  1704.         boolean skillUpdate = false; // Для того, чтобы лишний раз не посылать пакеты
  1705.         // Add the Expertise skill corresponding to its Expertise level
  1706.         if(expertiseIndex != i)
  1707.         {
  1708.             expertiseIndex = i;
  1709.             if(expertiseIndex > 0)
  1710.             {
  1711.                 addSkill(SkillTable.getInstance().getInfo(239, expertiseIndex), false);
  1712.                 skillUpdate = true;
  1713.             }
  1714.         }
  1715.  
  1716.         int newWeaponPenalty = 0;
  1717.         int newArmorPenalty = 0;
  1718.         ItemInstance[] items = getInventory().getPaperdollItems();
  1719.         for(ItemInstance item : items)
  1720.             if(item != null)
  1721.             {
  1722.                 int crystaltype = item.getTemplate().getCrystalType().ordinal();
  1723.                 if(item.getTemplate().getType2() == ItemTemplate.TYPE2_WEAPON)
  1724.                 {
  1725.                     if(crystaltype > newWeaponPenalty)
  1726.                         newWeaponPenalty = crystaltype;
  1727.                 }
  1728.                 else if(item.getTemplate().getType2() == ItemTemplate.TYPE2_SHIELD_ARMOR || item.getTemplate().getType2() == ItemTemplate.TYPE2_ACCESSORY)
  1729.                     if(crystaltype > newArmorPenalty)
  1730.                         newArmorPenalty = crystaltype;
  1731.             }
  1732.  
  1733.         newWeaponPenalty = newWeaponPenalty - expertiseIndex;
  1734.         if(newWeaponPenalty <= 0)
  1735.             newWeaponPenalty = 0;
  1736.         else if(newWeaponPenalty >= 4)
  1737.             newWeaponPenalty = 4;
  1738.  
  1739.         newArmorPenalty = newArmorPenalty - expertiseIndex;
  1740.         if(newArmorPenalty <= 0)
  1741.             newArmorPenalty = 0;
  1742.         else if(newArmorPenalty >= 4)
  1743.             newArmorPenalty = 4;
  1744.  
  1745.         int weaponExpertise = getWeaponsExpertisePenalty();
  1746.         int armorExpertise = getArmorsExpertisePenalty();
  1747.  
  1748.         if(weaponExpertise != newWeaponPenalty)
  1749.         {
  1750.             weaponExpertise = newWeaponPenalty;
  1751.             if(newWeaponPenalty > 0)
  1752.                 super.addSkill(SkillTable.getInstance().getInfo(6209, weaponExpertise));
  1753.             else
  1754.                 super.removeSkill(getKnownSkill(6209));
  1755.             skillUpdate = true;
  1756.         }
  1757.         if(armorExpertise != newArmorPenalty)
  1758.         {
  1759.             armorExpertise = newArmorPenalty;
  1760.             if(newArmorPenalty > 0)
  1761.                 super.addSkill(SkillTable.getInstance().getInfo(6213, armorExpertise));
  1762.             else
  1763.                 super.removeSkill(getKnownSkill(6213));
  1764.             skillUpdate = true;
  1765.         }
  1766.  
  1767.         if(skillUpdate)
  1768.         {
  1769.             getInventory().validateItemsSkills();
  1770.  
  1771.             sendPacket(new SkillList(this));
  1772.             sendEtcStatusUpdate();
  1773.             updateStats();
  1774.         }
  1775.     }
  1776.  
  1777.     public int getPvpKills()
  1778.     {
  1779.         return _pvpKills;
  1780.        
  1781.     }
  1782.  
  1783.     public void setPvpKills(int pvpKills)
  1784.     {
  1785.         _pvpKills = pvpKills;
  1786.     }
  1787.  
  1788.     public ClassId getClassId()
  1789.     {
  1790.         return getTemplate().classId;
  1791.     }
  1792.  
  1793.     public void addClanPointsOnProfession(final int id)
  1794.     {
  1795.         if(getLvlJoinedAcademy() != 0 && _clan != null && _clan.getLevel() >= 5 && ClassId.VALUES[id].getLevel() == 2)
  1796.             _clan.incReputation(100, true, "Academy");
  1797.         else if(getLvlJoinedAcademy() != 0 && _clan != null && _clan.getLevel() >= 5 && ClassId.VALUES[id].getLevel() == 3)
  1798.         {
  1799.             int earnedPoints;
  1800.             if(getLvlJoinedAcademy() <= 16)
  1801.                 earnedPoints = Config.CLAN_REPUTACION_POINTS_ACADEMIC_MAX;
  1802.             else if(getLvlJoinedAcademy() >= 39)
  1803.                 earnedPoints = Config.CLAN_REPUTACION_POINTS_ACADEMIC_MIN;
  1804.             else
  1805.                 earnedPoints = Config.CLAN_REPUTACION_POINTS_ACADEMIC_MAX - (getLvlJoinedAcademy() - 16) * 20;
  1806.  
  1807.             _clan.removeClanMember(getObjectId());
  1808.  
  1809.             SystemMessage2 sm = new SystemMessage2(SystemMsg.CLAN_ACADEMY_MEMBER_S1_HAS_SUCCESSFULLY_COMPLETED_THE_2ND_CLASS_TRANSFER_AND_OBTAINED_S2_CLAN_REPUTATION_POINTS);
  1810.             sm.addString(getName());
  1811.             sm.addNumber(_clan.incReputation(earnedPoints, true, "Academy"));
  1812.             _clan.broadcastToOnlineMembers(sm);
  1813.             _clan.broadcastToOtherOnlineMembers(new PledgeShowMemberListDelete(getName()), this);
  1814.  
  1815.             setClan(null);
  1816.             setTitle("");
  1817.             sendPacket(SystemMsg.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);
  1818.             setLeaveClanTime(0);
  1819.  
  1820.             broadcastCharInfo();
  1821.  
  1822.             sendPacket(PledgeShowMemberListDeleteAll.STATIC);
  1823.            
  1824.             ItemFunctions.addItem(this, Config.ACADEMIC_REVARD_ID, Config.ACADEMIC_REVARD_COUNT, true);
  1825.         }
  1826.     }
  1827.  
  1828.     /**
  1829.      * Set the template of the L2Player.
  1830.      *
  1831.      * @param id The Identifier of the L2PlayerTemplate to set to the L2Player
  1832.      */
  1833.     public synchronized void setClassId(final int id, boolean noban, boolean fromQuest)
  1834.     {
  1835.         if(!noban && !(ClassId.VALUES[id].equalsOrChildOf(ClassId.VALUES[getActiveClassId()]) || getPlayerAccess().CanChangeClass || Config.EVERYBODY_HAS_ADMIN_RIGHTS))
  1836.         {
  1837.             Thread.dumpStack();
  1838.             return;
  1839.         }
  1840.  
  1841.         //Если новый ID не принадлежит имеющимся классам значит это новая профа
  1842.         if(!getSubClasses().containsKey(id))
  1843.         {
  1844.             final SubClass cclass = getActiveClass();
  1845.             getSubClasses().remove(getActiveClassId());
  1846.             changeClassInDb(cclass.getClassId(), id);
  1847.             if(cclass.isBase())
  1848.             {
  1849.                 setBaseClass(id);
  1850.                 addClanPointsOnProfession(id);
  1851.                 ItemInstance coupons = null;
  1852.                 if(ClassId.VALUES[id].getLevel() == 2)
  1853.                 {
  1854.                     if(fromQuest && Config.ALT_ALLOW_SHADOW_WEAPONS)
  1855.                         coupons = ItemFunctions.createItem(8869);
  1856.                     unsetVar("newbieweapon");
  1857.                     unsetVar("p1q2");
  1858.                     unsetVar("p1q3");
  1859.                     unsetVar("p1q4");
  1860.                     unsetVar("prof1");
  1861.                     unsetVar("ng1");
  1862.                     unsetVar("ng2");
  1863.                     unsetVar("ng3");
  1864.                     unsetVar("ng4");
  1865.                 }
  1866.                 else if(ClassId.VALUES[id].getLevel() == 3)
  1867.                 {
  1868.                     if(fromQuest && Config.ALT_ALLOW_SHADOW_WEAPONS)
  1869.                         coupons = ItemFunctions.createItem(8870);
  1870.                     unsetVar("newbiearmor");
  1871.                     unsetVar("dd1"); // удаляем отметки о выдаче дименшен даймондов
  1872.                     unsetVar("dd2");
  1873.                     unsetVar("dd3");
  1874.                     unsetVar("prof2.1");
  1875.                     unsetVar("prof2.2");
  1876.                     unsetVar("prof2.3");
  1877.                 }
  1878.  
  1879.                 if(coupons != null)
  1880.                 {
  1881.                     coupons.setCount(15);
  1882.                     sendPacket(SystemMessage2.obtainItems(coupons));
  1883.                     getInventory().addItem(coupons);
  1884.                 }
  1885.             }
  1886.  
  1887.             // Выдача Holy Pomander
  1888.             switch(ClassId.VALUES[id])
  1889.             {
  1890.                 case cardinal:
  1891.                     ItemFunctions.addItem(this, 15307, 1, true);
  1892.                     break;
  1893.                 case evaSaint:
  1894.                     ItemFunctions.addItem(this, 15308, 1, true);
  1895.                     break;
  1896.                 case shillienSaint:
  1897.                     ItemFunctions.addItem(this, 15309, 4, true);
  1898.                     break;
  1899.             }
  1900.  
  1901.             cclass.setClassId(id);
  1902.             getSubClasses().put(id, cclass);
  1903.             rewardSkills(true);
  1904.             storeCharSubClasses();
  1905.  
  1906.             if(fromQuest)
  1907.             {
  1908.                 // Социалка при получении профы
  1909.                 broadcastPacket(new MagicSkillUse(this, this, 5103, 1, 1000, 0));
  1910.                 sendPacket(new PlaySound("ItemSound.quest_fanfare_2"));
  1911.             }
  1912.             broadcastCharInfo();
  1913.         }
  1914.  
  1915.  
  1916.         PlayerTemplate t = CharTemplateTable.getInstance().getTemplate(id, getSex() == 1);
  1917.         if(t == null)
  1918.         {
  1919.             _log.error("Missing template for classId: " + id);
  1920.             // do not throw error - only print error
  1921.             return;
  1922.         }
  1923.  
  1924.         // чтобы не терялась фракция, ибо она живет в CharTeplate
  1925.         t.setFaction(getFaction());
  1926.  
  1927.         // Set the template of the L2Player
  1928.         _template = t;
  1929.  
  1930.         // Update class icon in party and clan
  1931.         if(isInParty())
  1932.             getParty().broadCast(new PartySmallWindowUpdate(this));
  1933.         if(getClan() != null)
  1934.             getClan().broadcastToOnlineMembers(new PledgeShowMemberListUpdate(this));
  1935.         if(_matchingRoom != null)
  1936.             _matchingRoom.broadcastPlayerUpdate(this);
  1937.     }
  1938.  
  1939.     public long getExp()
  1940.     {
  1941.         return _activeClass == null ? 0 : _activeClass.getExp();
  1942.     }
  1943.  
  1944.     public long getMaxExp()
  1945.     {
  1946.         return _activeClass == null ? Experience.LEVEL[Experience.getMaxLevel() + 1] : _activeClass.getMaxExp();
  1947.     }
  1948.  
  1949.     public void setEnchantScroll(final ItemInstance scroll)
  1950.     {
  1951.         _enchantScroll = scroll;
  1952.     }
  1953.  
  1954.     public ItemInstance getEnchantScroll()
  1955.     {
  1956.         return _enchantScroll;
  1957.     }
  1958.  
  1959.     public void setFistsWeaponItem(final WeaponTemplate weaponItem)
  1960.     {
  1961.         _fistsWeaponItem = weaponItem;
  1962.     }
  1963.  
  1964.     public WeaponTemplate getFistsWeaponItem()
  1965.     {
  1966.         return _fistsWeaponItem;
  1967.     }
  1968.  
  1969.     public WeaponTemplate findFistsWeaponItem(final int classId)
  1970.     {
  1971.         //human fighter fists
  1972.         if(classId >= 0x00 && classId <= 0x09)
  1973.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(246);
  1974.  
  1975.         //human mage fists
  1976.         if(classId >= 0x0a && classId <= 0x11)
  1977.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(251);
  1978.  
  1979.         //elven fighter fists
  1980.         if(classId >= 0x12 && classId <= 0x18)
  1981.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(244);
  1982.  
  1983.         //elven mage fists
  1984.         if(classId >= 0x19 && classId <= 0x1e)
  1985.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(249);
  1986.  
  1987.         //dark elven fighter fists
  1988.         if(classId >= 0x1f && classId <= 0x25)
  1989.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(245);
  1990.  
  1991.         //dark elven mage fists
  1992.         if(classId >= 0x26 && classId <= 0x2b)
  1993.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(250);
  1994.  
  1995.         //orc fighter fists
  1996.         if(classId >= 0x2c && classId <= 0x30)
  1997.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(248);
  1998.  
  1999.         //orc mage fists
  2000.         if(classId >= 0x31 && classId <= 0x34)
  2001.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(252);
  2002.  
  2003.         //dwarven fists
  2004.         if(classId >= 0x35 && classId <= 0x39)
  2005.             return (WeaponTemplate) ItemHolder.getInstance().getTemplate(247);
  2006.  
  2007.         return null;
  2008.     }
  2009.  
  2010.     public void addExpAndCheckBonus(MonsterInstance mob, final double noRateExp, double noRateSp, double partyVitalityMod)
  2011.     {
  2012.         if(_activeClass == null)
  2013.             return;
  2014.  
  2015.         // Начисление душ камаэлям
  2016.         double neededExp = calcStat(Stats.SOULS_CONSUME_EXP, 0, mob, null);
  2017.         if(neededExp > 0 && noRateExp > neededExp)
  2018.         {
  2019.             mob.broadcastPacket(new SpawnEmitter(mob, this));
  2020.             ThreadPoolManager.getInstance().schedule(new GameObjectTasks.SoulConsumeTask(this), 1000);
  2021.         }
  2022.  
  2023.         double vitalityBonus = 0.;
  2024.         int npcLevel = mob.getLevel();
  2025.         if(Config.ALT_VITALITY_ENABLED)
  2026.         {
  2027.             boolean blessActive = getNevitSystem().isBlessingActive();
  2028.             vitalityBonus = mob.isRaid() ? 0. : getVitalityLevel(blessActive) / 2.;
  2029.             vitalityBonus *= Config.ALT_VITALITY_RATE;
  2030.             if(noRateExp > 0)
  2031.             {
  2032.                 if(!mob.isRaid())
  2033.                 {
  2034.                     // TODO: Разобратся, нельзя предметы использовать, или предметы не будут давать эффекта?
  2035.                     // (Все предметы для восполнения или поддержания энергии не действуют во время действия Нисхождения Невитта)
  2036.                     if(!blessActive && !(getVarB("NoExp") && getExp() == Experience.LEVEL[getLevel() + 1] - 1))
  2037.                     {
  2038.                         double points = ((noRateExp / (npcLevel * npcLevel)) * 100) / 9;
  2039.                         points *= Config.ALT_VITALITY_CONSUME_RATE;
  2040.                        
  2041.                         if(getEffectList().getEffectByType(EffectType.Vitality) != null)
  2042.                         {
  2043.                             points *= -1;
  2044.                         }
  2045.                         setVitality(getVitality() - points * partyVitalityMod);
  2046.                     }
  2047.                 }
  2048.                 else
  2049.                     setVitality(getVitality() + Config.ALT_VITALITY_RAID_BONUS);
  2050.             }
  2051.         }
  2052.  
  2053.         //При первом вызове, активируем таймеры бонусов.
  2054.         if(!isInPeaceZone())
  2055.         {
  2056.             setRecomTimerActive(true);
  2057.             getNevitSystem().startAdventTask();
  2058.             if((getLevel() - npcLevel) <= 9)
  2059.             {
  2060.                 if(Config.ALT_NEVIT_FORMULA)
  2061.                 {
  2062.                     int nevitPoints = (Experience.getMaxLevel() - getLevel()) * 1;
  2063.                     nevitPoints *= noRateExp / 3000;
  2064.                     if (Rnd.chance(40))
  2065.                     {
  2066.                         if (getLevel() > 40)
  2067.                             nevitPoints *= 2;
  2068.                         else
  2069.                             nevitPoints *= 4;
  2070.                     }
  2071.                     getNevitSystem().addPoints(nevitPoints);
  2072.                     //_log.error("Points: " + nevitPoints);
  2073.                 }
  2074.                 else
  2075.                 {
  2076.                     int nevitPoints = (int) Math.round(((noRateExp / (npcLevel * npcLevel)) * 100) / 20); //TODO: Формула от балды.
  2077.                     getNevitSystem().addPoints(nevitPoints);
  2078.                 }
  2079.             }
  2080.         }
  2081.  
  2082.         long normalExp = (long)  (noRateExp * ((Config.RATE_XP * getRateExp() + vitalityBonus) * getRecomBonusMul()));
  2083.         long normalSp = (long)  (noRateSp * (Config.RATE_SP * getRateSp() + vitalityBonus));
  2084.  
  2085.         long expWithoutBonus = (long)  (noRateExp * Config.RATE_XP * getRateExp());
  2086.         long spWithoutBonus = (long)  (noRateSp * Config.RATE_SP * getRateSp());
  2087.  
  2088.         addExpAndSp(normalExp, normalSp, normalExp - expWithoutBonus, normalSp - spWithoutBonus, false, true);
  2089.     }
  2090.  
  2091.     @Override
  2092.     public void addExpAndSp(long exp, long sp)
  2093.     {
  2094.         addExpAndSp(exp, sp, 0, 0, false, false);
  2095.     }
  2096.  
  2097.     public void addExpAndSp(long addToExp, long addToSp, long bonusAddExp, long bonusAddSp, boolean applyRate, boolean applyToPet)
  2098.     {
  2099.         if(_activeClass == null)
  2100.             return;
  2101.  
  2102.         if(applyRate)
  2103.         {
  2104.             addToExp *= Config.RATE_XP * getRateExp();
  2105.             addToSp *= Config.RATE_SP * getRateSp();
  2106.         }
  2107.  
  2108.         Summon pet = getPet();
  2109.         if(addToExp > 0)
  2110.         {
  2111.             if(applyToPet)
  2112.             {
  2113.                 if(pet != null && !pet.isDead() && !PetDataTable.isVitaminPet(pet.getNpcId()))
  2114.                     // Sin Eater забирает всю экспу у персонажа
  2115.                     if(pet.getNpcId() == PetDataTable.SIN_EATER_ID)
  2116.                     {
  2117.                         pet.addExpAndSp(addToExp, 0);
  2118.                         addToExp = 0;
  2119.                     }
  2120.                     else if(pet.isPet() && pet.getExpPenalty() > 0f)
  2121.                         if(pet.getLevel() > getLevel() - 20 && pet.getLevel() < getLevel() + 5)
  2122.                         {
  2123.                             pet.addExpAndSp((long) (addToExp * pet.getExpPenalty()), 0);
  2124.                             addToExp *= 1. - pet.getExpPenalty();
  2125.                         }
  2126.                         else
  2127.                         {
  2128.                             pet.addExpAndSp((long) (addToExp * pet.getExpPenalty() / 5.), 0);
  2129.                             addToExp *= 1. - pet.getExpPenalty() / 5.;
  2130.                         }
  2131.                     else if(pet.isSummon())
  2132.                         addToExp *= 1. - pet.getExpPenalty();
  2133.             }
  2134.  
  2135.             // Remove Karma when the player kills L2MonsterInstance
  2136.             //TODO [G1ta0] двинуть в метод начисления наград при убйистве моба
  2137.             /*if(!isCursedWeaponEquipped() && addToSp > 0 && _karma > 0)
  2138.                 _karma -= addToSp / (Config.KARMA_SP_DIVIDER * Config.RATE_SP);
  2139.  
  2140.             if(_karma < 0)
  2141.                 _karma = 0;*/
  2142.  
  2143.             long max_xp = getVarB("NoExp") ? Experience.LEVEL[getLevel() + 1] - 1 : getMaxExp();
  2144.             addToExp = Math.min(addToExp, max_xp - getExp());
  2145.         }
  2146.  
  2147.         int oldLvl = _activeClass.getLevel();
  2148.  
  2149.         _activeClass.addExp(addToExp);
  2150.         _activeClass.addSp(addToSp);
  2151.         if(getNevitSystem().isBlessingActive())
  2152.         {
  2153.             addVitality(Config.ALT_VITALITY_NEVIT_POINT);
  2154.         }
  2155.  
  2156.         if(addToExp > 0 && addToSp > 0 && (bonusAddExp > 0 || bonusAddSp > 0))
  2157.             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));
  2158.         else if(addToSp > 0 && addToExp == 0)
  2159.             sendPacket(new SystemMessage2(SystemMsg.YOU_HAVE_ACQUIRED_S1_SP).addNumber(addToSp));
  2160.         else if(addToSp > 0 && addToExp > 0)
  2161.             sendPacket(new SystemMessage2(SystemMsg.YOU_HAVE_EARNED_S1_EXPERIENCE_AND_S2_SP).addNumber(addToExp).addNumber(addToSp));
  2162.         else if(addToSp == 0 && addToExp > 0)
  2163.             sendPacket(new SystemMessage2(SystemMsg.YOU_HAVE_EARNED_S1_EXPERIENCE).addNumber(addToExp));
  2164.  
  2165.         int level = _activeClass.getLevel();
  2166.         if(level != oldLvl)
  2167.         {
  2168.             int levels = level - oldLvl;
  2169.             if(levels > 0)
  2170.                 getNevitSystem().addPoints(550); //1950
  2171.             levelSet(levels);
  2172.         }
  2173.  
  2174.         if(pet != null && pet.isPet() && PetDataTable.isVitaminPet(pet.getNpcId()))
  2175.         {
  2176.             PetInstance _pet = (PetInstance) pet;
  2177.             _pet.setLevel(getLevel());
  2178.             _pet.setExp(_pet.getExpForNextLevel());
  2179.             _pet.broadcastStatusUpdate();
  2180.         }
  2181.  
  2182.         updateStats();
  2183.     }
  2184.  
  2185.  
  2186.     /**
  2187.      * Give Expertise skill of this level.<BR><BR>
  2188.      * <B><U> Actions</U> :</B><BR><BR>
  2189.      * <li>Get the Level of the L2Player </li>
  2190.      * <li>Add the Expertise skill corresponding to its Expertise level</li>
  2191.      * <li>Update the overloaded status of the L2Player</li><BR><BR>
  2192.      * <p/>
  2193.      * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T give other free skills (SP needed = 0)</B></FONT><BR><BR>
  2194.      * @param send
  2195.      */
  2196.     public void rewardSkills(boolean send)
  2197.     {
  2198.         boolean update = false;
  2199.         if(Config.AUTO_LEARN_SKILLS)
  2200.         {
  2201.             int unLearnable = 0;
  2202.             Collection<SkillLearn> skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
  2203.             while(skills.size() > unLearnable)
  2204.             {
  2205.                 unLearnable = 0;
  2206.                 for(SkillLearn s : skills)
  2207.                 {
  2208.                     Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
  2209.                     if(sk == null || !sk.getCanLearn(getClassId()) || (!Config.AUTO_LEARN_FORGOTTEN_SKILLS && s.isClicked()))
  2210.                     {
  2211.                         unLearnable++;
  2212.                         continue;
  2213.                     }
  2214.                     addSkill(sk, true);
  2215.                 }
  2216.                 skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
  2217.             }
  2218.             update = true;
  2219.         }
  2220.         else
  2221.             // Скиллы дающиеся бесплатно не требуют изучения
  2222.             for(SkillLearn skill : SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL))
  2223.                 if(skill.getCost() == 0 && skill.getItemId() == 0)
  2224.                 {
  2225.                     Skill sk = SkillTable.getInstance().getInfo(skill.getId(), skill.getLevel());
  2226.                     addSkill(sk, true);
  2227.                     if(getAllShortCuts().size() > 0 && sk.getLevel() > 1)
  2228.                         for(ShortCut sc : getAllShortCuts())
  2229.                             if(sc.getId() == sk.getId() && sc.getType() == ShortCut.TYPE_SKILL)
  2230.                             {
  2231.                                 ShortCut newsc = new ShortCut(sc.getSlot(), sc.getPage(), sc.getType(), sc.getId(), sk.getLevel(), 1);
  2232.                                 sendPacket(new ShortCutRegister(this, newsc));
  2233.                                 registerShortCut(newsc);
  2234.                             }
  2235.                     update = true;
  2236.                 }
  2237.  
  2238.         if(send && update)
  2239.             sendPacket(new SkillList(this));
  2240.  
  2241.         updateStats();
  2242.     }
  2243.  
  2244.     public Race getRace()
  2245.     {
  2246.         return getBaseTemplate().race;
  2247.     }
  2248.  
  2249.     public int getIntSp()
  2250.     {
  2251.         return (int) getSp();
  2252.     }
  2253.  
  2254.     public long getSp()
  2255.     {
  2256.         return _activeClass == null ? 0 : _activeClass.getSp();
  2257.     }
  2258.  
  2259.     public void setSp(long sp)
  2260.     {
  2261.         if(_activeClass != null)
  2262.             _activeClass.setSp(sp);
  2263.     }
  2264.  
  2265.     public int getClanId()
  2266.     {
  2267.         return _clan == null ? 0 : _clan.getClanId();
  2268.     }
  2269.  
  2270.     public long getLeaveClanTime()
  2271.     {
  2272.         return _leaveClanTime;
  2273.     }
  2274.  
  2275.     public long getDeleteClanTime()
  2276.     {
  2277.         return _deleteClanTime;
  2278.     }
  2279.  
  2280.     public void setLeaveClanTime(final long time)
  2281.     {
  2282.         _leaveClanTime = time;
  2283.     }
  2284.  
  2285.     public void setDeleteClanTime(final long time)
  2286.     {
  2287.         _deleteClanTime = time;
  2288.     }
  2289.  
  2290.     public void setOnlineTime(final long time)
  2291.     {
  2292.         _onlineTime = time;
  2293.         _onlineBeginTime = System.currentTimeMillis();
  2294.     }
  2295.  
  2296.     public void setNoChannel(final long time)
  2297.     {
  2298.         _NoChannel = time;
  2299.         if(_NoChannel > 2145909600000L || _NoChannel < 0)
  2300.             _NoChannel = -1;
  2301.  
  2302.         if(_NoChannel > 0)
  2303.             _NoChannelBegin = System.currentTimeMillis();
  2304.         else
  2305.             _NoChannelBegin = 0;
  2306.     }
  2307.  
  2308.     public long getNoChannel()
  2309.     {
  2310.         return _NoChannel;
  2311.     }
  2312.  
  2313.     public long getNoChannelRemained()
  2314.     {
  2315.         if(_NoChannel == 0)
  2316.             return 0;
  2317.         else if(_NoChannel < 0)
  2318.             return -1;
  2319.         else
  2320.         {
  2321.             long remained = _NoChannel - System.currentTimeMillis() + _NoChannelBegin;
  2322.             if(remained < 0)
  2323.                 return 0;
  2324.  
  2325.             return remained;
  2326.         }
  2327.     }
  2328.  
  2329.     public void setLeaveClanCurTime()
  2330.     {
  2331.         _leaveClanTime = System.currentTimeMillis();
  2332.     }
  2333.  
  2334.     public void setDeleteClanCurTime()
  2335.     {
  2336.         _deleteClanTime = System.currentTimeMillis();
  2337.     }
  2338.  
  2339.     public boolean canJoinClan()
  2340.     {
  2341.         if(_leaveClanTime == 0)
  2342.             return true;
  2343.         if(System.currentTimeMillis() - _leaveClanTime >= 24 * 60 * 60 * 1000L)
  2344.         {
  2345.             _leaveClanTime = 0;
  2346.             return true;
  2347.         }
  2348.         return false;
  2349.     }
  2350.  
  2351.     public boolean canCreateClan()
  2352.     {
  2353.         if(_deleteClanTime == 0)
  2354.             return true;
  2355.         if(System.currentTimeMillis() - _deleteClanTime >= 10 * 24 * 60 * 60 * 1000L)
  2356.         {
  2357.             _deleteClanTime = 0;
  2358.             return true;
  2359.         }
  2360.         return false;
  2361.     }
  2362.  
  2363.     public IStaticPacket canJoinParty(Player inviter)
  2364.     {
  2365.         Request request = getRequest();
  2366.         if(request != null && request.isInProgress() && request.getOtherPlayer(this) != inviter)
  2367.             return SystemMsg.WAITING_FOR_ANOTHER_REPLY.packet(inviter); // занят
  2368.         if(isBlockAll() || getMessageRefusal()) // всех нафиг
  2369.             return SystemMsg.THAT_PERSON_IS_IN_MESSAGE_REFUSAL_MODE.packet(inviter);
  2370.         if(isInParty()) // уже
  2371.             return new SystemMessage2(SystemMsg.C1_IS_A_MEMBER_OF_ANOTHER_PARTY_AND_CANNOT_BE_INVITED).addName(this);
  2372.         if(inviter.getReflection() != getReflection()) // в разных инстантах
  2373.             if(inviter.getReflection() != ReflectionManager.DEFAULT && getReflection() != ReflectionManager.DEFAULT)
  2374.                 return SystemMsg.INVALID_TARGET.packet(inviter);
  2375.         if(isCursedWeaponEquipped() || inviter.isCursedWeaponEquipped()) // зарич
  2376.             return SystemMsg.INVALID_TARGET.packet(inviter);
  2377.         if(inviter.isInOlympiadMode() || isInOlympiadMode()) // олимпиада
  2378.             return SystemMsg.A_USER_CURRENTLY_PARTICIPATING_IN_THE_OLYMPIAD_CANNOT_SEND_PARTY_AND_FRIEND_INVITATIONS.packet(inviter);
  2379.         if(!inviter.getPlayerAccess().CanJoinParty || !getPlayerAccess().CanJoinParty) // низя
  2380.             return SystemMsg.INVALID_TARGET.packet(inviter);
  2381.         if(getTeam() != TeamType.NONE) // участник пвп эвента или дуэли
  2382.             return SystemMsg.INVALID_TARGET.packet(inviter);
  2383.         return null;
  2384.     }
  2385.  
  2386.     @Override
  2387.     public PcInventory getInventory()
  2388.     {
  2389.         return _inventory;
  2390.     }
  2391.  
  2392.     @Override
  2393.     public long getWearedMask()
  2394.     {
  2395.         return _inventory.getWearedMask();
  2396.     }
  2397.  
  2398.     public PcFreight getFreight()
  2399.     {
  2400.         return _freight;
  2401.     }
  2402.  
  2403.     public void removeItemFromShortCut(final int objectId)
  2404.     {
  2405.         _shortCuts.deleteShortCutByObjectId(objectId);
  2406.     }
  2407.  
  2408.     public void removeSkillFromShortCut(final int skillId)
  2409.     {
  2410.         _shortCuts.deleteShortCutBySkillId(skillId);
  2411.     }
  2412.  
  2413.     public boolean isSitting()
  2414.     {
  2415.         return _isSitting;
  2416.     }
  2417.  
  2418.     public void setSitting(boolean val)
  2419.     {
  2420.         _isSitting = val;
  2421.     }
  2422.  
  2423.     public boolean getSittingTask()
  2424.     {
  2425.         return sittingTaskLaunched;
  2426.     }
  2427.  
  2428.     @Override
  2429.     public void sitDown(StaticObjectInstance throne)
  2430.     {
  2431.         if(isSitting() || sittingTaskLaunched || isAlikeDead())
  2432.             return;
  2433.  
  2434.         if(isStunned() || isSleeping() || isParalyzed() || isAttackingNow() || isCastingNow() || isMoving)
  2435.         {
  2436.             getAI().setNextAction(nextAction.REST, null, null, false, false);
  2437.             return;
  2438.         }
  2439.  
  2440.         resetWaitSitTime();
  2441.         getAI().setIntention(CtrlIntention.AI_INTENTION_REST, null, null);
  2442.  
  2443.         if(throne == null)
  2444.             broadcastPacket(new ChangeWaitType(this, ChangeWaitType.WT_SITTING));
  2445.         else
  2446.             broadcastPacket(new ChairSit(this, throne));
  2447.  
  2448.         _sittingObject = throne;
  2449.         setSitting(true);
  2450.         sittingTaskLaunched = true;
  2451.         ThreadPoolManager.getInstance().schedule(new EndSitDownTask(this), 2500);
  2452.     }
  2453.  
  2454.     @Override
  2455.     public void standUp()
  2456.     {
  2457.         if(!isSitting() || sittingTaskLaunched || isInStoreMode() || isAlikeDead())
  2458.             return;
  2459.  
  2460.         //FIXME [G1ta0] эффект сам отключается во время действия, если персонаж не сидит, возможно стоит убрать
  2461.         getEffectList().stopAllSkillEffects(EffectType.Relax);
  2462.  
  2463.         getAI().clearNextAction();
  2464.         broadcastPacket(new ChangeWaitType(this, ChangeWaitType.WT_STANDING));
  2465.  
  2466.         _sittingObject = null;
  2467.         sittingTaskLaunched = true;
  2468.         //setSitting(false);
  2469.         ThreadPoolManager.getInstance().schedule(new EndStandUpTask(this), 2500);
  2470.     }
  2471.  
  2472.     public void updateWaitSitTime()
  2473.     {
  2474.         if(_waitTimeWhenSit < 200)
  2475.             _waitTimeWhenSit += 2;
  2476.     }
  2477.  
  2478.     public int getWaitSitTime()
  2479.     {
  2480.         return _waitTimeWhenSit;
  2481.     }
  2482.  
  2483.     public void resetWaitSitTime()
  2484.     {
  2485.         _waitTimeWhenSit = 0;
  2486.     }
  2487.  
  2488.     public Warehouse getWarehouse()
  2489.     {
  2490.         return _warehouse;
  2491.     }
  2492.  
  2493.     public ItemContainer getRefund()
  2494.     {
  2495.         return _refund;
  2496.     }
  2497.  
  2498.     public long getAdena()
  2499.     {
  2500.         return getInventory().getAdena();
  2501.     }
  2502.  
  2503.     public boolean reduceAdena(long adena)
  2504.     {
  2505.         return reduceAdena(adena, false);
  2506.     }
  2507.  
  2508.     /**
  2509.      * Забирает адену у игрока.<BR><BR>
  2510.      *
  2511.      * @param adena  - сколько адены забрать
  2512.      * @param notify - отображать системное сообщение
  2513.      * @return true если сняли
  2514.      */
  2515.     public boolean reduceAdena(long adena, boolean notify)
  2516.     {
  2517.         if(adena < 0)
  2518.             return false;
  2519.         if(adena == 0)
  2520.             return true;
  2521.         boolean result = getInventory().reduceAdena(adena);
  2522.         if(notify && result)
  2523.             sendPacket(SystemMessage2.removeItems(ItemTemplate.ITEM_ID_ADENA, adena));
  2524.         return result;
  2525.     }
  2526.  
  2527.     public ItemInstance addAdena(long adena)
  2528.     {
  2529.         return addAdena(adena, false);
  2530.     }
  2531.  
  2532.     /**
  2533.      * Добавляет адену игроку.<BR><BR>
  2534.      *
  2535.      * @param adena  - сколько адены дать
  2536.      * @param notify - отображать системное сообщение
  2537.      * @return L2ItemInstance - новое количество адены
  2538.      */
  2539.     public ItemInstance addAdena(long adena, boolean notify)
  2540.     {
  2541.         if(adena < 1)
  2542.             return null;
  2543.         ItemInstance item = getInventory().addAdena(adena);
  2544.         if(item != null && notify)
  2545.             sendPacket(SystemMessage2.obtainItems(ItemTemplate.ITEM_ID_ADENA, adena, 0));
  2546.         return item;
  2547.     }
  2548.  
  2549.     public GameClient getNetConnection()
  2550.     {
  2551.         return _connection;
  2552.     }
  2553.  
  2554.     public int getRevision()
  2555.     {
  2556.         return _connection == null ? 0 : _connection.getRevision();
  2557.     }
  2558.  
  2559.     public void setNetConnection(final GameClient connection)
  2560.     {
  2561.         _connection = connection;
  2562.     }
  2563.  
  2564.     public boolean isConnected()
  2565.     {
  2566.         return _connection != null && _connection.isConnected();
  2567.     }
  2568.  
  2569.     @Override
  2570.     public void onAction(final Player player, boolean shift)
  2571.     {
  2572.         if(isFrozen())
  2573.         {
  2574.             player.sendPacket(ActionFail.STATIC);
  2575.             return;
  2576.         }
  2577.  
  2578.         if(Events.onAction(player, this, shift))
  2579.         {
  2580.             player.sendPacket(ActionFail.STATIC);
  2581.             return;
  2582.         }
  2583.  
  2584.         // Check if the other player already target this L2Player
  2585.         if(player.getTarget() != this)
  2586.         {
  2587.             player.setTarget(this);
  2588.             if(player.getTarget() == this)
  2589.                 player.sendPacket(new MyTargetSelected(getObjectId(), 0)); // The color to display in the select window is White
  2590.             else
  2591.                 player.sendPacket(ActionFail.STATIC);
  2592.         }
  2593.         else if(getPrivateStoreType() != Player.STORE_PRIVATE_NONE)
  2594.         {
  2595.             if(getDistance(player) > INTERACTION_DISTANCE && player.getAI().getIntention() != CtrlIntention.AI_INTENTION_INTERACT)
  2596.             {
  2597.                 if(!shift)
  2598.                     player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this, null);
  2599.                 else
  2600.                     player.sendPacket(ActionFail.STATIC);
  2601.             }
  2602.             else
  2603.                 player.doInteract(this);
  2604.         }
  2605.         else if(isAutoAttackable(player))
  2606.             player.getAI().Attack(this, false, shift);
  2607.         else if(player != this)
  2608.         {
  2609.             if(player.getAI().getIntention() != CtrlIntention.AI_INTENTION_FOLLOW)
  2610.             {
  2611.                 if(!shift)
  2612.                     player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this, Config.FOLLOW_RANGE);
  2613.                 else
  2614.                     player.sendPacket(ActionFail.STATIC);
  2615.             }
  2616.             else
  2617.                 player.sendPacket(ActionFail.STATIC);
  2618.         }
  2619.         else
  2620.             player.sendPacket(ActionFail.STATIC);
  2621.     }
  2622.  
  2623.     @Override
  2624.     public void broadcastStatusUpdate()
  2625.     {
  2626.         if(!needStatusUpdate()) //По идее еше должно срезать траффик. Будут глюки с отображением - убрать это условие.
  2627.             return;
  2628.  
  2629.         StatusUpdate su = makeStatusUpdate(StatusUpdate.MAX_HP, StatusUpdate.MAX_MP, StatusUpdate.MAX_CP, StatusUpdate.CUR_HP, StatusUpdate.CUR_MP, StatusUpdate.CUR_CP);
  2630.         sendPacket(su);
  2631.  
  2632.         // Check if a party is in progress
  2633.         if(isInParty())
  2634.             // Send the Server->Client packet PartySmallWindowUpdate with current HP, MP and Level to all other L2Player of the Party
  2635.             getParty().broadcastToPartyMembers(this, new PartySmallWindowUpdate(this));
  2636.  
  2637.         DuelEvent duelEvent = getEvent(DuelEvent.class);
  2638.         if(duelEvent != null)
  2639.             duelEvent.sendPacket(new ExDuelUpdateUserInfo(this), getTeam().revert().name());
  2640.  
  2641.         if(isInOlympiadMode() && isOlympiadCompStart())
  2642.         {
  2643.             if(_olympiadGame != null)
  2644.                 _olympiadGame.broadcastInfo(this, null, false);
  2645.         }
  2646.     }
  2647.  
  2648.     private ScheduledFuture<?> _broadcastCharInfoTask;
  2649.  
  2650.     public class BroadcastCharInfoTask extends RunnableImpl
  2651.     {
  2652.         @Override
  2653.         public void runImpl() throws Exception
  2654.         {
  2655.             broadcastCharInfoImpl();
  2656.             _broadcastCharInfoTask = null;
  2657.         }
  2658.     }
  2659.  
  2660.     @Override
  2661.     public void broadcastCharInfo()
  2662.     {
  2663.         broadcastUserInfo(false);
  2664.     }
  2665.  
  2666.     /**
  2667.      * Отправляет UserInfo даному игроку и CharInfo всем окружающим.<BR><BR>
  2668.      * <p/>
  2669.      * <B><U> Концепт</U> :</B><BR><BR>
  2670.      * Сервер шлет игроку UserInfo.
  2671.      * Сервер вызывает метод {@link Creature#broadcastPacketToOthers(l2r.gameserver.network.serverpackets.L2GameServerPacket...)} для рассылки CharInfo<BR><BR>
  2672.      * <p/>
  2673.      * <B><U> Действия</U> :</B><BR><BR>
  2674.      * <li>Отсылка игроку UserInfo(личные и общие данные)</li>
  2675.      * <li>Отсылка другим игрокам CharInfo(Public data only)</li><BR><BR>
  2676.      * <p/>
  2677.      * <FONT COLOR=#FF0000><B> <U>Внимание</U> : НЕ ПОСЫЛАЙТЕ UserInfo другим игрокам либо CharInfo даному игроку.<BR>
  2678.      * НЕ ВЫЗЫВАЕЙТЕ ЭТОТ МЕТОД КРОМЕ ОСОБЫХ ОБСТОЯТЕЛЬСТВ(смена сабкласса к примеру)!!! Траффик дико кушается у игроков и начинаются лаги.<br>
  2679.      * Используйте метод {@link Player#sendChanges()}</B></FONT><BR><BR>
  2680.      */
  2681.     public void broadcastUserInfo(boolean force)
  2682.     {
  2683.         sendUserInfo(force);
  2684.  
  2685.         if(!isVisible() || isInvisible())
  2686.             return;
  2687.  
  2688.         if(Config.BROADCAST_CHAR_INFO_INTERVAL == 0)
  2689.             force = true;
  2690.  
  2691.         if(force)
  2692.         {
  2693.             if(_broadcastCharInfoTask != null)
  2694.             {
  2695.                 _broadcastCharInfoTask.cancel(false);
  2696.                 _broadcastCharInfoTask = null;
  2697.             }
  2698.             broadcastCharInfoImpl();
  2699.             return;
  2700.         }
  2701.  
  2702.         if(_broadcastCharInfoTask != null)
  2703.             return;
  2704.  
  2705.         _broadcastCharInfoTask = ThreadPoolManager.getInstance().schedule(new BroadcastCharInfoTask(), Config.BROADCAST_CHAR_INFO_INTERVAL);
  2706.     }
  2707.  
  2708.     private int _polyNpcId;
  2709.  
  2710.     public void setPolyId(int polyid)
  2711.     {
  2712.         _polyNpcId = polyid;
  2713.  
  2714.         teleToLocation(getLoc());
  2715.         broadcastUserInfo(true);
  2716.     }
  2717.  
  2718.     public boolean isPolymorphed()
  2719.     {
  2720.         return _polyNpcId != 0;
  2721.     }
  2722.  
  2723.     public int getPolyId()
  2724.     {
  2725.         return _polyNpcId;
  2726.     }
  2727.  
  2728.     private void broadcastCharInfoImpl()
  2729.     {
  2730.         if(!isVisible() || isInvisible())
  2731.             return;
  2732.  
  2733.         L2GameServerPacket ci = isPolymorphed() ? new NpcInfoPoly(this) : new CharInfo(this);
  2734.         L2GameServerPacket exCi = new ExBR_ExtraUserInfo(this);
  2735.         L2GameServerPacket dominion = getEvent(DominionSiegeEvent.class) != null ? new ExDominionWarStart(this) : null;
  2736.         for(Player player : World.getAroundPlayers(this))
  2737.         {
  2738.             player.sendPacket(ci, exCi);
  2739.             player.sendPacket(RelationChanged.update(player, this, player));
  2740.             if(dominion != null)
  2741.                 player.sendPacket(dominion);
  2742.         }
  2743.     }
  2744.  
  2745.     public void broadcastRelationChanged()
  2746.     {
  2747.         if(!isVisible() || isInvisible())
  2748.             return;
  2749.  
  2750.         for(Player player : World.getAroundPlayers(this))
  2751.             player.sendPacket(RelationChanged.update(player, this, player));
  2752.     }
  2753.  
  2754.     public void sendEtcStatusUpdate()
  2755.     {
  2756.         if(!isVisible())
  2757.             return;
  2758.  
  2759.         sendPacket(new EtcStatusUpdate(this));
  2760.     }
  2761.  
  2762.     private Future<?> _userInfoTask;
  2763.  
  2764.     private class UserInfoTask extends RunnableImpl
  2765.     {
  2766.         @Override
  2767.         public void runImpl() throws Exception
  2768.         {
  2769.             sendUserInfoImpl();
  2770.             _userInfoTask = null;
  2771.         }
  2772.     }
  2773.  
  2774.     private void sendUserInfoImpl()
  2775.     {
  2776.         sendPacket(new UserInfo(this), new ExBR_ExtraUserInfo(this));
  2777.         DominionSiegeEvent siegeEvent = getEvent(DominionSiegeEvent.class);
  2778.         if(siegeEvent != null)
  2779.             sendPacket(new ExDominionWarStart(this));
  2780.     }
  2781.  
  2782.     public void sendUserInfo()
  2783.     {
  2784.         sendUserInfo(false);
  2785.     }
  2786.  
  2787.     public void sendUserInfo(boolean force)
  2788.     {
  2789.         if(!isVisible() || entering || isLogoutStarted())
  2790.             return;
  2791.  
  2792.         if(Config.USER_INFO_INTERVAL == 0 || force)
  2793.         {
  2794.             if(_userInfoTask != null)
  2795.             {
  2796.                 _userInfoTask.cancel(false);
  2797.                 _userInfoTask = null;
  2798.             }
  2799.             sendUserInfoImpl();
  2800.             return;
  2801.         }
  2802.  
  2803.         if(_userInfoTask != null)
  2804.             return;
  2805.  
  2806.         _userInfoTask = ThreadPoolManager.getInstance().schedule(new UserInfoTask(), Config.USER_INFO_INTERVAL);
  2807.     }
  2808.  
  2809.     @Override
  2810.     public StatusUpdate makeStatusUpdate(int... fields)
  2811.     {
  2812.         StatusUpdate su = new StatusUpdate(getObjectId());
  2813.         for(int field : fields)
  2814.             switch(field)
  2815.             {
  2816.                 case StatusUpdate.CUR_HP:
  2817.                     su.addAttribute(field, (int) getCurrentHp());
  2818.                     break;
  2819.                 case StatusUpdate.MAX_HP:
  2820.                     su.addAttribute(field, getMaxHp());
  2821.                     break;
  2822.                 case StatusUpdate.CUR_MP:
  2823.                     su.addAttribute(field, (int) getCurrentMp());
  2824.                     break;
  2825.                 case StatusUpdate.MAX_MP:
  2826.                     su.addAttribute(field, getMaxMp());
  2827.                     break;
  2828.                 case StatusUpdate.CUR_LOAD:
  2829.                     su.addAttribute(field, getCurrentLoad());
  2830.                     break;
  2831.                 case StatusUpdate.MAX_LOAD:
  2832.                     su.addAttribute(field, getMaxLoad());
  2833.                     break;
  2834.                 case StatusUpdate.PVP_FLAG:
  2835.                     //su.addAttribute(field, _pvpFlag);
  2836.                     break;
  2837.                 case StatusUpdate.KARMA:
  2838.                     su.addAttribute(field, getKarma());
  2839.                     break;
  2840.                 case StatusUpdate.CUR_CP:
  2841.                     su.addAttribute(field, (int) getCurrentCp());
  2842.                     break;
  2843.                 case StatusUpdate.MAX_CP:
  2844.                     su.addAttribute(field, getMaxCp());
  2845.                     break;
  2846.             }
  2847.         return su;
  2848.     }
  2849.  
  2850.     public void sendStatusUpdate(boolean broadCast, boolean withPet, int... fields)
  2851.     {
  2852.         if(fields.length == 0 || entering && !broadCast)
  2853.             return;
  2854.  
  2855.         StatusUpdate su = makeStatusUpdate(fields);
  2856.         if(!su.hasAttributes())
  2857.             return;
  2858.  
  2859.         List<L2GameServerPacket> packets = new ArrayList<L2GameServerPacket>(withPet ? 2 : 1);
  2860.         if(withPet && getPet() != null)
  2861.             packets.add(getPet().makeStatusUpdate(fields));
  2862.  
  2863.         packets.add(su);
  2864.  
  2865.         if(!broadCast)
  2866.             sendPacket(packets);
  2867.         else if(entering)
  2868.             broadcastPacketToOthers(packets);
  2869.         else
  2870.             broadcastPacket(packets);
  2871.     }
  2872.  
  2873.     /**
  2874.      * @return the Alliance Identifier of the L2Player.<BR><BR>
  2875.      */
  2876.     public int getAllyId()
  2877.     {
  2878.         return _clan == null ? 0 : _clan.getAllyId();
  2879.     }
  2880.  
  2881.     @Override
  2882.     public void sendPacket(IStaticPacket p)
  2883.     {
  2884.         if(!isConnected())
  2885.             return;
  2886.  
  2887.         if(isPacketIgnored(p.packet(this)))
  2888.             return;
  2889.  
  2890.         _connection.sendPacket(p.packet(this));
  2891.     }
  2892.  
  2893.     @Override
  2894.     public void sendPacket(IStaticPacket... packets)
  2895.     {
  2896.         if(!isConnected())
  2897.             return;
  2898.  
  2899.         for(IStaticPacket p : packets)
  2900.         {
  2901.             if(isPacketIgnored(p))
  2902.                 continue;
  2903.  
  2904.             _connection.sendPacket(p.packet(this));
  2905.         }
  2906.     }
  2907.  
  2908.     private boolean isPacketIgnored(IStaticPacket p)
  2909.     {
  2910.         if(p == null)
  2911.             return true;
  2912.         if(_notShowBuffAnim && (p.getClass() == MagicSkillUse.class || p.getClass() == MagicSkillLaunched.class))
  2913.             return true;
  2914.  
  2915.         //if(_notShowTraders && (p.getClass() == PrivateStoreMsgBuy.class || p.getClass() == PrivateStoreMsgSell.class || p.getClass() == RecipeShopMsg.class))
  2916.         //      return true;
  2917.  
  2918.         return false;
  2919.     }
  2920.  
  2921.     @Override
  2922.     public void sendPacket(List<? extends IStaticPacket> packets)
  2923.     {
  2924.         if(!isConnected())
  2925.             return;
  2926.  
  2927.         for(IStaticPacket p : packets)
  2928.             _connection.sendPacket(p.packet(this));
  2929.     }
  2930.  
  2931.     public void doInteract(GameObject target)
  2932.     {
  2933.         if(target == null || isActionsDisabled())
  2934.         {
  2935.             sendActionFailed();
  2936.             return;
  2937.         }
  2938.         if(target.isPlayer())
  2939.         {
  2940.             if(target.getDistance(this) <= INTERACTION_DISTANCE)
  2941.             {
  2942.                 Player temp = (Player) target;
  2943.  
  2944.                 if(temp.getPrivateStoreType() == STORE_PRIVATE_SELL || temp.getPrivateStoreType() == STORE_PRIVATE_SELL_PACKAGE)
  2945.                 {
  2946.                     sendPacket(new PrivateStoreListSell(this, temp));
  2947.                     sendActionFailed();
  2948.                 }
  2949.                 else if(temp.getPrivateStoreType() == STORE_PRIVATE_BUY)
  2950.                 {
  2951.                     sendPacket(new PrivateStoreListBuy(this, temp));
  2952.                     sendActionFailed();
  2953.                 }
  2954.                 else if(temp.getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE)
  2955.                 {
  2956.                     sendPacket(new RecipeShopSellList(this, temp));
  2957.                     sendActionFailed();
  2958.                 }
  2959.                 sendActionFailed();
  2960.             }
  2961.             else if(getAI().getIntention() != CtrlIntention.AI_INTENTION_INTERACT)
  2962.                 getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this, null);
  2963.         }
  2964.         else
  2965.             target.onAction(this, false);
  2966.     }
  2967.  
  2968.     public void doAutoLootOrDrop(ItemInstance item, NpcInstance fromNpc)
  2969.     {
  2970.         boolean forceAutoloot = fromNpc.isFlying() || getReflection().isAutolootForced();
  2971.  
  2972.         if((fromNpc.isRaid() || fromNpc instanceof ReflectionBossInstance) && !Config.AUTO_LOOT_FROM_RAIDS && !item.isHerb() && !forceAutoloot)
  2973.         {
  2974.             item.dropToTheGround(this, fromNpc);
  2975.             return;
  2976.         }
  2977.  
  2978.         // Herbs
  2979.         if(item.isHerb())
  2980.         {
  2981.             if(!AutoLootHerbs && !forceAutoloot)
  2982.             {
  2983.                 item.dropToTheGround(this, fromNpc);
  2984.                 return;
  2985.             }
  2986.             Skill[] skills = item.getTemplate().getAttachedSkills();
  2987.  
  2988.             if(skills.length > 0)
  2989.             {
  2990.                 for(Skill skill : skills)
  2991.                 {
  2992.                     altUseSkill(skill, this);
  2993.                     if(getPet() != null && getPet().isSummon() && !getPet().isDead())
  2994.                     {
  2995.                         getPet().altUseSkill(skill, getPet());
  2996.                     }
  2997.                 }
  2998.             }
  2999.  
  3000.             item.deleteMe();
  3001.             return;
  3002.         }
  3003.  
  3004.         if(!_autoLoot && !forceAutoloot)
  3005.         {
  3006.             item.dropToTheGround(this, fromNpc);
  3007.             return;
  3008.         }
  3009.  
  3010.         // Check if the L2Player is in a Party
  3011.         if(!isInParty())
  3012.         {
  3013.             if ((Config.ALLOW_REFFERAL_SYSTEM) && (Config.ITEM_LIST.contains(Integer.valueOf(item.getItemId()))))
  3014.             {
  3015.                 RefferalSystem.applyBonus(this, item.getItemId(), (int)item.getCount());
  3016.             }
  3017.  
  3018.             if(!pickupItem(item, Log.Pickup))
  3019.             {
  3020.                 item.dropToTheGround(this, fromNpc);
  3021.                 return;
  3022.             }
  3023.         }
  3024.         else
  3025.             getParty().distributeItem(this, item, fromNpc);
  3026.  
  3027.         broadcastPickUpMsg(item);
  3028.     }
  3029.  
  3030.     @Override
  3031.     public void doPickupItem(final GameObject object)
  3032.     {
  3033.         // Check if the L2Object to pick up is a L2ItemInstance
  3034.         if(!object.isItem())
  3035.         {
  3036.             _log.warn("trying to pickup wrong target." + getTarget());
  3037.             return;
  3038.         }
  3039.  
  3040.         sendActionFailed();
  3041.         stopMove();
  3042.  
  3043.         ItemInstance item = (ItemInstance) object;
  3044.  
  3045.         synchronized(item)
  3046.         {
  3047.             if(!item.isVisible())
  3048.                 return;
  3049.  
  3050.             // Check if me not owner of item and, if in party, not in owner party and nonowner pickup delay still active
  3051.             if(!ItemFunctions.checkIfCanPickup(this, item))
  3052.             {
  3053.                 SystemMessage2 sm;
  3054.                 if(item.getItemId() == 57)
  3055.                 {
  3056.                     sm = new SystemMessage2(SystemMsg.YOU_HAVE_FAILED_TO_PICK_UP_S1_ADENA);
  3057.                     sm.addNumber(item.getCount());
  3058.                 }
  3059.                 else
  3060.                 {
  3061.                     sm = new SystemMessage2(SystemMsg.YOU_HAVE_FAILED_TO_PICK_UP_S1);
  3062.                     sm.addItemName(item.getItemId());
  3063.                 }
  3064.                 sendPacket(sm);
  3065.                 return;
  3066.             }
  3067.  
  3068.             // Herbs
  3069.             if(item.isHerb())
  3070.             {
  3071.                 Skill[] skills = item.getTemplate().getAttachedSkills();
  3072.                 if(skills.length > 0)
  3073.                     for(Skill skill : skills)
  3074.                         altUseSkill(skill, this);
  3075.  
  3076.                 broadcastPacket(new GetItem(item, getObjectId()));
  3077.                 item.deleteMe();
  3078.                 return;
  3079.             }
  3080.  
  3081.             FlagItemAttachment attachment = item.getAttachment() instanceof FlagItemAttachment ? (FlagItemAttachment) item.getAttachment() : null;
  3082.  
  3083.             if(!isInParty() || attachment != null)
  3084.             {
  3085.                 if(pickupItem(item, Log.Pickup))
  3086.                 {
  3087.                     broadcastPacket(new GetItem(item, getObjectId()));
  3088.                     broadcastPickUpMsg(item);
  3089.                     item.pickupMe();
  3090.                 }
  3091.             }
  3092.             else
  3093.                 getParty().distributeItem(this, item, null);
  3094.         }
  3095.     }
  3096.  
  3097.     public boolean pickupItem(ItemInstance item, String log)
  3098.     {
  3099.         PickableAttachment attachment = item.getAttachment() instanceof PickableAttachment ? (PickableAttachment) item.getAttachment() : null;
  3100.  
  3101.         if(!ItemFunctions.canAddItem(this, item))
  3102.             return false;
  3103.  
  3104.         if(item.getItemId() == ItemTemplate.ITEM_ID_ADENA || item.getItemId() == 6353)//FIXME [G1ta0] хардкод
  3105.         {
  3106.             Quest q = QuestManager.getQuest(255);
  3107.             if(q != null)
  3108.                 processQuestEvent(q.getName(), "CE" + item.getItemId(), null);
  3109.         }
  3110.  
  3111.         Log.LogItem(this, log, item);
  3112.         sendPacket(SystemMessage2.obtainItems(item));
  3113.         getInventory().addItem(item);
  3114.  
  3115.         if(attachment != null)
  3116.             attachment.pickUp(this);
  3117.  
  3118.         sendChanges();
  3119.         return true;
  3120.     }
  3121.  
  3122.     public void setObjectTarget(GameObject target)
  3123.     {
  3124.         setTarget(target);
  3125.         if(target == null)
  3126.             return;
  3127.  
  3128.         if(target == getTarget())
  3129.         {
  3130.             if(target.isNpc())
  3131.             {
  3132.                 NpcInstance npc = (NpcInstance) target;
  3133.                 sendPacket(new MyTargetSelected(npc.getObjectId(), getLevel() - npc.getLevel()));
  3134.                 sendPacket(npc.makeStatusUpdate(StatusUpdate.CUR_HP, StatusUpdate.MAX_HP));
  3135.                 sendPacket(new ValidateLocation(npc), ActionFail.STATIC);
  3136.             }
  3137.             else
  3138.                 sendPacket(new MyTargetSelected(target.getObjectId(), 0));
  3139.         }
  3140.     }
  3141.  
  3142.     @Override
  3143.     public void setTarget(GameObject newTarget)
  3144.     {
  3145.         // Check if the new target is visible
  3146.         if(newTarget != null && !newTarget.isVisible())
  3147.             newTarget = null;
  3148.  
  3149.         // Can't target and attack festival monsters if not participant
  3150.         if(newTarget instanceof FestivalMonsterInstance && !isFestivalParticipant())
  3151.             newTarget = null;
  3152.  
  3153.         Party party = getParty();
  3154.  
  3155.         // Can't target and attack rift invaders if not in the same room
  3156.         if(party != null && party.isInDimensionalRift())
  3157.         {
  3158.             int riftType = party.getDimensionalRift().getType();
  3159.             int riftRoom = party.getDimensionalRift().getCurrentRoom();
  3160.             if(newTarget != null && !DimensionalRiftManager.getInstance().getRoom(riftType, riftRoom).checkIfInZone(newTarget.getX(), newTarget.getY(), newTarget.getZ()))
  3161.                 newTarget = null;
  3162.         }
  3163.  
  3164.         GameObject oldTarget = getTarget();
  3165.  
  3166.         if(oldTarget != null)
  3167.         {
  3168.             if(oldTarget.equals(newTarget))
  3169.                 return;
  3170.  
  3171.             // Remove the L2Player from the _statusListener of the old target if it was a L2Character
  3172.             if(oldTarget.isCreature())
  3173.                 ((Creature) oldTarget).removeStatusListener(this);
  3174.  
  3175.             broadcastPacket(new TargetUnselected(this));
  3176.         }
  3177.  
  3178.         if(newTarget != null)
  3179.         {
  3180.             // Add the L2Player to the _statusListener of the new target if it's a L2Character
  3181.             if(newTarget.isCreature())
  3182.                 ((Creature) newTarget).addStatusListener(this);
  3183.  
  3184.             broadcastPacket(new TargetSelected(getObjectId(), newTarget.getObjectId(), getLoc()));
  3185.         }
  3186.  
  3187.         super.setTarget(newTarget);
  3188.     }
  3189.  
  3190.     /**
  3191.      * @return the active weapon instance (always equipped in the right hand).<BR><BR>
  3192.      */
  3193.     @Override
  3194.     public ItemInstance getActiveWeaponInstance()
  3195.     {
  3196.         return getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
  3197.     }
  3198.  
  3199.     /**
  3200.      * @return the active weapon item (always equipped in the right hand).<BR><BR>
  3201.      */
  3202.     @Override
  3203.     public WeaponTemplate getActiveWeaponItem()
  3204.     {
  3205.         final ItemInstance weapon = getActiveWeaponInstance();
  3206.  
  3207.         if(weapon == null)
  3208.             return getFistsWeaponItem();
  3209.  
  3210.         return (WeaponTemplate) weapon.getTemplate();
  3211.     }
  3212.  
  3213.     /**
  3214.      * @return the secondary weapon instance (always equipped in the left hand).<BR><BR>
  3215.      */
  3216.     @Override
  3217.     public ItemInstance getSecondaryWeaponInstance()
  3218.     {
  3219.         return getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
  3220.     }
  3221.  
  3222.     /**
  3223.      * @return the secondary weapon item (always equipped in the left hand) or the fists weapon.<BR><BR>
  3224.      */
  3225.     @Override
  3226.     public WeaponTemplate getSecondaryWeaponItem()
  3227.     {
  3228.         final ItemInstance weapon = getSecondaryWeaponInstance();
  3229.  
  3230.         if(weapon == null)
  3231.             return getFistsWeaponItem();
  3232.  
  3233.         final ItemTemplate item = weapon.getTemplate();
  3234.  
  3235.         if(item instanceof WeaponTemplate)
  3236.             return (WeaponTemplate) item;
  3237.  
  3238.         return null;
  3239.     }
  3240.  
  3241.     public boolean isWearingArmor(final ArmorType armorType)
  3242.     {
  3243.         final ItemInstance chest = getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
  3244.  
  3245.         if(chest == null)
  3246.             return armorType == ArmorType.NONE;
  3247.  
  3248.         if(chest.getItemType() != armorType)
  3249.             return false;
  3250.  
  3251.         if(chest.getBodyPart() == ItemTemplate.SLOT_FULL_ARMOR)
  3252.             return true;
  3253.  
  3254.         final ItemInstance legs = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS);
  3255.  
  3256.         return legs == null ? armorType == ArmorType.NONE : legs.getItemType() == armorType;
  3257.     }
  3258.  
  3259.     @Override
  3260.     public void reduceCurrentHp(double damage, Creature attacker, Skill skill, boolean awake, boolean standUp, boolean directHp, boolean canReflect, boolean transferDamage, boolean isDot, boolean sendMessage)
  3261.     {
  3262.         if(attacker == null || isDead() || (attacker.isDead() && !isDot))
  3263.             return;
  3264.  
  3265.         // 5182 = Blessing of protection, работает если разница уровней больше 10 и не в зоне осады
  3266.         if(attacker.isPlayer() && Math.abs(attacker.getLevel() - getLevel()) > 10)
  3267.         {
  3268.             // ПК не может нанести урон чару с блессингом
  3269.             if(attacker.getKarma() > 0 && getEffectList().getEffectsBySkillId(5182) != null && !isInZone(ZoneType.SIEGE))
  3270.                 return;
  3271.             // чар с блессингом не может нанести урон ПК
  3272.             if(getKarma() > 0 && attacker.getEffectList().getEffectsBySkillId(5182) != null && !attacker.isInZone(ZoneType.SIEGE))
  3273.                 return;
  3274.         }
  3275.  
  3276.         // Reduce the current HP of the L2Player
  3277.         super.reduceCurrentHp(damage, attacker, skill, awake, standUp, directHp, canReflect, transferDamage, isDot, sendMessage);
  3278.     }
  3279.  
  3280.     @Override
  3281.     protected void onReduceCurrentHp(double damage, Creature attacker, Skill skill, boolean awake, boolean standUp, boolean directHp)
  3282.     {
  3283.         if(standUp)
  3284.         {
  3285.             standUp();
  3286.             if(isFakeDeath())
  3287.                 breakFakeDeath();
  3288.         }
  3289.  
  3290.         if(attacker.isPlayable())
  3291.         {
  3292.             if(!directHp && getCurrentCp() > 0)
  3293.             {
  3294.                 double cp = getCurrentCp();
  3295.                 if(cp >= damage)
  3296.                 {
  3297.                     cp -= damage;
  3298.                     damage = 0;
  3299.                 }
  3300.                 else
  3301.                 {
  3302.                     damage -= cp;
  3303.                     cp = 0;
  3304.                 }
  3305.  
  3306.                 setCurrentCp(cp);
  3307.             }
  3308.         }
  3309.  
  3310.         double hp = getCurrentHp();
  3311.  
  3312.         DuelEvent duelEvent = getEvent(DuelEvent.class);
  3313.         if(duelEvent != null)
  3314.             if(hp - damage <= 1) // если хп <= 1 - убит
  3315.             {
  3316.                 setCurrentHp(1, false);
  3317.                 duelEvent.onDie(this);
  3318.                 return;
  3319.             }
  3320.  
  3321.         if(isInOlympiadMode())
  3322.         {
  3323.             OlympiadGame game =_olympiadGame;
  3324.             if(this != attacker && (skill == null || skill.isOffensive())) // считаем дамаг от простых ударов и атакующих скиллов
  3325.                 game.addDamage(this, Math.min(hp, damage));
  3326.  
  3327.             if(hp - damage <= 1) // если хп <= 1 - убит
  3328.                 if(game.getType() != CompType.TEAM)
  3329.                 {
  3330.                     game.setWinner(getOlympiadSide() == 1 ? 2 : 1);
  3331.                     game.endGame(20000, false);
  3332.                     setCurrentHp(1, false);
  3333.                     attacker.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
  3334.                     attacker.sendActionFailed();
  3335.                     return;
  3336.                 }
  3337.                 else if(game.doDie(this)) // Все умерли
  3338.                 {
  3339.                     game.setWinner(getOlympiadSide() == 1 ? 2 : 1);
  3340.                     game.endGame(20000, false);
  3341.                 }
  3342.         }
  3343.  
  3344.         super.onReduceCurrentHp(damage, attacker, skill, awake, standUp, directHp);
  3345.     }
  3346.  
  3347.     private void altDeathPenalty(final Creature killer)
  3348.     {
  3349.         // Reduce the Experience of the L2Player in function of the calculated Death Penalty
  3350.         if(!Config.ALT_GAME_DELEVEL)
  3351.             return;
  3352.         if(isInZoneBattle())
  3353.             return;
  3354.         if(getNevitSystem().isBlessingActive())
  3355.             return;
  3356.         deathPenalty(killer);
  3357.     }
  3358.  
  3359.     public final boolean atWarWith(final Player player)
  3360.     {
  3361.         return getFaction() != player.getFaction() && getFaction() != FactionManager.Faction.ADMIN;
  3362.     }
  3363.  
  3364.     public final void doPurePk(final Player killer)
  3365.     {
  3366.         // Check if the attacker has a PK counter greater than 0
  3367.         final int pkCountMulti = Math.max(killer.getPkKills() / 2, 1);
  3368.  
  3369.         // Calculate the level difference Multiplier between attacker and killed L2Player
  3370.         //final int lvlDiffMulti = Math.max(killer.getLevel() / _level, 1);
  3371.  
  3372.         // Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
  3373.         // Add karma to attacker and increase its PK counter
  3374.         killer.increaseKarma(Config.KARMA_MIN_KARMA * pkCountMulti); // * lvlDiffMulti);
  3375.         killer.setPkKills(killer.getPkKills() + 1);
  3376.     }
  3377.  
  3378.     public final void doKillInPeace(final Player killer) // Check if the L2Player killed haven't Karma
  3379.     {
  3380.         if(_karma <= 0)
  3381.             doPurePk(killer);
  3382.         else
  3383.             killer.setPvpKills(killer.getPvpKills() + 1);
  3384.     }
  3385.  
  3386.     public void checkAddItemToDrop(List<ItemInstance> array, List<ItemInstance> items, int maxCount)
  3387.     {
  3388.         for(int i = 0; i < maxCount && !items.isEmpty(); i++)
  3389.             array.add(items.remove(Rnd.get(items.size())));
  3390.     }
  3391.  
  3392.     public FlagItemAttachment getActiveWeaponFlagAttachment()
  3393.     {
  3394.         ItemInstance item = getActiveWeaponInstance();
  3395.         if(item == null || !(item.getAttachment() instanceof FlagItemAttachment))
  3396.             return null;
  3397.         return (FlagItemAttachment) item.getAttachment();
  3398.     }
  3399.  
  3400.     protected void doPKPVPManage(Creature killer)
  3401.     {
  3402.         FlagItemAttachment attachment = getActiveWeaponFlagAttachment();
  3403.         if(attachment != null)
  3404.             attachment.onDeath(this, killer);
  3405.  
  3406.  
  3407.         if(killer == null || killer == _summon || killer == this)
  3408.             return;
  3409.  
  3410.         if(isInZoneBattle() || killer.isInZoneBattle())
  3411.             return;
  3412.  
  3413.         if(killer instanceof Summon && (killer = killer.getPlayer()) == null)
  3414.             return;
  3415.  
  3416.         // Processing Karma/PKCount/PvPCount for killer
  3417.         if(killer.isPlayer())
  3418.         {
  3419.             final Player pk = killer.getPlayer();
  3420.             final int repValue = getLevel() - pk.getLevel() >= 20 ? 2 : 1;
  3421.             boolean war = atWarWith(pk);
  3422.  
  3423.             if(_clan != null)
  3424.             {
  3425.                 if(war || _clan.getSiege() != null && _clan.getSiege() == pk.getClan().getSiege() && (_clan.isDefender() && pk.getClan().isAttacker() || _clan.isAttacker() && pk.getClan().isDefender()))
  3426.                 {
  3427.                     if(pk.getClan().getReputationScore() > 0 && _clan.getLevel() >= 5 && _clan.getReputationScore() > 0 && pk.getClan().getLevel() >= 5)
  3428.                     {
  3429.                         _clan.broadcastToOtherOnlineMembers(new SystemMessage2(SystemMsg.YOUR_CLAN_MEMBER_S1_WAS_KILLED_S2_POINTS_HAVE_BEEN_DEDUCTED_FROM_YOUR_CLAN_REPUTATION_SCORE_AND_ADDED_TO_YOUR_OPPONENT_CLAN_REPUTATION_SCORE).addString(getName()).addNumber(-_clan.incReputation(-repValue, true, "ClanWar")), this);
  3430.                         pk.getClan().broadcastToOtherOnlineMembers(new SystemMessage2(SystemMsg.FOR_KILLING_AN_OPPOSING_CLAN_MEMBER_S1_POINTS_HAVE_BEEN_DEDUCTED_FROM_YOUR_OPPONENTS_CLAN_REPUTATION_SCORE).addNumber(pk.getClan().incReputation(repValue, true, "ClanWar")), pk);
  3431.                     }
  3432.                 }
  3433.             }
  3434.  
  3435.             if(isOnSiegeField())
  3436.                 return;
  3437.  
  3438.             if(/*_pvpFlag > 0 || */war)
  3439.                 pk.setPvpKills(pk.getPvpKills() + 1);
  3440.             else
  3441.                 doKillInPeace(pk);
  3442.  
  3443.             giveAdenaForPvp(pk);
  3444.  
  3445.             pk.sendChanges();
  3446.         }
  3447.  
  3448.         int karma = _karma;
  3449.         decreaseKarma(Config.KARMA_LOST_BASE);
  3450.  
  3451.         // в нормальных условиях вещи теряются только при смерти от гварда или игрока
  3452.         // кроме того, альт на потерю вещей при сметри позволяет терять вещи при смтери от монстра
  3453.         boolean isPvP = killer.isPlayable() || killer instanceof GuardInstance;
  3454.  
  3455.         if(killer.isMonster() && !Config.DROP_ITEMS_ON_DIE // если убил монстр и альт выключен
  3456.                 || isPvP // если убил игрок или гвард и
  3457.                 && (_pkKills < Config.MIN_PK_TO_ITEMS_DROP // количество пк слишком мало
  3458.                 || karma == 0 && Config.KARMA_NEEDED_TO_DROP) // кармы нет
  3459.                 || isFestivalParticipant() // в фестивале вещи не теряются
  3460.                 || !killer.isMonster() && !isPvP) // в прочих случаях тоже
  3461.             return;
  3462.  
  3463.         // No drop from GM's
  3464.         if(!Config.KARMA_DROP_GM && isGM())
  3465.             return;
  3466.  
  3467.         final int max_drop_count = isPvP ? Config.KARMA_DROP_ITEM_LIMIT : 1;
  3468.  
  3469.         double dropRate; // базовый шанс в процентах
  3470.         if(isPvP)
  3471.             dropRate = _pkKills * Config.KARMA_DROPCHANCE_MOD + Config.KARMA_DROPCHANCE_BASE;
  3472.         else
  3473.             dropRate = Config.NORMAL_DROPCHANCE_BASE;
  3474.  
  3475.         int dropEquipCount = 0, dropWeaponCount = 0, dropItemCount = 0;
  3476.  
  3477.         for(int i = 0; i < Math.ceil(dropRate / 100) && i < max_drop_count; i++)
  3478.             if(Rnd.chance(dropRate))
  3479.             {
  3480.                 int rand = Rnd.get(Config.DROPCHANCE_EQUIPPED_WEAPON + Config.DROPCHANCE_EQUIPMENT + Config.DROPCHANCE_ITEM) + 1;
  3481.                 if(rand > Config.DROPCHANCE_EQUIPPED_WEAPON + Config.DROPCHANCE_EQUIPMENT)
  3482.                     dropItemCount++;
  3483.                 else if(rand > Config.DROPCHANCE_EQUIPPED_WEAPON)
  3484.                     dropEquipCount++;
  3485.                 else
  3486.                     dropWeaponCount++;
  3487.             }
  3488.  
  3489.         List<ItemInstance> drop = new LazyArrayList<ItemInstance>(), // общий массив с результатами выбора
  3490.                 dropItem = new LazyArrayList<ItemInstance>(), dropEquip = new LazyArrayList<ItemInstance>(), dropWeapon = new LazyArrayList<ItemInstance>(); // временные
  3491.  
  3492.         getInventory().writeLock();
  3493.         try
  3494.         {
  3495.             for(ItemInstance item : getInventory().getItems())
  3496.             {
  3497.                 if(!item.canBeDropped(this, true) || Config.KARMA_LIST_NONDROPPABLE_ITEMS.contains(item.getItemId()))
  3498.                     continue;
  3499.  
  3500.                 if(item.getTemplate().getType2() == ItemTemplate.TYPE2_WEAPON)
  3501.                     dropWeapon.add(item);
  3502.                 else if(item.getTemplate().getType2() == ItemTemplate.TYPE2_SHIELD_ARMOR || item.getTemplate().getType2() == ItemTemplate.TYPE2_ACCESSORY)
  3503.                     dropEquip.add(item);
  3504.                 else if(item.getTemplate().getType2() == ItemTemplate.TYPE2_OTHER)
  3505.                     dropItem.add(item);
  3506.             }
  3507.  
  3508.             checkAddItemToDrop(drop, dropWeapon, dropWeaponCount);
  3509.             checkAddItemToDrop(drop, dropEquip, dropEquipCount);
  3510.             checkAddItemToDrop(drop, dropItem, dropItemCount);
  3511.  
  3512.             // Dropping items, if present
  3513.             if(drop.isEmpty())
  3514.                 return;
  3515.  
  3516.             for(ItemInstance item : drop)
  3517.             {
  3518.                 if(item.isAugmented() && !Config.ALT_ALLOW_DROP_AUGMENTED)
  3519.                     item.setAugmentationId(0);
  3520.  
  3521.                 item = getInventory().removeItem(item);
  3522.                 Log.LogItem(this, Log.PvPDrop, item);
  3523.  
  3524.                 if(item.getEnchantLevel() > 0)
  3525.                     sendPacket(new SystemMessage2(SystemMsg.DROPPED__S1_S2).addNumber(item.getEnchantLevel()).addItemName(item.getItemId()));
  3526.                 else
  3527.                     sendPacket(new SystemMessage2(SystemMsg.YOU_HAVE_DROPPED_S1).addItemName(item.getItemId()));
  3528.  
  3529.                 if(killer.isPlayable() && ((Config.AUTO_LOOT && Config.AUTO_LOOT_PK) || this.isInFlyingTransform()))
  3530.                 {
  3531.                     killer.getPlayer().getInventory().addItem(item);
  3532.                     Log.LogItem(this, Log.Pickup, item);
  3533.  
  3534.                     killer.getPlayer().sendPacket(SystemMessage2.obtainItems(item));
  3535.                 }
  3536.                 else
  3537.                     item.dropToTheGround(this, Location.findAroundPosition(this, Config.KARMA_RANDOM_DROP_LOCATION_LIMIT));
  3538.             }
  3539.         }
  3540.         finally
  3541.         {
  3542.             getInventory().writeUnlock();
  3543.         }
  3544.     }
  3545.  
  3546.     @Override
  3547.     protected void onDeath(Creature killer)
  3548.     {
  3549.         //Check for active charm of luck for death penalty
  3550.         getDeathPenalty().checkCharmOfLuck();
  3551.  
  3552.         if(isInStoreMode())
  3553.             setPrivateStoreType(Player.STORE_PRIVATE_NONE);
  3554.         if(isProcessingRequest())
  3555.         {
  3556.             Request request = getRequest();
  3557.             if(isInTrade())
  3558.             {
  3559.                 Player parthner = request.getOtherPlayer(this);
  3560.                 sendPacket(SendTradeDone.FAIL);
  3561.                 parthner.sendPacket(SendTradeDone.FAIL);
  3562.             }
  3563.             request.cancel();
  3564.         }
  3565.  
  3566.         setAgathion(0);
  3567.  
  3568.         boolean checkPvp = true;
  3569.         if(Config.ALLOW_CURSED_WEAPONS)
  3570.         {
  3571.             if(isCursedWeaponEquipped())
  3572.             {
  3573.                 CursedWeaponsManager.getInstance().dropPlayer(this);
  3574.                 checkPvp = false;
  3575.             }
  3576.             else if(killer != null && killer.isPlayer() && killer.isCursedWeaponEquipped())
  3577.             {
  3578.                 CursedWeaponsManager.getInstance().increaseKills(((Player) killer).getCursedWeaponEquippedId());
  3579.                 checkPvp = false;
  3580.             }
  3581.         }
  3582.  
  3583.         if(checkPvp)
  3584.         {
  3585.             doPKPVPManage(killer);
  3586.  
  3587.             //altDeathPenalty(killer);
  3588.         }
  3589.  
  3590.         //And in the end of process notify death penalty that owner died :)
  3591.         getDeathPenalty().notifyDead(killer);
  3592.  
  3593.         setIncreasedForce(0);
  3594.  
  3595.         if(isInParty() && getParty().isInReflection() && getParty().getReflection() instanceof DimensionalRift)
  3596.             ((DimensionalRift) getParty().getReflection()).memberDead(this);
  3597.  
  3598.         stopWaterTask();
  3599.  
  3600.         if(!isSalvation() && isOnSiegeField() && isCharmOfCourage())
  3601.         {
  3602.             ask(new ConfirmDlg(SystemMsg.YOUR_CHARM_OF_COURAGE_IS_TRYING_TO_RESURRECT_YOU, 60000), new ReviveAnswerListener(this, 100, false));
  3603.             setCharmOfCourage(false);
  3604.         }
  3605.  
  3606.         if(getLevel() < 6)
  3607.         {
  3608.             Quest q = QuestManager.getQuest(255);
  3609.             if(q != null)
  3610.                 processQuestEvent(q.getName(), "CE30", null);
  3611.         }
  3612.  
  3613.         super.onDeath(killer);
  3614.     }
  3615.  
  3616.     public void restoreExp()
  3617.     {
  3618.         restoreExp(100.);
  3619.     }
  3620.  
  3621.     public void restoreExp(double percent)
  3622.     {
  3623.         if(percent == 0)
  3624.             return;
  3625.  
  3626.         int lostexp = 0;
  3627.  
  3628.         String lostexps = getVar("lostexp");
  3629.         if(lostexps != null)
  3630.         {
  3631.             lostexp = Integer.parseInt(lostexps);
  3632.             unsetVar("lostexp");
  3633.         }
  3634.  
  3635.         if(lostexp != 0)
  3636.             addExpAndSp((long) (lostexp * percent / 100), 0);
  3637.     }
  3638.  
  3639.     public void deathPenalty(Creature killer)
  3640.     {
  3641.         if(killer == null)
  3642.             return;
  3643.         final boolean atwar = killer.getPlayer() != null && atWarWith(killer.getPlayer());
  3644.  
  3645.         double deathPenaltyBonus = getDeathPenalty().getLevel() * Config.ALT_DEATH_PENALTY_C5_EXPERIENCE_PENALTY;
  3646.         if(deathPenaltyBonus < 2)
  3647.             deathPenaltyBonus = 1;
  3648.         else
  3649.             deathPenaltyBonus = deathPenaltyBonus / 2;
  3650.  
  3651.         // The death steal you some Exp: 10-40 lvl 8% loose
  3652.         double percentLost = 8.0;
  3653.  
  3654.         int level = getLevel();
  3655.         if(level >= 79)
  3656.             percentLost = 1.0;
  3657.         else if(level >= 78)
  3658.             percentLost = 1.5;
  3659.         else if(level >= 76)
  3660.             percentLost = 2.0;
  3661.         else if(level >= 40)
  3662.             percentLost = 4.0;
  3663.  
  3664.         if(Config.ALT_DEATH_PENALTY)
  3665.             percentLost = percentLost * Config.RATE_XP + _pkKills * Config.ALT_PK_DEATH_RATE;
  3666.  
  3667.         if(isFestivalParticipant() || atwar)
  3668.             percentLost = percentLost / 4.0;
  3669.  
  3670.         // Calculate the Experience loss
  3671.         int lostexp = (int) Math.round((Experience.LEVEL[level + 1] - Experience.LEVEL[level]) * percentLost / 100);
  3672.         lostexp *= deathPenaltyBonus;
  3673.  
  3674.         lostexp = (int) calcStat(Stats.EXP_LOST, lostexp, killer, null);
  3675.  
  3676.         // На зарегистрированной осаде нет потери опыта, на чужой осаде - как при обычной смерти от *моба*
  3677.         if(isOnSiegeField())
  3678.         {
  3679.             SiegeEvent<?, ?> siegeEvent = getEvent(SiegeEvent.class);
  3680.             if(siegeEvent != null)
  3681.                 lostexp = 0;
  3682.  
  3683.             if(siegeEvent != null)
  3684.             {
  3685.                 List<Effect> effect = getEffectList().getEffectsBySkillId(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
  3686.                 if(effect != null)
  3687.                 {
  3688.                     int syndromeLvl = effect.get(0).getSkill().getLevel();
  3689.                     if(syndromeLvl < 5)
  3690.                     {
  3691.                         getEffectList().stopEffect(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
  3692.                         Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, syndromeLvl + 1);
  3693.                         skill.getEffects(this, this, false, false);
  3694.                     }
  3695.                     else if(syndromeLvl == 5)
  3696.                     {
  3697.                         getEffectList().stopEffect(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME);
  3698.                         Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, 5);
  3699.                         skill.getEffects(this, this, false, false);
  3700.                     }
  3701.                 }
  3702.                 else
  3703.                 {
  3704.                     Skill skill = SkillTable.getInstance().getInfo(Skill.SKILL_BATTLEFIELD_DEATH_SYNDROME, 1);
  3705.                     if(skill != null)
  3706.                         skill.getEffects(this, this, false, false);
  3707.                 }
  3708.             }
  3709.         }
  3710.  
  3711.         long before = getExp();
  3712.         addExpAndSp(-lostexp, 0);
  3713.         long lost = before - getExp();
  3714.  
  3715.         if(lost > 0)
  3716.             setVar("lostexp", String.valueOf(lost), -1);
  3717.     }
  3718.  
  3719.     public void setRequest(Request transaction)
  3720.     {
  3721.         _request = transaction;
  3722.     }
  3723.  
  3724.     public Request getRequest()
  3725.     {
  3726.         return _request;
  3727.     }
  3728.  
  3729.     /**
  3730.      * Проверка, занят ли игрок для ответа на зарос
  3731.      *
  3732.      * @return true, если игрок не может ответить на запрос
  3733.      */
  3734.     public boolean isBusy()
  3735.     {
  3736.         return isProcessingRequest() || isOutOfControl() || isInOlympiadMode() || getTeam() != TeamType.NONE || isInStoreMode() || isInDuel() || getMessageRefusal() || isBlockAll() || isInvisible();
  3737.     }
  3738.  
  3739.     public boolean isProcessingRequest()
  3740.     {
  3741.         return _request != null && _request.isInProgress();
  3742.     }
  3743.  
  3744.     public boolean isInTrade()
  3745.     {
  3746.         return isProcessingRequest() && getRequest().isTypeOf(L2RequestType.TRADE);
  3747.     }
  3748.  
  3749.     public List<L2GameServerPacket> addVisibleObject(GameObject object, Creature dropper)
  3750.     {
  3751.         if(isLogoutStarted() || object == null || object.getObjectId() == getObjectId() || !object.isVisible())
  3752.             return Collections.emptyList();
  3753.  
  3754.         return object.addPacketList(this, dropper);
  3755.     }
  3756.  
  3757.     @Override
  3758.     public List<L2GameServerPacket> addPacketList(Player forPlayer, Creature dropper)
  3759.     {
  3760.         if(isInvisible() && forPlayer.getObjectId() != getObjectId())
  3761.             return Collections.emptyList();
  3762.  
  3763.         if(getPrivateStoreType() != STORE_PRIVATE_NONE && forPlayer.getVarB("notraders"))
  3764.             return Collections.emptyList();
  3765.  
  3766.         // Если это фэйк обсервера - не показывать.
  3767.         if(isInObserverMode() && getCurrentRegion() != getObserverRegion() && getObserverRegion() == forPlayer.getCurrentRegion())
  3768.             return Collections.emptyList();
  3769.  
  3770.         List<L2GameServerPacket> list = new ArrayList<L2GameServerPacket>();
  3771.         if(forPlayer.getObjectId() != getObjectId())
  3772.             list.add(isPolymorphed() ? new NpcInfoPoly(this) : new CharInfo(this));
  3773.  
  3774.         list.add(new ExBR_ExtraUserInfo(this));
  3775.  
  3776.         if(isSitting() && _sittingObject != null)
  3777.             list.add(new ChairSit(this, _sittingObject));
  3778.  
  3779.         if(getPrivateStoreType() != STORE_PRIVATE_NONE)
  3780.         {
  3781.             if(getPrivateStoreType() == STORE_PRIVATE_BUY)
  3782.                 list.add(new PrivateStoreMsgBuy(this));
  3783.             else if(getPrivateStoreType() == STORE_PRIVATE_SELL || getPrivateStoreType() == STORE_PRIVATE_SELL_PACKAGE)
  3784.                 list.add(new PrivateStoreMsgSell(this));
  3785.             else if(getPrivateStoreType() == STORE_PRIVATE_MANUFACTURE)
  3786.                 list.add(new RecipeShopMsg(this));
  3787.             if(forPlayer.isInZonePeace()) // Мирным торговцам не нужно посылать больше пакетов, для экономии траффика
  3788.                 return list;
  3789.         }
  3790.  
  3791.         if(isCastingNow())
  3792.         {
  3793.             Creature castingTarget = getCastingTarget();
  3794.             Skill castingSkill = getCastingSkill();
  3795.             long animationEndTime = getAnimationEndTime();
  3796.             if(castingSkill != null && castingTarget != null && castingTarget.isCreature() && getAnimationEndTime() > 0)
  3797.                 list.add(new MagicSkillUse(this, castingTarget, castingSkill.getId(), castingSkill.getLevel(), (int) (animationEndTime - System.currentTimeMillis()), 0));
  3798.         }
  3799.  
  3800.         if(isInCombat())
  3801.             list.add(new AutoAttackStart(getObjectId()));
  3802.  
  3803.         list.add(RelationChanged.update(forPlayer, this, forPlayer));
  3804.         DominionSiegeEvent dominionSiegeEvent = getEvent(DominionSiegeEvent.class);
  3805.         if(dominionSiegeEvent != null)
  3806.             list.add(new ExDominionWarStart(this));
  3807.  
  3808.         if(isInBoat())
  3809.             list.add(getBoat().getOnPacket(this, getInBoatPosition()));
  3810.         else
  3811.         {
  3812.             if(isMoving || isFollow)
  3813.                 list.add(movePacket());
  3814.         }
  3815.         return list;
  3816.     }
  3817.  
  3818.     public List<L2GameServerPacket> removeVisibleObject(GameObject object, List<L2GameServerPacket> list)
  3819.     {
  3820.         if(isLogoutStarted() || object == null || object.getObjectId() == getObjectId()) //FIXME || isTeleporting())
  3821.             return null;
  3822.  
  3823.         List<L2GameServerPacket> result = list == null ? object.deletePacketList() : list;
  3824.  
  3825.         getAI().notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
  3826.         return result;
  3827.     }
  3828.  
  3829.     private void levelSet(int levels)
  3830.     {
  3831.         if(levels > 0)
  3832.         {
  3833.             sendPacket(SystemMsg.YOUR_LEVEL_HAS_INCREASED);
  3834.             broadcastPacket(new SocialAction(getObjectId(), SocialAction.LEVEL_UP));
  3835.  
  3836.             setCurrentHpMp(getMaxHp(), getMaxMp());
  3837.             setCurrentCp(getMaxCp());
  3838.  
  3839.             Quest q = QuestManager.getQuest(255);
  3840.             if(q != null)
  3841.                 processQuestEvent(q.getName(), "CE40", null);
  3842.         }
  3843.         else if(levels < 0)
  3844.             if(Config.ALT_REMOVE_SKILLS_ON_DELEVEL)
  3845.                 checkSkills();
  3846.  
  3847.         // Recalculate the party level
  3848.         if(isInParty())
  3849.             getParty().recalculatePartyData();
  3850.  
  3851.         if(_clan != null)
  3852.             _clan.broadcastToOnlineMembers(new PledgeShowMemberListUpdate(this));
  3853.  
  3854.         if(_matchingRoom != null)
  3855.             _matchingRoom.broadcastPlayerUpdate(this);
  3856.  
  3857.         // Give Expertise skill of this level
  3858.         rewardSkills(true);
  3859.     }
  3860.  
  3861.     /**
  3862.      * Удаляет все скиллы, которые учатся на уровне большем, чем текущий+maxDiff
  3863.      */
  3864.     public void checkSkills()
  3865.     {
  3866.         for(Skill sk : getAllSkillsArray())
  3867.             SkillTreeTable.checkSkill(this, sk);
  3868.     }
  3869.  
  3870.     public void startTimers()
  3871.     {
  3872.         startAutoSaveTask();
  3873.         startBonusTask();
  3874.         getInventory().startTimers();
  3875.         resumeQuestTimers();
  3876.     }
  3877.  
  3878.     public void stopAllTimers()
  3879.     {
  3880.         setAgathion(0);
  3881.         stopWaterTask();
  3882.         stopBonusTask();
  3883.         stopHourlyTask();
  3884.         stopKickTask();
  3885.         stopVitalityTask();
  3886.         stopPcBangPointsTask();
  3887.         stopAutoSaveTask();
  3888.         stopRecomBonusTask(true);
  3889.         getInventory().stopAllTimers();
  3890.         stopQuestTimers();
  3891.         getNevitSystem().stopTasksOnLogout();
  3892.     }
  3893.  
  3894.     @Override
  3895.     public Summon getPet()
  3896.     {
  3897.         return _summon;
  3898.     }
  3899.  
  3900.     public void setPet(Summon summon)
  3901.     {
  3902.         boolean isPet = false;
  3903.         if(_summon != null && _summon.isPet())
  3904.             isPet = true;
  3905.         unsetVar("pet");
  3906.         _summon = summon;
  3907.         autoShot();
  3908.         if(summon == null)
  3909.         {
  3910.             if(isPet)
  3911.             {
  3912.                 if(isLogoutStarted())
  3913.                     if(getPetControlItem() != null)
  3914.                         setVar("pet", String.valueOf(getPetControlItem().getObjectId()), -1);
  3915.                 setPetControlItem(null);
  3916.             }
  3917.             getEffectList().stopEffect(4140);
  3918.         }
  3919.     }
  3920.  
  3921.     public void scheduleDelete()
  3922.     {
  3923.         long time = 0L;
  3924.  
  3925.         if(Config.SERVICES_ENABLE_NO_CARRIER)
  3926.             time = Config.SERVICES_NO_CARRIER_DEFAULT_TIME;
  3927.  
  3928.         scheduleDelete(time * 1000L);
  3929.     }
  3930.  
  3931.     /**
  3932.      * Удалит персонажа из мира через указанное время, если на момент истечения времени он не будет присоединен.
  3933.      * <br><br>
  3934.      * TODO: через минуту делать его неуязвимым.<br>
  3935.      * TODO: сделать привязку времени к контексту, для зон с лимитом времени оставлять в игре на все время в зоне.<br>
  3936.      * <br>
  3937.      *
  3938.      * @param time время в миллисекундах
  3939.      */
  3940.     public void scheduleDelete(long time)
  3941.     {
  3942.        
  3943.         if(isLogoutStarted() || isInOfflineMode())
  3944.             return;
  3945.         if(time == 0)
  3946.         {
  3947.             deleteMe();
  3948.             return;
  3949.         }
  3950.        
  3951.         broadcastCharInfo();
  3952.  
  3953.         ThreadPoolManager.getInstance().schedule(new RunnableImpl()
  3954.         {
  3955.             @Override
  3956.             public void runImpl() throws Exception
  3957.             {
  3958.                 if(!isConnected())
  3959.                 {
  3960.                     prepareToLogout();
  3961.                     deleteMe();
  3962.                 }
  3963.             }
  3964.         }, time);
  3965.     }
  3966.  
  3967.     @Override
  3968.     protected void onDelete()
  3969.     {
  3970.         super.onDelete();
  3971.  
  3972.         // Убираем фэйк в точке наблюдения
  3973.         WorldRegion observerRegion = getObserverRegion();
  3974.         if(observerRegion != null)
  3975.             observerRegion.removeObject(this);
  3976.  
  3977.         //Send friendlists to friends that this player has logged off
  3978.         _friendList.notifyFriends(false);
  3979.  
  3980.         bookmarks.clear();
  3981.  
  3982.         _inventory.clear();
  3983.         _warehouse.clear();
  3984.         _summon = null;
  3985.         _arrowItem = null;
  3986.         _fistsWeaponItem = null;
  3987.         _chars = null;
  3988.         _enchantScroll = null;
  3989.         _lastNpc = HardReferences.emptyRef();
  3990.         _observerRegion = null;
  3991.     }
  3992.  
  3993.     public void setTradeList(List<TradeItem> list)
  3994.     {
  3995.         _tradeList = list;
  3996.     }
  3997.  
  3998.     public List<TradeItem> getTradeList()
  3999.     {
  4000.         return _tradeList;
  4001.     }
  4002.  
  4003.     public String getSellStoreName()
  4004.     {
  4005.         return _sellStoreName;
  4006.     }
  4007.  
  4008.     public void setSellStoreName(String name)
  4009.     {
  4010.         _sellStoreName = Strings.stripToSingleLine(name);
  4011.     }
  4012.  
  4013.     public void setSellList(boolean packageSell, List<TradeItem> list)
  4014.     {
  4015.         if (packageSell)
  4016.             _packageSellList = list;
  4017.         else
  4018.             _sellList = list;
  4019.     }
  4020.  
  4021.     public List<TradeItem> getSellList()
  4022.     {
  4023.         return getSellList(_privatestore == STORE_PRIVATE_SELL_PACKAGE);
  4024.     }
  4025.  
  4026.     public List<TradeItem> getSellList(boolean packageSell)
  4027.     {
  4028.         return packageSell ? _packageSellList : _sellList;
  4029.     }
  4030.  
  4031.     public String getBuyStoreName()
  4032.     {
  4033.         return _buyStoreName;
  4034.     }
  4035.  
  4036.     public void setBuyStoreName(String name)
  4037.     {
  4038.         _buyStoreName = Strings.stripToSingleLine(name);
  4039.     }
  4040.  
  4041.     public void setBuyList(List<TradeItem> list)
  4042.     {
  4043.         _buyList = list;
  4044.     }
  4045.  
  4046.     public List<TradeItem> getBuyList()
  4047.     {
  4048.         return _buyList;
  4049.     }
  4050.  
  4051.     public void setManufactureName(String name)
  4052.     {
  4053.         _manufactureName = Strings.stripToSingleLine(name);
  4054.     }
  4055.  
  4056.     public String getManufactureName()
  4057.     {
  4058.         return _manufactureName;
  4059.     }
  4060.  
  4061.     public List<ManufactureItem> getCreateList()
  4062.     {
  4063.         return _createList;
  4064.     }
  4065.  
  4066.     public void setCreateList(List<ManufactureItem> list)
  4067.     {
  4068.         _createList = list;
  4069.     }
  4070.  
  4071.     public void setPrivateStoreType(final int type)
  4072.     {
  4073.         _privatestore = type;
  4074.         if(type != STORE_PRIVATE_NONE)
  4075.             setVar("storemode", String.valueOf(type), -1);
  4076.         else
  4077.             unsetVar("storemode");
  4078.     }
  4079.  
  4080.     public boolean isInStoreMode()
  4081.     {
  4082.         return _privatestore != STORE_PRIVATE_NONE;
  4083.     }
  4084.  
  4085.     public int getPrivateStoreType()
  4086.     {
  4087.         return _privatestore;
  4088.     }
  4089.  
  4090.     /**
  4091.      * Set the _clan object, _clanId, _clanLeader Flag and title of the L2Player.<BR><BR>
  4092.      *
  4093.      * @param clan the clat to set
  4094.      */
  4095.     public void setClan(Clan clan)
  4096.     {
  4097.         if(_clan != clan && _clan != null)
  4098.             unsetVar("canWhWithdraw");
  4099.  
  4100.         Clan oldClan = _clan;
  4101.         if(oldClan != null && clan == null)
  4102.             for(Skill skill : oldClan.getAllSkills())
  4103.                 removeSkill(skill, false);
  4104.  
  4105.         _clan = clan;
  4106.  
  4107.         if(clan == null)
  4108.         {
  4109.             _pledgeType = Clan.SUBUNIT_NONE;
  4110.             _pledgeClass = 0;
  4111.             _powerGrade = 0;
  4112.             _apprentice = 0;
  4113.             getInventory().validateItems();
  4114.             return;
  4115.         }
  4116.  
  4117.         if(!clan.isAnyMember(getObjectId()))
  4118.         {
  4119.             setClan(null);
  4120.             if(!isNoble())
  4121.                 setTitle("");
  4122.         }
  4123.     }
  4124.  
  4125.     @Override
  4126.     public Clan getClan()
  4127.     {
  4128.         return _clan;
  4129.     }
  4130.  
  4131.     public SubUnit getSubUnit()
  4132.     {
  4133.         return _clan == null ? null : _clan.getSubUnit(_pledgeType);
  4134.     }
  4135.  
  4136.     public ClanHall getClanHall()
  4137.     {
  4138.         int id = _clan != null ? _clan.getHasHideout() : 0;
  4139.         return ResidenceHolder.getInstance().getResidence(ClanHall.class, id);
  4140.     }
  4141.  
  4142.     public Castle getCastle()
  4143.     {
  4144.         int id = _clan != null ? _clan.getCastle() : 0;
  4145.         return ResidenceHolder.getInstance().getResidence(Castle.class, id);
  4146.     }
  4147.  
  4148.     public Fortress getFortress()
  4149.     {
  4150.         int id = _clan != null ? _clan.getHasFortress() : 0;
  4151.         return ResidenceHolder.getInstance().getResidence(Fortress.class, id);
  4152.     }
  4153.    
  4154.     public BookMarkList getBookmarks()
  4155.     {
  4156.         return bookmarks;
  4157.     }
  4158.     public Alliance getAlliance()
  4159.     {
  4160.         return _clan == null ? null : _clan.getAlliance();
  4161.     }
  4162.  
  4163.     public boolean isClanLeader()
  4164.     {
  4165.         return _clan != null && getObjectId() == _clan.getLeaderId();
  4166.     }
  4167.  
  4168.     public boolean isAllyLeader()
  4169.     {
  4170.         return getAlliance() != null && getAlliance().getLeader().getLeaderId() == getObjectId();
  4171.     }
  4172.  
  4173.     @Override
  4174.     public void reduceArrowCount()
  4175.     {
  4176.         sendPacket(SystemMsg.YOU_CAREFULLY_NOCK_AN_ARROW);
  4177.         if(Config.CONSUMABLE_ARROW)
  4178.         {
  4179.             if(!getInventory().destroyItemByObjectId(getInventory().getPaperdollObjectId(Inventory.PAPERDOLL_LHAND), 1L))
  4180.             {
  4181.                 getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, null);
  4182.                 _arrowItem = null;
  4183.             }
  4184.         }
  4185.     }
  4186.  
  4187.     /**
  4188.      * Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2Player then return True.
  4189.      */
  4190.     protected boolean checkAndEquipArrows()
  4191.     {
  4192.         // Check if nothing is equipped in left hand
  4193.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null)
  4194.         {
  4195.             ItemInstance activeWeapon = getActiveWeaponInstance();
  4196.             if(activeWeapon != null)
  4197.             {
  4198.                 if(activeWeapon.getItemType() == WeaponType.BOW)
  4199.                     _arrowItem = getInventory().findArrowForBow(activeWeapon.getTemplate());
  4200.                 else if(activeWeapon.getItemType() == WeaponType.CROSSBOW)
  4201.                     getInventory().findArrowForCrossbow(activeWeapon.getTemplate());
  4202.             }
  4203.  
  4204.             // Equip arrows needed in left hand
  4205.             if(_arrowItem != null)
  4206.                 getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, _arrowItem);
  4207.         }
  4208.         else
  4209.             // Get the L2ItemInstance of arrows equipped in left hand
  4210.             _arrowItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
  4211.  
  4212.         return _arrowItem != null;
  4213.     }
  4214.  
  4215.     public void setUptime(final long time)
  4216.     {
  4217.         _uptime = time;
  4218.     }
  4219.  
  4220.     public long getUptime()
  4221.     {
  4222.         return System.currentTimeMillis() - _uptime;
  4223.     }
  4224.  
  4225.     public boolean isInParty()
  4226.     {
  4227.         return _party != null;
  4228.     }
  4229.  
  4230.     public void setParty(final Party party)
  4231.     {
  4232.         _party = party;
  4233.     }
  4234.  
  4235.     public void joinParty(final Party party)
  4236.     {
  4237.         if(party != null)
  4238.             party.addPartyMember(this);
  4239.     }
  4240.  
  4241.     public void leaveParty()
  4242.     {
  4243.         if(isInParty())
  4244.             _party.removePartyMember(this, false);
  4245.     }
  4246.  
  4247.     public Party getParty()
  4248.     {
  4249.         return _party;
  4250.     }
  4251.  
  4252.     public void setLastPartyPosition(Location loc)
  4253.     {
  4254.         _lastPartyPosition = loc;
  4255.     }
  4256.  
  4257.     public Location getLastPartyPosition()
  4258.     {
  4259.         return _lastPartyPosition;
  4260.     }
  4261.  
  4262.     public boolean isGM()
  4263.     {
  4264.         return _playerAccess != null && _playerAccess.IsGM;
  4265.     }
  4266.  
  4267.     /**
  4268.      * Нигде не используется, но может пригодиться для БД
  4269.      */
  4270.     public void setAccessLevel(final int level)
  4271.     {
  4272.         _accessLevel = level;
  4273.     }
  4274.  
  4275.     /**
  4276.      * Нигде не используется, но может пригодиться для БД
  4277.      */
  4278.     @Override
  4279.     public int getAccessLevel()
  4280.     {
  4281.         return _accessLevel;
  4282.     }
  4283.  
  4284.     public void setPlayerAccess(final PlayerAccess pa)
  4285.     {
  4286.         if(pa != null)
  4287.             _playerAccess = pa;
  4288.         else
  4289.             _playerAccess = new PlayerAccess();
  4290.  
  4291.         setAccessLevel(isGM() || _playerAccess.Menu ? 100 : 0);
  4292.     }
  4293.  
  4294.     public PlayerAccess getPlayerAccess()
  4295.     {
  4296.         return _playerAccess;
  4297.     }
  4298.  
  4299.     @Override
  4300.     public double getLevelMod()
  4301.     {
  4302.         return (89. + getLevel()) / 100.0;
  4303.     }
  4304.  
  4305.     /**
  4306.      * Update Stats of the L2Player client side by sending Server->Client packet UserInfo/StatusUpdate to this L2Player and CharInfo/StatusUpdate to all players around (broadcast).<BR><BR>
  4307.      */
  4308.     @Override
  4309.     public void updateStats()
  4310.     {
  4311.         if(entering || isLogoutStarted())
  4312.             return;
  4313.  
  4314.         refreshOverloaded();
  4315.         refreshExpertisePenalty();
  4316.         super.updateStats();
  4317.     }
  4318.  
  4319.     @Override
  4320.     public void sendChanges()
  4321.     {
  4322.         if(entering || isLogoutStarted())
  4323.             return;
  4324.         super.sendChanges();
  4325.     }
  4326.  
  4327.     /**
  4328.      * Send a Server->Client StatusUpdate packet with Karma to the L2Player and all L2Player to inform (broadcast).
  4329.      */
  4330.     public void updateKarma(boolean flagChanged)
  4331.     {
  4332.         sendStatusUpdate(true, true, StatusUpdate.KARMA);
  4333.         if(flagChanged)
  4334.             broadcastRelationChanged();
  4335.     }
  4336.  
  4337.     public boolean isOnline()
  4338.     {
  4339.         return _isOnline;
  4340.     }
  4341.  
  4342.     public void setIsOnline(boolean isOnline)
  4343.     {
  4344.         _isOnline = isOnline;
  4345.     }
  4346.  
  4347.     public void setOnlineStatus(boolean isOnline)
  4348.     {
  4349.         _isOnline = isOnline;
  4350.         updateOnlineStatus();
  4351.     }
  4352.  
  4353.     private void updateOnlineStatus()
  4354.     {
  4355.         Connection con = null;
  4356.         PreparedStatement statement = null;
  4357.         try
  4358.         {
  4359.             con = DatabaseFactory.getInstance().getConnection();
  4360.             statement = con.prepareStatement("UPDATE characters SET online=?, lastAccess=? WHERE obj_id=?");
  4361.             statement.setInt(1, isOnline() && !isInOfflineMode() ? 1 : 0);
  4362.             statement.setLong(2, System.currentTimeMillis() / 1000L);
  4363.             statement.setInt(3, getObjectId());
  4364.             statement.execute();
  4365.         }
  4366.         catch(final Exception e)
  4367.         {
  4368.             _log.error("", e);
  4369.         }
  4370.         finally
  4371.         {
  4372.             DbUtils.closeQuietly(con, statement);
  4373.         }
  4374.     }
  4375.  
  4376.     /**
  4377.      * Decrease Karma of the L2Player and Send it StatusUpdate packet with Karma and PvP Flag (broadcast).
  4378.      */
  4379.     public void increaseKarma(final long add_karma)
  4380.     {
  4381.         boolean flagChanged = _karma == 0;
  4382.         long new_karma = _karma + add_karma;
  4383.  
  4384.         if(new_karma > Integer.MAX_VALUE)
  4385.             new_karma = Integer.MAX_VALUE;
  4386.  
  4387.         if(_karma == 0 && new_karma > 0)
  4388.         {
  4389.             /*if(_pvpFlag > 0)
  4390.             {
  4391.                 _pvpFlag = 0;
  4392.                 if(_PvPRegTask != null)
  4393.                 {
  4394.                     _PvPRegTask.cancel(true);
  4395.                     _PvPRegTask = null;
  4396.                 }
  4397.                 sendStatusUpdate(true, true, StatusUpdate.PVP_FLAG);
  4398.             }*/
  4399.  
  4400.             _karma = (int) new_karma;
  4401.         }
  4402.         else
  4403.             _karma = (int) new_karma;
  4404.  
  4405.         updateKarma(flagChanged);
  4406.     }
  4407.  
  4408.     /**
  4409.      * Decrease Karma of the L2Player and Send it StatusUpdate packet with Karma and PvP Flag (broadcast).
  4410.      */
  4411.     public void decreaseKarma(final int i)
  4412.     {
  4413.         boolean flagChanged = _karma > 0;
  4414.         _karma -= i;
  4415.         if(_karma <= 0)
  4416.         {
  4417.             _karma = 0;
  4418.             updateKarma(flagChanged);
  4419.         }
  4420.         else
  4421.             updateKarma(false);
  4422.     }
  4423.  
  4424.     /**
  4425.      * Create a new L2Player and add it in the characters table of the database.<BR><BR>
  4426.      * <p/>
  4427.      * <B><U> Actions</U> :</B><BR><BR>
  4428.      * <li>Create a new L2Player with an account name </li>
  4429.      * <li>Set the name, the Hair Style, the Hair Color and the Face type of the L2Player</li>
  4430.      * <li>Add the player in the characters table of the database</li><BR><BR>
  4431.      *
  4432.      * @param accountName The name of the L2Player
  4433.      * @param name      The name of the L2Player
  4434.      * @param hairStyle   The hair style Identifier of the L2Player
  4435.      * @param hairColor   The hair color Identifier of the L2Player
  4436.      * @param face      The face type Identifier of the L2Player
  4437.      * @return The L2Player added to the database or null
  4438.      */
  4439.     public static Player create(int classId, int sex, String accountName, final String name, final int hairStyle, final int hairColor, final int face)
  4440.     {
  4441.         PlayerTemplate template = CharTemplateTable.getInstance().getTemplate(classId, sex != 0);
  4442.  
  4443.         // Create a new L2Player with an account name
  4444.         Player player = new Player(IdFactory.getInstance().getNextId(), template, accountName);
  4445.  
  4446.         player.setName(name);
  4447.         player.setTitle("");
  4448.         player.setHairStyle(hairStyle);
  4449.         player.setHairColor(hairColor);
  4450.         player.setFace(face);
  4451.         player.setCreateTime(System.currentTimeMillis());
  4452.  
  4453.         // Add the player in the characters table of the database
  4454.         if(!CharacterDAO.getInstance().insert(player))
  4455.             return null;
  4456.  
  4457.         return player;
  4458.     }
  4459.  
  4460.     /**
  4461.      * Retrieve a L2Player from the characters table of the database and add it in _allObjects of the L2World
  4462.      *
  4463.      * @return The L2Player loaded from the database
  4464.      */
  4465.     public Player restore(final int objectId)
  4466.     {
  4467.         Player player = null;
  4468.         Connection con = null;
  4469.         Statement statement = null;
  4470.         Statement statement2 = null;
  4471.         PreparedStatement statement3 = null;
  4472.         ResultSet rset = null;
  4473.         ResultSet rset2 = null;
  4474.         ResultSet rset3 = null;
  4475.         try
  4476.         {
  4477.             // Retrieve the L2Player from the characters table of the database
  4478.             con = DatabaseFactory.getInstance().getConnection();
  4479.             statement = con.createStatement();
  4480.             statement2 = con.createStatement();
  4481.             rset = statement.executeQuery("SELECT * FROM `characters` WHERE `obj_Id`=" + objectId + " LIMIT 1");
  4482.             rset2 = statement2.executeQuery("SELECT `class_id` FROM `character_subclasses` WHERE `char_obj_id`=" + objectId + " AND `isBase`=1 LIMIT 1");
  4483.  
  4484.             if(rset.next() && rset2.next())
  4485.             {
  4486.                 final int classId = rset2.getInt("class_id");
  4487.                 final boolean female = rset.getInt("sex") == 1;
  4488.                 final PlayerTemplate template = CharTemplateTable.getInstance().getTemplate(classId, female);
  4489.  
  4490.                 player = new Player(objectId, template);
  4491.  
  4492.                 player.loadVariables();
  4493.                 player.loadInstanceReuses();
  4494.                 player.loadPremiumItemList();
  4495.                 player.bookmarks.setCapacity(rset.getInt("bookmarks"));
  4496.                 player.bookmarks.restore();
  4497.                 player._friendList.restore();
  4498.                 player._postFriends = CharacterPostFriendDAO.getInstance().select(player);
  4499.                 CharacterGroupReuseDAO.getInstance().select(player);
  4500.  
  4501.                 player.setBaseClass(classId);
  4502.                 player._login = rset.getString("account_name");
  4503.                 player.setName(rset.getString("char_name"));
  4504.  
  4505.                 player.setFace(rset.getInt("face"));
  4506.                 player.setHairStyle(rset.getInt("hairStyle"));
  4507.                 player.setHairColor(rset.getInt("hairColor"));
  4508.                 player.setHeading(0);
  4509.  
  4510.                 player.setKarma(rset.getInt("karma"));
  4511.                 player.setPvpKills(rset.getInt("pvpkills"));
  4512.                 player.setPkKills(rset.getInt("pkkills"));
  4513.                 player.setLeaveClanTime(rset.getLong("leaveclan") * 1000L);
  4514.                 if(player.getLeaveClanTime() > 0 && player.canJoinClan())
  4515.                     player.setLeaveClanTime(0);
  4516.                 player.setDeleteClanTime(rset.getLong("deleteclan") * 1000L);
  4517.                 if(player.getDeleteClanTime() > 0 && player.canCreateClan())
  4518.                     player.setDeleteClanTime(0);
  4519.  
  4520.                 player.setNoChannel(rset.getLong("nochannel") * 1000L);
  4521.                 if(player.getNoChannel() > 0 && player.getNoChannelRemained() < 0)
  4522.                     player.setNoChannel(0);
  4523.  
  4524.                 player.setOnlineTime(rset.getLong("onlinetime") * 1000L);
  4525.  
  4526.                 final int clanId = rset.getInt("clanid");
  4527.                 if(clanId > 0)
  4528.                 {
  4529.                     player.setClan(ClanTable.getInstance().getClan(clanId));
  4530.                     player.setPledgeType(rset.getInt("pledge_type"));
  4531.                     player.setPowerGrade(rset.getInt("pledge_rank"));
  4532.                     player.setLvlJoinedAcademy(rset.getInt("lvl_joined_academy"));
  4533.                     player.setApprentice(rset.getInt("apprentice"));
  4534.                 }
  4535.  
  4536.                 player.setCreateTime(rset.getLong("createtime") * 1000L);
  4537.                 player.setDeleteTimer(rset.getInt("deletetime"));
  4538.  
  4539.                 if(player.getVar("titlecolor") != null)
  4540.                     player.setTitleColor(Integer.decode("0x" + player.getVar("titlecolor")));
  4541.                 else if(player.getClan() != null && player.getClan().getLeaderId() == player.getObjectId())
  4542.                     player.setTitleColor(Config.CLANLEADER_NAME_COLOUR);
  4543.                 if(player.getVar("namecolor") == null)
  4544.                     if(player.isGM())
  4545.                         player.setNameColor(Config.GM_NAME_COLOUR);
  4546.                     else if(player.getClan() != null && player.getClan().getLeaderId() == player.getObjectId())
  4547.                         player.setNameColor(Config.CLANLEADER_NAME_COLOUR);
  4548.                     else
  4549.                         player.setNameColor(Config.NORMAL_NAME_COLOUR);
  4550.                 else
  4551.                     player.setNameColor(Integer.decode("0x" + player.getVar("namecolor")));
  4552.  
  4553.                 if(Config.AUTO_LOOT_INDIVIDUAL)
  4554.                 {
  4555.                     player._autoLoot = player.getVarB("AutoLoot", Config.AUTO_LOOT);
  4556.                     player.AutoLootHerbs = player.getVarB("AutoLootHerbs", Config.AUTO_LOOT_HERBS);
  4557.                 }
  4558.  
  4559.                 player.setFistsWeaponItem(player.findFistsWeaponItem(classId));
  4560.                 player.setUptime(System.currentTimeMillis());
  4561.                 player.setLastAccess(rset.getLong("lastAccess"));
  4562.  
  4563.                 player.setRecomHave(rset.getInt("rec_have"));
  4564.                 player.setRecomLeft(rset.getInt("rec_left"));
  4565.                 player.setRecomBonusTime(rset.getInt("rec_bonus_time"));
  4566.  
  4567.                 if(player.getVar("recLeftToday") != null)
  4568.                     player.setRecomLeftToday(Integer.parseInt(player.getVar("recLeftToday")));
  4569.                 else
  4570.                     player.setRecomLeftToday(0);
  4571.  
  4572.                 player.getNevitSystem().setPoints(rset.getInt("hunt_points"), rset.getInt("hunt_time"));
  4573.  
  4574.                 player.setKeyBindings(rset.getBytes("key_bindings"));
  4575.  
  4576.                 player.setFame(rset.getInt("fame"), null);
  4577.  
  4578.                 player.setFaction(FactionManager.Faction.getFactionByOrdinal(rset.getInt("faction")));
  4579.                 player.addFamePoints(rset.getInt("fame_points"));
  4580.  
  4581.                 player.restoreRecipeBook();
  4582.  
  4583.                 if(Config.ENABLE_OLYMPIAD)
  4584.                 {
  4585.                     player.setHero(Hero.getInstance().isHero(player.getObjectId()));
  4586.                     player.setNoble(Olympiad.isNoble(player.getObjectId()));
  4587.                 }
  4588.  
  4589.                 player.updatePledgeClass();
  4590.  
  4591.                 int reflection = 0;
  4592.                
  4593.                 if(player.isInJail())
  4594.                 {
  4595.                     // рандомный спаун по тюрьме
  4596.                     player.setXYZ(Rnd.get(-114936, -114136), Rnd.get(-249768, -248952), -2984);
  4597.  
  4598.                     player.sitDown(null);
  4599.                     player.block();
  4600.  
  4601.                     long period = player.getVarTimeToExpire("jailed");
  4602.  
  4603.                     if(period != -1)
  4604.                     {
  4605.                         player._unjailTask = ThreadPoolManager.getInstance().schedule(new UnJailTask(player), period);
  4606.                     }
  4607.                 }
  4608.                 else if(player.getVar("jailedFrom") != null)
  4609.                 {
  4610.                     String[] re = player.getVar("jailedFrom").split(";");
  4611.  
  4612.                     player.setXYZ(Integer.parseInt(re[0]), Integer.parseInt(re[1]), Integer.parseInt(re[2]));
  4613.                     player.setReflection(re.length > 3 ? Integer.parseInt(re[3]) : 0);
  4614.  
  4615.                     player.unsetVar("jailedFrom");
  4616.                 }
  4617.                 else
  4618.                 {
  4619.                     player.setXYZ(rset.getInt("x"), rset.getInt("y"), rset.getInt("z"));
  4620.                     String ref = player.getVar("reflection");
  4621.  
  4622.                     if(ref != null)
  4623.                     {
  4624.                         reflection = Integer.parseInt(ref);
  4625.                         if(reflection > 0) // не портаем назад из ГХ, парнаса, джайла
  4626.                         {
  4627.                             String back = player.getVar("backCoords");
  4628.                             if(back != null)
  4629.                             {
  4630.                                 player.setLoc(Location.parseLoc(back));
  4631.                                 player.unsetVar("backCoords");
  4632.                             }
  4633.                             reflection = 0;
  4634.                         }
  4635.                     }
  4636.                 }
  4637.  
  4638.                 player.setReflection(reflection);
  4639.  
  4640.                 EventHolder.getInstance().findEvent(player);
  4641.  
  4642.                 //TODO [G1ta0] запускать на входе
  4643.                 Quest.restoreQuestStates(player);
  4644.  
  4645.                 player.getInventory().restore();
  4646.  
  4647.                 restoreCharSubClasses(player);
  4648.  
  4649.                 // 4 очка в минуту оффлайна
  4650.                 player.setVitality(rset.getInt("vitality") + (int) ((System.currentTimeMillis() / 1000L - rset.getLong("lastAccess")) / 15.));
  4651.  
  4652.                 try
  4653.                 {
  4654.                     String var = player.getVar("ExpandInventory");
  4655.                     if(var != null)
  4656.                         player.setExpandInventory(Integer.parseInt(var));
  4657.                 }
  4658.                 catch(Exception e)
  4659.                 {
  4660.                     _log.error("", e);
  4661.                 }
  4662.  
  4663.                 try
  4664.                 {
  4665.                     String var = player.getVar("ExpandWarehouse");
  4666.                     if(var != null)
  4667.                         player.setExpandWarehouse(Integer.parseInt(var));
  4668.                 }
  4669.                 catch(Exception e)
  4670.                 {
  4671.                     _log.error("", e);
  4672.                 }
  4673.  
  4674.                 try
  4675.                 {
  4676.                     String var = player.getVar(NO_ANIMATION_OF_CAST_VAR);
  4677.                     if(var != null)
  4678.                         player.setNotShowBuffAnim(Boolean.parseBoolean(var));
  4679.                 }
  4680.                 catch(Exception e)
  4681.                 {
  4682.                     _log.error("", e);
  4683.                 }
  4684.  
  4685.                 try
  4686.                 {
  4687.                     String var = player.getVar(NO_TRADERS_VAR);
  4688.                     if(var != null)
  4689.                         player.setNotShowTraders(Boolean.parseBoolean(var));
  4690.                 }
  4691.                 catch(Exception e)
  4692.                 {
  4693.                     _log.error("", e);
  4694.                 }
  4695.  
  4696.                 try
  4697.                 {
  4698.                     String var = player.getVar("pet");
  4699.                     if(var != null)
  4700.                         player.setPetControlItem(Integer.parseInt(var));
  4701.                 }
  4702.                 catch(Exception e)
  4703.                 {
  4704.                     _log.error("", e);
  4705.                 }
  4706.  
  4707.                 statement3 = con.prepareStatement("SELECT obj_Id, char_name FROM characters WHERE account_name=? AND obj_Id!=?");
  4708.                 statement3.setString(1, player._login);
  4709.                 statement3.setInt(2, objectId);
  4710.                 rset3 = statement3.executeQuery();
  4711.                 while(rset3.next())
  4712.                 {
  4713.                     final Integer charId = rset3.getInt("obj_Id");
  4714.                     final String charName = rset3.getString("char_name");
  4715.                     player._chars.put(charId, charName);
  4716.                 }
  4717.  
  4718.                 DbUtils.close(statement3, rset3);
  4719.  
  4720.                 //if(!player.isGM())
  4721.                 {
  4722.                     LazyArrayList<Zone> zones = LazyArrayList.newInstance();
  4723.  
  4724.                     World.getZones(zones, player.getLoc(), player.getReflection());
  4725.  
  4726.                     if(!zones.isEmpty())
  4727.                         for(Zone zone : zones)
  4728.                             if(zone.getType() == ZoneType.no_restart)
  4729.                             {
  4730.                                 if(System.currentTimeMillis() / 1000L - player.getLastAccess() > zone.getRestartTime())
  4731.                                 {
  4732.                                     player.sendMessage(new CustomMessage("l2r.gameserver.network.clientpackets.EnterWorld.TeleportedReasonNoRestart", player));
  4733.                                     player.setLoc(TeleportUtils.getRestartLocation(player, RestartType.TO_VILLAGE));
  4734.                                 }
  4735.                             }
  4736.                             else if(zone.getType() == ZoneType.SIEGE)
  4737.                             {
  4738.                                 SiegeEvent<?, ?> siegeEvent = player.getEvent(SiegeEvent.class);
  4739.                                 if(siegeEvent != null)
  4740.                                     player.setLoc(siegeEvent.getEnterLoc(player));
  4741.                                 else
  4742.                                 {
  4743.                                     Residence r = ResidenceHolder.getInstance().getResidence(zone.getParams().getInteger("residence"));
  4744.                                     player.setLoc(r.getNotOwnerRestartPoint(player));
  4745.                                 }
  4746.                             }
  4747.  
  4748.                     LazyArrayList.recycle(zones);
  4749.  
  4750.                     if(DimensionalRiftManager.getInstance().checkIfInRiftZone(player.getLoc(), false))
  4751.                         player.setLoc(DimensionalRiftManager.getInstance().getRoom(0, 0).getTeleportCoords());
  4752.                 }
  4753.  
  4754.                 player.restoreBlockList();
  4755.                 player._macroses.restore();
  4756.  
  4757.                 //FIXME [VISTALL] нужно ли?
  4758.                 player.refreshExpertisePenalty();
  4759.                 player.refreshOverloaded();
  4760.  
  4761.                 player.getWarehouse().restore();
  4762.                 player.getFreight().restore();
  4763.  
  4764.                 player.restoreTradeList();
  4765.                 if(player.getVar("storemode") != null)
  4766.                 {
  4767.                     player.setPrivateStoreType(Integer.parseInt(player.getVar("storemode")));
  4768.                     player.setSitting(true);
  4769.                 }
  4770.  
  4771.                 player.updateKetraVarka();
  4772.                 player.updateRam();
  4773.                 player.checkRecom();
  4774.             }
  4775.        
  4776.         }
  4777.         catch(final Exception e)
  4778.         {
  4779.             _log.error("Could not restore char data!", e);
  4780.         }
  4781.         finally
  4782.         {
  4783.             DbUtils.closeQuietly(statement2, rset2);
  4784.             DbUtils.closeQuietly(statement3, rset3);
  4785.             DbUtils.closeQuietly(con, statement, rset);
  4786.         }
  4787.         player._account = new AccountReportDAO(player.getAccountName());
  4788.         return player;
  4789.     }
  4790.  
  4791.     private void loadPremiumItemList()
  4792.     {
  4793.         Connection con = null;
  4794.         PreparedStatement statement = null;
  4795.         ResultSet rs = null;
  4796.         try
  4797.         {
  4798.             con = DatabaseFactory.getInstance().getConnection();
  4799.             statement = con.prepareStatement("SELECT itemNum, itemId, itemCount, itemSender FROM character_premium_items WHERE charId=?");
  4800.             statement.setInt(1, getObjectId());
  4801.             rs = statement.executeQuery();
  4802.             while(rs.next())
  4803.             {
  4804.                 int itemNum = rs.getInt("itemNum");
  4805.                 int itemId = rs.getInt("itemId");
  4806.                 long itemCount = rs.getLong("itemCount");
  4807.                 String itemSender = rs.getString("itemSender");
  4808.                 PremiumItem item = new PremiumItem(itemId, itemCount, itemSender);
  4809.                 _premiumItems.put(itemNum, item);
  4810.             }
  4811.         }
  4812.         catch(Exception e)
  4813.         {
  4814.             _log.error("", e);
  4815.         }
  4816.         finally
  4817.         {
  4818.             DbUtils.closeQuietly(con, statement, rs);
  4819.         }
  4820.     }
  4821.  
  4822.     public void updatePremiumItem(int itemNum, long newcount)
  4823.     {
  4824.         Connection con = null;
  4825.         PreparedStatement statement = null;
  4826.         try
  4827.         {
  4828.             con = DatabaseFactory.getInstance().getConnection();
  4829.             statement = con.prepareStatement("UPDATE character_premium_items SET itemCount=? WHERE charId=? AND itemNum=?");
  4830.             statement.setLong(1, newcount);
  4831.             statement.setInt(2, getObjectId());
  4832.             statement.setInt(3, itemNum);
  4833.             statement.execute();
  4834.         }
  4835.         catch(Exception e)
  4836.         {
  4837.             _log.error("", e);
  4838.         }
  4839.         finally
  4840.         {
  4841.             DbUtils.closeQuietly(con, statement);
  4842.         }
  4843.     }
  4844.  
  4845.     public void deletePremiumItem(int itemNum)
  4846.     {
  4847.         Connection con = null;
  4848.         PreparedStatement statement = null;
  4849.         try
  4850.         {
  4851.             con = DatabaseFactory.getInstance().getConnection();
  4852.             statement = con.prepareStatement("DELETE FROM character_premium_items WHERE charId=? AND itemNum=?");
  4853.             statement.setInt(1, getObjectId());
  4854.             statement.setInt(2, itemNum);
  4855.             statement.execute();
  4856.         }
  4857.         catch(Exception e)
  4858.         {
  4859.             _log.error("", e);
  4860.         }
  4861.         finally
  4862.         {
  4863.             DbUtils.closeQuietly(con, statement);
  4864.         }
  4865.     }
  4866.  
  4867.     public Map<Integer, PremiumItem> getPremiumItemList()
  4868.     {
  4869.         return _premiumItems;
  4870.     }
  4871.  
  4872.     private LinkedList<Player> _killers = new LinkedList<Player>();
  4873.  
  4874.     public void giveAdenaForPvp(Player pk)
  4875.     {
  4876.         if (GveConfig.GveFarmCheckIP && pk.getNetConnection().getIpAddr().hashCode() == this.getNetConnection().getIpAddr().hashCode())
  4877.         {
  4878.             return;
  4879.         }
  4880.  
  4881.         if (_killers.contains(pk))
  4882.         {
  4883.             pk.sendMessage(new CustomMessage("l2r.gve.pvp.already", pk));
  4884.             return;
  4885.         }
  4886.  
  4887.         pk.sendMessage(new CustomMessage("l2r.gve.pvp.reward", pk));
  4888.         pk.addAdena(_price, true);
  4889.  
  4890.         // очки славы: забираем у убитого, отдаём убившему
  4891.         {
  4892.             int fame = _rank._pointsGain;
  4893.  
  4894.             takeFamePoints(_rank._pointsLoss);
  4895.  
  4896.             if(pk.getParty() != null)
  4897.             {
  4898.                 int perPerson = fame / pk.getParty().getMemberCount();
  4899.  
  4900.                 if(perPerson < 1) // как минимум по 1 очку
  4901.                 {
  4902.                     perPerson = 1;
  4903.                 }
  4904.  
  4905.                 for(Player p : pk.getParty().getPartyMembers())
  4906.                 {
  4907.                     p.addFamePoints(perPerson);
  4908.                 }
  4909.             }
  4910.             else
  4911.             {
  4912.                 pk.addFamePoints(fame);
  4913.             }
  4914.         }
  4915.  
  4916.         if (GveConfig.GveFarmClanPointsGive)
  4917.         {
  4918.             Clan clan = pk.getClan();
  4919.             if (clan != null && clan.getLevel() >= GveConfig.GveFarmClanPointsMinLvl)
  4920.             {
  4921.                 int points;
  4922.  
  4923.                 switch (GveConfig.GveFarmClanPointsStyle)
  4924.                 {
  4925.                     case 1:  // Давать кол-во отчков, равное цене чара
  4926.                     {
  4927.                         points = _price;
  4928.                         break;
  4929.                     }
  4930.  
  4931.                     case 2:    // Давать кол-во отчков, равное цене чара умноженное на [GveFarmClanPointsStyleMul]
  4932.                     {
  4933.                         points = Math.round(_price * GveConfig.GveFarmClanPointsStyleMul);
  4934.                         break;
  4935.                     }
  4936.  
  4937.                     default:
  4938.                     case 3: // Фиксированно
  4939.                     {
  4940.                         points = GveConfig.GveFarmClanPointsCount;
  4941.                         break;
  4942.                     }
  4943.                 }
  4944.  
  4945.                 clan.incReputation(points, false, "pvp");
  4946.             }
  4947.         }
  4948.  
  4949.         if (_killers.size() == GveConfig.GveFarmKillersCount)
  4950.         {
  4951.             _killers.removeLast();
  4952.         }
  4953.  
  4954.         _killers.addFirst(pk);
  4955.     }
  4956.  
  4957.     /**
  4958.      * Update L2Player stats in the characters table of the database.
  4959.      */
  4960.     public void store(boolean fast)
  4961.     {
  4962.         if(!_storeLock.tryLock())
  4963.             return;
  4964.  
  4965.         try
  4966.         {
  4967.             Connection con = null;
  4968.             PreparedStatement statement = null;
  4969.             try
  4970.             {
  4971.                 con = DatabaseFactory.getInstance().getConnection();
  4972.                 statement = con.prepareStatement(//
  4973.                         "UPDATE characters SET face=?,hairStyle=?,hairColor=?,x=?,y=?,z=?" + //
  4974.                                 ",karma=?,pvpkills=?,pkkills=?,rec_have=?,rec_left=?,rec_bonus_time=?,hunt_points=?,hunt_time=?,clanid=?,deletetime=?," + //
  4975.                                 "title=?,accesslevel=?,online=?,leaveclan=?,deleteclan=?,nochannel=?," + //
  4976.                                 "onlinetime=?,pledge_type=?,pledge_rank=?,lvl_joined_academy=?,apprentice=?,key_bindings=?,pcBangPoints=?,char_name=?,vitality=?,fame=?,bookmarks=?,faction=?,fame_points=? WHERE obj_Id=? LIMIT 1");
  4977.                 statement.setInt(1, getFace());
  4978.                 statement.setInt(2, getHairStyle());
  4979.                 statement.setInt(3, getHairColor());
  4980.                 if(_stablePoint == null) // если игрок находится в точке в которой его сохранять не стоит (например на виверне) то сохраняются последние координаты
  4981.                 {
  4982.                     statement.setInt(4, getX());
  4983.                     statement.setInt(5, getY());
  4984.                     statement.setInt(6, getZ());
  4985.                 }
  4986.                 else
  4987.                 {
  4988.                     statement.setInt(4, _stablePoint.x);
  4989.                     statement.setInt(5, _stablePoint.y);
  4990.                     statement.setInt(6, _stablePoint.z);
  4991.                 }
  4992.                 statement.setInt(7, getKarma());
  4993.                 statement.setInt(8, getPvpKills());
  4994.                 statement.setInt(9, getPkKills());
  4995.                 statement.setInt(10, getRecomHave());
  4996.                 statement.setInt(11, getRecomLeft());
  4997.                 statement.setInt(12, getRecomBonusTime());
  4998.                 statement.setInt(13, getNevitSystem().getPoints());
  4999.                 statement.setInt(14, getNevitSystem().getTime());
  5000.                 statement.setInt(15, getClanId());
  5001.                 statement.setInt(16, getDeleteTimer());
  5002.                 statement.setString(17, _title);
  5003.                 statement.setInt(18, _accessLevel);
  5004.                 statement.setInt(19, isOnline() && !isInOfflineMode() ? 1 : 0);
  5005.                 statement.setLong(20, getLeaveClanTime() / 1000L);
  5006.                 statement.setLong(21, getDeleteClanTime() / 1000L);
  5007.                 statement.setLong(22, _NoChannel > 0 ? getNoChannelRemained() / 1000 : _NoChannel);
  5008.                 statement.setInt(23, (int) (_onlineBeginTime > 0 ? (_onlineTime + System.currentTimeMillis() - _onlineBeginTime) / 1000L : _onlineTime / 1000L));
  5009.                 statement.setInt(24, getPledgeType());
  5010.                 statement.setInt(25, getPowerGrade());
  5011.                 statement.setInt(26, getLvlJoinedAcademy());
  5012.                 statement.setInt(27, getApprentice());
  5013.                 statement.setBytes(28, getKeyBindings());
  5014.                 statement.setInt(29, getFamePoints());
  5015.                 statement.setString(30, getName());
  5016.                 statement.setInt(31, (int) getVitality());
  5017.                 statement.setInt(32, getFame());
  5018.                 statement.setInt(33, bookmarks.getCapacity());
  5019.                 statement.setInt(34, getFaction().ordinal());
  5020.                 statement.setInt(35, famePoints);
  5021.                 statement.setInt(36, getObjectId());
  5022.  
  5023.                 statement.executeUpdate();
  5024.                 GameStats.increaseUpdatePlayerBase();
  5025.  
  5026.                 if(!fast)
  5027.                 {
  5028.                     EffectsDAO.getInstance().insert(this);
  5029.                     CharacterGroupReuseDAO.getInstance().insert(this);
  5030.                     storeDisableSkills();
  5031.                     storeBlockList();
  5032.                 }
  5033.  
  5034.                 storeCharSubClasses();
  5035.                 bookmarks.store();
  5036.             }
  5037.             catch(Exception e)
  5038.             {
  5039.                 _log.error("Could not store char data: " + this + "!", e);
  5040.             }
  5041.             finally
  5042.             {
  5043.                 DbUtils.closeQuietly(con, statement);
  5044.             }
  5045.         }
  5046.         finally
  5047.         {
  5048.             _storeLock.unlock();
  5049.         }
  5050.     }
  5051.  
  5052.     /**
  5053.      * 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.
  5054.      *
  5055.      * @return The L2Skill replaced or null if just added a new L2Skill
  5056.      */
  5057.     public Skill addSkill(final Skill newSkill, final boolean store)
  5058.     {
  5059.         if(newSkill == null)
  5060.             return null;
  5061.  
  5062.         // Add a skill to the L2Player _skills and its Func objects to the calculator set of the L2Player
  5063.         Skill oldSkill = super.addSkill(newSkill);
  5064.  
  5065.         if(newSkill.equals(oldSkill))
  5066.             return oldSkill;
  5067.  
  5068.         // Add or update a L2Player skill in the character_skills table of the database
  5069.         if(store)
  5070.             storeSkill(newSkill, oldSkill);
  5071.  
  5072.         return oldSkill;
  5073.     }
  5074.  
  5075.     public Skill removeSkill(Skill skill, boolean fromDB)
  5076.     {
  5077.         if(skill == null)
  5078.             return null;
  5079.         return removeSkill(skill.getId(), fromDB);
  5080.     }
  5081.  
  5082.     /**
  5083.      * 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.
  5084.      *
  5085.      * @return The L2Skill removed
  5086.      */
  5087.     public Skill removeSkill(int id, boolean fromDB)
  5088.     {
  5089.         // Remove a skill from the L2Character and its Func objects from calculator set of the L2Character
  5090.         Skill oldSkill = super.removeSkillById(id);
  5091.  
  5092.         if(!fromDB)
  5093.             return oldSkill;
  5094.  
  5095.         if(oldSkill != null)
  5096.         {
  5097.             Connection con = null;
  5098.             PreparedStatement statement = null;
  5099.             try
  5100.             {
  5101.                 // Remove or update a L2Player skill from the character_skills table of the database
  5102.                 con = DatabaseFactory.getInstance().getConnection();
  5103.                 statement = con.prepareStatement("DELETE FROM character_skills WHERE skill_id=? AND char_obj_id=? AND class_index=?");
  5104.                 statement.setInt(1, oldSkill.getId());
  5105.                 statement.setInt(2, getObjectId());
  5106.                 statement.setInt(3, getActiveClassId());
  5107.                 statement.execute();
  5108.             }
  5109.             catch(final Exception e)
  5110.             {
  5111.                 _log.error("Could not delete skill!", e);
  5112.             }
  5113.             finally
  5114.             {
  5115.                 DbUtils.closeQuietly(con, statement);
  5116.             }
  5117.         }
  5118.  
  5119.         return oldSkill;
  5120.     }
  5121.  
  5122.     /**
  5123.      * Add or update a L2Player skill in the character_skills table of the database.
  5124.      */
  5125.     private void storeSkill(final Skill newSkill, final Skill oldSkill)
  5126.     {
  5127.         if(newSkill == null) // вообще-то невозможно
  5128.         {
  5129.             _log.warn("could not store new skill. its NULL");
  5130.             return;
  5131.         }
  5132.  
  5133.         Connection con = null;
  5134.         PreparedStatement statement = null;
  5135.         try
  5136.         {
  5137.             con = DatabaseFactory.getInstance().getConnection();
  5138.  
  5139.             statement = con.prepareStatement("REPLACE INTO character_skills (char_obj_id,skill_id,skill_level,class_index) values(?,?,?,?)");
  5140.             statement.setInt(1, getObjectId());
  5141.             statement.setInt(2, newSkill.getId());
  5142.             statement.setInt(3, newSkill.getLevel());
  5143.             statement.setInt(4, getActiveClassId());
  5144.             statement.execute();
  5145.         }
  5146.         catch(final Exception e)
  5147.         {
  5148.             _log.error("Error could not store skills!", e);
  5149.         }
  5150.         finally
  5151.         {
  5152.             DbUtils.closeQuietly(con, statement);
  5153.         }
  5154.     }
  5155.    
  5156.     public final void illegalAction(final String msg, final Integer jail_items)
  5157.     {
  5158.         Log.IllegalPlayerAction(this, msg, jail_items);
  5159.     }
  5160.    
  5161.     public final String toFullString()
  5162.     {
  5163.         final StringBuffer sb = new StringBuffer(160);
  5164.         sb.append("Player '").append(getName()).append("' [oid=").append(getObjectId()).append(", account='").append(getAccountName()).append(", ip=").append(getIP()).append("']");
  5165.         return sb.toString();
  5166.     }
  5167.    
  5168.     /**
  5169.      * Retrieve from the database all skills of this L2Player and add them to _skills.
  5170.      */
  5171.     private void restoreSkills()
  5172.     {
  5173.         Connection con = null;
  5174.         PreparedStatement statement = null;
  5175.         ResultSet rset = null;
  5176.         try
  5177.         {
  5178.             // Retrieve all skills of this L2Player from the database
  5179.             // Send the SQL query : SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? to the database
  5180.             con = DatabaseFactory.getInstance().getConnection();
  5181.             statement = con.prepareStatement("SELECT skill_id,skill_level FROM character_skills WHERE char_obj_id=? AND class_index=?");
  5182.             statement.setInt(1, getObjectId());
  5183.             statement.setInt(2, getActiveClassId());
  5184.             rset = statement.executeQuery();
  5185.  
  5186.             // Go though the recordset of this SQL query
  5187.             while(rset.next())
  5188.             {
  5189.                 final int id = rset.getInt("skill_id");
  5190.                 final int level = rset.getInt("skill_level");
  5191.  
  5192.                 // Create a L2Skill object for each record
  5193.                 final Skill skill = SkillTable.getInstance().getInfo(id, level);
  5194.  
  5195.                 if(skill == null)
  5196.                     continue;
  5197.  
  5198.                 // Remove skill if not possible
  5199.                 if(!isGM() && !SkillAcquireHolder.getInstance().isSkillPossible(this, skill))
  5200.                 {
  5201.                     int ReturnSP = SkillTreeTable.getInstance().getSkillCost(this, skill);
  5202.                     if(ReturnSP == Integer.MAX_VALUE || ReturnSP < 0)
  5203.                     {
  5204.                             ReturnSP = 0;
  5205.                     }
  5206.                     removeSkill(skill, true);
  5207.                     removeSkillFromShortCut(skill.getId());
  5208.                     if(ReturnSP > 0)
  5209.                     {
  5210.                             setSp(getSp() + ReturnSP);
  5211.                     }
  5212.                     illegalAction("has skill " + skill.getName() + " / ReturnSP: " + ReturnSP, 0);
  5213.                     continue;
  5214.                 }
  5215.  
  5216.                 super.addSkill(skill);
  5217.             }
  5218.  
  5219.             // Restore noble skills
  5220.             if(isNoble())
  5221.                 updateNobleSkills();
  5222.  
  5223.             // Restore Hero skills at main class only
  5224.             if(_hero && getBaseClassId() == getActiveClassId())
  5225.                 Hero.addSkills(this);
  5226.  
  5227.             // Restore clan skills
  5228.             if (_clan != null)
  5229.             {
  5230.                 _clan.addSkillsQuietly(this);
  5231.  
  5232.                 // Restore clan leader siege skills
  5233.                 if(_clan.getLeaderId() == getObjectId() && _clan.getLevel() >= 5)
  5234.                     SiegeUtils.addSiegeSkills(this);
  5235.             }
  5236.  
  5237.             // Give dwarven craft skill
  5238.             if(getActiveClassId() >= 53 && getActiveClassId() <= 57 || getActiveClassId() == 117 || getActiveClassId() == 118)
  5239.                 super.addSkill(SkillTable.getInstance().getInfo(1321, 1));
  5240.  
  5241.             super.addSkill(SkillTable.getInstance().getInfo(1322, 1));
  5242.  
  5243.             if(Config.UNSTUCK_SKILL && getSkillLevel(1050) < 0)
  5244.                 super.addSkill(SkillTable.getInstance().getInfo(2099, 1));
  5245.         }
  5246.         catch(final Exception e)
  5247.         {
  5248.             _log.warn("Could not restore skills for player objId: " + getObjectId());
  5249.             _log.error("", e);
  5250.         }
  5251.         finally
  5252.         {
  5253.             DbUtils.closeQuietly(con, statement, rset);
  5254.         }
  5255.     }
  5256.  
  5257.     public void storeDisableSkills()
  5258.     {
  5259.         Connection con = null;
  5260.         Statement statement = null;
  5261.         try
  5262.         {
  5263.             con = DatabaseFactory.getInstance().getConnection();
  5264.             statement = con.createStatement();
  5265.             statement.executeUpdate("DELETE FROM character_skills_save WHERE char_obj_id = " + getObjectId() + " AND class_index=" + getActiveClassId() + " AND `end_time` < " + System.currentTimeMillis());
  5266.  
  5267.             if(_skillReuses.isEmpty())
  5268.                 return;
  5269.  
  5270.             SqlBatch b = new SqlBatch("REPLACE INTO `character_skills_save` (`char_obj_id`,`skill_id`,`skill_level`,`class_index`,`end_time`,`reuse_delay_org`) VALUES");
  5271.             synchronized(_skillReuses)
  5272.             {
  5273.                 StringBuilder sb;
  5274.                 for(TimeStamp timeStamp : _skillReuses.values())
  5275.                 {
  5276.                     if(timeStamp.hasNotPassed())
  5277.                     {
  5278.                         sb = new StringBuilder("(");
  5279.                         sb.append(getObjectId()).append(",");
  5280.                         sb.append(timeStamp.getId()).append(",");
  5281.                         sb.append(timeStamp.getLevel()).append(",");
  5282.                         sb.append(getActiveClassId()).append(",");
  5283.                         sb.append(timeStamp.getEndTime()).append(",");
  5284.                         sb.append(timeStamp.getReuseBasic()).append(")");
  5285.                         b.write(sb.toString());
  5286.                     }
  5287.                 }
  5288.             }
  5289.             if(!b.isEmpty())
  5290.                 statement.executeUpdate(b.close());
  5291.         }
  5292.         catch(final Exception e)
  5293.         {
  5294.             _log.warn("Could not store disable skills data: " + e);
  5295.         }
  5296.         finally
  5297.         {
  5298.             DbUtils.closeQuietly(con, statement);
  5299.         }
  5300.     }
  5301.  
  5302.     public void restoreDisableSkills()
  5303.     {
  5304.         _skillReuses.clear();
  5305.  
  5306.         Connection con = null;
  5307.         Statement statement = null;
  5308.         ResultSet rset = null;
  5309.         try
  5310.         {
  5311.             con = DatabaseFactory.getInstance().getConnection();
  5312.             statement = con.createStatement();
  5313.             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());
  5314.             while(rset.next())
  5315.             {
  5316.                 int skillId = rset.getInt("skill_id");
  5317.                 int skillLevel = rset.getInt("skill_level");
  5318.                 long endTime = rset.getLong("end_time");
  5319.                 long rDelayOrg = rset.getLong("reuse_delay_org");
  5320.                 long curTime = System.currentTimeMillis();
  5321.  
  5322.                 Skill skill = SkillTable.getInstance().getInfo(skillId, skillLevel);
  5323.  
  5324.                 if(skill != null && endTime - curTime > 500)
  5325.                     _skillReuses.put(skill.hashCode(), new TimeStamp(skill, endTime, rDelayOrg));
  5326.             }
  5327.             DbUtils.close(statement);
  5328.  
  5329.             statement = con.createStatement();
  5330.             statement.executeUpdate("DELETE FROM character_skills_save WHERE char_obj_id = " + getObjectId() + " AND class_index=" + getActiveClassId() + " AND `end_time` < " + System.currentTimeMillis());
  5331.         }
  5332.         catch(Exception e)
  5333.         {
  5334.             _log.error("Could not restore active skills data!", e);
  5335.         }
  5336.         finally
  5337.         {
  5338.             DbUtils.closeQuietly(con, statement, rset);
  5339.         }
  5340.     }
  5341.  
  5342.     /**
  5343.      * Retrieve from the database all Henna of this L2Player, add them to _henna and calculate stats of the L2Player.<BR><BR>
  5344.      */
  5345.     private void restoreHenna()
  5346.     {
  5347.         Connection con = null;
  5348.         PreparedStatement statement = null;
  5349.         ResultSet rset = null;
  5350.         try
  5351.         {
  5352.             con = DatabaseFactory.getInstance().getConnection();
  5353.             statement = con.prepareStatement("select slot, symbol_id from character_hennas where char_obj_id=? AND class_index=?");
  5354.             statement.setInt(1, getObjectId());
  5355.             statement.setInt(2, getActiveClassId());
  5356.             rset = statement.executeQuery();
  5357.  
  5358.             for(int i = 0; i < 3; i++)
  5359.                 _henna[i] = null;
  5360.  
  5361.             while(rset.next())
  5362.             {
  5363.                 final int slot = rset.getInt("slot");
  5364.                 if(slot < 1 || slot > 3)
  5365.                     continue;
  5366.  
  5367.                 final int symbol_id = rset.getInt("symbol_id");
  5368.  
  5369.                 if(symbol_id != 0)
  5370.                 {
  5371.                     final Henna tpl = HennaHolder.getInstance().getHenna(symbol_id);
  5372.                     if(tpl != null)
  5373.                     {
  5374.                         _henna[slot - 1] = tpl;
  5375.                     }
  5376.                 }
  5377.             }
  5378.         }
  5379.         catch(final Exception e)
  5380.         {
  5381.             _log.warn("could not restore henna: " + e);
  5382.         }
  5383.         finally
  5384.         {
  5385.             DbUtils.closeQuietly(con, statement, rset);
  5386.         }
  5387.  
  5388.         // Calculate Henna modifiers of this L2Player
  5389.         recalcHennaStats();
  5390.  
  5391.     }
  5392.  
  5393.     public int getHennaEmptySlots()
  5394.     {
  5395.         int totalSlots = 1 + getClassId().level();
  5396.         for(int i = 0; i < 3; i++)
  5397.             if(_henna[i] != null)
  5398.                 totalSlots--;
  5399.  
  5400.         if(totalSlots <= 0)
  5401.             return 0;
  5402.  
  5403.         return totalSlots;
  5404.  
  5405.     }
  5406.  
  5407.     /**
  5408.      * 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><BR>
  5409.      */
  5410.     public boolean removeHenna(int slot)
  5411.     {
  5412.         if(slot < 1 || slot > 3)
  5413.             return false;
  5414.  
  5415.         slot--;
  5416.  
  5417.         if(_henna[slot] == null)
  5418.             return false;
  5419.  
  5420.         final Henna henna = _henna[slot];
  5421.         final int dyeID = henna.getDyeId();
  5422.  
  5423.         _henna[slot] = null;
  5424.  
  5425.         Connection con = null;
  5426.         PreparedStatement statement = null;
  5427.         try
  5428.         {
  5429.             con = DatabaseFactory.getInstance().getConnection();
  5430.             statement = con.prepareStatement("DELETE FROM character_hennas where char_obj_id=? and slot=? and class_index=?");
  5431.             statement.setInt(1, getObjectId());
  5432.             statement.setInt(2, slot + 1);
  5433.             statement.setInt(3, getActiveClassId());
  5434.             statement.execute();
  5435.         }
  5436.         catch(final Exception e)
  5437.         {
  5438.             _log.warn("could not remove char henna: " + e, e);
  5439.         }
  5440.         finally
  5441.         {
  5442.             DbUtils.closeQuietly(con, statement);
  5443.         }
  5444.  
  5445.         // Calculate Henna modifiers of this L2Player
  5446.         recalcHennaStats();
  5447.  
  5448.         // Send Server->Client HennaInfo packet to this L2Player
  5449.         sendPacket(new HennaInfo(this));
  5450.         // Send Server->Client UserInfo packet to this L2Player
  5451.         sendUserInfo(true);
  5452.  
  5453.         // Add the recovered dyes to the player's inventory and notify them.
  5454.         ItemFunctions.addItem(this, dyeID, henna.getDrawCount() / 2, true);
  5455.  
  5456.         return true;
  5457.     }
  5458.  
  5459.     /**
  5460.      * 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><BR>
  5461.      *
  5462.      * @param henna L2Henna для добавления
  5463.      */
  5464.     public boolean addHenna(Henna henna)
  5465.     {
  5466.         if(getHennaEmptySlots() == 0)
  5467.         {
  5468.             sendPacket(SystemMsg.NO_SLOT_EXISTS_TO_DRAW_THE_SYMBOL);
  5469.             return false;
  5470.         }
  5471.  
  5472.         // int slot = 0;
  5473.         for(int i = 0; i < 3; i++)
  5474.             if(_henna[i] == null)
  5475.             {
  5476.                 _henna[i] = henna;
  5477.  
  5478.                 // Calculate Henna modifiers of this L2Player
  5479.                 recalcHennaStats();
  5480.  
  5481.                 Connection con = null;
  5482.                 PreparedStatement statement = null;
  5483.                 try
  5484.                 {
  5485.                     con = DatabaseFactory.getInstance().getConnection();
  5486.                     statement = con.prepareStatement("INSERT INTO `character_hennas` (char_obj_id, symbol_id, slot, class_index) VALUES (?,?,?,?)");
  5487.                     statement.setInt(1, getObjectId());
  5488.                     statement.setInt(2, henna.getSymbolId());
  5489.                     statement.setInt(3, i + 1);
  5490.                     statement.setInt(4, getActiveClassId());
  5491.                     statement.execute();
  5492.                 }
  5493.                 catch(Exception e)
  5494.                 {
  5495.                     _log.warn("could not save char henna: " + e);
  5496.                 }
  5497.                 finally
  5498.                 {
  5499.                     DbUtils.closeQuietly(con, statement);
  5500.                 }
  5501.  
  5502.                 sendPacket(new HennaInfo(this));
  5503.                 sendUserInfo(true);
  5504.  
  5505.                 return true;
  5506.             }
  5507.  
  5508.         return false;
  5509.     }
  5510.  
  5511.     /**
  5512.      * Calculate Henna modifiers of this L2Player.
  5513.      */
  5514.     private void recalcHennaStats()
  5515.     {
  5516.         _hennaINT = 0;
  5517.         _hennaSTR = 0;
  5518.         _hennaCON = 0;
  5519.         _hennaMEN = 0;
  5520.         _hennaWIT = 0;
  5521.         _hennaDEX = 0;
  5522.  
  5523.         for(int i = 0; i < 3; i++)
  5524.         {
  5525.             Henna henna = _henna[i];
  5526.             if(henna == null)
  5527.                 continue;
  5528.             if(!henna.isForThisClass(this))
  5529.                 continue;
  5530.  
  5531.             _hennaINT += henna.getStatINT();
  5532.             _hennaSTR += henna.getStatSTR();
  5533.             _hennaMEN += henna.getStatMEN();
  5534.             _hennaCON += henna.getStatCON();
  5535.             _hennaWIT += henna.getStatWIT();
  5536.             _hennaDEX += henna.getStatDEX();
  5537.         }
  5538.  
  5539.         if(_hennaINT > Config.HENNA_STATS)
  5540.             _hennaINT = Config.HENNA_STATS;
  5541.         if(_hennaSTR > Config.HENNA_STATS)
  5542.             _hennaSTR = Config.HENNA_STATS;
  5543.         if(_hennaMEN > Config.HENNA_STATS)
  5544.             _hennaMEN = Config.HENNA_STATS;
  5545.         if(_hennaCON > Config.HENNA_STATS)
  5546.             _hennaCON = Config.HENNA_STATS;
  5547.         if(_hennaWIT > Config.HENNA_STATS)
  5548.             _hennaWIT = Config.HENNA_STATS;
  5549.         if(_hennaDEX > Config.HENNA_STATS)
  5550.             _hennaDEX = Config.HENNA_STATS;
  5551.     }
  5552.  
  5553.     /**
  5554.      * @param slot id слота у перса
  5555.      * @return the Henna of this L2Player corresponding to the selected slot.<BR><BR>
  5556.      */
  5557.     public Henna getHenna(final int slot)
  5558.     {
  5559.         if(slot < 1 || slot > 3)
  5560.             return null;
  5561.         return _henna[slot - 1];
  5562.     }
  5563.  
  5564.     public int getHennaStatINT()
  5565.     {
  5566.         return _hennaINT;
  5567.     }
  5568.  
  5569.     public int getHennaStatSTR()
  5570.     {
  5571.         return _hennaSTR;
  5572.     }
  5573.  
  5574.     public int getHennaStatCON()
  5575.     {
  5576.         return _hennaCON;
  5577.     }
  5578.  
  5579.     public int getHennaStatMEN()
  5580.     {
  5581.         return _hennaMEN;
  5582.     }
  5583.  
  5584.     public int getHennaStatWIT()
  5585.     {
  5586.         return _hennaWIT;
  5587.     }
  5588.  
  5589.     public int getHennaStatDEX()
  5590.     {
  5591.         return _hennaDEX;
  5592.     }
  5593.  
  5594.     @Override
  5595.     public boolean consumeItem(int itemConsumeId, long itemCount)
  5596.     {
  5597.         if(getInventory().destroyItemByItemId(itemConsumeId, itemCount))
  5598.         {
  5599.             sendPacket(SystemMessage2.removeItems(itemConsumeId, itemCount));
  5600.             return true;
  5601.         }
  5602.         return false;
  5603.     }
  5604.  
  5605.     @Override
  5606.     public boolean consumeItemMp(int itemId, int mp)
  5607.     {
  5608.         for(ItemInstance item : getInventory().getPaperdollItems())
  5609.             if(item != null && item.getItemId() == itemId)
  5610.             {
  5611.                 final int newMp = item.getLifeTime() - mp;
  5612.                 if(newMp >= 0)
  5613.                 {
  5614.                     item.setLifeTime(newMp);
  5615.                     sendPacket(new InventoryUpdate().addModifiedItem(item));
  5616.                     return true;
  5617.                 }
  5618.                 break;
  5619.             }
  5620.         return false;
  5621.     }
  5622.  
  5623.     /**
  5624.      * @return True if the L2Player is a Mage.<BR><BR>
  5625.      */
  5626.     @Override
  5627.     public boolean isMageClass()
  5628.     {
  5629.         return _template.baseMAtk > 3;
  5630.     }
  5631.  
  5632.     public boolean isMounted()
  5633.     {
  5634.         return _mountNpcId > 0;
  5635.     }
  5636.  
  5637.     public final boolean isRiding()
  5638.     {
  5639.         return _riding;
  5640.     }
  5641.  
  5642.     public final void setRiding(boolean mode)
  5643.     {
  5644.         _riding = mode;
  5645.     }
  5646.  
  5647.     /**
  5648.      * Проверяет, можно ли приземлиться в этой зоне.
  5649.      *
  5650.      * @return можно ли приземлится
  5651.      */
  5652.     public boolean checkLandingState()
  5653.     {
  5654.         if(isInZone(ZoneType.no_landing))
  5655.             return false;
  5656.  
  5657.         SiegeEvent<?, ?> siege = getEvent(SiegeEvent.class);
  5658.         if(siege != null)
  5659.         {
  5660.             Residence unit = siege.getResidence();
  5661.             return unit != null && getClan() != null && isClanLeader() && (getClan().getCastle() == unit.getId() || getClan().getHasFortress() == unit.getId());
  5662.         }
  5663.  
  5664.         return true;
  5665.     }
  5666.  
  5667.     public void setMount(int npcId, int obj_id, int level)
  5668.     {
  5669.         if(isCursedWeaponEquipped())
  5670.             return;
  5671.  
  5672.         switch(npcId)
  5673.         {
  5674.             case 0: // Dismount
  5675.                 setFlying(false);
  5676.                 setRiding(false);
  5677.                 if(getTransformation() > 0)
  5678.                     setTransformation(0);
  5679.                 removeSkillById(Skill.SKILL_STRIDER_ASSAULT);
  5680.                 removeSkillById(Skill.SKILL_WYVERN_BREATH);
  5681.                 getEffectList().stopEffect(Skill.SKILL_HINDER_STRIDER);
  5682.                 break;
  5683.             case PetDataTable.STRIDER_WIND_ID:
  5684.             case PetDataTable.STRIDER_STAR_ID:
  5685.             case PetDataTable.STRIDER_TWILIGHT_ID:
  5686.             case PetDataTable.RED_STRIDER_WIND_ID:
  5687.             case PetDataTable.RED_STRIDER_STAR_ID:
  5688.             case PetDataTable.RED_STRIDER_TWILIGHT_ID:
  5689.             case PetDataTable.GUARDIANS_STRIDER_ID:
  5690.                 setRiding(true);
  5691.                 if(isNoble())
  5692.                     addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_STRIDER_ASSAULT, 1), false);
  5693.                 break;
  5694.             case PetDataTable.WYVERN_ID:
  5695.                 setFlying(true);
  5696.                 setLoc(getLoc().changeZ(32));
  5697.                 addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_WYVERN_BREATH, 1), false);
  5698.                 break;
  5699.             case PetDataTable.WGREAT_WOLF_ID:
  5700.             case PetDataTable.FENRIR_WOLF_ID:
  5701.             case PetDataTable.WFENRIR_WOLF_ID:
  5702.                 setRiding(true);
  5703.                 break;
  5704.         }
  5705.  
  5706.         if(npcId > 0)
  5707.             unEquipWeapon();
  5708.  
  5709.         _mountNpcId = npcId;
  5710.         _mountObjId = obj_id;
  5711.         _mountLevel = level;
  5712.  
  5713.         broadcastUserInfo(true); // нужно послать пакет перед Ride для корректного снятия оружия с заточкой
  5714.         broadcastPacket(new Ride(this));
  5715.         broadcastUserInfo(true); // нужно послать пакет после Ride для корректного отображения скорости
  5716.  
  5717.         sendPacket(new SkillList(this));
  5718.     }
  5719.  
  5720.     public void unEquipWeapon()
  5721.     {
  5722.         ItemInstance wpn = getSecondaryWeaponInstance();
  5723.         if(wpn != null)
  5724.         {
  5725.             sendDisarmMessage(wpn);
  5726.             getInventory().unEquipItem(wpn);
  5727.         }
  5728.  
  5729.         wpn = getActiveWeaponInstance();
  5730.         if(wpn != null)
  5731.         {
  5732.             sendDisarmMessage(wpn);
  5733.             getInventory().unEquipItem(wpn);
  5734.         }
  5735.  
  5736.         abortAttack(true, true);
  5737.         abortCast(true, true);
  5738.     }
  5739.  
  5740.     /*
  5741.     @Override
  5742.     public double getMovementSpeedMultiplier()
  5743.     {
  5744.         int template_speed = _template.baseRunSpd;
  5745.         if(isMounted())
  5746.         {
  5747.             L2PetData petData = PetDataTable.getInstance().getInfo(_mountNpcId, _mountLevel);
  5748.             if(petData != null)
  5749.                 template_speed = petData.getSpeed();
  5750.         }
  5751.         return getRunSpeed() * 1f / template_speed;
  5752.     }
  5753.      */
  5754.  
  5755.     @Override
  5756.     public int getSpeed(int baseSpeed)
  5757.     {
  5758.         if(isMounted())
  5759.         {
  5760.             PetData petData = PetDataTable.getInstance().getInfo(_mountNpcId, _mountLevel);
  5761.             int speed = 187;
  5762.             if(petData != null)
  5763.                 speed = petData.getSpeed();
  5764.             double mod = 1.;
  5765.             int level = getLevel();
  5766.             if(_mountLevel > level && level - _mountLevel > 10)
  5767.                 mod = 0.5; // Штраф на разницу уровней между игроком и петом
  5768.             baseSpeed = (int) (mod * speed);
  5769.         }
  5770.         return super.getSpeed(baseSpeed);
  5771.     }
  5772.  
  5773.     private int _mountNpcId;
  5774.     private int _mountObjId;
  5775.     private int _mountLevel;
  5776.  
  5777.     public int getMountNpcId()
  5778.     {
  5779.         return _mountNpcId;
  5780.     }
  5781.  
  5782.     public int getMountObjId()
  5783.     {
  5784.         return _mountObjId;
  5785.     }
  5786.  
  5787.     public int getMountLevel()
  5788.     {
  5789.         return _mountLevel;
  5790.     }
  5791.  
  5792.     public void sendDisarmMessage(ItemInstance wpn)
  5793.     {
  5794.         if(wpn.getEnchantLevel() > 0)
  5795.         {
  5796.             SystemMessage2 sm = new SystemMessage2(SystemMsg.EQUIPMENT_OF__S1_S2_HAS_BEEN_REMOVED);
  5797.             sm.addNumber(wpn.getEnchantLevel());
  5798.             sm.addItemName(wpn.getItemId());
  5799.             sendPacket(sm);
  5800.         }
  5801.         else
  5802.         {
  5803.             SystemMessage2 sm = new SystemMessage2(SystemMsg.S1__HAS_BEEN_DISARMED);
  5804.             sm.addItemName(wpn.getItemId());
  5805.             sendPacket(sm);
  5806.         }
  5807.     }
  5808.  
  5809.     /**
  5810.      * Устанавливает тип используемого склада.
  5811.      *
  5812.      * @param type тип склада:<BR>
  5813.      *             <ul>
  5814.      *             <li>WarehouseType.PRIVATE
  5815.      *             <li>WarehouseType.CLAN
  5816.      *             <li>WarehouseType.CASTLE
  5817.      *             </ul>
  5818.      */
  5819.     public void setUsingWarehouseType(final WarehouseType type)
  5820.     {
  5821.         _usingWHType = type;
  5822.     }
  5823.  
  5824.     /**
  5825.      * Устанавливает тип используемого склада.
  5826.      *
  5827.      * @param type тип склада:<BR>
  5828.      *             <ul>
  5829.      *             <li>WarehouseType.PRIVATE
  5830.      *             <li>WarehouseType.CLAN
  5831.      *             <li>WarehouseType.CASTLE
  5832.      *             </ul>
  5833.      */
  5834.     public WarehouseType getUsingWarehouseType()
  5835.     {
  5836.         return _usingWHType;
  5837.     }
  5838.  
  5839.     public Collection<EffectCubic> getCubics()
  5840.     {
  5841.         return _cubics == null ? Collections.<EffectCubic>emptyList() : _cubics.values();
  5842.     }
  5843.  
  5844.     public void addCubic(EffectCubic cubic)
  5845.     {
  5846.         if(_cubics == null)
  5847.             _cubics = new ConcurrentHashMap<Integer, EffectCubic>(3);
  5848.         _cubics.put(cubic.getId(), cubic);
  5849.     }
  5850.  
  5851.     public void removeCubic(int id)
  5852.     {
  5853.         if(_cubics != null)
  5854.             _cubics.remove(id);
  5855.     }
  5856.  
  5857.     public EffectCubic getCubic(int id)
  5858.     {
  5859.         return _cubics == null ? null : _cubics.get(id);
  5860.     }
  5861.  
  5862.     @Override
  5863.     public String toString()
  5864.     {
  5865.         return getName() + "[" + getObjectId() + "]";
  5866.     }
  5867.  
  5868.     /**
  5869.      * @return the modifier corresponding to the Enchant Effect of the Active Weapon (Min : 127).<BR><BR>
  5870.      */
  5871.     public int getEnchantEffect()
  5872.     {
  5873.         final ItemInstance wpn = getActiveWeaponInstance();
  5874.  
  5875.         if(wpn == null)
  5876.             return 0;
  5877.  
  5878.         return Math.min(127, wpn.getEnchantLevel());
  5879.     }
  5880.  
  5881.     /**
  5882.      * Set the _lastFolkNpc of the L2Player corresponding to the last Folk witch one the player talked.<BR><BR>
  5883.      */
  5884.     public void setLastNpc(final NpcInstance npc)
  5885.     {
  5886.         if(npc == null)
  5887.             _lastNpc = HardReferences.emptyRef();
  5888.         else
  5889.             _lastNpc = npc.getRef();
  5890.     }
  5891.  
  5892.     /**
  5893.      * @return the _lastFolkNpc of the L2Player corresponding to the last Folk witch one the player talked.<BR><BR>
  5894.      */
  5895.     public NpcInstance getLastNpc()
  5896.     {
  5897.         return _lastNpc.get();
  5898.     }
  5899.  
  5900.     public void setMultisell(MultiSellListContainer multisell)
  5901.     {
  5902.         _multisell = multisell;
  5903.     }
  5904.  
  5905.     public MultiSellListContainer getMultisell()
  5906.     {
  5907.         return _multisell;
  5908.     }
  5909.  
  5910.     /**
  5911.      * @return True if L2Player is a participant in the Festival of Darkness.<BR><BR>
  5912.      */
  5913.     public boolean isFestivalParticipant()
  5914.     {
  5915.         return getReflection() instanceof DarknessFestival;
  5916.     }
  5917.  
  5918.     @Override
  5919.     public boolean unChargeShots(boolean spirit)
  5920.     {
  5921.         ItemInstance weapon = getActiveWeaponInstance();
  5922.         if(weapon == null)
  5923.             return false;
  5924.  
  5925.         if(spirit)
  5926.             weapon.setChargedSpiritshot(ItemInstance.CHARGED_NONE);
  5927.         else
  5928.             weapon.setChargedSoulshot(ItemInstance.CHARGED_NONE);
  5929.  
  5930.         autoShot();
  5931.         return true;
  5932.     }
  5933.  
  5934.     public boolean unChargeFishShot()
  5935.     {
  5936.         ItemInstance weapon = getActiveWeaponInstance();
  5937.         if(weapon == null)
  5938.             return false;
  5939.         weapon.setChargedFishshot(false);
  5940.         autoShot();
  5941.         return true;
  5942.     }
  5943.  
  5944.     public void autoShot()
  5945.     {
  5946.         for(Integer shotId : _activeSoulShots)
  5947.         {
  5948.             ItemInstance item = getInventory().getItemByItemId(shotId);
  5949.             if(item == null)
  5950.             {
  5951.                 removeAutoSoulShot(shotId);
  5952.                 continue;
  5953.             }
  5954.             IItemHandler handler = item.getTemplate().getHandler();
  5955.             if(handler == null)
  5956.                 continue;
  5957.             handler.useItem(this, item, false);
  5958.         }
  5959.     }
  5960.  
  5961.     public boolean getChargedFishShot()
  5962.     {
  5963.         ItemInstance weapon = getActiveWeaponInstance();
  5964.         return weapon != null && weapon.getChargedFishshot();
  5965.     }
  5966.  
  5967.     @Override
  5968.     public boolean getChargedSoulShot()
  5969.     {
  5970.         ItemInstance weapon = getActiveWeaponInstance();
  5971.         return weapon != null && weapon.getChargedSoulshot() == ItemInstance.CHARGED_SOULSHOT;
  5972.     }
  5973.  
  5974.     @Override
  5975.     public int getChargedSpiritShot()
  5976.     {
  5977.         ItemInstance weapon = getActiveWeaponInstance();
  5978.         if(weapon == null)
  5979.             return 0;
  5980.         return weapon.getChargedSpiritshot();
  5981.     }
  5982.  
  5983.     public void addAutoSoulShot(Integer itemId)
  5984.     {
  5985.         _activeSoulShots.add(itemId);
  5986.     }
  5987.  
  5988.     public void removeAutoSoulShot(Integer itemId)
  5989.     {
  5990.         _activeSoulShots.remove(itemId);
  5991.     }
  5992.  
  5993.     public Set<Integer> getAutoSoulShot()
  5994.     {
  5995.         return _activeSoulShots;
  5996.     }
  5997.  
  5998.     public void setInvisibleType(InvisibleType vis)
  5999.     {
  6000.         _invisibleType = vis;
  6001.     }
  6002.  
  6003.     @Override
  6004.     public InvisibleType getInvisibleType()
  6005.     {
  6006.         return _invisibleType;
  6007.     }
  6008.  
  6009.     public int getClanPrivileges()
  6010.     {
  6011.         if(_clan == null)
  6012.             return 0;
  6013.         if(isClanLeader())
  6014.             return Clan.CP_ALL;
  6015.         if(_powerGrade < 1 || _powerGrade > 9)
  6016.             return 0;
  6017.         RankPrivs privs = _clan.getRankPrivs(_powerGrade);
  6018.         if(privs != null)
  6019.             return privs.getPrivs();
  6020.         return 0;
  6021.     }
  6022.  
  6023.     public void teleToClosestTown()
  6024.     {
  6025.         teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_VILLAGE), ReflectionManager.DEFAULT);
  6026.     }
  6027.  
  6028.     public void teleToCastle()
  6029.     {
  6030.         teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_CASTLE), ReflectionManager.DEFAULT);
  6031.     }
  6032.  
  6033.     public void teleToFortress()
  6034.     {
  6035.         teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_FORTRESS), ReflectionManager.DEFAULT);
  6036.     }
  6037.  
  6038.     public void teleToClanhall()
  6039.     {
  6040.         teleToLocation(TeleportUtils.getRestartLocation(this, RestartType.TO_CLANHALL), ReflectionManager.DEFAULT);
  6041.     }
  6042.  
  6043.     @Override
  6044.     public void sendMessage(CustomMessage message)
  6045.     {
  6046.         sendMessage(message.toString());
  6047.     }
  6048.  
  6049.     @Override
  6050.     public void teleToLocation(int x, int y, int z, int refId)
  6051.     {
  6052.         if(isDeleted())
  6053.             return;
  6054.  
  6055.         super.teleToLocation(x, y, z, refId);
  6056.     }
  6057.  
  6058.     @Override
  6059.     public boolean onTeleported()
  6060.     {
  6061.         if (!super.onTeleported())
  6062.             return false;
  6063.  
  6064.         if(isFakeDeath())
  6065.             breakFakeDeath();
  6066.  
  6067.         if(isInBoat())
  6068.             setLoc(getBoat().getLoc());
  6069.  
  6070.         // 15 секунд после телепорта на персонажа не агрятся мобы
  6071.         setNonAggroTime(System.currentTimeMillis() + Config.NONAGGRO_TIME_ONTELEPORT);
  6072.  
  6073.         spawnMe();
  6074.  
  6075.         setLastClientPosition(getLoc());
  6076.         setLastServerPosition(getLoc());
  6077.  
  6078.         if(isPendingRevive())
  6079.             doRevive();
  6080.  
  6081.         sendActionFailed();
  6082.  
  6083.         getAI().notifyEvent(CtrlEvent.EVT_TELEPORTED);
  6084.  
  6085.         if(isLockedTarget() && getTarget() != null)
  6086.             sendPacket(new MyTargetSelected(getTarget().getObjectId(), 0));
  6087.  
  6088.         sendUserInfo(true);
  6089.         if(getPet() != null)
  6090.             getPet().teleportToOwner();
  6091.  
  6092.         return true;
  6093.     }
  6094.  
  6095.     public boolean enterObserverMode(Location loc)
  6096.     {
  6097.         WorldRegion observerRegion = World.getRegion(loc);
  6098.         if(observerRegion == null)
  6099.             return false;
  6100.         if (!_observerMode.compareAndSet(OBSERVER_NONE, OBSERVER_STARTING))
  6101.             return false;
  6102.  
  6103.         setTarget(null);
  6104.         stopMove();
  6105.         sitDown(null);
  6106.         setFlying(true);
  6107.  
  6108.         // Очищаем все видимые обьекты
  6109.         World.removeObjectsFromPlayer(this);
  6110.  
  6111.         setObserverRegion(observerRegion);
  6112.  
  6113.         // Отображаем надпись над головой
  6114.         broadcastCharInfo();
  6115.  
  6116.         // Переходим в режим обсервинга
  6117.         sendPacket(new ObserverStart(loc));
  6118.  
  6119.         return true;
  6120.     }
  6121.  
  6122.     public void appearObserverMode()
  6123.     {
  6124.         if (!_observerMode.compareAndSet(OBSERVER_STARTING, OBSERVER_STARTED))
  6125.                 return;
  6126.  
  6127.         WorldRegion currentRegion = getCurrentRegion();
  6128.         WorldRegion observerRegion = getObserverRegion();
  6129.  
  6130.         // Добавляем фэйк в точку наблюдения
  6131.         if(!observerRegion.equals(currentRegion))
  6132.             observerRegion.addObject(this);
  6133.  
  6134.         World.showObjectsToPlayer(this);
  6135.  
  6136.         OlympiadGame game = getOlympiadObserveGame();
  6137.         if(game != null)
  6138.         {
  6139.             game.addSpectator(this);
  6140.             game.broadcastInfo(null, this, true);
  6141.         }
  6142.     }
  6143.  
  6144.     public void leaveObserverMode()
  6145.     {
  6146.         if (!_observerMode.compareAndSet(OBSERVER_STARTED, OBSERVER_LEAVING))
  6147.             return;
  6148.  
  6149.         WorldRegion currentRegion = getCurrentRegion();
  6150.         WorldRegion observerRegion = getObserverRegion();
  6151.  
  6152.         // Убираем фэйк в точке наблюдения
  6153.         if(!observerRegion.equals(currentRegion))
  6154.             observerRegion.removeObject(this);
  6155.  
  6156.         // Очищаем все видимые обьекты
  6157.         World.removeObjectsFromPlayer(this);
  6158.  
  6159.         setObserverRegion(null);
  6160.  
  6161.         setTarget(null);
  6162.         stopMove();
  6163.  
  6164.         // Выходим из режима обсервинга
  6165.         sendPacket(new ObserverEnd(getLoc()));
  6166.     }
  6167.  
  6168.     public void returnFromObserverMode()
  6169.     {
  6170.         if (!_observerMode.compareAndSet(OBSERVER_LEAVING, OBSERVER_NONE))
  6171.             return;
  6172.  
  6173.         // Нужно при телепорте с более высокой точки на более низкую, иначе наносится вред от "падения"
  6174.         setLastClientPosition(null);
  6175.         setLastServerPosition(null);
  6176.  
  6177.         unblock();
  6178.         standUp();
  6179.         setFlying(false);
  6180.  
  6181.         broadcastCharInfo();
  6182.  
  6183.         World.showObjectsToPlayer(this);
  6184.     }
  6185.  
  6186.     public void enterOlympiadObserverMode(Location loc, OlympiadGame game, Reflection reflect)
  6187.     {
  6188.         WorldRegion observerRegion = World.getRegion(loc);
  6189.         WorldRegion oldObserver = getObserverRegion();
  6190.         if(observerRegion == null)
  6191.             return;
  6192.  
  6193.         OlympiadGame oldGame = getOlympiadObserveGame();
  6194.         if (!_observerMode.compareAndSet(oldGame != null ? OBSERVER_STARTED : OBSERVER_NONE, OBSERVER_STARTING))
  6195.             return;
  6196.  
  6197.         setTarget(null);
  6198.         stopMove();
  6199.  
  6200.         // Очищаем все видимые обьекты
  6201.         World.removeObjectsFromPlayer(this);
  6202.         setObserverRegion(observerRegion);
  6203.  
  6204.         if(oldGame != null)
  6205.         {
  6206.             if(isInObserverMode() && oldObserver != null)
  6207.             {
  6208.                 oldObserver.removeObject(this);
  6209.             }
  6210.  
  6211.             if(isInObserverMode() && oldObserver != null)
  6212.                 oldObserver.removeObject(this);
  6213.  
  6214.             oldGame.removeSpectator(this);
  6215.             sendPacket(ExOlympiadMatchEnd.STATIC);
  6216.         }
  6217.         else
  6218.         {
  6219.             block();
  6220.  
  6221.             // Отображаем надпись над головой
  6222.             broadcastCharInfo();
  6223.  
  6224.             // Меняем интерфейс
  6225.             sendPacket(new ExOlympiadMode(3));
  6226.         }
  6227.  
  6228.         setOlympiadObserveGame(game);
  6229.  
  6230.         // "Телепортируемся"
  6231.         setReflection(reflect);
  6232.         sendPacket(new TeleportToLocation(this, loc));
  6233.     }
  6234.  
  6235.     public void leaveOlympiadObserverMode(boolean removeFromGame)
  6236.     {
  6237.         OlympiadGame game = getOlympiadObserveGame();
  6238.         if (game == null)
  6239.             return;
  6240.         if (!_observerMode.compareAndSet(OBSERVER_STARTED, OBSERVER_LEAVING))
  6241.             return;
  6242.  
  6243.         if (removeFromGame)
  6244.             game.removeSpectator(this);
  6245.         setOlympiadObserveGame(null);
  6246.  
  6247.         WorldRegion currentRegion = getCurrentRegion();
  6248.         WorldRegion observerRegion = getObserverRegion();
  6249.  
  6250.         // Убираем фэйк в точке наблюдения
  6251.         if(observerRegion != null && currentRegion != null && !observerRegion.equals(currentRegion))
  6252.             observerRegion.removeObject(this);
  6253.  
  6254.         // Очищаем все видимые обьекты
  6255.         World.removeObjectsFromPlayer(this);
  6256.  
  6257.         setObserverRegion(null);
  6258.  
  6259.         setTarget(null);
  6260.         stopMove();
  6261.  
  6262.         // Меняем интерфейс
  6263.         sendPacket(new ExOlympiadMode(0));
  6264.         sendPacket(ExOlympiadMatchEnd.STATIC);
  6265.  
  6266.         setReflection(ReflectionManager.DEFAULT);
  6267.         // "Телепортируемся"
  6268.         sendPacket(new TeleportToLocation(this, getLoc()));
  6269.     }
  6270.  
  6271.     public void setOlympiadSide(final int i)
  6272.     {
  6273.         _olympiadSide = i;
  6274.     }
  6275.  
  6276.     public int getOlympiadSide()
  6277.     {
  6278.         return _olympiadSide;
  6279.     }
  6280.  
  6281.     @Override
  6282.     public boolean isInObserverMode()
  6283.     {
  6284.         return _observerMode.get() > 0;
  6285.     }
  6286.  
  6287.     public int getObserverMode()
  6288.     {
  6289.         return _observerMode.get();
  6290.     }
  6291.  
  6292.     public WorldRegion getObserverRegion()
  6293.     {
  6294.         return _observerRegion;
  6295.     }
  6296.  
  6297.     public void setObserverRegion(WorldRegion region)
  6298.     {
  6299.         _observerRegion = region;
  6300.     }
  6301.  
  6302.     public int getTeleMode()
  6303.     {
  6304.         return _telemode;
  6305.     }
  6306.  
  6307.     public void setTeleMode(final int mode)
  6308.     {
  6309.         _telemode = mode;
  6310.     }
  6311.  
  6312.     public void setLoto(final int i, final int val)
  6313.     {
  6314.         _loto[i] = val;
  6315.     }
  6316.  
  6317.     public int getLoto(final int i)
  6318.     {
  6319.         return _loto[i];
  6320.     }
  6321.  
  6322.     public void setRace(final int i, final int val)
  6323.     {
  6324.         _race[i] = val;
  6325.     }
  6326.  
  6327.     public int getRace(final int i)
  6328.     {
  6329.         return _race[i];
  6330.     }
  6331.  
  6332.     public boolean getMessageRefusal()
  6333.     {
  6334.         return _messageRefusal;
  6335.     }
  6336.  
  6337.     public void setMessageRefusal(final boolean mode)
  6338.     {
  6339.         _messageRefusal = mode;
  6340.     }
  6341.  
  6342.     public void setTradeRefusal(final boolean mode)
  6343.     {
  6344.         _tradeRefusal = mode;
  6345.     }
  6346.  
  6347.     public boolean getTradeRefusal()
  6348.     {
  6349.         return _tradeRefusal;
  6350.     }
  6351.  
  6352.     public void addToBlockList(final String charName)
  6353.     {
  6354.         if(charName == null || charName.equalsIgnoreCase(getName()) || isInBlockList(charName))
  6355.         {
  6356.             // уже в списке
  6357.             sendPacket(SystemMsg.YOU_HAVE_FAILED_TO_REGISTER_THE_USER_TO_YOUR_IGNORE_LIST);
  6358.             return;
  6359.         }
  6360.  
  6361.         Player block_target = World.getPlayer(charName);
  6362.  
  6363.         if(block_target != null)
  6364.         {
  6365.             if(block_target.isGM())
  6366.             {
  6367.                 sendPacket(SystemMsg.YOU_MAY_NOT_IMPOSE_A_BLOCK_ON_A_GM);
  6368.                 return;
  6369.             }
  6370.             _blockList.put(block_target.getObjectId(), block_target.getName());
  6371.             sendPacket(new SystemMessage2(SystemMsg.S1_HAS_BEEN_ADDED_TO_YOUR_IGNORE_LIST).addString(block_target.getName()));
  6372.             block_target.sendPacket(new SystemMessage2(SystemMsg.S1__HAS_PLACED_YOU_ON_HIS_HER_IGNORE_LIST).addString(getName()));
  6373.             return;
  6374.         }
  6375.  
  6376.         int charId = CharacterDAO.getInstance().getObjectIdByName(charName);
  6377.  
  6378.         if(charId == 0)
  6379.         {
  6380.             // чар не существует
  6381.             sendPacket(SystemMsg.YOU_HAVE_FAILED_TO_REGISTER_THE_USER_TO_YOUR_IGNORE_LIST);
  6382.             return;
  6383.         }
  6384.  
  6385.         if(Config.gmlist.containsKey(charId) && Config.gmlist.get(charId).IsGM)
  6386.         {
  6387.             sendPacket(SystemMsg.YOU_MAY_NOT_IMPOSE_A_BLOCK_ON_A_GM);
  6388.             return;
  6389.         }
  6390.         _blockList.put(charId, charName);
  6391.         sendPacket(new SystemMessage2(SystemMsg.S1_HAS_BEEN_ADDED_TO_YOUR_IGNORE_LIST).addString(charName));
  6392.     }
  6393.  
  6394.     public void removeFromBlockList(final String charName)
  6395.     {
  6396.         int charId = 0;
  6397.         for(int blockId : _blockList.keySet())
  6398.             if(charName.equalsIgnoreCase(_blockList.get(blockId)))
  6399.             {
  6400.                 charId = blockId;
  6401.                 break;
  6402.             }
  6403.         if(charId == 0)
  6404.         {
  6405.             sendPacket(SystemMsg.YOU_HAVE_FAILED_TO_DELETE_THE_CHARACTER_FROM_IGNORE_LIST);
  6406.             return;
  6407.         }
  6408.         sendPacket(new SystemMessage2(SystemMsg.S1_HAS_BEEN_REMOVED_FROM_YOUR_IGNORE_LIST).addString(_blockList.remove(charId)));
  6409.         Player block_target = GameObjectsStorage.getPlayer(charId);
  6410.         if(block_target != null)
  6411.             block_target.sendMessage(getName() + " has removed you from his/her Ignore List."); //В системных(619 == 620) мессагах ошибка ;)
  6412.     }
  6413.  
  6414.     public boolean isInBlockList(final Player player)
  6415.     {
  6416.         return isInBlockList(player.getObjectId());
  6417.     }
  6418.  
  6419.     public boolean isInBlockList(final int charId)
  6420.     {
  6421.         return _blockList != null && _blockList.containsKey(charId);
  6422.     }
  6423.  
  6424.     public boolean isInBlockList(final String charName)
  6425.     {
  6426.         for(int blockId : _blockList.keySet())
  6427.             if(charName.equalsIgnoreCase(_blockList.get(blockId)))
  6428.                 return true;
  6429.         return false;
  6430.     }
  6431.  
  6432.     private void restoreBlockList()
  6433.     {
  6434.         _blockList.clear();
  6435.  
  6436.         Connection con = null;
  6437.         PreparedStatement statement = null;
  6438.         ResultSet rs = null;
  6439.         try
  6440.         {
  6441.             con = DatabaseFactory.getInstance().getConnection();
  6442.             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 = ?");
  6443.             statement.setInt(1, getObjectId());
  6444.             rs = statement.executeQuery();
  6445.             while(rs.next())
  6446.             {
  6447.                 int targetId = rs.getInt("target_Id");
  6448.                 String name = rs.getString("char_name");
  6449.                 if(name == null)
  6450.                     continue;
  6451.                 _blockList.put(targetId, name);
  6452.             }
  6453.         }
  6454.         catch(SQLException e)
  6455.         {
  6456.             _log.warn("Can't restore player blocklist " + e, e);
  6457.         }
  6458.         finally
  6459.         {
  6460.             DbUtils.closeQuietly(con, statement, rs);
  6461.         }
  6462.     }
  6463.  
  6464.     private void storeBlockList()
  6465.     {
  6466.         Connection con = null;
  6467.         Statement statement = null;
  6468.         try
  6469.         {
  6470.             con = DatabaseFactory.getInstance().getConnection();
  6471.             statement = con.createStatement();
  6472.             statement.executeUpdate("DELETE FROM character_blocklist WHERE obj_Id=" + getObjectId());
  6473.  
  6474.             if(_blockList.isEmpty())
  6475.                 return;
  6476.  
  6477.             SqlBatch b = new SqlBatch("INSERT IGNORE INTO `character_blocklist` (`obj_Id`,`target_Id`) VALUES");
  6478.  
  6479.             synchronized(_blockList)
  6480.             {
  6481.                 StringBuilder sb;
  6482.                 for(Entry<Integer, String> e : _blockList.entrySet())
  6483.                 {
  6484.                     sb = new StringBuilder("(");
  6485.                     sb.append(getObjectId()).append(",");
  6486.                     sb.append(e.getKey()).append(")");
  6487.                     b.write(sb.toString());
  6488.                 }
  6489.             }
  6490.             if(!b.isEmpty())
  6491.                 statement.executeUpdate(b.close());
  6492.         }
  6493.         catch(Exception e)
  6494.         {
  6495.             _log.warn("Can't store player blocklist " + e);
  6496.         }
  6497.         finally
  6498.         {
  6499.             DbUtils.closeQuietly(con, statement);
  6500.         }
  6501.     }
  6502.  
  6503.     public boolean isBlockAll()
  6504.     {
  6505.         return _blockAll;
  6506.     }
  6507.  
  6508.     public void setBlockAll(final boolean state)
  6509.     {
  6510.         _blockAll = state;
  6511.     }
  6512.  
  6513.     public Collection<String> getBlockList()
  6514.     {
  6515.         return _blockList.values();
  6516.     }
  6517.  
  6518.     public Map<Integer, String> getBlockListMap()
  6519.     {
  6520.         return _blockList;
  6521.     }
  6522.  
  6523.     public void setHero(final boolean hero)
  6524.     {
  6525.         _hero = hero;
  6526.     }
  6527.  
  6528.     @Override
  6529.     public boolean isHero()
  6530.     {
  6531.         return _hero;
  6532.     }
  6533.  
  6534.     public void setIsInOlympiadMode(final boolean b)
  6535.     {
  6536.         _inOlympiadMode = b;
  6537.     }
  6538.  
  6539.     @Override
  6540.     public boolean isInOlympiadMode()
  6541.     {
  6542.         return _inOlympiadMode;
  6543.     }
  6544.  
  6545.     public boolean isOlympiadGameStart()
  6546.     {
  6547.         return _olympiadGame != null && _olympiadGame.getState() == 1;
  6548.     }
  6549.  
  6550.     public boolean isOlympiadCompStart()
  6551.     {
  6552.         return _olympiadGame != null && _olympiadGame.getState() == 2;
  6553.     }
  6554.  
  6555.     public void updateNobleSkills()
  6556.     {
  6557.         if(isNoble())
  6558.         {
  6559.             if(isClanLeader() && getClan().getCastle() > 0)
  6560.                 super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_WYVERN_AEGIS, 1));
  6561.             super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_NOBLESSE_BLESSING, 1));
  6562.             super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_SUMMON_CP_POTION, 1));
  6563.             super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_FORTUNE_OF_NOBLESSE, 1));
  6564.             super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_HARMONY_OF_NOBLESSE, 1));
  6565.             super.addSkill(SkillTable.getInstance().getInfo(Skill.SKILL_SYMPHONY_OF_NOBLESSE, 1));
  6566.         }
  6567.         else
  6568.         {
  6569.             super.removeSkillById(Skill.SKILL_WYVERN_AEGIS);
  6570.             super.removeSkillById(Skill.SKILL_NOBLESSE_BLESSING);
  6571.             super.removeSkillById(Skill.SKILL_SUMMON_CP_POTION);
  6572.             super.removeSkillById(Skill.SKILL_FORTUNE_OF_NOBLESSE);
  6573.             super.removeSkillById(Skill.SKILL_HARMONY_OF_NOBLESSE);
  6574.             super.removeSkillById(Skill.SKILL_SYMPHONY_OF_NOBLESSE);
  6575.         }
  6576.     }
  6577.  
  6578.     public void setNoble(boolean noble)
  6579.     {
  6580.         if(noble) //broadcast skill animation: Presentation - Attain Noblesse
  6581.             broadcastPacket(new MagicSkillUse(this, this, 6673, 1, 1000, 0));
  6582.         _noble = noble;
  6583.     }
  6584.  
  6585.     public boolean isNoble()
  6586.     {
  6587.         return _noble;
  6588.     }
  6589.  
  6590.     public int getSubLevel()
  6591.     {
  6592.         return isSubClassActive() ? getLevel() : 0;
  6593.     }
  6594.  
  6595.     /* varka silenos and ketra orc quests related functions */
  6596.     public void updateKetraVarka()
  6597.     {
  6598.         if(ItemFunctions.getItemCount(this, 7215) > 0)
  6599.             _ketra = 5;
  6600.         else if(ItemFunctions.getItemCount(this, 7214) > 0)
  6601.             _ketra = 4;
  6602.         else if(ItemFunctions.getItemCount(this, 7213) > 0)
  6603.             _ketra = 3;
  6604.         else if(ItemFunctions.getItemCount(this, 7212) > 0)
  6605.             _ketra = 2;
  6606.         else if(ItemFunctions.getItemCount(this, 7211) > 0)
  6607.             _ketra = 1;
  6608.         else if(ItemFunctions.getItemCount(this, 7225) > 0)
  6609.             _varka = 5;
  6610.         else if(ItemFunctions.getItemCount(this, 7224) > 0)
  6611.             _varka = 4;
  6612.         else if(ItemFunctions.getItemCount(this, 7223) > 0)
  6613.             _varka = 3;
  6614.         else if(ItemFunctions.getItemCount(this, 7222) > 0)
  6615.             _varka = 2;
  6616.         else if(ItemFunctions.getItemCount(this, 7221) > 0)
  6617.             _varka = 1;
  6618.         else
  6619.         {
  6620.             _varka = 0;
  6621.             _ketra = 0;
  6622.         }
  6623.     }
  6624.  
  6625.     public int getVarka()
  6626.     {
  6627.         return _varka;
  6628.     }
  6629.  
  6630.     public int getKetra()
  6631.     {
  6632.         return _ketra;
  6633.     }
  6634.  
  6635.     public void updateRam()
  6636.     {
  6637.         if(ItemFunctions.getItemCount(this, 7247) > 0)
  6638.             _ram = 2;
  6639.         else if(ItemFunctions.getItemCount(this, 7246) > 0)
  6640.             _ram = 1;
  6641.         else
  6642.             _ram = 0;
  6643.     }
  6644.  
  6645.     public int getRam()
  6646.     {
  6647.         return _ram;
  6648.     }
  6649.  
  6650.     public void setPledgeType(final int typeId)
  6651.     {
  6652.         _pledgeType = typeId;
  6653.     }
  6654.  
  6655.     public int getPledgeType()
  6656.     {
  6657.         return _pledgeType;
  6658.     }
  6659.  
  6660.     public void setLvlJoinedAcademy(int lvl)
  6661.     {
  6662.         _lvlJoinedAcademy = lvl;
  6663.     }
  6664.  
  6665.     public int getLvlJoinedAcademy()
  6666.     {
  6667.         return _lvlJoinedAcademy;
  6668.     }
  6669.  
  6670.     public int getPledgeClass()
  6671.     {
  6672.         return _pledgeClass;
  6673.     }
  6674.  
  6675.     public void updatePledgeClass()
  6676.     {
  6677.         int CLAN_LEVEL = _clan == null ? -1 : _clan.getLevel();
  6678.         boolean IN_ACADEMY = _clan != null && Clan.isAcademy(_pledgeType);
  6679.         boolean IS_GUARD = _clan != null && Clan.isRoyalGuard(_pledgeType);
  6680.         boolean IS_KNIGHT = _clan != null && Clan.isOrderOfKnights(_pledgeType);
  6681.  
  6682.         boolean IS_GUARD_CAPTAIN = false, IS_KNIGHT_COMMANDER = false, IS_LEADER = false;
  6683.  
  6684.         SubUnit unit = getSubUnit();
  6685.         if(unit != null)
  6686.         {
  6687.             UnitMember unitMember = unit.getUnitMember(getObjectId());
  6688.             if(unitMember == null)
  6689.             {
  6690.                 _log.warn("Player: unitMember null, clan: " + _clan.getClanId() + "; pledgeType: " + unit.getType());
  6691.                 return;
  6692.             }
  6693.             IS_GUARD_CAPTAIN = Clan.isRoyalGuard(unitMember.getLeaderOf());
  6694.             IS_KNIGHT_COMMANDER = Clan.isOrderOfKnights(unitMember.getLeaderOf());
  6695.             IS_LEADER = unitMember.getLeaderOf() == Clan.SUBUNIT_MAIN_CLAN;
  6696.         }
  6697.  
  6698.         switch(CLAN_LEVEL)
  6699.         {
  6700.             case -1:
  6701.                 _pledgeClass = RANK_VAGABOND;
  6702.                 break;
  6703.             case 0:
  6704.             case 1:
  6705.             case 2:
  6706.             case 3:
  6707.                 if(IS_LEADER)
  6708.                     _pledgeClass = RANK_HEIR;
  6709.                 else
  6710.                     _pledgeClass = RANK_VASSAL;
  6711.                 break;
  6712.             case 4:
  6713.                 if(IS_LEADER)
  6714.                     _pledgeClass = RANK_KNIGHT;
  6715.                 else
  6716.                     _pledgeClass = RANK_HEIR;
  6717.                 break;
  6718.             case 5:
  6719.                 if(IS_LEADER)
  6720.                     _pledgeClass = RANK_WISEMAN;
  6721.                 else if(IN_ACADEMY)
  6722.                     _pledgeClass = RANK_VASSAL;
  6723.                 else
  6724.                     _pledgeClass = RANK_HEIR;
  6725.                 break;
  6726.             case 6:
  6727.                 if(IS_LEADER)
  6728.                     _pledgeClass = RANK_BARON;
  6729.                 else if(IN_ACADEMY)
  6730.                     _pledgeClass = RANK_VASSAL;
  6731.                 else if(IS_GUARD_CAPTAIN)
  6732.                     _pledgeClass = RANK_WISEMAN;
  6733.                 else if(IS_GUARD)
  6734.                     _pledgeClass = RANK_HEIR;
  6735.                 else
  6736.                     _pledgeClass = RANK_KNIGHT;
  6737.                 break;
  6738.             case 7:
  6739.                 if(IS_LEADER)
  6740.                     _pledgeClass = RANK_COUNT;
  6741.                 else if(IN_ACADEMY)
  6742.                     _pledgeClass = RANK_VASSAL;
  6743.                 else if(IS_GUARD_CAPTAIN)
  6744.                     _pledgeClass = RANK_VISCOUNT;
  6745.                 else if(IS_GUARD)
  6746.                     _pledgeClass = RANK_KNIGHT;
  6747.                 else if(IS_KNIGHT_COMMANDER)
  6748.                     _pledgeClass = RANK_BARON;
  6749.                 else if(IS_KNIGHT)
  6750.                     _pledgeClass = RANK_HEIR;
  6751.                 else
  6752.                     _pledgeClass = RANK_WISEMAN;
  6753.                 break;
  6754.             case 8:
  6755.                 if(IS_LEADER)
  6756.                     _pledgeClass = RANK_MARQUIS;
  6757.                 else if(IN_ACADEMY)
  6758.                     _pledgeClass = RANK_VASSAL;
  6759.                 else if(IS_GUARD_CAPTAIN)
  6760.                     _pledgeClass = RANK_COUNT;
  6761.                 else if(IS_GUARD)
  6762.                     _pledgeClass = RANK_WISEMAN;
  6763.                 else if(IS_KNIGHT_COMMANDER)
  6764.                     _pledgeClass = RANK_VISCOUNT;
  6765.                 else if(IS_KNIGHT)
  6766.                     _pledgeClass = RANK_KNIGHT;
  6767.                 else
  6768.                     _pledgeClass = RANK_BARON;
  6769.                 break;
  6770.             case 9:
  6771.                 if(IS_LEADER)
  6772.                     _pledgeClass = RANK_DUKE;
  6773.                 else if(IN_ACADEMY)
  6774.                     _pledgeClass = RANK_VASSAL;
  6775.                 else if(IS_GUARD_CAPTAIN)
  6776.                     _pledgeClass = RANK_MARQUIS;
  6777.                 else if(IS_GUARD)
  6778.                     _pledgeClass = RANK_BARON;
  6779.                 else if(IS_KNIGHT_COMMANDER)
  6780.                     _pledgeClass = RANK_COUNT;
  6781.                 else if(IS_KNIGHT)
  6782.                     _pledgeClass = RANK_WISEMAN;
  6783.                 else
  6784.                     _pledgeClass = RANK_VISCOUNT;
  6785.                 break;
  6786.             case 10:
  6787.                 if(IS_LEADER)
  6788.                     _pledgeClass = RANK_GRAND_DUKE;
  6789.                 else if(IN_ACADEMY)
  6790.                     _pledgeClass = RANK_VASSAL;
  6791.                 else if(IS_GUARD)
  6792.                     _pledgeClass = RANK_VISCOUNT;
  6793.                 else if(IS_KNIGHT)
  6794.                     _pledgeClass = RANK_BARON;
  6795.                 else if(IS_GUARD_CAPTAIN)
  6796.                     _pledgeClass = RANK_DUKE;
  6797.                 else if(IS_KNIGHT_COMMANDER)
  6798.                     _pledgeClass = RANK_MARQUIS;
  6799.                 else
  6800.                     _pledgeClass = RANK_COUNT;
  6801.                 break;
  6802.             case 11:
  6803.                 if(IS_LEADER)
  6804.                     _pledgeClass = RANK_DISTINGUISHED_KING;
  6805.                 else if(IN_ACADEMY)
  6806.                     _pledgeClass = RANK_VASSAL;
  6807.                 else if(IS_GUARD)
  6808.                     _pledgeClass = RANK_COUNT;
  6809.                 else if(IS_KNIGHT)
  6810.                     _pledgeClass = RANK_VISCOUNT;
  6811.                 else if(IS_GUARD_CAPTAIN)
  6812.                     _pledgeClass = RANK_GRAND_DUKE;
  6813.                 else if(IS_KNIGHT_COMMANDER)
  6814.                     _pledgeClass = RANK_DUKE;
  6815.                 else
  6816.                     _pledgeClass = RANK_MARQUIS;
  6817.                 break;
  6818.         }
  6819.  
  6820.         if(_hero && _pledgeClass < RANK_MARQUIS)
  6821.             _pledgeClass = RANK_MARQUIS;
  6822.         else if(_noble && _pledgeClass < RANK_BARON)
  6823.             _pledgeClass = RANK_BARON;
  6824.     }
  6825.  
  6826.     public void setPowerGrade(final int grade)
  6827.     {
  6828.         _powerGrade = grade;
  6829.     }
  6830.  
  6831.     public int getPowerGrade()
  6832.     {
  6833.         return _powerGrade;
  6834.     }
  6835.  
  6836.     public void setApprentice(final int apprentice)
  6837.     {
  6838.         _apprentice = apprentice;
  6839.     }
  6840.  
  6841.     public int getApprentice()
  6842.     {
  6843.         return _apprentice;
  6844.     }
  6845.  
  6846.     public int getSponsor()
  6847.     {
  6848.         return _clan == null ? 0 : _clan.getAnyMember(getObjectId()).getSponsor();
  6849.     }
  6850.  
  6851.     @Override
  6852.     public String getTitle()
  6853.     {
  6854.         return getRank()._name;
  6855.     }
  6856.  
  6857.     public String getTitleIncludePrice()
  6858.     {
  6859.         StringBuilder sb = new StringBuilder();
  6860.         sb.append(getTitle());
  6861.         sb.append(" [");
  6862.         sb.append(_price);
  6863.         sb.append("a]");
  6864.         return sb.toString();
  6865.     }
  6866.  
  6867.     public int getPrice()
  6868.     {
  6869.         return _price;
  6870.     }
  6871.    
  6872.     @Override
  6873.     public String getName()
  6874.     {
  6875.         return super.getName();
  6876.     }
  6877.    
  6878.     public int getNameColor()
  6879.     {
  6880.         if(isInObserverMode())
  6881.             return Color.black.getRGB();
  6882.  
  6883.         return _nameColor;
  6884.     }
  6885.  
  6886.     public int getTitleColor()
  6887.     {
  6888.         if(isInObserverMode())
  6889.             return Color.black.getRGB();
  6890.        
  6891.         return _titlecolor;
  6892.     }
  6893.  
  6894.     public void updatePrice() // TODO: уж очень глухая затычка, надо переработать (скорость работы менее 1 ms.)
  6895.     {
  6896.         int temp = 1;
  6897.  
  6898.         ItemInstance weapon = getActiveWeaponInstance();
  6899.         if (weapon != null)
  6900.         {
  6901.             switch (weapon.getCrystalType().externalOrdinal)
  6902.             {
  6903.                 case 5: // S grade
  6904.                     if (weapon.getEnchantLevel() > GveConfig.PriceGveWeaponEnch)
  6905.                     {
  6906.                         temp += GveConfig.PriceGveEnchWeaponSgrBonus;
  6907.                     }
  6908.                     else
  6909.                     {
  6910.                         temp += GveConfig.PriceGveWeaponSgrBonus;
  6911.                     }
  6912.                     break;
  6913.  
  6914.                 case 4: // A grade
  6915.                     if (weapon.getEnchantLevel() > GveConfig.PriceGveWeaponEnch)
  6916.                     {
  6917.                         temp += GveConfig.PriceGveEnchWeaponAgrBonus;
  6918.                     }
  6919.                     else
  6920.                     {
  6921.                         temp += GveConfig.PriceGveWeaponAgrBonus;
  6922.                     }
  6923.                     break;
  6924.  
  6925.                 case 3: // B grade
  6926.                     if (weapon.getEnchantLevel() > GveConfig.PriceGveWeaponEnch)
  6927.                     {
  6928.                         temp += GveConfig.PriceGveEnchWeaponBgrBonus;
  6929.                     }
  6930.                     else
  6931.                     {
  6932.                         temp += GveConfig.PriceGveWeaponBgrBonus;
  6933.                     }
  6934.                     break;
  6935.             }
  6936.         }
  6937.  
  6938.         Inventory i = getInventory();
  6939.  
  6940.  
  6941.         List<ItemInstance> armor = new ArrayList<ItemInstance>();
  6942.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_HEAD));
  6943.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_CHEST));
  6944.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_GLOVES));
  6945.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_FEET));
  6946.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_LEGS));
  6947.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_NECK));
  6948.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_REAR));
  6949.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_LEAR));
  6950.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_RFINGER));
  6951.         armor.add(i.getPaperdollItem(Inventory.PAPERDOLL_LFINGER));
  6952.  
  6953.         int avg_enchant = 0, avg_grade = 0, count = 0;
  6954.  
  6955.  
  6956.         for (ItemInstance item : armor)
  6957.         {
  6958.             if (item == null)
  6959.             {
  6960.                 continue;
  6961.             }
  6962.  
  6963.             count++;
  6964.  
  6965.             avg_enchant += item.getEnchantLevel();
  6966.             avg_grade += item.getCrystalType().externalOrdinal;
  6967.         }
  6968.  
  6969.         if (count > 0)
  6970.         {
  6971.             avg_enchant = Math.round(avg_enchant / count);
  6972.  
  6973.             if (avg_enchant >= 6)
  6974.             {
  6975.                 temp += GveConfig.PriceGveArmor6EnchBonus;
  6976.             }
  6977.             else if (avg_enchant >= 3)
  6978.             {
  6979.                 temp += GveConfig.PriceGveArmor3EnchBonus;
  6980.             }
  6981.  
  6982.             avg_grade = Math.round(avg_grade / count);
  6983.  
  6984.             switch (avg_grade)
  6985.             {
  6986.                 case 5: // S grade
  6987.                     temp += GveConfig.PriceGveArmorSgr;
  6988.                     break;
  6989.                 case 4: // A grade
  6990.                     temp += GveConfig.PriceGveArmorAgr;
  6991.                     break;
  6992.                 case 3: // B grade
  6993.                     temp += GveConfig.PriceGveArmorBgr;
  6994.                     break;
  6995.             }
  6996.         }
  6997.  
  6998.         if (isHero())
  6999.         {
  7000.             temp += GveConfig.PriceGveHeroBonus;
  7001.         }
  7002.  
  7003.         if (getPvpKills() >= GveConfig.PriceGvePvpCount)
  7004.         {
  7005.             temp += GveConfig.PriceGvePvpBonus;
  7006.         }
  7007.  
  7008.         // надбавка за ранг
  7009.         temp += _rank.adenaInc;
  7010.  
  7011.         _price = temp;
  7012.  
  7013.         broadcastUserInfo(false);
  7014.     }
  7015.  
  7016.     public void setNameColor(final int nameColor)
  7017.     {
  7018.         if
  7019.         (  
  7020.                 nameColor != Config.NORMAL_NAME_COLOUR &&
  7021.                 nameColor != Config.CLANLEADER_NAME_COLOUR &&
  7022.                 nameColor != Config.GM_NAME_COLOUR &&
  7023.                 nameColor != Config.SERVICES_OFFLINE_TRADE_NAME_COLOR &&
  7024.                 nameColor != Config.NAME_COLOR_1 &&
  7025.                 nameColor != Config.NAME_COLOR_2 &&
  7026.                 nameColor != Config.NAME_COLOR_3 &&
  7027.                 nameColor != Config.NAME_COLOR_4 &&
  7028.                 nameColor != Config.NAME_COLOR_5
  7029.         )
  7030.             setVar("namecolor", Integer.toHexString(nameColor), -1);
  7031.         else if(nameColor == Config.NORMAL_NAME_COLOUR)
  7032.             unsetVar("namecolor");
  7033.         _nameColor = nameColor;
  7034.     }
  7035.  
  7036.     public void setTitleColor(final int titleColor)
  7037.     {
  7038.         if
  7039.         (       titleColor != Config.CLAN_LEADER_COLOR_TITLE &&
  7040.                 titleColor != Config.TITLE_COLOR_1 &&
  7041.                 titleColor != Config.TITLE_COLOR_1 &&
  7042.                 titleColor != Config.TITLE_COLOR_2 &&
  7043.                 titleColor != Config.TITLE_COLOR_3 &&
  7044.                 titleColor != Config.TITLE_COLOR_4 &&
  7045.                 titleColor != Config.TITLE_COLOR_5
  7046.         )
  7047.             setVar("titlecolor", Integer.toHexString(titleColor), -1);
  7048.         else if(titleColor == Config.NORMAL_TITLE_COLOUR)
  7049.             unsetVar("titlecolor");
  7050.         _titlecolor = titleColor;
  7051.     }
  7052.  
  7053.     public void setNameColor(final int red, final int green, final int blue)
  7054.     {
  7055.         _nameColor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16);
  7056.         if
  7057.         (
  7058.                 _nameColor != Config.NORMAL_NAME_COLOUR &&
  7059.                 _nameColor != Config.CLANLEADER_NAME_COLOUR &&
  7060.                 _nameColor != Config.GM_NAME_COLOUR &&
  7061.                 _nameColor != Config.SERVICES_OFFLINE_TRADE_NAME_COLOR &&
  7062.                 _nameColor != Config.NAME_COLOR_1 &&
  7063.                 _nameColor != Config.NAME_COLOR_2 &&
  7064.                 _nameColor != Config.NAME_COLOR_3 &&
  7065.                 _nameColor != Config.NAME_COLOR_4 &&
  7066.                 _nameColor != Config.NAME_COLOR_5
  7067.         )
  7068.             setVar("namecolor", Integer.toHexString(_nameColor), -1);
  7069.         else
  7070.             unsetVar("namecolor");
  7071.     }
  7072.  
  7073.     public void setTitleColor(final int red, final int green, final int blue)
  7074.     {
  7075.         _titlecolor = (red & 0xFF) + ((green & 0xFF) << 8) + ((blue & 0xFF) << 16);
  7076.         if
  7077.         (
  7078.                 _titlecolor != Config.CLAN_LEADER_COLOR_TITLE &&
  7079.                 _titlecolor != Config.TITLE_COLOR_1 &&
  7080.                 _titlecolor != Config.TITLE_COLOR_2 &&
  7081.                 _titlecolor != Config.TITLE_COLOR_3 &&
  7082.                 _titlecolor != Config.TITLE_COLOR_4 &&
  7083.                 _titlecolor != Config.TITLE_COLOR_5
  7084.         )
  7085.             setVar("titlecolor", Integer.toHexString(_titlecolor), -1);
  7086.         else
  7087.             unsetVar("titlecolor");
  7088.     }
  7089.     private final Map<String, PlayerVar> user_variables = new ConcurrentHashMap<String, PlayerVar>();
  7090.  
  7091.     public void setVar(String name, String value, long expirationTime)
  7092.     {
  7093.         if(user_variables.containsKey(name))
  7094.         {
  7095.             getVarObject(name).stopExpireTask();
  7096.         }
  7097.  
  7098.         user_variables.put(name, new PlayerVar(this, name, value, expirationTime));
  7099.         mysql.set("REPLACE INTO character_variables (obj_id, type, name, value, expire_time) VALUES (?,'user-var',?,?,?)", getObjectId(), name, value, expirationTime);
  7100.     }
  7101.  
  7102.     public void setVar(String name, int value, long expirationTime)
  7103.     {
  7104.         setVar(name, String.valueOf(value), expirationTime);
  7105.     }
  7106.  
  7107.     public void setVar(String name, long value, long expirationTime)
  7108.     {
  7109.         setVar(name, String.valueOf(value), expirationTime);
  7110.     }
  7111.    
  7112.     public void setVar(String name, double value, long expirationTime)
  7113.     {
  7114.         setVar(name, String.valueOf(value), expirationTime);
  7115.     }
  7116.  
  7117.     public void unsetVar(String name)
  7118.     {
  7119.         if(name == null)
  7120.             return;
  7121.  
  7122.         PlayerVar pv = user_variables.remove(name);
  7123.  
  7124.         if(pv != null)
  7125.         {
  7126.             pv.stopExpireTask();
  7127.             mysql.set("DELETE FROM `character_variables` WHERE `obj_id`=? AND `type`='user-var' AND `name`=? LIMIT 1", getObjectId(), name);
  7128.         }
  7129.     }
  7130.  
  7131.     public String getVar(String name)
  7132.     {
  7133.         PlayerVar pv = getVarObject(name);
  7134.  
  7135.         if(pv == null)
  7136.         {
  7137.             return null;
  7138.         }
  7139.  
  7140.         return pv.getValue();
  7141.     }
  7142.  
  7143.     public long getVarTimeToExpire(String name)
  7144.     {
  7145.         try
  7146.         {
  7147.             return getVarObject(name).getTimeToExpire();
  7148.         }
  7149.         catch (NullPointerException npe)
  7150.         {}
  7151.  
  7152.         return 0;
  7153.     }
  7154.  
  7155.     public PlayerVar getVarObject(String name)
  7156.     {
  7157.         return user_variables.get(name);
  7158.     }
  7159.  
  7160.     public boolean getVarB(String name, boolean defaultVal)
  7161.     {
  7162.         PlayerVar pv = getVarObject(name);
  7163.  
  7164.         if(pv == null)
  7165.         {
  7166.             return defaultVal;
  7167.         }
  7168.  
  7169.         return pv.getValueBoolean();
  7170.     }
  7171.  
  7172.     public boolean getVarB(String name)
  7173.     {
  7174.         return getVarB(name, false);
  7175.     }
  7176.  
  7177.     public long getVarLong(String name)
  7178.     {
  7179.         return getVarLong(name, 0L);
  7180.     }
  7181.  
  7182.     public long getVarLong(String name, long defaultVal)
  7183.     {
  7184.         long result = defaultVal;
  7185.         String var = getVar(name);
  7186.         if(var != null)
  7187.             result = Long.parseLong(var);
  7188.         return result;
  7189.     }
  7190.  
  7191.     public int getVarInt(String name)
  7192.     {
  7193.         return getVarInt(name, 0);
  7194.     }
  7195.  
  7196.     public int getVarInt(String name, int defaultVal)
  7197.     {
  7198.         int result = defaultVal;
  7199.         String var = getVar(name);
  7200.         if(var != null)
  7201.             result = Integer.parseInt(var);
  7202.         return result;
  7203.     }
  7204.  
  7205.     public double getVarD(String name, double defaultVal)
  7206.     {
  7207.         double result = defaultVal;
  7208.         String var = getVar(name);
  7209.         if (var != null)
  7210.             result = Double.parseDouble(var);
  7211.         return result;
  7212.     }
  7213.      
  7214.     public Map<String, PlayerVar> getVars()
  7215.     {
  7216.         return user_variables;
  7217.     }
  7218.  
  7219.     private void loadVariables()
  7220.     {
  7221.         Connection con = null;
  7222.         PreparedStatement offline = null;
  7223.         ResultSet rs = null;
  7224.         try
  7225.         {
  7226.             con = DatabaseFactory.getInstance().getConnection();
  7227.             offline = con.prepareStatement("SELECT * FROM character_variables WHERE obj_id = ?");
  7228.             offline.setInt(1, getObjectId());
  7229.             rs = offline.executeQuery();
  7230.  
  7231.             while(rs.next())
  7232.             {
  7233.                 String name = rs.getString("name");
  7234.                 String value = Strings.stripSlashes(rs.getString("value"));
  7235.                 long expire_time = rs.getLong("expire_time");
  7236.                 long curtime = System.currentTimeMillis();
  7237.  
  7238.                 if(expire_time <= curtime && expire_time > 0) // [Akumu]: expired
  7239.                 {
  7240.                     continue;
  7241.                 }
  7242.  
  7243.                 user_variables.put(name, new PlayerVar(this, name, value, expire_time));
  7244.             }
  7245.  
  7246.             // TODO Здесь обязятельно выставлять все стандартные параметры, иначе будут NPE
  7247.             if(getVar("lang@") == null)
  7248.                 setVar("lang@", Config.DEFAULT_LANG, -1);
  7249.         }
  7250.         catch(Exception e)
  7251.         {
  7252.             _log.error("", e);
  7253.         }
  7254.         finally
  7255.         {
  7256.             DbUtils.closeQuietly(con, offline, rs);
  7257.         }
  7258.     }
  7259.  
  7260.     public static String getVarFromPlayer(int objId, String var)
  7261.     {
  7262.         String value = null;
  7263.         Connection con = null;
  7264.         PreparedStatement offline = null;
  7265.         ResultSet rs = null;
  7266.         try
  7267.         {
  7268.             con = DatabaseFactory.getInstance().getConnection();
  7269.             offline = con.prepareStatement("SELECT value FROM character_variables WHERE obj_id = ? AND name = ?");
  7270.             offline.setInt(1, objId);
  7271.             offline.setString(2, var);
  7272.             rs = offline.executeQuery();
  7273.             if(rs.next())
  7274.                 value = Strings.stripSlashes(rs.getString("value"));
  7275.         }
  7276.         catch(Exception e)
  7277.         {
  7278.             _log.error("", e);
  7279.         }
  7280.         finally
  7281.         {
  7282.             DbUtils.closeQuietly(con, offline, rs);
  7283.         }
  7284.         return value;
  7285.     }
  7286.  
  7287.     public String getLang()
  7288.     {
  7289.         return getVar("lang@");
  7290.     }
  7291.  
  7292.     public int getLangId()
  7293.     {
  7294.         String lang = getLang();
  7295.         if(lang.equalsIgnoreCase("en") || lang.equalsIgnoreCase("e") || lang.equalsIgnoreCase("eng"))
  7296.             return LANG_ENG;
  7297.         if(lang.equalsIgnoreCase("ru") || lang.equalsIgnoreCase("r") || lang.equalsIgnoreCase("rus"))
  7298.             return LANG_RUS;
  7299.         return LANG_UNK;
  7300.     }
  7301.  
  7302.     public Language getLanguage()
  7303.     {
  7304.         String lang = getLang();
  7305.         if(lang == null || lang.equalsIgnoreCase("en") || lang.equalsIgnoreCase("e") || lang.equalsIgnoreCase("eng"))
  7306.             return Language.ENGLISH;
  7307.         if(lang.equalsIgnoreCase("ru") || lang.equalsIgnoreCase("r") || lang.equalsIgnoreCase("rus"))
  7308.             return Language.RUSSIAN;
  7309.         return Language.ENGLISH;
  7310.     }
  7311.  
  7312.     public boolean isLangRus()
  7313.     {
  7314.         return getLangId() == LANG_RUS;
  7315.     }
  7316.  
  7317.     public boolean isLangEng()
  7318.     {
  7319.         return getLangId() == LANG_ENG;
  7320.     }
  7321.  
  7322.     public int isAtWarWith(final Integer id)
  7323.     {
  7324.         return _clan == null || !_clan.isAtWarWith(id) ? 0 : 1;
  7325.     }
  7326.  
  7327.     public int isAtWar()
  7328.     {
  7329.         return _clan == null || _clan.isAtWarOrUnderAttack() <= 0 ? 0 : 1;
  7330.     }
  7331.  
  7332.     public void stopWaterTask()
  7333.     {
  7334.         if(_taskWater != null)
  7335.         {
  7336.             _taskWater.cancel(false);
  7337.             _taskWater = null;
  7338.             sendPacket(new SetupGauge(this, SetupGauge.CYAN, 0));
  7339.             sendChanges();
  7340.         }
  7341.     }
  7342.  
  7343.     public void startWaterTask()
  7344.     {
  7345.         if(isDead())
  7346.             stopWaterTask();
  7347.         else if(Config.ALLOW_WATER && _taskWater == null)
  7348.         {
  7349.             int timeinwater = (int) (calcStat(Stats.BREATH, 86, null, null) * 1000L);
  7350.             sendPacket(new SetupGauge(this, SetupGauge.CYAN, timeinwater));
  7351.             if(getTransformation() > 0 && getTransformationTemplate() > 0 && !isCursedWeaponEquipped())
  7352.                 setTransformation(0);
  7353.             _taskWater = ThreadPoolManager.getInstance().scheduleAtFixedRate(new WaterTask(this), timeinwater, 1000L);
  7354.             sendChanges();
  7355.         }
  7356.     }
  7357.  
  7358.     public void doRevive(double percent)
  7359.     {
  7360.         restoreExp(percent);
  7361.         doRevive();
  7362.     }
  7363.  
  7364.     @Override
  7365.     public void doRevive()
  7366.     {
  7367.         super.doRevive();
  7368.         setAgathionRes(false);
  7369.         unsetVar("lostexp");
  7370.         updateEffectIcons();
  7371.         autoShot();
  7372.     }
  7373.  
  7374.     public void reviveRequest(Player reviver, double percent, boolean pet)
  7375.     {
  7376.         ReviveAnswerListener reviveAsk = _askDialog != null && _askDialog.getValue() instanceof ReviveAnswerListener ? (ReviveAnswerListener)_askDialog.getValue() : null;
  7377.         if(reviveAsk != null)
  7378.         {
  7379.             if(reviveAsk.isForPet() == pet && reviveAsk.getPower() >= percent)
  7380.             {
  7381.                 reviver.sendPacket(SystemMsg.BETTER_RESURRECTION_HAS_BEEN_ALREADY_PROPOSED);
  7382.                 return;
  7383.             }
  7384.             if(pet && !reviveAsk.isForPet())
  7385.             {
  7386.                 reviver.sendPacket(SystemMsg.SINCE_THE_MASTER_WAS_IN_THE_PROCESS_OF_BEING_RESURRECTED_THE_ATTEMPT_TO_RESURRECT_THE_PET_HAS_BEEN_CANCELLED);
  7387.                 return;
  7388.             }
  7389.             if(pet && isDead())
  7390.             {
  7391.                 reviver.sendPacket(SystemMsg.WHILE_A_PET_IS_ATTEMPTING_TO_RESURRECT_IT_CANNOT_HELP_IN_RESURRECTING_ITS_MASTER);
  7392.                 return;
  7393.             }
  7394.         }
  7395.  
  7396.         if(pet && getPet() != null && getPet().isDead() || !pet && isDead())
  7397.         {
  7398.             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, 0);
  7399.             pkt.addName(reviver).addString(Math.round(percent) + " percent");
  7400.  
  7401.             ask(pkt, new ReviveAnswerListener(this, percent, pet));
  7402.         }
  7403.     }
  7404.  
  7405.     public void summonCharacterRequest(final Creature summoner, final Location loc, final int summonConsumeCrystal)
  7406.     {
  7407.         ConfirmDlg cd = new ConfirmDlg(SystemMsg.C1_WISHES_TO_SUMMON_YOU_FROM_S2, 60000);
  7408.         cd.addName(summoner).addZoneName(loc);
  7409.  
  7410.         ask(cd, new SummonAnswerListener(this, loc, summonConsumeCrystal));
  7411.     }
  7412.  
  7413.     public void scriptRequest(String text, String scriptName, Object[] args)
  7414.     {
  7415.         ask(new ConfirmDlg(SystemMsg.S1, 30000).addString(text), new ScriptAnswerListener(this, scriptName, args));
  7416.     }
  7417.  
  7418.     public void updateNoChannel(final long time)
  7419.     {
  7420.         setNoChannel(time);
  7421.  
  7422.         Connection con = null;
  7423.         PreparedStatement statement = null;
  7424.         try
  7425.         {
  7426.             con = DatabaseFactory.getInstance().getConnection();
  7427.  
  7428.             final String stmt = "UPDATE characters SET nochannel = ? WHERE obj_Id=?";
  7429.             statement = con.prepareStatement(stmt);
  7430.             statement.setLong(1, _NoChannel > 0 ? _NoChannel / 1000 : _NoChannel);
  7431.             statement.setInt(2, getObjectId());
  7432.             statement.executeUpdate();
  7433.         }
  7434.         catch(final Exception e)
  7435.         {
  7436.             _log.warn("Could not activate nochannel:" + e);
  7437.         }
  7438.         finally
  7439.         {
  7440.             DbUtils.closeQuietly(con, statement);
  7441.         }
  7442.  
  7443.         sendPacket(new EtcStatusUpdate(this));
  7444.     }
  7445.  
  7446.     private void checkRecom()
  7447.     {
  7448.         Calendar temp = Calendar.getInstance();
  7449.         temp.set(Calendar.HOUR_OF_DAY, 6);
  7450.         temp.set(Calendar.MINUTE, 30);
  7451.         temp.set(Calendar.SECOND, 0);
  7452.         temp.set(Calendar.MILLISECOND, 0);
  7453.         long count = Math.round((System.currentTimeMillis() / 1000 - _lastAccess) / 86400);
  7454.         if(count == 0 && _lastAccess < temp.getTimeInMillis() / 1000 && System.currentTimeMillis() > temp.getTimeInMillis())
  7455.             count++;
  7456.  
  7457.         for(int i = 1; i < count; i++)
  7458.             setRecomHave(getRecomHave() - 20);
  7459.  
  7460.         if(count > 0)
  7461.             restartRecom();
  7462.     }
  7463.  
  7464.     public void restartRecom()
  7465.     {
  7466.         setRecomBonusTime(3600);
  7467.         setRecomLeftToday(0);
  7468.         setRecomLeft(20);
  7469.         setRecomHave(getRecomHave() - 20);
  7470.         stopRecomBonusTask(false);
  7471.         startRecomBonusTask();
  7472.         sendUserInfo(true);
  7473.         sendVoteSystemInfo();
  7474.     }
  7475.  
  7476.     @Override
  7477.     public boolean isInBoat()
  7478.     {
  7479.         return _boat != null;
  7480.     }
  7481.  
  7482.     public Boat getBoat()
  7483.     {
  7484.         return _boat;
  7485.     }
  7486.  
  7487.     public void setBoat(Boat boat)
  7488.     {
  7489.         _boat = boat;
  7490.     }
  7491.  
  7492.     public Location getInBoatPosition()
  7493.     {
  7494.         return _inBoatPosition;
  7495.     }
  7496.  
  7497.     public void setInBoatPosition(Location loc)
  7498.     {
  7499.         _inBoatPosition = loc;
  7500.     }
  7501.  
  7502.     public Map<Integer, SubClass> getSubClasses()
  7503.     {
  7504.         return _classlist;
  7505.     }
  7506.  
  7507.     public void setBaseClass(final int baseClass)
  7508.     {
  7509.         _baseClass = baseClass;
  7510.     }
  7511.  
  7512.     public int getBaseClassId()
  7513.     {
  7514.         return _baseClass;
  7515.     }
  7516.  
  7517.     public void setActiveClass(SubClass activeClass)
  7518.     {
  7519.         _activeClass = activeClass;
  7520.     }
  7521.  
  7522.     public SubClass getActiveClass()
  7523.     {
  7524.         return _activeClass;
  7525.     }
  7526.  
  7527.     public int getActiveClassId()
  7528.     {
  7529.         return getActiveClass().getClassId();
  7530.     }
  7531.  
  7532.     /**
  7533.      * Changing index of class in DB, used for changing class when finished professional quests
  7534.      *
  7535.      * @param oldclass
  7536.      * @param newclass
  7537.      */
  7538.     public synchronized void changeClassInDb(final int oldclass, final int newclass)
  7539.     {
  7540.         Connection con = null;
  7541.         PreparedStatement statement = null;
  7542.         try
  7543.         {
  7544.             con = DatabaseFactory.getInstance().getConnection();
  7545.             statement = con.prepareStatement("UPDATE character_subclasses SET class_id=? WHERE char_obj_id=? AND class_id=?");
  7546.             statement.setInt(1, newclass);
  7547.             statement.setInt(2, getObjectId());
  7548.             statement.setInt(3, oldclass);
  7549.             statement.executeUpdate();
  7550.             DbUtils.close(statement);
  7551.  
  7552.             statement = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=?");
  7553.             statement.setInt(1, getObjectId());
  7554.             statement.setInt(2, newclass);
  7555.             statement.executeUpdate();
  7556.             DbUtils.close(statement);
  7557.  
  7558.             statement = con.prepareStatement("UPDATE character_hennas SET class_index=? WHERE char_obj_id=? AND class_index=?");
  7559.             statement.setInt(1, newclass);
  7560.             statement.setInt(2, getObjectId());
  7561.             statement.setInt(3, oldclass);
  7562.             statement.executeUpdate();
  7563.             DbUtils.close(statement);
  7564.  
  7565.             statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE object_id=? AND class_index=?");
  7566.             statement.setInt(1, getObjectId());
  7567.             statement.setInt(2, newclass);
  7568.             statement.executeUpdate();
  7569.             DbUtils.close(statement);
  7570.  
  7571.             statement = con.prepareStatement("UPDATE character_shortcuts SET class_index=? WHERE object_id=? AND class_index=?");
  7572.             statement.setInt(1, newclass);
  7573.             statement.setInt(2, getObjectId());
  7574.             statement.setInt(3, oldclass);
  7575.             statement.executeUpdate();
  7576.             DbUtils.close(statement);
  7577.  
  7578.             statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=? AND class_index=?");
  7579.             statement.setInt(1, getObjectId());
  7580.             statement.setInt(2, newclass);
  7581.             statement.executeUpdate();
  7582.             DbUtils.close(statement);
  7583.  
  7584.             statement = con.prepareStatement("UPDATE character_skills SET class_index=? WHERE char_obj_id=? AND class_index=?");
  7585.             statement.setInt(1, newclass);
  7586.             statement.setInt(2, getObjectId());
  7587.             statement.setInt(3, oldclass);
  7588.             statement.executeUpdate();
  7589.             DbUtils.close(statement);
  7590.  
  7591.             statement = con.prepareStatement("DELETE FROM character_effects_save WHERE object_id=? AND id=?");
  7592.             statement.setInt(1, getObjectId());
  7593.             statement.setInt(2, newclass);
  7594.             statement.executeUpdate();
  7595.             DbUtils.close(statement);
  7596.  
  7597.             statement = con.prepareStatement("UPDATE character_effects_save SET id=? WHERE object_id=? AND id=?");
  7598.             statement.setInt(1, newclass);
  7599.             statement.setInt(2, getObjectId());
  7600.             statement.setInt(3, oldclass);
  7601.             statement.executeUpdate();
  7602.             DbUtils.close(statement);
  7603.  
  7604.             statement = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=?");
  7605.             statement.setInt(1, getObjectId());
  7606.             statement.setInt(2, newclass);
  7607.             statement.executeUpdate();
  7608.             DbUtils.close(statement);
  7609.  
  7610.             statement = con.prepareStatement("UPDATE character_skills_save SET class_index=? WHERE char_obj_id=? AND class_index=?");
  7611.             statement.setInt(1, newclass);
  7612.             statement.setInt(2, getObjectId());
  7613.             statement.setInt(3, oldclass);
  7614.             statement.executeUpdate();
  7615.             DbUtils.close(statement);
  7616.         }
  7617.         catch(final SQLException e)
  7618.         {
  7619.             _log.error("", e);
  7620.         }
  7621.         finally
  7622.         {
  7623.             DbUtils.closeQuietly(con, statement);
  7624.         }
  7625.     }
  7626.  
  7627.     /**
  7628.      * Сохраняет информацию о классах в БД
  7629.      */
  7630.     public void storeCharSubClasses()
  7631.     {
  7632.         SubClass main = getActiveClass();
  7633.         if(main != null)
  7634.         {
  7635.             main.setCp(getCurrentCp());
  7636.             //main.setExp(getExp());
  7637.             //main.setLevel(getLevel());
  7638.             //main.setSp(getSp());
  7639.             main.setHp(getCurrentHp());
  7640.             main.setMp(getCurrentMp());
  7641.             main.setActive(true);
  7642.             getSubClasses().put(getActiveClassId(), main);
  7643.         }
  7644.         else
  7645.             _log.warn("Could not store char sub data, main class " + getActiveClassId() + " not found for " + this);
  7646.  
  7647.         Connection con = null;
  7648.         Statement statement = null;
  7649.         try
  7650.         {
  7651.             con = DatabaseFactory.getInstance().getConnection();
  7652.             statement = con.createStatement();
  7653.  
  7654.             StringBuilder sb;
  7655.             for(SubClass subClass : getSubClasses().values())
  7656.             {
  7657.                 sb = new StringBuilder("UPDATE character_subclasses SET ");
  7658.                 sb.append("exp=").append(subClass.getExp()).append(",");
  7659.                 sb.append("sp=").append(subClass.getSp()).append(",");
  7660.                 sb.append("curHp=").append(subClass.getHp()).append(",");
  7661.                 sb.append("curMp=").append(subClass.getMp()).append(",");
  7662.                 sb.append("curCp=").append(subClass.getCp()).append(",");
  7663.                 sb.append("level=").append(subClass.getLevel()).append(",");
  7664.                 sb.append("active=").append(subClass.isActive() ? 1 : 0).append(",");
  7665.                 sb.append("isBase=").append(subClass.isBase() ? 1 : 0).append(",");
  7666.                 sb.append("death_penalty=").append(subClass.getDeathPenalty(this).getLevelOnSaveDB()).append(",");
  7667.                 sb.append("certification='").append(subClass.getCertification()).append("'");
  7668.                 sb.append(" WHERE char_obj_id=").append(getObjectId()).append(" AND class_id=").append(subClass.getClassId()).append(" LIMIT 1");
  7669.                 statement.executeUpdate(sb.toString());
  7670.             }
  7671.  
  7672.             sb = new StringBuilder("UPDATE character_subclasses SET ");
  7673.             sb.append("maxHp=").append(getMaxHp()).append(",");
  7674.             sb.append("maxMp=").append(getMaxMp()).append(",");
  7675.             sb.append("maxCp=").append(getMaxCp());
  7676.             sb.append(" WHERE char_obj_id=").append(getObjectId()).append(" AND active=1 LIMIT 1");
  7677.             statement.executeUpdate(sb.toString());
  7678.         }
  7679.         catch(final Exception e)
  7680.         {
  7681.             _log.warn("Could not store char sub data: " + e);
  7682.             _log.error("", e);
  7683.         }
  7684.         finally
  7685.         {
  7686.             DbUtils.closeQuietly(con, statement);
  7687.         }
  7688.     }
  7689.  
  7690.     /**
  7691.      * Restore list of character professions and set up active proof
  7692.      * Used when character is loading
  7693.      */
  7694.     public static void restoreCharSubClasses(final Player player)
  7695.     {
  7696.         Connection con = null;
  7697.         PreparedStatement statement = null;
  7698.         ResultSet rset = null;
  7699.         try
  7700.         {
  7701.             con = DatabaseFactory.getInstance().getConnection();
  7702.             statement = con.prepareStatement("SELECT class_id,exp,sp,curHp,curCp,curMp,active,isBase,death_penalty,certification FROM character_subclasses WHERE char_obj_id=?");
  7703.             statement.setInt(1, player.getObjectId());
  7704.             rset = statement.executeQuery();
  7705.  
  7706.             SubClass activeSubclass = null;
  7707.             while(rset.next())
  7708.             {
  7709.                 final SubClass subClass = new SubClass();
  7710.                 subClass.setBase(rset.getInt("isBase") != 0);
  7711.                 subClass.setClassId(rset.getInt("class_id"));
  7712.                 subClass.setExp(rset.getLong("exp"));
  7713.                 subClass.setSp(rset.getInt("sp"));
  7714.                 subClass.setHp(rset.getDouble("curHp"));
  7715.                 subClass.setMp(rset.getDouble("curMp"));
  7716.                 subClass.setCp(rset.getDouble("curCp"));
  7717.                 subClass.setDeathPenalty(new DeathPenalty(player, rset.getInt("death_penalty")));
  7718.                 subClass.setCertification(rset.getInt("certification"));
  7719.  
  7720.                 boolean active = rset.getInt("active") != 0;
  7721.                 if(active)
  7722.                     activeSubclass = subClass;
  7723.                 player.getSubClasses().put(subClass.getClassId(), subClass);
  7724.             }
  7725.  
  7726.             if(player.getSubClasses().size() == 0)
  7727.                 throw new Exception("There are no one subclass for player: " + player);
  7728.  
  7729.             int BaseClassId = player.getBaseClassId();
  7730.             if(BaseClassId == -1)
  7731.                 throw new Exception("There are no base subclass for player: " + player);
  7732.  
  7733.             if(activeSubclass != null)
  7734.                 player.setActiveSubClass(activeSubclass.getClassId(), false);
  7735.  
  7736.             if(player.getActiveClass() == null)
  7737.             {
  7738.                 //если из-за какого-либо сбоя ни один из сабкласов не отмечен как активный помечаем базовый как активный
  7739.                 final SubClass subClass = player.getSubClasses().get(BaseClassId);
  7740.                 subClass.setActive(true);
  7741.                 player.setActiveSubClass(subClass.getClassId(), false);
  7742.             }
  7743.         }
  7744.         catch(final Exception e)
  7745.         {
  7746.             _log.warn("Could not restore char sub-classes: " + e);
  7747.             _log.error("", e);
  7748.         }
  7749.         finally
  7750.         {
  7751.             DbUtils.closeQuietly(con, statement, rset);
  7752.         }
  7753.     }
  7754.  
  7755.     /**
  7756.      * Добавить класс, используется только для сабклассов
  7757.      *
  7758.      * @param storeOld
  7759.      * @param certification
  7760.      */
  7761.     public boolean addSubClass(final int classId, boolean storeOld, int certification)
  7762.     {
  7763.         if(_classlist.size() >= 4)
  7764.             return false;
  7765.  
  7766.         final ClassId newId = ClassId.VALUES[classId];
  7767.  
  7768.         final SubClass newClass = new SubClass();
  7769.         newClass.setBase(false);
  7770.         if(newId.getRace() == null)
  7771.             return false;
  7772.  
  7773.         newClass.setClassId(classId);
  7774.         newClass.setCertification(certification);
  7775.  
  7776.         _classlist.put(classId, newClass);
  7777.  
  7778.         Connection con = null;
  7779.         PreparedStatement statement = null;
  7780.         try
  7781.         {
  7782.             // Store the basic info about this new sub-class.
  7783.             con = DatabaseFactory.getInstance().getConnection();
  7784.             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 (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
  7785.             statement.setInt(1, getObjectId());
  7786.             statement.setInt(2, newClass.getClassId());
  7787.             statement.setLong(3, Experience.LEVEL[40]);
  7788.             statement.setInt(4, 0);
  7789.             statement.setDouble(5, getCurrentHp());
  7790.             statement.setDouble(6, getCurrentMp());
  7791.             statement.setDouble(7, getCurrentCp());
  7792.             statement.setDouble(8, getCurrentHp());
  7793.             statement.setDouble(9, getCurrentMp());
  7794.             statement.setDouble(10, getCurrentCp());
  7795.             statement.setInt(11, 40);
  7796.             statement.setInt(12, 0);
  7797.             statement.setInt(13, 0);
  7798.             statement.setInt(14, 0);
  7799.             statement.setInt(15, certification);
  7800.             statement.execute();
  7801.         }
  7802.         catch(final Exception e)
  7803.         {
  7804.             _log.warn("Could not add character sub-class: " + e, e);
  7805.             return false;
  7806.         }
  7807.         finally
  7808.         {
  7809.             DbUtils.closeQuietly(con, statement);
  7810.         }
  7811.  
  7812.         setActiveSubClass(classId, storeOld);
  7813.  
  7814.         boolean countUnlearnable = true;
  7815.         int unLearnable = 0;
  7816.  
  7817.         Collection<SkillLearn> skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
  7818.         while(skills.size() > unLearnable)
  7819.         {
  7820.             for(final SkillLearn s : skills)
  7821.             {
  7822.                 final Skill sk = SkillTable.getInstance().getInfo(s.getId(), s.getLevel());
  7823.                 if(sk == null || !sk.getCanLearn(newId))
  7824.                 {
  7825.                     if(countUnlearnable)
  7826.                         unLearnable++;
  7827.                     continue;
  7828.                 }
  7829.                 addSkill(sk, true);
  7830.             }
  7831.             countUnlearnable = false;
  7832.             skills = SkillAcquireHolder.getInstance().getAvailableSkills(this, AcquireType.NORMAL);
  7833.         }
  7834.  
  7835.         sendPacket(new SkillList(this));
  7836.         setCurrentHpMp(getMaxHp(), getMaxMp(), true);
  7837.         setCurrentCp(getMaxCp());
  7838.         return true;
  7839.     }
  7840.  
  7841.     /**
  7842.      * Удаляет всю информацию о классе и добавляет новую, только для сабклассов
  7843.      */
  7844.     public boolean modifySubClass(final int oldClassId, final int newClassId)
  7845.     {
  7846.         final SubClass originalClass = _classlist.get(oldClassId);
  7847.         if(originalClass == null || originalClass.isBase())
  7848.             return false;
  7849.  
  7850.         final int certification = originalClass.getCertification();
  7851.  
  7852.         Connection con = null;
  7853.         PreparedStatement statement = null;
  7854.         try
  7855.         {
  7856.             con = DatabaseFactory.getInstance().getConnection();
  7857.             // Remove all basic info stored about this sub-class.
  7858.             statement = con.prepareStatement("DELETE FROM character_subclasses WHERE char_obj_id=? AND class_id=? AND isBase = 0");
  7859.             statement.setInt(1, getObjectId());
  7860.             statement.setInt(2, oldClassId);
  7861.             statement.execute();
  7862.             DbUtils.close(statement);
  7863.  
  7864.             // Remove all skill info stored for this sub-class.
  7865.             statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=? AND class_index=? ");
  7866.             statement.setInt(1, getObjectId());
  7867.             statement.setInt(2, oldClassId);
  7868.             statement.execute();
  7869.             DbUtils.close(statement);
  7870.  
  7871.             // Remove all saved skills info stored for this sub-class.
  7872.             statement = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=? AND class_index=? ");
  7873.             statement.setInt(1, getObjectId());
  7874.             statement.setInt(2, oldClassId);
  7875.             statement.execute();
  7876.             DbUtils.close(statement);
  7877.  
  7878.             // Remove all saved effects stored for this sub-class.
  7879.             statement = con.prepareStatement("DELETE FROM character_effects_save WHERE object_id=? AND id=? ");
  7880.             statement.setInt(1, getObjectId());
  7881.             statement.setInt(2, oldClassId);
  7882.             statement.execute();
  7883.             DbUtils.close(statement);
  7884.  
  7885.             // Remove all henna info stored for this sub-class.
  7886.             statement = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=? AND class_index=? ");
  7887.             statement.setInt(1, getObjectId());
  7888.             statement.setInt(2, oldClassId);
  7889.             statement.execute();
  7890.             DbUtils.close(statement);
  7891.  
  7892.             // Remove all shortcuts info stored for this sub-class.
  7893.             statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE object_id=? AND class_index=? ");
  7894.             statement.setInt(1, getObjectId());
  7895.             statement.setInt(2, oldClassId);
  7896.             statement.execute();
  7897.             DbUtils.close(statement);
  7898.         }
  7899.         catch(final Exception e)
  7900.         {
  7901.             _log.warn("Could not delete char sub-class: " + e);
  7902.             _log.error("", e);
  7903.         }
  7904.         finally
  7905.         {
  7906.             DbUtils.closeQuietly(con, statement);
  7907.         }
  7908.         _classlist.remove(oldClassId);
  7909.  
  7910.         return newClassId <= 0 || addSubClass(newClassId, false, certification);
  7911.     }
  7912.  
  7913.     /**
  7914.      * Устанавливает активный сабкласс
  7915.      * <p/>
  7916.      * <li>Retrieve from the database all skills of this L2Player and add them to _skills </li>
  7917.      * <li>Retrieve from the database all macroses of this L2Player and add them to _macroses</li>
  7918.      * <li>Retrieve from the database all shortCuts of this L2Player and add them to _shortCuts</li><BR><BR>
  7919.      */
  7920.     public void setActiveSubClass(final int subId, final boolean store)
  7921.     {
  7922.         final SubClass sub = getSubClasses().get(subId);
  7923.         if(sub == null)
  7924.             return;
  7925.  
  7926.         if(getActiveClass() != null)
  7927.         {
  7928.             EffectsDAO.getInstance().insert(this);
  7929.             storeDisableSkills();
  7930.  
  7931.             if(QuestManager.getQuest(422) != null)
  7932.             {
  7933.                 String qn = QuestManager.getQuest(422).getName();
  7934.                 if(qn != null)
  7935.                 {
  7936.                     QuestState qs = getQuestState(qn);
  7937.                     if(qs != null)
  7938.                         qs.exitCurrentQuest(true);
  7939.                 }
  7940.             }
  7941.         }
  7942.  
  7943.         if(store)
  7944.         {
  7945.             final SubClass oldsub = getActiveClass();
  7946.             oldsub.setCp(getCurrentCp());
  7947.             //oldsub.setExp(getExp());
  7948.             //oldsub.setLevel(getLevel());
  7949.             //oldsub.setSp(getSp());
  7950.             oldsub.setHp(getCurrentHp());
  7951.             oldsub.setMp(getCurrentMp());
  7952.             oldsub.setActive(false);
  7953.             getSubClasses().put(getActiveClassId(), oldsub);
  7954.         }
  7955.  
  7956.         sub.setActive(true);
  7957.         setActiveClass(sub);
  7958.         getSubClasses().put(getActiveClassId(), sub);
  7959.  
  7960.         setClassId(subId, false, false);
  7961.  
  7962.         removeAllSkills();
  7963.  
  7964.         getEffectList().stopAllEffects();
  7965.  
  7966.         if(getPet() != null && (getPet().isSummon() || Config.ALT_IMPROVED_PETS_LIMITED_USE && (getPet().getNpcId() == PetDataTable.IMPROVED_BABY_KOOKABURRA_ID && !isMageClass() || getPet().getNpcId() == PetDataTable.IMPROVED_BABY_BUFFALO_ID && isMageClass())))
  7967.             getPet().unSummon();
  7968.  
  7969.         setAgathion(0);
  7970.  
  7971.         restoreSkills();
  7972.         rewardSkills(false);
  7973.         checkSkills();
  7974.         sendPacket(new ExStorageMaxCount(this));
  7975.  
  7976.         refreshExpertisePenalty();
  7977.  
  7978.         sendPacket(new SkillList(this));
  7979.  
  7980.         getInventory().refreshEquip();
  7981.         getInventory().validateItems();
  7982.  
  7983.         for(int i = 0; i < 3; i++)
  7984.             _henna[i] = null;
  7985.  
  7986.         restoreHenna();
  7987.         sendPacket(new HennaInfo(this));
  7988.  
  7989.         EffectsDAO.getInstance().restoreEffects(this);
  7990.         restoreDisableSkills();
  7991.  
  7992.         setCurrentHpMp(sub.getHp(), sub.getMp());
  7993.         setCurrentCp(sub.getCp());
  7994.  
  7995.         _shortCuts.restore();
  7996.         sendPacket(new ShortCutInit(this));
  7997.         for(int shotId : getAutoSoulShot())
  7998.             sendPacket(new ExAutoSoulShot(shotId, true));
  7999.         sendPacket(new SkillCoolTime(this));
  8000.  
  8001.         broadcastPacket(new SocialAction(getObjectId(), SocialAction.LEVEL_UP));
  8002.  
  8003.         getDeathPenalty().restore(this);
  8004.  
  8005.         setIncreasedForce(0);
  8006.  
  8007.         startHourlyTask();
  8008.  
  8009.         broadcastCharInfo();
  8010.         updateEffectIcons();
  8011.         updateStats();
  8012.     }
  8013.  
  8014.     /**
  8015.      * Через delay миллисекунд выбросит игрока из игры
  8016.      */
  8017.     public void startKickTask(long delayMillis)
  8018.     {
  8019.         stopKickTask();
  8020.         _kickTask = ThreadPoolManager.getInstance().schedule(new KickTask(this), delayMillis);
  8021.     }
  8022.  
  8023.     public void stopKickTask()
  8024.     {
  8025.         if(_kickTask != null)
  8026.         {
  8027.             _kickTask.cancel(false);
  8028.             _kickTask = null;
  8029.         }
  8030.     }
  8031.  
  8032.     public void startBonusTask()
  8033.     {
  8034.         if(Config.SERVICES_RATE_TYPE != Bonus.NO_BONUS)
  8035.         {
  8036.             int bonusExpire = getNetConnection().getBonusExpire();
  8037.             double bonus = getNetConnection().getBonus();
  8038.             if(bonusExpire > System.currentTimeMillis() / 1000L)
  8039.             {
  8040.                 getBonus().setRateXp(bonus);
  8041.                 getBonus().setRateSp(bonus);
  8042.                 getBonus().setDropAdena(bonus);
  8043.                 getBonus().setDropItems(bonus);
  8044.                 getBonus().setDropSpoil(bonus);
  8045.  
  8046.                 getBonus().setBonusExpire(bonusExpire);
  8047.  
  8048.                 if(_bonusExpiration == null)
  8049.                     _bonusExpiration = LazyPrecisionTaskManager.getInstance().startBonusExpirationTask(this);
  8050.             }
  8051.             else if(bonus > 0 && Config.SERVICES_RATE_TYPE == Bonus.BONUS_GLOBAL_ON_GAMESERVER)
  8052.                 AccountBonusDAO.getInstance().delete(getAccountName());
  8053.         }
  8054.     }
  8055.    
  8056.     public long getOnlineTime()
  8057.        {
  8058.       return this._onlineTime / 1000L;
  8059.        }
  8060.    
  8061.     public void stopBonusTask()
  8062.     {
  8063.         if(_bonusExpiration != null)
  8064.         {
  8065.             _bonusExpiration.cancel(false);
  8066.             _bonusExpiration = null;
  8067.         }
  8068.     }
  8069.  
  8070.     @Override
  8071.     public int getInventoryLimit()
  8072.     {
  8073.         return (int) calcStat(Stats.INVENTORY_LIMIT, 0, null, null);
  8074.     }
  8075.  
  8076.     public int getWarehouseLimit()
  8077.     {
  8078.         return (int) calcStat(Stats.STORAGE_LIMIT, 0, null, null);
  8079.     }
  8080.  
  8081.     public int getTradeLimit()
  8082.     {
  8083.         return (int) calcStat(Stats.TRADE_LIMIT, 0, null, null);
  8084.     }
  8085.  
  8086.     public int getDwarvenRecipeLimit()
  8087.     {
  8088.         return (int) calcStat(Stats.DWARVEN_RECIPE_LIMIT, 50, null, null) + Config.ALT_ADD_RECIPES;
  8089.     }
  8090.  
  8091.     public int getCommonRecipeLimit()
  8092.     {
  8093.         return (int) calcStat(Stats.COMMON_RECIPE_LIMIT, 50, null, null) + Config.ALT_ADD_RECIPES;
  8094.     }
  8095.  
  8096.     /**
  8097.      * Возвращает тип атакующего элемента
  8098.      */
  8099.     public Element getAttackElement()
  8100.     {
  8101.         return Formulas.getAttackElement(this, null);
  8102.     }
  8103.  
  8104.     /**
  8105.      * Возвращает силу атаки элемента
  8106.      *
  8107.      * @return значение атаки
  8108.      */
  8109.     public int getAttack(Element element)
  8110.     {
  8111.         if(element == Element.NONE)
  8112.             return 0;
  8113.         return (int) calcStat(element.getAttack(), 0., null, null);
  8114.     }
  8115.  
  8116.     /**
  8117.      * Возвращает защиту от элемента
  8118.      *
  8119.      * @return значение защиты
  8120.      */
  8121.     public int getDefence(Element element)
  8122.     {
  8123.         if(element == Element.NONE)
  8124.             return 0;
  8125.         return (int) calcStat(element.getDefence(), 0., null, null);
  8126.     }
  8127.  
  8128.     public boolean getAndSetLastItemAuctionRequest()
  8129.     {
  8130.         if(_lastItemAuctionInfoRequest + 2000L < System.currentTimeMillis())
  8131.         {
  8132.             _lastItemAuctionInfoRequest = System.currentTimeMillis();
  8133.             return true;
  8134.         }
  8135.         else
  8136.         {
  8137.             _lastItemAuctionInfoRequest = System.currentTimeMillis();
  8138.             return false;
  8139.         }
  8140.     }
  8141.  
  8142.     @Override
  8143.     public int getNpcId()
  8144.     {
  8145.         return -2;
  8146.     }
  8147.  
  8148.     public GameObject getVisibleObject(int id)
  8149.     {
  8150.         if(getObjectId() == id)
  8151.             return this;
  8152.  
  8153.         GameObject target = null;
  8154.  
  8155.         if(getTargetId() == id)
  8156.             target = getTarget();
  8157.  
  8158.         if(target == null && _party != null)
  8159.             for(Player p : _party.getPartyMembers())
  8160.                 if(p != null && p.getObjectId() == id)
  8161.                 {
  8162.                     target = p;
  8163.                     break;
  8164.                 }
  8165.  
  8166.         if(target == null)
  8167.             target = World.getAroundObjectById(this, id);
  8168.  
  8169.         return target == null || target.isInvisible() ? null : target;
  8170.     }
  8171.  
  8172.     @Override
  8173.     public int getPAtk(final Creature target)
  8174.     {
  8175.         double init = getActiveWeaponInstance() == null ? (isMageClass() ? 3 : 4) : 0;
  8176.         return (int) calcStat(Stats.POWER_ATTACK, init, target, null);
  8177.     }
  8178.  
  8179.     @Override
  8180.     public int getPDef(final Creature target)
  8181.     {
  8182.         double init = 4.; //empty cloak and underwear slots
  8183.  
  8184.         final ItemInstance chest = getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
  8185.         if(chest == null)
  8186.             init += isMageClass() ? ArmorTemplate.EMPTY_BODY_MYSTIC : ArmorTemplate.EMPTY_BODY_FIGHTER;
  8187.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS) == null && (chest == null || chest.getBodyPart() != ItemTemplate.SLOT_FULL_ARMOR))
  8188.             init += isMageClass() ? ArmorTemplate.EMPTY_LEGS_MYSTIC : ArmorTemplate.EMPTY_LEGS_FIGHTER;
  8189.  
  8190.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_HEAD) == null)
  8191.             init += ArmorTemplate.EMPTY_HELMET;
  8192.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_GLOVES) == null)
  8193.             init += ArmorTemplate.EMPTY_GLOVES;
  8194.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_FEET) == null)
  8195.             init += ArmorTemplate.EMPTY_BOOTS;
  8196.  
  8197.         return (int) calcStat(Stats.POWER_DEFENCE, init, target, null);
  8198.     }
  8199.  
  8200.     @Override
  8201.     public int getMDef(final Creature target, final Skill skill)
  8202.     {
  8203.         double init = 0.;
  8204.  
  8205.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEAR) == null)
  8206.             init += ArmorTemplate.EMPTY_EARRING;
  8207.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_REAR) == null)
  8208.             init += ArmorTemplate.EMPTY_EARRING;
  8209.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_NECK) == null)
  8210.             init += ArmorTemplate.EMPTY_NECKLACE;
  8211.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_LFINGER) == null)
  8212.             init += ArmorTemplate.EMPTY_RING;
  8213.         if(getInventory().getPaperdollItem(Inventory.PAPERDOLL_RFINGER) == null)
  8214.             init += ArmorTemplate.EMPTY_RING;
  8215.  
  8216.         return (int) calcStat(Stats.MAGIC_DEFENCE, init, target, skill);
  8217.     }
  8218.  
  8219.     public boolean isSubClassActive()
  8220.     {
  8221.         return getBaseClassId() != getActiveClassId();
  8222.     }
  8223.  
  8224.     @Override
  8225.     public boolean isCursedWeaponEquipped()
  8226.     {
  8227.         return _cursedWeaponEquippedId != 0;
  8228.     }
  8229.  
  8230.     public void setCursedWeaponEquippedId(int value)
  8231.     {
  8232.         _cursedWeaponEquippedId = value;
  8233.     }
  8234.  
  8235.     public int getCursedWeaponEquippedId()
  8236.     {
  8237.         return _cursedWeaponEquippedId;
  8238.     }
  8239.  
  8240.     @Override
  8241.     public boolean isImmobilized()
  8242.     {
  8243.         return super.isImmobilized() || isOverloaded() || isSitting() || isFishing();
  8244.     }
  8245.  
  8246.     @Override
  8247.     public boolean isBlocked()
  8248.     {
  8249.         return super.isBlocked() || isInMovie() || isInObserverMode() || isTeleporting() || isLogoutStarted();
  8250.     }
  8251.  
  8252.     @Override
  8253.     public boolean isInvul()
  8254.     {
  8255.         return super.isInvul() || isInMovie();
  8256.     }
  8257.  
  8258.     /**
  8259.      * if True, the L2Player can't take more item
  8260.      */
  8261.     public void setOverloaded(boolean overloaded)
  8262.     {
  8263.         _overloaded = overloaded;
  8264.     }
  8265.  
  8266.     public boolean isOverloaded()
  8267.     {
  8268.         return _overloaded;
  8269.     }
  8270.  
  8271.     public boolean isFishing()
  8272.     {
  8273.         return _isFishing;
  8274.     }
  8275.  
  8276.     public Fishing getFishing()
  8277.     {
  8278.         return _fishing;
  8279.     }
  8280.  
  8281.     public void setFishing(boolean value)
  8282.     {
  8283.         _isFishing = value;
  8284.     }
  8285.  
  8286.     public void startFishing(FishTemplate fish, int lureId)
  8287.     {
  8288.         _fishing.setFish(fish);
  8289.         _fishing.setLureId(lureId);
  8290.         _fishing.startFishing();
  8291.     }
  8292.  
  8293.     public void stopFishing()
  8294.     {
  8295.         _fishing.stopFishing();
  8296.     }
  8297.  
  8298.     public Location getFishLoc()
  8299.     {
  8300.         return _fishing.getFishLoc();
  8301.     }
  8302.  
  8303.     public Bonus getBonus()
  8304.     {
  8305.         return _bonus;
  8306.     }
  8307.  
  8308.     public boolean hasBonus()
  8309.     {
  8310.         return _bonus.getBonusExpire() > System.currentTimeMillis() / 1000L;
  8311.     }
  8312.  
  8313.     @Override
  8314.     public double getRateAdena()
  8315.     {
  8316.         return _party == null ? _bonus.getDropAdena() : _party._rateAdena;
  8317.     }
  8318.  
  8319.     @Override
  8320.     public double getRateItems()
  8321.     {
  8322.         return _party == null ? _bonus.getDropItems() : _party._rateDrop;
  8323.     }
  8324.  
  8325.     @Override
  8326.     public double getRateExp()
  8327.     {
  8328.         return calcStat(Stats.EXP, (_party == null ? _bonus.getRateXp() : _party._rateExp), null, null);
  8329.     }
  8330.  
  8331.     @Override
  8332.     public double getRateSp()
  8333.     {
  8334.         return calcStat(Stats.SP, (_party == null ? _bonus.getRateSp() : _party._rateSp), null, null);
  8335.     }
  8336.  
  8337.     @Override
  8338.     public double getRateSpoil()
  8339.     {
  8340.         return _party == null ? _bonus.getDropSpoil() : _party._rateSpoil;
  8341.     }
  8342.  
  8343.     private boolean _maried = false;
  8344.     private int _partnerId = 0;
  8345.     private int _coupleId = 0;
  8346.     private boolean _maryrequest = false;
  8347.     private boolean _maryaccepted = false;
  8348.  
  8349.     public boolean isMaried()
  8350.     {
  8351.         return _maried;
  8352.     }
  8353.  
  8354.     public void setMaried(boolean state)
  8355.     {
  8356.         _maried = state;
  8357.     }
  8358.  
  8359.     public void setMaryRequest(boolean state)
  8360.     {
  8361.         _maryrequest = state;
  8362.     }
  8363.  
  8364.     public boolean isMaryRequest()
  8365.     {
  8366.         return _maryrequest;
  8367.     }
  8368.  
  8369.     public void setMaryAccepted(boolean state)
  8370.     {
  8371.         _maryaccepted = state;
  8372.     }
  8373.  
  8374.     public boolean isMaryAccepted()
  8375.     {
  8376.         return _maryaccepted;
  8377.     }
  8378.  
  8379.     public int getPartnerId()
  8380.     {
  8381.         return _partnerId;
  8382.     }
  8383.  
  8384.     public void setPartnerId(int partnerid)
  8385.     {
  8386.         _partnerId = partnerid;
  8387.     }
  8388.  
  8389.     public int getCoupleId()
  8390.     {
  8391.         return _coupleId;
  8392.     }
  8393.  
  8394.     public void setCoupleId(int coupleId)
  8395.     {
  8396.         _coupleId = coupleId;
  8397.     }
  8398.  
  8399.     public void setUndying(boolean val)
  8400.     {
  8401.         if(!isGM())
  8402.             return;
  8403.         _isUndying = val;
  8404.     }
  8405.  
  8406.     public boolean isUndying()
  8407.     {
  8408.         return _isUndying;
  8409.     }
  8410.  
  8411.    
  8412.     private List<Player> _snoopListener = new ArrayList<Player>();
  8413.     private List<Player> _snoopedPlayer = new ArrayList<Player>();
  8414.    
  8415.     public void broadcastSnoop(int type, String name, int fStringId, String... params)
  8416.     {
  8417.         if(_snoopListener.size() > 0)
  8418.         {
  8419.             Snoop sn = new Snoop(getObjectId(), getName(), type, name, name, fStringId, params);
  8420.             for(Player pci : _snoopListener)
  8421.                 if(pci != null)
  8422.                     pci.sendPacket(sn);
  8423.         }
  8424.     }
  8425.    
  8426.     public void addSnooper(Player pci)
  8427.     {
  8428.         if(!_snoopListener.contains(pci))
  8429.             _snoopListener.add(pci);
  8430.     }
  8431.    
  8432.     public void removeSnooper(Player pci)
  8433.     {
  8434.         _snoopListener.remove(pci);
  8435.     }
  8436.    
  8437.     public void addSnooped(Player pci)
  8438.     {
  8439.         if(!_snoopedPlayer.contains(pci))
  8440.             _snoopedPlayer.add(pci);
  8441.     }
  8442.    
  8443.     public void removeSnooped(Player pci)
  8444.     {
  8445.         _snoopedPlayer.remove(pci);
  8446.     }
  8447.      
  8448.  
  8449.     /**
  8450.      * Сброс реюза всех скилов персонажа.
  8451.      */
  8452.     public void resetReuse()
  8453.     {
  8454.         _skillReuses.clear();
  8455.         _sharedGroupReuses.clear();
  8456.     }
  8457.  
  8458.     public DeathPenalty getDeathPenalty()
  8459.     {
  8460.         return _activeClass == null ? null : _activeClass.getDeathPenalty(this);
  8461.     }
  8462.  
  8463.     private boolean _charmOfCourage = false;
  8464.  
  8465.     public boolean isCharmOfCourage()
  8466.     {
  8467.         return _charmOfCourage;
  8468.     }
  8469.  
  8470.     public void setCharmOfCourage(boolean val)
  8471.     {
  8472.         _charmOfCourage = val;
  8473.  
  8474.         if(!val)
  8475.             getEffectList().stopEffect(Skill.SKILL_CHARM_OF_COURAGE);
  8476.  
  8477.         sendEtcStatusUpdate();
  8478.     }
  8479.  
  8480.     private int _increasedForce = 0;
  8481.     private int _consumedSouls = 0;
  8482.  
  8483.     @Override
  8484.     public int getIncreasedForce()
  8485.     {
  8486.         return _increasedForce;
  8487.     }
  8488.  
  8489.     @Override
  8490.     public int getConsumedSouls()
  8491.     {
  8492.         return _consumedSouls;
  8493.     }
  8494.  
  8495.     @Override
  8496.     public void setConsumedSouls(int i, NpcInstance monster)
  8497.     {
  8498.         if(i == _consumedSouls)
  8499.             return;
  8500.  
  8501.         int max = (int) calcStat(Stats.SOULS_LIMIT, 0, monster, null);
  8502.  
  8503.         if(i > max)
  8504.             i = max;
  8505.  
  8506.         if(i <= 0)
  8507.         {
  8508.             _consumedSouls = 0;
  8509.             sendEtcStatusUpdate();
  8510.             return;
  8511.         }
  8512.  
  8513.         if(_consumedSouls != i)
  8514.         {
  8515.             int diff = i - _consumedSouls;
  8516.             if(diff > 0)
  8517.             {
  8518.                 SystemMessage2 sm = new SystemMessage2(SystemMsg.YOUR_SOUL_HAS_INCREASED_BY_S1_SO_IT_IS_NOW_AT_S2);
  8519.                 sm.addNumber(diff);
  8520.                 sm.addNumber(i);
  8521.                 sendPacket(sm);
  8522.             }
  8523.         }
  8524.         else if(max == i)
  8525.         {
  8526.             sendPacket(SystemMsg.SOUL_CANNOT_BE_ABSORBED_ANY_MORE);
  8527.             return;
  8528.         }
  8529.  
  8530.         _consumedSouls = i;
  8531.         sendPacket(new EtcStatusUpdate(this));
  8532.     }
  8533.  
  8534.     @Override
  8535.     public void setIncreasedForce(int i)
  8536.     {
  8537.         i = Math.min(i, Charge.MAX_CHARGE);
  8538.         i = Math.max(i, 0);
  8539.  
  8540.         if(i != 0 && i > _increasedForce)
  8541.             sendPacket(new SystemMessage2(SystemMsg.YOUR_FORCE_HAS_INCREASED_TO_S1_LEVEL).addNumber(i));
  8542.  
  8543.         _increasedForce = i;
  8544.         sendEtcStatusUpdate();
  8545.     }
  8546.  
  8547.     private long _lastFalling;
  8548.  
  8549.     public boolean isFalling()
  8550.     {
  8551.         return System.currentTimeMillis() - _lastFalling < 5000;
  8552.     }
  8553.  
  8554.     public void falling(int height)
  8555.     {
  8556.         if(!Config.DAMAGE_FROM_FALLING || isDead() || isFlying() || isInWater() || isInBoat())
  8557.             return;
  8558.         _lastFalling = System.currentTimeMillis();
  8559.         int damage = (int) calcStat(Stats.FALL, getMaxHp() / 2000 * height, null, null);
  8560.         if(damage > 0)
  8561.         {
  8562.             int curHp = (int) getCurrentHp();
  8563.             if(curHp - damage < 1)
  8564.                 setCurrentHp(1, false);
  8565.             else
  8566.                 setCurrentHp(curHp - damage, false);
  8567.             sendPacket(new SystemMessage2(SystemMsg.YOU_RECEIVED_S1_DAMAGE_FROM_TAKING_A_HIGH_FALL).addNumber(damage));
  8568.         }
  8569.     }
  8570.  
  8571.     /**
  8572.      * Системные сообщения о текущем состоянии хп
  8573.      */
  8574.     @Override
  8575.     public void checkHpMessages(double curHp, double newHp)
  8576.     {
  8577.         //сюда пасивные скиллы
  8578.         int[] _hp = {
  8579.                 30,
  8580.                 30
  8581.         };
  8582.         int[] skills = {
  8583.                 290,
  8584.                 291
  8585.         };
  8586.  
  8587.         //сюда активные эффекты
  8588.         int[] _effects_skills_id = {
  8589.                 139,
  8590.                 176,
  8591.                 292,
  8592.                 292,
  8593.                 420
  8594.         };
  8595.         int[] _effects_hp = {
  8596.                 30,
  8597.                 30,
  8598.                 30,
  8599.                 60,
  8600.                 30
  8601.         };
  8602.  
  8603.         double percent = getMaxHp() / 100;
  8604.         double _curHpPercent = curHp / percent;
  8605.         double _newHpPercent = newHp / percent;
  8606.         boolean needsUpdate = false;
  8607.  
  8608.         //check for passive skills
  8609.         for(int i = 0; i < skills.length; i++)
  8610.         {
  8611.             int level = getSkillLevel(skills[i]);
  8612.             if(level > 0)
  8613.                 if(_curHpPercent > _hp[i] && _newHpPercent <= _hp[i])
  8614.                 {
  8615.                     sendPacket(new SystemMessage2(SystemMsg.SINCE_HP_HAS_DECREASED_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(skills[i], level));
  8616.                     needsUpdate = true;
  8617.                 }
  8618.                 else if(_curHpPercent <= _hp[i] && _newHpPercent > _hp[i])
  8619.                 {
  8620.                     sendPacket(new SystemMessage2(SystemMsg.SINCE_HP_HAS_INCREASED_THE_EFFECT_OF_S1_WILL_DISAPPEAR).addSkillName(skills[i], level));
  8621.                     needsUpdate = true;
  8622.                 }
  8623.         }
  8624.  
  8625.         //check for active effects
  8626.         for(Integer i = 0; i < _effects_skills_id.length; i++)
  8627.             if(getEffectList().getEffectsBySkillId(_effects_skills_id[i]) != null)
  8628.                 if(_curHpPercent > _effects_hp[i] && _newHpPercent <= _effects_hp[i])
  8629.                 {
  8630.                     sendPacket(new SystemMessage2(SystemMsg.SINCE_HP_HAS_DECREASED_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(_effects_skills_id[i], 1));
  8631.                     needsUpdate = true;
  8632.                 }
  8633.                 else if(_curHpPercent <= _effects_hp[i] && _newHpPercent > _effects_hp[i])
  8634.                 {
  8635.                     sendPacket(new SystemMessage2(SystemMsg.SINCE_HP_HAS_INCREASED_THE_EFFECT_OF_S1_WILL_DISAPPEAR).addSkillName(_effects_skills_id[i], 1));
  8636.                     needsUpdate = true;
  8637.                 }
  8638.  
  8639.         if(needsUpdate)
  8640.             sendChanges();
  8641.     }
  8642.  
  8643.     /**
  8644.      * Системные сообщения для темных эльфов о вкл/выкл ShadowSence (skill id = 294)
  8645.      */
  8646.     public void checkDayNightMessages()
  8647.     {
  8648.         int level = getSkillLevel(294);
  8649.         if(level > 0)
  8650.             if(GameTimeController.getInstance().isNowNight())
  8651.                 sendPacket(new SystemMessage2(SystemMsg.IT_IS_NOW_MIDNIGHT_AND_THE_EFFECT_OF_S1_CAN_BE_FELT).addSkillName(294, level));
  8652.             else
  8653.                 sendPacket(new SystemMessage2(SystemMsg.IT_IS_DAWN_AND_THE_EFFECT_OF_S1_WILL_NOW_DISAPPEAR).addSkillName(294, level));
  8654.         sendChanges();
  8655.     }
  8656.  
  8657.     public int getZoneMask()
  8658.     {
  8659.         return _zoneMask;
  8660.     }
  8661.  
  8662.     //TODO [G1ta0] переработать в лисенер?
  8663.     @Override
  8664.     protected void onUpdateZones(List<Zone> leaving, List<Zone> entering)
  8665.     {
  8666.         super.onUpdateZones(leaving, entering);
  8667.  
  8668.         if((leaving == null || leaving.isEmpty()) && (entering == null || entering.isEmpty()))
  8669.             return;
  8670.  
  8671.         boolean lastInCombatZone = (_zoneMask & ZONE_PVP_FLAG) == ZONE_PVP_FLAG;
  8672.         boolean lastInDangerArea = (_zoneMask & ZONE_ALTERED_FLAG) == ZONE_ALTERED_FLAG;
  8673.         boolean lastOnSiegeField = (_zoneMask & ZONE_SIEGE_FLAG) == ZONE_SIEGE_FLAG;
  8674.         boolean lastInPeaceZone = (_zoneMask & ZONE_PEACE_FLAG) == ZONE_PEACE_FLAG;
  8675.         //FIXME G1ta0 boolean lastInSSQZone = (_zoneMask & ZONE_SSQ_FLAG) == ZONE_SSQ_FLAG;
  8676.  
  8677.         boolean isInCombatZone = isInCombatZone();
  8678.         boolean isInDangerArea = isInDangerArea();
  8679.         boolean isOnSiegeField = isOnSiegeField();
  8680.         boolean isInPeaceZone = isInPeaceZone();
  8681.         boolean isInSSQZone = isInSSQZone();
  8682.  
  8683.         // обновляем компас, только если персонаж в мире
  8684.         int lastZoneMask = _zoneMask;
  8685.         _zoneMask = 0;
  8686.  
  8687.         if(isInCombatZone)
  8688.             _zoneMask |= ZONE_PVP_FLAG;
  8689.         if(isInDangerArea)
  8690.             _zoneMask |= ZONE_ALTERED_FLAG;
  8691.         if(isOnSiegeField)
  8692.             _zoneMask |= ZONE_SIEGE_FLAG;
  8693.         if(isInPeaceZone)
  8694.             _zoneMask |= ZONE_PEACE_FLAG;
  8695.         if(isInSSQZone)
  8696.             _zoneMask |= ZONE_SSQ_FLAG;
  8697.  
  8698.         if(lastZoneMask != _zoneMask)
  8699.             sendPacket(new ExSetCompassZoneCode(this));
  8700.  
  8701.         if(lastInCombatZone != isInCombatZone)
  8702.             broadcastRelationChanged();
  8703.  
  8704.         if(lastInDangerArea != isInDangerArea)
  8705.             sendPacket(new EtcStatusUpdate(this));
  8706.  
  8707.         if(lastOnSiegeField != isOnSiegeField)
  8708.         {
  8709.             broadcastRelationChanged();
  8710.             if(isOnSiegeField)
  8711.                 sendPacket(SystemMsg.YOU_HAVE_ENTERED_A_COMBAT_ZONE);
  8712.             else
  8713.             {
  8714.                 sendPacket(SystemMsg.YOU_HAVE_LEFT_A_COMBAT_ZONE);
  8715.                 /*if(!isTeleporting() && getPvpFlag() == 0)
  8716.                     startPvPFlag(null); */
  8717.             }
  8718.         }
  8719.  
  8720.         if(lastInPeaceZone != isInPeaceZone)
  8721.             if(isInPeaceZone)
  8722.             {
  8723.                 setRecomTimerActive(false);
  8724.                 if(getNevitSystem().isActive())
  8725.                     getNevitSystem().stopAdventTask(true);
  8726.                 startVitalityTask();
  8727.             }
  8728.             else
  8729.                 stopVitalityTask();
  8730.  
  8731.         if(isInWater())
  8732.             startWaterTask();
  8733.         else
  8734.             stopWaterTask();
  8735.     }
  8736.  
  8737.     public void startAutoSaveTask()
  8738.     {
  8739.         if(!Config.AUTOSAVE)
  8740.             return;
  8741.         if(_autoSaveTask == null)
  8742.             _autoSaveTask = AutoSaveManager.getInstance().addAutoSaveTask(this);
  8743.     }
  8744.  
  8745.     public void stopAutoSaveTask()
  8746.     {
  8747.         if(_autoSaveTask != null)
  8748.             _autoSaveTask.cancel(false);
  8749.         _autoSaveTask = null;
  8750.     }
  8751.  
  8752.     public void startVitalityTask()
  8753.     {
  8754.         if(!Config.ALT_VITALITY_ENABLED)
  8755.             return;
  8756.         if(_vitalityTask == null)
  8757.             _vitalityTask = LazyPrecisionTaskManager.getInstance().addVitalityRegenTask(this);
  8758.     }
  8759.  
  8760.     public void stopVitalityTask()
  8761.     {
  8762.         if(_vitalityTask != null)
  8763.             _vitalityTask.cancel(false);
  8764.         _vitalityTask = null;
  8765.     }
  8766.  
  8767.     public void stopPcBangPointsTask()
  8768.     {
  8769.         if(_pcCafePointsTask != null)
  8770.             _pcCafePointsTask.cancel(false);
  8771.         _pcCafePointsTask = null;
  8772.     }
  8773. //TODO тюряга
  8774.     public void startUnjailTask(Player player, int time)
  8775.     {
  8776.         if(time < 1)
  8777.         {
  8778.             return; // ибо нехуй
  8779.         }
  8780.  
  8781.         if(_unjailTask != null)
  8782.         {
  8783.             _unjailTask.cancel(false);
  8784.         }
  8785.  
  8786.         _unjailTask = ThreadPoolManager.getInstance().schedule(new UnJailTask(player), time * 60000);
  8787.     }
  8788.  
  8789.     public void stopUnjailTask()
  8790.     {
  8791.         if(_unjailTask != null)
  8792.             _unjailTask.cancel(false);
  8793.         _unjailTask = null;
  8794.     }
  8795.  
  8796.     @Override
  8797.     public void sendMessage(String message)
  8798.     {
  8799.         sendPacket(new SystemMessage(message));
  8800.     }
  8801.  
  8802.     private Location _lastClientPosition;
  8803.     private Location _lastServerPosition;
  8804.  
  8805.     public void setLastClientPosition(Location position)
  8806.     {
  8807.         _lastClientPosition = position;
  8808.     }
  8809.  
  8810.     public Location getLastClientPosition()
  8811.     {
  8812.         return _lastClientPosition;
  8813.     }
  8814.  
  8815.     public void setLastServerPosition(Location position)
  8816.     {
  8817.         _lastServerPosition = position;
  8818.     }
  8819.  
  8820.     public Location getLastServerPosition()
  8821.     {
  8822.         return _lastServerPosition;
  8823.     }
  8824.  
  8825.     private int _useSeed = 0;
  8826.  
  8827.     public void setUseSeed(int id)
  8828.     {
  8829.         _useSeed = id;
  8830.     }
  8831.  
  8832.     public int getUseSeed()
  8833.     {
  8834.         return _useSeed;
  8835.     }
  8836.  
  8837.     public int getRelation(Player target)
  8838.     {
  8839.         int result = 0;
  8840.  
  8841.         if(getClan() != null)
  8842.         {
  8843.             result |= RelationChanged.RELATION_CLAN_MEMBER;
  8844.             if(getClan() == target.getClan())
  8845.                 result |= RelationChanged.RELATION_CLAN_MATE;
  8846.             if(getClan().getAllyId() != 0)
  8847.                 result |= RelationChanged.RELATION_ALLY_MEMBER;
  8848.         }
  8849.  
  8850.         if(isClanLeader())
  8851.             result |= RelationChanged.RELATION_LEADER;
  8852.  
  8853.         Party party = getParty();
  8854.         if(party != null && party == target.getParty())
  8855.         {
  8856.             result |= RelationChanged.RELATION_HAS_PARTY;
  8857.  
  8858.             switch(party.getPartyMembers().indexOf(this))
  8859.             {
  8860.                 case 0:
  8861.                     result |= RelationChanged.RELATION_PARTYLEADER; // 0x10
  8862.                     break;
  8863.                 case 1:
  8864.                     result |= RelationChanged.RELATION_PARTY4; // 0x8
  8865.                     break;
  8866.                 case 2:
  8867.                     result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY2 + RelationChanged.RELATION_PARTY1; // 0x7
  8868.                     break;
  8869.                 case 3:
  8870.                     result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY2; // 0x6
  8871.                     break;
  8872.                 case 4:
  8873.                     result |= RelationChanged.RELATION_PARTY3 + RelationChanged.RELATION_PARTY1; // 0x5
  8874.                     break;
  8875.                 case 5:
  8876.                     result |= RelationChanged.RELATION_PARTY3; // 0x4
  8877.                     break;
  8878.                 case 6:
  8879.                     result |= RelationChanged.RELATION_PARTY2 + RelationChanged.RELATION_PARTY1; // 0x3
  8880.                     break;
  8881.                 case 7:
  8882.                     result |= RelationChanged.RELATION_PARTY2; // 0x2
  8883.                     break;
  8884.                 case 8:
  8885.                     result |= RelationChanged.RELATION_PARTY1; // 0x1
  8886.                     break;
  8887.             }
  8888.         }
  8889.  
  8890.         Clan clan1 = getClan();
  8891.         Clan clan2 = target.getClan();
  8892.         if(clan1 != null && clan2 != null)
  8893.         {
  8894.             if(target.getPledgeType() != Clan.SUBUNIT_ACADEMY && getPledgeType() != Clan.SUBUNIT_ACADEMY)
  8895.                 if(clan2.isAtWarWith(clan1.getClanId()))
  8896.                 {
  8897.                     result |= RelationChanged.RELATION_1SIDED_WAR;
  8898.                     if(clan1.isAtWarWith(clan2.getClanId()))
  8899.                         result |= RelationChanged.RELATION_MUTUAL_WAR;
  8900.                 }
  8901.             if(getBlockCheckerArena() != -1)
  8902.             {
  8903.                 result |= RelationChanged.RELATION_INSIEGE;
  8904.                 ArenaParticipantsHolder holder = HandysBlockCheckerManager.getInstance().getHolder(getBlockCheckerArena());
  8905.                 if(holder.getPlayerTeam(this) == 0)
  8906.                     result |= RelationChanged.RELATION_ENEMY;
  8907.                 else
  8908.                     result |= RelationChanged.RELATION_ALLY;
  8909.                 result |= RelationChanged.RELATION_ATTACKER;
  8910.             }
  8911.         }
  8912.  
  8913.         for(GlobalEvent e : getEvents())
  8914.             result =  e.getRelation(this, target, result);
  8915.  
  8916.         return result;
  8917.     }
  8918.  
  8919.     /**
  8920.      * 0=White, 1=Purple, 2=PurpleBlink
  8921.      */
  8922.     //protected int _pvpFlag;
  8923.  
  8924.     private Future<?> _PvPRegTask;
  8925.     private long _lastPvpAttack;
  8926.  
  8927.     public long getlastPvpAttack()
  8928.     {
  8929.         return _lastPvpAttack;
  8930.     }
  8931.  
  8932.     /*@Override
  8933.     public void startPvPFlag(Creature target)
  8934.     {
  8935.         if(_karma > 0)
  8936.             return;
  8937.  
  8938.         long startTime = System.currentTimeMillis();
  8939.         if(target != null && target.getPvpFlag() != 0)
  8940.             startTime -= Config.PVP_TIME / 2;
  8941.         if(_pvpFlag != 0 && _lastPvpAttack > startTime)
  8942.             return;
  8943.  
  8944.         _lastPvpAttack = startTime;
  8945.  
  8946.         updatePvPFlag(1);
  8947.  
  8948.         if(_PvPRegTask == null)
  8949.             _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
  8950.     }
  8951.  
  8952.     public void stopPvPFlag()
  8953.     {
  8954.         if(_PvPRegTask != null)
  8955.         {
  8956.             _PvPRegTask.cancel(false);
  8957.             _PvPRegTask = null;
  8958.         }
  8959.         updatePvPFlag(0);
  8960.     }
  8961.  
  8962.     public void updatePvPFlag(int value)
  8963.     {
  8964.         if(_handysBlockCheckerEventArena != -1)
  8965.             return;
  8966.         if(_pvpFlag == value)
  8967.             return;
  8968.  
  8969.         setPvpFlag(value);
  8970.  
  8971.         sendStatusUpdate(true, true, StatusUpdate.PVP_FLAG);
  8972.  
  8973.         broadcastRelationChanged();
  8974.     }
  8975.  
  8976.     public void setPvpFlag(int pvpFlag)
  8977.     {
  8978.         _pvpFlag = pvpFlag;
  8979.     }
  8980.  
  8981.     @Override
  8982.     public int getPvpFlag()
  8983.     {
  8984.         return _pvpFlag;
  8985.     }*/
  8986.  
  8987.     public boolean isInDuel()
  8988.     {
  8989.         return getEvent(DuelEvent.class) != null;
  8990.     }
  8991.  
  8992.     private Map<Integer, TamedBeastInstance> _tamedBeasts = new ConcurrentHashMap<Integer, TamedBeastInstance>();
  8993.  
  8994.     public Map<Integer, TamedBeastInstance> getTrainedBeasts()
  8995.     {
  8996.         return _tamedBeasts;
  8997.     }
  8998.  
  8999.     public void addTrainedBeast(TamedBeastInstance tamedBeast)
  9000.     {
  9001.         _tamedBeasts.put(tamedBeast.getObjectId(), tamedBeast);
  9002.     }
  9003.  
  9004.     public void removeTrainedBeast(int npcId)
  9005.     {
  9006.         _tamedBeasts.remove(npcId);
  9007.     }
  9008.  
  9009.     private long _lastAttackPacket = 0;
  9010.  
  9011.     public long getLastAttackPacket()
  9012.     {
  9013.         return _lastAttackPacket;
  9014.     }
  9015.  
  9016.     public void setLastAttackPacket()
  9017.     {
  9018.         _lastAttackPacket = System.currentTimeMillis();
  9019.     }
  9020.  
  9021.     private long _lastMovePacket = 0;
  9022.  
  9023.     public long getLastMovePacket()
  9024.     {
  9025.         return _lastMovePacket;
  9026.     }
  9027.  
  9028.     public void setLastMovePacket()
  9029.     {
  9030.         _lastMovePacket = System.currentTimeMillis();
  9031.     }
  9032.  
  9033.     public byte[] getKeyBindings()
  9034.     {
  9035.         return _keyBindings;
  9036.     }
  9037.  
  9038.     public void setKeyBindings(byte[] keyBindings)
  9039.     {
  9040.         if(keyBindings == null)
  9041.             keyBindings = ArrayUtils.EMPTY_BYTE_ARRAY;
  9042.         _keyBindings = keyBindings;
  9043.     }
  9044.  
  9045.     /**
  9046.      * Возвращает количество PcBangPoint'РѕРІ даного РёРіСЂРѕРєР°
  9047.      *
  9048.      * @return количество PcCafe Bang Points
  9049.      */
  9050.     public int getFamePoints()
  9051.     {
  9052.         return famePoints;
  9053.     }
  9054.  
  9055.     public void addFamePoints(int count)
  9056.     {
  9057.         famePoints += count;
  9058.         sendPacket(new ExPCCafePointInfo(this, count, 1, 2, 12));
  9059.         updateRank();
  9060.     }
  9061.  
  9062.     public void takeFamePoints(int count)
  9063.     {
  9064.         famePoints -= count;
  9065.  
  9066.         if(famePoints < 0)
  9067.         {
  9068.             count += famePoints;
  9069.             famePoints = 0;
  9070.         }
  9071.  
  9072.         sendPacket(new ExPCCafePointInfo(this, 0, 1, 2, 12));
  9073.         updateRank();
  9074.     }
  9075.  
  9076.     /**
  9077.      * Устанавливает режим трансформаии<BR>
  9078.      *
  9079.      * @param transformationId идентификатор трансформации
  9080.      *                         Известные режимы:<BR>
  9081.      *                         <li>0 - стандартный вид чара
  9082.      *                         <li>1 - Onyx Beast
  9083.      *                         <li>2 - Death Blader
  9084.      *                         <li>etc.
  9085.      */
  9086.     public void setTransformation(int transformationId)
  9087.     {
  9088.         if(transformationId == _transformationId || _transformationId != 0 && transformationId != 0)
  9089.             return;
  9090.  
  9091.         // Для каждой трансформации свой набор скилов
  9092.         if(transformationId == 0) // Обычная форма
  9093.         {
  9094.             // Останавливаем текущий эффект трансформации
  9095.             for(Effect effect : getEffectList().getAllEffects())
  9096.                 if(effect != null && effect.getEffectType() == EffectType.Transformation)
  9097.                 {
  9098.                     if (effect.calc() == 0) // Не обрываем Dispel
  9099.                         continue;
  9100.                     effect.exit();
  9101.                     preparateToTransform(effect.getSkill());
  9102.                     break;
  9103.                 }
  9104.  
  9105.             // Удаляем скилы трансформации
  9106.             if(!_transformationSkills.isEmpty())
  9107.             {
  9108.                 for(Skill s : _transformationSkills.values())
  9109.                     if(!s.isCommon() && !SkillAcquireHolder.getInstance().isSkillPossible(this, s) && !s.isHeroic())
  9110.                         super.removeSkill(s);
  9111.                 _transformationSkills.clear();
  9112.             }
  9113.         }
  9114.         else
  9115.         {
  9116.             if(!isCursedWeaponEquipped())
  9117.             {
  9118.                 // Добавляем скилы трансформации
  9119.                 for(Effect effect : getEffectList().getAllEffects())
  9120.                     if(effect != null && effect.getEffectType() == EffectType.Transformation)
  9121.                     {
  9122.                         if(effect.getSkill() instanceof Transformation && ((Transformation) effect.getSkill()).isDisguise)
  9123.                         {
  9124.                             for(Skill s : getAllSkills())
  9125.                                 if(s != null && (s.isActive() || s.isToggle()))
  9126.                                     _transformationSkills.put(s.getId(), s);
  9127.                         }
  9128.                         else
  9129.                             for(AddedSkill s : effect.getSkill().getAddedSkills())
  9130.                                 if(s.level == 0) // трансформация позволяет пользоваться обычным скиллом
  9131.                                 {
  9132.                                     int s2 = getSkillLevel(s.id);
  9133.                                     if(s2 > 0)
  9134.                                         _transformationSkills.put(s.id, SkillTable.getInstance().getInfo(s.id, s2));
  9135.                                 }
  9136.                                 else if(s.level == -2) // XXX: дикий изжоп для скиллов зависящих от уровня игрока
  9137.                                 {
  9138.                                     int learnLevel = Math.max(effect.getSkill().getMagicLevel(), 40);
  9139.                                     int maxLevel = SkillTable.getInstance().getBaseLevel(s.id);
  9140.                                     int curSkillLevel = 1;
  9141.                                     if(maxLevel > 3)
  9142.                                         curSkillLevel += getLevel() - learnLevel;
  9143.                                     else
  9144.                                         curSkillLevel += (getLevel() - learnLevel) / ((76 - learnLevel) / maxLevel); // не спрашивайте меня что это такое
  9145.                                     curSkillLevel = Math.min(Math.max(curSkillLevel, 1), maxLevel);
  9146.                                     _transformationSkills.put(s.id, SkillTable.getInstance().getInfo(s.id, curSkillLevel));
  9147.                                 }
  9148.                                 else
  9149.                                     _transformationSkills.put(s.id, s.getSkill());
  9150.                         preparateToTransform(effect.getSkill());
  9151.                         break;
  9152.                     }
  9153.             }
  9154.             else
  9155.                 preparateToTransform(null);
  9156.  
  9157.             if(!isInOlympiadMode() && !isCursedWeaponEquipped() && _hero && getBaseClassId() == getActiveClassId())
  9158.             {
  9159.                 // Добавляем хиро скиллы проклятому трансформу
  9160.                 _transformationSkills.put(395, SkillTable.getInstance().getInfo(395, 1));
  9161.                 _transformationSkills.put(396, SkillTable.getInstance().getInfo(396, 1));
  9162.                 _transformationSkills.put(1374, SkillTable.getInstance().getInfo(1374, 1));
  9163.                 _transformationSkills.put(1375, SkillTable.getInstance().getInfo(1375, 1));
  9164.                 _transformationSkills.put(1376, SkillTable.getInstance().getInfo(1376, 1));
  9165.             }
  9166.  
  9167.             for(Skill s : _transformationSkills.values())
  9168.                 addSkill(s, false);
  9169.         }
  9170.  
  9171.         _transformationId = transformationId;
  9172.  
  9173.         sendPacket(new ExBasicActionList(this));
  9174.         sendPacket(new SkillList(this));
  9175.         sendPacket(new ShortCutInit(this));
  9176.         for(int shotId : getAutoSoulShot())
  9177.             sendPacket(new ExAutoSoulShot(shotId, true));
  9178.         broadcastUserInfo(true);
  9179.     }
  9180.  
  9181.     private void preparateToTransform(Skill transSkill)
  9182.     {
  9183.         if(transSkill == null || !transSkill.isBaseTransformation())
  9184.         {
  9185.             // Останавливаем тугл скиллы
  9186.             for(Effect effect : getEffectList().getAllEffects())
  9187.                 if(effect != null && effect.getSkill().isToggle())
  9188.                     effect.exit();
  9189.         }
  9190.     }
  9191.  
  9192.     public boolean isInFlyingTransform()
  9193.     {
  9194.         return _transformationId == 8 || _transformationId == 9 || _transformationId == 260;
  9195.     }
  9196.  
  9197.     public boolean isInMountTransform()
  9198.     {
  9199.         return _transformationId == 106 || _transformationId == 109 || _transformationId == 110 || _transformationId == 20001;
  9200.     }
  9201.  
  9202.     /**
  9203.      * Возвращает режим трансформации
  9204.      *
  9205.      * @return ID режима трансформации
  9206.      */
  9207.     public int getTransformation()
  9208.     {
  9209.         return _transformationId;
  9210.     }
  9211.  
  9212.     /**
  9213.      * Возвращает имя трансформации
  9214.      *
  9215.      * @return String
  9216.      */
  9217.     public String getTransformationName()
  9218.     {
  9219.         return _transformationName;
  9220.     }
  9221.  
  9222.     /**
  9223.      * Устанавливает имя трансформаии
  9224.      *
  9225.      * @param name имя трансформации
  9226.      */
  9227.     public void setTransformationName(String name)
  9228.     {
  9229.         _transformationName = name;
  9230.     }
  9231.  
  9232.     /**
  9233.      * Устанавливает шаблон трансформации, используется для определения коллизий
  9234.      *
  9235.      * @param template ID шаблона
  9236.      */
  9237.     public void setTransformationTemplate(int template)
  9238.     {
  9239.         _transformationTemplate = template;
  9240.     }
  9241.  
  9242.     /**
  9243.      * Возвращает шаблон трансформации, используется для определения коллизий
  9244.      *
  9245.      * @return NPC ID
  9246.      */
  9247.     public int getTransformationTemplate()
  9248.     {
  9249.         return _transformationTemplate;
  9250.     }
  9251.  
  9252.     /**
  9253.      * Возвращает коллекцию скиллов, с учетом текущей трансформации
  9254.      */
  9255.     @Override
  9256.     public final Collection<Skill> getAllSkills()
  9257.     {
  9258.         // Трансформация неактивна
  9259.         if(_transformationId == 0)
  9260.             return super.getAllSkills();
  9261.  
  9262.         // Трансформация активна
  9263.         Map<Integer, Skill> tempSkills = new HashMap<Integer, Skill>();
  9264.         for(Skill s : super.getAllSkills())
  9265.             if(s != null && !s.isActive() && !s.isToggle())
  9266.                 tempSkills.put(s.getId(), s);
  9267.         tempSkills.putAll(_transformationSkills); // Добавляем к пассивкам скилы текущей трансформации
  9268.         return tempSkills.values();
  9269.     }
  9270.  
  9271.     public void setAgathion(int id)
  9272.     {
  9273.         if(_agathionId == id)
  9274.             return;
  9275.  
  9276.         _agathionId = id;
  9277.         broadcastCharInfo();
  9278.     }
  9279.  
  9280.     public int getAgathionId()
  9281.     {
  9282.         return _agathionId;
  9283.     }
  9284.  
  9285.     private Location _groundSkillLoc;
  9286.  
  9287.     public void setGroundSkillLoc(Location location)
  9288.     {
  9289.         _groundSkillLoc = location;
  9290.     }
  9291.  
  9292.     public Location getGroundSkillLoc()
  9293.     {
  9294.         return _groundSkillLoc;
  9295.     }
  9296.  
  9297.     /**
  9298.      * Персонаж в процессе выхода из игры
  9299.      *
  9300.      * @return возвращает true если процесс выхода уже начался
  9301.      */
  9302.     public boolean isLogoutStarted()
  9303.     {
  9304.         return _isLogout.get();
  9305.     }
  9306.  
  9307.     public void setOfflineMode(boolean val)
  9308.     {
  9309.         if(!val)
  9310.             unsetVar("offline");
  9311.         _offline = val;
  9312.     }
  9313.  
  9314.     public boolean isInOfflineMode()
  9315.     {
  9316.         return _offline;
  9317.     }
  9318.  
  9319.     public void saveTradeList()
  9320.     {
  9321.         String val = "";
  9322.  
  9323.         if(_sellList == null || _sellList.isEmpty())
  9324.             unsetVar("selllist");
  9325.         else
  9326.         {
  9327.             for(TradeItem i : _sellList)
  9328.                 val += i.getObjectId() + ";" + i.getCount() + ";" + i.getOwnersPrice() + ":";
  9329.             setVar("selllist", val, -1);
  9330.             val = "";
  9331.             if(_tradeList != null && getSellStoreName() != null)
  9332.                 setVar("sellstorename", getSellStoreName(), -1);
  9333.         }
  9334.  
  9335.         if(_packageSellList == null || _packageSellList.isEmpty())
  9336.             unsetVar("packageselllist");
  9337.         else
  9338.         {
  9339.             for(TradeItem i : _packageSellList)
  9340.                 val += i.getObjectId() + ";" + i.getCount() + ";" + i.getOwnersPrice() + ":";
  9341.             setVar("packageselllist", val, -1);
  9342.             val = "";
  9343.             if(_tradeList != null && getSellStoreName() != null)
  9344.                 setVar("sellstorename", getSellStoreName(), -1);
  9345.         }
  9346.  
  9347.         if(_buyList == null || _buyList.isEmpty())
  9348.             unsetVar("buylist");
  9349.         else
  9350.         {
  9351.             for(TradeItem i : _buyList)
  9352.                 val += i.getItemId() + ";" + i.getCount() + ";" + i.getOwnersPrice() + ":";
  9353.             setVar("buylist", val, -1);
  9354.             val = "";
  9355.             if(_tradeList != null && getBuyStoreName() != null)
  9356.                 setVar("buystorename", getBuyStoreName(), -1);
  9357.         }
  9358.  
  9359.         if(_createList == null || _createList.isEmpty())
  9360.             unsetVar("createlist");
  9361.         else
  9362.         {
  9363.             for(ManufactureItem i : _createList)
  9364.                 val += i.getRecipeId() + ";" + i.getCost() + ":";
  9365.             setVar("createlist", val, -1);
  9366.             if(getManufactureName() != null)
  9367.                 setVar("manufacturename", getManufactureName(), -1);
  9368.         }
  9369.     }
  9370.  
  9371.     public void restoreTradeList()
  9372.     {
  9373.         String var;
  9374.         var = getVar("selllist");
  9375.         if(var != null)
  9376.         {
  9377.             _sellList = new CopyOnWriteArrayList<TradeItem>();
  9378.             String[] items = var.split(":");
  9379.             for(String item : items)
  9380.             {
  9381.                 if(item.equals(""))
  9382.                     continue;
  9383.                 String[] values = item.split(";");
  9384.                 if(values.length < 3)
  9385.                     continue;
  9386.  
  9387.                 int oId = Integer.parseInt(values[0]);
  9388.                 long count = Long.parseLong(values[1]);
  9389.                 long price = Long.parseLong(values[2]);
  9390.  
  9391.                 ItemInstance itemToSell = getInventory().getItemByObjectId(oId);
  9392.  
  9393.                 if(count < 1 || itemToSell == null)
  9394.                     continue;
  9395.  
  9396.                 if(count > itemToSell.getCount())
  9397.                     count = itemToSell.getCount();
  9398.  
  9399.                 TradeItem i = new TradeItem(itemToSell);
  9400.                 i.setCount(count);
  9401.                 i.setOwnersPrice(price);
  9402.  
  9403.                 _sellList.add(i);
  9404.             }
  9405.             var = getVar("sellstorename");
  9406.             if(var != null)
  9407.                 setSellStoreName(var);
  9408.         }
  9409.         var = getVar("packageselllist");
  9410.         if(var != null)
  9411.         {
  9412.             _packageSellList = new CopyOnWriteArrayList<TradeItem>();
  9413.             String[] items = var.split(":");
  9414.             for(String item : items)
  9415.             {
  9416.                 if(item.equals(""))
  9417.                     continue;
  9418.                 String[] values = item.split(";");
  9419.                 if(values.length < 3)
  9420.                     continue;
  9421.  
  9422.                 int oId = Integer.parseInt(values[0]);
  9423.                 long count = Long.parseLong(values[1]);
  9424.                 long price = Long.parseLong(values[2]);
  9425.  
  9426.                 ItemInstance itemToSell = getInventory().getItemByObjectId(oId);
  9427.  
  9428.                 if(count < 1 || itemToSell == null)
  9429.                     continue;
  9430.  
  9431.                 if(count > itemToSell.getCount())
  9432.                     count = itemToSell.getCount();
  9433.  
  9434.                 TradeItem i = new TradeItem(itemToSell);
  9435.                 i.setCount(count);
  9436.                 i.setOwnersPrice(price);
  9437.  
  9438.                 _packageSellList.add(i);
  9439.             }
  9440.             var = getVar("sellstorename");
  9441.             if(var != null)
  9442.                 setSellStoreName(var);
  9443.         }
  9444.         var = getVar("buylist");
  9445.         if(var != null)
  9446.         {
  9447.             _buyList = new CopyOnWriteArrayList<TradeItem>();
  9448.             String[] items = var.split(":");
  9449.             for(String item : items)
  9450.             {
  9451.                 if(item.equals(""))
  9452.                     continue;
  9453.                 String[] values = item.split(";");
  9454.                 if(values.length < 3)
  9455.                     continue;
  9456.                 TradeItem i = new TradeItem();
  9457.                 i.setItemId(Integer.parseInt(values[0]));
  9458.                 i.setCount(Long.parseLong(values[1]));
  9459.                 i.setOwnersPrice(Long.parseLong(values[2]));
  9460.                 _buyList.add(i);
  9461.             }
  9462.             var = getVar("buystorename");
  9463.             if(var != null)
  9464.                 setBuyStoreName(var);
  9465.         }
  9466.         var = getVar("createlist");
  9467.         if(var != null)
  9468.         {
  9469.             _createList = new CopyOnWriteArrayList<ManufactureItem>();
  9470.             String[] items = var.split(":");
  9471.             for(String item : items)
  9472.             {
  9473.                 if(item.equals(""))
  9474.                     continue;
  9475.                 String[] values = item.split(";");
  9476.                 if(values.length < 2)
  9477.                     continue;
  9478.                 int recId = Integer.parseInt(values[0]);
  9479.                 long price = Long.parseLong(values[1]);
  9480.                 if(findRecipe(recId))
  9481.                     _createList.add(new ManufactureItem(recId, price));
  9482.             }
  9483.             var = getVar("manufacturename");
  9484.             if(var != null)
  9485.                 setManufactureName(var);
  9486.         }
  9487.     }
  9488.  
  9489.     public void restoreRecipeBook()
  9490.     {
  9491.         Connection con = null;
  9492.         PreparedStatement statement = null;
  9493.         ResultSet rset = null;
  9494.         try
  9495.         {
  9496.             con = DatabaseFactory.getInstance().getConnection();
  9497.             statement = con.prepareStatement("SELECT id FROM character_recipebook WHERE char_id=?");
  9498.             statement.setInt(1, getObjectId());
  9499.             rset = statement.executeQuery();
  9500.  
  9501.             while(rset.next())
  9502.             {
  9503.                 int id = rset.getInt("id");
  9504.                 Recipe recipe = RecipeHolder.getInstance().getRecipeByRecipeId(id);
  9505.                 registerRecipe(recipe, false);
  9506.             }
  9507.         }
  9508.         catch(Exception e)
  9509.         {
  9510.             _log.warn("count not recipe skills:" + e);
  9511.             _log.error("", e);
  9512.         }
  9513.         finally
  9514.         {
  9515.             DbUtils.closeQuietly(con, statement, rset);
  9516.         }
  9517.     }
  9518.  
  9519.     public DecoyInstance getDecoy()
  9520.     {
  9521.         return _decoy;
  9522.     }
  9523.  
  9524.     public void setDecoy(DecoyInstance decoy)
  9525.     {
  9526.         _decoy = decoy;
  9527.     }
  9528.  
  9529.     public int getMountType()
  9530.     {
  9531.         switch(getMountNpcId())
  9532.         {
  9533.             case PetDataTable.STRIDER_WIND_ID:
  9534.             case PetDataTable.STRIDER_STAR_ID:
  9535.             case PetDataTable.STRIDER_TWILIGHT_ID:
  9536.             case PetDataTable.RED_STRIDER_WIND_ID:
  9537.             case PetDataTable.RED_STRIDER_STAR_ID:
  9538.             case PetDataTable.RED_STRIDER_TWILIGHT_ID:
  9539.             case PetDataTable.GUARDIANS_STRIDER_ID:
  9540.                 return 1;
  9541.             case PetDataTable.WYVERN_ID:
  9542.                 return 2;
  9543.             case PetDataTable.WGREAT_WOLF_ID:
  9544.             case PetDataTable.FENRIR_WOLF_ID:
  9545.             case PetDataTable.WFENRIR_WOLF_ID:
  9546.                 return 3;
  9547.         }
  9548.         return 0;
  9549.     }
  9550.  
  9551.     @Override
  9552.     public double getColRadius()
  9553.     {
  9554.         if (getTransformation() != 0)
  9555.         {
  9556.             final int template = getTransformationTemplate();
  9557.             if (template != 0)
  9558.             {
  9559.                 final NpcTemplate npcTemplate = NpcHolder.getInstance().getTemplate(template);
  9560.                 if (npcTemplate != null)
  9561.                     return npcTemplate.collisionRadius;
  9562.             }
  9563.         }
  9564.         else if (isMounted())
  9565.         {
  9566.             final int mountTemplate = getMountNpcId();
  9567.             if (mountTemplate != 0)
  9568.             {
  9569.                 final NpcTemplate mountNpcTemplate = NpcHolder.getInstance().getTemplate(mountTemplate);
  9570.                 if (mountNpcTemplate != null)
  9571.                     return mountNpcTemplate.collisionRadius;
  9572.             }
  9573.         }
  9574.         return getBaseTemplate().collisionRadius;
  9575.     }
  9576.  
  9577.     @Override
  9578.     public double getColHeight()
  9579.     {
  9580.         if (getTransformation() != 0)
  9581.         {
  9582.             final int template = getTransformationTemplate();
  9583.             if (template != 0)
  9584.             {
  9585.                 final NpcTemplate npcTemplate = NpcHolder.getInstance().getTemplate(template);
  9586.                 if (npcTemplate != null)
  9587.                     return npcTemplate.collisionHeight;
  9588.             }
  9589.         }
  9590.         else if (isMounted())
  9591.         {
  9592.             final int mountTemplate = getMountNpcId();
  9593.             if (mountTemplate != 0)
  9594.             {
  9595.                 final NpcTemplate mountNpcTemplate = NpcHolder.getInstance().getTemplate(mountTemplate);
  9596.                 if (mountNpcTemplate != null)
  9597.                     return mountNpcTemplate.collisionHeight;
  9598.             }
  9599.         }
  9600.         return getBaseTemplate().collisionHeight;
  9601.     }
  9602.  
  9603.     @Override
  9604.     public void setReflection(Reflection reflection)
  9605.     {
  9606.         if(getReflection() == reflection)
  9607.             return;
  9608.  
  9609.         super.setReflection(reflection);
  9610.  
  9611.         if(_summon != null && !_summon.isDead())
  9612.             _summon.setReflection(reflection);
  9613.  
  9614.         if(reflection != ReflectionManager.DEFAULT)
  9615.         {
  9616.             String var = getVar("reflection");
  9617.             if(var == null || !var.equals(String.valueOf(reflection.getId())))
  9618.                 setVar("reflection", String.valueOf(reflection.getId()), -1);
  9619.         }
  9620.         else
  9621.             unsetVar("reflection");
  9622.  
  9623.         if(getActiveClass() != null)
  9624.         {
  9625.             getInventory().validateItems();
  9626.             // Для квеста _129_PailakaDevilsLegacy
  9627.             if(getPet() != null && (getPet().getNpcId() == 14916 || getPet().getNpcId() == 14917))
  9628.                 getPet().unSummon();
  9629.         }
  9630.     }
  9631.  
  9632.     public boolean isTerritoryFlagEquipped()
  9633.     {
  9634.         ItemInstance weapon = getActiveWeaponInstance();
  9635.         return weapon != null && weapon.getTemplate().isTerritoryFlag();
  9636.     }
  9637.  
  9638.     private int _buyListId;
  9639.  
  9640.     public void setBuyListId(int listId)
  9641.     {
  9642.         _buyListId = listId;
  9643.     }
  9644.  
  9645.     public int getBuyListId()
  9646.     {
  9647.         return _buyListId;
  9648.     }
  9649.  
  9650.     public int getFame()
  9651.     {
  9652.         return _fame;
  9653.     }
  9654.  
  9655.     public void setFame(int fame, String log)
  9656.     {
  9657.         fame = Math.min(Config.LIM_FAME, fame);
  9658.         if(log != null && !log.isEmpty())
  9659.             Log.add(_name + "|" + (fame - _fame) + "|" + fame + "|" + log, "fame");
  9660.         if(fame > _fame)
  9661.             sendPacket(new SystemMessage2(SystemMsg.YOU_HAVE_ACQUIRED_S1_REPUTATION_SCORE).addNumber(fame - _fame));
  9662.         _fame = fame;
  9663.         sendChanges();
  9664.     }
  9665.  
  9666.     public int getVitalityLevel(boolean blessActive)
  9667.     {
  9668.         return Config.ALT_VITALITY_ENABLED ? (blessActive ? 4 : _vitalityLevel) : 0;
  9669.     }
  9670.  
  9671.     public double getVitality()
  9672.     {
  9673.         return Config.ALT_VITALITY_ENABLED ? _vitality : 0;
  9674.     }
  9675.  
  9676.     public void addVitality(double val)
  9677.     {
  9678.         setVitality(getVitality() + val);
  9679.     }
  9680.  
  9681.     public void setVitality(double newVitality)
  9682.     {
  9683.         if(!Config.ALT_VITALITY_ENABLED)
  9684.         {
  9685.             return;
  9686.         }
  9687.        
  9688.         newVitality = Math.max(Math.min(newVitality, Config.VITALITY_LEVELS[4]), 0);
  9689.         if(newVitality >= _vitality || getLevel() >= 10)
  9690.         {
  9691.             if(newVitality != _vitality)
  9692.             {
  9693.                 if(newVitality == 0)
  9694.                 {
  9695.                     sendPacket(SystemMsg.VITALITY_IS_FULLY_EXHAUSTED);
  9696.                 }
  9697.                 else if(newVitality == Config.VITALITY_LEVELS[4])
  9698.                 {
  9699.                     sendPacket(SystemMsg.YOUR_VITALITY_IS_AT_MAXIMUM);
  9700.                 }
  9701.             }
  9702.             _vitality = newVitality;
  9703.         }
  9704.        
  9705.         int newLevel = 0;
  9706.         if(_vitality >= Config.VITALITY_LEVELS[3])
  9707.         {
  9708.             newLevel = 4;
  9709.         }
  9710.         else if(_vitality >= Config.VITALITY_LEVELS[2])
  9711.         {
  9712.             newLevel = 3;
  9713.         }
  9714.         else if(_vitality >= Config.VITALITY_LEVELS[1])
  9715.         {
  9716.             newLevel = 2;
  9717.         }
  9718.         else if(_vitality >= Config.VITALITY_LEVELS[0])
  9719.         {
  9720.             newLevel = 1;
  9721.         }
  9722.        
  9723.         if(_vitalityLevel > newLevel)
  9724.             getNevitSystem().addPoints(900); //TODO: Количество от балды.
  9725.  
  9726.         if(_vitalityLevel != newLevel)
  9727.         {
  9728.             if(_vitalityLevel != -1) // при ините чара сообщения не шлём
  9729.             {
  9730.                 sendPacket(newLevel < _vitalityLevel ? SystemMsg.VITALITY_HAS_DECREASED : SystemMsg.VITALITY_HAS_INCREASED);
  9731.             }
  9732.             _vitalityLevel = newLevel;
  9733.             sendUserInfo(false);
  9734.         }
  9735.  
  9736.         sendPacket(new ExVitalityPointInfo((int) _vitality));
  9737.     }
  9738.  
  9739.     private final int _incorrectValidateCount = 0;
  9740.  
  9741.     public int getIncorrectValidateCount()
  9742.     {
  9743.         return _incorrectValidateCount;
  9744.     }
  9745.  
  9746.     public int setIncorrectValidateCount(int count)
  9747.     {
  9748.         return _incorrectValidateCount;
  9749.     }
  9750.  
  9751.     public int getExpandInventory()
  9752.     {
  9753.         return _expandInventory;
  9754.     }
  9755.  
  9756.     public void setExpandInventory(int inventory)
  9757.     {
  9758.         _expandInventory = inventory;
  9759.     }
  9760.  
  9761.     public int getExpandWarehouse()
  9762.     {
  9763.         return _expandWarehouse;
  9764.     }
  9765.  
  9766.     public void setExpandWarehouse(int warehouse)
  9767.     {
  9768.         _expandWarehouse = warehouse;
  9769.     }
  9770.  
  9771.     public boolean isNotShowBuffAnim()
  9772.     {
  9773.         return _notShowBuffAnim;
  9774.     }
  9775.  
  9776.     public void setNotShowBuffAnim(boolean value)
  9777.     {
  9778.         _notShowBuffAnim = value;
  9779.     }
  9780.  
  9781.     public void enterMovieMode()
  9782.     {
  9783.         if(isInMovie()) //already in movie
  9784.             return;
  9785.  
  9786.         setTarget(null);
  9787.         stopMove();
  9788.         setIsInMovie(true);
  9789.         sendPacket(new CameraMode(1));
  9790.     }
  9791.  
  9792.     public void leaveMovieMode()
  9793.     {
  9794.         setIsInMovie(false);
  9795.         sendPacket(new CameraMode(0));
  9796.         broadcastCharInfo();
  9797.     }
  9798.  
  9799.     public void specialCamera(GameObject target, int dist, int yaw, int pitch, int time, int duration)
  9800.     {
  9801.         sendPacket(new SpecialCamera(target.getObjectId(), dist, yaw, pitch, time, duration));
  9802.     }
  9803.  
  9804.     public void specialCamera(GameObject target, int dist, int yaw, int pitch, int time, int duration, int turn, int rise, int widescreen, int unk)
  9805.     {
  9806.         sendPacket(new SpecialCamera(target.getObjectId(), dist, yaw, pitch, time, duration, turn, rise, widescreen ,unk));
  9807.     }
  9808.  
  9809.     private int _movieId = 0;
  9810.     private boolean _isInMovie;
  9811.  
  9812.     public void setMovieId(int id)
  9813.     {
  9814.         _movieId = id;
  9815.     }
  9816.  
  9817.     public int getMovieId()
  9818.     {
  9819.         return _movieId;
  9820.     }
  9821.  
  9822.     public boolean isInMovie()
  9823.     {
  9824.         return _isInMovie;
  9825.     }
  9826.  
  9827.     public void setIsInMovie(boolean state)
  9828.     {
  9829.         _isInMovie = state;
  9830.     }
  9831.  
  9832.     public void showQuestMovie(SceneMovie movie)
  9833.     {
  9834.         if(isInMovie()) //already in movie
  9835.             return;
  9836.  
  9837.         sendActionFailed();
  9838.         setTarget(null);
  9839.         stopMove();
  9840.         setMovieId(movie.getId());
  9841.         setIsInMovie(true);
  9842.         sendPacket(movie.packet(this));
  9843.     }
  9844.  
  9845.     public void showQuestMovie(int movieId)
  9846.     {
  9847.         if(isInMovie()) //already in movie
  9848.             return;
  9849.  
  9850.         sendActionFailed();
  9851.         setTarget(null);
  9852.         stopMove();
  9853.         setMovieId(movieId);
  9854.         setIsInMovie(true);
  9855.         sendPacket(new ExStartScenePlayer(movieId));
  9856.     }
  9857.  
  9858.     public void setAutoLoot(boolean enable)
  9859.     {
  9860.         if(Config.AUTO_LOOT_INDIVIDUAL)
  9861.         {
  9862.             _autoLoot = enable;
  9863.             setVar("AutoLoot", String.valueOf(enable), -1);
  9864.         }
  9865.     }
  9866.  
  9867.     public void setAutoLootHerbs(boolean enable)
  9868.     {
  9869.         if(Config.AUTO_LOOT_INDIVIDUAL)
  9870.         {
  9871.             AutoLootHerbs = enable;
  9872.             setVar("AutoLootHerbs", String.valueOf(enable), -1);
  9873.         }
  9874.     }
  9875.  
  9876.     public boolean isAutoLootEnabled()
  9877.     {
  9878.         return _autoLoot;
  9879.     }
  9880.  
  9881.     public boolean isAutoLootHerbsEnabled()
  9882.     {
  9883.         return AutoLootHerbs;
  9884.     }
  9885.  
  9886.     public final void reName(String name, boolean saveToDB)
  9887.     {
  9888.         setName(name);
  9889.         if(saveToDB)
  9890.             saveNameToDB();
  9891.         broadcastCharInfo();
  9892.     }
  9893.  
  9894.     public final void reName(String name)
  9895.     {
  9896.         reName(name, false);
  9897.     }
  9898.  
  9899.     public final void saveNameToDB()
  9900.     {
  9901.         Connection con = null;
  9902.         PreparedStatement st = null;
  9903.         try
  9904.         {
  9905.             con = DatabaseFactory.getInstance().getConnection();
  9906.             st = con.prepareStatement("UPDATE characters SET char_name = ? WHERE obj_Id = ?");
  9907.             st.setString(1, getName());
  9908.             st.setInt(2, getObjectId());
  9909.             st.executeUpdate();
  9910.         }
  9911.         catch(Exception e)
  9912.         {
  9913.             _log.error("", e);
  9914.         }
  9915.         finally
  9916.         {
  9917.             DbUtils.closeQuietly(con, st);
  9918.         }
  9919.     }
  9920.  
  9921.     @Override
  9922.     public Player getPlayer()
  9923.     {
  9924.         return this;
  9925.     }
  9926.  
  9927.     private List<String> getStoredBypasses(boolean bbs)
  9928.     {
  9929.         if(bbs)
  9930.         {
  9931.             if(bypasses_bbs == null)
  9932.                 bypasses_bbs = new LazyArrayList<String>();
  9933.             return bypasses_bbs;
  9934.         }
  9935.         if(bypasses == null)
  9936.             bypasses = new LazyArrayList<String>();
  9937.         return bypasses;
  9938.     }
  9939.  
  9940.     public void cleanBypasses(boolean bbs)
  9941.     {
  9942.         List<String> bypassStorage = getStoredBypasses(bbs);
  9943.         synchronized(bypassStorage)
  9944.         {
  9945.             bypassStorage.clear();
  9946.         }
  9947.     }
  9948.  
  9949.     public String encodeBypasses(String htmlCode, boolean bbs)
  9950.     {
  9951.         List<String> bypassStorage = getStoredBypasses(bbs);
  9952.         synchronized(bypassStorage)
  9953.         {
  9954.             return BypassManager.encode(htmlCode, bypassStorage, bbs);
  9955.         }
  9956.     }
  9957.  
  9958.     public DecodedBypass decodeBypass(String bypass)
  9959.     {
  9960.         BypassType bpType = BypassManager.getBypassType(bypass);
  9961.         boolean bbs = bpType == BypassType.ENCODED_BBS || bpType == BypassType.SIMPLE_BBS;
  9962.         List<String> bypassStorage = getStoredBypasses(bbs);
  9963.         if(bpType == BypassType.ENCODED || bpType == BypassType.ENCODED_BBS)
  9964.             return BypassManager.decode(bypass, bypassStorage, bbs, this);
  9965.         if(bpType == BypassType.SIMPLE)
  9966.             return new DecodedBypass(bypass, false).trim();
  9967.         if(bpType == BypassType.SIMPLE_BBS && !bypass.startsWith("_bbsscripts"))
  9968.             return new DecodedBypass(bypass, true).trim();
  9969.         ICommunityBoardHandler handler = CommunityBoardManager.getInstance().getCommunityHandler(bypass);
  9970.         if(handler != null)
  9971.             return new DecodedBypass(bypass, handler).trim();
  9972.         _log.warn("Direct access to bypass: " + bypass + " / Player: " + getName());
  9973.         return null;
  9974.     }
  9975.  
  9976.     public int getTalismanCount()
  9977.     {
  9978.         return (int) calcStat(Stats.TALISMANS_LIMIT, 0, null, null);
  9979.     }
  9980.  
  9981.     public boolean getOpenCloak()
  9982.     {
  9983.         if(Config.ALT_OPEN_CLOAK_SLOT)
  9984.             return true;
  9985.         return (int) calcStat(Stats.CLOAK_SLOT, 0, null, null) > 0;
  9986.     }
  9987.  
  9988.     public final void disableDrop(int time)
  9989.     {
  9990.         _dropDisabled = System.currentTimeMillis() + time;
  9991.     }
  9992.  
  9993.     public final boolean isDropDisabled()
  9994.     {
  9995.         return _dropDisabled > System.currentTimeMillis();
  9996.     }
  9997.  
  9998.     private ItemInstance _petControlItem = null;
  9999.  
  10000.     public void setPetControlItem(int itemObjId)
  10001.     {
  10002.         setPetControlItem(getInventory().getItemByObjectId(itemObjId));
  10003.     }
  10004.  
  10005.     public void setPetControlItem(ItemInstance item)
  10006.     {
  10007.         _petControlItem = item;
  10008.     }
  10009.  
  10010.     public ItemInstance getPetControlItem()
  10011.     {
  10012.         return _petControlItem;
  10013.     }
  10014.  
  10015.     private AtomicBoolean isActive = new AtomicBoolean();
  10016.  
  10017.     public boolean isActive()
  10018.     {
  10019.         return isActive.get();
  10020.     }
  10021.  
  10022.     public void setActive()
  10023.     {
  10024.         setNonAggroTime(0);
  10025.  
  10026.         if(isActive.getAndSet(true))
  10027.             return;
  10028.  
  10029.         onActive();
  10030.     }
  10031.  
  10032.     private void onActive()
  10033.     {
  10034.         setNonAggroTime(0);
  10035.         sendPacket(SystemMsg.YOU_ARE_PROTECTED_AGGRESSIVE_MONSTERS);
  10036.         if(getPetControlItem() != null)
  10037.             ThreadPoolManager.getInstance().execute(new RunnableImpl()
  10038.             {
  10039.                 @Override
  10040.                 public void runImpl()
  10041.                 {
  10042.                     if(getPetControlItem() != null)
  10043.                         summonPet();
  10044.                 }
  10045.  
  10046.             });
  10047.     }
  10048.  
  10049.     public void summonPet()
  10050.     {
  10051.         if(getPet() != null)
  10052.             return;
  10053.  
  10054.         ItemInstance controlItem = getPetControlItem();
  10055.         if(controlItem == null)
  10056.             return;
  10057.  
  10058.         int npcId = PetDataTable.getSummonId(controlItem);
  10059.         if(npcId == 0)
  10060.             return;
  10061.  
  10062.         NpcTemplate petTemplate = NpcHolder.getInstance().getTemplate(npcId);
  10063.         if(petTemplate == null)
  10064.             return;
  10065.  
  10066.         PetInstance pet = PetInstance.restore(controlItem, petTemplate, this);
  10067.         if(pet == null)
  10068.             return;
  10069.  
  10070.         setPet(pet);
  10071.         pet.setTitle(getName());
  10072.  
  10073.         if(!pet.isRespawned())
  10074.         {
  10075.             pet.setCurrentHp(pet.getMaxHp(), false);
  10076.             pet.setCurrentMp(pet.getMaxMp());
  10077.             pet.setCurrentFed(pet.getMaxFed());
  10078.             pet.updateControlItem();
  10079.             pet.store();
  10080.         }
  10081.  
  10082.         pet.getInventory().restore();
  10083.  
  10084.         pet.setNonAggroTime(System.currentTimeMillis() + Config.NONAGGRO_TIME_ONTELEPORT);
  10085.         pet.setReflection(getReflection());
  10086.         pet.spawnMe(Location.findPointToStay(this, 50, 70));
  10087.         pet.setRunning();
  10088.         pet.setFollowMode(true);
  10089.         pet.getInventory().validateItems();
  10090.  
  10091.         if(pet instanceof PetBabyInstance)
  10092.             ((PetBabyInstance) pet).startBuffTask();
  10093.     }
  10094.  
  10095.     private Map<Integer, Long> _traps;
  10096.  
  10097.     public Collection<TrapInstance> getTraps()
  10098.     {
  10099.         if(_traps == null)
  10100.             return null;
  10101.         Collection<TrapInstance> result = new ArrayList<TrapInstance>(getTrapsCount());
  10102.         TrapInstance trap;
  10103.         for(Integer trapId : _traps.keySet())
  10104.             if((trap = (TrapInstance) GameObjectsStorage.get(_traps.get(trapId))) != null)
  10105.                 result.add(trap);
  10106.             else
  10107.                 _traps.remove(trapId);
  10108.         return result;
  10109.     }
  10110.  
  10111.     public int getTrapsCount()
  10112.     {
  10113.         return _traps == null ? 0 : _traps.size();
  10114.     }
  10115.  
  10116.     public void addTrap(TrapInstance trap)
  10117.     {
  10118.         if(_traps == null)
  10119.             _traps = new HashMap<Integer, Long>();
  10120.         _traps.put(trap.getObjectId(), trap.getStoredId());
  10121.     }
  10122.  
  10123.     public void removeTrap(TrapInstance trap)
  10124.     {
  10125.         Map<Integer, Long> traps = _traps;
  10126.         if(traps == null || traps.isEmpty())
  10127.             return;
  10128.         traps.remove(trap.getObjectId());
  10129.     }
  10130.  
  10131.     public void destroyFirstTrap()
  10132.     {
  10133.         Map<Integer, Long> traps = _traps;
  10134.         if(traps == null || traps.isEmpty())
  10135.             return;
  10136.         TrapInstance trap;
  10137.         for(Integer trapId : traps.keySet())
  10138.         {
  10139.             if((trap = (TrapInstance) GameObjectsStorage.get(traps.get(trapId))) != null)
  10140.             {
  10141.                 trap.deleteMe();
  10142.                 return;
  10143.             }
  10144.             return;
  10145.         }
  10146.     }
  10147.  
  10148.     public void destroyAllTraps()
  10149.     {
  10150.         Map<Integer, Long> traps = _traps;
  10151.         if(traps == null || traps.isEmpty())
  10152.             return;
  10153.         List<TrapInstance> toRemove = new ArrayList<TrapInstance>();
  10154.         for(Integer trapId : traps.keySet())
  10155.             toRemove.add((TrapInstance) GameObjectsStorage.get(traps.get(trapId)));
  10156.         for(TrapInstance t : toRemove)
  10157.             if(t != null)
  10158.                 t.deleteMe();
  10159.     }
  10160.  
  10161.     public void setBlockCheckerArena(byte arena)
  10162.     {
  10163.         _handysBlockCheckerEventArena = arena;
  10164.     }
  10165.  
  10166.     public int getBlockCheckerArena()
  10167.     {
  10168.         return _handysBlockCheckerEventArena;
  10169.     }
  10170.  
  10171.     @Override
  10172.     public PlayerListenerList getListeners()
  10173.     {
  10174.         if(listeners == null)
  10175.             synchronized(this)
  10176.             {
  10177.                 if(listeners == null)
  10178.                     listeners = new PlayerListenerList(this);
  10179.             }
  10180.         return (PlayerListenerList) listeners;
  10181.     }
  10182.  
  10183.     @Override
  10184.     public PlayerStatsChangeRecorder getStatsRecorder()
  10185.     {
  10186.         if(_statsRecorder == null)
  10187.             synchronized(this)
  10188.             {
  10189.                 if(_statsRecorder == null)
  10190.                     _statsRecorder = new PlayerStatsChangeRecorder(this);
  10191.             }
  10192.         return (PlayerStatsChangeRecorder) _statsRecorder;
  10193.     }
  10194.  
  10195.     private Future<?> _hourlyTask;
  10196.     private int _hoursInGame = 0;
  10197.  
  10198.     public int getHoursInGame()
  10199.     {
  10200.         _hoursInGame++;
  10201.         return _hoursInGame;
  10202.     }
  10203.  
  10204.     public void startHourlyTask()
  10205.     {
  10206.         _hourlyTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new HourlyTask(this), 3600000L, 3600000L);
  10207.     }
  10208.  
  10209.     public void stopHourlyTask()
  10210.     {
  10211.         if(_hourlyTask != null)
  10212.         {
  10213.             _hourlyTask.cancel(false);
  10214.             _hourlyTask = null;
  10215.         }
  10216.     }
  10217.  
  10218.     public long getPremiumPoints()
  10219.     {
  10220.         if(Config.GAME_POINT_ITEM_ID != -1)
  10221.             return ItemFunctions.getItemCount(this, Config.GAME_POINT_ITEM_ID);
  10222.         else
  10223.             return getNetConnection().getPointG();
  10224.     }
  10225.  
  10226.     public void reducePremiumPoints(final int val)
  10227.     {
  10228.         int reduce = (getNetConnection().getPointG() - (val));
  10229.         if(Config.GAME_POINT_ITEM_ID != -1)
  10230.             ItemFunctions.removeItem(this, Config.GAME_POINT_ITEM_ID, val, true);
  10231.         else
  10232.             getNetConnection().setPointG(reduce);
  10233.     }
  10234.  
  10235.     private boolean _agathionResAvailable = false;
  10236.  
  10237.     public boolean isAgathionResAvailable()
  10238.     {
  10239.         return _agathionResAvailable;
  10240.     }
  10241.  
  10242.     public void setAgathionRes(boolean val)
  10243.     {
  10244.         _agathionResAvailable = val;
  10245.     }
  10246.  
  10247.     public boolean isClanAirShipDriver()
  10248.     {
  10249.         return isInBoat() && getBoat().isClanAirShip() && ((ClanAirShip) getBoat()).getDriver() == this;
  10250.     }
  10251.  
  10252.     /**
  10253.      * _userSession - испольюзуется для хранения временных переменных.
  10254.      */
  10255.     private Map<String, String> _userSession;
  10256.  
  10257.     public String getSessionVar(String key)
  10258.     {
  10259.         if(_userSession == null)
  10260.             return null;
  10261.         return _userSession.get(key);
  10262.     }
  10263.  
  10264.     public void setSessionVar(String key, String val)
  10265.     {
  10266.         if(_userSession == null)
  10267.             _userSession = new ConcurrentHashMap<String, String>();
  10268.  
  10269.         if(val == null || val.isEmpty())
  10270.             _userSession.remove(key);
  10271.         else
  10272.             _userSession.put(key, val);
  10273.     }
  10274.  
  10275.     public FriendList getFriendList()
  10276.     {
  10277.         return _friendList;
  10278.     }
  10279.  
  10280.     public boolean isNotShowTraders()
  10281.     {
  10282.         return _notShowTraders;
  10283.     }
  10284.  
  10285.     public void setNotShowTraders(boolean notShowTraders)
  10286.     {
  10287.         _notShowTraders = notShowTraders;
  10288.     }
  10289.  
  10290.     public boolean isDebug()
  10291.     {
  10292.         return _debug;
  10293.     }
  10294.  
  10295.     public void setDebug(boolean b)
  10296.     {
  10297.         _debug = b;
  10298.     }
  10299.     public final boolean isInJail()
  10300.     {
  10301.         return getVarB("jailed");
  10302.     }
  10303.  
  10304.     public void sendItemList(boolean show)
  10305.     {
  10306.         ItemInstance[] items = getInventory().getItems();
  10307.         LockType lockType = getInventory().getLockType();
  10308.         int[] lockItems = getInventory().getLockItems();
  10309.  
  10310.         int allSize = items.length;
  10311.         int questItemsSize = 0;
  10312.         int agathionItemsSize = 0;
  10313.         for(ItemInstance item : items)
  10314.         {
  10315.             if(item.getTemplate().isQuest())
  10316.                 questItemsSize++;
  10317.             if(item.getTemplate().getAgathionEnergy() > 0)
  10318.                 agathionItemsSize ++;
  10319.         }
  10320.  
  10321.         sendPacket(new ItemList(allSize - questItemsSize, items, show, lockType, lockItems));
  10322.         if(questItemsSize > 0)
  10323.             sendPacket(new ExQuestItemList(questItemsSize, items, lockType, lockItems));
  10324.         if(agathionItemsSize > 0)
  10325.             sendPacket(new ExBR_AgathionEnergyInfo(agathionItemsSize, items));
  10326.     }
  10327.  
  10328.     public int getBeltInventoryIncrease()
  10329.     {
  10330.         ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_BELT);
  10331.         if(item != null && item.getTemplate().getAttachedSkills() != null)
  10332.             for(Skill skill : item.getTemplate().getAttachedSkills())
  10333.                 for(FuncTemplate func : skill.getAttachedFuncs())
  10334.                     if(func._stat == Stats.INVENTORY_LIMIT)
  10335.                         return (int) func._value;
  10336.         return 0;
  10337.     }
  10338.  
  10339.     @Override
  10340.     public boolean isPlayer()
  10341.     {
  10342.         return true;
  10343.     }
  10344.  
  10345.     public boolean checkCoupleAction(Player target)
  10346.     {
  10347.         if(target.getPrivateStoreType() != Player.STORE_PRIVATE_NONE)
  10348.         {
  10349.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IN_PRIVATE_STORE).addName(target));
  10350.             return false;
  10351.         }
  10352.         if(target.isFishing())
  10353.         {
  10354.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_FISHING).addName(target));
  10355.             return false;
  10356.         }
  10357.         if(target.isInCombat())
  10358.         {
  10359.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_COMBAT).addName(target));
  10360.             return false;
  10361.         }
  10362.         if(target.isCursedWeaponEquipped())
  10363.         {
  10364.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_CURSED_WEAPON_EQUIPED).addName(target));
  10365.             return false;
  10366.         }
  10367.         if(target.isInOlympiadMode())
  10368.         {
  10369.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_OLYMPIAD).addName(target));
  10370.             return false;
  10371.         }
  10372.         if(target.isOnSiegeField())
  10373.         {
  10374.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_SIEGE).addName(target));
  10375.             return false;
  10376.         }
  10377.         if(target.isInBoat() || target.getMountNpcId() != 0)
  10378.         {
  10379.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_VEHICLE_MOUNT_OTHER).addName(target));
  10380.             return false;
  10381.         }
  10382.         if(target.isTeleporting())
  10383.         {
  10384.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_TELEPORTING).addName(target));
  10385.             return false;
  10386.         }
  10387.         if(target.getTransformation() != 0)
  10388.         {
  10389.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_IN_TRANSFORM).addName(target));
  10390.             return false;
  10391.         }
  10392.         if(target.isDead())
  10393.         {
  10394.             sendPacket(new SystemMessage2(SystemMsg.COUPLE_ACTION_CANNOT_C1_TARGET_IS_DEAD).addName(target));
  10395.             return false;
  10396.         }
  10397.         return true;
  10398.     }
  10399.  
  10400.     @Override
  10401.     public void startAttackStanceTask()
  10402.     {
  10403.         startAttackStanceTask0();
  10404.         Summon summon = getPet();
  10405.         if(summon != null)
  10406.             summon.startAttackStanceTask0();
  10407.     }
  10408.  
  10409.     @Override
  10410.     public void displayGiveDamageMessage(Creature target, int damage, boolean crit, boolean miss, boolean shld, boolean magic)
  10411.     {
  10412.         super.displayGiveDamageMessage(target, damage, crit, miss, shld, magic);
  10413.         if(crit)
  10414.             if(magic)
  10415.                 sendPacket(new SystemMessage(SystemMessage.MAGIC_CRITICAL_HIT).addName(this));
  10416.             else
  10417.                 sendPacket(new SystemMessage(SystemMessage.C1_HAD_A_CRITICAL_HIT).addName(this));
  10418.  
  10419.         if(miss)
  10420.             sendPacket(new SystemMessage(SystemMessage.C1S_ATTACK_WENT_ASTRAY).addName(this));
  10421.         else if(!target.isDamageBlocked())
  10422.             sendPacket(new SystemMessage(SystemMessage.C1_HAS_GIVEN_C2_DAMAGE_OF_S3).addName(this).addName(target).addNumber(damage));
  10423.  
  10424.         if(target.isPlayer())
  10425.         {
  10426.             if(shld && damage > 1)
  10427.                 target.sendPacket(SystemMsg.YOUR_SHIELD_DEFENSE_HAS_SUCCEEDED);
  10428.             else if(shld && damage == 1)
  10429.                 target.sendPacket(SystemMsg.YOUR_EXCELLENT_SHIELD_DEFENSE_WAS_A_SUCCESS);
  10430.         }
  10431.     }
  10432.  
  10433.     @Override
  10434.     public void displayReceiveDamageMessage(Creature attacker, int damage)
  10435.     {
  10436.         if(attacker != this)
  10437.             sendPacket(new SystemMessage2(SystemMsg.C1_HAS_RECEIVED_DAMAGE_OF_S3_FROM_C2).addName(this).addName(attacker).addNumber((long) damage));
  10438.     }
  10439.  
  10440.     public IntObjectMap<String> getPostFriends()
  10441.     {
  10442.         return _postFriends;
  10443.     }
  10444.  
  10445.     public boolean isSharedGroupDisabled(int groupId)
  10446.     {
  10447.         TimeStamp sts = _sharedGroupReuses.get(groupId);
  10448.         if(sts == null)
  10449.             return false;
  10450.         if(sts.hasNotPassed())
  10451.             return true;
  10452.         _sharedGroupReuses.remove(groupId);
  10453.         return false;
  10454.     }
  10455.  
  10456.     public TimeStamp getSharedGroupReuse(int groupId)
  10457.     {
  10458.         return _sharedGroupReuses.get(groupId);
  10459.     }
  10460.  
  10461.     public void addSharedGroupReuse(int group, TimeStamp stamp)
  10462.     {
  10463.         _sharedGroupReuses.put(group, stamp);
  10464.     }
  10465.  
  10466.     public Collection<IntObjectMap.Entry<TimeStamp>> getSharedGroupReuses()
  10467.     {
  10468.         return _sharedGroupReuses.entrySet();
  10469.     }
  10470.  
  10471.     public void sendReuseMessage(ItemInstance item)
  10472.     {
  10473.         TimeStamp sts = getSharedGroupReuse(item.getTemplate().getReuseGroup());
  10474.         if(sts == null || !sts.hasNotPassed())
  10475.             return;
  10476.  
  10477.         long timeleft = sts.getReuseCurrent();
  10478.         long hours = timeleft / 3600000;
  10479.         long minutes = (timeleft - hours * 3600000) / 60000;
  10480.         long seconds = (long) Math.ceil((timeleft - hours * 3600000 - minutes * 60000) / 1000.);
  10481.  
  10482.         if(hours > 0)
  10483.             sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[2]).addItemName(item.getTemplate().getItemId()).addInteger(hours).addInteger(minutes).addInteger(seconds));
  10484.         else if(minutes > 0)
  10485.             sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[1]).addItemName(item.getTemplate().getItemId()).addInteger(minutes).addInteger(seconds));
  10486.         else
  10487.             sendPacket(new SystemMessage2(item.getTemplate().getReuseType().getMessages()[0]).addItemName(item.getTemplate().getItemId()).addInteger(seconds));
  10488.     }
  10489.  
  10490.     public NevitSystem getNevitSystem()
  10491.     {
  10492.         return _nevitSystem;
  10493.     }
  10494.  
  10495.     public void ask(ConfirmDlg dlg, OnAnswerListener listener)
  10496.     {
  10497.         if(_askDialog != null)
  10498.             return;
  10499.         int rnd = Rnd.nextInt();
  10500.         _askDialog = new ImmutablePair<Integer, OnAnswerListener>(rnd, listener);
  10501.         dlg.setRequestId(rnd);
  10502.         sendPacket(dlg);
  10503.     }
  10504.  
  10505.     public Pair<Integer, OnAnswerListener> getAskListener(boolean clear)
  10506.     {
  10507.         if(!clear)
  10508.             return _askDialog;
  10509.         else
  10510.         {
  10511.             Pair<Integer, OnAnswerListener> ask = _askDialog;
  10512.             _askDialog = null;
  10513.             return ask;
  10514.         }
  10515.     }
  10516.  
  10517.     @Override
  10518.     public boolean isDead()
  10519.     {
  10520.         return (isInOlympiadMode() || isInDuel()) ? getCurrentHp() <= 1. : super.isDead();
  10521.     }
  10522.  
  10523.     @Override
  10524.     public int getAgathionEnergy()
  10525.     {
  10526.         ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LBRACELET);
  10527.         return item == null ? 0 : item.getAgathionEnergy();
  10528.     }
  10529.  
  10530.     @Override
  10531.     public void setAgathionEnergy(int val)
  10532.     {
  10533.         ItemInstance item = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LBRACELET);
  10534.         if(item == null)
  10535.             return;
  10536.         item.setAgathionEnergy(val);
  10537.         item.setJdbcState(JdbcEntityState.UPDATED);
  10538.  
  10539.         sendPacket(new ExBR_AgathionEnergyInfo(1, item));
  10540.     }
  10541.  
  10542.     public boolean hasPrivilege(Privilege privilege)
  10543.     {
  10544.         return _clan != null && (getClanPrivileges() & privilege.mask()) == privilege.mask();
  10545.     }
  10546.  
  10547.     public MatchingRoom getMatchingRoom()
  10548.     {
  10549.         return _matchingRoom;
  10550.     }
  10551.  
  10552.     public void setMatchingRoom(MatchingRoom matchingRoom)
  10553.     {
  10554.         _matchingRoom = matchingRoom;
  10555.     }
  10556.  
  10557.     public void dispelBuffs()
  10558.     {
  10559.         for(Effect e : getEffectList().getAllEffects())
  10560.             if(!e.getSkill().isOffensive() && !e.getSkill().isNewbie() && e.isCancelable() && !e.getSkill().isPreservedOnDeath())
  10561.             {
  10562.                 sendPacket(new SystemMessage2(SystemMsg.THE_EFFECT_OF_S1_HAS_BEEN_REMOVED).addSkillName(e.getSkill().getId(), e.getSkill().getLevel()));
  10563.                 e.exit();
  10564.             }
  10565.         if(getPet() != null)
  10566.             for(Effect e : getPet().getEffectList().getAllEffects())
  10567.                 if(!e.getSkill().isOffensive() && !e.getSkill().isNewbie() && e.isCancelable() && !e.getSkill().isPreservedOnDeath())
  10568.                     e.exit();
  10569.     }
  10570.  
  10571.     public void setInstanceReuse(int id, long time)
  10572.     {
  10573.         final SystemMessage2 msg = new SystemMessage2(SystemMsg.INSTANT_ZONE_FROM_HERE__S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_ENTRY_POSSIBLE).addString(getName());
  10574.         sendPacket(msg);
  10575.         _instancesReuses.put(id, time);
  10576.         mysql.set("REPLACE INTO character_instances (obj_id, id, reuse) VALUES (?,?,?)", getObjectId(), id, time);
  10577.     }
  10578.  
  10579.     public void removeInstanceReuse(int id)
  10580.     {
  10581.         if(_instancesReuses.remove(id) != null)
  10582.             mysql.set("DELETE FROM `character_instances` WHERE `obj_id`=? AND `id`=? LIMIT 1", getObjectId(), id);
  10583.     }
  10584.  
  10585.     public void removeAllInstanceReuses()
  10586.     {
  10587.         _instancesReuses.clear();
  10588.         mysql.set("DELETE FROM `character_instances` WHERE `obj_id`=?", getObjectId());
  10589.     }
  10590.  
  10591.     public void removeInstanceReusesByGroupId(int groupId)
  10592.     {
  10593.         for(int i : InstantZoneHolder.getInstance().getSharedReuseInstanceIdsByGroup(groupId))
  10594.             if(getInstanceReuse(i) != null)
  10595.                 removeInstanceReuse(i);
  10596.     }
  10597.  
  10598.     public Long getInstanceReuse(int id)
  10599.     {
  10600.         return _instancesReuses.get(id);
  10601.     }
  10602.  
  10603.     public Map<Integer, Long> getInstanceReuses()
  10604.     {
  10605.         return _instancesReuses;
  10606.     }
  10607.  
  10608.     private void loadInstanceReuses()
  10609.     {
  10610.         Connection con = null;
  10611.         PreparedStatement offline = null;
  10612.         ResultSet rs = null;
  10613.         try
  10614.         {
  10615.             con = DatabaseFactory.getInstance().getConnection();
  10616.             offline = con.prepareStatement("SELECT * FROM character_instances WHERE obj_id = ?");
  10617.             offline.setInt(1, getObjectId());
  10618.             rs = offline.executeQuery();
  10619.             while(rs.next())
  10620.             {
  10621.                 int id = rs.getInt("id");
  10622.                 long reuse = rs.getLong("reuse");
  10623.                 _instancesReuses.put(id, reuse);
  10624.             }
  10625.         }
  10626.         catch(Exception e)
  10627.         {
  10628.             _log.error("", e);
  10629.         }
  10630.         finally
  10631.         {
  10632.             DbUtils.closeQuietly(con, offline, rs);
  10633.         }
  10634.     }
  10635.  
  10636.     public Reflection getActiveReflection()
  10637.     {
  10638.         for(Reflection r : ReflectionManager.getInstance().getAll())
  10639.             if(r != null && ArrayUtils.contains(r.getVisitors(), getObjectId()))
  10640.                 return r;
  10641.         return null;
  10642.     }
  10643.  
  10644.     public boolean canEnterInstance(int instancedZoneId)
  10645.     {
  10646.         InstantZone iz = InstantZoneHolder.getInstance().getInstantZone(instancedZoneId);
  10647.  
  10648.         if(isDead())
  10649.             return false;
  10650.  
  10651.         if(ReflectionManager.getInstance().size() > Config.MAX_REFLECTIONS_COUNT)
  10652.         {
  10653.             sendPacket(SystemMsg.THE_MAXIMUM_NUMBER_OF_INSTANCE_ZONES_HAS_BEEN_EXCEEDED);
  10654.             return false;
  10655.         }
  10656.  
  10657.         if(iz == null)
  10658.         {
  10659.             sendPacket(SystemMsg.SYSTEM_ERROR);
  10660.             return false;
  10661.         }
  10662.  
  10663.         if(ReflectionManager.getInstance().getCountByIzId(instancedZoneId) >= iz.getMaxChannels())
  10664.         {
  10665.             sendPacket(SystemMsg.THE_MAXIMUM_NUMBER_OF_INSTANCE_ZONES_HAS_BEEN_EXCEEDED);
  10666.             return false;
  10667.         }
  10668.  
  10669.         return iz.getEntryType().canEnter(this, iz);
  10670.     }
  10671.  
  10672.     public boolean canReenterInstance(int instancedZoneId)
  10673.     {
  10674.         InstantZone iz = InstantZoneHolder.getInstance().getInstantZone(instancedZoneId);
  10675.         if(getActiveReflection() != null && getActiveReflection().getInstancedZoneId() != instancedZoneId)
  10676.         {
  10677.             sendPacket(SystemMsg.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
  10678.             return false;
  10679.         }
  10680.         if(iz.isDispelBuffs())
  10681.             dispelBuffs();
  10682.         return iz.getEntryType().canReEnter(this, iz);
  10683.     }
  10684.  
  10685.     public int getBattlefieldChatId()
  10686.     {
  10687.         return _battlefieldChatId;
  10688.     }
  10689.  
  10690.     public void setBattlefieldChatId(int battlefieldChatId)
  10691.     {
  10692.         _battlefieldChatId = battlefieldChatId;
  10693.     }
  10694.  
  10695.     @Override
  10696.     public void broadCast(IStaticPacket... packet)
  10697.     {
  10698.         sendPacket(packet);
  10699.     }
  10700.  
  10701.     @Override
  10702.     public Iterator<Player> iterator()
  10703.     {
  10704.         return Collections.singleton(this).iterator();
  10705.     }
  10706.  
  10707.     public PlayerGroup getPlayerGroup()
  10708.     {
  10709.         if(getParty() != null)
  10710.         {
  10711.             if(getParty().getCommandChannel() != null)
  10712.                 return getParty().getCommandChannel();
  10713.             else
  10714.                 return getParty();
  10715.         }
  10716.         else
  10717.             return this;
  10718.     }
  10719.  
  10720.     public boolean isActionBlocked(String action)
  10721.     {
  10722.         return _blockedActions.contains(action);
  10723.     }
  10724.  
  10725.     public void blockActions(String... actions)
  10726.     {
  10727.         Collections.addAll(_blockedActions, actions);
  10728.     }
  10729.  
  10730.     public void unblockActions(String... actions)
  10731.     {
  10732.         for(String action : actions)
  10733.             _blockedActions.remove(action);
  10734.     }
  10735.  
  10736.     public OlympiadGame getOlympiadGame()
  10737.     {
  10738.         return _olympiadGame;
  10739.     }
  10740.  
  10741.     public void setOlympiadGame(OlympiadGame olympiadGame)
  10742.     {
  10743.         _olympiadGame = olympiadGame;
  10744.     }
  10745.  
  10746.     public OlympiadGame getOlympiadObserveGame()
  10747.     {
  10748.         return _olympiadObserveGame;
  10749.     }
  10750.  
  10751.     public void setOlympiadObserveGame(OlympiadGame olympiadObserveGame)
  10752.     {
  10753.         _olympiadObserveGame = olympiadObserveGame;
  10754.     }
  10755.  
  10756.     public void addRadar(int x, int y, int z)
  10757.     {
  10758.         sendPacket(new RadarControl(0, 1, x, y, z));
  10759.     }
  10760.  
  10761.     public void addRadarWithMap(int x, int y, int z)
  10762.     {
  10763.         sendPacket(new RadarControl(0, 2, x, y, z));
  10764.     }
  10765.  
  10766.     public PetitionMainGroup getPetitionGroup()
  10767.     {
  10768.         return _petitionGroup;
  10769.     }
  10770.  
  10771.     public void setPetitionGroup(PetitionMainGroup petitionGroup)
  10772.     {
  10773.         _petitionGroup = petitionGroup;
  10774.     }
  10775.  
  10776.     public int getLectureMark()
  10777.     {
  10778.         return _lectureMark;
  10779.     }
  10780.  
  10781.     public void setLectureMark(int lectureMark)
  10782.     {
  10783.         _lectureMark = lectureMark;
  10784.     }
  10785.    
  10786.     /**
  10787.     * Initializes his _botPunish object with the specified punish
  10788.     * and for the specified time
  10789.     * @param punishType
  10790.     * @param minsOfPunish
  10791.     */
  10792.     public synchronized void setPunishDueBotting(AutoHuntingPunish.Punish punishType, int minsOfPunish)
  10793.     {
  10794.         if(_AutoHuntingPunish == null)
  10795.             _AutoHuntingPunish = new AutoHuntingPunish(punishType, minsOfPunish);
  10796.     }
  10797.    
  10798.     /**
  10799.     * Returns the current object-representative player punish
  10800.     * @return
  10801.     */
  10802.     public AutoHuntingPunish getPlayerPunish()
  10803.     {
  10804.         return _AutoHuntingPunish;
  10805.     }
  10806.    
  10807.     /**
  10808.     * Returns the type of punish being applied
  10809.     * @return
  10810.     */
  10811.     public AutoHuntingPunish.Punish getBotPunishType()
  10812.     {
  10813.         return _AutoHuntingPunish.getBotPunishType();
  10814.     }
  10815.    
  10816.     /**
  10817.     * Will return true if the player has any bot punishment
  10818.     * active
  10819.     * @return
  10820.     */
  10821.     public boolean isBeingPunished()
  10822.     {
  10823.         return _AutoHuntingPunish != null;
  10824.     }
  10825.      
  10826.     /**
  10827.     * Will end the punishment once a player attempt to
  10828.     * perform any forbid action and his punishment has
  10829.     * expired
  10830.     */
  10831.     public void endPunishment()
  10832.     {
  10833.         Connection con = null;
  10834.         try
  10835.         {
  10836.             con = L2DatabaseFactory.getInstance().getConnection();
  10837.             PreparedStatement statement = con.prepareStatement("DELETE FROM bot_reported_punish WHERE charId = ?");
  10838.             statement.setInt(1, getObjectId());
  10839.             statement.execute();
  10840.             statement.close();
  10841.         }
  10842.         catch(SQLException sqle)
  10843.         {
  10844.             sqle.printStackTrace();
  10845.         }
  10846.         finally
  10847.         {
  10848.             try
  10849.             {
  10850.                 con.close();
  10851.             }
  10852.             catch(SQLException sqle) { }
  10853.         }
  10854.         _AutoHuntingPunish = null;
  10855.         this.sendMessage("Your punishment has expired. Do not bot again!");
  10856.     }
  10857.    
  10858.    
  10859.     /**
  10860.      * Sets exp holded by the character on log in
  10861.      * @param current exp
  10862.      */
  10863.     public void setFirstExp(long value)
  10864.     {
  10865.         _firstExp = value;
  10866.     }
  10867.    
  10868.     /**
  10869.      * Will return true if the player has gained exp
  10870.      * since logged in
  10871.      * @return
  10872.      */
  10873.     public boolean hasEarnedExp()
  10874.     {
  10875.         if(getExp() - _firstExp != 0)
  10876.             return true;
  10877.         return false;
  10878.     }
  10879.    
  10880.     public int getNameColorP()
  10881.     {
  10882.         return _nameColor;
  10883.     }  
  10884.    
  10885.     private boolean _InTvT = false;
  10886.     private boolean _inCtF = false;
  10887.     private boolean _inLastHero = false;
  10888.  
  10889.     public boolean isInTvT()
  10890.     {
  10891.         return _InTvT;
  10892.     }
  10893.  
  10894.     public boolean isInCtF()
  10895.     {
  10896.         return _inCtF;
  10897.     }
  10898.  
  10899.     public boolean isInLastHero()
  10900.     {
  10901.         return _inLastHero;
  10902.     }
  10903.  
  10904.     public boolean isInPvPEvent()
  10905.     {
  10906.         return !_InTvT && !_inCtF && !_inLastHero ? false : true;
  10907.     }
  10908.  
  10909.     public void setIsInTvT(boolean param)
  10910.     {
  10911.         _InTvT = param;
  10912.     }
  10913.  
  10914.     public void setIsInCtF(boolean param)
  10915.     {
  10916.         _inCtF = param;
  10917.     }
  10918.  
  10919.     public void setIsInLastHero(boolean param)
  10920.     {
  10921.         _inLastHero = param;
  10922.     }
  10923.      
  10924.     public void TitleColor()
  10925.     {
  10926.         if(Config.ENEBLE_TITLE_COLOR_MOD)
  10927.         {
  10928.             if(Config.TYPE_TITLE_COLOR_MOD == "PvP")
  10929.             {
  10930.                 if(getPvpKills() >= Config.COUNT_TITLE_1)
  10931.                 {
  10932.                     setTitleColor(Config.TITLE_COLOR_1);
  10933.                 }
  10934.                 if(getPvpKills() >= Config.COUNT_TITLE_2)
  10935.                 {
  10936.                     setTitleColor(Config.TITLE_COLOR_2);
  10937.                 }
  10938.                 if(getPvpKills() >= Config.COUNT_TITLE_3)
  10939.                 {
  10940.                     setTitleColor(Config.TITLE_COLOR_3);
  10941.                 }
  10942.                 if(getPvpKills() >= Config.COUNT_TITLE_4)
  10943.                 {
  10944.                     setTitleColor(Config.TITLE_COLOR_4);
  10945.                 }
  10946.                 if(getPvpKills() >= Config.COUNT_TITLE_5)
  10947.                 {
  10948.                     setTitleColor(Config.TITLE_COLOR_5);
  10949.                 }
  10950.             }
  10951.             if(Config.TYPE_TITLE_COLOR_MOD == "Pk")
  10952.             {
  10953.                 if(getPkKills() >= Config.COUNT_TITLE_1)
  10954.                 {
  10955.                     setTitleColor(Config.TITLE_COLOR_1);
  10956.                 }
  10957.                 if(getPkKills() >= Config.COUNT_TITLE_2)
  10958.                 {
  10959.                     setTitleColor(Config.TITLE_COLOR_2);
  10960.                 }
  10961.                 if(getPkKills() >= Config.COUNT_TITLE_3)
  10962.                 {
  10963.                     setTitleColor(Config.TITLE_COLOR_3);
  10964.                 }
  10965.                 if(getPkKills() >= Config.COUNT_TITLE_4)
  10966.                 {
  10967.                     setTitleColor(Config.TITLE_COLOR_4);
  10968.                 }
  10969.                 if(getPkKills() >= Config.COUNT_TITLE_5)
  10970.                 {
  10971.                     setTitleColor(Config.TITLE_COLOR_5);
  10972.                 }
  10973.             }
  10974.         }
  10975.     }
  10976.    
  10977.     public void NameColor()
  10978.     {
  10979.         if(Config.ENEBLE_NAME_COLOR_MOD)
  10980.         {
  10981.             if(Config.TYPE_NAME_COLOR_MOD == "PvP")
  10982.             {
  10983.                 if(getPvpKills() >= Config.COUNT_NAME_1)
  10984.                 {
  10985.                     setNameColor(Config.NAME_COLOR_1);
  10986.                 }
  10987.                 if(getPvpKills() >= Config.COUNT_NAME_2)
  10988.                 {
  10989.                     setNameColor(Config.NAME_COLOR_2);
  10990.                 }
  10991.                 if(getPvpKills() >= Config.COUNT_NAME_3)
  10992.                 {
  10993.                     setNameColor(Config.NAME_COLOR_3);
  10994.                 }
  10995.                 if(getPvpKills() >= Config.COUNT_NAME_4)
  10996.                 {
  10997.                     setNameColor(Config.NAME_COLOR_4);
  10998.                 }
  10999.                 if(getPvpKills() >= Config.COUNT_NAME_5)
  11000.                 {
  11001.                     setNameColor(Config.NAME_COLOR_5);
  11002.                 }
  11003.             }
  11004.             if(Config.TYPE_NAME_COLOR_MOD == "Pk")
  11005.             {
  11006.                 if(getPkKills() >= Config.COUNT_NAME_1)
  11007.                 {
  11008.                     setNameColor(Config.NAME_COLOR_1);
  11009.                 }
  11010.                 if(getPkKills() >= Config.COUNT_NAME_2)
  11011.                 {
  11012.                     setNameColor(Config.NAME_COLOR_2);
  11013.                 }
  11014.                 if(getPkKills() >= Config.COUNT_NAME_3)
  11015.                 {
  11016.                     setNameColor(Config.NAME_COLOR_3);
  11017.                 }
  11018.                 if(getPkKills() >= Config.COUNT_NAME_4)
  11019.                 {
  11020.                     setNameColor(Config.NAME_COLOR_4);
  11021.                 }
  11022.                 if(getPkKills() >= Config.COUNT_NAME_5)
  11023.                 {
  11024.                     setNameColor(Config.NAME_COLOR_5);
  11025.                 }
  11026.             }
  11027.         }
  11028.     }
  11029.  
  11030.    public void setMacroSkill(Skill skill)
  11031.    {
  11032.        this._macroSkill = skill;
  11033.    }
  11034.    
  11035.    public Skill getMacroSkill()
  11036.    {
  11037.        return this._macroSkill;
  11038.    }
  11039. }
Add Comment
Please, Sign In to add comment