forked from Upstream/mmocore
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
e4f01f8efa
2
pom.xml
2
pom.xml
@ -125,7 +125,7 @@
|
||||
<dependency>
|
||||
<groupId>io.lumine</groupId>
|
||||
<artifactId>MythicLib-dist</artifactId>
|
||||
<version>1.3</version>
|
||||
<version>1.3-R17</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.Indyuce.mmocore;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.comp.Metrics;
|
||||
import io.lumine.mythic.lib.version.SpigotPlugin;
|
||||
import io.lumine.mythic.utils.plugin.LuminePlugin;
|
||||
@ -40,7 +41,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.skill.cast.listener.SkillBar;
|
||||
import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
|
||||
import net.Indyuce.mmocore.skill.list.Ambers;
|
||||
import net.Indyuce.mmocore.skill.list.Neptune_Gift;
|
||||
import net.Indyuce.mmocore.skill.list.Sneaky_Picky;
|
||||
@ -221,6 +222,14 @@ public class MMOCore extends LuminePlugin {
|
||||
DebugMode.enableActionBar();
|
||||
}
|
||||
|
||||
// Skill casting
|
||||
try {
|
||||
SkillCastingMode mode = SkillCastingMode.valueOf(UtilityMethods.enumName(getConfig().getString("skill-casting.mode")));
|
||||
Bukkit.getPluginManager().registerEvents(mode.loadFromConfig(getConfig().getConfigurationSection("skill-casting")), this);
|
||||
} catch (RuntimeException exception) {
|
||||
getLogger().log(Level.WARNING, "Could not load skill casting: " + exception.getMessage());
|
||||
}
|
||||
|
||||
if (configManager.overrideVanillaExp = getConfig().getBoolean("override-vanilla-exp"))
|
||||
Bukkit.getPluginManager().registerEvents(new VanillaExperienceOverride(), this);
|
||||
|
||||
|
20
src/main/java/net/Indyuce/mmocore/api/SoundEvent.java
Normal file
20
src/main/java/net/Indyuce/mmocore/api/SoundEvent.java
Normal file
@ -0,0 +1,20 @@
|
||||
package net.Indyuce.mmocore.api;
|
||||
|
||||
public enum SoundEvent {
|
||||
LEVEL_UP,
|
||||
WARP_TELEPORT,
|
||||
WARP_CANCELLED,
|
||||
WARP_CHARGE,
|
||||
WARP_UNLOCK,
|
||||
HOTBAR_SWAP,
|
||||
SPELL_CAST_BEGIN,
|
||||
SPELL_CAST_END,
|
||||
CANT_SELECT_CLASS,
|
||||
SELECT_CLASS,
|
||||
LEVEL_ATTRIBUTE,
|
||||
RESET_ATTRIBUTES,
|
||||
NOT_ENOUGH_POINTS,
|
||||
CANCEL_QUEST,
|
||||
START_QUEST,
|
||||
CLOSE_LOOT_CHEST;
|
||||
}
|
@ -1,53 +1,106 @@
|
||||
package net.Indyuce.mmocore.api;
|
||||
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.util.configobject.ConfigObject;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class SoundObject {
|
||||
private final Sound sound;
|
||||
private final String key;
|
||||
private final float volume;
|
||||
private final float pitch;
|
||||
|
||||
public SoundObject(String input) {
|
||||
String[] split = input.split(",");
|
||||
if(split.length > 2) {
|
||||
input = split[0];
|
||||
volume = Float.parseFloat(split[1]);
|
||||
pitch = Float.parseFloat(split[2]);
|
||||
} else {
|
||||
volume = 1;
|
||||
pitch = 1;
|
||||
}
|
||||
|
||||
Sound sound = null;
|
||||
String key = "";
|
||||
try {
|
||||
sound = Sound.valueOf(input.toUpperCase().replace("-", "_"));
|
||||
} catch(Exception ignored) {
|
||||
key = input;
|
||||
}
|
||||
@Nullable
|
||||
private final Sound sound;
|
||||
|
||||
this.sound = sound;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public boolean hasSound() {
|
||||
return key.isEmpty();
|
||||
}
|
||||
|
||||
public Sound getSound() {
|
||||
return sound;
|
||||
}
|
||||
@Nullable
|
||||
private final String key;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
private final float volume;
|
||||
private final float pitch;
|
||||
|
||||
public float getVolume() {
|
||||
return volume;
|
||||
}
|
||||
public SoundObject(String input) {
|
||||
String[] split = input.split(",");
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
Sound sound = null;
|
||||
String key = null;
|
||||
try {
|
||||
sound = Sound.valueOf(UtilityMethods.enumName(split[0]));
|
||||
} catch (Exception ignored) {
|
||||
key = split[0];
|
||||
}
|
||||
|
||||
this.sound = sound;
|
||||
this.key = key;
|
||||
|
||||
volume = split.length > 1 ? Float.parseFloat(split[1]) : 1;
|
||||
pitch = split.length > 2 ? Float.parseFloat(split[2]) : 1;
|
||||
}
|
||||
|
||||
public SoundObject(ConfigurationSection config) {
|
||||
String input = config.getString("sound");
|
||||
|
||||
Sound sound = null;
|
||||
String key = null;
|
||||
try {
|
||||
sound = Sound.valueOf(UtilityMethods.enumName(input));
|
||||
} catch (Exception ignored) {
|
||||
key = input;
|
||||
}
|
||||
|
||||
this.sound = sound;
|
||||
this.key = key;
|
||||
|
||||
volume = (float) config.getDouble("volume", 1);
|
||||
pitch = (float) config.getDouble("pitch", 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If this object is custom a custom sound, potentially
|
||||
* from a resource pack
|
||||
*/
|
||||
public boolean isCustom() {
|
||||
return sound == null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Sound getSound() {
|
||||
return sound;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public float getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public void playTo(Player player) {
|
||||
playTo(player, volume, pitch);
|
||||
}
|
||||
|
||||
public void playTo(Player player, float volume, float pitch) {
|
||||
if (isCustom())
|
||||
player.playSound(player.getLocation(), key, volume, pitch);
|
||||
else
|
||||
player.playSound(player.getLocation(), sound, volume, pitch);
|
||||
}
|
||||
|
||||
public void playAt(Location loc) {
|
||||
playAt(loc, volume, pitch);
|
||||
}
|
||||
|
||||
public void playAt(Location loc, float volume, float pitch) {
|
||||
if (isCustom())
|
||||
loc.getWorld().playSound(loc, key, volume, pitch);
|
||||
else
|
||||
loc.getWorld().playSound(loc, sound, volume, pitch);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ 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.api.Waypoint;
|
||||
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
|
||||
@ -26,12 +27,12 @@ import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.PlayerProfessions;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import net.Indyuce.mmocore.skill.cast.listener.SkillBar.SkillCasting;
|
||||
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -64,6 +65,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
private double mana, stamina, stellium;
|
||||
private Party party;
|
||||
private Guild guild;
|
||||
private SkillCastingHandler skillCasting;
|
||||
|
||||
private final PlayerQuests questData;
|
||||
private final PlayerStats playerStats;
|
||||
@ -74,11 +76,10 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
private final PlayerProfessions collectSkills = new PlayerProfessions(this);
|
||||
private final PlayerAttributes attributes = new PlayerAttributes(this);
|
||||
private final Map<String, SavedClassInformation> classSlots = new HashMap<>();
|
||||
private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
|
||||
private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
|
||||
|
||||
// NON-FINAL player data stuff made public to facilitate field change
|
||||
public int skillGuiDisplayOffset;
|
||||
public SkillCasting skillCasting;
|
||||
public boolean noCooldown;
|
||||
public CombatRunnable combat;
|
||||
|
||||
@ -438,7 +439,7 @@ private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
|
||||
return;
|
||||
if (getPlayer().getLocation().getBlockX() != x || getPlayer().getLocation().getBlockY() != y
|
||||
|| getPlayer().getLocation().getBlockZ() != z) {
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.WARP_CANCELLED);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_CANCELLED).playTo(getPlayer());
|
||||
MMOCore.plugin.configManager.getSimpleMessage("warping-canceled").send(getPlayer());
|
||||
giveStellium(waypoint.getStelliumCost(), PlayerResourceUpdateEvent.UpdateReason.SKILL_REGENERATION);
|
||||
cancel();
|
||||
@ -449,12 +450,12 @@ private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
|
||||
if (t++ >= 100) {
|
||||
getPlayer().teleport(waypoint.getLocation());
|
||||
getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 20, 1, false, false));
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.WARP_TELEPORT);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_TELEPORT).playTo(getPlayer());
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.WARP_CHARGE, 1, (float) (t / Math.PI * .015 + .5));
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_CHARGE).playTo(getPlayer(), 1, (float) (t / Math.PI * .015 + .5));
|
||||
double r = Math.sin((double) t / 100 * Math.PI);
|
||||
for (double j = 0; j < Math.PI * 2; j += Math.PI / 4)
|
||||
getPlayer().getLocation().getWorld().spawnParticle(Particle.REDSTONE,
|
||||
@ -532,7 +533,7 @@ private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
|
||||
Bukkit.getPluginManager().callEvent(new PlayerLevelUpEvent(this, null, oldLevel, level));
|
||||
if (isOnline()) {
|
||||
new ConfigMessage("level-up").addPlaceholders("level", "" + level).send(getPlayer());
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.LEVEL_UP);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer());
|
||||
new SmallParticleEffect(getPlayer(), Particle.SPELL_INSTANT);
|
||||
}
|
||||
getStats().updateStats();
|
||||
@ -675,6 +676,22 @@ private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
|
||||
return skillCasting != null;
|
||||
}
|
||||
|
||||
public void setSkillCasting(SkillCastingHandler skillCasting) {
|
||||
Validate.isTrue(!isCasting(), "Player already in casting mode");
|
||||
this.skillCasting = skillCasting;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SkillCastingHandler getSkillCasting() {
|
||||
return Objects.requireNonNull(skillCasting, "Player not in casting mode");
|
||||
}
|
||||
|
||||
public void leaveCastingMode() {
|
||||
Validate.isTrue(isCasting(), "Player not in casting mode");
|
||||
skillCasting.close();
|
||||
this.skillCasting = null;
|
||||
}
|
||||
|
||||
public void displayActionBar(String message) {
|
||||
if (!isOnline())
|
||||
return;
|
||||
@ -808,7 +825,7 @@ private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
|
||||
* checks if they could potentially upgrade to one of these
|
||||
*
|
||||
* @return If the player can change its current class to
|
||||
* a subclass
|
||||
* a subclass
|
||||
*/
|
||||
public boolean canChooseSubclass() {
|
||||
for (Subclass subclass : getProfess().getSubclasses())
|
||||
|
@ -149,21 +149,18 @@ public class Party {
|
||||
new ArrayList<>(members).forEach(action);
|
||||
}
|
||||
|
||||
private static final String PARTY_BUFF_MODIFIER_KEY = "mmocoreParty";
|
||||
|
||||
/**
|
||||
* Applies party stat bonuses to a specific player
|
||||
*/
|
||||
private void applyStatBonuses(PlayerData player) {
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).addModifier(PARTY_BUFF_MODIFIER_KEY,
|
||||
MMOCore.plugin.partyManager.getBonus(stat).multiply(members.size() - 1)));
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(buff -> buff.multiply(members.size() - 1).register(player.getMMOPlayerData()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear party stat bonuses from a player
|
||||
*/
|
||||
private void clearStatBonuses(PlayerData player) {
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).remove(PARTY_BUFF_MODIFIER_KEY));
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(buff -> buff.unregister(player.getMMOPlayerData()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,7 @@ import com.google.gson.JsonObject;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
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;
|
||||
@ -195,7 +196,7 @@ public class PlayerProfessions {
|
||||
new SmallParticleEffect(playerData.getPlayer(), Particle.SPELL_INSTANT);
|
||||
new ConfigMessage("profession-level-up").addPlaceholders("level", "" + level, "profession", profession.getName())
|
||||
.send(playerData.getPlayer());
|
||||
MMOCore.plugin.soundManager.play(playerData.getPlayer(), SoundManager.SoundEvent.LEVEL_UP);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(playerData.getPlayer());
|
||||
playerData.getStats().updateStats();
|
||||
|
||||
// Apply profession experience table
|
||||
|
@ -23,11 +23,14 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BrewPotionExperienceSource extends ExperienceSource<PotionMeta> {
|
||||
private final double multiplier;
|
||||
private final List<PotionType> types = new ArrayList<>();
|
||||
|
||||
public BrewPotionExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
|
||||
super(dispenser);
|
||||
|
||||
multiplier = config.getDouble("multiplier", 1);
|
||||
|
||||
if (config.contains("effect"))
|
||||
for (String key : config.getString("effect").split(","))
|
||||
types.add(PotionType.valueOf(key.toUpperCase().replace("-", "_")));
|
||||
@ -164,7 +167,7 @@ public class BrewPotionExperienceSource extends ExperienceSource<PotionMeta> {
|
||||
*/
|
||||
// exp += getTotal(mapEffectDurations());
|
||||
|
||||
getDispenser().giveExperience(PlayerData.get(player), (int) exp, null);
|
||||
getDispenser().giveExperience(PlayerData.get(player), (int) exp * multiplier, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.Indyuce.mmocore.gui;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerAttributeUseEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||
@ -89,13 +90,13 @@ public class AttributeView extends EditableInventory {
|
||||
int spent = playerData.getAttributes().countSkillPoints();
|
||||
if (spent < 1) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("no-attribute-points-spent").send(player);
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.NOT_ENOUGH_POINTS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerData.getAttributeReallocationPoints() < 1) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-attribute-reallocation-point").send(player);
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.NOT_ENOUGH_POINTS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -103,7 +104,7 @@ public class AttributeView extends EditableInventory {
|
||||
playerData.giveAttributePoints(spent);
|
||||
playerData.giveAttributeReallocationPoints(-1);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("attribute-points-reallocated", "points", "" + playerData.getAttributePoints()).send(player);
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.RESET_ATTRIBUTES);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.RESET_ATTRIBUTES).playTo(getPlayer());
|
||||
open();
|
||||
}
|
||||
|
||||
@ -112,21 +113,21 @@ public class AttributeView extends EditableInventory {
|
||||
|
||||
if (playerData.getAttributePoints() < 1) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-attribute-point").send(player);
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.NOT_ENOUGH_POINTS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
|
||||
return;
|
||||
}
|
||||
|
||||
AttributeInstance ins = playerData.getAttributes().getInstance(attribute);
|
||||
if (attribute.hasMax() && ins.getBase() >= attribute.getMax()) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("attribute-max-points-hit").send(player);
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.NOT_ENOUGH_POINTS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
|
||||
return;
|
||||
}
|
||||
|
||||
ins.addBase(1);
|
||||
playerData.giveAttributePoints(-1);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("attribute-level-up", "attribute", attribute.getName(), "level", "" + ins.getBase()).send(player);
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.LEVEL_ATTRIBUTE);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_ATTRIBUTE).playTo(getPlayer());
|
||||
|
||||
PlayerAttributeUseEvent playerAttributeUseEvent = new PlayerAttributeUseEvent(playerData, attribute);
|
||||
Bukkit.getServer().getPluginManager().callEvent(playerAttributeUseEvent);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.Indyuce.mmocore.gui;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
|
||||
@ -125,7 +126,7 @@ public class ClassConfirmation extends EditableInventory {
|
||||
(playerData.hasSavedClass(profess) ? playerData.getClassInfo(profess)
|
||||
: new SavedClassInformation(MMOCore.plugin.dataProvider.getDataManager().getDefaultData())).load(profess, playerData);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("class-select", "class", profess.getName()).send(player);
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.SELECT_CLASS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.SELECT_CLASS).playTo(player);
|
||||
player.closeInventory();
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ 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.ConfigMessage;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.ClassOption;
|
||||
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
|
||||
@ -109,14 +110,14 @@ public class ClassSelect extends EditableInventory {
|
||||
return;
|
||||
|
||||
if (playerData.getClassPoints() < 1) {
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.CANT_SELECT_CLASS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player);
|
||||
new ConfigMessage("cant-choose-new-class").send(player);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerClass profess = MMOCore.plugin.classManager.get(tag);
|
||||
if (profess.equals(playerData.getProfess())) {
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.CANT_SELECT_CLASS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("already-on-class", "class", profess.getName()).send(player);
|
||||
return;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ 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.SoundEvent;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.quest.Quest;
|
||||
@ -235,7 +236,7 @@ public class QuestViewer extends EditableInventory {
|
||||
if (playerData.getQuestData().hasCurrent(quest)) {
|
||||
if (event.getAction() == InventoryAction.PICKUP_HALF) {
|
||||
playerData.getQuestData().start(null);
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.CANCEL_QUEST);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.CANCEL_QUEST).playTo(player);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("cancel-quest").send(player);
|
||||
open();
|
||||
}
|
||||
@ -293,7 +294,7 @@ public class QuestViewer extends EditableInventory {
|
||||
* eventually start a new quest.
|
||||
*/
|
||||
MMOCore.plugin.configManager.getSimpleMessage("start-quest", "quest", quest.getName()).send(player);
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.START_QUEST);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.START_QUEST).playTo(player);
|
||||
playerData.getQuestData().start(quest);
|
||||
open();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.Indyuce.mmocore.gui;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
|
||||
@ -66,7 +67,7 @@ public class SubclassConfirmation extends EditableInventory {
|
||||
|
||||
playerData.setClass(profess);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("class-select", "class", profess.getName()).send(player);
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.SELECT_CLASS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.SELECT_CLASS).playTo(player);
|
||||
player.closeInventory();
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ 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.ConfigMessage;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
|
||||
import net.Indyuce.mmocore.api.player.profess.Subclass;
|
||||
@ -118,7 +119,7 @@ public class SubclassSelect extends EditableInventory {
|
||||
|
||||
if (playerData.getClassPoints() < 1) {
|
||||
player.closeInventory();
|
||||
MMOCore.plugin.soundManager.play(getPlayer(), SoundManager.SoundEvent.CANT_SELECT_CLASS);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(getPlayer());
|
||||
new ConfigMessage("cant-choose-new-class").send(player);
|
||||
return;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.Indyuce.mmocore.listener;
|
||||
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -29,7 +30,7 @@ public class WaypointsListener implements Listener {
|
||||
data.unlockWaypoint(waypoint);
|
||||
new SmallParticleEffect(player, Particle.SPELL_WITCH);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("new-waypoint", "waypoint", waypoint.getName()).send(player);
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.WARP_UNLOCK);
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_UNLOCK).playTo(player);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.Indyuce.mmocore.loot.chest;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -66,7 +67,7 @@ public class LootChest {
|
||||
|
||||
// If a player is responsible of closing the chest, close it with sound
|
||||
if (player) {
|
||||
MMOCore.plugin.soundManager.play(block.loc.getBlock(), SoundManager.SoundEvent.CLOSE_LOOT_CHEST);
|
||||
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.lootChests.unregister(this);
|
||||
}
|
||||
|
@ -1,72 +1,24 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.SoundObject;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SoundManager {
|
||||
private final Map<SoundEvent, SoundObject> sounds = new HashMap<>();
|
||||
private final Map<SoundEvent, SoundObject> sounds = new HashMap<>();
|
||||
|
||||
public SoundManager(FileConfiguration config) {
|
||||
for(SoundEvent sound : SoundEvent.values())
|
||||
sounds.put(sound, new SoundObject(config.getString(sound.name().replace("_", "-").toLowerCase())));
|
||||
}
|
||||
public SoundManager(FileConfiguration config) {
|
||||
for (SoundEvent sound : SoundEvent.values())
|
||||
sounds.put(sound, new SoundObject(config.getString(sound.name().replace("_", "-").toLowerCase())));
|
||||
}
|
||||
|
||||
|
||||
public void play(Block block, SoundEvent event) {
|
||||
play(block, block.getLocation(), event);
|
||||
}
|
||||
|
||||
public void play(Block block, Location loc, SoundEvent event) {
|
||||
SoundObject sound = sounds.get(event);
|
||||
if(sound.hasSound())
|
||||
block.getWorld().playSound(loc, sound.getSound(), sound.getVolume(), sound.getPitch());
|
||||
else block.getWorld().playSound(loc, sound.getKey(), sound.getVolume(), sound.getPitch());
|
||||
}
|
||||
|
||||
public void play(Player player, SoundEvent event) {
|
||||
play(player, player.getLocation(), event);
|
||||
}
|
||||
|
||||
public void play(Player player, Location loc, SoundEvent event) {
|
||||
SoundObject sound = sounds.get(event);
|
||||
if(sound.hasSound())
|
||||
player.playSound(loc, sound.getSound(), sound.getVolume(), sound.getPitch());
|
||||
else player.playSound(loc, sound.getKey(), sound.getVolume(), sound.getPitch());
|
||||
}
|
||||
|
||||
public void play(Player player, SoundEvent event, float volume, float pitch) {
|
||||
play(player, player.getLocation(), event, volume, pitch);
|
||||
}
|
||||
|
||||
public void play(Player player, Location loc, SoundEvent event, float volume, float pitch) {
|
||||
SoundObject sound = sounds.get(event);
|
||||
if(sound.hasSound())
|
||||
player.playSound(loc, sound.getSound(), volume, pitch);
|
||||
else player.playSound(loc, sound.getKey(), volume, pitch);
|
||||
}
|
||||
|
||||
public enum SoundEvent {
|
||||
LEVEL_UP,
|
||||
WARP_TELEPORT,
|
||||
WARP_CANCELLED,
|
||||
WARP_CHARGE,
|
||||
WARP_UNLOCK,
|
||||
HOTBAR_SWAP,
|
||||
SPELL_CAST_BEGIN,
|
||||
SPELL_CAST_END,
|
||||
CANT_SELECT_CLASS,
|
||||
SELECT_CLASS,
|
||||
LEVEL_ATTRIBUTE,
|
||||
RESET_ATTRIBUTES,
|
||||
NOT_ENOUGH_POINTS,
|
||||
CANCEL_QUEST,
|
||||
START_QUEST,
|
||||
CLOSE_LOOT_CHEST
|
||||
}
|
||||
@NotNull
|
||||
public SoundObject getSound(SoundEvent event) {
|
||||
return Objects.requireNonNull(sounds.get(event), "Could not find sound for " + event.name());
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,7 @@ public abstract class PlayerDataManager {
|
||||
* @return Player data, if it's loaded
|
||||
*/
|
||||
public PlayerData get(UUID uuid) {
|
||||
if(isLoaded(uuid))
|
||||
return Objects.requireNonNull(data.get(uuid), "Player data is not loaded");
|
||||
else return setup(uuid);
|
||||
return Objects.requireNonNull(data.get(uuid), "Player data is not loaded");
|
||||
}
|
||||
|
||||
/**
|
||||
|
40
src/main/java/net/Indyuce/mmocore/skill/cast/KeyCombo.java
Normal file
40
src/main/java/net/Indyuce/mmocore/skill/cast/KeyCombo.java
Normal file
@ -0,0 +1,40 @@
|
||||
package net.Indyuce.mmocore.skill.cast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* There is one key combo per skill slot. This means
|
||||
* that independently of both the player's class and
|
||||
* the skill bounty to the n-th slot, the key combo to
|
||||
* perform to cast the n-th skill is always the same
|
||||
*/
|
||||
public class KeyCombo {
|
||||
private final List<PlayerKey> keys = new ArrayList<>();
|
||||
|
||||
public int countKeys() {
|
||||
return keys.size();
|
||||
}
|
||||
|
||||
public void registerKey(PlayerKey key) {
|
||||
keys.add(key);
|
||||
}
|
||||
|
||||
public PlayerKey getAt(int index) {
|
||||
return keys.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
KeyCombo keyCombo = (KeyCombo) o;
|
||||
return Objects.equals(keys, keyCombo.keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return keys.hashCode();
|
||||
}
|
||||
}
|
@ -5,25 +5,40 @@ public enum PlayerKey {
|
||||
/**
|
||||
* When a player left clicks
|
||||
*/
|
||||
LEFT_CLICK,
|
||||
LEFT_CLICK(false),
|
||||
|
||||
/**
|
||||
* When a player right clicks
|
||||
*/
|
||||
RIGHT_CLICK,
|
||||
RIGHT_CLICK(false),
|
||||
|
||||
/**
|
||||
* When a player drops the item they are holding
|
||||
*/
|
||||
DROP,
|
||||
DROP(true),
|
||||
|
||||
/**
|
||||
* When a player swaps their hand items
|
||||
*/
|
||||
SWAP_HANDS,
|
||||
SWAP_HANDS(true),
|
||||
|
||||
/**
|
||||
* When a player sneaks (doesn't trigger when unsneaking)
|
||||
*/
|
||||
CROUCH;
|
||||
CROUCH(false);
|
||||
|
||||
private final boolean cancellableEvent;
|
||||
|
||||
private PlayerKey(boolean cancelableEvent) {
|
||||
this.cancellableEvent = cancelableEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether or not the event causing the key press event
|
||||
* should be cancelled when this key is actually being registered
|
||||
* as a key combo action.
|
||||
*/
|
||||
public boolean shouldCancelEvent() {
|
||||
return cancellableEvent;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
package net.Indyuce.mmocore.skill.cast;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public abstract class SkillCastingHandler extends BukkitRunnable implements Listener {
|
||||
private final PlayerData caster;
|
||||
|
||||
private boolean open = true;
|
||||
|
||||
public SkillCastingHandler(PlayerData caster, int runnablePeriod) {
|
||||
this.caster = caster;
|
||||
|
||||
runTaskTimer(MMOCore.plugin, 0, runnablePeriod);
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
public PlayerData getCaster() {
|
||||
return caster;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
Validate.isTrue(open, "Skill casting already ended");
|
||||
|
||||
open = false;
|
||||
|
||||
// Unregister listeners
|
||||
HandlerList.unregisterAll(this);
|
||||
|
||||
// Cancel runnable
|
||||
cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!caster.isOnline() || caster.getPlayer().isDead())
|
||||
caster.leaveCastingMode();
|
||||
else
|
||||
onTick();
|
||||
}
|
||||
|
||||
public abstract void onTick();
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
package net.Indyuce.mmocore.skill.cast;
|
||||
|
||||
import net.Indyuce.mmocore.skill.cast.listener.KeyCombos;
|
||||
import net.Indyuce.mmocore.skill.cast.listener.SkillBar;
|
||||
import net.Indyuce.mmocore.skill.cast.listener.SkillScroller;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public enum CastingMethod {
|
||||
public enum SkillCastingMode {
|
||||
|
||||
/**
|
||||
* The first ever casting method to be implemented in MMOCore.
|
||||
@ -14,14 +16,19 @@ public enum CastingMethod {
|
||||
* When pressing a key, the list of bound skills display on the
|
||||
* action bar
|
||||
*/
|
||||
SKILL_BAR(config-> new SkillBar(config)),
|
||||
|
||||
SKILL_SCROLL;
|
||||
SKILL_BAR(config -> new SkillBar(config)),
|
||||
|
||||
/**
|
||||
* Initialize your skill combo by pressing some key
|
||||
* TODO
|
||||
*/
|
||||
KEY_COMBOS(),
|
||||
SKILL_SCROLL(config -> new SkillScroller(config)),
|
||||
|
||||
/**
|
||||
* Initialize your skill combo by pressing some key.
|
||||
* <p>
|
||||
* Then press a certain amount of keys to
|
||||
*/
|
||||
KEY_COMBOS(config -> new KeyCombos(config)),
|
||||
|
||||
/**
|
||||
* Not implemented yet.
|
||||
@ -30,7 +37,7 @@ public enum CastingMethod {
|
||||
* a book with all the skills displayed into it and click
|
||||
* some clickable text to cast the skill.
|
||||
*/
|
||||
SPELL_BOOK(),
|
||||
// SPELL_BOOK(null),
|
||||
|
||||
/**
|
||||
* Not implemented yet.
|
||||
@ -38,11 +45,17 @@ public enum CastingMethod {
|
||||
* Much like the spell book but using a custom GUI instead
|
||||
* of a spell book to display the available skills.
|
||||
*/
|
||||
SPELL_GUI();
|
||||
// SPELL_GUI(null),
|
||||
|
||||
;
|
||||
|
||||
private final Function<ConfigurationSection, Listener> listenerLoader;
|
||||
|
||||
CastingMethod(Function<ConfigurationSection, Listener> listenerLoader) {
|
||||
SkillCastingMode(Function<ConfigurationSection, Listener> listenerLoader) {
|
||||
this.listenerLoader = listenerLoader;
|
||||
}
|
||||
|
||||
public Listener loadFromConfig(ConfigurationSection config) {
|
||||
return listenerLoader.apply(config);
|
||||
}
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
package net.Indyuce.mmocore.skill.cast.listener;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.SoundObject;
|
||||
import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.skill.cast.KeyCombo;
|
||||
import net.Indyuce.mmocore.skill.cast.PlayerKey;
|
||||
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class KeyCombos implements Listener {
|
||||
|
||||
/**
|
||||
* Using instances of KeyCombo as keys work because
|
||||
* {@link KeyCombo} has a working implementation for the
|
||||
* hash code method
|
||||
*/
|
||||
private final Map<KeyCombo, Integer> combos = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Key players need to press to start a combo
|
||||
*/
|
||||
private final PlayerKey initializerKey;
|
||||
private final int longestCombo;
|
||||
|
||||
/**
|
||||
* Handles the display of the action bar when casting a skill.
|
||||
* Set to null if disabled
|
||||
*/
|
||||
@Nullable
|
||||
private final ActionBarOptions actionBarOptions;
|
||||
|
||||
@Nullable
|
||||
private final SoundObject beginComboSound, comboClickSound, failComboSound;
|
||||
|
||||
/**
|
||||
* Essentially the inverse of the {@link #combos} map. This maps
|
||||
* the skill slot to the corresponding key combo. There's no problem
|
||||
* because the maps are 100% bijective
|
||||
*/
|
||||
private static final Map<Integer, KeyCombo> PUBLIC_COMBOS = new HashMap<>();
|
||||
|
||||
public KeyCombos(ConfigurationSection config) {
|
||||
|
||||
int longestCombo = 0;
|
||||
|
||||
// Load different combos
|
||||
for (String key : config.getConfigurationSection("combos").getKeys(false))
|
||||
try {
|
||||
int spellSlot = Integer.valueOf(key);
|
||||
Validate.isTrue(spellSlot >= 0, "Spell slot must be at least 0");
|
||||
Validate.isTrue(!combos.values().contains(spellSlot), "There is already a key combo with the same skill slot");
|
||||
KeyCombo combo = new KeyCombo();
|
||||
for (String str : config.getStringList("combos." + key))
|
||||
combo.registerKey(PlayerKey.valueOf(UtilityMethods.enumName(str)));
|
||||
|
||||
combos.put(combo, spellSlot);
|
||||
longestCombo = Math.max(longestCombo, combo.countKeys());
|
||||
|
||||
PUBLIC_COMBOS.put(spellSlot, combo);
|
||||
} catch (RuntimeException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load key combo '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
|
||||
this.longestCombo = longestCombo;
|
||||
|
||||
// Load player key names
|
||||
actionBarOptions = config.contains("action-bar") ? new ActionBarOptions(config.getConfigurationSection("action-bar")) : null;
|
||||
|
||||
// Load sounds
|
||||
beginComboSound = config.contains("sound.begin-combo") ? new SoundObject(config.getConfigurationSection("sound.begin-combo")) : null;
|
||||
comboClickSound = config.contains("sound.combo-key") ? new SoundObject(config.getConfigurationSection("sound.combo-key")) : null;
|
||||
failComboSound = config.contains("sound.fail-combo") ? new SoundObject(config.getConfigurationSection("sound.fail-combo")) : null;
|
||||
|
||||
// Find initializer key
|
||||
initializerKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("initializer-key"), "Could not find initializer key")));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void whenPressingKey(PlayerKeyPressEvent event) {
|
||||
PlayerData playerData = event.getData();
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
if (!event.getData().isCasting()) {
|
||||
if (event.getPressed() == initializerKey) {
|
||||
|
||||
// Cancel event if necessary
|
||||
if (event.getPressed().shouldCancelEvent())
|
||||
event.setCancelled(true);
|
||||
|
||||
// Start combo
|
||||
playerData.setSkillCasting(new CustomSkillCastingHandler(playerData));
|
||||
if (beginComboSound != null)
|
||||
beginComboSound.playTo(player);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Adding pressed key
|
||||
CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting();
|
||||
casting.current.registerKey(event.getPressed());
|
||||
casting.onTick();
|
||||
if (comboClickSound != null)
|
||||
comboClickSound.playTo(player);
|
||||
|
||||
// Cancel event if necessary
|
||||
if (event.getPressed().shouldCancelEvent())
|
||||
event.setCancelled(true);
|
||||
|
||||
// Hash current combo and check
|
||||
if (combos.containsKey(casting.current)) {
|
||||
int spellSlot = combos.get(casting.current) - 1;
|
||||
playerData.leaveCastingMode();
|
||||
|
||||
// Cast spell
|
||||
if (playerData.hasSkillBound(spellSlot)) {
|
||||
PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
playerData.getBoundSkill(spellSlot).toCastable(playerData).cast(new TriggerMetadata(caster, null, null));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if current combo is too large
|
||||
if (casting.current.countKeys() >= longestCombo) {
|
||||
playerData.leaveCastingMode();
|
||||
if (failComboSound != null)
|
||||
failComboSound.playTo(player);
|
||||
}
|
||||
}
|
||||
|
||||
private class CustomSkillCastingHandler extends SkillCastingHandler {
|
||||
private final KeyCombo current = new KeyCombo();
|
||||
|
||||
CustomSkillCastingHandler(PlayerData caster) {
|
||||
super(caster, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick() {
|
||||
if (actionBarOptions != null)
|
||||
getCaster().displayActionBar(actionBarOptions.format(current));
|
||||
}
|
||||
}
|
||||
|
||||
private class ActionBarOptions {
|
||||
private final String separator, noKey;
|
||||
|
||||
/**
|
||||
* Saves the names for all the players keys. Used when displaying
|
||||
* the current player's key combo on the action bar
|
||||
*/
|
||||
private final Map<PlayerKey, String> keyNames = new HashMap<>();
|
||||
|
||||
ActionBarOptions(ConfigurationSection config) {
|
||||
this.separator = Objects.requireNonNull(config.getString("separator"), "Could not find action bar option 'separator'");
|
||||
this.noKey = Objects.requireNonNull(config.getString("no-key"), "Could not find action bar option 'no-key'");
|
||||
|
||||
for (PlayerKey key : PlayerKey.values())
|
||||
keyNames.put(key, Objects.requireNonNull(config.getString("key-name." + key.name()), "Could not find translation for key " + key.name()));
|
||||
}
|
||||
|
||||
public String format(KeyCombo currentCombo) {
|
||||
|
||||
// Join all keys with separator
|
||||
String builder = currentCombo.countKeys() == 0 ? noKey : keyNames.get(currentCombo.getAt(0));
|
||||
int j = 1;
|
||||
for (; j < currentCombo.countKeys(); j++)
|
||||
builder += separator + keyNames.get(currentCombo.getAt(j));
|
||||
|
||||
// All remaining
|
||||
for (; j < longestCombo; j++)
|
||||
builder += separator + noKey;
|
||||
|
||||
return MythicLib.plugin.parseColors(builder);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,24 +4,20 @@ import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.SoundEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.listener.event.PlayerPressKeyListener;
|
||||
import net.Indyuce.mmocore.manager.ConfigManager;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.cast.PlayerKey;
|
||||
import org.bukkit.Bukkit;
|
||||
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -38,7 +34,8 @@ public class SkillBar implements Listener {
|
||||
return;
|
||||
|
||||
// Always cancel event
|
||||
event.setCancelled(true);
|
||||
if (event.getPressed().shouldCancelEvent())
|
||||
event.setCancelled(true);
|
||||
|
||||
// Enter spell casting
|
||||
Player player = event.getData().getPlayer();
|
||||
@ -46,15 +43,13 @@ public class SkillBar implements Listener {
|
||||
if (player.getGameMode() != GameMode.SPECTATOR
|
||||
&& (MMOCore.plugin.configManager.canCreativeCast || player.getGameMode() != GameMode.CREATIVE)
|
||||
&& !playerData.isCasting()
|
||||
&& playerData.getBoundSkills().size() > 0) {
|
||||
playerData.skillCasting = new SkillCasting(playerData);
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.SPELL_CAST_BEGIN);
|
||||
&& !playerData.getBoundSkills().isEmpty()) {
|
||||
playerData.setSkillCasting(new CustomSkillCastingHandler(playerData));
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_BEGIN).playTo(player);
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillCasting extends BukkitRunnable implements Listener {
|
||||
private final PlayerData playerData;
|
||||
|
||||
private class CustomSkillCastingHandler extends SkillCastingHandler {
|
||||
private final String ready = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.ready").message();
|
||||
private final String onCooldown = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.on-cooldown").message();
|
||||
private final String noMana = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.no-mana").message();
|
||||
@ -62,18 +57,15 @@ public class SkillBar implements Listener {
|
||||
|
||||
private int j;
|
||||
|
||||
public SkillCasting(PlayerData playerData) {
|
||||
this.playerData = playerData;
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
CustomSkillCastingHandler(PlayerData playerData) {
|
||||
super(playerData, 1);
|
||||
}
|
||||
|
||||
@EventHandler()
|
||||
public void onSkillCast(PlayerItemHeldEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!playerData.isOnline()) return;
|
||||
if (!event.getPlayer().equals(playerData.getPlayer()))
|
||||
if (!getCaster().isOnline()) return;
|
||||
if (!event.getPlayer().equals(getCaster().getPlayer()))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -92,9 +84,9 @@ public class SkillBar implements Listener {
|
||||
* cancelling the first one, the player held item slot must go back
|
||||
* to the previous one.
|
||||
*/
|
||||
if (slot >= 0 && playerData.hasSkillBound(slot)) {
|
||||
PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
playerData.getBoundSkill(slot).toCastable(playerData).cast(new TriggerMetadata(caster, null, null));
|
||||
if (slot >= 0 && getCaster().hasSkillBound(slot)) {
|
||||
PlayerMetadata caster = getCaster().getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
getCaster().getBoundSkill(slot).toCastable(getCaster()).cast(new TriggerMetadata(caster, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,20 +96,14 @@ public class SkillBar implements Listener {
|
||||
ConfigManager.SwapAction action = player.isSneaking()
|
||||
? MMOCore.plugin.configManager.sneakingSwapAction
|
||||
: MMOCore.plugin.configManager.normalSwapAction;
|
||||
if (action != ConfigManager.SwapAction.SPELL_CAST || !playerData.isOnline()) return;
|
||||
if (event.getPlayer().equals(playerData.getPlayer())) {
|
||||
MMOCore.plugin.soundManager.play(player, SoundManager.SoundEvent.SPELL_CAST_END);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.no-longer").send(playerData.getPlayer());
|
||||
close();
|
||||
if (action != ConfigManager.SwapAction.SPELL_CAST || !getCaster().isOnline()) return;
|
||||
if (event.getPlayer().equals(getCaster().getPlayer())) {
|
||||
MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_END).playTo(player);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.no-longer").send(getCaster().getPlayer());
|
||||
PlayerData.get(player).leaveCastingMode();
|
||||
}
|
||||
}
|
||||
|
||||
private void close() {
|
||||
playerData.skillCasting = null;
|
||||
HandlerList.unregisterAll(this);
|
||||
cancel();
|
||||
}
|
||||
|
||||
private String getFormat(PlayerData data) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
if (!data.isOnline()) return str.toString();
|
||||
@ -146,19 +132,14 @@ public class SkillBar implements Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!playerData.isOnline() || playerData.getPlayer().isDead()) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
public void onTick() {
|
||||
if (j % 20 == 0)
|
||||
playerData.displayActionBar(getFormat(playerData));
|
||||
getCaster().displayActionBar(getFormat(getCaster()));
|
||||
|
||||
for (int k = 0; k < 2; k++) {
|
||||
double a = (double) j++ / 5;
|
||||
playerData.getProfess().getCastParticle()
|
||||
.display(playerData.getPlayer().getLocation().add(Math.cos(a), 1 + Math.sin(a / 3) / 1.3, Math.sin(a)));
|
||||
getCaster().getProfess().getCastParticle()
|
||||
.display(getCaster().getPlayer().getLocation().add(Math.cos(a), 1 + Math.sin(a / 3) / 1.3, Math.sin(a)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,135 @@
|
||||
package net.Indyuce.mmocore.skill.cast.listener;
|
||||
|
||||
import io.lumine.mythic.lib.UtilityMethods;
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
|
||||
import net.Indyuce.mmocore.api.SoundObject;
|
||||
import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.skill.cast.PlayerKey;
|
||||
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SkillScroller implements Listener {
|
||||
|
||||
/**
|
||||
* Key players need to press to start casting
|
||||
*/
|
||||
private final PlayerKey enterKey, castKey;
|
||||
|
||||
@Nullable
|
||||
private final SoundObject enterSound, changeSound, leaveSound;
|
||||
|
||||
public SkillScroller(ConfigurationSection config) {
|
||||
|
||||
// Load sounds
|
||||
enterSound = config.contains("sound.enter") ? new SoundObject(config.getConfigurationSection("sound.enter")) : null;
|
||||
changeSound = config.contains("sound.change") ? new SoundObject(config.getConfigurationSection("sound.change")) : null;
|
||||
leaveSound = config.contains("sound.leave") ? new SoundObject(config.getConfigurationSection("sound.leave")) : null;
|
||||
|
||||
// Find keybinds
|
||||
enterKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("enter-key"), "Could not find enter key")));
|
||||
castKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("cast-key"), "Could not find cast key")));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void whenPressingKey(PlayerKeyPressEvent event) {
|
||||
PlayerData playerData = event.getData();
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
if (event.getPressed() == enterKey) {
|
||||
|
||||
// Leave casting mode
|
||||
if (playerData.isCasting()) {
|
||||
|
||||
// Cancel event if necessary
|
||||
if (event.getPressed().shouldCancelEvent())
|
||||
event.setCancelled(true);
|
||||
|
||||
playerData.leaveCastingMode();
|
||||
if (leaveSound != null)
|
||||
leaveSound.playTo(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there are skills bound
|
||||
if (playerData.getBoundSkills().isEmpty())
|
||||
return;
|
||||
|
||||
// Cancel event if necessary
|
||||
if (event.getPressed().shouldCancelEvent())
|
||||
event.setCancelled(true);
|
||||
|
||||
// Enter casting mode
|
||||
playerData.setSkillCasting(new CustomSkillCastingHandler(playerData));
|
||||
if (enterSound != null)
|
||||
enterSound.playTo(player);
|
||||
}
|
||||
|
||||
if (event.getPressed() == castKey && playerData.isCasting()) {
|
||||
|
||||
// Cancel event if necessary
|
||||
if (event.getPressed().shouldCancelEvent())
|
||||
event.setCancelled(true);
|
||||
|
||||
CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting();
|
||||
PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
playerData.getBoundSkill(casting.index).toCastable(playerData).cast(new TriggerMetadata(caster, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onScroll(PlayerItemHeldEvent event) {
|
||||
PlayerData playerData = PlayerData.get(event.getPlayer());
|
||||
if (!playerData.isCasting())
|
||||
return;
|
||||
|
||||
if (playerData.getBoundSkills().isEmpty()) {
|
||||
playerData.leaveCastingMode();
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
int previous = event.getPreviousSlot(), current = event.getNewSlot();
|
||||
int dist1 = 9 + current - previous, dist2 = current - previous, dist3 = current - previous - 9;
|
||||
int change = Math.abs(dist1) < Math.abs(dist2) ? (Math.abs(dist1) < Math.abs(dist3) ? dist1 : dist3) : (Math.abs(dist3) < Math.abs(dist2) ? dist3 : dist2);
|
||||
|
||||
// Scroll trough items
|
||||
CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting();
|
||||
casting.index = mod(casting.index + change, playerData.getBoundSkills().size());
|
||||
casting.onTick();
|
||||
}
|
||||
|
||||
private int mod(int x, int n) {
|
||||
|
||||
while (x < 0)
|
||||
x += n;
|
||||
|
||||
while (x >= n)
|
||||
x -= n;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private class CustomSkillCastingHandler extends SkillCastingHandler {
|
||||
private int index = 0;
|
||||
|
||||
CustomSkillCastingHandler(PlayerData caster) {
|
||||
super(caster, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick() {
|
||||
getCaster().displayActionBar("CLICK: " + getCaster().getBoundSkill(index).getSkill().getName());
|
||||
}
|
||||
}
|
||||
}
|
@ -62,6 +62,47 @@ protect-custom-mine: false
|
||||
# provide the player with experience points or not
|
||||
should-cobblestone-generators-give-exp: false
|
||||
|
||||
# Edit how to cast skills here. This part of the config is
|
||||
# pretty tricky so it's best to read the wiki page before editing anything
|
||||
skill-casting:
|
||||
mode: KEY_COMBOS
|
||||
initializer-key: SWAP_HANDS
|
||||
sound:
|
||||
begin-combo:
|
||||
sound: BLOCK_END_PORTAL_FRAME_FILL
|
||||
volume: 1
|
||||
pitch: 2
|
||||
combo-key:
|
||||
sound: BLOCK_LEVER_CLICK
|
||||
volume: 1
|
||||
pitch: 2
|
||||
fail-combo:
|
||||
sound: BLOCK_FIRE_EXTINGUISH
|
||||
volume: 1
|
||||
pitch: 2
|
||||
action-bar:
|
||||
separator: ' - '
|
||||
no-key: '***'
|
||||
key-name:
|
||||
LEFT_CLICK: 'LEFT'
|
||||
RIGHT_CLICK: 'RGHT'
|
||||
DROP: 'DROP'
|
||||
SWAP_HANDS: 'SWAP'
|
||||
CROUCH: 'SHFT'
|
||||
combos:
|
||||
'1':
|
||||
- LEFT_CLICK
|
||||
- LEFT_CLICK
|
||||
'2':
|
||||
- LEFT_CLICK
|
||||
- RIGHT_CLICK
|
||||
'3':
|
||||
- RIGHT_CLICK
|
||||
- LEFT_CLICK
|
||||
'4':
|
||||
- RIGHT_CLICK
|
||||
- RIGHT_CLICK
|
||||
|
||||
loot-chests:
|
||||
|
||||
# Time in seconds it takes for a loot chest to
|
||||
@ -140,17 +181,19 @@ death-exp-loss:
|
||||
# Percentage of current EXP you lose when dying.
|
||||
percent: 30
|
||||
|
||||
# Modify the keybinds for the 'swap hand items' key (F by default)
|
||||
#
|
||||
# Available actions:
|
||||
# - spell_cast (enters the default spell casting mode)
|
||||
# - vanilla (swaps hand items)
|
||||
# - hotbar_swap (swap the player's horbat with the 9 lowest inventory slots)
|
||||
#
|
||||
# If the action is invalid, it will use 'vanilla' by default
|
||||
swap-keybind:
|
||||
normal: spell_cast
|
||||
sneaking: hotbar_swap
|
||||
# Fun extra RPG feature that switches the player's hotbar with
|
||||
# the 9 lower row items of his inventory. This allows the player
|
||||
# to have two different item sets or quickly have access to pots
|
||||
# TODO
|
||||
hotbar-swapping:
|
||||
enabled: true
|
||||
|
||||
# Keybind which triggers
|
||||
# Available keybinds
|
||||
keybind: SWAP_HANDS
|
||||
|
||||
# If the player has to sneak to swap hotbars
|
||||
crouching: true
|
||||
|
||||
# Set this to true to allow players
|
||||
# in creative mode to enter casting mode
|
||||
|
Loading…
Reference in New Issue
Block a user