diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java index 454b83f2..cf552a0c 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java @@ -153,8 +153,19 @@ public class EntityProjectile extends EntitySnowball implements IMagicals, ICast @Override public void onUpdate() { + + if (!world.isRemote) { + if (Math.abs(motionX) < 0.01 && Math.abs(motionZ) < 0.01 && Math.abs(motionY) < 0.01) { + setDead(); + } + } + super.onUpdate(); + if (ticksExisted % 1000 == 0) { + setNoGravity(false); + } + if (hasEffect()) { if (getEffect().getDead()) { setDead(); @@ -211,13 +222,13 @@ public class EntityProjectile extends EntitySnowball implements IMagicals, ICast Item item = getItem().getItem(); if (item instanceof ITossableItem) { - ((ITossableItem)item).onImpact(world, result.getBlockPos(), world.getBlockState(result.getBlockPos())); + ((ITossableItem)item).onImpact(this, result.getBlockPos(), world.getBlockState(result.getBlockPos())); } if (hasEffect()) { IMagicEffect effect = this.getEffect(); if (effect instanceof ITossable) { - ((ITossable)effect).onImpact(world, result.getBlockPos(), world.getBlockState(result.getBlockPos())); + ((ITossable)effect).onImpact(this, result.getBlockPos(), world.getBlockState(result.getBlockPos())); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/init/UItems.java b/src/main/java/com/minelittlepony/unicopia/init/UItems.java index 15e737f9..fbbceeea 100644 --- a/src/main/java/com/minelittlepony/unicopia/init/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/init/UItems.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.item.ItemCereal; import com.minelittlepony.unicopia.item.ItemCloud; import com.minelittlepony.unicopia.item.ItemCurse; import com.minelittlepony.unicopia.item.ItemFruitLeaves; +import com.minelittlepony.unicopia.item.ItemMagicStaff; import com.minelittlepony.unicopia.item.ItemMoss; import com.minelittlepony.unicopia.item.ItemOfHolding; import com.minelittlepony.unicopia.item.ItemRottenApple; @@ -22,6 +23,7 @@ import com.minelittlepony.unicopia.item.UItemDecoration; import com.minelittlepony.unicopia.item.UItemSlab; import com.minelittlepony.unicopia.item.URecord; import com.minelittlepony.unicopia.spell.SpellRegistry; +import com.minelittlepony.unicopia.spell.SpellScorch; import net.minecraft.block.BlockDoublePlant; import net.minecraft.block.BlockFlower; @@ -140,6 +142,7 @@ public class UItems { public static final ItemSpellbook spellbook = new ItemSpellbook(Unicopia.MODID, "spellbook"); public static final Item staff_meadow_brook = new ItemStaff(Unicopia.MODID, "staff_meadow_brook").setMaxDamage(2); + public static final Item staff_remembrance = new ItemMagicStaff(Unicopia.MODID, "staff_remembrance", new SpellScorch()); public static final ItemMoss moss = new ItemMoss(Unicopia.MODID, "moss"); @@ -243,7 +246,7 @@ public class UItems { cloud_farmland, mist_door, library_door, bakery_door, anvil, bag_of_holding, spell, curse, spellbook, mug, enchanted_torch, - staff_meadow_brook, alicorn_amulet, + staff_meadow_brook, staff_remembrance, alicorn_amulet, alfalfa_seeds, alfalfa_leaves, cereal, sugar_cereal, sugar_block, @@ -278,7 +281,7 @@ public class UItems { cloud_farmland, mist_door, library_door, bakery_door, anvil, bag_of_holding, spell, curse, spellbook, mug, enchanted_torch, - staff_meadow_brook, alicorn_amulet, + staff_meadow_brook, staff_remembrance, alicorn_amulet, alfalfa_seeds, alfalfa_leaves, cereal, sugar_cereal, sugar_block, diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemMagicStaff.java b/src/main/java/com/minelittlepony/unicopia/item/ItemMagicStaff.java new file mode 100644 index 00000000..8919f32e --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemMagicStaff.java @@ -0,0 +1,160 @@ +package com.minelittlepony.unicopia.item; + +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.Predicates; +import com.minelittlepony.unicopia.power.IPower; +import com.minelittlepony.unicopia.spell.CasterUtils; +import com.minelittlepony.unicopia.spell.IAligned; +import com.minelittlepony.unicopia.spell.ICaster; +import com.minelittlepony.unicopia.spell.ITossedEffect; +import com.minelittlepony.unicopia.spell.SpellAffinity; +import com.minelittlepony.unicopia.tossable.ITossableItem; +import com.minelittlepony.util.lang.ClientLocale; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ItemMagicStaff extends ItemStaff implements IAligned, ITossableItem { + + @Nonnull + private final ITossedEffect effect; + + public ItemMagicStaff(String domain, String name, @Nonnull ITossedEffect effect) { + super(domain, name); + + this.effect = effect; + setMaxDamage(500); + } + + @Override + public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { + SpellAffinity affinity = getAffinity(); + tooltip.add(affinity.getColourCode() + ClientLocale.format(affinity.getUnlocalizedName())); + } + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + if (Predicates.MAGI.test(player) && hand == EnumHand.MAIN_HAND) { + ItemStack itemstack = player.getHeldItem(hand); + + player.setActiveHand(hand); + + return new ActionResult(EnumActionResult.SUCCESS, itemstack); + } + + return super.onItemRightClick(world, player, hand); + } + + @Override + public void onPlayerStoppedUsing(ItemStack itemstack, World world, EntityLivingBase entity, int timeLeft) { + if (Predicates.MAGI.test(entity) && entity instanceof EntityPlayer) { + + int i = getMaxItemUseDuration(itemstack) - timeLeft; + + if (i > 10) { + if (canBeThrown(itemstack)) { + toss(world, itemstack, (EntityPlayer)entity); + } + } + } + } + + @Override + protected boolean castContainedEffect(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) { + if (attacker.isSneaking()) { + stack.damageItem(50, attacker); + + if (attacker instanceof EntityPlayer) { + IPower.takeFromPlayer((EntityPlayer)attacker, 4); + } + + onImpact( + CasterUtils.toCaster(target).orElseGet(() -> CasterUtils.near(target)), + target.getPosition(), + target.getEntityWorld().getBlockState(target.getPosition()) + ); + + return true; + } + + return false; + } + + public void onUpdate(ItemStack stack, World world, Entity entity, int itemSlot, boolean isSelected) { + + if (entity instanceof EntityLivingBase) { + EntityLivingBase living = (EntityLivingBase)entity; + + if (living.getActiveItemStack().getItem() == this) { + Vec3d eyes = entity.getPositionEyes(1); + + float i = getMaxItemUseDuration(stack) - living.getItemInUseCount(); + + world.spawnParticle(i > 150 ? EnumParticleTypes.SMOKE_LARGE : EnumParticleTypes.CLOUD, eyes.x, eyes.y, eyes.z, + (world.rand.nextGaussian() - 0.5) / 10, + (world.rand.nextGaussian() - 0.5) / 10, + (world.rand.nextGaussian() - 0.5) / 10 + ); + world.playSound(null, entity.getPosition(), SoundEvents.ENTITY_GUARDIAN_ATTACK, SoundCategory.PLAYERS, 1, i / 20); + + if (i > 200) { + living.resetActiveHand(); + living.attackEntityFrom(DamageSource.MAGIC, 1200); + onImpact( + CasterUtils.toCaster(entity).orElseGet(() -> CasterUtils.near(entity)), + entity.getPosition(), + entity.getEntityWorld().getBlockState(entity.getPosition()) + ); + } + } + } + + } + + public int getMaxItemUseDuration(ItemStack stack) { + return 72000; + } + + @Override + public boolean canBeThrown(ItemStack stack) { + return true; + } + + @Override + public void toss(World world, ItemStack stack, EntityPlayer player) { + CasterUtils.toCaster(player).ifPresent(effect::toss); + + IPower.takeFromPlayer(player, 4); + + stack.damageItem(1, player); + } + + @Override + public void onImpact(ICaster caster, BlockPos pos, IBlockState state) { + effect.onImpact(caster, pos, state); + } + + @Override + public SpellAffinity getAffinity() { + return effect.getAffinity(); + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemStaff.java b/src/main/java/com/minelittlepony/unicopia/item/ItemStaff.java index a35bd838..ef1091fb 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/ItemStaff.java +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemStaff.java @@ -8,11 +8,9 @@ import javax.annotation.Nullable; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.minelittlepony.unicopia.Predicates; -import com.minelittlepony.unicopia.tossable.ITossableItem; import com.minelittlepony.util.lang.ClientLocale; import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -25,15 +23,11 @@ import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemSword; -import net.minecraft.util.ActionResult; -import net.minecraft.util.EnumActionResult; -import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; -public class ItemStaff extends ItemSword implements ITossableItem { +public class ItemStaff extends ItemSword { protected static final UUID ATTACK_REACH_MODIFIER = UUID.fromString("FA235E1C-4280-A865-B01B-CBAE9985ACA3"); @@ -46,19 +40,6 @@ public class ItemStaff extends ItemSword implements ITossableItem { setMaxStackSize(1); } - @Override - public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { - ItemStack itemstack = player.getHeldItem(hand); - - if (canBeThrown(itemstack)) { - toss(world, itemstack, player); - - return new ActionResult(EnumActionResult.SUCCESS, itemstack); - } - - return super.onItemRightClick(world, player, hand); - } - @Override public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity target) { World w = player.getEntityWorld(); @@ -113,16 +94,6 @@ public class ItemStaff extends ItemSword implements ITossableItem { return EnumAction.BOW; } - @Override - public boolean canBeThrown(ItemStack stack) { - return false; - } - - @Override - public void onImpact(World world, BlockPos pos, IBlockState state) { - - } - @Override public Multimap getItemAttributeModifiers(EntityEquipmentSlot slot) { Multimap multimap = HashMultimap.create(); diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemTomato.java b/src/main/java/com/minelittlepony/unicopia/item/ItemTomato.java index 75e9ab6e..3690aeb5 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/ItemTomato.java +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemTomato.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.item; import com.minelittlepony.unicopia.forgebullshit.IMultiItem; import com.minelittlepony.unicopia.player.PlayerSpeciesList; +import com.minelittlepony.unicopia.spell.ICaster; import com.minelittlepony.unicopia.tossable.ITossableItem; import net.minecraft.block.material.Material; @@ -96,9 +97,9 @@ public class ItemTomato extends ItemFood implements ITossableItem, IMultiItem { } @Override - public void onImpact(World world, BlockPos pos, IBlockState state) { - if (!world.isRemote && state.getMaterial() == Material.GLASS) { - world.destroyBlock(pos, true); + public void onImpact(ICaster caster, BlockPos pos, IBlockState state) { + if (caster.isLocal() && state.getMaterial() == Material.GLASS) { + caster.getWorld().destroyBlock(pos, true); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java b/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java index 6060a004..a56c0f34 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/CasterUtils.java @@ -3,10 +3,12 @@ package com.minelittlepony.unicopia.spell; import java.util.Optional; import java.util.stream.Stream; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.google.common.collect.Streams; import com.minelittlepony.unicopia.Predicates; +import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.player.PlayerSpeciesList; import net.minecraft.entity.Entity; @@ -71,6 +73,13 @@ public class CasterUtils { .anyMatch(s -> s.equals(effectName)); } + public static ICaster near(@Nonnull Entity entity) { + EntitySpell caster = new EntitySpell(entity.world); + caster.copyLocationAndAnglesFrom(entity); + + return caster; + } + public static Optional> toCaster(@Nullable Entity entity) { if (entity instanceof ICaster) { diff --git a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java index 2e1204ba..e662b93a 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java @@ -7,6 +7,7 @@ import java.util.stream.Stream; import javax.annotation.Nullable; +import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.player.IOwned; import com.minelittlepony.unicopia.power.IPower; import com.minelittlepony.util.shape.IShape; @@ -59,6 +60,20 @@ public interface ICaster extends IOwned, ILevelle return getEntity().getEntityWorld(); } + /** + * Returns true if we're executing on the client. + */ + default boolean isRemote() { + return getWorld().isRemote; + } + + /** + * Returns true if we're executing on the server. + */ + default boolean isLocal() { + return !isRemote(); + } + /** * Gets the center position where this caster is located. */ @@ -66,6 +81,14 @@ public interface ICaster extends IOwned, ILevelle return getEntity().getPosition(); } + default ICaster at(BlockPos newOrigin) { + EntitySpell spell = new EntitySpell(getWorld()); + spell.setPosition(newOrigin.getX(), newOrigin.getY(), newOrigin.getZ()); + spell.setOwner(getOwner()); + + return spell; + } + default Vec3d getOriginVector() { return getEntity().getPositionVector(); } @@ -99,6 +122,4 @@ 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/ITossedEffect.java b/src/main/java/com/minelittlepony/unicopia/spell/ITossedEffect.java index 8f3dc5e9..c39cf7ec 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/ITossedEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/ITossedEffect.java @@ -1,29 +1,38 @@ package com.minelittlepony.unicopia.spell; +import javax.annotation.Nullable; + import com.minelittlepony.unicopia.entity.EntityProjectile; import com.minelittlepony.unicopia.init.UItems; import com.minelittlepony.unicopia.tossable.ITossable; import net.minecraft.entity.Entity; +import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; import net.minecraft.world.World; public interface ITossedEffect extends IMagicEffect, ITossable> { + default SoundEvent getThrowSound(ICaster caster) { + return SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT; + } + default ItemStack getCastAppearance(ICaster caster) { Item item = this.getAffinity() == SpellAffinity.BAD ? UItems.curse : UItems.spell; return SpellRegistry.instance().enchantStack(new ItemStack(item), getName()); } - default void toss(ICaster caster) { + @Nullable + default EntityProjectile toss(ICaster caster) { World world = caster.getWorld(); Entity entity = caster.getOwner(); - world.playSound(null, entity.posX, entity.posY, entity.posZ, getThrowSound(caster), SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); + world.playSound(null, entity.posX, entity.posY, entity.posZ, getThrowSound(caster), SoundCategory.NEUTRAL, 0.7F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); if (!world.isRemote) { EntityProjectile projectile = new EntityProjectile(world, caster.getOwner()); @@ -36,6 +45,10 @@ public interface ITossedEffect extends IMagicEffect, ITossable> { projectile.shoot(entity, entity.rotationPitch, entity.rotationYaw, 0, 1.5F, 1); world.spawnEntity(projectile); + + return projectile; } + + return null; } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java index e8e3dda5..8897cae8 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java @@ -26,6 +26,10 @@ public enum SpellAffinity { return this == BAD ? "curse" : "spell"; } + public String getUnlocalizedName() { + return "affinity." + getTranslationKey() + ".name"; + } + public int getCorruption() { return corruption; } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellAwkward.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellAwkward.java index 8a54ea5a..ab05017d 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellAwkward.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellAwkward.java @@ -71,7 +71,7 @@ public class SpellAwkward extends AbstractSpell implements ITossedEffect, IUseAc } @Override - public void onImpact(World world, BlockPos pos, IBlockState state) { + public void onImpact(ICaster caster, BlockPos pos, IBlockState state) { // noop } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellChangelingTrap.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellChangelingTrap.java index 787603cb..45f447d5 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellChangelingTrap.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellChangelingTrap.java @@ -5,7 +5,6 @@ import com.minelittlepony.unicopia.init.USounds; import com.minelittlepony.unicopia.player.IPlayer; import com.minelittlepony.unicopia.player.PlayerSpeciesList; import com.minelittlepony.util.WorldEvent; -import com.minelittlepony.util.vector.VecHelper; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; @@ -20,7 +19,6 @@ import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect, IAttachedEffect { @@ -154,9 +152,9 @@ public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect, } @Override - public void onImpact(World world, BlockPos pos, IBlockState state) { - if (!world.isRemote) { - VecHelper.findAllEntitiesInRange(null, world, pos, 5) + public void onImpact(ICaster caster, BlockPos pos, IBlockState state) { + if (caster.isLocal()) { + caster.findAllEntitiesInRange(5) .filter(e -> e instanceof EntityPlayer) .map(e -> PlayerSpeciesList.instance().getPlayer((EntityPlayer)e)) .forEach(this::entrap); diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java index 3aed186f..7f406941 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java @@ -48,6 +48,7 @@ public class SpellRegistry { registerSpell(SpellSiphon::new); registerSpell(SpellLight::new); registerSpell(SpellChangelingTrap::new); + registerSpell(SpellScorch::new); } @Nullable diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellScorch.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellScorch.java new file mode 100644 index 00000000..cbf50779 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellScorch.java @@ -0,0 +1,82 @@ +package com.minelittlepony.unicopia.spell; + +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.entity.EntityProjectile; +import com.minelittlepony.unicopia.init.UParticles; +import com.minelittlepony.util.PosHelper; +import com.minelittlepony.util.shape.Sphere; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.BlockPos; + +public class SpellScorch extends SpellFire implements ITossedEffect { + + @Override + public String getName() { + return "scorch"; + } + + @Override + public boolean isCraftable() { + return false; + } + + @Override + public int getTint() { + return 0; + } + + @Override + public boolean update(ICaster source) { + + BlockPos pos = PosHelper.findSolidGroundAt(source.getWorld(), source.getOrigin()); + + IBlockState state = source.getWorld().getBlockState(pos); + + IBlockState newState = affected.getConverted(state); + + if (!state.equals(newState)) { + source.getWorld().setBlockState(pos, newState, 3); + source.spawnParticles(new Sphere(false, 1), 5, p -> { + p = PosHelper.offset(p, pos); + + source.getWorld().spawnParticle(EnumParticleTypes.SMOKE_NORMAL, + p.x, p.y, p.z, 0, 0, 0); + }); + } + + return true; + } + + @Override + public void render(ICaster source) { + source.spawnParticles(EnumParticleTypes.FLAME.getParticleID(), 3); + source.spawnParticles(UParticles.UNICORN_MAGIC, 3, getTint()); + } + + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.BAD; + } + + @Override + @Nullable + public EntityProjectile toss(ICaster caster) { + EntityProjectile projectile = ITossedEffect.super.toss(caster); + + if (projectile != null) { + projectile.setNoGravity(true); + } + + return projectile; + } + + @Override + public void onImpact(ICaster caster, BlockPos pos, IBlockState state) { + if (caster.isLocal()) { + caster.getWorld().newExplosion(caster.getOwner(), pos.getX(), pos.getY(), pos.getZ(), 2, true, true); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/tossable/ITossable.java b/src/main/java/com/minelittlepony/unicopia/tossable/ITossable.java index b95b0c9a..15b24194 100644 --- a/src/main/java/com/minelittlepony/unicopia/tossable/ITossable.java +++ b/src/main/java/com/minelittlepony/unicopia/tossable/ITossable.java @@ -1,13 +1,14 @@ package com.minelittlepony.unicopia.tossable; +import com.minelittlepony.unicopia.spell.ICaster; + import net.minecraft.block.state.IBlockState; import net.minecraft.init.SoundEvents; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; public interface ITossable { - void onImpact(World world, BlockPos pos, IBlockState state); + void onImpact(ICaster caster, BlockPos pos, IBlockState state); default SoundEvent getThrowSound(T stack) { return SoundEvents.ENTITY_SNOWBALL_THROW; diff --git a/src/main/java/com/minelittlepony/util/PosHelper.java b/src/main/java/com/minelittlepony/util/PosHelper.java index 6e6c1ebd..dcd6a741 100644 --- a/src/main/java/com/minelittlepony/util/PosHelper.java +++ b/src/main/java/com/minelittlepony/util/PosHelper.java @@ -12,10 +12,25 @@ import com.minelittlepony.util.shape.IShape; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.BlockPos.MutableBlockPos; +import net.minecraft.world.World; public class PosHelper { + public static Vec3d offset(Vec3d a, Vec3i b) { + return a.add(b.getX(), b.getY(), b.getZ()); + } + + public static BlockPos findSolidGroundAt(World world, BlockPos pos) { + while ((pos.getY() > 0 || !world.isOutsideBuildHeight(pos)) + && (world.isAirBlock(pos) || world.getBlockState(pos).getBlock().isReplaceable(world, pos))) { + pos = pos.down(); + } + + return pos; + } + public static void all(BlockPos origin, Consumer consumer, EnumFacing... directions) { for (EnumFacing facing : directions) { consumer.accept(origin.offset(facing)); diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index cb61a11c..6fa1b336 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -43,6 +43,7 @@ item.chitin_shell.name=Chitinous Shell item.moss.name=Moss item.staff_meadow_brook.name=Meadow Brook's Staff item.staff_meadow_brook.tagline=It's a big stick +item.staff_remembrance.name=Staff of Remembrance item.alicorn_amulet.name=The Alicorn Amulet item.alicorn_amulet.tagline=Time Worn: %s @@ -53,6 +54,10 @@ item.gem.enchanted.name=Gem of %s item.corrupted_gem.name=Fractured Gem item.corrupted_gem.enchanted.name=Fractured Gem of %s +affinity.good.name=Pure +affinity.neutral.name=Neutral +affinity.bad.name=Corrupt + spell.shield.name=Defense spell.shield.tagline=Protection I diff --git a/src/main/resources/assets/unicopia/models/item/staff_remembrance.json b/src/main/resources/assets/unicopia/models/item/staff_remembrance.json new file mode 100644 index 00000000..97844a9d --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/staff_remembrance.json @@ -0,0 +1,6 @@ +{ + "parent": "unicopia:item/handheld_staff", + "textures": { + "layer0": "unicopia:items/staff_remembrance" + } +} diff --git a/src/main/resources/assets/unicopia/recipes/staff_remembrence.json b/src/main/resources/assets/unicopia/recipes/staff_remembrence.json new file mode 100644 index 00000000..f1d1a408 --- /dev/null +++ b/src/main/resources/assets/unicopia/recipes/staff_remembrence.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + " /*", + " / ", + "/ " + ], + "key": { + "/": [ + { "item": "minecraft:stick" } + ], + "*": [ + { + "item": "unicopia:gem", + "nbt": { + "spell": "fire" + } + } + ] + }, + "result": { "item": "unicopia:staff_remembrence", "count": 1 } +} diff --git a/src/main/resources/assets/unicopia/textures/items/staff_remembrance.png b/src/main/resources/assets/unicopia/textures/items/staff_remembrance.png new file mode 100644 index 00000000..12454c12 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/items/staff_remembrance.png differ