IGroupedItemDropCalculationStrategy.java 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Copyright (C) 2004-2015 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.model.drops.strategy;
  20. import java.util.ArrayList;
  21. import java.util.Collections;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.concurrent.ConcurrentHashMap;
  25. import com.l2jserver.gameserver.model.actor.L2Character;
  26. import com.l2jserver.gameserver.model.drops.GeneralDropItem;
  27. import com.l2jserver.gameserver.model.drops.GroupedGeneralDropItem;
  28. import com.l2jserver.gameserver.model.drops.IDropItem;
  29. import com.l2jserver.gameserver.model.holders.ItemHolder;
  30. import com.l2jserver.util.Rnd;
  31. /**
  32. * @author Battlecruiser
  33. */
  34. public interface IGroupedItemDropCalculationStrategy
  35. {
  36. /**
  37. * 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.
  38. */
  39. public static final IGroupedItemDropCalculationStrategy DEFAULT_STRATEGY = new IGroupedItemDropCalculationStrategy()
  40. {
  41. private final Map<GroupedGeneralDropItem, GeneralDropItem> singleItemCache = new ConcurrentHashMap<>();
  42. private GeneralDropItem getSingleItem(GroupedGeneralDropItem dropItem)
  43. {
  44. final GeneralDropItem item1 = dropItem.getItems().iterator().next();
  45. 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()));
  46. return singleItemCache.get(dropItem);
  47. }
  48. @Override
  49. public List<ItemHolder> calculateDrops(GroupedGeneralDropItem dropItem, L2Character victim, L2Character killer)
  50. {
  51. if (dropItem.getItems().size() == 1)
  52. {
  53. return getSingleItem(dropItem).calculateDrops(victim, killer);
  54. }
  55. GroupedGeneralDropItem normalized = dropItem.normalizeMe(victim, killer);
  56. if (normalized.getChance() > (Rnd.nextDouble() * 100))
  57. {
  58. final double random = (Rnd.nextDouble() * 100);
  59. double totalChance = 0;
  60. for (GeneralDropItem item2 : normalized.getItems())
  61. {
  62. // Grouped item chance rates should not be modified (the whole magic was already done by normalizing thus the items' chance sum is always 100%).
  63. totalChance += item2.getChance();
  64. if (totalChance > random)
  65. {
  66. int amountMultiply = 1;
  67. if (dropItem.isPreciseCalculated() && (normalized.getChance() >= 100))
  68. {
  69. amountMultiply = (int) (normalized.getChance()) / 100;
  70. if ((normalized.getChance() % 100) > (Rnd.nextDouble() * 100))
  71. {
  72. amountMultiply++;
  73. }
  74. }
  75. return Collections.singletonList(new ItemHolder(item2.getItemId(), Rnd.get(item2.getMin(victim), item2.getMax(victim)) * amountMultiply));
  76. }
  77. }
  78. }
  79. return null;
  80. }
  81. };
  82. /**
  83. * This strategy calculates a group's drop by calculating drops of its individual items and merging its results.
  84. */
  85. public static final IGroupedItemDropCalculationStrategy DISBAND_GROUP = (item, victim, killer) ->
  86. {
  87. List<ItemHolder> dropped = new ArrayList<>();
  88. for (IDropItem dropItem : item.extractMe())
  89. {
  90. dropped.addAll(dropItem.calculateDrops(victim, killer));
  91. }
  92. return dropped.isEmpty() ? null : dropped;
  93. };
  94. /**
  95. * 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.
  96. */
  97. public static final IGroupedItemDropCalculationStrategy PRECISE_MULTIPLE_GROUP_ROLLS = (item, victim, killer) ->
  98. {
  99. if (!item.isPreciseCalculated())
  100. {
  101. // if item hasn't precise calculation there's no change from DEFAULT_STRATEGY
  102. return DEFAULT_STRATEGY.calculateDrops(item, victim, victim);
  103. }
  104. GroupedGeneralDropItem newItem = new GroupedGeneralDropItem(item.getChance(), DEFAULT_STRATEGY, item.getKillerChanceModifierStrategy(), IPreciseDeterminationStrategy.NEVER);
  105. newItem.setItems(item.getItems());
  106. GroupedGeneralDropItem normalized = newItem.normalizeMe(victim, killer);
  107. // Let's determine the number of rolls.
  108. int rolls = (int) (normalized.getChance() / 100);
  109. if ((Rnd.nextDouble() * 100) < (normalized.getChance() % 100))
  110. {
  111. rolls++;
  112. }
  113. List<ItemHolder> dropped = new ArrayList<>(rolls);
  114. for (int i = 0; i < rolls; i++)
  115. {
  116. // 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.
  117. dropped.addAll(normalized.calculateDrops(victim, killer));
  118. }
  119. return dropped.isEmpty() ? null : dropped;
  120. };
  121. public List<ItemHolder> calculateDrops(GroupedGeneralDropItem item, L2Character victim, L2Character killer);
  122. }