Bladeren bron

BETA: Items reuse implementation:
* Item handlers return true on successful usage, false otherwise.
* Implemented item reuse delay and shared reuse group.
* Implemented database persistence for item reuse time.
* Moved reuse stamps for skills to FastMap as they originally were.
* Reworked TimeStamp class and moved out of L2PcInstance.
* Added proper JavaDocs to L2ItemInstance.
* Unhardcoded Calculator.

Zoey76 13 jaren geleden
bovenliggende
commit
36b4d13408

+ 3 - 6
L2J_Server_BETA/java/com/l2jserver/gameserver/handler/IItemHandler.java

@@ -19,12 +19,8 @@ import java.util.logging.Logger;
 import com.l2jserver.gameserver.model.actor.L2Playable;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
 
-
 /**
- * Mother class of all itemHandlers.<BR><BR>
- * an IItemHandler implementation has to be stateless
- *
- * @version $Revision: 1.1.4.3 $ $Date: 2005/03/27 15:30:09 $
+ * Mother class of all Item Handlers.
  */
 public interface IItemHandler
 {
@@ -35,6 +31,7 @@ public interface IItemHandler
 	 * @param playable L2PlayableInstance designating the player
 	 * @param item L2ItemInstance designating the item to use
 	 * @param forceUse ctrl hold on item use
+	 * @return {@code true} if the item all conditions are met and the item is used, {@code false} otherwise.
 	 */
-	public void useItem(L2Playable playable, L2ItemInstance item, boolean forceUse);
+	public boolean useItem(L2Playable playable, L2ItemInstance item, boolean forceUse);
 }

+ 6 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/model/L2Augmentation.java

@@ -129,19 +129,18 @@ public final class L2Augmentation
 			player.addSkill(_skill);
 			if (_skill.isActive())
 			{
-				if (!player.getReuseTimeStamp().isEmpty() && player.getReuseTimeStamp().containsKey(_skill.getReuseHashCode()))
+				final long delay = player.getSkillRemainingReuseTime(_skill.getReuseHashCode());
+				if (delay > 0)
 				{
-					final long delay = player.getReuseTimeStamp().get(_skill.getReuseHashCode()).getRemaining();
-					if (delay > 0)
-					{
-						player.disableSkill(_skill, delay);
-						updateTimeStamp = true;
-					}
+					player.disableSkill(_skill, delay);
+					updateTimeStamp = true;
 				}
 			}
 			player.sendSkillList();
 			if (updateTimeStamp)
+			{
 				player.sendPacket(new SkillCoolTime(player));
+			}
 		}
 	}
 	

+ 4 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/L2Clan.java

@@ -41,7 +41,6 @@ import com.l2jserver.gameserver.instancemanager.TerritoryWarManager;
 import com.l2jserver.gameserver.instancemanager.TerritoryWarManager.Territory;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.actor.instance.L2PcInstance.TimeStamp;
 import com.l2jserver.gameserver.model.itemcontainer.ItemContainer;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.network.SystemMessageId;
@@ -279,13 +278,14 @@ public class L2Clan
 			SiegeManager.getInstance().addSiegeSkills(newLeader);
 			
 			// Transferring siege skills TimeStamps from old leader to new leader to prevent unlimited headquarters
-			if (!exLeader.getReuseTimeStamp().isEmpty())
+			if (!exLeader.getSkillReuseTimeStamps().isEmpty())
 			{
+				TimeStamp t;
 				for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(newLeader.isNoble(), getHasCastle() > 0))
 				{
-					if (exLeader.getReuseTimeStamp().containsKey(sk.getReuseHashCode()))
+					if (exLeader.hasSkillReuse(sk.getReuseHashCode()))
 					{
-						TimeStamp t = exLeader.getReuseTimeStamp().get(sk.getReuseHashCode());
+						t = exLeader.getSkillReuseTimeStamp(sk.getReuseHashCode());
 						newLeader.addTimeStamp(sk, t.getReuse(), t.getStamp());
 					}
 				}

+ 1 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/ShortCuts.java

@@ -76,10 +76,7 @@ public class ShortCuts
 			{
 				return;
 			}
-			if (item.isEtcItem())
-			{
-				shortcut.setSharedReuseGroup(item.getEtcItem().getSharedReuseGroup());
-			}
+			shortcut.setSharedReuseGroup(item.getSharedReuseGroup());
 		}
 		final L2ShortCut oldShortCut = _shortCuts.put(shortcut.getSlot() + (shortcut.getPage() * MAX_SHORTCUTS_PER_BAR), shortcut);
 		registerShortCutInDb(shortcut, oldShortCut);

+ 160 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/TimeStamp.java

