mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-22 05:06:45 +01:00
parent
248116df21
commit
e886a16388
@ -1,3 +1,10 @@
|
||||
Version 2.2.018
|
||||
Fixed a probability bug where certain skills would max out in chance to succeed well before they were supposed to (such as Dodge)
|
||||
(Codebase) Added more unit tests for Probability and RNG
|
||||
|
||||
NOTES:
|
||||
This probability bug was a big oopsie and showed a gap in unit test coverage, I've added that coverage and a bug like this in theory shouldn't happen again.
|
||||
|
||||
Version 2.2.017
|
||||
Fixed a bug with default Mace permissions (thanks SrBedrock)
|
||||
Fixed Blast Mining being almost completely broken
|
||||
|
@ -59,9 +59,6 @@ public class AcrobaticsCommand extends SkillCommand {
|
||||
|
||||
messages.add(getStatMessage(SubSkillType.ACROBATICS_ROLL, rollStrings[0])
|
||||
+ (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", rollStrings[1]) : ""));
|
||||
|
||||
/*messages.add(getStatMessage(true, false, SubSkillType.ACROBATICS_ROLL, String.valueOf(graceChance))
|
||||
+ (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", String.valueOf(graceChanceLucky)) : ""));*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,8 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public abstract class SkillCommand implements TabExecutor {
|
||||
public static final String ABILITY_GENERIC_TEMPLATE_CUSTOM = "Ability.Generic.Template.Custom";
|
||||
public static final String ABILITY_GENERIC_TEMPLATE = "Ability.Generic.Template";
|
||||
protected PrimarySkillType skill;
|
||||
|
||||
protected DecimalFormat percent = new DecimalFormat("##0.00%");
|
||||
@ -163,8 +165,6 @@ public abstract class SkillCommand implements TabExecutor {
|
||||
/*
|
||||
* CHILD SKILLS
|
||||
*/
|
||||
|
||||
|
||||
var parents = mcMMO.p.getSkillTools().getChildSkillParents(skill);
|
||||
|
||||
//TODO: Add JSON here
|
||||
@ -186,28 +186,7 @@ public abstract class SkillCommand implements TabExecutor {
|
||||
player.sendMessage(LocaleLoader.getString("Commands.XPGain.Overhaul", LocaleLoader.getString("Commands.XPGain.Child")));
|
||||
|
||||
player.sendMessage(LocaleLoader.getString("Effects.Child.Overhaul", skillValue, parentMessage.toString()));
|
||||
//LEVEL
|
||||
//player.sendMessage(LocaleLoader.getString("Effects.Child.Overhaul", skillValue, skillValue));
|
||||
|
||||
}
|
||||
/*
|
||||
if (!SkillTools.isChildSkill(skill)) {
|
||||
player.sendMessage(LocaleLoader.getString("Skills.Header", skillName));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.XPGain", LocaleLoader.getString("Commands.XPGain." + StringUtils.getCapitalized(skill.toString()))));
|
||||
player.sendMessage(LocaleLoader.getString("Effects.Level", skillValue, mcMMOPlayer.getSkillXpLevel(skill), mcMMOPlayer.getXpToLevel(skill)));
|
||||
} else {
|
||||
player.sendMessage(LocaleLoader.getString("Skills.Header", skillName + " " + LocaleLoader.getString("Skills.Child")));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.XPGain", LocaleLoader.getString("Commands.XPGain.Child")));
|
||||
player.sendMessage(LocaleLoader.getString("Effects.Child", skillValue));
|
||||
|
||||
player.sendMessage(LocaleLoader.getString("Skills.Header", LocaleLoader.getString("Skills.Parents")));
|
||||
Set<PrimarySkillType> parents = FamilyTree.getParents(skill);
|
||||
|
||||
for (PrimarySkillType parent : parents) {
|
||||
player.sendMessage(parent.getName() + " - " + LocaleLoader.getString("Effects.Level", mcMMOPlayer.getSkillLevel(parent), mcMMOPlayer.getSkillXpLevel(parent), mcMMOPlayer.getXpToLevel(parent)));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -222,10 +201,6 @@ public abstract class SkillCommand implements TabExecutor {
|
||||
return Math.min((int) skillValue, maxLevel) / rankChangeLevel;
|
||||
}
|
||||
|
||||
// protected String[] getAbilityDisplayValues(SkillActivationType skillActivationType, Player player, SubSkillType subSkill) {
|
||||
// return RandomChanceUtil.calculateAbilityDisplayValues(skillActivationType, player, subSkill);
|
||||
// }
|
||||
|
||||
protected String[] calculateLengthDisplayValues(Player player, float skillValue) {
|
||||
int maxLength = mcMMO.p.getSkillTools().getSuperAbilityMaxLength(mcMMO.p.getSkillTools().getSuperAbility(skill));
|
||||
int abilityLengthVar = mcMMO.p.getAdvancedConfig().getAbilityLength();
|
||||
@ -252,14 +227,19 @@ public abstract class SkillCommand implements TabExecutor {
|
||||
return getStatMessage(false, false, subSkillType, vars);
|
||||
}
|
||||
|
||||
protected String getStatMessage(boolean isExtra, boolean isCustom, SubSkillType subSkillType, String... vars) {
|
||||
String templateKey = isCustom ? "Ability.Generic.Template.Custom" : "Ability.Generic.Template";
|
||||
String statDescriptionKey = !isExtra ? subSkillType.getLocaleKeyStatDescription() : subSkillType.getLocaleKeyStatExtraDescription();
|
||||
protected String getStatMessage(boolean isExtra, boolean isCustom,
|
||||
@NotNull SubSkillType subSkillType, String... vars) {
|
||||
final String templateKey = isCustom ? ABILITY_GENERIC_TEMPLATE_CUSTOM : ABILITY_GENERIC_TEMPLATE;
|
||||
final String statDescriptionKey = !isExtra
|
||||
? subSkillType.getLocaleKeyStatDescription()
|
||||
: subSkillType.getLocaleKeyStatExtraDescription();
|
||||
|
||||
if (isCustom)
|
||||
if (isCustom) {
|
||||
return LocaleLoader.getString(templateKey, LocaleLoader.getString(statDescriptionKey, vars));
|
||||
else {
|
||||
String[] mergedList = NotificationManager.addItemToFirstPositionOfArray(LocaleLoader.getString(statDescriptionKey), vars);
|
||||
} else {
|
||||
final String[] mergedList
|
||||
= NotificationManager.addItemToFirstPositionOfArray(
|
||||
LocaleLoader.getString(statDescriptionKey), vars);
|
||||
return LocaleLoader.getString(templateKey, mergedList);
|
||||
}
|
||||
}
|
||||
@ -276,8 +256,6 @@ public abstract class SkillCommand implements TabExecutor {
|
||||
|
||||
protected abstract void permissionsCheck(Player player);
|
||||
|
||||
//protected abstract List<String> effectsDisplay();
|
||||
|
||||
protected abstract List<String> statsDisplay(Player player, float skillValue, boolean hasEndurance, boolean isLucky);
|
||||
|
||||
protected abstract List<Component> getTextComponents(Player player);
|
||||
|
@ -41,7 +41,7 @@ public class ProbabilityUtil {
|
||||
public static double chanceOfSuccessPercentage(@Nullable McMMOPlayer mmoPlayer,
|
||||
@NotNull SubSkillType subSkillType,
|
||||
boolean isLucky) {
|
||||
Probability probability = getSubSkillProbability(subSkillType, mmoPlayer);
|
||||
final Probability probability = getSubSkillProbability(subSkillType, mmoPlayer);
|
||||
//Probability values are on a 0-1 scale and need to be "transformed" into a 1-100 scale
|
||||
double percentageValue = probability.getValue(); //Doesn't need to be scaled
|
||||
|
||||
@ -437,7 +437,7 @@ public class ProbabilityUtil {
|
||||
return Probability.ofPercent(ceiling);
|
||||
}
|
||||
|
||||
double odds = (skillLevel / maxBonusLevel) * 100D;
|
||||
double odds = ((skillLevel / maxBonusLevel) * ceiling);
|
||||
|
||||
// make sure the odds aren't lower or higher than the floor or ceiling
|
||||
return Probability.ofPercent(Math.min(Math.max(floor, odds), ceiling));
|
||||
|
@ -12,6 +12,8 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gmail.nossr50.datatypes.skills.PrimarySkillType.ACROBATICS;
|
||||
import static com.gmail.nossr50.datatypes.skills.PrimarySkillType.MINING;
|
||||
import static com.gmail.nossr50.datatypes.skills.SubSkillType.*;
|
||||
import static com.gmail.nossr50.util.random.ProbabilityTestUtils.assertProbabilityExpectations;
|
||||
import static com.gmail.nossr50.util.random.ProbabilityUtil.calculateCurrentSkillProbability;
|
||||
@ -68,9 +70,106 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
|
||||
assertProbabilityExpectations(20, probability);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> provideSkillProbabilityTestData() {
|
||||
return Stream.of(
|
||||
// skillLevel, floor, ceiling, maxBonusLevel, expectedValue
|
||||
|
||||
// 20% chance at skill level 1000
|
||||
Arguments.of(1000, 0, 20, 1000, 0.2),
|
||||
// 10% chance at skill level 500
|
||||
Arguments.of(500, 0, 20, 1000, 0.1),
|
||||
// 5% chance at skill level 250
|
||||
Arguments.of(250, 0, 20, 1000, 0.05),
|
||||
// 0% chance at skill level 0
|
||||
Arguments.of(0, 0, 20, 1000, 0.0),
|
||||
// 0% chance at skill level 1000
|
||||
Arguments.of(1000, 0, 0, 1000, 0.0),
|
||||
// 1% chance at skill level 1000
|
||||
Arguments.of(1000, 0, 1, 1000, 0.01)
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideSkillProbabilityTestData")
|
||||
void testCalculateCurrentSkillProbability(double skillLevel, double floor, double ceiling, double maxBonusLevel,
|
||||
double expectedValue) {
|
||||
// When
|
||||
final Probability probability = calculateCurrentSkillProbability(skillLevel, floor, ceiling, maxBonusLevel);
|
||||
|
||||
// Then
|
||||
assertEquals(expectedValue, probability.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateCurrentSkillProbabilityShouldBeTwenty() {
|
||||
final Probability probability = calculateCurrentSkillProbability(1000, 0, 20, 1000);
|
||||
assertEquals(0.2D, probability.getValue());
|
||||
public void getRNGDisplayValuesShouldReturn10PercentForDodge() {
|
||||
// Given
|
||||
when(advancedConfig.getMaximumProbability(ACROBATICS_DODGE)).thenReturn(20D);
|
||||
when(advancedConfig.getMaxBonusLevel(ACROBATICS_DODGE)).thenReturn(1000);
|
||||
mmoPlayer.modifySkill(ACROBATICS, 500);
|
||||
|
||||
// When & Then
|
||||
final String[] rngDisplayValues = ProbabilityUtil.getRNGDisplayValues(mmoPlayer, ACROBATICS_DODGE);
|
||||
assertEquals("10.00%", rngDisplayValues[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRNGDisplayValuesShouldReturn20PercentForDodge() {
|
||||
// Given
|
||||
when(advancedConfig.getMaximumProbability(ACROBATICS_DODGE)).thenReturn(20D);
|
||||
when(advancedConfig.getMaxBonusLevel(ACROBATICS_DODGE)).thenReturn(1000);
|
||||
mmoPlayer.modifySkill(ACROBATICS, 1000);
|
||||
|
||||
// When & then
|
||||
final String[] rngDisplayValues = ProbabilityUtil.getRNGDisplayValues(mmoPlayer, ACROBATICS_DODGE);
|
||||
assertEquals("20.00%", rngDisplayValues[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRNGDisplayValuesShouldReturn0PercentForDodge() {
|
||||
// Given
|
||||
when(advancedConfig.getMaximumProbability(ACROBATICS_DODGE)).thenReturn(20D);
|
||||
when(advancedConfig.getMaxBonusLevel(ACROBATICS_DODGE)).thenReturn(1000);
|
||||
mmoPlayer.modifySkill(ACROBATICS, 0);
|
||||
|
||||
// When & then
|
||||
final String[] rngDisplayValues = ProbabilityUtil.getRNGDisplayValues(mmoPlayer, ACROBATICS_DODGE);
|
||||
assertEquals("0.00%", rngDisplayValues[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRNGDisplayValuesShouldReturn10PercentForDoubleDrops() {
|
||||
// Given
|
||||
when(advancedConfig.getMaximumProbability(MINING_DOUBLE_DROPS)).thenReturn(100D);
|
||||
when(advancedConfig.getMaxBonusLevel(MINING_DOUBLE_DROPS)).thenReturn(1000);
|
||||
mmoPlayer.modifySkill(MINING, 100);
|
||||
|
||||
// When & Then
|
||||
final String[] rngDisplayValues = ProbabilityUtil.getRNGDisplayValues(mmoPlayer, MINING_DOUBLE_DROPS);
|
||||
assertEquals("10.00%", rngDisplayValues[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRNGDisplayValuesShouldReturn50PercentForDoubleDrops() {
|
||||
// Given
|
||||
when(advancedConfig.getMaximumProbability(MINING_DOUBLE_DROPS)).thenReturn(100D);
|
||||
when(advancedConfig.getMaxBonusLevel(MINING_DOUBLE_DROPS)).thenReturn(1000);
|
||||
mmoPlayer.modifySkill(MINING, 500);
|
||||
|
||||
// When & Then
|
||||
final String[] rngDisplayValues = ProbabilityUtil.getRNGDisplayValues(mmoPlayer, MINING_DOUBLE_DROPS);
|
||||
assertEquals("50.00%", rngDisplayValues[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRNGDisplayValuesShouldReturn100PercentForDoubleDrops() {
|
||||
// Given
|
||||
when(advancedConfig.getMaximumProbability(MINING_DOUBLE_DROPS)).thenReturn(100D);
|
||||
when(advancedConfig.getMaxBonusLevel(MINING_DOUBLE_DROPS)).thenReturn(1000);
|
||||
mmoPlayer.modifySkill(MINING, 1000);
|
||||
|
||||
// When & Then
|
||||
final String[] rngDisplayValues = ProbabilityUtil.getRNGDisplayValues(mmoPlayer, MINING_DOUBLE_DROPS);
|
||||
assertEquals("100.00%", rngDisplayValues[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user