Browse Source

BETA: Shots rework:
* Using inheritance to simplify code and reuse it.
* Implemented isPhyisical method to L2Skill to use properly soulshots.
* Keeping charged shots when unequip item to match retail behavior.

Rumen Nikiforov 12 năm trước cách đây
mục cha
commit
be05f8be82
19 tập tin đã thay đổi với 390 bổ sung514 xóa
  1. 29 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/L2Object.java
  2. 38 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/ShotType.java
  3. 52 245
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Character.java
  4. 58 54
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Npc.java
  5. 67 23
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Summon.java
  6. 23 25
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
  7. 20 6
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PetInstance.java
  8. 30 62
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/instance/L2ItemInstance.java
  9. 4 4
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/olympiad/AbstractOlympiadGame.java
  10. 8 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/L2Skill.java
  11. 5 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillChargeDmg.java
  12. 9 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillDrain.java
  13. 37 21
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillElemental.java
  14. 4 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillTeleport.java
  15. 1 38
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/stats/Formulas.java
  16. 4 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestAutoSoulShot.java
  17. 0 14
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestDestroyItem.java
  18. 1 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestDropItem.java
  19. 0 10
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestUnEquipItem.java

+ 29 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/L2Object.java

@@ -807,10 +807,38 @@ public abstract class L2Object
 	/**
 	 * Check if the object is in the given zone Id.
 	 * @param zone the zone Id to check
-	 * @return {code true} if the object is in that zone Id
+	 * @return {@code true} if the object is in that zone Id
 	 */
 	public boolean isInsideZone(ZoneId zone)
 	{
 		return false;
 	}
+	
+	/**
+	 * Check if current object has charged shot.
+	 * @param type of the shot to be checked.
+	 * @return {@code true} if the object has charged shot
+	 */
+	public boolean isChargedShot(ShotType type)
+	{
+		return false;
+	}
+	
+	/**
+	 * Charging shot into the current object.
+	 * @param type of the shot to be charged.
+	 * @param charged
+	 */
+	public void setChargedShot(ShotType type, boolean charged)
+	{	
+	}
+	
+	/**
+	 * Try to recharge a shot.
+	 * @param physical skill are using Soul shots.
+	 * @param magical skill are using Spirit shots.
+	 */
+	public void rechargeShots(boolean physical, boolean magical)
+	{
+	}
 }

+ 38 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/ShotType.java

@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * @author UnAfraid
+ */
+public enum ShotType
+{
+	SOULSHOTS,
+	SPIRITSHOTS,
+	BLESSED_SPIRITSHOTS,
+	FISH_SOULSHOTS;
+	
+	private final int _mask;
+	
+	private ShotType()
+	{
+		_mask = (1 << ordinal());
+	}
+	
+	public int getMask()
+	{
+		return _mask;
+	}
+}

+ 52 - 245
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Character.java

@@ -63,6 +63,7 @@ import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.L2WorldRegion;
 import com.l2jserver.gameserver.model.Location;
 import com.l2jserver.gameserver.model.PcCondOverride;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.actor.instance.L2NpcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2NpcWalkerInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
@@ -862,10 +863,7 @@ public abstract class L2Character extends L2Object
 		}
 		
 		stopEffectsOnAction();
-		
-		// Get the active weapon instance (always equipped in the right hand)
-		L2ItemInstance weaponInst = getActiveWeaponInstance();
-		
+				
 		// Get the active weapon item corresponding to the active weapon instance (always equipped in the right hand)
 		L2Weapon weaponItem = getActiveWeaponItem();
 		
@@ -1015,25 +1013,11 @@ public abstract class L2Character extends L2Object
 		if (Config.ALT_GAME_TIREDNESS)
 			setCurrentCp(getCurrentCp() - 10);
 		
-		// Recharge any active auto soulshot tasks for player (or player's summon if one exists).
-		if (isPlayer() || isSummon())
-			getActingPlayer().rechargeAutoSoulShot(true, false, isSummon());
+		// Recharge any active auto soulshot tasks for current L2Character instance.
+		rechargeShots(true, false);
 		
 		// Verify if soulshots are charged.
-		boolean wasSSCharged;
-		
-		if (isSummon() && !(isPet() && weaponInst != null))
-			wasSSCharged = (((L2Summon) this).getChargedSoulShot() != L2ItemInstance.CHARGED_NONE);
-		else
-			wasSSCharged = (weaponInst != null && weaponInst.getChargedSoulshot() != L2ItemInstance.CHARGED_NONE);
-		
-		if (isL2Attackable())
-		{
-			if (((L2Npc) this).useSoulShot())
-			{
-				wasSSCharged = true;
-			}
-		}
+		boolean wasSSCharged = isChargedShot(ShotType.SOULSHOTS);
 		
 		// Get the Attack Speed of the L2Character (delay (in milliseconds) before next attack)
 		int timeAtk = calculateTimeBetweenAttacks(target, weaponItem);
@@ -1100,10 +1084,7 @@ public abstract class L2Character extends L2Object
 			 */
 
 			// If we didn't miss the hit, discharge the shoulshots, if any
-			if (isSummon() && !(isPet() && weaponInst != null))
-				((L2Summon) this).setChargedSoulShot(L2ItemInstance.CHARGED_NONE);
-			else if (weaponInst != null)
-				weaponInst.setChargedSoulshot(L2ItemInstance.CHARGED_NONE);
+			setChargedShot(ShotType.SOULSHOTS, false);
 			
 			if (player != null)
 			{
@@ -1282,18 +1263,7 @@ public abstract class L2Character extends L2Object
 		}
 		
 		// Create a new hit task with Medium priority
-		if (isL2Attackable())
-		{
-			if (((L2Attackable) this)._soulshotcharged)
-			{
-				// Create a new hit task with Medium priority
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, true, shld1), sAtk);
-			}
-			else
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, false, shld1), sAtk);
-		}
-		else
-			ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, attack.soulshot, shld1), sAtk);
+		ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, attack.soulshot, shld1), sAtk);
 		
 		// Calculate and set the disable delay of the bow in function of the Attack Speed
 		_disableCrossBowAttackEndTime = (sAtk + reuse) / GameTimeController.MILLIS_IN_TICK + GameTimeController.getGameTicks();
@@ -1364,33 +1334,13 @@ public abstract class L2Character extends L2Object
 			damage2 /= 2;
 		}
 		
