RandomChanceUtil refactor part 3

This commit is contained in:
nossr50 2021-02-18 12:48:16 -08:00
parent fe889cf1c5
commit e30c7110eb
10 changed files with 65 additions and 60 deletions

View File

@ -1,4 +1,6 @@
Version 2.1.175
(API) Many skills with RNG elements now send out a SubSkillEvent (which can be used to modify probability or cancel the results), some skills without RNG still send out this event when activated, this event is cancellable so it can be used to make a skill fail
Treasure drop rate from Shake, Fishing, Hylian, and Excavation now benefit from the Luck perk
Added a setting to chat.yml to toggle sending party or admin chat messages to console
Added a set of "mastery" subskills meant for end game progression
Added the mastery subskill 'Mother Lode' to Mining

View File

@ -28,6 +28,8 @@ import org.bukkit.Color;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
@ -215,7 +217,7 @@ public enum PrimarySkillType {
}
}
public static PrimarySkillType bySecondaryAbility(SubSkillType subSkillType) {
public static @Nullable PrimarySkillType bySecondaryAbility(@NotNull SubSkillType subSkillType) {
for (PrimarySkillType type : values()) {
if (type.getSkillAbilities().contains(subSkillType)) {
return type;

View File

@ -11,10 +11,10 @@ import org.jetbrains.annotations.NotNull;
* Generic event for mcMMO skill handling.
*/
public abstract class McMMOPlayerSkillEvent extends PlayerEvent {
protected PrimarySkillType skill;
protected @NotNull PrimarySkillType skill;
protected int skillLevel;
protected McMMOPlayerSkillEvent(Player player, PrimarySkillType skill) {
protected McMMOPlayerSkillEvent(@NotNull Player player, @NotNull PrimarySkillType skill) {
super(player);
this.skill = skill;
this.skillLevel = UserManager.getPlayer(player).getSkillLevel(skill);
@ -23,7 +23,7 @@ public abstract class McMMOPlayerSkillEvent extends PlayerEvent {
/**
* @return The skill involved in this event
*/
public PrimarySkillType getSkill() {
public @NotNull PrimarySkillType getSkill() {
return skill;
}

View File

@ -1,48 +1,36 @@
package com.gmail.nossr50.events.skills.secondaryabilities;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
import com.gmail.nossr50.events.skills.McMMOPlayerSkillEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.jetbrains.annotations.NotNull;
public class SubSkillEvent extends McMMOPlayerSkillEvent implements Cancellable {
private SubSkillType subSkillType;
private final @NotNull SubSkillType subSkillType;
private boolean cancelled = false;
private double resultModifier = 1.0D;
/**
* Only skills using the old system will fire this event
* @param player target player
* @param subSkillType target subskill
* @Deprecated Skills will be using a new system stemming from the AbstractSubSkill class so make sure you check for both events, this event will be removed eventually.
*/
@Deprecated
public SubSkillEvent(Player player, SubSkillType subSkillType) {
super(player, PrimarySkillType.bySecondaryAbility(subSkillType));
public SubSkillEvent(@NotNull Player player, @NotNull SubSkillType subSkillType) {
super(player, subSkillType.getParentSkill());
this.subSkillType = subSkillType;
}
/**
* Only skills using the old system will fire this event
* @param player target player
* @param subSkillType target subskill
* @param resultModifier a value multiplied against the final result of the dice roll, typically between 0-1.0
* @Deprecated Skills will be using a new system stemming from the AbstractSubSkill class so make sure you check for both events, this event will be removed eventually.
* @param resultModifier a value multiplied against the probability (1.5 would increase probability by 50%)
*/
@Deprecated
public SubSkillEvent(Player player, SubSkillType subSkillType, double resultModifier) {
super(player, PrimarySkillType.bySecondaryAbility(subSkillType));
public SubSkillEvent(@NotNull Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
super(player, subSkillType.getParentSkill());
this.subSkillType = subSkillType;
this.resultModifier = resultModifier;
}
public SubSkillEvent(Player player, AbstractSubSkill abstractSubSkill)
{
super(player, abstractSubSkill.getPrimarySkill());
}
public double getResultModifier() {
return resultModifier;
}
@ -55,7 +43,7 @@ public class SubSkillEvent extends McMMOPlayerSkillEvent implements Cancellable
* Gets the SubSkillType involved in the event
* @return the SubSkillType
*/
public SubSkillType getSubSkillType() {
public @NotNull SubSkillType getSubSkillType() {
return subSkillType;
}

View File

@ -10,7 +10,6 @@ import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
@ -116,10 +115,10 @@ public class ArcheryManager extends SkillManager {
* @param oldDamage The raw damage value of this arrow before we modify it
*/
public double skillShot(double oldDamage) {
if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.ARCHERY_SKILL_SHOT, getPlayer())) {
if (SkillUtils.isNonRNGSkillActivationSuccessful(SubSkillType.ARCHERY_SKILL_SHOT, getPlayer())) {
return Archery.getSkillShotBonusDamage(getPlayer(), oldDamage);
} else {
return oldDamage;
}
return Archery.getSkillShotBonusDamage(getPlayer(), oldDamage);
}
}

View File

@ -11,8 +11,10 @@ import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.random.SkillProbabilityType;
import com.gmail.nossr50.util.skills.*;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
@ -69,11 +71,11 @@ public class AxesManager extends SkillManager {
* Handle the effects of the Axe Mastery ability
*/
public double axeMastery() {
if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.AXES_AXE_MASTERY, getPlayer())) {
return 0;
if (SkillUtils.isNonRNGSkillActivationSuccessful(SubSkillType.AXES_AXE_MASTERY, getPlayer())) {
return Axes.getAxeMasteryBonusDamage(getPlayer());
}
return Axes.getAxeMasteryBonusDamage(getPlayer());
return 0;
}
/**

View File

@ -17,7 +17,6 @@ import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
@ -72,7 +71,7 @@ public class UnarmedManager extends SkillManager {
}
public boolean blockCrackerCheck(@NotNull BlockState blockState) {
if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.UNARMED_BLOCK_CRACKER, getPlayer())) {
if (!SkillUtils.isNonRNGSkillActivationSuccessful(SubSkillType.UNARMED_BLOCK_CRACKER, getPlayer())) {
return false;
}
@ -149,11 +148,11 @@ public class UnarmedManager extends SkillManager {
* Handle the effects of the Iron Arm ability
*/
public double calculateSteelArmStyleDamage() {
if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.UNARMED_STEEL_ARM_STYLE, getPlayer())) {
return 0;
if (SkillUtils.isNonRNGSkillActivationSuccessful(SubSkillType.UNARMED_STEEL_ARM_STYLE, getPlayer())) {
return getSteelArmStyleDamage();
}
return getSteelArmStyleDamage();
return 0;
}
public double getSteelArmStyleDamage() {

View File

@ -9,7 +9,6 @@ import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
import com.gmail.nossr50.events.experience.McMMOPlayerLevelChangeEvent;
import com.gmail.nossr50.events.experience.McMMOPlayerLevelDownEvent;
import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
@ -190,8 +189,7 @@ public final class EventUtils {
* @param subSkillType target subskill
* @return the event after it has been fired
*/
@Deprecated
public static @NotNull SubSkillEvent callSubSkillEvent(Player player, SubSkillType subSkillType) {
public static @NotNull SubSkillEvent callSubSkillEvent(@NotNull Player player, @NotNull SubSkillType subSkillType) {
SubSkillEvent event = new SubSkillEvent(player, subSkillType);
mcMMO.p.getServer().getPluginManager().callEvent(event);
@ -213,19 +211,6 @@ public final class EventUtils {
return event;
}
/**
* Calls a new SubSkillEvent for this SubSkill and then returns it
* @param player target player
* @param abstractSubSkill target subskill
* @return the event after it has been fired
*/
public static SubSkillEvent callSubSkillEvent(Player player, AbstractSubSkill abstractSubSkill) {
SubSkillEvent event = new SubSkillEvent(player, abstractSubSkill);
mcMMO.p.getServer().getPluginManager().callEvent(event);
return event;
}
public static FakePlayerAnimationEvent callFakeArmSwingEvent(Player player) {
FakePlayerAnimationEvent event = new FakePlayerAnimationEvent(player);
mcMMO.p.getServer().getPluginManager().callEvent(event);

View File

@ -13,9 +13,7 @@ public class ProbabilityImpl implements Probability {
* @param staticProbability the value to assign to this probability
*/
public ProbabilityImpl(double staticProbability) throws ValueOutOfBoundsException {
if(staticProbability > 1) {
throw new ValueOutOfBoundsException("Value should never be above 1 for Probability! This suggests a coding mistake, contact the devs!");
} else if (staticProbability < 0) {
if (staticProbability < 0) {
throw new ValueOutOfBoundsException("Value should never be negative for Probability! This suggests a coding mistake, contact the devs!");
}

View File

@ -10,8 +10,10 @@ import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
@ -348,16 +350,34 @@ public final class SkillUtils {
*
* 3) Creates a {@link Probability} and pipes it to {@link RandomChanceUtil} which processes the result and returns it
*
* This also calls a {@link SubSkillEvent} which can be cancelled, if it is cancelled this will return false
* The outcome of the probability can also be modified by this event that is called
*
* @param subSkillType target subskill
* @param player target player, can be null (null players are given odds equivalent to a player with no levels or luck)
* @return true if the Skill RNG succeeds, false if it fails
*/
public static boolean isSkillRNGSuccessful(@NotNull SubSkillType subSkillType, @Nullable Player player) {
public static boolean isSkillRNGSuccessful(@NotNull SubSkillType subSkillType, @NotNull Player player) {
try {
//Process probability
Probability probability = getSubSkillProbability(subSkillType, player);
//Player can be null
boolean isLucky = player != null && Permissions.lucky(player, subSkillType.getParentSkill());
//Send out event
SubSkillEvent subSkillEvent = EventUtils.callSubSkillEvent(player, subSkillType);
if(subSkillEvent.isCancelled()) {
return false; //Event got cancelled so this doesn't succeed
}
//Result modifier
double resultModifier = subSkillEvent.getResultModifier();
//Mutate probability
if(resultModifier != 1.0D)
probability = ProbabilityFactory.ofPercentageValue(probability.getValue() * resultModifier);
//Luck
boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
if(isLucky) {
return RandomChanceUtil.processProbability(probability, RandomChanceUtil.LUCKY_MODIFIER);
@ -407,6 +427,16 @@ public final class SkillUtils {
}
}
/**
* Skills activate without RNG, this allows other plugins to prevent that activation
* @param subSkillType target subskill
* @param player target player
* @return true if the skill succeeds (wasn't cancelled by any other plugin)
*/
public static boolean isNonRNGSkillActivationSuccessful(@NotNull SubSkillType subSkillType, @NotNull Player player) {
return !EventUtils.callSubSkillEvent(player, subSkillType).isCancelled();
}
/**
* Grab the {@link Probability} for a specific {@link SubSkillType} for a specific {@link Player}
*