Browse Source

Drops code clean up.

Added docs for drop rates configs.
Fixed chance multiplier for old drop behavior in grouped drop item.
NosBit 10 years ago
parent
commit
c6a0e0b5c9

+ 17 - 1
L2J_Server/dist/game/config/Rates.properties

@@ -6,15 +6,25 @@
 # Please take extreme caution when changing anything. Also please understand what you are changing before you do so on a live server.
 
 # ---------------------------------------------------------------------------
-# Standard Settings (Retail value = 1)
+# Item Rates
 # ---------------------------------------------------------------------------
+# Warning: to achieve old l2j behavior before drops rework you need to enable OldDropBehavior in L2JMods.properties
+# and increase only chance multipliers! Remember if you increase both chance and amount you will have higher rates than expected
+# Example: if amount multiplier is 5 and chance multiplier is 5 you will end up with 5*5 = 25 drop rates so be careful!
+
 
+# Multiplies the amount of items dropped from monster on ground when it dies.
 DeathDropAmountMultiplier = 1
+# Multiplies the amount of items looted from monster when a skill like Sweeper(Spoil) is used.
 CorpseDropAmountMultiplier = 1
+# Multiplies the amount of items dropped from monster on ground when it dies.
 HerbDropAmountMultiplier = 1
 
+# Multiplies the chance of items that can be dropped from monster on ground when it dies.
 DeathDropChanceMultiplier = 1
+# Multiplies the chance of items that can be looted from monster when a skill like Sweeper(Spoil) is used.
 CorpseDropChanceMultiplier = 1
+# Multiplies the chance of items that can be dropped from monster on ground when it dies.
 HerbDropChanceMultiplier = 1
 
 # List of items affected by custom drop rate by id, used now for Adena rate too.
@@ -25,6 +35,12 @@ HerbDropChanceMultiplier = 1
 DropAmountMultiplierByItemId = 57,1
 DropChanceMultiplierByItemId = 57,1
 
+
+# ---------------------------------------------------------------------------
+# Standard Settings (Retail value = 1)
+# ---------------------------------------------------------------------------
+
+
 # Experience multiplier
 RateXp = 1
 # Skill points multiplier

+ 19 - 23
L2J_Server/java/com/l2jserver/gameserver/model/actor/L2Attackable.java

@@ -19,9 +19,12 @@
 package com.l2jserver.gameserver.model.actor;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.Level;
 
 import com.l2jserver.Config;
@@ -86,10 +89,10 @@ public class L2Attackable extends L2Npc
 	private boolean _seeded = false;
 	private L2Seed _seed = null;
 	private int _seederObjId = 0;
-	private ItemHolder _harvestItem;
+	private final AtomicReference<ItemHolder> _harvestItem = new AtomicReference<>();
 	// Spoil
 	private int _spoilerObjectId;
-	private ItemHolder[] _sweepItems;
+	private final AtomicReference<Collection<ItemHolder>> _sweepItems = new AtomicReference<>();
 	// Over-hit
 	private boolean _overhit;
 	private double _overhitDamage;
@@ -983,14 +986,10 @@ public class L2Attackable extends L2Npc
 		
 		if (isSpoiled())
 		{
-			List<ItemHolder> sweepItems = npcTemplate.calculateDrops(DropListScope.CORPSE, this, player);
-			if ((sweepItems != null) && !sweepItems.isEmpty())
-			{
-				_sweepItems = sweepItems.toArray(new ItemHolder[sweepItems.size()]);
-			}
+			_sweepItems.set(npcTemplate.calculateDrops(DropListScope.CORPSE, this, player));
 		}
 		
