Browse Source

Skills reuse rework part 2, DP update required !
Instead of using only skillId for storing reuse delay now we using integer hash(skillId, skillLvl).
Hash can be overriden in xml (if you want several skills share same reuse delay):
<set name="sharedReuse" val="2287-1" /> (skillId-skillLvl)
Also added augmentation skills fix by Gnacik (equip delay replaced with reuse delay).

_DS_ 15 years ago
parent
commit
d855ceae1b

+ 11 - 11
L2_GameServer/java/com/l2jserver/gameserver/ai/L2AttackableAI.java

@@ -887,7 +887,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						if(sk.getTargetType() == L2Skill.SkillTargetType.TARGET_SELF)
 							continue;
 						if((sk.getMpConsume()>=_actor.getCurrentMp()
-								|| _actor.isSkillDisabled(sk.getId())
+								|| _actor.isSkillDisabled(sk)
 								||(sk.isMagic()&&_actor.isMuted())
 								||(!sk.isMagic()&&_actor.isPhysicalMuted())))
 						{
@@ -912,7 +912,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				for(L2Skill sk:_skillrender._healskills)
 				{
 					if((sk.getMpConsume() >= _actor.getCurrentMp()
-							|| _actor.isSkillDisabled(sk.getId())
+							|| _actor.isSkillDisabled(sk)
 							||(sk.isMagic() && _actor.isMuted()))
 							||(!sk.isMagic() && _actor.isPhysicalMuted()))
 					{
@@ -926,7 +926,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			for(L2Skill sk:_skillrender._healskills)
 			{
 				if((sk.getMpConsume() >= _actor.getCurrentMp()
-						|| _actor.isSkillDisabled(sk.getId())
+						|| _actor.isSkillDisabled(sk)
 						||(sk.isMagic() && _actor.isMuted()))
 						||(!sk.isMagic() && _actor.isPhysicalMuted()))
 				{
@@ -974,7 +974,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						if(sk.getTargetType() == L2Skill.SkillTargetType.TARGET_SELF)
 							continue;
 						if((sk.getMpConsume() >= _actor.getCurrentMp()
-								|| _actor.isSkillDisabled(sk.getId())
+								|| _actor.isSkillDisabled(sk)
 								||(sk.isMagic() && _actor.isMuted())
 								||(!sk.isMagic() && _actor.isPhysicalMuted())))
 						{
@@ -998,7 +998,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			for(L2Skill sk:_skillrender._resskills)
 			{
 				if((sk.getMpConsume() >= _actor.getCurrentMp()
-						|| _actor.isSkillDisabled(sk.getId())
+						|| _actor.isSkillDisabled(sk)
 						||(sk.isMagic() && _actor.isMuted()))
 						||(!sk.isMagic() && _actor.isPhysicalMuted()))
 				{
@@ -1159,7 +1159,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 	{
 		if (sk == null)
 			return false;
-		if (sk.getMpConsume() >= _actor.getCurrentMp() || _actor.isSkillDisabled(sk.getId())
+		if (sk.getMpConsume() >= _actor.getCurrentMp() || _actor.isSkillDisabled(sk)
 				|| (sk.isMagic() && _actor.isMuted()) || (!sk.isMagic() && _actor.isPhysicalMuted()))
 			return false;
 		if(getAttackTarget() == null)
@@ -1747,7 +1747,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				for(L2Skill sk : _skillrender._immobiliseskills)
 				{
 					if(sk.getMpConsume() >= _actor.getCurrentMp()
-							|| _actor.isSkillDisabled(sk.getId())
+							|| _actor.isSkillDisabled(sk)
 							|| (sk.getCastRange()+ _actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius <= dist2 && !canAura(sk))
 							|| (sk.isMagic()&&_actor.isMuted())
 							|| (!sk.isMagic()&&_actor.isPhysicalMuted()))
@@ -1774,7 +1774,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				for(L2Skill sk:_skillrender._cotskills)
 				{
 					if(sk.getMpConsume()>=_actor.getCurrentMp()
-							|| _actor.isSkillDisabled(sk.getId())
+							|| _actor.isSkillDisabled(sk)
 							||(sk.getCastRange()+ _actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius <= dist2 && !canAura(sk))
 							||(sk.isMagic()&&_actor.isMuted())
 							||(!sk.isMagic()&&_actor.isPhysicalMuted()))
@@ -1800,7 +1800,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				for(L2Skill sk:_skillrender._debuffskills)
 				{
 					if(sk.getMpConsume()>=_actor.getCurrentMp()
-							|| _actor.isSkillDisabled(sk.getId())
+							|| _actor.isSkillDisabled(sk)
 							||(sk.getCastRange()+ _actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius <= dist2 && !canAura(sk))
 							||(sk.isMagic()&&_actor.isMuted())
 							||(!sk.isMagic()&&_actor.isPhysicalMuted()))
@@ -1827,7 +1827,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				for(L2Skill sk : _skillrender._negativeskills)
 				{
 					if(sk.getMpConsume() >= _actor.getCurrentMp()
-							|| _actor.isSkillDisabled(sk.getId())
+							|| _actor.isSkillDisabled(sk)
 							||(sk.getCastRange() + _actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius <= dist2 && !canAura(sk))
 							||(sk.isMagic()&&_actor.isMuted())
 							||(!sk.isMagic()&&_actor.isPhysicalMuted()))
@@ -1854,7 +1854,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				for(L2Skill sk:_skillrender._atkskills)
 				{
 					if(sk.getMpConsume()>=_actor.getCurrentMp()
-							|| _actor.isSkillDisabled(sk.getId())
+							|| _actor.isSkillDisabled(sk)
 							||(sk.getCastRange()+ _actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius <= dist2 && !canAura(sk))
 							||(sk.isMagic()&&_actor.isMuted())
 							||(!sk.isMagic()&&_actor.isPhysicalMuted()))

+ 5 - 5
L2_GameServer/java/com/l2jserver/gameserver/ai/L2ControllableMobAI.java

@@ -152,7 +152,7 @@ public class L2ControllableMobAI extends L2AttackableAI
 			
 			for (L2Skill sk : skills)
 			{
-				if (Util.checkIfInRange(sk.getCastRange(), _actor, getAttackTarget(), true) && !_actor.isSkillDisabled(sk.getId()) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+				if (Util.checkIfInRange(sk.getCastRange(), _actor, getAttackTarget(), true) && !_actor.isSkillDisabled(sk) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
 				{
 					_accessor.doCast(sk);
 					return;
@@ -212,7 +212,7 @@ public class L2ControllableMobAI extends L2AttackableAI
 			{
 				int castRange = sk.getCastRange();
 				
-				if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk.getId()) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+				if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
 				{
 					_accessor.doCast(sk);
 					return;
@@ -264,7 +264,7 @@ public class L2ControllableMobAI extends L2AttackableAI
 			{
 				int castRange = sk.getCastRange();
 				
-				if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk.getId()) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+				if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
 				{
 					_accessor.doCast(sk);
 					return;
@@ -349,7 +349,7 @@ public class L2ControllableMobAI extends L2AttackableAI
 				{
 					int castRange = sk.getCastRange();
 					
-					if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk.getId()) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
+					if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk) && _actor.getCurrentMp() > _actor.getStat().getMpConsume(sk))
 					{
 						_accessor.doCast(sk);
 						return;
@@ -385,7 +385,7 @@ public class L2ControllableMobAI extends L2AttackableAI
 				{
 					int castRange = sk.getCastRange();
 					
-					if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk.getId()) && _actor.getCurrentMp() < _actor.getStat().getMpConsume(sk))
+					if (castRange * castRange >= dist2 && !_actor.isSkillDisabled(sk) && _actor.getCurrentMp() < _actor.getStat().getMpConsume(sk))
 					{
 						_accessor.doCast(sk);
 						return;

+ 4 - 4
L2_GameServer/java/com/l2jserver/gameserver/ai/L2FortSiegeGuardAI.java

@@ -412,7 +412,7 @@ public class L2FortSiegeGuardAI extends L2CharacterAI implements Runnable
 						{
 							if (_actor.getCurrentMp() < sk.getMpConsume())
 								continue;
-							if (_actor.isSkillDisabled(sk.getId()))
+							if (_actor.isSkillDisabled(sk))
 								continue;
 							if (!Util.checkIfInRange(sk.getCastRange(), _actor, cha, true))
 								continue;
@@ -460,7 +460,7 @@ public class L2FortSiegeGuardAI extends L2CharacterAI implements Runnable
 					{
 						if (_actor.getCurrentMp() < sk.getMpConsume())
 							continue;
-						if (_actor.isSkillDisabled(sk.getId()))
+						if (_actor.isSkillDisabled(sk))
 							continue;
 						if (!Util.checkIfInRange(sk.getCastRange(), _actor, npc, true))
 							continue;
@@ -541,7 +541,7 @@ public class L2FortSiegeGuardAI extends L2CharacterAI implements Runnable
 			{
 				int castRange = sk.getCastRange();
 				
-				if ((dist_2 <= castRange * castRange) && castRange > 70 && !_actor.isSkillDisabled(sk.getId()) && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !sk.isPassive())
+				if ((dist_2 <= castRange * castRange) && castRange > 70 && !_actor.isSkillDisabled(sk) && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !sk.isPassive())
 				{
 					
 					L2Object OldTarget = _actor.getTarget();
@@ -670,7 +670,7 @@ public class L2FortSiegeGuardAI extends L2CharacterAI implements Runnable
 				{
 					int castRange = sk.getCastRange();
 					
-					if (castRange * castRange >= dist_2 && !sk.isPassive() && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !_actor.isSkillDisabled(sk.getId()))
+					if (castRange * castRange >= dist_2 && !sk.isPassive() && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !_actor.isSkillDisabled(sk))
 					{
 						L2Object OldTarget = _actor.getTarget();
 						if (sk.getSkillType() == L2SkillType.BUFF || sk.getSkillType() == L2SkillType.HEAL)

+ 4 - 4
L2_GameServer/java/com/l2jserver/gameserver/ai/L2SiegeGuardAI.java

@@ -396,7 +396,7 @@ public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
 						{
 							if (_actor.getCurrentMp() < sk.getMpConsume())
 								continue;
-							if (_actor.isSkillDisabled(sk.getId()))
+							if (_actor.isSkillDisabled(sk))
 								continue;
 							if (!Util.checkIfInRange(sk.getCastRange(), _actor, cha, true))
 								continue;
@@ -444,7 +444,7 @@ public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
 					{
 						if (_actor.getCurrentMp() < sk.getMpConsume())
 							continue;
-						if (_actor.isSkillDisabled(sk.getId()))
+						if (_actor.isSkillDisabled(sk))
 							continue;
 						if (!Util.checkIfInRange(sk.getCastRange(), _actor, npc, true))
 							continue;
@@ -521,7 +521,7 @@ public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
 			{
 				int castRange = sk.getCastRange();
 				
-				if ((dist_2 <= castRange * castRange) && castRange > 70 && !_actor.isSkillDisabled(sk.getId()) && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !sk.isPassive())
+				if ((dist_2 <= castRange * castRange) && castRange > 70 && !_actor.isSkillDisabled(sk) && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !sk.isPassive())
 				{
 					
 					L2Object OldTarget = _actor.getTarget();
@@ -648,7 +648,7 @@ public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
 				{
 					int castRange = sk.getCastRange();
 					
-					if (castRange * castRange >= dist_2 && !sk.isPassive() && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !_actor.isSkillDisabled(sk.getId()))
+					if (castRange * castRange >= dist_2 && !sk.isPassive() && _actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk) && !_actor.isSkillDisabled(sk))
 					{
 						L2Object OldTarget = _actor.getTarget();
 						if (sk.getSkillType() == L2SkillType.BUFF || sk.getSkillType() == L2SkillType.HEAL)

+ 4 - 4
L2_GameServer/java/com/l2jserver/gameserver/model/ChanceSkillList.java

@@ -150,11 +150,11 @@ public class ChanceSkillList extends FastMap<IChanceSkillTrigger, ChanceConditio
 						return;
 				} 
 
-				if (_owner.isSkillDisabled(skill.getId()))
+				if (_owner.isSkillDisabled(skill))
 					return;
 
 				if (skill.getReuseDelay() > 0)
-					_owner.disableSkill(skill.getId(), skill.getReuseDelay());
+					_owner.disableSkill(skill, skill.getReuseDelay());
 
 				L2Object[] targets = skill.getTargetList(_owner, false, target);
 
@@ -195,11 +195,11 @@ public class ChanceSkillList extends FastMap<IChanceSkillTrigger, ChanceConditio
 			if (caster == null
 					|| triggered == null
 					|| triggered.getSkillType() == L2SkillType.NOTDONE
-					|| caster.isSkillDisabled(triggered.getId()))
+					|| caster.isSkillDisabled(triggered))
 				return;
 
 			if (triggered.getReuseDelay() > 0)
-				caster.disableSkill(triggered.getId(), triggered.getReuseDelay());
+				caster.disableSkill(triggered, triggered.getReuseDelay());
 
 			L2Object[] targets = triggered.getTargetList(caster, false, target);
 

+ 5 - 6
L2_GameServer/java/com/l2jserver/gameserver/model/L2Augmentation.java

@@ -131,16 +131,15 @@ public final class L2Augmentation
 			player.addSkill(_skill);
 			if (_skill.isActive())
 			{
-				if (player.getReuseTimeStamp().isEmpty() || !player.getReuseTimeStamp().containsKey(_skill.getId()))
+				if (!player.getReuseTimeStamp().isEmpty() && player.getReuseTimeStamp().containsKey(_skill.getId()))
 				{
-					int equipDelay = _skill.getEquipDelay();
-					if (equipDelay > 0)
+					final long delay = player.getReuseTimeStamp().get(_skill.getId()).getRemaining();
+					if (delay > 0)
 					{
-						player.addTimeStamp(_skill.getId(), equipDelay);
-						player.disableSkill(_skill.getId(), equipDelay);
+						player.disableSkill(_skill, delay);
+						updateTimeStamp = true;
 					}
 				}
-				updateTimeStamp = true;
 			}
 			player.sendSkillList();
 			if (updateTimeStamp)

+ 6 - 2
L2_GameServer/java/com/l2jserver/gameserver/model/L2Clan.java

@@ -33,6 +33,7 @@ import com.l2jserver.gameserver.instancemanager.FortManager;
 import com.l2jserver.gameserver.instancemanager.SiegeManager;
 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.network.SystemMessageId;
 import com.l2jserver.gameserver.network.communityserver.CommunityServerThread;
@@ -274,8 +275,11 @@ public class L2Clan
         	{
         		for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(newLeader.isNoble()))
         		{
-        			if (exLeader.getReuseTimeStamp().containsKey(sk.getId()))
-        				newLeader.addTimeStamp(exLeader.getReuseTimeStamp().get(sk.getId()));
+        			if (exLeader.getReuseTimeStamp().containsKey(sk.getReuseHashCode()))
+        			{
+        				TimeStamp t = exLeader.getReuseTimeStamp().get(sk.getReuseHashCode());
+        				newLeader.addTimeStamp(sk, t.getReuse(), t.getStamp());
+        			}
         		}
         		newLeader.sendPacket(new SkillCoolTime(newLeader));
         	}       	

+ 24 - 0
L2_GameServer/java/com/l2jserver/gameserver/model/L2Skill.java

@@ -22,6 +22,7 @@ import java.util.logging.Logger;
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.GeoData;
 import com.l2jserver.gameserver.datatables.HeroSkillTable;
+import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.datatables.SkillTreeTable;
 import com.l2jserver.gameserver.model.actor.L2Attackable;
 import com.l2jserver.gameserver.model.actor.L2Character;
@@ -175,6 +176,7 @@ public abstract class L2Skill implements IChanceSkillTrigger
     private final int _hitTime;
     //private final int _skillInterruptTime;
     private final int _coolTime;
+    private final int _reuseHashCode;
     private final int _reuseDelay;
     private final int _buffDuration;
     // for item skills delay on equip
@@ -354,6 +356,23 @@ 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);
+
         if (Config.ENABLE_MODIFY_SKILL_REUSE && Config.SKILL_REUSE_LIST.containsKey(_id))
         {
                 if ( Config.DEBUG )
@@ -815,6 +834,11 @@ public abstract class L2Skill implements IChanceSkillTrigger
         return _reuseDelay;
     }
 
+    public final int getReuseHashCode()
+    {
+    	return _reuseHashCode;
+    }
+
     public final int getEquipDelay()
     {
     	return _equipDelay;

+ 34 - 39
L2_GameServer/java/com/l2jserver/gameserver/model/actor/L2Character.java

@@ -1717,7 +1717,7 @@ public abstract class L2Character extends L2Object
 		boolean skillMastery = Formulas.calcSkillMastery(this, skill);
 
 		// Skill reuse check
-		if (reuseDelay > 30000 && !skillMastery) addTimeStamp(skill.getId(),reuseDelay);
+		if (reuseDelay > 30000 && !skillMastery) addTimeStamp(skill, reuseDelay);
 
 		// Check if this skill consume mp on start casting
 		int initmpcons = getStat().getMpInitialConsume(skill);
@@ -1755,7 +1755,7 @@ public abstract class L2Character extends L2Object
 				}
 			}
 			
-			disableSkill(skill.getId(), reuseDelay);
+			disableSkill(skill, reuseDelay);
 		}
 		
 		// Make sure that char is facing selected target
@@ -1878,7 +1878,7 @@ public abstract class L2Character extends L2Object
 	 */
 	protected boolean checkDoCastConditions(L2Skill skill)
 	{
-		if (skill == null || isSkillDisabled(skill.getId()) || (skill.getFlyType() != null && isMovementDisabled()))
+		if (skill == null || isSkillDisabled(skill) || (skill.getFlyType() != null && isMovementDisabled()))
 		{
 			// Send a Server->Client packet ActionFailed to the L2PcInstance
             sendPacket(ActionFailed.STATIC_PACKET);
@@ -2007,16 +2007,8 @@ public abstract class L2Character extends L2Object
 	 * @param reuse delay
 	 * <BR><B>Overridden in :</B>  (L2PcInstance)
 	 */
-	public void addTimeStamp(int s, int r) {/***/}
+	public void addTimeStamp(L2Skill skill, long reuse) {/***/}
 
-	/**
-	 * Index according to skill id the current timestamp of use.<br><br>
-	 *
-	 * @param skill id
-	 * <BR><B>Overridden in :</B>  (L2PcInstance)
-	 */
-	public void removeTimeStamp(int s) {/***/}
-	
 	public void startFusionSkill(L2Character target, L2Skill skill)
 	{
 		if (skill.getSkillType() != L2SkillType.FUSION)
@@ -6229,54 +6221,57 @@ public abstract class L2Character extends L2Object
 	 * @param skillId The identifier of the L2Skill to enable
 	 *
 	 */
-	public void enableSkill(int skillId)
+	public void enableSkill(L2Skill skill)
 	{
-		if (_disabledSkills == null)
+		if (skill == null || _disabledSkills == null)
 			return;
 
-		_disabledSkills.remove(Integer.valueOf(skillId));
-
-		if (this instanceof L2PcInstance)
-			removeTimeStamp(skillId);
+		_disabledSkills.remove(Integer.valueOf(skill.getReuseHashCode()));
 	}
 
 	/**
-	 * Disable a skill (add it to _disabledSkills of the L2Character).<BR><BR>
-	 *
-	 * <B><U> Concept</U> :</B><BR><BR>
-	 * All skills disabled are identified by their skillId in <B>_disabledSkills</B> of the L2Character <BR><BR>
-	 *
-	 * @param skillId The identifier of the L2Skill to disable
-	 *
+	 * Disable this skill id for the duration of the delay in milliseconds.
+	 * @param skill
+	 * @param delay (seconds * 1000)
 	 */
-	public void disableSkill(int skillId)
+	public void disableSkill(L2Skill skill, long delay)
 	{
-		disableSkill(skillId, 0);
+		if (skill == null)
+			return;
+
+		if (_disabledSkills == null)
+			_disabledSkills = Collections.synchronizedMap(new FastMap<Integer, Long>());
+
+		_disabledSkills.put(Integer.valueOf(skill.getReuseHashCode()), delay > 10 ? System.currentTimeMillis() + delay : Long.MAX_VALUE);
 	}
 
 	/**
-	 * Disable this skill id for the duration of the delay in milliseconds.
-	 * @param skillId
-	 * @param delay (seconds * 1000)
+	 * Check if a skill is disabled.<BR><BR>
+	 *
+	 * <B><U> Concept</U> :</B><BR><BR>
+	 * All skills disabled are identified by their reuse hashcodes in <B>_disabledSkills</B> of the L2Character <BR><BR>
+	 *
+	 * @param skill The L2Skill to check
+	 *
 	 */
-	public void disableSkill(int skillId, long delay)
+	public boolean isSkillDisabled(L2Skill skill)
 	{
-		if (_disabledSkills == null)
-			_disabledSkills = Collections.synchronizedMap(new FastMap<Integer, Long>());
+		if (skill == null)
+			return true;
 
-		_disabledSkills.put(skillId, delay > 10 ? System.currentTimeMillis() + delay : Long.MAX_VALUE);
+		return isSkillDisabled(skill.getReuseHashCode());
 	}
 
 	/**
 	 * Check if a skill is disabled.<BR><BR>
 	 *
 	 * <B><U> Concept</U> :</B><BR><BR>
-	 * All skills disabled are identified by their skillId in <B>_disabledSkills</B> of the L2Character <BR><BR>
+	 * All skills disabled are identified by their reuse hashcodes in <B>_disabledSkills</B> of the L2Character <BR><BR>
 	 *
-	 * @param skillId The identifier of the L2Skill to disable
+	 * @param reuseHashcode The reuse hashcode of the skillId/level to check
 	 *
 	 */
-	public boolean isSkillDisabled(int skillId)
+	public boolean isSkillDisabled(int reuseHashcode)
 	{
 		if (isAllSkillsDisabled())
 			return true;
@@ -6284,13 +6279,13 @@ public abstract class L2Character extends L2Object
 		if (_disabledSkills == null)
 			return false;
 
-		final Long timeStamp = _disabledSkills.get(Integer.valueOf(skillId));
+		final Long timeStamp = _disabledSkills.get(Integer.valueOf(reuseHashcode));
 		if (timeStamp == null)
 			return false;
 
 		if (timeStamp < System.currentTimeMillis())
 		{
-			_disabledSkills.remove(Integer.valueOf(skillId));
+			_disabledSkills.remove(Integer.valueOf(reuseHashcode));
 			return false;
 		}
 

+ 1 - 1
L2_GameServer/java/com/l2jserver/gameserver/model/actor/L2Summon.java

@@ -597,7 +597,7 @@ public abstract class L2Summon extends L2Playable
         //************************************* Check skill availability *******************************************
 
         // Check if this skill is enabled (e.g. reuse time)
-        if (isSkillDisabled(skill.getId()))
+        if (isSkillDisabled(skill))
         {
         	if (getOwner() != null) 
             	getOwner().sendPacket(new SystemMessage(SystemMessageId.PET_SKILL_CANNOT_BE_USED_RECHARCHING));

+ 53 - 37
L2_GameServer/java/com/l2jserver/gameserver/model/actor/instance/L2BabyPetInstance.java

@@ -28,6 +28,7 @@ import com.l2jserver.gameserver.model.L2Skill;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
+import com.l2jserver.gameserver.skills.SkillHolder;
 import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
 import com.l2jserver.util.Rnd;
 
@@ -41,16 +42,16 @@ import javolution.util.FastList;
  */
 public final class L2BabyPetInstance extends L2PetInstance
 {
-	protected static final int BUFF_CONTROL = 5771;
+	private static final int BUFF_CONTROL = 5771;
 
-	protected FastList<Integer> _buffs = null;
-	protected int _majorHeal = 0;
-	protected int _minorHeal = 0;
-	protected int _recharge = 0;
+	private FastList<SkillHolder> _buffs = null;
+	private SkillHolder _majorHeal = null;
+	private SkillHolder _minorHeal = null;
+	private SkillHolder _recharge = null;
 
 	private Future<?> _castTask;
 
-	protected long _buffControlTimestamp = 0;
+	private int _buffControlReuseHashcode = 0;
 
 	public L2BabyPetInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, L2ItemInstance control)
 	{
@@ -72,7 +73,10 @@ public final class L2BabyPetInstance extends L2PetInstance
 			if (skill != null)
 			{
 				if (skill.getId() == BUFF_CONTROL)
+				{
+					_buffControlReuseHashcode = skill.getReuseHashCode();
 					continue;
+				}
 
 				switch (skill.getSkillType())
 				{
@@ -80,27 +84,27 @@ public final class L2BabyPetInstance extends L2PetInstance
 						if (healPower == 0)
 						{
 							// set both heal types to the same skill
-							_majorHeal = id;
-							_minorHeal = id;
+							_majorHeal = new SkillHolder(skill);
+							_minorHeal = _majorHeal;
 							healPower = skill.getPower();
 						}
 						else
 						{
 							// another heal skill found - search for most powerful
 							if (skill.getPower() > healPower)
-								_majorHeal = id;
+								_majorHeal = new SkillHolder(skill);
 							else
-								_minorHeal = id;
+								_minorHeal = new SkillHolder(skill);
 						}
 						break;
 					case BUFF:
 						if (_buffs == null)
-							_buffs = new FastList<Integer>();
-						_buffs.add(id);
+							_buffs = new FastList<SkillHolder>();
+						_buffs.add(new SkillHolder(skill));
 						break;
 					case MANAHEAL:
 					case MANARECHARGE:
-						_recharge = id;
+						_recharge = new SkillHolder(skill);
 						break;
 				}
 			}
@@ -144,7 +148,7 @@ public final class L2BabyPetInstance extends L2PetInstance
 
 	private final void startCastTask()
 	{
-		if ((_majorHeal > 0 || _buffs != null || _recharge > 0) 
+		if ((_majorHeal != null || _buffs != null || _recharge != null) 
 			&& _castTask == null && !isDead()) // cast task is not yet started and not dead (will start on revive)
 				_castTask = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new CastTask(this), 3000, 1000);
 	}
@@ -212,39 +216,51 @@ public final class L2BabyPetInstance extends L2PetInstance
 			{
 				L2Skill skill = null;
 
-				if (_majorHeal > 0)
+				if (_majorHeal != null)
 				{
 					// if the owner's HP is more than 80%, do nothing.
 					// if the owner's HP is very low (less than 20%) have a high chance for strong heal
 					// otherwise, have a low chance for weak heal
 					final double hpPercent = owner.getCurrentHp()/owner.getMaxHp();
-					if (hpPercent < 0.15
-							&& !_baby.isSkillDisabled(_majorHeal)
-							&& Rnd.get(100) <= 75)
-						skill = SkillTable.getInstance().getInfo(_majorHeal, PetSkillsTable.getInstance().getAvailableLevel(_baby, _majorHeal));
-					else if (hpPercent < 0.8
-							&& !_baby.isSkillDisabled(_minorHeal)
-							&& Rnd.get(100) <= 25)
-						skill = SkillTable.getInstance().getInfo(_minorHeal, PetSkillsTable.getInstance().getAvailableLevel(_baby, _minorHeal));
-
-					if (skill != null && _baby.getCurrentMp() >= skill.getMpConsume())
+					if (hpPercent < 0.15)
 					{
-						castSkill(skill);
-						return;
+						skill = _majorHeal.getSkill();
+						if (!_baby.isSkillDisabled(skill)
+								&& Rnd.get(100) <= 75)
+						{
+							if (_baby.getCurrentMp() >= skill.getMpConsume())
+							{
+								castSkill(skill);
+								return;
+							}
+						}
+					}
+					if (hpPercent < 0.8)
+					{
+						skill = _minorHeal.getSkill();
+						if (!_baby.isSkillDisabled(skill)
+								&& Rnd.get(100) <= 25)
+						{
+							if (_baby.getCurrentMp() >= skill.getMpConsume())
+							{
+								castSkill(skill);
+								return;
+							}
+						}
 					}
 				}
 
-				if (!_baby.isSkillDisabled(BUFF_CONTROL)) // Buff Control is not active
+				if (!_baby.isSkillDisabled(_buffControlReuseHashcode)) // Buff Control is not active
 				{
 					// searching for usable buffs
 					if (_buffs != null && !_buffs.isEmpty())
 					{
-						for (int id : _buffs)
+						for (SkillHolder i : _buffs)
 						{
-							if (_baby.isSkillDisabled(id))
+							skill = i.getSkill();
+							if (_baby.isSkillDisabled(skill))
 								continue;
-							skill = SkillTable.getInstance().getInfo(id, PetSkillsTable.getInstance().getAvailableLevel(_baby, id));
-							if (skill != null && _baby.getCurrentMp() >= skill.getMpConsume())
+							if (_baby.getCurrentMp() >= skill.getMpConsume())
 								_currentBuffs.add(skill);
 						}
 					}
@@ -304,14 +320,14 @@ public final class L2BabyPetInstance extends L2PetInstance
 				}
 
 				// buffs/heal not casted, trying recharge, if exist
-				if (_recharge > 0
-						&& !_baby.isSkillDisabled(_recharge)
-						&& owner.getCurrentMp()/owner.getMaxMp() < 0.7
+				if (_recharge != null
 						&& owner.isInCombat() // recharge casted only if owner in combat stance
+						&& owner.getCurrentMp()/owner.getMaxMp() < 0.7
 						&& Rnd.get(100) <= 60)
 				{
-					skill = SkillTable.getInstance().getInfo(_recharge, PetSkillsTable.getInstance().getAvailableLevel(_baby, _recharge));
-					if (skill != null && _baby.getCurrentMp() >= skill.getMpConsume())
+					skill = _recharge.getSkill();
+					if (!_baby.isSkillDisabled(skill)
+							&& _baby.getCurrentMp() >= skill.getMpConsume())
 					{
 						castSkill(skill);
 						return;

+ 91 - 114
L2_GameServer/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -261,7 +261,7 @@ public final class L2PcInstance extends L2Playable
 
 	// Character Skill Save SQL String Definitions:
 	private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (charId,skill_id,skill_level,effect_count,effect_cur_time,reuse_delay,systime,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?,?)";
-	private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,effect_count,effect_cur_time, reuse_delay, systime FROM character_skills_save WHERE charId=? AND class_index=? AND restore_type=? ORDER BY buff_index ASC";
+	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 Character SQL String Definitions:
@@ -4163,7 +4163,18 @@ public final class L2PcInstance extends L2Playable
 	{
 		_currentSkillWorldPosition = worldPosition;
 	}
-	
+
+	/**
+	 * 
+	 * @see com.l2jserver.gameserver.model.actor.L2Character#enableSkill(com.l2jserver.gameserver.model.L2Skill)
+	 */
+	@Override
+	public void enableSkill(L2Skill skill)
+	{
+		super.enableSkill(skill);
+		_reuseTimeStamps.remove(Integer.valueOf(skill.getReuseHashCode()));
+	}
+
 	/**
 	 * 
 	 * @see com.l2jserver.gameserver.model.actor.L2Character#checkDoCastConditions(com.l2jserver.gameserver.model.L2Skill)
@@ -7690,7 +7701,7 @@ public final class L2PcInstance extends L2Playable
 				{
 					if (effect == null)
 						continue;
-					
+
 					switch (effect.getEffectType())
 					{
 						case HEAL_OVER_TIME:
@@ -7699,28 +7710,26 @@ public final class L2PcInstance extends L2Playable
 						case HIDE:
 							continue;
 					}
-					
+
 					L2Skill skill = effect.getSkill();
-					int skillId = skill.getId();
-					
-					if (storedSkills.contains(skillId))
+					if (storedSkills.contains(skill.getReuseHashCode()))
 						continue;
-					
-					storedSkills.add(skillId);
-					
+
+					storedSkills.add(skill.getReuseHashCode());
+
 					if (effect != null && !effect.isHerbEffect() && effect.getInUse()
 					        && !skill.isToggle())
 					{
 						
 						statement.setInt(1, getObjectId());
-						statement.setInt(2, skillId);
+						statement.setInt(2, skill.getId());
 						statement.setInt(3, skill.getLevel());
 						statement.setInt(4, effect.getCount());
 						statement.setInt(5, effect.getTime());
 						
-						if (_reuseTimeStamps.containsKey(skillId))
+						if (_reuseTimeStamps.containsKey(Integer.valueOf(skill.getReuseHashCode())))
 						{
-							TimeStamp t = _reuseTimeStamps.get(skillId);
+							TimeStamp t = _reuseTimeStamps.get(skill.getReuseHashCode());
 							statement.setLong(6, t.hasNotPassed() ? t.getReuse() : 0);
 							statement.setDouble(7, t.hasNotPassed() ? t.getStamp() : 0);
 						}
@@ -7740,18 +7749,19 @@ 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 (TimeStamp t : _reuseTimeStamps.values())
+			for (int hash : _reuseTimeStamps.keySet())
 			{
-				if (t.hasNotPassed())
+				if (storedSkills.contains(hash))
+					continue;
+
+				TimeStamp t = _reuseTimeStamps.get(hash);
+				if (t != null && t.hasNotPassed())
 				{
-					int skillId = t.getSkill();
-					if (storedSkills.contains(skillId))
-						continue;
-					storedSkills.add(skillId);
+					storedSkills.add(hash);
 
 					statement.setInt(1, getObjectId());
-					statement.setInt(2, skillId);
-					statement.setInt(3, -1);
+					statement.setInt(2, t.getSkillId());
+					statement.setInt(3, t.getSkillLvl());
 					statement.setInt(4, -1);
 					statement.setInt(5, -1);
 					statement.setLong(6, t.getReuse());
@@ -7760,7 +7770,6 @@ public final class L2PcInstance extends L2Playable
 					statement.setInt(9, getClassIndex());
 					statement.setInt(10, ++buff_index);
 					statement.execute();
-					
 				}
 			}
 			statement.close();
@@ -8015,77 +8024,53 @@ public final class L2PcInstance extends L2Playable
 			PreparedStatement statement;
 			ResultSet rset;
 
-			/**
-			*  Restore Type 0
-			*  These skill were still in effect on the character
-			*  upon logout. Some of which were self casted and
-			*  might still have had a long reuse delay which also
-			*  is restored.
-			*/
 			statement = con.prepareStatement(RESTORE_SKILL_SAVE);
 			statement.setInt(1, getObjectId());
 			statement.setInt(2, getClassIndex());
-			statement.setInt(3, 0);
 			rset = statement.executeQuery();
 
 			while (rset.next())
 			{
-				int skillId = rset.getInt("skill_id");
-				int skillLvl = rset.getInt("skill_level");
 				int effectCount = rset.getInt("effect_count");
 				int effectCurTime = rset.getInt("effect_cur_time");
-				double reuseDelay = rset.getInt("reuse_delay");
-				double systime = rset.getDouble("systime");
+				long reuseDelay = rset.getLong("reuse_delay");
+				long systime = rset.getLong("systime");
+				int restoreType = rset.getInt("restore_type");
 
-				double remainingTime = systime - System.currentTimeMillis();
-
-				// Just incase the admin minipulated this table incorrectly :x
-				if(skillId == -1 || effectCount == -1 || effectCurTime == -1 || reuseDelay < 0)
+				final L2Skill skill = SkillTable.getInstance().getInfo(rset.getInt("skill_id"), rset.getInt("skill_level"));
+				if (skill == null)
 					continue;
 
-				L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
-				L2Effect[] effects = skill.getEffects(this, this);
-
+				final long remainingTime = systime - System.currentTimeMillis();
 				if (remainingTime > 10)
 				{
-					disableSkill(skillId, (long)remainingTime);
-					addTimeStamp(new TimeStamp(skillId, (long)reuseDelay, (long)systime));
+					disableSkill(skill, remainingTime);
+					addTimeStamp(skill, reuseDelay, systime);
 				}
 
-				for (L2Effect effect : effects)
+				/**
+				 *  Restore Type 1
+				 *  The remaning skills lost effect upon logout but
+				 *  were still under a high reuse delay.
+				 */
+				if (restoreType > 0)
+					continue;
+
+				/**
+				*  Restore Type 0
+				*  These skill were still in effect on the character
+				*  upon logout. Some of which were self casted and
+				*  might still have had a long reuse delay which also
+				*  is restored.
+				*  
+				*/
+				for (L2Effect effect : skill.getEffects(this, this))
                 {
 					effect.setCount(effectCount);
 					effect.setFirstTime(effectCurTime);
                 }
 			}
-			rset.close();
-			statement.close();
 
-			/**
-			 * Restore Type 1
-			 * The remaning skills lost effect upon logout but
-			 * were still under a high reuse delay.
-			 */
-			statement = con.prepareStatement(RESTORE_SKILL_SAVE);
-			statement.setInt(1, getObjectId());
-			statement.setInt(2, getClassIndex());
-			statement.setInt(3, 1);
-			rset = statement.executeQuery();
-
-			while (rset.next())
-			{
-				int skillId = rset.getInt("skill_id");
-				double reuseDelay = rset.getDouble("reuse_delay");
-				double systime = rset.getDouble("systime");
-
-				double remainingTime = systime - System.currentTimeMillis();
-
-				if (remainingTime < 10)
-					continue;
-
-				disableSkill(skillId, (long)remainingTime);
-				addTimeStamp(new TimeStamp(skillId, (long)reuseDelay, (long)systime));
-			}
 			rset.close();
 			statement.close();
 
@@ -8771,14 +8756,13 @@ public final class L2PcInstance extends L2Playable
 			return false;
         
         // Check if this skill is enabled (ex : reuse time)
-        if (isSkillDisabled(skill.getId()))
+        if (isSkillDisabled(skill))
         {
         	SystemMessage sm = null;
-        	FastMap<Integer, TimeStamp> timeStamp = getReuseTimeStamp();
 				
-        	if (timeStamp != null && timeStamp.containsKey(skill.getId()))
+        	if (_reuseTimeStamps.containsKey(Integer.valueOf(skill.getReuseHashCode())))
         	{
-        		int remainingTime = (int)(_reuseTimeStamps.get(skill.getId()).getRemaining()/1000);
+        		int remainingTime = (int)(_reuseTimeStamps.get(Integer.valueOf(skill.getReuseHashCode())).getRemaining()/1000);
         		int hours = remainingTime/3600;
         		int minutes = (remainingTime%3600)/60;
         		int seconds = (remainingTime%60);
@@ -13030,42 +13014,50 @@ public final class L2PcInstance extends L2Playable
 	 */
 	public static class TimeStamp
 	{
-		private int skill;
-		private long reuse;
-		private long stamp;
+		private final int _skillId;
+		private final int _skillLvl;
+		private final long _reuse;
+		private final long _stamp;
 
-		public TimeStamp(int _skill, long _reuse)
+		public TimeStamp(L2Skill skill, long reuse)
 		{
-			skill = _skill;
-			reuse = _reuse;
-			stamp = System.currentTimeMillis()+ reuse;
+			_skillId = skill.getId();
+			_skillLvl = skill.getLevel();
+			_reuse = reuse;
+			_stamp = System.currentTimeMillis()+ reuse;
 		}
 
-		public TimeStamp(int _skill, long _reuse, long _systime)
+		public TimeStamp(L2Skill skill, long reuse, long systime)
 		{
-			skill = _skill;
-			reuse = _reuse;
-			stamp = _systime;
+			_skillId = skill.getId();
+			_skillLvl = skill.getLevel();
+			_reuse = reuse;
+			_stamp = systime;
 		}
-		
+
 		public long getStamp()
 		{
-				return stamp;
+				return _stamp;
 		}
 
-		public int getSkill()
+		public int getSkillId()
         {
-            return skill;
+            return _skillId;
         }
-        
-        public long getReuse()
+
+		public int getSkillLvl()
+		{
+			return _skillLvl;
+		}
+
+		public long getReuse()
         {
-            return reuse;
+            return _reuse;
         }
         
         public long getRemaining()
         {
-            return Math.max(stamp - System.currentTimeMillis(), 0);
+            return Math.max(_stamp - System.currentTimeMillis(), 0);
         }
 
 		/* Check if the reuse delay has passed and
@@ -13074,11 +13066,7 @@ public final class L2PcInstance extends L2Playable
 		 * the delay. */
 		public boolean hasNotPassed()
 		{
-            if (System.currentTimeMillis() < stamp)
-            {
-                return true;
-            }
-			return false;
+			return System.currentTimeMillis() < _stamp;
 		}
 	}
 
@@ -13089,9 +13077,9 @@ public final class L2PcInstance extends L2Playable
 	 * @param reuse delay
 	 */
 	@Override
-	public void addTimeStamp(int s, int r)
+	public void addTimeStamp(L2Skill skill, long reuse)
 	{
-		_reuseTimeStamps.put(s, new TimeStamp(s, r));
+		_reuseTimeStamps.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse));
 	}
 
 	/**
@@ -13099,22 +13087,11 @@ public final class L2PcInstance extends L2Playable
 	 * instance for restoration purposes only.
 	 * @param TimeStamp
 	 */
-	public void addTimeStamp(TimeStamp ts)
+	public void addTimeStamp(L2Skill skill, long reuse, long systime)
 	{
-		_reuseTimeStamps.put(ts.getSkill(), ts);
+		_reuseTimeStamps.put(skill.getReuseHashCode(), new TimeStamp(skill, reuse, systime));
 	}
 
-	/**
-	 * Index according to skill id the current
-	 * timestamp of use.
-	 * @param skillid
-	 */
-	@Override
-	public void removeTimeStamp(int s)
-	{
-		_reuseTimeStamps.remove(s);
-	}
-	
 	@Override
 	public L2PcInstance getActingPlayer()
 	{

+ 12 - 9
L2_GameServer/java/com/l2jserver/gameserver/model/itemcontainer/Inventory.java

@@ -422,14 +422,15 @@ public abstract class Inventory extends ItemContainer
 
 							if (itemSkill.isActive())
 							{
-								if (player.getReuseTimeStamp().isEmpty() || !player.getReuseTimeStamp().containsKey(itemSkill.getId()))
+								if (player.getReuseTimeStamp().isEmpty()
+										|| !player.getReuseTimeStamp().containsKey(itemSkill.getReuseHashCode()))
 								{
 									int equipDelay = itemSkill.getEquipDelay();
 
 									if (equipDelay > 0)
 									{
-										player.addTimeStamp(itemSkill.getId(), equipDelay);
-										player.disableSkill(itemSkill.getId(), equipDelay);
+										player.addTimeStamp(itemSkill, equipDelay);
+										player.disableSkill(itemSkill, equipDelay);
 									}
 								}
 								updateTimeStamp = true;
@@ -479,14 +480,15 @@ public abstract class Inventory extends ItemContainer
 
 							if (itemSkill.isActive())
 							{
-								if (player.getReuseTimeStamp().isEmpty() || !player.getReuseTimeStamp().containsKey(itemSkill.getId()))
+								if (player.getReuseTimeStamp().isEmpty()
+										|| !player.getReuseTimeStamp().containsKey(itemSkill.getReuseHashCode()))
 								{
 									int equipDelay = itemSkill.getEquipDelay();
 
 									if (equipDelay > 0)
 									{
-										player.addTimeStamp(itemSkill.getId(), itemSkill.getEquipDelay());
-										player.disableSkill(itemSkill.getId(), itemSkill.getEquipDelay());
+										player.addTimeStamp(itemSkill, itemSkill.getEquipDelay());
+										player.disableSkill(itemSkill, itemSkill.getEquipDelay());
 									}
 								}
 								updateTimeStamp = true;
@@ -567,14 +569,15 @@ public abstract class Inventory extends ItemContainer
 
 										if (itemSkill.isActive())
 										{
-											if (player.getReuseTimeStamp().isEmpty() || !player.getReuseTimeStamp().containsKey(itemSkill.getId()))
+											if (player.getReuseTimeStamp().isEmpty()
+													|| !player.getReuseTimeStamp().containsKey(itemSkill.getReuseHashCode()))
 											{
 												int equipDelay = itemSkill.getEquipDelay();
 
 												if (equipDelay > 0)
 												{
-													player.addTimeStamp(itemSkill.getId(), itemSkill.getEquipDelay());
-													player.disableSkill(itemSkill.getId(), itemSkill.getEquipDelay());
+													player.addTimeStamp(itemSkill, itemSkill.getEquipDelay());
+													player.disableSkill(itemSkill, itemSkill.getEquipDelay());
 												}
 											}
 											updateTimeStamp = true;

+ 1 - 1
L2_GameServer/java/com/l2jserver/gameserver/model/olympiad/OlympiadGame.java

@@ -271,7 +271,7 @@ class OlympiadGame
 				// enable skills with cool time <= 15 minutes
 				for (L2Skill skill : player.getAllSkills())
 					if (skill.getReuseDelay() <= 900000)
-						player.enableSkill(skill.getId());
+						player.enableSkill(skill);
 					
 				player.sendSkillList();
 				player.sendPacket(new SkillCoolTime(player));

+ 1 - 1
L2_GameServer/java/com/l2jserver/gameserver/network/serverpackets/SkillCoolTime.java

@@ -59,7 +59,7 @@ public class SkillCoolTime extends L2GameServerPacket
         writeD(_reuseTimeStamps.size()); // list size
         for (TimeStamp ts : _reuseTimeStamps)
         {
-            writeD(ts.getSkill());
+            writeD(ts.getSkillId());
             writeD(0x00);
             writeD((int) ts.getReuse() / 1000);
             writeD((int) ts.getRemaining() / 1000);

+ 6 - 0
L2_GameServer/java/com/l2jserver/gameserver/skills/SkillHolder.java

@@ -34,6 +34,12 @@ public final class SkillHolder
 		_skillLvl = skillLvl;
 	}
 
+	public SkillHolder(L2Skill skill)
+	{
+		_skillId = skill.getId();
+		_skillLvl = skill.getLevel();
+	}
+
 	public final int getSkillId()
 	{
 		return _skillId;