All pastes #839343 Raw Edit

Anonymous

public text v1 · immutable
#839343 ·published 2007-12-30 23:51 UTC
rendered paste body
Index: java/net/sf/l2j/gameserver/clientpackets/MoveBackwardToLocation.java
===================================================================
--- java/net/sf/l2j/gameserver/clientpackets/MoveBackwardToLocation.java	(revision 2917)
+++ java/net/sf/l2j/gameserver/clientpackets/MoveBackwardToLocation.java	(working copy)
@@ -108,7 +108,7 @@
 		{
 			activeChar.sendPacket(new ActionFailed());
 		}
-		else if (activeChar.isAttackingNow() && activeChar.getActiveWeaponItem() != null && (activeChar.getActiveWeaponItem().getItemType() == L2WeaponType.BOW))
+		else if (activeChar.isAttackingNow() && activeChar.getActiveWeaponItem() != null && ((activeChar.getActiveWeaponItem().getItemType() == L2WeaponType.BOW) || (activeChar.getActiveWeaponItem().getItemType() == L2WeaponType.CROSSBOW)))
 		{
 			activeChar.sendPacket(new ActionFailed());
 		}
Index: java/net/sf/l2j/gameserver/network/SystemMessageId.java
===================================================================
--- java/net/sf/l2j/gameserver/network/SystemMessageId.java	(revision 2920)
+++ java/net/sf/l2j/gameserver/network/SystemMessageId.java	(working copy)
@@ -785,10 +785,22 @@
 
 	/**
 	 * ID: 112<br>
-	 * Message: You may no longer adjust items in the trade because the trade has been confirmed.
+	 * Message: You have run out of arrows.
 	 */
 	NOT_ENOUGH_ARROWS(112),
 
+    /**
+     * ID: 2224<br>
+     * Message: Crossbow is preparing to fire.
+     */
+    CROSSBOW_PREPARING_TO_FIRE(2224),
+
+    /**
+     * ID: 2226<br>
+     * Message: Not enough bolts.
+     */
+    NOT_ENOUGH_BOLTS(2226),
+
 	/**
 	 * ID: 129<br>
 	 * Message: Your inventory is full.
Index: java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java
===================================================================
--- java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java	(revision 2917)
+++ java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java	(working copy)
@@ -556,6 +556,7 @@
 	private long _requestExpireTime = 0;
 	private L2Request _request = new L2Request(this);
 	private L2ItemInstance _arrowItem;
+    private L2ItemInstance _boltItem;
 
 	// Used for protection after teleport
 	private long _protectEndTime = 0;
@@ -5314,6 +5315,66 @@
 		return _arrowItem != null;
 	}
 
+    /**
+     * Reduce the number of bolts owned by the L2PcInstance and send it Server->Client Packet InventoryUpdate or ItemList (to unequip if the last bolt was consummed).<BR><BR>
+     */
+    @Override
+    protected void reduceBoltCount()
+    {
+        L2ItemInstance bolts = getInventory().destroyItem("Consume", getInventory().getPaperdollObjectId(Inventory.PAPERDOLL_LHAND), 1, this, null);
+
+        if (Config.DEBUG) _log.fine("bolt count:" + (bolts==null? 0 : bolts.getCount()));
+
+        if (bolts == null || bolts.getCount() == 0)
+        {
+            getInventory().unEquipItemInSlot(Inventory.PAPERDOLL_LHAND);
+            _boltItem = null;
+
+            if (Config.DEBUG) _log.fine("removed bolts count");
+            sendPacket(new ItemList(this,false));
+        }
+        else
+        {
+            if (!Config.FORCE_INVENTORY_UPDATE)
+            {
+                InventoryUpdate iu = new InventoryUpdate();
+                iu.addModifiedItem(bolts);
+                sendPacket(iu);
+            }
+            else sendPacket(new ItemList(this, false));
+        }
+    }
+
+    /**
+     * Equip bolts needed in left hand and send a Server->Client packet ItemList to the L2PcINstance then return True.<BR><BR>
+     */
+    @Override
+    protected boolean checkAndEquipBolts()
+    {
+        // Check if nothing is equiped in left hand
+        if (getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND) == null)
+        {
+            // Get the L2ItemInstance of the arrows needed for this bow
+            _boltItem = getInventory().findBoltForCrossBow(getActiveWeaponItem());
+
+            if (_boltItem != null)
+            {
+                // Equip arrows needed in left hand
+                getInventory().setPaperdollItem(Inventory.PAPERDOLL_LHAND, _boltItem);
+
+                // Send a Server->Client packet ItemList to this L2PcINstance to update left hand equipement
+                ItemList il = new ItemList(this, false);
+                sendPacket(il);
+            }
+        }
+        else
+        {
+            // Get the L2ItemInstance of arrows equiped in left hand
+            _boltItem = getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+        }
+
+        return _boltItem != null;
+    }
 	/**
 	 * Disarm the player's weapon and shield.<BR><BR>
 	 */
