コード例 #1
0
  /**
   * Begins an experience gain. The amount will be affected by skill modifiers, global rate, perks,
   * and may be shared with the party
   *
   * @param skill Skill being used
   * @param xp Experience amount to process
   */
  public void beginXpGain(SkillType skill, float xp, XPGainReason xpGainReason) {
    Validate.isTrue(xp >= 0.0, "XP gained should be greater than or equal to zero.");

    if (xp <= 0.0) {
      return;
    }

    if (skill.isChildSkill()) {
      Set<SkillType> parentSkills = FamilyTree.getParents(skill);
      float splitXp = xp / parentSkills.size();

      for (SkillType parentSkill : parentSkills) {
        if (parentSkill.getPermissions(player)) {
          beginXpGain(parentSkill, splitXp, xpGainReason);
        }
      }

      return;
    }

    // Return if the experience has been shared
    if (party != null
        && ShareHandler.handleXpShare(
            xp, this, skill, ShareHandler.getSharedXpGainReason(xpGainReason))) {
      return;
    }

    beginUnsharedXpGain(skill, xp, xpGainReason);
  }
コード例 #2
0
ファイル: EventUtils.java プロジェクト: eliadil/mcMMO
  public static boolean handleStatsLossEvent(
      Player player,
      HashMap<String, Integer> levelChanged,
      HashMap<String, Float> experienceChanged) {
    McMMOPlayerStatLossEvent event =
        new McMMOPlayerStatLossEvent(player, levelChanged, experienceChanged);
    mcMMO.p.getServer().getPluginManager().callEvent(event);

    boolean isCancelled = event.isCancelled();

    if (!isCancelled) {
      levelChanged = event.getLevelChanged();
      experienceChanged = event.getExperienceChanged();
      PlayerProfile playerProfile = UserManager.getPlayer(player).getProfile();

      for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
        String skillName = skillType.toString();
        int playerSkillLevel = playerProfile.getSkillLevel(skillType);

        playerProfile.modifySkill(skillType, playerSkillLevel - levelChanged.get(skillName));
        playerProfile.removeXp(skillType, experienceChanged.get(skillName));

        if (playerProfile.getSkillXpLevel(skillType) < 0) {
          playerProfile.setSkillXpLevel(skillType, 0);
        }

        if (playerProfile.getSkillLevel(skillType) < 0) {
          playerProfile.modifySkill(skillType, 0);
        }
      }
    }

    return !isCancelled;
  }
コード例 #3
0
ファイル: Add.java プロジェクト: EntityReborn/CH-mcMMO
    public Construct exec(Target t, Environment environment, Construct... args)
        throws ConfigRuntimeException {
      Static.checkPlugin("mcMMO", t);

      BukkitMCPlayer player = (BukkitMCPlayer) Static.GetPlayer(args[0], t);
      SkillType skill;
      int amount = 1;

      try {
        skill = SkillType.valueOf(args[1].val().toUpperCase());
      } catch (Exception e) {
        throw new ConfigRuntimeException(
            "Unknown McMMO skilltype for mcmmo_add_level, " + args[1].val(),
            Exceptions.ExceptionType.NotFoundException,
            t);
      }

      if (args.length == 3) {
        try {
          amount = Integer.parseInt(args[2].val());
        } catch (Exception e) {
          throw new ConfigRuntimeException(
              "Bad amount for mcmmo_add_level, " + args[2].val(),
              Exceptions.ExceptionType.RangeException,
              t);
        }
      }

      ExperienceAPI.addLevel(player._Player(), skill.name(), amount);

      return new CVoid(t);
    }
コード例 #4
0
ファイル: SkillType.java プロジェクト: nwich/mcMMO
 public static SkillType bySecondaryAbility(SecondaryAbility skillAbility) {
   for (SkillType type : values()) {
     if (type.getSkillAbilities().contains(skillAbility)) {
       return type;
     }
   }
   return null;
 }
コード例 #5
0
ファイル: SkillType.java プロジェクト: nwich/mcMMO
  public static SkillType byAbility(AbilityType ability) {
    for (SkillType type : values()) {
      if (type.getAbility() == ability) {
        return type;
      }
    }

    return null;
  }