@@ -0,0 +1,160 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.model;
+
+import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.skills.L2Skill;
+
+/**
+ * Simple class containing all necessary information to maintain<br>
+ * valid time stamps and reuse for skills and items reuse upon re-login.<br>
+ * <b>Filter this carefully as it becomes redundant to store reuse for small delays.</b>
+ * @author Yesod, Zoey76
+ */
+public class TimeStamp
+{
+	private final int _id1; // Item or Skill Id.
+	private final int _id2; // Item Object Id or Skill Level.
+	private final long _reuse;
+	private final long _stamp;
+	private final int _group;
+	
+	/**
+	 * @param skill the skill upon the stamp will be created.
+	 * @param reuse the reuse time for this skill.
+	 */
+	public TimeStamp(L2Skill skill, long reuse)
+	{
+		_id1 = skill.getId();
+		_id2 = skill.getLevel();
+		_reuse = reuse;
+		_stamp = System.currentTimeMillis() + reuse;
+		_group = -1;
+	}
+	
+	/**
+	 * @param skill the skill upon the stamp will be created.
+	 * @param reuse the reuse time for this skill.
+	 * @param systime overrides the system time with a customized one.
+	 */
+	public TimeStamp(L2Skill skill, long reuse, long systime)
+	{
+		_id1 = skill.getId();
+		_id2 = skill.getLevel();
+		_reuse = reuse;
+		_stamp = systime;
+		_group = -1;
+	}
+	
+	/**
+	 * @param item the item upon the stamp will be created.
+	 * @param reuse the reuse time for this item.
+	 */
+	public TimeStamp(L2ItemInstance item, long reuse)
+	{
+		_id1 = item.getItemId();
+		_id2 = item.getObjectId();
+		_reuse = reuse;
+		_stamp = System.currentTimeMillis() + reuse;
+		_group = item.getSharedReuseGroup();
+	}
+	
+	/**
+	 * @param item the item upon the stamp will be created.
+	 * @param reuse the reuse time for this item.
+	 * @param systime overrides the system time with a customized one.
+	 */
+	public TimeStamp(L2ItemInstance item, long reuse, long systime)
+	{
+		_id1 = item.getItemId();
+		_id2 = item.getObjectId();
+		_reuse = reuse;
+		_stamp = systime;
+		_group = item.getSharedReuseGroup();
+	}
+	
+	/**
+	 * @return the time stamp, either the system time where this time stamp was created or the custom time assigned.
+	 */
+	public long getStamp()
+	{
+		return _stamp;
+	}
+	
+	/**
+	 * @return the first Id for the item, the item Id.
+	 */
+	public int getItemId()
+	{
+		return _id1;
+	}
+	
+	/**
+	 * @return the second Id for the item, the item object Id.
+	 */
+	public int getItemObjectId()
+	{
+		return _id2;
+	}
+	
+	/**
+	 * @return the skill Id.
+	 */
+	public int getSkillId()
+	{
+		return _id1;
+	}
+	
+	/**
+	 * @return the skill level.
+	 */
+	public int getSkillLvl()
+	{
+		return _id2;
+	}
+	
+	/**
+	 * @return the reuse set for this Item/Skill.
+	 */
+	public long getReuse()
+	{
+		return _reuse;
+	}
+	
+	/**
+	 * @return the shared reuse group for the item, -1 for skills.
+	 */
+	public int getSharedReuseGroup()
+	{
+		return _group;
+	}
+	
+	/**
+	 * @return the remaining time for this time stamp to expire.
+	 */
+	public long getRemaining()
+	{
+		return Math.max(_stamp - System.currentTimeMillis(), 0);
+	}
+	
+	/**
+	 * Check if the reuse delay has passed and if it has not then update the stored reuse time according to what is currently remaining on the delay.
+	 * @return {@code true} if this time stamp has expired, {@code false} otherwise.
+	 */
+	public boolean hasNotPassed()
+	{
+		return System.currentTimeMillis() < _stamp;
+	}
+}

+ 195 - 80
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -26,6 +26,7 @@ import java.util.Calendar;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledFuture;
@@ -129,6 +130,7 @@ import com.l2jserver.gameserver.model.PartyMatchRoomList;
 import com.l2jserver.gameserver.model.PartyMatchWaitingList;
 import com.l2jserver.gameserver.model.ShortCuts;
 import com.l2jserver.gameserver.model.TerritoryWard;
+import com.l2jserver.gameserver.model.TimeStamp;
 import com.l2jserver.gameserver.model.TradeList;
 import com.l2jserver.gameserver.model.actor.L2Attackable;
 import com.l2jserver.gameserver.model.actor.L2Character;
@@ -221,6 +223,7 @@ import com.l2jserver.gameserver.network.serverpackets.ExSetCompassZoneCode;
 import com.l2jserver.gameserver.network.serverpackets.ExSpawnEmitter;
 import com.l2jserver.gameserver.network.serverpackets.ExStartScenePlayer;
 import com.l2jserver.gameserver.network.serverpackets.ExStorageMaxCount;
+import com.l2jserver.gameserver.network.serverpackets.ExUseSharedGroupItem;
 import com.l2jserver.gameserver.network.serverpackets.ExVitalityPointInfo;
 import com.l2jserver.gameserver.network.serverpackets.ExVoteSystemInfo;
 import com.l2jserver.gameserver.network.serverpackets.FriendStatusPacket;
@@ -296,6 +299,11 @@ public final class L2PcInstance extends L2Playable
 	private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,effect_count,effect_cur_time, reuse_delay, systime, restore_type FROM character_skills_save WHERE charId=? AND class_index=? ORDER BY buff_index ASC";
 	private static final String DELETE_SKILL_SAVE = "DELETE FROM character_skills_save WHERE charId=? AND class_index=?";
 	
+	// Character Item Reuse Time String Definition:
+	private static final String ADD_ITEM_REUSE_SAVE = "INSERT INTO character_item_reuse_save (charId,itemId,itemObjId,reuseDelay,systime) VALUES (?,?,?,?,?)";
+	private static final String RESTORE_ITEM_REUSE_SAVE = "SELECT charId,itemId,itemObjId,reuseDelay,systime FROM character_item_reuse_save WHERE charId=?";
+	private static final String DELETE_ITEM_REUSE_SAVE = "DELETE FROM character_item_reuse_save WHERE charId=?";
+	
 	// Character Character SQL String Definitions:
 	private static final String INSERT_CHARACTER = "INSERT INTO characters (account_name,charId,char_name,level,maxHp,curHp,maxCp,curCp,maxMp,curMp,face,hairStyle,hairColor,sex,exp,sp,karma,fame,pvpkills,pkkills,clanid,race,classid,deletetime,cancraft,title,title_color,accesslevel,online,isin7sdungeon,clan_privs,wantspeace,base_class,newbie,nobless,power_grade,createDate) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
 	private static final String UPDATE_CHARACTER = "UPDATE characters SET level=?,maxHp=?,curHp=?,maxCp=?,curCp=?,maxMp=?,curMp=?,face=?,hairStyle=?,hairColor=?,sex=?,heading=?,x=?,y=?,z=?,exp=?,expBeforeDeath=?,sp=?,karma=?,fame=?,pvpkills=?,pkkills=?,clanid=?,race=?,classid=?,deletetime=?,title=?,title_color=?,accesslevel=?,online=?,isin7sdungeon=?,clan_privs=?,wantspeace=?,base_class=?,onlinetime=?,punish_level=?,punish_timer=?,newbie=?,nobless=?,power_grade=?,subpledge=?,lvl_joined_academy=?,apprentice=?,sponsor=?,varka_ketra_ally=?,clan_join_expiry_time=?,clan_create_expiry_time=?,char_name=?,death_penalty_level=?,bookmarkslot=?,vitality_points=?,language=? WHERE charId=?";
