mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-22 13:16:45 +01:00
Some work on milestones is done
This commit is contained in:
parent
b9c8743ee3
commit
bec088c969
@ -9,6 +9,12 @@ Key:
|
|||||||
|
|
||||||
Version 2.1.0
|
Version 2.1.0
|
||||||
+ Added config setting to enable or disable classic mcMMO mode
|
+ Added config setting to enable or disable classic mcMMO mode
|
||||||
|
+ (Config) Added rank settings for the new Woodcutting skill
|
||||||
|
+ (Config) Added configurable parameters for the new Tree Feller
|
||||||
|
+ (Config) Added classic toggle for Tree Feller
|
||||||
|
+ (Permissions) Added permission nodes for Harvest Lumber, Splinter, Nature's Bounty, and Bark Surgeon
|
||||||
|
! Woodcutting's Double Drop subskill is now named Harvest Lumber
|
||||||
|
! Replaced the old Double Drop permission node for woodcutting with a new Harvest Lumber permission node
|
||||||
! (API) SkillType is now PrimarySkill
|
! (API) SkillType is now PrimarySkill
|
||||||
! (API) SecondarySkill is now SubSkill
|
! (API) SecondarySkill is now SubSkill
|
||||||
! (API) AbilityType is now SuperAbility
|
! (API) AbilityType is now SuperAbility
|
||||||
|
@ -4,7 +4,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.gmail.nossr50.datatypes.skills.PrimarySkill;
|
import com.gmail.nossr50.datatypes.skills.PrimarySkill;
|
||||||
|
import com.gmail.nossr50.datatypes.skills.SkillMilestone;
|
||||||
import com.gmail.nossr50.datatypes.skills.SubSkill;
|
import com.gmail.nossr50.datatypes.skills.SubSkill;
|
||||||
|
import com.gmail.nossr50.util.player.UserManager;
|
||||||
|
import com.gmail.nossr50.util.skills.SkillMilestoneFactory;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import com.gmail.nossr50.config.AdvancedConfig;
|
import com.gmail.nossr50.config.AdvancedConfig;
|
||||||
@ -20,6 +23,9 @@ public class WoodcuttingCommand extends SkillCommand {
|
|||||||
private boolean canTreeFell;
|
private boolean canTreeFell;
|
||||||
private boolean canLeafBlow;
|
private boolean canLeafBlow;
|
||||||
private boolean canDoubleDrop;
|
private boolean canDoubleDrop;
|
||||||
|
private boolean canSplinter;
|
||||||
|
private boolean canBarkSurgeon;
|
||||||
|
private boolean canNaturesBounty;
|
||||||
|
|
||||||
public WoodcuttingCommand() {
|
public WoodcuttingCommand() {
|
||||||
super(PrimarySkill.WOODCUTTING);
|
super(PrimarySkill.WOODCUTTING);
|
||||||
@ -36,17 +42,29 @@ public class WoodcuttingCommand extends SkillCommand {
|
|||||||
|
|
||||||
// DOUBLE DROPS
|
// DOUBLE DROPS
|
||||||
if (canDoubleDrop) {
|
if (canDoubleDrop) {
|
||||||
String[] doubleDropStrings = calculateAbilityDisplayValues(skillValue, SubSkill.WOODCUTTING_DOUBLE_DROPS, isLucky);
|
if(AdvancedConfig.getInstance().isSubSkillClassic(SubSkill.WOODCUTTING_HARVEST_LUMBER))
|
||||||
doubleDropChance = doubleDropStrings[0];
|
setDoubleDropClassicChanceStrings(skillValue, isLucky);
|
||||||
doubleDropChanceLucky = doubleDropStrings[1];
|
else
|
||||||
|
{
|
||||||
|
//TODO: Set up datastrings for new harvest
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setDoubleDropClassicChanceStrings(float skillValue, boolean isLucky) {
|
||||||
|
String[] doubleDropStrings = calculateAbilityDisplayValues(skillValue, SubSkill.WOODCUTTING_HARVEST_LUMBER, isLucky);
|
||||||
|
doubleDropChance = doubleDropStrings[0];
|
||||||
|
doubleDropChanceLucky = doubleDropStrings[1];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void permissionsCheck(Player player) {
|
protected void permissionsCheck(Player player) {
|
||||||
canTreeFell = Permissions.treeFeller(player);
|
canTreeFell = Permissions.treeFeller(player);
|
||||||
canDoubleDrop = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_DOUBLE_DROPS) && !skill.getDoubleDropsDisabled();
|
canDoubleDrop = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_HARVEST_LUMBER) && !skill.getDoubleDropsDisabled();
|
||||||
canLeafBlow = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_LEAF_BLOWER);
|
canLeafBlow = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_LEAF_BLOWER);
|
||||||
|
canSplinter = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_SPLINTER);
|
||||||
|
canBarkSurgeon = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_BARK_SURGEON);
|
||||||
|
canNaturesBounty = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_NATURES_BOUNTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -65,6 +83,20 @@ public class WoodcuttingCommand extends SkillCommand {
|
|||||||
messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Woodcutting.Effect.4"), LocaleLoader.getString("Woodcutting.Effect.5")));
|
messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Woodcutting.Effect.4"), LocaleLoader.getString("Woodcutting.Effect.5")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (canSplinter) {
|
||||||
|
messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Woodcutting.Effect.6"), LocaleLoader.getString("Woodcutting.Effect.7")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canBarkSurgeon) {
|
||||||
|
messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Woodcutting.Effect.8"), LocaleLoader.getString("Woodcutting.Effect.9")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canNaturesBounty) {
|
||||||
|
messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Woodcutting.Effect.10"), LocaleLoader.getString("Woodcutting.Effect.11")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.gmail.nossr50.datatypes.skills.PrimarySkill;
|
||||||
import com.gmail.nossr50.datatypes.skills.SubSkill;
|
import com.gmail.nossr50.datatypes.skills.SubSkill;
|
||||||
import com.gmail.nossr50.skills.alchemy.Alchemy;
|
import com.gmail.nossr50.skills.alchemy.Alchemy;
|
||||||
import com.gmail.nossr50.skills.fishing.Fishing;
|
import com.gmail.nossr50.skills.fishing.Fishing;
|
||||||
@ -33,6 +34,11 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
|
|||||||
// Validate all the settings!
|
// Validate all the settings!
|
||||||
List<String> reason = new ArrayList<String>();
|
List<String> reason = new ArrayList<String>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the future this method will check keys for all skills, but for now it only checks overhauled skills
|
||||||
|
*/
|
||||||
|
checkKeys(reason);
|
||||||
|
|
||||||
/* GENERAL */
|
/* GENERAL */
|
||||||
if (getAbilityLength() < 1) {
|
if (getAbilityLength() < 1) {
|
||||||
reason.add("Skills.General.Ability.IncreaseLevel should be at least 1!");
|
reason.add("Skills.General.Ability.IncreaseLevel should be at least 1!");
|
||||||
@ -648,16 +654,17 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* WOODCUTTING */
|
/* WOODCUTTING */
|
||||||
|
|
||||||
if (getLeafBlowUnlockLevel() < 0) {
|
if (getLeafBlowUnlockLevel() < 0) {
|
||||||
reason.add("Skills.Woodcutting.LeafBlower.UnlockLevel should be at least 0!");
|
reason.add("Skills.Woodcutting.LeafBlower.UnlockLevel should be at least 0!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getMaxChance(SubSkill.WOODCUTTING_DOUBLE_DROPS) < 1) {
|
if (getMaxChance(SubSkill.WOODCUTTING_HARVEST_LUMBER) < 1) {
|
||||||
reason.add("Skills.Woodcutting.DoubleDrops.ChanceMax should be at least 1!");
|
reason.add("Skills.Woodcutting.HarvestLumber.ChanceMax should be at least 1!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getMaxBonusLevel(SubSkill.WOODCUTTING_DOUBLE_DROPS) < 1) {
|
if (getMaxBonusLevel(SubSkill.WOODCUTTING_HARVEST_LUMBER) < 1) {
|
||||||
reason.add("Skills.Woodcutting.DoubleDrops.MaxBonusLevel should be at least 1!");
|
reason.add("Skills.Woodcutting.HarvestLumber.MaxBonusLevel should be at least 1!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* KRAKEN */
|
/* KRAKEN */
|
||||||
@ -690,6 +697,30 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
|
|||||||
public int getMaxBonusLevel(SubSkill subSkill) { return config.getInt(subSkill.getAdvConfigAddress() + ".MaxBonusLevel"); }
|
public int getMaxBonusLevel(SubSkill subSkill) { return config.getInt(subSkill.getAdvConfigAddress() + ".MaxBonusLevel"); }
|
||||||
public double getMaxChance(SubSkill subSkill) { return config.getDouble(subSkill.getAdvConfigAddress() + ".ChanceMax", 100.0D);}
|
public double getMaxChance(SubSkill subSkill) { return config.getDouble(subSkill.getAdvConfigAddress() + ".ChanceMax", 100.0D);}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the level required to unlock a subskill at a given rank
|
||||||
|
* @param subSkill The subskill
|
||||||
|
* @param rank The rank of the skill
|
||||||
|
* @return The level required to use this rank of the subskill
|
||||||
|
* @deprecated Right now mcMMO is an overhaul process, this will only work for skills I have overhauled. I will be removing the deprecated tag when that is true.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public int getSubSkillUnlockLevel(SubSkill subSkill, int rank)
|
||||||
|
{
|
||||||
|
return config.getInt(subSkill.getAdvConfigAddress() + ".Rank_Levels.Rank_"+rank+".LevelReq");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some SubSkills have the ability to retain classic functionality
|
||||||
|
* @param subSkill SubSkill with classic functionality
|
||||||
|
* @return true if the subskill is in classic mode
|
||||||
|
*/
|
||||||
|
public boolean isSubSkillClassic(SubSkill subSkill)
|
||||||
|
{
|
||||||
|
return config.getBoolean(subSkill.getAdvConfigAddress()+".Classic");
|
||||||
|
}
|
||||||
|
|
||||||
/* ACROBATICS */
|
/* ACROBATICS */
|
||||||
public double getDodgeDamageModifier() { return config.getDouble("Skills.Acrobatics.Dodge.DamageModifier", 2.0D); }
|
public double getDodgeDamageModifier() { return config.getDouble("Skills.Acrobatics.Dodge.DamageModifier", 2.0D); }
|
||||||
|
|
||||||
@ -857,4 +888,39 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
|
|||||||
public String getPlayerUnleashMessage() { return config.getString("Kraken.Unleashed_Message.Player", ""); }
|
public String getPlayerUnleashMessage() { return config.getString("Kraken.Unleashed_Message.Player", ""); }
|
||||||
public String getPlayerDefeatMessage() { return config.getString("Kraken.Defeated_Message.Killed", ""); }
|
public String getPlayerDefeatMessage() { return config.getString("Kraken.Defeated_Message.Killed", ""); }
|
||||||
public String getPlayerEscapeMessage() { return config.getString("Kraken.Defeated_Message.Escape", ""); }
|
public String getPlayerEscapeMessage() { return config.getString("Kraken.Defeated_Message.Escape", ""); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for valid keys in the advanced.yml file for subskill ranks
|
||||||
|
*/
|
||||||
|
private void checkKeys(List<String> reasons)
|
||||||
|
{
|
||||||
|
//For now we will only check ranks of stuff I've overhauled
|
||||||
|
for(SubSkill subSkill : SubSkill.values())
|
||||||
|
{
|
||||||
|
if(subSkill.getParentSkill() == PrimarySkill.WOODCUTTING)
|
||||||
|
{
|
||||||
|
//Keeping track of the rank requirements and making sure there are no logical errors
|
||||||
|
int curRank = 0;
|
||||||
|
int prevRank = 0;
|
||||||
|
|
||||||
|
for(int x = 0; x < subSkill.getNumRanks(); x++)
|
||||||
|
{
|
||||||
|
if(curRank > 0)
|
||||||
|
prevRank = curRank;
|
||||||
|
|
||||||
|
curRank = getSubSkillUnlockLevel(subSkill, x);
|
||||||
|
|
||||||
|
//Do we really care if its below 0? Probably not
|
||||||
|
if(curRank < 0)
|
||||||
|
reasons.add(subSkill.getAdvConfigAddress() + ".Rank_Levels.Rank_"+curRank+".LevelReq should be above or equal to 0!");
|
||||||
|
|
||||||
|
if(prevRank > curRank)
|
||||||
|
{
|
||||||
|
//We're going to allow this but we're going to warn them
|
||||||
|
plugin.getLogger().info("You have the ranks for the subskill "+subSkill.toString()+" set up poorly, sequential ranks should have ascending requirements");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,8 +244,16 @@ public class Config extends AutoUpdateConfigLoader {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* General Settings */
|
/* General Settings */
|
||||||
|
|
||||||
//Classic mode will default the value to true if the config file doesn't contain the entry (server is from a previous mcMMO install)
|
//Classic mode will default the value to true if the config file doesn't contain the entry (server is from a previous mcMMO install)
|
||||||
public boolean getClassicMode() { return config.getBoolean("General.Classic_Mode", true); }
|
public boolean getClassicMode() { return config.getBoolean("General.Classic_Mode", true); }
|
||||||
|
|
||||||
|
//XP needed to level is multiplied by this when using classic mode
|
||||||
|
public int getClassicModeXPFormulaFactor() { return config.getInt("General.Skill_Scaling.Classic_XP_Formula_Factor", 1); }
|
||||||
|
|
||||||
|
//Level requirements for subskills is multiplied by this when using classic mode
|
||||||
|
public int getClassicModeLevelReqFactor() { return config.getInt("General.Skill_Scaling.Classic_LevelReq_Factor", 10); }
|
||||||
|
|
||||||
public String getLocale() { return config.getString("General.Locale", "en_us"); }
|
public String getLocale() { return config.getString("General.Locale", "en_us"); }
|
||||||
public boolean getMOTDEnabled() { return config.getBoolean("General.MOTD_Enabled", true); }
|
public boolean getMOTDEnabled() { return config.getBoolean("General.MOTD_Enabled", true); }
|
||||||
public boolean getShowProfileLoadedMessage() { return config.getBoolean("General.Show_Profile_Loaded", true); }
|
public boolean getShowProfileLoadedMessage() { return config.getBoolean("General.Show_Profile_Loaded", true); }
|
||||||
|
@ -50,7 +50,7 @@ public enum PrimarySkill {
|
|||||||
SWORDS(SwordsManager.class, Color.fromRGB(178, 34, 34), SuperAbility.SERRATED_STRIKES, ToolType.SWORD, ImmutableList.of(SubSkill.SWORDS_BLEED, SubSkill.SWORDS_COUNTER)),
|
SWORDS(SwordsManager.class, Color.fromRGB(178, 34, 34), SuperAbility.SERRATED_STRIKES, ToolType.SWORD, ImmutableList.of(SubSkill.SWORDS_BLEED, SubSkill.SWORDS_COUNTER)),
|
||||||
TAMING(TamingManager.class, Color.PURPLE, ImmutableList.of(SubSkill.TAMING_BEAST_LORE, SubSkill.TAMING_CALL_OF_THE_WILD, SubSkill.TAMING_ENVIRONMENTALLY_AWARE, SubSkill.TAMING_FAST_FOOD, SubSkill.TAMING_GORE, SubSkill.TAMING_HOLY_HOUND, SubSkill.TAMING_SHARPENED_CLAWS, SubSkill.TAMING_SHOCK_PROOF, SubSkill.TAMING_THICK_FUR, SubSkill.TAMING_PUMMEL)),
|
TAMING(TamingManager.class, Color.PURPLE, ImmutableList.of(SubSkill.TAMING_BEAST_LORE, SubSkill.TAMING_CALL_OF_THE_WILD, SubSkill.TAMING_ENVIRONMENTALLY_AWARE, SubSkill.TAMING_FAST_FOOD, SubSkill.TAMING_GORE, SubSkill.TAMING_HOLY_HOUND, SubSkill.TAMING_SHARPENED_CLAWS, SubSkill.TAMING_SHOCK_PROOF, SubSkill.TAMING_THICK_FUR, SubSkill.TAMING_PUMMEL)),
|
||||||
UNARMED(UnarmedManager.class, Color.BLACK, SuperAbility.BERSERK, ToolType.FISTS, ImmutableList.of(SubSkill.UNARMED_BLOCK_CRACKER, SubSkill.UNARMED_DEFLECT, SubSkill.UNARMED_DISARM, SubSkill.UNARMED_IRON_ARM, SubSkill.UNARMED_IRON_GRIP)),
|
UNARMED(UnarmedManager.class, Color.BLACK, SuperAbility.BERSERK, ToolType.FISTS, ImmutableList.of(SubSkill.UNARMED_BLOCK_CRACKER, SubSkill.UNARMED_DEFLECT, SubSkill.UNARMED_DISARM, SubSkill.UNARMED_IRON_ARM, SubSkill.UNARMED_IRON_GRIP)),
|
||||||
WOODCUTTING(WoodcuttingManager.class, Color.OLIVE, SuperAbility.TREE_FELLER, ToolType.AXE, ImmutableList.of(SubSkill.WOODCUTTING_LEAF_BLOWER, SubSkill.WOODCUTTING_DOUBLE_DROPS));
|
WOODCUTTING(WoodcuttingManager.class, Color.OLIVE, SuperAbility.TREE_FELLER, ToolType.AXE, ImmutableList.of(SubSkill.WOODCUTTING_LEAF_BLOWER, SubSkill.WOODCUTTING_BARK_SURGEON, SubSkill.WOODCUTTING_SPLINTER, SubSkill.WOODCUTTING_NATURES_BOUNTY, SubSkill.WOODCUTTING_TREE_FELLER, SubSkill.WOODCUTTING_HARVEST_LUMBER));
|
||||||
|
|
||||||
private Class<? extends SkillManager> managerClass;
|
private Class<? extends SkillManager> managerClass;
|
||||||
private Color runescapeColor;
|
private Color runescapeColor;
|
||||||
|
@ -1,39 +1,106 @@
|
|||||||
package com.gmail.nossr50.datatypes.skills;
|
package com.gmail.nossr50.datatypes.skills;
|
||||||
|
|
||||||
|
import com.gmail.nossr50.config.AdvancedConfig;
|
||||||
|
import com.gmail.nossr50.datatypes.player.PlayerProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a gated subskill
|
* This class represents a gated subskill
|
||||||
* A gated subskill is a subskill that requires a certain level to unlock
|
* A SkillMilestone is a representation of a specific rank for a subskill
|
||||||
|
* A SkillMilestone may contain a child, the child represents the next rank of the subskill
|
||||||
* This class is mostly to make it easier to grab information about subskills for a player
|
* This class is mostly to make it easier to grab information about subskills for a player
|
||||||
*/
|
*/
|
||||||
public class SkillMilestone {
|
public class SkillMilestone {
|
||||||
private int unlockLevel; //Level that grants access to this skill
|
private final int unlockLevel; //Level that grants access to this skill
|
||||||
private SubSkill subskill; //Subskill that this milestone belongs to
|
private final SubSkill subskill; //Subskill that this milestone belongs to
|
||||||
private SkillMilestone childMilestone; //Next rank in the milestone
|
private SkillMilestone childMilestone; //Next rank in the milestone
|
||||||
|
private SkillMilestone lastChild; //The final child milestone in this chain
|
||||||
|
private final int curRank; //The current rank of this SkillMilestone
|
||||||
|
|
||||||
public SkillMilestone(SubSkill subskill, int unlockLevel, SkillMilestone childMilestone)
|
public SkillMilestone(SubSkill subskill, int curRank)
|
||||||
{
|
{
|
||||||
this.subskill = subskill;
|
this.subskill = subskill;
|
||||||
this.unlockLevel = unlockLevel;
|
this.curRank = curRank;
|
||||||
|
this.unlockLevel = AdvancedConfig.getInstance().getSubSkillUnlockLevel(subskill, curRank);
|
||||||
//Assign a child subskill if it exists
|
|
||||||
if(childMilestone != null)
|
|
||||||
this.childMilestone = childMilestone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SkillMilestone(SubSkill subskill, int unlockLevel)
|
|
||||||
{
|
|
||||||
this(subskill, unlockLevel, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the level requirement for this subskill's rank
|
||||||
|
* @return The level required to use this subskill
|
||||||
|
*/
|
||||||
public int getUnlockLevel() {
|
public int getUnlockLevel() {
|
||||||
return unlockLevel;
|
return unlockLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get's the current milestone the player is working towards
|
||||||
|
* @param playerProfile
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public SkillMilestone getCurrentMilestoneForPlayer(PlayerProfile playerProfile)
|
||||||
|
{
|
||||||
|
if(playerProfile.getSkillLevel(subskill.getParentSkill()) >= unlockLevel)
|
||||||
|
{
|
||||||
|
if(childMilestone != null)
|
||||||
|
return childMilestone.getCurrentMilestoneForPlayer(playerProfile);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the associated SubSkill for this milestone
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public SubSkill getSubskill() {
|
public SubSkill getSubskill() {
|
||||||
return subskill;
|
return subskill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the child milestone, which is the next rank of this skill
|
||||||
|
* @return The child milestone of this skill
|
||||||
|
*/
|
||||||
public SkillMilestone getChildMilestone() {
|
public SkillMilestone getChildMilestone() {
|
||||||
return childMilestone;
|
return childMilestone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a child milestone, which represents the next rank of this skill
|
||||||
|
*/
|
||||||
|
public void addChildMilestone()
|
||||||
|
{
|
||||||
|
childMilestone = new SkillMilestone(this.subskill, curRank+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This grabs the final child in the chain of child milestones, which represents the last rank of this subskill
|
||||||
|
* @return The final child for this SkillMilestone, which is the final rank for the associated subskill. Null if this Milestone has no children.
|
||||||
|
*/
|
||||||
|
public SkillMilestone getFinalChild()
|
||||||
|
{
|
||||||
|
//Return lastchild if we already have the ref stored
|
||||||
|
if(lastChild != null)
|
||||||
|
return lastChild;
|
||||||
|
|
||||||
|
//If the next child doesn't exist return this
|
||||||
|
if(childMilestone == null) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we have children, find their children until the chain stops and store that reference and return it
|
||||||
|
return lastChild = childMilestone.getFinalChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current rank of this SkillMilestone for the associated subskill
|
||||||
|
* @return The current rank of this subskill
|
||||||
|
*/
|
||||||
|
public int getCurRank() { return curRank; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requirement for the next rank of this subskill
|
||||||
|
* @return The level requirement for the next rank of this SkillMilestone chain
|
||||||
|
*/
|
||||||
|
public int getNextRankReq() { return childMilestone.unlockLevel; }
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.gmail.nossr50.datatypes.skills;
|
|||||||
|
|
||||||
import com.gmail.nossr50.util.StringUtils;
|
import com.gmail.nossr50.util.StringUtils;
|
||||||
|
|
||||||
import com.gmail.nossr50.datatypes.skills.PrimarySkill.*;
|
|
||||||
public enum SubSkill {
|
public enum SubSkill {
|
||||||
/* !! Warning -- Do not let subskills share a name with any existing PrimarySkill as it will clash with the static import !! */
|
/* !! Warning -- Do not let subskills share a name with any existing PrimarySkill as it will clash with the static import !! */
|
||||||
|
|
||||||
@ -85,12 +84,38 @@ public enum SubSkill {
|
|||||||
UNARMED_IRON_GRIP,
|
UNARMED_IRON_GRIP,
|
||||||
|
|
||||||
/* Woodcutting */
|
/* Woodcutting */
|
||||||
WOODCUTTING_TREE_FELLER,
|
WOODCUTTING_TREE_FELLER(5),
|
||||||
WOODCUTTING_LEAF_BLOWER,
|
WOODCUTTING_LEAF_BLOWER(3),
|
||||||
WOODCUTTING_SURGEON,
|
WOODCUTTING_BARK_SURGEON(3),
|
||||||
WOODCUTTING_NATURES_BOUNTY,
|
WOODCUTTING_NATURES_BOUNTY(3),
|
||||||
WOODCUTTING_SPLINTER,
|
WOODCUTTING_SPLINTER(3),
|
||||||
WOODCUTTING_DOUBLE_DROPS;
|
WOODCUTTING_HARVEST_LUMBER(3);
|
||||||
|
|
||||||
|
private final int numRanks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If our SubSkill has more than 1 rank define it
|
||||||
|
* @param numRanks The number of ranks our SubSkill has
|
||||||
|
*/
|
||||||
|
SubSkill(int numRanks)
|
||||||
|
{
|
||||||
|
this.numRanks = numRanks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SubSkills will default to having only 1 rank if not defined
|
||||||
|
*/
|
||||||
|
SubSkill()
|
||||||
|
{
|
||||||
|
this.numRanks = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getNumRanks()
|
||||||
|
{
|
||||||
|
return numRanks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* !!! This relies on the immutable lists in PrimarySkill being populated !!!
|
* !!! This relies on the immutable lists in PrimarySkill being populated !!!
|
||||||
@ -136,7 +161,7 @@ public enum SubSkill {
|
|||||||
* Find where to begin our substring (after the prefix)
|
* Find where to begin our substring (after the prefix)
|
||||||
*/
|
*/
|
||||||
String endResult = "";
|
String endResult = "";
|
||||||
char[] enumNameCharArray = subSkillName.toString().toCharArray();
|
char[] enumNameCharArray = subSkillName.toCharArray();
|
||||||
int subStringIndex = 0;
|
int subStringIndex = 0;
|
||||||
|
|
||||||
//Find where to start our substring for this constants name
|
//Find where to start our substring for this constants name
|
||||||
@ -152,12 +177,17 @@ public enum SubSkill {
|
|||||||
/*
|
/*
|
||||||
* Split the string up so we can capitalize each part
|
* Split the string up so we can capitalize each part
|
||||||
*/
|
*/
|
||||||
String subskillNameWithoutPrefix = subSkillName.toString().substring(subStringIndex);
|
String subskillNameWithoutPrefix = subSkillName.substring(subStringIndex);
|
||||||
String splitStrings[] = subskillNameWithoutPrefix.split("_");
|
if(subskillNameWithoutPrefix.contains("_"))
|
||||||
|
|
||||||
for(String string : splitStrings)
|
|
||||||
{
|
{
|
||||||
endResult += StringUtils.getCapitalized(string);
|
String splitStrings[] = subskillNameWithoutPrefix.split("_");
|
||||||
|
|
||||||
|
for(String string : splitStrings)
|
||||||
|
{
|
||||||
|
endResult += StringUtils.getCapitalized(string);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
endResult += StringUtils.getCapitalized(subskillNameWithoutPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
return endResult;
|
return endResult;
|
||||||
|
@ -47,7 +47,6 @@ import net.shatteredlands.shatt.backup.ZipLibrary;
|
|||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
@ -189,9 +188,6 @@ public class mcMMO extends JavaPlugin {
|
|||||||
|
|
||||||
getServer().getPluginManager().disablePlugin(this);
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Grab the setting for classic mode
|
|
||||||
classicModeEnabled = Config.getInstance().getClassicMode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,7 +38,7 @@ public class WoodcuttingManager extends SkillManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canGetDoubleDrops() {
|
protected boolean canGetDoubleDrops() {
|
||||||
return Permissions.isSubSkillEnabled(getPlayer(), SubSkill.WOODCUTTING_DOUBLE_DROPS) && SkillUtils.isActivationSuccessful(SubSkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkill.WOODCUTTING_DOUBLE_DROPS, getPlayer(), this.skill, getSkillLevel(), activationChance);
|
return Permissions.isSubSkillEnabled(getPlayer(), SubSkill.WOODCUTTING_HARVEST_LUMBER) && SkillUtils.isActivationSuccessful(SubSkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkill.WOODCUTTING_HARVEST_LUMBER, getPlayer(), this.skill, getSkillLevel(), activationChance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +21,14 @@ public class FormulaManager {
|
|||||||
|
|
||||||
private FormulaType previousFormula;
|
private FormulaType previousFormula;
|
||||||
|
|
||||||
|
//Used for XP formula scaling
|
||||||
|
private boolean classicModeEnabled;
|
||||||
|
private int classicModeXPFormulaFactor;
|
||||||
|
|
||||||
public FormulaManager() {
|
public FormulaManager() {
|
||||||
|
/* Setting for Classic Mode (Scales a lot of stuff up by * 10) */
|
||||||
|
classicModeEnabled = Config.getInstance().getClassicMode();
|
||||||
|
classicModeXPFormulaFactor = Config.getInstance().getClassicModeXPFormulaFactor();
|
||||||
loadFormula();
|
loadFormula();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +112,9 @@ public class FormulaManager {
|
|||||||
public int getCachedXpToLevel(int level, FormulaType formulaType) {
|
public int getCachedXpToLevel(int level, FormulaType formulaType) {
|
||||||
int experience;
|
int experience;
|
||||||
|
|
||||||
|
//If we're in classic we use the XP factor from config settings
|
||||||
|
int skillSystemMultiplier = classicModeEnabled ? classicModeXPFormulaFactor : 10;
|
||||||
|
|
||||||
if (formulaType == FormulaType.UNKNOWN) {
|
if (formulaType == FormulaType.UNKNOWN) {
|
||||||
formulaType = FormulaType.LINEAR;
|
formulaType = FormulaType.LINEAR;
|
||||||
}
|
}
|
||||||
@ -116,7 +126,7 @@ public class FormulaManager {
|
|||||||
switch (formulaType) {
|
switch (formulaType) {
|
||||||
case LINEAR:
|
case LINEAR:
|
||||||
if (!experienceNeededLinear.containsKey(level)) {
|
if (!experienceNeededLinear.containsKey(level)) {
|
||||||
experience = (int) Math.floor( 10 * (base + level * multiplier));
|
experience = (int) Math.floor( skillSystemMultiplier * (base + level * multiplier));
|
||||||
experienceNeededLinear.put(level, experience);
|
experienceNeededLinear.put(level, experience);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +134,7 @@ public class FormulaManager {
|
|||||||
|
|
||||||
case EXPONENTIAL:
|
case EXPONENTIAL:
|
||||||
if (!experienceNeededExponential.containsKey(level)) {
|
if (!experienceNeededExponential.containsKey(level)) {
|
||||||
experience = (int) Math.floor( 10 * multiplier * Math.pow(level, exponent) + base);
|
experience = (int) Math.floor( skillSystemMultiplier * (multiplier * Math.pow(level, exponent) + base));
|
||||||
experienceNeededExponential.put(level, experience);
|
experienceNeededExponential.put(level, experience);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.gmail.nossr50.util.skills;
|
||||||
|
|
||||||
|
import com.gmail.nossr50.config.AdvancedConfig;
|
||||||
|
import com.gmail.nossr50.datatypes.skills.SkillMilestone;
|
||||||
|
import com.gmail.nossr50.datatypes.skills.SubSkill;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Factory class builds SkillMilestone chains as needed
|
||||||
|
* SkillMilestones are stored in a hash map
|
||||||
|
*/
|
||||||
|
public class SkillMilestoneFactory {
|
||||||
|
|
||||||
|
private static HashMap<SubSkill, SkillMilestone> skillMilestoneMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a the SkillMilestone chain for this subskill
|
||||||
|
* Builds that chain if it doesn't exist before returning the parent node
|
||||||
|
* @param subSkill The SubSkill to get the SkillMilestone chain for
|
||||||
|
* @return The parent node of the SkillMilestone chain for the target subskill
|
||||||
|
*/
|
||||||
|
public static SkillMilestone getSkillMilestone(SubSkill subSkill)
|
||||||
|
{
|
||||||
|
//Init the map
|
||||||
|
if(skillMilestoneMap == null)
|
||||||
|
skillMilestoneMap = new HashMap<>();
|
||||||
|
|
||||||
|
if(skillMilestoneMap.get(subSkill) == null)
|
||||||
|
return buildSkillMilestone(subSkill);
|
||||||
|
else
|
||||||
|
return skillMilestoneMap.get(subSkill);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a SkillMilestone chain for a given subskill
|
||||||
|
* @param subSkill The subskill to build the SkillMilestone chain for
|
||||||
|
* @return The base node of the SkillMilestone chain
|
||||||
|
*/
|
||||||
|
private static SkillMilestone buildSkillMilestone(SubSkill subSkill)
|
||||||
|
{
|
||||||
|
//Init our parent node
|
||||||
|
SkillMilestone newSkillMilestone = new SkillMilestone(subSkill, AdvancedConfig.getInstance().getSubSkillUnlockLevel(subSkill, 1));
|
||||||
|
|
||||||
|
//There's probably a better way to do this
|
||||||
|
for(int x = 0; x < subSkill.getNumRanks()-1; x++)
|
||||||
|
{
|
||||||
|
newSkillMilestone.addChildMilestone();
|
||||||
|
}
|
||||||
|
|
||||||
|
//DEBUG
|
||||||
|
System.out.println("Milestone constructed for "+subSkill);
|
||||||
|
return skillMilestoneMap.put(subSkill, newSkillMilestone);
|
||||||
|
}
|
||||||
|
}
|
@ -564,15 +564,80 @@ Skills:
|
|||||||
# Settings for Woodcutting
|
# Settings for Woodcutting
|
||||||
###
|
###
|
||||||
Woodcutting:
|
Woodcutting:
|
||||||
LeafBlower:
|
Splinter:
|
||||||
# UnlockLevel: At this level, the passive ability LeafBlower unlocks
|
Rank_Levels:
|
||||||
UnlockLevel: 100
|
Rank_1:
|
||||||
|
LevelReq: 5
|
||||||
DoubleDrops:
|
Rank_2:
|
||||||
# ChanceMax: Maximum chance of receiving double drops
|
LevelReq: 30
|
||||||
|
Rank_3:
|
||||||
|
LevelReq: 55
|
||||||
|
TreeFeller:
|
||||||
|
# If set to true then tree feller will not use the new system and will use its old behaviour
|
||||||
|
Classic: false
|
||||||
|
# This is the time in seconds to build a new charge of Tree Feller
|
||||||
|
ChargeRate: 600
|
||||||
|
Rank_Levels:
|
||||||
|
Rank_1:
|
||||||
|
LevelReq: 10
|
||||||
|
TreeSizeMax: 100
|
||||||
|
Charges: 1
|
||||||
|
Rank_2:
|
||||||
|
LevelReq: 25
|
||||||
|
TreeSizeMax: 200
|
||||||
|
Charges: 1
|
||||||
|
Rank_3:
|
||||||
|
LevelReq: 50
|
||||||
|
TreeSizeMax: 200
|
||||||
|
Charges: 2
|
||||||
|
Rank_4:
|
||||||
|
LevelReq: 75
|
||||||
|
TreeSizeMax: 200
|
||||||
|
Charges: 3
|
||||||
|
Rank_5:
|
||||||
|
LevelReq: 100
|
||||||
|
TreeSizeMax: 500
|
||||||
|
Charges: 3
|
||||||
|
BarkSurgeon:
|
||||||
|
Rank_Levels:
|
||||||
|
Rank_1:
|
||||||
|
LevelReq: 70
|
||||||
|
Rank_2:
|
||||||
|
LevelReq: 80
|
||||||
|
Rank_3:
|
||||||
|
LevelReq: 95
|
||||||
|
NaturesBounty:
|
||||||
|
Rank_Levels:
|
||||||
|
Rank_1:
|
||||||
|
LevelReq: 40
|
||||||
|
Rank_2:
|
||||||
|
LevelReq: 60
|
||||||
|
Rank_3:
|
||||||
|
LevelReq: 90
|
||||||
|
# Double Drops
|
||||||
|
HarvestLumber:
|
||||||
|
Classic: false
|
||||||
|
# ChanceMax & MaxBonusLevel are only used for Classic, I'll make that more clear in the future.
|
||||||
|
# ChanceMax: Maximum chance of receiving double drops (100 = 100%)
|
||||||
# MaxBonusLevel: Level when the maximum chance of receiving double drops is reached
|
# MaxBonusLevel: Level when the maximum chance of receiving double drops is reached
|
||||||
ChanceMax: 100.0
|
ChanceMax: 100.0
|
||||||
MaxBonusLevel: 100
|
MaxBonusLevel: 100
|
||||||
|
Rank_Levels:
|
||||||
|
Rank_1:
|
||||||
|
LevelReq: 20
|
||||||
|
Rank_2:
|
||||||
|
LevelReq: 45
|
||||||
|
Rank_3:
|
||||||
|
LevelReq: 85
|
||||||
|
LeafBlower:
|
||||||
|
Rank_Levels:
|
||||||
|
Rank_1:
|
||||||
|
LevelReq: 15
|
||||||
|
Rank_2:
|
||||||
|
LevelReq: 35
|
||||||
|
Rank_3:
|
||||||
|
LevelReq: 65
|
||||||
|
|
||||||
#
|
#
|
||||||
# Customize the kraken!
|
# Customize the kraken!
|
||||||
###
|
###
|
||||||
|
@ -8,7 +8,14 @@
|
|||||||
# Settings for mcMMO in general
|
# Settings for mcMMO in general
|
||||||
###
|
###
|
||||||
General:
|
General:
|
||||||
Classic_Mode: false
|
Skill_Scaling:
|
||||||
|
# Turning this on will scale mcMMO around 1-1000 with default scaling factor
|
||||||
|
Classic_Mode: false
|
||||||
|
Skill_Scaling:
|
||||||
|
# This is the value that is skill level requirements are multiplied by in Classic Mode (Default is 10)
|
||||||
|
Classic_LevelReq_Factor: 10
|
||||||
|
# This is the value that the xp required to level is multiplied by when in classic mode
|
||||||
|
Classic_XP_Formula_Factor: 1
|
||||||
Locale: en_US
|
Locale: en_US
|
||||||
MOTD_Enabled: true
|
MOTD_Enabled: true
|
||||||
# Send a message to the player when his profile was successfully loaded
|
# Send a message to the player when his profile was successfully loaded
|
||||||
|
@ -408,8 +408,14 @@ Woodcutting.Effect.0=Tree Feller (ABILITY)
|
|||||||
Woodcutting.Effect.1=Make trees explode
|
Woodcutting.Effect.1=Make trees explode
|
||||||
Woodcutting.Effect.2=Leaf Blower
|
Woodcutting.Effect.2=Leaf Blower
|
||||||
Woodcutting.Effect.3=Blow Away Leaves
|
Woodcutting.Effect.3=Blow Away Leaves
|
||||||
Woodcutting.Effect.4=Double Drops
|
Woodcutting.Effect.4=Harvest Lumber
|
||||||
Woodcutting.Effect.5=Double the normal loot
|
Woodcutting.Effect.5=Skillfully extract more Lumber
|
||||||
|
Woodcutting.Effect.6=Splinter
|
||||||
|
Woodcutting.Effect.7=Cut down trees more efficiently.
|
||||||
|
Woodcutting.Effect.8=Bark Surgeon
|
||||||
|
Woodcutting.Effect.9=Extract useful materials when stripping trees.
|
||||||
|
Woodcutting.Effect.10=Nature's Bounty
|
||||||
|
Woodcutting.Effect.11=Gather experience from nature.
|
||||||
Woodcutting.Listener=Woodcutting:
|
Woodcutting.Listener=Woodcutting:
|
||||||
Woodcutting.SkillName=WOODCUTTING
|
Woodcutting.SkillName=WOODCUTTING
|
||||||
Woodcutting.Skills.TreeFeller.Off=[[RED]]**Tree Feller has worn off**
|
Woodcutting.Skills.TreeFeller.Off=[[RED]]**Tree Feller has worn off**
|
||||||
|
@ -12,7 +12,7 @@ description: >
|
|||||||
|
|
||||||
author: nossr50
|
author: nossr50
|
||||||
authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking]
|
authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking]
|
||||||
website: https://github.com/mcMMO-Dev/mcMMO
|
website: https://mcmmo.org
|
||||||
main: com.gmail.nossr50.mcMMO
|
main: com.gmail.nossr50.mcMMO
|
||||||
softdepend: [CombatTag, HealthBar]
|
softdepend: [CombatTag, HealthBar]
|
||||||
load: STARTUP
|
load: STARTUP
|
||||||
@ -668,10 +668,19 @@ permissions:
|
|||||||
mcmmo.ability.woodcutting.all:
|
mcmmo.ability.woodcutting.all:
|
||||||
description: Allows access to all Woodcutting abilities
|
description: Allows access to all Woodcutting abilities
|
||||||
children:
|
children:
|
||||||
mcmmo.ability.woodcutting.doubledrops: true
|
mcmmo.ability.woodcutting.harvestlumber: true
|
||||||
|
mcmmo.ability.woodcutting.splinter: true
|
||||||
|
mcmmo.ability.woodcutting.barksurgeon: true
|
||||||
|
mcmmo.ability.woodcutting.naturesbounty: true
|
||||||
mcmmo.ability.woodcutting.leafblower: true
|
mcmmo.ability.woodcutting.leafblower: true
|
||||||
mcmmo.ability.woodcutting.treefeller: true
|
mcmmo.ability.woodcutting.treefeller: true
|
||||||
mcmmo.ability.woodcutting.doubledrops:
|
mcmmo.ability.woodcutting.splinter:
|
||||||
|
description: Allows access to Splinter
|
||||||
|
mcmmo.ability.woodcutting.barksurgeon:
|
||||||
|
description: Allows access to Bark Surgeon
|
||||||
|
mcmmo.ability.woodcutting.naturesbounty:
|
||||||
|
description: Allows access to Natures Bounty
|
||||||
|
mcmmo.ability.woodcutting.harvestlumber:
|
||||||
description: Allows double drop chance when woodcutting
|
description: Allows double drop chance when woodcutting
|
||||||
mcmmo.ability.woodcutting.leafblower:
|
mcmmo.ability.woodcutting.leafblower:
|
||||||
description: Allows access to Leaf Blower ability
|
description: Allows access to Leaf Blower ability
|
||||||
|
Loading…
Reference in New Issue
Block a user