-		if (isL2Attackable())
-		{
-			if (((L2Attackable) this)._soulshotcharged)
-			{
-				
-				// Create a new hit task with Medium priority for hit 1
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, true, shld1), sAtk / 2);
-				
-				// Create a new hit task with Medium priority for hit 2 with a higher delay
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage2, crit2, miss2, true, shld2), sAtk);
-			}
-			else
-			{
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, false, shld1), sAtk / 2);
-				
-				// Create a new hit task with Medium priority for hit 2 with a higher delay
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage2, crit2, miss2, false, shld2), sAtk);
-			}
-		}
-		else
-		{
-			// Create a new hit task with Medium priority for hit 1
-			ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, attack.soulshot, shld1), sAtk / 2);
-			
-			// Create a new hit task with Medium priority for hit 2 with a higher delay
-			ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage2, crit2, miss2, attack.soulshot, shld2), sAtk);
-		}
+		
+		// Create a new hit task with Medium priority for hit 1
+		ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, attack.soulshot, shld1), sAtk / 2);
+		
+		// Create a new hit task with Medium priority for hit 2 with a higher delay
+		ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage2, crit2, miss2, attack.soulshot, shld2), sAtk);
+		
 		
 		// Add those hits to the Server-Client packet Attack
 		attack.hit(attack.createHit(target, damage1, miss1, crit1, shld1), attack.createHit(target, damage2, miss2, crit2, shld2));
@@ -1554,18 +1504,7 @@ public abstract class L2Character extends L2Object
 		}
 		
 		// Create a new hit task with Medium priority
-		if (isL2Attackable())
-		{
-			if (((L2Attackable) this)._soulshotcharged)
-			{
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, true, shld1), sAtk);
-			}
-			else
-				ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, false, shld1), sAtk);
-			
-		}
-		else
-			ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, attack.soulshot, shld1), sAtk);
+		ThreadPoolManager.getInstance().scheduleAi(new HitTask(target, damage1, crit1, miss1, attack.soulshot, shld1), sAtk);
 		
 		// Add this hit to the Server-Client packet Attack
 		attack.hit(attack.createHit(target, damage1, miss1, crit1, shld1));
@@ -1651,17 +1590,15 @@ public abstract class L2Character extends L2Object
 			}
 			return;
 		}
-
+		
 		// Override casting type
 		if (skill.isSimultaneousCast() && !simultaneously)
 			simultaneously = true;
 		
 		stopEffectsOnAction();
 		
-		//Recharge AutoSoulShot
-		if (isPlayer() || isSummon())
-			getActingPlayer().rechargeAutoSoulShot(skill.useSoulShot(), skill.useSpiritShot(), isSummon());
-				
+		rechargeShots(skill.useSoulShot(), skill.useSpiritShot());
+		
 		// Set the target of the skill in function of Skill Type and Target Type
 		L2Character target = null;
 		// Get all possible targets of the skill in a table in function of the skill target type
@@ -1810,34 +1747,12 @@ public abstract class L2Character extends L2Object
 				coolTime = Formulas.calcAtkSpd(this, skill, coolTime);
 		}
 		
-		int shotSave = L2ItemInstance.CHARGED_NONE;
-		
 		// Calculate altered Cast Speed due to BSpS/SpS
-		L2ItemInstance weaponInst = getActiveWeaponInstance();
-		if (weaponInst != null)
-		{
-			if (skill.isMagic() && !effectWhileCasting)
-			{
-				if (weaponInst.getChargedSpiritshot() != L2ItemInstance.CHARGED_NONE)
-				{
-					// Using SPS/BSPS Casting Time of Magic Skills is reduced in 40%
-					hitTime = (int) (0.60 * hitTime);
-					coolTime = (int) (0.60 * coolTime);
-				}
-			}
-			
-			// Save shots value for repeats
-			if (skill.useSoulShot())
-				shotSave = weaponInst.getChargedSoulshot();
-			else if (skill.useSpiritShot())
-				shotSave = weaponInst.getChargedSpiritshot();
-		}
-		
-		if (isNpc())
+		if (skill.isMagic() && !effectWhileCasting)
 		{
-			// Using SPS/BSPS Casting Time of Magic Skills is reduced in 40%
-			if (((L2Npc) this).useSpiritShot())
+			if (isChargedShot(ShotType.SPIRITSHOTS) || isChargedShot(ShotType.BLESSED_SPIRITSHOTS))
 			{
+				// Using SPS/BSPS Casting Time of Magic Skills is reduced in 40%
 				hitTime = (int) (0.60 * hitTime);
 				coolTime = (int) (0.60 * coolTime);
 			}
@@ -1851,7 +1766,9 @@ public abstract class L2Character extends L2Object
 		}
 		// if basic hitTime is higher than 500 than the min hitTime is 500
 		else if (skill.getHitTime() >= 500 && hitTime < 500)
+		{
 			hitTime = 500;
+		}
 		
 		// queue herbs and potions
 		if (isCastingSimultaneouslyNow() && simultaneously)
@@ -2009,7 +1926,7 @@ public abstract class L2Character extends L2Object
 		if (skill.getFlyType() != null)
 			ThreadPoolManager.getInstance().scheduleEffect(new FlyToLocationTask(this, target, skill), 50);
 		
-		MagicUseTask mut = new MagicUseTask(targets, skill, hitTime, coolTime, simultaneously, shotSave);
+		MagicUseTask mut = new MagicUseTask(targets, skill, hitTime, coolTime, simultaneously);
 		
 		// launch the magic in hitTime milliseconds
 		if (hitTime > 410)
@@ -2939,9 +2856,8 @@ public abstract class L2Character extends L2Object
 		int coolTime;
 		int phase;
 		boolean simultaneously;
-		int shots;
 		
-		public MagicUseTask(L2Object[] tgts, L2Skill s, int hit, int coolT, boolean simultaneous, int shot)
+		public MagicUseTask(L2Object[] tgts, L2Skill s, int hit, int coolT, boolean simultaneous)
 		{
 			targets = tgts;
 			skill = s;
@@ -2950,7 +2866,6 @@ public abstract class L2Character extends L2Object
 			hitTime = hit;
 			coolTime = coolT;
 			simultaneously = simultaneous;
-			shots = shot;
 		}
 		
 		@Override
@@ -6484,9 +6399,9 @@ public abstract class L2Character extends L2Object
 				if (weaponInst != null)
 				{
 					if (mut.skill.useSoulShot())
-						weaponInst.setChargedSoulshot(mut.shots);
+						setChargedShot(ShotType.SOULSHOTS, true);
 					else if (mut.skill.useSpiritShot())
-						weaponInst.setChargedSpiritshot(mut.shots);
+						setChargedShot(ShotType.SPIRITSHOTS, true);
 				}
 			}
 			
@@ -6980,9 +6895,7 @@ public abstract class L2Character extends L2Object
 			angleDiff += 360;
 		if (angleDiff >= 360 - maxAngleDiff)
 			angleDiff -= 360;
