mirror of
https://github.com/SimplexDevelopment/ArcanumOcculta.git
synced 2024-12-22 12:17:37 +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.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
|
||||
{
|
||||
@ -110,4 +124,75 @@ public abstract class AbstractSpell implements Spell
|
||||
{
|
||||
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.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.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.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public final class SoulPebble extends AbstractSpell
|
||||
{
|
||||
@ -35,56 +31,33 @@ public final class SoulPebble extends AbstractSpell
|
||||
public SpellEffect[] getSpellEffects()
|
||||
{
|
||||
final SpellEffect[] effects = new SpellEffect[1];
|
||||
effects[0] = (target, caster) ->
|
||||
{
|
||||
final Wand wand = caster.getWand();
|
||||
final double damage = baseDamage().multiply(wand.getSpellBonus());
|
||||
|
||||
SpellUtils.damage(target, caster.bukkit(), damage);
|
||||
};
|
||||
effects[0] = SpellUtils.soulEffectBase(baseDamage());
|
||||
return effects;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
final double expMod = this.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 ItemDisplay projectile = SpellUtils.createProjectile(Material.AIR, player.getWorld(), location,
|
||||
velocity);
|
||||
caster.removeMana(this.manaCost().getManaCost());
|
||||
caster.addExperience(random().nextDouble(expMod * 0.25));
|
||||
final Entity projectile = prepareProjectile(caster, Material.AIR);
|
||||
|
||||
while (!projectile.isOnGround() || !projectile.isDead())
|
||||
{
|
||||
projectile.getWorld().spawnParticle(Particle.SOUL, projectile.getLocation(), 1,
|
||||
random().nextGaussian() * 0.2,
|
||||
random().nextGaussian() * 0.2,
|
||||
random().nextGaussian() * 0.2);
|
||||
tracer(projectile.getWorld(), projectile.getLocation(), Particle.SOUL);
|
||||
|
||||
if (!projectile.getNearbyEntities(1, 1, 1).isEmpty()) {
|
||||
projectile.getNearbyEntities(1, 1, 1)
|
||||
.stream()
|
||||
.filter(LivingEntity.class::isInstance)
|
||||
.map(LivingEntity.class::cast)
|
||||
.forEach(entity -> SpellUtils.applyEffects(
|
||||
this.getSpellEffects(),
|
||||
entity,
|
||||
caster));
|
||||
if (!projectile.getNearbyEntities(1, 1, 1).isEmpty())
|
||||
{
|
||||
applyEffects(projectile.getNearbyEntities(1, 1, 1),
|
||||
caster);
|
||||
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.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
|
||||
{
|
||||
@ -46,12 +52,36 @@ public final class SoulShard extends AbstractSpell
|
||||
@Override
|
||||
public SpellEffect[] getSpellEffects()
|
||||
{
|
||||
return new SpellEffect[0];
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,25 +22,23 @@
|
||||
|
||||
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.SpellEffect;
|
||||
import app.simplexdev.arcanumocculta.api.spell.enums.Damages;
|
||||
import app.simplexdev.arcanumocculta.spells.PrimarySpellList;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import java.util.SplittableRandom;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Damageable;
|
||||
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.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()
|
||||
{
|
||||
@ -55,28 +53,116 @@ public final class SpellUtils
|
||||
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)
|
||||
{
|
||||
return SpellUtils.primarySpellList.getSpell(id).dupe();
|
||||
}
|
||||
|
||||
public static ItemDisplay createProjectile(final Material visual, final World world, final Location location,
|
||||
final Vector velocity)
|
||||
public static SpellEffect soulEffectBase(final Damages baseDamage)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user