From 55b050a992e572b79256b60a0a31d96d8c492fc6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 26 Sep 2018 17:53:12 +0200 Subject: [PATCH] Gems slowly lose their power over time; added a gem to transfer power over long distances --- .../unicopia/entity/EntitySpell.java | 37 ++++- .../unicopia/model/ModelGem.java | 46 +++++- .../unicopia/network/EffectSync.java | 2 +- .../unicopia/player/PlayerCapabilities.java | 13 +- .../unicopia/power/PowerMagic.java | 26 +--- .../unicopia/render/RenderGem.java | 9 ++ .../unicopia/spell/ICaster.java | 2 +- .../unicopia/spell/IMagicEffect.java | 12 +- .../unicopia/spell/SpellCharge.java | 141 ++++++++++++++++++ .../unicopia/spell/SpellRegistry.java | 1 + .../unicopia/spell/SpellShield.java | 20 +-- .../com/minelittlepony/util/shape/Line.java | 94 ++++++++++++ .../resources/assets/unicopia/lang/en_US.lang | 2 + 13 files changed, 352 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java create mode 100644 src/main/java/com/minelittlepony/util/shape/Line.java diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java index 5a10c362..714a23a8 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java @@ -7,7 +7,6 @@ import com.minelittlepony.unicopia.UItems; 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; @@ -31,7 +30,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, ILevelled { +public class EntitySpell extends EntityLiving implements IMagicals, ICaster { private EntityLivingBase owner = null; @@ -57,14 +56,20 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster 0) { + distance /= getCurrentLevel(); + } return super.isInRangeToRenderDist(distance); } + @Override public void setEffect(IMagicEffect effect) { effectDelegate.set(effect); } + @Override public IMagicEffect getEffect() { return effectDelegate.get(); } @@ -162,6 +167,19 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster 0 && !world.isRemote && world.rand.nextInt(200) == 0) { + addLevels(-1); + if (getCurrentLevel() <= 0) { + setDead(); + } + } + + if (overLevelCap()) { + if (world.rand.nextInt(10) == 0) { + spawnExplosionParticle(); + } + } } @Override @@ -175,6 +193,7 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster 10 || overLevelCap()) { + if (overLevelCap() || (rand.nextFloat() * getCurrentLevel()) > 10) { world.createExplosion(this, posX, posY, posZ, getCurrentLevel()/2, true); setDead(); return false; @@ -257,7 +278,7 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster 0; i--) { + GlStateManager.pushMatrix(); + GlStateManager.rotate(floatOffset / i, 0, 1, 0); + GlStateManager.translate(0.6F, 0, 0); + renderOverlay(0.6F, scale); + GlStateManager.popMatrix(); + } setLightingConditionsBrightness(entity.getBrightnessForRender()); @@ -112,6 +145,13 @@ public class ModelGem extends ModelBase { GlStateManager.popMatrix(); } + protected void renderOverlay(float grow, float scale) { + + + body.render(scale); + + } + private void setLightingConditionsBrightness(int brightness) { int texX = brightness % 0x10000; int texY = brightness / 0x10000; diff --git a/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java b/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java index e0cb5138..94e97db8 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java +++ b/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java @@ -33,7 +33,7 @@ public class EffectSync { String id = comp.getString("effect_id"); if (effect == null || id != effect.getName()) { effect = SpellRegistry.instance().createEffectFromNBT(comp); - } else { + } else if (owned.getEntity().world.isRemote) { effect.readFromNBT(comp); } } diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java index e07a439a..9e2e1d6e 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerCapabilities.java @@ -144,10 +144,10 @@ class PlayerCapabilities implements IPlayer, ICaster { setEffect(null); } else { if (entity.getEntityWorld().isRemote) { // && entity.getEntityWorld().getWorldTime() % 10 == 0 - getEffect().render(this); + getEffect().renderOnPerson(this); } - if (!getEffect().update(this)) { + if (!getEffect().updateOnPerson(this)) { setEffect(null); } } @@ -249,4 +249,13 @@ class PlayerCapabilities implements IPlayer, ICaster { public EntityPlayer getOwner() { return entity; } + + @Override + public int getCurrentLevel() { + return 0; + } + + @Override + public void setCurrentLevel(int level) { + } } diff --git a/src/main/java/com/minelittlepony/unicopia/power/PowerMagic.java b/src/main/java/com/minelittlepony/unicopia/power/PowerMagic.java index b08571f9..dae0427b 100644 --- a/src/main/java/com/minelittlepony/unicopia/power/PowerMagic.java +++ b/src/main/java/com/minelittlepony/unicopia/power/PowerMagic.java @@ -2,16 +2,16 @@ package com.minelittlepony.unicopia.power; import org.lwjgl.input.Keyboard; -import com.google.gson.annotations.Expose; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.player.IPlayer; import com.minelittlepony.unicopia.player.PlayerSpeciesList; +import com.minelittlepony.unicopia.power.data.Hit; import com.minelittlepony.unicopia.spell.SpellShield; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.world.World; -public class PowerMagic implements IPower { +public class PowerMagic implements IPower { @Override public String getKeyName() { @@ -39,23 +39,23 @@ public class PowerMagic implements IPower { } @Override - public Magic tryActivate(EntityPlayer player, World w) { - return new Magic(0); + public Hit tryActivate(EntityPlayer player, World w) { + return new Hit(); } @Override - public Class getPackageType() { - return Magic.class; + public Class getPackageType() { + return Hit.class; } @Override - public void apply(EntityPlayer player, Magic data) { + public void apply(EntityPlayer player, Hit data) { IPlayer prop = PlayerSpeciesList.instance().getPlayer(player); if (prop.getEffect() instanceof SpellShield) { prop.setEffect(null); } else { - prop.setEffect(new SpellShield(data.type)); + prop.setEffect(new SpellShield()); } } @@ -68,14 +68,4 @@ public class PowerMagic implements IPower { public void postApply(IPlayer player) { } - - class Magic implements IData { - - @Expose - public int type; - - public Magic(int strength) { - type = strength; - } - } } diff --git a/src/main/java/com/minelittlepony/unicopia/render/RenderGem.java b/src/main/java/com/minelittlepony/unicopia/render/RenderGem.java index 8ac70871..bee320ce 100644 --- a/src/main/java/com/minelittlepony/unicopia/render/RenderGem.java +++ b/src/main/java/com/minelittlepony/unicopia/render/RenderGem.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.render; import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.model.ModelGem; +import net.minecraft.client.renderer.culling.ICamera; import net.minecraft.client.renderer.entity.RenderLiving; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.util.ResourceLocation; @@ -15,14 +16,22 @@ public class RenderGem extends RenderLiving { super(rendermanagerIn, new ModelGem(), 0); } + @Override protected ResourceLocation getEntityTexture(EntitySpell entity) { return gem; } + @Override + public boolean shouldRender(EntitySpell livingEntity, ICamera camera, double camX, double camY, double camZ) { + return true; + } + + @Override protected float getDeathMaxRotation(EntitySpell entity) { return 0; } + @Override protected boolean canRenderName(EntitySpell targetEntity) { return super.canRenderName(targetEntity) && (targetEntity.getAlwaysRenderNameTagForRender() || targetEntity.hasCustomName() && targetEntity == renderManager.pointedEntity); diff --git a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java index 36e0be5a..49fabe1a 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java @@ -7,7 +7,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public interface ICaster extends IOwned { +public interface ICaster extends IOwned, ILevelled { void setEffect(IMagicEffect effect); IMagicEffect getEffect(); diff --git a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java index d261fb4e..fb5a9e94 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java @@ -25,7 +25,9 @@ public interface IMagicEffect extends InbtSerialisable, ILevelled { * @param source The entity we are currently attached to. * @return true to keep alive */ - boolean update(ICaster caster); + default boolean updateOnPerson(ICaster caster) { + return update(caster, getCurrentLevel()); + } /** * Called every tick when attached to a gem. @@ -41,8 +43,8 @@ public interface IMagicEffect extends InbtSerialisable, ILevelled { * * @param source The entity we are currently attached to. */ - default void render(ICaster source) { - + default void renderOnPerson(ICaster source) { + render(source, getCurrentLevel()); } /** @@ -52,9 +54,7 @@ public interface IMagicEffect extends InbtSerialisable, ILevelled { * @param source The entity we are attached to. * @param level Current spell level */ - default void render(ICaster source, int level) { - - } + void render(ICaster source, int level); /** * Return true to allow the gem update and move. diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java new file mode 100644 index 00000000..d2cb2ad6 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java @@ -0,0 +1,141 @@ +package com.minelittlepony.unicopia.spell; + +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.stream.Collectors; + +import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.client.particle.Particles; +import com.minelittlepony.unicopia.entity.EntitySpell; +import com.minelittlepony.util.shape.IShape; +import com.minelittlepony.util.shape.Line; + +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class SpellCharge extends AbstractSpell { + + private int desiredLevel = 0; + + boolean searching = true; + + private UUID targettedEntityId; + private EntitySpell targettedEntity; + + private static final AxisAlignedBB searchArea = new AxisAlignedBB(-15, -15, -15, 15, 15, 15); + + @Override + public String getName() { + return "charge"; + } + + @Override + public void render(ICaster source, int level) { + if (source.getWorld().rand.nextInt(4 + level * 4) == 0) { + EntitySpell target = getTarget(source); + + if (target != null) { + Vec3d start = source.getEntity().getPositionVector(); + Vec3d end = target.getPositionVector(); + + IShape line = new Line(start, end); + + Random rand = source.getWorld().rand; + + for (int i = 0; i < line.getVolumeOfSpawnableSpace(); i++) { + Vec3d pos = line.computePoint(rand); + Particles.instance().spawnParticle(Unicopia.MAGIC_PARTICLE, false, + pos.x + start.x, pos.y + start.y, pos.z + start.z, + 0, 0, 0); + } + } + + } + } + + protected boolean canTargetEntity(Entity e) { + return e instanceof EntitySpell && ((EntitySpell)e).hasEffect(); + } + + protected void setTarget(EntitySpell e) { + searching = false; + targettedEntity = e; + targettedEntityId = e.getUniqueID(); + } + + protected EntitySpell getTarget(ICaster source) { + if (targettedEntity == null && targettedEntityId != null) { + source.getWorld().getEntities(EntitySpell.class, e -> e.getUniqueID().equals(targettedEntityId)).stream().findFirst().ifPresent(this::setTarget); + } + + if (targettedEntity != null && targettedEntity.isDead) { + targettedEntity = null; + targettedEntityId = null; + searching = true; + } + + return targettedEntity; + } + + @Override + public boolean update(ICaster source, int level) { + + if (searching) { + BlockPos origin = source.getOrigin(); + + List list = source.getWorld().getEntitiesInAABBexcluding(source.getEntity(), + searchArea.offset(origin), this::canTargetEntity).stream().sorted((a, b) -> { + return (int)(a.getDistanceSq(origin) - b.getDistanceSq(origin)); + }).collect(Collectors.toList()); + + if (list.size() > 0) { + setTarget((EntitySpell)list.get(0)); + } + } else { + EntitySpell target = getTarget(source); + + if (target != null && !target.overLevelCap() && level > 0) { + source.addLevels(-1); + target.addLevels(1); + } + } + + return !isDead; + } + + @Override + public int getMaxLevel() { + return 2; + } + + @Override + public int getCurrentLevel() { + return desiredLevel; + } + + @Override + public void setCurrentLevel(int level) { + desiredLevel = level; + } + + @Override + public void writeToNBT(NBTTagCompound compound) { + if (targettedEntityId != null) { + compound.setUniqueId("target", targettedEntityId); + } + compound.setInteger("level", desiredLevel); + } + + @Override + public void readFromNBT(NBTTagCompound compound) { + if (compound.hasKey("target")) { + targettedEntityId = compound.getUniqueId("target"); + } + + desiredLevel = compound.getInteger("level"); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java index 57ab22ce..1ea4050d 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java @@ -24,6 +24,7 @@ public class SpellRegistry { private SpellRegistry() { registerSpell("shield", 0xffff00, SpellShield::new); + registerSpell("charge", 0x0000ff, SpellCharge::new); } public IMagicEffect getSpellFromName(String name) { diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java index 68a2a96d..95b3e989 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java @@ -25,13 +25,6 @@ public class SpellShield extends AbstractSpell { private int strength = 0; - public SpellShield() { - } - - public SpellShield(int type) { - setCurrentLevel(type); - } - @Override public int getCurrentLevel() { return strength; @@ -49,19 +42,12 @@ public class SpellShield extends AbstractSpell { @Override public int getMaxLevel() { - return -1; - } - - @Override - public void render(ICaster source) { - spawnParticles(source, 4 + (strength * 2)); + return 17; } @Override public void render(ICaster source, int level) { - if (source.getWorld().rand.nextInt(4 + level * 4) == 0) { - spawnParticles(source, 4 + (level * 2)); - } + spawnParticles(source, 4 + (level * 2)); } protected void spawnParticles(ICaster source, int strength) { @@ -82,7 +68,7 @@ public class SpellShield extends AbstractSpell { } @Override - public boolean update(ICaster source) { + public boolean updateOnPerson(ICaster source) { update(source, strength); if (source.getEntity().getEntityWorld().getWorldTime() % 50 == 0) { diff --git a/src/main/java/com/minelittlepony/util/shape/Line.java b/src/main/java/com/minelittlepony/util/shape/Line.java new file mode 100644 index 00000000..dee56f42 --- /dev/null +++ b/src/main/java/com/minelittlepony/util/shape/Line.java @@ -0,0 +1,94 @@ +package com.minelittlepony.util.shape; + +import java.util.Random; + +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +/** + * A lonely Line. The simplest form of shape. + * + */ +public class Line implements IShape { + + double len; + + double dX; + double dY; + double dZ; + + double sX; + double sY; + double sZ; + + private float yaw = 0; + private float pitch = 0; + + /** + * Creates a line with a given length, starting point, and gradient represented + * by another point. + * + * @param length Length of this line + * @param startX Offset X from origin + * @param startY Offset Y from origin + * @param startZ Offset Z from origin + * @param deltaX Change in X + * @param deltaY Change in Y + * @param deltaZ Change in Z + */ + public Line(double length, double startX, double startY, double startZ, double deltaX, double deltaY, double deltaZ) { + len = length; + dX = deltaX; + dY = deltaY; + dZ = deltaZ; + sX = startX; + sY = startY; + sZ = startZ; + } + + public Line(Vec3d start, Vec3d end) { + Vec3d lenV = end.subtract(start); + + len = lenV.length(); + + sX = start.x; + sY = start.y; + sZ = start.z; + + dX = lenV.x / len; + dY = lenV.y / len; + dZ = lenV.z / len; + } + + public double getVolumeOfSpawnableSpace() { + return len; + } + + public double getXOffset() { + return sX; + } + + public double getYOffset() { + return sY; + } + + public double getZOffset() { + return sZ; + } + + public Vec3d computePoint(Random rand) { + double distance = MathHelper.nextDouble(rand, 0, len); + return (new Vec3d(distance * dX, distance * dY, distance * dZ)).rotateYaw(yaw).rotatePitch(pitch); + } + + public Line setRotation(float u, float v) { + yaw = u; + pitch = v; + return this; + } + + public boolean isPointInside(Vec3d point) { + point = point.rotateYaw(-yaw).rotatePitch(-pitch); + return point.x/dX == point.y/dY && point.x/dX == point.z/dZ; + } +} diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index 3a22d325..fb2dfb8f 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -21,6 +21,8 @@ item.gem.name=Gem item.corrupted_gem.name=Fractured Gem item.gem.shield.name=Gem of Repulsion item.corrupted_gem.shield.name=Corrupt Gem of Repulsion +item.gem.charge.name=Channeling Gem +item.corrupted_gem.charge.name=Gem of Draining item.gem.fire.name=Gem of Flame item.corrupted_gem.fire.name=Corrupt Gem of Burning item.gem.inferno.name=Gem of Inferno