forked from Upstream/mmocore
Merge remote-tracking branch 'origin/master'
# Conflicts: # src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java # src/main/java/net/Indyuce/mmocore/api/quest/trigger/ExperienceTrigger.java # src/main/java/net/Indyuce/mmocore/experience/ExperienceObject.java # src/main/java/net/Indyuce/mmocore/experience/Profession.java # src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java
This commit is contained in:
commit
026d0194ea
36
pom.xml
36
pom.xml
@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.Indyuce</groupId>
|
||||
<artifactId>MMOCore</artifactId>
|
||||
<version>1.9.2</version>
|
||||
<version>1.9.3</version>
|
||||
<name>MMOCore</name>
|
||||
<description>Offer your players a brand new RPG experience!!</description>
|
||||
|
||||
@ -39,10 +39,17 @@
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
|
||||
<configuration>
|
||||
<source>9</source>
|
||||
<target>9</target>
|
||||
@ -215,6 +222,33 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Quest Plugin-->
|
||||
<dependency>
|
||||
<groupId>me.blackvein</groupId>
|
||||
<artifactId>Quests</artifactId>
|
||||
<version>4.4.1-b340</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.skytasul.quests</groupId>
|
||||
<artifactId>BeautyQuests</artifactId>
|
||||
<version>0.19.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.guillaumevdn</groupId>
|
||||
<artifactId>QuestCreator</artifactId>
|
||||
<version>6.39.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.guillaumevdn</groupId>
|
||||
<artifactId>GCore</artifactId>
|
||||
<version>8.39.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Guild plugins -->
|
||||
<dependency>
|
||||
<groupId>com.massivecraft</groupId>
|
||||
|
@ -8,11 +8,10 @@ import io.lumine.mythic.utils.plugin.LuminePlugin;
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.api.PlayerActionBar;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.attribute.AttributeModifier;
|
||||
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.util.debug.DebugMode;
|
||||
import net.Indyuce.mmocore.command.*;
|
||||
import net.Indyuce.mmocore.comp.MMOCoreTargetRestriction;
|
||||
import net.Indyuce.mmocore.comp.citizens.CitizenInteractEventListener;
|
||||
import net.Indyuce.mmocore.comp.citizens.CitizensMMOLoader;
|
||||
import net.Indyuce.mmocore.comp.mythicmobs.MythicHook;
|
||||
@ -32,7 +31,6 @@ import net.Indyuce.mmocore.listener.event.PlayerPressKeyListener;
|
||||
import net.Indyuce.mmocore.listener.option.*;
|
||||
import net.Indyuce.mmocore.listener.profession.FishingListener;
|
||||
import net.Indyuce.mmocore.listener.profession.PlayerCollectStats;
|
||||
import net.Indyuce.mmocore.loot.chest.LootChest;
|
||||
import net.Indyuce.mmocore.manager.*;
|
||||
import net.Indyuce.mmocore.manager.data.DataProvider;
|
||||
import net.Indyuce.mmocore.manager.data.mysql.MySQLDataProvider;
|
||||
@ -41,6 +39,7 @@ import net.Indyuce.mmocore.manager.profession.*;
|
||||
import net.Indyuce.mmocore.manager.social.BoosterManager;
|
||||
import net.Indyuce.mmocore.manager.social.PartyManager;
|
||||
import net.Indyuce.mmocore.manager.social.RequestManager;
|
||||
import net.Indyuce.mmocore.party.MMOCoreTargetRestriction;
|
||||
import net.Indyuce.mmocore.party.PartyModule;
|
||||
import net.Indyuce.mmocore.party.PartyModuleType;
|
||||
import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
|
||||
@ -55,7 +54,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class MMOCore extends LuminePlugin {
|
||||
@ -78,6 +76,7 @@ public class MMOCore extends LuminePlugin {
|
||||
public final LootChestManager lootChests = new LootChestManager();
|
||||
public final MMOLoadManager loadManager = new MMOLoadManager();
|
||||
public final RestrictionManager restrictionManager = new RestrictionManager();
|
||||
public final StatManager statManager = new StatManager();
|
||||
@Deprecated
|
||||
public final SkillTreeManager skillTreeManager = new SkillTreeManager();
|
||||
|
||||
@ -116,8 +115,10 @@ public class MMOCore extends LuminePlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register target restrictions due to MMOCore in MythicLib
|
||||
// Register MMOCore-specific objects
|
||||
MythicLib.plugin.getEntities().registerRestriction(new MMOCoreTargetRestriction());
|
||||
MythicLib.plugin.getModifiers().registerModifierType("attribute", configObject -> new AttributeModifier(configObject));
|
||||
|
||||
|
||||
// Register extra objective, drop items...
|
||||
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null)
|
||||
@ -189,23 +190,6 @@ public class MMOCore extends LuminePlugin {
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 100, 20);
|
||||
|
||||
/*
|
||||
* Clean active loot chests every 5 minutes. Cannot register this runnable in
|
||||
* the loot chest manager because it is instanced when the plugin loads
|
||||
*/
|
||||
new BukkitRunnable() {
|
||||
public void run() {
|
||||
Iterator<LootChest> iterator = lootChests.getActive().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
LootChest next = iterator.next();
|
||||
if (next.shouldExpire()) {
|
||||
iterator.remove();
|
||||
next.expire(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(this, 5 * 60 * 20, 5 * 60 * 20);
|
||||
|
||||
/*
|
||||
* For the sake of the lord, make sure they aren't using MMOItems Mana and
|
||||
* Stamina Addon...This should prevent a couple error reports produced by people
|
||||
@ -230,6 +214,19 @@ public class MMOCore extends LuminePlugin {
|
||||
DebugMode.enableActionBar();
|
||||
}
|
||||
|
||||
// Load quest module
|
||||
try {
|
||||
String questPluginName = UtilityMethods.enumName(getConfig().getString("quest-plugin"));
|
||||
PartyModuleType moduleType = PartyModuleType.valueOf(questPluginName);
|
||||
Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed");
|
||||
partyModule = moduleType.provideModule();
|
||||
} catch (RuntimeException exception) {
|
||||
getLogger().log(Level.WARNING, "Could not initialize quest module: " + exception.getMessage());
|
||||
partyModule = new MMOCorePartyModule();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Load party module
|
||||
try {
|
||||
String partyPluginName = UtilityMethods.enumName(getConfig().getString("party-plugin"));
|
||||
@ -241,6 +238,7 @@ public class MMOCore extends LuminePlugin {
|
||||
partyModule = new MMOCorePartyModule();
|
||||
}
|
||||
|
||||
|
||||
// Skill casting
|
||||
try {
|
||||
SkillCastingMode mode = SkillCastingMode.valueOf(UtilityMethods.enumName(getConfig().getString("skill-casting.mode")));
|
||||
@ -388,6 +386,7 @@ public class MMOCore extends LuminePlugin {
|
||||
|
||||
configManager = new ConfigManager();
|
||||
|
||||
statManager.initialize(clearBefore);
|
||||
if (clearBefore)
|
||||
MythicLib.plugin.getSkills().initialize(true);
|
||||
skillManager.initialize(clearBefore);
|
||||
@ -417,8 +416,6 @@ public class MMOCore extends LuminePlugin {
|
||||
if (getConfig().isConfigurationSection("action-bar"))
|
||||
actionBarManager.reload(getConfig().getConfigurationSection("action-bar"));
|
||||
|
||||
StatType.load();
|
||||
|
||||
if (clearBefore)
|
||||
PlayerData.getAll().forEach(PlayerData::update);
|
||||
}
|
||||
|
@ -1,73 +1,72 @@
|
||||
package net.Indyuce.mmocore.api;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerActivity;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class PlayerActionBar extends BukkitRunnable {
|
||||
boolean initialized = false;
|
||||
|
||||
private ActionBarConfig config;
|
||||
private DecimalFormat digit;
|
||||
|
||||
public void reload(ConfigurationSection cfg) {
|
||||
config = new ActionBarConfig(cfg);
|
||||
digit = MythicLib.plugin.getMMOConfig().newDecimalFormat(config.digit);
|
||||
boolean initialized = false;
|
||||
|
||||
if(!initialized && config.enabled) {
|
||||
runTaskTimer(MMOCore.plugin, 0, config.ticks);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public long getTimeOut() {
|
||||
return config.timeout;
|
||||
}
|
||||
private ActionBarConfig config;
|
||||
private DecimalFormat digit;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (PlayerData data : PlayerData.getAll())
|
||||
if (data.isOnline() && !data.getPlayer().isDead() && !data.isCasting() && data.getActivityTimeOut(PlayerActivity.ACTION_BAR_MESSAGE) == 0) {
|
||||
data.getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(MMOCore.plugin.placeholderParser.parse(data.getPlayer(),
|
||||
MythicLib.plugin.parseColors((data.getProfess().hasActionBar() ? data.getProfess().getActionBar() : config.format)
|
||||
.replace("{health}", digit.format(data.getPlayer().getHealth()))
|
||||
.replace("{max_health}", "" + StatType.MAX_HEALTH.format(data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()))
|
||||
.replace("{mana_icon}", data.getProfess().getManaDisplay().getIcon())
|
||||
.replace("{mana}", digit.format(data.getMana()))
|
||||
.replace("{max_mana}", "" + StatType.MAX_MANA.format(data.getStats().getStat(StatType.MAX_MANA)))
|
||||
.replace("{stamina}", digit.format(data.getStamina()))
|
||||
.replace("{max_stamina}", "" + StatType.MAX_STAMINA.format(data.getStats().getStat(StatType.MAX_STAMINA)))
|
||||
.replace("{stellium}", digit.format(data.getStellium()))
|
||||
.replace("{max_stellium}", "" + StatType.MAX_STELLIUM.format(data.getStats().getStat(StatType.MAX_STELLIUM)))
|
||||
.replace("{class}", data.getProfess().getName())
|
||||
.replace("{xp}", "" + data.getExperience())
|
||||
.replace("{armor}", "" + StatType.ARMOR.format(data.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).getValue()))
|
||||
.replace("{level}", "" + data.getLevel())
|
||||
.replace("{name}", data.getPlayer().getDisplayName())))));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ActionBarConfig {
|
||||
private final boolean enabled;
|
||||
private final int ticks, timeout;
|
||||
private final String digit, format;
|
||||
|
||||
private ActionBarConfig(ConfigurationSection config) {
|
||||
enabled = config.getBoolean("enabled", false);
|
||||
timeout = config.getInt("", 60);
|
||||
digit = config.getString("decimal", "0.#");
|
||||
ticks = config.getInt("ticks-to-update", 5);
|
||||
format = config.getString("format", "please format me :c");
|
||||
}
|
||||
}
|
||||
public void reload(ConfigurationSection cfg) {
|
||||
config = new ActionBarConfig(cfg);
|
||||
digit = MythicLib.plugin.getMMOConfig().newDecimalFormat(config.digit);
|
||||
|
||||
if (!initialized && config.enabled) {
|
||||
runTaskTimer(MMOCore.plugin, 0, config.ticks);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public long getTimeOut() {
|
||||
return config.timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (PlayerData data : PlayerData.getAll())
|
||||
if (data.isOnline() && !data.getPlayer().isDead() && !data.isCasting() && data.getActivityTimeOut(PlayerActivity.ACTION_BAR_MESSAGE) == 0) {
|
||||
data.getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(MMOCore.plugin.placeholderParser.parse(data.getPlayer(),
|
||||
MythicLib.plugin.parseColors((data.getProfess().hasActionBar() ? data.getProfess().getActionBar() : config.format)
|
||||
.replace("{health}", digit.format(data.getPlayer().getHealth()))
|
||||
.replace("{max_health}", StatInfo.valueOf("MAX_HEALTH").format(data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()))
|
||||
.replace("{mana_icon}", data.getProfess().getManaDisplay().getIcon())
|
||||
.replace("{mana}", digit.format(data.getMana()))
|
||||
.replace("{max_mana}", StatInfo.valueOf("MAX_MANA").format(data.getStats().getStat("MAX_MANA")))
|
||||
.replace("{stamina}", digit.format(data.getStamina()))
|
||||
.replace("{max_stamina}", StatInfo.valueOf("MAX_STAMINA").format(data.getStats().getStat("MAX_STAMINA")))
|
||||
.replace("{stellium}", digit.format(data.getStellium()))
|
||||
.replace("{max_stellium}", StatInfo.valueOf("MAX_STELLIUM").format(data.getStats().getStat("MAX_STELLIUM")))
|
||||
.replace("{class}", data.getProfess().getName())
|
||||
.replace("{xp}", "" + data.getExperience())
|
||||
.replace("{armor}", StatInfo.valueOf("ARMOR").format(data.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).getValue()))
|
||||
.replace("{level}", "" + data.getLevel())
|
||||
.replace("{name}", data.getPlayer().getDisplayName())))));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ActionBarConfig {
|
||||
private final boolean enabled;
|
||||
private final int ticks, timeout;
|
||||
private final String digit, format;
|
||||
|
||||
private ActionBarConfig(ConfigurationSection config) {
|
||||
enabled = config.getBoolean("enabled", false);
|
||||
timeout = config.getInt("", 60);
|
||||
digit = config.getString("decimal", "0.#");
|
||||
ticks = config.getInt("ticks-to-update", 5);
|
||||
format = config.getString("format", "please format me :c");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,14 +16,14 @@ public class PlayerExperienceGainEvent extends PlayerDataEvent implements Cancel
|
||||
private final Profession profession;
|
||||
private final EXPSource source;
|
||||
|
||||
private int experience;
|
||||
private double experience;
|
||||
private boolean cancelled;
|
||||
|
||||
public PlayerExperienceGainEvent(PlayerData player, int experience, EXPSource source) {
|
||||
public PlayerExperienceGainEvent(PlayerData player, double experience, EXPSource source) {
|
||||
this(player, null, experience, source);
|
||||
}
|
||||
|
||||
public PlayerExperienceGainEvent(PlayerData player, @Nullable Profession profession, int experience, EXPSource source) {
|
||||
public PlayerExperienceGainEvent(PlayerData player, @Nullable Profession profession, double experience, EXPSource source) {
|
||||
super(player);
|
||||
|
||||
this.profession = profession;
|
||||
@ -31,7 +31,7 @@ public class PlayerExperienceGainEvent extends PlayerDataEvent implements Cancel
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public int getExperience() {
|
||||
public double getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
|
@ -1,30 +1,19 @@
|
||||
package net.Indyuce.mmocore.api.load;
|
||||
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.*;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.*;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import net.Indyuce.mmocore.api.block.BlockType;
|
||||
import net.Indyuce.mmocore.api.block.SkullBlockType;
|
||||
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.BiomeCondition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.LevelCondition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.PermissionCondition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.WorldCondition;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.DropTableDropItem;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.GoldDropItem;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.NoteDropItem;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.VanillaDropItem;
|
||||
import net.Indyuce.mmocore.experience.source.BrewPotionExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.CraftItemExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.EnchantItemExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.FishItemExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.KillMobExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.MineBlockExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.PlaceBlockExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.RepairItemExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.SmeltItemExperienceSource;
|
||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||
import net.Indyuce.mmocore.api.quest.objective.ClickonObjective;
|
||||
import net.Indyuce.mmocore.api.quest.objective.GoToObjective;
|
||||
@ -44,127 +33,154 @@ import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
|
||||
public class DefaultMMOLoader extends MMOLoader {
|
||||
|
||||
@Override
|
||||
public Trigger loadTrigger(MMOLineConfig config) {
|
||||
if (config.getKey().equals("message"))
|
||||
return new MessageTrigger(config);
|
||||
@Override
|
||||
public Trigger loadTrigger(MMOLineConfig config) {
|
||||
if (config.getKey().equals("message"))
|
||||
return new MessageTrigger(config);
|
||||
|
||||
if (config.getKey().equals("sound") || config.getKey().equals("playsound"))
|
||||
return new SoundTrigger(config);
|
||||
if (config.getKey().equals("sound") || config.getKey().equals("playsound"))
|
||||
return new SoundTrigger(config);
|
||||
|
||||
if (config.getKey().equals("mana"))
|
||||
return new ManaTrigger(config);
|
||||
if (config.getKey().equals("mana"))
|
||||
return new ManaTrigger(config);
|
||||
|
||||
if (config.getKey().equals("stamina"))
|
||||
return new StaminaTrigger(config);
|
||||
|
||||
if (config.getKey().equals("stellium"))
|
||||
return new StelliumTrigger(config);
|
||||
if (config.getKey().equals("stamina"))
|
||||
return new StaminaTrigger(config);
|
||||
|
||||
if (config.getKey().equals("command"))
|
||||
return new CommandTrigger(config);
|
||||
if (config.getKey().equals("stellium"))
|
||||
return new StelliumTrigger(config);
|
||||
|
||||
if (config.getKey().equals("item") || config.getKey().equals("vanilla"))
|
||||
return new ItemTrigger(config);
|
||||
if (config.getKey().equals("command"))
|
||||
return new CommandTrigger(config);
|
||||
|
||||
if (config.getKey().equals("exp") || config.getKey().equals("experience"))
|
||||
return new ExperienceTrigger(config);
|
||||
if (config.getKey().equals("item") || config.getKey().equals("vanilla"))
|
||||
return new ItemTrigger(config);
|
||||
|
||||
return null;
|
||||
}
|
||||
if (config.getKey().equals("exp") || config.getKey().equals("experience"))
|
||||
return new ExperienceTrigger(config);
|
||||
|
||||
@Override
|
||||
public DropItem loadDropItem(MMOLineConfig config) {
|
||||
if (config.getKey().equals("droptable"))
|
||||
return new DropTableDropItem(config);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (config.getKey().equals("vanilla"))
|
||||
return new VanillaDropItem(config);
|
||||
@Override
|
||||
public DropItem loadDropItem(MMOLineConfig config) {
|
||||
if (config.getKey().equals("droptable"))
|
||||
return new DropTableDropItem(config);
|
||||
|
||||
if (config.getKey().equals("note"))
|
||||
return new NoteDropItem(config);
|
||||
if (config.getKey().equals("vanilla"))
|
||||
return new VanillaDropItem(config);
|
||||
|
||||
if (config.getKey().equals("gold") || config.getKey().equals("coin"))
|
||||
return new GoldDropItem(config);
|
||||
if (config.getKey().equals("note"))
|
||||
return new NoteDropItem(config);
|
||||
|
||||
return null;
|
||||
}
|
||||
if (config.getKey().equals("gold") || config.getKey().equals("coin"))
|
||||
return new GoldDropItem(config);
|
||||
|
||||
@Override
|
||||
public Objective loadObjective(MMOLineConfig config, ConfigurationSection section) {
|
||||
if (config.getKey().equals("goto"))
|
||||
return new GoToObjective(section, config);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (config.getKey().equals("mineblock"))
|
||||
return new MineBlockObjective(section, config);
|
||||
@Override
|
||||
public Objective loadObjective(MMOLineConfig config, ConfigurationSection section) {
|
||||
if (config.getKey().equals("goto"))
|
||||
return new GoToObjective(section, config);
|
||||
|
||||
if (config.getKey().equals("killmob"))
|
||||
return new KillMobObjective(section, config);
|
||||
if (config.getKey().equals("mineblock"))
|
||||
return new MineBlockObjective(section, config);
|
||||
|
||||
if (config.getKey().equals("clickon"))
|
||||
return new ClickonObjective(section, config);
|
||||
if (config.getKey().equals("killmob"))
|
||||
return new KillMobObjective(section, config);
|
||||
|
||||
return null;
|
||||
}
|
||||
if (config.getKey().equals("clickon"))
|
||||
return new ClickonObjective(section, config);
|
||||
|
||||
@Override
|
||||
public Condition loadCondition(MMOLineConfig config) {
|
||||
if (config.getKey().equals("world"))
|
||||
return new WorldCondition(config);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (config.getKey().equals("biome"))
|
||||
return new BiomeCondition(config);
|
||||
@Override
|
||||
public Condition loadCondition(MMOLineConfig config) {
|
||||
if (config.getKey().equals("distance"))
|
||||
return new DistanceCondition(config);
|
||||
|
||||
if (config.getKey().equals("level"))
|
||||
return new LevelCondition(config);
|
||||
|
||||
if (config.getKey().equals("permission"))
|
||||
return new PermissionCondition(config);
|
||||
if (config.getKey().equals("world"))
|
||||
return new WorldCondition(config);
|
||||
|
||||
return null;
|
||||
}
|
||||
if (config.getKey().equals("biome"))
|
||||
return new BiomeCondition(config);
|
||||
|
||||
@Override
|
||||
public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, ExperienceDispenser dispenser) {
|
||||
if (config.getKey().equals("fishitem"))
|
||||
return new FishItemExperienceSource(dispenser, config);
|
||||
if (config.getKey().equals("level"))
|
||||
return new LevelCondition(config);
|
||||
|
||||
if (config.getKey().equals("killmob"))
|
||||
return new KillMobExperienceSource(dispenser, config);
|
||||
if (config.getKey().equals("permission"))
|
||||
return new PermissionCondition(config);
|
||||
|
||||
if (config.getKey().equals("mineblock"))
|
||||
return new MineBlockExperienceSource(dispenser, config);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (config.getKey().equals("placeblock"))
|
||||
return new PlaceBlockExperienceSource(dispenser, config);
|
||||
@Override
|
||||
public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, ExperienceDispenser dispenser) {
|
||||
if (config.getKey().equals("resource"))
|
||||
return new ResourceExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("brewpotion"))
|
||||
return new BrewPotionExperienceSource(dispenser, config);
|
||||
if (config.getKey().equals("climb"))
|
||||
return new ClimbExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("smeltitem"))
|
||||
return new SmeltItemExperienceSource(dispenser, config);
|
||||
if (config.getKey().equals("damagedealt"))
|
||||
return new DamageDealtExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("enchantitem"))
|
||||
return new EnchantItemExperienceSource(dispenser, config);
|
||||
if (config.getKey().equals("damagetaken"))
|
||||
return new DamageTakenExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("repairitem"))
|
||||
return new RepairItemExperienceSource(dispenser, config);
|
||||
if (config.getKey().equals("move"))
|
||||
return new MoveExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("craftitem"))
|
||||
return new CraftItemExperienceSource(dispenser, config);
|
||||
if (config.getKey().equals("play"))
|
||||
return new PlayExperienceSource(dispenser, config);
|
||||
|
||||
return null;
|
||||
}
|
||||
if (config.getKey().equals("projectile"))
|
||||
return new ProjectileExperienceSource(dispenser, config);
|
||||
|
||||
@Override
|
||||
public BlockType loadBlockType(MMOLineConfig config) {
|
||||
if (config.getKey().equals("ride"))
|
||||
return new RideExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equalsIgnoreCase("vanilla"))
|
||||
return new VanillaBlockType(config);
|
||||
|
||||
if (config.getKey().equalsIgnoreCase("skull") || config.getKey().equals("head") || config.getKey().equals("playerhead"))
|
||||
return new SkullBlockType(config);
|
||||
if (config.getKey().equals("tame"))
|
||||
return new TameExperienceSource(dispenser, config);
|
||||
|
||||
return null;
|
||||
}
|
||||
if (config.getKey().equals("killmob"))
|
||||
return new KillMobExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("mineblock"))
|
||||
return new MineBlockExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("placeblock"))
|
||||
return new PlaceBlockExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("brewpotion"))
|
||||
return new BrewPotionExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("smeltitem"))
|
||||
return new SmeltItemExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("enchantitem"))
|
||||
return new EnchantItemExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("repairitem"))
|
||||
return new RepairItemExperienceSource(dispenser, config);
|
||||
|
||||
if (config.getKey().equals("craftitem"))
|
||||
return new CraftItemExperienceSource(dispenser, config);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockType loadBlockType(MMOLineConfig config) {
|
||||
|
||||
if (config.getKey().equalsIgnoreCase("vanilla"))
|
||||
return new VanillaBlockType(config);
|
||||
|
||||
if (config.getKey().equalsIgnoreCase("skull") || config.getKey().equals("head") || config.getKey().equals("playerhead"))
|
||||
return new SkullBlockType(config);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package net.Indyuce.mmocore.api.load;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.api.block.BlockType;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||
|
@ -1,15 +1,11 @@
|
||||
package net.Indyuce.mmocore.api.player;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.player.MMOPlayerData;
|
||||
import io.lumine.mythic.lib.player.TemporaryPlayerData;
|
||||
import io.lumine.mythic.lib.player.cooldown.CooldownMap;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigMessage;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.player.Unlockable;
|
||||
import net.Indyuce.mmocore.waypoint.CostType;
|
||||
import net.Indyuce.mmocore.waypoint.Waypoint;
|
||||
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
@ -21,11 +17,9 @@ import net.Indyuce.mmocore.api.player.profess.Subclass;
|
||||
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
||||
import net.Indyuce.mmocore.api.player.social.FriendRequest;
|
||||
import net.Indyuce.mmocore.api.player.stats.PlayerStats;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.quest.PlayerQuests;
|
||||
import net.Indyuce.mmocore.api.util.Closable;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.ExperienceTableClaimer;
|
||||
@ -33,11 +27,14 @@ import net.Indyuce.mmocore.experience.PlayerProfessions;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceItem;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import net.Indyuce.mmocore.guild.provided.Guild;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.party.AbstractParty;
|
||||
import net.Indyuce.mmocore.party.provided.Party;
|
||||
import net.Indyuce.mmocore.player.Unlockable;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
|
||||
import net.Indyuce.mmocore.waypoint.Waypoint;
|
||||
import net.Indyuce.mmocore.waypoint.WaypointOption;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
@ -70,7 +67,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
*/
|
||||
@Nullable
|
||||
private PlayerClass profess;
|
||||
private int level, experience, classPoints, skillPoints, attributePoints, attributeReallocationPoints;// skillReallocationPoints,
|
||||
private int level, classPoints, skillPoints, attributePoints, attributeReallocationPoints;// skillReallocationPoints,
|
||||
private double experience;
|
||||
private double mana, stamina, stellium;
|
||||
private Guild guild;
|
||||
private SkillCastingHandler skillCasting;
|
||||
@ -88,8 +86,9 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
|
||||
/**
|
||||
* Saves all the items that have been unlocked so far by
|
||||
* the player. This can be used by other plugins by
|
||||
* implementing the {@link Unlockable} interface
|
||||
* the player. This is used for:
|
||||
* - waypoints
|
||||
* - skills
|
||||
*
|
||||
* @see {@link Unlockable}
|
||||
*/
|
||||
@ -289,8 +288,11 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
return guild != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the item is unlocked by the player
|
||||
*/
|
||||
public boolean hasUnlocked(Unlockable unlockable) {
|
||||
throw new RuntimeException("Not implemented yet");
|
||||
return unlockedItems.contains(unlockable.getUnlockNamespacedKey());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -299,7 +301,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
* @return If the item was already unlocked when calling this method
|
||||
*/
|
||||
public boolean unlock(Unlockable unlockable) {
|
||||
throw new RuntimeException("Not implemented yet");
|
||||
return unlockedItems.add(unlockable.getUnlockNamespacedKey());
|
||||
}
|
||||
|
||||
public void setLevel(int level) {
|
||||
@ -320,7 +322,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
giveExperience(total, source);
|
||||
}
|
||||
|
||||
public void setExperience(int value) {
|
||||
public void setExperience(double value) {
|
||||
experience = Math.max(0, value);
|
||||
refreshVanillaExp();
|
||||
}
|
||||
@ -457,9 +459,9 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
* Teleports the player to a specific waypoint. This applies
|
||||
* the stellium waypoint cost and plays the teleport animation.
|
||||
*
|
||||
* @param waypoint Target waypoint
|
||||
* @param target Target waypoint
|
||||
*/
|
||||
public void warp(Waypoint waypoint, CostType costType) {
|
||||
public void warp(Waypoint target, double cost) {
|
||||
|
||||
/*
|
||||
* This cooldown is only used internally to make sure the player is not
|
||||
@ -467,8 +469,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
* player waypoints data
|
||||
*/
|
||||
setLastActivity(PlayerActivity.USE_WAYPOINT);
|
||||
|
||||
final double cost = waypoint.getCost(costType);
|
||||
giveStellium(-cost, PlayerResourceUpdateEvent.UpdateReason.USE_WAYPOINT);
|
||||
|
||||
new BukkitRunnable() {
|
||||
@ -491,7 +491,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
|
||||
MMOCore.plugin.configManager.getSimpleMessage("warping-comencing", "left", "" + ((120 - t) / 20)).send(getPlayer());
|
||||
if (t++ >= 100) {
|
||||
getPlayer().teleport(waypoint.getLocation());
|
||||
getPlayer().teleport(target.getLocation());
|
||||
getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 20, 1, false, false));
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_TELEPORT).playTo(getPlayer());
|
||||
cancel();
|
||||
@ -518,7 +518,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
* @param value Experience to give the player
|
||||
* @param source How the player earned experience
|
||||
*/
|
||||
public void giveExperience(int value, EXPSource source) {
|
||||
public void giveExperience(double value, EXPSource source) {
|
||||
giveExperience(value, source, null, true);
|
||||
}
|
||||
|
||||
@ -532,13 +532,16 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
* @param splitExp Should the exp be split among party members
|
||||
*/
|
||||
public void giveExperience(double value, EXPSource source, @Nullable Location hologramLocation, boolean splitExp) {
|
||||
if (value <= 0)
|
||||
return;
|
||||
|
||||
if (hasReachedMaxLevel()) {
|
||||
setExperience(0);
|
||||
return;
|
||||
}
|
||||
|
||||
value = MMOCore.plugin.boosterManager.calculateExp(null, value);
|
||||
value *= 1 + getStats().getStat(StatType.ADDITIONAL_EXPERIENCE) / 100;
|
||||
value *= 1 + getStats().getStat("ADDITIONAL_EXPERIENCE") / 100;
|
||||
|
||||
// Splitting exp through party members
|
||||
AbstractParty party = getParty();
|
||||
@ -549,7 +552,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
member.giveExperience(value, EXPSource.PARTY_SHARING, null, false);
|
||||
}
|
||||
|
||||
PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, (int) value, source);
|
||||
PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, value, source);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
@ -590,7 +593,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
refreshVanillaExp();
|
||||
}
|
||||
|
||||
public int getExperience() {
|
||||
public double getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
@ -611,7 +614,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
public void giveMana(double amount, PlayerResourceUpdateEvent.UpdateReason reason) {
|
||||
|
||||
// Avoid calling useless event
|
||||
double max = getStats().getStat(StatType.MAX_MANA);
|
||||
double max = getStats().getStat("MAX_MANA");
|
||||
double newest = Math.max(0, Math.min(mana + amount, max));
|
||||
if (mana == newest)
|
||||
return;
|
||||
@ -636,7 +639,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
public void giveStamina(double amount, PlayerResourceUpdateEvent.UpdateReason reason) {
|
||||
|
||||
// Avoid calling useless event
|
||||
double max = getStats().getStat(StatType.MAX_STAMINA);
|
||||
double max = getStats().getStat("MAX_STAMINA");
|
||||
double newest = Math.max(0, Math.min(stamina + amount, max));
|
||||
if (stamina == newest)
|
||||
return;
|
||||
@ -661,7 +664,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
public void giveStellium(double amount, PlayerResourceUpdateEvent.UpdateReason reason) {
|
||||
|
||||
// Avoid calling useless event
|
||||
double max = getStats().getStat(StatType.MAX_STELLIUM);
|
||||
double max = getStats().getStat("MAX_STELLIUM");
|
||||
double newest = Math.max(0, Math.min(stellium + amount, max));
|
||||
if (stellium == newest)
|
||||
return;
|
||||
@ -696,15 +699,15 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
||||
}
|
||||
|
||||
public void setMana(double amount) {
|
||||
mana = Math.max(0, Math.min(amount, getStats().getStat(StatType.MAX_MANA)));
|
||||
mana = Math.max(0, Math.min(amount, getStats().getStat("MAX_MANA")));
|
||||
}
|
||||
|
||||
public void setStamina(double amount) {
|
||||
stamina = Math.max(0, Math.min(amount, getStats().getStat(StatType.MAX_STAMINA)));
|
||||
stamina = Math.max(0, Math.min(amount, getStats().getStat("MAX_STAMINA")));
|
||||
}
|
||||
|
||||
public void setStellium(double amount) {
|
||||
stellium = Math.max(0, Math.min(amount, getStats().getStat(StatType.MAX_STELLIUM)));
|
||||
stellium = Math.max(0, Math.min(amount, getStats().getStat("MAX_STELLIUM")));
|
||||
}
|
||||
|
||||
public boolean isFullyLoaded() {
|
||||
|
@ -12,6 +12,7 @@ import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Objects;
|
||||
|
||||
public class AttributeModifier extends PlayerModifier {
|
||||
private final String attribute;
|
||||
@ -74,9 +75,10 @@ public class AttributeModifier extends PlayerModifier {
|
||||
public AttributeModifier(ConfigObject object) {
|
||||
super(object.getString("key"), EquipmentSlot.OTHER, ModifierSource.OTHER);
|
||||
|
||||
String str = Objects.requireNonNull(object.getString("value"));
|
||||
type = str.toCharArray()[str.length() - 1] == '%' ? ModifierType.RELATIVE : ModifierType.FLAT;
|
||||
value = Double.parseDouble(type == ModifierType.RELATIVE ? str.substring(0, str.length() - 1) : str);
|
||||
this.attribute = object.getString("attribute");
|
||||
this.value = object.getDouble("value");
|
||||
type = object.getBoolean("multiplicative", false) ? ModifierType.RELATIVE : ModifierType.FLAT;
|
||||
}
|
||||
|
||||
public String getAttribute() {
|
||||
|
@ -3,57 +3,109 @@ package net.Indyuce.mmocore.api.player.attribute;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class PlayerAttribute {
|
||||
private final String id, name;
|
||||
private final int max;
|
||||
public class PlayerAttribute implements ExperienceObject {
|
||||
private final String id, name;
|
||||
private final int max;
|
||||
private final ExperienceTable expTable;
|
||||
|
||||
/**
|
||||
* Used to store stats using StatType, but attributes also need to access
|
||||
* non basic MMOCore stats hence the string maps keys
|
||||
*/
|
||||
private final Set<StatModifier> buffs = new HashSet<>();
|
||||
/**
|
||||
* All buffs granted by an attribute. These are normalized and
|
||||
* must be multiplied by the player level first
|
||||
*/
|
||||
private final Set<StatModifier> buffs = new HashSet<>();
|
||||
|
||||
public PlayerAttribute(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Could not load config");
|
||||
id = config.getName().toLowerCase().replace("_", "-").replace(" ", "-");
|
||||
public PlayerAttribute(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Could not load config");
|
||||
id = config.getName().toLowerCase().replace("_", "-").replace(" ", "-");
|
||||
|
||||
name = MythicLib.plugin.parseColors(config.getString("name", "Attribute"));
|
||||
max = config.contains("max-points") ? Math.max(1, config.getInt("max-points")) : 0;
|
||||
name = MythicLib.plugin.parseColors(config.getString("name", "Attribute"));
|
||||
max = config.contains("max-points") ? Math.max(1, config.getInt("max-points")) : 0;
|
||||
|
||||
if (config.contains("buff"))
|
||||
for (String key : config.getConfigurationSection("buff").getKeys(false))
|
||||
try {
|
||||
String stat = key.toUpperCase().replace("-", "_").replace(" ", "_");
|
||||
buffs.add(new StatModifier("attribute." + id, stat, config.getString("buff." + key)));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not load buff '" + key + "' from attribute '" + id + "': " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
if (config.contains("buff"))
|
||||
for (String key : config.getConfigurationSection("buff").getKeys(false))
|
||||
try {
|
||||
String stat = key.toUpperCase().replace("-", "_").replace(" ", "_");
|
||||
buffs.add(new StatModifier("attribute." + id, stat, config.getString("buff." + key)));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not load buff '" + key + "' from attribute '" + id + "': " + exception.getMessage());
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
// Load exp table
|
||||
ExperienceTable expTable = null;
|
||||
if (config.contains("exp-table"))
|
||||
try {
|
||||
expTable = MMOCore.plugin.experience.loadExperienceTable(config.get("exp-table"));
|
||||
} catch (RuntimeException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load exp table from class '" + id + "': " + exception.getMessage());
|
||||
}
|
||||
this.expTable = expTable;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean hasMax() {
|
||||
return max > 0;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
public boolean hasMax() {
|
||||
return max > 0;
|
||||
}
|
||||
|
||||
public Set<StatModifier> getBuffs() {
|
||||
return buffs;
|
||||
}
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public Set<StatModifier> getBuffs() {
|
||||
return buffs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "attribute:" + getId().replace("-", "_");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ExperienceTable getExperienceTable() {
|
||||
return Objects.requireNonNull(expTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExperienceTable() {
|
||||
return expTable != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ExpCurve getExpCurve() {
|
||||
throw new RuntimeException("Attributes don't have experience");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, @NotNull EXPSource source) {
|
||||
throw new RuntimeException("Attributes don't have experience");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldHandle(PlayerData playerData) {
|
||||
throw new RuntimeException("Attributes don't have experience");
|
||||
}
|
||||
}
|
||||
|
@ -129,8 +129,17 @@ public class PlayerAttributes {
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds X points to the base of the player attribute AND applies
|
||||
* the attribute experience table.
|
||||
*
|
||||
* @param value Amount of attribute points spent in the attribute
|
||||
*/
|
||||
public void addBase(int value) {
|
||||
PlayerAttribute attribute = MMOCore.plugin.attributeManager.get(id);
|
||||
setBase(spent + value);
|
||||
if (attribute.hasExperienceTable())
|
||||
attribute.getExperienceTable().claim(data, spent, attribute);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -159,14 +168,14 @@ public class PlayerAttributes {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public void addModifier(String key, double value) {
|
||||
addModifier(new AttributeModifier(key, id, value, ModifierType.FLAT, EquipmentSlot.OTHER, ModifierSource.OTHER));
|
||||
public AttributeModifier addModifier(String key, double value) {
|
||||
return addModifier(new AttributeModifier(key, id, value, ModifierType.FLAT, EquipmentSlot.OTHER, ModifierSource.OTHER));
|
||||
}
|
||||
|
||||
public void addModifier(AttributeModifier modifier) {
|
||||
map.put(modifier.getKey(), modifier);
|
||||
|
||||
public AttributeModifier addModifier(AttributeModifier modifier) {
|
||||
AttributeModifier mod = map.put(modifier.getKey(), modifier);
|
||||
update();
|
||||
return mod;
|
||||
}
|
||||
|
||||
public Set<String> getKeys() {
|
||||
@ -177,7 +186,7 @@ public class PlayerAttributes {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
public void removeModifier(String key) {
|
||||
public AttributeModifier removeModifier(String key) {
|
||||
AttributeModifier mod = map.remove(key);
|
||||
|
||||
/*
|
||||
@ -190,12 +199,13 @@ public class PlayerAttributes {
|
||||
((Closeable) mod).close();
|
||||
update();
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
PlayerAttribute attribute = MMOCore.plugin.attributeManager.get(id);
|
||||
PlayerAttribute attr = MMOCore.plugin.attributeManager.get(id);
|
||||
int total = getTotal();
|
||||
attribute.getBuffs().forEach(buff -> buff.multiply(total).register(data.getMMOPlayerData()));
|
||||
attr.getBuffs().forEach(buff -> buff.multiply(total).register(data.getMMOPlayerData()));
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -13,17 +13,17 @@ import net.Indyuce.mmocore.api.player.profess.event.EventTrigger;
|
||||
import net.Indyuce.mmocore.api.player.profess.resource.ManaDisplayOptions;
|
||||
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
||||
import net.Indyuce.mmocore.api.player.profess.resource.ResourceRegeneration;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.CastingParticle;
|
||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.CastingParticle;
|
||||
import net.Indyuce.mmocore.player.playerclass.ClassTrigger;
|
||||
import net.Indyuce.mmocore.player.playerclass.ClassTriggerType;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
@ -51,7 +51,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
||||
private final ExpCurve expCurve;
|
||||
private final ExperienceTable expTable;
|
||||
|
||||
private final Map<StatType, LinearValue> stats = new HashMap<>();
|
||||
private final Map<String, LinearValue> stats = new HashMap<>();
|
||||
private final Map<String, ClassSkill> skills = new LinkedHashMap<>();
|
||||
private final List<Subclass> subclasses = new ArrayList<>();
|
||||
|
||||
@ -124,7 +124,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
||||
if (config.contains("attributes"))
|
||||
for (String key : config.getConfigurationSection("attributes").getKeys(false))
|
||||
try {
|
||||
stats.put(StatType.valueOf(key.toUpperCase().replace("-", "_")),
|
||||
stats.put(UtilityMethods.enumName(key),
|
||||
new LinearValue(config.getConfigurationSection("attributes." + key)));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load stat info '" + key + "' from class '"
|
||||
@ -298,6 +298,18 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
||||
return options.containsKey(option) ? options.get(option) : option.getDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) {
|
||||
hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null
|
||||
: hologramLocation;
|
||||
playerData.giveExperience(experience, source, hologramLocation, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldHandle(PlayerData playerData) {
|
||||
return equals(playerData.getProfess());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public ClassTrigger getClassTrigger(ClassTriggerType type) {
|
||||
@ -319,16 +331,11 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
||||
return eventTriggers.get(name);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setStat(StatType type, double base, double perLevel) {
|
||||
setStat(type, new LinearValue(base, perLevel));
|
||||
public void setDefaultStatFormula(String type, LinearValue value) {
|
||||
stats.put(UtilityMethods.enumName(type), value);
|
||||
}
|
||||
|
||||
public void setStat(StatType type, LinearValue value) {
|
||||
stats.put(type, value);
|
||||
}
|
||||
|
||||
public double calculateStat(StatType stat, int level) {
|
||||
public double calculateStat(String stat, int level) {
|
||||
return getStatInfo(stat).calculate(level);
|
||||
}
|
||||
|
||||
@ -384,8 +391,15 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
||||
return skills.values();
|
||||
}
|
||||
|
||||
private LinearValue getStatInfo(StatType type) {
|
||||
return stats.containsKey(type) ? stats.get(type) : type.getDefault();
|
||||
@NotNull
|
||||
private LinearValue getStatInfo(String stat) {
|
||||
LinearValue found = stats.get(stat);
|
||||
return found == null ? StatInfo.valueOf(stat).getDefaultFormula() : found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof PlayerClass && ((PlayerClass) obj).id.equals(id);
|
||||
}
|
||||
|
||||
public String getActionBar() {
|
||||
@ -395,29 +409,4 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
||||
public boolean hasActionBar() {
|
||||
return actionBarFormat != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) {
|
||||
hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null
|
||||
: hologramLocation == null ? getPlayerLocation(playerData) : hologramLocation;
|
||||
playerData.giveExperience(experience, source, hologramLocation, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldHandle(PlayerData playerData) {
|
||||
return equals(playerData.getProfess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PlayerClass that = (PlayerClass) o;
|
||||
return id.equals(that.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,14 @@ import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import net.Indyuce.mmocore.manager.data.PlayerDataManager.DefaultPlayerData;
|
||||
|
||||
public class SavedClassInformation {
|
||||
private final int level, experience, skillPoints, attributePoints, attributeReallocationPoints;
|
||||
private final int level, skillPoints, attributePoints, attributeReallocationPoints;
|
||||
private final double experience;
|
||||
private final Map<String, Integer> attributes;
|
||||
private final Map<String, Integer> skills;
|
||||
|
||||
public SavedClassInformation(ConfigurationSection config) {
|
||||
level = config.getInt("level");
|
||||
experience = config.getInt("experience");
|
||||
experience = config.getDouble("experience");
|
||||
skillPoints = config.getInt("skill-points");
|
||||
attributePoints = config.getInt("attribute-points");
|
||||
attributeReallocationPoints = config.getInt("attribute-realloc-points");
|
||||
@ -38,7 +39,7 @@ public class SavedClassInformation {
|
||||
|
||||
public SavedClassInformation(JsonObject json) {
|
||||
level = json.get("level").getAsInt();
|
||||
experience = json.get("experience").getAsInt();
|
||||
experience = json.get("experience").getAsDouble();
|
||||
skillPoints = json.get("skill-points").getAsInt();
|
||||
attributePoints = json.get("attribute-points").getAsInt();
|
||||
attributeReallocationPoints = json.get("attribute-realloc-points").getAsInt();
|
||||
@ -63,11 +64,11 @@ public class SavedClassInformation {
|
||||
this(data.getLevel(), 0, data.getSkillPoints(), data.getAttributePoints(), data.getAttrReallocPoints());
|
||||
}
|
||||
|
||||
public SavedClassInformation(int level, int experience, int skillPoints, int attributePoints, int attributeReallocationPoints) {
|
||||
public SavedClassInformation(int level, double experience, int skillPoints, int attributePoints, int attributeReallocationPoints) {
|
||||
this(level, experience, skillPoints, attributePoints, attributeReallocationPoints, new HashMap<>(), new HashMap<>());
|
||||
}
|
||||
|
||||
private SavedClassInformation(int level, int experience, int skillPoints, int attributePoints, int attributeReallocationPoints,
|
||||
private SavedClassInformation(int level, double experience, int skillPoints, int attributePoints, int attributeReallocationPoints,
|
||||
Map<String, Integer> attributes, Map<String, Integer> skills) {
|
||||
this.level = level;
|
||||
this.experience = experience;
|
||||
@ -82,7 +83,7 @@ public class SavedClassInformation {
|
||||
return level;
|
||||
}
|
||||
|
||||
public int getExperience() {
|
||||
public double getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package net.Indyuce.mmocore.api.player.profess.resource;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.ClassOption;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.quest.trigger.ManaTrigger;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
|
||||
@ -20,27 +19,27 @@ public enum PlayerResource {
|
||||
(data, amount) -> data.getPlayer().setHealth(amount)),
|
||||
|
||||
MANA(PlayerData::getMana,
|
||||
data -> data.getStats().getStat(StatType.MAX_MANA),
|
||||
data -> data.getStats().getStat("MAX_MANA"),
|
||||
(data, amount) -> data.giveMana(amount, PlayerResourceUpdateEvent.UpdateReason.REGENERATION),
|
||||
(data, amount) -> data.giveMana(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
|
||||
(data, amount) -> data.giveMana(-amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
|
||||
(data, amount) -> data.setMana(amount)),
|
||||
|
||||
STAMINA(PlayerData::getStamina,
|
||||
data -> data.getStats().getStat(StatType.MAX_STAMINA),
|
||||
data -> data.getStats().getStat("MAX_STAMINA"),
|
||||
(data, amount) -> data.giveStamina(amount, PlayerResourceUpdateEvent.UpdateReason.REGENERATION),
|
||||
(data, amount) -> data.giveStamina(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
|
||||
(data, amount) -> data.giveStamina(-amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
|
||||
(data, amount) -> data.setStamina(amount)),
|
||||
|
||||
STELLIUM(PlayerData::getStellium,
|
||||
data -> data.getStats().getStat(StatType.MAX_STELLIUM),
|
||||
data -> data.getStats().getStat("MAX_STELLIUM"),
|
||||
(data, amount) -> data.giveStellium(amount, PlayerResourceUpdateEvent.UpdateReason.REGENERATION),
|
||||
(data, amount) -> data.giveStellium(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
|
||||
(data, amount) -> data.giveStellium(-amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
|
||||
(data, amount) -> data.setStellium(amount));
|
||||
|
||||
private final StatType regenStat, maxRegenStat;
|
||||
private final String regenStat, maxRegenStat;
|
||||
private final ClassOption offCombatRegen;
|
||||
private final Function<PlayerData, Double> current, max;
|
||||
private final BiConsumer<PlayerData, Double> regen;
|
||||
@ -54,8 +53,8 @@ public enum PlayerResource {
|
||||
BiConsumer<PlayerData, Double> give,
|
||||
BiConsumer<PlayerData, Double> take,
|
||||
BiConsumer<PlayerData, Double> set) {
|
||||
this.regenStat = StatType.valueOf(name() + "_REGENERATION");
|
||||
this.maxRegenStat = StatType.valueOf("MAX_" + name() + "_REGENERATION");
|
||||
this.regenStat = name() + "_REGENERATION";
|
||||
this.maxRegenStat = "MAX_" + name() + "_REGENERATION";
|
||||
this.offCombatRegen = ClassOption.valueOf("OFF_COMBAT_" + name() + "_REGEN");
|
||||
this.current = current;
|
||||
this.max = max;
|
||||
@ -68,14 +67,14 @@ public enum PlayerResource {
|
||||
/**
|
||||
* @return Stat which corresponds to flat resource regeneration
|
||||
*/
|
||||
public StatType getRegenStat() {
|
||||
public String getRegenStat() {
|
||||
return regenStat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stat which corresponds to resource regeneration scaling with the player's max health
|
||||
*/
|
||||
public StatType getMaxRegenStat() {
|
||||
public String getMaxRegenStat() {
|
||||
return maxRegenStat;
|
||||
}
|
||||
|
||||
|
@ -8,17 +8,14 @@ import io.lumine.mythic.lib.player.modifier.ModifierSource;
|
||||
import io.lumine.mythic.lib.player.modifier.ModifierType;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class PlayerStats {
|
||||
private final PlayerData data;
|
||||
|
||||
/**
|
||||
* Utilclass to easily manipulate the MMOLib stat map
|
||||
* Util class to easily manipulate the MMOLib stat map
|
||||
*
|
||||
* @param data Playerdata
|
||||
*/
|
||||
@ -34,6 +31,7 @@ public class PlayerStats {
|
||||
return data.getMMOPlayerData().getStatMap();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public StatInstance getInstance(StatType stat) {
|
||||
return getMap().getInstance(stat.name());
|
||||
}
|
||||
@ -42,35 +40,26 @@ public class PlayerStats {
|
||||
return getMap().getInstance(stat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for stat type enum to have dynamic professions.
|
||||
* ID FORMAT: STAT_TYPE_HERE_PROFESSION_HERE
|
||||
*
|
||||
* @param type the type of stat
|
||||
* @param profession the stat's specific permission
|
||||
* @return instance of found stat
|
||||
* @author Ehhthan
|
||||
*/
|
||||
@NotNull
|
||||
public StatInstance getInstance(StatType type, @Nullable Profession profession) {
|
||||
if (profession == null)
|
||||
return getInstance(type);
|
||||
else {
|
||||
String id = (type.name() + '_' + profession.getId()).replace('-', '_').replace(' ', '_').toUpperCase(Locale.ROOT);
|
||||
return getInstance(id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* applies relative attributes on the base stat too
|
||||
*/
|
||||
public double getStat(StatType stat) {
|
||||
public double getStat(String stat) {
|
||||
return getInstance(stat).getTotal();
|
||||
}
|
||||
|
||||
public double getBase(StatType stat) {
|
||||
return data.getProfess().calculateStat(stat,
|
||||
stat.hasProfession() ? data.getCollectionSkills().getLevel(stat.getProfession()) : data.getLevel());
|
||||
/**
|
||||
* MMOCore base stat value differs from the on in MythicLib.
|
||||
* <p>
|
||||
* MythicLib: the base stat value is only defined for stats
|
||||
* which are based on vanilla player attributes. It corresponds
|
||||
* to the stat amount any player has with NO attribute modifier whatsoever.
|
||||
* <p>
|
||||
* MMOCore: the base stat value corresponds to the stat amount
|
||||
* the player CLASS grants. It can be similar or equal to the one
|
||||
* in MMOCore but it really is completely different.
|
||||
*
|
||||
* @return MMOCore base stat value
|
||||
*/
|
||||
public double getBase(String stat) {
|
||||
Profession profession = StatInfo.valueOf(stat).profession;
|
||||
return data.getProfess().calculateStat(stat, profession == null ? data.getLevel() : data.getCollectionSkills().getLevel(profession));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,7 +70,7 @@ public class PlayerStats {
|
||||
* see {@link PlayerData#update()} for more info
|
||||
*/
|
||||
public synchronized void updateStats() {
|
||||
for (StatType stat : StatType.values()) {
|
||||
for (StatType stat : StatType.values()) { // TODO fix
|
||||
StatInstance instance = getMap().getInstance(stat.name());
|
||||
StatInstance.ModifierPacket packet = instance.newPacket();
|
||||
|
||||
@ -89,7 +78,7 @@ public class PlayerStats {
|
||||
packet.removeIf(str -> str.equals("mmocoreClass"));
|
||||
|
||||
// Add newest one
|
||||
double total = getBase(stat) - instance.getBase();
|
||||
double total = getBase(stat.name()) - instance.getBase();
|
||||
if (total != 0)
|
||||
packet.addModifier(new StatModifier("mmocoreClass", stat.name(), total, ModifierType.FLAT, EquipmentSlot.OTHER, ModifierSource.OTHER));
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
package net.Indyuce.mmocore.api.player.stats;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Objects;
|
||||
|
||||
@Deprecated
|
||||
public enum StatType {
|
||||
|
||||
// Vanilla stats
|
||||
@ -61,6 +61,7 @@ public enum StatType {
|
||||
// Utility
|
||||
ADDITIONAL_EXPERIENCE,
|
||||
COOLDOWN_REDUCTION,
|
||||
CHANCE,
|
||||
|
||||
// Damage-type based stats
|
||||
MAGIC_DAMAGE,
|
||||
@ -86,17 +87,17 @@ public enum StatType {
|
||||
/**
|
||||
* Reduces amount of tugs needed to fish
|
||||
*/
|
||||
FISHING_STRENGTH("fishing"),
|
||||
FISHING_STRENGTH,
|
||||
|
||||
/**
|
||||
* Chance of instant success when fishing
|
||||
*/
|
||||
CRITICAL_FISHING_CHANCE("fishing"),
|
||||
CRITICAL_FISHING_CHANCE,
|
||||
|
||||
/**
|
||||
* Chance of crit fishing failure
|
||||
*/
|
||||
CRITICAL_FISHING_FAILURE_CHANCE("fishing"),
|
||||
CRITICAL_FISHING_FAILURE_CHANCE,
|
||||
|
||||
/**
|
||||
* Chance of dropping more minerals when mining.
|
||||
@ -113,49 +114,35 @@ public enum StatType {
|
||||
*/
|
||||
LUCK_OF_THE_FIELD;
|
||||
|
||||
private String profession;
|
||||
|
||||
private LinearValue defaultInfo;
|
||||
private DecimalFormat format;
|
||||
|
||||
StatType() {
|
||||
// Completely custom stat
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
StatType(String profession) {
|
||||
this.profession = profession;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getProfession() {
|
||||
return profession;
|
||||
return findProfession().getId();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public Profession findProfession() {
|
||||
return MMOCore.plugin.professionManager.get(profession);
|
||||
return StatInfo.valueOf(name()).profession;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean hasProfession() {
|
||||
return profession != null;
|
||||
return findProfession() != null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@NotNull
|
||||
public LinearValue getDefault() {
|
||||
return defaultInfo;
|
||||
return StatInfo.valueOf(name()).getDefaultFormula();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean matches(Profession profession) {
|
||||
return this.profession != null && this.profession.equals(profession.getId());
|
||||
return Objects.equals(findProfession(), profession);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String format(double value) {
|
||||
return format.format(value);
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
FileConfiguration config = new ConfigFile("stats").getConfig();
|
||||
for (StatType stat : values()) {
|
||||
stat.defaultInfo = config.contains("default." + stat.name()) ? new LinearValue(config.getConfigurationSection("default." + stat.name())) : new LinearValue(0, 0);
|
||||
stat.format = MythicLib.plugin.getMMOConfig().newDecimalFormat(config.contains("decimal-format." + stat.name()) ? config.getString("decimal-format." + stat.name()) : "0.#");
|
||||
}
|
||||
return StatInfo.valueOf(name()).format(value);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.Indyuce.mmocore.api.quest.trigger;
|
||||
|
||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.SimpleExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
@ -9,17 +10,14 @@ import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ExperienceTrigger extends Trigger {
|
||||
@NotNull
|
||||
private final RandomAmount amount;
|
||||
@NotNull
|
||||
private final EXPSource source;
|
||||
@Nullable
|
||||
private final ExperienceObject expObject;
|
||||
@NotNull
|
||||
private final ExperienceDispenser dispenser;
|
||||
|
||||
public ExperienceTrigger(MMOLineConfig config) {
|
||||
super(config);
|
||||
@ -29,15 +27,15 @@ public class ExperienceTrigger extends Trigger {
|
||||
if (config.contains("profession")) {
|
||||
String id = config.getString("profession").toLowerCase().replace("_", "-");
|
||||
Validate.isTrue(MMOCore.plugin.professionManager.has(id), "Could not find profession");
|
||||
expObject = MMOCore.plugin.professionManager.get(id);
|
||||
dispenser = MMOCore.plugin.professionManager.get(id);
|
||||
} else
|
||||
expObject = null;
|
||||
dispenser = new SimpleExperienceObject();
|
||||
amount = new RandomAmount(config.getString("amount"));
|
||||
source = config.contains("source") ? EXPSource.valueOf(config.getString("source").toUpperCase()) : EXPSource.QUEST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(PlayerData player) {
|
||||
Objects.requireNonNullElse(expObject, player.getProfess()).giveExperience(player, amount.calculateInt(), null, source);
|
||||
dispenser.giveExperience(player, amount.calculateInt(), null, source);
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ public class MMOCoreUtils {
|
||||
*/
|
||||
public static void decreaseDurability(Player player, EquipmentSlot slot, int damage) {
|
||||
ItemStack item = player.getInventory().getItem(slot);
|
||||
if (!item.hasItemMeta() || !(item.getItemMeta() instanceof Damageable) || item.getItemMeta().isUnbreakable())
|
||||
if (item == null || item.getType().getMaxDurability() == 0 || !item.hasItemMeta() || !(item.getItemMeta() instanceof Damageable) || item.getItemMeta().isUnbreakable())
|
||||
return;
|
||||
|
||||
PlayerItemDamageEvent event = new PlayerItemDamageEvent(player, item, damage);
|
||||
|
@ -110,4 +110,16 @@ public class LinearValue {
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LinearValue{" +
|
||||
"base=" + base +
|
||||
", perLevel=" + perLevel +
|
||||
", min=" + min +
|
||||
", max=" + max +
|
||||
", hasmin=" + hasmin +
|
||||
", hasmax=" + hasmax +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ public class ExperienceCommandTreeNode extends CommandTreeNode {
|
||||
int amount;
|
||||
try {
|
||||
amount = Integer.parseInt(args[5]);
|
||||
Validate.isTrue(amount > 0);
|
||||
} catch (NumberFormatException exception) {
|
||||
Validate.isTrue(amount >= 0);
|
||||
} catch (RuntimeException exception) {
|
||||
sender.sendMessage(ChatColor.RED + args[5] + " is not a valid number.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package net.Indyuce.mmocore.command.rpg.debug;
|
||||
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.api.stat.StatInstance;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
|
||||
import io.lumine.mythic.lib.command.api.CommandTreeNode;
|
||||
import io.lumine.mythic.lib.command.api.Parameter;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -15,10 +15,7 @@ public class StatModifiersCommandTreeNode extends CommandTreeNode {
|
||||
public StatModifiersCommandTreeNode(CommandTreeNode parent) {
|
||||
super(parent, "statmods");
|
||||
|
||||
addParameter(new Parameter("<stat>", (explorer, list) -> {
|
||||
for (StatType stat : StatType.values())
|
||||
list.add(stat.name());
|
||||
}));
|
||||
addParameter(new Parameter("<stat>", (explorer, list) -> list.add("STAT_ID")));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -32,15 +29,7 @@ public class StatModifiersCommandTreeNode extends CommandTreeNode {
|
||||
}
|
||||
PlayerData data = PlayerData.get((Player) sender);
|
||||
|
||||
StatType stat;
|
||||
try {
|
||||
stat = StatType.valueOf(args[2].toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
sender.sendMessage(ChatColor.RED + "Could not find stat: " + args[2] + ".");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
StatInstance instance = data.getStats().getInstance(stat);
|
||||
StatInstance instance = data.getStats().getInstance(UtilityMethods.enumName(args[2]));
|
||||
sender.sendMessage("Stat Modifiers (" + instance.getKeys().size() + "):");
|
||||
for (String key : instance.getKeys()) {
|
||||
StatModifier mod = instance.getModifier(key);
|
||||
|
@ -1,51 +1,36 @@
|
||||
package net.Indyuce.mmocore.command.rpg.debug;
|
||||
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.command.api.CommandTreeNode;
|
||||
import io.lumine.mythic.lib.command.api.Parameter;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import io.lumine.mythic.lib.command.api.CommandTreeNode;
|
||||
import io.lumine.mythic.lib.command.api.Parameter;
|
||||
|
||||
public class StatValueCommandTreeNode extends CommandTreeNode {
|
||||
public StatValueCommandTreeNode(CommandTreeNode parent) {
|
||||
super(parent, "statvalue");
|
||||
public StatValueCommandTreeNode(CommandTreeNode parent) {
|
||||
super(parent, "statvalue");
|
||||
|
||||
addParameter(new Parameter("<stat>", (explorer, list) -> {
|
||||
for (StatType stat : StatType.values())
|
||||
list.add(stat.name());
|
||||
}));
|
||||
addParameter(new Parameter("(formatted)", (explorer, list) -> list.add("true")));
|
||||
}
|
||||
addParameter(new Parameter("<stat>", (explorer, list) -> list.add("STAT_ID")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandSender sender, String[] args) {
|
||||
if (args.length < 3)
|
||||
return CommandResult.THROW_USAGE;
|
||||
@Override
|
||||
public CommandResult execute(CommandSender sender, String[] args) {
|
||||
if (args.length < 3)
|
||||
return CommandResult.THROW_USAGE;
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.RED + "This command can only be used by a player.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
PlayerData data = PlayerData.get((Player) sender);
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.RED + "This command can only be used by a player.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
PlayerData data = PlayerData.get((Player) sender);
|
||||
|
||||
StatType stat;
|
||||
try {
|
||||
stat = StatType.valueOf(args[2].toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
sender.sendMessage(ChatColor.RED + "Could not find stat: " + args[2] + ".");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
StatInfo stat = StatInfo.valueOf(UtilityMethods.enumName(args[2]));
|
||||
sender.sendMessage(DebugCommandTreeNode.commandPrefix + "Stat Value (" + ChatColor.BLUE + stat.name + ChatColor.WHITE + "): "
|
||||
+ ChatColor.GREEN + data.getStats().getStat(stat.name));
|
||||
|
||||
if (args.length > 3 && args[3].equals("true"))
|
||||
sender.sendMessage(DebugCommandTreeNode.commandPrefix + "Stat Value (" + ChatColor.BLUE + stat.name() + ChatColor.WHITE + "): "
|
||||
+ ChatColor.GREEN + stat.format(data.getStats().getStat(stat)) + ChatColor.WHITE + " *");
|
||||
else
|
||||
sender.sendMessage(DebugCommandTreeNode.commandPrefix + "Stat Value (" + ChatColor.BLUE + stat.name() + ChatColor.WHITE + "): "
|
||||
+ ChatColor.GREEN + data.getStats().getStat(stat));
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package net.Indyuce.mmocore.command.rpg.waypoint;
|
||||
|
||||
import io.lumine.mythic.lib.api.util.SmartGive;
|
||||
import io.lumine.mythic.lib.command.api.CommandTreeNode;
|
||||
import io.lumine.mythic.lib.command.api.Parameter;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.util.item.WaypointBookBuilder;
|
||||
import net.Indyuce.mmocore.waypoint.Waypoint;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ItemCommandTreeNode extends CommandTreeNode {
|
||||
public ItemCommandTreeNode(CommandTreeNode parent) {
|
||||
super(parent, "item");
|
||||
|
||||
addParameter(new Parameter("<waypoint>", (explorer, list) -> MMOCore.plugin.waypointManager.getAll().forEach(way -> list.add(way.getId()))));
|
||||
addParameter(Parameter.PLAYER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandSender sender, String[] args) {
|
||||
if (args.length < 4)
|
||||
return CommandResult.THROW_USAGE;
|
||||
|
||||
if (!MMOCore.plugin.waypointManager.has(args[2])) {
|
||||
sender.sendMessage(ChatColor.RED + "Could not find waypoint " + args[2]);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
Player player = Bukkit.getPlayer(args[3]);
|
||||
if (player == null) {
|
||||
sender.sendMessage(ChatColor.RED + "Could not find player " + args[3]);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
Waypoint waypoint = MMOCore.plugin.waypointManager.get(args[2]);
|
||||
new SmartGive(player).give(new WaypointBookBuilder(waypoint).build());
|
||||
sender.sendMessage(ChatColor.GOLD + "Gave " + player.getName() + ChatColor.YELLOW + " a waypoint book of " + ChatColor.GOLD + waypoint.getId()
|
||||
+ ChatColor.YELLOW + ".");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ public class WaypointsCommandTreeNode extends CommandTreeNode {
|
||||
addChild(new UnlockCommandTreeNode(this));
|
||||
addChild(new OpenCommandTreeNode(this));
|
||||
addChild(new TeleportCommandTreeNode(this));
|
||||
addChild(new ItemCommandTreeNode(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,28 +0,0 @@
|
||||
package net.Indyuce.mmocore.comp;
|
||||
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import io.lumine.mythic.lib.comp.target.TargetRestriction;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.party.AbstractParty;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class MMOCoreTargetRestriction implements TargetRestriction {
|
||||
|
||||
@Override
|
||||
public boolean canTarget(Player player, LivingEntity target, InteractionType interaction) {
|
||||
|
||||
if (interaction.isOffense() && target instanceof Player && PlayerData.has(target.getUniqueId())) {
|
||||
PlayerData targetData = PlayerData.get(target.getUniqueId());
|
||||
|
||||
// Check for the same party
|
||||
AbstractParty party = targetData.getParty();
|
||||
if (party != null && party.hasMember(player))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import io.lumine.mythic.lib.api.util.AltChar;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import net.Indyuce.mmocore.api.quest.PlayerQuests;
|
||||
import net.Indyuce.mmocore.experience.PlayerProfessions;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
@ -72,11 +72,11 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
}
|
||||
|
||||
else if (identifier.equals("health") && player.isOnline()) {
|
||||
return StatType.MAX_HEALTH.format(player.getPlayer().getHealth());
|
||||
return StatInfo.valueOf("MAX_HEALTH").format(player.getPlayer().getHealth());
|
||||
}
|
||||
|
||||
else if (identifier.equals("max_health") && player.isOnline()) {
|
||||
return StatType.MAX_HEALTH.format(player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
||||
return StatInfo.valueOf("MAX_HEALTH").format(player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
||||
}
|
||||
|
||||
else if (identifier.equals("health_bar") && player.isOnline()) {
|
||||
@ -153,7 +153,7 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getMana());
|
||||
|
||||
else if (identifier.equals("mana_bar")) {
|
||||
return playerData.getProfess().getManaDisplay().generateBar(playerData.getMana(), playerData.getStats().getStat(StatType.MAX_MANA));
|
||||
return playerData.getProfess().getManaDisplay().generateBar(playerData.getMana(), playerData.getStats().getStat("MAX_MANA"));
|
||||
}
|
||||
|
||||
else if (identifier.startsWith("exp_multiplier_")) {
|
||||
@ -173,7 +173,7 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
|
||||
else if (identifier.equals("stamina_bar")) {
|
||||
StringBuilder format = new StringBuilder();
|
||||
double ratio = 20 * playerData.getStamina() / playerData.getStats().getStat(StatType.MAX_STAMINA);
|
||||
double ratio = 20 * playerData.getStamina() / playerData.getStats().getStat("MAX_STAMINA");
|
||||
for (double j = 1; j < 20; j++)
|
||||
format.append(ratio >= j ? MMOCore.plugin.configManager.staminaFull
|
||||
: ratio >= j - .5 ? MMOCore.plugin.configManager.staminaHalf : MMOCore.plugin.configManager.staminaEmpty)
|
||||
@ -182,8 +182,8 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
}
|
||||
|
||||
else if (identifier.startsWith("stat_")) {
|
||||
StatType type = StatType.valueOf(identifier.substring(5).toUpperCase());
|
||||
return type == null ? "Invalid Stat" : type.format(playerData.getStats().getStat(type));
|
||||
StatInfo info = StatInfo.valueOf(identifier.substring(5).toUpperCase());
|
||||
return info.format(playerData.getStats().getStat(info.name));
|
||||
}
|
||||
|
||||
else if (identifier.equals("stellium"))
|
||||
@ -191,7 +191,7 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
|
||||
else if (identifier.equals("stellium_bar")) {
|
||||
StringBuilder format = new StringBuilder();
|
||||
double ratio = 20 * playerData.getStellium() / playerData.getStats().getStat(StatType.MAX_STELLIUM);
|
||||
double ratio = 20 * playerData.getStellium() / playerData.getStats().getStat("MAX_STELLIUM");
|
||||
for (double j = 1; j < 20; j++)
|
||||
format.append(ratio >= j ? ChatColor.BLUE : ratio >= j - .5 ? ChatColor.AQUA : ChatColor.WHITE).append(AltChar.listSquare);
|
||||
return format.toString();
|
||||
|
@ -3,8 +3,8 @@ package net.Indyuce.mmocore.comp.region;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
|
||||
public class RegionCondition extends Condition {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package net.Indyuce.mmocore.comp.region;
|
||||
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||
import net.Indyuce.mmocore.api.load.MMOLoader;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
package net.Indyuce.mmocore.experience;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Either a profession or a class
|
||||
* General implementation for professions, classes and attributes.
|
||||
* <p>
|
||||
* An experience object is a type of object that can level up.
|
||||
* It has an experience curve and table and can receive EXP
|
||||
*
|
||||
* @author jules
|
||||
*/
|
||||
@ -26,40 +26,11 @@ public interface ExperienceObject extends ExperienceDispenser {
|
||||
@Nullable
|
||||
ExpCurve getExpCurve();
|
||||
|
||||
boolean hasExperienceTable();
|
||||
|
||||
/**
|
||||
* @return Table read when leveling up
|
||||
*/
|
||||
@NotNull
|
||||
ExperienceTable getExperienceTable();
|
||||
|
||||
/**
|
||||
* Called when experience is gained in main class/profession
|
||||
*
|
||||
* @param playerData Player gaining the experience
|
||||
* @param experience Experience gained. Note that it is a double
|
||||
* because it gets converted to an integer at
|
||||
* the very last moment in MMOCore
|
||||
* @param hologramLocation Location of displayed hologram. When set to null
|
||||
* and if exp holograms are enabled it will take the
|
||||
* player's location instead.
|
||||
* @param source Why the EXP was gained
|
||||
*/
|
||||
void giveExperience(PlayerData playerData, double experience, @org.jetbrains.annotations.Nullable Location hologramLocation, @NotNull EXPSource source);
|
||||
|
||||
/**
|
||||
* Experience sources handle both CLASS experience sources and PROFESSION
|
||||
* experience sources. Professions have no problem because whatever
|
||||
* class the player has chosen, he can get exp in that profession.
|
||||
* <p>
|
||||
* But class experience sources must first make sure that the player has
|
||||
* the right class before giving exp to the player
|
||||
*/
|
||||
boolean shouldHandle(PlayerData playerData);
|
||||
|
||||
@Nullable
|
||||
default Location getPlayerLocation(PlayerData player) {
|
||||
return player.isOnline() ? MMOCoreUtils.getCenterLocation(player.getPlayer()) : null;
|
||||
}
|
||||
boolean hasExperienceTable();
|
||||
}
|
||||
|
@ -4,13 +4,13 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigMessage;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
|
||||
import org.apache.commons.lang.Validate;
|
||||
@ -26,7 +26,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class PlayerProfessions {
|
||||
private final Map<String, Integer> exp = new HashMap<>();
|
||||
private final Map<String, Double> exp = new HashMap<>();
|
||||
private final Map<String, Integer> level = new HashMap<>();
|
||||
|
||||
private final PlayerData playerData;
|
||||
@ -41,7 +41,7 @@ public class PlayerProfessions {
|
||||
public PlayerProfessions load(ConfigurationSection config) {
|
||||
for (String key : config.getKeys(false))
|
||||
if (MMOCore.plugin.professionManager.has(key)) {
|
||||
exp.put(key, config.getInt(key + ".exp"));
|
||||
exp.put(key, config.getDouble(key + ".exp"));
|
||||
level.put(key, config.getInt(key + ".level"));
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ public class PlayerProfessions {
|
||||
for (Entry<String, JsonElement> entry : obj.entrySet())
|
||||
if (MMOCore.plugin.professionManager.has(entry.getKey())) {
|
||||
JsonObject value = entry.getValue().getAsJsonObject();
|
||||
exp.put(entry.getKey(), value.get("exp").getAsInt());
|
||||
exp.put(entry.getKey(), value.get("exp").getAsDouble());
|
||||
level.put(entry.getKey(), value.get("level").getAsInt());
|
||||
}
|
||||
|
||||
@ -111,11 +111,11 @@ public class PlayerProfessions {
|
||||
return getLevel(profession.getId());
|
||||
}
|
||||
|
||||
public int getExperience(String id) {
|
||||
return exp.getOrDefault(id, 0);
|
||||
public double getExperience(String id) {
|
||||
return exp.getOrDefault(id, 0.);
|
||||
}
|
||||
|
||||
public int getExperience(Profession profession) {
|
||||
public double getExperience(Profession profession) {
|
||||
return getExperience(profession.getId());
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ public class PlayerProfessions {
|
||||
level.put(profession.getId(), Math.max(1, current - value));
|
||||
}
|
||||
|
||||
public void setExperience(Profession profession, int value) {
|
||||
public void setExperience(Profession profession, double value) {
|
||||
exp.put(profession.getId(), value);
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ public class PlayerProfessions {
|
||||
giveExperience(profession, total, source);
|
||||
}
|
||||
|
||||
public void giveExperience(Profession profession, int value, EXPSource source) {
|
||||
public void giveExperience(Profession profession, double value, EXPSource source) {
|
||||
giveExperience(profession, value, source, null);
|
||||
}
|
||||
|
||||
@ -157,6 +157,8 @@ public class PlayerProfessions {
|
||||
|
||||
public void giveExperience(Profession profession, double value, EXPSource source, @Nullable Location hologramLocation) {
|
||||
Validate.isTrue(playerData.isOnline(), "Cannot give experience to offline player");
|
||||
if (value <= 0)
|
||||
return;
|
||||
|
||||
if (hasReachedMaxLevel(profession)) {
|
||||
setExperience(profession, 0);
|
||||
@ -166,19 +168,20 @@ public class PlayerProfessions {
|
||||
value = MMOCore.plugin.boosterManager.calculateExp(profession, value);
|
||||
|
||||
// Adds functionality for additional experience per profession.
|
||||
value *= 1 + playerData.getStats().getInstance(StatType.ADDITIONAL_EXPERIENCE, profession).getTotal() / 100;
|
||||
value *= 1 + playerData.getStats().getInstance("ADDITIONAL_EXPERIENCE_" + UtilityMethods.enumName(profession.getId())).getTotal() / 100;
|
||||
|
||||
// Display hologram
|
||||
if (hologramLocation != null)
|
||||
MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), MMOCore.plugin.configManager.getSimpleMessage("exp-hologram", "exp", "" + value).message());
|
||||
|
||||
PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(playerData, profession, (int) value, source);
|
||||
PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(playerData, profession, value, source);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
|
||||
exp.put(profession.getId(), Math.max(0, exp.getOrDefault(profession.getId(), 0) + event.getExperience()));
|
||||
int needed, exp, level, oldLevel = getLevel(profession);
|
||||
exp.put(profession.getId(), Math.max(0, exp.getOrDefault(profession.getId(), 0.) + event.getExperience()));
|
||||
int level, oldLevel = getLevel(profession);
|
||||
double needed,exp;
|
||||
|
||||
/*
|
||||
* Loop for exp overload when leveling up, will continue
|
||||
@ -195,7 +198,7 @@ public class PlayerProfessions {
|
||||
this.exp.put(profession.getId(), exp - needed);
|
||||
this.level.put(profession.getId(), level + 1);
|
||||
check = true;
|
||||
playerData.giveExperience((int) profession.getExperience().calculate(level), null);
|
||||
playerData.giveExperience(profession.getExperience().calculate(level), null);
|
||||
}
|
||||
|
||||
if (check) {
|
||||
|
@ -64,7 +64,7 @@ public class Profession extends PostLoadObject implements ExperienceObject {
|
||||
|
||||
maxLevel = config.getInt("max-level");
|
||||
|
||||
if (config.contains("exp-sources")) {
|
||||
if (config.contains("exp-sources"))
|
||||
for (String key : config.getStringList("exp-sources"))
|
||||
try {
|
||||
MMOCore.plugin.experience.registerSource(MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), this));
|
||||
@ -72,7 +72,6 @@ public class Profession extends PostLoadObject implements ExperienceObject {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING,
|
||||
"Could not register exp source '" + key + "' from profession '" + id + "': " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -127,7 +126,7 @@ public class Profession extends PostLoadObject implements ExperienceObject {
|
||||
@Override
|
||||
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) {
|
||||
hologramLocation = !getOption(Profession.ProfessionOption.EXP_HOLOGRAMS) ? null
|
||||
: hologramLocation == null ? getPlayerLocation(playerData) : hologramLocation;
|
||||
: hologramLocation;
|
||||
playerData.getCollectionSkills().giveExperience(this, experience, EXPSource.SOURCE, hologramLocation);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
package net.Indyuce.mmocore.experience;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SimpleExperienceObject implements ExperienceDispenser {
|
||||
|
||||
@Override
|
||||
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) {
|
||||
hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null
|
||||
: hologramLocation == null ? getPlayerLocation(playerData) : hologramLocation;
|
||||
playerData.giveExperience(experience, source, hologramLocation, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldHandle(PlayerData playerData) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -21,9 +21,7 @@ public interface ExperienceDispenser {
|
||||
* Called when experience is gained in main class/profession
|
||||
*
|
||||
* @param playerData Player gaining the experience
|
||||
* @param experience Experience gained. Note that it is a double
|
||||
* because it gets converted to an integer at
|
||||
* the very last moment in MMOCore
|
||||
* @param experience Experience gained
|
||||
* @param hologramLocation Location of displayed hologram. When set to null
|
||||
* and if exp holograms are enabled it will take the
|
||||
* player's location instead.
|
||||
|
@ -13,7 +13,10 @@ import java.util.Random;
|
||||
|
||||
public class ExperienceItem {
|
||||
private final String id;
|
||||
|
||||
//A period of 0 means the item will only trigger one time.
|
||||
private final int period;
|
||||
private final int firstTrigger;
|
||||
private final double claimChance, failReduction;
|
||||
private final List<Trigger> triggers;
|
||||
|
||||
@ -23,6 +26,7 @@ public class ExperienceItem {
|
||||
* One item for an experience table
|
||||
*
|
||||
* @param period The experience item is claimed every X level ups
|
||||
* @param firstTrigger The experience item if claimed for the first time at X level ups.
|
||||
* @param claimChance Chance for that item to be claimed every X level ups
|
||||
* @param failReduction Between 0 and 1, by how much the fail chance is reduced
|
||||
* every time the item is not claimed when leveling up.
|
||||
@ -32,19 +36,22 @@ public class ExperienceItem {
|
||||
* where n is the amount of successive claiming fails
|
||||
* @param triggers Actions cast when the exp item is claimed
|
||||
*/
|
||||
public ExperienceItem(String id, int period, double claimChance, double failReduction, List<Trigger> triggers) {
|
||||
public ExperienceItem(String id, int period, int firstTrigger, double claimChance, double failReduction, List<Trigger> triggers) {
|
||||
this.id = id;
|
||||
this.period = period;
|
||||
this.claimChance = claimChance;
|
||||
this.failReduction = failReduction;
|
||||
this.triggers = triggers;
|
||||
this.firstTrigger = firstTrigger;
|
||||
}
|
||||
|
||||
public ExperienceItem(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Config cannot be null");
|
||||
Validate.isTrue(config.contains("triggers"));
|
||||
id = config.getName();
|
||||
period = config.getInt("period", 1);
|
||||
|
||||
period = config.getInt("period", 0);
|
||||
firstTrigger = config.getInt("first-trigger", period);
|
||||
claimChance = config.getDouble("chance", 100) / 100;
|
||||
failReduction = config.getDouble("fail-reduction", 80) / 100;
|
||||
triggers = new ArrayList<>();
|
||||
@ -64,7 +71,7 @@ public class ExperienceItem {
|
||||
* account the randomness factor from the 'chance' parameter
|
||||
*/
|
||||
public boolean roll(int professionLevel, int timesCollected) {
|
||||
int claimsRequired = professionLevel - (timesCollected + 1) * period;
|
||||
int claimsRequired = professionLevel + 1 - (firstTrigger - timesCollected * period);
|
||||
if (claimsRequired < 1)
|
||||
return false;
|
||||
|
||||
|
@ -168,7 +168,7 @@ public class BrewPotionExperienceSource extends ExperienceSource<PotionMeta> {
|
||||
*/
|
||||
// exp += getTotal(mapEffectDurations());
|
||||
|
||||
getDispenser().giveExperience(PlayerData.get(player), (int) exp * multiplier, null, EXPSource.SOURCE);
|
||||
getDispenser().giveExperience(PlayerData.get(player), exp * multiplier, player.getLocation(), EXPSource.SOURCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,75 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class ClimbExperienceSource extends SpecificExperienceSource<Material> {
|
||||
//Can be Ladder,Vines,Twisting Vines,Weeping Vines.
|
||||
private final Material type;
|
||||
|
||||
/**
|
||||
* Gives Experience when a player climbs on a ladder, a vine, a twisting vine or a weeping vine depending
|
||||
* on the type precised (if no type is precised it will give xp for the 4)
|
||||
* The xp given depends on the vertical distance travelled, the random amount given correspond
|
||||
* to the xp when you climb, one block
|
||||
*/
|
||||
public ClimbExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
//If no type precised Ladder and all vines types work
|
||||
if (!config.contains("type"))
|
||||
type = null;
|
||||
else {
|
||||
String str = config.getString("type").toUpperCase().replace("-", "_");
|
||||
Validate.isTrue(str.equals("LADDER") ||
|
||||
str.equals("VINE") || str.equals("TWISTING_VINES_PLANT") || str.equals("WEEPING_VINES"),
|
||||
"ClimbExperienceSource problem: The type must be ladder, vine, twisted-vines or weeping-vines");
|
||||
|
||||
type = Material.valueOf(str);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<ClimbExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<ClimbExperienceSource>() {
|
||||
@EventHandler
|
||||
public void onClimb(PlayerMoveEvent e) {
|
||||
double delta=e.getTo().getBlockY()-e.getFrom().getBlockY();
|
||||
if (delta > 0) {
|
||||
if (e.getPlayer().hasMetadata("NPC"))
|
||||
return;
|
||||
PlayerData playerData = PlayerData.get(e.getPlayer());
|
||||
for (ClimbExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, e.getFrom().getBlock().getType()))
|
||||
source.giveExperience(playerData, delta, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, Material material) {
|
||||
if (type == null)
|
||||
return material.equals(Material.LADDER) || material.equals(Material.VINE) ||
|
||||
material.equals(Material.WEEPING_VINES) || material.equals(Material.TWISTING_VINES) ||
|
||||
material.equals(Material.WEEPING_VINES_PLANT) || material.equals(Material.TWISTING_VINES_PLANT);
|
||||
if (type.equals(Material.WEEPING_VINES))
|
||||
return material.equals(Material.WEEPING_VINES) || material.equals(Material.WEEPING_VINES_PLANT);
|
||||
if (type.equals(Material.TWISTING_VINES))
|
||||
return material.equals(Material.TWISTING_VINES) || material.equals(Material.TWISTING_VINES_PLANT);
|
||||
return material.equals(type);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.damage.DamagePacket;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import scala.Enumeration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DamageDealtExperienceSource extends SpecificExperienceSource<DamageType> {
|
||||
private final DamageType type;
|
||||
|
||||
/**
|
||||
* Gives experience when a player deals damage of a certain type. If no type is given it will give xp for all
|
||||
* the damage type. The random value you give correspond to the xp you get per damage dealt.
|
||||
*/
|
||||
|
||||
public DamageDealtExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
if (!config.contains("type"))
|
||||
type = null;
|
||||
else {
|
||||
String str = config.getString("type").toUpperCase().replace("-", "_");
|
||||
//Checks if the damage type correspond to a value of the damage type enum
|
||||
Validate.isTrue(Arrays.stream(DamageType.values()).map(Objects::toString).collect(Collectors.toList()).contains(str),
|
||||
"Type value not allowed. Type value allowed: magic, physical, weapon, skill, projectile," +
|
||||
" unarmed, on-hit, minion, dot.");
|
||||
type = DamageType.valueOf(str);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<DamageDealtExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<DamageDealtExperienceSource>() {
|
||||
@EventHandler
|
||||
public void onDamageDealt(PlayerAttackEvent e) {
|
||||
PlayerData playerData = PlayerData.get(e.getPlayer());
|
||||
for (DamageDealtExperienceSource source : getSources()) {
|
||||
double value = 0;
|
||||
for (DamagePacket packet : e.getDamage().getPackets()) {
|
||||
for (DamageType damageType : packet.getTypes()) {
|
||||
if (source.matchesParameter(playerData, damageType))
|
||||
value += packet.getFinalValue();
|
||||
}
|
||||
|
||||
}
|
||||
source.giveExperience(playerData, value, null);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, DamageType damageType) {
|
||||
if (type == null)
|
||||
return true;
|
||||
else
|
||||
return type.equals(damageType);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DamageTakenExperienceSource extends SpecificExperienceSource<EntityDamageEvent.DamageCause> {
|
||||
private final EntityDamageEvent.DamageCause cause;
|
||||
|
||||
/**
|
||||
* Gives experience when a player takes damage from a certain cause. If no cause is given it will give xp for all
|
||||
* the damage causes. The random value you give correspond to the xp you get per damage taken.
|
||||
*/
|
||||
public DamageTakenExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
if (!config.contains("cause"))
|
||||
cause = null;
|
||||
else {
|
||||
String str = config.getString("cause").toUpperCase().replace("-", "_");
|
||||
//Checks if the damage type correspond to a value of the damage type enum
|
||||
Validate.isTrue(Arrays.stream(EntityDamageEvent.DamageCause.values()).map(Objects::toString).collect(Collectors.toList()).contains(str),
|
||||
"Cause not allowed. Go check at all the Damage Causes in EntityDamageEvent.DamageCause enum.");
|
||||
cause = EntityDamageEvent.DamageCause.valueOf(str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<DamageTakenExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<DamageTakenExperienceSource>() {
|
||||
@EventHandler
|
||||
public void onDamageTaken(EntityDamageEvent e) {
|
||||
if (e.getEntity() instanceof Player && !e.getEntity().hasMetadata("NPC")) {
|
||||
double amount = e.getDamage();
|
||||
PlayerData playerData = PlayerData.get((OfflinePlayer) e.getEntity());
|
||||
//We wait 2 tick to check if the player is Dead
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (DamageTakenExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, e.getCause()))
|
||||
source.giveExperience(playerData, amount, null);
|
||||
}
|
||||
}
|
||||
}.runTaskLater(MMOCore.plugin, 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, EntityDamageEvent.DamageCause damageCause) {
|
||||
if (player.getPlayer().isDead())
|
||||
return false;
|
||||
if (cause == null)
|
||||
return true;
|
||||
return damageCause.equals(cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class EatExperienceSource extends SpecificExperienceSource<ItemStack> {
|
||||
private final Material type;
|
||||
|
||||
/**
|
||||
* Gives xp when you eat a certain type of food. If not type is given it will give xp from all the food sources.
|
||||
* The amount of xp given is the xp per food regenerated.
|
||||
*/
|
||||
public EatExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
if(!config.contains("type"))
|
||||
type=null;
|
||||
else {
|
||||
Material material=Material.valueOf(config.getString("type").toUpperCase().replace("-","_"));
|
||||
Validate.isTrue(material!=null,"You must precise a valid material!");
|
||||
type=material;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<EatExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<EatExperienceSource>() {
|
||||
|
||||
@EventHandler
|
||||
public void a(FoodLevelChangeEvent e) {
|
||||
if (!(e.getEntity() instanceof Player) || e.getEntity().hasMetadata("NPC"))
|
||||
return;
|
||||
PlayerData playerData = PlayerData.get((OfflinePlayer) e.getEntity());
|
||||
for (EatExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, e.getItem()))
|
||||
source.giveExperience(playerData, e.getFoodLevel(), null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, ItemStack obj) {
|
||||
if(type==null)
|
||||
return true;
|
||||
return type.equals(obj.getType());
|
||||
}
|
||||
|
||||
}
|
@ -60,7 +60,7 @@ public class EnchantItemExperienceSource extends ExperienceSource<Void> {
|
||||
double exp = 0;
|
||||
for (Entry<Enchantment, Integer> entry : applicableEnchants.entrySet())
|
||||
exp += MMOCore.plugin.enchantManager.getBaseExperience(entry.getKey()) * entry.getValue();
|
||||
getDispenser().giveExperience(player, (int) exp, event.getEnchantBlock().getLocation(), EXPSource.SOURCE);
|
||||
getDispenser().giveExperience(player, exp, event.getEnchantBlock().getLocation(), EXPSource.SOURCE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class MineBlockExperienceSource extends SpecificExperienceSource<Material> {
|
||||
public final Material material;
|
||||
private final Material material;
|
||||
private final boolean silkTouch;
|
||||
private final boolean crop;
|
||||
|
||||
|
@ -0,0 +1,81 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MoveExperienceSource extends SpecificExperienceSource {
|
||||
private final MovingType type;
|
||||
|
||||
public MoveExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
if (!config.contains("type"))
|
||||
type = null;
|
||||
else {
|
||||
String str = config.getString("type").toUpperCase().replace("-", "_");
|
||||
//Checks if the damage type correspond to a value of the damage type enum
|
||||
Validate.isTrue(Arrays.stream(MoveExperienceSource.MovingType.values()).map(Objects::toString).collect(Collectors.toList()).contains(str),
|
||||
"moving-type value not allowed. Moving type values allowed: sneak, fly, swim, sprint, walk.");
|
||||
type = MovingType.valueOf(str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<MoveExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<MoveExperienceSource>() {
|
||||
@EventHandler
|
||||
public void onMove(PlayerMoveEvent e) {
|
||||
double deltax = e.getTo().getBlockX() - e.getFrom().getBlockX();
|
||||
double deltay = e.getTo().getBlockY() - e.getFrom().getBlockY();
|
||||
double deltaz = e.getTo().getBlockZ() - e.getFrom().getBlockZ();
|
||||
if (deltax != 0 && deltay != 0 && deltaz != 0) {
|
||||
double delta = Math.sqrt(deltax * deltax + deltay * deltay + deltaz * deltaz);
|
||||
if (e.getPlayer().hasMetadata("NPC"))
|
||||
return;
|
||||
Player player = e.getPlayer();
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
for (MoveExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, null)) {
|
||||
giveExperience(playerData, delta, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, Object obj) {
|
||||
return type == null || type.matches(player.getPlayer());
|
||||
}
|
||||
|
||||
public enum MovingType {
|
||||
SNEAK(Player::isSneaking),
|
||||
FLY((p) -> p.isFlying() || p.isGliding()),
|
||||
SWIM((p) -> p.getLocation().getBlock().isLiquid()),
|
||||
SPRINT(Player::isSprinting),
|
||||
WALK((p) -> !p.isSneaking() && !p.isSprinting() && !p.isFlying() && !p.getLocation().getBlock().isLiquid());
|
||||
|
||||
private final Function<Player, Boolean> matching;
|
||||
|
||||
MovingType(Function<Player, Boolean> matching) {
|
||||
this.matching = matching;
|
||||
}
|
||||
|
||||
public boolean matches(Player player) {
|
||||
return !player.isInsideVehicle() && matching.apply(player);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class PlayExperienceSource extends SpecificExperienceSource {
|
||||
|
||||
private final World world;
|
||||
private final double x1, x2, z1, z2;
|
||||
private final boolean inCombat;
|
||||
|
||||
/**
|
||||
* Experience source giving the specified amount of xp to all the players online each second in certain world bounds.
|
||||
* If no bounds are given, it will give the xp to every player online. You can also specifiy if the player
|
||||
* has to be inCombat or not to get the xp.
|
||||
*/
|
||||
public PlayExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
|
||||
inCombat = config.getBoolean("in-combat", false);
|
||||
world = config.contains("world") ? Objects.requireNonNull(Bukkit.getWorld(config.getString("world")), "Could not find world " + config.getString("world")) : null;
|
||||
if (!config.contains("x1") || !config.contains("x2")) {
|
||||
x1 = Double.NEGATIVE_INFINITY;
|
||||
x2 = Double.POSITIVE_INFINITY;
|
||||
} else {
|
||||
x1 = Math.min(config.getInt("x1"), config.getInt("x2"));
|
||||
x2 = Math.max(config.getInt("x1"), config.getInt("x2"));
|
||||
}
|
||||
if (!config.contains("z1") || !config.contains("z2")) {
|
||||
z1 = Double.NEGATIVE_INFINITY;
|
||||
z2 = Double.POSITIVE_INFINITY;
|
||||
} else {
|
||||
z1 = Math.min(config.getInt("z1"), config.getInt("z2"));
|
||||
z2 = Math.max(config.getInt("z1"), config.getInt("z2"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<PlayExperienceSource> newManager() {
|
||||
return new PlayingExperienceSourceManager();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, Object obj) {
|
||||
if (inCombat && !player.isInCombat())
|
||||
return false;
|
||||
|
||||
if (world == null)
|
||||
return true;
|
||||
Location location = player.getPlayer().getLocation();
|
||||
return location.getWorld().equals(world) && location.getX() > x1 && location.getX() < x2
|
||||
&& location.getZ() > z1 && location.getZ() < z2;
|
||||
}
|
||||
|
||||
|
||||
private class PlayingExperienceSourceManager extends ExperienceSourceManager<PlayExperienceSource> {
|
||||
|
||||
public PlayingExperienceSourceManager() {
|
||||
new BukkitRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Bukkit.getOnlinePlayers().forEach((player) -> {
|
||||
if (!player.hasMetadata("NPC")) {
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
for (PlayExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, null))
|
||||
giveExperience(playerData, 1, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}.runTaskTimer(MMOCore.plugin, 0, 20);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.Trident;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ProjectileExperienceSource extends SpecificExperienceSource<Projectile> {
|
||||
private final ProjectileType projectileType;
|
||||
|
||||
public ProjectileExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
if (!config.contains("type"))
|
||||
projectileType = null;
|
||||
else {
|
||||
String str = config.getString("type").toUpperCase().replace("-", "_");
|
||||
Validate.isTrue(Arrays.stream(ProjectileType.values()).map(ProjectileType::toString).collect(Collectors.toList()).contains(str));
|
||||
projectileType = ProjectileType.valueOf(str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<ProjectileExperienceSource> newManager() {
|
||||
|
||||
return new ExperienceSourceManager<ProjectileExperienceSource>() {
|
||||
HashMap<Projectile, Location> projectiles = new HashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onHit(ProjectileHitEvent e) {
|
||||
if (e.getHitBlock() != null && projectiles.containsKey(e.getEntity()))
|
||||
projectiles.remove(e.getEntity());
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
|
||||
if (e.getEntity() instanceof Projectile) {
|
||||
Projectile projectile = (Projectile) e.getEntity();
|
||||
if (!projectiles.containsKey(projectile))
|
||||
return;
|
||||
if (projectile.getShooter() instanceof Player && !((Player) projectile.getShooter()).hasMetadata("NPC")) {
|
||||
Player player = (Player) projectile.getShooter();
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
double distance = projectiles.get(projectile).distance(e.getEntity().getLocation());
|
||||
for (ProjectileExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, projectile))
|
||||
source.giveExperience(playerData, e.getFinalDamage() * distance, null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
projectiles.remove(projectile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Mark every arrow with the the location at which it was shot to calculate the distance
|
||||
@EventHandler
|
||||
public void onLaunch(ProjectileLaunchEvent e) {
|
||||
if (e.getEntity().getShooter() instanceof Player) {
|
||||
Player player = (Player) e.getEntity().getShooter();
|
||||
if (player.hasMetadata("NPC"))
|
||||
return;
|
||||
|
||||
|
||||
projectiles.put(e.getEntity(), e.getLocation());
|
||||
//Remove the projectile 15 s after it was launched
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
projectiles.remove(e.getEntity());
|
||||
}
|
||||
}.runTaskLater(MMOCore.plugin, 60 * 20L);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, Projectile projectile) {
|
||||
if (projectileType == null)
|
||||
return true;
|
||||
return projectileType.matches(projectile);
|
||||
}
|
||||
|
||||
|
||||
public enum ProjectileType {
|
||||
ARROW((p) -> p instanceof Arrow),
|
||||
TRIDENT((p) -> p instanceof Trident);
|
||||
|
||||
private final Function<Projectile, Boolean> matching;
|
||||
|
||||
ProjectileType(Function<Projectile, Boolean> matching) {
|
||||
this.matching = matching;
|
||||
}
|
||||
|
||||
|
||||
public boolean matches(Projectile projectile) {
|
||||
return matching.apply(projectile);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -75,7 +75,7 @@ public class RepairItemExperienceSource extends ExperienceSource<ItemStack> {
|
||||
*/
|
||||
double exp = MMOCore.plugin.smithingManager.getBaseExperience(item.getType())
|
||||
* Math.max(0, ((Damageable) old.getItemMeta()).getDamage() - ((Damageable) item.getItemMeta()).getDamage()) / 100;
|
||||
getDispenser().giveExperience(data, (int) exp, null, EXPSource.SOURCE);
|
||||
getDispenser().giveExperience(data, exp, data.getPlayer().getLocation(), EXPSource.SOURCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ResourceExperienceSource extends SpecificExperienceSource<PlayerResource> {
|
||||
private final PlayerResource resource;
|
||||
|
||||
/**
|
||||
* Gives experience when the player uses a specific resoure. If no resource is precised it will trigger for
|
||||
* mana, stamina and stellium. The amount specified si the xp given per resource consummed.
|
||||
*/
|
||||
public ResourceExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
if (!config.contains("resource"))
|
||||
resource = null;
|
||||
else {
|
||||
String str = config.getString("resource").toUpperCase().replace("-", "_");
|
||||
Validate.isTrue(str.equals("MANA") || str.equals("STELLIUM") || str.equals("STAMINA"),
|
||||
"ResourceExperienceSource problem: The resource can only be mana, stamina or STELLIUM");
|
||||
resource = PlayerResource.valueOf(str);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<ResourceExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<ResourceExperienceSource>() {
|
||||
@EventHandler
|
||||
public void onResource(PlayerResourceUpdateEvent e) {
|
||||
if (e.getPlayer().hasMetadata("NPC"))
|
||||
return;
|
||||
PlayerData playerData = PlayerData.get(e.getPlayer());
|
||||
if(e.getAmount()<0)
|
||||
for (ResourceExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, e.getResource()))
|
||||
source.giveExperience(playerData, -e.getAmount(), null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, PlayerResource obj) {
|
||||
if (resource == null)
|
||||
return !obj.equals(PlayerResource.HEALTH);
|
||||
return resource.equals(obj);
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class RideExperienceSource extends SpecificExperienceSource<EntityType> {
|
||||
private final EntityType type;
|
||||
|
||||
/**
|
||||
* Gives experience when a player moves riding a certain entity. If no entity type is given it will give xp if you move
|
||||
* while riding an entity whatever it is.
|
||||
* The random value you give correspond to the xp you get per block travelled while riding.
|
||||
*/
|
||||
public RideExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
if (!config.contains("type"))
|
||||
type = null;
|
||||
else {
|
||||
String str = config.getString("type").toUpperCase().replace("-", "_");
|
||||
Validate.isTrue(Arrays.stream(EntityType.values()).map(Objects::toString).collect(Collectors.toList()).contains(str),
|
||||
"The type must correspond to an entity that exist in the game.");
|
||||
type = EntityType.valueOf(str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<RideExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<RideExperienceSource>() {
|
||||
@EventHandler
|
||||
public void onRide(PlayerMoveEvent e) {
|
||||
|
||||
if (e.getPlayer().isInsideVehicle()) {
|
||||
double deltax = e.getTo().getBlockX() - e.getFrom().getBlockX();
|
||||
double deltay = e.getTo().getBlockY() - e.getFrom().getBlockY();
|
||||
double deltaz = e.getTo().getBlockZ() - e.getFrom().getBlockZ();
|
||||
if (deltax != 0 && deltay != 0 && deltaz != 0) {
|
||||
double delta = Math.sqrt(deltax * deltax + deltay * deltay + deltaz * deltaz);
|
||||
if (e.getPlayer().hasMetadata("NPC"))
|
||||
return;
|
||||
PlayerData playerData = PlayerData.get(e.getPlayer());
|
||||
Entity vehicle = e.getPlayer().getVehicle();
|
||||
for (RideExperienceSource source : getSources()) {
|
||||
if (source.matchesParameter(playerData, vehicle.getType()))
|
||||
giveExperience(playerData, e.getFrom().distance(e.getTo()), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, EntityType obj) {
|
||||
if (type == null)
|
||||
return true;
|
||||
return type.equals(obj);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package net.Indyuce.mmocore.experience.source;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Wolf;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
public class TameExperienceSource extends SpecificExperienceSource {
|
||||
public TameExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExperienceSourceManager<TameExperienceSource> newManager() {
|
||||
return new ExperienceSourceManager<TameExperienceSource>() {
|
||||
|
||||
@EventHandler
|
||||
public void onWolfHit(EntityDamageByEntityEvent e) {
|
||||
if(e.getDamager() instanceof Wolf) {
|
||||
Wolf wolf= (Wolf) e.getDamager();
|
||||
if(wolf.getOwner() instanceof Player &&!((Player) wolf.getOwner()).hasMetadata("NPC")) {
|
||||
PlayerData playerData=PlayerData.get((OfflinePlayer) wolf.getOwner());
|
||||
for(TameExperienceSource source:getSources()) {
|
||||
source.giveExperience(playerData,e.getDamage(), MMOCoreUtils.getCenterLocation(e.getEntity()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesParameter(PlayerData player, Object obj) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -5,11 +5,13 @@ import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class SpecificExperienceSource<T> extends ExperienceSource<T> {
|
||||
private final RandomAmount amount;
|
||||
double counter = 0;
|
||||
|
||||
/**
|
||||
* Used to register experience sources with SPECIFIC experience outputs.
|
||||
@ -27,8 +29,8 @@ public abstract class SpecificExperienceSource<T> extends ExperienceSource<T> {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public int rollAmount() {
|
||||
return amount.calculateInt();
|
||||
public double rollAmount() {
|
||||
return amount.calculate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,7 @@ import net.Indyuce.mmocore.gui.api.item.InventoryItem;
|
||||
import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
@ -66,8 +67,9 @@ public class AttributeView extends EditableInventory {
|
||||
holders.register("current", total);
|
||||
holders.register("attribute_points", inv.getPlayerData().getAttributePoints());
|
||||
attribute.getBuffs().forEach(buff -> {
|
||||
holders.register("buff_" + buff.getStat().toLowerCase(), buff.getValue());
|
||||
holders.register("total_" + buff.getStat().toLowerCase(), buff.multiply(total).getValue());
|
||||
StatInfo info = StatInfo.valueOf(buff.getStat());
|
||||
holders.register("buff_" + buff.getStat().toLowerCase(), info.format(buff.getValue()));
|
||||
holders.register("total_" + buff.getStat().toLowerCase(), info.format(buff.multiply(total).getValue()));
|
||||
});
|
||||
return holders;
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
package net.Indyuce.mmocore.gui;
|
||||
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.experience.Booster;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
|
||||
import net.Indyuce.mmocore.experience.Booster;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import net.Indyuce.mmocore.gui.api.EditableInventory;
|
||||
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
|
||||
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
|
||||
@ -18,10 +19,13 @@ import net.Indyuce.mmocore.party.AbstractParty;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class PlayerStats extends EditableInventory {
|
||||
public PlayerStats() {
|
||||
super("player-stats");
|
||||
@ -78,7 +82,7 @@ public class PlayerStats extends EditableInventory {
|
||||
Placeholders holders = new Placeholders();
|
||||
net.Indyuce.mmocore.api.player.stats.PlayerStats stats = inv.getPlayerData().getStats();
|
||||
|
||||
double ratio = (double) inv.getPlayerData().getCollectionSkills().getExperience(profession)
|
||||
double ratio = inv.getPlayerData().getCollectionSkills().getExperience(profession)
|
||||
/ (double) inv.getPlayerData().getCollectionSkills().getLevelUpExperience(profession);
|
||||
|
||||
String bar = "" + ChatColor.BOLD;
|
||||
@ -91,9 +95,9 @@ public class PlayerStats extends EditableInventory {
|
||||
holders.register("level", "" + inv.getPlayerData().getCollectionSkills().getLevel(profession));
|
||||
holders.register("xp", inv.getPlayerData().getCollectionSkills().getExperience(profession));
|
||||
holders.register("percent", decimal.format(ratio * 100));
|
||||
for (StatType stat : StatType.values())
|
||||
if (stat.matches(profession))
|
||||
holders.register(stat.name().toLowerCase(), stat.format(stats.getStat(stat)));
|
||||
for (StatInfo stat : MMOCore.plugin.statManager.getLoaded())
|
||||
if (Objects.equals(stat.profession, profession))
|
||||
holders.register(stat.name.toLowerCase(), stat.format(stats.getStat(stat.name)));
|
||||
|
||||
return holders;
|
||||
}
|
||||
@ -113,21 +117,35 @@ public class PlayerStats extends EditableInventory {
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(GeneratedInventory inv, int n) {
|
||||
return new Placeholders() {
|
||||
final net.Indyuce.mmocore.api.player.stats.PlayerStats stats = inv.getPlayerData().getStats();
|
||||
|
||||
net.Indyuce.mmocore.api.player.stats.PlayerStats stats = inv.getPlayerData().getStats();
|
||||
Placeholders holders = new Placeholders();
|
||||
public String apply(Player player, String str) {
|
||||
while (str.contains("{") && str.substring(str.indexOf("{")).contains("}")) {
|
||||
String holder = str.substring(str.indexOf("{") + 1, str.indexOf("}"));
|
||||
String replaced;
|
||||
|
||||
for (StatType stat : StatType.values()) {
|
||||
double base = stats.getBase(stat), total = stats.getStat(stat), extra = total - base;
|
||||
holders.register(stat.name().toLowerCase(), stat.format(total));
|
||||
holders.register(stat.name().toLowerCase() + "_base", stat.format(base));
|
||||
holders.register(stat.name().toLowerCase() + "_extra", stat.format(extra));
|
||||
}
|
||||
if (holder.endsWith("_base")) {
|
||||
StatInfo info = StatInfo.valueOf(UtilityMethods.enumName(holder.substring(0, holder.length() - 5)));
|
||||
replaced = info.format(stats.getBase(info.name));
|
||||
} else if (holder.endsWith("_extra")) {
|
||||
StatInfo info = StatInfo.valueOf(UtilityMethods.enumName(holder.substring(0, holder.length() - 5)));
|
||||
replaced = info.format(stats.getStat(info.name) - stats.getBase(info.name));
|
||||
} else if (holder.startsWith("attribute_")) {
|
||||
PlayerAttribute attr = MMOCore.plugin.attributeManager.get(holder.substring(10).replace("_", "-").toLowerCase());
|
||||
replaced = String.valueOf(inv.getPlayerData().getAttributes().getAttribute(attr));
|
||||
} else {
|
||||
StatInfo info = StatInfo.valueOf(UtilityMethods.enumName(holder));
|
||||
replaced = info.format(stats.getStat(info.name));
|
||||
}
|
||||
|
||||
for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll())
|
||||
holders.register("attribute_" + attribute.getId().replace("-", "_"), inv.getPlayerData().getAttributes().getAttribute(attribute));
|
||||
str = str.replace("{" + holder + "}", replaced);
|
||||
}
|
||||
|
||||
return holders;
|
||||
// External placeholders
|
||||
return MMOCore.plugin.placeholderParser.parse(player, str);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,6 @@ import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
@ -38,9 +37,6 @@ public class SkillList extends EditableInventory {
|
||||
if (function.equals("skill"))
|
||||
return new SkillItem(config);
|
||||
|
||||
if (function.equals("switch"))
|
||||
return new SwitchItem(config);
|
||||
|
||||
if (function.equals("level"))
|
||||
return new LevelItem(config);
|
||||
|
||||
@ -49,7 +45,7 @@ public class SkillList extends EditableInventory {
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
RegisteredSkill selected = inv.selected.getSkill();
|
||||
RegisteredSkill selected = inv.selected == null ? null : inv.selected.getSkill();
|
||||
Placeholders holders = new Placeholders();
|
||||
|
||||
holders.register("skill_caps", selected.getName().toUpperCase());
|
||||
@ -58,11 +54,6 @@ public class SkillList extends EditableInventory {
|
||||
|
||||
return holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return !inv.binding;
|
||||
}
|
||||
};
|
||||
|
||||
if (function.equals("slot"))
|
||||
@ -74,7 +65,7 @@ public class SkillList extends EditableInventory {
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
RegisteredSkill selected = inv.selected.getSkill();
|
||||
RegisteredSkill selected = inv.selected == null ? null : inv.selected.getSkill();
|
||||
RegisteredSkill skill = inv.getPlayerData().hasSkillBound(n) ? inv.getPlayerData().getBoundSkill(n).getSkill() : null;
|
||||
|
||||
Placeholders holders = new Placeholders();
|
||||
@ -82,7 +73,7 @@ public class SkillList extends EditableInventory {
|
||||
holders.register("skill", skill == null ? none : skill.getName());
|
||||
holders.register("index", "" + (n + 1));
|
||||
holders.register("slot", MMOCoreUtils.intToRoman(n + 1));
|
||||
holders.register("selected", selected.getName());
|
||||
holders.register("selected", selected == null ? none : selected.getName());
|
||||
|
||||
return holders;
|
||||
}
|
||||
@ -102,16 +93,29 @@ public class SkillList extends EditableInventory {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return inv.binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDifferentDisplay() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
if (function.equals("previous"))
|
||||
return new SimplePlaceholderItem<SkillViewerInventory>(config) {
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return inv.page > 0;
|
||||
}
|
||||
};
|
||||
if (function.equals("next")) {
|
||||
return new SimplePlaceholderItem<SkillViewerInventory>(config) {
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
final int perPage = inv.skillSlots.size();
|
||||
return inv.page < (inv.skills.size() - 1) / perPage;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return new SimplePlaceholderItem(config);
|
||||
}
|
||||
@ -120,30 +124,6 @@ public class SkillList extends EditableInventory {
|
||||
return new SkillViewerInventory(data, this);
|
||||
}
|
||||
|
||||
public class SwitchItem extends SimplePlaceholderItem<SkillViewerInventory> {
|
||||
private final SimplePlaceholderItem binding, upgrading;
|
||||
|
||||
public SwitchItem(ConfigurationSection config) {
|
||||
super(config);
|
||||
|
||||
Validate.isTrue(config.contains("binding"), "Config must have 'binding'");
|
||||
Validate.isTrue(config.contains("upgrading"), "Config must have 'upgrading'");
|
||||
|
||||
binding = new SimplePlaceholderItem(config.getConfigurationSection("binding"));
|
||||
upgrading = new SimplePlaceholderItem(config.getConfigurationSection("upgrading"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
return inv.binding ? upgrading.display(inv) : binding.display(inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class LevelItem extends InventoryItem<SkillViewerInventory> {
|
||||
private final int offset;
|
||||
|
||||
@ -193,20 +173,11 @@ public class SkillList extends EditableInventory {
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
return new Placeholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return !inv.binding;
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillItem extends InventoryItem<SkillViewerInventory> {
|
||||
private final int selectedSkillSlot;
|
||||
|
||||
public SkillItem(ConfigurationSection config) {
|
||||
super(Material.BARRIER, config);
|
||||
|
||||
selectedSkillSlot = config.getInt("selected-slot");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -217,15 +188,17 @@ public class SkillList extends EditableInventory {
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
|
||||
/*
|
||||
* calculate placeholders
|
||||
*/
|
||||
ClassSkill skill = inv.skills.get(mod(n + inv.getPlayerData().skillGuiDisplayOffset, inv.skills.size()));
|
||||
// Calculate placeholders
|
||||
int index = n + inv.skillSlots.size() * inv.page;
|
||||
if (index >= inv.skills.size())
|
||||
return new ItemStack(Material.AIR);
|
||||
|
||||
ClassSkill skill = inv.skills.get(index);
|
||||
Placeholders holders = getPlaceholders(inv.getPlayerData(), skill);
|
||||
|
||||
List<String> lore = new ArrayList<>(getLore());
|
||||
|
||||
int index = lore.indexOf("{lore}");
|
||||
index = lore.indexOf("{lore}");
|
||||
lore.remove(index);
|
||||
List<String> skillLore = skill.calculateLore(inv.getPlayerData());
|
||||
for (int j = 0; j < skillLore.size(); j++)
|
||||
@ -238,9 +211,7 @@ public class SkillList extends EditableInventory {
|
||||
for (int j = 0; j < lore.size(); j++)
|
||||
lore.set(j, ChatColor.GRAY + holders.apply(inv.getPlayer(), lore.get(j)));
|
||||
|
||||
/*
|
||||
* generate item
|
||||
*/
|
||||
// Generate item
|
||||
ItemStack item = skill.getSkill().getIcon();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(holders.apply(inv.getPlayer(), getName()));
|
||||
@ -272,8 +243,9 @@ public class SkillList extends EditableInventory {
|
||||
private final List<Integer> skillSlots;
|
||||
private final List<Integer> slotSlots;
|
||||
|
||||
private boolean binding;
|
||||
//The skill the player Selected
|
||||
private ClassSkill selected;
|
||||
private int page = 0;
|
||||
|
||||
public SkillViewerInventory(PlayerData playerData, EditableInventory editable) {
|
||||
super(playerData, editable);
|
||||
@ -281,24 +253,23 @@ public class SkillList extends EditableInventory {
|
||||
skills = new ArrayList<>(playerData.getProfess().getSkills());
|
||||
skillSlots = getEditable().getByFunction("skill").getSlots();
|
||||
slotSlots = getEditable().getByFunction("slot").getSlots();
|
||||
selected = skills.get(page * skillSlots.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String calculateName() {
|
||||
return getName();
|
||||
return getName().replace("{skill}", selected.getSkill().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
int selectedSkillSlot = ((SkillItem) getEditable().getByFunction("skill")).selectedSkillSlot;
|
||||
selected = skills.get(mod(selectedSkillSlot + playerData.skillGuiDisplayOffset, skills.size()));
|
||||
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
|
||||
|
||||
/*
|
||||
if (skillSlots.contains(event.getRawSlot())
|
||||
&& event.getRawSlot() != ((SkillItem) getEditable().getByFunction("skill")).selectedSkillSlot) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
@ -306,24 +277,26 @@ public class SkillList extends EditableInventory {
|
||||
open();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if (item.getFunction().equals("skill")) {
|
||||
int index = skillSlots.size() * page + skillSlots.indexOf(event.getRawSlot());
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
selected = skills.get(index);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("previous")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset - 1) % skills.size();
|
||||
page--;
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("next")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset + 1) % skills.size();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("switch")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
binding = !binding;
|
||||
page++;
|
||||
open();
|
||||
return;
|
||||
}
|
||||
@ -331,51 +304,50 @@ public class SkillList extends EditableInventory {
|
||||
/*
|
||||
* binding or unbinding skills.
|
||||
*/
|
||||
if (binding) {
|
||||
for (int index = 0; index < slotSlots.size(); index++) {
|
||||
int slot = slotSlots.get(index);
|
||||
if (event.getRawSlot() == slot) {
|
||||
if (item.getFunction().equals("slot")) {
|
||||
int index = slotSlots.indexOf(event.getRawSlot());
|
||||
|
||||
// unbind if there is a current spell.
|
||||
if (event.getAction() == InventoryAction.PICKUP_HALF) {
|
||||
if (!playerData.hasSkillBound(index)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("no-skill-bound").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 2);
|
||||
playerData.unbindSkill(index);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected == null)
|
||||
return;
|
||||
|
||||
if (selected.getSkill().getTrigger().isPassive()) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-active-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerData.hasSkillUnlocked(selected)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 2);
|
||||
playerData.setBoundSkill(index, selected);
|
||||
open();
|
||||
// unbind if there is a current spell.
|
||||
if (event.getAction() == InventoryAction.PICKUP_HALF) {
|
||||
if (!playerData.hasSkillBound(index)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("no-skill-bound").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 2);
|
||||
playerData.unbindSkill(index);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* upgrading a player skill
|
||||
*/
|
||||
} else if (item.getFunction().equals("upgrade")) {
|
||||
if (selected == null)
|
||||
return;
|
||||
|
||||
if (selected.getSkill().getTrigger().isPassive()) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-active-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerData.hasSkillUnlocked(selected)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 2);
|
||||
playerData.setBoundSkill(index, selected);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upgrading a player skill
|
||||
*/
|
||||
if (item.getFunction().equals("upgrade")) {
|
||||
if (!playerData.hasSkillUnlocked(selected)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
@ -402,6 +374,7 @@ public class SkillList extends EditableInventory {
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int mod(int x, int n) {
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.Indyuce.mmocore.gui;
|
||||
|
||||
import io.lumine.mythic.lib.api.item.ItemTag;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerActivity;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
@ -10,18 +8,24 @@ import net.Indyuce.mmocore.gui.api.GeneratedInventory;
|
||||
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
|
||||
import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
||||
import net.Indyuce.mmocore.waypoint.CostType;
|
||||
import net.Indyuce.mmocore.waypoint.Waypoint;
|
||||
import net.Indyuce.mmocore.waypoint.WaypointOption;
|
||||
import net.Indyuce.mmocore.waypoint.WaypointPath;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Map;
|
||||
|
||||
public class WaypointViewer extends EditableInventory {
|
||||
public WaypointViewer() {
|
||||
@ -65,7 +69,7 @@ public class WaypointViewer extends EditableInventory {
|
||||
|
||||
public class WaypointItem extends SimplePlaceholderItem<WaypointViewerInventory> {
|
||||
private final SimplePlaceholderItem noWaypoint, locked;
|
||||
private final WaypointItemHandler availWaypoint, notLinked, notDynamic, noStellium;
|
||||
private final WaypointItemHandler availWaypoint, noStellium, notLinked, notDynamic, currentWayPoint;
|
||||
|
||||
public WaypointItem(ConfigurationSection config) {
|
||||
super(Material.BARRIER, config);
|
||||
@ -74,15 +78,17 @@ public class WaypointViewer extends EditableInventory {
|
||||
Validate.notNull(config.getConfigurationSection("locked"), "Could not load 'locked' config");
|
||||
Validate.notNull(config.getConfigurationSection("not-a-destination"), "Could not load 'not-a-destination' config");
|
||||
Validate.notNull(config.getConfigurationSection("not-dynamic"), "Could not load 'not-dynamic' config");
|
||||
Validate.notNull(config.getConfigurationSection("current-waypoint"), "Could not load 'current-waypoint' config");
|
||||
Validate.notNull(config.getConfigurationSection("not-enough-stellium"), "Could not load 'not-enough-stellium' config");
|
||||
Validate.notNull(config.getConfigurationSection("display"), "Could not load 'display' config");
|
||||
|
||||
noWaypoint = new SimplePlaceholderItem(config.getConfigurationSection("no-waypoint"));
|
||||
locked = new SimplePlaceholderItem(config.getConfigurationSection("locked"));
|
||||
notLinked = new WaypointItemHandler(config.getConfigurationSection("not-a-destination"));
|
||||
notDynamic = new WaypointItemHandler(config.getConfigurationSection("not-dynamic"));
|
||||
noStellium = new WaypointItemHandler(config.getConfigurationSection("not-enough-stellium"));
|
||||
availWaypoint = new WaypointItemHandler(config.getConfigurationSection("display"));
|
||||
notLinked = new WaypointItemHandler(config.getConfigurationSection("not-a-destination"), true);
|
||||
notDynamic = new WaypointItemHandler(config.getConfigurationSection("not-dynamic"), true);
|
||||
currentWayPoint = new WaypointItemHandler(config.getConfigurationSection("current-waypoint"), true);
|
||||
noStellium = new WaypointItemHandler(config.getConfigurationSection("not-enough-stellium"), false);
|
||||
availWaypoint = new WaypointItemHandler(config.getConfigurationSection("display"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,19 +105,22 @@ public class WaypointViewer extends EditableInventory {
|
||||
|
||||
// Locked waypoint?
|
||||
Waypoint waypoint = inv.waypoints.get(index);
|
||||
if (inv.current != null && inv.current.equals(waypoint))
|
||||
return currentWayPoint.display(inv, n);
|
||||
|
||||
if (!inv.getPlayerData().hasWaypoint(waypoint))
|
||||
return locked.display(inv, n);
|
||||
|
||||
// Waypoints are not linked
|
||||
if (inv.current != null && !inv.current.hasDestination(waypoint))
|
||||
if (inv.current != null && !inv.paths.containsKey(waypoint))
|
||||
return notLinked.display(inv, n);
|
||||
|
||||
// Not dynamic waypoint
|
||||
if (inv.current == null && !waypoint.hasOption(WaypointOption.DYNAMIC))
|
||||
if (inv.current == null && !inv.paths.containsKey(waypoint))
|
||||
return notDynamic.display(inv, n);
|
||||
|
||||
// Stellium cost
|
||||
if (waypoint.getCost(inv.current == null ? CostType.DYNAMIC_USE : CostType.NORMAL_USE) > inv.getPlayerData().getStellium())
|
||||
//Normal cost
|
||||
if (inv.paths.get(waypoint).getCost() > inv.getPlayerData().getStellium())
|
||||
return noStellium.display(inv, n);
|
||||
|
||||
return availWaypoint.display(inv, n);
|
||||
@ -119,8 +128,11 @@ public class WaypointViewer extends EditableInventory {
|
||||
}
|
||||
|
||||
public class WaypointItemHandler extends InventoryItem<WaypointViewerInventory> {
|
||||
public WaypointItemHandler(ConfigurationSection config) {
|
||||
private final boolean onlyName;
|
||||
|
||||
public WaypointItemHandler(ConfigurationSection config, boolean onlyName) {
|
||||
super(config);
|
||||
this.onlyName = onlyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -129,7 +141,21 @@ public class WaypointViewer extends EditableInventory {
|
||||
|
||||
// If a player can teleport to another waypoint given his location
|
||||
Waypoint waypoint = inv.waypoints.get(inv.page * inv.getEditable().getByFunction("waypoint").getSlots().size() + n);
|
||||
return NBTItem.get(disp).addTag(new ItemTag("waypointId", waypoint.getId())).toItem();
|
||||
ItemMeta meta = disp.getItemMeta();
|
||||
|
||||
// Add waypoint lore if not empty
|
||||
if (!waypoint.getLore().isEmpty()) {
|
||||
List<String> lore = meta.getLore();
|
||||
Placeholders placeholders = new Placeholders();
|
||||
for (String str : waypoint.getLore())
|
||||
lore.add(0, ChatColor.GRAY + placeholders.apply(inv.getPlayer(), str));
|
||||
meta.setLore(lore);
|
||||
}
|
||||
|
||||
PersistentDataContainer container = meta.getPersistentDataContainer();
|
||||
container.set(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING, waypoint.getId());
|
||||
disp.setItemMeta(meta);
|
||||
return disp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -138,9 +164,12 @@ public class WaypointViewer extends EditableInventory {
|
||||
|
||||
Waypoint waypoint = inv.waypoints.get(inv.page * inv.getByFunction("waypoint").getSlots().size() + n);
|
||||
holders.register("name", waypoint.getName());
|
||||
holders.register("current_cost", decimal.format(waypoint.getCost(inv.waypointCostType)));
|
||||
holders.register("normal_cost", decimal.format(waypoint.getCost(CostType.NORMAL_USE)));
|
||||
holders.register("dynamic_cost", decimal.format(waypoint.getCost(CostType.DYNAMIC_USE)));
|
||||
if (!onlyName) {
|
||||
holders.register("current_cost", inv.paths.get(waypoint).getCost());
|
||||
holders.register("normal_cost", decimal.format(inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).getCost() : Double.POSITIVE_INFINITY));
|
||||
holders.register("dynamic_cost", decimal.format(waypoint.getDynamicCost()));
|
||||
holders.register("intermediary_waypoints", inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).displayIntermediaryWayPoints(inv.isDynamicUse()) : "None");
|
||||
}
|
||||
|
||||
return holders;
|
||||
}
|
||||
@ -148,8 +177,9 @@ public class WaypointViewer extends EditableInventory {
|
||||
|
||||
public class WaypointViewerInventory extends GeneratedInventory {
|
||||
private final List<Waypoint> waypoints = new ArrayList<>(MMOCore.plugin.waypointManager.getAll());
|
||||
@Nullable
|
||||
private final Waypoint current;
|
||||
private final CostType waypointCostType;
|
||||
private final Map<Waypoint, WaypointPath> paths = new HashMap<>();
|
||||
|
||||
private int page;
|
||||
|
||||
@ -157,7 +187,29 @@ public class WaypointViewer extends EditableInventory {
|
||||
super(playerData, editable);
|
||||
|
||||
this.current = current;
|
||||
this.waypointCostType = current == null ? CostType.DYNAMIC_USE : CostType.NORMAL_USE;
|
||||
if (current != null)
|
||||
for (WaypointPath pathInfo : current.getAllPath())
|
||||
paths.put(pathInfo.getFinalWaypoint(), pathInfo);
|
||||
|
||||
if (current == null) {
|
||||
|
||||
//Iterate through all the dynamic points and find all the points it is linked to and the path
|
||||
HashMap<Waypoint, Double> dynamicPoints = new HashMap<>();
|
||||
//We first check all the dynamic waypoints
|
||||
for (Waypoint waypoint : waypoints) {
|
||||
if (waypoint.mayBeUsedDynamically(playerData.getPlayer())) {
|
||||
paths.put(waypoint, new WaypointPath(waypoint, waypoint.getDynamicCost()));
|
||||
dynamicPoints.put(waypoint, waypoint.getDynamicCost());
|
||||
}
|
||||
}
|
||||
for (Waypoint source : dynamicPoints.keySet()) {
|
||||
for (WaypointPath target : source.getAllPath()) {
|
||||
if (!paths.containsKey(target.getFinalWaypoint()) || paths.get(target.getFinalWaypoint()).getCost() > target.getCost() + dynamicPoints.get(source)) {
|
||||
paths.put(target.getFinalWaypoint(), target.addCost(dynamicPoints.get(source)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -165,6 +217,10 @@ public class WaypointViewer extends EditableInventory {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public boolean isDynamicUse() {
|
||||
return current == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
|
||||
if (item.getFunction().equals("next")) {
|
||||
@ -180,7 +236,10 @@ public class WaypointViewer extends EditableInventory {
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("waypoint")) {
|
||||
String tag = NBTItem.get(event.getCurrentItem()).getString("waypointId");
|
||||
PersistentDataContainer container = event.getCurrentItem().getItemMeta().getPersistentDataContainer();
|
||||
String tag = container.has(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) ?
|
||||
container.get(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) : "";
|
||||
|
||||
if (tag.equals(""))
|
||||
return;
|
||||
|
||||
@ -198,20 +257,20 @@ public class WaypointViewer extends EditableInventory {
|
||||
}
|
||||
|
||||
// Waypoint does not have target as destination
|
||||
if (current != null && !current.hasDestination(waypoint)) {
|
||||
if (current != null && current.getPath(waypoint) == null) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("cannot-teleport-to").send(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Not dynamic waypoint
|
||||
if (current == null && !waypoint.hasOption(WaypointOption.DYNAMIC)) {
|
||||
if (current == null && !paths.containsKey(waypoint)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-dynamic-waypoint").send(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Stellium cost
|
||||
CostType costType = current == null ? CostType.DYNAMIC_USE : CostType.NORMAL_USE;
|
||||
double left = waypoint.getCost(costType) - playerData.getStellium();
|
||||
double withdraw = paths.get(waypoint).getCost();
|
||||
double left = withdraw - playerData.getStellium();
|
||||
if (left > 0) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-enough-stellium", "more", decimal.format(left)).send(player);
|
||||
return;
|
||||
@ -221,7 +280,8 @@ public class WaypointViewer extends EditableInventory {
|
||||
return;
|
||||
|
||||
player.closeInventory();
|
||||
playerData.warp(waypoint, costType);
|
||||
playerData.warp(waypoint, withdraw);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public abstract class GeneratedInventory extends PluginInventory {
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
Inventory inv = Bukkit.createInventory(this, editable.getSlots(), MythicLib.plugin.parseColors(calculateName()));
|
||||
Inventory inv = Bukkit.createInventory(this, editable.getSlots(), MythicLib.plugin.getPlaceholderParser().parse(getPlayer(), calculateName()));
|
||||
|
||||
for (InventoryItem item : editable.getItems())
|
||||
if (item.canDisplay(this))
|
||||
|
@ -11,7 +11,7 @@ import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.experience.source.MineBlockExperienceSource;
|
||||
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
@ -52,7 +52,7 @@ public class ClassTriggers implements Listener {
|
||||
public void onAttack(PlayerAttackEvent event) {
|
||||
for (Map.Entry<DamageType, ClassTriggerType> entry : damageTriggers.entrySet())
|
||||
if (event.getDamage().hasType(entry.getKey()))
|
||||
applyTriggers(event.getPlayer(), entry.getValue()); //, () -> new TriggerMetadata(event.getAttack(), event.getEntity())
|
||||
applyTriggers(event.getPlayer(), entry.getValue(), () -> new TriggerMetadata(event.getAttack(), event.getEntity()));
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
@ -88,6 +88,16 @@ public class ClassTriggers implements Listener {
|
||||
return applyTriggers(PlayerData.get(player), type, triggerMetaProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply class shortcut skills from a specific class trigger type.
|
||||
*
|
||||
* @param player Player triggering
|
||||
* @param type Trigger type
|
||||
* @param triggerMetaProvider Small optimization: if no shortcut skill is found
|
||||
* with the corresponding trigger type, trigger meta
|
||||
* is not calculated which saves computations
|
||||
* @return Skill result or null if no shortcut skill was cast
|
||||
*/
|
||||
@Nullable
|
||||
private SkillResult applyTriggers(PlayerData player, ClassTriggerType type, Provider<TriggerMetadata> triggerMetaProvider) {
|
||||
ClassTrigger trigger = player.getProfess().getClassTrigger(type);
|
||||
|
@ -1,22 +1,36 @@
|
||||
package net.Indyuce.mmocore.listener;
|
||||
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.loot.chest.LootChest;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
|
||||
public class LootableChestsListener implements Listener {
|
||||
@EventHandler
|
||||
public void a(InventoryCloseEvent event) {
|
||||
if (!(event.getInventory().getHolder() instanceof Chest))
|
||||
return;
|
||||
|
||||
Chest chest = (Chest) event.getInventory().getHolder();
|
||||
LootChest lootChest = MMOCore.plugin.lootChests.getChest(chest.getLocation());
|
||||
if (lootChest != null)
|
||||
lootChest.expire(true);
|
||||
}
|
||||
@EventHandler
|
||||
public void expireOnClose(InventoryCloseEvent event) {
|
||||
if (!(event.getInventory().getHolder() instanceof Chest))
|
||||
return;
|
||||
|
||||
Chest chest = (Chest) event.getInventory().getHolder();
|
||||
LootChest lootChest = MMOCore.plugin.lootChests.getChest(chest.getLocation());
|
||||
if (lootChest != null)
|
||||
lootChest.expire(true);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
|
||||
public void noBreaking(BlockBreakEvent event) {
|
||||
Block block = event.getBlock();
|
||||
if (block.getType() == Material.CHEST) {
|
||||
LootChest lootChest = MMOCore.plugin.lootChests.getChest(block.getLocation());
|
||||
if (lootChest != null)
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,19 @@ public class WaypointsListener implements Listener {
|
||||
return;
|
||||
|
||||
NBTItem nbtItem = NBTItem.get(event.getItem());
|
||||
if (Objects.equals(nbtItem.getString("MMOCoreItemId"), "WAYPOINT_BOOK"))
|
||||
InventoryManager.WAYPOINTS.newInventory(PlayerData.get(event.getPlayer())).open();
|
||||
if (Objects.equals(nbtItem.getString("MMOCoreItemId"), "WAYPOINT_BOOK")) {
|
||||
String waypointId = nbtItem.getString("WaypointBookId");
|
||||
Waypoint waypoint = MMOCore.plugin.waypointManager.get(waypointId);
|
||||
if (waypoint == null)
|
||||
return;
|
||||
|
||||
PlayerData playerData = PlayerData.get(event.getPlayer());
|
||||
if (playerData.hasWaypoint(waypoint))
|
||||
return;
|
||||
|
||||
playerData.unlockWaypoint(waypoint);
|
||||
event.getItem().setAmount(event.getItem().getAmount() - 1); // Consume item
|
||||
MMOCore.plugin.configManager.getSimpleMessage("new-waypoint-book", "waypoint", waypoint.getName()).send(event.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class RedirectVanillaExp implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerExpChangeEvent event) {
|
||||
int a = (int) (event.getAmount() * ratio);
|
||||
double a = (event.getAmount() * ratio);
|
||||
if (a > 0)
|
||||
PlayerData.get(event.getPlayer()).giveExperience(a, EXPSource.VANILLA);
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.event.CustomPlayerFishEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||
@ -80,11 +79,11 @@ public class FishingListener implements Listener {
|
||||
|
||||
public FishingData(Player player, FishHook hook, FishingDropTable table) {
|
||||
this.location = hook.getLocation();
|
||||
this.caught = table.getRandomItem();
|
||||
this.caught = table.getRandomItem(PlayerData.get(player));
|
||||
this.playerData = PlayerData.get(this.player = player);
|
||||
this.hook = hook;
|
||||
|
||||
this.fishStrength = (int) Math.floor(caught.rollTugs() * (1 - PlayerData.get(player).getStats().getStat(StatType.FISHING_STRENGTH) / 100));
|
||||
this.fishStrength = (int) Math.floor(caught.rollTugs() * (1 - PlayerData.get(player).getStats().getStat("FISHING_STRENGTH") / 100));
|
||||
this.experienceDropped = caught.rollExperience();
|
||||
|
||||
fishing.add(player.getUniqueId());
|
||||
@ -148,7 +147,7 @@ public class FishingListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentPulls == 0 && RANDOM.nextDouble() < PlayerData.get(player).getStats().getStat(StatType.CRITICAL_FISHING_CHANCE) / 100)
|
||||
if (currentPulls == 0 && RANDOM.nextDouble() < PlayerData.get(player).getStats().getStat("CRITICAL_FISHING_CHANCE") / 100)
|
||||
setCriticalFish();
|
||||
|
||||
// Check if enough pulls; if not, wait till the next fish event
|
||||
@ -165,7 +164,7 @@ public class FishingListener implements Listener {
|
||||
(mainhand != null && mainhand.getType() == Material.FISHING_ROD) ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND, 1);
|
||||
|
||||
// Critical fishing failure
|
||||
if (!isCriticalFish() && RANDOM.nextDouble() < PlayerData.get(player).getStats().getStat(StatType.CRITICAL_FISHING_FAILURE_CHANCE) / 100) {
|
||||
if (!isCriticalFish() && RANDOM.nextDouble() < PlayerData.get(player).getStats().getStat("CRITICAL_FISHING_FAILURE_CHANCE") / 100) {
|
||||
player.setVelocity(hook.getLocation().subtract(player.getLocation()).toVector().setY(0).multiply(3).setY(.5));
|
||||
hook.getWorld().spawnParticle(Particle.SMOKE_NORMAL, location, 24, 0, 0, 0, .08);
|
||||
return;
|
||||
|
@ -1,7 +1,8 @@
|
||||
package net.Indyuce.mmocore.listener.profession;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import net.Indyuce.mmocore.api.event.CustomBlockMineEvent;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -11,10 +12,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import net.Indyuce.mmocore.api.event.CustomBlockMineEvent;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import java.util.Random;
|
||||
|
||||
public class PlayerCollectStats implements Listener {
|
||||
private static final Random random = new Random();
|
||||
@ -23,26 +21,26 @@ public class PlayerCollectStats implements Listener {
|
||||
public void a(CustomBlockMineEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
// give haste if right enchant
|
||||
double h = event.getData().getStats().getStat(StatType.GATHERING_HASTE);
|
||||
// Give haste if right enchant
|
||||
double h = event.getData().getStats().getStat("GATHERING_HASTE");
|
||||
if (h > 0 && random.nextDouble() < h * .045) {
|
||||
new SmallParticleEffect(player, Particle.SPELL_INSTANT);
|
||||
player.removePotionEffect(PotionEffectType.FAST_DIGGING);
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.FAST_DIGGING, (int) (10 * h), (int) (1 + h / 7)));
|
||||
}
|
||||
|
||||
// drop more items if fortune enchant
|
||||
double f = event.getData().getStats().getStat(StatType.FORTUNE);
|
||||
// Drop more items if fortune enchant
|
||||
double f = event.getData().getStats().getStat("FORTUNE");
|
||||
if (f > 0 && random.nextDouble() < f * .045) {
|
||||
int a = (int) (1.5 * Math.sqrt(f / 1.1));
|
||||
for (ItemStack item : event.getDrops())
|
||||
item.setAmount(item.getAmount() + a);
|
||||
}
|
||||
|
||||
if(MythicLib.plugin.getVersion().getWrapper().isCropFullyGrown(event.getBlock()))
|
||||
{
|
||||
// drop more items if fortune enchant
|
||||
double l = event.getData().getStats().getStat(StatType.LUCK_OF_THE_FIELD);
|
||||
if (MythicLib.plugin.getVersion().getWrapper().isCropFullyGrown(event.getBlock())) {
|
||||
|
||||
// Drop more CROP items
|
||||
double l = event.getData().getStats().getStat("LUCK_OF_THE_FIELD");
|
||||
if (l > 0 && random.nextDouble() < l * .045) {
|
||||
int a = (int) (1.5 * Math.sqrt(l / 1.1));
|
||||
Location loc = event.getBlock().getLocation().add(.5, .1, .5);
|
||||
|
@ -10,8 +10,7 @@ public class ChestTier {
|
||||
private final TierEffect effect;
|
||||
private final ScalingFormula capacity;
|
||||
private final DropTable table;
|
||||
|
||||
public final double chance;
|
||||
private final double chance;
|
||||
|
||||
public ChestTier(ConfigurationSection config) {
|
||||
effect = config.isConfigurationSection("effect") ? new TierEffect(config.getConfigurationSection("effect")) : null;
|
||||
@ -24,6 +23,10 @@ public class ChestTier {
|
||||
return capacity.calculate(player.getLevel());
|
||||
}
|
||||
|
||||
public double getChance() {
|
||||
return chance;
|
||||
}
|
||||
|
||||
public DropTable getDropTable() {
|
||||
return table;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package net.Indyuce.mmocore.loot.chest;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.util.HashableLocation;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -9,7 +10,6 @@ import org.bukkit.Particle;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -20,7 +20,7 @@ public class LootChest {
|
||||
private final ReplacedBlock block;
|
||||
@Nullable
|
||||
private final BukkitRunnable effectRunnable;
|
||||
private final long date = System.currentTimeMillis();
|
||||
private final BukkitRunnable closeRunnable;
|
||||
|
||||
private boolean active = true;
|
||||
|
||||
@ -36,6 +36,13 @@ public class LootChest {
|
||||
this.region = region;
|
||||
this.block = new ReplacedBlock(block);
|
||||
this.effectRunnable = tier.hasEffect() ? tier.getEffect().startNewRunnable(block.getLocation().add(.5, .5, .5)) : null;
|
||||
closeRunnable = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
expire(false);
|
||||
}
|
||||
};
|
||||
closeRunnable.runTaskLater(MMOCore.plugin, MMOCore.plugin.configManager.lootChestExpireTime);
|
||||
}
|
||||
|
||||
public ChestTier getTier() {
|
||||
@ -50,15 +57,8 @@ public class LootChest {
|
||||
return region;
|
||||
}
|
||||
|
||||
public boolean hasPlayerNearby() {
|
||||
for (Player player : block.loc.getWorld().getPlayers())
|
||||
if (player.getLocation().distanceSquared(block.loc) < 625)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldExpire() {
|
||||
return System.currentTimeMillis() - date > MMOCore.plugin.configManager.lootChestExpireTime;
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,10 +76,14 @@ public class LootChest {
|
||||
Validate.isTrue(active, "Chest has already expired");
|
||||
active = false;
|
||||
|
||||
// Close runnable
|
||||
if (!closeRunnable.isCancelled())
|
||||
closeRunnable.cancel();
|
||||
|
||||
// If a player is responsible of closing the chest, close it with sound
|
||||
if (player) {
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.CLOSE_LOOT_CHEST).playAt(block.loc);
|
||||
block.loc.getWorld().spawnParticle(Particle.CRIT, block.loc.clone().add(.5, .5, .5), 16, 0, 0, 0, .5);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.CLOSE_LOOT_CHEST).playAt(block.loc.bukkit());
|
||||
block.loc.getWorld().spawnParticle(Particle.CRIT, block.loc.bukkit().add(.5, .5, .5), 16, 0, 0, 0, .5);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -87,7 +91,7 @@ public class LootChest {
|
||||
* off and accumulate on the ground (+during dev phase)
|
||||
*/
|
||||
else
|
||||
((Chest) block.loc.getBlock().getState()).getBlockInventory().clear();
|
||||
((Chest) block.loc.bukkit().getBlock().getState()).getBlockInventory().clear();
|
||||
|
||||
block.restore();
|
||||
if (effectRunnable != null)
|
||||
@ -97,22 +101,28 @@ public class LootChest {
|
||||
public static class ReplacedBlock {
|
||||
private final Material material;
|
||||
private final BlockData data;
|
||||
private final Location loc;
|
||||
private final HashableLocation loc;
|
||||
|
||||
public ReplacedBlock(Block block) {
|
||||
this.material = block.getType();
|
||||
this.data = block.getBlockData();
|
||||
this.loc = block.getLocation();
|
||||
this.loc = new HashableLocation(block.getLocation());
|
||||
}
|
||||
|
||||
public HashableLocation getLocation() {
|
||||
return loc;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean matches(Location loc) {
|
||||
return this.loc.getWorld().equals(loc.getWorld()) && this.loc.getBlockX() == loc.getBlockX() && this.loc.getBlockY() == loc.getBlockY()
|
||||
&& this.loc.getBlockZ() == loc.getBlockZ();
|
||||
return this.loc.getWorld().equals(loc.getWorld()) && this.loc.getX() == loc.getBlockX() && this.loc.getY() == loc.getBlockY()
|
||||
&& this.loc.getZ() == loc.getBlockZ();
|
||||
}
|
||||
|
||||
public void restore() {
|
||||
loc.getBlock().setType(material);
|
||||
loc.getBlock().setBlockData(data);
|
||||
Block block = loc.bukkit().getBlock();
|
||||
block.setType(material);
|
||||
block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import org.bukkit.block.Chest;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
@ -33,7 +34,7 @@ public class LootChestRegion {
|
||||
}
|
||||
};
|
||||
|
||||
private static final Random random = new Random();
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
public LootChestRegion(ConfigurationSection config) {
|
||||
Validate.notNull(config, "Could not load config");
|
||||
@ -85,7 +86,7 @@ public class LootChestRegion {
|
||||
player.setLastActivity(PlayerActivity.LOOT_CHEST_SPAWN);
|
||||
|
||||
// First randomly determine the chest tier
|
||||
ChestTier tier = rollTier();
|
||||
ChestTier tier = rollTier(player);
|
||||
|
||||
// Find a random location, 20 trials max
|
||||
Location location = getRandomLocation(player.getPlayer().getLocation());
|
||||
@ -108,7 +109,7 @@ public class LootChestRegion {
|
||||
location.getBlock().setType(Material.CHEST);
|
||||
Chest chest = (Chest) location.getBlock().getState();
|
||||
tier.getDropTable().collect(builder).forEach(item -> {
|
||||
Integer slot = slots.get(random.nextInt(slots.size()));
|
||||
Integer slot = slots.get(RANDOM.nextInt(slots.size()));
|
||||
chest.getInventory().setItem(slot, item);
|
||||
slots.remove(slot);
|
||||
});
|
||||
@ -116,17 +117,39 @@ public class LootChestRegion {
|
||||
MMOCore.plugin.lootChests.register(lootChest);
|
||||
}
|
||||
|
||||
// TODO stat to increase chance to get higher tiers?
|
||||
public ChestTier rollTier() {
|
||||
/**
|
||||
* @param player Player rolling the tier
|
||||
* @return A randomly picked tiers taking into account tier spawn rates
|
||||
* and the player Chance attribute
|
||||
*/
|
||||
@NotNull
|
||||
public ChestTier rollTier(PlayerData player) {
|
||||
double chance = player.getStats().getStat("CHANCE") * MMOCore.plugin.configManager.lootChestsChanceWeight;
|
||||
|
||||
double s = 0;
|
||||
double sum = 0;
|
||||
for (ChestTier tier : tiers)
|
||||
sum += getTierCoefficient(tier.getChance(), chance);
|
||||
Validate.isTrue(sum > 0, "No chest tier was found");
|
||||
|
||||
double cummulated = 0;
|
||||
for (ChestTier tier : tiers) {
|
||||
if (random.nextDouble() < tier.chance / (1 - s))
|
||||
cummulated += getTierCoefficient(tier.getChance(), chance);
|
||||
if (RANDOM.nextDouble() < cummulated / sum)
|
||||
return tier;
|
||||
s += tier.chance;
|
||||
}
|
||||
|
||||
return tiers.stream().findAny().orElse(null);
|
||||
throw new RuntimeException("Could not roll chest tier");
|
||||
}
|
||||
|
||||
private static final double CHANCE_COEF = 7 / 100;
|
||||
|
||||
/**
|
||||
* - Chance = 0 | tier coefficient is left unchanged.
|
||||
* - Chance -> +oo | all tier coefficients are the same (1)
|
||||
* - Chance = 50 | coefficients become their square roots
|
||||
*/
|
||||
private double getTierCoefficient(double initialTierChance, double chance) {
|
||||
return Math.pow(initialTierChance, 1 / Math.pow(1 + CHANCE_COEF * chance, 1 / 3));
|
||||
}
|
||||
|
||||
public Location getRandomLocation(Location center) {
|
||||
@ -151,9 +174,9 @@ public class LootChestRegion {
|
||||
* Chooses a random direction and get the block in
|
||||
* that direction which has the same height as the player
|
||||
*/
|
||||
double a = random.nextDouble() * 2 * Math.PI;
|
||||
double a = RANDOM.nextDouble() * 2 * Math.PI;
|
||||
Vector dir = new Vector(Math.cos(a), 0, Math.sin(a))
|
||||
.multiply(algOptions.minRange + random.nextDouble() * (algOptions.maxRange - algOptions.minRange));
|
||||
.multiply(algOptions.minRange + RANDOM.nextDouble() * (algOptions.maxRange - algOptions.minRange));
|
||||
Location random = center.add(dir);
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||
package net.Indyuce.mmocore.loot.chest.condition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
@ -1,4 +1,4 @@
|
||||
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||
package net.Indyuce.mmocore.loot.chest.condition;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||
package net.Indyuce.mmocore.loot.chest.condition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
@ -0,0 +1,34 @@
|
||||
package net.Indyuce.mmocore.loot.chest.condition;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public class DistanceCondition extends Condition{
|
||||
private final Location location;
|
||||
private final double distance;
|
||||
|
||||
public DistanceCondition(MMOLineConfig config) {
|
||||
super(config);
|
||||
Validate.isTrue(config.contains("world"));
|
||||
Validate.isTrue(config.contains("x"));
|
||||
Validate.isTrue(config.contains("y"));
|
||||
Validate.isTrue(config.contains("z"));
|
||||
Validate.isTrue(config.contains("distance"));
|
||||
Validate.isTrue(Bukkit.getWorld(config.getString("world"))!=null,"This world doesn't exist");
|
||||
location=new Location(Bukkit.getWorld(config.getString("world")),config.getDouble("x"),
|
||||
config.getDouble("y"),config.getDouble("z"));
|
||||
distance=config.getDouble("distance");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMet(ConditionInstance entity) {
|
||||
Entity entity1=entity.getEntity();
|
||||
return entity1.getWorld().equals(location.getWorld())&&location.distance(entity1.getLocation())<distance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||
package net.Indyuce.mmocore.loot.chest.condition;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
@ -1,4 +1,4 @@
|
||||
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||
package net.Indyuce.mmocore.loot.chest.condition;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -15,8 +15,6 @@ public class PermissionCondition extends Condition {
|
||||
|
||||
@Override
|
||||
public boolean isMet(ConditionInstance entity) {
|
||||
if (entity.getEntity() instanceof Player)
|
||||
return entity.getEntity().hasPermission(perm);
|
||||
return false;
|
||||
return entity.getEntity() instanceof Player && entity.getEntity().hasPermission(perm);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.Indyuce.mmocore.loot.droptable.condition;
|
||||
package net.Indyuce.mmocore.loot.chest.condition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
@ -5,8 +5,8 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@ -73,7 +73,7 @@ public class DropTable extends PostLoadObject {
|
||||
public List<ItemStack> collect(LootBuilder builder) {
|
||||
|
||||
for (DropItem item : drops)
|
||||
if (item.rollChance() && builder.getCapacity() >= item.getWeight()) {
|
||||
if (item.rollChance(builder.getEntity()) && builder.getCapacity() >= item.getWeight()) {
|
||||
item.collect(builder);
|
||||
builder.reduceCapacity(item.getWeight());
|
||||
}
|
||||
|
@ -2,41 +2,45 @@ package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
|
||||
public abstract class DropItem {
|
||||
protected static final Random random = new Random();
|
||||
protected static final Random random = new Random();
|
||||
|
||||
private final double chance, weight;
|
||||
private final RandomAmount amount;
|
||||
private final double chance, weight;
|
||||
private final RandomAmount amount;
|
||||
|
||||
public DropItem(MMOLineConfig config) {
|
||||
chance = config.args().length > 0 ? Double.parseDouble(config.args()[0]) : 1;
|
||||
amount = config.args().length > 1 ? new RandomAmount(config.args()[1]) : new RandomAmount(1, 1);
|
||||
weight = config.args().length > 2 ? Double.parseDouble(config.args()[2]) : 0;
|
||||
}
|
||||
public DropItem(MMOLineConfig config) {
|
||||
chance = config.args().length > 0 ? Double.parseDouble(config.args()[0]) : 1;
|
||||
amount = config.args().length > 1 ? new RandomAmount(config.args()[1]) : new RandomAmount(1, 1);
|
||||
weight = config.args().length > 2 ? Double.parseDouble(config.args()[2]) : 0;
|
||||
}
|
||||
|
||||
public RandomAmount getAmount() {
|
||||
return amount;
|
||||
}
|
||||
public RandomAmount getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public double getChance() {
|
||||
return chance;
|
||||
}
|
||||
public double getChance() {
|
||||
return chance;
|
||||
}
|
||||
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
}
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public int rollAmount() {
|
||||
return amount.calculateInt();
|
||||
}
|
||||
public int rollAmount() {
|
||||
return amount.calculateInt();
|
||||
}
|
||||
|
||||
public boolean rollChance() {
|
||||
return random.nextDouble() < chance;
|
||||
}
|
||||
/**
|
||||
* If the player chance is 0 the random value will remain the same. When he get lucks the chance gets closer to one.
|
||||
*/
|
||||
public boolean rollChance(PlayerData player) {
|
||||
return Math.pow(random.nextDouble(), 1 / Math.log(1 + player.getStats().getStat("CHANCE"))) < chance;
|
||||
}
|
||||
|
||||
public abstract void collect(LootBuilder builder);
|
||||
public abstract void collect(LootBuilder builder);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package net.Indyuce.mmocore.loot.droptable.dropitem;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.loot.droptable.DropTable;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.LootBuilder;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
@ -27,6 +27,7 @@ public class ConfigManager {
|
||||
public String partyChatPrefix, noSkillBoundPlaceholder;
|
||||
public ChatColor staminaFull, staminaHalf, staminaEmpty;
|
||||
public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown;
|
||||
public double lootChestsChanceWeight;
|
||||
|
||||
private final FileConfiguration messages;
|
||||
private final boolean chatInput;
|
||||
@ -93,10 +94,11 @@ public class ConfigManager {
|
||||
chatInput = MMOCore.plugin.getConfig().getBoolean("use-chat-input");
|
||||
partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix");
|
||||
combatLogTimer = MMOCore.plugin.getConfig().getInt("combat-log.timer") * 1000L;
|
||||
lootChestExpireTime = Math.max(MMOCore.plugin.getConfig().getInt("loot-chests.chest-expire-time"), 1) * 1000L;
|
||||
lootChestExpireTime = Math.max(MMOCore.plugin.getConfig().getInt("loot-chests.chest-expire-time"), 1) * 20;
|
||||
lootChestPlayerCooldown = (long) MMOCore.plugin.getConfig().getDouble("player-cooldown") * 1000L;
|
||||
globalSkillCooldown = MMOCore.plugin.getConfig().getLong("global-skill-cooldown") * 50;
|
||||
noSkillBoundPlaceholder = getSimpleMessage("no-skill-placeholder").message();
|
||||
lootChestsChanceWeight = MMOCore.plugin.getConfig().getDouble("chance-stat-weight.loot-chests");
|
||||
|
||||
staminaFull = getColorOrDefault("stamina-whole", ChatColor.GREEN);
|
||||
staminaHalf = getColorOrDefault("stamina-half", ChatColor.DARK_GREEN);
|
||||
|
@ -1,33 +1,36 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.loot.chest.LootChest;
|
||||
import net.Indyuce.mmocore.loot.chest.LootChestRegion;
|
||||
import net.Indyuce.mmocore.util.HashableLocation;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class LootChestManager implements MMOCoreManager {
|
||||
|
||||
/**
|
||||
* Active loot chests in the server
|
||||
*/
|
||||
private final Set<LootChest> active = new HashSet<>();
|
||||
/**
|
||||
* Active loot chests in the server
|
||||
*/
|
||||
private final Map<HashableLocation, LootChest> active = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Registered loot chest regions
|
||||
*/
|
||||
private final Map<String, LootChestRegion> regions = new HashMap<>();
|
||||
/**
|
||||
* Registered loot chest regions
|
||||
*/
|
||||
private final Map<String, LootChestRegion> regions = new HashMap<>();
|
||||
|
||||
public boolean hasRegion(String id) {
|
||||
return regions.containsKey(id);
|
||||
}
|
||||
public boolean hasRegion(String id) {
|
||||
return regions.containsKey(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Region with specific identifier
|
||||
@ -38,48 +41,42 @@ public class LootChestManager implements MMOCoreManager {
|
||||
return Objects.requireNonNull(regions.get(id), "Could not find region with ID '" + id + "'");
|
||||
}
|
||||
|
||||
public Collection<LootChestRegion> getRegions() {
|
||||
return regions.values();
|
||||
}
|
||||
public Collection<LootChestRegion> getRegions() {
|
||||
return regions.values();
|
||||
}
|
||||
|
||||
public Set<LootChest> getActive() {
|
||||
return active;
|
||||
}
|
||||
public Collection<LootChest> getActive() {
|
||||
return active.values();
|
||||
}
|
||||
|
||||
public void register(LootChest chest) {
|
||||
active.add(chest);
|
||||
}
|
||||
public void register(LootChest chest) {
|
||||
active.put(chest.getBlock().getLocation(), chest);
|
||||
}
|
||||
|
||||
public void unregister(LootChest chest) {
|
||||
active.remove(chest);
|
||||
}
|
||||
public void unregister(LootChest chest) {
|
||||
active.remove(chest.getBlock().getLocation());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LootChest getChest(Location loc) {
|
||||
@Nullable
|
||||
public LootChest getChest(Location loc) {
|
||||
return active.get(new HashableLocation(loc));
|
||||
}
|
||||
|
||||
for (LootChest chest : active)
|
||||
if (chest.getBlock().matches(loc))
|
||||
return chest;
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
if (clearBefore) {
|
||||
regions.values().forEach(region -> region.getRunnable().cancel());
|
||||
regions.clear();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
if (clearBefore) {
|
||||
regions.values().forEach(region -> region.getRunnable().cancel());
|
||||
regions.clear();
|
||||
}
|
||||
|
||||
FileConfiguration config = new ConfigFile("loot-chests").getConfig();
|
||||
for (String key : config.getKeys(false))
|
||||
try {
|
||||
LootChestRegion region = new LootChestRegion(config.getConfigurationSection(key));
|
||||
regions.put(region.getId(), region);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING,
|
||||
"An error occured while trying to load loot chest region '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
FileConfiguration config = new ConfigFile("loot-chests").getConfig();
|
||||
for (String key : config.getKeys(false))
|
||||
try {
|
||||
LootChestRegion region = new LootChestRegion(config.getConfigurationSection(key));
|
||||
regions.put(region.getId(), region);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING,
|
||||
"An error occured while trying to load loot chest region '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import net.Indyuce.mmocore.api.block.BlockType;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
|
||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||
import net.Indyuce.mmocore.api.load.DefaultMMOLoader;
|
||||
|
71
src/main/java/net/Indyuce/mmocore/manager/StatManager.java
Normal file
71
src/main/java/net/Indyuce/mmocore/manager/StatManager.java
Normal file
@ -0,0 +1,71 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class StatManager implements MMOCoreManager {
|
||||
private final Map<String, StatInfo> loaded = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
if (clearBefore)
|
||||
loaded.clear();
|
||||
|
||||
FileConfiguration config = new ConfigFile("stats").getConfig();
|
||||
|
||||
// Read decimal formats
|
||||
for (String key : config.getConfigurationSection("decimal-format").getKeys(false))
|
||||
registerDecimalFormat(key, MythicLib.plugin.getMMOConfig().newDecimalFormat(config.getString("decimal-format." + key)));
|
||||
|
||||
// Read default formulas
|
||||
for (String key : config.getConfigurationSection("default").getKeys(false))
|
||||
registerDefaultFormula(key, new LinearValue(config.getConfigurationSection("default." + key)));
|
||||
}
|
||||
|
||||
public Collection<StatInfo> getLoaded() {
|
||||
return loaded.values();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StatInfo getInfo(String stat) {
|
||||
return loaded.get(stat);
|
||||
}
|
||||
|
||||
public void registerProfession(String stat, Profession profession) {
|
||||
compute(stat).profession = profession;
|
||||
}
|
||||
|
||||
public void registerDefaultFormula(String stat, LinearValue defaultFormula) {
|
||||
compute(stat).defaultInfo = defaultFormula;
|
||||
}
|
||||
|
||||
public void registerDecimalFormat(String stat, DecimalFormat format) {
|
||||
compute(stat).format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A stat info for the specified stat. If it doesn't
|
||||
* exist when method is called, it is registered into the map
|
||||
*/
|
||||
@NotNull
|
||||
private StatInfo compute(String stat) {
|
||||
StatInfo found = loaded.get(stat);
|
||||
if (found != null)
|
||||
return found;
|
||||
|
||||
StatInfo newInfo = new StatInfo(stat);
|
||||
loaded.put(stat, newInfo);
|
||||
return newInfo;
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ public class WaypointManager implements MMOCoreManager {
|
||||
return waypoints.containsKey(id);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Waypoint get(String id) {
|
||||
return waypoints.get(id);
|
||||
}
|
||||
@ -55,5 +56,12 @@ public class WaypointManager implements MMOCoreManager {
|
||||
} catch (RuntimeException exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not load waypoint '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
|
||||
for (Waypoint waypoint : waypoints.values())
|
||||
try {
|
||||
waypoint.postLoad();
|
||||
} catch (RuntimeException exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not post-load waypoint '" + waypoint.getId() + "': " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import net.Indyuce.mmocore.api.player.OfflinePlayerData;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
|
||||
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.guild.provided.Guild;
|
||||
import net.Indyuce.mmocore.manager.data.PlayerDataManager;
|
||||
import net.Indyuce.mmocore.manager.data.mysql.MySQLTableEditor.Table;
|
||||
@ -35,6 +34,13 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
|
||||
try {
|
||||
MMOCore.sqlDebug("Loading data for: '" + data.getUniqueId() + "'...");
|
||||
|
||||
// Initialize custom resources
|
||||
if (!data.hasUsedTemporaryData()) {
|
||||
data.setMana(data.getStats().getStat("MAX_MANA"));
|
||||
data.setStamina(data.getStats().getStat("MAX_STAMINA"));
|
||||
data.setStellium(data.getStats().getStat("MAX_STELLIUM"));
|
||||
}
|
||||
|
||||
if (!result.next()) {
|
||||
data.setLevel(getDefaultData().getLevel());
|
||||
data.setClassPoints(getDefaultData().getClassPoints());
|
||||
@ -44,12 +50,6 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
|
||||
data.setExperience(0);
|
||||
data.getQuestData().updateBossBar();
|
||||
|
||||
if (!data.hasUsedTemporaryData()) {
|
||||
data.setMana(data.getStats().getStat(StatType.MAX_MANA));
|
||||
data.setStamina(data.getStats().getStat(StatType.MAX_STAMINA));
|
||||
data.setStellium(data.getStats().getStat(StatType.MAX_STELLIUM));
|
||||
}
|
||||
|
||||
data.setFullyLoaded();
|
||||
MMOCore.sqlDebug("Loaded DEFAULT data for: '" + data.getUniqueId() + "' as no saved data was found.");
|
||||
return;
|
||||
@ -69,12 +69,6 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
|
||||
json.entrySet().forEach(entry -> data.getItemClaims().put(entry.getKey(), entry.getValue().getAsInt()));
|
||||
}
|
||||
|
||||
if (!data.hasUsedTemporaryData()) {
|
||||
data.setMana(data.getStats().getStat(StatType.MAX_MANA));
|
||||
data.setStamina(data.getStats().getStat(StatType.MAX_STAMINA));
|
||||
data.setStellium(data.getStats().getStat(StatType.MAX_STELLIUM));
|
||||
}
|
||||
|
||||
if (!isEmpty(result.getString("guild"))) {
|
||||
Guild guild = provider.getGuildManager().getGuild(result.getString("guild"));
|
||||
data.setGuild(guild.getMembers().has(data.getUniqueId()) ? guild : null);
|
||||
|
@ -6,7 +6,6 @@ import net.Indyuce.mmocore.api.player.OfflinePlayerData;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
|
||||
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.guild.provided.Guild;
|
||||
import net.Indyuce.mmocore.manager.data.DataProvider;
|
||||
import net.Indyuce.mmocore.manager.data.PlayerDataManager;
|
||||
@ -41,9 +40,9 @@ public class YAMLPlayerDataManager extends PlayerDataManager {
|
||||
data.setClass(MMOCore.plugin.classManager.get(config.getString("class")));
|
||||
|
||||
if (!data.hasUsedTemporaryData()) {
|
||||
data.setMana(data.getStats().getStat(StatType.MAX_MANA));
|
||||
data.setStamina(data.getStats().getStat(StatType.MAX_STAMINA));
|
||||
data.setStellium(data.getStats().getStat(StatType.MAX_STELLIUM));
|
||||
data.setMana(data.getStats().getStat("MAX_MANA"));
|
||||
data.setStamina(data.getStats().getStat("MAX_STAMINA"));
|
||||
data.setStellium(data.getStats().getStat("MAX_STELLIUM"));
|
||||
}
|
||||
|
||||
if (config.contains("guild")) {
|
||||
|
@ -7,11 +7,10 @@ import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
|
||||
import net.Indyuce.mmocore.api.block.BlockType;
|
||||
import net.Indyuce.mmocore.api.block.SkullBlockType;
|
||||
import net.Indyuce.mmocore.api.block.VanillaBlockType;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.manager.profession.SpecificProfessionManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
|
@ -4,17 +4,19 @@ import io.lumine.mythic.lib.MythicLib;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class EnchantManager extends SpecificProfessionManager {
|
||||
private final Map<Enchantment, Double> base = new HashMap<>();
|
||||
private final Map<Enchantment, Double> base = new HashMap<>();
|
||||
|
||||
public EnchantManager() {
|
||||
super("base-enchant-exp");
|
||||
}
|
||||
public EnchantManager() {
|
||||
super("base-enchant-exp");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadProfessionConfiguration(ConfigurationSection config) {
|
||||
@ -27,17 +29,20 @@ public class EnchantManager extends SpecificProfessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void registerBaseExperience(Enchantment enchant, double value) {
|
||||
base.put(enchant, value);
|
||||
}
|
||||
public void registerBaseExperience(Enchantment enchant, double value) {
|
||||
base.put(enchant, value);
|
||||
}
|
||||
|
||||
public double getBaseExperience(Enchantment enchant) {
|
||||
return base.get(enchant);
|
||||
}
|
||||
@NotNull
|
||||
public double getBaseExperience(Enchantment enchant) {
|
||||
// Can be null if argument passed is an enchant with no config attached to it
|
||||
@Nullable Double found = base.get(enchant);
|
||||
return found == null ? 0 : found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
if (clearBefore)
|
||||
base.clear();
|
||||
}
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
if (clearBefore)
|
||||
base.clear();
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ package net.Indyuce.mmocore.manager.profession;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.droptable.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
||||
import net.Indyuce.mmocore.loot.droptable.dropitem.fishing.FishingDropItem;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@ -29,6 +30,11 @@ public class FishingManager extends SpecificProfessionManager {
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not load fishing drop table " + key + ": " + exception.getMessage());
|
||||
}
|
||||
|
||||
// Link fishing stats to this profession
|
||||
MMOCore.plugin.statManager.registerProfession("FISHING_STRENGTH", getLinkedProfession());
|
||||
MMOCore.plugin.statManager.registerProfession("CRITICAL_FISHING_CHANCE", getLinkedProfession());
|
||||
MMOCore.plugin.statManager.registerProfession("CRITICAL_FISHING_FAILURE_CHANCE", getLinkedProfession());
|
||||
}
|
||||
|
||||
public FishingDropTable calculateDropTable(Entity entity) {
|
||||
@ -44,7 +50,6 @@ public class FishingManager extends SpecificProfessionManager {
|
||||
public static class FishingDropTable {
|
||||
private final Set<Condition> conditions = new HashSet<>();
|
||||
private final List<FishingDropItem> items = new ArrayList<>();
|
||||
private double maxWeight = 0;
|
||||
|
||||
public FishingDropTable(ConfigurationSection section) {
|
||||
Validate.notNull(section, "Could not load config");
|
||||
@ -70,7 +75,6 @@ public class FishingManager extends SpecificProfessionManager {
|
||||
try {
|
||||
FishingDropItem dropItem = new FishingDropItem(new MMOLineConfig(str));
|
||||
items.add(dropItem);
|
||||
maxWeight += dropItem.getItem().getWeight();
|
||||
} catch (RuntimeException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING,
|
||||
"Could not load item '" + str + "' from fishing drop table '" + id + "': " + exception.getMessage());
|
||||
@ -90,12 +94,25 @@ public class FishingManager extends SpecificProfessionManager {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
public FishingDropItem getRandomItem() {
|
||||
double randomCoefficient = RANDOM.nextDouble() * maxWeight;
|
||||
/**
|
||||
* The chance stat will make low weight items more
|
||||
* likely to be chosen by the algorithm
|
||||
*
|
||||
* @return Randomly computed fishing drop item
|
||||
*/
|
||||
public FishingDropItem getRandomItem(PlayerData player) {
|
||||
double chance = player.getStats().getStat("CHANCE");
|
||||
|
||||
for (FishingDropItem item : items)
|
||||
if ((randomCoefficient -= item.getItem().getWeight()) <= 0)
|
||||
//chance=0 ->the tier.chance remains the same
|
||||
//chance ->+inf -> the tier.chance becomes the same for everyone, uniform law
|
||||
//chance=8-> tierChance=sqrt(tierChance)
|
||||
double sum = 0;
|
||||
double randomCoefficient=RANDOM.nextDouble();
|
||||
for (FishingDropItem item : items) {
|
||||
sum += Math.pow(item.getItem().getWeight(), 1 / Math.log(1 + chance));
|
||||
if(sum<randomCoefficient)
|
||||
return item;
|
||||
}
|
||||
|
||||
throw new NullPointerException("Could not find item in drop table");
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ public class BoosterManager {
|
||||
return d;
|
||||
}
|
||||
|
||||
public int calculateExp(Profession profession, double exp) {
|
||||
return (int) (exp * getMultiplier(profession));
|
||||
public double calculateExp(Profession profession, double exp) {
|
||||
return (exp * getMultiplier(profession));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.Indyuce.mmocore.manager.social;
|
||||
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.manager.MMOCoreManager;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
@ -26,8 +26,7 @@ public class PartyManager implements MMOCoreManager {
|
||||
if (config != null)
|
||||
for (String key : config.getKeys(false))
|
||||
try {
|
||||
StatType stat = StatType.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
buffs.add(new StatModifier("mmocoreParty", stat.name(), config.getString(key)));
|
||||
buffs.add(new StatModifier("mmocoreParty", UtilityMethods.enumName(key), config.getString(key)));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not load party buff '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package net.Indyuce.mmocore.party;
|
||||
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import io.lumine.mythic.lib.comp.target.TargetRestriction;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class MMOCoreTargetRestriction implements TargetRestriction {
|
||||
|
||||
@Override
|
||||
public boolean canTarget(Player player, LivingEntity livingEntity, InteractionType interactionType) {
|
||||
if (!interactionType.isOffense() || !(livingEntity instanceof Player) || livingEntity.hasMetadata("NPC"))
|
||||
return true;
|
||||
|
||||
AbstractParty party = MMOCore.plugin.partyModule.getParty(PlayerData.get(player));
|
||||
// TODO check for guild
|
||||
return party == null || !party.hasMember((Player) livingEntity);
|
||||
}
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
package net.Indyuce.mmocore.party;
|
||||
|
||||
import net.Indyuce.mmocore.party.compat.*;
|
||||
import net.Indyuce.mmocore.party.compat.DungeonsXLPartyModule;
|
||||
import net.Indyuce.mmocore.party.compat.McMMOPartyModule;
|
||||
import net.Indyuce.mmocore.party.compat.PAFPartyModule;
|
||||
import net.Indyuce.mmocore.party.compat.PartiesPartyModule;
|
||||
import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
public enum PartyModuleType {
|
||||
DUNGEONS("Dungeons", DungeonsPartyModule::new),
|
||||
// DUNGEONS("Dungeons", DungeonsPartyModule::new),
|
||||
DUNGEONSXL("DungeonsXL", DungeonsXLPartyModule::new),
|
||||
MCMMO("mcMMO", McMMOPartyModule::new),
|
||||
MMOCORE("MMOCore", MMOCorePartyModule::new),
|
||||
|
@ -2,7 +2,6 @@ package net.Indyuce.mmocore.party.provided;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.listener.PartyListener;
|
||||
import net.Indyuce.mmocore.party.PartyModule;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -1,16 +1,10 @@
|
||||
package net.Indyuce.mmocore.listener;
|
||||
package net.Indyuce.mmocore.party.provided;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.event.social.PartyChatEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.manager.ConfigManager.SimpleMessage;
|
||||
import net.Indyuce.mmocore.party.AbstractParty;
|
||||
import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
|
||||
import net.Indyuce.mmocore.party.provided.Party;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -45,21 +39,4 @@ public class PartyListener implements Listener {
|
||||
party.getOnlineMembers().forEach(member -> format.send(member.getPlayer()));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel damage of players from the same party
|
||||
*
|
||||
* @deprecated This should be useful with the {@link io.lumine.mythic.lib.comp.target.TargetRestriction} update
|
||||
*/
|
||||
@Deprecated
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void b(PlayerAttackEvent event) {
|
||||
LivingEntity entity = event.getEntity();
|
||||
if (entity instanceof Player && !entity.hasMetadata("NPC")) {
|
||||
PlayerData targetData = PlayerData.get((Player) event.getEntity());
|
||||
AbstractParty party = targetData.getParty();
|
||||
if (party != null && party.hasMember(event.getData().getPlayer()))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,8 +3,8 @@ package net.Indyuce.mmocore.player;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
/**
|
||||
* Some item that can be unlocked. ALl unlockable are saved in the same list in
|
||||
* the player data. This useful list can be used for:
|
||||
* Some item that can be unlocked. All unlockables are saved in the
|
||||
* same list in the player data. This useful list can be used for:
|
||||
* - waypoints
|
||||
* - skill tree nodes
|
||||
* - skills using skill books? TODO
|
||||
@ -15,8 +15,8 @@ import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
public interface Unlockable {
|
||||
|
||||
/**
|
||||
* Format being used is the minecraft's default
|
||||
* namespaced key format, e.g "skill_tree:strength_1_5"
|
||||
* Format being used is the minecraft's default namespaced
|
||||
* key format, e.g "skill_tree:strength_1_5" for readability
|
||||
*/
|
||||
String getUnlockNamespacedKey();
|
||||
}
|
||||
|
71
src/main/java/net/Indyuce/mmocore/player/stats/StatInfo.java
Normal file
71
src/main/java/net/Indyuce/mmocore/player/stats/StatInfo.java
Normal file
@ -0,0 +1,71 @@
|
||||
package net.Indyuce.mmocore.player.stats;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Jules
|
||||
* @impl MMOCore used to have a giant enum of all the stat types
|
||||
* which is now incompatible with MythicLib because the MMO plugins
|
||||
* now have completely OPEN to edition numeric stat registries
|
||||
*/
|
||||
public class StatInfo {
|
||||
public final String name;
|
||||
|
||||
/**
|
||||
* Profession linked to that stat. Stats which have a profession linked to
|
||||
* them do NOT scale on the main player level but rather on that specific
|
||||
* profession level
|
||||
*/
|
||||
public Profession profession;
|
||||
|
||||
/**
|
||||
* Default formula for the stat
|
||||
*/
|
||||
public LinearValue defaultInfo;
|
||||
|
||||
/**
|
||||
* How that stat displays anywhere in GUIs
|
||||
*/
|
||||
public DecimalFormat format;
|
||||
|
||||
private static final DecimalFormat DEFAULT_DECIMAL_FORMAT = new DecimalFormat("0.#");
|
||||
|
||||
public StatInfo(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String format(double d) {
|
||||
return (format == null ? DEFAULT_DECIMAL_FORMAT : format).format(d);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LinearValue getDefaultFormula() {
|
||||
return defaultInfo == null ? LinearValue.ZERO : defaultInfo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StatInfo valueOf(String str) {
|
||||
StatInfo found = MMOCore.plugin.statManager.getInfo(str);
|
||||
return found == null ? new StatInfo(str) : found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
StatInfo statInfo = (StatInfo) o;
|
||||
return name.equals(statInfo.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
}
|
@ -3,4 +3,6 @@ package net.Indyuce.mmocore.quest;
|
||||
public interface AbstractQuest {
|
||||
|
||||
public String getName();
|
||||
|
||||
public String getId();
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package net.Indyuce.mmocore.quest;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.quest.Quest;
|
||||
import net.Indyuce.mmocore.quest.compat.QuestModule;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class MMOCoreQuestModule implements QuestModule {
|
||||
@Override
|
||||
public AbstractQuest getQuestOrThrow(String id) {
|
||||
Quest quest=MMOCore.plugin.questManager.get(id);
|
||||
if(quest==null)
|
||||
return null;
|
||||
return new MMOCoreQuest(quest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCompletedQuest(String quest, Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public class MMOCoreQuest implements AbstractQuest {
|
||||
Quest quest;
|
||||
|
||||
public MMOCoreQuest(Quest quest) {
|
||||
|
||||
this.quest = quest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package net.Indyuce.mmocore.quest;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
public interface QuestModule<T extends AbstractQuest, U extends PlayerQuestData<T>> {
|
||||
|
||||
/**
|
||||
* @return Quest with given name
|
||||
*/
|
||||
public T getQuestOrThrow(String id);
|
||||
|
||||
/**
|
||||
* @return Info about the completed quests from a specific player
|
||||
*/
|
||||
public U getQuestData(PlayerData playerData);
|
||||
}
|
32
src/main/java/net/Indyuce/mmocore/quest/QuestModuleType.java
Normal file
32
src/main/java/net/Indyuce/mmocore/quest/QuestModuleType.java
Normal file
@ -0,0 +1,32 @@
|
||||
package net.Indyuce.mmocore.quest;
|
||||
|
||||
import net.Indyuce.mmocore.quest.compat.BeautyQuestsModule;
|
||||
import net.Indyuce.mmocore.quest.compat.BlackVeinQuestsModule;
|
||||
import net.Indyuce.mmocore.quest.compat.QuestCreatorModule;
|
||||
import net.Indyuce.mmocore.quest.compat.QuestModule;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
public enum QuestModuleType {
|
||||
MMOCORE("MMOCore", MMOCoreQuestModule::new),
|
||||
QUESTS("Quests", BlackVeinQuestsModule::new),
|
||||
BEAUTY_QUEST("BeautyQuests", BeautyQuestsModule::new),
|
||||
QUEST_CREATOR("QuestCreator", QuestCreatorModule::new);
|
||||
|
||||
private final String pluginName;
|
||||
private final Provider<QuestModule> provider;
|
||||
|
||||
QuestModuleType(String pluginName, Provider<QuestModule> provider) {
|
||||
this.pluginName = pluginName;
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return Bukkit.getPluginManager().getPlugin(pluginName) != null;
|
||||
}
|
||||
|
||||
public QuestModule provideModule() {
|
||||
return provider.get();
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package net.Indyuce.mmocore.quest.compat;
|
||||
|
||||
import fr.skytasul.quests.api.QuestsAPI;
|
||||
import fr.skytasul.quests.players.PlayerAccount;
|
||||
import fr.skytasul.quests.players.PlayerQuestDatas;
|
||||
import fr.skytasul.quests.players.PlayersManager;
|
||||
import fr.skytasul.quests.structure.Quest;
|
||||
import net.Indyuce.mmocore.quest.AbstractQuest;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class BeautyQuestsModule implements QuestModule<BeautyQuestsModule.BeautyQuestQuest> {
|
||||
|
||||
@Override
|
||||
public BeautyQuestQuest getQuestOrThrow(String questId) {
|
||||
Quest quest = QuestsAPI.getQuests().getQuest(Integer.parseInt(questId));
|
||||
return quest == null ? null : new BeautyQuestQuest(quest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCompletedQuest(String questId, Player player) {
|
||||
PlayerAccount account = PlayersManager.getPlayerAccount(player);
|
||||
PlayerQuestDatas quest = account.getQuestDatas(QuestsAPI.getQuests().getQuest(Integer.parseInt(questId)));
|
||||
return quest.isFinished();
|
||||
}
|
||||
|
||||
public class BeautyQuestQuest implements AbstractQuest {
|
||||
|
||||
Quest quest;
|
||||
|
||||
public BeautyQuestQuest(Quest quest) {
|
||||
this.quest = quest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return quest.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return String.valueOf(quest.getID());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
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());
|
||||
|
||||
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,57 @@
|
||||
package net.Indyuce.mmocore.quest.compat;
|
||||
|
||||
import com.guillaumevdn.questcreator.ConfigQC;
|
||||
import com.guillaumevdn.questcreator.data.user.QuestHistoryElement;
|
||||
import com.guillaumevdn.questcreator.data.user.UserQC;
|
||||
import com.guillaumevdn.questcreator.lib.model.ElementModel;
|
||||
import com.guillaumevdn.questcreator.lib.quest.QuestEndType;
|
||||
import net.Indyuce.mmocore.quest.AbstractQuest;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class QuestCreatorModule implements QuestModule<QuestCreatorModule.QuestCreatorQuest> {
|
||||
|
||||
@Override
|
||||
public QuestCreatorQuest getQuestOrThrow(String id) {
|
||||
return new QuestCreatorQuest(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCompletedQuest(String questId, Player player) {
|
||||
UserQC playerData = UserQC.cachedOrNull(player);
|
||||
Validate.notNull(playerData, "QuestCreator User hasn't been loaded!");
|
||||
|
||||
// Gets all the quests the player has succeeded at
|
||||
List<QuestHistoryElement> elements = playerData.getQuestHistory().getElements(questId, Arrays.asList(QuestEndType.SUCCESS), 0);
|
||||
for (QuestHistoryElement el : elements)
|
||||
if (el.getModelId().equals(questId))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* QC ElementModel corresponds to our quest and their
|
||||
* quests correspond to our Quest progress class
|
||||
*/
|
||||
public class QuestCreatorQuest implements AbstractQuest {
|
||||
ElementModel questModel;
|
||||
|
||||
public QuestCreatorQuest(String modelId) {
|
||||
questModel = ConfigQC.models.getElement(modelId).orNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return questModel.getDisplayName().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return questModel.getId();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package net.Indyuce.mmocore.quest.compat;
|
||||
|
||||
import net.Indyuce.mmocore.quest.AbstractQuest;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface QuestModule<T extends AbstractQuest> {
|
||||
|
||||
/**
|
||||
* @return Quest with given identifier
|
||||
*/
|
||||
public T getQuestOrThrow(String id);
|
||||
|
||||
/**
|
||||
* @return If a specific player has made a certain quest
|
||||
*/
|
||||
public boolean hasCompletedQuest(String quest, Player player);
|
||||
}
|
@ -4,6 +4,7 @@ import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.player.cooldown.CooldownObject;
|
||||
import io.lumine.mythic.lib.player.modifier.ModifierSource;
|
||||
import io.lumine.mythic.lib.player.skill.PassiveSkill;
|
||||
import io.lumine.mythic.lib.skill.custom.condition.Condition;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.IntegerLinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
@ -17,6 +18,9 @@ public class ClassSkill implements CooldownObject {
|
||||
private final int unlockLevel, maxSkillLevel;
|
||||
private final Map<String, LinearValue> modifiers = new HashMap<>();
|
||||
|
||||
@Deprecated
|
||||
private final Set<Condition> unlockConditions = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Class used to save information about skills IN A CLASS CONTEXT i.e at
|
||||
* which level the skill can be unlocked, etc.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user