-		if (Math.abs(angleDiff) <= maxAngleDiff)
-			return true;
-		return false;
+		return Math.abs(angleDiff) <= maxAngleDiff;
 	}
 	
 	/**
@@ -7003,9 +6916,7 @@ public abstract class L2Character extends L2Object
 			angleDiff += 360;
 		if (angleDiff >= 360 - maxAngleDiff)
 			angleDiff -= 360;
-		if (Math.abs(angleDiff) <= maxAngleDiff)
-			return true;
-		return false;
+		return Math.abs(angleDiff) <= maxAngleDiff;
 	}
 	
 	public boolean isInFrontOfTarget()
@@ -7577,6 +7488,29 @@ public abstract class L2Character extends L2Object
 		}
 	}
 	
+	public void addOverrideCond(PcCondOverride... excs)
+	{
+		for (PcCondOverride exc : excs)
+		{
+			_exceptions |= exc.getMask();
+		}
+		GlobalVariablesManager.getInstance().storeVariable(COND_EXCEPTIONS, Long.toString(_exceptions));
+	}
+	
+	public void removeOverridedCond(PcCondOverride... excs)
+	{
+		for (PcCondOverride exc : excs)
+		{
+			_exceptions &= ~exc.getMask();
+		}
+		GlobalVariablesManager.getInstance().storeVariable(COND_EXCEPTIONS, Long.toString(_exceptions));
+	}
+	
+	public boolean canOverrideCond(PcCondOverride excs)
+	{
+		return (_exceptions & excs.getMask()) == excs.getMask();
+	}
+	
 	// LISTENERS
 	
 	/**
@@ -7842,131 +7776,4 @@ public abstract class L2Character extends L2Object
 	{
 		globalSkillUseListeners.remove(listener);
 	}
-	
-	/**
-	 * Sets the character's spiritshot charge to none, if the skill allows it.
-	 * @param skill 
-	 */
-	public void spsUncharge(L2Skill skill)
-	{
-		if (!skill.isStatic())
-			spsUncharge();
-	}
-	
-	/**
-	 * Sets the character's spiritshot charge to none.
-	 */
-	public void spsUncharge()
-	{	
-		if (isPlayer())
-		{
-			L2ItemInstance weapon = getActiveWeaponInstance();
-			if (weapon != null)
-			{
-				weapon.setChargedSpiritshot(L2ItemInstance.CHARGED_NONE);
-			}
-		}
-		else if (isSummon()) // If is not player, check for summon.
-		{
-			((L2Summon) this).setChargedSpiritShot(L2ItemInstance.CHARGED_NONE);
-		}
-		else if (isNpc())
-		{
-			((L2Npc) this)._spiritshotcharged = false;
-		}
-	}
-	
-	/**
-	 * Sets the character's soulshot charge to none, if the skill allows it.
-	 * @param skill 
-	 */
-	public void ssUncharge(L2Skill skill)
-	{
-		if (!skill.isStatic())
-			ssUncharge();
-	}
-	
-	/**
-	 * Sets the character's soulshot charge to none.
-	 */
-	public void ssUncharge()
-	{
-		if (isPlayer())
-		{
-			L2ItemInstance weapon = getActiveWeaponInstance();
-			if (weapon != null)
-			{
-				weapon.setChargedSoulshot(L2ItemInstance.CHARGED_NONE);
-			}
-		}
-		else if (isSummon()) // If is not player, check for summon.
-		{
-			((L2Summon) this).setChargedSoulShot(L2ItemInstance.CHARGED_NONE);
-		}
-		else if (isNpc())
-		{
-			((L2Npc) this)._soulshotcharged = false;
-		}
-	}
-		
-	public boolean isSoulshotCharged(L2Skill skill)
-	{
-		L2ItemInstance weapon = getActiveWeaponInstance();
-		if (isPlayer() && !skill.isMagic() && (weapon != null) && (weapon.getChargedSoulshot() == L2ItemInstance.CHARGED_SOULSHOT))
-		{
-			return true;
-		}
-		else if (isNpc() && ((L2Npc) this)._soulshotcharged)
-		{
-			return true;
-		}
-		return isSummon() && ((L2Summon) this).getChargedSoulShot() == L2ItemInstance.CHARGED_SOULSHOT;
-	}
-	
-	public boolean isSpiritshotCharged(L2Skill skill)
-	{
-		L2ItemInstance weapon = getActiveWeaponInstance();
-		if (isPlayer() && skill.isMagic() && (weapon != null) && (weapon.getChargedSpiritshot() == L2ItemInstance.CHARGED_SPIRITSHOT))
-		{
-			return true;
-		}
-		else if (isNpc() && ((L2Npc) this)._spiritshotcharged)
-		{
-			return true;
-		}
-		return isSummon() && ((L2Summon) this).getChargedSpiritShot() == L2ItemInstance.CHARGED_SPIRITSHOT;
-	}
-	
-	public boolean isBlessedSpiritshotCharged(L2Skill skill)
-	{
-		L2ItemInstance weaponInst = getActiveWeaponInstance();
-		if (isPlayer() && skill.isMagic() && weaponInst != null && weaponInst.getChargedSpiritshot() == L2ItemInstance.CHARGED_BLESSED_SPIRITSHOT)
-		{
-			return true;
-		}
-		return isSummon() && ((L2Summon) this).getChargedSpiritShot() == L2ItemInstance.CHARGED_BLESSED_SPIRITSHOT;
-	}
-	
-	public void addOverrideCond(PcCondOverride... excs)
-	{
-		for (PcCondOverride exc : excs)
-		{
-			_exceptions |= exc.getMask();
-		}
-		GlobalVariablesManager.getInstance().storeVariable(COND_EXCEPTIONS, Long.toString(_exceptions));
-	}
-	
-	public void removeOverridedCond(PcCondOverride... excs)
-	{
-		for (PcCondOverride exc : excs)
-		{
-			_exceptions &= ~exc.getMask();
-		}
-		GlobalVariablesManager.getInstance().storeVariable(COND_EXCEPTIONS, Long.toString(_exceptions));
-	}
-	
-	public boolean canOverrideCond(PcCondOverride excs)
-	{
-		return (_exceptions & excs.getMask()) == excs.getMask();
-	}
 }

+ 58 - 54
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Npc.java

@@ -39,6 +39,7 @@ import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2Spawn;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.L2WorldRegion;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.actor.instance.L2ClanHallManagerInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2DoormenInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2FestivalGuideInstance;
@@ -131,12 +132,8 @@ public class L2Npc extends L2Character
 	private double _currentCollisionHeight; // used for npc grow effect skills
 	private double _currentCollisionRadius; // used for npc grow effect skills
 	
-	public boolean _soulshotcharged = false;
-	public boolean _spiritshotcharged = false;
 	private int _soulshotamount = 0;
 	private int _spiritshotamount = 0;