コード例 #6
0
  /**
   * Creates a new mcMMO replacer. This also validates if all variables are available and can be
   * used in the runtime.
   */
  public McmmoVariables() {
    final ImmutableSet.Builder<String> builder = ImmutableSet.builder();
    // goes through all available skill types
    for (SkillType type : SkillType.values()) {
      final String skillName = type.name().toLowerCase(Locale.ENGLISH);
      builder.add('%' + skillName + '%');
    }

    skillTypes = builder.build();
  }
コード例 #7
0
  /**
   * Check to see if an ability can be activated.
   *
   * @param skill The skill the ability is based on
   */
  public void checkAbilityActivation(SkillType skill) {
    ToolType tool = skill.getTool();
    AbilityType ability = skill.getAbility();

    setToolPreparationMode(tool, false);

    if (getAbilityMode(ability)) {
      return;
    }

    int timeRemaining = calculateTimeRemaining(ability);

    if (timeRemaining > 0) {
      /*
       * Axes and Woodcutting are odd because they share the same tool.
       * We show them the too tired message when they take action.
       */
      if (skill == SkillType.WOODCUTTING || skill == SkillType.AXES) {
        player.sendMessage(LocaleLoader.getString("Skills.TooTired", timeRemaining));
      }

      return;
    }

    if (EventUtils.callPlayerAbilityActivateEvent(player, skill).isCancelled()) {
      return;
    }

    int ticks =
        PerksUtils.handleActivationPerks(
            player,
            2 + (getSkillLevel(skill) / AdvancedConfig.getInstance().getAbilityLength()),
            ability.getMaxLength());

    // Notify people that ability has been activated
    ParticleEffectUtils.playAbilityEnabledEffect(player);

    if (useChatNotifications()) {
      player.sendMessage(ability.getAbilityOn());
    }

    SkillUtils.sendSkillMessage(player, ability.getAbilityPlayer(player));

    // Enable the ability
    profile.setAbilityDATS(
        ability, System.currentTimeMillis() + (ticks * Misc.TIME_CONVERSION_FACTOR));
    setAbilityMode(ability, true);

    if (ability == AbilityType.SUPER_BREAKER || ability == AbilityType.GIGA_DRILL_BREAKER) {
      SkillUtils.handleAbilitySpeedIncrease(player);
    }

    new AbilityDisableTask(this, ability)
        .runTaskLater(mcMMO.p, ticks * Misc.TICK_CONVERSION_FACTOR);
  }
コード例 #8
0
  /**
   * Gets the power level of this player.
   *
   * @return the power level of the player
   */
  public int getPowerLevel() {
    int powerLevel = 0;

    for (SkillType type : SkillType.NON_CHILD_SKILLS) {
      if (type.getPermissions(player)) {
        powerLevel += getSkillLevel(type);
      }
    }

    return powerLevel;
  }
コード例 #9
0
  public void processAbilityActivation(SkillType skill) {
    if (Config.getInstance().getAbilitiesOnlyActivateWhenSneaking() && !player.isSneaking()) {
      return;
    }

    ItemStack inHand = player.getItemInHand();

    if (mcMMO.getModManager().isCustomTool(inHand)
        && !mcMMO.getModManager().getTool(inHand).isAbilityEnabled()) {
      return;
    }

    if (!getAbilityUse()) {
      return;
    }

    for (AbilityType abilityType : AbilityType.values()) {
      if (getAbilityMode(abilityType)) {
        return;
      }
    }

    AbilityType ability = skill.getAbility();
    ToolType tool = skill.getTool();

    /*
     * Woodcutting & Axes need to be treated differently.
     * Basically the tool always needs to ready and we check to see if the cooldown is over when the user takes action
     */
    if (ability.getPermissions(player) && tool.inHand(inHand) && !getToolPreparationMode(tool)) {
      if (skill != SkillType.WOODCUTTING && skill != SkillType.AXES) {
        int timeRemaining = calculateTimeRemaining(ability);

        if (!getAbilityMode(ability) && timeRemaining > 0) {
          player.sendMessage(LocaleLoader.getString("Skills.TooTired", timeRemaining));
          return;
        }
      }

      if (Config.getInstance().getAbilityMessagesEnabled()) {
        player.sendMessage(tool.getRaiseTool());
      }

      setToolPreparationMode(tool, true);
      new ToolLowerTask(this, tool)
          .runTaskLaterAsynchronously(mcMMO.p, 4 * Misc.TICK_CONVERSION_FACTOR);
    }
  }
