2.1.0 is probably playable now, but not unfinished

This commit is contained in:
nossr50 2019-01-15 02:43:44 -08:00
parent 0acde4a8af
commit 4a30fcc2de
22 changed files with 489 additions and 396 deletions

View File

@ -59,7 +59,7 @@ Version 2.1.0
! (Skills) Some skill level rank requirements have changed ! (Skills) Some skill level rank requirements have changed
! (Skills) Fixed an edge case bug where Blast Mining wouldn't inform the player that it was on cooldown ! (Skills) Fixed an edge case bug where Blast Mining wouldn't inform the player that it was on cooldown
! (Skills) mcMMO skills will now be on a scale from 1-100 instead of 0-1000 (for existing mcMMO installs this is opt-in and off by default) ! (Skills) mcMMO skills will now be on a scale from 1-100 instead of 0-1000 (for existing mcMMO installs this is opt-in and off by default)
! (Skills) Skill Super Powers (Tree Feller, etc...) will now require level 10+ to use ! (Skills) Skill Super Powers are now unlockabled skills, unlocking at level 10
! (Skills) Acrobatics' Roll exploit detection was tweaked to still allow for Roll to trigger even if it rewards no XP ! (Skills) Acrobatics' Roll exploit detection was tweaked to still allow for Roll to trigger even if it rewards no XP
! (Skills) Acrobatics' Roll & Gracefull Roll are now considered the same skill (both mechanics are still there) ! (Skills) Acrobatics' Roll & Gracefull Roll are now considered the same skill (both mechanics are still there)
! (Skills) Woodcutting's Double Drop subskill is now named Harvest Lumber ! (Skills) Woodcutting's Double Drop subskill is now named Harvest Lumber
@ -92,7 +92,7 @@ Version 2.1.0
! (API) SecondaryAbilityEvent is now SubSkillEvent ! (API) SecondaryAbilityEvent is now SubSkillEvent
! (API) SubSkillType has had many helpful methods added to it ! (API) SubSkillType has had many helpful methods added to it
! (API) GREEN_THUMB_PLANT & GREEN_THUMB_BLOCK are replaced by GREEN_THUMB ! (API) GREEN_THUMB_PLANT & GREEN_THUMB_BLOCK are replaced by GREEN_THUMB
! (Code) Refactored some unreadable code relating to SecondaryAbility activation in SkillUtils ! (Code) Refactored some unreadable code relating to SecondaryAbilityType activation in SkillUtils
Version 2.0.0 Version 2.0.0
= Fixed an interaction between Tree Feller and Stripped Wood = Fixed an interaction between Tree Feller and Stripped Wood

View File

@ -1,6 +1,7 @@
package com.gmail.nossr50.commands.skills; package com.gmail.nossr50.commands.skills;
import com.gmail.nossr50.datatypes.json.McMMOUrl; import com.gmail.nossr50.datatypes.json.McMMOUrl;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.StringUtils; import com.gmail.nossr50.util.StringUtils;
public enum McMMOWebLinks { public enum McMMOWebLinks {
@ -20,4 +21,25 @@ public enum McMMOWebLinks {
{ {
return StringUtils.getCapitalized(toString()); return StringUtils.getCapitalized(toString());
} }
public String getLocaleDescription()
{
switch (this)
{
case WEBSITE:
return LocaleLoader.getString( "JSON.URL.Website");
case DISCORD:
return LocaleLoader.getString( "JSON.URL.Discord");
case PATREON:
return LocaleLoader.getString( "JSON.URL.Patreon");
case HELP_TRANSLATE:
return LocaleLoader.getString( "JSON.URL.Translation");
case SPIGOT:
return LocaleLoader.getString("JSON.URL.Spigot");
case WIKI:
return LocaleLoader.getString("JSON.URL.Wiki");
default:
return "";
}
}
} }

View File

@ -22,6 +22,9 @@ public class MmoInfoCommand implements TabExecutor {
@Override @Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) { public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
/*
* Only allow players to use this command
*/
if(commandSender instanceof Player) if(commandSender instanceof Player)
{ {
if(args.length < 1) if(args.length < 1)
@ -33,8 +36,14 @@ public class MmoInfoCommand implements TabExecutor {
if(args == null || args[0] == null) if(args == null || args[0] == null)
return false; return false;
//Real skill if(args[0].equalsIgnoreCase( "???"))
if(InteractionManager.getAbstractByName(args[0]) != null || PrimarySkillType.SUBSKILL_NAMES.contains(args[0])) {
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.Header"));
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.SubSkillHeader", "???"));
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.DetailsHeader"));
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.Mystery"));
return true;
} else if(InteractionManager.getAbstractByName(args[0]) != null || PrimarySkillType.SUBSKILL_NAMES.contains(args[0]))
{ {
displayInfo(player, args[0]); displayInfo(player, args[0]);
return true; return true;
@ -42,8 +51,10 @@ public class MmoInfoCommand implements TabExecutor {
//Not a real skill //Not a real skill
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.NoMatch")); player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.NoMatch"));
return true;
} }
} }
return false; return false;
} }
@ -59,8 +70,6 @@ public class MmoInfoCommand implements TabExecutor {
private void displayInfo(Player player, String subSkillName) private void displayInfo(Player player, String subSkillName)
{ {
System.out.println("[mcMMO] Debug: Grabbing info for skill "+subSkillName);
//Check to see if the skill exists in the new system //Check to see if the skill exists in the new system
AbstractSubSkill abstractSubSkill = InteractionManager.getAbstractByName(subSkillName); AbstractSubSkill abstractSubSkill = InteractionManager.getAbstractByName(subSkillName);
if(abstractSubSkill != null) if(abstractSubSkill != null)

View File

@ -174,7 +174,7 @@ public class TamingCommand extends SkillCommand {
protected List<TextComponent> getTextComponents(Player player) { protected List<TextComponent> getTextComponents(Player player) {
List<TextComponent> textComponents = new ArrayList<>(); List<TextComponent> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, PrimarySkillType.TAMING); TextComponentFactory.getSubSkillTextComponents(player, textComponents, this.skill);
return textComponents; return textComponents;
} }

View File

@ -6,6 +6,7 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TextComponentFactory; import com.gmail.nossr50.util.TextComponentFactory;
import com.gmail.nossr50.util.skills.RankUtils;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -40,12 +41,7 @@ public class WoodcuttingCommand extends SkillCommand {
// DOUBLE DROPS // DOUBLE DROPS
if (canDoubleDrop) { if (canDoubleDrop) {
if(AdvancedConfig.getInstance().isSubSkillClassic(SubSkillType.WOODCUTTING_HARVEST_LUMBER))
setDoubleDropClassicChanceStrings(skillValue, isLucky); setDoubleDropClassicChanceStrings(skillValue, isLucky);
else
{
//TODO: Set up datastrings for new harvest
}
} }
} }
@ -58,7 +54,7 @@ public class WoodcuttingCommand extends SkillCommand {
@Override @Override
protected void permissionsCheck(Player player) { protected void permissionsCheck(Player player) {
canTreeFell = Permissions.treeFeller(player); canTreeFell = Permissions.treeFeller(player);
canDoubleDrop = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_HARVEST_LUMBER) && !skill.getDoubleDropsDisabled(); canDoubleDrop = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_HARVEST_LUMBER) && !skill.getDoubleDropsDisabled() && RankUtils.getRank(player, SubSkillType.WOODCUTTING_HARVEST_LUMBER) >= 1;
canLeafBlow = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_LEAF_BLOWER); canLeafBlow = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_LEAF_BLOWER);
canSplinter = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_SPLINTER); canSplinter = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_SPLINTER);
canBarkSurgeon = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_BARK_SURGEON); canBarkSurgeon = Permissions.isSubSkillEnabled(player, SubSkillType.WOODCUTTING_BARK_SURGEON);

View File