@@ -464,6 +472,11 @@ public final class L2PcInstance extends L2Playable
 	private long _punishTimer = 0;
 	private ScheduledFuture<?> _punishTask;
 	
+	private boolean _canFeed;
+	private int _eventEffectId = 0;
+	private boolean _isInSiege;
+	private boolean _isInHideoutSiege = false;
+	
 	public enum PunishLevel
 	{
 		NONE(0, ""),
@@ -4289,7 +4302,7 @@ public final class L2PcInstance extends L2Playable
 	public void enableSkill(L2Skill skill)
 	{
 		super.enableSkill(skill);
-		_reuseTimeStamps.remove(skill.getReuseHashCode());
+		_reuseTimeStampsSkills.remove(skill.getReuseHashCode());
 	}
 	
 	/**
@@ -7435,6 +7448,8 @@ public final class L2PcInstance extends L2Playable
 			if (Config.STORE_SKILL_COOLTIME)
 				player.restoreEffects();
 			
+			player.restoreItemReuse();
+			
 			// Restore current Cp, HP and MP values
 			player.setCurrentCp(currentCp);
 			player.setCurrentHp(currentHp);
@@ -7763,6 +7778,7 @@ public final class L2PcInstance extends L2Playable
 		storeCharBase();
 		storeCharSub();
 		storeEffect(storeActiveEffects);
+		storeItemReuseDelay();
 		transformInsertInfo();
 		if(Config.STORE_RECIPE_SHOPLIST)
 			storeRecipeShopList();
@@ -7962,9 +7978,9 @@ public final class L2PcInstance extends L2Playable
 						statement.setInt(4, effect.getCount());
 						statement.setInt(5, effect.getTime());
 						
-						if (_reuseTimeStamps.containsKey(skill.getReuseHashCode()))
+						if (_reuseTimeStampsSkills.containsKey(skill.getReuseHashCode()))
 						{
-							TimeStamp t = _reuseTimeStamps.get(skill.getReuseHashCode());
+							TimeStamp t = _reuseTimeStampsSkills.get(skill.getReuseHashCode());
 							statement.setLong(6, t.hasNotPassed() ? t.getReuse() : 0);
 							statement.setDouble(7, t.hasNotPassed() ? t.getStamp() : 0);
 						}
@@ -7984,13 +8000,17 @@ public final class L2PcInstance extends L2Playable
 			
 			// Store the reuse delays of remaining skills which
 			// lost effect but still under reuse delay. 'restore_type' 1.
-			for (int hash : _reuseTimeStamps.keys())
+			int hash;
+			TimeStamp t;
+			for (Entry<Integer, TimeStamp> ts : _reuseTimeStampsSkills.entrySet())
 			{
+				hash = ts.getKey();
 				if (storedSkills.contains(hash))
+				{
 					continue;
-				
-				TimeStamp t = _reuseTimeStamps.get(hash);
-				if (t != null && t.hasNotPassed())
+				}
+				t = ts.getValue();
+				if ((t != null) && t.hasNotPassed())
 				{
 					storedSkills.add(hash);
 					
@@ -8019,6 +8039,44 @@ public final class L2PcInstance extends L2Playable
 		}
 	}
 	
+	private void storeItemReuseDelay()
+	{
+		Connection con = null;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			PreparedStatement statement = con.prepareStatement(DELETE_ITEM_REUSE_SAVE);
+			
+			statement.setInt(1, getObjectId());
+			statement.execute();
+			statement.close();
+			
+			statement = con.prepareStatement(ADD_ITEM_REUSE_SAVE);
+			for (TimeStamp ts : _reuseTimeStampsItems.values())
+			{
+				if ((ts != null) && ts.hasNotPassed())
+				{
+					statement.setInt(1, getObjectId());
+					statement.setInt(2, ts.getItemId());
+					statement.setInt(3, ts.getItemObjectId());
+					statement.setLong(4, ts.getReuse());
+					statement.setDouble(5, ts.getStamp());
+					statement.execute();
+				}
+			}
+			statement.close();
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.WARNING, "Could not store char item reuse data: ", e);
+		}
+		finally
+		{
+			L2DatabaseFactory.close(con);
+		}
+	}
+	
 	/**
 	 * @return True if the L2PcInstance is on line.
 	 */
@@ -8349,6 +8407,79 @@ public final class L2PcInstance extends L2Playable
 		}
 	}
 	