-		List<ItemHolder> deathItems = npcTemplate.calculateDrops(DropListScope.DEATH, this, player);
+		Collection<ItemHolder> deathItems = npcTemplate.calculateDrops(DropListScope.DEATH, this, player);
 		if (deathItems != null)
 		{
 			for (ItemHolder drop : deathItems)
@@ -1138,7 +1137,7 @@ public class L2Attackable extends L2Npc
 	@Override
 	public boolean isSweepActive()
 	{
-		return _sweepItems != null;
+		return _sweepItems.get() != null;
 	}
 	
 	/**
@@ -1146,10 +1145,11 @@ public class L2Attackable extends L2Npc
 	 */
 	public List<L2Item> getSpoilLootItems()
 	{
-		final List<L2Item> lootItems = new ArrayList<>();
-		if (isSweepActive())
+		final Collection<ItemHolder> sweepItems = _sweepItems.get();
+		final List<L2Item> lootItems = new LinkedList<>();
+		if (sweepItems != null)
 		{
-			for (ItemHolder item : _sweepItems)
+			for (ItemHolder item : sweepItems)
 			{
 				lootItems.add(ItemTable.getInstance().getTemplate(item.getId()));
 			}
@@ -1160,21 +1160,17 @@ public class L2Attackable extends L2Npc
 	/**
 	 * @return table containing all L2ItemInstance that can be spoiled.
 	 */
-	public synchronized ItemHolder[] takeSweep()
+	public Collection<ItemHolder> takeSweep()
 	{
-		ItemHolder[] sweep = _sweepItems;
-		_sweepItems = null;
-		return sweep;
+		return _sweepItems.getAndSet(null);
 	}
 	
 	/**
 	 * @return table containing all L2ItemInstance that can be harvested.
 	 */
-	public synchronized ItemHolder takeHarvest()
+	public ItemHolder takeHarvest()
 	{
-		ItemHolder harvest = _harvestItem;
-		_harvestItem = null;
-		return harvest;
+		return _harvestItem.getAndSet(null);
 	}
 	
 	/**
@@ -1418,7 +1414,7 @@ public class L2Attackable extends L2Npc
 		// Clear all aggro char from list
 		clearAggroList();
 		// Clear Harvester reward
-		_harvestItem = null;
+		_harvestItem.set(null);
 		// Clear mod Seeded stat
 		_seeded = false;
 		_seed = null;
@@ -1426,7 +1422,7 @@ public class L2Attackable extends L2Npc
 		// Clear overhit value
 		overhitEnabled(false);
 		
-		_sweepItems = null;
+		_sweepItems.set(null);
 		resetAbsorbList();
 		
 		setWalking();
@@ -1516,7 +1512,7 @@ public class L2Attackable extends L2Npc
 			{
 				count += diff;
 			}
-			_harvestItem = new ItemHolder(_seed.getCropId(), count * Config.RATE_DROP_MANOR);
+			_harvestItem.set(new ItemHolder(_seed.getCropId(), count * Config.RATE_DROP_MANOR));
 		}
 	}
 	

+ 6 - 4
L2J_Server/java/com/l2jserver/gameserver/model/actor/templates/L2NpcTemplate.java

@@ -19,7 +19,9 @@
 package com.l2jserver.gameserver.model.actor.templates;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -545,7 +547,7 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		return dropLists != null ? dropLists.get(dropListScope) : null;
 	}
 	
-	public List<ItemHolder> calculateDrops(DropListScope dropListScope, L2Character victim, L2Character killer)
+	public Collection<ItemHolder> calculateDrops(DropListScope dropListScope, L2Character victim, L2Character killer)
 	{
 		List<IDropItem> dropList = getDropList(dropListScope);
 		if (dropList == null)
@@ -553,10 +555,10 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 			return null;
 		}
 		
-		List<ItemHolder> calculatedDrops = null;
+		Collection<ItemHolder> calculatedDrops = null;
 		for (IDropItem dropItem : dropList)
 		{
-			List<ItemHolder> drops = dropItem.calculateDrops(victim, killer);
+			final Collection<ItemHolder> drops = dropItem.calculateDrops(victim, killer);
 			if ((drops == null) || drops.isEmpty())
 			{
 				continue;
@@ -564,7 +566,7 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 			
 			if (calculatedDrops == null)
 			{
-				calculatedDrops = new ArrayList<>(drops.size());
+				calculatedDrops = new LinkedList<>();
 			}
 			
 			calculatedDrops.addAll(drops);

+ 19 - 45
L2J_Server/java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java

@@ -19,7 +19,7 @@
 package com.l2jserver.gameserver.model.drops;
 
 import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.datatables.ItemTable;
@@ -187,13 +187,10 @@ public class GeneralDropItem implements IDropItem
 			}
 		}
 		
-		// global champions chance multiplier, there is no such option yet
-		// @formatter:off
-		/*if (victim.isChampion())
+		if (victim.isChampion())
 		{
-			multiplier *= getItemId() != Inventory.ADENA_ID ? Config.L2JMOD_CHAMPION_REWARDS_CHANCE : Config.L2JMOD_CHAMPION_ADENAS_REWARDS_CHANCE;
-		}*/
-		// @formatter:on
+			multiplier *= Config.L2JMOD_CHAMPION_REWARDS;
+		}
 		
 		return (getChance() * multiplier);
 	}
@@ -203,7 +200,7 @@ public class GeneralDropItem implements IDropItem
 	 * @see com.l2jserver.gameserver.model.drop.IDropItem#calculateDrops(com.l2jserver.gameserver.model.actor.L2Character, com.l2jserver.gameserver.model.actor.L2Character)
 	 */
 	@Override
-	public List<ItemHolder> calculateDrops(L2Character victim, L2Character killer)
+	public Collection<ItemHolder> calculateDrops(L2Character victim, L2Character killer)
 	{
 		final int levelDifference = victim.getLevel() - killer.getLevel();
 		final double levelGapChanceToDrop;
@@ -222,48 +219,25 @@ public class GeneralDropItem implements IDropItem
 			return null;
 		}
 		
-		final List<ItemHolder> items = new ArrayList<>(1);
-		
-		if (Config.L2JMOD_OLD_DROP_BEHAVIOR)
+		final double chance = getChance(victim, killer);
+		int successes;
+		if (!Config.L2JMOD_OLD_DROP_BEHAVIOR)
 		{
-			double chance = getChance(victim, killer);
-			if (Config.L2JMOD_CHAMPION_ENABLE && victim.isChampion() && (getItemId() != Inventory.ADENA_ID))
-			{
-				chance *= Config.L2JMOD_CHAMPION_REWARDS;
-			}
-			
-			long amount = 0;
-			
-			if (chance > 100)
-			{
-				int chanceOveflow = (int) (chance / 100);
-				chance = chance % 100;
-				while (chanceOveflow > 0)
-				{
-					amount += Rnd.get(getMin(victim, killer), getMax(victim, killer));
-					chanceOveflow--;
-				}
-			}
-			
-			if (chance > (Rnd.nextDouble() * 100))
-			{
-				amount += Rnd.get(getMin(victim, killer), getMax(victim, killer));
-			}
-			
-			if (amount > 0)
-			{
-				items.add(new ItemHolder(getItemId(), amount));
-			}
+			successes = chance > (Rnd.nextDouble() * 100) ? 1 : 0;
 		}
 		else
 		{
-			if (getChance(victim, killer) > (Rnd.nextDouble() * 100))
-			{
-				final long amount = Rnd.get(getMin(victim, killer), getMax(victim, killer));
-				items.add(new ItemHolder(getItemId(), amount));
-			}
+			successes = (int) (chance / 100);
+			successes += (chance % 100) > (Rnd.nextDouble() * 100) ? 1 : 0;
+		}
+		
+		if (successes > 0)
+		{
+			final Collection<ItemHolder> items = new ArrayList<>(1);
+			items.add(new ItemHolder(getItemId(), Rnd.get(getMin(victim, killer), getMax(victim, killer)) * successes));
+			return items;
 		}
 		
-		return items;
+		return null;
 	}
 }

