Bladeren bron

Some work on milestones is done

nossr50 6 jaren geleden
bovenliggende
commit
bec088c969

+ 6 - 0
Changelog.txt

@@ -9,6 +9,12 @@ Key:
 
 Version 2.1.0
  + 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) SecondarySkill is now SubSkill
  ! (API) AbilityType is now SuperAbility

+ 36 - 4
src/main/java/com/gmail/nossr50/commands/skills/WoodcuttingCommand.java

@@ -4,7 +4,10 @@ import java.util.ArrayList;
 import java.util.List;
 
 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.util.player.UserManager;
+import com.gmail.nossr50.util.skills.SkillMilestoneFactory;
 import org.bukkit.entity.Player;
 
 import com.gmail.nossr50.config.AdvancedConfig;
@@ -20,6 +23,9 @@ public class WoodcuttingCommand extends SkillCommand {
     private boolean canTreeFell;
     private boolean canLeafBlow;
     private boolean canDoubleDrop;
+    private boolean canSplinter;
+    private boolean canBarkSurgeon;
+    private boolean canNaturesBounty;
 
     public WoodcuttingCommand() {
         super(PrimarySkill.WOODCUTTING);
@@ -36,17 +42,29 @@ public class WoodcuttingCommand extends SkillCommand {
 
         // DOUBLE DROPS
         if (canDoubleDrop) {
-            String[] doubleDropStrings = calculateAbilityDisplayValues(skillValue, SubSkill.WOODCUTTING_DOUBLE_DROPS, isLucky);
-            doubleDropChance = doubleDropStrings[0];
-            doubleDropChanceLucky = doubleDropStrings[1];
+            if(AdvancedConfig.getInstance().isSubSkillClassic(SubSkill.WOODCUTTING_HARVEST_LUMBER))
+                setDoubleDropClassicChanceStrings(skillValue, isLucky);
+            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
     protected void permissionsCheck(Player 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);
+        canSplinter = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_SPLINTER);
+        canBarkSurgeon = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_BARK_SURGEON);
+        canNaturesBounty = Permissions.isSubSkillEnabled(player, SubSkill.WOODCUTTING_NATURES_BOUNTY);
     }
 
     @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")));
         }
 
+        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;
     }
 

+ 70 - 4
src/main/java/com/gmail/nossr50/config/AdvancedConfig.java

@@ -4,6 +4,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import com.gmail.nossr50.datatypes.skills.PrimarySkill;
 import com.gmail.nossr50.datatypes.skills.SubSkill;
 import com.gmail.nossr50.skills.alchemy.Alchemy;
 import com.gmail.nossr50.skills.fishing.Fishing;
@@ -33,6 +34,11 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
         // Validate all the settings!
         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 */
         if (getAbilityLength() < 1) {
             reason.add("Skills.General.Ability.IncreaseLevel should be at least 1!");
@@ -648,16 +654,17 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
         }
 
         /* WOODCUTTING */
+
         if (getLeafBlowUnlockLevel() < 0) {
             reason.add("Skills.Woodcutting.LeafBlower.UnlockLevel should be at least 0!");
         }
 
-        if (getMaxChance(SubSkill.WOODCUTTING_DOUBLE_DROPS) < 1) {
-            reason.add("Skills.Woodcutting.DoubleDrops.ChanceMax should be at least 1!");
+        if (getMaxChance(SubSkill.WOODCUTTING_HARVEST_LUMBER) < 1) {
+            reason.add("Skills.Woodcutting.HarvestLumber.ChanceMax should be at least 1!");
         }
 
-        if (getMaxBonusLevel(SubSkill.WOODCUTTING_DOUBLE_DROPS) < 1) {
-            reason.add("Skills.Woodcutting.DoubleDrops.MaxBonusLevel should be at least 1!");
+        if (getMaxBonusLevel(SubSkill.WOODCUTTING_HARVEST_LUMBER) < 1) {
+            reason.add("Skills.Woodcutting.HarvestLumber.MaxBonusLevel should be at least 1!");
         }
 
         /* KRAKEN */
@@ -690,6 +697,30 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
     public int getMaxBonusLevel(SubSkill subSkill) { return config.getInt(subSkill.getAdvConfigAddress() + ".MaxBonusLevel"); }
     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 */
     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 getPlayerDefeatMessage() { return config.getString("Kraken.Defeated_Message.Killed", ""); }
     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");
+                    }
+                }
+            }
+        }
+    }
 }

+ 8 - 0
src/main/java/com/gmail/nossr50/config/Config.java