Index: java/net/sf/l2j/gameserver/model/L2Character.java
===================================================================
--- java/net/sf/l2j/gameserver/model/L2Character.java	(revision 2917)
+++ java/net/sf/l2j/gameserver/model/L2Character.java	(working copy)
@@ -35,7 +35,6 @@
 import net.sf.l2j.Config;
 import net.sf.l2j.gameserver.GameTimeController;
 import net.sf.l2j.gameserver.GeoData;
-import net.sf.l2j.gameserver.Olympiad;
 import net.sf.l2j.gameserver.ThreadPoolManager;
 import net.sf.l2j.gameserver.ai.CtrlEvent;
 import net.sf.l2j.gameserver.ai.CtrlIntention;
@@ -77,15 +76,12 @@
 import net.sf.l2j.gameserver.serverpackets.ChangeWaitType;
 import net.sf.l2j.gameserver.serverpackets.CharInfo;
 import net.sf.l2j.gameserver.serverpackets.EtcStatusUpdate;
-import net.sf.l2j.gameserver.serverpackets.MoveToLocation;
-import net.sf.l2j.gameserver.serverpackets.ExOlympiadSpelledInfo;
 import net.sf.l2j.gameserver.serverpackets.L2GameServerPacket;
-import net.sf.l2j.gameserver.serverpackets.AbnormalStatusUpdate;
 import net.sf.l2j.gameserver.serverpackets.MagicSkillCanceld;
 import net.sf.l2j.gameserver.serverpackets.MagicSkillLaunched;
 import net.sf.l2j.gameserver.serverpackets.MagicSkillUse;
+import net.sf.l2j.gameserver.serverpackets.MoveToLocation;
 import net.sf.l2j.gameserver.serverpackets.NpcInfo;
-import net.sf.l2j.gameserver.serverpackets.PartySpelled;
 import net.sf.l2j.gameserver.serverpackets.PetInfo;
 import net.sf.l2j.gameserver.serverpackets.RelationChanged;
 import net.sf.l2j.gameserver.serverpackets.Revive;
@@ -547,6 +543,7 @@
 	 * <B><U> Actions</U> :</B><BR><BR>
 	 * <li>Get the active weapon (always equiped in the right hand) </li><BR><BR>
 	 * <li>If weapon is a bow, check for arrows, MP and bow re-use delay (if necessary, equip the L2PcInstance with arrows in left hand)</li>
+     * <li>If weapon is a crossbow, check for bolts and crossbow re-use delay (if necessary, equip the L2PcInstance with bolts in left hand)</li>
 	 * <li>If weapon is a bow, consume MP and set the new period of bow non re-use </li><BR><BR>
 	 * <li>Get the Attack Speed of the L2Character (delay (in milliseconds) before next attack) </li>
 	 * <li>Select the type of attack to start (Simple, Bow, Pole or Dual) and verify if SoulShot are charged then start calculation</li>
@@ -686,10 +683,52 @@
 					return;
 				}
 			}
-			else if (this instanceof L2NpcInstance)
-			{
-				if (_disableBowAttackEndTime > GameTimeController.getGameTicks())
-				    return;
+        }
+		// Check for a crossbow
+		if ((weaponItem != null && weaponItem.getItemType() == L2WeaponType.CROSSBOW))
+		{
+		    //Check for bolts
+		    if (this instanceof L2PcInstance)
+		    {
+		        // Checking if target has moved to peace zone - only for player-crossbow attacks at the moment
+		        // Other melee is checked in movement code and for offensive spells a check is done every time
+		        if (target.isInsidePeaceZone((L2PcInstance)this))
+		        {
+		            getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
+		            sendPacket(new ActionFailed());
+		            return;
+		        }
+
+		        // Verify if the crossbow can be use
+		        if (_disableCrossBowAttackEndTime <= GameTimeController.getGameTicks())
+		        {
+		            // Set the period of bow non re-use
+		            _disableCrossBowAttackEndTime = 5 * GameTimeController.TICKS_PER_SECOND + GameTimeController.getGameTicks();
+		        }
+		        else
+		        {
+		            // Cancel the action because the crossbow can't be re-use at this moment
+		            ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), 1000);
+
+		            sendPacket(new ActionFailed());
+		            return;
+		        }
+
+		        // Equip bolts needed in left hand and send a Server->Client packet ItemList to the L2PcINstance then return True
+		        if (!checkAndEquipBolts())
+		        {
+		            // Cancel the action because the L2PcInstance have no arrow
+		            getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
+
+		            sendPacket(new ActionFailed());
+		            sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_BOLTS));
+		            return;
+		        }
+		    }
+		    else if (this instanceof L2NpcInstance)
+		    {
+		        if (_disableCrossBowAttackEndTime > GameTimeController.getGameTicks())
+		            return;
 			}
 		}
 