+	/**
+	 * Retrieve from the database all Item Reuse Time of this L2PcInstance and add them to the player.
+	 */
+	private void restoreItemReuse()
+	{
+		Connection con = null;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement = con.prepareStatement(RESTORE_ITEM_REUSE_SAVE);
+			statement.setInt(1, getObjectId());
+			final ResultSet rset = statement.executeQuery();
+			int itemId;
+			@SuppressWarnings("unused")
+			int itemObjId;
+			long reuseDelay;
+			long systime;
+			boolean isInInventory;
+			long remainingTime;
+			while (rset.next())
+			{
+				itemId = rset.getInt("itemId");
+				itemObjId = rset.getInt("itemObjId");
+				reuseDelay = rset.getLong("reuseDelay");
+				systime = rset.getLong("systime");
+				isInInventory = true;
+				
+				// Using item Id
+				L2ItemInstance item = getInventory().getItemByItemId(itemId);
+				if (item == null)
+				{
+					item = getWarehouse().getItemByItemId(itemId);
+					isInInventory = false;
+				}
+				
+				if ((item != null) && (item.getItemId() == itemId) && (item.getReuseDelay() > 0))
+				{
+					remainingTime = systime - System.currentTimeMillis();
+					// Hardcoded to 10 seconds.
+					if (remainingTime > 10)
+					{
+						addTimeStampItem(item, reuseDelay, systime);
+						
+						if (isInInventory && item.isEtcItem())
+						{
+							final int group = item.getSharedReuseGroup();
+							if (group > 0)
+							{
+								sendPacket(new ExUseSharedGroupItem(itemId, group, (int) remainingTime, (int) reuseDelay));
+							}
+						}
+					}
+				}
+			}
+			
+			rset.close();
+			statement.close();
+			
+			statement = con.prepareStatement(DELETE_ITEM_REUSE_SAVE);
+			statement.setInt(1, getObjectId());
+			statement.executeUpdate();
+			statement.close();
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.WARNING, "Could not restore "+this+" Item Reuse data: " + e.getMessage(), e);
+		}
+		finally
+		{
+			L2DatabaseFactory.close(con);
+		}
+	}
+	
 	/**
 	 * Retrieve from the database all Henna of this L2PcInstance, add them to _henna and calculate stats of the L2PcInstance.<BR><BR>
 	 */
@@ -9009,10 +9140,9 @@ public final class L2PcInstance extends L2Playable
 		if (isSkillDisabled(skill))
 		{
 			SystemMessage sm = null;
-			
-			if (_reuseTimeStamps.containsKey(skill.getReuseHashCode()))
+			if (_reuseTimeStampsSkills.containsKey(skill.getReuseHashCode()))
 			{
-				int remainingTime = (int)(_reuseTimeStamps.get(skill.getReuseHashCode()).getRemaining()/1000);
+				int remainingTime = (int)(_reuseTimeStampsSkills.get(skill.getReuseHashCode()).getRemaining()/1000);
 				int hours = remainingTime/3600;
 				int minutes = (remainingTime%3600)/60;
 				int seconds = (remainingTime%60);
@@ -10878,7 +11008,7 @@ public final class L2PcInstance extends L2Playable
 			 * 2. Register the correct _classId against applied 'classIndex'.
 			 */
 			store(Config.SUBCLASS_STORE_SKILL_COOLTIME);
-			_reuseTimeStamps.clear();
+			_reuseTimeStampsSkills.clear();
 			
 			// clear charges
 			_charges.set(0);
@@ -13218,96 +13348,81 @@ public final class L2PcInstance extends L2Playable
 			addSkill(SkillTable.getInstance().getInfo(5076, getDeathPenaltyBuffLevel()), false);
 	}
 	
-	private final L2TIntObjectHashMap<TimeStamp> _reuseTimeStamps = new L2TIntObjectHashMap<TimeStamp>();
-	private boolean _canFeed;
-	private int _eventEffectId = 0;
-	private boolean _isInSiege;
-	private boolean _isInHideoutSiege = false;
+	private FastMap<Integer, TimeStamp> _reuseTimeStampsItems = new FastMap<>();
 	
-	public TimeStamp[] getReuseTimeStamps()
+	public void addTimeStampItem(L2ItemInstance item, long reuse)
 	{
-		return _reuseTimeStamps.values(new TimeStamp[0]);
+		_reuseTimeStampsItems.put(item.getObjectId(), new TimeStamp(item, reuse));
 	}
 	
-	public L2TIntObjectHashMap<TimeStamp> getReuseTimeStamp()
+	public void addTimeStampItem(L2ItemInstance item, long reuse, long systime)
 	{
-		return _reuseTimeStamps;
+		_reuseTimeStampsItems.put(item.getObjectId(), new TimeStamp(item, reuse, systime));
 	}
 	
-	/**
-	 * Simple class containing all neccessary information to maintain
-	 * valid timestamps and reuse for skills upon relog. Filter this
-	 * carefully as it becomes redundant to store reuse for small delays.
-	 * @author  Yesod
-	 */
-	public static class TimeStamp
+	public long getItemRemainingReuseTime(int itemObjId)
 	{
-		private final int _skillId;
-		private final int _skillLvl;
-		private final long _reuse;
-		private final long _stamp;
-		
-		public TimeStamp(L2Skill skill, long reuse)
-		{
-			_skillId = skill.getId();
-			_skillLvl = skill.getLevel();
-			_reuse = reuse;
-			_stamp = System.currentTimeMillis()+ reuse;
-		}
-		
-		public TimeStamp(L2Skill skill, long reuse, long systime)
+		if (_reuseTimeStampsItems.isEmpty() || !_reuseTimeStampsItems.containsKey(itemObjId))
 		{
-			_skillId = skill.getId();
-			_skillLvl = skill.getLevel();
-			_reuse = reuse;
-			_stamp = systime;
+			return -1;
 		}
-		
-		public long getStamp()
-		{
-			return _stamp;
-		}
-		
-		public int getSkillId()
-		{
-			return _skillId;
-		}
-		
-		public int getSkillLvl()
-		{
-			return _skillLvl;
-		}
-		
-		public long getReuse()
+		return _reuseTimeStampsItems.get(itemObjId).getRemaining();
+	}
+	
+	public long getReuseDelayOnGroup(int group)
+	{
+		if (group > 0)
 		{
-			return _reuse;
+			for (TimeStamp ts : _reuseTimeStampsItems.values())
+			{
+				if ((ts.getSharedReuseGroup() == group) && ts.hasNotPassed())
+				{
+					return ts.getRemaining();
+				}
+			}
 		}
-		
-		public long getRemaining()
+		return 0;
+	}
+	
+	private final FastMap<Integer, TimeStamp> _reuseTimeStampsSkills = new FastMap<>();
+	
+	public FastMap<Integer, TimeStamp> getSkillReuseTimeStamps()
+	{
+		return _reuseTimeStampsSkills;
+	}
+	
+	public long getSkillRemainingReuseTime(int skillReuseHashId)
+	{
+		if (_reuseTimeStampsSkills.isEmpty() || !_reuseTimeStampsSkills.containsKey(skillReuseHashId))
 		{
-			return Math.max(_stamp - System.currentTimeMillis(), 0);
+			return -1;
 		}
-		
-		/* Check if the reuse delay has passed and
-		 * if it has not then update the stored reuse time
-		 * according to what is currently remaining on
-		 * the delay. */
-		public boolean hasNotPassed()
+		return _reuseTimeStampsSkills.get(skillReuseHashId).getRemaining();
+	}
+	
+	public boolean hasSkillReuse(int skillReuseHashId)
+	{
+		if (_reuseTimeStampsSkills.isEmpty() || !_reuseTimeStampsSkills.containsKey(skillReuseHashId))
 		{
-			return System.currentTimeMillis() < _stamp;
+			return false;
 		}
+		return _reuseTimeStampsSkills.get(skillReuseHashId).hasNotPassed();
+	}
+	
+	public TimeStamp getSkillReuseTimeStamp(int skillReuseHashId)
+	{
+		return _reuseTimeStampsSkills.get(skillReuseHashId);
 	}
 	
 	/**
-	 * Index according to skill id the current
-	 * timestamp of use.
+	 * Index according to skill id the current timestamp of use.
 	 * @param skill
 	 * @param reuse delay
 	 */
 	@Override
 	public void addTimeStamp(L2Skill skill, long reuse)
 	{
-		_reuseTimeStamps.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse));
+		_reuseTimeStampsSkills.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse));
 	}
 	
 	/**
@@ -13319,9 +13434,11 @@ public final class L2PcInstance extends L2Playable
 	 */
 	public void addTimeStamp(L2Skill skill, long reuse, long systime)
 	{
-		_reuseTimeStamps.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse, systime));
+		_reuseTimeStampsSkills.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse, systime));
 	}
 	