@ -37,11 +37,6 @@ 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 (getAbilityLengthRetro() < 1) { if (getAbilityLengthRetro() < 1) {
reason.add("Skills.General.Ability.Length.RetroMode.IncreaseLevel should be at least 1!"); reason.add("Skills.General.Ability.Length.RetroMode.IncreaseLevel should be at least 1!");
@ -814,51 +809,6 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
return config.getBoolean(keyLocation); return config.getBoolean(keyLocation);
}*/ }*/
/**
* Gets the level required to unlock a subskill at a given rank
* @param subSkillType 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(SubSkillType subSkillType, int rank)
{
/*
* This is a bit messy but
*
* Some skills have per-rank settings as child nodes for Rank_x nodes
* If they do, we have to grab the child node named LevelReq from Rank_x for that skill
*
* Other skills which do not have complex per-rank settings will instead find their Level Requirement returned at Rank_x
*/
if(config.get(subSkillType.getAdvConfigAddress() + ".Rank_Levels.Rank_"+rank+".LevelReq") != null)
return config.getInt(subSkillType.getAdvConfigAddress() + ".Rank_Levels.Rank_"+rank+".LevelReq");
else
return config.getInt(subSkillType.getAdvConfigAddress() + ".Rank_Levels.Rank_"+rank);
}
@Deprecated /* NEW VERSION */
public int getSubSkillUnlockLevel(AbstractSubSkill abstractSubSkill, int rank)
{
/*
* This is a bit messy but
*
* Some skills have per-rank settings as child nodes for Rank_x nodes
* If they do, we have to grab the child node named LevelReq from Rank_x for that skill
*
* Other skills which do not have complex per-rank settings will instead find their Level Requirement returned at Rank_x
*/
String key = "Skills."+abstractSubSkill.getPrimaryKeyName()+"."+abstractSubSkill.getConfigKeyName();
if(config.get(key + ".Rank_Levels.Rank_"+rank+".LevelReq") != null)
return config.getInt(key + ".Rank_Levels.Rank_"+rank+".LevelReq");
else
return config.getInt(key + ".Rank_Levels.Rank_"+rank);
}
/** /**
* Some SubSkills have the ability to retain classic functionality * Some SubSkills have the ability to retain classic functionality
* @param subSkillType SubSkillType with classic functionality * @param subSkillType SubSkillType with classic functionality
@ -1034,39 +984,4 @@ 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(SubSkillType subSkillType : SubSkillType.values())
{
if(subSkillType.getParentSkill() == PrimarySkillType.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 < subSkillType.getNumRanks(); x++)
{
if(curRank > 0)
prevRank = curRank;
curRank = getSubSkillUnlockLevel(subSkillType, x);
//Do we really care if its below 0? Probably not
if(curRank < 0)
reasons.add(subSkillType.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 "+ subSkillType.toString()+" set up poorly, sequential ranks should have ascending requirements");
}
}
}
}
}
} }

View File

@ -557,9 +557,10 @@ public class Config extends AutoUpdateConfigLoader {
return (cap <= 0) ? Integer.MAX_VALUE : cap; return (cap <= 0) ? Integer.MAX_VALUE : cap;
} }
public int getSkillAbilityGate(PrimarySkillType skill) {
/*public int isSuperAbilityUnlocked(PrimarySkillType skill) {
return config.getInt("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Ability_Activation_Level_Gate"); return config.getInt("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Ability_Activation_Level_Gate");
} }*/
public boolean getTruncateSkills() { return config.getBoolean("General.TruncateSkills", false); } public boolean getTruncateSkills() { return config.getBoolean("General.TruncateSkills", false); }

View File

@ -1,5 +1,11 @@
package com.gmail.nossr50.config; package com.gmail.nossr50.config;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
import java.util.ArrayList;
import java.util.List;
public class RankConfig extends AutoUpdateConfigLoader { public class RankConfig extends AutoUpdateConfigLoader {
private static RankConfig instance; private static RankConfig instance;
@ -22,4 +28,93 @@ public class RankConfig extends AutoUpdateConfigLoader {
return instance; return instance;
} }
@Override
protected boolean validateKeys() {
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);
return noErrorsInConfig(reason);
}
/**
* Returns the unlock level for a subskill depending on the gamemode
* @param subSkillType target subskill
* @param rank the rank we are checking
* @return the level requirement for a subskill at this particular rank
*/
public int getSubSkillUnlockLevel(SubSkillType subSkillType, int rank)
{
String key = subSkillType.getRankConfigAddress();
return findRankByRootAddress(rank, key);
}
/**
* Returns the unlock level for a subskill depending on the gamemode
* @param abstractSubSkill target subskill
* @param rank the rank we are checking
* @return the level requirement for a subskill at this particular rank
*/
public int getSubSkillUnlockLevel(AbstractSubSkill abstractSubSkill, int rank)
{
String key = abstractSubSkill.getPrimaryKeyName()+"."+abstractSubSkill.getConfigKeyName();
return findRankByRootAddress(rank, key);
}
/**
* Returns the unlock level for a subskill depending on the gamemode
* @param key root address of the subskill in the rankskills.yml file
* @param rank the rank we are checking
* @return the level requirement for a subskill at this particular rank
*/
private int findRankByRootAddress(int rank, String key) {
String scalingKey = Config.getInstance().getIsRetroMode() ? ".RetroMode." : ".Standard.";
String targetRank = "Rank_" + rank;
key += scalingKey;
key += targetRank;
return config.getInt(key);
}
/**
* Checks for valid keys for subskill ranks
*/
private void checkKeys(List<String> reasons)
{
//For now we will only check ranks of stuff I've overhauled
for(SubSkillType subSkillType : SubSkillType.values())
{
//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 < subSkillType.getNumRanks(); x++)
{
if(curRank > 0)
prevRank = curRank;
curRank = getSubSkillUnlockLevel(subSkillType, x);
//Do we really care if its below 0? Probably not
if(curRank < 0)
{
reasons.add(subSkillType.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 "+ subSkillType.toString()+" set up poorly, sequential ranks should have ascending requirements");
}
}
}
}
} }

View File

@ -44,6 +44,7 @@ import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.ParticleEffectUtils; import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.PerksUtils; import com.gmail.nossr50.util.skills.PerksUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.sounds.SoundManager; import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType; import com.gmail.nossr50.util.sounds.SoundType;
@ -739,20 +740,17 @@ public class McMMOPlayer {
return; return;
} }
/*
* Check if the player has passed the gate requirement //TODO: This is hacky and temporary solution until skills are move to the new system
*/ //Potential problems with this include skills with two super abilities (ie mining)
if(Config.getInstance().getAbilitiesGateEnabled()) if(!skill.isSuperAbilityUnlocked(getPlayer()))
{ {
if(getSkillLevel(skill) < skill.getSkillAbilityGate()) int diff = RankUtils.getSuperAbilityUnlockRequirement(skill.getAbility()) - getSkillLevel(skill);
{
int diff = skill.getSkillAbilityGate() - getSkillLevel(skill);
//Inform the player they are not yet skilled enough //Inform the player they are not yet skilled enough
NotificationManager.sendPlayerInformation(player, NotificationType.ABILITY_COOLDOWN, "Skills.AbilityGateRequirementFail", String.valueOf(diff), skill.getName()); NotificationManager.sendPlayerInformation(player, NotificationType.ABILITY_COOLDOWN, "Skills.AbilityGateRequirementFail", String.valueOf(diff), skill.getName());
return; return;
} }
}
int timeRemaining = calculateTimeRemaining(ability); int timeRemaining = calculateTimeRemaining(ability);

View File

