diff --git a/LICENSE.MD b/LICENSE.MD new file mode 100644 index 0000000..d180905 --- /dev/null +++ b/LICENSE.MD @@ -0,0 +1,19 @@ +Copyright (c) 2023 Simplex Development Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), +to deal with the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 34890c0..2c51c4f 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ repositories { dependencies { compileOnly "org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT" + compileOnly "org.reflections:reflections:0.10.2" } def targetJavaVersion = 17 diff --git a/src/main/java/app/simplexdev/arcanumocculta/ArcanumOcculta.java b/src/main/java/app/simplexdev/arcanumocculta/ArcanumOcculta.java index 5046135..0ed3c62 100644 --- a/src/main/java/app/simplexdev/arcanumocculta/ArcanumOcculta.java +++ b/src/main/java/app/simplexdev/arcanumocculta/ArcanumOcculta.java @@ -2,16 +2,15 @@ package app.simplexdev.arcanumocculta; import org.bukkit.plugin.java.JavaPlugin; -public final class ArcanumOcculta extends JavaPlugin { - +public class ArcanumOcculta extends JavaPlugin +{ @Override public void onEnable() { - // Plugin startup logic } - @Override - public void onDisable() { - // Plugin shutdown logic + public static ArcanumOcculta getInstance() + { + return JavaPlugin.getPlugin(ArcanumOcculta.class); } } diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/book/SpellBook.java b/src/main/java/app/simplexdev/arcanumocculta/api/book/SpellBook.java deleted file mode 100644 index 9a92d79..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/book/SpellBook.java +++ /dev/null @@ -1,32 +0,0 @@ -package app.simplexdev.arcanumocculta.api.book; - -import app.simplexdev.arcanumocculta.api.spell.Spell; -import org.bukkit.inventory.ItemStack; - -import java.util.List; - -public interface SpellBook { - String getBookName(); - - void setBookName(final String name); - - String getBookDescription(); - - void setBookDescription(final String description); - - ItemStack getBookItem(); - - void setBookItem(final ItemStack itemStack); - - List getSpells(); - - void addSpell(Spell spell); - - void removeSpell(Spell spell); - - Spell getSpell(final String name); - - Spell getSpell(final int index); - - int getSpellCount(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/book/SpellTome.java b/src/main/java/app/simplexdev/arcanumocculta/api/book/SpellTome.java deleted file mode 100644 index 3cd49db..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/book/SpellTome.java +++ /dev/null @@ -1,14 +0,0 @@ -package app.simplexdev.arcanumocculta.api.book; - -import app.simplexdev.arcanumocculta.api.spell.Spell; -import org.bukkit.inventory.ItemStack; - -public interface SpellTome { - String getTomeName(); - - String getTomeDescription(); - - ItemStack getTomeItem(); - - Spell getContainedSpell(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/caster/AbstractCaster.java b/src/main/java/app/simplexdev/arcanumocculta/api/caster/AbstractCaster.java new file mode 100644 index 0000000..4c9bfe1 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/caster/AbstractCaster.java @@ -0,0 +1,137 @@ +package app.simplexdev.arcanumocculta.api.caster; + +import app.simplexdev.arcanumocculta.api.wand.Wand; +import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public abstract class AbstractCaster implements Caster +{ + private final SpellBook spellBook; + private final UUID playerUUID; + private final String name; + private Wand wand; + private CasterLevel level; + private double currentExperience; + private double currentMana; + private double maxMana; + + protected AbstractCaster(final Player player, final Wand wand, final SpellBook spellBook, final CasterLevel level) + { + this.spellBook = spellBook; + this.playerUUID = player.getUniqueId(); + this.name = player.getName(); + this.wand = wand; + this.level = level; + } + + @Override + public Wand getWand() + { + return this.wand; + } + + public void setWand(final Wand wand) + { + this.wand = wand; + } + + @Override + public SpellBook getSpellBook() + { + return this.spellBook; + } + + @Override + public UUID getUniqueId() + { + return this.playerUUID; + } + + @Override + public String getName() + { + return this.name; + } + + @Override + public CasterLevel getCurrentLevel() + { + return this.level; + } + + public void setCurrentLevel(final CasterLevel level) + { + this.level = level; + } + + @Override + public double getCurrentExperience() + { + return this.currentExperience; + } + + public void setCurrentExperience(final double experience) + { + this.currentExperience = experience; + } + + @Override + public double getCurrentMana() + { + return this.currentMana; + } + + public void setCurrentMana(final double mana) + { + this.currentMana = mana; + } + + @Override + public double getMaxMana() + { + return this.maxMana; + } + + @Override + public void setMaxMana(final double mana) + { + this.maxMana = mana; + } + + public void addExperience(final double experience) + { + this.currentExperience = this.currentExperience + experience; + } + + public void removeExperience(final double experience) + { + this.currentExperience = this.currentExperience - experience; + } + + public void addMana(final double mana) + { + this.currentMana = this.currentMana + mana; + } + + public void removeMana(final double mana) + { + this.currentMana = this.currentMana - mana; + } + + public void setManaToMax() + { + this.currentMana = this.maxMana; + } + + public void setExperienceToZero() + { + this.currentExperience = 0; + } + + @Override + public Player bukkit() + { + return Bukkit.getPlayer(this.playerUUID); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/caster/AbstractSpellBook.java b/src/main/java/app/simplexdev/arcanumocculta/api/caster/AbstractSpellBook.java new file mode 100644 index 0000000..c805a0a --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/caster/AbstractSpellBook.java @@ -0,0 +1,97 @@ +package app.simplexdev.arcanumocculta.api.caster; + +import app.simplexdev.arcanumocculta.api.spell.Spell; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.SplittableRandom; +import java.util.UUID; + +public abstract class AbstractSpellBook implements SpellBook +{ + private final List spells = new ArrayList<>(); + + @Override + public boolean hasSpell(final Spell spell) + { + return getSpells().contains(spell); + } + + @Override + public List getSpells() + { + return this.spells; + } + + @Override + public void addSpell(Spell spell) + { + this.spells.add(spell); + } + + @Override + public void removeSpell(Spell spell) + { + this.spells.remove(spell); + } + + @Override + public Spell getSpell(String id) + { + return getSpells().stream() + .filter(spell -> spell.getId().equalsIgnoreCase(id)) + .findFirst() + .orElse(getSpells().get(0)); + } + + public Spell getSpell(UUID uuid) + { + return getSpells().stream() + .filter(spell -> spell.getUniqueId().equals(uuid)) + .findFirst() + .orElse(getSpells().get(0)); + } + + @Override + public Spell getSpell(int index) + { + if (index < 0 || index > getSpells().size() - 1) + return getSpells().get(0); + return getSpells().get(index); + } + + @Override + public int getSpellCount() + { + return getSpells().size(); + } + + @Override + public void setSpell(int index, Spell spell) + { + this.spells.set(index, spell); + } + + @Override + public void setSpell(String name, Spell spell) + { + this.spells.set(getSpells().indexOf(getSpell(name)), spell); + } + + @Override + public void clearSpells() + { + this.spells.clear(); + } + + public void addAll(Collection spells) { + this.spells.addAll(spells); + } + + @Override + public Spell randomSpell() + { + final SplittableRandom random = new SplittableRandom(); + return getSpells().get(random.nextInt(getSpells().size())); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/caster/Caster.java b/src/main/java/app/simplexdev/arcanumocculta/api/caster/Caster.java new file mode 100644 index 0000000..67b55b6 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/caster/Caster.java @@ -0,0 +1,44 @@ +package app.simplexdev.arcanumocculta.api.caster; + +import app.simplexdev.arcanumocculta.api.wand.Wand; +import java.util.UUID; +import org.bukkit.entity.Player; + +public interface Caster +{ + Wand getWand(); + + void setWand(Wand wand); + + SpellBook getSpellBook(); + + String getName(); + + UUID getUniqueId(); + + double getCurrentMana(); + + void setCurrentMana(double mana); + + double getMaxMana(); + + void setMaxMana(double maxMana); + + CasterLevel getCurrentLevel(); + + void setCurrentLevel(CasterLevel level); + + double getCurrentExperience(); + + void setCurrentExperience(double experience); + + void addMana(double mana); + + void removeMana(double mana); + + void addExperience(double experience); + + void removeExperience(double experience); + + Player bukkit(); +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/caster/CasterLevel.java b/src/main/java/app/simplexdev/arcanumocculta/api/caster/CasterLevel.java new file mode 100644 index 0000000..78ec485 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/caster/CasterLevel.java @@ -0,0 +1,85 @@ +package app.simplexdev.arcanumocculta.api.caster; + +import java.text.MessageFormat; +import java.util.stream.Stream; +import org.bukkit.ChatColor; + +public enum CasterLevel +{ + + APPRENTICE(1, 250D, "Apprentice", "an Apprentice", ChatColor.WHITE, "Lvl1"), + PRIMARY(2, 500D, "Primary", "a Primary", ChatColor.RED, "Lvl2"), + SCHOLAR(3, 750D, "Scholar", "a Scholar", ChatColor.AQUA, "Lvl3"), + PREFECT(4, 1000D, "Prefect", "a Prefect", ChatColor.BLUE, "Lvl4"), + GRADUATE(5, 1250D, "Graduate", "a Graduate", ChatColor.GRAY, "Lvl5"), + ADEPT(6, 1500D, "Adept", "an Adept", ChatColor.DARK_PURPLE, "Lvl6"), + MAGISTRATE(7, 1750D, "Magister", "a Magister", ChatColor.DARK_GREEN, "Lvl7"), + HEADMASTER(8, 2000D, "Headmaster", "a Headmaster", ChatColor.GOLD, "Lvl8"), + ARCH_MAGE(9, 4000D, "Arch-Mage", "an Arch-Mage", ChatColor.BLACK, "Lvl9"); + + private final int level; + private final double experienceMarker; + private final String name; + private final String plural; + private final ChatColor rankColor; + private final String suffix; + + CasterLevel(final int level, final double experienceMarker, final String name, final String plural, + final ChatColor rankColor, + final String suffix) + { + this.experienceMarker = experienceMarker; + this.level = level; + this.name = name; + this.plural = plural; + this.rankColor = rankColor; + this.suffix = MessageFormat.format("{0}[{1}{2}{3}]{4}", + ChatColor.DARK_GRAY, + rankColor, + suffix, + ChatColor.DARK_GRAY, + ChatColor.RESET); + } + + public static CasterLevel fromOrdinal(final int ordinal) + { + return Stream.of(CasterLevel.values()) + .filter(lvl -> lvl.getLevel() == ordinal) + .findFirst() + .orElse(CasterLevel.APPRENTICE); + } + + public int getLevel() + { + return this.level; + } + + public String getName() + { + return this.name; + } + + public String getPlural() + { + return this.plural; + } + + public ChatColor getRankColor() + { + return this.rankColor; + } + + public String getSuffix() + { + return this.suffix; + } + + public double getExperienceMarker() + { + return this.experienceMarker; + } + + public boolean isAtLeast(final CasterLevel level) { + return this.getLevel() >= level.getLevel(); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/caster/SpellBook.java b/src/main/java/app/simplexdev/arcanumocculta/api/caster/SpellBook.java new file mode 100644 index 0000000..a2916d0 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/caster/SpellBook.java @@ -0,0 +1,29 @@ +package app.simplexdev.arcanumocculta.api.caster; + +import app.simplexdev.arcanumocculta.api.spell.Spell; +import java.util.List; + +public interface SpellBook +{ + List getSpells(); + + void addSpell(Spell spell); + + void removeSpell(Spell spell); + + Spell getSpell(String name); + + Spell getSpell(int index); + + int getSpellCount(); + + void setSpell(int index, Spell spell); + + void setSpell(String name, Spell spell); + + void clearSpells(); + + Spell randomSpell(); + + boolean hasSpell(final Spell spell); +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/display/SpellDisplay.java b/src/main/java/app/simplexdev/arcanumocculta/api/display/SpellDisplay.java deleted file mode 100644 index 2fa4b42..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/display/SpellDisplay.java +++ /dev/null @@ -1,24 +0,0 @@ -package app.simplexdev.arcanumocculta.api.display; - -import app.simplexdev.arcanumocculta.api.player.Caster; -import app.simplexdev.arcanumocculta.api.spell.Spell; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.World; -import org.bukkit.entity.Display; - -public interface SpellDisplay { - T getDisplay(); - - Location getLocation(); - - World getWorld(); - - Caster getWhoCast(); - - Spell getCastSpell(); - - Particle[] getParticles(); - - void display(boolean force); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/effect/CompoundEffect.java b/src/main/java/app/simplexdev/arcanumocculta/api/effect/CompoundEffect.java deleted file mode 100644 index 8b694f2..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/effect/CompoundEffect.java +++ /dev/null @@ -1,7 +0,0 @@ -package app.simplexdev.arcanumocculta.api.effect; - -import org.bukkit.potion.PotionEffectType; - -public interface CompoundEffect extends Effect { - PotionEffectType[] getEffectTypes(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/effect/Effect.java b/src/main/java/app/simplexdev/arcanumocculta/api/effect/Effect.java deleted file mode 100644 index 1ca7273..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/effect/Effect.java +++ /dev/null @@ -1,14 +0,0 @@ -package app.simplexdev.arcanumocculta.api.effect; - -import java.time.Duration; - -public interface Effect -{ - Duration getDuration(); - - float getAmplifier(); - - boolean isAmbient(); - - boolean forceDisplay(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/effect/EffectProvider.java b/src/main/java/app/simplexdev/arcanumocculta/api/effect/EffectProvider.java deleted file mode 100644 index ecf4908..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/effect/EffectProvider.java +++ /dev/null @@ -1,5 +0,0 @@ -package app.simplexdev.arcanumocculta.api.effect; - -public interface EffectProvider { - T getEffect(Class type); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/effect/PassiveEffect.java b/src/main/java/app/simplexdev/arcanumocculta/api/effect/PassiveEffect.java deleted file mode 100644 index 46ee374..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/effect/PassiveEffect.java +++ /dev/null @@ -1,12 +0,0 @@ -package app.simplexdev.arcanumocculta.api.effect; - -import app.simplexdev.arcanumocculta.api.player.Caster; - -public interface PassiveEffect extends Effect -{ - Caster getWandHolder(); - - void onTick(); - - PassiveEffects getPassiveEffect(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/effect/PassiveEffects.java b/src/main/java/app/simplexdev/arcanumocculta/api/effect/PassiveEffects.java deleted file mode 100644 index 6986bd6..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/effect/PassiveEffects.java +++ /dev/null @@ -1,30 +0,0 @@ -package app.simplexdev.arcanumocculta.api.effect; - -import java.time.Duration; - -public enum PassiveEffects { - MANA_REGEN(Duration.ofSeconds(10L), 2.0), - LIFE_STEAL(Duration.ofSeconds(5L), 1.0), - ABSORPTION(Duration.ofSeconds(30L), 4.0), - SPELL_SHIELD(Duration.ofSeconds(5L), 5.0), - IMMUNITY(Duration.ofSeconds(5L), 100.0), - WITHER(Duration.ofSeconds(5L), 2.0), - DAMAGE_BOOST(Duration.ofSeconds(5L), 2.75), - IMPROVED_ACCURACY(Duration.ofSeconds(5L), 5.0); - - private final Duration duration; - private final double amount; - - PassiveEffects(final Duration duration, final double amount) { - this.duration = duration; - this.amount = amount; - } - - Duration getDuration() { - return this.duration; - } - - double getAmount() { - return this.amount; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/effect/SpecialEffect.java b/src/main/java/app/simplexdev/arcanumocculta/api/effect/SpecialEffect.java deleted file mode 100644 index 49284be..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/effect/SpecialEffect.java +++ /dev/null @@ -1,7 +0,0 @@ -package app.simplexdev.arcanumocculta.api.effect; - -import org.bukkit.entity.LivingEntity; - -public interface SpecialEffect extends Effect { - void applyEffect(final LivingEntity target); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/effect/SpellEffect.java b/src/main/java/app/simplexdev/arcanumocculta/api/effect/SpellEffect.java deleted file mode 100644 index 02f6499..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/effect/SpellEffect.java +++ /dev/null @@ -1,7 +0,0 @@ -package app.simplexdev.arcanumocculta.api.effect; - -import org.bukkit.potion.PotionEffectType; - -public interface SpellEffect extends Effect { - PotionEffectType getEffectType(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/player/Caster.java b/src/main/java/app/simplexdev/arcanumocculta/api/player/Caster.java deleted file mode 100644 index 1ec0d8c..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/player/Caster.java +++ /dev/null @@ -1,96 +0,0 @@ -package app.simplexdev.arcanumocculta.api.player; - -import app.simplexdev.arcanumocculta.api.book.SpellBook; -import org.bukkit.entity.Player; - -import java.util.List; -import java.util.UUID; - -public interface Caster { - /** - * @return The {@link UUID} of the caster. - */ - UUID getCasterUUID(); - - /** - * @return The name of the caster. - */ - String getDisplayName(); - - /** - * @return The {@link Player} associated with this caster. - */ - Player bukkit(); - - /** - * @return The amount of maximum mana the caster is allowed to have. - */ - double getMaximumMana(); - - /** - * Sets the maximum amount of mana the caster is allowed to have. - * - * @param mana The amount of mana to set the maximum to. - */ - void setMaximumMana(final double mana); - - /** - * @return The amount of mana the caster currently has. - */ - double getCurrentMana(); - - /** - * Adds mana to the caster. - * - * @param mana The amount of mana to add. - * @return The players updated {@link #getCurrentMana()}. - */ - double addMana(final double mana); - - /** - * Increases the amount of maximum mana this caster is allowed to have. - * - * @param mana The amount of mana to increase the maximum by. - * @return The players updated {@link #getMaximumMana()}. - */ - double increaseMaximumMana(final double mana); - - /** - * Removes mana from the caster. - * - * @param mana The amount of mana to remove. - * @return The players updated {@link #getCurrentMana()}. - */ - double removeMana(final double mana); - - /** - * Decreases the amount of maximum mana this caster is allowed to have. - * - * @param mana The amount of mana to decrease the maximum by. - * @return The players updated {@link #getMaximumMana()}. - */ - double decreaseMaximumMana(final double mana); - - /** - * Sets the amount of mana the caster currently has. - * - * @param mana The amount of mana to set the user's current mana to. - */ - void setMana(final double mana); - - /** - * @return The {@link SpellBook} of the caster. - */ - SpellBook getSpellbook(); - - /** - * @return A list of {@link SpellResistance}s the caster has. - */ - List getSpellResistances(); - - void addSpellResistance(SpellResistance resistance); - - void removeSpellResistance(SpellResistance resistance); - - boolean hasResistance(int spellOrdinal); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/player/SpellResistance.java b/src/main/java/app/simplexdev/arcanumocculta/api/player/SpellResistance.java deleted file mode 100644 index 2245a99..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/player/SpellResistance.java +++ /dev/null @@ -1,9 +0,0 @@ -package app.simplexdev.arcanumocculta.api.player; - -public interface SpellResistance { - String getSpellName(); - - double getResistance(); - - int getOrdinal(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/player/Wand.java b/src/main/java/app/simplexdev/arcanumocculta/api/player/Wand.java deleted file mode 100644 index 81e26e6..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/player/Wand.java +++ /dev/null @@ -1,18 +0,0 @@ -package app.simplexdev.arcanumocculta.api.player; - -import app.simplexdev.arcanumocculta.api.effect.PassiveEffect; -import org.bukkit.inventory.ItemStack; - -import java.util.List; - -public interface Wand { - String getWandName(); - - String getWandDescription(); - - ItemStack getWandItem(); - - double getManaPenalty(); - - List getPassiveEffects(); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/AbstractSpell.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/AbstractSpell.java new file mode 100644 index 0000000..3bc3e4f --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/spell/AbstractSpell.java @@ -0,0 +1,198 @@ +package app.simplexdev.arcanumocculta.api.spell; + +import app.simplexdev.arcanumocculta.api.caster.Caster; +import app.simplexdev.arcanumocculta.api.caster.CasterLevel; +import app.simplexdev.arcanumocculta.api.spell.enums.Damages; +import app.simplexdev.arcanumocculta.api.spell.enums.Durations; +import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts; +import app.simplexdev.arcanumocculta.util.SpellUtils; +import java.util.List; +import java.util.SplittableRandom; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +public abstract class AbstractSpell implements Spell +{ + private final String name; + private final String id; + private final String description; + private final CasterLevel levelRequirement; + private final Damages baseDamage; + private final Durations effectDuration; + private final ManaCosts manaCost; + private final long coolDown; + private final SplittableRandom random = new SplittableRandom(); + + protected AbstractSpell(final String name, final String id, + final String description, final CasterLevel levelRequirement, + final Damages baseDamage, final Durations effectDuration, + final ManaCosts manaCost, final long coolDown) + { + this.name = name; + this.id = id; + this.description = description; + this.levelRequirement = levelRequirement; + this.baseDamage = baseDamage; + this.effectDuration = effectDuration; + this.manaCost = manaCost; + this.coolDown = coolDown; + } + + @Override + public String getName() + { + return name; + } + + @Override + public String getId() + { + return this.id; + } + + @Override + public String getDescription() + { + return description; + } + + @Override + public CasterLevel getLevelRequirement() + { + return levelRequirement; + } + + @Override + public Damages baseDamage() + { + return baseDamage; + } + + @Override + public Durations effectDuration() + { + return effectDuration; + } + + @Override + public ManaCosts manaCost() + { + return manaCost; + } + + @Override + public long coolDown() + { + return coolDown; + } + + @Override + public Spell dupe() + { + try + { + return this.getClass() + .getDeclaredConstructor() + .newInstance(); + } + catch (ReflectiveOperationException e) + { + Bukkit.getLogger().severe(e.getMessage()); + return null; + } + } + + @Override + public boolean isUnlocked(Caster caster) + { + return caster.getSpellBook().hasSpell(this) + && caster.getCurrentLevel().isAtLeast(this.getLevelRequirement()); + } + + protected SplittableRandom random() + { + return random; + } + + /** + * Checks if the caster has enough mana to cast this spell. + * + * @param caster The caster who is casting the spell + * @return True if the caster has enough mana, false otherwise + */ + protected boolean checkManaCosts(final Caster caster) + { + boolean isValid = !manaCost().isMoreThan(caster.getCurrentMana()); + if (!isValid) + caster.bukkit().sendMessage(ChatColor.RED + "You don't have enough mana to cast this spell!"); + + return isValid; + } + + public void applyEffects(final List targets, final Caster caster) + { + targets.stream() + .filter(LivingEntity.class::isInstance) + .map(LivingEntity.class::cast) + .forEach(entity -> applyEffectsIndividually( + getSpellEffects(), + entity, + caster)); + } + + public Entity prepareProjectile(final Caster caster, final Material visual) + { + final double expMod = getLevelRequirement().getExperienceMarker(); + + final Player player = caster.bukkit(); + final Location location = player.getLocation().clone().add(0, player.getEyeHeight(), 0); + final Vector velocity = player.getLocation().getDirection().multiply(2); + final Entity projectile = createProjectile(visual, player.getWorld(), location, + velocity); + caster.removeMana(manaCost().getManaCost()); + caster.addExperience(random().nextDouble(expMod * 0.25)); + return projectile; + } + + public void tracer(final World world, final Location location, final Particle particle) + { + world.spawnParticle(particle, + location, + 0, + random().nextDouble(-2, 2), + random().nextDouble(-2, 2), + random().nextDouble(-2, 2)); + } + + private void applyEffectsIndividually(final SpellEffect[] effects, final LivingEntity target, + final Caster caster) + { + for (final SpellEffect effect : effects) + effect.apply(target, caster); + } + + private static ItemDisplay createProjectile(final Material visual, final World world, final Location location, + final Vector velocity) + { + final ItemDisplay display = (ItemDisplay) world.spawnEntity(location, EntityType.ITEM_DISPLAY); + display.setItemStack(new ItemStack(visual)); + display.setGravity(true); + display.setPersistent(false); + display.setSilent(true); + display.setShadowRadius(0); + display.setShadowStrength(0); + display.setVelocity(velocity); + return display; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/Spell.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/Spell.java index 8415455..5d3fe9d 100644 --- a/src/main/java/app/simplexdev/arcanumocculta/api/spell/Spell.java +++ b/src/main/java/app/simplexdev/arcanumocculta/api/spell/Spell.java @@ -1,23 +1,47 @@ package app.simplexdev.arcanumocculta.api.spell; -import app.simplexdev.arcanumocculta.api.effect.Effect; -import app.simplexdev.arcanumocculta.api.effect.EffectProvider; -import org.bukkit.entity.Projectile; +import app.simplexdev.arcanumocculta.api.caster.Caster; +import app.simplexdev.arcanumocculta.api.caster.CasterLevel; +import app.simplexdev.arcanumocculta.api.spell.enums.Damages; +import app.simplexdev.arcanumocculta.api.spell.enums.Durations; +import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts; +import app.simplexdev.arcanumocculta.api.wand.Wand; +import java.util.UUID; -import java.time.Duration; +public interface Spell +{ + String getName(); -public interface Spell { - String getSpellName(); + String getId(); - String getSpellDescription(); + default UUID getUniqueId() + { + return UUID.nameUUIDFromBytes(this.getName().getBytes()); + } - double getManaCost(); + String getDescription(); - Duration getCoolDown(); + CasterLevel getLevelRequirement(); - int getSpellLevel(); + Damages baseDamage(); - SpellProjectile getSpellProjectile(); + SpellEffect[] getSpellEffects(); - T getEffect(); + Durations effectDuration(); + + ManaCosts manaCost(); + + long coolDown(); + + boolean isUnlocked(final Caster caster); + + void cast(final Caster caster, final Wand wand); + + /** + * Used to create a copy of the spell for player spell books. + * Should only ever be used by the primary list when initializing a player's spell book. + * + * @return a copy of the spell. + */ + Spell dupe(); } diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/SpellEffect.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/SpellEffect.java new file mode 100644 index 0000000..f180e46 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/spell/SpellEffect.java @@ -0,0 +1,10 @@ +package app.simplexdev.arcanumocculta.api.spell; + +import app.simplexdev.arcanumocculta.api.caster.Caster; +import org.bukkit.entity.LivingEntity; + +@FunctionalInterface +public interface SpellEffect +{ + void apply(final LivingEntity target, final Caster caster); +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/SpellProjectile.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/SpellProjectile.java deleted file mode 100644 index 01ea8a7..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/api/spell/SpellProjectile.java +++ /dev/null @@ -1,18 +0,0 @@ -package app.simplexdev.arcanumocculta.api.spell; - -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; - -import java.util.List; - -public interface SpellProjectile { - Class getProjectileType(); - - List getParticles(); - - void cast(final Location target); - - void cast(final LivingEntity target); -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/Damages.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/Damages.java new file mode 100644 index 0000000..bcaf92b --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/Damages.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Simplex Development Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package app.simplexdev.arcanumocculta.api.spell.enums; + +public enum Damages +{ + MINIMAL(0.5), + LIGHT(1.0), + NEUTRAL(1.5), + MODERATE(2.0), + INTERMEDIATE(2.5), + HEAVY(3.0), + MAJOR(3.5), + SEVERE(4.0), + EXTREME(4.5), + IMMENSE(5.0), + CRITICAL(6.5), + FATAL(10.0), + OVERKILL(20.0), + DEVASTATION(50.0); + + private final double damage; + + Damages(double damage) + { + this.damage = damage; + } + + public double getDamage() + { + return damage; + } + + public double multiply(double multiplier) { + return damage * multiplier; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/Durations.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/Durations.java new file mode 100644 index 0000000..cc28a76 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/Durations.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Simplex Development Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package app.simplexdev.arcanumocculta.api.spell.enums; + +public enum Durations +{ + INSTANT(1L), + SHORT(20L), + MEDIUM(20L * 5L), + LONG(20L * 30L), + VERY_LONG(20L * 60L), + AGES(20L * 60L * 5L); + + private final long ticks; + + Durations(final long ticks) + { + this.ticks = ticks; + } + + public long getTicks() + { + return this.ticks; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/ManaCosts.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/ManaCosts.java new file mode 100644 index 0000000..bb3c26c --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/ManaCosts.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Simplex Development Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package app.simplexdev.arcanumocculta.api.spell.enums; + +public enum ManaCosts +{ + MINIMAL_CAST(5.0), + LIGHT_CAST(10.0), + MODERATE_CAST(20.0), + HEAVY_CAST(30.0), + MAJOR_CAST(50.0), + EXTREME_CAST(100.0), + IMMENSE_CAST(200.0), + MASTER_CAST(500.0); + + private final double manaCost; + + ManaCosts(final double manaCost) { + this.manaCost = manaCost; + } + + public double getManaCost() { + return manaCost; + } + + public boolean isMoreThan(final double manaCost) { + return this.manaCost > manaCost; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/SpellTypes.java b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/SpellTypes.java new file mode 100644 index 0000000..042a51f --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/spell/enums/SpellTypes.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Simplex Development Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package app.simplexdev.arcanumocculta.api.spell.enums; + +// Reference for implementation. +public enum SpellTypes +{ + SOUL_PEBBLE, SOUL_SHARD, LARGE_SOUL_SHARD, SOUL_COMET_SHARD, SOUL_COMET, SOUL_SHARD_SPIRAL, SOUL_STARS, + SOUL_STAR_SHOWER, SOUL_ARC, SOUL_BARRAGE, SOUL_BURST, SOUL_CANNON, SOUL_HAMMER, SOUL_BLAST, SOUL_EXPLOSION, + SOUL_LAMP, SOUL_PHALANX, GREAT_SOUL_PHALANX, SOUL_MIST, ARS_NOVA, ARS_ENIGMA, ARS_ULTIMA, + + FLAME_SLING, FLAME_BURST, CATCH_FLAME, FLAME_BARRAGE, FIREBALL, METEORITE, METEOR, FLAME_WHIP, FLAME_FAN, + FLAME_ORB, FLAME_PILLARS, FLAME_WHIRLWIND, + + WITHER_BURST, WITHER_SHOT, WITHER_SHARD, WITHER_COMET, WITHER_METEORITE, + + HEALING, GREATER_HEALING, HEAL_OTHER, HEALING_HANDS, HEALING_WAVE, GUARDIAN_PROTECTION, SAVIORS_BLESSING, + DIVING_BLESSING, DIVINE_GRACE, ULTIMATE_HEALING, DIVINE_INTERVENTION, DIVINE_RETRIBUTION, + + LIGHTNING_BOLT, LIGHTNING_STORM, STAR_SHOWER, STORM_CALL, LIGHTNING_BARRAGE; +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/wand/AbstractWand.java b/src/main/java/app/simplexdev/arcanumocculta/api/wand/AbstractWand.java new file mode 100644 index 0000000..3b3efe0 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/wand/AbstractWand.java @@ -0,0 +1,69 @@ +package app.simplexdev.arcanumocculta.api.wand; + +import org.bukkit.inventory.ItemStack; + +public abstract class AbstractWand implements Wand +{ + private final ItemStack item; + private final CapType capType; + private final CoreType coreType; + private final GemType gemType; + private final String name; + private final String description; + + protected AbstractWand(String name, + String description, ItemStack item, CapType capType, + CoreType coreType, GemType gemType) + { + this.name = name; + this.description = description; + this.item = item; + this.capType = capType; + this.coreType = coreType; + this.gemType = gemType; + } + + @Override + public String getName() + { + return name; + } + + @Override + public String getDescription() + { + return description; + } + + @Override + public ItemStack getItem() + { + return item; + } + + @Override + public double getSpellBonus() + { + return getCapType().getSpellBoost() + + getCoreType().getSpellBoost() + + getGemType().getSpellBoost(); + } + + @Override + public CapType getCapType() + { + return capType; + } + + @Override + public CoreType getCoreType() + { + return coreType; + } + + @Override + public GemType getGemType() + { + return gemType; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/wand/CapType.java b/src/main/java/app/simplexdev/arcanumocculta/api/wand/CapType.java new file mode 100644 index 0000000..180aedd --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/wand/CapType.java @@ -0,0 +1,28 @@ +package app.simplexdev.arcanumocculta.api.wand; + +import org.bukkit.Material; + +public enum CapType +{ + IRON(Material.IRON_NUGGET, 1.0), + GOLD(Material.GOLD_NUGGET, 2.5), + DIAMOND(Material.DIAMOND, 3.0), + OBSIDIAN(Material.OBSIDIAN, 4.5), + NETHERITE(Material.NETHERITE_INGOT, 6.0); + + private final Material material; + private final double spellBoost; + + CapType(final Material material, final double spellBoost) { + this.material = material; + this.spellBoost = spellBoost; + } + + public final Material getMaterial() { + return this.material; + } + + public final double getSpellBoost() { + return this.spellBoost; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/wand/CoreType.java b/src/main/java/app/simplexdev/arcanumocculta/api/wand/CoreType.java new file mode 100644 index 0000000..aaf6dd0 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/wand/CoreType.java @@ -0,0 +1,32 @@ +package app.simplexdev.arcanumocculta.api.wand; + +import org.bukkit.Material; + +public enum CoreType +{ + WOOD(Material.STICK, 1.0), + IRON(Material.IRON_INGOT, 1.25), + GOLD(Material.GOLD_INGOT, 1.5), + OBSIDIAN(Material.OBSIDIAN, 1.75), + BLAZE(Material.BLAZE_ROD, 2.0), + ENDER(Material.END_ROD, 2.5); + + private final Material material; + private final double spellBoost; + + CoreType(final Material material, final double spellBoost) + { + this.spellBoost = spellBoost; + this.material = material; + } + + public Material getMaterial() + { + return this.material; + } + + public double getSpellBoost() + { + return spellBoost; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/wand/GemType.java b/src/main/java/app/simplexdev/arcanumocculta/api/wand/GemType.java new file mode 100644 index 0000000..6556b4e --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/wand/GemType.java @@ -0,0 +1,32 @@ +package app.simplexdev.arcanumocculta.api.wand; + +import org.bukkit.Material; + +public enum GemType +{ + NONE(Material.AIR, 1.0), + LAPIS(Material.LAPIS_LAZULI, 1.25), + REDSTONE(Material.REDSTONE, 1.5), + EMERALD(Material.EMERALD, 2.0), + DIAMOND(Material.DIAMOND, 3.0), + QUARTZ(Material.QUARTZ, 4.0); + + private final Material material; + private final double spellBoost; + + GemType(final Material material, final double spellBoost) + { + this.spellBoost = spellBoost; + this.material = material; + } + + public Material getMaterial() + { + return this.material; + } + + public double getSpellBoost() + { + return spellBoost; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/api/wand/Wand.java b/src/main/java/app/simplexdev/arcanumocculta/api/wand/Wand.java new file mode 100644 index 0000000..50ff60f --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/api/wand/Wand.java @@ -0,0 +1,20 @@ +package app.simplexdev.arcanumocculta.api.wand; + +import org.bukkit.inventory.ItemStack; + +public interface Wand +{ + String getName(); + + String getDescription(); + + ItemStack getItem(); + + double getSpellBonus(); + + CapType getCapType(); + + CoreType getCoreType(); + + GemType getGemType(); +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/SimpleCaster.java b/src/main/java/app/simplexdev/arcanumocculta/base/SimpleCaster.java new file mode 100644 index 0000000..528c499 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/base/SimpleCaster.java @@ -0,0 +1,19 @@ +package app.simplexdev.arcanumocculta.base; + +import app.simplexdev.arcanumocculta.api.caster.AbstractCaster; +import app.simplexdev.arcanumocculta.api.caster.CasterLevel; +import app.simplexdev.arcanumocculta.api.caster.SpellBook; +import app.simplexdev.arcanumocculta.api.wand.Wand; +import org.bukkit.entity.Player; + +public class SimpleCaster extends AbstractCaster +{ + public SimpleCaster(Player player, Wand wand, + SpellBook spellBook, + CasterLevel level) + { + super(player, wand, spellBook, level); + } + + +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/SimpleSpellBook.java b/src/main/java/app/simplexdev/arcanumocculta/base/SimpleSpellBook.java new file mode 100644 index 0000000..0cf8787 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/base/SimpleSpellBook.java @@ -0,0 +1,7 @@ +package app.simplexdev.arcanumocculta.base; + +import app.simplexdev.arcanumocculta.api.caster.AbstractSpellBook; + +public class SimpleSpellBook extends AbstractSpellBook +{ +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/SimpleWand.java b/src/main/java/app/simplexdev/arcanumocculta/base/SimpleWand.java new file mode 100644 index 0000000..628408d --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/base/SimpleWand.java @@ -0,0 +1,18 @@ +package app.simplexdev.arcanumocculta.base; + +import app.simplexdev.arcanumocculta.api.wand.AbstractWand; +import app.simplexdev.arcanumocculta.api.wand.CapType; +import app.simplexdev.arcanumocculta.api.wand.CoreType; +import app.simplexdev.arcanumocculta.api.wand.GemType; +import org.bukkit.inventory.ItemStack; + +public class SimpleWand extends AbstractWand +{ + public SimpleWand(String name, String description, ItemStack item, + CapType capType, + CoreType coreType, + GemType gemType) + { + super(name, description, item, capType, coreType, gemType); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/book/AbstractSpellBook.java b/src/main/java/app/simplexdev/arcanumocculta/base/book/AbstractSpellBook.java deleted file mode 100644 index 2b26771..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/book/AbstractSpellBook.java +++ /dev/null @@ -1,99 +0,0 @@ -package app.simplexdev.arcanumocculta.base.book; - -import app.simplexdev.arcanumocculta.api.book.SpellBook; -import app.simplexdev.arcanumocculta.api.spell.Spell; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.ArrayList; -import java.util.List; - -public abstract class AbstractSpellBook implements SpellBook { - private final List spellbook = new ArrayList<>(); - - private String name; - private String description; - private ItemStack itemStack; - - protected AbstractSpellBook(final String name) { - this.name = name; - this.description = ChatColor.BLUE + "A simple spell book."; - - final ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, 1); - ItemMeta meta = stack.getItemMeta(); - - if (meta != null) { - meta.setDisplayName(name); - meta.setLore(List.of(description)); - stack.setItemMeta(meta); - } - - this.itemStack = stack; - } - - @Override - public String getBookName() { - return name; - } - - @Override - public void setBookName(String name) { - this.name = name; - } - - @Override - public String getBookDescription() { - return description; - } - - @Override - public void setBookDescription(String description) { - this.description = description; - } - - @Override - public ItemStack getBookItem() { - return itemStack; - } - - @Override - public void setBookItem(final ItemStack stack) { - this.itemStack = stack; - } - - @Override - public List getSpells() { - return this.spellbook; - } - - @Override - public void addSpell(Spell spell) { - this.spellbook.add(spell); - } - - @Override - public void removeSpell(Spell spell) { - this.spellbook.remove(spell); - } - - @Override - public Spell getSpell(String name) { - return getSpells() - .stream() - .filter(spell -> spell.getSpellName().equalsIgnoreCase(name)) - .findFirst() - .orElse(null); - } - - @Override - public Spell getSpell(int index) { - return getSpells().get(index); - } - - @Override - public int getSpellCount() { - return getSpells().size(); - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/book/AbstractSpellTome.java b/src/main/java/app/simplexdev/arcanumocculta/base/book/AbstractSpellTome.java deleted file mode 100644 index bc3aa08..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/book/AbstractSpellTome.java +++ /dev/null @@ -1,50 +0,0 @@ -package app.simplexdev.arcanumocculta.base.book; - -import app.simplexdev.arcanumocculta.api.book.SpellTome; -import app.simplexdev.arcanumocculta.api.spell.Spell; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.List; - -public abstract class AbstractSpellTome implements SpellTome { - private final Spell containedSpell; - private final String name; - private final String description; - private final ItemStack item; - - protected AbstractSpellTome(final String name, final String description, final Spell containedSpell) { - this.containedSpell = containedSpell; - this.name = name; - this.description = description; - final ItemStack stack = new ItemStack(Material.BOOK, 1); - final ItemMeta meta = stack.getItemMeta(); - if (meta != null) { - meta.setDisplayName(name); - meta.setLore(List.of(description)); - stack.setItemMeta(meta); - } - this.item = stack; - } - - @Override - public String getTomeName() { - return this.name; - } - - @Override - public String getTomeDescription() { - return this.description; - } - - @Override - public ItemStack getTomeItem() { - return this.item; - } - - @Override - public Spell getContainedSpell() { - return this.containedSpell; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractCompoundEffect.java b/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractCompoundEffect.java deleted file mode 100644 index 56fd687..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractCompoundEffect.java +++ /dev/null @@ -1,40 +0,0 @@ -package app.simplexdev.arcanumocculta.base.effect; - -import app.simplexdev.arcanumocculta.api.effect.CompoundEffect; -import org.bukkit.potion.PotionEffectType; - -import java.time.Duration; - -public abstract class AbstractCompoundEffect extends AbstractEffect implements CompoundEffect { - private final PotionEffectType[] effectTypes; - - protected AbstractCompoundEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay, PotionEffectType... effectTypes) { - super(duration, amplifier, ambient, forceDisplay); - this.effectTypes = effectTypes; - } - - protected AbstractCompoundEffect(Duration duration, float amplifier, boolean forceDisplay, PotionEffectType... effectTypes) { - super(duration, amplifier, forceDisplay); - this.effectTypes = effectTypes; - } - - protected AbstractCompoundEffect(Duration duration, float amplifier, PotionEffectType... effectTypes) { - super(duration, amplifier); - this.effectTypes = effectTypes; - } - - protected AbstractCompoundEffect(Duration duration, PotionEffectType... effectTypes) { - super(duration); - this.effectTypes = effectTypes; - } - - protected AbstractCompoundEffect(PotionEffectType... effectTypes) { - super(); - this.effectTypes = effectTypes; - } - - @Override - public PotionEffectType[] getEffectTypes() { - return new PotionEffectType[0]; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractEffect.java b/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractEffect.java deleted file mode 100644 index ffaabc6..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractEffect.java +++ /dev/null @@ -1,55 +0,0 @@ -package app.simplexdev.arcanumocculta.base.effect; - -import app.simplexdev.arcanumocculta.api.effect.Effect; - -import java.time.Duration; - -public abstract class AbstractEffect implements Effect { - private final Duration duration; - private final float amplifier; - private final boolean ambient; - private final boolean forceDisplay; - - protected AbstractEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay) { - this.duration = duration; - this.amplifier = amplifier; - this.ambient = ambient; - this.forceDisplay = forceDisplay; - } - - protected AbstractEffect(Duration duration, float amplifier, boolean forceDisplay) { - this(duration, amplifier, false, forceDisplay); - } - - protected AbstractEffect(Duration duration, float amplifier) { - this(duration, amplifier, false, false); - } - - protected AbstractEffect(Duration duration) { - this(duration, 1, false, false); - } - - protected AbstractEffect() { - this(Duration.ofSeconds(5L), 1, false, false); - } - - @Override - public Duration getDuration() { - return duration; - } - - @Override - public float getAmplifier() { - return amplifier; - } - - @Override - public boolean isAmbient() { - return ambient; - } - - @Override - public boolean forceDisplay() { - return forceDisplay; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractPassiveEffect.java b/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractPassiveEffect.java deleted file mode 100644 index 3beaf9c..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractPassiveEffect.java +++ /dev/null @@ -1,53 +0,0 @@ -package app.simplexdev.arcanumocculta.base.effect; - -import app.simplexdev.arcanumocculta.api.effect.PassiveEffect; -import app.simplexdev.arcanumocculta.api.effect.PassiveEffects; -import app.simplexdev.arcanumocculta.api.player.Caster; - -import java.time.Duration; - -public abstract class AbstractPassiveEffect extends AbstractEffect implements PassiveEffect { - - private final Caster wandHolder; - private final PassiveEffects passiveEffect; - - protected AbstractPassiveEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay, Caster wandHolder, PassiveEffects passiveEffect) { - super(duration, amplifier, ambient, forceDisplay); - this.wandHolder = wandHolder; - this.passiveEffect = passiveEffect; - } - - public AbstractPassiveEffect(Duration duration, float amplifier, boolean forceDisplay, Caster wandHolder, PassiveEffects passiveEffect) { - super(duration, amplifier, forceDisplay); - this.wandHolder = wandHolder; - this.passiveEffect = passiveEffect; - } - - protected AbstractPassiveEffect(Duration duration, float amplifier, Caster wandHolder, PassiveEffects passiveEffect) { - super(duration, amplifier); - this.wandHolder = wandHolder; - this.passiveEffect = passiveEffect; - } - - protected AbstractPassiveEffect(Duration duration, Caster wandHolder, PassiveEffects passiveEffect) { - super(duration); - this.wandHolder = wandHolder; - this.passiveEffect = passiveEffect; - } - - protected AbstractPassiveEffect(Caster wandHolder, PassiveEffects passiveEffect) { - super(); - this.wandHolder = wandHolder; - this.passiveEffect = passiveEffect; - } - - @Override - public Caster getWandHolder() { - return wandHolder; - } - - @Override - public PassiveEffects getPassiveEffect() { - return passiveEffect; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractSpellEffect.java b/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractSpellEffect.java deleted file mode 100644 index c72937e..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/effect/AbstractSpellEffect.java +++ /dev/null @@ -1,40 +0,0 @@ -package app.simplexdev.arcanumocculta.base.effect; - -import app.simplexdev.arcanumocculta.api.effect.SpellEffect; -import org.bukkit.potion.PotionEffectType; - -import java.time.Duration; - -public abstract class AbstractSpellEffect extends AbstractEffect implements SpellEffect { - private final PotionEffectType effectType; - - protected AbstractSpellEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay, PotionEffectType effectType) { - super(duration, amplifier, ambient, forceDisplay); - this.effectType = effectType; - } - - protected AbstractSpellEffect(Duration duration, float amplifier, boolean forceDisplay, PotionEffectType effectType) { - super(duration, amplifier, forceDisplay); - this.effectType = effectType; - } - - protected AbstractSpellEffect(Duration duration, float amplifier, PotionEffectType effectType) { - super(duration, amplifier); - this.effectType = effectType; - } - - protected AbstractSpellEffect(Duration duration, PotionEffectType effectType) { - super(duration); - this.effectType = effectType; - } - - protected AbstractSpellEffect(PotionEffectType effectType) { - super(); - this.effectType = effectType; - } - - @Override - public PotionEffectType getEffectType() { - return effectType; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/player/AbstractCaster.java b/src/main/java/app/simplexdev/arcanumocculta/base/player/AbstractCaster.java deleted file mode 100644 index 40f2709..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/player/AbstractCaster.java +++ /dev/null @@ -1,124 +0,0 @@ -package app.simplexdev.arcanumocculta.base.player; - -import app.simplexdev.arcanumocculta.api.book.SpellBook; -import app.simplexdev.arcanumocculta.api.player.Caster; -import app.simplexdev.arcanumocculta.api.player.SpellResistance; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -public abstract class AbstractCaster implements Caster { - private final String name; - private final UUID uuid; - private final SpellBook spellBook; - private final List spellResistances = new ArrayList<>(); - - private double maximumMana; - private double currentMana; - - protected AbstractCaster(final Player player, SpellBook spellBook) { - this.name = player.getName(); - this.uuid = player.getUniqueId(); - this.spellBook = spellBook; - - this.maximumMana = 20; - this.currentMana = maximumMana; - } - - @Override - public UUID getCasterUUID() { - return uuid; - } - - @Override - public String getDisplayName() { - return name; - } - - @Override - public double getMaximumMana() { - return maximumMana; - } - - @Override - public void setMaximumMana(double mana) { - this.maximumMana = mana; - } - - @Override - public double getCurrentMana() { - return currentMana; - } - - @Override - public double addMana(double mana) { - this.currentMana += mana; - return getCurrentMana(); - } - - @Override - public double increaseMaximumMana(double mana) { - this.maximumMana += mana; - return getMaximumMana(); - } - - @Override - public double removeMana(double mana) { - final double newMana = currentMana - mana; - if (newMana < 0) { - currentMana = 0; - } else { - currentMana = newMana; - } - return getCurrentMana(); - } - - @Override - public double decreaseMaximumMana(double mana) { - final double newMana = maximumMana - mana; - if (newMana < 0) { - maximumMana = 0; - } else { - maximumMana = newMana; - } - return getMaximumMana(); - } - - @Override - public void setMana(double mana) { - if (mana > getMaximumMana()) { - currentMana = getMaximumMana(); - } else if (mana < 0) { - currentMana = 0; - } else { - currentMana = mana; - } - } - - @Override - public SpellBook getSpellbook() { - return spellBook; - } - - @Override - public List getSpellResistances() { - return spellResistances; - } - - @Override - public void addSpellResistance(SpellResistance resistance) { - this.spellResistances.add(resistance); - } - - @Override - public void removeSpellResistance(SpellResistance resistance) { - this.spellResistances.remove(resistance); - } - - @Override - public boolean hasResistance(int ordinal) { - return getSpellResistances().stream().anyMatch(resistance -> resistance.getOrdinal() == ordinal); - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/player/AbstractWand.java b/src/main/java/app/simplexdev/arcanumocculta/base/player/AbstractWand.java deleted file mode 100644 index b1bd2ba..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/player/AbstractWand.java +++ /dev/null @@ -1,48 +0,0 @@ -package app.simplexdev.arcanumocculta.base.player; - -import app.simplexdev.arcanumocculta.api.effect.PassiveEffect; -import app.simplexdev.arcanumocculta.api.player.Wand; -import org.bukkit.inventory.ItemStack; - -import java.util.ArrayList; -import java.util.List; - -public abstract class AbstractWand implements Wand { - private final List passiveEffects = new ArrayList<>(); - private String name; - private String description; - private ItemStack item; - private double manaPenalty; - - protected AbstractWand(String name, String description, ItemStack item, double manaPenalty) { - this.name = name; - this.description = description; - this.item = item; - this.manaPenalty = manaPenalty; - } - - @Override - public String getWandName() { - return name; - } - - @Override - public String getWandDescription() { - return description; - } - - @Override - public ItemStack getWandItem() { - return item; - } - - @Override - public double getManaPenalty() { - return manaPenalty; - } - - @Override - public List getPassiveEffects() { - return passiveEffects; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/player/SimpleSpellResistance.java b/src/main/java/app/simplexdev/arcanumocculta/base/player/SimpleSpellResistance.java deleted file mode 100644 index ec6d8c8..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/player/SimpleSpellResistance.java +++ /dev/null @@ -1,30 +0,0 @@ -package app.simplexdev.arcanumocculta.base.player; - -import app.simplexdev.arcanumocculta.api.player.SpellResistance; - -public class SimpleSpellResistance implements SpellResistance { - private final String name; - private final double resistance; - private final int ordinal; - - public SimpleSpellResistance(String spellName, double resistance, int ordinal) { - this.name = spellName; - this.resistance = resistance; - this.ordinal = ordinal; - } - - @Override - public String getSpellName() { - return name; - } - - @Override - public double getResistance() { - return resistance; - } - - @Override - public int getOrdinal() { - return ordinal; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/spell/AbstractSpell.java b/src/main/java/app/simplexdev/arcanumocculta/base/spell/AbstractSpell.java deleted file mode 100644 index 600e4c2..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/spell/AbstractSpell.java +++ /dev/null @@ -1,68 +0,0 @@ -package app.simplexdev.arcanumocculta.base.spell; - -import app.simplexdev.arcanumocculta.api.effect.Effect; -import app.simplexdev.arcanumocculta.api.spell.Spell; - -import java.time.Duration; - -public abstract class AbstractSpell implements Spell { - private final String name; - private final String description; - private final double manaCost; - private final Duration coolDown; - private final int spellLevel; - private final T spellEffect; - - private long coolDownEnd; - - protected AbstractSpell(String name, String description, double manaCost, Duration coolDown, int spellLevel, T effect) { - this.name = name; - this.description = description; - this.manaCost = manaCost; - this.coolDown = coolDown; - this.spellLevel = spellLevel; - this.spellEffect = effect; - } - - protected AbstractSpell(String name, String description, double manaCost, Duration coolDown, T effect) { - this(name, description, manaCost, coolDown, 1, effect); - } - - protected AbstractSpell(String name, String description, double manaCost, T effect) { - this(name, description, manaCost, Duration.ofSeconds(10L), effect); - } - - protected AbstractSpell(String name, String description, T effect) { - this(name, description, 5.0, effect); - } - - @Override - public String getSpellName() { - return name; - } - - @Override - public String getSpellDescription() { - return description; - } - - @Override - public double getManaCost() { - return manaCost; - } - - @Override - public Duration getCoolDown() { - return coolDown; - } - - @Override - public int getSpellLevel() { - return spellLevel; - } - - @Override - public T getEffect() { - return spellEffect; - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/base/spell/AbstractSpellProjectile.java b/src/main/java/app/simplexdev/arcanumocculta/base/spell/AbstractSpellProjectile.java deleted file mode 100644 index 28536d1..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/base/spell/AbstractSpellProjectile.java +++ /dev/null @@ -1,143 +0,0 @@ -package app.simplexdev.arcanumocculta.base.spell; - -import app.simplexdev.arcanumocculta.api.effect.CompoundEffect; -import app.simplexdev.arcanumocculta.api.effect.Effect; -import app.simplexdev.arcanumocculta.api.effect.SpecialEffect; -import app.simplexdev.arcanumocculta.api.effect.SpellEffect; -import app.simplexdev.arcanumocculta.api.player.Caster; -import app.simplexdev.arcanumocculta.api.spell.Spell; -import app.simplexdev.arcanumocculta.api.spell.SpellProjectile; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.entity.AreaEffectCloud; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public abstract class AbstractSpellProjectile implements SpellProjectile { - - private static final List accepted = List.of( - EntityType.ARROW, - EntityType.SPECTRAL_ARROW, - EntityType.FIREBALL, - EntityType.DRAGON_FIREBALL, - EntityType.SMALL_FIREBALL, - EntityType.WITHER_SKULL, - EntityType.ENDER_PEARL, - EntityType.SNOWBALL, - EntityType.EGG, - EntityType.TRIDENT, - EntityType.FIREWORK, - EntityType.LLAMA_SPIT, - EntityType.SHULKER_BULLET, - EntityType.FISHING_HOOK, - EntityType.SPLASH_POTION, - EntityType.THROWN_EXP_BOTTLE); - - private final Class projectile; - private final List particles; - private final Caster caster; - private final Spell spell; - - protected AbstractSpellProjectile(final Spell spell, final Caster caster, final Class projectile, final Particle... particles) { - this.projectile = projectile; - this.particles = Arrays.asList(particles); - this.caster = caster; - this.spell = spell; - } - - @Override - public Class getProjectileType() { - return projectile; - } - - @Override - public List getParticles() { - return particles; - } - - @Override - public void cast(Location target) { - final Vector velocity = caster.bukkit().getEyeLocation().getDirection().multiply(2); - final T launched = caster.bukkit().launchProjectile(getProjectileType(), velocity); - - while (!launched.isDead()) { - final double randomXOffset = Math.sin((Math.random() * 10 - 2) % Math.PI) * 5; - final double randomYOffset = ((Math.random() * 10 - 2) % Math.PI) * 5; - final double randomZOffset = Math.cos((Math.random() * 10 - 2) % (2 * Math.PI)) * 5; - particles.forEach(particle -> launched.getWorld().spawnParticle(particle, launched.getLocation(), 1, randomXOffset, randomYOffset, randomZOffset)); - - if (launched.isOnGround() - || launched.isDead() - || launched.getTicksLived() > 100 - || launched.getLocation().clone().equals(target)) { - break; - } - } - - final Effect effect = spell.getEffect(); - if (effect instanceof SpellEffect sp) { - PotionEffect e = sp.getEffectType().createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier()); - AreaEffectCloud cloud = (AreaEffectCloud) target.getWorld().spawnEntity(target, EntityType.AREA_EFFECT_CLOUD); - cloud.addCustomEffect(e, true); - cloud.setRadius(2.5F); - cloud.setDuration((int) sp.getDuration().getSeconds()); - cloud.setSource(caster.bukkit()); - } else if (effect instanceof CompoundEffect sp) { - final List effects = new ArrayList<>(); - for (PotionEffectType type : sp.getEffectTypes()) { - PotionEffect e = type.createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier()); - effects.add(e); - } - AreaEffectCloud cloud = (AreaEffectCloud) target.getWorld().spawnEntity(target, EntityType.AREA_EFFECT_CLOUD); - for (PotionEffect e : effects) { - cloud.addCustomEffect(e, true); - } - cloud.setRadius(2.5F); - cloud.setDuration((int) sp.getDuration().getSeconds()); - cloud.setSource(caster.bukkit()); - } - } - - @Override - public void cast(LivingEntity target) { - final Vector velocity = caster.bukkit().getEyeLocation().getDirection().multiply(2); - final T launched = caster.bukkit().launchProjectile(getProjectileType(), velocity); - - while (!launched.isDead()) { - final double randomXOffset = Math.sin((Math.random() * 10 - 2) % Math.PI) * 5; - final double randomYOffset = ((Math.random() * 10 - 2) % Math.PI) * 5; - final double randomZOffset = Math.cos((Math.random() * 10 - 2) % (2 * Math.PI)) * 5; - particles.forEach(particle -> launched.getWorld().spawnParticle(particle, launched.getLocation(), 1, randomXOffset, randomYOffset, randomZOffset)); - - if (launched.isOnGround() - || launched.isDead() - || launched.getTicksLived() > 100 - || launched.getLocation().clone().equals(target)) { - break; - } - } - - final Effect effect = spell.getEffect(); - if (effect instanceof SpellEffect sp) { - PotionEffect e = sp.getEffectType().createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier()); - target.addPotionEffect(e); - } else if (effect instanceof CompoundEffect sp) { - final List effects = new ArrayList<>(); - for (PotionEffectType type : sp.getEffectTypes()) { - PotionEffect e = type.createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier()); - effects.add(e); - } - target.addPotionEffects(effects); - } else if (effect instanceof SpecialEffect sp) { - sp.applyEffect(target); - } - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/cooldown/CooldownService.java b/src/main/java/app/simplexdev/arcanumocculta/cooldown/CooldownService.java new file mode 100644 index 0000000..98592c5 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/cooldown/CooldownService.java @@ -0,0 +1,45 @@ +package app.simplexdev.arcanumocculta.cooldown; + +import app.simplexdev.arcanumocculta.api.caster.Caster; +import app.simplexdev.arcanumocculta.api.spell.Spell; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CooldownService +{ + private final Map> cooldowns = new HashMap<>(); + + public void tick() + { + cooldowns.forEach((c, sl) -> { + sl.removeIf(CooldownStatus::hasExpired); + + if (sl.isEmpty()) cooldowns.remove(c); + }); + } + + public void include(final Caster caster, final CooldownStatus status) + { + List statuses = cooldowns.get(caster); + if (status == null) statuses = new ArrayList<>(); + + statuses.add(status); + cooldowns.put(caster, statuses); + } + + public void exclude(final CooldownStatus status) + { + cooldowns.forEach((c, sl) -> sl.removeIf(s -> s.getSpellUUID().equals(status.getSpellUUID()))); + } + + public boolean isOnCooldown(final Spell spell) + { + tick(); + return cooldowns.values() + .stream() + .flatMap(List::stream) + .anyMatch(status -> status.getSpellUUID().equals(spell.getUniqueId())); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/cooldown/CooldownStatus.java b/src/main/java/app/simplexdev/arcanumocculta/cooldown/CooldownStatus.java new file mode 100644 index 0000000..b4618e3 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/cooldown/CooldownStatus.java @@ -0,0 +1,31 @@ +package app.simplexdev.arcanumocculta.cooldown; + +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; + +public class CooldownStatus +{ + private final Duration duration; + private final Instant currentTime; + private final Instant endTime; + private final UUID spellUUID; + + public CooldownStatus(final UUID spellUUID, final Duration duration) + { + this.duration = duration; + this.currentTime = Instant.now(); + this.endTime = this.currentTime.plus(duration); + this.spellUUID = spellUUID; + } + + public UUID getSpellUUID() + { + return spellUUID; + } + + public boolean hasExpired() + { + return Instant.now().isAfter(this.endTime); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/spell/FireballSpell.java b/src/main/java/app/simplexdev/arcanumocculta/spell/FireballSpell.java deleted file mode 100644 index 54a5d1d..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/spell/FireballSpell.java +++ /dev/null @@ -1,23 +0,0 @@ -package app.simplexdev.arcanumocculta.spell; - -import app.simplexdev.arcanumocculta.api.effect.SpellEffect; -import app.simplexdev.arcanumocculta.api.player.Caster; -import app.simplexdev.arcanumocculta.base.spell.AbstractSpell; -import app.simplexdev.arcanumocculta.spell.effect.FireballEffect; -import app.simplexdev.arcanumocculta.spell.projectile.FireballProjectile; - -import java.time.Duration; - -public final class FireballSpell extends AbstractSpell { - private final Caster caster; - - public FireballSpell(final Caster caster) { - super("Fireball", "Fires a fireball in the direction you're facing.", new FireballEffect(Duration.ofSeconds(1), 1)); - this.caster = caster; - } - - @Override - public FireballProjectile getSpellProjectile() { - return new FireballProjectile(this, this.caster); - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/spell/effect/FireballEffect.java b/src/main/java/app/simplexdev/arcanumocculta/spell/effect/FireballEffect.java deleted file mode 100644 index f0eb174..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/spell/effect/FireballEffect.java +++ /dev/null @@ -1,12 +0,0 @@ -package app.simplexdev.arcanumocculta.spell.effect; - -import app.simplexdev.arcanumocculta.base.effect.AbstractSpellEffect; -import org.bukkit.potion.PotionEffectType; - -import java.time.Duration; - -public class FireballEffect extends AbstractSpellEffect { - public FireballEffect(Duration duration, float amplifier) { - super(duration, amplifier, PotionEffectType.HARM); - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/spell/projectile/FireballProjectile.java b/src/main/java/app/simplexdev/arcanumocculta/spell/projectile/FireballProjectile.java deleted file mode 100644 index 6564564..0000000 --- a/src/main/java/app/simplexdev/arcanumocculta/spell/projectile/FireballProjectile.java +++ /dev/null @@ -1,15 +0,0 @@ -package app.simplexdev.arcanumocculta.spell.projectile; - -import app.simplexdev.arcanumocculta.api.player.Caster; -import app.simplexdev.arcanumocculta.api.spell.Spell; -import app.simplexdev.arcanumocculta.base.spell.AbstractSpellProjectile; -import app.simplexdev.arcanumocculta.spell.FireballSpell; -import org.bukkit.Particle; -import org.bukkit.entity.Fireball; - -public class FireballProjectile extends AbstractSpellProjectile { - public FireballProjectile(FireballSpell spell, - Caster caster) { - super(spell, caster, Fireball.class, Particle.FLAME, Particle.SMALL_FLAME, Particle.LAVA); - } -} diff --git a/src/main/java/app/simplexdev/arcanumocculta/spells/PrimarySpellList.java b/src/main/java/app/simplexdev/arcanumocculta/spells/PrimarySpellList.java new file mode 100644 index 0000000..bac7578 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/spells/PrimarySpellList.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Simplex Development Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package app.simplexdev.arcanumocculta.spells; + +import app.simplexdev.arcanumocculta.api.caster.AbstractSpellBook; +import app.simplexdev.arcanumocculta.api.spell.AbstractSpell; +import app.simplexdev.arcanumocculta.api.spell.Spell; +import app.simplexdev.arcanumocculta.util.SpellUtils; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import org.bukkit.Bukkit; +import org.reflections.Reflections; +import org.reflections.scanners.Scanners; + +public class PrimarySpellList extends AbstractSpellBook +{ + public PrimarySpellList() + { + Set> spellClasses = m0().getSubTypesOf(AbstractSpell.class); + final Set v0 = new HashSet<>(); + spellClasses.forEach(spellClass -> + { + try + { + final Spell spell = spellClass.getDeclaredConstructor().newInstance(); + v0.add(spell); + } + catch (ReflectiveOperationException e) + { + Bukkit.getLogger().severe(e.getMessage()); + } + }); + this.addAll(v0); + } + + private Reflections m0() + { + final Reflections v0 = new Reflections(SpellUtils.SPELL_PACKAGE + ".flame", + Scanners.SubTypes); + final Reflections v1 = new Reflections(SpellUtils.SPELL_PACKAGE + ".soul", + Scanners.SubTypes); + final Reflections v2 = new Reflections(SpellUtils.SPELL_PACKAGE + ".wither", Scanners.SubTypes); + + return v0.merge(v1).merge(v2); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/spells/soul/SoulPebble.java b/src/main/java/app/simplexdev/arcanumocculta/spells/soul/SoulPebble.java new file mode 100644 index 0000000..7374475 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/spells/soul/SoulPebble.java @@ -0,0 +1,63 @@ +package app.simplexdev.arcanumocculta.spells.soul; + +import app.simplexdev.arcanumocculta.api.caster.Caster; +import app.simplexdev.arcanumocculta.api.caster.CasterLevel; +import app.simplexdev.arcanumocculta.api.spell.AbstractSpell; +import app.simplexdev.arcanumocculta.api.spell.SpellEffect; +import app.simplexdev.arcanumocculta.api.spell.enums.Damages; +import app.simplexdev.arcanumocculta.api.spell.enums.Durations; +import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts; +import app.simplexdev.arcanumocculta.api.wand.Wand; +import app.simplexdev.arcanumocculta.util.SpellUtils; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.entity.Entity; + +public final class SoulPebble extends AbstractSpell +{ + public SoulPebble() + { + super("Soul Pebble", + "soul_pebble", + "Fires a small soul pebble", + CasterLevel.APPRENTICE, + Damages.MINIMAL, + Durations.INSTANT, + ManaCosts.MINIMAL_CAST, + 5L); + } + + @Override + public SpellEffect[] getSpellEffects() + { + final SpellEffect[] effects = new SpellEffect[1]; + effects[0] = SpellUtils.soulEffectBase(baseDamage()); + return effects; + } + + @Override + public void cast(Caster caster, Wand wand) + { + if (!this.checkManaCosts(caster)) + { + return; + } + + final Entity projectile = prepareProjectile(caster, Material.AIR); + + while (!projectile.isOnGround() || !projectile.isDead()) + { + tracer(projectile.getWorld(), projectile.getLocation(), Particle.SOUL); + + if (!projectile.getNearbyEntities(1, 1, 1).isEmpty()) + { + applyEffects(projectile.getNearbyEntities(1, 1, 1), + caster); + projectile.remove(); + } + + if (projectile.isOnGround()) + projectile.remove(); + } + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/spells/soul/SoulShard.java b/src/main/java/app/simplexdev/arcanumocculta/spells/soul/SoulShard.java new file mode 100644 index 0000000..1643a5f --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/spells/soul/SoulShard.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Simplex Development Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package app.simplexdev.arcanumocculta.spells.soul; + +import app.simplexdev.arcanumocculta.api.caster.Caster; +import app.simplexdev.arcanumocculta.api.caster.CasterLevel; +import app.simplexdev.arcanumocculta.api.spell.AbstractSpell; +import app.simplexdev.arcanumocculta.api.spell.enums.Damages; +import app.simplexdev.arcanumocculta.api.spell.enums.Durations; +import app.simplexdev.arcanumocculta.api.spell.SpellEffect; +import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts; +import app.simplexdev.arcanumocculta.api.wand.Wand; +import app.simplexdev.arcanumocculta.util.SpellUtils; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffectType; + +public final class SoulShard extends AbstractSpell +{ + public SoulShard() + { + super("Soul Shard", + "soul_shard", + "A larger version of soul pebble.", + CasterLevel.APPRENTICE, Damages.LIGHT, + Durations.INSTANT, ManaCosts.LIGHT_CAST, + 5L); + } + + @Override + public SpellEffect[] getSpellEffects() + { + final SpellEffect[] effects = new SpellEffect[1]; + effects[0] = SpellUtils.soulEffectBase(baseDamage()); + return effects; + } + + @Override + public void cast(Caster caster, Wand wand) + { + if (!this.checkManaCosts(caster)) + { + return; + } + + final Entity projectile = prepareProjectile(caster, Material.AIR); + + while (!projectile.isDead()) { + for (int i = 0; i < 3; i++) { + tracer(projectile.getWorld(), projectile.getLocation(), Particle.SOUL); + } + + if (!projectile.getNearbyEntities(1, 1, 1).isEmpty()) + { + applyEffects(projectile.getNearbyEntities(1, 1, 1), + caster); + projectile.remove(); + } + + if (projectile.isOnGround()) { + projectile.remove(); + } + } + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/storage/local/PlayerYaml.java b/src/main/java/app/simplexdev/arcanumocculta/storage/local/PlayerYaml.java new file mode 100644 index 0000000..0d481a6 --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/storage/local/PlayerYaml.java @@ -0,0 +1,95 @@ +package app.simplexdev.arcanumocculta.storage.local; + +import app.simplexdev.arcanumocculta.ArcanumOcculta; +import app.simplexdev.arcanumocculta.api.caster.Caster; +import app.simplexdev.arcanumocculta.api.caster.CasterLevel; +import app.simplexdev.arcanumocculta.api.caster.SpellBook; +import app.simplexdev.arcanumocculta.api.wand.CapType; +import app.simplexdev.arcanumocculta.api.wand.CoreType; +import app.simplexdev.arcanumocculta.api.wand.GemType; +import app.simplexdev.arcanumocculta.api.wand.Wand; +import app.simplexdev.arcanumocculta.base.SimpleCaster; +import app.simplexdev.arcanumocculta.base.SimpleSpellBook; +import app.simplexdev.arcanumocculta.base.SimpleWand; +import app.simplexdev.arcanumocculta.util.SpellUtils; +import java.util.List; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class PlayerYaml +{ + private final YamlHolder yamlHolder; + + public PlayerYaml(final ArcanumOcculta plugin, final String name) + { + this.yamlHolder = new YamlHolder(plugin, "player-default.yml", name, plugin.getDataFolder(), false); + } + + public YamlHolder getYamlHolder() + { + return yamlHolder; + } + + public Wand retrieveWand() + { + ConfigurationSection wandSection = yamlHolder.getConfigurationSection("wand"); + String name = wandSection.getString("name"); + String description = wandSection.getString("description"); + Material material = Material.getMaterial(wandSection.getString("item")); + CoreType core = CoreType.valueOf(wandSection.getString("core")); + CapType cap = CapType.valueOf(wandSection.getString("cap")); + ItemStack item = new ItemStack(material, 1); + ItemMeta meta = item.getItemMeta(); + if (meta != null) + { + meta.setDisplayName(name); + meta.setLore(List.of(description)); + item.setItemMeta(meta); + } + GemType gem = GemType.valueOf(wandSection.getString("gem")); + return new SimpleWand(name, description, item, cap, core, gem); + } + + public void saveWand(final Wand wand) + { + ConfigurationSection wandSection = yamlHolder.getConfigurationSection("wand"); + wandSection.set("name", wand.getName()); + wandSection.set("description", wand.getDescription()); + wandSection.set("item", wand.getItem().getType().name()); + wandSection.set("core", wand.getCoreType().name()); + wandSection.set("cap", wand.getCapType().name()); + wandSection.set("gem", wand.getGemType().name()); + yamlHolder.save(); + } + + public Caster fetchCaster(final Player player) + { + ConfigurationSection caster = yamlHolder.getConfigurationSection("caster"); + CasterLevel level = CasterLevel.fromOrdinal(caster.getInt("caster_rank")); + double xp = caster.getDouble("current_experience"); + double currentMana = caster.getDouble("current_mana"); + double maxMana = caster.getDouble("max_mana"); + + final Wand wand = retrieveWand(); + final SpellBook spellBook = retrieveSpellBook(); + Caster c = new SimpleCaster(player, wand, spellBook, level); + c.setCurrentExperience(xp); + c.setCurrentMana(currentMana); + c.setMaxMana(maxMana); + return c; + } + + public SpellBook retrieveSpellBook() + { + final SpellBook book = new SimpleSpellBook(); + List spellBook = yamlHolder.getStringList("spellbook"); + for (String spell : spellBook) + { + book.addSpell(SpellUtils.copyFromPrimaryList(spell)); + } + return book; + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/storage/local/YamlHolder.java b/src/main/java/app/simplexdev/arcanumocculta/storage/local/YamlHolder.java new file mode 100644 index 0000000..7c771ba --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/storage/local/YamlHolder.java @@ -0,0 +1,106 @@ +package app.simplexdev.arcanumocculta.storage.local; + +import app.simplexdev.arcanumocculta.ArcanumOcculta; +import java.io.File; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.List; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +public class YamlHolder +{ + private final YamlConfiguration configuration; + private final ArcanumOcculta plugin; + + public YamlHolder(final ArcanumOcculta plugin, final String resourceLocation, final String fileName, + final File parentFolder, + final boolean copyDefaults) + { + final File file = new File(parentFolder, fileName); + this.plugin = plugin; + + try + { + if (file.createNewFile() || copyDefaults) + { + final String creatingFile = String.format("Creating %s...", fileName); + plugin.getLogger().info(creatingFile); + plugin.saveResource(resourceLocation, true); + } + } + catch (IOException ex) + { + plugin.getLogger().severe(ex.getMessage()); + } + + this.configuration = YamlConfiguration.loadConfiguration(file); + } + + public String getString(final String path) + { + return this.configuration.getString(path); + } + + public boolean getBoolean(final String path) + { + return this.configuration.getBoolean(path); + } + + public int getInt(final String path) + { + return this.configuration.getInt(path); + } + + public double getDouble(final String path) + { + return this.configuration.getDouble(path); + } + + public ConfigurationSection getConfigurationSection(final String path) + { + return this.configuration.getConfigurationSection(path); + } + + public List getStringList(final String path) + { + return this.configuration.getStringList(path); + } + + public void set(final String path, final Object value) + { + this.configuration.set(path, value); + } + + public void save() + { + try + { + this.configuration.save(this.configuration.getCurrentPath()); + } + catch (IOException ex) + { + final String message = MessageFormat.format("Failed to save {0}!", this.configuration.getCurrentPath()); + plugin.getLogger().severe(message); + } + } + + public void load() + { + try + { + this.configuration.load(this.configuration.getCurrentPath()); + } + catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) + { + final String message = MessageFormat.format("Failed to load {0}!", this.configuration.getCurrentPath()); + plugin.getLogger().severe(message); + } + } + + public void reload() + { + this.save(); + this.load(); + } +} diff --git a/src/main/java/app/simplexdev/arcanumocculta/util/SpellUtils.java b/src/main/java/app/simplexdev/arcanumocculta/util/SpellUtils.java new file mode 100644 index 0000000..8d4716c --- /dev/null +++ b/src/main/java/app/simplexdev/arcanumocculta/util/SpellUtils.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023 Simplex Development Group + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package app.simplexdev.arcanumocculta.util; + +import app.simplexdev.arcanumocculta.api.spell.Spell; +import app.simplexdev.arcanumocculta.api.spell.SpellEffect; +import app.simplexdev.arcanumocculta.api.spell.enums.Damages; +import app.simplexdev.arcanumocculta.spells.PrimarySpellList; +import java.util.SplittableRandom; +import org.bukkit.Particle; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +public final class SpellUtils +{ + public static final String SPELL_PACKAGE = PrimarySpellList.class.getPackageName(); + private static final PrimarySpellList primarySpellList = new PrimarySpellList(); + private static final SplittableRandom RANDOM = new SplittableRandom(); + + private SpellUtils() + { + throw new AssertionError(); + } + + public static void damage(final Damageable target, final LivingEntity damager, final double damage) + { + if (target instanceof Player) + target.damage(damage % 20.0, damager); + else + target.damage(damage); + } + + public static Spell copyFromPrimaryList(final String id) + { + return SpellUtils.primarySpellList.getSpell(id).dupe(); + } + + public static SpellEffect soulEffectBase(final Damages baseDamage) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + if (target instanceof Player player) + // Player is freezing when hit, as if they were in powdered snow for 1 minute. + player.setFreezeTicks(1200); + + damage(target, caster.bukkit(), damage); + }; + } + + public static SpellEffect flameEffectBase(final Damages baseDamage) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + // Fire ticks for 15 seconds. + target.setFireTicks(300); + + damage(target, caster.bukkit(), damage); + }; + } + + public static SpellEffect witherEffectBase(final Damages baseDamage) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + // Wither for 10 seconds. + target.addPotionEffect(PotionEffectType.WITHER.createEffect(200, 2)); + + damage(target, caster.bukkit(), damage); + }; + } + + public static SpellEffect lightningEffectBase(final Damages baseDamage) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + // Lightning on target + target.getWorld().strikeLightning(target.getLocation()); + + damage(target, caster.bukkit(), damage); + }; + } + + public static SpellEffect healEffectBase(final Damages baseDamage) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + // Heal target + target.setHealth(target.getHealth() + damage); + }; + } + + public static SpellEffect regenEffectBase(final Damages baseDamage) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + // Regen target + target.addPotionEffect(PotionEffectType.REGENERATION.createEffect(300, 3)); + target.setHealth(target.getHealth() + ((target.getHealth() + damage) / 2)); + }; + } + + public static SpellEffect meteorLikeEffectBase(final Damages baseDamage, + final Vector incomingVelocity, + final float size) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + // Meteor like effect + // TODO: Make a configuration option to enable/disable explosions destroying blocks. + target.getWorld().createExplosion(target.getLocation(), size, true, false); + target.setVelocity(incomingVelocity.normalize().multiply(2).multiply(-1)); + damage(target, caster.bukkit(), damage); + }; + } + + public static SpellEffect arsLikeEffectBase(final Damages baseDamage) + { + return (target, caster) -> + { + final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); + // Ars Magica like effect + target.setVelocity(caster.bukkit().getLocation().clone().getDirection().multiply(2)); + if (target instanceof Player player) + player.setFreezeTicks(1200); + for (int i = 0; i < 50; i++) + { + target.getWorld().spawnParticle(Particle.SOUL_FIRE_FLAME, + target.getLocation(), + 0, + RANDOM.nextDouble(-2, 2), + RANDOM.nextDouble(-2, 2), + RANDOM.nextDouble(-2, 2)); + } + + damage(target, caster.bukkit(), damage); + }; + } +} diff --git a/src/main/resources/player-default.yml b/src/main/resources/player-default.yml new file mode 100644 index 0000000..73f881e --- /dev/null +++ b/src/main/resources/player-default.yml @@ -0,0 +1,18 @@ +caster: + caster_rank: 1 + current_experience: 0 + current_mana: 100 + max_mana: 100 + spell_influence: 0 + spell_points: 0 + +spellbook: + - FIREBALL + +wand: + name: Basic Wand + description: A basic wand + item: STICK + core: WOOD + gem: NONE + cap: IRON diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 35907f2..f8aa978 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,3 +3,5 @@ version: '${version}' main: app.simplexdev.arcanumocculta.ArcanumOcculta api-version: '1.20' load: STARTUP +libraries: + - org.reflections:reflections:0.10.2