コード例 #10
0
ファイル: ExperienceConfig.java プロジェクト: riking/mcMMO
 /* Materials  */
 public int getXp(SkillType skill, Material material) {
   return config.getInt(
       "Experience."
           + StringUtils.getCapitalized(skill.toString())
           + "."
           + StringUtils.getPrettyItemString(material).replace(" ", "_"));
 }
コード例 #11
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
 /*
  * SKILL SETTINGS
  */
 public boolean getDoubleDropsEnabled(SkillType skill, Material material) {
   return config.getBoolean(
       "Double_Drops."
           + StringUtils.getCapitalized(skill.toString())
           + "."
           + StringUtils.getPrettyItemString(material).replace(" ", "_"));
 }
コード例 #12
0
ファイル: EventUtils.java プロジェクト: eliadil/mcMMO
  public static boolean handleVampirismEvent(
      Player killer,
      Player victim,
      HashMap<String, Integer> levelChanged,
      HashMap<String, Float> experienceChanged) {
    McMMOPlayerVampirismEvent eventKiller =
        new McMMOPlayerVampirismEvent(killer, false, levelChanged, experienceChanged);
    McMMOPlayerVampirismEvent eventVictim =
        new McMMOPlayerVampirismEvent(victim, true, levelChanged, experienceChanged);
    mcMMO.p.getServer().getPluginManager().callEvent(eventKiller);
    mcMMO.p.getServer().getPluginManager().callEvent(eventVictim);

    boolean isCancelled = eventKiller.isCancelled() || eventVictim.isCancelled();

    if (!isCancelled) {
      HashMap<String, Integer> levelChangedKiller = eventKiller.getLevelChanged();
      HashMap<String, Float> experienceChangedKiller = eventKiller.getExperienceChanged();

      HashMap<String, Integer> levelChangedVictim = eventVictim.getLevelChanged();
      HashMap<String, Float> experienceChangedVictim = eventVictim.getExperienceChanged();

      McMMOPlayer killerPlayer = UserManager.getPlayer(killer);
      PlayerProfile victimProfile = UserManager.getPlayer(victim).getProfile();

      for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
        String skillName = skillType.toString();
        int victimSkillLevel = victimProfile.getSkillLevel(skillType);

        killerPlayer.addLevels(skillType, levelChangedKiller.get(skillName));
        killerPlayer.beginUnsharedXpGain(
            skillType, experienceChangedKiller.get(skillName), XPGainReason.VAMPIRISM);

        victimProfile.modifySkill(skillType, victimSkillLevel - levelChangedVictim.get(skillName));
        victimProfile.removeXp(skillType, experienceChangedVictim.get(skillName));

        if (victimProfile.getSkillXpLevel(skillType) < 0) {
          victimProfile.setSkillXpLevel(skillType, 0);
        }

        if (victimProfile.getSkillLevel(skillType) < 0) {
          victimProfile.modifySkill(skillType, 0);
        }
      }
    }

    return !isCancelled;
  }
コード例 #13
0
ファイル: EventUtils.java プロジェクト: jiangzhonghui/mcMMO
  public static McMMOPlayerAbilityDeactivateEvent callAbilityDeactivateEvent(
      Player player, AbilityType ability) {
    McMMOPlayerAbilityDeactivateEvent event =
        new McMMOPlayerAbilityDeactivateEvent(player, SkillType.byAbility(ability));
    mcMMO.p.getServer().getPluginManager().callEvent(event);

    return event;
  }
コード例 #14
0
  protected String[] calculateLengthDisplayValues(Player player, float skillValue) {
    int maxLength = skill.getAbility().getMaxLength();
    int length = 2 + (int) (skillValue / AdvancedConfig.getInstance().getAbilityLength());
    int enduranceLength = PerksUtils.handleActivationPerks(player, length, maxLength);

    if (maxLength != 0) {
      length = Math.min(length, maxLength);
    }

    return new String[] {String.valueOf(length), String.valueOf(enduranceLength)};
  }
コード例 #15
0
ファイル: SkillType.java プロジェクト: nwich/mcMMO
  static {
    List<SkillType> childSkills = new ArrayList<SkillType>();
    List<SkillType> nonChildSkills = new ArrayList<SkillType>();
    ArrayList<String> names = new ArrayList<String>();

    for (SkillType skill : values()) {
      if (skill.isChildSkill()) {
        childSkills.add(skill);
      } else {
        nonChildSkills.add(skill);
      }

      names.add(skill.getName());
    }

    Collections.sort(names);
    SKILL_NAMES = ImmutableList.copyOf(names);

    CHILD_SKILLS = ImmutableList.copyOf(childSkills);
    NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
  }
