Pārlūkot izejas kodu

BETA: Item drop related changes:
* Minor fixes in `L2Attackable` logic to avoid `ItemHolder` object creation on item drops.
* Added methods overloads, now there are two methods one with primitives and one with `ItemHolder` that just pass the parameters to the former method.
* Keep in mind this design:
* Having method overload with different logic is discouraged.
* Having method overload logic with non primitive parameters is discouraged, since it will lead to useless object creation in some cases.
* Having too much method overloads is discouraged.
* Added a new method (and corresponding method overload) to `Quest` class to allow NPCs to drop items by script without being `L2Attackable`.
* Added/fixed multiple missing !JavaDocs.

Zoey76 11 gadi atpakaļ
vecāks
revīzija
4cc55e05fd

+ 27 - 19
L2J_Server_BETA/java/com/l2jserver/gameserver/model/L2Party.java

@@ -636,47 +636,55 @@ public class L2Party extends AbstractPlayerGroup
 	}
 	
 	/**
-	 * distribute item(s) to party members
-	 * @param player
-	 * @param item
-	 * @param spoil
-	 * @param target
+	 * Distributes item loot between party members.
+	 * @param player the reference player
+	 * @param itemId the item ID
+	 * @param itemCount the item count
+	 * @param spoil {@code true} if it's spoil loot
+	 * @param target the NPC target
 	 */
-	public void distributeItem(L2PcInstance player, ItemHolder item, boolean spoil, L2Attackable target)
+	public void distributeItem(L2PcInstance player, int itemId, long itemCount, boolean spoil, L2Attackable target)
 	{
-		if (item == null)
+		if (itemId == PcInventory.ADENA_ID)
 		{
+			distributeAdena(player, itemCount, target);
 			return;
 		}
 		
-		if (item.getId() == PcInventory.ADENA_ID)
-		{
-			distributeAdena(player, item.getCount(), target);
-			return;
-		}
+		L2PcInstance looter = getActualLooter(player, itemId, spoil, target);
 		
-		L2PcInstance looter = getActualLooter(player, item.getId(), spoil, target);
-		
-		looter.addItem(spoil ? "Sweeper" : "Party", item, player, true);
+		looter.addItem(spoil ? "Sweeper" : "Party", itemId, itemCount, player, true);
 		
 		// Send messages to other party members about reward
-		if (item.getCount() > 1)
+		if (itemCount > 1)
 		{
 			SystemMessage msg = spoil ? SystemMessage.getSystemMessage(SystemMessageId.C1_SWEEPED_UP_S3_S2) : SystemMessage.getSystemMessage(SystemMessageId.C1_OBTAINED_S3_S2);
 			msg.addString(looter.getName());
-			msg.addItemName(item.getId());
-			msg.addItemNumber(item.getCount());
+			msg.addItemName(itemId);
+			msg.addItemNumber(itemCount);
 			broadcastToPartyMembers(looter, msg);
 		}
 		else
 		{
 			SystemMessage msg = spoil ? SystemMessage.getSystemMessage(SystemMessageId.C1_SWEEPED_UP_S2) : SystemMessage.getSystemMessage(SystemMessageId.C1_OBTAINED_S2);
 			msg.addString(looter.getName());
-			msg.addItemName(item.getId());
+			msg.addItemName(itemId);
 			broadcastToPartyMembers(looter, msg);
 		}
 	}
 	
