Просмотр исходного кода

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 лет назад
Родитель
Сommit
be05f8be82
19 измененных файлов с 390 добавлено и 514 удалено
  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.