Some work on milestones is done

This commit is contained in:
nossr50 2018-12-31 10:10:00 -08:00
parent b9c8743ee3
commit bec088c969
15 changed files with 412 additions and 55 deletions

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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();
} }
/** /**

View File

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

View File

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

View File

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

View File

@ -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!
### ###

View File

@ -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

View File

@ -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**

View File

@ -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