mirror of
https://gitlab.com/phoenix-dvpmt/mmocore.git
synced 2025-11-18 06:24:17 +01:00
Merge branch 'master' into sao
This commit is contained in:
commit
a803716bec
@ -94,17 +94,18 @@
|
|||||||
<url>https://maven.enginehub.org/repo/</url>
|
<url>https://maven.enginehub.org/repo/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
<repository>
|
|
||||||
<id>dmulloy2-repo</id>
|
|
||||||
<url>https://repo.dmulloy2.net/repository/public/</url>
|
|
||||||
</repository>
|
|
||||||
|
|
||||||
<!-- Party and Friends Repository -->
|
<!-- Party and Friends Repository -->
|
||||||
<repository>
|
<repository>
|
||||||
<id>simonsators Repo</id>
|
<id>simonsators Repo</id>
|
||||||
<url>https://simonsator.de/repo</url>
|
<url>https://simonsator.de/repo</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
|
<!-- Quests (plugin) -->
|
||||||
|
<repository>
|
||||||
|
<id>codemc-repo</id>
|
||||||
|
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
<!-- Heroes Repository
|
<!-- Heroes Repository
|
||||||
<repository>
|
<repository>
|
||||||
<id>herocraft</id>
|
<id>herocraft</id>
|
||||||
@ -227,9 +228,9 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.comphenix.protocol</groupId>
|
<groupId>net.dmulloy2</groupId>
|
||||||
<artifactId>ProtocolLib</artifactId>
|
<artifactId>ProtocolLib</artifactId>
|
||||||
<version>4.8.0</version>
|
<version>5.4.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
@ -325,9 +326,9 @@
|
|||||||
|
|
||||||
<!-- Quest Plugins -->
|
<!-- Quest Plugins -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.blackvein</groupId>
|
<groupId>me.pikamug.quests</groupId>
|
||||||
<artifactId>Quests</artifactId>
|
<artifactId>quests-core</artifactId>
|
||||||
<version>4.4.1-b340</version>
|
<version>5.2.7</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|||||||
@ -725,7 +725,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
|
|||||||
* @return Experience needed in order to reach next level
|
* @return Experience needed in order to reach next level
|
||||||
*/
|
*/
|
||||||
public long getLevelUpExperience() {
|
public long getLevelUpExperience() {
|
||||||
return getProfess().getExpCurve().getExperience(getLevel() + 1);
|
return getProfess().getExpCurve().getExperience(this, getLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnline() {
|
public boolean isOnline() {
|
||||||
@ -752,7 +752,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
|
|||||||
|
|
||||||
public void giveLevels(int value, @NotNull EXPSource source) {
|
public void giveLevels(int value, @NotNull EXPSource source) {
|
||||||
long equivalentExp = 0;
|
long equivalentExp = 0;
|
||||||
while (value-- > 0) equivalentExp += getProfess().getExpCurve().getExperience(getLevel() + value + 1);
|
while (value-- > 0) equivalentExp += getProfess().getExpCurve().getExperience(this, getLevel() + value);
|
||||||
giveExperience(equivalentExp, source);
|
giveExperience(equivalentExp, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1088,7 +1088,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
|
|||||||
* Loop for exp overload when leveling up, will continue
|
* Loop for exp overload when leveling up, will continue
|
||||||
* looping until exp is 0 or max currentLevel has been reached
|
* looping until exp is 0 or max currentLevel has been reached
|
||||||
*/
|
*/
|
||||||
while (experience >= (experienceNeeded = getProfess().getExpCurve().getExperience(newLevel + 1))) {
|
while (experience >= (experienceNeeded = getProfess().getExpCurve().getExperience(this, newLevel))) {
|
||||||
|
|
||||||
if (maxLevel > 0 && newLevel >= maxLevel) {
|
if (maxLevel > 0 && newLevel >= maxLevel) {
|
||||||
experience = 0;
|
experience = 0;
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
package net.Indyuce.mmocore.api.player.attribute;
|
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.stat.StatInstance;
|
|
||||||
import io.lumine.mythic.lib.api.stat.handler.StatHandler;
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This fixes an issue where registering new stat modifiers in ML
|
|
||||||
* to add extra attribute points does NOT update the stats granted
|
|
||||||
* by the attribute.
|
|
||||||
* <p>
|
|
||||||
* This stat handler MAY call subsequent stat handlers. There might
|
|
||||||
* be infinite recursion problems if another attr. grants extra attribute pts.
|
|
||||||
*/
|
|
||||||
public class MMOCoreAttributeStatHandler extends StatHandler {
|
|
||||||
private final PlayerAttribute attr;
|
|
||||||
|
|
||||||
public MMOCoreAttributeStatHandler(ConfigurationSection config, PlayerAttribute attr) {
|
|
||||||
super(config, "ADDITIONAL_" + attr.getId().toUpperCase().replace("-", "_"));
|
|
||||||
|
|
||||||
this.attr = attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called on login but the MMOCore playerData
|
|
||||||
* is not loaded yet, hence the try/catch clause
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void runUpdate(StatInstance instance) {
|
|
||||||
try {
|
|
||||||
final PlayerData playerData = PlayerData.get(instance.getMap().getPlayerData());
|
|
||||||
playerData.getAttributes().getInstance(attr).updateStats();
|
|
||||||
} catch (NullPointerException exception) {
|
|
||||||
// Player data is not loaded yet so there's nothing to update.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,7 +6,7 @@ import io.lumine.mythic.lib.util.lang3.Validate;
|
|||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.experience.EXPSource;
|
import net.Indyuce.mmocore.experience.EXPSource;
|
||||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@ -84,7 +84,7 @@ public class PlayerAttribute implements ExperienceObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public @NotNull String getKey() {
|
||||||
return "attribute:" + getId().replace("-", "_");
|
return "attribute:" + getId().replace("-", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +99,9 @@ public class PlayerAttribute implements ExperienceObject {
|
|||||||
return expTable != null;
|
return expTable != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ExpCurve getExpCurve() {
|
public ExperienceCurve getExpCurve() {
|
||||||
throw new RuntimeException("Attributes don't have experience");
|
throw new RuntimeException("Attributes don't have experience");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,8 +25,8 @@ import net.Indyuce.mmocore.api.player.profess.resource.ResourceRegeneration;
|
|||||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||||
import net.Indyuce.mmocore.experience.EXPSource;
|
import net.Indyuce.mmocore.experience.EXPSource;
|
||||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
|
||||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||||
|
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||||
import net.Indyuce.mmocore.loot.chest.particle.CastingParticle;
|
import net.Indyuce.mmocore.loot.chest.particle.CastingParticle;
|
||||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||||
@ -59,7 +59,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
|||||||
private final ManaDisplayOptions manaDisplay;
|
private final ManaDisplayOptions manaDisplay;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final ExpCurve expCurve;
|
private final ExperienceCurve expCurve;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final ExperienceTable expTable;
|
private final ExperienceTable expTable;
|
||||||
@ -111,10 +111,14 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
|||||||
actionBarFormat = config.contains("action-bar") ? config.getString("action-bar") : null;
|
actionBarFormat = config.contains("action-bar") ? config.getString("action-bar") : null;
|
||||||
|
|
||||||
// Exp curve
|
// Exp curve
|
||||||
expCurve = config.contains("exp-curve")
|
ExperienceCurve expCurve = ExperienceCurve.DEFAULT;
|
||||||
? MMOCore.plugin.experience.getCurveOrThrow(
|
try {
|
||||||
config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
|
expCurve = ExperienceCurve.fromConfig(config.getString("exp-curve"));
|
||||||
: ExpCurve.DEFAULT;
|
} catch (Throwable exception) {
|
||||||
|
MMOCore.log(Level.WARNING, "Could not load exp curve from class '" + id + "': " + exception.getMessage());
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
this.expCurve = expCurve;
|
||||||
|
|
||||||
// Main exp table
|
// Main exp table
|
||||||
ExperienceTable expTable = null;
|
ExperienceTable expTable = null;
|
||||||
@ -261,7 +265,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
|||||||
manaDisplay = ManaDisplayOptions.DEFAULT;
|
manaDisplay = ManaDisplayOptions.DEFAULT;
|
||||||
maxLevel = 0;
|
maxLevel = 0;
|
||||||
displayOrder = 0;
|
displayOrder = 0;
|
||||||
expCurve = ExpCurve.DEFAULT;
|
expCurve = ExperienceCurve.DEFAULT;
|
||||||
expTable = null;
|
expTable = null;
|
||||||
comboMap = null;
|
comboMap = null;
|
||||||
castParticle = new CastingParticle(VParticle.INSTANT_EFFECT.get());
|
castParticle = new CastingParticle(VParticle.INSTANT_EFFECT.get());
|
||||||
@ -282,7 +286,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public @NotNull String getKey() {
|
||||||
return "class_" + getId();
|
return "class_" + getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +319,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ExpCurve getExpCurve() {
|
public @NotNull ExperienceCurve getExpCurve() {
|
||||||
return expCurve;
|
return expCurve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ public class InfoCommandTreeNode extends CommandTreeNode {
|
|||||||
for (Profession profession : MMOCore.plugin.professionManager.getAll())
|
for (Profession profession : MMOCore.plugin.professionManager.getAll())
|
||||||
sender.sendMessage(
|
sender.sendMessage(
|
||||||
ChatColor.YELLOW + profession.getName() + ": Lvl " + ChatColor.GOLD + playerData.getCollectionSkills().getLevel(profession)
|
ChatColor.YELLOW + profession.getName() + ": Lvl " + ChatColor.GOLD + playerData.getCollectionSkills().getLevel(profession)
|
||||||
+ ChatColor.YELLOW + " - " + ChatColor.GOLD + playerData.getCollectionSkills().getExperience(profession)
|
+ ChatColor.YELLOW + " - " + ChatColor.GOLD + MythicLib.plugin.getMMOConfig().decimal.format(playerData.getCollectionSkills().getExperience(profession))
|
||||||
+ ChatColor.YELLOW + " / " + ChatColor.GOLD + playerData.getCollectionSkills().getLevelUpExperience(profession));
|
+ ChatColor.YELLOW + " / " + ChatColor.GOLD + playerData.getCollectionSkills().getLevelUpExperience(profession));
|
||||||
sender.sendMessage(ChatColor.YELLOW + "----------------------------------------------------");
|
sender.sendMessage(ChatColor.YELLOW + "----------------------------------------------------");
|
||||||
return CommandResult.SUCCESS;
|
return CommandResult.SUCCESS;
|
||||||
|
|||||||
@ -200,14 +200,24 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
|||||||
if (playerData.hasSkillBound(slot))
|
if (playerData.hasSkillBound(slot))
|
||||||
return Double.toString(playerData.getCooldownMap().getCooldown(playerData.getBoundSkill(slot)));
|
return Double.toString(playerData.getCooldownMap().getCooldown(playerData.getBoundSkill(slot)));
|
||||||
else return MMOCore.plugin.configManager.noSkillBoundPlaceholder;
|
else return MMOCore.plugin.configManager.noSkillBoundPlaceholder;
|
||||||
} else if (identifier.startsWith("profession_experience_"))
|
}
|
||||||
|
|
||||||
|
// Current exp in profession
|
||||||
|
else if (identifier.startsWith("profession_experience_")) {
|
||||||
return MythicLib.plugin.getMMOConfig().decimal.format(
|
return MythicLib.plugin.getMMOConfig().decimal.format(
|
||||||
playerData.getCollectionSkills().getExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
|
playerData.getCollectionSkills().getExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
else if (identifier.startsWith("profession_next_level_"))
|
// Exp needed to level up profession
|
||||||
return String.valueOf(PlayerData.get(player).getCollectionSkills()
|
else if (identifier.startsWith("profession_next_level_")) {
|
||||||
.getLevelUpExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
|
final var professionId = identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase();
|
||||||
|
final @Nullable var profession = MMOCore.plugin.professionManager.get(professionId);
|
||||||
|
if (profession == null) return "{profession_not_found}";
|
||||||
|
final var professionLevel = playerData.getCollectionSkills().getLevel(profession);
|
||||||
|
return String.valueOf(profession.getExpCurve().getExperience(playerData, professionLevel));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of online members in party
|
||||||
else if (identifier.startsWith("party_count")) {
|
else if (identifier.startsWith("party_count")) {
|
||||||
final @Nullable AbstractParty party = playerData.getParty();
|
final @Nullable AbstractParty party = playerData.getParty();
|
||||||
return party == null ? "0" : String.valueOf(party.countMembers());
|
return party == null ? "0" : String.valueOf(party.countMembers());
|
||||||
|
|||||||
@ -1,81 +0,0 @@
|
|||||||
package net.Indyuce.mmocore.experience;
|
|
||||||
|
|
||||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ExpCurve {
|
|
||||||
private final String id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Experience needed to level up. Different professions or classes can have
|
|
||||||
* different exp curves so that it is easier to balance.
|
|
||||||
*/
|
|
||||||
private final List<Long> experience = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Purely arbitrary but MMOCore needs a default exp curve for everything
|
|
||||||
* otherwise there might be divisions by 0 when trying to update the vanilla
|
|
||||||
* exp bar which requires a 0.0 -> 1.0 float as parameter.
|
|
||||||
*
|
|
||||||
* See {@link PlayerData#refreshVanillaExp()}
|
|
||||||
*/
|
|
||||||
public static final ExpCurve DEFAULT = new ExpCurve("default", 100, 200, 300, 400, 500);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads an exp curve from a text file, one line after the other. Each exp
|
|
||||||
* value has to be the only thing written on every line
|
|
||||||
*
|
|
||||||
* @param file Text file to read data from
|
|
||||||
*/
|
|
||||||
public ExpCurve(File file) {
|
|
||||||
this.id = file.getName().replace(".txt", "").toLowerCase().replace("_", "-").replace(" ", "-");
|
|
||||||
|
|
||||||
try {
|
|
||||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
|
||||||
String readLine;
|
|
||||||
while ((readLine = reader.readLine()) != null)
|
|
||||||
experience.add(Long.valueOf(readLine));
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
|
||||||
} catch(Throwable throwable) {
|
|
||||||
throw new RuntimeException(throwable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public constructor for external plugins
|
|
||||||
*
|
|
||||||
* @param id Some unique identifier to let other plugin features refer
|
|
||||||
* to your exp curve.
|
|
||||||
* @param values The exp values, at to be at least one or the constructor
|
|
||||||
* will throw an error
|
|
||||||
*/
|
|
||||||
public ExpCurve(String id, long... values) {
|
|
||||||
this.id = id;
|
|
||||||
for (long value : values)
|
|
||||||
experience.add(value);
|
|
||||||
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param level Level being reached by some player
|
|
||||||
* @return Experience needed to reach provided level. The level serves
|
|
||||||
* an index for a list checkup. If the level is higher than
|
|
||||||
* the list size, it just returns the last value of the list
|
|
||||||
*/
|
|
||||||
public long getExperience(int level) {
|
|
||||||
Validate.isTrue(level > 0, "Level must be stricly positive");
|
|
||||||
return experience.get(Math.min(level, experience.size()) - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
package net.Indyuce.mmocore.experience;
|
package net.Indyuce.mmocore.experience;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General implementation for professions, classes and attributes.
|
* General implementation for professions, classes and attributes.
|
||||||
@ -17,6 +17,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
*/
|
*/
|
||||||
public interface ExperienceObject extends ExperienceDispenser {
|
public interface ExperienceObject extends ExperienceDispenser {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
String getKey();
|
String getKey();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,14 +25,14 @@ public interface ExperienceObject extends ExperienceDispenser {
|
|||||||
*
|
*
|
||||||
* @return Exp curve of that object
|
* @return Exp curve of that object
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@NotNull
|
||||||
ExpCurve getExpCurve();
|
ExperienceCurve getExpCurve();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should throw an error if called when
|
* Throws an exception no experience table
|
||||||
* {@link #hasExperienceTable()} returns false
|
|
||||||
*
|
*
|
||||||
* @return Table read when leveling up
|
* @return Table read when leveling up
|
||||||
|
* @see #hasExperienceTable()
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
ExperienceTable getExperienceTable();
|
ExperienceTable getExperienceTable();
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
public class PlayerProfessions {
|
public class PlayerProfessions {
|
||||||
private final Map<String, Double> exp = new HashMap<>();
|
private final Map<String, Double> exp = new HashMap<>();
|
||||||
@ -120,11 +121,14 @@ public class PlayerProfessions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getLevelUpExperience(Profession profession) {
|
public long getLevelUpExperience(Profession profession) {
|
||||||
return profession.getExpCurve().getExperience(getLevel(profession) + 1);
|
return profession.getExpCurve().getExperience(playerData, getLevel(profession));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public long getLevelUpExperience(String id) {
|
public long getLevelUpExperience(String id) {
|
||||||
return MMOCore.plugin.professionManager.has(id) ? MMOCore.plugin.professionManager.get(id).getExpCurve().getExperience(getLevel(id) + 1) : 0;
|
final var prof = MMOCore.plugin.professionManager.get(id);
|
||||||
|
if (prof == null) return 0;
|
||||||
|
return prof.getExpCurve().getExperience(null, getLevel(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -132,6 +136,12 @@ public class PlayerProfessions {
|
|||||||
setLevel(profession, value, PlayerLevelChangeEvent.Reason.UNKNOWN);
|
setLevel(profession, value, PlayerLevelChangeEvent.Reason.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void takeLevels(@NotNull Profession profession, int value) {
|
||||||
|
int current = Math.max(1, level.getOrDefault(profession.getId(), 1));
|
||||||
|
level.put(profession.getId(), Math.max(1, current - value));
|
||||||
|
}
|
||||||
|
|
||||||
public void setLevel(@NotNull Profession profession, int newLevel, @NotNull PlayerLevelChangeEvent.Reason reason) {
|
public void setLevel(@NotNull Profession profession, int newLevel, @NotNull PlayerLevelChangeEvent.Reason reason) {
|
||||||
if (profession.hasMaxLevel()) newLevel = Math.min(profession.getMaxLevel(), newLevel);
|
if (profession.hasMaxLevel()) newLevel = Math.min(profession.getMaxLevel(), newLevel);
|
||||||
final var previousValue = level.put(profession.getId(), Math.max(1, newLevel));
|
final var previousValue = level.put(profession.getId(), Math.max(1, newLevel));
|
||||||
@ -146,12 +156,6 @@ public class PlayerProfessions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public void takeLevels(@NotNull Profession profession, int value) {
|
|
||||||
int current = Math.max(1, level.getOrDefault(profession.getId(), 1));
|
|
||||||
level.put(profession.getId(), Math.max(1, current - value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExperience(Profession profession, double value) {
|
public void setExperience(Profession profession, double value) {
|
||||||
exp.put(profession.getId(), value);
|
exp.put(profession.getId(), value);
|
||||||
}
|
}
|
||||||
@ -159,7 +163,8 @@ public class PlayerProfessions {
|
|||||||
public void giveLevels(Profession profession, int value, EXPSource source) {
|
public void giveLevels(Profession profession, int value, EXPSource source) {
|
||||||
long equivalentExp = 0;
|
long equivalentExp = 0;
|
||||||
final var currentLevel = getLevel(profession);
|
final var currentLevel = getLevel(profession);
|
||||||
while (value-- > 0) equivalentExp += profession.getExpCurve().getExperience(currentLevel + value + 1);
|
while (value-- > 0)
|
||||||
|
equivalentExp += profession.getExpCurve().getExperience(playerData, currentLevel + value);
|
||||||
giveExperience(profession, equivalentExp, source);
|
giveExperience(profession, equivalentExp, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +176,8 @@ public class PlayerProfessions {
|
|||||||
giveExperience(profession, value, source, null, true);
|
giveExperience(profession, value, source, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Random RANDOM = new Random();
|
||||||
|
|
||||||
public void giveExperience(@NotNull Profession profession, double value, @NotNull EXPSource source, @Nullable Location hologramLocation, boolean splitExp) {
|
public void giveExperience(@NotNull Profession profession, double value, @NotNull EXPSource source, @Nullable Location hologramLocation, boolean splitExp) {
|
||||||
Validate.isTrue(playerData.isOnline(), "Cannot give experience to offline player");
|
Validate.isTrue(playerData.isOnline(), "Cannot give experience to offline player");
|
||||||
if (value <= 0) {
|
if (value <= 0) {
|
||||||
@ -200,8 +207,11 @@ public class PlayerProfessions {
|
|||||||
if (event.isCancelled()) return;
|
if (event.isCancelled()) return;
|
||||||
|
|
||||||
// Display hologram
|
// Display hologram
|
||||||
if (hologramLocation != null && profession.getOption(Profession.ProfessionOption.EXP_HOLOGRAMS))
|
if (hologramLocation != null && profession.getOption(Profession.ProfessionOption.EXP_HOLOGRAMS)) {
|
||||||
MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), Language.EXP_HOLOGRAM.getFormat().replace("{exp}", MythicLib.plugin.getMMOConfig().decimal.format(event.getExperience())));
|
// TODO custom location per profession/exp source.
|
||||||
|
hologramLocation.add(.5 + .7 * RANDOM.nextDouble(), 1.3 + RANDOM.nextDouble() / 3, .5 + .7 * RANDOM.nextDouble());
|
||||||
|
MMOCoreUtils.displayIndicator(hologramLocation, Language.EXP_HOLOGRAM.getFormat().replace("{exp}", MythicLib.plugin.getMMOConfig().decimal.format(event.getExperience())));
|
||||||
|
}
|
||||||
|
|
||||||
final var maxLevel = profession.getMaxLevel();
|
final var maxLevel = profession.getMaxLevel();
|
||||||
var currentExp = Math.max(0d, exp.getOrDefault(profession.getId(), 0d) + event.getExperience());
|
var currentExp = Math.max(0d, exp.getOrDefault(profession.getId(), 0d) + event.getExperience());
|
||||||
@ -213,7 +223,7 @@ public class PlayerProfessions {
|
|||||||
* Loop for exp overload when leveling up, will continue
|
* Loop for exp overload when leveling up, will continue
|
||||||
* looping until exp is 0 or max newLevel has been reached
|
* looping until exp is 0 or max newLevel has been reached
|
||||||
*/
|
*/
|
||||||
while (currentExp >= (experienceNeeded = profession.getExpCurve().getExperience(newLevel))) {
|
while (currentExp >= (experienceNeeded = profession.getExpCurve().getExperience(playerData, newLevel))) {
|
||||||
|
|
||||||
if (maxLevel > 0 && newLevel >= maxLevel) {
|
if (maxLevel > 0 && newLevel >= maxLevel) {
|
||||||
currentExp = 0;
|
currentExp = 0;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import io.lumine.mythic.lib.util.PreloadedObject;
|
|||||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||||
import net.Indyuce.mmocore.util.formula.ScalingFormula;
|
import net.Indyuce.mmocore.util.formula.ScalingFormula;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@ -22,7 +23,8 @@ public class Profession implements ExperienceObject, PreloadedObject {
|
|||||||
private final String id, name;
|
private final String id, name;
|
||||||
private final int maxLevel;
|
private final int maxLevel;
|
||||||
private final Map<ProfessionOption, Boolean> options = new HashMap<>();
|
private final Map<ProfessionOption, Boolean> options = new HashMap<>();
|
||||||
private final ExpCurve expCurve;
|
@NotNull
|
||||||
|
private final ExperienceCurve expCurve;
|
||||||
private final ExperienceTable expTable;
|
private final ExperienceTable expTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,9 +46,7 @@ public class Profession implements ExperienceObject, PreloadedObject {
|
|||||||
this.name = config.getString("name");
|
this.name = config.getString("name");
|
||||||
Validate.notNull(name, "Could not load name");
|
Validate.notNull(name, "Could not load name");
|
||||||
|
|
||||||
expCurve = config.contains("exp-curve")
|
expCurve = ExperienceCurve.fromConfig(config.getString("exp-curve"));
|
||||||
? MMOCore.plugin.experience.getCurveOrThrow(config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
|
|
||||||
: ExpCurve.DEFAULT;
|
|
||||||
experience = ScalingFormula.fromConfig(config.get("experience"));
|
experience = ScalingFormula.fromConfig(config.get("experience"));
|
||||||
|
|
||||||
ExperienceTable expTable = null;
|
ExperienceTable expTable = null;
|
||||||
@ -99,12 +99,12 @@ public class Profession implements ExperienceObject, PreloadedObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public @NotNull String getKey() {
|
||||||
return "profession_" + getId();
|
return "profession_" + getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ExpCurve getExpCurve() {
|
public @NotNull ExperienceCurve getExpCurve() {
|
||||||
return expCurve;
|
return expCurve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
package net.Indyuce.mmocore.experience.curve;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.util.FileUtils;
|
||||||
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public interface ExperienceCurve {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrary values. MMOCore needs a default exp curve for everything otherwise
|
||||||
|
* it would be swarming be divisions by 0 when trying to update the vanilla
|
||||||
|
* exp bar which requires a 0.0 -> 1.0 float as parameter.
|
||||||
|
* <p>
|
||||||
|
* See {@link PlayerData#refreshVanillaExp()}
|
||||||
|
*/
|
||||||
|
public static final ExperienceCurve DEFAULT = new ListExperienceCurve(100, 200, 300, 400, 500);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If 1 is provided as level, this method returns the experience needed
|
||||||
|
* to reach level 2. If the exp curve is a formula, it will provide 1 to the formula.
|
||||||
|
* If the exp curve is a list, it will return the first element of the list.
|
||||||
|
*
|
||||||
|
* @param player Player leveling up
|
||||||
|
* @param level Current level of the player.
|
||||||
|
* @return Experience needed to reach the next level.
|
||||||
|
*/
|
||||||
|
public long getExperience(@NotNull PlayerData player, int level);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ExperienceCurve fromConfig(@Nullable String configInput) {
|
||||||
|
|
||||||
|
// [BACKWARDS COMPATIBILITY] Load from predefined file
|
||||||
|
try {
|
||||||
|
if (configInput == null) throw new RuntimeException();
|
||||||
|
final var expCurveFile = FileUtils.getFile(MMOCore.plugin, "expcurves/" + configInput + ".txt");
|
||||||
|
return new ListExperienceCurve(expCurveFile);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configInput == null) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load from file
|
||||||
|
else if (configInput.endsWith(".txt")) {
|
||||||
|
final var expCurveFile = FileUtils.getFile(MMOCore.plugin, configInput);
|
||||||
|
return new ListExperienceCurve(expCurveFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load as formula
|
||||||
|
else {
|
||||||
|
return new FormulaExperienceCurve(configInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package net.Indyuce.mmocore.experience.curve;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.MythicLib;
|
||||||
|
import io.lumine.mythic.lib.util.formula.NumericalExpression;
|
||||||
|
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class FormulaExperienceCurve implements ExperienceCurve {
|
||||||
|
private final String formula;
|
||||||
|
|
||||||
|
public FormulaExperienceCurve(@NotNull String formula) {
|
||||||
|
this.formula = formula;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getExperience(@NotNull PlayerData player, int level) {
|
||||||
|
try {
|
||||||
|
Validate.isTrue(level > 0, "Level must be stricly positive, got " + level);
|
||||||
|
final var parsed = MythicLib.plugin.getPlaceholderParser().parse(player.getPlayer(), this.formula);
|
||||||
|
final var value = (int) NumericalExpression.eval(parsed.replace("{level}", String.valueOf(level)));
|
||||||
|
Validate.isTrue(value > 0, "Exp curve must return a positive value, got " + value);
|
||||||
|
return value;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
MythicLib.plugin.getLogger().warning("Error parsing exp formula '" + this.formula + "' for player " + player.getPlayer().getName() + ", using 100: " + e.getMessage());
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
package net.Indyuce.mmocore.experience.curve;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ListExperienceCurve implements ExperienceCurve {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experience needed to level up. At index i, experience needed
|
||||||
|
* to level up from level N to (N + 1).
|
||||||
|
*/
|
||||||
|
private final List<Long> experience;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an exp curve from a text file, one line after the other. Each
|
||||||
|
* exp value has to be the only thing written on every line
|
||||||
|
*
|
||||||
|
* @param file Text file to read data from
|
||||||
|
*/
|
||||||
|
public ListExperienceCurve(@NotNull File file) {
|
||||||
|
this.experience = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||||
|
String readLine;
|
||||||
|
while ((readLine = reader.readLine()) != null)
|
||||||
|
experience.add(Long.valueOf(readLine));
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
throw new RuntimeException(throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exp curve with specific level up exp values
|
||||||
|
*
|
||||||
|
* @param values The exp values. There has to be at least one
|
||||||
|
*/
|
||||||
|
public ListExperienceCurve(long... values) {
|
||||||
|
this.experience = new ArrayList<>(values.length);
|
||||||
|
for (long value : values) experience.add(value);
|
||||||
|
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getExperience(@NotNull PlayerData player, int level) {
|
||||||
|
Validate.isTrue(level > 0, "Level must be stricly positive");
|
||||||
|
return experience.get(Math.min(level, experience.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,6 +15,7 @@ import org.bukkit.event.EventPriority;
|
|||||||
import org.bukkit.event.inventory.CraftItemEvent;
|
import org.bukkit.event.inventory.CraftItemEvent;
|
||||||
import org.bukkit.event.inventory.InventoryAction;
|
import org.bukkit.event.inventory.InventoryAction;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class CraftItemExperienceSource extends SpecificExperienceSource<Material> {
|
public class CraftItemExperienceSource extends SpecificExperienceSource<Material> {
|
||||||
@ -45,7 +46,7 @@ public class CraftItemExperienceSource extends SpecificExperienceSource<Material
|
|||||||
|
|
||||||
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
|
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This makes sure that the crafting recipe was performed correctly.
|
* This makes sure that the crafting recipe was performed correctly.
|
||||||
*
|
*
|
||||||
* In some scenarii, the CraftItemEvent (which is only a click event
|
* In some scenarii, the CraftItemEvent (which is only a click event
|
||||||
@ -62,27 +63,32 @@ public class CraftItemExperienceSource extends SpecificExperienceSource<Material
|
|||||||
* - https://git.lumine.io/mythiccraft/mmocore/-/issues/102
|
* - https://git.lumine.io/mythiccraft/mmocore/-/issues/102
|
||||||
* - https://www.spigotmc.org/threads/how-to-get-amount-of-item-crafted.377598/
|
* - https://www.spigotmc.org/threads/how-to-get-amount-of-item-crafted.377598/
|
||||||
*/
|
*/
|
||||||
final int index = getLowerAmountIngredientIndex(event.getInventory().getMatrix());
|
final var index = getLowerAmountIngredientIndex(event.getInventory().getMatrix());
|
||||||
final int oldAmount = event.getInventory().getMatrix()[index].getAmount();
|
final var oldItem = event.getInventory().getMatrix()[index];
|
||||||
final int itemsCraftedPerRecipe = event.getInventory().getResult().getAmount();
|
final var oldAmount = oldItem.getAmount();
|
||||||
final Material resultType = event.getInventory().getResult().getType();
|
final var itemsCraftedPerRecipe = event.getInventory().getResult().getAmount();
|
||||||
|
final var resultType = event.getInventory().getResult().getType();
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
|
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
|
||||||
|
|
||||||
// First check
|
final var newItem = event.getInventory().getMatrix()[index];
|
||||||
int newAmount = getAmount(event.getInventory().getMatrix()[index]);
|
final var newAmount = getEffectiveNewAmount(newItem, oldItem);
|
||||||
|
|
||||||
if (newAmount >= oldAmount) return;
|
if (newAmount >= oldAmount) return;
|
||||||
|
|
||||||
// Deduce amount crafted
|
// Deduce amount crafted
|
||||||
int amountCrafted = (event.getClick().isShiftClick() ? oldAmount - newAmount : 1) * itemsCraftedPerRecipe;
|
final var amountCrafted = (event.getClick().isShiftClick() ? oldAmount - newAmount : 1) * itemsCraftedPerRecipe;
|
||||||
for (CraftItemExperienceSource source : getSources())
|
for (CraftItemExperienceSource source : getSources())
|
||||||
if (source.matches(data, resultType))
|
if (source.matches(data, resultType))
|
||||||
source.giveExperience(data, amountCrafted, event.getInventory().getLocation());
|
source.giveExperience(data, amountCrafted, event.getInventory().getLocation());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getAmount(@Nullable ItemStack item) {
|
private int getEffectiveNewAmount(@Nullable ItemStack item, @NotNull ItemStack oldItem) {
|
||||||
return item == null || item.getType() == Material.AIR ? 0 : item.getAmount();
|
// Some items are consumed and leave behind a different type (e.g. buckets)
|
||||||
|
// If that's the case just say all items were crafted
|
||||||
|
// Fixes https://gitlab.com/phoenix-dvpmt/mmocore/-/issues/1165
|
||||||
|
return item == null || item.getType() == Material.AIR || item.getType() != oldItem.getType() ? 0 : item.getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getLowerAmountIngredientIndex(ItemStack[] matrix) {
|
private int getLowerAmountIngredientIndex(ItemStack[] matrix) {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package net.Indyuce.mmocore.manager;
|
package net.Indyuce.mmocore.manager;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.MythicLib;
|
import io.lumine.mythic.lib.MythicLib;
|
||||||
|
import io.lumine.mythic.lib.api.stat.StatInstance;
|
||||||
import io.lumine.mythic.lib.util.FileUtils;
|
import io.lumine.mythic.lib.util.FileUtils;
|
||||||
import io.lumine.mythic.lib.util.config.YamlFile;
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.attribute.MMOCoreAttributeStatHandler;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -40,20 +40,23 @@ public class AttributeManager implements MMOCoreManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(boolean clearBefore) {
|
public void initialize(boolean clearBefore) {
|
||||||
if (clearBefore) {
|
if (clearBefore)
|
||||||
map.clear();
|
map.clear();
|
||||||
MythicLib.plugin.getStats().clearRegisteredStats(handler -> handler instanceof MMOCoreAttributeStatHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileUtils.loadObjectsFromFolder(MMOCore.plugin, "attributes", false, (key, config) -> {
|
FileUtils.loadObjectsFromFolder(MMOCore.plugin, "attributes", false, (key, config) -> {
|
||||||
final String path = key.toLowerCase().replace("_", "-").replace(" ", "-");
|
final String path = key.toLowerCase().replace("_", "-").replace(" ", "-");
|
||||||
map.put(path, new PlayerAttribute(config));
|
map.put(path, new PlayerAttribute(config));
|
||||||
}, "Could not load attribute '%s' from file '%s': %s");
|
}, "Could not load attribute '%s' from file '%s': %s");
|
||||||
|
|
||||||
final var statsConfig = new YamlFile(MythicLib.plugin, "stats").getContent();
|
// MythicLib stat handlers
|
||||||
for (PlayerAttribute attr : getAll()) {
|
for (PlayerAttribute attr : getAll()) {
|
||||||
final MMOCoreAttributeStatHandler handler = new MMOCoreAttributeStatHandler(statsConfig, attr);
|
final var statId = attr.getId().toUpperCase().replace("-", "_") + "_PERCENT";
|
||||||
MythicLib.plugin.getStats().registerStat(handler, handler.getStat() + "_PERCENT");
|
MythicLib.plugin.getStats().computeStat(statId).addUpdateListener(ins -> this.updateMMOCoreStatAttributeValue(ins, attr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateMMOCoreStatAttributeValue(@NotNull StatInstance instance, PlayerAttribute attribute) {
|
||||||
|
final var playerData = PlayerData.get(instance.getMap().getPlayerData());
|
||||||
|
playerData.getAttributes().getInstance(attribute).updateStats();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,12 +69,6 @@ public class ConfigManager {
|
|||||||
if (!FileUtils.getFile(MMOCore.plugin, "exp-tables").exists())
|
if (!FileUtils.getFile(MMOCore.plugin, "exp-tables").exists())
|
||||||
copyDefaultFile("exp-tables/default_exp_tables.yml");
|
copyDefaultFile("exp-tables/default_exp_tables.yml");
|
||||||
|
|
||||||
if (!FileUtils.getFile(MMOCore.plugin, "expcurves").exists()) {
|
|
||||||
copyDefaultFile("expcurves/levels.txt");
|
|
||||||
copyDefaultFile("expcurves/mining.txt");
|
|
||||||
copyDefaultFile("expcurves/skill-tree-node.txt");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FileUtils.getFile(MMOCore.plugin, "loot-chests").exists())
|
if (!FileUtils.getFile(MMOCore.plugin, "loot-chests").exists())
|
||||||
copyDefaultFile("loot-chests/default_loot_chests.yml");
|
copyDefaultFile("loot-chests/default_loot_chests.yml");
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
package net.Indyuce.mmocore.manager;
|
package net.Indyuce.mmocore.manager;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.util.FileUtils;
|
import io.lumine.mythic.lib.util.FileUtils;
|
||||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||||
@ -14,7 +13,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ExperienceManager implements MMOCoreManager {
|
public class ExperienceManager implements MMOCoreManager {
|
||||||
private final Map<String, ExpCurve> expCurves = new HashMap<>();
|
|
||||||
private final Map<String, ExperienceTable> expTables = new HashMap<>();
|
private final Map<String, ExperienceTable> expTables = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,14 +43,29 @@ public class ExperienceManager implements MMOCoreManager {
|
|||||||
getManager(path).registerSource(source);
|
getManager(path).registerSource(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public boolean hasCurve(String id) {
|
public boolean hasCurve(String id) {
|
||||||
return expCurves.containsKey(id);
|
try {
|
||||||
|
ExperienceCurve.fromConfig("expcurves/" + id + ".txt");
|
||||||
|
return true;
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@NotNull
|
@NotNull
|
||||||
public ExpCurve getCurveOrThrow(String id) {
|
public ExperienceCurve getCurveOrThrow(String id) {
|
||||||
Validate.isTrue(hasCurve(id), "Could not find exp curve with ID '" + id + "'");
|
try {
|
||||||
return expCurves.get(id);
|
return ExperienceCurve.fromConfig(id + ".txt");
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
throw new IllegalArgumentException("Could not find exp curve with ID '" + id + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public Collection<ExperienceCurve> getCurves() {
|
||||||
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -82,10 +95,6 @@ public class ExperienceManager implements MMOCoreManager {
|
|||||||
throw new IllegalArgumentException("Please provide either a string (exp table name) or a config section (locally define an exp table)");
|
throw new IllegalArgumentException("Please provide either a string (exp table name) or a config section (locally define an exp table)");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ExpCurve> getCurves() {
|
|
||||||
return expCurves.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<ExperienceTable> getTables() {
|
public Collection<ExperienceTable> getTables() {
|
||||||
return expTables.values();
|
return expTables.values();
|
||||||
}
|
}
|
||||||
@ -100,21 +109,15 @@ public class ExperienceManager implements MMOCoreManager {
|
|||||||
@Override
|
@Override
|
||||||
public void initialize(boolean clearBefore) {
|
public void initialize(boolean clearBefore) {
|
||||||
if (clearBefore) {
|
if (clearBefore) {
|
||||||
expCurves.clear();
|
|
||||||
expTables.clear();
|
expTables.clear();
|
||||||
|
|
||||||
managers.forEach((c, manager) -> manager.close());
|
managers.forEach((c, manager) -> manager.close());
|
||||||
managers.clear();
|
managers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exp curves
|
|
||||||
FileUtils.loadObjectsFromFolderRaw(MMOCore.plugin, "expcurves", file -> {
|
|
||||||
final ExpCurve curve = new ExpCurve(file);
|
|
||||||
expCurves.put(curve.getId(), curve);
|
|
||||||
}, "Could not load exp curve from file '%s': %s");
|
|
||||||
|
|
||||||
// Exp tables
|
// Exp tables
|
||||||
FileUtils.loadObjectsFromFolder(MMOCore.plugin ,"exp-tables", false, (key, config) -> {
|
FileUtils.loadObjectsFromFolder(MMOCore.plugin, "exp-tables", false, (key, config) -> {
|
||||||
final ExperienceTable table = new ExperienceTable(config);
|
final ExperienceTable table = new ExperienceTable(config);
|
||||||
expTables.put(table.getId(), table);
|
expTables.put(table.getId(), table);
|
||||||
}, "Could not load exp table '%s' from file '%s': %s");
|
}, "Could not load exp table '%s' from file '%s': %s");
|
||||||
|
|||||||
@ -161,7 +161,11 @@ public class YAMLDatabaseImpl extends YAMLFlatDatabase<PlayerData, OfflinePlayer
|
|||||||
|
|
||||||
// Saves the nodes levels
|
// Saves the nodes levels
|
||||||
config.set("skill-tree-level", null);
|
config.set("skill-tree-level", null);
|
||||||
MMOCore.plugin.skillTreeManager.getAllNodes().forEach(node -> config.set("skill-tree-level." + node.getFullId(), data.getNodeLevel(node)));
|
config.createSection("skill-tree-level");
|
||||||
|
for (var node : MMOCore.plugin.skillTreeManager.getAllNodes()) {
|
||||||
|
final var nodeLevel = data.getNodeLevel(node);
|
||||||
|
if (nodeLevel > 0) config.set("skill-tree-level." + node.getFullId(), nodeLevel);
|
||||||
|
}
|
||||||
|
|
||||||
// Skill levels
|
// Skill levels
|
||||||
config.set("skill", null);
|
config.set("skill", null);
|
||||||
|
|||||||
@ -205,12 +205,15 @@ public class CustomBlockManager extends SpecificProfessionManager {
|
|||||||
this.protectVanillaBlocks = config.getBoolean("protect-vanilla-blocks");
|
this.protectVanillaBlocks = config.getBoolean("protect-vanilla-blocks");
|
||||||
this.enableToolRestrictions = config.getBoolean("enable-tool-restrictions");
|
this.enableToolRestrictions = config.getBoolean("enable-tool-restrictions");
|
||||||
|
|
||||||
for (String key : config.getStringList("conditions"))
|
// Avoid warnings if disabled
|
||||||
try {
|
if (enabled)
|
||||||
customMineConditions.add(MMOCore.plugin.loadManager.loadCondition(new MMOLineConfig(key)));
|
for (String key : config.getStringList("conditions"))
|
||||||
} catch (IllegalArgumentException exception) {
|
try {
|
||||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load custom mining condition '" + key + "': " + exception.getMessage());
|
customMineConditions.add(MMOCore.plugin.loadManager.loadCondition(new MMOLineConfig(key)));
|
||||||
}
|
} catch (IllegalArgumentException exception) {
|
||||||
|
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load custom mining condition '" + key + "': " + exception.getMessage());
|
||||||
|
}
|
||||||
|
else customMineConditions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package net.Indyuce.mmocore.quest;
|
package net.Indyuce.mmocore.quest;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.quest.compat.BeautyQuestModule;
|
import net.Indyuce.mmocore.quest.compat.BeautyQuestModule;
|
||||||
import net.Indyuce.mmocore.quest.compat.BlackVeinQuestsModule;
|
import net.Indyuce.mmocore.quest.compat.QuestsModule;
|
||||||
import net.Indyuce.mmocore.quest.compat.QuestCreatorModule;
|
import net.Indyuce.mmocore.quest.compat.QuestCreatorModule;
|
||||||
import net.Indyuce.mmocore.quest.compat.QuestModule;
|
import net.Indyuce.mmocore.quest.compat.QuestModule;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -10,7 +10,7 @@ import javax.inject.Provider;
|
|||||||
|
|
||||||
public enum QuestModuleType {
|
public enum QuestModuleType {
|
||||||
MMOCORE("MMOCore", MMOCoreQuestModule::new),
|
MMOCORE("MMOCore", MMOCoreQuestModule::new),
|
||||||
QUESTS("Quests", BlackVeinQuestsModule::new),
|
QUESTS("Quests", QuestsModule::new),
|
||||||
BEAUTY_QUEST("BeautyQuests", BeautyQuestModule::new),
|
BEAUTY_QUEST("BeautyQuests", BeautyQuestModule::new),
|
||||||
QUEST_CREATOR("QuestCreator", QuestCreatorModule::new);
|
QUEST_CREATOR("QuestCreator", QuestCreatorModule::new);
|
||||||
|
|
||||||
|
|||||||
@ -1,54 +0,0 @@
|
|||||||
package net.Indyuce.mmocore.quest.compat;
|
|
||||||
|
|
||||||
import me.blackvein.quests.Quest;
|
|
||||||
import me.blackvein.quests.Quester;
|
|
||||||
import me.blackvein.quests.Quests;
|
|
||||||
import net.Indyuce.mmocore.quest.AbstractQuest;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
|
|
||||||
public class BlackVeinQuestsModule implements QuestModule<BlackVeinQuestsModule.BlackVeinQuestQuest> {
|
|
||||||
private final Quests plugin = (Quests) Bukkit.getPluginManager().getPlugin("Quests");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlackVeinQuestQuest getQuestOrThrow(String id) {
|
|
||||||
Quests plugin = (Quests) Bukkit.getPluginManager().getPlugin("Quests");
|
|
||||||
return plugin.getQuestById(id)==null?null:new BlackVeinQuestQuest(plugin.getQuestById(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasCompletedQuest(String questId, Player player) {
|
|
||||||
Quester quester = plugin.getQuester(player.getUniqueId());
|
|
||||||
if(quester==null)
|
|
||||||
return false;
|
|
||||||
for(Quest quest:quester.getCompletedQuests()) {
|
|
||||||
if(quest.getId().equals(questId))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class BlackVeinQuestQuest implements AbstractQuest {
|
|
||||||
private final Quest quest;
|
|
||||||
|
|
||||||
public BlackVeinQuestQuest(Quest quest) {
|
|
||||||
this.quest = quest;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return quest.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return quest.getId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package net.Indyuce.mmocore.quest.compat;
|
||||||
|
|
||||||
|
import me.pikamug.quests.BukkitQuestsPlugin;
|
||||||
|
import me.pikamug.quests.player.Quester;
|
||||||
|
import me.pikamug.quests.quests.Quest;
|
||||||
|
import net.Indyuce.mmocore.quest.AbstractQuest;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class QuestsModule implements QuestModule<QuestsModule.QuestImpl> {
|
||||||
|
private final BukkitQuestsPlugin plugin;
|
||||||
|
|
||||||
|
public QuestsModule() {
|
||||||
|
plugin = (BukkitQuestsPlugin) Bukkit.getPluginManager().getPlugin("Quests");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QuestImpl getQuestOrThrow(String id) {
|
||||||
|
final var found = plugin.getQuest(id);
|
||||||
|
return found == null ? null : new QuestImpl(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasCompletedQuest(String questId, Player player) {
|
||||||
|
Quester quester = plugin.getQuester(player.getUniqueId());
|
||||||
|
if (quester == null) return false;
|
||||||
|
|
||||||
|
for (var quest : quester.getCompletedQuests())
|
||||||
|
if (quest.getId().equals(questId)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class QuestImpl implements AbstractQuest {
|
||||||
|
private final Quest quest;
|
||||||
|
|
||||||
|
public QuestImpl(Quest quest) {
|
||||||
|
this.quest = quest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return quest.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return quest.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,7 +9,7 @@ import io.lumine.mythic.lib.util.lang3.Validate;
|
|||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.experience.EXPSource;
|
import net.Indyuce.mmocore.experience.EXPSource;
|
||||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||||
import net.Indyuce.mmocore.skilltree.display.DisplayMap;
|
import net.Indyuce.mmocore.skilltree.display.DisplayMap;
|
||||||
@ -204,7 +204,7 @@ public class SkillTreeNode implements ExperienceObject {
|
|||||||
public static final String KEY_PREFIX = "node";
|
public static final String KEY_PREFIX = "node";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public @NotNull String getKey() {
|
||||||
return KEY_PREFIX + ":" + getFullId().replace("-", "_");
|
return KEY_PREFIX + ":" + getFullId().replace("-", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,9 +269,9 @@ public class SkillTreeNode implements ExperienceObject {
|
|||||||
throw new RuntimeException("Skill trees don't have experience");
|
throw new RuntimeException("Skill trees don't have experience");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ExpCurve getExpCurve() {
|
public ExperienceCurve getExpCurve() {
|
||||||
throw new RuntimeException("Skill trees don't have experience");
|
throw new RuntimeException("Skill trees don't have experience");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,8 +20,14 @@ options:
|
|||||||
off-combat-health-regen: false
|
off-combat-health-regen: false
|
||||||
off-combat-mana-regen: false
|
off-combat-mana-regen: false
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/class_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current class level.
|
||||||
|
# | Example: '{level} * 200'
|
||||||
|
exp-curve: '{level} * 200'
|
||||||
|
|
||||||
exp-table: class_exp_table
|
exp-table: class_exp_table
|
||||||
|
|
||||||
|
|||||||
@ -36,8 +36,14 @@ display:
|
|||||||
# item-model: 'minecraft:dirt'
|
# item-model: 'minecraft:dirt'
|
||||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/class_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current class level.
|
||||||
|
# | Example: '{level} * 200'
|
||||||
|
exp-curve: '{level} * 200'
|
||||||
|
|
||||||
skill-slots:
|
skill-slots:
|
||||||
1:
|
1:
|
||||||
|
|||||||
@ -36,8 +36,14 @@ display:
|
|||||||
# item-model: 'minecraft:dirt'
|
# item-model: 'minecraft:dirt'
|
||||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/class_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current class level.
|
||||||
|
# | Example: '{level} * 200'
|
||||||
|
exp-curve: '{level} * 200'
|
||||||
|
|
||||||
# The maximum level players can reach
|
# The maximum level players can reach
|
||||||
max-level: 100
|
max-level: 100
|
||||||
|
|||||||
@ -35,8 +35,14 @@ display:
|
|||||||
# item-model: 'minecraft:dirt'
|
# item-model: 'minecraft:dirt'
|
||||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/class_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current class level.
|
||||||
|
# | Example: '{level} * 200'
|
||||||
|
exp-curve: '{level} * 200'
|
||||||
|
|
||||||
# The maximum level players can reach
|
# The maximum level players can reach
|
||||||
max-level: 100
|
max-level: 100
|
||||||
|
|||||||
@ -35,8 +35,14 @@ display:
|
|||||||
# item-model: 'minecraft:dirt'
|
# item-model: 'minecraft:dirt'
|
||||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/class_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current class level.
|
||||||
|
# | Example: '{level} * 200'
|
||||||
|
exp-curve: '{level} * 200'
|
||||||
|
|
||||||
skill-slots:
|
skill-slots:
|
||||||
1:
|
1:
|
||||||
|
|||||||
@ -36,8 +36,14 @@ display:
|
|||||||
# item-model: 'minecraft:dirt'
|
# item-model: 'minecraft:dirt'
|
||||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/class_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current class level.
|
||||||
|
# | Example: '{level} * 200'
|
||||||
|
exp-curve: '{level} * 200'
|
||||||
|
|
||||||
# The maximum level players can reach
|
# The maximum level players can reach
|
||||||
max-level: 100
|
max-level: 100
|
||||||
|
|||||||
@ -39,8 +39,14 @@ display:
|
|||||||
# item-model: 'minecraft:dirt'
|
# item-model: 'minecraft:dirt'
|
||||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/class_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current class level.
|
||||||
|
# | Example: '{level} * 200'
|
||||||
|
exp-curve: '{level} * 200'
|
||||||
|
|
||||||
# The maximum level players can reach
|
# The maximum level players can reach
|
||||||
max-level: 100
|
max-level: 100
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
200
|
|
||||||
400
|
|
||||||
600
|
|
||||||
800
|
|
||||||
1000
|
|
||||||
1200
|
|
||||||
1400
|
|
||||||
1600
|
|
||||||
1800
|
|
||||||
2000
|
|
||||||
2200
|
|
||||||
2400
|
|
||||||
2600
|
|
||||||
2800
|
|
||||||
3000
|
|
||||||
3200
|
|
||||||
3400
|
|
||||||
3600
|
|
||||||
3800
|
|
||||||
4000
|
|
||||||
4200
|
|
||||||
4400
|
|
||||||
4600
|
|
||||||
4800
|
|
||||||
5000
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
100
|
|
||||||
200
|
|
||||||
300
|
|
||||||
400
|
|
||||||
500
|
|
||||||
600
|
|
||||||
700
|
|
||||||
800
|
|
||||||
900
|
|
||||||
1000
|
|
||||||
1100
|
|
||||||
1200
|
|
||||||
1300
|
|
||||||
1400
|
|
||||||
1500
|
|
||||||
1600
|
|
||||||
1700
|
|
||||||
1800
|
|
||||||
1900
|
|
||||||
2000
|
|
||||||
2100
|
|
||||||
2200
|
|
||||||
2300
|
|
||||||
2400
|
|
||||||
2500
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
|
||||||
5
|
|
||||||
6
|
|
||||||
7
|
|
||||||
8
|
|
||||||
9
|
|
||||||
10
|
|
||||||
11
|
|
||||||
12
|
|
||||||
13
|
|
||||||
14
|
|
||||||
15
|
|
||||||
16
|
|
||||||
17
|
|
||||||
18
|
|
||||||
19
|
|
||||||
20
|
|
||||||
21
|
|
||||||
22
|
|
||||||
23
|
|
||||||
24
|
|
||||||
25
|
|
||||||
@ -8,8 +8,14 @@ experience:
|
|||||||
base: 20
|
base: 20
|
||||||
per-level: 3
|
per-level: 3
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
exp-sources:
|
exp-sources:
|
||||||
- 'brewpotion{effect=SPEED}'
|
- 'brewpotion{effect=SPEED}'
|
||||||
@ -20,31 +26,31 @@ exp-sources:
|
|||||||
alchemy-experience:
|
alchemy-experience:
|
||||||
|
|
||||||
special:
|
special:
|
||||||
|
|
||||||
# When brewing a potion into a splash potion,
|
# When brewing a potion into a splash potion,
|
||||||
# only 40% of the base EXP is earned.
|
# only 40% of the base EXP is earned.
|
||||||
splash: 40
|
splash: 40
|
||||||
|
|
||||||
# When brewing a potion into a splash potion,
|
# When brewing a potion into a splash potion,
|
||||||
# only 40% of the base EXP is earned.
|
# only 40% of the base EXP is earned.
|
||||||
lingering: 40
|
lingering: 40
|
||||||
|
|
||||||
# When extending a pot duration,
|
# When extending a pot duration,
|
||||||
# only 40% of base EXP is earned.
|
# only 40% of base EXP is earned.
|
||||||
extend: 40
|
extend: 40
|
||||||
|
|
||||||
# When upgrading a potion level,
|
# When upgrading a potion level,
|
||||||
# only 40% of base EXP is earned.
|
# only 40% of base EXP is earned.
|
||||||
upgrade: 40
|
upgrade: 40
|
||||||
|
|
||||||
# Base EXP of potions
|
# Base EXP of potions
|
||||||
effects:
|
effects:
|
||||||
|
|
||||||
# Water bottles
|
# Water bottles
|
||||||
AWKWARD: 5
|
AWKWARD: 5
|
||||||
MUNDANE: 5
|
MUNDANE: 5
|
||||||
THICK: 5
|
THICK: 5
|
||||||
|
|
||||||
# Potion effects
|
# Potion effects
|
||||||
NIGHT_VISION: 10
|
NIGHT_VISION: 10
|
||||||
INVISIBILITY: 10
|
INVISIBILITY: 10
|
||||||
|
|||||||
@ -8,8 +8,14 @@ experience:
|
|||||||
base: 10
|
base: 10
|
||||||
per-level: 2
|
per-level: 2
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
# Remove the 'enchant' parameter from the line config
|
# Remove the 'enchant' parameter from the line config
|
||||||
# to make the profession get EXP with ANY enchant.
|
# to make the profession get EXP with ANY enchant.
|
||||||
|
|||||||
@ -7,8 +7,14 @@ experience:
|
|||||||
base: 10
|
base: 10
|
||||||
per-level: 2
|
per-level: 2
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
exp-sources:
|
exp-sources:
|
||||||
- 'mineblock{type=WHEAT;amount=1-3;crop=true;player-placed=true;silk-touch=false}'
|
- 'mineblock{type=WHEAT;amount=1-3;crop=true;player-placed=true;silk-touch=false}'
|
||||||
|
|||||||
@ -8,8 +8,14 @@ experience:
|
|||||||
base: 20
|
base: 20
|
||||||
per-level: 3
|
per-level: 3
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
exp-sources: {}
|
exp-sources: {}
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,14 @@ experience:
|
|||||||
base: 20
|
base: 20
|
||||||
per-level: 3
|
per-level: 3
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: mining
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
# This part of the config is ONLY for custom mining.
|
# This part of the config is ONLY for custom mining.
|
||||||
# Custom Mining must be setup in config.yml and it
|
# Custom Mining must be setup in config.yml and it
|
||||||
|
|||||||
@ -7,8 +7,14 @@ experience:
|
|||||||
base: 20
|
base: 20
|
||||||
per-level: 3
|
per-level: 3
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
exp-sources:
|
exp-sources:
|
||||||
- 'craftitem{type=BLAST_FURNACE;amount=1}'
|
- 'craftitem{type=BLAST_FURNACE;amount=1}'
|
||||||
|
|||||||
@ -8,8 +8,14 @@ experience:
|
|||||||
base: 20
|
base: 20
|
||||||
per-level: 3
|
per-level: 3
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
exp-sources:
|
exp-sources:
|
||||||
- 'repairitem{}'
|
- 'repairitem{}'
|
||||||
|
|||||||
@ -8,8 +8,14 @@ experience:
|
|||||||
base: 13
|
base: 13
|
||||||
per-level: 2.5
|
per-level: 2.5
|
||||||
|
|
||||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||||
exp-curve: levels
|
# | The TXT files contains only the experience required per level, one per line.
|
||||||
|
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||||
|
# Or a formula using the {level} and PAPI placeholders.
|
||||||
|
# | The formula should return the total experience required to reach the next
|
||||||
|
# | level if {level} is the player's current profession level.
|
||||||
|
# | Example: '{level} * 150'
|
||||||
|
exp-curve: '{level} * 150'
|
||||||
|
|
||||||
exp-sources:
|
exp-sources:
|
||||||
- 'mineblock{type=OAK_LOG;amount=1-3}'
|
- 'mineblock{type=OAK_LOG;amount=1-3}'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user