+	
+	
 	@Override
 	public L2PcInstance getActingPlayer()
 	{
@@ -13437,10 +13554,8 @@ public final class L2PcInstance extends L2Playable
 		getStat().updateVitalityPoints(points, useRates, quiet);
 	}
 	
-	/*
-	 * Function for skill summon friend or Gate Chant.
-	 */
 	/**
+	 * Function for skill summon friend or Gate Chant.
 	 * Request Teleport 
 	 * @param requester 
 	 * @param skill 

+ 2 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/itemcontainer/Inventory.java

@@ -402,8 +402,7 @@ public abstract class Inventory extends ItemContainer
 						
 						if (itemSkill.isActive())
 						{
-							if (player.getReuseTimeStamp().isEmpty()
-									|| !player.getReuseTimeStamp().containsKey(itemSkill.getReuseHashCode()))
+							if (player.hasSkillReuse(itemSkill.getReuseHashCode()))
 							{
 								int equipDelay = itemSkill.getEquipDelay();
 								
@@ -499,8 +498,7 @@ public abstract class Inventory extends ItemContainer
 										
 										if (itemSkill.isActive())
 										{
-											if (player.getReuseTimeStamp().isEmpty()
-													|| !player.getReuseTimeStamp().containsKey(itemSkill.getReuseHashCode()))
+											if (player.hasSkillReuse(itemSkill.getReuseHashCode()))
 											{
 												int equipDelay = itemSkill.getEquipDelay();
 												

+ 0 - 10
L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/L2EtcItem.java

@@ -29,7 +29,6 @@ import com.l2jserver.util.StringUtil;
 public final class L2EtcItem extends L2Item
 {
 	private String _handler;
-	private final int _sharedReuseGroup;
 	private L2EtcItemType _type;
 	private final boolean _isBlessed;
 	private final List<L2ExtractableProduct> _extractableItems;
@@ -75,7 +74,6 @@ public final class L2EtcItem extends L2Item
 		}
 		
 		_handler = set.getString("handler", null); // ! null !
-		_sharedReuseGroup = set.getInteger("shared_reuse_group", -1);
 		_isBlessed = set.getBool("blessed", false);
 		
 		// Extractable
@@ -158,14 +156,6 @@ public final class L2EtcItem extends L2Item
 		return _handler;
 	}
 	
-	/**
-	 * @return the shared reuse time group.
-	 */
-	public int getSharedReuseGroup()
-	{
-		return _sharedReuseGroup;
-	}
-	
 	/**
 	 * @return {@code true} if the item is blessed, {@code false} otherwise.
 	 */

+ 25 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/L2Item.java

