All pastes #839278 Raw Edit

Stuff

public text v1 · immutable
#839278 ·published 2007-12-30 23:08 UTC
rendered paste body
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/L2Character.java
===================================================================
--- java/net/sf/l2j/gameserver/model/L2Character.java	(revision 2917)
+++ java/net/sf/l2j/gameserver/model/L2Character.java	(working copy)
@@ -686,6 +686,47 @@
 					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 (_disableBowAttackEndTime > GameTimeController.getGameTicks())
@@ -743,6 +784,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 +921,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 +3137,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 +4597,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 +4936,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
 	 */