コード例 #16
0
ファイル: ChildConfig.java プロジェクト: 95001588/mcMMO
  @Override
  protected void loadKeys() {
    config.setDefaults(YamlConfiguration.loadConfiguration(plugin.getResource("child.yml")));

    FamilyTree.clearRegistrations(); // when reloading, need to clear statics

    for (SkillType skill : SkillType.CHILD_SKILLS) {
      plugin.debug("Finding parents of " + skill.name());

      EnumSet<SkillType> parentSkills = EnumSet.noneOf(SkillType.class);
      boolean useDefaults = false; // If we had an error we back out and use defaults

      for (String name : config.getStringList(StringUtils.getCapitalized(skill.name()))) {
        try {
          SkillType parentSkill = SkillType.valueOf(name.toUpperCase());
          FamilyTree.enforceNotChildSkill(parentSkill);
          parentSkills.add(parentSkill);
        } catch (IllegalArgumentException ex) {
          plugin.getLogger().warning(name + " is not a valid skill type, or is a child skill!");
          useDefaults = true;
          break;
        }
      }

      if (useDefaults) {
        parentSkills.clear();
        for (String name :
            config.getDefaults().getStringList(StringUtils.getCapitalized(skill.name()))) {
          /* We do less checks in here because it's from inside our jar.
           * If they're dedicated enough to have modified it, they can have the errors it may produce.
           * Alternatively, this can be used to allow child skills to be parent skills, provided there are no circular dependencies this is an advanced sort of configuration.
           */
          parentSkills.add(SkillType.valueOf(name.toUpperCase()));
        }
      }

      // Register them
      for (SkillType parentSkill : parentSkills) {
        plugin.debug("Registering " + parentSkill.name() + " as parent of " + skill.name());
        FamilyTree.registerParent(skill, parentSkill);
      }
    }

    FamilyTree.closeRegistration();
  }
コード例 #17
0
  /**
   * Applies an experience gain
   *
   * @param skillType Skill being used
   * @param xp Experience amount to add
   */
  public void applyXpGain(SkillType skillType, float xp, XPGainReason xpGainReason) {
    if (!skillType.getPermissions(player)) {
      return;
    }

    if (skillType.isChildSkill()) {
      Set<SkillType> parentSkills = FamilyTree.getParents(skillType);

      for (SkillType parentSkill : parentSkills) {
        applyXpGain(parentSkill, xp / parentSkills.size(), xpGainReason);
      }

      return;
    }

    if (!EventUtils.handleXpGainEvent(player, skillType, xp, xpGainReason)) {
      return;
    }

    isUsingUnarmed = (skillType == SkillType.UNARMED);
    checkXp(skillType, xpGainReason);
  }
コード例 #18
0
ファイル: SkillType.java プロジェクト: nwich/mcMMO
  public static SkillType getSkill(String skillName) {
    if (!Config.getInstance().getLocale().equalsIgnoreCase("en_US")) {
      for (SkillType type : values()) {
        if (skillName.equalsIgnoreCase(
            LocaleLoader.getString(StringUtils.getCapitalized(type.name()) + ".SkillName"))) {
          return type;
        }
      }
    }

    for (SkillType type : values()) {
      if (type.name().equalsIgnoreCase(skillName)) {
        return type;
      }
    }

    if (!skillName.equalsIgnoreCase("all")) {
      mcMMO.p.getLogger().warning("Invalid mcMMO skill (" + skillName + ")"); // TODO: Localize
    }

    return null;
  }
コード例 #19
0
  /**
   * Modifies an experience gain using skill modifiers, global rate and perks
   *
   * @param skillType Skill being used
   * @param xp Experience amount to process
   * @return Modified experience
   */
  private float modifyXpGain(SkillType skillType, float xp) {
    if (player.getGameMode() == GameMode.CREATIVE
        || (skillType.getMaxLevel() <= getSkillLevel(skillType))
        || (Config.getInstance().getPowerLevelCap() <= getPowerLevel())) {
      return 0;
    }

    xp =
        (float)
            (xp
                / skillType.getXpModifier()
                * ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier());

    if (Config.getInstance().getToolModsEnabled()) {
      CustomTool tool = mcMMO.getModManager().getTool(player.getItemInHand());

      if (tool != null) {
        xp *= tool.getXpMultiplier();
      }
    }

    return PerksUtils.handleXpPerks(player, xp, skillType);
  }