@ -23,6 +23,7 @@ import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils; import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.skills.ParticleEffectUtils; import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -40,7 +41,7 @@ public enum PrimarySkillType {
AXES(AxesManager.class, Color.AQUA, SuperAbilityType.SKULL_SPLITTER, ToolType.AXE, ImmutableList.of(SubSkillType.AXES_SKULL_SPLITTER, SubSkillType.AXES_ARMOR_IMPACT, SubSkillType.AXES_AXE_MASTERY, SubSkillType.AXES_CRITICAL_STRIKES, SubSkillType.AXES_GREATER_IMPACT)), AXES(AxesManager.class, Color.AQUA, SuperAbilityType.SKULL_SPLITTER, ToolType.AXE, ImmutableList.of(SubSkillType.AXES_SKULL_SPLITTER, SubSkillType.AXES_ARMOR_IMPACT, SubSkillType.AXES_AXE_MASTERY, SubSkillType.AXES_CRITICAL_STRIKES, SubSkillType.AXES_GREATER_IMPACT)),
EXCAVATION(ExcavationManager.class, Color.fromRGB(139, 69, 19), SuperAbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL, ImmutableList.of(SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER, SubSkillType.EXCAVATION_TREASURE_HUNTER)), EXCAVATION(ExcavationManager.class, Color.fromRGB(139, 69, 19), SuperAbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL, ImmutableList.of(SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER, SubSkillType.EXCAVATION_TREASURE_HUNTER)),
FISHING(FishingManager.class, Color.NAVY, ImmutableList.of(SubSkillType.FISHING_FISHERMANS_DIET, SubSkillType.FISHING_TREASURE_HUNTER, SubSkillType.FISHING_ICE_FISHING, SubSkillType.FISHING_MAGIC_HUNTER, SubSkillType.FISHING_MASTER_ANGLER, SubSkillType.FISHING_SHAKE)), FISHING(FishingManager.class, Color.NAVY, ImmutableList.of(SubSkillType.FISHING_FISHERMANS_DIET, SubSkillType.FISHING_TREASURE_HUNTER, SubSkillType.FISHING_ICE_FISHING, SubSkillType.FISHING_MAGIC_HUNTER, SubSkillType.FISHING_MASTER_ANGLER, SubSkillType.FISHING_SHAKE)),
HERBALISM(HerbalismManager.class, Color.GREEN, SuperAbilityType.GREEN_TERRA, ToolType.HOE, ImmutableList.of(SubSkillType.HERBALISM_FARMERS_DIET, SubSkillType.HERBALISM_GREEN_THUMB, SubSkillType.HERBALISM_DOUBLE_DROPS, SubSkillType.HERBALISM_HYLIAN_LUCK, SubSkillType.HERBALISM_SHROOM_THUMB)), HERBALISM(HerbalismManager.class, Color.GREEN, SuperAbilityType.GREEN_TERRA, ToolType.HOE, ImmutableList.of(SubSkillType.HERBALISM_GREEN_TERRA, SubSkillType.HERBALISM_FARMERS_DIET, SubSkillType.HERBALISM_GREEN_THUMB, SubSkillType.HERBALISM_DOUBLE_DROPS, SubSkillType.HERBALISM_HYLIAN_LUCK, SubSkillType.HERBALISM_SHROOM_THUMB)),
MINING(MiningManager.class, Color.GRAY, SuperAbilityType.SUPER_BREAKER, ToolType.PICKAXE, ImmutableList.of(SubSkillType.MINING_SUPER_BREAKER, SubSkillType.MINING_DEMOLITIONS_EXPERTISE, SubSkillType.MINING_BIGGER_BOMBS, SubSkillType.MINING_BLAST_MINING, SubSkillType.MINING_DOUBLE_DROPS)), MINING(MiningManager.class, Color.GRAY, SuperAbilityType.SUPER_BREAKER, ToolType.PICKAXE, ImmutableList.of(SubSkillType.MINING_SUPER_BREAKER, SubSkillType.MINING_DEMOLITIONS_EXPERTISE, SubSkillType.MINING_BIGGER_BOMBS, SubSkillType.MINING_BLAST_MINING, SubSkillType.MINING_DOUBLE_DROPS)),
REPAIR(RepairManager.class, Color.SILVER, ImmutableList.of(SubSkillType.REPAIR_ARCANE_FORGING, SubSkillType.REPAIR_REPAIR_MASTERY, SubSkillType.REPAIR_SUPER_REPAIR)), REPAIR(RepairManager.class, Color.SILVER, ImmutableList.of(SubSkillType.REPAIR_ARCANE_FORGING, SubSkillType.REPAIR_REPAIR_MASTERY, SubSkillType.REPAIR_SUPER_REPAIR)),
SALVAGE(SalvageManager.class, Color.ORANGE, ImmutableList.of(SubSkillType.SALVAGE_UNDERSTANDING_THE_ART, SubSkillType.SALVAGE_ADVANCED_SALVAGE, SubSkillType.SALVAGE_ARCANE_SALVAGE)), SALVAGE(SalvageManager.class, Color.ORANGE, ImmutableList.of(SubSkillType.SALVAGE_UNDERSTANDING_THE_ART, SubSkillType.SALVAGE_ADVANCED_SALVAGE, SubSkillType.SALVAGE_ARCANE_SALVAGE)),
@ -124,7 +125,7 @@ public enum PrimarySkillType {
return Config.getInstance().getLevelCap(this); return Config.getInstance().getLevelCap(this);
} }
public int getSkillAbilityGate() { return Config.getInstance().getSkillAbilityGate(this); } public boolean isSuperAbilityUnlocked(Player player) { return RankUtils.getRank(player, getAbility().getSubSkillTypeDefinition()) >= 1; }
public boolean getPVPEnabled() { public boolean getPVPEnabled() {
return Config.getInstance().getPVPEnabled(this); return Config.getInstance().getPVPEnabled(this);

View File

@ -11,20 +11,20 @@ public enum SubSkillType {
ACROBATICS_ROLL, ACROBATICS_ROLL,
/* ALCHEMY */ /* ALCHEMY */
ALCHEMY_CATALYSIS, ALCHEMY_CATALYSIS(1),
ALCHEMY_CONCOCTIONS(8), ALCHEMY_CONCOCTIONS(8),
/* ARCHERY */ /* ARCHERY */
ARCHERY_DAZE(), ARCHERY_DAZE,
ARCHERY_ARROW_RETRIEVAL, ARCHERY_ARROW_RETRIEVAL,
ARCHERY_SKILL_SHOT(20), ARCHERY_SKILL_SHOT(20),
/* Axes */ /* Axes */
AXES_ARMOR_IMPACT, AXES_ARMOR_IMPACT(20),
AXES_AXE_MASTERY(4), AXES_AXE_MASTERY(4),
AXES_CRITICAL_STRIKES, AXES_CRITICAL_STRIKES,
AXES_GREATER_IMPACT, AXES_GREATER_IMPACT,
AXES_SKULL_SPLITTER(0), AXES_SKULL_SPLITTER(1),
/* Excavation */ /* Excavation */
EXCAVATION_TREASURE_HUNTER, EXCAVATION_TREASURE_HUNTER,
@ -44,11 +44,12 @@ public enum SubSkillType {
HERBALISM_DOUBLE_DROPS, HERBALISM_DOUBLE_DROPS,
HERBALISM_HYLIAN_LUCK, HERBALISM_HYLIAN_LUCK,
HERBALISM_SHROOM_THUMB, HERBALISM_SHROOM_THUMB,
HERBALISM_GREEN_TERRA,
/* Mining */ /* Mining */
MINING_DOUBLE_DROPS, MINING_DOUBLE_DROPS,
MINING_SUPER_BREAKER(0), MINING_SUPER_BREAKER(1),
MINING_BLAST_MINING, MINING_BLAST_MINING(8),
MINING_BIGGER_BOMBS, MINING_BIGGER_BOMBS,
MINING_DEMOLITIONS_EXPERTISE, MINING_DEMOLITIONS_EXPERTISE,
@ -60,29 +61,29 @@ public enum SubSkillType {
/* Salvage */ /* Salvage */
SALVAGE_ADVANCED_SALVAGE, SALVAGE_ADVANCED_SALVAGE,
SALVAGE_ARCANE_SALVAGE, SALVAGE_ARCANE_SALVAGE,
SALVAGE_UNDERSTANDING_THE_ART, SALVAGE_UNDERSTANDING_THE_ART(8),
/* Smelting */ /* Smelting */
SMELTING_FLUX_MINING, SMELTING_FLUX_MINING,
SMELTING_FUEL_EFFICIENCY, SMELTING_FUEL_EFFICIENCY,
SMELTING_SECOND_SMELT, SMELTING_SECOND_SMELT,
SMELTING_UNDERSTANDING_THE_ART, SMELTING_UNDERSTANDING_THE_ART(8),
/* Swords */ /* Swords */
SWORDS_BLEED, SWORDS_BLEED,
SWORDS_COUNTER_ATTACK, SWORDS_COUNTER_ATTACK,
SWORDS_SERRATED_STRIKES, SWORDS_SERRATED_STRIKES(1),
/* Taming */ /* Taming */
TAMING_BEAST_LORE, TAMING_BEAST_LORE,
TAMING_CALL_OF_THE_WILD, TAMING_CALL_OF_THE_WILD,
TAMING_ENVIRONMENTALLY_AWARE, TAMING_ENVIRONMENTALLY_AWARE(1),
TAMING_FAST_FOOD_SERVICE, TAMING_FAST_FOOD_SERVICE(1),
TAMING_GORE, TAMING_GORE,
TAMING_HOLY_HOUND, TAMING_HOLY_HOUND(1),
TAMING_SHARPENED_CLAWS, TAMING_SHARPENED_CLAWS(1),
TAMING_SHOCK_PROOF, TAMING_SHOCK_PROOF(1),
TAMING_THICK_FUR, TAMING_THICK_FUR(1),
TAMING_PUMMEL, TAMING_PUMMEL,
/* Unarmed */ /* Unarmed */
@ -91,7 +92,7 @@ public enum SubSkillType {
UNARMED_DISARM, UNARMED_DISARM,
UNARMED_IRON_ARM_STYLE, UNARMED_IRON_ARM_STYLE,
UNARMED_IRON_GRIP, UNARMED_IRON_GRIP,
UNARMED_BERSERK(0), UNARMED_BERSERK(1),
/* Woodcutting */ /* Woodcutting */
WOODCUTTING_TREE_FELLER(5), WOODCUTTING_TREE_FELLER(5),
@ -99,7 +100,7 @@ public enum SubSkillType {
WOODCUTTING_BARK_SURGEON(3), WOODCUTTING_BARK_SURGEON(3),
WOODCUTTING_NATURES_BOUNTY(3), WOODCUTTING_NATURES_BOUNTY(3),
WOODCUTTING_SPLINTER(3), WOODCUTTING_SPLINTER(3),
WOODCUTTING_HARVEST_LUMBER(3); WOODCUTTING_HARVEST_LUMBER(1);
private final int numRanks; private final int numRanks;
//TODO: SuperAbilityType should also contain flags for active by default? Not sure if it should work that way. //TODO: SuperAbilityType should also contain flags for active by default? Not sure if it should work that way.
@ -131,13 +132,21 @@ public enum SubSkillType {
public PrimarySkillType getParentSkill() { return PrimarySkillType.bySecondaryAbility(this); } public PrimarySkillType getParentSkill() { return PrimarySkillType.bySecondaryAbility(this); }
/** /**
* Returns the permission root address for the advanced.yml for this subskill * Returns the root address for this skill in the advanced.yml file
* @return permission root address in advanced.yml for this subskill * @return the root address for this skill in advanced.yml
*/ */
public String getAdvConfigAddress() { public String getAdvConfigAddress() {
return "Skills." + StringUtils.getCapitalized(getParentSkill().toString()) + "." + getConfigName(toString()); return "Skills." + StringUtils.getCapitalized(getParentSkill().toString()) + "." + getConfigName(toString());
} }
/**
* Returns the root address for this skill in the rankskills.yml file
* @return the root address for this skill in rankskills.yml
*/
public String getRankConfigAddress() {
return StringUtils.getCapitalized(getParentSkill().toString()) + "." + getConfigName(toString());
}
/** /**
* Get the string representation of the permission node for this subskill * Get the string representation of the permission node for this subskill
* @return the permission node for this subskill * @return the permission node for this subskill

View File

@ -1,9 +1,15 @@
package com.gmail.nossr50.datatypes.skills; package com.gmail.nossr50.datatypes.skills;
import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.subskills.interfaces.SubSkill;
import com.gmail.nossr50.util.BlockUtils; import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils; import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.google.common.collect.ImmutableList;
import jdk.nashorn.internal.ir.annotations.Immutable;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -69,11 +75,27 @@ public enum SuperAbilityType {
null), null),
; ;
/*
* Defining their associated SubSkillType definitions
* This is a bit of a band-aid fix until the new skill system is in place
*/
static {
BERSERK.subSkillTypeDefinition = SubSkillType.UNARMED_BERSERK;
SUPER_BREAKER.subSkillTypeDefinition = SubSkillType.MINING_SUPER_BREAKER;
GIGA_DRILL_BREAKER.subSkillTypeDefinition = SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER;
GREEN_TERRA.subSkillTypeDefinition = SubSkillType.HERBALISM_GREEN_TERRA;
SKULL_SPLITTER.subSkillTypeDefinition = SubSkillType.AXES_SKULL_SPLITTER;
TREE_FELLER.subSkillTypeDefinition = SubSkillType.WOODCUTTING_TREE_FELLER;
SERRATED_STRIKES.subSkillTypeDefinition = SubSkillType.SWORDS_SERRATED_STRIKES;
BLAST_MINING.subSkillTypeDefinition = SubSkillType.MINING_BLAST_MINING;
}
private String abilityOn; private String abilityOn;
private String abilityOff; private String abilityOff;
private String abilityPlayer; private String abilityPlayer;
private String abilityRefresh; private String abilityRefresh;
private String abilityPlayerOff; private String abilityPlayerOff;
private SubSkillType subSkillTypeDefinition;
private SuperAbilityType(String abilityOn, String abilityOff, String abilityPlayer, String abilityRefresh, String abilityPlayerOff) { private SuperAbilityType(String abilityOn, String abilityOff, String abilityPlayer, String abilityRefresh, String abilityPlayerOff) {
this.abilityOn = abilityOn; this.abilityOn = abilityOn;
@ -200,4 +222,12 @@ public enum SuperAbilityType {
return false; return false;
} }
} }
/**
* Grabs the associated SubSkillType definition for this SuperAbilityType
* @return the matching SubSkillType definition for this SuperAbilityType
*/
public SubSkillType getSubSkillTypeDefinition() {
return subSkillTypeDefinition;
}
} }

View File

@ -210,7 +210,7 @@ public class mcMMO extends JavaPlugin {
placeStore.saveAll(); // Save our metadata placeStore.saveAll(); // Save our metadata
placeStore.cleanUp(); // Cleanup empty metadata stores placeStore.cleanUp(); // Cleanup empty metadata stores
} }
catch (NullPointerException e) {} catch (NullPointerException e) { e.printStackTrace(); }
debug("Canceling all tasks..."); debug("Canceling all tasks...");
getServer().getScheduler().cancelTasks(this); // This removes our tasks getServer().getScheduler().cancelTasks(this); // This removes our tasks

View File

@ -64,9 +64,7 @@ public final class Alchemy {
List<AlchemyBrewTask> toFinish = new ArrayList<AlchemyBrewTask>(); List<AlchemyBrewTask> toFinish = new ArrayList<AlchemyBrewTask>();
for (AlchemyBrewTask alchemyBrewTask : brewingStandMap.values()) { toFinish.addAll(brewingStandMap.values());
toFinish.add(alchemyBrewTask);
}
for (AlchemyBrewTask alchemyBrewTask : toFinish) { for (AlchemyBrewTask alchemyBrewTask : toFinish) {
alchemyBrewTask.finishImmediately(); alchemyBrewTask.finishImmediately();

View File

@ -18,7 +18,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
public final class Woodcutting { public final class Woodcutting {
public static int leafBlowerUnlockLevel = AdvancedConfig.getInstance().getLeafBlowUnlockLevel();
public static int treeFellerThreshold = Config.getInstance().getTreeFellerThreshold(); public static int treeFellerThreshold = Config.getInstance().getTreeFellerThreshold();

View File

@ -13,6 +13,7 @@ import com.gmail.nossr50.skills.woodcutting.Woodcutting.ExperienceGainMethod;
import com.gmail.nossr50.util.*; import com.gmail.nossr50.util.*;
import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.skills.CombatUtils; import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillActivationType; import com.gmail.nossr50.util.skills.SkillActivationType;
import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Material; import org.bukkit.Material;
@ -31,7 +32,9 @@ public class WoodcuttingManager extends SkillManager {
} }
public boolean canUseLeafBlower(ItemStack heldItem) { public boolean canUseLeafBlower(ItemStack heldItem) {
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.WOODCUTTING_LEAF_BLOWER) && getSkillLevel() >= Woodcutting.leafBlowerUnlockLevel && ItemUtils.isAxe(heldItem); return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.WOODCUTTING_LEAF_BLOWER)
&& RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.WOODCUTTING_LEAF_BLOWER)
&& ItemUtils.isAxe(heldItem);
} }
public boolean canUseTreeFeller(ItemStack heldItem) { public boolean canUseTreeFeller(ItemStack heldItem) {
@ -39,7 +42,9 @@ public class WoodcuttingManager extends SkillManager {
} }
protected boolean canGetDoubleDrops() { protected boolean canGetDoubleDrops() {
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.WOODCUTTING_HARVEST_LUMBER) && SkillUtils.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.WOODCUTTING_HARVEST_LUMBER, getPlayer(), this.skill, getSkillLevel(), activationChance); return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.WOODCUTTING_HARVEST_LUMBER)
&& RankUtils.hasReachedRank(1, getPlayer(), SubSkillType.WOODCUTTING_HARVEST_LUMBER)
&& SkillUtils.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.WOODCUTTING_HARVEST_LUMBER, getPlayer(), this.skill, getSkillLevel(), activationChance);
} }
/** /**

View File

@ -3,6 +3,7 @@ package com.gmail.nossr50.util;
import com.gmail.nossr50.commands.skills.McMMOWebLinks; import com.gmail.nossr50.commands.skills.McMMOWebLinks;
import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.RankConfig;
import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.json.McMMOUrl; import com.gmail.nossr50.datatypes.json.McMMOUrl;
import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.McMMOPlayer;
@ -23,12 +24,6 @@ import java.util.List;
* This class handles many of the JSON components that mcMMO makes and uses * This class handles many of the JSON components that mcMMO makes and uses
*/ */
public class TextComponentFactory { public class TextComponentFactory {
//public static HashMap<String, TextComponent> subSkillTextComponents;
//Yeah there's probably a better way to do this
//public static HashMap<String, BaseComponent[]> lockedComponentMap;
//public static BaseComponent[] webComponents;
/** /**
* Makes a text component using strings from a locale and supports passing an undefined number of variables to the LocaleLoader * Makes a text component using strings from a locale and supports passing an undefined number of variables to the LocaleLoader
@ -39,20 +34,13 @@ public class TextComponentFactory {
*/ */
public static TextComponent getNotificationMultipleValues(String localeKey, NotificationType notificationType, String... values) public static TextComponent getNotificationMultipleValues(String localeKey, NotificationType notificationType, String... values)
{ {
//TODO: Make this colored String preColoredString = LocaleLoader.getString(localeKey, (Object[]) values);
String preColoredString = LocaleLoader.getString(localeKey, values);
/*for(int x = 0; x < values.length; x++)
{
}*/
return new TextComponent(preColoredString); return new TextComponent(preColoredString);
} }
public static TextComponent getNotificationTextComponentFromLocale(String localeKey, NotificationType notificationType) public static TextComponent getNotificationTextComponentFromLocale(String localeKey, NotificationType notificationType)
{ {
return getNotificationTextComponent(LocaleLoader.getString(localeKey), notificationType); return getNotificationTextComponent(LocaleLoader.getString(localeKey));
} }
public static TextComponent getNotificationLevelUpTextComponent(McMMOPlayer player, PrimarySkillType skill, int currentLevel) public static TextComponent getNotificationLevelUpTextComponent(McMMOPlayer player, PrimarySkillType skill, int currentLevel)
@ -69,47 +57,18 @@ public class TextComponentFactory {
return textComponent; return textComponent;
} }
public static TextComponent getNotificationTextComponent(String text, NotificationType notificationType) private static TextComponent getNotificationTextComponent(String text)
{ {
TextComponent textComponent = new TextComponent(text);
//textComponent.setColor(getNotificationColor(notificationType)); //textComponent.setColor(getNotificationColor(notificationType));
return textComponent; return new TextComponent(text);
} }
/*public static ChatColor getNotificationColor(NotificationType notificationType)
{
ChatColor color = ChatColor.WHITE;
switch(notificationType)
{
case SUPER_ABILITY:
break;
case TOOL:
break;
case SUBSKILL_UNLOCKED:
break;
case SUBSKILL_MESSAGE:
break;
case LEVEL_UP_MESSAGE:
break;
case XP_GAIN:
break;
}
return color;
}*/
public static void sendPlayerUrlHeader(Player player) { public static void sendPlayerUrlHeader(Player player) {
if(!Config.getInstance().getUrlLinksEnabled()) if(!Config.getInstance().getUrlLinksEnabled())
return; return;
Player.Spigot spigotPlayer = player.spigot(); Player.Spigot spigotPlayer = player.spigot();
/*if(webComponents != null)
{
player.spigot().sendMessage(webComponents);
return;
}*/
TextComponent prefix = new TextComponent("[| "); TextComponent prefix = new TextComponent("[| ");
prefix.setColor(ChatColor.DARK_AQUA); prefix.setColor(ChatColor.DARK_AQUA);
TextComponent suffix = new TextComponent(" |]"); TextComponent suffix = new TextComponent(" |]");
@ -137,7 +96,6 @@ public class TextComponentFactory {
public static void sendPlayerSubSkillList(Player player, List<TextComponent> textComponents) public static void sendPlayerSubSkillList(Player player, List<TextComponent> textComponents)
{ {
TextComponent emptySpace = new TextComponent(" "); TextComponent emptySpace = new TextComponent(" ");
//TextComponent atSymbolText = new TextComponent(atSymbol);
ArrayList<BaseComponent> bulkMessage = new ArrayList<>(); ArrayList<BaseComponent> bulkMessage = new ArrayList<>();
int newLineCount = 0; //Hacky solution to wordwrap problems int newLineCount = 0; //Hacky solution to wordwrap problems
@ -181,7 +139,7 @@ public class TextComponentFactory {
player.spigot().sendMessage(bulkArray); player.spigot().sendMessage(bulkArray);
} }
public static TextComponent getWebLinkTextComponent(McMMOWebLinks webLinks) private static TextComponent getWebLinkTextComponent(McMMOWebLinks webLinks)
{ {
TextComponent webTextComponent; TextComponent webTextComponent;
@ -227,7 +185,7 @@ public class TextComponentFactory {
webTextComponent = new TextComponent("NOT DEFINED"); webTextComponent = new TextComponent("NOT DEFINED");
} }
webTextComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, getUrlHoverEvent(webLinks))); addNewHoverComponentToTextComponent(webTextComponent, getUrlHoverEvent(webLinks));
webTextComponent.setInsertion(webLinks.getUrl()); webTextComponent.setInsertion(webLinks.getUrl());
return webTextComponent; return webTextComponent;
@ -248,35 +206,38 @@ public class TextComponentFactory {
case WEBSITE: case WEBSITE:
addUrlHeaderHover(webLinks, componentBuilder); addUrlHeaderHover(webLinks, componentBuilder);
componentBuilder.append("\n\n").italic(false); componentBuilder.append("\n\n").italic(false);
componentBuilder.append("The official mcMMO Website!").color(ChatColor.GREEN); componentBuilder.append(webLinks.getLocaleDescription()).color(ChatColor.GREEN);
componentBuilder.append("\nDev Blogs, and information related to mcMMO can be found here").color(ChatColor.GRAY);
break; break;
case SPIGOT: case SPIGOT:
addUrlHeaderHover(webLinks, componentBuilder); addUrlHeaderHover(webLinks, componentBuilder);
componentBuilder.append("\n\n").italic(false); componentBuilder.append("\n\n").italic(false);
componentBuilder.append("The official mcMMO Spigot Resource Page!").color(ChatColor.GREEN); componentBuilder.append(webLinks.getLocaleDescription()).color(ChatColor.GREEN);
componentBuilder.append("\nI post regularly in the discussion thread here!").color(ChatColor.GRAY); componentBuilder.append("\nI post regularly in the discussion thread here!").color(ChatColor.GRAY);
break; break;
case PATREON: case PATREON:
addUrlHeaderHover(webLinks, componentBuilder); addUrlHeaderHover(webLinks, componentBuilder);
componentBuilder.append("\n\n").italic(false); componentBuilder.append("\n\n").italic(false);
componentBuilder.append("Support nossr50 and development of mcMMO on Patreon!").color(ChatColor.GREEN); componentBuilder.append(webLinks.getLocaleDescription()).color(ChatColor.GREEN);
componentBuilder.append("\n");
componentBuilder.append("Show support by buying me a coffee :)").italic(false).color(ChatColor.GRAY);
break; break;
case WIKI: case WIKI:
addUrlHeaderHover(webLinks, componentBuilder); addUrlHeaderHover(webLinks, componentBuilder);
componentBuilder.append("\n\n").italic(false); componentBuilder.append("\n\n").italic(false);
componentBuilder.append("The official mcMMO wiki!").color(ChatColor.GREEN); componentBuilder.append(webLinks.getLocaleDescription()).color(ChatColor.GREEN);
componentBuilder.append("\n"); componentBuilder.append("\n");
componentBuilder.append("I'm looking for more wiki staff, contact me on our discord!").italic(false).color(ChatColor.DARK_GRAY); componentBuilder.append("I'm looking for more wiki staff, contact me on our discord!").italic(false).color(ChatColor.DARK_GRAY);
break; break;
case DISCORD: case DISCORD:
addUrlHeaderHover(webLinks, componentBuilder); addUrlHeaderHover(webLinks, componentBuilder);
componentBuilder.append("\n\n").italic(false); componentBuilder.append("\n\n").italic(false);
componentBuilder.append("The official mcMMO Discord server!").color(ChatColor.GREEN); componentBuilder.append(webLinks.getLocaleDescription()).color(ChatColor.GREEN);
break; break;
case HELP_TRANSLATE: case HELP_TRANSLATE:
addUrlHeaderHover(webLinks, componentBuilder); addUrlHeaderHover(webLinks, componentBuilder);
componentBuilder.append("\n\n").italic(false); componentBuilder.append("\n\n").italic(false);
componentBuilder.append("mcMMO's translation service!").color(ChatColor.GREEN); componentBuilder.append(webLinks.getLocaleDescription()).color(ChatColor.GREEN);
componentBuilder.append("\n"); componentBuilder.append("\n");
componentBuilder.append("You can use this website to help translate mcMMO into your language!" + componentBuilder.append("You can use this website to help translate mcMMO into your language!" +
"\nIf you want to know more contact me in discord.").italic(false).color(ChatColor.DARK_GRAY); "\nIf you want to know more contact me in discord.").italic(false).color(ChatColor.DARK_GRAY);
@ -295,84 +256,85 @@ public class TextComponentFactory {
return new ClickEvent(ClickEvent.Action.OPEN_URL, url); return new ClickEvent(ClickEvent.Action.OPEN_URL, url);
} }
public static TextComponent getSubSkillTextComponent(Player player, SubSkillType subSkillType) private static TextComponent getSubSkillTextComponent(Player player, SubSkillType subSkillType)
{ {
//Get skill name
//Get skill name & description from our locale file
//String key = subSkillType.toString();
String skillName = subSkillType.getLocaleName(); String skillName = subSkillType.getLocaleName();
TextComponent textComponent;
//Setup Text Component //Setup Text Component
TextComponent textComponent = new TextComponent(skillName); if(RankUtils.hasUnlockedSubskill(player, subSkillType))
//textComponent.setColor(ChatColor.DARK_AQUA); {
textComponent = new TextComponent(skillName);
textComponent.setColor(ChatColor.DARK_AQUA);
textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/mmoinfo "+subSkillType.getNiceNameNoSpaces(subSkillType)));
}
else {
textComponent = new TextComponent("???");
textComponent.setColor(ChatColor.DARK_GRAY);
textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/mmoinfo ???"));
}
//Hover Event //Hover Event
textComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, getBaseComponent(player, subSkillType))); addNewHoverComponentToTextComponent(textComponent, getSubSkillHoverComponent(player, subSkillType));
//Insertion //Insertion
textComponent.setInsertion(skillName); textComponent.setInsertion(skillName);
textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/mmoinfo "+subSkillType.getNiceNameNoSpaces(subSkillType)));
return textComponent; return textComponent;
} }
public static TextComponent getSubSkillTextComponent(Player player, AbstractSubSkill abstractSubSkill) private static void addNewHoverComponentToTextComponent(TextComponent textComponent, BaseComponent[] baseComponent) {
textComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, baseComponent));
}
private static TextComponent getSubSkillTextComponent(Player player, AbstractSubSkill abstractSubSkill)
{ {
//String key = abstractSubSkill.getConfigKeyName(); //String key = abstractSubSkill.getConfigKeyName();
String skillName = abstractSubSkill.getNiceName(); String skillName = abstractSubSkill.getNiceName();
//Setup Text Component //Setup Text Component
TextComponent textComponent = new TextComponent(skillName); TextComponent textComponent;
//Setup Text Component
if(RankUtils.hasUnlockedSubskill(player, abstractSubSkill))
{
textComponent = new TextComponent(skillName);
textComponent.setColor(ChatColor.DARK_AQUA); textComponent.setColor(ChatColor.DARK_AQUA);
textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/mmoinfo "+abstractSubSkill.getConfigKeyName()));
}
else {
textComponent = new TextComponent("???");
textComponent.setColor(ChatColor.DARK_GRAY);
textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/mmoinfo ???"));
}
//Hover Event //Hover Event
textComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, getBaseComponent(player, abstractSubSkill))); addNewHoverComponentToTextComponent(textComponent, getSubSkillHoverComponent(player, abstractSubSkill));
//Insertion //Insertion
textComponent.setInsertion(skillName); textComponent.setInsertion(skillName);
textComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/mmoinfo "+abstractSubSkill.getConfigKeyName()));
return textComponent; return textComponent;
} }
private static BaseComponent[] getBaseComponent(Player player, AbstractSubSkill abstractSubSkill) private static BaseComponent[] getSubSkillHoverComponent(Player player, AbstractSubSkill abstractSubSkill)
{ {
int curRank = RankUtils.getRank(player, abstractSubSkill); return getSubSkillHoverEventJSON(abstractSubSkill, player);
String key = abstractSubSkill.getConfigKeyName();
//If the player hasn't unlocked this skill yet we use a different JSON template
if(abstractSubSkill.getNumRanks() > 0 && curRank == 0)
{
BaseComponent[] newComponents = getSubSkillHoverEventJSON(abstractSubSkill, player, curRank);
return newComponents;
} }
return getSubSkillHoverEventJSON(abstractSubSkill, player, curRank); private static BaseComponent[] getSubSkillHoverComponent(Player player, SubSkillType subSkillType)
}
private static BaseComponent[] getBaseComponent(Player player, SubSkillType subSkillType)
{ {
int curRank = RankUtils.getRank(player, subSkillType); return getSubSkillHoverEventJSON(subSkillType, player);
String key = subSkillType.toString();
//If the player hasn't unlocked this skill yet we use a different JSON template
if(subSkillType.getNumRanks() > 0 && curRank == 0)
{
BaseComponent[] newComponents = getSubSkillHoverEventJSON(subSkillType, player, curRank);
return newComponents;
}
return getSubSkillHoverEventJSON(subSkillType, player, curRank);
} }
/** /**
* Used for the skill in the new skill system (Deriving from AbstractSubSkill) * Used for the skill in the new skill system (Deriving from AbstractSubSkill)
* @param abstractSubSkill this subskill * @param abstractSubSkill this subskill
* @param player * @param player the player who owns this subskill
* @param curRank * @return the hover basecomponent object for this subskill
* @return
*/ */
private static BaseComponent[] getSubSkillHoverEventJSON(AbstractSubSkill abstractSubSkill, Player player, int curRank) private static BaseComponent[] getSubSkillHoverEventJSON(AbstractSubSkill abstractSubSkill, Player player)
{ {
String skillName = abstractSubSkill.getNiceName(); String skillName = abstractSubSkill.getNiceName();
@ -390,10 +352,15 @@ public class TextComponentFactory {
ChatColor ccLevelRequirement = ChatColor.BLUE; ChatColor ccLevelRequirement = ChatColor.BLUE;
ChatColor ccLevelRequired = ChatColor.RED; ChatColor ccLevelRequired = ChatColor.RED;
//SubSkillType Name ComponentBuilder componentBuilder;
ComponentBuilder componentBuilder = getNewComponentBuilder(skillName, ccSubSkillHeader);
if(RankUtils.getRank(player, abstractSubSkill) == 0) //SubSkillType Name
if(RankUtils.hasUnlockedSubskill(player, abstractSubSkill))
componentBuilder = getNewComponentBuilder(skillName, ccSubSkillHeader);
else
componentBuilder = getNewComponentBuilder("???", ccSubSkillHeader);
if(!RankUtils.hasUnlockedSubskill(player, abstractSubSkill))
{ {
//Skill is not unlocked yet //Skill is not unlocked yet
addLocked(abstractSubSkill, ccLocked, ccLevelRequirement, ccLevelRequired, componentBuilder); addLocked(abstractSubSkill, ccLocked, ccLevelRequirement, ccLevelRequired, componentBuilder);
@ -436,15 +403,26 @@ public class TextComponentFactory {
} }
} }
private static void addLocked(SubSkillType subSkillType, ChatColor ccLocked, ChatColor ccLevelRequirement, ChatColor ccLevelRequired, ComponentBuilder componentBuilder) {
addLocked(ccLocked, ccLevelRequirement, componentBuilder);
componentBuilder.append(String.valueOf(RankConfig.getInstance().getSubSkillUnlockLevel(subSkillType, 1))).color(ccLevelRequired);
//componentBuilder.append("\n");
}
private static void addLocked(AbstractSubSkill abstractSubSkill, ChatColor ccLocked, ChatColor ccLevelRequirement, ChatColor ccLevelRequired, ComponentBuilder componentBuilder) { private static void addLocked(AbstractSubSkill abstractSubSkill, ChatColor ccLocked, ChatColor ccLevelRequirement, ChatColor ccLevelRequired, ComponentBuilder componentBuilder) {
addLocked(ccLocked, ccLevelRequirement, componentBuilder);
componentBuilder.append(String.valueOf(RankConfig.getInstance().getSubSkillUnlockLevel(abstractSubSkill, 1))).color(ccLevelRequired);
//componentBuilder.append("\n");
}
private static void addLocked(ChatColor ccLocked, ChatColor ccLevelRequirement, ComponentBuilder componentBuilder) {
componentBuilder.append(LocaleLoader.getString("JSON.Locked")).color(ccLocked).bold(true); componentBuilder.append(LocaleLoader.getString("JSON.Locked")).color(ccLocked).bold(true);
componentBuilder.append("\n").append("\n").bold(false); componentBuilder.append("\n").append("\n").bold(false);
componentBuilder.append(LocaleLoader.getString("JSON.LevelRequirement") + ": ").color(ccLevelRequirement); componentBuilder.append(LocaleLoader.getString("JSON.LevelRequirement") + ": ").color(ccLevelRequirement);
componentBuilder.append(String.valueOf(AdvancedConfig.getInstance().getSubSkillUnlockLevel(abstractSubSkill, 1))).color(ccLevelRequired);
} }
@Deprecated @Deprecated
private static BaseComponent[] getSubSkillHoverEventJSON(SubSkillType subSkillType, Player player, int curRank) private static BaseComponent[] getSubSkillHoverEventJSON(SubSkillType subSkillType, Player player)
{ {
String skillName = subSkillType.getLocaleName(); String skillName = subSkillType.getLocaleName();
@ -462,17 +440,18 @@ public class TextComponentFactory {
ChatColor ccLevelRequirement = ChatColor.BLUE; ChatColor ccLevelRequirement = ChatColor.BLUE;
ChatColor ccLevelRequired = ChatColor.RED; ChatColor ccLevelRequired = ChatColor.RED;
//SubSkillType Name ComponentBuilder componentBuilder;
ComponentBuilder componentBuilder = getNewComponentBuilder(skillName, ccSubSkillHeader);
if(RankUtils.getRank(player, subSkillType) == 0) //SubSkillType Name
if(RankUtils.hasUnlockedSubskill(player, subSkillType))
componentBuilder = getNewComponentBuilder(skillName, ccSubSkillHeader);
else
componentBuilder = getNewComponentBuilder("???", ccSubSkillHeader);
if(!RankUtils.hasUnlockedSubskill(player, subSkillType))
{ {
//Skill is not unlocked yet //Skill is not unlocked yet
componentBuilder.append(LocaleLoader.getString("JSON.Locked")).color(ccLocked).bold(true); addLocked(subSkillType, ccLocked, ccLevelRequirement, ccLevelRequired, componentBuilder);
componentBuilder.append("\n").append("\n").bold(false);
componentBuilder.append(LocaleLoader.getString("JSON.LevelRequirement") +": ").color(ccLevelRequirement);
componentBuilder.append(String.valueOf(AdvancedConfig.getInstance().getSubSkillUnlockLevel(subSkillType, 1))).color(ccLevelRequired);
} else { } else {
//addSubSkillTypeToHoverEventJSON(subSkillType, componentBuilder); //addSubSkillTypeToHoverEventJSON(subSkillType, componentBuilder);
@ -484,13 +463,13 @@ public class TextComponentFactory {
//Empty line //Empty line
componentBuilder.append("\n").bold(false); componentBuilder.append("\n").bold(false);
} }
}
componentBuilder.append(LocaleLoader.getString("JSON.DescriptionHeader")); componentBuilder.append(LocaleLoader.getString("JSON.DescriptionHeader"));
componentBuilder.color(ccDescriptionHeader); componentBuilder.color(ccDescriptionHeader);
componentBuilder.append("\n"); componentBuilder.append("\n");
componentBuilder.append(subSkillType.getLocaleDescription()); componentBuilder.append(subSkillType.getLocaleDescription());
componentBuilder.color(ccDescription); componentBuilder.color(ccDescription);
}
return componentBuilder.create(); return componentBuilder.create();
} }

View File

@ -1,7 +1,8 @@
package com.gmail.nossr50.util.skills; package com.gmail.nossr50.util.skills;
import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.RankConfig;
import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill; import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -38,6 +39,58 @@ public class RankUtils {
} }
} }
/**
* Returns whether or not the player has unlocked the first rank in target subskill
* @param player the player
* @param subSkillType the target subskill
* @return true if the player has at least one rank in the skill
*/
public static boolean hasUnlockedSubskill(Player player, SubSkillType subSkillType)
{
int curRank = getRank(player, subSkillType);
//-1 means the skill has no unlockable levels and is therefor unlocked
return curRank == -1 || curRank >= 1;
}
/**
* Returns whether or not the player has unlocked the first rank in target subskill
* @param player the player
* @param abstractSubSkill the target subskill
* @return true if the player has at least one rank in the skill
*/
public static boolean hasUnlockedSubskill(Player player, AbstractSubSkill abstractSubSkill)
{
int curRank = getRank(player, abstractSubSkill);
//-1 means the skill has no unlockable levels and is therefor unlocked
return curRank == -1 || curRank >= 1;
}
/**
* Returns whether or not the player has reached the specified rank in target subskill
* @param rank the target rank
* @param player the player
* @param subSkillType the target subskill
* @return true if the player is at least that rank in this subskill
*/
public static boolean hasReachedRank(int rank, Player player, SubSkillType subSkillType)
{
return getRank(player, subSkillType) >= rank;
}
/**
* Returns whether or not the player has reached the specified rank in target subskill
* @param rank the target rank
* @param player the player
* @param abstractSubSkill the target subskill
* @return true if the player is at least that rank in this subskill
*/
public static boolean hasReachedRank(int rank, Player player, AbstractSubSkill abstractSubSkill)
{
return getRank(player, abstractSubSkill) >= rank;
}
/** /**
* Gets the current rank of the subskill for the player * Gets the current rank of the subskill for the player
* @param player The player in question * @param player The player in question
@ -162,6 +215,23 @@ public class RankUtils {
subSkillRanks.put(s, new HashMap<>()); subSkillRanks.put(s, new HashMap<>());
} }
/* public static int getSubSkillUnlockRequirement(SubSkillType subSkillType)
{
String skillName = subSkillType.toString();
int numRanks = subSkillType.getNumRanks();
if(subSkillRanks == null)
subSkillRanks = new HashMap<>();
if(numRanks == 0)
return -1; //-1 Means the skill doesn't have ranks
if(subSkillRanks.get(skillName) == null && numRanks > 0)
addRanks(subSkillType);
return subSkillRanks.get(subSkillType.toString()).get(1);
}*/
/** /**
* Gets the unlock level for a specific rank in a subskill * Gets the unlock level for a specific rank in a subskill
* @param subSkillType The target subskill * @param subSkillType The target subskill
@ -169,13 +239,18 @@ public class RankUtils {
* @return The level at which this rank unlocks * @return The level at which this rank unlocks
*/ */
@Deprecated @Deprecated
private static int getUnlockLevel(SubSkillType subSkillType, int rank) public static int getUnlockLevel(SubSkillType subSkillType, int rank)
{ {
return AdvancedConfig.getInstance().getSubSkillUnlockLevel(subSkillType, rank); return RankConfig.getInstance().getSubSkillUnlockLevel(subSkillType, rank);
} }
private static int getUnlockLevel(AbstractSubSkill abstractSubSkill, int rank) public static int getUnlockLevel(AbstractSubSkill abstractSubSkill, int rank)
{ {
return AdvancedConfig.getInstance().getSubSkillUnlockLevel(abstractSubSkill, rank); return RankConfig.getInstance().getSubSkillUnlockLevel(abstractSubSkill, rank);
}
public static int getSuperAbilityUnlockRequirement(SuperAbilityType superAbilityType)
{
return getUnlockLevel(superAbilityType.getSubSkillTypeDefinition(), 1);
} }
} }

