mirror of
https://github.com/SimplexDevelopment/ArcanumOcculta.git
synced 2024-11-14 21:43:33 +00:00
Wonderful API!
Now for implementations 😧
This commit is contained in:
parent
893ed446c4
commit
bc4f6c033f
@ -5,8 +5,22 @@ import app.simplexdev.arcanumocculta.api.caster.CasterLevel;
|
|||||||
import app.simplexdev.arcanumocculta.api.spell.enums.Damages;
|
import app.simplexdev.arcanumocculta.api.spell.enums.Damages;
|
||||||
import app.simplexdev.arcanumocculta.api.spell.enums.Durations;
|
import app.simplexdev.arcanumocculta.api.spell.enums.Durations;
|
||||||
import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts;
|
import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts;
|
||||||
|
import app.simplexdev.arcanumocculta.util.SpellUtils;
|
||||||
|
import java.util.List;
|
||||||
import java.util.SplittableRandom;
|
import java.util.SplittableRandom;
|
||||||
import org.bukkit.Bukkit;
|
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
|
public abstract class AbstractSpell implements Spell
|
||||||
{
|
{
|
||||||
@ -110,4 +124,75 @@ public abstract class AbstractSpell implements Spell
|
|||||||
{
|
{
|
||||||
return 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<Entity> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,15 @@ package app.simplexdev.arcanumocculta.spells.soul;
|
|||||||
import app.simplexdev.arcanumocculta.api.caster.Caster;
|
import app.simplexdev.arcanumocculta.api.caster.Caster;
|
||||||
import app.simplexdev.arcanumocculta.api.caster.CasterLevel;
|
import app.simplexdev.arcanumocculta.api.caster.CasterLevel;
|
||||||
import app.simplexdev.arcanumocculta.api.spell.AbstractSpell;
|
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.Damages;
|
||||||
import app.simplexdev.arcanumocculta.api.spell.enums.Durations;
|
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.spell.enums.ManaCosts;
|
||||||
import app.simplexdev.arcanumocculta.api.wand.Wand;
|
import app.simplexdev.arcanumocculta.api.wand.Wand;
|
||||||
import app.simplexdev.arcanumocculta.util.SpellUtils;
|
import app.simplexdev.arcanumocculta.util.SpellUtils;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.entity.ItemDisplay;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
public final class SoulPebble extends AbstractSpell
|
public final class SoulPebble extends AbstractSpell
|
||||||
{
|
{
|
||||||
@ -35,56 +31,33 @@ public final class SoulPebble extends AbstractSpell
|
|||||||
public SpellEffect[] getSpellEffects()
|
public SpellEffect[] getSpellEffects()
|
||||||
{
|
{
|
||||||
final SpellEffect[] effects = new SpellEffect[1];
|
final SpellEffect[] effects = new SpellEffect[1];
|
||||||
effects[0] = (target, caster) ->
|
effects[0] = SpellUtils.soulEffectBase(baseDamage());
|
||||||
{
|
|
||||||
final Wand wand = caster.getWand();
|
|
||||||
final double damage = baseDamage().multiply(wand.getSpellBonus());
|
|
||||||
|
|
||||||
SpellUtils.damage(target, caster.bukkit(), damage);
|
|
||||||
};
|
|
||||||
return effects;
|
return effects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(Caster caster, Wand wand)
|
public void cast(Caster caster, Wand wand)
|
||||||
{
|
{
|
||||||
if (this.manaCost().isMoreThan(caster.getCurrentMana()))
|
if (!this.checkManaCosts(caster))
|
||||||
{
|
{
|
||||||
caster.bukkit().sendMessage("You do not have enough mana to cast this spell!");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final double expMod = this.getLevelRequirement().getExperienceMarker();
|
final Entity projectile = prepareProjectile(caster, Material.AIR);
|
||||||
|
|
||||||
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 ItemDisplay projectile = SpellUtils.createProjectile(Material.AIR, player.getWorld(), location,
|
|
||||||
velocity);
|
|
||||||
caster.removeMana(this.manaCost().getManaCost());
|
|
||||||
caster.addExperience(random().nextDouble(expMod * 0.25));
|
|
||||||
|
|
||||||
while (!projectile.isOnGround() || !projectile.isDead())
|
while (!projectile.isOnGround() || !projectile.isDead())
|
||||||
{
|
{
|
||||||
projectile.getWorld().spawnParticle(Particle.SOUL, projectile.getLocation(), 1,
|
tracer(projectile.getWorld(), projectile.getLocation(), Particle.SOUL);
|
||||||
random().nextGaussian() * 0.2,
|
|
||||||
random().nextGaussian() * 0.2,
|
|
||||||
random().nextGaussian() * 0.2);
|
|
||||||
|
|
||||||
if (!projectile.getNearbyEntities(1, 1, 1).isEmpty()) {
|
if (!projectile.getNearbyEntities(1, 1, 1).isEmpty())
|
||||||
projectile.getNearbyEntities(1, 1, 1)
|
{
|
||||||
.stream()
|
applyEffects(projectile.getNearbyEntities(1, 1, 1),
|
||||||
.filter(LivingEntity.class::isInstance)
|
caster);
|
||||||
.map(LivingEntity.class::cast)
|
|
||||||
.forEach(entity -> SpellUtils.applyEffects(
|
|
||||||
this.getSpellEffects(),
|
|
||||||
entity,
|
|
||||||
caster));
|
|
||||||
projectile.remove();
|
projectile.remove();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (projectile.isOnGround()) projectile.remove();
|
if (projectile.isOnGround())
|
||||||
|
projectile.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,12 @@ import app.simplexdev.arcanumocculta.api.spell.enums.Durations;
|
|||||||
import app.simplexdev.arcanumocculta.api.spell.SpellEffect;
|
import app.simplexdev.arcanumocculta.api.spell.SpellEffect;
|
||||||
import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts;
|
import app.simplexdev.arcanumocculta.api.spell.enums.ManaCosts;
|
||||||
import app.simplexdev.arcanumocculta.api.wand.Wand;
|
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 final class SoulShard extends AbstractSpell
|
||||||
{
|
{
|
||||||
@ -46,12 +52,36 @@ public final class SoulShard extends AbstractSpell
|
|||||||
@Override
|
@Override
|
||||||
public SpellEffect[] getSpellEffects()
|
public SpellEffect[] getSpellEffects()
|
||||||
{
|
{
|
||||||
return new SpellEffect[0];
|
final SpellEffect[] effects = new SpellEffect[1];
|
||||||
|
effects[0] = SpellUtils.soulEffectBase(baseDamage());
|
||||||
|
return effects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(Caster caster, Wand wand)
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,25 +22,23 @@
|
|||||||
|
|
||||||
package app.simplexdev.arcanumocculta.util;
|
package app.simplexdev.arcanumocculta.util;
|
||||||
|
|
||||||
import app.simplexdev.arcanumocculta.api.caster.Caster;
|
|
||||||
import app.simplexdev.arcanumocculta.api.spell.Spell;
|
import app.simplexdev.arcanumocculta.api.spell.Spell;
|
||||||
import app.simplexdev.arcanumocculta.api.spell.SpellEffect;
|
import app.simplexdev.arcanumocculta.api.spell.SpellEffect;
|
||||||
|
import app.simplexdev.arcanumocculta.api.spell.enums.Damages;
|
||||||
import app.simplexdev.arcanumocculta.spells.PrimarySpellList;
|
import app.simplexdev.arcanumocculta.spells.PrimarySpellList;
|
||||||
import org.bukkit.Location;
|
import java.util.SplittableRandom;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Damageable;
|
import org.bukkit.entity.Damageable;
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.ItemDisplay;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public final class SpellUtils
|
public final class SpellUtils
|
||||||
{
|
{
|
||||||
public static final String SPELL_PACKAGE = PrimarySpellList.class.getPackageName();
|
public static final String SPELL_PACKAGE = PrimarySpellList.class.getPackageName();
|
||||||
private static final PrimarySpellList primarySpellList = new PrimarySpellList();
|
private static final PrimarySpellList primarySpellList = new PrimarySpellList();
|
||||||
|
private static final SplittableRandom RANDOM = new SplittableRandom();
|
||||||
|
|
||||||
private SpellUtils()
|
private SpellUtils()
|
||||||
{
|
{
|
||||||
@ -55,28 +53,116 @@ public final class SpellUtils
|
|||||||
target.damage(damage);
|
target.damage(damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void applyEffects(final SpellEffect[] effects, final LivingEntity target, final Caster caster)
|
|
||||||
{
|
|
||||||
for (final SpellEffect effect : effects)
|
|
||||||
effect.apply(target, caster);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Spell copyFromPrimaryList(final String id)
|
public static Spell copyFromPrimaryList(final String id)
|
||||||
{
|
{
|
||||||
return SpellUtils.primarySpellList.getSpell(id).dupe();
|
return SpellUtils.primarySpellList.getSpell(id).dupe();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemDisplay createProjectile(final Material visual, final World world, final Location location,
|
public static SpellEffect soulEffectBase(final Damages baseDamage)
|
||||||
final Vector velocity)
|
|
||||||
{
|
{
|
||||||
final ItemDisplay display = (ItemDisplay) world.spawnEntity(location, EntityType.ITEM_DISPLAY);
|
return (target, caster) ->
|
||||||
display.setItemStack(new ItemStack(visual));
|
{
|
||||||
display.setGravity(true);
|
final var damage = baseDamage.multiply(caster.getWand().getSpellBonus());
|
||||||
display.setPersistent(false);
|
if (target instanceof Player player)
|
||||||
display.setSilent(true);
|
// Player is freezing when hit, as if they were in powdered snow for 1 minute.
|
||||||
display.setShadowRadius(0);
|
player.setFreezeTicks(1200);
|
||||||
display.setShadowStrength(0);
|
|
||||||
display.setVelocity(velocity);
|
damage(target, caster.bukkit(), damage);
|
||||||
return display;
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user