+	/**
+	 * Method overload for {@link L2Party#distributeItem(L2PcInstance, int, long, boolean, L2Attackable)}
+	 * @param player the reference player
+	 * @param item the item holder
+	 * @param spoil {@code true} if it's spoil loot
+	 * @param target the NPC target
+	 */
+	public void distributeItem(L2PcInstance player, ItemHolder item, boolean spoil, L2Attackable target)
+	{
+		distributeItem(player, item.getId(), item.getCount(), spoil, target);
+	}
+	
 	/**
 	 * distribute adena to party members
 	 * @param player

+ 26 - 20
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Attackable.java

@@ -1572,8 +1572,7 @@ public class L2Attackable extends L2Npc
 					// Broadcast message if RaidBoss was defeated
 					if (isRaid() && !isRaidMinion())
 					{
-						SystemMessage sm;
-						sm = SystemMessage.getSystemMessage(SystemMessageId.C1_DIED_DROPPED_S3_S2);
+						final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_DIED_DROPPED_S3_S2);
 						sm.addCharName(this);
 						sm.addItemName(item.getId());
 						sm.addItemNumber(item.getCount());
@@ -1682,47 +1681,48 @@ public class L2Attackable extends L2Npc
 		{
 			if (Rnd.get(L2DropData.MAX_CHANCE) < drop.getEventDrop().getDropChance())
 			{
-				final ItemHolder rewardItem = new ItemHolder(drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)], Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount()));
-				
+				final int itemId = drop.getEventDrop().getItemIdList()[Rnd.get(drop.getEventDrop().getItemIdList().length)];
+				final long itemCount = Rnd.get(drop.getEventDrop().getMinCount(), drop.getEventDrop().getMaxCount());
 				if (Config.AUTO_LOOT || isFlying())
 				{
-					player.doAutoLoot(this, rewardItem); // Give the item(s) to the L2PcInstance that has killed the L2Attackable
+					player.doAutoLoot(this, itemId, itemCount); // Give the item(s) to the L2PcInstance that has killed the L2Attackable
 				}
 				else
 				{
-					dropItem(player, rewardItem); // drop the item on the ground
+					dropItem(player, itemId, itemCount); // drop the item on the ground
 				}
 			}
 		}
 	}
 	
 	/**
-	 * Drop reward item.
-	 * @param mainDamageDealer
-	 * @param item
-	 * @return
+	 * Drops an item.
+	 * @param player the last attacker or main damage dealer
+	 * @param itemId the item ID
+	 * @param itemCount the item count
+	 * @return the dropped item
 	 */