View File

@ -122,43 +122,11 @@ Skills:
MaxBonusLevel: 100 MaxBonusLevel: 100
MinSpeed: 1.0 MinSpeed: 1.0
MaxSpeed: 4.0 MaxSpeed: 4.0
# Rank_Levels: Alchemy level where rank gets unlocked
Rank_Levels:
Rank_1: 0
Rank_2: 12
Rank_3: 25
Rank_4: 37
Rank_5: 50
Rank_6: 62
Rank_7: 75
Rank_8: 87
# #
# Settings for Archery # Settings for Archery
### ###
Archery: Archery:
SkillShot: SkillShot:
Rank_Levels:
Rank_1: 5
Rank_2: 10
Rank_3: 15
Rank_4: 20
Rank_5: 25
Rank_6: 30
Rank_7: 35
Rank_8: 40
Rank_9: 45
Rank_10: 50
Rank_11: 55
Rank_12: 60
Rank_13: 65
Rank_14: 70
Rank_15: 75
Rank_16: 80
Rank_17: 85
Rank_18: 90
Rank_19: 95
Rank_20: 100
# RankDamageMultiplier: The current rank of this subskill is multiplied by this value to determine the bonus damage, rank 20 would result in 200% damage increase with a value of 10.0 for RankDamageMultiplier # RankDamageMultiplier: The current rank of this subskill is multiplied by this value to determine the bonus damage, rank 20 would result in 200% damage increase with a value of 10.0 for RankDamageMultiplier
# RankDamageMultiplier is a percentage # RankDamageMultiplier is a percentage
RankDamageMultiplier: 10.0 RankDamageMultiplier: 10.0
@ -189,11 +157,6 @@ Skills:
# This number is multiplied by the current rank the player has in this subskill to find the amount of additional damage to apply # This number is multiplied by the current rank the player has in this subskill to find the amount of additional damage to apply
# With the default config value of 1.0, at rank 4 a player will deal 4.0 extra damage with Axes (1.0 * 4) # With the default config value of 1.0, at rank 4 a player will deal 4.0 extra damage with Axes (1.0 * 4)
RankDamageMultiplier: 1.0 RankDamageMultiplier: 1.0
Rank_Levels:
Rank_1: 5
Rank_2: 10
Rank_3: 15
Rank_4: 20
CriticalStrikes: CriticalStrikes:
# ChanceMax: Maximum chance of causing a critical hit when on <MaxBonusLevel> or higher # ChanceMax: Maximum chance of causing a critical hit when on <MaxBonusLevel> or higher
# MaxBonusLevel: Level where <ChanceMax> of causing critical hits is reached # MaxBonusLevel: Level where <ChanceMax> of causing critical hits is reached
@ -226,16 +189,6 @@ Skills:
# Settings for Fishing # Settings for Fishing
### ###
Fishing: Fishing:
# Rank_Levels: Fishing level where rank gets unlocked
Rank_Levels:
Rank_1: 0
Rank_2: 12
Rank_3: 25
Rank_4: 37
Rank_5: 50
Rank_6: 62
Rank_7: 70
Rank_8: 87
ShakeChance: ShakeChance:
Rank_1: 15.0 Rank_1: 15.0
@ -277,15 +230,11 @@ Skills:
# Settings for Herbalism # Settings for Herbalism
### ###
Herbalism: Herbalism:
FarmersDiet:
# This determines when Farmers Diet adds extra hunger recovery to food
RankChange: 20
GreenThumb: GreenThumb:
# StageChange: Level value when the GreenThumb stage rank goes up # StageChange: Level value when the GreenThumb stage rank goes up
# ChanceMax: Maximum chance of GreenThumb when on <MaxBonusLevel> or higher # ChanceMax: Maximum chance of GreenThumb when on <MaxBonusLevel> or higher
# MaxBonusLevel: On this level, GreenThumb chance will be <ChanceMax> # MaxBonusLevel: On this level, GreenThumb chance will be <ChanceMax>
StageChange: 20
ChanceMax: 100.0 ChanceMax: 100.0
MaxBonusLevel: 100 MaxBonusLevel: 100
@ -318,15 +267,6 @@ Skills:
# BlastMining_Rank: BlastMining rank unlocks # BlastMining_Rank: BlastMining rank unlocks
BlastMining: BlastMining:
Rank_Levels:
Rank_1: 12
Rank_2: 25
Rank_3: 37
Rank_4: 50
Rank_5: 62
Rank_6: 75
Rank_7: 87
Rank_8: 100
# BlastDamageDecrease Ranks: % of damage reduced from TNT explosions # BlastDamageDecrease Ranks: % of damage reduced from TNT explosions
BlastDamageDecrease: BlastDamageDecrease:
@ -400,15 +340,6 @@ Skills:
ArcaneForging: ArcaneForging:
May_Lose_Enchants: true May_Lose_Enchants: true
Rank_Levels:
Rank_1: 12
Rank_2: 25
Rank_3: 37
Rank_4: 50
Rank_5: 62
Rank_6: 75
Rank_7: 87
Rank_8: 100
Keep_Enchants_Chance: Keep_Enchants_Chance:
Rank_1: 10.0 Rank_1: 10.0
Rank_2: 20.0 Rank_2: 20.0
@ -490,17 +421,6 @@ Skills:
UnlockLevel: 25 UnlockLevel: 25
Chance: 33.0 Chance: 33.0
# Rank_Levels: Smelting level where rank gets unlocked
Rank_Levels:
Rank_1: 12
Rank_2: 25
Rank_3: 37
Rank_4: 50
Rank_5: 62
Rank_6: 75
Rank_7: 87
Rank_8: 100
# VanillaXPMultiplier: Vanilla XP gained from smelting ores is multiplied by these values. # VanillaXPMultiplier: Vanilla XP gained from smelting ores is multiplied by these values.
VanillaXPMultiplier: VanillaXPMultiplier:
Rank_1: 1 Rank_1: 1
@ -630,14 +550,6 @@ Skills:
# Settings for Woodcutting # Settings for Woodcutting
### ###
Woodcutting: Woodcutting:
Splinter:
Rank_Levels:
Rank_1:
LevelReq: 5
Rank_2:
LevelReq: 30
Rank_3:
LevelReq: 55
TreeFeller: TreeFeller:
# If set to true then tree feller will not use the new system and will use its old behaviour # If set to true then tree feller will not use the new system and will use its old behaviour
Classic: false Classic: false
@ -645,64 +557,27 @@ Skills:
ChargeRate: 600 ChargeRate: 600
Rank_Levels: Rank_Levels:
Rank_1: Rank_1:
LevelReq: 10
TreeSizeMax: 100 TreeSizeMax: 100
Charges: 1 Charges: 1
Rank_2: Rank_2:
LevelReq: 25
TreeSizeMax: 200 TreeSizeMax: 200
Charges: 1 Charges: 1
Rank_3: Rank_3:
LevelReq: 50
TreeSizeMax: 200 TreeSizeMax: 200
Charges: 2 Charges: 2
Rank_4: Rank_4:
LevelReq: 75
TreeSizeMax: 200 TreeSizeMax: 200
Charges: 3 Charges: 3
Rank_5: Rank_5:
LevelReq: 100
TreeSizeMax: 500 TreeSizeMax: 500
Charges: 3 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 # Double Drops
HarvestLumber: HarvestLumber:
Classic: false
# ChanceMax & MaxBonusLevel are only used for Classic, I'll make that more clear in the future. # 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%) # 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
Style: Style:
JSON: JSON:
Notification: Notification:

