diff --git a/core/src/main/java/com/nisovin/magicspells/castmodifiers/conditions/FixedPoseCondition.java b/core/src/main/java/com/nisovin/magicspells/castmodifiers/conditions/FixedPoseCondition.java new file mode 100644 index 000000000..94b57c7b0 --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/castmodifiers/conditions/FixedPoseCondition.java @@ -0,0 +1,30 @@ +package com.nisovin.magicspells.castmodifiers.conditions; + +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; + +import com.nisovin.magicspells.castmodifiers.Condition; + +public class FixedPoseCondition extends Condition { + + @Override + public boolean initialize(String var) { + return var.isEmpty(); + } + + @Override + public boolean check(LivingEntity caster) { + return caster.hasFixedPose(); + } + + @Override + public boolean check(LivingEntity caster, LivingEntity target) { + return target.hasFixedPose(); + } + + @Override + public boolean check(LivingEntity caster, Location location) { + return false; + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/castmodifiers/conditions/PoseCondition.java b/core/src/main/java/com/nisovin/magicspells/castmodifiers/conditions/PoseCondition.java new file mode 100644 index 000000000..ab2c1ca0d --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/castmodifiers/conditions/PoseCondition.java @@ -0,0 +1,46 @@ +package com.nisovin.magicspells.castmodifiers.conditions; + +import java.util.Set; +import java.util.EnumSet; + +import org.bukkit.Location; +import org.bukkit.entity.Pose; +import org.bukkit.entity.LivingEntity; + +import com.nisovin.magicspells.castmodifiers.Condition; + +public class PoseCondition extends Condition { + + private final Set poses = EnumSet.noneOf(Pose.class); + + @Override + public boolean initialize(String var) { + String[] split = var.split(","); + + for (String pose : split) { + try { + poses.add(Pose.valueOf(pose.trim().toUpperCase())); + } catch (IllegalArgumentException e) { + return false; + } + } + + return !poses.isEmpty(); + } + + @Override + public boolean check(LivingEntity caster) { + return poses.contains(caster.getPose()); + } + + @Override + public boolean check(LivingEntity caster, LivingEntity target) { + return poses.contains(target.getPose()); + } + + @Override + public boolean check(LivingEntity caster, Location location) { + return false; + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/spells/passive/InsideBlockListener.java b/core/src/main/java/com/nisovin/magicspells/spells/passive/InsideBlockListener.java new file mode 100644 index 000000000..5339775bf --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/spells/passive/InsideBlockListener.java @@ -0,0 +1,60 @@ +package com.nisovin.magicspells.spells.passive; + +import java.util.List; +import java.util.ArrayList; + +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.entity.LivingEntity; +import org.bukkit.block.data.BlockData; + +import io.papermc.paper.event.entity.EntityInsideBlockEvent; + +import com.nisovin.magicspells.MagicSpells; +import com.nisovin.magicspells.util.OverridePriority; +import com.nisovin.magicspells.spells.passive.util.PassiveListener; + +public class InsideBlockListener extends PassiveListener { + + private List blockData; + + @Override + public void initialize(String var) { + if (var == null || var.isEmpty()) return; + + blockData = new ArrayList<>(); + + for (String data : var.split(",(?![^\\[]*])")) { + try { + blockData.add(Bukkit.createBlockData(data.trim().toLowerCase())); + } catch (IllegalArgumentException e) { + MagicSpells.error("Invalid block data '" + data + "' in insideblock trigger on passive spell '" + passiveSpell.getInternalName() + "'"); + } + } + } + + @OverridePriority + @EventHandler + public void onSwim(EntityInsideBlockEvent event) { + if (!isCancelStateOk(event.isCancelled())) return; + if (!(event.getEntity() instanceof LivingEntity caster) || !canTrigger(caster) || !hasSpell(caster)) return; + + Block block = event.getBlock(); + if (blockData != null && check(block)) return; + + boolean casted = passiveSpell.activate(caster, block.getLocation().add(0.5, 0.5, 0.5)); + if (cancelDefaultAction(casted)) event.setCancelled(true); + } + + private boolean check(Block block) { + BlockData bd = block.getBlockData(); + + for (BlockData data : blockData) + if (bd.matches(data)) + return false; + + return true; + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/spells/passive/StartPoseListener.java b/core/src/main/java/com/nisovin/magicspells/spells/passive/StartPoseListener.java new file mode 100644 index 000000000..7baa7284a --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/spells/passive/StartPoseListener.java @@ -0,0 +1,43 @@ +package com.nisovin.magicspells.spells.passive; + +import java.util.Set; +import java.util.EnumSet; + +import org.bukkit.entity.Pose; +import org.bukkit.event.EventHandler; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityPoseChangeEvent; + +import com.nisovin.magicspells.MagicSpells; +import com.nisovin.magicspells.util.OverridePriority; +import com.nisovin.magicspells.spells.passive.util.PassiveListener; + +public class StartPoseListener extends PassiveListener { + + private Set poses; + + @Override + public void initialize(String var) { + if (var == null || var.isEmpty()) return; + + poses = EnumSet.noneOf(Pose.class); + + for (String pose : var.split(",")) { + try { + poses.add(Pose.valueOf(pose.trim().toUpperCase())); + } catch (IllegalArgumentException e) { + MagicSpells.error("Invalid pose '" + pose + "' in startpose trigger on passive spell '" + passiveSpell.getInternalName() + "'"); + } + } + } + + @OverridePriority + @EventHandler + public void onPoseChange(EntityPoseChangeEvent event) { + if (!(event.getEntity() instanceof LivingEntity caster) || !canTrigger(caster) || !hasSpell(caster)) return; + if (poses != null && !poses.contains(event.getPose())) return; + + passiveSpell.activate(caster); + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/spells/passive/StopPoseListener.java b/core/src/main/java/com/nisovin/magicspells/spells/passive/StopPoseListener.java new file mode 100644 index 000000000..df731e1ff --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/spells/passive/StopPoseListener.java @@ -0,0 +1,43 @@ +package com.nisovin.magicspells.spells.passive; + +import java.util.Set; +import java.util.EnumSet; + +import org.bukkit.entity.Pose; +import org.bukkit.event.EventHandler; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityPoseChangeEvent; + +import com.nisovin.magicspells.MagicSpells; +import com.nisovin.magicspells.util.OverridePriority; +import com.nisovin.magicspells.spells.passive.util.PassiveListener; + +public class StopPoseListener extends PassiveListener { + + private Set poses; + + @Override + public void initialize(String var) { + if (var == null || var.isEmpty()) return; + + poses = EnumSet.noneOf(Pose.class); + + for (String pose : var.split(",")) { + try { + poses.add(Pose.valueOf(pose.trim().toUpperCase())); + } catch (IllegalArgumentException e) { + MagicSpells.error("Invalid pose '" + pose + "' in startpose trigger on passive spell '" + passiveSpell.getInternalName() + "'"); + } + } + } + + @OverridePriority + @EventHandler + public void onPoseChange(EntityPoseChangeEvent event) { + if (!(event.getEntity() instanceof LivingEntity caster) || !canTrigger(caster) || !hasSpell(caster)) return; + if (poses != null && !poses.contains(caster.getPose())) return; + + passiveSpell.activate(caster); + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/spells/targeted/PoseSpell.java b/core/src/main/java/com/nisovin/magicspells/spells/targeted/PoseSpell.java new file mode 100644 index 000000000..3233d8ee7 --- /dev/null +++ b/core/src/main/java/com/nisovin/magicspells/spells/targeted/PoseSpell.java @@ -0,0 +1,46 @@ +package com.nisovin.magicspells.spells.targeted; + +import org.bukkit.entity.Pose; +import org.bukkit.entity.LivingEntity; + +import com.nisovin.magicspells.util.SpellData; +import com.nisovin.magicspells.util.CastResult; +import com.nisovin.magicspells.util.TargetInfo; +import com.nisovin.magicspells.util.MagicConfig; +import com.nisovin.magicspells.spells.TargetedSpell; +import com.nisovin.magicspells.util.config.ConfigData; +import com.nisovin.magicspells.spells.TargetedEntitySpell; + +public class PoseSpell extends TargetedSpell implements TargetedEntitySpell { + + private final ConfigData pose; + + private final ConfigData fixed; + + public PoseSpell(MagicConfig config, String spellName) { + super(config, spellName); + + pose = getConfigDataEnum("pose", Pose.class, null); + fixed = getConfigDataBoolean("fixed", false); + } + + @Override + public CastResult cast(SpellData data) { + TargetInfo info = getTargetedEntity(data); + if (info.noTarget()) return noTarget(info); + + return castAtEntity(info.spellData()); + } + + @Override + public CastResult castAtEntity(SpellData data) { + Pose pose = this.pose.get(data); + if (pose == null) return new CastResult(PostCastAction.ALREADY_HANDLED, data); + + data.target().setPose(pose, fixed.get(data)); + + playSpellEffects(data); + return new CastResult(PostCastAction.HANDLE_NORMALLY, data); + } + +} diff --git a/core/src/main/java/com/nisovin/magicspells/util/managers/ConditionManager.java b/core/src/main/java/com/nisovin/magicspells/util/managers/ConditionManager.java index 7c8dd7b56..6f5697a1c 100644 --- a/core/src/main/java/com/nisovin/magicspells/util/managers/ConditionManager.java +++ b/core/src/main/java/com/nisovin/magicspells/util/managers/ConditionManager.java @@ -184,6 +184,8 @@ private void initialize() { addCondition("passable", PassableCondition.class); addCondition("replaceable", ReplaceableCondition.class); addCondition("solid", SolidCondition.class); + addCondition("pose", PoseCondition.class); + addCondition("fixedpose", FixedPoseCondition.class); } } diff --git a/core/src/main/java/com/nisovin/magicspells/util/managers/PassiveManager.java b/core/src/main/java/com/nisovin/magicspells/util/managers/PassiveManager.java index 8a0667952..a7e9329c1 100644 --- a/core/src/main/java/com/nisovin/magicspells/util/managers/PassiveManager.java +++ b/core/src/main/java/com/nisovin/magicspells/util/managers/PassiveManager.java @@ -91,6 +91,7 @@ private void initialize() { addListener("hitarrow", HitArrowListener.class); addListener("hotbardeselect", HotbarDeselectListener.class); addListener("hotbarselect", HotbarSelectListener.class); + addListener("insideblock", InsideBlockListener.class); addListener("inventoryaction", InventoryActionListener.class); addListener("inventoryclick", InventoryClickListener.class); addListener("inventoryclose", InventoryCloseListener.class); @@ -132,11 +133,13 @@ private void initialize() { addListener("spelltarget", SpellTargetListener.class); addListener("startfly", StartFlyListener.class); addListener("startglide", StartGlideListener.class); + addListener("startpose", StartPoseListener.class); addListener("startsneak", StartSneakListener.class); addListener("startsprint", StartSprintListener.class); addListener("startswim", StartSwimListener.class); addListener("stopfly", StopFlyListener.class); addListener("stopglide", StopGlideListener.class); + addListener("stoppose", StopPoseListener.class); addListener("stopsneak", StopSneakListener.class); addListener("stopsprint", StopSprintListener.class); addListener("stopswim", StopSwimListener.class);