-	public boolean _ssrecharged = true;
-	public boolean _spsrecharged = true;
 	private int _displayEffect = 0;
 	
 	/**
@@ -146,6 +143,8 @@ public class L2Npc extends L2Character
 	
 	private final L2NpcAIData _staticAIData = getTemplate().getAIDataStatic();
 	
+	private int _shotsMask = 0;
+	
 	//AI Recall
 	public int getSoulShot()
 	{
@@ -167,56 +166,6 @@ public class L2Npc extends L2Character
 		return _staticAIData.getSpiritShotChance();
 	}
 	
-	public boolean useSoulShot()
-	{
-		if (_soulshotcharged)
-			return true;
-		if (_ssrecharged)
-		{
-			_soulshotamount = getSoulShot();
-			_ssrecharged = false;
-		}
-		else if (_soulshotamount > 0)
-		{
-			if (Rnd.get(100) <= getSoulShotChance())
-			{
-				_soulshotamount = _soulshotamount - 1;
-				Broadcast.toSelfAndKnownPlayersInRadius(this, new MagicSkillUse(this, this, 2154, 1, 0, 0), 600);
-				_soulshotcharged = true;
-			}
-		}
-		else
-			return false;
-		
-		return _soulshotcharged;
-	}
-	
-	public boolean useSpiritShot()
-	{
-		if (_spiritshotcharged)
-			return true;
-		
-		//_spiritshotcharged = false;
-		if (_spsrecharged)
-		{
-			_spiritshotamount = getSpiritShot();
-			_spsrecharged = false;
-		}
-		else if (_spiritshotamount > 0)
-		{
-			if (Rnd.get(100) <= getSpiritShotChance())
-			{
-				_spiritshotamount = _spiritshotamount - 1;
-				Broadcast.toSelfAndKnownPlayersInRadius(this, new MagicSkillUse(this, this, 2061, 1, 0, 0), 600);
-				_spiritshotcharged = true;
-			}
-		}
-		else
-			return false;
-		
-		return _spiritshotcharged;
-	}
-	
 	public int getEnemyRange()
 	{
 		return _staticAIData.getEnemyRange();
@@ -1722,4 +1671,59 @@ public class L2Npc extends L2Character
 	{
 		return WalkingManager.getInstance().isRegistered(this);
 	}
+		
+	@Override
+	public boolean isChargedShot(ShotType type)
+	{
+		return (_shotsMask & type.getMask()) == type.getMask();
+	}
+	
+	@Override
+	public void setChargedShot(ShotType type, boolean charged)
+	{
+		if (charged)
+		{
+			_shotsMask |= type.getMask();
+		}
+		else
+		{
+			_shotsMask &= ~ type.getMask();
+		}
+	}
+	
+	@Override
+	public void rechargeShots(boolean physical, boolean magic)
+	{
+		if (_soulshotamount > 0 || _spiritshotamount > 0)
+		{
+			if (physical)
+			{
+				if (_soulshotamount == 0)
+				{
+					return;
+				}
+				else if (Rnd.get(100) > getSoulShotChance())
+				{
+					return;
+				}
+				_soulshotamount--;
+				Broadcast.toSelfAndKnownPlayersInRadius(this, new MagicSkillUse(this, this, 2154, 1, 0, 0), 600);
+				setChargedShot(ShotType.SOULSHOTS, true);
+			}
+			if (magic)
+			{
+				if (_spiritshotamount == 0)
+				{
+					return;
+				}
+				else if (Rnd.get(100) > getSpiritShotChance())
+				{
+					return;
+				}
+				_spiritshotamount--;
+				Broadcast.toSelfAndKnownPlayersInRadius(this, new MagicSkillUse(this, this, 2061, 1, 0, 0), 600);
+				setChargedShot(ShotType.SPIRITSHOTS, true);
+			}
+		}
+	}
 }

+ 67 - 23
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Summon.java

@@ -22,10 +22,13 @@ import com.l2jserver.gameserver.ai.L2CharacterAI;
 import com.l2jserver.gameserver.ai.L2SummonAI;
 import com.l2jserver.gameserver.datatables.ExperienceTable;
 import com.l2jserver.gameserver.datatables.ItemTable;
+import com.l2jserver.gameserver.handler.IItemHandler;
+import com.l2jserver.gameserver.handler.ItemHandler;
 import com.l2jserver.gameserver.instancemanager.TerritoryWarManager;
 import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2Party;
 import com.l2jserver.gameserver.model.L2WorldRegion;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.actor.L2Attackable.AggroInfo;
 import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2MerchantSummonInstance;
@@ -41,6 +44,7 @@ import com.l2jserver.gameserver.model.itemcontainer.PetInventory;
 import com.l2jserver.gameserver.model.items.L2EtcItem;
 import com.l2jserver.gameserver.model.items.L2Weapon;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.items.type.L2ActionType;
 import com.l2jserver.gameserver.model.olympiad.OlympiadGameManager;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.targets.L2TargetType;
@@ -68,15 +72,14 @@ public abstract class L2Summon extends L2Playable
 	private boolean _follow = true;
 	private boolean _previousFollowStatus = true;
 	
-	private int _chargedSoulShot;
-	private int _chargedSpiritShot;
-	
 	//  /!\ BLACK MAGIC /!\
 	// we dont have walk speed in pet data so for now use runspd / 3
 	public static final int WALK_SPEED_MULTIPLIER = 3;
 	
 	public boolean _restoreSummon = true;
 	
+	private int _shotsMask = 0;
+	
 	public class AIAccessor extends L2Character.AIAccessor
 	{
 		protected AIAccessor()
@@ -293,16 +296,6 @@ public abstract class L2Summon extends L2Playable
 		return 1;
 	}
 	
-	public void setChargedSoulShot(int shotType)
-	{
-		_chargedSoulShot = shotType;
-	}
-	
-	public void setChargedSpiritShot(int shotType)
-	{
-		_chargedSpiritShot = shotType;
-	}
-	
 	public void followOwner()
 	{
 		setFollowStatus(true);
@@ -470,16 +463,6 @@ public abstract class L2Summon extends L2Playable
 		return _owner.isAutoAttackable(attacker);
 	}
 	
-	public int getChargedSoulShot()
-	{
-		return _chargedSoulShot;
-	}
-	
-	public int getChargedSpiritShot()
-	{
-		return _chargedSpiritShot;
-	}
-	
 	public int getControlObjectId()
 	{
 		return 0;
@@ -944,4 +927,65 @@ public abstract class L2Summon extends L2Playable
 	{
 		return true;
 	}
+		
+	@Override
+	public boolean isChargedShot(ShotType type)
+	{
+		return (_shotsMask & type.getMask()) == type.getMask();
+	}
+	
+	@Override
+	public void setChargedShot(ShotType type, boolean charged)
+	{
+		if (charged)
+		{
+			_shotsMask |= type.getMask();
+		}
+		else
+		{
+			_shotsMask &= ~ type.getMask();
+		}
+	}
+	
+	@Override
+	public void rechargeShots(boolean physical, boolean magic)
+	{
+		L2ItemInstance item;
+		IItemHandler handler;
+		
+		if (getOwner().getAutoSoulShot() == null || getOwner().getAutoSoulShot().isEmpty())
+			return;
+		
+		for (int itemId : getOwner().getAutoSoulShot())
+		{
+			item = getInventory().getItemByItemId(itemId);
+			
+			if (item != null)
+			{
+				if (magic)
+				{
+					if (item.getItem().getDefaultAction() == L2ActionType.summon_spiritshot)
+					{
+						handler = ItemHandler.getInstance().getHandler(item.getEtcItem());
+						if (handler != null)
+							handler.useItem(getOwner(), item, false);
+					}
+				}
+				
+				if (physical)
+				{
+					if (item.getItem().getDefaultAction() == L2ActionType.summon_soulshot)
+					{
+						handler = ItemHandler.getInstance().getHandler(item.getEtcItem());
+						if (handler != null)
+							handler.useItem(getOwner(), item, false);
+					}
+				}
+			}
+			else
+			{
+				getOwner().removeAutoSoulShot(itemId);
+			}
+		}
+	}
 }

+ 23 - 25
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -129,6 +129,7 @@ import com.l2jserver.gameserver.model.PartyMatchRoomList;
 import com.l2jserver.gameserver.model.PartyMatchWaitingList;
 import com.l2jserver.gameserver.model.PcCondOverride;
 import com.l2jserver.gameserver.model.ShortCuts;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.TerritoryWard;
 import com.l2jserver.gameserver.model.TimeStamp;
 import com.l2jserver.gameserver.model.TradeList;
@@ -2461,22 +2462,6 @@ public final class L2PcInstance extends L2Playable
 		}
 	}
 	
-	public void checkSShotsMatch(L2ItemInstance equipped, L2ItemInstance unequipped)
-	{
-		if (unequipped == null)
-			return;
-		
-		unequipped.setChargedSoulshot(L2ItemInstance.CHARGED_NONE);
-		unequipped.setChargedSpiritshot(L2ItemInstance.CHARGED_NONE);
-		
-		// on retail auto shots never disabled on uneqip
-		/*if (unequipped.getItem().getType2() == L2Item.TYPE2_WEAPON &&
-				(equipped == null ? true : equipped.getItem().getItemGradeSPlus() != unequipped.getItem().getItemGradeSPlus()))
-		{
-			disableAutoShotByCrystalType(unequipped.getItem().getItemGradeSPlus());
-		}*/
-	}
-	
 	public void useEquippableItem(L2ItemInstance item, boolean abortAttack)
 	{
 		// Equip or unEquip
@@ -2484,11 +2469,6 @@ public final class L2PcInstance extends L2Playable
 		final boolean isEquiped = item.isEquipped();
 		final int oldInvLimit = getInventoryLimit();
 		SystemMessage sm = null;
-		if ((item.getItem().getBodyPart() & L2Item.SLOT_MULTI_ALLWEAPON) != 0)
-		{
-			L2ItemInstance old = getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
-			checkSShotsMatch(item, old);
-		}
 		
 		if(!fireEquipmentListeners(isEquiped,item))
 		{
@@ -2540,7 +2520,7 @@ public final class L2PcInstance extends L2Playable
 				
 				if ((item.getItem().getBodyPart() & L2Item.SLOT_MULTI_ALLWEAPON) != 0)
 				{
-					rechargeAutoSoulShot(true, true, false);
+					rechargeShots(true, true);
 				}
 			}
 			else
@@ -9821,7 +9801,8 @@ public final class L2PcInstance extends L2Playable
 		return _activeSoulShots;
 	}
 	
