some implementation

This commit is contained in:
Paul Reilly 2023-07-19 16:32:48 -05:00
parent bc4f6c033f
commit eb3805eb1f
7 changed files with 247 additions and 19 deletions

View File

@ -14,12 +14,16 @@ import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Particle; import org.bukkit.Particle;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemDisplay; 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.inventory.ItemStack;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
public abstract class AbstractSpell implements Spell public abstract class AbstractSpell implements Spell
@ -146,18 +150,21 @@ public abstract class AbstractSpell implements Spell
.filter(LivingEntity.class::isInstance) .filter(LivingEntity.class::isInstance)
.map(LivingEntity.class::cast) .map(LivingEntity.class::cast)
.forEach(entity -> applyEffectsIndividually( .forEach(entity -> applyEffectsIndividually(
getSpellEffects(),
entity, entity,
caster)); caster,
getSpellEffects()));
} }
public Entity prepareProjectile(final Caster caster, final Material visual) public void simulateExplosion(final Location location, final float size, boolean breakBlocks) {
location.getWorld().createExplosion(location, size, true, breakBlocks);
}
public Entity prepareProjectile(final Caster caster, final Material visual, final Vector velocity)
{ {
final double expMod = getLevelRequirement().getExperienceMarker(); final double expMod = getLevelRequirement().getExperienceMarker();
final Player player = caster.bukkit(); final Player player = caster.bukkit();
final Location location = player.getLocation().clone().add(0, player.getEyeHeight(), 0); 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, final Entity projectile = createProjectile(visual, player.getWorld(), location,
velocity); velocity);
caster.removeMana(manaCost().getManaCost()); caster.removeMana(manaCost().getManaCost());
@ -175,8 +182,43 @@ public abstract class AbstractSpell implements Spell
random().nextDouble(-2, 2)); random().nextDouble(-2, 2));
} }
private void applyEffectsIndividually(final SpellEffect[] effects, final LivingEntity target, public void spiral(final World world, final Location location, final Particle particle)
final Caster caster) {
final double step = 0.5;
final double radius = 2;
final double area = Math.PI * Math.pow(radius, 2);
final double theta = area / step;
final double phi = step / radius;
for (double i = 0; i < theta; i += phi)
{
final double x = radius * Math.cos(i);
final double z = radius * Math.sin(i);
world.spawnParticle(particle, location.clone().add(x, 0, z), 0);
}
}
public AreaEffectCloud cloud(final World world,
final Location location,
final Particle particle,
final float size,
final int duration,
final PotionType effect) {
AreaEffectCloud cloud = (AreaEffectCloud) world.spawnEntity(location, EntityType.AREA_EFFECT_CLOUD);
cloud.setParticle(particle);
cloud.setDuration(duration);
if (effect != null) {
cloud.setBasePotionData(new PotionData(effect));
}
cloud.setRadius(size);
cloud.setRadiusPerTick(size / 0.5F);
return cloud;
}
protected void applyEffectsIndividually(final LivingEntity target,
final Caster caster, final SpellEffect... effects)
{ {
for (final SpellEffect effect : effects) for (final SpellEffect effect : effects)
effect.apply(target, caster); effect.apply(target, caster);

View File

@ -25,9 +25,9 @@ package app.simplexdev.arcanumocculta.api.spell.enums;
// Reference for implementation. // Reference for implementation.
public enum SpellTypes public enum SpellTypes
{ {
SOUL_PEBBLE, SOUL_SHARD, LARGE_SOUL_SHARD, SOUL_COMET_SHARD, SOUL_COMET, SOUL_SHARD_SPIRAL, SOUL_STARS, SOUL_PEBBLE, SOUL_SHARD, LARGE_SOUL_SHARD, SOUL_COMET, SOUL_SPIRAL,
SOUL_STAR_SHOWER, SOUL_ARC, SOUL_BARRAGE, SOUL_BURST, SOUL_CANNON, SOUL_HAMMER, SOUL_BLAST, SOUL_EXPLOSION, SOUL_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, 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_SLING, FLAME_BURST, CATCH_FLAME, FLAME_BARRAGE, FIREBALL, METEORITE, METEOR, FLAME_WHIP, FLAME_FAN,
FLAME_ORB, FLAME_PILLARS, FLAME_WHIRLWIND, FLAME_ORB, FLAME_PILLARS, FLAME_WHIRLWIND,

View File

@ -0,0 +1,81 @@
/*
* 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.flame;
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.block.BlockFace;
import org.bukkit.entity.Entity;
public class FlameSling extends AbstractSpell
{
protected FlameSling()
{
super("Flame Sling", "flame_sling",
"Lob a ball of fire at your enemies!",
CasterLevel.APPRENTICE,
Damages.LIGHT,
Durations.MEDIUM,
ManaCosts.LIGHT_CAST,
10L);
}
@Override
public SpellEffect[] getSpellEffects()
{
final SpellEffect[] effects = new SpellEffect[1];
effects[0] = SpellUtils.flameEffectBase(baseDamage());
return effects;
}
@Override
public void cast(Caster caster, Wand wand)
{
if (!checkManaCosts(caster))
return;
final Entity projectile = prepareProjectile(caster, Material.FIRE_CHARGE,
caster.bukkit()
.getLocation().clone()
.getDirection().multiply(2));
while (!projectile.isDead()) {
if (!projectile.getNearbyEntities(1, 1, 1).isEmpty()) {
applyEffects(projectile.getNearbyEntities(1, 1, 1), caster);
projectile.remove();
}
if (projectile.isOnGround()) {
projectile.remove();
}
}
}
}

View File

@ -43,7 +43,12 @@ public final class SoulPebble extends AbstractSpell
return; return;
} }
final Entity projectile = prepareProjectile(caster, Material.AIR); final Entity projectile = prepareProjectile(caster, Material.AIR,
caster.bukkit()
.getLocation()
.clone()
.getDirection()
.multiply(2));
while (!projectile.isOnGround() || !projectile.isDead()) while (!projectile.isOnGround() || !projectile.isDead())
{ {

View File

@ -25,17 +25,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.Material; import org.bukkit.Material;
import org.bukkit.Particle; import org.bukkit.Particle;
import org.bukkit.entity.Entity; 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
{ {
@ -65,10 +63,17 @@ public final class SoulShard extends AbstractSpell
return; return;
} }
final Entity projectile = prepareProjectile(caster, Material.AIR); final Entity projectile = prepareProjectile(caster, Material.AIR,
caster.bukkit()
.getLocation()
.clone()
.getDirection()
.multiply(2));
while (!projectile.isDead()) { while (!projectile.isDead())
for (int i = 0; i < 3; i++) { {
for (int i = 0; i < 3; i++)
{
tracer(projectile.getWorld(), projectile.getLocation(), Particle.SOUL); tracer(projectile.getWorld(), projectile.getLocation(), Particle.SOUL);
} }
@ -79,7 +84,8 @@ public final class SoulShard extends AbstractSpell
projectile.remove(); projectile.remove();
} }
if (projectile.isOnGround()) { if (projectile.isOnGround())
{
projectile.remove(); projectile.remove();
} }
} }

View File

@ -0,0 +1,93 @@
/*
* 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.wither;
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 java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
public final class WitherMeteorite extends AbstractSpell
{
public WitherMeteorite()
{
super("Wither Meteorite",
"wither_meteorite",
"Call down a wither skull from the heavens to wreak havoc on your enemies.",
CasterLevel.ARCH_MAGE,
Damages.OVERKILL,
Durations.MEDIUM,
ManaCosts.IMMENSE_CAST,
600L);
}
@Override
public SpellEffect[] getSpellEffects()
{
final SpellEffect[] effects = new SpellEffect[2];
effects[0] = SpellUtils.witherEffectBase(baseDamage(), effectDuration());
return effects;
}
@Override
public void cast(Caster caster, Wand wand)
{
if (this.checkManaCosts(caster))
return;
final Location location = caster.bukkit().getEyeLocation().clone().add(0, 256, 0);
final Vector direction = location.getDirection().add(new Vector(0, -5, 0));
final Entity projectile = prepareProjectile(caster,
Material.WITHER_SKELETON_SKULL,
direction);
getSpellEffects()[1] = SpellUtils.meteorLikeEffectBase(baseDamage(), direction, 4F);
while (!projectile.isDead())
{
if (!projectile.getNearbyEntities(5, 5, 5).isEmpty())
{
final List<Entity> e = projectile.getNearbyEntities(5, 5, 5);
applyEffects(e, caster);
projectile.remove();
}
if (projectile.isOnGround())
{
simulateExplosion(projectile.getLocation(), 4F, true);
projectile.remove();
}
}
}
}

View File

@ -25,6 +25,7 @@ package app.simplexdev.arcanumocculta.util;
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.api.spell.enums.Damages;
import app.simplexdev.arcanumocculta.api.spell.enums.Durations;
import app.simplexdev.arcanumocculta.spells.PrimarySpellList; import app.simplexdev.arcanumocculta.spells.PrimarySpellList;
import java.util.SplittableRandom; import java.util.SplittableRandom;
import org.bukkit.Particle; import org.bukkit.Particle;
@ -83,13 +84,13 @@ public final class SpellUtils
}; };
} }
public static SpellEffect witherEffectBase(final Damages baseDamage) public static SpellEffect witherEffectBase(final Damages baseDamage, final Durations duration)
{ {
return (target, caster) -> return (target, caster) ->
{ {
final var damage = baseDamage.multiply(caster.getWand().getSpellBonus()); final var damage = baseDamage.multiply(caster.getWand().getSpellBonus());
// Wither for 10 seconds. // Wither for 10 seconds.
target.addPotionEffect(PotionEffectType.WITHER.createEffect(200, 2)); target.addPotionEffect(PotionEffectType.WITHER.createEffect((int) duration.getTicks(), 3));
damage(target, caster.bukkit(), damage); damage(target, caster.bukkit(), damage);
}; };