コード例 #20
0
  public McMMOPlayer(Player player, PlayerProfile profile) {
    String playerName = player.getName();
    UUID uuid = player.getUniqueId();

    this.player = player;
    playerMetadata = new FixedMetadataValue(mcMMO.p, playerName);
    this.profile = profile;

    if (profile.getUniqueId() == null) {
      profile.setUniqueId(uuid);
    }

    /*
     * I'm using this method because it makes code shorter and safer (we don't have to add all SkillTypes manually),
     * but I actually have no idea about the performance impact, if there is any.
     * If in the future someone wants to remove this, don't forget to also remove what is in the SkillType enum. - bm01
     */
    try {
      for (SkillType skillType : SkillType.values()) {
        skillManagers.put(
            skillType,
            skillType.getManagerClass().getConstructor(McMMOPlayer.class).newInstance(this));
      }
    } catch (Exception e) {
      e.printStackTrace();
      mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p);
    }

    for (AbilityType abilityType : AbilityType.values()) {
      abilityMode.put(abilityType, false);
      abilityInformed.put(abilityType, true); // This is intended
    }

    for (ToolType toolType : ToolType.values()) {
      toolMode.put(toolType, false);
    }
  }
コード例 #21
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
  public boolean getDoubleDropsDisabled(SkillType skill) {
    String skillName = StringUtils.getCapitalized(skill.toString());
    ConfigurationSection section = config.getConfigurationSection("Double_Drops." + skillName);
    if (section == null) return false;
    Set<String> keys = section.getKeys(false);
    boolean disabled = true;

    for (String key : keys) {
      if (config.getBoolean("Double_Drops." + skillName + "." + key)) {
        disabled = false;
        break;
      }
    }

    return disabled;
  }
コード例 #22
0
  /**
   * Check the XP of a skill.
   *
   * @param skillType The skill to check
   */
  private void checkXp(SkillType skillType, XPGainReason xpGainReason) {
    if (getSkillXpLevelRaw(skillType) < getXpToLevel(skillType)) {
      return;
    }

    int levelsGained = 0;
    float xpRemoved = 0;

    while (getSkillXpLevelRaw(skillType) >= getXpToLevel(skillType)) {
      if (hasReachedLevelCap(skillType)) {
        setSkillXpLevel(skillType, 0);
        break;
      }

      xpRemoved += profile.levelUp(skillType);
      levelsGained++;
    }

    if (!EventUtils.handleLevelChangeEvent(
        player, skillType, levelsGained, xpRemoved, true, xpGainReason)) {
      return;
    }

    if (Config.getInstance().getLevelUpSoundsEnabled()) {
      player.playSound(
          player.getLocation(),
          Sound.ENTITY_EXPERIENCE_ORB_PICKUP,
          Misc.LEVELUP_VOLUME,
          Misc.LEVELUP_PITCH);
    }

    player.sendMessage(
        LocaleLoader.getString(
            StringUtils.getCapitalized(skillType.toString()) + ".Skillup",
            levelsGained,
            getSkillLevel(skillType)));
  }
コード例 #23
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
 public boolean getPVEEnabled(SkillType skill) {
   return config.getBoolean(
       "Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVE", true);
 }
コード例 #24
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
 public int getLevelCap(SkillType skill) {
   int cap =
       config.getInt("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Level_Cap");
   return (cap <= 0) ? Integer.MAX_VALUE : cap;
 }
コード例 #25
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
 public void setHardcoreVampirismEnabled(SkillType skillType, boolean enabled) {
   config.set(
       "Hardcore.Vampirism.Enabled." + StringUtils.getCapitalized(skillType.toString()), enabled);
 }
コード例 #26
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
 public boolean getHardcoreVampirismEnabled(SkillType skillType) {
   return config.getBoolean(
       "Hardcore.Vampirism.Enabled." + StringUtils.getCapitalized(skillType.toString()), false);
 }
