Skill casting timeout, fixed casting particles

This commit is contained in:
Jules 2023-10-22 00:03:35 +02:00
parent 2d779d19bf
commit 88d02f140f
8 changed files with 114 additions and 83 deletions

View File

@ -0,0 +1,32 @@
package net.Indyuce.mmocore.skill.cast;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public abstract class SkillCastingHandler implements Listener {
private final int timeoutDelay;
private final boolean timesOut;
public SkillCastingHandler(@NotNull ConfigurationSection config) {
timesOut = config.contains("time-out");
timeoutDelay = config.getInt("time-out");
Validate.isTrue(!timesOut || timeoutDelay > 0, "Timeout must be strictly positive or disabled");
}
public boolean doesTimeOut() {
return timesOut;
}
public int getTimeoutDelay() {
return timeoutDelay;
}
@NotNull
public abstract SkillCastingMode getCastingMode();
@NotNull
public abstract SkillCastingInstance newInstance(@NotNull PlayerData player);
}

View File

@ -7,17 +7,21 @@ import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
public abstract class SkillCastingInstance extends BukkitRunnable implements Listener {
private final PlayerData caster;
private final SkillCastingHandler handler;
private final int runnablePeriod = 10; // Hard coded
private boolean open = true;
private int j;
private int j, sinceLastActivity;
public SkillCastingInstance(PlayerData caster, int runnablePeriod) {
public SkillCastingInstance(@NotNull SkillCastingHandler handler, @NotNull PlayerData caster) {
this.handler = handler;
this.caster = caster;
runTaskTimer(MMOCore.plugin, 0, runnablePeriod);
runTaskTimer(MMOCore.plugin, 0, 1);
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
}
@ -26,7 +30,7 @@ public abstract class SkillCastingInstance extends BukkitRunnable implements Lis
}
public void close() {
Validate.isTrue(open, "Skill casting already ended");
Validate.isTrue(open, "Skill casting already closed");
open = false;
@ -37,6 +41,12 @@ public abstract class SkillCastingInstance extends BukkitRunnable implements Lis
cancel();
}
public void refreshTimeOut() {
sinceLastActivity = 0;
}
private static final int PARTICLES_PER_TICK = 2;
@Override
public void run() {
if (!caster.isOnline() || caster.getPlayer().isDead()) {
@ -44,16 +54,20 @@ public abstract class SkillCastingInstance extends BukkitRunnable implements Lis
return;
}
// Check for timeout
if (handler.doesTimeOut() && sinceLastActivity++ > handler.getTimeoutDelay()) {
caster.leaveSkillCasting(true);
return;
}
// Apply casting particles
if (caster.getProfess().getCastParticle() != null)
for (int k = 0; k < 2; k++) {
double a = (double) j++ / 5;
caster.getProfess().getCastParticle()
.display(caster.getPlayer().getLocation().add(Math.cos(a), 1 + Math.sin(a / 3) / 1.3, Math.sin(a)));
}
if (caster.getProfess().getCastParticle() != null) for (int k = 0; k < PARTICLES_PER_TICK; k++) {
final double a = (double) (PARTICLES_PER_TICK * j + k) / 4;
caster.getProfess().getCastParticle().display(caster.getPlayer().getLocation().add(Math.cos(a), 1 + Math.sin(a / 3) / 1.3, Math.sin(a)));
}
// Apply casting mode-specific effects
onTick();
if (j++ % runnablePeriod == 0) onTick();
}
public abstract void onTick();

View File

@ -1,18 +0,0 @@
package net.Indyuce.mmocore.skill.cast;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
/**
* @apiNote Purely for API
*/
public interface SkillCastingListener extends Listener {
@NotNull
public SkillCastingMode getCastingMode();
@NotNull
public SkillCastingInstance newInstance(@NotNull PlayerData player);
}

View File

@ -1,8 +1,8 @@
package net.Indyuce.mmocore.skill.cast;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.skill.cast.listener.SkillBar;
import net.Indyuce.mmocore.skill.cast.listener.KeyCombos;
import net.Indyuce.mmocore.skill.cast.listener.SkillBar;
import net.Indyuce.mmocore.skill.cast.listener.SkillCastingDisabled;
import net.Indyuce.mmocore.skill.cast.listener.SkillScroller;
import org.apache.commons.lang.Validate;
@ -42,7 +42,7 @@ public enum SkillCastingMode {
/**
* Entirely disables skill casting.
*/
NONE(config -> new SkillCastingDisabled());
NONE(config -> new SkillCastingDisabled(config));
/**
* Not implemented yet.
@ -63,11 +63,11 @@ public enum SkillCastingMode {
;
private final Function<ConfigurationSection, SkillCastingListener> listenerLoader;
private final Function<ConfigurationSection, SkillCastingHandler> listenerLoader;
private static SkillCastingListener current;
private static SkillCastingHandler current;
SkillCastingMode(Function<ConfigurationSection, SkillCastingListener> listenerLoader) {
SkillCastingMode(Function<ConfigurationSection, SkillCastingHandler> listenerLoader) {
this.listenerLoader = listenerLoader;
}
@ -81,7 +81,7 @@ public enum SkillCastingMode {
}
@NotNull
public static SkillCastingListener getCurrent() {
public static SkillCastingHandler getCurrent() {
return Objects.requireNonNull(current, "Skill casting mode hasn't been initialized yet");
}
}

View File

@ -21,8 +21,7 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.*;
public class KeyCombos implements SkillCastingListener {
public class KeyCombos extends SkillCastingHandler {
private final ComboMap comboMap;
/**
@ -43,7 +42,9 @@ public class KeyCombos implements SkillCastingListener {
@Nullable
private final SoundObject beginComboSound, comboClickSound, failComboSound;
public KeyCombos(ConfigurationSection config) {
public KeyCombos(@NotNull ConfigurationSection config) {
super(config);
comboMap = new ComboMap(config.getConfigurationSection("combos"));
actionBarOptions = config.contains("action-bar") ? new ActionBarOptions(config.getConfigurationSection("action-bar")) : null;
@ -108,6 +109,7 @@ public class KeyCombos implements SkillCastingListener {
if (casting == null) return;
// Adding pressed key
casting.refreshTimeOut();
casting.current.registerKey(event.getPressed());
casting.onTick();
if (comboClickSound != null) comboClickSound.playTo(player);
@ -135,30 +137,6 @@ public class KeyCombos implements SkillCastingListener {
}
}
private static final Set<TriggerType> IGNORED_WHEN_CASTING = new HashSet<>();
static {
IGNORED_WHEN_CASTING.add(TriggerType.RIGHT_CLICK);
IGNORED_WHEN_CASTING.add(TriggerType.LEFT_CLICK);
IGNORED_WHEN_CASTING.add(TriggerType.SHIFT_RIGHT_CLICK);
IGNORED_WHEN_CASTING.add(TriggerType.SHIFT_LEFT_CLICK);
IGNORED_WHEN_CASTING.add(TriggerType.SNEAK);
}
/**
* This makes sure NO skills are cast when in casting mode so that
* item abilities from MMOItems don't interfere with that.
* <p>
* Any trigger type that has a PlayerKey associated to it will
* be ignored if the player is currently in casting mode.
*/
@EventHandler
public void ignoreOtherSkills(PlayerCastSkillEvent event) {
TriggerType triggerType = event.getCast().getTrigger();
if (IGNORED_WHEN_CASTING.contains(triggerType) && PlayerData.get(event.getData()).isCasting())
event.setCancelled(true);
}
/**
* Loads the player current combos & the combos applicable to the player
* (combos defined in its class or the default combos of the config.yml)
@ -168,7 +146,7 @@ public class KeyCombos implements SkillCastingListener {
private final ComboMap combos;
CustomSkillCastingInstance(PlayerData caster) {
super(caster, 10);
super(KeyCombos.this, caster);
combos = Objects.requireNonNullElse(caster.getProfess().getComboMap(), comboMap);
}
@ -180,6 +158,26 @@ public class KeyCombos implements SkillCastingListener {
getCaster().getPlayer().sendTitle(" ", actionBarOptions.format(this), 0, 20, 0);
else getCaster().displayActionBar(actionBarOptions.format(this));
}
private static final List<TriggerType> IGNORED_WHEN_CASTING = Arrays.asList(
TriggerType.RIGHT_CLICK,
TriggerType.LEFT_CLICK,
TriggerType.SHIFT_RIGHT_CLICK,
TriggerType.SHIFT_LEFT_CLICK,
TriggerType.SNEAK);
/**
* This makes sure NO skills are cast when in casting mode so that
* item abilities from MMOItems don't interfere with that.
* <p>
* Any trigger type that has a PlayerKey associated to it will
* be ignored if the player is currently in casting mode.
*/
@EventHandler
public void ignoreOtherSkills(PlayerCastSkillEvent event) {
if (!event.getPlayer().equals(getCaster().getPlayer())) return;
if (IGNORED_WHEN_CASTING.contains(event.getCast().getTrigger())) event.setCancelled(true);
}
}
private class ActionBarOptions {

View File

@ -9,25 +9,23 @@ import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.cast.PlayerKey;
import net.Indyuce.mmocore.skill.cast.SkillCastingInstance;
import net.Indyuce.mmocore.skill.cast.SkillCastingListener;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import net.Indyuce.mmocore.skill.cast.*;
import org.bukkit.GameMode;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class SkillBar implements SkillCastingListener {
public class SkillBar extends SkillCastingHandler {
private final PlayerKey mainKey;
private final boolean disableSneak;
public SkillBar(ConfigurationSection config) {
public SkillBar(@NotNull ConfigurationSection config) {
super(config);
mainKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("open"), "Could not find open key")));
disableSneak = config.getBoolean("disable-sneak");
}
@ -70,7 +68,7 @@ public class SkillBar implements SkillCastingListener {
private int j;
CustomSkillCastingInstance(PlayerData playerData) {
super(playerData, 1);
super(SkillBar.this, playerData);
}
@EventHandler
@ -89,7 +87,8 @@ public class SkillBar implements SkillCastingListener {
if (event.getPreviousSlot() == event.getNewSlot()) return;
event.setCancelled(true);
int slot = event.getNewSlot() + 1 + (event.getNewSlot() >= player.getInventory().getHeldItemSlot() ? -1 : 0);
refreshTimeOut();
final int slot = event.getNewSlot() + 1 + (event.getNewSlot() >= player.getInventory().getHeldItemSlot() ? -1 : 0);
/*
* The event is called again soon after the first since when
@ -153,7 +152,7 @@ public class SkillBar implements SkillCastingListener {
@Override
public void onTick() {
if (j++ % 20 == 0) getCaster().displayActionBar(getFormat(getCaster()));
if (j++ % 2 == 0) getCaster().displayActionBar(getFormat(getCaster()));
}
}
}

View File

@ -1,12 +1,16 @@
package net.Indyuce.mmocore.skill.cast.listener;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
import net.Indyuce.mmocore.skill.cast.SkillCastingInstance;
import net.Indyuce.mmocore.skill.cast.SkillCastingListener;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public class SkillCastingDisabled implements SkillCastingListener {
public class SkillCastingDisabled extends SkillCastingHandler {
public SkillCastingDisabled(@NotNull ConfigurationSection config) {
super(config);
}
@Override
public SkillCastingInstance newInstance(@NotNull PlayerData player) {

View File

@ -9,8 +9,8 @@ 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 net.Indyuce.mmocore.skill.cast.SkillCastingInstance;
import net.Indyuce.mmocore.skill.cast.SkillCastingListener;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import org.bukkit.GameMode;
import org.bukkit.configuration.ConfigurationSection;
@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.Objects;
public class SkillScroller implements SkillCastingListener {
public class SkillScroller extends SkillCastingHandler {
/**
* Key players need to press to start casting
@ -32,7 +32,8 @@ public class SkillScroller implements SkillCastingListener {
@Nullable
private final SoundObject enterSound, changeSound, leaveSound;
public SkillScroller(ConfigurationSection config) {
public SkillScroller(@NotNull ConfigurationSection config) {
super(config);
// Load sounds
enterSound = config.contains("sound.enter") ? new SoundObject(config.getConfigurationSection("sound.enter")) : null;
@ -110,14 +111,15 @@ public class SkillScroller implements SkillCastingListener {
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);
final int previous = event.getPreviousSlot(), current = event.getNewSlot();
final int dist1 = 9 + current - previous, dist2 = current - previous, dist3 = current - previous - 9;
final 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
CustomSkillCastingInstance casting = (CustomSkillCastingInstance) playerData.getSkillCasting();
final CustomSkillCastingInstance casting = (CustomSkillCastingInstance) playerData.getSkillCasting();
casting.index = mod(casting.index + change, playerData.getBoundSkills().size());
casting.onTick();
casting.refreshTimeOut();
if (changeSound != null) changeSound.playTo(event.getPlayer());
}
@ -135,7 +137,7 @@ public class SkillScroller implements SkillCastingListener {
private int index = 0;
CustomSkillCastingInstance(PlayerData caster) {
super(caster, 10);
super(SkillScroller.this, caster);
}
@Override