@@ -244,8 +244,16 @@ public class Config extends AutoUpdateConfigLoader {
      */
 
     /* 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)
     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 boolean getMOTDEnabled() { return config.getBoolean("General.MOTD_Enabled", true); }
     public boolean getShowProfileLoadedMessage() { return config.getBoolean("General.Show_Profile_Loaded", true); }

+ 1 - 1
src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkill.java

@@ -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)),
     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)),
-    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 Color runescapeColor;

+ 80 - 13
src/main/java/com/gmail/nossr50/datatypes/skills/SkillMilestone.java

@@ -1,39 +1,106 @@
 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
- * 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
  */
 public class SkillMilestone {
-    private int unlockLevel; //Level that grants access to this skill
-    private SubSkill subskill; //Subskill that this milestone belongs to
+    private final int unlockLevel; //Level that grants access to this skill
+    private final SubSkill subskill; //Subskill that this milestone belongs to
     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.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;
+    /**
+     * Gets the level requirement for this subskill's rank
+     * @return The level required to use this subskill
+     */
+    public int getUnlockLevel() {
+        return unlockLevel;
     }
 
-    public SkillMilestone(SubSkill subskill, int unlockLevel)
+    /**
+     * Get's the current milestone the player is working towards
+     * @param playerProfile
+     * @return
+     */
+    public SkillMilestone getCurrentMilestoneForPlayer(PlayerProfile playerProfile)
     {
-        this(subskill, unlockLevel, null);
-    }
+        if(playerProfile.getSkillLevel(subskill.getParentSkill()) >= unlockLevel)
+        {
+            if(childMilestone != null)
+                return childMilestone.getCurrentMilestoneForPlayer(playerProfile);
 
-    public int getUnlockLevel() {
-        return unlockLevel;
+            return this;
+        } else {
+            return this;
+        }
     }
 
+    /**
+     * Gets the associated SubSkill for this milestone
+     * @return
+     */
     public SubSkill getSubskill() {
         return subskill;
     }
 
+    /**
+     * Gets the child milestone, which is the next rank of this skill
+     * @return The child milestone of this skill
+     */
     public SkillMilestone getChildMilestone() {
         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; }
 }

+ 43 - 13
src/main/java/com/gmail/nossr50/datatypes/skills/SubSkill.java

@@ -2,7 +2,6 @@ package com.gmail.nossr50.datatypes.skills;
 
 import com.gmail.nossr50.util.StringUtils;
 
-import com.gmail.nossr50.datatypes.skills.PrimarySkill.*;
 public enum SubSkill {
     /* !! 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,
 
     /* Woodcutting */
-    WOODCUTTING_TREE_FELLER,
-    WOODCUTTING_LEAF_BLOWER,
-    WOODCUTTING_SURGEON,
-    WOODCUTTING_NATURES_BOUNTY,
-    WOODCUTTING_SPLINTER,
-    WOODCUTTING_DOUBLE_DROPS;
+    WOODCUTTING_TREE_FELLER(5),
+    WOODCUTTING_LEAF_BLOWER(3),
+    WOODCUTTING_BARK_SURGEON(3),
+    WOODCUTTING_NATURES_BOUNTY(3),
+    WOODCUTTING_SPLINTER(3),
+    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 !!!
@@ -136,7 +161,7 @@ public enum SubSkill {
          * Find where to begin our substring (after the prefix)
          */
         String endResult = "";
-        char[] enumNameCharArray = subSkillName.toString().toCharArray();
+        char[] enumNameCharArray = subSkillName.toCharArray();
         int subStringIndex = 0;
 
         //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
          */
-        String subskillNameWithoutPrefix = subSkillName.toString().substring(subStringIndex);
-        String splitStrings[] = subskillNameWithoutPrefix.split("_");
-
-        for(String string : splitStrings)
+        String subskillNameWithoutPrefix = subSkillName.substring(subStringIndex);
+        if(subskillNameWithoutPrefix.contains("_"))
         {
-            endResult += StringUtils.getCapitalized(string);
+            String splitStrings[] = subskillNameWithoutPrefix.split("_");
+
+            for(String string : splitStrings)
+            {
+                endResult += StringUtils.getCapitalized(string);
+            }
+        } else {
+            endResult += StringUtils.getCapitalized(subskillNameWithoutPrefix);
         }
 
         return endResult;

+ 0 - 4
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -47,7 +47,6 @@ import net.shatteredlands.shatt.backup.ZipLibrary;
 import org.bukkit.Material;
 import org.bukkit.entity.Player;
 import org.bukkit.event.HandlerList;
-import org.bukkit.event.Listener;
 import org.bukkit.metadata.FixedMetadataValue;
 import org.bukkit.plugin.PluginManager;
 import org.bukkit.plugin.java.JavaPlugin;
@@ -189,9 +188,6 @@ public class mcMMO extends JavaPlugin {
 
             getServer().getPluginManager().disablePlugin(this);
         }
-
-        //Grab the setting for classic mode
-        classicModeEnabled = Config.getInstance().getClassicMode();
     }
 
     /**

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java

@@ -38,7 +38,7 @@ public class WoodcuttingManager extends SkillManager {
     }
 
     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);
     }
 
     /**

+ 12 - 2
src/main/java/com/gmail/nossr50/util/experience/FormulaManager.java

@@ -21,7 +21,14 @@ public class FormulaManager {
 
     private FormulaType previousFormula;
 
+    //Used for XP formula scaling
+    private boolean classicModeEnabled;
+    private int classicModeXPFormulaFactor;
+
     public FormulaManager() {
+        /* Setting for Classic Mode (Scales a lot of stuff up by * 10) */
+        classicModeEnabled = Config.getInstance().getClassicMode();
+        classicModeXPFormulaFactor = Config.getInstance().getClassicModeXPFormulaFactor();
         loadFormula();
     }
 
@@ -105,6 +112,9 @@ public class FormulaManager {
     public int getCachedXpToLevel(int level, FormulaType formulaType) {
         int experience;
 
+        //If we're in classic we use the XP factor from config settings
+        int skillSystemMultiplier = classicModeEnabled ? classicModeXPFormulaFactor : 10;
+
         if (formulaType == FormulaType.UNKNOWN) {
             formulaType = FormulaType.LINEAR;
         }
@@ -116,7 +126,7 @@ public class FormulaManager {
         switch (formulaType) {
             case LINEAR:
                 if (!experienceNeededLinear.containsKey(level)) {
-                    experience = (int) Math.floor( 10 * (base + level * multiplier));
+                    experience = (int) Math.floor( skillSystemMultiplier * (base + level * multiplier));
                     experienceNeededLinear.put(level, experience);
                 }
 
@@ -124,7 +134,7 @@ public class FormulaManager {
 
             case EXPONENTIAL:
                 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);
                 }
 

+ 55 - 0
src/main/java/com/gmail/nossr50/util/skills/SkillMilestoneFactory.java

@@ -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);
+    }
+}

+ 71 - 6
src/main/resources/advanced.yml

@@ -564,15 +564,80 @@ Skills:
     #  Settings for Woodcutting
     ###
     Woodcutting:
-        LeafBlower:
-            # UnlockLevel: At this level, the passive ability LeafBlower unlocks
-            UnlockLevel: 100
-
-        DoubleDrops:
-            # ChanceMax: Maximum chance of receiving double drops
+        Splinter:
+            Rank_Levels:
+                Rank_1:
+                    LevelReq: 5
+                Rank_2:
+                    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
             ChanceMax: 100.0
             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!
 ###

+ 8 - 1
src/main/resources/config.yml

@@ -8,7 +8,14 @@
 #  Settings for mcMMO in 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
     MOTD_Enabled: true
     # Send a message to the player when his profile was successfully loaded

+ 8 - 2
src/main/resources/locale/locale_en_US.properties

@@ -408,8 +408,14 @@ Woodcutting.Effect.0=Tree Feller (ABILITY)
 Woodcutting.Effect.1=Make trees explode
 Woodcutting.Effect.2=Leaf Blower
 Woodcutting.Effect.3=Blow Away Leaves
-Woodcutting.Effect.4=Double Drops
-Woodcutting.Effect.5=Double the normal loot
+Woodcutting.Effect.4=Harvest Lumber
+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.SkillName=WOODCUTTING
 Woodcutting.Skills.TreeFeller.Off=[[RED]]**Tree Feller has worn off**

+ 12 - 3
src/main/resources/plugin.yml

@@ -12,7 +12,7 @@ description: >
 
 author: nossr50
 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
 softdepend: [CombatTag, HealthBar]
 load: STARTUP
@@ -668,10 +668,19 @@ permissions:
     mcmmo.ability.woodcutting.all:
         description: Allows access to all Woodcutting abilities
         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.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
     mcmmo.ability.woodcutting.leafblower:
         description: Allows access to Leaf Blower ability