+ 24 - 55
L2J_Server/java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java

@@ -19,6 +19,7 @@
 package com.l2jserver.gameserver.model.drops;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -104,9 +105,9 @@ public class GroupedGeneralDropItem implements IDropItem
 	 * @see com.l2jserver.gameserver.model.drop.IDropItem#calculateDrops(com.l2jserver.gameserver.model.actor.L2Character, com.l2jserver.gameserver.model.actor.L2Character)
 	 */
 	@Override
-	public List<ItemHolder> calculateDrops(L2Character victim, L2Character killer)
+	public Collection<ItemHolder> calculateDrops(L2Character victim, L2Character killer)
 	{
-		int levelDifference = victim.getLevel() - killer.getLevel();
+		final int levelDifference = victim.getLevel() - killer.getLevel();
 		double chanceModifier;
 		if (victim instanceof L2RaidBossInstance)
 		{
@@ -124,61 +125,29 @@ public class GroupedGeneralDropItem implements IDropItem
 			}
 		}
 		
-		if ((getChance(victim, killer) * chanceModifier) > (Rnd.nextDouble() * 100))
+		final double chance = getChance(victim, killer) * chanceModifier;
+		int successes;
+		if (!Config.L2JMOD_OLD_DROP_BEHAVIOR)
 		{
-			final List<ItemHolder> items = new ArrayList<>(1);
-			long amount = 0;
-			double totalChance = 0;
-			double random = (Rnd.nextDouble() * 100);
-			double chance = 0;
-			
-			if (Config.L2JMOD_OLD_DROP_BEHAVIOR)
-			{
-				for (GeneralDropItem item : getItems())
-				{
-					// Grouped item chance rates should not be modified.
-					totalChance += item.getChance();
-					
-					if (totalChance > 100)
-					{
-						int chanceOverflow = (int) (totalChance / 100);
-						chance = totalChance % 100;
-						while (chanceOverflow > 0)
-						{
-							amount += Rnd.get(item.getMin(victim, killer), item.getMax(victim, killer));
-							chanceOverflow--;
-						}
-					}
-					else
-					{
-						chance = totalChance;
-					}
-					
-					if (chance > random)
-					{
-						amount += Rnd.get(item.getMin(victim, killer), item.getMax(victim, killer));
-					}
-					
-					if (amount > 0)
-					{
-						items.add(new ItemHolder(item.getItemId(), amount));
-						return items;
-					}
-				}
-			}
-			else
+			successes = chance > (Rnd.nextDouble() * 100) ? 1 : 0;
+		}
+		else
+		{
+			successes = (int) (chance / 100);
+			successes += (chance % 100) > (Rnd.nextDouble() * 100) ? 1 : 0;
+		}
+		
+		double totalChance = 0;
+		final double random = (Rnd.nextDouble() * 100);
+		for (GeneralDropItem item : getItems())
+		{
+			// Grouped item chance rates should not be modified.
+			totalChance += item.getChance();
+			if (totalChance > random)
 			{
-				for (GeneralDropItem item : getItems())
-				{
-					// Grouped item chance rates should not be modified.
-					totalChance += item.getChance();
-					if (totalChance > random)
-					{
-						amount = Rnd.get(item.getMin(victim, killer), item.getMax(victim, killer));
-						items.add(new ItemHolder(item.getItemId(), amount));
-						return items;
-					}
-				}
+				final Collection<ItemHolder> items = new ArrayList<>(1);
+				items.add(new ItemHolder(item.getItemId(), Rnd.get(item.getMin(victim, killer), item.getMax(victim, killer)) * successes));
+				return items;
 			}
 		}
 		

+ 3 - 3
L2J_Server/java/com/l2jserver/gameserver/model/drops/IDropItem.java

@@ -18,7 +18,7 @@
  */
 package com.l2jserver.gameserver.model.drops;
 
-import java.util.List;
+import java.util.Collection;
 
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
@@ -32,7 +32,7 @@ public interface IDropItem
 	 * Calculates drops of this drop item.
 	 * @param victim the victim
 	 * @param killer the killer
-	 * @return {@code null} or empty list if there are no drops, a list containing all items to drop otherwise
+	 * @return {@code null} or empty collection if there are no drops, a collection containing all items to drop otherwise
 	 */
-	public List<ItemHolder> calculateDrops(L2Character victim, L2Character killer);
+	public Collection<ItemHolder> calculateDrops(L2Character victim, L2Character killer);
 }