From cfc78f2f3268a87e339f2d884a8b99eab60b315e Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 5 Feb 2019 11:24:48 +0200 Subject: [PATCH] Added Gem of Assistance and Gem of inferno --- .../entity/ai/EntityAIFollowCaster.java | 48 ++++++++ .../forgebullshit/RegistryLockSpinner.java | 2 +- .../unicopia/spell/SpellDrake.java | 104 ++++++++++++++++ .../unicopia/spell/SpellFire.java | 10 +- .../unicopia/spell/SpellInferno.java | 113 ++++++++++++++++++ .../unicopia/spell/SpellRegistry.java | 2 + .../resources/assets/unicopia/lang/en_US.lang | 9 ++ 7 files changed, 282 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/ai/EntityAIFollowCaster.java create mode 100644 src/main/java/com/minelittlepony/unicopia/spell/SpellDrake.java create mode 100644 src/main/java/com/minelittlepony/unicopia/spell/SpellInferno.java diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ai/EntityAIFollowCaster.java b/src/main/java/com/minelittlepony/unicopia/entity/ai/EntityAIFollowCaster.java new file mode 100644 index 00000000..eacd41da --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/ai/EntityAIFollowCaster.java @@ -0,0 +1,48 @@ +package com.minelittlepony.unicopia.entity.ai; + +import java.lang.reflect.Field; + +import com.google.common.base.Predicate; + +import com.minelittlepony.unicopia.forgebullshit.RegistryLockSpinner; +import com.minelittlepony.unicopia.spell.ICaster; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIFollow; + +public class EntityAIFollowCaster extends EntityAIFollow { + + protected final ICaster entity; + + private static Field __followPredicate; + + static { + try { + Field f = EntityAIFollow.class.getDeclaredFields()[1]; + f.setAccessible(true); + __followPredicate = RegistryLockSpinner.makeNonFinal(f); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + __followPredicate = null; + } + } + + public EntityAIFollowCaster(ICaster caster, double walkSpeed, float maxDistance, float area) { + super((EntityLiving)caster.getEntity(), walkSpeed, maxDistance, area); + + entity = caster; + + if (__followPredicate != null) { + try { + __followPredicate.set(this, (Predicate)(e -> { + Entity owner = caster.getOwner(); + return e != null && (e == owner || (owner != null && owner.getUniqueID().equals(e.getUniqueID()))); + })); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/forgebullshit/RegistryLockSpinner.java b/src/main/java/com/minelittlepony/unicopia/forgebullshit/RegistryLockSpinner.java index d811f0c4..48e9c6a6 100644 --- a/src/main/java/com/minelittlepony/unicopia/forgebullshit/RegistryLockSpinner.java +++ b/src/main/java/com/minelittlepony/unicopia/forgebullshit/RegistryLockSpinner.java @@ -71,7 +71,7 @@ public final class RegistryLockSpinner { } @FUF(reason = "Not exactly forge's fault, but it was would be nice of them to not leave these as final") - private static Field makeNonFinal(Field f) throws IllegalArgumentException, IllegalAccessException { + public static Field makeNonFinal(Field f) throws IllegalArgumentException, IllegalAccessException { initModifiersField(); if (Modifier.isFinal(f.getModifiers()) && modifieres != null) { modifieres.setInt(f, f.getModifiers() & ~Modifier.FINAL); diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellDrake.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellDrake.java new file mode 100644 index 00000000..a27045de --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellDrake.java @@ -0,0 +1,104 @@ +package com.minelittlepony.unicopia.spell; + +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.entity.EntitySpell; +import com.minelittlepony.unicopia.entity.ai.EntityAIFollowCaster; + +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.pathfinding.PathNavigateGround; +import net.minecraft.util.math.AxisAlignedBB; + +public class SpellDrake extends AbstractSpell { + + private static final AxisAlignedBB EFFECT_BOUNDS = new AxisAlignedBB(-2, -2, -2, 2, 2, 2); + + @Nullable + private IMagicEffect piggyBackSpell; + + private boolean firstUpdate = true; + + @Override + public String getName() { + return "drake"; + } + + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.NEUTRAL; + } + + @Override + public int getTint() { + return 0xFAEBD7; + } + + @Override + public void setDead() { + super.setDead(); + + if (piggyBackSpell != null) { + piggyBackSpell.setDead(); + } + } + + @Override + public boolean allowAI() { + return true; + } + + public boolean getDead() { + return super.getDead() || (piggyBackSpell != null && piggyBackSpell.getDead()); + } + + @Override + public boolean update(ICaster source, int level) { + + if (firstUpdate) { + firstUpdate = false; + + if (source.getOwner() instanceof EntitySpell) { + EntitySpell living = (EntitySpell)source.getOwner(); + + ((PathNavigateGround)living.getNavigator()).setCanSwim(false); + living.tasks.addTask(1, new EntityAISwimming(living)); + living.tasks.addTask(2, new EntityAIFollowCaster(source, 1, 4, 6)); + } + } + + if (piggyBackSpell == null) { + AxisAlignedBB bb = EFFECT_BOUNDS.offset(source.getOriginVector()); + + source.getWorld().getEntitiesInAABBexcluding(source.getEntity(), bb, e -> e instanceof EntitySpell).stream() + .map(i -> (EntitySpell)i) + .filter(i -> i.getEffect() != null && !(i.getEffect() instanceof SpellDrake)) + .findFirst().ifPresent(i -> { + piggyBackSpell = i.getEffect(); + i.setEffect(null); + }); + } + + return piggyBackSpell != null && piggyBackSpell.update(source, level); + } + + @Override + public void render(ICaster source, int level) { + if (piggyBackSpell != null) { + piggyBackSpell.render(source, level); + } + } + + public void writeToNBT(NBTTagCompound compound) { + if (piggyBackSpell != null) { + compound.setTag("effect", SpellRegistry.instance().serializeEffectToNBT(piggyBackSpell)); + } + } + + @Override + public void readFromNBT(NBTTagCompound compound) { + if (compound.hasKey("effect")) { + piggyBackSpell = SpellRegistry.instance().createEffectFromNBT(compound.getCompoundTag("effect")); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java index a8656751..dc730fc1 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java @@ -100,11 +100,11 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl boolean result = false; if (player == null || player.isSneaking()) { - result = applyBlocks(player, world, pos); + result = applyBlocks(world, pos); } else { for (BlockPos i : PosHelper.getAllInRegionMutable(pos, effect_range)) { - result |= applyBlocks(player, world, i); + result |= applyBlocks(world, i); } } @@ -127,7 +127,7 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl boolean result = false; for (BlockPos i : PosHelper.getAllInRegionMutable(pos, effect_range)) { - result |= applyBlocks(null, source.getWorld(), i); + result |= applyBlocks(source.getWorld(), i); } if (!result) { @@ -137,7 +137,7 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl return result ? SpellCastResult.NONE : SpellCastResult.DEFAULT; } - protected boolean applyBlocks(EntityPlayer owner, World world, BlockPos pos) { + protected boolean applyBlocks(World world, BlockPos pos) { IBlockState state = world.getBlockState(pos); Block id = state.getBlock(); @@ -191,7 +191,7 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl return false; } - protected boolean applyEntities(EntityPlayer owner, World world, BlockPos pos) { + protected boolean applyEntities(Entity owner, World world, BlockPos pos) { return VecHelper .findAllEntitiesInRange(owner, world, pos, 3) .filter(i -> applyEntitySingle(owner, world, i)) diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellInferno.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellInferno.java new file mode 100644 index 00000000..bcbcf590 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellInferno.java @@ -0,0 +1,113 @@ +package com.minelittlepony.unicopia.spell; + +import com.minelittlepony.util.MagicalDamageSource; +import com.minelittlepony.util.blockstate.IStateMapping; +import com.minelittlepony.util.blockstate.StateMapList; +import com.minelittlepony.util.shape.IShape; +import com.minelittlepony.util.shape.Sphere; + +import net.minecraft.block.BlockBush; +import net.minecraft.block.BlockOre; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class SpellInferno extends SpellFire { + + public final StateMapList hellFireAffected = new StateMapList(); + + public SpellInferno() { + hellFireAffected.add(IStateMapping.build( + s -> s.getBlock() == Blocks.GRASS || s.getBlock() == Blocks.DIRT || s.getBlock() == Blocks.STONE, + s -> Blocks.NETHERRACK.getDefaultState())); + + hellFireAffected.replaceBlock(Blocks.SAND, Blocks.SOUL_SAND); + hellFireAffected.replaceBlock(Blocks.GRAVEL, Blocks.SOUL_SAND); + + hellFireAffected.add(IStateMapping.build( + s -> s.getMaterial() == Material.WATER, + s -> Blocks.OBSIDIAN.getDefaultState())); + + hellFireAffected.add(IStateMapping.build( + s -> s.getBlock() instanceof BlockBush, + s -> Blocks.NETHER_WART.getDefaultState())); + + hellFireAffected.add(IStateMapping.build( + s -> (s.getBlock() != Blocks.QUARTZ_ORE) && (s.getBlock() instanceof BlockOre), + s -> Blocks.QUARTZ_ORE.getDefaultState())); + } + + @Override + public String getName() { + return "inferno"; + } + + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.BAD; + } + + @Override + public int getTint() { + return 0xFF8C00; + } + + @Override + public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) { + return SpellCastResult.PLACE; + } + + @Override + public boolean update(ICaster source, int level) { + World w = source.getWorld(); + + if (!w.isRemote) { + int radius = 4 + (level * 4); + IShape shape = new Sphere(false, radius); + + Vec3d origin = source.getOriginVector(); + + for (int i = 0; i < radius; i++) { + BlockPos pos = new BlockPos(shape.computePoint(w.rand).add(origin)); + + IBlockState state = w.getBlockState(pos); + IBlockState newState = hellFireAffected.getConverted(state); + + if (!state.equals(newState)) { + w.setBlockState(pos, newState, 3); + + playEffect(w, pos); + } + } + + shape = new Sphere(false, radius - 1); + for (int i = 0; i < radius * 2; i++) { + if (w.rand.nextInt(12) == 0) { + BlockPos pos = new BlockPos(shape.computePoint(w.rand).add(origin)); + + if (!applyBlocks(w, pos)) { + applyEntities(source.getOwner(), w, pos); + } + } + } + } + return false; + } + + @Override + protected DamageSource getDamageCause(Entity target, EntityLivingBase attacker) { + if (attacker != null && attacker.getUniqueID().equals(target.getUniqueID())) { + return MagicalDamageSource.causeMobDamage("fire.own", null); + } + return MagicalDamageSource.causeMobDamage("fire", attacker); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java index c067130a..8b5e8d2f 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java @@ -40,6 +40,8 @@ public class SpellRegistry { registerSpell(SpellDisguise::new); registerSpell(SpellNecromancy::new); registerSpell(SpellAwkward::new); + registerSpell(SpellInferno::new); + registerSpell(SpellDrake::new); } @Nullable diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index c54eb78f..5f25100e 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -51,6 +51,9 @@ spell.charge.tagline=Energy I spell.ice.name=Frost spell.ice.tagline=Ice I +spell.drake.name=Assistance +spell.drake.tagline=Helpfulness I + curse.shield.name=Repulsion curse.shield.tagline=Hostility I @@ -63,6 +66,12 @@ curse.vortex.tagline=Torture I curse.necromancy.name=Necromancy curse.necromancy.tagline=Resurrection I +curse.drake.name=Assistance +curse.drake.tagline=Unhelpfulness I + +curse.inferno.name=Inferno +curse.inferno.tagline=Fire II + item.spellbook.name=Spellbook item.bag_of_holding.name=Bag of Holding