From 38e7b8bc36a87d6900aa325fee33ade41f302970 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 24 Sep 2018 21:37:16 +0200 Subject: [PATCH] Fix up spells slightly --- .../minelittlepony/unicopia/Predicates.java | 6 +- .../unicopia/entity/EntitySpell.java | 111 ++++++++------- .../unicopia/item/ICastable.java | 4 + .../unicopia/item/ItemSpell.java | 8 ++ .../unicopia/model/ModelGem.java | 4 +- .../unicopia/player/PlayerCapabilities.java | 4 +- .../unicopia/spell/AbstractSpell.java | 13 -- .../unicopia/spell/ICaster.java | 10 ++ .../unicopia/spell/ILevelled.java | 26 ++++ .../unicopia/spell/IMagicEffect.java | 56 +++----- .../unicopia/spell/SpellShield.java | 127 ++++++++++-------- 11 files changed, 200 insertions(+), 169 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/spell/ILevelled.java diff --git a/src/main/java/com/minelittlepony/unicopia/Predicates.java b/src/main/java/com/minelittlepony/unicopia/Predicates.java index e69e0f82..95ebcc02 100644 --- a/src/main/java/com/minelittlepony/unicopia/Predicates.java +++ b/src/main/java/com/minelittlepony/unicopia/Predicates.java @@ -12,12 +12,12 @@ public final class Predicates { return player != null && PlayerSpeciesList.instance().getPlayer(player).getPlayerSpecies().canInteractWithClouds(); }; - public static final Predicate MAGI = player -> { - return player != null && PlayerSpeciesList.instance().getPlayer(player).getPlayerSpecies().canCast(); + public static final Predicate MAGI = entity -> { + return entity instanceof EntityPlayer && PlayerSpeciesList.instance().getPlayer((EntityPlayer)entity).getPlayerSpecies().canCast(); }; public static final Predicate ITEMS = entity -> { - return entity.isEntityAlive() && entity instanceof EntityItem; + return entity instanceof EntityItem && entity.isEntityAlive(); }; public static final Predicate ITEM_INTERACT_WITH_CLOUDS = item -> { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java index 89a75acd..5a10c362 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java @@ -1,10 +1,13 @@ package com.minelittlepony.unicopia.entity; +import org.apache.commons.lang3.StringUtils; + import com.minelittlepony.unicopia.Predicates; import com.minelittlepony.unicopia.UItems; -import com.minelittlepony.unicopia.item.ItemSpell; +import com.minelittlepony.unicopia.item.ICastable; import com.minelittlepony.unicopia.network.EffectSync; import com.minelittlepony.unicopia.spell.ICaster; +import com.minelittlepony.unicopia.spell.ILevelled; import com.minelittlepony.unicopia.spell.IMagicEffect; import com.minelittlepony.unicopia.spell.SpellRegistry; @@ -28,7 +31,7 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class EntitySpell extends EntityLiving implements IMagicals, ICaster { +public class EntitySpell extends EntityLiving implements IMagicals, ICaster, ILevelled { private EntityLivingBase owner = null; @@ -102,7 +105,7 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster 10 || overLevelCap()) { - world.createExplosion(this, posX, posY, posZ, getLevel()/2, true); - setDead(); - return false; - } - } - - playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1f, 1); - - return true; - } - return false; - } - public EnumActionResult applyPlayerInteraction(EntityPlayer player, Vec3d vec, EnumHand hand) { if (Predicates.MAGI.test(player)) { ItemStack currentItem = player.getHeldItem(EnumHand.MAIN_HAND); - if (currentItem != null && currentItem.getItem() instanceof ItemSpell) { - tryLevelUp(currentItem); + if (currentItem != null + && currentItem.getItem() instanceof ICastable + && ((ICastable)currentItem.getItem()).canFeed(this, currentItem) + && tryLevelUp(currentItem)) { if (!player.capabilities.isCreativeMode) { currentItem.shrink(1); @@ -258,24 +231,48 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster 10 || overLevelCap()) { + world.createExplosion(this, posX, posY, posZ, getCurrentLevel()/2, true); + setDead(); + return false; + } + } + + playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1f, 1); + + return true; + } + + return false; + } + + @Override + public int getMaxLevel() { + return getEffect().getMaxLevel(); } - public boolean canLevelUp() { - int max = getEffect().getMaxLevel(); - return max < 0 || getLevel() < max; - } + @Override + public int getCurrentLevel() { + return dataManager.get(LEVEL); + } + + @Override + public void setCurrentLevel(int level) { + dataManager.set(LEVEL, Math.min(level, 0)); + } public boolean overLevelCap() { - int max = getEffect().getMaxLevel(); - return max > 0 && getLevel() >= (max * 1.1); - } - - public void decreaseLevel() { - int level = getLevel() - 1; - if (level < 0) level = 0; - setLevel(level); + int max = getMaxLevel(); + return max > 0 && getCurrentLevel() >= (max * 1.1); } @Override @@ -287,7 +284,7 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster 0) { - floatOffset *= spell.getLevel() + 1; + if (spell.getCurrentLevel() > 0) { + floatOffset *= spell.getCurrentLevel() + 1; } floatOffset += spell.hoverStart; diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java index af424ced..044e3689 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java @@ -139,10 +139,10 @@ class PlayerCapabilities implements IPlayer, ICaster { setEffect(null); } else { if (entity.getEntityWorld().isRemote) { // && entity.getEntityWorld().getWorldTime() % 10 == 0 - getEffect().render(entity); + getEffect().render(this); } - if (!getEffect().update(entity)) { + if (!getEffect().update(this)) { setEffect(null); } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java index e60efdb1..d9c526db 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java @@ -1,8 +1,5 @@ package com.minelittlepony.unicopia.spell; -import net.minecraft.entity.Entity; -import net.minecraft.world.World; - public abstract class AbstractSpell implements IMagicEffect { protected boolean isDead = false; @@ -16,14 +13,4 @@ public abstract class AbstractSpell implements IMagicEffect { public boolean getDead() { return isDead; } - - @Override - public boolean update(Entity source) { - return false; - } - - @Override - public boolean updateAt(ICaster source, World w, double x, double y, double z, int level) { - return false; - } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java index fbbb5e90..36e0be5a 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java @@ -4,6 +4,8 @@ import com.minelittlepony.unicopia.player.IOwned; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; public interface ICaster extends IOwned { void setEffect(IMagicEffect effect); @@ -20,4 +22,12 @@ public interface ICaster extends IOwned { default Entity getEntity() { return getOwner(); } + + default World getWorld() { + return getEntity().getEntityWorld(); + } + + default BlockPos getOrigin() { + return getEntity().getPosition(); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/ILevelled.java b/src/main/java/com/minelittlepony/unicopia/spell/ILevelled.java new file mode 100644 index 00000000..99af16a1 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/ILevelled.java @@ -0,0 +1,26 @@ +package com.minelittlepony.unicopia.spell; + +public interface ILevelled { + + /** + * Maximum level this spell can reach or -1 for unlimited. + *
+ * If a gem goes past this level it is more likely to explode. + */ + default int getMaxLevel() { + return 0; + } + + default boolean canLevelUp() { + int max = getMaxLevel(); + return max < 0 || getCurrentLevel() < max; + } + + int getCurrentLevel(); + + void setCurrentLevel(int level); + + default void addLevels(int levels) { + setCurrentLevel(getCurrentLevel() + levels); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java index 0e45822e..d261fb4e 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java @@ -2,24 +2,10 @@ package com.minelittlepony.unicopia.spell; import com.minelittlepony.unicopia.InbtSerialisable; -import net.minecraft.entity.Entity; -import net.minecraft.world.World; - /** - * - * Interface for a magic spell - * + * Interface for a magic spells */ -public interface IMagicEffect extends InbtSerialisable { - - /** - * Maximum level this spell can reach or -1 for unlimited. - *
- * If a gem goes past this level it is more likely to explode. - */ - default int getMaxLevel() { - return 0; - } +public interface IMagicEffect extends InbtSerialisable, ILevelled { String getName(); @@ -39,42 +25,34 @@ public interface IMagicEffect extends InbtSerialisable { * @param source The entity we are currently attached to. * @return true to keep alive */ - boolean update(Entity source); - - /** - * Called every tick when attached to a player. Used to apply particle effects. - * Is only called on the client side. - * - * @param source The entity we are currently attached to. - */ - default void render(Entity source) { - - } + boolean update(ICaster caster); /** * Called every tick when attached to a gem. * - * @param source The entity we are attached to. - * @param w The world - * @param x Entity position x - * @param y Entity position y - * @param z Entity position z - * @param level Current spell level + * @param source The entity we are currently attached to. + * @param level Current active spell level */ - boolean updateAt(ICaster source, World w, double x, double y, double z, int level); + boolean update(ICaster source, int level); + + /** + * Called every tick when attached to a player. Used to apply particle effects. + * Is only called on the client side. + * + * @param source The entity we are currently attached to. + */ + default void render(ICaster source) { + + } /** * Called every tick when attached to an entity to produce particle effects. * Is only called on the client side. * * @param source The entity we are attached to. - * @param w The world - * @param x Entity position x - * @param y Entity position y - * @param z Entity position z * @param level Current spell level */ - default void renderAt(ICaster source, World w, double x, double y, double z, int level) { + default void render(ICaster source, int level) { } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java index 2eb6b473..68a2a96d 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java @@ -1,5 +1,8 @@ package com.minelittlepony.unicopia.spell; +import java.util.Random; + +import com.minelittlepony.unicopia.Predicates; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.client.particle.Particles; @@ -15,8 +18,8 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; public class SpellShield extends AbstractSpell { @@ -26,12 +29,18 @@ public class SpellShield extends AbstractSpell { } public SpellShield(int type) { - setStrength(type); + setCurrentLevel(type); } - public void setStrength(int level) { - strength = level; - } + @Override + public int getCurrentLevel() { + return strength; + } + + @Override + public void setCurrentLevel(int level) { + strength = level; + } @Override public String getName() { @@ -44,21 +53,28 @@ public class SpellShield extends AbstractSpell { } @Override - public void render(Entity source) { - spawnParticles(source.getEntityWorld(), source.posX, source.posY, source.posZ, 4 + (strength * 2)); + public void render(ICaster source) { + spawnParticles(source, 4 + (strength * 2)); } - public void renderAt(ICaster source, World w, double x, double y, double z, int level) { - if (w.rand.nextInt(4 + level * 4) == 0) { - spawnParticles(w, x, y, z, 4 + (level * 2)); + @Override + public void render(ICaster source, int level) { + if (source.getWorld().rand.nextInt(4 + level * 4) == 0) { + spawnParticles(source, 4 + (level * 2)); } } - protected void spawnParticles(World w, double x, double y, double z, int strength) { + protected void spawnParticles(ICaster source, int strength) { IShape sphere = new Sphere(true, strength); + Random rand = source.getWorld().rand; + + int x = source.getOrigin().getX(); + int y = source.getOrigin().getY(); + int z = source.getOrigin().getZ(); + for (int i = 0; i < strength * 6; i++) { - Vec3d pos = sphere.computePoint(w.rand); + Vec3d pos = sphere.computePoint(rand); Particles.instance().spawnParticle(Unicopia.MAGIC_PARTICLE, false, pos.x + x, pos.y + y, pos.z + z, 0, 0, 0); @@ -66,12 +82,12 @@ public class SpellShield extends AbstractSpell { } @Override - public boolean update(Entity source) { - applyEntities(null, source, source.getEntityWorld(), source.posX, source.posY, source.posZ, strength); + public boolean update(ICaster source) { + update(source, strength); - if (source.getEntityWorld().getWorldTime() % 50 == 0) { + if (source.getEntity().getEntityWorld().getWorldTime() % 50 == 0) { double radius = 4 + (strength * 2); - if (!IPower.takeFromPlayer((EntityPlayer)source, radius/4)) { + if (!IPower.takeFromPlayer((EntityPlayer)source.getOwner(), radius/4)) { setDead(); } } @@ -80,49 +96,52 @@ public class SpellShield extends AbstractSpell { } @Override - public boolean updateAt(ICaster source, World w, double x, double y, double z, int level) { - return applyEntities(source, source.getOwner(), w, x, y, z, level); - } - - private boolean applyEntities(ICaster source, Entity owner, World w, double x, double y, double z, int level) { + public boolean update(ICaster source, int level) { double radius = 4 + (level * 2); - AxisAlignedBB bb = new AxisAlignedBB(x - radius, y - radius, z - radius, x + radius, y + radius, z + radius); + Entity owner = source.getOwner(); + BlockPos pos = source.getOrigin(); - for (Entity i : w.getEntitiesWithinAABBExcludingEntity(source == null ? null : source.getEntity(), bb)) { - if ((!i.equals(owner) - || (owner instanceof EntityPlayer - && !PlayerSpeciesList.instance().getPlayer((EntityPlayer)owner).getPlayerSpecies().canCast()))) { + int x = pos.getX(), y = pos.getY(), z = pos.getZ(); - double dist = i.getDistance(x, y, z); - double dist2 = i.getDistance(x, y - i.getEyeHeight(), z); + BlockPos begin = pos.add(-radius, -radius, -radius); + BlockPos end = pos.add(radius, radius, radius); - boolean projectile = ProjectileUtil.isProjectile(i); + AxisAlignedBB bb = new AxisAlignedBB(begin, end); - if (dist <= radius || dist2 <= radius) { - if (projectile) { - if (!ProjectileUtil.isProjectileThrownBy(i, owner)) { - if (dist < radius/2) { - i.playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1f, 1); - i.setDead(); - } else { - ricochet(i, x, y, z); - } - } - } else if (i instanceof EntityLivingBase) { - double force = dist; - if (i instanceof EntityPlayer) { - force = calculateForce((EntityPlayer)i); - } + boolean ownerIsValid = Predicates.MAGI.test(owner); - i.addVelocity( - -(x - i.posX) / force, - -(y - i.posY) / force + (dist < 1 ? dist : 0), - -(z - i.posZ) / force); - } - } - } + for (Entity i : source.getWorld().getEntitiesInAABBexcluding(source.getEntity(), bb, entity -> !(ownerIsValid && entity.equals(owner)))) { + double dist = i.getDistance(x, y, z); + double dist2 = i.getDistance(x, y - i.getEyeHeight(), z); + + if (dist > radius && dist2 > radius) { + continue; + } + + if (ProjectileUtil.isProjectile(i)) { + if (!ProjectileUtil.isProjectileThrownBy(i, owner)) { + if (dist < radius/2) { + i.playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1F, 1); + i.setDead(); + } else { + ricochet(i, pos); + } + } + } else if (i instanceof EntityLivingBase) { + double force = Math.min(0.25F, dist); + + if (i instanceof EntityPlayer) { + force = calculateForce((EntityPlayer)i); + } + + i.addVelocity( + -(x - i.posX) / force, + -(y - i.posY) / force + (dist < 1 ? dist : 0), + -(z - i.posZ) / force); + } } + return true; } @@ -142,11 +161,11 @@ public class SpellShield extends AbstractSpell { return force; } - private void ricochet(Entity projectile, double x, double y, double z) { + private void ricochet(Entity projectile, BlockPos pos) { Vec3d position = new Vec3d(projectile.posX, projectile.posY, projectile.posZ); Vec3d motion = new Vec3d(projectile.motionX, projectile.motionY, projectile.motionZ); - Vec3d normal = position.subtract(x, y, z).normalize(); + Vec3d normal = position.subtract(pos.getX(), pos.getY(), pos.getZ()).normalize(); Vec3d approach = motion.subtract(normal); if (approach.length() >= motion.length()) { @@ -154,10 +173,12 @@ public class SpellShield extends AbstractSpell { } } + @Override public void writeToNBT(NBTTagCompound compound) { compound.setInteger("spell_strength", strength); } + @Override public void readFromNBT(NBTTagCompound compound) { strength = compound.getInteger("spell_strength"); }