@@ -743,6 +782,8 @@
 			hitted = doAttackHitSimple(attack, target, timeToHit);
 		else if (weaponItem.getItemType() == L2WeaponType.BOW)
 			hitted = doAttackHitByBow(attack, target, timeAtk, reuse);
+        else if (weaponItem.getItemType() == L2WeaponType.CROSSBOW)
+            hitted = doAttackHitByCrossBow(attack, target, timeAtk, reuse);
 		else if (weaponItem.getItemType() == L2WeaponType.POLE)
 			hitted = doAttackHitByPole(attack, timeToHit);
 		else if (isUsingDualWeapon())
@@ -878,6 +919,78 @@
 		return !miss1;
 	}
 
+    /**
+     * Launch a CrossBow attack.<BR><BR>
+     *
+     * <B><U> Actions</U> :</B><BR><BR>
+     * <li>Calculate if hit is missed or not </li>
+     * <li>Consumme bolts </li>
+     * <li>If hit isn't missed, calculate if shield defense is efficient </li>
+     * <li>If hit isn't missed, calculate if hit is critical </li>
+     * <li>If hit isn't missed, calculate physical damages </li>
+     * <li>If the L2Character is a L2PcInstance, Send a Server->Client packet SetupGauge </li>
+     * <li>Create a new hit task with Medium priority</li>
+     * <li>Calculate and set the disable delay of the crossbow in function of the Attack Speed</li>
+     * <li>Add this hit to the Server-Client packet Attack </li><BR><BR>
+     *
+     * @param attack Server->Client packet Attack in which the hit will be added
+     * @param target The L2Character targeted
+     * @param sAtk The Attack Speed of the attacker
+     *
+     * @return True if the hit isn't missed
+     *
+     */
+    private boolean doAttackHitByCrossBow(Attack attack, L2Character target, int sAtk, int reuse)
+    {
+        int damage1 = 0;
+        boolean shld1 = false;
+        boolean crit1 = false;
+
+        // Calculate if hit is missed or not
+        boolean miss1 = Formulas.getInstance().calcHitMiss(this, target);
+
+        // Consumme arrows
+        reduceBoltCount();
+
+        _move = null;
+
+        // Check if hit isn't missed
+        if (!miss1)
+        {
+            // Calculate if shield defense is efficient
+            shld1 = Formulas.getInstance().calcShldUse(this, target);
+
+            // Calculate if hit is critical
+            crit1 = Formulas.getInstance().calcCrit(getStat().getCriticalHit(target, null));
+
+            // Calculate physical damages
+            damage1 = (int)Formulas.getInstance().calcPhysDam(this, target, null, shld1, crit1, false, attack.soulshot);
+        }
+
+        // Check if the L2Character is a L2PcInstance
+        if (this instanceof L2PcInstance)
+        {
+            // Send a system message
+            sendPacket(new SystemMessage(SystemMessageId.CROSSBOW_PREPARING_TO_FIRE));
+
+            // Send a Server->Client packet SetupGauge
+            SetupGauge sg = new SetupGauge(SetupGauge.RED, sAtk+reuse);
+            sendPacket(sg);
+        }
+
+        // Create a new hit task with Medium priority
+        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();
+
+        // Add this hit to the Server-Client packet Attack
+        attack.addHit(target, damage1, miss1, crit1, shld1);
+
+        // Return true if hit isn't missed
+        return !miss1;
+    }
+
 	/**
 	 * Launch a Dual attack.<BR><BR>
 	 *
@@ -3022,6 +3135,7 @@
 	private int     _attackEndTime;
 	private int     _attacking;
 	private int     _disableBowAttackEndTime;
+    private int     _disableCrossBowAttackEndTime;
 
 
 	/** Table of calculators containing all standard NPC calculator (ex : ACCURACY_COMBAT, EVASION_RATE */
@@ -4481,6 +4595,18 @@
 		return true;
 	}
 
