Преглед на файлове

Drops code clean up.

Added docs for drop rates configs.
Fixed chance multiplier for old drop behavior in grouped drop item.
NosBit преди 10 години
родител
ревизия
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);
 }