| ");
sb.append("Chance: | ");
sb.append("");
- sb.append(chanceFormat.format(Math.min(normalized.getChance(), 100)));
+ sb.append(chanceFormat.format(Math.min(generalGroupedDropItem.getChance(npc, activeChar), 100)));
sb.append("% |
");
- for (GeneralDropItem generalDropItem : normalized.getItems())
+ for (final GeneralDropItem generalDropItem : generalGroupedDropItem.getItems())
{
final L2Item item = ItemTable.getInstance().getTemplate(generalDropItem.getItemId());
sb.append("");
@@ -324,9 +376,9 @@ public class NpcViewMod implements IBypassHandler
sb.append(item.getName());
sb.append(" | ");
sb.append("Amount: | ");
- final MinMax minMax = getPreciseMinMax(normalized.getChance(), generalDropItem.getMin(npc, activeChar), generalDropItem.getMax(npc, activeChar), generalDropItem.isPreciseCalculated());
- final long min = minMax.min;
- final long max = minMax.max;
+
+ final long min = generalDropItem.getMin(npc, activeChar);
+ final long max = generalDropItem.getMax(npc, activeChar);
sb.append(amountFormat.format(min));
if (min != max)
{
@@ -379,62 +431,4 @@ public class NpcViewMod implements IBypassHandler
html = html.replaceAll("%items%", bodySb.toString());
Util.sendCBHtml(activeChar, html);
}
-
- /**
- * @param activeChar
- * @param npc
- * @param amountFormat
- * @param chanceFormat
- * @param sb
- * @param dropItem
- */
- private static void addGeneralDropItem(L2PcInstance activeChar, L2Npc npc, DecimalFormat amountFormat, DecimalFormat chanceFormat, StringBuilder sb, GeneralDropItem dropItem)
- {
- final L2Item item = ItemTable.getInstance().getTemplate(dropItem.getItemId());
- sb.append("");
- sb.append("");
- sb.append(" ");
- sb.append(" | ");
- sb.append(item.getName());
- sb.append(" | | ");
- sb.append("Amount: | ");
- sb.append("");
- final MinMax minMax = getPreciseMinMax(dropItem.getChance(npc, activeChar), dropItem.getMin(npc, activeChar), dropItem.getMax(npc, activeChar), dropItem.isPreciseCalculated());
-
- final long min = minMax.min;
- final long max = minMax.max;
- sb.append(amountFormat.format(min));
- if (min != max)
- {
- sb.append(" - ");
- sb.append(amountFormat.format(max));
- }
-
- sb.append(" | Chance: | ");
- sb.append("");
- sb.append(chanceFormat.format(Math.min(dropItem.getChance(npc, activeChar), 100)));
- sb.append("% | | | | ");
- }
-
- private static class MinMax
- {
- public final long min, max;
-
- public MinMax(long min, long max)
- {
- this.min = min;
- this.max = max;
- }
- }
-
- private static MinMax getPreciseMinMax(double chance, long min, long max, boolean isPrecise)
- {
- if (!isPrecise || (chance <= 100))
- {
- return new MinMax(min, max);
- }
-
- final int mult = (int) chance / 100;
- return new MinMax(mult * min, (chance % 100) > 0 ? (mult + 1) * max : mult * max);
- }
}
diff --git a/trunk/dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java b/trunk/dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java
index dbe00051dc..1089903af3 100644
--- a/trunk/dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java
+++ b/trunk/dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java
@@ -49,11 +49,15 @@ public class Premium implements IVoicedCommandHandler
html.append(" | Rate SP: x" + Config.RATE_SP + " | ");
html.append("Drop Chance: x" + Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER + " | ");
html.append("Drop Amount: x" + Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER + " | ");
+ html.append("Spoil Chance: x" + Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER + " | ");
+ html.append("Spoil Amount: x" + Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER + "
| ");
html.append("Premium Info & Rules
| ");
html.append("Rate XP: x" + (Config.RATE_XP * Config.PREMIUM_RATE_XP) + " | ");
html.append("Rate SP: x" + (Config.RATE_SP * Config.PREMIUM_RATE_SP) + " | ");
html.append("Drop Chance: x" + (Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_DROP_CHANCE) + " | ");
html.append("Drop Amount: x" + (Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_DROP_AMOUNT) + " | ");
+ html.append("Spoil Chance: x" + (Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_SPOIL_CHANCE) + " | ");
+ html.append("Spoil Amount: x" + (Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_SPOIL_AMOUNT) + " | ");
html.append(" 1. Premium benefits CAN NOT BE TRANSFERED. | ");
html.append(" 2. Premium does not effect party members. | ");
html.append(" 3. Premium benefits effect ALL characters in same account. | ");
@@ -67,6 +71,8 @@ public class Premium implements IVoicedCommandHandler
html.append("Rate SP: x" + (Config.RATE_SP * Config.PREMIUM_RATE_SP) + " | ");
html.append("Drop Chance: x" + (Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_DROP_CHANCE) + " | ");
html.append("Drop Amount: x" + (Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_DROP_AMOUNT) + " | ");
+ html.append("Spoil Chance: x" + (Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_SPOIL_CHANCE) + " | ");
+ html.append("Spoil Amount: x" + (Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_SPOIL_AMOUNT) + " | ");
html.append("Expires: " + String.valueOf(format.format(endDate)) + " | ");
html.append("Current Date: " + String.valueOf(format.format(System.currentTimeMillis())) + "
| ");
html.append("Premium Info & Rules
| ");
diff --git a/trunk/dist/game/data/scripts/quests/Q10751_WindsOfFateEncounters/Q10751_WindsOfFateEncounters.java b/trunk/dist/game/data/scripts/quests/Q10751_WindsOfFateEncounters/Q10751_WindsOfFateEncounters.java
index d0e5b7eaef..02197a4eba 100644
--- a/trunk/dist/game/data/scripts/quests/Q10751_WindsOfFateEncounters/Q10751_WindsOfFateEncounters.java
+++ b/trunk/dist/game/data/scripts/quests/Q10751_WindsOfFateEncounters/Q10751_WindsOfFateEncounters.java
@@ -222,12 +222,12 @@ public class Q10751_WindsOfFateEncounters extends Quest implements IBypassHandle
if (classId == 184)
{
htmltext = "33943-ccf.html";
- giveItems(player, NAVARIS_SUPPORT_BOX_F, 1);
+ giveItems(player, NAVARIS_SUPPORT_BOX_F);
}
else if (classId == 185)
{
htmltext = "33942-ccm.html";
- giveItems(player, NAVARIS_SUPPORT_BOX_M, 1);
+ giveItems(player, NAVARIS_SUPPORT_BOX_M);
}
player.broadcastUserInfo();
qs.exitQuest(false, true);
diff --git a/trunk/java/com/l2jmobius/Config.java b/trunk/java/com/l2jmobius/Config.java
index c4e45c6841..0d88876a1e 100644
--- a/trunk/java/com/l2jmobius/Config.java
+++ b/trunk/java/com/l2jmobius/Config.java
@@ -492,7 +492,6 @@ public final class Config
public static int SAVE_DROPPED_ITEM_INTERVAL;
public static boolean CLEAR_DROPPED_ITEM_TABLE;
public static boolean AUTODELETE_INVALID_QUEST_DATA;
- public static boolean PRECISE_DROP_CALCULATION;
public static boolean MULTIPLE_ITEM_DROP;
public static boolean FORCE_INVENTORY_UPDATE;
public static boolean LAZY_CACHE;
@@ -782,6 +781,7 @@ public final class Config
public static int L2JMOD_DUALBOX_CHECK_MAX_L2EVENT_PARTICIPANTS_PER_IP;
public static Map L2JMOD_DUALBOX_CHECK_WHITELIST;
public static boolean L2JMOD_ALLOW_CHANGE_PASSWORD;
+ public static boolean L2JMOD_OLD_DROP_BEHAVIOR;
public static boolean ALLOW_HUMAN;
public static boolean ALLOW_ELF;
public static boolean ALLOW_DARKELF;
@@ -828,10 +828,13 @@ public final class Config
public static boolean PREMIUM_SYSTEM_ENABLED;
public static float PREMIUM_RATE_XP;
public static float PREMIUM_RATE_SP;
+ public static Map PREMIUM_RATE_DROP_ITEMS_ID;
public static float PREMIUM_RATE_DROP_CHANCE;
public static float PREMIUM_RATE_DROP_AMOUNT;
- public static Map PREMIUM_RATE_DROP_CHANCE_MULTIPLIER;
- public static Map PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER;
+ public static float PREMIUM_RATE_SPOIL_CHANCE;
+ public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PC_BANG_ENABLED;
public static int PC_BANG_MAX_POINTS;
public static boolean PC_BANG_ENABLE_DOUBLE_POINTS;
@@ -849,8 +852,6 @@ public final class Config
public static boolean ALT_ATTACKABLE_NPCS;
public static boolean ALT_GAME_VIEWNPC;
public static int MAX_DRIFT_RANGE;
- public static boolean DEEPBLUE_DROP_RULES;
- public static boolean DEEPBLUE_DROP_RULES_RAID;
public static boolean SHOW_NPC_LVL;
public static boolean SHOW_CREST_WITHOUT_QUEST;
public static boolean ENABLE_RANDOM_ENCHANT_EFFECT;
@@ -935,8 +936,8 @@ public final class Config
public static float RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
public static float RATE_HERB_DROP_CHANCE_MULTIPLIER;
public static float RATE_RAID_DROP_CHANCE_MULTIPLIER;
- public static Map RATE_DROP_AMOUNT_MULTIPLIER;
- public static Map RATE_DROP_CHANCE_MULTIPLIER;
+ public static Map RATE_DROP_AMOUNT_BY_ID;
+ public static Map RATE_DROP_CHANCE_BY_ID;
public static float RATE_KARMA_LOST;
public static float RATE_KARMA_EXP_LOST;
public static float RATE_SIEGE_GUARDS_PRICE;
@@ -1840,7 +1841,6 @@ public final class Config
SAVE_DROPPED_ITEM_INTERVAL = General.getInt("SaveDroppedItemInterval", 60) * 60000;
CLEAR_DROPPED_ITEM_TABLE = General.getBoolean("ClearDroppedItemTable", false);
AUTODELETE_INVALID_QUEST_DATA = General.getBoolean("AutoDeleteInvalidQuestData", false);
- PRECISE_DROP_CALCULATION = General.getBoolean("PreciseDropCalculation", true);
MULTIPLE_ITEM_DROP = General.getBoolean("MultipleItemDrop", true);
FORCE_INVENTORY_UPDATE = General.getBoolean("ForceInventoryUpdate", false);
LAZY_CACHE = General.getBoolean("LazyCache", true);
@@ -2016,8 +2016,6 @@ public final class Config
ALT_ATTACKABLE_NPCS = NPC.getBoolean("AltAttackableNpcs", true);
ALT_GAME_VIEWNPC = NPC.getBoolean("AltGameViewNpc", false);
MAX_DRIFT_RANGE = NPC.getInt("MaxDriftRange", 300);
- DEEPBLUE_DROP_RULES = NPC.getBoolean("UseDeepBlueDropRules", true);
- DEEPBLUE_DROP_RULES_RAID = NPC.getBoolean("UseDeepBlueDropRulesRaid", true);
SHOW_NPC_LVL = NPC.getBoolean("ShowNpcLevel", false);
SHOW_CREST_WITHOUT_QUEST = NPC.getBoolean("ShowCrestWithoutQuest", false);
ENABLE_RANDOM_ENCHANT_EFFECT = NPC.getBoolean("EnableRandomEnchantEffect", false);
@@ -2142,8 +2140,9 @@ public final class Config
RATE_CORPSE_DROP_CHANCE_MULTIPLIER = RatesSettings.getFloat("CorpseDropChanceMultiplier", 1);
RATE_HERB_DROP_CHANCE_MULTIPLIER = RatesSettings.getFloat("HerbDropChanceMultiplier", 1);
RATE_RAID_DROP_CHANCE_MULTIPLIER = RatesSettings.getFloat("RaidDropChanceMultiplier", 1);
+
final String[] dropAmountMultiplier = RatesSettings.getString("DropAmountMultiplierByItemId", "").split(";");
- RATE_DROP_AMOUNT_MULTIPLIER = new HashMap<>(dropAmountMultiplier.length);
+ RATE_DROP_AMOUNT_BY_ID = new HashMap<>(dropAmountMultiplier.length);
if (!dropAmountMultiplier[0].isEmpty())
{
for (String item : dropAmountMultiplier)
@@ -2157,7 +2156,7 @@ public final class Config
{
try
{
- RATE_DROP_AMOUNT_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+ RATE_DROP_AMOUNT_BY_ID.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
}
catch (NumberFormatException nfe)
{
@@ -2171,7 +2170,7 @@ public final class Config
}
final String[] dropChanceMultiplier = RatesSettings.getString("DropChanceMultiplierByItemId", "").split(";");
- RATE_DROP_CHANCE_MULTIPLIER = new HashMap<>(dropChanceMultiplier.length);
+ RATE_DROP_CHANCE_BY_ID = new HashMap<>(dropChanceMultiplier.length);
if (!dropChanceMultiplier[0].isEmpty())
{
for (String item : dropChanceMultiplier)
@@ -2185,7 +2184,7 @@ public final class Config
{
try
{
- RATE_DROP_CHANCE_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+ RATE_DROP_CHANCE_BY_ID.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
}
catch (NumberFormatException nfe)
{
@@ -2245,6 +2244,8 @@ public final class Config
L2JMOD_ENABLE_WAREHOUSESORTING_CLAN = CustomSettings.getBoolean("EnableWarehouseSortingClan", false);
L2JMOD_ENABLE_WAREHOUSESORTING_PRIVATE = CustomSettings.getBoolean("EnableWarehouseSortingPrivate", false);
+ L2JMOD_OLD_DROP_BEHAVIOR = CustomSettings.getBoolean("OldDropBehavior", false);
+
if (TVT_EVENT_PARTICIPATION_NPC_ID == 0)
{
TVT_EVENT_ENABLED = false;
@@ -2610,57 +2611,59 @@ public final class Config
PREMIUM_SYSTEM_ENABLED = CustomSettings.getBoolean("EnablePremiumSystem", false);
PREMIUM_RATE_XP = CustomSettings.getFloat("PremiumRateXp", 2);
PREMIUM_RATE_SP = CustomSettings.getFloat("PremiumRateSp", 2);
- PREMIUM_RATE_DROP_CHANCE = CustomSettings.getFloat("PremiumRateDropChance", 1);
- PREMIUM_RATE_DROP_AMOUNT = CustomSettings.getFloat("PremiumRateDropAmount", 2);
- final String[] premiumDropChanceMultiplier = CustomSettings.getString("PremiumDropChanceMultiplierByItemId", "").split(";");
- PREMIUM_RATE_DROP_CHANCE_MULTIPLIER = new HashMap<>(premiumDropChanceMultiplier.length);
+ PREMIUM_RATE_DROP_CHANCE = CustomSettings.getFloat("PremiumRateDropChance", 2);
+ PREMIUM_RATE_DROP_AMOUNT = CustomSettings.getFloat("PremiumRateDropAmount", 1);
+ PREMIUM_RATE_SPOIL_CHANCE = CustomSettings.getFloat("PremiumRateSpoilChance", 2);
+ PREMIUM_RATE_SPOIL_AMOUNT = CustomSettings.getFloat("PremiumRateSpoilAmount", 1);
+ String[] premiumDropChanceMultiplier = CustomSettings.getString("PremiumRateDropChanceByItemId", "").split(";");
+ PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
{
for (String item : premiumDropChanceMultiplier)
{
- final String[] itemSplit = item.split(",");
+ String[] itemSplit = item.split(",");
if (itemSplit.length != 2)
{
- _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumDropChanceMultiplierByItemId \"", item, "\""));
+ _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropChanceByItemId \"", item, "\""));
}
else
{
try
{
- PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+ PREMIUM_RATE_DROP_CHANCE_BY_ID.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
}
catch (NumberFormatException nfe)
{
if (!item.isEmpty())
{
- _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumDropChanceMultiplierByItemId \"", item, "\""));
+ _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropChanceByItemId \"", item, "\""));
}
}
}
}
}
- final String[] premiumDropAmountMultiplier = CustomSettings.getString("PremiumDropAmountMultiplierByItemId", "").split(";");
- PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER = new HashMap<>(premiumDropAmountMultiplier.length);
+ String[] premiumDropAmountMultiplier = CustomSettings.getString("PremiumRateDropAmountByItemId", "").split(";");
+ PREMIUM_RATE_DROP_AMOUNT_BY_ID = new HashMap<>(premiumDropAmountMultiplier.length);
if (!premiumDropAmountMultiplier[0].isEmpty())
{
for (String item : premiumDropAmountMultiplier)
{
- final String[] itemSplit = item.split(",");
+ String[] itemSplit = item.split(",");
if (itemSplit.length != 2)
{
- _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumDropAmountMultiplierByItemId \"", item, "\""));
+ _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropAmountByItemId \"", item, "\""));
}
else
{
try
{
- PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+ PREMIUM_RATE_DROP_AMOUNT_BY_ID.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
}
catch (NumberFormatException nfe)
{
if (!item.isEmpty())
{
- _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumDropAmountMultiplierByItemId \"", item, "\""));
+ _log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropAmountByItemId \"", item, "\""));
}
}
}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/CorpseDropItem.java b/trunk/java/com/l2jmobius/gameserver/model/drops/CorpseDropItem.java
new file mode 100644
index 0000000000..7b5009acdc
--- /dev/null
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/CorpseDropItem.java
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.model.drops;
+
+import com.l2jmobius.Config;
+
+/**
+ * @author NosBit
+ */
+public class CorpseDropItem extends GeneralDropItem
+{
+ /**
+ * @param itemId the item id
+ * @param min the min count
+ * @param max the max count
+ * @param chance the chance of this drop item
+ */
+ public CorpseDropItem(int itemId, long min, long max, double chance)
+ {
+ super(itemId, min, max, chance);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalAmountMultiplier()
+ */
+ @Override
+ protected double getGlobalAmountMultiplier(boolean isPremium)
+ {
+ return isPremium ? Config.PREMIUM_RATE_SPOIL_AMOUNT * Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER : Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalChanceMultiplier()
+ */
+ @Override
+ protected double getGlobalChanceMultiplier(boolean isPremium)
+ {
+ return isPremium ? Config.PREMIUM_RATE_SPOIL_CHANCE * Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER : Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
+ }
+}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/DeathDropItem.java b/trunk/java/com/l2jmobius/gameserver/model/drops/DeathDropItem.java
new file mode 100644
index 0000000000..f8dda068f3
--- /dev/null
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/DeathDropItem.java
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.model.drops;
+
+import com.l2jmobius.Config;
+
+/**
+ * @author NosBit
+ */
+public class DeathDropItem extends GeneralDropItem
+{
+ /**
+ * @param itemId the item id
+ * @param min the min count
+ * @param max the max count
+ * @param chance the chance of this drop item
+ */
+ public DeathDropItem(int itemId, long min, long max, double chance)
+ {
+ super(itemId, min, max, chance);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalAmountMultiplier()
+ */
+ @Override
+ protected double getGlobalAmountMultiplier(boolean isPremium)
+ {
+ return isPremium ? Config.PREMIUM_RATE_DROP_AMOUNT * Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER : Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalChanceMultiplier()
+ */
+ @Override
+ protected double getGlobalChanceMultiplier(boolean isPremium)
+ {
+ return isPremium ? Config.PREMIUM_RATE_DROP_CHANCE * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER : Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
+ }
+}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/DropListScope.java b/trunk/java/com/l2jmobius/gameserver/model/drops/DropListScope.java
index 426cef32c0..47ef304167 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/DropListScope.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/DropListScope.java
@@ -16,44 +16,75 @@
*/
package com.l2jmobius.gameserver.model.drops;
-import com.l2jmobius.gameserver.model.drops.strategy.IAmountMultiplierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IChanceMultiplierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IGroupedItemDropCalculationStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IKillerChanceModifierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IPreciseDeterminationStrategy;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* @author NosBit
*/
-public enum DropListScope implements IDropItemFactory, IGroupedDropItemFactory
+public enum DropListScope
{
- DEATH((itemId, min, max, chance) -> new GeneralDropItem(itemId, min, max, chance, IAmountMultiplierStrategy.DROP, IChanceMultiplierStrategy.DROP), chance -> new GroupedGeneralDropItem(chance)),
- CORPSE((itemId, min, max, chance) -> new GeneralDropItem(itemId, min, max, chance, IAmountMultiplierStrategy.SPOIL, IChanceMultiplierStrategy.SPOIL), DEATH),
+ DEATH(DeathDropItem.class, GroupedDeathDropItem.class),
+ CORPSE(CorpseDropItem.class, GroupedCorpseDropItem.class);
- /**
- * This droplist scope isn't affected by ANY rates, nor Champion, etc...
- */
- STATIC((itemId, min, max, chance) -> new GeneralDropItem(itemId, min, max, chance, IAmountMultiplierStrategy.STATIC, IChanceMultiplierStrategy.STATIC, IPreciseDeterminationStrategy.ALWAYS, IKillerChanceModifierStrategy.NO_RULES), chance -> new GroupedGeneralDropItem(chance, IGroupedItemDropCalculationStrategy.DEFAULT_STRATEGY, IKillerChanceModifierStrategy.NO_RULES, IPreciseDeterminationStrategy.ALWAYS)),
- QUEST((itemId, min, max, chance) -> new GeneralDropItem(itemId, min, max, chance, IAmountMultiplierStrategy.STATIC, IChanceMultiplierStrategy.QUEST, IPreciseDeterminationStrategy.ALWAYS, IKillerChanceModifierStrategy.NO_RULES), STATIC);
+ private static final Logger _log = Logger.getLogger(DropListScope.class.getName());
- private final IDropItemFactory _factory;
- private final IGroupedDropItemFactory _groupFactory;
+ private final Class extends GeneralDropItem> _dropItemClass;
+ private final Class extends GroupedGeneralDropItem> _groupedDropItemClass;
- private DropListScope(IDropItemFactory factory, IGroupedDropItemFactory groupFactory)
+ private DropListScope(Class extends GeneralDropItem> dropItemClass, Class extends GroupedGeneralDropItem> groupedDropItemClass)
{
- _factory = factory;
- _groupFactory = groupFactory;
+ _dropItemClass = dropItemClass;
+ _groupedDropItemClass = groupedDropItemClass;
}
- @Override
public IDropItem newDropItem(int itemId, long min, long max, double chance)
{
- return _factory.newDropItem(itemId, min, max, chance);
+ final Constructor extends GeneralDropItem> constructor;
+ try
+ {
+ constructor = _dropItemClass.getConstructor(int.class, long.class, long.class, double.class);
+ }
+ catch (NoSuchMethodException | SecurityException e)
+ {
+ _log.log(Level.SEVERE, "Constructor(int, long, long, double) not found for " + _dropItemClass.getSimpleName(), e);
+ return null;
+ }
+
+ try
+ {
+ return constructor.newInstance(itemId, min, max, chance);
+ }
+ catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
+ {
+ _log.log(Level.SEVERE, "", e);
+ return null;
+ }
}
- @Override
public GroupedGeneralDropItem newGroupedDropItem(double chance)
{
- return _groupFactory.newGroupedDropItem(chance);
+ final Constructor extends GroupedGeneralDropItem> constructor;
+ try
+ {
+ constructor = _groupedDropItemClass.getConstructor(double.class);
+ }
+ catch (NoSuchMethodException | SecurityException e)
+ {
+ _log.log(Level.SEVERE, "Constructor(double) not found for " + _groupedDropItemClass.getSimpleName(), e);
+ return null;
+ }
+
+ try
+ {
+ return constructor.newInstance(chance);
+ }
+ catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
+ {
+ _log.log(Level.SEVERE, "", e);
+ return null;
+ }
}
}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/GeneralDropItem.java b/trunk/java/com/l2jmobius/gameserver/model/drops/GeneralDropItem.java
index fe0e04f333..689fcc05cf 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/GeneralDropItem.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/GeneralDropItem.java
@@ -16,34 +16,28 @@
*/
package com.l2jmobius.gameserver.model.drops;
-import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.strategy.IAmountMultiplierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IChanceMultiplierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IDropCalculationStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IKillerChanceModifierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.INonGroupedKillerChanceModifierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IPreciseDeterminationStrategy;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.L2Item;
+import com.l2jmobius.gameserver.util.Util;
+import com.l2jmobius.util.Rnd;
/**
* @author NosBit
*/
-public final class GeneralDropItem implements IDropItem
+public class GeneralDropItem implements IDropItem
{
private final int _itemId;
private final long _min;
private final long _max;
private final double _chance;
- protected final IAmountMultiplierStrategy _amountStrategy;
- protected final IChanceMultiplierStrategy _chanceStrategy;
- protected final IPreciseDeterminationStrategy _preciseStrategy;
- protected final INonGroupedKillerChanceModifierStrategy _killerStrategy;
- protected final IDropCalculationStrategy _dropCalculationStrategy;
-
/**
* @param itemId the item id
* @param min the min count
@@ -51,225 +45,243 @@ public final class GeneralDropItem implements IDropItem
* @param chance the chance of this drop item
*/
public GeneralDropItem(int itemId, long min, long max, double chance)
- {
- this(itemId, min, max, chance, 1, 1);
- }
-
- public GeneralDropItem(int itemId, long min, long max, double chance, double defaultAmountMultiplier, double defaultChanceMultiplier)
- {
- this(itemId, min, max, defaultChanceMultiplier, IAmountMultiplierStrategy.DEFAULT_STRATEGY(defaultAmountMultiplier), IChanceMultiplierStrategy.DEFAULT_STRATEGY(defaultChanceMultiplier));
- }
-
- public GeneralDropItem(int itemId, long min, long max, double chance, IAmountMultiplierStrategy amountMultiplierStrategy, IChanceMultiplierStrategy chanceMultiplierStrategy)
- {
- this(itemId, min, max, chance, amountMultiplierStrategy, chanceMultiplierStrategy, IPreciseDeterminationStrategy.DEFAULT, IKillerChanceModifierStrategy.DEFAULT_NONGROUP_STRATEGY);
- }
-
- public GeneralDropItem(int itemId, long min, long max, double chance, IAmountMultiplierStrategy amountMultiplierStrategy, IChanceMultiplierStrategy chanceMultiplierStrategy, IPreciseDeterminationStrategy preciseStrategy, INonGroupedKillerChanceModifierStrategy killerStrategy)
- {
- this(itemId, min, max, chance, amountMultiplierStrategy, chanceMultiplierStrategy, preciseStrategy, killerStrategy, IDropCalculationStrategy.DEFAULT_STRATEGY);
- }
-
- public GeneralDropItem(int itemId, long min, long max, double chance, IAmountMultiplierStrategy amountMultiplierStrategy, IChanceMultiplierStrategy chanceMultiplierStrategy, IPreciseDeterminationStrategy preciseStrategy, INonGroupedKillerChanceModifierStrategy killerStrategy, IDropCalculationStrategy dropCalculationStrategy)
{
_itemId = itemId;
_min = min;
_max = max;
_chance = chance;
- _amountStrategy = amountMultiplierStrategy;
- _chanceStrategy = chanceMultiplierStrategy;
- _preciseStrategy = preciseStrategy;
- _killerStrategy = killerStrategy;
- _dropCalculationStrategy = dropCalculationStrategy;
}
- /**
- * @return the _amountStrategy
- */
- public final IAmountMultiplierStrategy getAmountStrategy()
+ protected double getGlobalChanceMultiplier(boolean isPremium)
{
- return _amountStrategy;
+ return 1.;
}
- /**
- * @return the _chanceStrategy
- */
- public final IChanceMultiplierStrategy getChanceStrategy()
+ protected double getGlobalAmountMultiplier(boolean isPremium)
{
- return _chanceStrategy;
+ return 1.;
}
- /**
- * @return the _preciseStrategy
- */
- public final IPreciseDeterminationStrategy getPreciseStrategy()
+ private final long getMinMax(L2Character victim, L2Character killer, long val)
{
- return _preciseStrategy;
- }
-
- /**
- * @return the _killerStrategy
- */
- public final INonGroupedKillerChanceModifierStrategy getKillerChanceModifierStrategy()
- {
- return _killerStrategy;
- }
-
- /**
- * @return the _dropCalculationStrategy
- */
- public final IDropCalculationStrategy getDropCalculationStrategy()
- {
- return _dropCalculationStrategy;
+ double multiplier = 1;
+
+ // individual drop amount
+ Float individualDropAmountMultiplier = null;
+ if (killer.getActingPlayer().hasPremiumStatus())
+ {
+ final Float normalMultiplier = Config.RATE_DROP_AMOUNT_BY_ID.get(getItemId());
+ final Float premiumMultiplier = Config.PREMIUM_RATE_DROP_AMOUNT_BY_ID.get(getItemId());
+ if ((normalMultiplier != null) && (premiumMultiplier != null))
+ {
+ individualDropAmountMultiplier = normalMultiplier * premiumMultiplier;
+ }
+ else if (normalMultiplier != null)
+ {
+ individualDropAmountMultiplier = normalMultiplier;
+ }
+ else if (premiumMultiplier != null)
+ {
+ individualDropAmountMultiplier = premiumMultiplier;
+ }
+ }
+ else
+ {
+ individualDropAmountMultiplier = Config.RATE_DROP_AMOUNT_BY_ID.get(getItemId());
+ }
+
+ if (individualDropAmountMultiplier != null)
+ {
+ // individual amount list multiplier
+ multiplier *= individualDropAmountMultiplier;
+ }
+ else
+ {
+ final L2Item item = ItemTable.getInstance().getTemplate(getItemId());
+ // global amount multiplier
+ if ((item != null) && item.hasExImmediateEffect())
+ {
+ // global herb amount multiplier
+ multiplier *= Config.RATE_HERB_DROP_AMOUNT_MULTIPLIER;
+ }
+ else if (victim.isRaid())
+ {
+ // global raid amount multiplier
+ multiplier *= Config.RATE_RAID_DROP_AMOUNT_MULTIPLIER;
+ }
+ else
+ {
+ // drop type specific amount multiplier
+ multiplier *= getGlobalAmountMultiplier(killer.getActingPlayer().hasPremiumStatus());
+ }
+ }
+
+ // global champions amount multiplier
+ if (victim.isChampion())
+ {
+ multiplier *= getItemId() != Inventory.ADENA_ID ? Config.L2JMOD_CHAMPION_REWARDS_AMOUNT : Config.L2JMOD_CHAMPION_ADENAS_REWARDS_AMOUNT;
+ }
+
+ return (long) (val * multiplier);
}
/**
* Gets the item id
* @return the item id
*/
- public final int getItemId()
+ public int getItemId()
{
return _itemId;
}
/**
- * Gets the base min drop count
+ * Gets the min drop count
* @return the min
*/
- public final long getMin()
+ public long getMin()
{
return _min;
}
/**
- * Gets the min drop count modified by server rates
- * @param victim the victim who drops the item
- * @param killer who kills the victim
+ * Gets the min drop count
+ * @param victim the victim
+ * @param killer the killer
* @return the min modified by any rates.
*/
- public final long getMin(L2Character victim, L2Character killer)
+ public long getMin(L2Character victim, L2Character killer)
{
- if (Config.PREMIUM_SYSTEM_ENABLED && killer.isPlayer() && killer.getActingPlayer().hasPremiumStatus())
- {
- if (Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId) != null)
- {
- return (long) (getMin() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId));
- }
- return (long) (getMin() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT);
- }
- return (long) (getMin() * getAmountMultiplier(victim));
+ return getMinMax(victim, killer, getMin());
}
/**
- * Gets the base max drop count
+ * Gets the max drop count
* @return the max
*/
- public final long getMax()
+ public long getMax()
{
return _max;
}
/**
- * Gets the max drop count modified by server rates
- * @param victim the victim who drops the item
- * @param killer who kills the victim
+ * Gets the max drop count
+ * @param victim the victim
+ * @param killer the killer
* @return the max modified by any rates.
*/
- public final long getMax(L2Character victim, L2Character killer)
+ public long getMax(L2Character victim, L2Character killer)
{
- if (Config.PREMIUM_SYSTEM_ENABLED && killer.isPlayer() && killer.getActingPlayer().hasPremiumStatus())
- {
- if (Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId) != null)
- {
- return (long) (getMax() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId));
- }
- return (long) (getMax() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT);
- }
- return (long) (getMax() * getAmountMultiplier(victim));
+ return getMinMax(victim, killer, getMax());
}
/**
* Gets the chance of this drop item.
* @return the chance
*/
- public final double getChance()
+ public double getChance()
{
return _chance;
}
/**
- * Gets the general chance to drop this item modified by rates.
- * This shall be used in calculating chance within drop groups.
- * @param victim the victim who drops the item
+ * Gets the chance of this drop item.
+ * @param victim the victim
+ * @param killer the killer
* @return the chance modified by any rates.
*/
- public final double getChance(L2Character victim)
+ public double getChance(L2Character victim, L2Character killer)
{
- return getChance() * getChanceMultiplier(victim);
- }
-
- /**
- * Gets the chance of dropping this item for current killer and victim (modified by server rates and another rules based on killer)
- * This shall be used to calculate chance outside of drop groups.
- * @param victim the victim who drops the item
- * @param killer who kills the victim
- * @return a chance to drop modified by deep blue drop rules
- */
- public final double getChance(L2Character victim, L2Character killer)
- {
- if (Config.PREMIUM_SYSTEM_ENABLED && killer.isPlayer() && killer.getActingPlayer().hasPremiumStatus())
+ double multiplier = 1;
+
+ // individual drop chance
+ Float individualDropChanceMultiplier = null;
+ if (killer.getActingPlayer().hasPremiumStatus())
{
- if (Config.PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.get(_itemId) != null)
+ final Float normalMultiplier = Config.RATE_DROP_CHANCE_BY_ID.get(getItemId());
+ final Float premiumMultiplier = Config.PREMIUM_RATE_DROP_CHANCE_BY_ID.get(getItemId());
+ if ((normalMultiplier != null) && (premiumMultiplier != null))
{
- return getKillerChanceModifier(victim, killer) * getChance(victim) * Config.PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.get(_itemId);
+ individualDropChanceMultiplier = normalMultiplier * premiumMultiplier;
+ }
+ else if (normalMultiplier != null)
+ {
+ individualDropChanceMultiplier = normalMultiplier;
+ }
+ else if (premiumMultiplier != null)
+ {
+ individualDropChanceMultiplier = premiumMultiplier;
}
- return getKillerChanceModifier(victim, killer) * getChance(victim) * Config.PREMIUM_RATE_DROP_CHANCE;
}
- return getKillerChanceModifier(victim, killer) * getChance(victim);
+ else
+ {
+ individualDropChanceMultiplier = Config.RATE_DROP_CHANCE_BY_ID.get(getItemId());
+ }
+
+ if (individualDropChanceMultiplier != null)
+ {
+ multiplier *= individualDropChanceMultiplier;
+ }
+ else
+ {
+ final L2Item item = ItemTable.getInstance().getTemplate(getItemId());
+ if ((item != null) && item.hasExImmediateEffect())
+ {
+ multiplier *= Config.RATE_HERB_DROP_CHANCE_MULTIPLIER;
+ }
+ else if (victim.isRaid())
+ {
+ // global raid chance multiplier
+ multiplier *= Config.RATE_RAID_DROP_CHANCE_MULTIPLIER;
+ }
+ else
+ {
+ multiplier *= getGlobalChanceMultiplier(killer.getActingPlayer().hasPremiumStatus());
+ }
+ }
+
+ if (victim.isChampion())
+ {
+ multiplier *= getItemId() != Inventory.ADENA_ID ? Config.L2JMOD_CHAMPION_REWARDS_CHANCE : Config.L2JMOD_CHAMPION_ADENAS_REWARDS_CHANCE;
+ }
+
+ return (getChance() * multiplier);
}
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drop.IDropItem#calculateDrops(com.l2jserver.gameserver.model.actor.L2Character, com.l2jserver.gameserver.model.actor.L2Character)
+ */
@Override
- public final List calculateDrops(L2Character victim, L2Character killer)
+ public Collection calculateDrops(L2Character victim, L2Character killer)
{
- return _dropCalculationStrategy.calculateDrops(this, victim, killer);
- }
-
- /**
- * @return true if chance over 100% should be handled
- */
- public final boolean isPreciseCalculated()
- {
- return _preciseStrategy.isPreciseCalculated(this);
- }
-
- /**
- * This handles by default deep blue drop rules. It may also be used to handle another drop chance rules based on killer
- * @param victim the victim who drops the item
- * @param killer who kills the victim
- * @return a number between 0 and 1 (usually)
- */
- protected final double getKillerChanceModifier(L2Character victim, L2Character killer)
- {
- return _killerStrategy.getKillerChanceModifier(this, victim, killer);
- }
-
- /**
- * This gets standard server rates for this item
- * @param victim who drops the item
- * @return
- */
- protected final double getAmountMultiplier(L2Character victim)
- {
- return _amountStrategy.getAmountMultiplier(this, victim);
- }
-
- /**
- * This gets standard server rates for this item
- * @param victim who drops the item
- * @return
- */
- protected final double getChanceMultiplier(L2Character victim)
- {
- return _chanceStrategy.getChanceMultiplier(this, victim);
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ final double levelGapChanceToDrop;
+ if (getItemId() == Inventory.ADENA_ID)
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ else
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+
+ // There is a chance of level gap that it wont drop this item
+ if (levelGapChanceToDrop < (Rnd.nextDouble() * 100))
+ {
+ return null;
+ }
+
+ final double chance = getChance(victim, killer);
+ final boolean successes = chance > (Rnd.nextDouble() * 100);
+ if (successes)
+ {
+ final Collection items = new ArrayList<>(1);
+ final long baseDropCount = Rnd.get(getMin(victim, killer), getMax(victim, killer));
+ final long finaldropCount = (long) (Config.L2JMOD_OLD_DROP_BEHAVIOR ? (baseDropCount * Math.max(1, chance / 100)) + (chance > 100 ? (chance % 100) > (Rnd.nextDouble() * 100) ? baseDropCount : 0 : 0) : baseDropCount);
+ items.add(new ItemHolder(getItemId(), finaldropCount));
+ return items;
+ }
+
+ return null;
}
}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/IGroupedDropItemFactory.java b/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedCorpseDropItem.java
similarity index 59%
rename from trunk/java/com/l2jmobius/gameserver/model/drops/IGroupedDropItemFactory.java
rename to trunk/java/com/l2jmobius/gameserver/model/drops/GroupedCorpseDropItem.java
index 34e08542b6..2f737f84b8 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/IGroupedDropItemFactory.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedCorpseDropItem.java
@@ -16,10 +16,28 @@
*/
package com.l2jmobius.gameserver.model.drops;
+import com.l2jmobius.Config;
+
/**
- * @author Battlecruiser
+ * @author NosBit
*/
-public interface IGroupedDropItemFactory
+public class GroupedCorpseDropItem extends GroupedGeneralDropItem
{
- GroupedGeneralDropItem newGroupedDropItem(double chance);
+ /**
+ * @param chance the chance of this drop item.
+ */
+ public GroupedCorpseDropItem(double chance)
+ {
+ super(chance);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drops.GroupedGeneralDropItem#getGlobalChanceMultiplier()
+ */
+ @Override
+ protected double getGlobalChanceMultiplier()
+ {
+ return Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
+ }
}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/IDropItemFactory.java b/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedDeathDropItem.java
similarity index 60%
rename from trunk/java/com/l2jmobius/gameserver/model/drops/IDropItemFactory.java
rename to trunk/java/com/l2jmobius/gameserver/model/drops/GroupedDeathDropItem.java
index 6c0f77962d..e1b861cec3 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/IDropItemFactory.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedDeathDropItem.java
@@ -16,17 +16,28 @@
*/
package com.l2jmobius.gameserver.model.drops;
+import com.l2jmobius.Config;
+
/**
- * @author Battlecruiser
+ * @author NosBit
*/
-public interface IDropItemFactory
+public class GroupedDeathDropItem extends GroupedGeneralDropItem
{
/**
- * @param itemId the item id
- * @param min the min count
- * @param max the max count
- * @param chance the chance of this drop item
- * @return the drop item created by this factory
+ * @param chance the chance of this drop item.
*/
- IDropItem newDropItem(int itemId, long min, long max, double chance);
+ public GroupedDeathDropItem(double chance)
+ {
+ super(chance);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drops.GroupedGeneralDropItem#getGlobalChanceMultiplier()
+ */
+ @Override
+ protected double getGlobalChanceMultiplier()
+ {
+ return Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
+ }
}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedGeneralDropItem.java b/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedGeneralDropItem.java
index 35a515d1ce..b231a6d01d 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedGeneralDropItem.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/GroupedGeneralDropItem.java
@@ -17,232 +17,131 @@
package com.l2jmobius.gameserver.model.drops;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.strategy.IAmountMultiplierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IChanceMultiplierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IGroupedItemDropCalculationStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IKillerChanceModifierStrategy;
-import com.l2jmobius.gameserver.model.drops.strategy.IPreciseDeterminationStrategy;
+import com.l2jmobius.gameserver.model.actor.instance.L2RaidBossInstance;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
+import com.l2jmobius.gameserver.model.items.L2Item;
+import com.l2jmobius.gameserver.util.Util;
+import com.l2jmobius.util.Rnd;
/**
* @author NosBit
*/
-public final class GroupedGeneralDropItem implements IDropItem
+public class GroupedGeneralDropItem implements IDropItem
{
private final double _chance;
private List _items;
- protected final IGroupedItemDropCalculationStrategy _dropCalculationStrategy;
- protected final IKillerChanceModifierStrategy _killerChanceModifierStrategy;
- protected final IPreciseDeterminationStrategy _preciseStrategy;
/**
* @param chance the chance of this drop item.
*/
public GroupedGeneralDropItem(double chance)
{
- this(chance, IGroupedItemDropCalculationStrategy.DEFAULT_STRATEGY, IKillerChanceModifierStrategy.DEFAULT_STRATEGY, IPreciseDeterminationStrategy.DEFAULT);
+ _chance = chance;
}
- /**
- * @param chance the chance of this drop item.
- * @param dropStrategy to calculate drops.
- * @param killerStrategy
- * @param preciseStrategy
- */
- public GroupedGeneralDropItem(double chance, IGroupedItemDropCalculationStrategy dropStrategy, IKillerChanceModifierStrategy killerStrategy, IPreciseDeterminationStrategy preciseStrategy)
+ protected double getGlobalChanceMultiplier()
{
- _chance = chance;
- _dropCalculationStrategy = dropStrategy;
- _killerChanceModifierStrategy = killerStrategy;
- _preciseStrategy = preciseStrategy;
+ return 1.;
}
/**
* Gets the chance of this drop item.
* @return the chance
*/
- public final double getChance()
+ public double getChance()
{
return _chance;
}
+ /**
+ * Gets the chance of this drop item.
+ * @param victim the victim
+ * @param killer the killer
+ * @return the chance modified by any rates.
+ */
+ public double getChance(L2Character victim, L2Character killer)
+ {
+ for (final GeneralDropItem gdi : getItems())
+ {
+ final L2Item item = ItemTable.getInstance().getTemplate(gdi.getItemId());
+ if ((item == null) || !item.hasExImmediateEffect())
+ {
+ return getChance() * getGlobalChanceMultiplier();
+ }
+ }
+
+ return getChance() * Config.RATE_HERB_DROP_CHANCE_MULTIPLIER;
+ }
+
/**
* Gets the items.
* @return the items
*/
- public final List getItems()
+ public List getItems()
{
return _items;
}
- /**
- * @return the strategy
- */
- public final IGroupedItemDropCalculationStrategy getDropCalculationStrategy()
- {
- return _dropCalculationStrategy;
- }
-
- /**
- * @return the _killerChanceModifierStrategy
- */
- public IKillerChanceModifierStrategy getKillerChanceModifierStrategy()
- {
- return _killerChanceModifierStrategy;
- }
-
- /**
- * @return the _preciseStrategy
- */
- public final IPreciseDeterminationStrategy getPreciseStrategy()
- {
- return _preciseStrategy;
- }
-
/**
* Sets an item list to this drop item.
* @param items the item list
*/
- public final void setItems(List items)
+ public void setItems(List items)
{
_items = Collections.unmodifiableList(items);
}
- /**
- * Returns a list of items in the group with chance multiplied by chance of the group
- * @return the list of items with modified chances
+ /*
+ * (non-Javadoc)
+ * @see com.l2jserver.gameserver.model.drop.IDropItem#calculateDrops(com.l2jserver.gameserver.model.actor.L2Character, com.l2jserver.gameserver.model.actor.L2Character)
*/
- public final List extractMe()
- {
- final List items = new ArrayList<>();
- for (GeneralDropItem item : getItems())
- {
- // precise and killer strategies of the group
- items.add(new GeneralDropItem(item.getItemId(), item.getMin(), item.getMax(), (item.getChance() * getChance()) / 100, item.getAmountStrategy(), item.getChanceStrategy(), getPreciseStrategy(), getKillerChanceModifierStrategy(), item.getDropCalculationStrategy()));
- }
- return items;
- }
-
- /**
- * statically normalizes a group, useful when need to convert legacy SQL data
- * @return a new group with items, which have a sum of getChance() of 100%
- */
- public final GroupedGeneralDropItem normalizeMe()
- {
- double sumchance = 0;
- for (GeneralDropItem item : getItems())
- {
- sumchance += (item.getChance() * getChance()) / 100;
- }
- final double sumchance1 = sumchance;
- final GroupedGeneralDropItem group = new GroupedGeneralDropItem(sumchance1, getDropCalculationStrategy(), IKillerChanceModifierStrategy.NO_RULES, getPreciseStrategy());
- final List items = new ArrayList<>();
- for (GeneralDropItem item : getItems())
- {
- // modify only the chance, leave all other rules intact
- items.add(new GeneralDropItem(item.getItemId(), item.getMin(), item.getMax(), (item.getChance() * getChance()) / sumchance1, item.getAmountStrategy(), item.getChanceStrategy(), item.getPreciseStrategy(), item.getKillerChanceModifierStrategy(), item.getDropCalculationStrategy()));
- }
- group.setItems(items);
- return group;
- }
-
- /**
- * Creates a normalized group taking into account all drop modifiers, needed when handling a group which has items with different chance rates
- * @param victim
- * @param killer
- * @return a new normalized group with all drop modifiers applied
- */
- public final GroupedGeneralDropItem normalizeMe(L2Character victim, L2Character killer)
- {
- return normalizeMe(victim, killer, true, 1);
- }
-
- /**
- * Creates a normalized group taking into account all drop modifiers, needed when handling a group which has items with different chance rates
- * @param victim
- * @param killer
- * @param chanceModifier an additional chance modifier
- * @return a new normalized group with all drop modifiers applied
- */
- public final GroupedGeneralDropItem normalizeMe(L2Character victim, L2Character killer, double chanceModifier)
- {
- return normalizeMe(victim, killer, true, chanceModifier);
- }
-
- /**
- * Creates a normalized group taking into account all drop modifiers, needed when handling a group which has items with different chance rates
- * @param victim
- * @return a new normalized group with all victim modifiers applied
- */
- public final GroupedGeneralDropItem normalizeMe(L2Character victim)
- {
- return normalizeMe(victim, null, false, 1);
- }
-
- /**
- * Creates a normalized group taking into account all drop modifiers, needed when handling a group which has items with different chance rates
- * @param victim
- * @param chanceModifier an additional chance modifier
- * @return a new normalized group with all victim modifiers applied
- */
- public final GroupedGeneralDropItem normalizeMe(L2Character victim, double chanceModifier)
- {
- return normalizeMe(victim, null, false, chanceModifier);
- }
-
- /**
- * Creates a normalized group taking into account all drop modifiers, needed when handling a group which has items with different chance rates
- * @param victim
- * @param killer
- * @param applyKillerModifier if to modify chance by {@link GroupedGeneralDropItem#getKillerChanceModifier(L2Character, L2Character)}
- * @param chanceModifier an additional chance modifier
- * @return a new normalized group with all drop modifiers applied
- */
- private final GroupedGeneralDropItem normalizeMe(L2Character victim, L2Character killer, boolean applyKillerModifier, double chanceModifier)
- {
- if (applyKillerModifier)
- {
- chanceModifier *= getKillerChanceModifier(victim, killer);
- }
- double sumchance = 0;
- for (GeneralDropItem item : getItems())
- {
- sumchance += (item.getChance(victim, killer) * getChance() * chanceModifier) / 100;
- }
- final GroupedGeneralDropItem group = new GroupedGeneralDropItem(sumchance, getDropCalculationStrategy(), IKillerChanceModifierStrategy.NO_RULES, getPreciseStrategy()); // to discard further deep blue calculations
- final List items = new ArrayList<>();
- for (GeneralDropItem item : getItems())
- {
- // the item is made almost "static"
- items.add(new GeneralDropItem(item.getItemId(), item.getMin(victim, killer), item.getMax(victim, killer), (item.getChance(victim, killer) * getChance() * chanceModifier) / sumchance, IAmountMultiplierStrategy.STATIC, IChanceMultiplierStrategy.STATIC, getPreciseStrategy(), IKillerChanceModifierStrategy.NO_RULES, item.getDropCalculationStrategy()));
- }
- group.setItems(items);
- return group;
- }
-
@Override
- public final List calculateDrops(L2Character victim, L2Character killer)
+ public Collection calculateDrops(L2Character victim, L2Character killer)
{
- return _dropCalculationStrategy.calculateDrops(this, victim, killer);
- }
-
- /**
- * This handles by default deep blue drop rules. It may also be used to handle another drop chance rules based on killer
- * @param victim the victim who drops the item
- * @param killer who kills the victim
- * @return a number between 0 and 1 (usually)
- */
- public final double getKillerChanceModifier(L2Character victim, L2Character killer)
- {
- return _killerChanceModifierStrategy.getKillerChanceModifier(this, victim, killer);
- }
-
- public boolean isPreciseCalculated()
- {
- return _preciseStrategy.isPreciseCalculated(this);
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ double chanceModifier;
+ if (victim instanceof L2RaidBossInstance)
+ {
+ chanceModifier = Math.max(0, Math.min(1, (levelDifference * 0.15) + 1));
+ }
+ else
+ {
+ chanceModifier = 1;
+ if (Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0) < (Rnd.nextDouble() * 100))
+ {
+ return null;
+ }
+ }
+
+ final double chance = getChance(victim, killer) * chanceModifier;
+ final boolean successes = chance > (Rnd.nextDouble() * 100);
+
+ if (successes)
+ {
+ 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)
+ {
+ final Collection items = new ArrayList<>(1);
+ final long baseDropCount = Rnd.get(item.getMin(victim, killer), item.getMax(victim, killer));
+ final long finaldropCount = (long) (Config.L2JMOD_OLD_DROP_BEHAVIOR ? (baseDropCount * Math.max(1, chance / 100)) + (chance > 100 && (chance % 100) > (Rnd.nextDouble() * 100) ? baseDropCount : 0) : baseDropCount);
+ items.add(new ItemHolder(item.getItemId(), finaldropCount));
+ return items;
+ }
+ }
+ }
+
+ return null;
}
}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/IDropItem.java b/trunk/java/com/l2jmobius/gameserver/model/drops/IDropItem.java
index c110afb8de..a740085bf4 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/IDropItem.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/drops/IDropItem.java
@@ -16,7 +16,7 @@
*/
package com.l2jmobius.gameserver.model.drops;
-import java.util.List;
+import java.util.Collection;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
@@ -32,5 +32,5 @@ public interface IDropItem
* @param killer the killer
* @return {@code null} or empty collection if there are no drops, a collection containing all items to drop otherwise
*/
- List calculateDrops(L2Character victim, L2Character killer);
+ public Collection calculateDrops(L2Character victim, L2Character killer);
}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IAmountMultiplierStrategy.java b/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IAmountMultiplierStrategy.java
deleted file mode 100644
index acdfa573e0..0000000000
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IAmountMultiplierStrategy.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.l2jmobius.gameserver.model.drops.strategy;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.datatables.ItemTable;
-import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-
-/**
- * @author Battlecruiser
- */
-public interface IAmountMultiplierStrategy
-{
- IAmountMultiplierStrategy DROP = DEFAULT_STRATEGY(Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER);
- IAmountMultiplierStrategy SPOIL = DEFAULT_STRATEGY(Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER);
- IAmountMultiplierStrategy STATIC = (item, victim) -> 1;
-
- static IAmountMultiplierStrategy DEFAULT_STRATEGY(double defaultMultiplier)
- {
- return (item, victim) ->
- {
- double multiplier = 1;
- if (victim.isChampion())
- {
- multiplier *= item.getItemId() != Inventory.ADENA_ID ? Config.L2JMOD_CHAMPION_REWARDS_AMOUNT : Config.L2JMOD_CHAMPION_ADENAS_REWARDS_AMOUNT;
- }
- final Float dropAmountMultiplier = Config.RATE_DROP_AMOUNT_MULTIPLIER.get(item.getItemId());
- if (dropAmountMultiplier != null)
- {
- multiplier *= dropAmountMultiplier;
- }
- else if (ItemTable.getInstance().getTemplate(item.getItemId()).hasExImmediateEffect())
- {
- multiplier *= Config.RATE_HERB_DROP_AMOUNT_MULTIPLIER;
- }
- else if (victim.isRaid())
- {
- multiplier *= Config.RATE_RAID_DROP_AMOUNT_MULTIPLIER;
- }
- else
- {
- multiplier *= defaultMultiplier;
- }
- return multiplier;
- };
- }
-
- double getAmountMultiplier(GeneralDropItem item, L2Character victim);
-}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IChanceMultiplierStrategy.java b/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IChanceMultiplierStrategy.java
deleted file mode 100644
index 04c1f6b269..0000000000
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IChanceMultiplierStrategy.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.l2jmobius.gameserver.model.drops.strategy;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.datatables.ItemTable;
-import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-
-/**
- * @author Battlecruiser
- */
-public interface IChanceMultiplierStrategy
-{
- IChanceMultiplierStrategy DROP = DEFAULT_STRATEGY(Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER);
- IChanceMultiplierStrategy SPOIL = DEFAULT_STRATEGY(Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER);
- IChanceMultiplierStrategy STATIC = (item, victim) -> 1;
-
- IChanceMultiplierStrategy QUEST = (item, victim) ->
- {
- double championmult;
- if ((item.getItemId() == Inventory.ADENA_ID) || (item.getItemId() == Inventory.ANCIENT_ADENA_ID))
- {
- championmult = Config.L2JMOD_CHAMPION_ADENAS_REWARDS_CHANCE;
- }
- else
- {
- championmult = Config.L2JMOD_CHAMPION_REWARDS_CHANCE;
- }
-
- return (Config.L2JMOD_CHAMPION_ENABLE && (victim != null) && victim.isChampion()) ? (Config.RATE_QUEST_DROP * championmult) : Config.RATE_QUEST_DROP;
- };
-
- static IChanceMultiplierStrategy DEFAULT_STRATEGY(double defaultMultiplier)
- {
- return (item, victim) ->
- {
- float multiplier = 1;
- if (victim.isChampion())
- {
- multiplier *= item.getItemId() != Inventory.ADENA_ID ? Config.L2JMOD_CHAMPION_REWARDS_CHANCE : Config.L2JMOD_CHAMPION_ADENAS_REWARDS_CHANCE;
- }
- final Float dropChanceMultiplier = Config.RATE_DROP_CHANCE_MULTIPLIER.get(item.getItemId());
- if (dropChanceMultiplier != null)
- {
- multiplier *= dropChanceMultiplier;
- }
- else if (ItemTable.getInstance().getTemplate(item.getItemId()).hasExImmediateEffect())
- {
- multiplier *= Config.RATE_HERB_DROP_CHANCE_MULTIPLIER;
- }
- else if (victim.isRaid())
- {
- multiplier *= Config.RATE_RAID_DROP_CHANCE_MULTIPLIER;
- }
- else
- {
- multiplier *= defaultMultiplier;
- }
- return multiplier;
- };
- }
-
- double getChanceMultiplier(GeneralDropItem item, L2Character victim);
-}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IDropCalculationStrategy.java b/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IDropCalculationStrategy.java
deleted file mode 100644
index c516a86422..0000000000
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IDropCalculationStrategy.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.l2jmobius.gameserver.model.drops.strategy;
-
-import java.util.Collections;
-import java.util.List;
-
-import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
-import com.l2jmobius.gameserver.model.holders.ItemHolder;
-import com.l2jmobius.util.Rnd;
-
-/**
- * @author Battlecruiser
- */
-public interface IDropCalculationStrategy
-{
- IDropCalculationStrategy DEFAULT_STRATEGY = (item, victim, killer) ->
- {
- final double chance = item.getChance(victim, killer);
- if (chance > (Rnd.nextDouble() * 100))
- {
- int amountMultiply = 1;
- if (item.isPreciseCalculated() && (chance > 100))
- {
- amountMultiply = (int) chance / 100;
- if ((chance % 100) > (Rnd.nextDouble() * 100))
- {
- amountMultiply++;
- }
- }
-
- return Collections.singletonList(new ItemHolder(item.getItemId(), Rnd.get(item.getMin(victim, killer), item.getMax(victim, killer)) * amountMultiply));
- }
-
- return null;
- };
-
- List calculateDrops(GeneralDropItem item, L2Character victim, L2Character killer);
-}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IGroupedItemDropCalculationStrategy.java b/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IGroupedItemDropCalculationStrategy.java
deleted file mode 100644
index 8d6648902a..0000000000
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IGroupedItemDropCalculationStrategy.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.l2jmobius.gameserver.model.drops.strategy;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
-import com.l2jmobius.gameserver.model.drops.GroupedGeneralDropItem;
-import com.l2jmobius.gameserver.model.drops.IDropItem;
-import com.l2jmobius.gameserver.model.holders.ItemHolder;
-import com.l2jmobius.util.Rnd;
-
-/**
- * @author Battlecruiser
- */
-public interface IGroupedItemDropCalculationStrategy
-{
- /**
- * The default strategy used in L2J to calculate drops. When the group's chance raises over 100% and group has precise calculation, the dropped item's amount increases.
- */
- IGroupedItemDropCalculationStrategy DEFAULT_STRATEGY = new IGroupedItemDropCalculationStrategy()
- {
- private final Map singleItemCache = new ConcurrentHashMap<>();
-
- private GeneralDropItem getSingleItem(GroupedGeneralDropItem dropItem)
- {
- final GeneralDropItem item1 = dropItem.getItems().iterator().next();
- singleItemCache.putIfAbsent(dropItem, new GeneralDropItem(item1.getItemId(), item1.getMin(), item1.getMax(), (item1.getChance() * dropItem.getChance()) / 100, item1.getAmountStrategy(), item1.getChanceStrategy(), dropItem.getPreciseStrategy(), dropItem.getKillerChanceModifierStrategy(), item1.getDropCalculationStrategy()));
- return singleItemCache.get(dropItem);
- }
-
- @Override
- public List calculateDrops(GroupedGeneralDropItem dropItem, L2Character victim, L2Character killer)
- {
- if (dropItem.getItems().size() == 1)
- {
- return getSingleItem(dropItem).calculateDrops(victim, killer);
- }
-
- final GroupedGeneralDropItem normalized = dropItem.normalizeMe(victim, killer);
- if (normalized.getChance() > (Rnd.nextDouble() * 100))
- {
- final double random = Rnd.nextDouble() * 100;
- double totalChance = 0;
- for (GeneralDropItem item2 : normalized.getItems())
- {
- // Grouped item chance rates should not be modified (the whole magic was already done by normalizing thus the items' chance sum is always 100%).
- totalChance += Math.sqrt(item2.getChance());
- if (totalChance > random)
- {
- int amountMultiply = 1;
- if (dropItem.isPreciseCalculated() && (normalized.getChance() >= 100))
- {
- amountMultiply = (int) normalized.getChance() / 100;
- if ((normalized.getChance() % 100) > (Rnd.nextDouble() * 100))
- {
- amountMultiply++;
- }
- }
-
- return Collections.singletonList(new ItemHolder(item2.getItemId(), Rnd.get(item2.getMin(victim, killer), item2.getMax(victim, killer)) * amountMultiply));
- }
- }
- }
- return null;
- }
- };
-
- /**
- * This strategy calculates a group's drop by calculating drops of its individual items and merging its results.
- */
- IGroupedItemDropCalculationStrategy DISBAND_GROUP = (item, victim, killer) ->
- {
- final List dropped = new ArrayList<>();
- for (IDropItem dropItem : item.extractMe())
- {
- dropped.addAll(dropItem.calculateDrops(victim, killer));
- }
- return dropped.isEmpty() ? null : dropped;
- };
-
- /**
- * This strategy when group has precise calculation rolls multiple times over group to determine drops when group's chance raises over 100% instead of just multiplying the dropped item's amount. Thus it can produce different items from group at once.
- */
- IGroupedItemDropCalculationStrategy PRECISE_MULTIPLE_GROUP_ROLLS = (item, victim, killer) ->
- {
- if (!item.isPreciseCalculated())
- {
- // if item hasn't precise calculation there's no change from DEFAULT_STRATEGY
- return DEFAULT_STRATEGY.calculateDrops(item, victim, victim);
- }
- final GroupedGeneralDropItem newItem = new GroupedGeneralDropItem(item.getChance(), DEFAULT_STRATEGY, item.getKillerChanceModifierStrategy(), IPreciseDeterminationStrategy.NEVER);
- newItem.setItems(item.getItems());
- final GroupedGeneralDropItem normalized = newItem.normalizeMe(victim, killer);
- // Let's determine the number of rolls.
- int rolls = (int) (normalized.getChance() / 100);
- if ((Rnd.nextDouble() * 100) < (normalized.getChance() % 100))
- {
- rolls++;
- }
- final List dropped = new ArrayList<>(rolls);
- for (int i = 0; i < rolls; i++)
- {
- // As further normalizing on already normalized drop group does nothing, we can just pass the calculation to DEFAULT_STRATEGY with precise calculation disabled as we handle it.
- dropped.addAll(normalized.calculateDrops(victim, killer));
- }
- return dropped.isEmpty() ? null : dropped;
- };
-
- List calculateDrops(GroupedGeneralDropItem item, L2Character victim, L2Character killer);
-}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IKillerChanceModifierStrategy.java b/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IKillerChanceModifierStrategy.java
deleted file mode 100644
index 57a4b583c9..0000000000
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IKillerChanceModifierStrategy.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.l2jmobius.gameserver.model.drops.strategy;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
-import com.l2jmobius.gameserver.model.drops.IDropItem;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author Battlecruiser
- */
-public interface IKillerChanceModifierStrategy extends INonGroupedKillerChanceModifierStrategy
-{
- IKillerChanceModifierStrategy DEFAULT_STRATEGY = (item, victim, killer) ->
- {
- final int levelDifference = victim.getLevel() - killer.getLevel();
- if ((victim.isRaid()) && Config.DEEPBLUE_DROP_RULES_RAID)
- {
- // FIXME: Config?
- return Math.max(0, Math.min(1, (levelDifference * 0.15) + 1));
- }
- else if (Config.DEEPBLUE_DROP_RULES)
- {
- return Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0) / 100;
- }
- return 1;
- };
- INonGroupedKillerChanceModifierStrategy DEFAULT_NONGROUP_STRATEGY = (item, victim, killer) ->
- {
- if (((!(victim.isRaid())) && Config.DEEPBLUE_DROP_RULES) || ((victim.isRaid()) && Config.DEEPBLUE_DROP_RULES_RAID))
- {
- final int levelDifference = victim.getLevel() - killer.getLevel();
- if (item.getItemId() == Inventory.ADENA_ID)
- {
- return Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0) / 100;
- }
- return Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0) / 100;
- }
- return 1;
- };
-
- IKillerChanceModifierStrategy NO_RULES = (item, victim, killer) -> 1;
-
- double getKillerChanceModifier(IDropItem item, L2Character victim, L2Character killer);
-
- @Override
- default double getKillerChanceModifier(GeneralDropItem item, L2Character victim, L2Character killer)
- {
- return getKillerChanceModifier((IDropItem) item, victim, killer);
- }
-}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/INonGroupedKillerChanceModifierStrategy.java b/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/INonGroupedKillerChanceModifierStrategy.java
deleted file mode 100644
index be809ae392..0000000000
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/INonGroupedKillerChanceModifierStrategy.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.l2jmobius.gameserver.model.drops.strategy;
-
-import com.l2jmobius.gameserver.model.actor.L2Character;
-import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
-
-/**
- * @author Battlecruiser
- */
-public interface INonGroupedKillerChanceModifierStrategy
-{
- double getKillerChanceModifier(GeneralDropItem item, L2Character victim, L2Character killer);
-}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IPreciseDeterminationStrategy.java b/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IPreciseDeterminationStrategy.java
deleted file mode 100644
index 76815ff3c5..0000000000
--- a/trunk/java/com/l2jmobius/gameserver/model/drops/strategy/IPreciseDeterminationStrategy.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.l2jmobius.gameserver.model.drops.strategy;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.gameserver.model.drops.IDropItem;
-
-/**
- * @author Battlecruiser
- */
-public interface IPreciseDeterminationStrategy
-{
- IPreciseDeterminationStrategy ALWAYS = dropItem -> true;
-
- IPreciseDeterminationStrategy DEFAULT = dropItem -> Config.PRECISE_DROP_CALCULATION;
-
- IPreciseDeterminationStrategy NEVER = dropItem -> false;
-
- /**
- * @param dropItem
- * @return true if drop calculation strategy should use precise rules
- */
- boolean isPreciseCalculated(IDropItem dropItem);
-}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/event/LongTimeEvent.java b/trunk/java/com/l2jmobius/gameserver/model/event/LongTimeEvent.java
index 6d301ddfb0..d71604337d 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/event/LongTimeEvent.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/event/LongTimeEvent.java
@@ -39,7 +39,6 @@ import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.instancemanager.EventShrineManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.announce.EventAnnouncement;
-import com.l2jmobius.gameserver.model.drops.DropListScope;
import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.script.DateRange;
@@ -189,7 +188,7 @@ public class LongTimeEvent extends Quest
continue;
}
- _dropList.add((GeneralDropItem) DropListScope.STATIC.newDropItem(itemId, minCount, maxCount, finalChance));
+ _dropList.add(new GeneralDropItem(itemId, minCount, maxCount, finalChance));
}
catch (NumberFormatException nfe)
{
diff --git a/trunk/java/com/l2jmobius/gameserver/model/events/AbstractScript.java b/trunk/java/com/l2jmobius/gameserver/model/events/AbstractScript.java
index 7ee019a566..4e9bbfe022 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/events/AbstractScript.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/events/AbstractScript.java
@@ -23,12 +23,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -62,9 +58,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
-import com.l2jmobius.gameserver.model.drops.GroupedGeneralDropItem;
-import com.l2jmobius.gameserver.model.drops.IDropItem;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.entity.Fort;
import com.l2jmobius.gameserver.model.entity.Instance;
@@ -144,7 +137,6 @@ import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager;
import com.l2jmobius.gameserver.scripting.ScriptManager;
import com.l2jmobius.gameserver.util.MinionList;
import com.l2jmobius.util.Rnd;
-import com.l2jmobius.util.Util;
/**
* Abstract script.
@@ -2349,499 +2341,6 @@ public abstract class AbstractScript implements INamable
return false;
}
- /**
- * Gives an item to the player
- * @param player
- * @param item
- * @param victim the character that "dropped" the item
- * @return true if at least one item was given, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, IDropItem item, L2Character victim)
- {
- final List items = item.calculateDrops(victim, player);
- if ((items == null) || items.isEmpty())
- {
- return false;
- }
- giveItems(player, items);
- return true;
- }
-
- /**
- * Gives an item to the player
- * @param player
- * @param items
- */
- protected static void giveItems(L2PcInstance player, List items)
- {
- for (ItemHolder item : items)
- {
- giveItems(player, item);
- }
- }
-
- /**
- * Gives an item to the player
- * @param player
- * @param item
- * @param limit the maximum amount of items the player can have. Won't give more if this limit is reached.
- * @return true if at least one item was given to the player, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, ItemHolder item, long limit)
- {
- final long maxToGive = limit - player.getInventory().getInventoryItemCount(item.getId(), -1);
- if (maxToGive <= 0)
- {
- return false;
- }
- giveItems(player, item.getId(), Math.min(maxToGive, item.getCount()));
- return true;
- }
-
- protected static boolean giveItems(L2PcInstance player, ItemHolder item, long limit, boolean playSound)
- {
- final boolean drop = giveItems(player, item, limit);
- if (drop && playSound)
- {
- playSound(player, QuestSound.ITEMSOUND_QUEST_ITEMGET);
- }
- return drop;
- }
-
- /**
- * @param player
- * @param items
- * @param limit the maximum amount of items the player can have. Won't give more if this limit is reached.
- * @return true if at least one item was given to the player, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, List items, long limit)
- {
- boolean b = false;
- for (ItemHolder item : items)
- {
- b |= giveItems(player, item, limit);
- }
- return b;
- }
-
- protected static boolean giveItems(L2PcInstance player, List items, long limit, boolean playSound)
- {
- final boolean drop = giveItems(player, items, limit);
- if (drop && playSound)
- {
- playSound(player, QuestSound.ITEMSOUND_QUEST_ITEMGET);
- }
- return drop;
- }
-
- /**
- * @param player
- * @param items
- * @param limit the maximum amount of items the player can have. Won't give more if this limit is reached. If a no limit for an itemId is specified, item will always be given
- * @return true if at least one item was given to the player, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, List items, Map limit)
- {
- return giveItems(player, items, Util.mapToFunction(limit));
- }
-
- /**
- * @param player
- * @param items
- * @param limit the maximum amount of items the player can have. Won't give more if this limit is reached. If a no limit for an itemId is specified, item will always be given
- * @return true if at least one item was given to the player, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, List items, Function limit)
- {
- boolean b = false;
- for (ItemHolder item : items)
- {
- if (limit != null)
- {
- final Long longLimit = limit.apply(item.getId());
- // null -> no limit specified for that item id. This trick is to avoid limit.apply() be called twice (once for the null check)
- if (longLimit != null)
- {
- b |= giveItems(player, item, longLimit);
- continue; // the item is given, continue with next
- }
- }
- // da BIG else
- // no limit specified here (either limit or limit.apply(item.getId()) is null)
- b = true;
- giveItems(player, item);
- }
- return b;
- }
-
- protected static boolean giveItems(L2PcInstance player, List items, Function limit, boolean playSound)
- {
- final boolean drop = giveItems(player, items, limit);
- if (drop && playSound)
- {
- playSound(player, QuestSound.ITEMSOUND_QUEST_ITEMGET);
- }
- return drop;
- }
-
- protected static boolean giveItems(L2PcInstance player, List items, Map limit, boolean playSound)
- {
- return giveItems(player, items, Util.mapToFunction(limit), playSound);
- }
-
- /**
- * @param player
- * @param item
- * @param victim the character that "dropped" the item
- * @param limit the maximum amount of items the player can have. Won't give more if this limit is reached.
- * @return true if at least one item was given to the player, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, IDropItem item, L2Character victim, int limit)
- {
- return giveItems(player, item.calculateDrops(victim, player), limit);
- }
-
- protected static boolean giveItems(L2PcInstance player, IDropItem item, L2Character victim, int limit, boolean playSound)
- {
- final boolean drop = giveItems(player, item, victim, limit);
- if (drop && playSound)
- {
- playSound(player, QuestSound.ITEMSOUND_QUEST_ITEMGET);
- }
- return drop;
- }
-
- /**
- * @param player
- * @param item
- * @param victim the character that "dropped" the item
- * @param limit the maximum amount of items the player can have. Won't give more if this limit is reached. If a no limit for an itemId is specified, item will always be given
- * @return true if at least one item was given to the player, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, IDropItem item, L2Character victim, Map limit)
- {
- return giveItems(player, item.calculateDrops(victim, player), limit);
- }
-
- /**
- * @param player
- * @param item
- * @param victim the character that "dropped" the item
- * @param limit the maximum amount of items the player can have. Won't give more if this limit is reached. If a no limit for an itemId is specified, item will always be given
- * @return true if at least one item was given to the player, false otherwise
- */
- protected static boolean giveItems(L2PcInstance player, IDropItem item, L2Character victim, Function limit)
- {
- return giveItems(player, item.calculateDrops(victim, player), limit);
- }
-
- protected static boolean giveItems(L2PcInstance player, IDropItem item, L2Character victim, Map limit, boolean playSound)
- {
- return giveItems(player, item, victim, Util.mapToFunction(limit), playSound);
- }
-
- protected static boolean giveItems(L2PcInstance player, IDropItem item, L2Character victim, Function limit, boolean playSound)
- {
- final boolean drop = giveItems(player, item, victim, limit);
- if (drop && playSound)
- {
- playSound(player, QuestSound.ITEMSOUND_QUEST_ITEMGET);
- }
- return drop;
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, Collection items, Function limit, boolean playSound)
- {
- final Map> rewardedCounts = calculateDistribution(players, items, limit);
- // now give the calculated items to the players
- giveItems(rewardedCounts, playSound);
- return rewardedCounts;
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, Collection items, Map limit, boolean playSound)
- {
- return distributeItems(players, items, Util.mapToFunction(limit), playSound);
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, Collection items, long limit, boolean playSound)
- {
- return distributeItems(players, items, t -> limit, playSound);
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param item the items to distribute
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @return the counts of each items given to each player
- */
- protected static Map distributeItems(Collection players, ItemHolder item, long limit, boolean playSound)
- {
- final Map> distribution = distributeItems(players, Collections.singletonList(item), limit, playSound);
- final Map returnMap = new HashMap<>();
- for (Entry> entry : distribution.entrySet())
- {
- for (Entry entry2 : entry.getValue().entrySet())
- {
- returnMap.put(entry.getKey(), entry2.getValue());
- }
- }
- return returnMap;
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param killer the one who "kills" the victim
- * @param victim the character that "dropped" the item
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, IDropItem items, L2Character killer, L2Character victim, Function limit, boolean playSound)
- {
- return distributeItems(players, items.calculateDrops(victim, killer), limit, playSound);
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param killer the one who "kills" the victim
- * @param victim the character that "dropped" the item
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, IDropItem items, L2Character killer, L2Character victim, Map limit, boolean playSound)
- {
- return distributeItems(players, items.calculateDrops(victim, killer), limit, playSound);
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param killer the one who "kills" the victim
- * @param victim the character that "dropped" the item
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, IDropItem items, L2Character killer, L2Character victim, long limit, boolean playSound)
- {
- return distributeItems(players, items.calculateDrops(victim, killer), limit, playSound);
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param killer the one who "kills" the victim
- * @param victim the character that "dropped" the item
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @param smartDrop true if to not calculate a drop, which can't be given to any player 'cause of limits
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, GroupedGeneralDropItem items, L2Character killer, L2Character victim, Function limit, boolean playSound, boolean smartDrop)
- {
- GroupedGeneralDropItem toDrop;
- if (smartDrop)
- {
- toDrop = new GroupedGeneralDropItem(items.getChance(), items.getDropCalculationStrategy(), items.getKillerChanceModifierStrategy(), items.getPreciseStrategy());
- final List dropItems = new LinkedList<>(items.getItems());
- ITEM_LOOP: for (Iterator it = dropItems.iterator(); it.hasNext();)
- {
- final GeneralDropItem item = it.next();
- for (L2PcInstance player : players)
- {
- final int itemId = item.getItemId();
- if (player.getInventory().getInventoryItemCount(itemId, -1, true) < avoidNull(limit, itemId))
- {
- // we can give this item to this player
- continue ITEM_LOOP;
- }
- }
- // there's nobody to give this item to
- it.remove();
- }
- toDrop.setItems(dropItems);
- toDrop = toDrop.normalizeMe(victim, killer);
- }
- else
- {
- toDrop = items;
- }
- return distributeItems(players, toDrop, killer, victim, limit, playSound);
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param killer the one who "kills" the victim
- * @param victim the character that "dropped" the item
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @param smartDrop true if to not calculate a drop, which can't be given to any player
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, GroupedGeneralDropItem items, L2Character killer, L2Character victim, Map limit, boolean playSound, boolean smartDrop)
- {
- return distributeItems(players, items, killer, victim, Util.mapToFunction(limit), playSound, smartDrop);
- }
-
- /**
- * Distributes items to players equally
- * @param players the players to whom the items will be distributed
- * @param items the items to distribute
- * @param killer the one who "kills" the victim
- * @param victim the character that "dropped" the item
- * @param limit the limit what single player can have of each item
- * @param playSound if to play sound if a player gets at least one item
- * @param smartDrop true if to not calculate a drop, which can't be given to any player
- * @return the counts of each items given to each player
- */
- protected static Map> distributeItems(Collection players, GroupedGeneralDropItem items, L2Character killer, L2Character victim, long limit, boolean playSound, boolean smartDrop)
- {
- return distributeItems(players, items, killer, victim, t -> limit, playSound, smartDrop);
- }
-
- /**
- * @param players
- * @param items
- * @param limit
- * @return
- */
- private static Map> calculateDistribution(Collection players, Collection items, Function limit)
- {
- final Map> rewardedCounts = new HashMap<>();
- for (L2PcInstance player : players)
- {
- rewardedCounts.put(player, new HashMap());
- }
- NEXT_ITEM: for (ItemHolder item : items)
- {
- long equaldist = item.getCount() / players.size();
- long randomdist = item.getCount() % players.size();
- final List toDist = new ArrayList<>(players);
- do // this must happen at least once in order to get away already full players (and then equaldist can become nonzero)
- {
- for (Iterator it = toDist.iterator(); it.hasNext();)
- {
- final L2PcInstance player = it.next();
- if (!rewardedCounts.get(player).containsKey(item.getId()))
- {
- rewardedCounts.get(player).put(item.getId(), 0L);
- }
- final long maxGive = avoidNull(limit, item.getId()) - player.getInventory().getInventoryItemCount(item.getId(), -1, true) - rewardedCounts.get(player).get(item.getId());
- long toGive = equaldist;
- if (equaldist >= maxGive)
- {
- toGive = maxGive;
- randomdist += equaldist - maxGive; // overflown items are available to next players
- it.remove(); // this player is already full
- }
- rewardedCounts.get(player).put(item.getId(), rewardedCounts.get(player).get(item.getId()) + toGive);
- }
- if (toDist.isEmpty())
- {
- // there's no one to give items anymore, all players will be full when we give the items
- continue NEXT_ITEM;
- }
- equaldist = randomdist / toDist.size(); // the rest of items may be allowed to be equally distributed between remaining players
- randomdist %= toDist.size();
- }
- while (equaldist > 0);
- while (randomdist > 0)
- {
- if (toDist.isEmpty())
- {
- // we don't have any player left
- continue NEXT_ITEM;
- }
- final L2PcInstance player = toDist.get(getRandom(toDist.size()));
- // avoid null return
- final long maxGive = avoidNull(limit, item.getId()) - limit.apply(item.getId()) - player.getInventory().getInventoryItemCount(item.getId(), -1, true) - rewardedCounts.get(player).get(item.getId());
- if (maxGive > 0)
- {
- // we can add an item to player
- // so we add one item to player
- rewardedCounts.get(player).put(item.getId(), rewardedCounts.get(player).get(item.getId()) + 1);
- randomdist--;
- }
- toDist.remove(player); // Either way this player isn't allowable for next random award
- }
- }
- return rewardedCounts;
- }
-
- /**
- * This function is for avoidance null returns in function limits
- * @param the type of function arg
- * @param function the function
- * @param arg the argument
- * @return {@link Long#MAX_VALUE} if function.apply(arg) is null, function.apply(arg) otherwise
- */
- private static long avoidNull(Function function, T arg)
- {
- final Long longLimit = function.apply(arg);
- return longLimit == null ? Long.MAX_VALUE : longLimit;
- }
-
- /**
- * Distributes items to players
- * @param rewardedCounts A scheme of distribution items (the structure is: Map>)
- * @param playSound if to play sound if a player gets at least one item
- */
- private static void giveItems(Map> rewardedCounts, boolean playSound)
- {
- for (Entry> entry : rewardedCounts.entrySet())
- {
- final L2PcInstance player = entry.getKey();
- boolean playPlayerSound = false;
- for (Entry item : entry.getValue().entrySet())
- {
- if (item.getValue() >= 0)
- {
- playPlayerSound = true;
- giveItems(player, item.getKey(), item.getValue());
- }
- }
- if (playSound && playPlayerSound)
- {
- playSound(player, QuestSound.ITEMSOUND_QUEST_ITEMGET);
- }
- }
- }
-
/**
* Take an amount of a specified item from player's inventory.
* @param player the player whose item to take
diff --git a/trunk/java/com/l2jmobius/gameserver/model/itemcontainer/ItemContainer.java b/trunk/java/com/l2jmobius/gameserver/model/itemcontainer/ItemContainer.java
index ad1611d36c..384c40b277 100644
--- a/trunk/java/com/l2jmobius/gameserver/model/itemcontainer/ItemContainer.java
+++ b/trunk/java/com/l2jmobius/gameserver/model/itemcontainer/ItemContainer.java
@@ -236,7 +236,7 @@ public abstract class ItemContainer
item = olditem;
// Updates database
- if ((item.getId() == Inventory.ADENA_ID) && (count < (10000 * Config.RATE_DROP_AMOUNT_MULTIPLIER.getOrDefault(Inventory.ADENA_ID, 1f))))
+ if ((item.getId() == Inventory.ADENA_ID) && (count < (10000 * Config.RATE_DROP_AMOUNT_BY_ID.getOrDefault(Inventory.ADENA_ID, 1f))))
{
// Small adena changes won't be saved to database all the time
if ((GameTimeController.getInstance().getGameTicks() % 5) == 0)
@@ -287,7 +287,7 @@ public abstract class ItemContainer
item.setLastChange(L2ItemInstance.MODIFIED);
// Updates database
// If Adena drop rate is not present it will be x1.
- if ((itemId == Inventory.ADENA_ID) && (count < (10000 * Config.RATE_DROP_AMOUNT_MULTIPLIER.getOrDefault(Inventory.ADENA_ID, 1f))))
+ if ((itemId == Inventory.ADENA_ID) && (count < (10000 * Config.RATE_DROP_AMOUNT_BY_ID.getOrDefault(Inventory.ADENA_ID, 1f))))
{
// Small adena changes won't be saved to database all the time
if ((GameTimeController.getInstance().getGameTicks() % 5) == 0)
diff --git a/trunk/java/com/l2jmobius/util/Util.java b/trunk/java/com/l2jmobius/util/Util.java
index c04d6a60f6..8d59ac58ca 100644
--- a/trunk/java/com/l2jmobius/util/Util.java
+++ b/trunk/java/com/l2jmobius/util/Util.java
@@ -29,8 +29,6 @@ import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
import java.util.logging.Logger;
/**
@@ -223,16 +221,4 @@ public final class Util
.orElse(dateNowWithDifferentTime.with(TemporalAdjusters.next(daysOfWeek.get(0))));
// @formatter:on
}
-
- /**
- * This method translates map to function
- * @param key type of the map and argument of the function
- * @param value type of the map and return type of the function
- * @param map the input map
- * @return a function which returns map.get(arg)
- */
- public static Function mapToFunction(Map map)
- {
- return key -> map.get(key);
- }
}
| |