コード例 #27
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
 public void setHardcoreStatLossEnabled(SkillType skillType, boolean enabled) {
   config.set(
       "Hardcore.Death_Stat_Loss.Enabled." + StringUtils.getCapitalized(skillType.toString()),
       enabled);
 }
コード例 #28
0
ファイル: ExperienceConfig.java プロジェクト: riking/mcMMO
 /* Skill modifiers */
 public double getFormulaSkillModifier(SkillType skill) {
   return config.getDouble(
       "Experience_Formula.Modifier." + StringUtils.getCapitalized(skill.toString()));
 }
コード例 #29
0
ファイル: Config.java プロジェクト: jjm223/mcMMO
 /* Hardcore Mode */
 public boolean getHardcoreStatLossEnabled(SkillType skillType) {
   return config.getBoolean(
       "Hardcore.Death_Stat_Loss.Enabled." + StringUtils.getCapitalized(skillType.toString()),
       false);
 }
コード例 #30
0
  @Override
  public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    if (CommandUtils.noConsoleUsage(sender)) {
      return true;
    }

    switch (args.length) {
      case 0:
        Player player = (Player) sender;
        McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);

        boolean isLucky = Permissions.lucky(player, skill);
        boolean hasEndurance = (PerksUtils.handleActivationPerks(player, 0, 0) != 0);
        float skillValue = mcMMOPlayer.getSkillLevel(skill);

        permissionsCheck(player);
        dataCalculations(player, skillValue, isLucky);

        if (Config.getInstance().getSkillUseBoard()) {
          ScoreboardManager.enablePlayerSkillScoreboard(player, skill);
        }

        if (!skill.isChildSkill()) {
          player.sendMessage(LocaleLoader.getString("Skills.Header", skillName));
          player.sendMessage(
              LocaleLoader.getString(
                  "Commands.XPGain",
                  LocaleLoader.getString(
                      "Commands.XPGain." + StringUtils.getCapitalized(skill.toString()))));
          player.sendMessage(
              LocaleLoader.getString(
                  "Effects.Level",
                  (int) skillValue,
                  mcMMOPlayer.getSkillXpLevel(skill),
                  mcMMOPlayer.getXpToLevel(skill)));
        } else {
          player.sendMessage(
              LocaleLoader.getString(
                  "Skills.Header", skillName + " " + LocaleLoader.getString("Skills.Child")));
          player.sendMessage(
              LocaleLoader.getString(
                  "Commands.XPGain", LocaleLoader.getString("Commands.XPGain.Child")));
          player.sendMessage(LocaleLoader.getString("Effects.Child", (int) skillValue));

          player.sendMessage(
              LocaleLoader.getString("Skills.Header", LocaleLoader.getString("Skills.Parents")));
          Set<SkillType> parents = FamilyTree.getParents(skill);

          for (SkillType parent : parents) {
            player.sendMessage(
                parent.getName()
                    + " - "
                    + LocaleLoader.getString(
                        "Effects.Level",
                        mcMMOPlayer.getSkillLevel(parent),
                        mcMMOPlayer.getSkillXpLevel(parent),
                        mcMMOPlayer.getXpToLevel(parent)));
          }
        }

        List<String> effectMessages = effectsDisplay();

        if (!effectMessages.isEmpty()) {
          player.sendMessage(
              LocaleLoader.getString("Skills.Header", LocaleLoader.getString("Effects.Effects")));

          if (isLucky) {
            String perkPrefix = LocaleLoader.getString("MOTD.PerksPrefix");
            player.sendMessage(
                perkPrefix
                    + LocaleLoader.getString(
                        "Effects.Template",
                        LocaleLoader.getString("Perks.Lucky.Name"),
                        LocaleLoader.getString("Perks.Lucky.Desc", skillName)));
          }

          for (String message : effectMessages) {
            player.sendMessage(message);
          }
        }

        List<String> statsMessages = statsDisplay(player, skillValue, hasEndurance, isLucky);

        if (!statsMessages.isEmpty()) {
          player.sendMessage(
              LocaleLoader.getString(
                  "Skills.Header", LocaleLoader.getString("Commands.Stats.Self")));

          for (String message : statsMessages) {
            player.sendMessage(message);
          }
        }

        player.sendMessage(
            LocaleLoader.getString("Guides.Available", skillName, skillName.toLowerCase()));
        return true;

      default:
        return skillGuideCommand.onCommand(sender, command, label, args);
    }
  }