-	public void rechargeAutoSoulShot(boolean physical, boolean magic, boolean summon)
+	@Override
+	public void rechargeShots(boolean physical, boolean magic)
 	{
 		L2ItemInstance item;
 		IItemHandler handler;
@@ -9837,7 +9818,7 @@ public final class L2PcInstance extends L2Playable
 			{
 				if (magic)
 				{
-					if (item.getItem().getDefaultAction() == (summon ? L2ActionType.summon_spiritshot : L2ActionType.spiritshot))
+					if (item.getItem().getDefaultAction() == L2ActionType.spiritshot)
 					{
 						handler = ItemHandler.getInstance().getHandler(item.getEtcItem());
 						if (handler != null)
@@ -9847,7 +9828,7 @@ public final class L2PcInstance extends L2Playable
 				
 				if (physical)
 				{
-					if (item.getItem().getDefaultAction() == (summon ? L2ActionType.summon_soulshot : L2ActionType.soulshot))
+					if (item.getItem().getDefaultAction() == L2ActionType.soulshot)
 					{
 						handler = ItemHandler.getInstance().getHandler(item.getEtcItem());
 						if (handler != null)
@@ -15201,6 +15182,23 @@ public final class L2PcInstance extends L2Playable
 		return true;
 	}
 	
+	@Override
+	public boolean isChargedShot(ShotType type)
+	{
+		L2ItemInstance weapon = getActiveWeaponInstance();
+		return weapon != null && weapon.isChargedShot(type);
+	}
+	
+	@Override
+	public void setChargedShot(ShotType type, boolean charged)
+	{
+		L2ItemInstance weapon = getActiveWeaponInstance();
+		if (weapon != null)
+		{
+			weapon.setChargedShot(type, charged);
+		}
+	}
+	
 	// LISTENERS
 	/**
 	 * Fires all the equipment listeners, if any.<br>

+ 20 - 6
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PetInstance.java

@@ -44,6 +44,7 @@ import com.l2jserver.gameserver.model.L2Party;
 import com.l2jserver.gameserver.model.L2PetData;
 import com.l2jserver.gameserver.model.L2PetLevelData;
 import com.l2jserver.gameserver.model.L2World;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.stat.PetStat;
@@ -1199,10 +1200,6 @@ public class L2PetInstance extends L2Summon
 		{
 			_feedTask.cancel(false);
 			_feedTask = null;
-			if (Config.DEBUG)
-			{
-				_logPet.fine("Pet [#" + getObjectId() + "] feed task stop");
-			}
 		}
 	}
 	
@@ -1251,7 +1248,7 @@ public class L2PetInstance extends L2Summon
 	
 	private void deathPenalty()
 	{
-		// TODO Need Correct Penalty
+		// TODO: Need Correct Penalty
 		
 		int lvl = getStat().getLevel();
 		double percentLost = (-0.07 * lvl) + 6.5;
@@ -1481,4 +1478,21 @@ public class L2PetInstance extends L2Summon
 	{
 		return true;
 	}
-}
+	
+	@Override
+	public boolean isChargedShot(ShotType type)
+	{
+		L2ItemInstance weapon = getActiveWeaponInstance();
+		return (weapon != null) && weapon.isChargedShot(type);
+	}
+	
+	@Override
+	public void setChargedShot(ShotType type, boolean charged)
+	{
+		L2ItemInstance weapon = getActiveWeaponInstance();
+		if (weapon != null)
+		{
+			weapon.setChargedShot(type, charged);
+		}
+	}
+}

+ 30 - 62
L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/instance/L2ItemInstance.java

@@ -45,6 +45,7 @@ import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.L2WorldRegion;
 import com.l2jserver.gameserver.model.Location;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.knownlist.NullKnownList;
@@ -152,20 +153,7 @@ public final class L2ItemInstance extends L2Object
 	private long _dropTime;
 	
 	private boolean _published = false;
-	
-	public static final int CHARGED_NONE = 0;
-	public static final int CHARGED_SOULSHOT = 1;
-	public static final int CHARGED_SPIRITSHOT = 1;
-	// public static final int CHARGED_BLESSED_SOULSHOT = 2; // It's a really exists? ;-)
-	public static final int CHARGED_BLESSED_SPIRITSHOT = 2;
-	
-	/** Item charged with SoulShot (type of SoulShot) */
-	private int _chargedSoulshot = CHARGED_NONE;
-	/** Item charged with SpiritShot (type of SpiritShot) */
-	private int _chargedSpiritshot = CHARGED_NONE;
-	
-	private boolean _chargedFishtshot = false;
-	
+		
 	private boolean _protected;
 	
 	public static final int UNCHANGED = 0;
@@ -185,6 +173,8 @@ public final class L2ItemInstance extends L2Object
 	
 	private final DropProtection _dropProtection = new DropProtection();
 	
+	private int _shotsMask = 0;
+	
 	/**
 	 * Constructor of the L2ItemInstance from the objectId and the itemId.
 	 * @param objectId : int designating the ID of the object in the world
@@ -1300,7 +1290,7 @@ public final class L2ItemInstance extends L2Object
 					InventoryUpdate iu = new InventoryUpdate();
 					for (L2ItemInstance item : unequiped)
 					{
-						player.checkSShotsMatch(null, item);
+						item.unChargeAllShots();
 						iu.addModifiedItem(item);
 					}
 					player.sendPacket(iu);
@@ -1365,52 +1355,6 @@ public final class L2ItemInstance extends L2Object
 		return false;
 	}
 	
-	/**
-	 * Returns the type of charge with SoulShot of the item.
-	 * @return int (CHARGED_NONE, CHARGED_SOULSHOT)
-	 */
-	public int getChargedSoulshot()
-	{
-		return _chargedSoulshot;
-	}
-	
-	/**
-	 * Returns the type of charge with SpiritShot of the item
-	 * @return int (CHARGED_NONE, CHARGED_SPIRITSHOT, CHARGED_BLESSED_SPIRITSHOT)
-	 */
-	public int getChargedSpiritshot()
-	{
-		return _chargedSpiritshot;
-	}
-	
-	public boolean getChargedFishshot()
-	{
-		return _chargedFishtshot;
-	}
-	
-	/**
-	 * Sets the type of charge with SoulShot of the item
-	 * @param type : int (CHARGED_NONE, CHARGED_SOULSHOT)
-	 */
-	public void setChargedSoulshot(int type)
-	{
-		_chargedSoulshot = type;
-	}
-	
-	/**
-	 * Sets the type of charge with SpiritShot of the item
-	 * @param type : int (CHARGED_NONE, CHARGED_SPIRITSHOT, CHARGED_BLESSED_SPIRITSHOT)
-	 */
-	public void setChargedSpiritshot(int type)
-	{
-		_chargedSpiritshot = type;
-	}
-	
-	public void setChargedFishshot(boolean type)
-	{
-		_chargedFishtshot = type;
-	}
-	
 	/**
 	 * This function basically returns a set of functions from L2Item/L2Armor/L2Weapon, but may add additional functions, if this particular item instance is enhanched for a particular player.
 	 * @param player : L2Character designating the player
@@ -1815,7 +1759,7 @@ public final class L2ItemInstance extends L2Object
 				InventoryUpdate iu = new InventoryUpdate();
 				for (L2ItemInstance item : unequiped)
 				{
-					player.checkSShotsMatch(null, item);
+					item.unChargeAllShots();
 					iu.addModifiedItem(item);
 				}
 				player.sendPacket(iu);
@@ -2227,4 +2171,28 @@ public final class L2ItemInstance extends L2Object
 		html.replace("%itemId%", String.valueOf(getObjectId()));
 		activeChar.sendPacket(html);
 	}
+		
+	@Override
+	public boolean isChargedShot(ShotType type)
+	{
+		return (_shotsMask & type.getMask()) == type.getMask();
+	}
+	
+	@Override
+	public void setChargedShot(ShotType type, boolean charged)
+	{
+		if (charged)
+		{
+			_shotsMask |= type.getMask();
+		}
+		else
+		{
+			_shotsMask &= ~ type.getMask();
+		}
+	}
+	
+	public void unChargeAllShots()
+	{
+		_shotsMask = 0;
+	}
 }

+ 4 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/olympiad/AbstractOlympiadGame.java

@@ -297,10 +297,10 @@ public abstract class AbstractOlympiadGame
 			player.disableAutoShotsAll();
 			
 			// Discharge any active shots
-			if (player.getActiveWeaponInstance() != null)
-			{
-				player.getActiveWeaponInstance().setChargedSoulshot(L2ItemInstance.CHARGED_NONE);
-				player.getActiveWeaponInstance().setChargedSpiritshot(L2ItemInstance.CHARGED_NONE);
+			L2ItemInstance item = player.getActiveWeaponInstance();
+			if (item != null)
+			{	
+				item.unChargeAllShots();
 			}
 			
 			// enable skills with cool time <= 15 minutes

+ 8 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/L2Skill.java

@@ -889,6 +889,14 @@ public abstract class L2Skill implements IChanceSkillTrigger
 		return _level;
 	}
 	
+	/**
+	 * @return Returns true to set physical skills.
+	 */
+	public final boolean isPhysical()
+	{
+		return _magic == 0;
+	}
+	
 	/**
 	 * @return Returns true to set magic skills.
 	 */

+ 5 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillChargeDmg.java

@@ -20,6 +20,7 @@ import java.util.logging.Logger;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.model.L2Object;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.effects.L2Effect;
@@ -53,7 +54,7 @@ public class L2SkillChargeDmg extends L2Skill
 			// thanks Diego Vargas of L2Guru: 70*((0.8+0.201*No.Charges) * (PATK+POWER)) / PDEF
 			modifier = 0.8 + 0.201 * (getNumCharges() + caster.getActingPlayer().getCharges());
 		}
-		boolean soul = caster.isSoulshotCharged(this);
+		boolean ss = isPhysical() && caster.isChargedShot(ShotType.SOULSHOTS);
 		
 		for (L2Character target: (L2Character[]) targets)
 		{
@@ -90,7 +91,7 @@ public class L2SkillChargeDmg extends L2Skill
 			if (getBaseCritRate() > 0 && !isStaticDamage())
 				crit = Formulas.calcCrit(this.getBaseCritRate() * 10 * BaseStats.STR.calcBonus(caster), true, target);
 			// damage calculation, crit is static 2x
-			double damage = isStaticDamage() ? getPower() : Formulas.calcPhysDam(caster, target, this, shld, false, false, soul);
+			double damage = isStaticDamage() ? getPower() : Formulas.calcPhysDam(caster, target, this, shld, false, false, ss);
 			if (crit)
 				damage *= 2;
 			
@@ -186,6 +187,7 @@ public class L2SkillChargeDmg extends L2Skill
 			getEffectsSelf(caster);
 		}
 		
-		caster.ssUncharge(this);
+		// Consume shot
+		caster.setChargedShot(ShotType.SOULSHOTS, false);
 	}
 }

+ 9 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillDrain.java

@@ -20,6 +20,7 @@ import java.util.logging.Logger;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.model.L2Object;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Npc;
@@ -56,6 +57,10 @@ public class L2SkillDrain extends L2Skill
 			return;
 		}
 		
+		boolean ss = isPhysical() && activeChar.isChargedShot(ShotType.SOULSHOTS);
+		boolean sps = isMagic() && activeChar.isChargedShot(ShotType.SPIRITSHOTS);
+		boolean bss = isMagic() && activeChar.isChargedShot(ShotType.BLESSED_SPIRITSHOTS);
+		
 		for (L2Character target : (L2Character[]) targets)
 		{
 			if (target.isAlikeDead() && (getTargetType() != L2TargetType.TARGET_CORPSE_MOB))
@@ -70,7 +75,7 @@ public class L2SkillDrain extends L2Skill
 			
 			boolean mcrit = Formulas.calcMCrit(activeChar.getMCriticalHit(target, this));
 			byte shld = Formulas.calcShldUse(activeChar, target, this);
-			int damage = isStaticDamage() ? (int) getPower() : (int) Formulas.calcMagicDam(activeChar, target, this, shld, activeChar.isSpiritshotCharged(this), activeChar.isBlessedSpiritshotCharged(this), mcrit);
+			int damage = isStaticDamage() ? (int) getPower() : (int) Formulas.calcMagicDam(activeChar, target, this, shld, sps, bss, mcrit);
 			
 			int _drain = 0;
 			int _cp = (int) target.getCurrentCp();
@@ -148,7 +153,7 @@ public class L2SkillDrain extends L2Skill
 					{
 						// activate attacked effects, if any
 						target.stopSkillEffects(getId());
-						if (Formulas.calcSkillSuccess(activeChar, target, this, shld, false, activeChar.isSpiritshotCharged(this), activeChar.isBlessedSpiritshotCharged(this)))
+						if (Formulas.calcSkillSuccess(activeChar, target, this, shld, ss, sps, bss))
 						{
 							getEffects(activeChar, target);
 						}
@@ -180,7 +185,8 @@ public class L2SkillDrain extends L2Skill
 		}
 		// cast self effect if any
 		getEffectsSelf(activeChar);
-		activeChar.spsUncharge(this);
+		// Consume shot
+		activeChar.setChargedShot(bss ? ShotType.BLESSED_SPIRITSHOTS : ShotType.SPIRITSHOTS, false);
 	}
 	
 	public void useCubicSkill(L2CubicInstance activeCubic, L2Object[] targets)

+ 37 - 21
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillElemental.java

@@ -15,6 +15,7 @@
 package com.l2jserver.gameserver.model.skills.l2skills;
 
 import com.l2jserver.gameserver.model.L2Object;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.effects.L2Effect;
@@ -23,27 +24,29 @@ import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.stats.Env;
 import com.l2jserver.gameserver.model.stats.Formulas;
 
-public class L2SkillElemental extends L2Skill {
-	
+public class L2SkillElemental extends L2Skill
+{
 	private final int[] _seeds;
 	private final boolean _seedAny;
 	
-	public L2SkillElemental(StatsSet set) {
+	public L2SkillElemental(StatsSet set)
+	{
 		super(set);
 		
 		_seeds = new int[3];
-		_seeds[0] = set.getInteger("seed1",0);
-		_seeds[1] = set.getInteger("seed2",0);
-		_seeds[2] = set.getInteger("seed3",0);
+		_seeds[0] = set.getInteger("seed1", 0);
+		_seeds[1] = set.getInteger("seed2", 0);
+		_seeds[2] = set.getInteger("seed3", 0);
 		
-		if (set.getInteger("seed_any",0)==1)
+		if (set.getInteger("seed_any", 0) == 1)
 			_seedAny = true;
 		else
 			_seedAny = false;
 	}
 	
 	@Override
-	public void useSkill(L2Character activeChar, L2Object[] targets) {
+	public void useSkill(L2Character activeChar, L2Object[] targets)
+	{
 		if (activeChar.isAlikeDead())
 			return;
 		
@@ -58,29 +61,41 @@ public class L2SkillElemental extends L2Skill {
 			}
 		}
 		
-		for (L2Character target: (L2Character[]) targets)
+		boolean ss = isPhysical() && activeChar.isChargedShot(ShotType.SOULSHOTS);
+		boolean sps = isMagic() && activeChar.isChargedShot(ShotType.SPIRITSHOTS);
+		boolean bss = isMagic() && activeChar.isChargedShot(ShotType.BLESSED_SPIRITSHOTS);
+		
+		for (L2Character target : (L2Character[]) targets)
 		{
 			if (target.isAlikeDead())
 				continue;
 			
 			boolean charged = true;
-			if (!_seedAny){
-				for (int i=0;i<_seeds.length;i++){
-					if (_seeds[i]!=0){
+			if (!_seedAny)
+			{
+				for (int i = 0; i < _seeds.length; i++)
+				{
+					if (_seeds[i] != 0)
+					{
 						L2Effect e = target.getFirstEffect(_seeds[i]);
-						if (e==null || !e.getInUse()){
+						if (e == null || !e.getInUse())
+						{
 							charged = false;
 							break;
 						}
 					}
 				}
 			}
-			else {
+			else
+			{
 				charged = false;
-				for (int i=0;i<_seeds.length;i++){
-					if (_seeds[i]!=0){
+				for (int i = 0; i < _seeds.length; i++)
+				{
+					if (_seeds[i] != 0)
+					{
 						L2Effect e = target.getFirstEffect(_seeds[i]);
-						if (e!=null && e.getInUse()){
+						if (e != null && e.getInUse())
+						{
 							charged = true;
 							break;
 						}
@@ -96,8 +111,7 @@ public class L2SkillElemental extends L2Skill {
 			boolean mcrit = Formulas.calcMCrit(activeChar.getMCriticalHit(target, this));
 			byte shld = Formulas.calcShldUse(activeChar, target, this);
 			
-			int damage = (int)Formulas.calcMagicDam(
-					activeChar, target, this, shld, activeChar.isSpiritshotCharged(this), activeChar.isBlessedSpiritshotCharged(this), mcrit);
+			int damage = (int) Formulas.calcMagicDam(activeChar, target, this, shld, sps, bss, mcrit);
 			
 			if (damage > 0)
 			{
@@ -116,9 +130,11 @@ public class L2SkillElemental extends L2Skill {
 			
 			// activate attacked effects, if any
 			target.stopSkillEffects(getId());
-			getEffects(activeChar, target, new Env(shld, activeChar.isSpiritshotCharged(this), false, activeChar.isBlessedSpiritshotCharged(this)));
+			
+			getEffects(activeChar, target, new Env(shld, ss, sps, bss));
 		}
 		
-		activeChar.spsUncharge(this);
+		// Consume shot
+		activeChar.setChargedShot(bss ? ShotType.BLESSED_SPIRITSHOTS : ShotType.SPIRITSHOTS, false);
 	}
 }

+ 4 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/l2skills/L2SkillTeleport.java

@@ -21,6 +21,7 @@ import com.l2jserver.gameserver.instancemanager.MapRegionManager;
 import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.Location;
 import com.l2jserver.gameserver.model.PcCondOverride;
+import com.l2jserver.gameserver.model.ShotType;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
@@ -55,6 +56,8 @@ public class L2SkillTeleport extends L2Skill
 	@Override
 	public void useSkill(L2Character activeChar, L2Object[] targets)
 	{	
+		boolean bss = isMagic() && activeChar.isChargedShot(ShotType.BLESSED_SPIRITSHOTS);
+		
 		if (activeChar.isPlayer())
 		{
 			// Thanks nbd
@@ -165,7 +168,7 @@ public class L2SkillTeleport extends L2Skill
 				}
 			}
 			
-			activeChar.spsUncharge(this);
+			activeChar.setChargedShot(bss ? ShotType.BLESSED_SPIRITSHOTS : ShotType.SPIRITSHOTS, false);
 		}
 		catch (Exception e)
 		{

+ 1 - 38
L2J_Server_BETA/java/com/l2jserver/gameserver/model/stats/Formulas.java

@@ -717,18 +717,7 @@ public final class Formulas
 		double damage = attacker.getPAtk(target);
 		double defence = target.getPDef(attacker);
 		damage += calcValakasTrait(attacker, target, skill);
-		if (attacker.isNpc())
-		{
-			if (((L2Npc) attacker)._soulshotcharged)
-			{
-				ss = true;
-			}
-			else
-			{
-				ss = false;
-			}
-			((L2Npc) attacker)._soulshotcharged = false;
-		}
+		
 		// Def bonusses in PvP fight
 		if (isPvP)
 		{
@@ -998,19 +987,6 @@ public final class Formulas
 		final boolean isPvE = attacker.isPlayable() && target.isL2Attackable();
 		double mAtk = attacker.getMAtk(target, skill);
 		double mDef = target.getMDef(attacker, skill);
-		// AI SpiritShot
-		if (attacker.isNpc())
-		{
-			if (((L2Npc) attacker)._spiritshotcharged)
-			{
-				ss = true;
-			}
-			else
-			{
-				ss = false;
-			}
-			((L2Npc) attacker)._spiritshotcharged = false;
-		}
 		// --------------------------------
 		// Pvp bonuses for def
 		if (isPvP)
@@ -2376,19 +2352,6 @@ public final class Formulas
 	
 	public static double calcManaDam(L2Character attacker, L2Character target, L2Skill skill, boolean ss, boolean bss)
 	{
-		// AI SpiritShot
-		if (attacker.isNpc())
-		{
-			if (((L2Npc) attacker)._spiritshotcharged)
-			{
-				ss = true;
-			}
-			else
-			{
-				ss = false;
-			}
-			((L2Npc) attacker)._spiritshotcharged = false;
-		}
 		// Mana Burn = (SQR(M.Atk)*Power*(Target Max MP/97))/M.Def
 		double mAtk = attacker.getMAtk(target, skill);
 		double mDef = target.getMDef(attacker, skill);

+ 4 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestAutoSoulShot.java

@@ -97,7 +97,9 @@ public final class RequestAutoSoulShot extends L2GameClientPacket
 							sm.addItemName(item);// Update Message by rocknow
 							activeChar.sendPacket(sm);
 							
-							activeChar.rechargeAutoSoulShot(true, true, true);
+							activeChar.rechargeShots(true, true);
+							activeChar.getPet().rechargeShots(true, true);
+							
 						}
 						else
 							activeChar.sendPacket(SystemMessageId.NO_SERVITOR_CANNOT_AUTOMATE_USE);
@@ -126,7 +128,7 @@ public final class RequestAutoSoulShot extends L2GameClientPacket
 						sm.addItemName(item);// Update Message by rocknow
 						activeChar.sendPacket(sm);
 						
-						activeChar.rechargeAutoSoulShot(true, true, false);
+						activeChar.rechargeShots(true, true);
 					}
 				}
 			}

+ 0 - 14
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestDestroyItem.java

@@ -130,20 +130,6 @@ public final class RequestDestroyItem extends L2GameClientPacket
 		if (_count > itemToRemove.getCount())
 			count = itemToRemove.getCount();
 		
-		if (itemToRemove.isEquipped())
-		{
-			L2ItemInstance[] unequiped = activeChar.getInventory().unEquipItemInSlotAndRecord(itemToRemove.getLocationSlot());
-			InventoryUpdate iu = new InventoryUpdate();
-			for (L2ItemInstance item : unequiped)
-			{
-				activeChar.checkSShotsMatch(null, item);
-				
-				iu.addModifiedItem(item);
-			}
-			activeChar.sendPacket(iu);
-			activeChar.broadcastUserInfo();
-		}
-		
 		if (itemToRemove.getItem().isPetItem())
 		{
 			if (activeChar.getPet() != null && activeChar.getPet().getControlObjectId() == _objectId)

+ 1 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestDropItem.java

@@ -186,8 +186,7 @@ public final class RequestDropItem extends L2GameClientPacket
 			InventoryUpdate iu = new InventoryUpdate();
 			for (L2ItemInstance itm : unequiped)
 			{
-				activeChar.checkSShotsMatch(null, itm);
-				
+				itm.unChargeAllShots();
 				iu.addModifiedItem(itm);
 			}
 			activeChar.sendPacket(iu);

+ 0 - 10
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestUnEquipItem.java

@@ -21,7 +21,6 @@ import com.l2jserver.gameserver.model.items.L2EtcItem;
 import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
 import com.l2jserver.gameserver.network.SystemMessageId;
-import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
 
 /**
@@ -101,15 +100,6 @@ public class RequestUnEquipItem extends L2GameClientPacket
 		}
 		
 		final L2ItemInstance[] unequipped = activeChar.getInventory().unEquipItemInBodySlotAndRecord(_slot);
-		final InventoryUpdate iu = new InventoryUpdate();
-		for (L2ItemInstance itm : unequipped)
-		{
-			activeChar.checkSShotsMatch(null, itm);
-			iu.addModifiedItem(itm);
-		}
-		
-		// Show the update in the inventory.
-		activeChar.sendPacket(iu);
 		activeChar.broadcastUserInfo();
 		
 		// This can be 0 if the user pressed the right mouse button twice very fast.