@@ -57,6 +57,8 @@ import com.l2jserver.util.StringUtil;
  */
 public abstract class L2Item
 {
+	protected static final Logger _log = Logger.getLogger(L2Item.class.getName());
+	
 	public static final int TYPE1_WEAPON_RING_EARRING_NECKLACE = 0;
 	public static final int TYPE1_SHIELD_ARMOR = 1;
 	public static final int TYPE1_ITEM_QUESTITEM_ADENA = 4;
@@ -205,7 +207,8 @@ public abstract class L2Item
 	
 	private final List<Quest> _questEvents = new FastList<Quest>();
 	private final int _useSkillDisTime;
-	protected static final Logger _log = Logger.getLogger(L2Item.class.getName());
+	private final int _reuseDelay;
+	private int _sharedReuseGroup;
 	
 	/**
 	 * Constructor of the L2Item that fill class variables.<BR><BR>
@@ -245,6 +248,8 @@ public abstract class L2Item
 		//used for custom type select
 		_defaultAction = set.getEnum("default_action", L2ActionType.class, L2ActionType.none);
 		_useSkillDisTime = set.getInteger("useSkillDisTime", 0);
+		_reuseDelay = set.getInteger("reuse_delay", 0);
+		_sharedReuseGroup = set.getInteger("shared_reuse_group", 0);
 		
 		//TODO cleanup + finish
 		String equip_condition = set.getString("equip_condition", null);
@@ -995,10 +1000,26 @@ public abstract class L2Item
 	{
 		return _useSkillDisTime;
 	}
-
+	
+	/**
+	 * @return the Reuse Delay of item.
+	 */
+	public int getReuseDelay()
+	{
+		return _reuseDelay;
+	}
+	
+	/**
+	 * @return the shared reuse group.
+	 */
+	public int getSharedReuseGroup()
+	{
+		return _sharedReuseGroup;
+	}
+	
 	/**
-	 * Get the icon link in client files.<BR> Usable in HTML windows.
-	 * @return the _icon
+	 * Usable in HTML windows.
+	 * @return the icon link in client files.
 	 */
 	public String getIcon()
 	{

+ 0 - 11
L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/L2Weapon.java

@@ -65,8 +65,6 @@ public final class L2Weapon extends L2Item
 	private SkillHolder _skillsOnCrit;
 	private Condition _skillsOnCritCondition = null;
 	
-	private final int _reuseDelay;
-	
 	private final boolean _isForceEquip;
 	private final boolean _isAttackWeapon;
 	private final boolean _useWeaponSkillsOnly;
@@ -87,7 +85,6 @@ public final class L2Weapon extends L2Item
 		_spiritShotCount = set.getInteger("spiritshots", 0);
 		_rndDam = set.getInteger("random_damage", 0);
 		_mpConsume = set.getInteger("mp_consume", 0);
-		_reuseDelay = set.getInteger("reuse_delay", 0);
 		
 		String skill = set.getString("enchant4_skill", null);
 		if (skill != null)
@@ -241,14 +238,6 @@ public final class L2Weapon extends L2Item
 		return _rndDam;
 	}
 	
-	/**
-	 * @return the Reuse Delay of the L2Weapon.
-	 */
-	public int getReuseDelay()
-	{
-		return _reuseDelay;
-	}
-	
 	/**
 	 * @return the MP consumption with the weapon.
 	 */

+ 29 - 26
L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/instance/L2ItemInstance.java

@@ -566,8 +566,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the type of item
-	 * @return Enum
+	 * @return the type of item.
 	 */
 	public L2ItemType getItemType()
 	{
@@ -575,8 +574,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the ID of the item
-	 * @return int
+	 * @return the Id of the item.
 	 */
 	public int getItemId()
 	{
@@ -584,8 +582,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the ID of the item
-	 * @return int
+	 * @return the display Id of the item.
 	 */
 	public int getDisplayId()
 	{
@@ -593,8 +590,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns true if item is an EtcItem
-	 * @return boolean
+	 * @return {@code true} if item is an EtcItem, {@code false} otherwise.
 	 */
 	public boolean isEtcItem()
 	{
@@ -602,8 +598,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns true if item is a Weapon/Shield
-	 * @return boolean
+	 * @return {@code true} if item is a Weapon/Shield, {@code false} otherwise.
 	 */
 	public boolean isWeapon()
 	{
@@ -611,8 +606,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns true if item is an Armor
-	 * @return boolean
+	 * @return {@code true} if item is an Armor, {@code false} otherwise.
 	 */
 	public boolean isArmor()
 	{
@@ -620,8 +614,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the characteristics of the L2EtcItem
-	 * @return L2EtcItem
+	 * @return the characteristics of the L2EtcItem, {@code false} otherwise.
 	 */
 	public L2EtcItem getEtcItem()
 	{
@@ -633,8 +626,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the characteristics of the L2Weapon
-	 * @return L2Weapon
+	 * @return the characteristics of the L2Weapon.
 	 */
 	public L2Weapon getWeaponItem()
 	{
@@ -646,8 +638,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the characteristics of the L2Armor
-	 * @return L2Armor
+	 * @return the characteristics of the L2Armor.
 	 */
 	public L2Armor getArmorItem()
 	{
@@ -659,8 +650,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the quantity of crystals for crystallization
-	 * @return int
+	 * @return the quantity of crystals for crystallization.
 	 */
 	public final int getCrystalCount()
 	{
@@ -668,8 +658,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the reference price of the item
-	 * @return int
+	 * @return the reference price of the item.
 	 */
 	public int getReferencePrice()
 	{
@@ -677,8 +666,7 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the name of the item
-	 * @return String
+	 * @return the name of the item.
 	 */
 	public String getItemName()
 	{
@@ -686,8 +674,23 @@ public final class L2ItemInstance extends L2Object
 	}
 	
 	/**
-	 * Returns the last change of the item
-	 * @return int
+	 * @return the reuse delay of this item.
+	 */
+	public int getReuseDelay()
+	{
+		return _item.getReuseDelay();
+	}
+	
+	/**
+	 * @return the shared reuse item group.
+	 */
+	public int getSharedReuseGroup()
+	{
+		return _item.getSharedReuseGroup();
+	}
+	
+	/**
+	 * @return the last change of the item
 	 */
 	public int getLastChange()
 	{

+ 1 - 16
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/L2Skill.java

@@ -393,22 +393,7 @@ public abstract class L2Skill implements IChanceSkillTrigger
 		_coolTime = set.getInteger("coolTime", 0);
 		_isDebuff = set.getBool("isDebuff", false);
 		_feed = set.getInteger("feed", 0);
-		
-		String reuseHash = set.getString("sharedReuse", null);
-		if (reuseHash != null)
-		{
-			try
-			{
-				String[] valuesSplit = reuseHash.split("-");
-				_reuseHashCode = SkillTable.getSkillHashCode(Integer.parseInt(valuesSplit[0]), Integer.parseInt(valuesSplit[1]));
-			}
-			catch (Exception e)
-			{
-				throw new IllegalArgumentException("SkillId: "+_id+" invalid sharedReuse value: "+reuseHash+", \"skillId-skillLvl\" required");
-			}
-		}
-		else
-			_reuseHashCode = SkillTable.getSkillHashCode(_id, _level);
+		_reuseHashCode = SkillTable.getSkillHashCode(_id, _level);
 		
 		if (Config.ENABLE_MODIFY_SKILL_REUSE && Config.SKILL_REUSE_LIST.containsKey(_id))
 		{

+ 91 - 22
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/UseItem.java

@@ -40,8 +40,8 @@ import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.L2SkillType;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
+import com.l2jserver.gameserver.network.serverpackets.ExUseSharedGroupItem;
 import com.l2jserver.gameserver.network.serverpackets.ItemList;
-import com.l2jserver.gameserver.network.serverpackets.ShowCalculator;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
 
 /**
@@ -94,7 +94,14 @@ public final class UseItem extends L2GameClientPacket
 	{
 		final L2PcInstance activeChar = getClient().getActiveChar();
 		if (activeChar == null)
+		{
 			return;
+		}
+		
+		if (Config.DEBUG)
+		{
+			_log.log(Level.INFO, activeChar + ": use item " + _objectId);
+		}
 		
 		// Flood protect UseItem
 		if (!getClient().getFloodProtectors().getUseItem().tryPerformAction("use item"))
@@ -142,14 +149,13 @@ public final class UseItem extends L2GameClientPacket
 		if (!item.isEquipped() && !item.getItem().checkCondition(activeChar, activeChar, true))
 			return;
 		
-		if (!activeChar.getInventory().canManipulateWithItemId(item.getItemId()))
+		_itemId = item.getItemId();
+		if (!activeChar.getInventory().canManipulateWithItemId(_itemId))
 		{
 			activeChar.sendMessage("Cannot use this item.");
 			return;
 		}
 		
-		_itemId = item.getItemId();
-		
 		if (activeChar.isFishing() && (_itemId < 6535 || _itemId > 6540))
 		{
 			// You cannot do anything else while fishing
@@ -172,11 +178,31 @@ public final class UseItem extends L2GameClientPacket
 
 		}
 		
-		if (Config.DEBUG)
-			_log.log(Level.INFO, activeChar.getObjectId() + ": use item " + _objectId);
+		// If the item has reuse time and it has not passed.
+		// Message from reuse delay must come from item.
+		final int reuseDelay = item.getReuseDelay();
+		final int sharedReuseGroup = item.getSharedReuseGroup();
+		if (reuseDelay > 0)
+		{
+			final long reuse = activeChar.getItemRemainingReuseTime(item.getObjectId());
+			if (reuse > 0)
+			{
+				reuseData(activeChar, item);
+				sendSharedGroupUpdate(activeChar, sharedReuseGroup, reuse, reuseDelay);
+				return;
+			}
+			
+			final long reuseOnGroup = activeChar.getReuseDelayOnGroup(sharedReuseGroup); 
+			if (reuseOnGroup > 0)
+			{
+				reuseData(activeChar, item);
+				sendSharedGroupUpdate(activeChar, sharedReuseGroup, reuseOnGroup, reuseDelay);
+				return;
+			}
+		}
 		
 		if (item.isEquipable())
-		{	
+		{
 			// Don't allow to put formal wear while a cursed weapon is equipped.
 			if (activeChar.isCursedWeaponEquipped() && _itemId == 6408)
 			{
@@ -184,7 +210,7 @@ public final class UseItem extends L2GameClientPacket
 			}
 			
 			// Equip or unEquip
-			if (FortSiegeManager.getInstance().isCombat(item.getItemId()))
+			if (FortSiegeManager.getInstance().isCombat(_itemId))
 				return;	//no message
 			else if (activeChar.isCombatFlagEquipped())
 				return;
@@ -308,16 +334,12 @@ public final class UseItem extends L2GameClientPacket
 		else
 		{
 			if(activeChar.isCastingNow() && !(item.isPotion() || item.isElixir()))
-				return;
-			
-			L2Weapon weaponItem = activeChar.getActiveWeaponItem();
-			int itemid = item.getItemId();
-			if (itemid == 4393)
 			{
-				activeChar.sendPacket(new ShowCalculator(4393));
+				return;
 			}
-			else if ((weaponItem != null && weaponItem.getItemType() == L2WeaponType.FISHINGROD)
-					&& ((itemid >= 6519 && itemid <= 6527) || (itemid >= 7610 && itemid <= 7613) || (itemid >= 7807 && itemid <= 7809) || (itemid >= 8484 && itemid <= 8486) || (itemid >= 8505 && itemid <= 8513)))
+			
+			final L2Weapon weaponItem = activeChar.getActiveWeaponItem();
+			if ((weaponItem != null && weaponItem.getItemType() == L2WeaponType.FISHINGROD) && ((_itemId >= 6519 && _itemId <= 6527) || (_itemId >= 7610 && _itemId <= 7613) || (_itemId >= 7807 && _itemId <= 7809) || (_itemId >= 8484 && _itemId <= 8486) || (_itemId >= 8505 && _itemId <= 8513)))
 			{
 				activeChar.getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, item);
 				activeChar.broadcastUserInfo();
@@ -325,17 +347,64 @@ public final class UseItem extends L2GameClientPacket
 				sendPacket(new ItemList(activeChar, false));
 				return;
 			}
-			else
+			
+			final IItemHandler handler = ItemHandler.getInstance().getHandler(item.getEtcItem());
+			if (handler == null)
 			{
-				IItemHandler handler = ItemHandler.getInstance().getHandler(item.getEtcItem());
-				if (handler != null)
-					handler.useItem(activeChar, item, _ctrlPressed);
-				else if (Config.DEBUG)
-					_log.log(Level.WARNING, "No item handler registered for item ID " + item.getItemId() + ".");
+				_log.log(Level.WARNING, "No item handler registered for item ID " + _itemId + ".");
+				return;
+			}
+			
+			// Item reuse time should be added if the item is successfully used.
+			// Skill reuse delay is done at handlers.itemhandlers.ItemSkillsTemplate;
+			if (handler.useItem(activeChar, item, _ctrlPressed))
+			{
+				if (reuseDelay > 0)
+				{
+					activeChar.addTimeStampItem(item, reuseDelay);
+					sendSharedGroupUpdate(activeChar, sharedReuseGroup, reuseDelay, reuseDelay);
+				}
 			}
 		}
 	}
 	
+	private void reuseData(L2PcInstance activeChar, L2ItemInstance item)
+	{
+		SystemMessage sm = null;
+		final long remainingTime = activeChar.getItemRemainingReuseTime(item.getObjectId());
+		final int hours = (int) (remainingTime / 3600000L);
+		final int minutes = (int) (remainingTime % 3600000L) / 60000;
+		final int seconds = (int) (remainingTime / 1000 % 60);
+		if (hours > 0)
+		{
+			sm = SystemMessage.getSystemMessage(SystemMessageId.S2_HOURS_S3_MINUTES_S4_SECONDS_REMAINING_FOR_REUSE_S1);
+			sm.addItemName(item);
+			sm.addNumber(hours);
+			sm.addNumber(minutes);
+		}
+		else if (minutes > 0)
+		{
+			sm = SystemMessage.getSystemMessage(SystemMessageId.S2_MINUTES_S3_SECONDS_REMAINING_FOR_REUSE_S1);
+			sm.addItemName(item);
+			sm.addNumber(minutes);
+		}
+		else
+		{
+			sm = SystemMessage.getSystemMessage(SystemMessageId.S2_SECONDS_REMAINING_FOR_REUSE_S1);
+			sm.addItemName(item);
+		}
+		sm.addNumber(seconds);
+		activeChar.sendPacket(sm);
+	}
+	
+	private void sendSharedGroupUpdate(L2PcInstance activeChar, int group, long remaining, int reuse)
+	{
+		if (group > 0)
+		{
+			activeChar.sendPacket(new ExUseSharedGroupItem(_itemId, group, remaining, reuse));
+		}
+	}
+	
 	@Override
 	public String getType()
 	{

+ 12 - 15
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/ExUseSharedGroupItem.java

@@ -20,39 +20,36 @@ package com.l2jserver.gameserver.network.serverpackets;
  */
 public class ExUseSharedGroupItem extends L2GameServerPacket
 {
-	private static final String _S__FE_4A_EXUSESHAREDGROUPITEM = "[S] FE:4a ExUseSharedGroupItem";
-	private int _itemId, _grpId, _remainedTime, _totalTime;
+	private static final String _S__FE_4A_EXUSESHAREDGROUPITEM = "[S] FE:4A ExUseSharedGroupItem";
 	
-	public ExUseSharedGroupItem(int itemId, int grpId, int remainedTime, int totalTime)
+	private final int _itemId;
+	private final int _grpId;
+	private final int _remainingTime;
+	private final int _totalTime;
+	
+	public ExUseSharedGroupItem(int itemId, int grpId, long remainingTime, int totalTime)
 	{
 		_itemId = itemId;
 		_grpId = grpId;
-		_remainedTime = remainedTime / 1000;
+		_remainingTime = (int) (remainingTime / 1000);
 		_totalTime = totalTime / 1000;
 	}
 	
-	/**
-	 * @see com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket#writeImpl()
-	 */
 	@Override
 	protected void writeImpl()
 	{
-		writeC(0xfe);
-		writeH(0x4a);
+		writeC(0xFE);
+		writeH(0x4A);
 		
 		writeD(_itemId);
 		writeD(_grpId);
-		writeD(_remainedTime);
+		writeD(_remainingTime);
 		writeD(_totalTime);
 	}
 	
-	/**
-	 * @see com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket#getType()
-	 */
 	@Override
 	public String getType()
 	{
 		return _S__FE_4A_EXUSESHAREDGROUPITEM;
 	}
-	
-}
+}

+ 17 - 26
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/SkillCoolTime.java

@@ -14,51 +14,37 @@
  */
 package com.l2jserver.gameserver.network.serverpackets;
 
-import java.util.Collections;
-
 import javolution.util.FastList;
 
+import com.l2jserver.gameserver.model.TimeStamp;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.actor.instance.L2PcInstance.TimeStamp;
-
 
 /**
- *
- * @author  KenM
+ * @author KenM, Zoey76
  */
 public class SkillCoolTime extends L2GameServerPacket
 {
-	public FastList<TimeStamp> _reuseTimeStamps;
+	private static final String _S__C7_SKILLCOOLTIME = "[S] C7 SkillCoolTime";
+	
+	private final FastList<TimeStamp> _skillReuseTimeStamps = new FastList<>();
 	
 	public SkillCoolTime(L2PcInstance cha)
 	{
-		_reuseTimeStamps = new FastList<TimeStamp>();
-		Collections.addAll(_reuseTimeStamps, cha.getReuseTimeStamps());
-		for (TimeStamp ts : _reuseTimeStamps)
+		for (TimeStamp ts : cha.getSkillReuseTimeStamps().values())
 		{
 			if (!ts.hasNotPassed())
-				_reuseTimeStamps.remove(ts);
+			{
+				_skillReuseTimeStamps.add(ts);
+			}
 		}
 	}
 	
-	/**
-	 * @see com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket#getType()
-	 */
-	@Override
-	public String getType()
-	{
-		return "[S] C7 SkillCoolTime";
-	}
-	
-	/**
-	 * @see com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket#writeImpl()
-	 */
 	@Override
 	protected void writeImpl()
 	{
-		writeC(0xc7);
-		writeD(_reuseTimeStamps.size()); // list size
-		for (TimeStamp ts : _reuseTimeStamps)
+		writeC(0xC7);
+		writeD(_skillReuseTimeStamps.size()); // list size
+		for (TimeStamp ts : _skillReuseTimeStamps)
 		{
 			writeD(ts.getSkillId());
 			writeD(0x00);
@@ -67,4 +53,9 @@ public class SkillCoolTime extends L2GameServerPacket
 		}
 	}
 	
+	@Override
+	public String getType()
+	{
+		return _S__C7_SKILLCOOLTIME;
+	}
 }