2
0

RandomChanceUtil.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package com.gmail.nossr50.util.random;
  2. import com.gmail.nossr50.config.AdvancedConfig;
  3. import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
  4. import com.gmail.nossr50.datatypes.skills.SubSkillType;
  5. import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
  6. import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent;
  7. import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillRandomCheckEvent;
  8. import com.gmail.nossr50.mcMMO;
  9. import com.gmail.nossr50.util.EventUtils;
  10. import com.gmail.nossr50.util.Misc;
  11. import com.gmail.nossr50.util.Permissions;
  12. import com.gmail.nossr50.util.skills.SkillActivationType;
  13. import org.bukkit.entity.Player;
  14. import java.text.DecimalFormat;
  15. import java.util.Random;
  16. public class RandomChanceUtil
  17. {
  18. public static final DecimalFormat percent = new DecimalFormat("##0.00%");
  19. //public static final DecimalFormat decimal = new DecimalFormat("##0.00");
  20. public static final double LINEAR_CURVE_VAR = 100.0D;
  21. /**
  22. * This method is the final step in determining if a Sub-Skill / Secondary Skill in mcMMO successfully activates either from chance or otherwise
  23. * Random skills check for success based on numbers and then fire a cancellable event, if that event is not cancelled they succeed
  24. * non-RNG skills just fire the cancellable event and succeed if they go uncancelled
  25. *
  26. * @param skillActivationType this value represents what kind of activation procedures this sub-skill uses
  27. * @param subSkillType The identifier for this specific sub-skill
  28. * @param player The owner of this sub-skill
  29. * @return returns true if all conditions are met and they event is not cancelled
  30. */
  31. public static boolean isActivationSuccessful(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player)
  32. {
  33. switch(skillActivationType)
  34. {
  35. case RANDOM_LINEAR_100_SCALE_WITH_CAP:
  36. return checkRandomChanceExecutionSuccess(player, subSkillType, true);
  37. case RANDOM_STATIC_CHANCE:
  38. return checkRandomStaticChanceExecutionSuccess(player, subSkillType);
  39. case ALWAYS_FIRES:
  40. SubSkillEvent event = EventUtils.callSubSkillEvent(player, subSkillType);
  41. return !event.isCancelled();
  42. default:
  43. return false;
  44. }
  45. }
  46. public static double getActivationChance(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player)
  47. {
  48. switch(skillActivationType)
  49. {
  50. case RANDOM_LINEAR_100_SCALE_WITH_CAP:
  51. return getRandomChanceExecutionSuccess(player, subSkillType, true);
  52. case RANDOM_STATIC_CHANCE:
  53. return getRandomStaticChanceExecutionSuccess(player, subSkillType);
  54. default:
  55. return 0.1337;
  56. }
  57. }
  58. /**
  59. * Checks whether or not the random chance succeeds
  60. * @return true if the random chance succeeds
  61. */
  62. public static boolean checkRandomChanceExecutionSuccess(double chance)
  63. {
  64. //Check the odds
  65. chance *= 100;
  66. /*
  67. * Stuff like treasures can specify a drop chance from 0.05 to 100
  68. * Because of that we need to use a large int bound and multiply the chance by 100
  69. */
  70. return rollDice(chance, 10000);
  71. }
  72. public static boolean rollDice(double chanceOfSuccess, int bound) {
  73. Random random = new Random();
  74. if (chanceOfSuccess > random.nextInt(bound))
  75. return true;
  76. else
  77. return false;
  78. }
  79. /**
  80. * Used for stuff like Excavation, Fishing, etc...
  81. * @param randomChance
  82. * @return
  83. */
  84. public static boolean checkRandomChanceExecutionSuccess(RandomChanceSkillStatic randomChance)
  85. {
  86. double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
  87. //Check the odds
  88. return rollDice(chanceOfSuccess, 100);
  89. }
  90. public static boolean checkRandomChanceExecutionSuccess(RandomChanceSkill randomChance)
  91. {
  92. double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
  93. Random random = new Random();
  94. //Check the odds
  95. return rollDice(chanceOfSuccess, 100);
  96. }
  97. /*public static double getRandomChanceExecutionChance(RandomChanceSkill randomChance)
  98. {
  99. double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
  100. return chanceOfSuccess;
  101. }*/
  102. /**
  103. * Gets the Static Chance for something to activate
  104. * @param randomChance
  105. * @return
  106. */
  107. public static double getRandomChanceExecutionChance(RandomChanceExecution randomChance) {
  108. double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
  109. return chanceOfSuccess;
  110. }
  111. /*private static double calculateChanceOfSuccess(RandomChanceStatic randomChance) {
  112. double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap());
  113. return chanceOfSuccess;
  114. }*/
  115. private static double calculateChanceOfSuccess(RandomChanceSkill randomChance) {
  116. double skillLevel = randomChance.getSkillLevel();
  117. double maximumProbability = randomChance.getProbabilityCap();
  118. double maximumBonusLevel = randomChance.getMaximumBonusLevelCap();
  119. double chanceOfSuccess;
  120. if (skillLevel >= maximumBonusLevel) {
  121. //Chance of success is equal to the maximum probability if the maximum bonus level has been reached
  122. chanceOfSuccess = maximumProbability;
  123. } else {
  124. //Get chance of success
  125. chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), maximumProbability, maximumBonusLevel);
  126. }
  127. return chanceOfSuccess;
  128. }
  129. /**
  130. * The formula for RNG success is determined like this
  131. * maximum probability * ( x / maxlevel )
  132. *
  133. * @return the chance of success from 0-100 (100 = guaranteed)
  134. */
  135. private static int getChanceOfSuccess(double x, double y, double z)
  136. {
  137. //return (int) (x / (y / LINEAR_CURVE_VAR));
  138. return (int) (y * (x/z));
  139. // max probability * (weight/maxlevel) = chance of success
  140. }
  141. private static int getChanceOfSuccess(double x, double y)
  142. {
  143. return (int) (x / (y / LINEAR_CURVE_VAR));
  144. // max probability * (weight/maxlevel) = chance of success
  145. }
  146. public static double getRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType, boolean hasCap)
  147. {
  148. RandomChanceSkill rcs = new RandomChanceSkill(player, subSkillType, hasCap);
  149. return getRandomChanceExecutionChance(rcs);
  150. }
  151. public static double getRandomStaticChanceExecutionSuccess(Player player, SubSkillType subSkillType)
  152. {
  153. try {
  154. return getRandomChanceExecutionChance(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType));
  155. } catch (InvalidStaticChance invalidStaticChance) {
  156. //Catch invalid static skills
  157. invalidStaticChance.printStackTrace();
  158. }
  159. return 0.1337; //Puts on shades
  160. }
  161. public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType, boolean hasCap)
  162. {
  163. return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, hasCap));
  164. }
  165. public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType)
  166. {
  167. return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType));
  168. }
  169. public static boolean checkRandomStaticChanceExecutionSuccess(Player player, SubSkillType subSkillType)
  170. {
  171. try {
  172. return checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType));
  173. } catch (InvalidStaticChance invalidStaticChance) {
  174. //Catch invalid static skills
  175. invalidStaticChance.printStackTrace();
  176. }
  177. return false;
  178. }
  179. /**
  180. * Grabs static activation rolls for Secondary Abilities
  181. * @param subSkillType The secondary ability to grab properties of
  182. * @throws InvalidStaticChance if the skill has no defined static chance this exception will be thrown and you should know you're a naughty boy
  183. * @return The static activation roll involved in the RNG calculation
  184. */
  185. public static double getStaticRandomChance(SubSkillType subSkillType) throws InvalidStaticChance
  186. {
  187. switch(subSkillType)
  188. {
  189. case AXES_ARMOR_IMPACT:
  190. return AdvancedConfig.getInstance().getImpactChance();
  191. case AXES_GREATER_IMPACT:
  192. return AdvancedConfig.getInstance().getGreaterImpactChance();
  193. case TAMING_FAST_FOOD_SERVICE:
  194. return AdvancedConfig.getInstance().getFastFoodChance();
  195. default:
  196. throw new InvalidStaticChance();
  197. }
  198. }
  199. public static boolean sendSkillEvent(Player player, SubSkillType subSkillType, double activationChance)
  200. {
  201. SubSkillRandomCheckEvent event = new SubSkillRandomCheckEvent(player, subSkillType, activationChance);
  202. return !event.isCancelled();
  203. }
  204. /*public static boolean treasureDropSuccessful(Player player, double dropChance, int activationChance) {
  205. SubSkillRandomCheckEvent event = new SubSkillRandomCheckEvent(player, SubSkillType.EXCAVATION_ARCHAEOLOGY, dropChance / activationChance);
  206. mcMMO.p.getServer().getPluginManager().callEvent(event);
  207. return (event.getChance() * activationChance) > (Misc.getRandom().nextDouble() * activationChance) && !event.isCancelled();
  208. }*/
  209. public static boolean isActivationSuccessful(SkillActivationType skillActivationType, AbstractSubSkill abstractSubSkill, Player player)
  210. {
  211. return isActivationSuccessful(skillActivationType, abstractSubSkill.getSubSkillType(), player);
  212. }
  213. public static String[] calculateAbilityDisplayValues(SkillActivationType skillActivationType, Player player, SubSkillType subSkillType) {
  214. double successChance = getActivationChance(skillActivationType, subSkillType, player);
  215. String[] displayValues = new String[2];
  216. boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
  217. displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
  218. displayValues[1] = isLucky ? percent.format(Math.min(successChance * 1.3333D, 100.0D) / 100.0D) : null;
  219. return displayValues;
  220. }
  221. public static String[] calculateAbilityDisplayValuesStatic(Player player, PrimarySkillType primarySkillType, double chance) {
  222. RandomChanceStatic rcs = new RandomChanceStatic(chance);
  223. double successChance = getRandomChanceExecutionChance(rcs);
  224. String[] displayValues = new String[2];
  225. boolean isLucky = Permissions.lucky(player, primarySkillType);
  226. displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
  227. displayValues[1] = isLucky ? percent.format(Math.min(successChance * 1.3333D, 100.0D) / 100.0D) : null;
  228. return displayValues;
  229. }
  230. public static String[] calculateAbilityDisplayValuesCustom(SkillActivationType skillActivationType, Player player, SubSkillType subSkillType, double multiplier) {
  231. double successChance = getActivationChance(skillActivationType, subSkillType, player);
  232. successChance *= multiplier; //Currently only used for graceful roll
  233. String[] displayValues = new String[2];
  234. boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
  235. displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
  236. displayValues[1] = isLucky ? percent.format(Math.min(successChance * 1.3333D, 100.0D) / 100.0D) : null;
  237. return displayValues;
  238. }
  239. }