From 1700ce927658338be514e08798c8ce4d5c4c5c2a Mon Sep 17 00:00:00 2001 From: Sollace Date: Fri, 15 Feb 2019 16:08:28 +0200 Subject: [PATCH] The light and dark gems will now interact with each other --- .../particle/client/ParticleSphere.java | 26 +-- .../spell/AbstractAttachableSpell.java | 106 ++++++++++++ .../unicopia/spell/CasterUtils.java | 10 ++ .../unicopia/spell/ICaster.java | 6 + .../unicopia/spell/SpellCharge.java | 83 ++------- .../unicopia/spell/SpellDarkness.java | 161 +++++++++++++++--- .../unicopia/spell/SpellShield.java | 8 +- .../unicopia/spell/SpellVortex.java | 2 +- 8 files changed, 294 insertions(+), 108 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/spell/AbstractAttachableSpell.java diff --git a/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleSphere.java b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleSphere.java index 6965cda5..111ca568 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleSphere.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleSphere.java @@ -18,21 +18,21 @@ public class ParticleSphere extends Particle implements IAttachableParticle { protected int tint; protected float alpha; - protected int radius; + protected float radius; private ICaster caster; private static final ModelSphere model = new ModelSphere(); public ParticleSphere(int id, World w, double x, double y, double z, double vX, double vY, double vZ, int... args) { - this(w, x, y, z, args[0], args[1], args[2]/255F); + this(w, x, y, z, args[0] / 1000F, args[1], args[2]/255F); this.motionX = vX; this.motionY = vY; this.motionZ = vZ; } - public ParticleSphere(World w, double x, double y, double z, int radius, int tint, float alpha) { + public ParticleSphere(World w, double x, double y, double z, float radius, int tint, float alpha) { super(w, x, y, z); this.radius = radius; @@ -69,9 +69,7 @@ public class ParticleSphere extends Particle implements IAttachableParticle { setPosition(e.posX, e.posY, e.posZ); } } else { - if (this.rand.nextInt(10000) == 0) { - this.radius--; - } + radius *= 0.9998281; } } @@ -82,17 +80,19 @@ public class ParticleSphere extends Particle implements IAttachableParticle { GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); - GlStateManager.depthMask(false); - GlStateManager.shadeModel(GL11.GL_SMOOTH); - GlStateManager.tryBlendFuncSeparate( - GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, - GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + if (alpha < 0) { + GlStateManager.depthMask(false); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.tryBlendFuncSeparate( + GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, + GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + } + Color.glColor(tint, alpha); model.setPosition(posX, posY, posZ); model.render(radius); - GlStateManager.color(1, 1, 1, 1); GL11.glPopAttrib(); @@ -101,7 +101,7 @@ public class ParticleSphere extends Particle implements IAttachableParticle { @Override public void setAttribute(int key, Object value) { if (key == 0) { - radius = (int)value; + radius = (float)value; } } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/AbstractAttachableSpell.java b/src/main/java/com/minelittlepony/unicopia/spell/AbstractAttachableSpell.java new file mode 100644 index 00000000..454c7afe --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/AbstractAttachableSpell.java @@ -0,0 +1,106 @@ +package com.minelittlepony.unicopia.spell; + +import java.util.UUID; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.entity.EntitySpell; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; + +public abstract class AbstractAttachableSpell extends AbstractSpell { + + boolean searching = true; + + @Nullable + private UUID targettedEntityId; + + @Nullable + private EntitySpell targettedEntity; + + protected void setTarget(@Nonnull EntitySpell e) { + searching = false; + targettedEntity = e; + targettedEntityId = e.getUniqueID(); + setDirty(true); + } + + public boolean hasTarget() { + if (targettedEntity != null && targettedEntity.isDead) { + targettedEntity = null; + targettedEntityId = null; + searching = true; + setDirty(true); + } + + return targettedEntity != null; + } + + @Nullable + 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; + setDirty(true); + } + + return targettedEntity; + } + + @Override + public boolean update(ICaster source) { + + if (searching) { + searchForTarget(source); + } else { + getTarget(source); + } + + return !getDead(); + } + + protected void searchForTarget(ICaster source) { + BlockPos origin = source.getOrigin(); + + source.getWorld().getEntitiesInAABBexcluding(source.getEntity(), getSearchArea(source), e -> { + return e instanceof EntitySpell && canTargetEntity((EntitySpell)e); + }).stream() + .sorted((a, b) -> (int)(a.getDistanceSq(origin) - b.getDistanceSq(origin))) + .findFirst() + .map(EntitySpell.class::cast) + .ifPresent(this::setTarget); + } + + protected abstract AxisAlignedBB getSearchArea(ICaster source); + + protected abstract boolean canTargetEntity(EntitySpell e); + + @Override + public void writeToNBT(NBTTagCompound compound) { + super.writeToNBT(compound); + + if (targettedEntityId != null) { + compound.setUniqueId("target", targettedEntityId); + } + } + + @Override + public void readFromNBT(NBTTagCompound compound) { + super.readFromNBT(compound); + + if (compound.hasKey("target")) { + targettedEntityId = compound.getUniqueId("target"); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java b/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java index 5e6ddb33..6060a004 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java @@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.Predicates; import com.minelittlepony.unicopia.player.PlayerSpeciesList; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -38,6 +39,15 @@ public class CasterUtils { .map(Optional::get); } + static Stream> findAllSpells(ICaster source) { + return source.getWorld().getEntities(EntityLivingBase.class, e -> { + return e instanceof ICaster || e instanceof EntityPlayer; + }).stream() + .map(CasterUtils::toCaster) + .filter(Optional::isPresent) + .map(Optional::get); + } + static Stream> findAllSpellsInRange(ICaster source, AxisAlignedBB bb) { return source.getWorld().getEntitiesInAABBexcluding(source.getEntity(), bb, e -> !e.isDead && (e instanceof ICaster || Predicates.MAGI.test(e)) diff --git a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java index 2977e374..adf1b6dd 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java @@ -84,6 +84,10 @@ public interface ICaster extends IOwned, ILevelle } } + default Stream> findAllSpells() { + return CasterUtils.findAllSpells(this); + } + default Stream> findAllSpellsInRange(double radius) { return CasterUtils.findAllSpellsInRange(this, radius); } @@ -95,4 +99,6 @@ public interface ICaster extends IOwned, ILevelle default Stream findAllEntitiesInRange(double radius) { return VecHelper.findAllEntitiesInRange(getEntity(), getWorld(), getOrigin(), radius); } + + } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java index 53aae2f1..d40663d8 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java @@ -1,27 +1,15 @@ package com.minelittlepony.unicopia.spell; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; - import com.minelittlepony.unicopia.UParticles; import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.particle.Particles; 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 { - - boolean searching = true; - - private UUID targettedEntityId; - private EntitySpell targettedEntity; +public class SpellCharge extends AbstractAttachableSpell { private static final AxisAlignedBB searchArea = new AxisAlignedBB(-15, -15, -15, 15, 15, 15); @@ -40,6 +28,16 @@ public class SpellCharge extends AbstractSpell { return 0x7272B7; } + @Override + protected boolean canTargetEntity(EntitySpell e) { + return e.hasEffect(); + } + + @Override + protected AxisAlignedBB getSearchArea(ICaster source) { + return searchArea.offset(source.getOriginVector()); + } + @Override public void render(ICaster source) { if (source.getWorld().rand.nextInt(4 + source.getCurrentLevel() * 4) == 0) { @@ -58,48 +56,11 @@ public class SpellCharge extends AbstractSpell { } } - 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) { + super.update(source); - if (searching) { - BlockPos origin = source.getOrigin(); - - List list = source.getWorld().getEntitiesInAABBexcluding(source.getEntity(), - searchArea.offset(origin), this::canTargetEntity).stream().sorted((a, b) -> - (int)(a.getDistanceSq(origin) - b.getDistanceSq(origin)) - ).collect(Collectors.toList()); - - if (list.size() > 0) { - setTarget((EntitySpell)list.get(0)); - } - } else { + if (!searching) { EntitySpell target = getTarget(source); if (target != null && !target.overLevelCap() && source.getCurrentLevel() > 0) { @@ -110,22 +71,4 @@ public class SpellCharge extends AbstractSpell { return !getDead(); } - - @Override - public void writeToNBT(NBTTagCompound compound) { - super.writeToNBT(compound); - - if (targettedEntityId != null) { - compound.setUniqueId("target", targettedEntityId); - } - } - - @Override - public void readFromNBT(NBTTagCompound compound) { - super.readFromNBT(compound); - - if (compound.hasKey("target")) { - targettedEntityId = compound.getUniqueId("target"); - } - } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellDarkness.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellDarkness.java index a5e08326..f4fc4344 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellDarkness.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellDarkness.java @@ -1,13 +1,19 @@ package com.minelittlepony.unicopia.spell; import java.util.Random; +import java.util.function.Consumer; import com.minelittlepony.unicopia.UParticles; import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.particle.Particles; import com.minelittlepony.util.MagicalDamageSource; +import com.minelittlepony.util.PosHelper; +import com.minelittlepony.util.shape.IShape; import com.minelittlepony.util.shape.Sphere; +import net.minecraft.block.IGrowable; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAIAvoidEntity; import net.minecraft.entity.player.EntityPlayer; @@ -16,10 +22,13 @@ import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; -public class SpellDarkness extends AbstractSpell.RangedAreaSpell { +public class SpellDarkness extends AbstractAttachableSpell { + + private static final AxisAlignedBB searchArea = new AxisAlignedBB(-5, -5, -5, 5, 5, 5); final SoundEvent[] scarySounds = new SoundEvent[] { SoundEvents.AMBIENT_CAVE, @@ -62,22 +71,71 @@ public class SpellDarkness extends AbstractSpell.RangedAreaSpell { @Override public boolean update(ICaster source) { + super.update(source); + + int soundChance = 15; + int radius = 7 + (source.getCurrentLevel() * 3); - if (source.getWorld().rand.nextInt(15) == 0) { - source.getWorld().playSound(null, source.getOrigin(), getScarySoundEffect(source.getWorld().rand), SoundCategory.AMBIENT, + if (hasTarget()) { + soundChance *= 10; + + source.getEntity().motionY -= 0.01; + + applyBlocks(source, radius); + applyEntities(source, radius, e -> applyLight(source, e)); + } else { + applyEntities(source, radius, e -> applyDark(source, e)); + } + + if (source.getWorld().rand.nextInt(soundChance) == 0) { + source.getWorld().playSound(null, source.getOrigin(), + getSoundEffect(source.getWorld().rand), SoundCategory.AMBIENT, 0.2F + source.getWorld().rand.nextFloat(), 0.3F); } - source.findAllEntitiesInRange(radius * 1.5F) - .filter(e -> e instanceof EntityLivingBase) - .map(EntityLivingBase.class::cast) - .forEach(e -> applyDarkness(source, e)); - return false; + + return !getDead(); } - protected void applyDarkness(ICaster source, EntityLivingBase entity) { - if (!CasterUtils.isHoldingEffect("light", entity)) { + private void applyBlocks(ICaster source, int radius) { + for (BlockPos pos : PosHelper.getAllInRegionMutable(source.getOrigin(), new Sphere(false, radius))) { + if (source.getWorld().rand.nextInt(500) == 0) { + IBlockState state = source.getWorld().getBlockState(pos); + + if (state.getBlock() instanceof IGrowable) { + IGrowable growable = (IGrowable)state.getBlock(); + + if (growable.canGrow(source.getWorld(), pos, state, source.getWorld().isRemote)) { + growable.grow(source.getWorld(), source.getWorld().rand, pos, state); + + return; + } + } + } + } + } + + private void applyEntities(ICaster source, int radius, Consumer consumer) { + source.findAllEntitiesInRange(radius * 1.5F) + .filter(e -> e instanceof EntityLivingBase) + .map(EntityLivingBase.class::cast) + .forEach(consumer);; + } + + private void applyLight(ICaster source, EntityLivingBase entity) { + if (entity.getHealth() < entity.getMaxHealth()) { + entity.heal(1); + } + } + + private void applyDark(ICaster source, EntityLivingBase entity) { + + if (isAreaOccupied(source, entity.getPositionVector())) { + return; + } + + if (!isLightholder(entity)) { entity.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 100, 3)); Vec3d origin = source.getOriginVector(); @@ -102,7 +160,12 @@ public class SpellDarkness extends AbstractSpell.RangedAreaSpell { } } - protected SoundEvent getScarySoundEffect(Random rand) { + public SoundEvent getSoundEffect(Random rand) { + + if (hasTarget()) { + return SoundEvents.BLOCK_NOTE_CHIME; + } + return scarySounds[rand.nextInt(scarySounds.length)]; } @@ -110,22 +173,80 @@ public class SpellDarkness extends AbstractSpell.RangedAreaSpell { public void render(ICaster source) { int radius = 7 + (source.getCurrentLevel() * 3); - source.spawnParticles(new Sphere(false, radius), radius * 6, pos -> { - if (!source.getWorld().isAirBlock(new BlockPos(pos).down())) { - int size = source.getWorld().rand.nextInt(4); + boolean tamed = hasTarget(); - if (size > 0) { - double vX = (source.getWorld().rand.nextFloat() - 0.5) * 2; - double vZ = (source.getWorld().rand.nextFloat() - 0.5) * 2; + int tint = tamed ? 0xFFFFFF : getTint(); - Particles.instance().spawnParticle(UParticles.SPHERE, false, pos, vX, 0, vZ, size, getTint(), 100); - } - } + if (tamed) { + radius /= 3; + } + + IShape shape = new Sphere(false, radius); + + source.spawnParticles(shape, radius * 6, pos -> { + spawnSphere(source, pos, tint, searching ? 4 : 2); }); + + source.findAllEntitiesInRange(radius * 1.5F).filter(this::isLightholder).forEach(e -> { + Vec3d pos = shape.computePoint(source.getWorld().rand).add(e.getPositionEyes(1)); + + spawnSphere(source, pos, 0xFFFFFF, 1); + }); + } + + public boolean isLightholder(Entity e) { + if (e instanceof EntitySpell) { + return true; + } + + return e instanceof EntityLivingBase && CasterUtils.isHoldingEffect("light", (EntityLivingBase)e); + } + + public boolean isAreaOccupied(ICaster source, Vec3d pos) { + if (source.getWorld().isAirBlock(new BlockPos(pos).down())) { + return source.findAllSpells().anyMatch(spell -> { + SpellShield effect = spell.getEffect(SpellShield.class, false); + + if (effect != null) { + return pos.distanceTo(spell.getOriginVector()) <= effect.getDrawDropOffRange(spell); + } + + return false; + }); + } + + return false; + } + + public void spawnSphere(ICaster source, Vec3d pos, int tint, int maxSize) { + if (isAreaOccupied(source, pos)) { + return; + } + + float size = source.getWorld().rand.nextFloat() * maxSize; + + float particleSpeed = hasTarget() ? 0.3F : 0.5F; + + if (size > 0) { + double vX = (source.getWorld().rand.nextFloat() - 0.5) * particleSpeed; + double vZ = (source.getWorld().rand.nextFloat() - 0.5) * particleSpeed; + + Particles.instance().spawnParticle(UParticles.SPHERE, false, pos, vX, 0, vZ, (int)(size * 1000), tint, 100); + } } @Override public SpellAffinity getAffinity() { return SpellAffinity.BAD; } + + @Override + protected AxisAlignedBB getSearchArea(ICaster source) { + return searchArea.offset(source.getOriginVector()); + } + + @Override + protected boolean canTargetEntity(EntitySpell e) { + return e.hasEffect() && "light".equals(e.getEffect().getName()); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java index 84be711a..46239a14 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java @@ -37,14 +37,14 @@ public class SpellShield extends AbstractSpell.RangedAreaSpell { @Override public void render(ICaster source) { - int radius = 4 + (source.getCurrentLevel() * 2); + float radius = 4 + (source.getCurrentLevel() * 2); - source.spawnParticles(new Sphere(true, radius), radius * 6, pos -> { + source.spawnParticles(new Sphere(true, radius), (int)(radius * 6), pos -> { Particles.instance().spawnParticle(UParticles.UNICORN_MAGIC, false, pos, 0, 0, 0); }); particlEffect - .ifMissing(source, () -> Particles.instance().spawnParticle(UParticles.SPHERE, true, source.getOriginVector(), 0, 0, 0, radius, getTint(), 30)) + .ifMissing(source, () -> Particles.instance().spawnParticle(UParticles.SPHERE, true, source.getOriginVector(), 0, 0, 0, 1, getTint(), 30)) .ifPresent(p -> p.setAttribute(0, radius)); } @@ -62,7 +62,7 @@ public class SpellShield extends AbstractSpell.RangedAreaSpell { return !getDead(); } - protected double getDrawDropOffRange(ICaster source) { + public double getDrawDropOffRange(ICaster source) { return 4 + (source.getCurrentLevel() * 2); } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java index d4fac4d5..ce7430d9 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java @@ -38,7 +38,7 @@ public class SpellVortex extends SpellShield { } @Override - protected double getDrawDropOffRange(ICaster caster) { + public double getDrawDropOffRange(ICaster caster) { return 10 + (caster.getCurrentLevel() * 2); }