View File

@ -277,8 +277,6 @@ Abilities:
Enabled: true Enabled: true
Messages: true Messages: true
Activation: Activation:
# If set to true, abilities will not be available until they meet specific level requirements to use
Level_Gate_Abilities: true
Only_Activate_When_Sneaking: false Only_Activate_When_Sneaking: false
Cooldowns: Cooldowns:
Berserk: 240 Berserk: 240

View File

@ -40,6 +40,12 @@ JSON.Taming=Taming
JSON.Unarmed=Unarmed JSON.Unarmed=Unarmed
JSON.Woodcutting=Woodcutting JSON.Woodcutting=Woodcutting
JSON.LevelUp=increased to JSON.LevelUp=increased to
JSON.URL.Website=The official mcMMO Website!
JSON.URL.Discord=The official mcMMO Discord server!
JSON.URL.Patreon=Support nossr50 and his work for mcMMO on Patreon!
JSON.URL.Spigot=The official mcMMO Spigot Resource Page!
JSON.URL.Translation=Translate mcMMO into other languages!
JSON.URL.Wiki=The official mcMMO wiki!
#This is the message sent to players when an ability is activated #This is the message sent to players when an ability is activated
JSON.Notification.SuperAbility={0} JSON.Notification.SuperAbility={0}
@ -634,6 +640,7 @@ Commands.Usage.Skill=skill
Commands.Usage.SubSkill=subskill Commands.Usage.SubSkill=subskill
Commands.Usage.XP=xp Commands.Usage.XP=xp
Commands.Description.mmoinfo=Read details about a skill or mechanic. Commands.Description.mmoinfo=Read details about a skill or mechanic.
Commands.MmoInfo.Mystery=[[GRAY]]You haven't unlocked this skill yet, but when you do you will be able to read details about it here!
Commands.MmoInfo.NoMatch=That subskill doesn't exist! Commands.MmoInfo.NoMatch=That subskill doesn't exist!
Commands.MmoInfo.Header=[[DARK_AQUA]]-=[]=====[][[GOLD]] MMO Info [[DARK_AQUA]][]=====[]=- Commands.MmoInfo.Header=[[DARK_AQUA]]-=[]=====[][[GOLD]] MMO Info [[DARK_AQUA]][]=====[]=-
Commands.MmoInfo.SubSkillHeader=[[GOLD]]Name:[[YELLOW]] {0} Commands.MmoInfo.SubSkillHeader=[[GOLD]]Name:[[YELLOW]] {0}

