diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/listener/profession/FishingListener.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/listener/profession/FishingListener.java index 43c927ec..87719b7a 100644 --- a/spigot-plugin/src/main/java/net/Indyuce/mmocore/listener/profession/FishingListener.java +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/listener/profession/FishingListener.java @@ -7,7 +7,7 @@ import net.Indyuce.mmocore.experience.EXPSource; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.loot.LootBuilder; -import net.Indyuce.mmocore.loot.droptable.dropitem.fishing.FishingDropItem; +import net.Indyuce.mmocore.loot.fishing.FishingDropItem; import net.Indyuce.mmocore.manager.profession.FishingManager.FishingDropTable; import org.bukkit.Bukkit; import org.bukkit.Location; diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/RandomWeightedRoll.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/RandomWeightedRoll.java new file mode 100644 index 00000000..53e3fae2 --- /dev/null +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/RandomWeightedRoll.java @@ -0,0 +1,79 @@ +package net.Indyuce.mmocore.loot; + +import net.Indyuce.mmocore.api.player.PlayerData; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Random; + +/** + * Used whenever the chance stat appears in MMOCore + * + * @param Any weighted object, currently either fishing drop + * items or loot chest tiers. + */ +public class RandomWeightedRoll { + private final Collection collection; + private final T rolled; + + private static final Random RANDOM = new Random(); + + public RandomWeightedRoll(PlayerData player, Collection collection, double chanceWeight) { + this.collection = collection; + + double partialSum = 0; + final double randomCoefficient = RANDOM.nextDouble(), chance = chanceWeight * player.getStats().getStat("CHANCE"), sum = weightedSum(chance); + + for (T item : collection) { + partialSum += computeRealWeight(item, chance); + if (partialSum > randomCoefficient * sum) { + rolled = item; + return; + } + } + + throw new RuntimeException("Could not roll item"); + } + + /** + * The chance stat will make low weight items more + * likely to be chosen by the algorithm. + * + * @return Randomly computed item + */ + @NotNull + public T rollItem() { + return rolled; + } + + private double weightedSum(double chance) { + double sum = 0; + for (T item : collection) + sum += computeRealWeight(item, chance); + return sum; + } + + private static final double CHANCE_COEFFICIENT = 7. / 100; + + /** + * chance = 0 | tier chances are unchanged + * chance = +inf | uniform law for any drop item + * chance = 100 | all tier chances are taken their square root + * + * @return The real weight of an item considering the player's chance stat. + */ + private double computeRealWeight(T item, double chance) { + return Math.pow(item.getWeight(), 1 / Math.pow(1 + CHANCE_COEFFICIENT * chance, 1 / 3)); + } + + /* + Should this be used + private double getTierCoefficient(double initialTierChance, double chance) { + /** + * - Chance = 0 | tier coefficient is left unchanged. + * - Chance -> +oo | all tier coefficients are the same (1) + * - Chance = 50 | coefficients become their square roots + * + return Math.pow(initialTierChance, 1 / Math.pow(1 + CHANCE_COEF * chance, 1 / 3)); + }*/ +} diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/Weighted.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/Weighted.java new file mode 100644 index 00000000..4845b7a4 --- /dev/null +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/Weighted.java @@ -0,0 +1,6 @@ +package net.Indyuce.mmocore.loot; + +public interface Weighted { + + public double getWeight(); +} diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/ChestTier.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/ChestTier.java index 3d33006a..0e82e44d 100644 --- a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/ChestTier.java +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/ChestTier.java @@ -3,10 +3,11 @@ package net.Indyuce.mmocore.loot.chest; import io.lumine.mythic.lib.api.math.ScalingFormula; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.loot.Weighted; import net.Indyuce.mmocore.loot.droptable.DropTable; import org.bukkit.configuration.ConfigurationSection; -public class ChestTier { +public class ChestTier implements Weighted { private final TierEffect effect; private final ScalingFormula capacity; private final DropTable table; @@ -27,6 +28,11 @@ public class ChestTier { return chance; } + @Override + public double getWeight() { + return chance; + } + public DropTable getDropTable() { return table; } diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java index 8b39522e..07ccc933 100644 --- a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java @@ -5,6 +5,7 @@ import net.Indyuce.mmocore.api.event.LootChestSpawnEvent; import net.Indyuce.mmocore.api.player.PlayerActivity; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.loot.LootBuilder; +import net.Indyuce.mmocore.loot.RandomWeightedRoll; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -124,32 +125,7 @@ public class LootChestRegion { */ @NotNull public ChestTier rollTier(PlayerData player) { - double chance = player.getStats().getStat("CHANCE") * MMOCore.plugin.configManager.lootChestsChanceWeight; - - double sum = 0; - for (ChestTier tier : tiers) - sum += getTierCoefficient(tier.getChance(), chance); - Validate.isTrue(sum > 0, "No chest tier was found"); - - double cummulated = 0; - for (ChestTier tier : tiers) { - cummulated += getTierCoefficient(tier.getChance(), chance); - if (RANDOM.nextDouble() < cummulated / sum) - return tier; - } - - throw new RuntimeException("Could not roll chest tier"); - } - - private static final double CHANCE_COEF = 7 / 100; - - /** - * - Chance = 0 | tier coefficient is left unchanged. - * - Chance -> +oo | all tier coefficients are the same (1) - * - Chance = 50 | coefficients become their square roots - */ - private double getTierCoefficient(double initialTierChance, double chance) { - return Math.pow(initialTierChance, 1 / Math.pow(1 + CHANCE_COEF * chance, 1 / 3)); + return new RandomWeightedRoll<>(player, tiers, MMOCore.plugin.configManager.lootChestsChanceWeight).rollItem(); } public Location getRandomLocation(Location center) { diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/fishing/FishingDropItem.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/fishing/FishingDropItem.java similarity index 86% rename from spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/fishing/FishingDropItem.java rename to spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/fishing/FishingDropItem.java index 7762aa7b..b7ef45f4 100644 --- a/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/fishing/FishingDropItem.java +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/loot/fishing/FishingDropItem.java @@ -1,15 +1,16 @@ -package net.Indyuce.mmocore.loot.droptable.dropitem.fishing; +package net.Indyuce.mmocore.loot.fishing; import io.lumine.mythic.lib.api.MMOLineConfig; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.util.math.formula.RandomAmount; import net.Indyuce.mmocore.loot.LootBuilder; +import net.Indyuce.mmocore.loot.Weighted; import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem; import org.apache.commons.lang.Validate; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; -public class FishingDropItem { +public class FishingDropItem implements Weighted { private final RandomAmount experience, tugs; private final DropItem dropItem; @@ -23,9 +24,9 @@ public class FishingDropItem { Validate.isTrue(dropItem.getWeight() > 0, "A fishing drop table item must have a strictly positive weight"); } - @Deprecated - public int getWeight() { - return (int) Math.floor(getItem().getWeight()); + @Override + public double getWeight() { + return dropItem.getWeight(); } public DropItem getItem() { diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java index bbf3ce55..c9ca4bbf 100644 --- a/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java @@ -27,7 +27,7 @@ public class ConfigManager { public String partyChatPrefix, noSkillBoundPlaceholder; public ChatColor staminaFull, staminaHalf, staminaEmpty; public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown; - public double lootChestsChanceWeight; + public double lootChestsChanceWeight, fishingDropsChanceWeight; public int maxPartyLevelDifference; private final FileConfiguration messages; @@ -100,6 +100,7 @@ public class ConfigManager { globalSkillCooldown = MMOCore.plugin.getConfig().getLong("global-skill-cooldown") * 50; noSkillBoundPlaceholder = getSimpleMessage("no-skill-placeholder").message(); lootChestsChanceWeight = MMOCore.plugin.getConfig().getDouble("chance-stat-weight.loot-chests"); + fishingDropsChanceWeight = MMOCore.plugin.getConfig().getDouble("chance-stat-weight.fishing-drops"); maxPartyLevelDifference = MMOCore.plugin.getConfig().getInt("party.max-level-difference"); staminaFull = getColorOrDefault("stamina-whole", ChatColor.GREEN); diff --git a/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java b/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java index e794c9e3..aad6403d 100644 --- a/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java +++ b/spigot-plugin/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java @@ -3,9 +3,10 @@ package net.Indyuce.mmocore.manager.profession; import io.lumine.mythic.lib.api.MMOLineConfig; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.loot.RandomWeightedRoll; import net.Indyuce.mmocore.loot.chest.condition.Condition; import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance; -import net.Indyuce.mmocore.loot.droptable.dropitem.fishing.FishingDropItem; +import net.Indyuce.mmocore.loot.fishing.FishingDropItem; import org.apache.commons.lang.Validate; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -16,8 +17,6 @@ import java.util.logging.Level; public class FishingManager extends SpecificProfessionManager { private final Set tables = new LinkedHashSet<>(); - private static final Random RANDOM = new Random(); - public FishingManager() { super("on-fish"); } @@ -96,25 +95,12 @@ public class FishingManager extends SpecificProfessionManager { /** * The chance stat will make low weight items more - * likely to be chosen by the algorithm + * likely to be chosen by the algorithm. * * @return Randomly computed fishing drop item */ public FishingDropItem getRandomItem(PlayerData player) { - double chance = player.getStats().getStat("CHANCE"); - - //chance=0 ->the tier.chance remains the same - //chance ->+inf -> the tier.chance becomes the same for everyone, uniform law - //chance=8-> tierChance=sqrt(tierChance) - double sum = 0; - double randomCoefficient=RANDOM.nextDouble(); - for (FishingDropItem item : items) { - sum += Math.pow(item.getItem().getWeight(), 1 / Math.log(1 + chance)); - if(sum(player, items, MMOCore.plugin.configManager.fishingDropsChanceWeight).rollItem(); } } diff --git a/spigot-plugin/src/main/resources/config.yml b/spigot-plugin/src/main/resources/config.yml index 141b310d..93027bb8 100644 --- a/spigot-plugin/src/main/resources/config.yml +++ b/spigot-plugin/src/main/resources/config.yml @@ -85,6 +85,7 @@ guild-plugin: mmocore # all set to 1 by default, this option is really server specific chance-stat-weight: loot-chests: 1 + fishing-drops: 1 # Whether blocks generated with a "cobblegenerator" should # provide the player with experience points or not