-	public L2ItemInstance dropItem(L2PcInstance mainDamageDealer, ItemHolder item)
+	public L2ItemInstance dropItem(L2PcInstance player, int itemId, long itemCount)
 	{
 		int randDropLim = 70;
 		
 		L2ItemInstance ditem = null;
-		for (int i = 0; i < item.getCount(); i++)
+		for (int i = 0; i < itemCount; i++)
 		{
 			// Randomize drop position
 			int newX = (getX() + Rnd.get((randDropLim * 2) + 1)) - randDropLim;
 			int newY = (getY() + Rnd.get((randDropLim * 2) + 1)) - randDropLim;
-			int newZ = Math.max(getZ(), mainDamageDealer.getZ()) + 20; // TODO: temp hack, do something nicer when we have geodatas
+			int newZ = Math.max(getZ(), player.getZ()) + 20; // TODO: temp hack, do something nicer when we have geodatas
 			
-			if (ItemTable.getInstance().getTemplate(item.getId()) != null)
+			if (ItemTable.getInstance().getTemplate(itemId) != null)
 			{
 				// Init the dropped L2ItemInstance and add it in the world as a visible object at the position where mob was last
-				ditem = ItemTable.getInstance().createItem("Loot", item.getId(), item.getCount(), mainDamageDealer, this);
-				ditem.getDropProtection().protect(mainDamageDealer);
+				ditem = ItemTable.getInstance().createItem("Loot", itemId, itemCount, player, this);
+				ditem.getDropProtection().protect(player);
 				ditem.dropMe(this, newX, newY, newZ);
 				
 				// Add drop to auto destroy item task
-				if (!Config.LIST_PROTECTED_ITEMS.contains(item.getId()))
+				if (!Config.LIST_PROTECTED_ITEMS.contains(itemId))
 				{
 					if (((Config.AUTODESTROY_ITEM_AFTER > 0) && (ditem.getItemType() != L2EtcItemType.HERB)) || ((Config.HERB_AUTO_DESTROY_TIME > 0) && (ditem.getItemType() == L2EtcItemType.HERB)))
 					{
@@ -1739,15 +1739,21 @@ public class L2Attackable extends L2Npc
 			}
 			else
 			{
-				_log.log(Level.SEVERE, "Item doesn't exist so cannot be dropped. Item ID: " + item.getId());
+				_log.log(Level.SEVERE, "Item doesn't exist so cannot be dropped. Item ID: " + itemId);
 			}
 		}
 		return ditem;
 	}
 	
-	public L2ItemInstance dropItem(L2PcInstance lastAttacker, int itemId, int itemCount)
+	/**
+	 * Method overload for {@link L2Attackable#dropItem(L2PcInstance, int, long)}
+	 * @param player the last attacker or main damage dealer
+	 * @param item the item holder
+	 * @return the dropped item
+	 */
+	public L2ItemInstance dropItem(L2PcInstance player, ItemHolder item)
 	{
-		return dropItem(lastAttacker, new ItemHolder(itemId, itemCount));
+		return dropItem(player, item.getId(), item.getCount());
 	}
 	
 	/**

+ 27 - 10
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -4712,27 +4712,44 @@ public final class L2PcInstance extends L2Playable
 	}
 	
 	/**
-	 * Manage AutoLoot Task. <B><U> Actions</U> :</B> <li>Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or YOU_PICKED_UP_S1_S2</li> <li>Add the Item to the L2PcInstance inventory</li> <li>Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new
-	 * slot) or ModifiedItem (increase amount)</li> <li>Send a Server->Client packet StatusUpdate to this L2PcInstance with current weight</li> <FONT COLOR=#FF0000><B> <U>Caution</U> : If a Party is in progress, distribute Items between party members</B></FONT>
-	 * @param target The L2ItemInstance dropped
-	 * @param item
+	 * Manages AutoLoot Task.<br>
+	 * <ul>
+	 * <li>Send a system message to the player.</li>
+	 * <li>Add the item to the player's inventory.</li>
+	 * <li>Send a Server->Client packet InventoryUpdate to this player with NewItem (use a new slot) or ModifiedItem (increase amount).</li>
+	 * <li>Send a Server->Client packet StatusUpdate to this player with current weight.</li>
+	 * </ul>
+	 * <font color=#FF0000><B><U>Caution</U>: If a party is in progress, distribute the items between the party members!</b></font>
+	 * @param target the NPC dropping the item
+	 * @param itemId the item ID
+	 * @param itemCount the item count
 	 */
-	public void doAutoLoot(L2Attackable target, ItemHolder item)
+	public void doAutoLoot(L2Attackable target, int itemId, long itemCount)
 	{
-		if (isInParty() && (ItemTable.getInstance().getTemplate(item.getId()).getItemType() != L2EtcItemType.HERB))
+		if (isInParty() && (ItemTable.getInstance().getTemplate(itemId).getItemType() != L2EtcItemType.HERB))
 		{
-			getParty().distributeItem(this, item, false, target);
+			getParty().distributeItem(this, itemId, itemCount, false, target);
 		}
-		else if (item.getId() == PcInventory.ADENA_ID)
+		else if (itemId == PcInventory.ADENA_ID)
 		{
-			addAdena("Loot", item.getCount(), target, true);
+			addAdena("Loot", itemCount, target, true);
 		}
 		else
 		{
-			addItem("Loot", item, target, true);
+			addItem("Loot", itemId, itemCount, target, true);
 		}
 	}
 	
+	/**
+	 * Method overload for {@link L2PcInstance#doAutoLoot(L2Attackable, int, long)}
+	 * @param target the NPC dropping the item
+	 * @param item the item holder
+	 */
+	public void doAutoLoot(L2Attackable target, ItemHolder item)
+	{
+		doAutoLoot(target, item.getId(), item.getCount());
+	}
+	
 	/**
 	 * Manage Pickup Task. <B><U> Actions</U> :</B> <li>Send a Server->Client packet StopMove to this L2PcInstance</li> <li>Remove the L2ItemInstance from the world and send server->client GetItem packets</li> <li>Send a System Message to the L2PcInstance : YOU_PICKED_UP_S1_ADENA or
 	 * YOU_PICKED_UP_S1_S2</li> <li>Add the Item to the L2PcInstance inventory</li> <li>Send a Server->Client packet InventoryUpdate to this L2PcInstance with NewItem (use a new slot) or ModifiedItem (increase amount)</li> <li>Send a Server->Client packet StatusUpdate to this L2PcInstance with

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

@@ -1777,9 +1777,9 @@ public final class L2ItemInstance extends L2Object
 		return itemLootShedule;
 	}
 	
-	public void setProtected(boolean is_protected)
+	public void setProtected(boolean isProtected)
 	{
-		_protected = is_protected;
+		_protected = isProtected;
 	}
 	
 	public boolean isProtected()

+ 54 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/quest/Quest.java

@@ -37,6 +37,7 @@ import java.util.logging.Logger;
 import com.l2jserver.Config;
 import com.l2jserver.L2DatabaseFactory;
 import com.l2jserver.gameserver.GameTimeController;
+import com.l2jserver.gameserver.ItemsAutoDestroy;
 import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.cache.HtmCache;
 import com.l2jserver.gameserver.datatables.DoorTable;
@@ -69,6 +70,7 @@ import com.l2jserver.gameserver.model.interfaces.IPositionable;
 import com.l2jserver.gameserver.model.itemcontainer.PcInventory;
 import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.items.type.L2EtcItemType;
 import com.l2jserver.gameserver.model.olympiad.CompetitionType;
 import com.l2jserver.gameserver.model.quest.AITasks.AggroRangeEnter;
 import com.l2jserver.gameserver.model.quest.AITasks.SeeCreature;
@@ -3523,6 +3525,58 @@ public class Quest extends ManagedScript implements IIdentifiable
 		return check;
 	}
 	
+	/**
+	 * Drops an item given an NPC.
+	 * @param npc the NPC dropping the item
+	 * @param itemId the item ID
+	 * @param itemCount the item count
+	 */
+	public void dropItem(L2Npc npc, int itemId, long itemCount)
+	{
+		for (int i = 0; i < itemCount; i++)
+		{
+			// Randomize drop position.
+			final int newX = (npc.getX() + Rnd.get((70 * 2) + 1)) - 70;
+			final int newY = (npc.getY() + Rnd.get((70 * 2) + 1)) - 70;
+			final int newZ = npc.getZ() + 20;
+			
+			if (ItemTable.getInstance().getTemplate(itemId) == null)
+			{
+				_log.log(Level.SEVERE, "Item doesn't exist so cannot be dropped. Item ID: " + itemId + " Quest: " + getName());
+				return;
+			}
+			
+			final L2ItemInstance item = ItemTable.getInstance().createItem("Loot", itemId, itemCount, null, null);
+			item.dropMe(npc, newX, newY, newZ);
+			
+			// Add drop to auto destroy item task.
+			if (!Config.LIST_PROTECTED_ITEMS.contains(itemId))
+			{
+				if (((Config.AUTODESTROY_ITEM_AFTER > 0) && (item.getItemType() != L2EtcItemType.HERB)) || ((Config.HERB_AUTO_DESTROY_TIME > 0) && (item.getItemType() == L2EtcItemType.HERB)))
+				{
+					ItemsAutoDestroy.getInstance().addItem(item);
+				}
+			}
+			item.setProtected(false);
+			
+			// If stackable, end loop as entire count is included in 1 instance of item.
+			if (item.isStackable() || !Config.MULTIPLE_ITEM_DROP)
+			{
+				break;
+			}
+		}
+	}
+	
+	/**
+	 * Method overload for {@link Quest#dropItem(L2Npc, int, long)}
+	 * @param npc the NPC dropping the item
+	 * @param item the item holder
+	 */
+	public void dropItem(L2Npc npc, ItemHolder item)
+	{
+		dropItem(npc, item.getId(), item.getCount());
+	}
+	
 	/**
 	 * Remove all quest items associated with this quest from the specified player's inventory.
 	 * @param player the player whose quest items to remove