+    /**
+     * Retun True if bolts are available.<BR><BR>
+     *
+     * <B><U> Overriden in </U> :</B><BR><BR>
+     * <li> L2PcInstance</li><BR><BR>
+     *
+     */
+    protected boolean checkAndEquipBolts()
+    {
+        return true;
+    }
+
 	/**
 	 * Add Exp and Sp to the L2Character.<BR><BR>
 	 *
@@ -4808,6 +4934,11 @@
 		// default is to do nothin
 	}
 
+    protected void reduceBoltCount()
+    {
+        // default is to do nothin
+    }
+
 	/**
 	 * Manage Forced attack (shift + select target).<BR><BR>
 	 *
Index: java/net/sf/l2j/gameserver/model/Inventory.java
===================================================================
--- java/net/sf/l2j/gameserver/model/Inventory.java	(revision 2917)
+++ java/net/sf/l2j/gameserver/model/Inventory.java	(working copy)
@@ -169,6 +169,33 @@
     	}
     }
 
+    final class CrossBowListener implements PaperdollListener
+    {
+        public void notifyUnequiped(int slot, L2ItemInstance item)
+        {
+            if (slot != PAPERDOLL_LRHAND)
+                return;
+            if (Config.ASSERT) assert null == getPaperdollItem(PAPERDOLL_LRHAND);
+            if (item.getItemType() == L2WeaponType.CROSSBOW)
+            {
+                L2ItemInstance bolts = getPaperdollItem(PAPERDOLL_LHAND);
+                if (bolts != null)
+                    setPaperdollItem(PAPERDOLL_LHAND, null);
+            }
+        }
+        public void notifyEquiped(int slot, L2ItemInstance item)
+        {
+            if (slot != PAPERDOLL_LRHAND)
+                return;
+            if (Config.ASSERT) assert item == getPaperdollItem(PAPERDOLL_LRHAND);
+            if (item.getItemType() == L2WeaponType.CROSSBOW)
+            {
+                L2ItemInstance bolts = findBoltForCrossBow(item.getItem());
+                if (bolts != null)
+                    setPaperdollItem(PAPERDOLL_LHAND, bolts);
+            }
+        }  
+    }
     final class BowListener implements PaperdollListener
     {
     	public void notifyUnequiped(int slot, L2ItemInstance item)
@@ -501,6 +528,7 @@
 		_paperdoll = new L2ItemInstance[25];
 		_paperdollListeners = new FastList<PaperdollListener>();
 		addPaperdollListener(new ArmorSetListener());
+        addPaperdollListener(new CrossBowListener());
 		addPaperdollListener(new BowListener());
 		addPaperdollListener(new ItemPassiveSkillsListener());
 		addPaperdollListener(new StatsListener());
@@ -1190,6 +1218,29 @@
 		return getItemByItemId(arrowsId);
 	}
 
+    /**
+     * Return the L2ItemInstance of the bolts needed for this crossbow.<BR><BR>
+     * @param crossbow : L2Item designating the crossbow
+     * @return L2ItemInstance pointing out bolts for crossbow
+     */
+    public L2ItemInstance findBoltForCrossBow(L2Item crossbow)
+    {
+        int boltsId = 0;
+        
+        switch (crossbow.getCrystalType())
+        {
+        default: 
+        case L2Item.CRYSTAL_NONE:   boltsId = 9632; break; // Wooden Bolt
+        case L2Item.CRYSTAL_D:      boltsId = 9633; break; // Bone Bolt
+        case L2Item.CRYSTAL_C:      boltsId = 9634; break; // Steel Bolt
+        case L2Item.CRYSTAL_B:      boltsId = 9635; break; // Silver Bolt
+        case L2Item.CRYSTAL_A:      boltsId = 9636; break; // Mithril Bolt
+        case L2Item.CRYSTAL_S:      boltsId = 9637; break; // Shining Bolt
+        }
+
+        // Get the L2ItemInstance corresponding to the item identifier and return it
+        return getItemByItemId(boltsId);
+    }
 	/**
 	 * Get back items in inventory from database
 	 */
Index: java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminEnchant.java
===================================================================
--- java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminEnchant.java	(revision 2917)
+++ java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminEnchant.java	(working copy)
@@ -157,7 +157,7 @@
             itemInstance = parmorInstance;
         } else
         {
-            // for bows and double handed weapons
+            // for bows/crossbows and double handed weapons
             parmorInstance = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LRHAND);
             if (parmorInstance != null && parmorInstance.getLocationSlot() == Inventory.PAPERDOLL_LRHAND)
                 itemInstance = parmorInstance;