View File

@ -3,9 +3,8 @@
# You can however, change when they unlock, if you make all ranks of a skill level 0 for example every player will have the most powerful version of that skill right away. # You can however, change when they unlock, if you make all ranks of a skill level 0 for example every player will have the most powerful version of that skill right away.
# Retro Mode and Standard have separate config settings to make it easier for server owners to understand the difference between the two # Retro Mode and Standard have separate config settings to make it easier for server owners to understand the difference between the two
# Retro Mode is setup to be an entirely cosmetic change, keeping the old 0-1000 feeling of mcMMO # Retro Mode is setup to be an entirely cosmetic change, keeping the old 0-1000 feeling of mcMMO
# Retro Mode has 10x faster leveling and 10x higher skill requirements, if you do the math you can see its the same as Standard other than cosmetics! # Retro Mode has 10x faster leveling and 10x higher skill requirements, if you do the math you can see its the same as Standrd and only cosmetic!
### ###
Alchemy:
Alchemy: Alchemy:
Catalysis: Catalysis:
Standard: Standard:
@ -55,7 +54,7 @@ Archery:
Rank_19: 95 Rank_19: 95
Rank_20: 100 Rank_20: 100
Retro: Retro:
Rank_1: 5 Rank_1: 50
Rank_2: 100 Rank_2: 100
Rank_3: 150 Rank_3: 150
Rank_4: 200 Rank_4: 200
@ -76,6 +75,11 @@ Archery:
Rank_19: 950 Rank_19: 950
Rank_20: 1000 Rank_20: 1000
Axes: Axes:
SkullSplitter:
Standard:
Rank_1: 10
RetroMode:
Rank_1: 100
ArmorImpact: ArmorImpact:
Standard: Standard:
Rank_1: 5 Rank_1: 5
@ -99,7 +103,7 @@ Axes:
Rank_19: 95 Rank_19: 95
Rank_20: 100 Rank_20: 100
Retro: Retro:
Rank_1: 5 Rank_1: 50
Rank_2: 100 Rank_2: 100
Rank_3: 150 Rank_3: 150
Rank_4: 200 Rank_4: 200
@ -202,6 +206,11 @@ Salvage:
Rank_7: 850 Rank_7: 850
Rank_8: 1000 Rank_8: 1000
Mining: Mining:
SuperBreaker:
Standard:
Rank_1: 10
RetroMode:
Rank_1: 100
BlastMining: BlastMining:
Standard: Standard:
Rank_1: 10 Rank_1: 10
@ -222,6 +231,11 @@ Mining:
Rank_7: 850 Rank_7: 850
Rank_8: 1000 Rank_8: 1000
Herbalism: Herbalism:
GreenTerra:
Standard:
Rank_1: 10
RetroMode:
Rank_1: 100
GreenThumb: GreenThumb:
Standard: Standard:
Rank_1: 20 Rank_1: 20
@ -291,3 +305,70 @@ Fishing:
Rank_6: 750 Rank_6: 750
Rank_7: 850 Rank_7: 850
Rank_8: 1000 Rank_8: 1000
Swords:
SerratedStrikes:
Standard:
Rank_1: 10
RetroMode:
Rank_1: 100
Unarmed:
Berserk:
Standard:
Rank_1: 10
RetroMode:
Rank_1: 100
Woodcutting:
Splinter:
Standard:
Rank_1: 5
Rank_2: 30
Rank_3: 55
RetroMode:
Rank_1: 50
Rank_2: 300
Rank_3: 550
TreeFeller:
Standard:
Rank_1: 10
Rank_2: 25
Rank_3: 50
Rank_4: 75
Rank_5: 100
RetroMode:
Rank_1: 100
Rank_2: 250
Rank_3: 500
Rank_4: 750
Rank_5: 1000
BarkSurgeon:
Standard:
Rank_1: 70
Rank_2: 80
Rank_3: 95
RetroMode:
Rank_1: 700
Rank_2: 800
Rank_3: 950
NaturesBounty:
Standard:
Rank_1: 40
Rank_2: 60
Rank_3: 90
RetroMode:
Rank_1: 400
Rank_2: 600
Rank_3: 900
HarvestLumber:
Standard:
Rank_1: 1
RetroMode:
Rank_1: 10
LeafBlower:
Standard:
Rank_1: 15
Rank_2: 35
Rank_3: 65
RetroMode:
Rank_1: 150
Rank_2: 350
Rank_3: 650