From 3f9cf6c5a66e6ae8973d02aedd4bd9e7322363c4 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 9 Apr 2019 13:45:36 +0200 Subject: [PATCH] Spears! (WIP) --- .../unicopia/entity/EntityProjectile.java | 13 +- .../unicopia/entity/EntitySpear.java | 156 +++++++++++++++++ .../unicopia/init/UEntities.java | 6 +- .../minelittlepony/unicopia/init/UItems.java | 5 +- .../unicopia/item/ItemSpear.java | 72 ++++++++ .../unicopia/render/RenderSpear.java | 21 +++ .../unicopia/tossable/ITossableItem.java | 36 +++- .../unicopia/tossable/ITossed.java | 24 +++ .../util/MagicalDamageSource.java | 10 +- .../resources/assets/unicopia/lang/en_US.lang | 2 + .../textures/entity/projectiles/spear.png | Bin 0 -> 191 bytes unicopia notes.txt | 163 ++++++++++++++++++ 12 files changed, 496 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/entity/EntitySpear.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/ItemSpear.java create mode 100644 src/main/java/com/minelittlepony/unicopia/render/RenderSpear.java create mode 100644 src/main/java/com/minelittlepony/unicopia/tossable/ITossed.java create mode 100644 src/main/resources/assets/unicopia/textures/entity/projectiles/spear.png create mode 100644 unicopia notes.txt diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java index 49cfb8d1..64eabf08 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.spell.SpellAffinity; import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.unicopia.tossable.ITossable; import com.minelittlepony.unicopia.tossable.ITossableItem; +import com.minelittlepony.unicopia.tossable.ITossed; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -28,7 +29,7 @@ import net.minecraft.world.World; * * Can also carry a spell if needed. */ -public class EntityProjectile extends EntitySnowball implements IMagicals, ICaster { +public class EntityProjectile extends EntitySnowball implements IMagicals, ITossed, ICaster { private static final DataParameter ITEM = EntityDataManager .createKey(EntityProjectile.class, DataSerializers.ITEM_STACK); @@ -118,23 +119,28 @@ public class EntityProjectile extends EntitySnowball implements IMagicals, ICast return effectDelegate.has(); } + @Override public void setItem(ItemStack stack) { getDataManager().set(ITEM, stack); getDataManager().setDirty(ITEM); } + @Override public void setThrowDamage(float damage) { getDataManager().set(DAMAGE, Math.max(0, damage)); } + @Override public float getThrowDamage() { return getDataManager().get(DAMAGE); } + @Override public void setHydrophobic() { getDataManager().set(HYDROPHOBIC, true); } + @Override public boolean getHydrophobic() { return getDataManager().get(HYDROPHOBIC); } @@ -194,6 +200,11 @@ public class EntityProjectile extends EntitySnowball implements IMagicals, ICast } } + @Override + public void launch(Entity entityThrower, float rotationPitchIn, float rotationYawIn, float pitchOffset, float velocity, float inaccuracy) { + shoot(entityThrower, rotationPitchIn, rotationYawIn, pitchOffset, velocity, inaccuracy); + } + @Override public void handleStatusUpdate(byte id) { if (id == 3) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpear.java b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpear.java new file mode 100644 index 00000000..4a56e34e --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpear.java @@ -0,0 +1,156 @@ +package com.minelittlepony.unicopia.entity; + +import com.minelittlepony.unicopia.init.UItems; +import com.minelittlepony.unicopia.tossable.ITossed; +import com.minelittlepony.util.MagicalDamageSource; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.MoverType; +import net.minecraft.entity.monster.EntityEnderman; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.server.SPacketChangeGameState; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; + +public class EntitySpear extends EntityArrow implements ITossed { + + private int knockback; + + public EntitySpear(World world) { + super(world); + } + + public EntitySpear(World world, double x, double y, double z) { + super(world, x, y, z); + } + + public EntitySpear(World world, EntityLivingBase shooter) { + super(world, shooter); + } + + @Override + public void shoot(double x, double y, double z, float velocity, float inaccuracy) { + + setDamage(0); + + super.shoot(x, y, z, velocity, inaccuracy); + } + + public void move(MoverType type, double x, double y, double z) { + super.move(type, x, y, z); + + if (type == MoverType.SELF && !inGround) { + setDamage(getDamage() + 0.02); + } + } + + public void setKnockbackStrength(int amount) { + super.setKnockbackStrength(amount); + knockback = amount; + } + + @Override + protected void onHit(RayTraceResult raytraceResultIn) { + Entity entity = raytraceResultIn.entityHit; + + if (entity != null) { + float speed = MathHelper.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ); + int damage = MathHelper.ceil(speed * getDamage()); + + if (getIsCritical()) { + damage += rand.nextInt(damage / 2 + 2); + } + + DamageSource damagesource = MagicalDamageSource.causeIndirect("spear", this, shootingEntity == null ? this : shootingEntity); + + if (isBurning() && !(entity instanceof EntityEnderman)) { + entity.setFire(5); + } + + if (entity.attackEntityFrom(damagesource, damage)) { + if (entity instanceof EntityLivingBase) { + EntityLivingBase entitylivingbase = (EntityLivingBase)entity; + + if (!world.isRemote) { + entitylivingbase.setArrowCountInEntity(entitylivingbase.getArrowCountInEntity() + 1); + } + + if (knockback > 0) { + float f1 = MathHelper.sqrt(motionX * motionX + motionZ * motionZ); + + if (f1 > 0.0F) { + entitylivingbase.addVelocity( + motionX * knockback * 0.6000000238418579D / f1, + 0.1D, + motionZ * knockback * 0.6000000238418579D / f1); + } + } + + if (shootingEntity instanceof EntityLivingBase) { + EnchantmentHelper.applyThornEnchantments(entitylivingbase, shootingEntity); + EnchantmentHelper.applyArthropodEnchantments((EntityLivingBase)shootingEntity, entitylivingbase); + } + + arrowHit(entitylivingbase); + + if (shootingEntity != null && entitylivingbase != shootingEntity && entitylivingbase instanceof EntityPlayer && shootingEntity instanceof EntityPlayerMP) { + ((EntityPlayerMP)shootingEntity).connection.sendPacket(new SPacketChangeGameState(6, 0)); + } + } + + playSound(SoundEvents.ENTITY_ARROW_HIT, 1.0F, 1.2F / (rand.nextFloat() * 0.2F + 0.9F)); + + if (!(entity instanceof EntityEnderman)) { + setDead(); + } + + return; + } + } + + super.onHit(raytraceResultIn); + } + + @Override + protected ItemStack getArrowStack() { + return new ItemStack(UItems.spear); + } + + @Override + public void setItem(ItemStack stack) { + + } + + @Override + public void setThrowDamage(float damage) { + setDamage(damage); + } + + @Override + public float getThrowDamage() { + return (float)getDamage(); + } + + @Override + public void setHydrophobic() { + + } + + @Override + public boolean getHydrophobic() { + return false; + } + + @Override + public void launch(Entity shooter, float pitch, float yaw, float pitchOffset, float velocity, float inaccuracy) { + shoot(shooter, pitch, yaw, pitchOffset, velocity, inaccuracy); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/init/UEntities.java b/src/main/java/com/minelittlepony/unicopia/init/UEntities.java index c0238f32..f717a3bb 100644 --- a/src/main/java/com/minelittlepony/unicopia/init/UEntities.java +++ b/src/main/java/com/minelittlepony/unicopia/init/UEntities.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.entity.EntityConstructionCloud; import com.minelittlepony.unicopia.entity.EntityCuccoon; import com.minelittlepony.unicopia.entity.EntityRacingCloud; import com.minelittlepony.unicopia.entity.EntityRainbow; +import com.minelittlepony.unicopia.entity.EntitySpear; import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.entity.EntitySpellbook; import com.minelittlepony.unicopia.entity.EntityProjectile; @@ -19,6 +20,7 @@ import com.minelittlepony.unicopia.render.RenderCuccoon; import com.minelittlepony.unicopia.render.RenderGem; import com.minelittlepony.unicopia.render.RenderProjectile; import com.minelittlepony.unicopia.render.RenderRainbow; +import com.minelittlepony.unicopia.render.RenderSpear; import com.minelittlepony.unicopia.render.RenderSpellbook; import net.minecraft.entity.EnumCreatureType; @@ -49,7 +51,8 @@ public class UEntities { builder.creature(EntityCuccoon.class, "cuccoon"), builder.creature(EntityButterfly.class, "butterfly").withEgg(0x222200, 0xaaeeff), builder.projectile(EntityRainbow.class, "rainbow", 500, 5), - builder.projectile(EntityProjectile.class, "thrown_item", 100, 10) + builder.projectile(EntityProjectile.class, "thrown_item", 100, 10), + builder.projectile(EntitySpear.class, "spear", 100, 10) ); } @@ -61,6 +64,7 @@ public class UEntities { RenderingRegistry.registerEntityRenderingHandler(EntityRainbow.class, RenderRainbow::new); RenderingRegistry.registerEntityRenderingHandler(EntityButterfly.class, RenderButterfly::new); RenderingRegistry.registerEntityRenderingHandler(EntityCuccoon.class, RenderCuccoon::new); + RenderingRegistry.registerEntityRenderingHandler(EntitySpear.class, RenderSpear::new); } public static void registerSpawnEntries(Biome biome) { diff --git a/src/main/java/com/minelittlepony/unicopia/init/UItems.java b/src/main/java/com/minelittlepony/unicopia/init/UItems.java index 300216a3..15fe3a0d 100644 --- a/src/main/java/com/minelittlepony/unicopia/init/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/init/UItems.java @@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.item.ItemMoss; import com.minelittlepony.unicopia.item.ItemOfHolding; import com.minelittlepony.unicopia.item.ItemRottenApple; import com.minelittlepony.unicopia.item.ItemRottenTomato; +import com.minelittlepony.unicopia.item.ItemSpear; import com.minelittlepony.unicopia.item.ItemSpell; import com.minelittlepony.unicopia.item.ItemSpellbook; import com.minelittlepony.unicopia.item.ItemStaff; @@ -157,6 +158,8 @@ public class UItems { 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 Item spear = new ItemSpear(Unicopia.MODID, "spear"); + public static final ItemMoss moss = new ItemMoss(Unicopia.MODID, "moss"); public static final Item alfalfa_seeds = new ItemSeedFood(1, 4, UBlocks.alfalfa, Blocks.FARMLAND) @@ -259,7 +262,7 @@ public class UItems { zap_apple, rotten_apple, cooked_zap_apple, apple_seeds, apple_leaves, - dew_drop, + dew_drop, spear, tomato, rotten_tomato, cloudsdale_tomato, rotten_cloudsdale_tomato, diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemSpear.java b/src/main/java/com/minelittlepony/unicopia/item/ItemSpear.java new file mode 100644 index 00000000..6be6ee21 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemSpear.java @@ -0,0 +1,72 @@ +package com.minelittlepony.unicopia.item; + +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.entity.EntitySpear; +import com.minelittlepony.unicopia.spell.ICaster; +import com.minelittlepony.unicopia.tossable.ITossableItem; +import com.minelittlepony.unicopia.tossable.ITossed; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.dispenser.IPosition; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class ItemSpear extends Item implements ITossableItem { + + public ItemSpear(String domain, String name) { + setFull3D(); + setTranslationKey(name); + setRegistryName(domain, name); + } + + @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 isEnchantable(ItemStack stack) { + return true; + } + + public boolean canApplyAtEnchantingTable(ItemStack stack, net.minecraft.enchantment.Enchantment enchantment) { + switch (enchantment.type) { + case WEAPON: + case BOW: + return true; + default: return false; + } + } + + @Nullable + @Override + public ITossed createProjectile(World world, EntityPlayer player) { + return new EntitySpear(world, player); + } + + @Nullable + @Override + public ITossed createProjectile(World world, IPosition pos) { + return null; + } + + @Override + public void onImpact(ICaster caster, BlockPos pos, IBlockState state) { + + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/render/RenderSpear.java b/src/main/java/com/minelittlepony/unicopia/render/RenderSpear.java new file mode 100644 index 00000000..5294d9e0 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/render/RenderSpear.java @@ -0,0 +1,21 @@ +package com.minelittlepony.unicopia.render; + +import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.entity.EntitySpear; + +import net.minecraft.client.renderer.entity.RenderArrow; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ResourceLocation; + +public class RenderSpear extends RenderArrow { + public static final ResourceLocation TEXTURE = new ResourceLocation(Unicopia.MODID, "textures/entity/projectiles/spear.png"); + + public RenderSpear(RenderManager manager) { + super(manager); + } + + @Override + protected ResourceLocation getEntityTexture(EntitySpear entity) { + return TEXTURE; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/tossable/ITossableItem.java b/src/main/java/com/minelittlepony/unicopia/tossable/ITossableItem.java index 9c2f9fe4..496920df 100644 --- a/src/main/java/com/minelittlepony/unicopia/tossable/ITossableItem.java +++ b/src/main/java/com/minelittlepony/unicopia/tossable/ITossableItem.java @@ -1,11 +1,14 @@ package com.minelittlepony.unicopia.tossable; +import javax.annotation.Nullable; + import com.minelittlepony.unicopia.entity.EntityProjectile; import com.minelittlepony.unicopia.item.IDispensable; import net.minecraft.block.BlockDispenser; import net.minecraft.dispenser.IBlockSource; import net.minecraft.dispenser.IPosition; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.stats.StatList; @@ -33,6 +36,16 @@ public interface ITossableItem extends ITossable, IDispensable { return new ActionResult<>(EnumActionResult.PASS, stack); } + @Nullable + default ITossed createProjectile(World world, EntityPlayer player) { + return new EntityProjectile(world, player); + } + + @Nullable + default ITossed createProjectile(World world, IPosition pos) { + return new EntityProjectile(world, pos.getX(), pos.getY(), pos.getZ()); + } + default void toss(World world, ItemStack itemstack, EntityPlayer player) { if (!player.capabilities.isCreativeMode) { itemstack.shrink(1); @@ -41,27 +54,34 @@ public interface ITossableItem extends ITossable, IDispensable { world.playSound(null, player.posX, player.posY, player.posZ, getThrowSound(itemstack), SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); if (!world.isRemote) { - EntityProjectile projectile = new EntityProjectile(world, player); + ITossed projectile = createProjectile(world, player); + + if (projectile == null) { + return; + } projectile.setItem(itemstack); projectile.setThrowDamage(getThrowDamage(itemstack)); - projectile.shoot(player, player.rotationPitch, player.rotationYaw, 0, 1.5F, 1); + projectile.launch(player, player.rotationPitch, player.rotationYaw, 0, 1.5F, 1); - world.spawnEntity(projectile); + world.spawnEntity((Entity)projectile); } player.addStat(StatList.getObjectUseStats(itemstack.getItem())); } default ItemStack toss(World world, IPosition pos, EnumFacing facing, ItemStack stack) { - EntityProjectile iprojectile = new EntityProjectile(world, pos.getX(), pos.getY(), pos.getZ()); + ITossed projectile = createProjectile(world, pos); - iprojectile.setItem(stack); - iprojectile.setThrowDamage(getThrowDamage(stack)); + if (projectile == null) { + return stack; + } - iprojectile.shoot(facing.getXOffset(), facing.getYOffset() + 0.1F, facing.getZOffset(), 1.1F, 6); + projectile.setItem(stack); + projectile.setThrowDamage(getThrowDamage(stack)); + projectile.launch(facing.getXOffset(), facing.getYOffset() + 0.1F, facing.getZOffset(), 1.1F, 6); - world.spawnEntity(iprojectile); + world.spawnEntity((Entity)projectile); stack.shrink(1); diff --git a/src/main/java/com/minelittlepony/unicopia/tossable/ITossed.java b/src/main/java/com/minelittlepony/unicopia/tossable/ITossed.java new file mode 100644 index 00000000..616750de --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/tossable/ITossed.java @@ -0,0 +1,24 @@ +package com.minelittlepony.unicopia.tossable; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.IProjectile; +import net.minecraft.item.ItemStack; + +public interface ITossed extends IProjectile { + + void setItem(ItemStack stack); + + void setThrowDamage(float damage); + + float getThrowDamage(); + + void setHydrophobic(); + + boolean getHydrophobic(); + + void launch(Entity entityThrower, float rotationPitchIn, float rotationYawIn, float pitchOffset, float velocity, float inaccuracy); + + default void launch(double x, double y, double z, float velocity, float inaccuracy) { + shoot(x, y, z, velocity, inaccuracy); + } +} diff --git a/src/main/java/com/minelittlepony/util/MagicalDamageSource.java b/src/main/java/com/minelittlepony/util/MagicalDamageSource.java index c04de301..98fee58c 100644 --- a/src/main/java/com/minelittlepony/util/MagicalDamageSource.java +++ b/src/main/java/com/minelittlepony/util/MagicalDamageSource.java @@ -1,13 +1,17 @@ package com.minelittlepony.util; +import javax.annotation.Nullable; + import com.minelittlepony.util.lang.ServerLocale; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.item.ItemStack; import net.minecraft.util.DamageSource; import net.minecraft.util.EntityDamageSource; +import net.minecraft.util.EntityDamageSourceIndirect; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; @@ -18,13 +22,17 @@ public class MagicalDamageSource extends EntityDamageSource { } public static DamageSource causePlayerDamage(String type, EntityPlayer player) { - return new MagicalDamageSource(type, player); + return causeMobDamage(type, player); } public static DamageSource causeMobDamage(String type, EntityLivingBase source) { return new MagicalDamageSource(type, source); } + public static DamageSource causeIndirect(String type, EntityArrow source, @Nullable Entity instigator) { + return new EntityDamageSourceIndirect(type, source, instigator).setProjectile(); + } + protected MagicalDamageSource(String type) { this(type, null); } diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index 30dcfeef..fbbf383d 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -45,6 +45,7 @@ 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.spear.name=Spear item.alicorn_amulet.name=The Alicorn Amulet item.alicorn_amulet.tagline=Time Worn: %s @@ -173,6 +174,7 @@ entity.cloud.name=Cloud entity.spell.name=Magic entity.spellbook.name=Spellbook entity.butterfly.name=Butterfly +entity.spear.name=Spear toxicity.safe.name=Safe toxicity.mild.name=Mildly Toxic diff --git a/src/main/resources/assets/unicopia/textures/entity/projectiles/spear.png b/src/main/resources/assets/unicopia/textures/entity/projectiles/spear.png new file mode 100644 index 0000000000000000000000000000000000000000..b1214231fe42ee29805dd6d6e0dd3a8101f8558f GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJHcuDFkch*{6<=OltQTOo$dkgb zAgs$kV#2GAW_JEVSA*U({M6m|-*JbBe5MLWh-5N|aWTJY_^)AOWyK)Ix`4&aFNEi>fW!wAhn0+r`6NmYtYCJNHF(t! k$lha>a0MbXp`3wXLgMUmOgAFVdQ&MBb@0NE@;(EtDd literal 0 HcmV?d00001 diff --git a/unicopia notes.txt b/unicopia notes.txt new file mode 100644 index 00000000..73e45ff1 --- /dev/null +++ b/unicopia notes.txt @@ -0,0 +1,163 @@ +Wishlist: + + Unicorn: + + locate (highlights nearest gem, fire, metal, wood, or water) + - Use a sound indicator and particle effects to point in the direction of nearby ores + + fire control lets you use telekinesis to control flames, and theres water control for doing it with water and ice + - Staffs for the fire and ice gems + + - Air gem (Neutral) + Level 1 (Gem of Air) (Neutral): No effects + Level 2 (Gem of Space) (Dark): No effects + + - Gravity Gems (Solaris) + Level 1 (Gem of Slowfall): Reduces the gravity for the holder, allows hor higher jumping + Level 2 (Gem of Inversion) (Dark): Inverts the gravity for the holder and nearby players when placed + Level 3 (Gem of Harshness) (Dark): Increases gravity for the holder + + - Earth gems (Excavation) + Level 1 (Gem of Cleansing) (Good): Clears nearby dirt when used + Level 2 (Gem of Harkness) (Neutral): Clears a small path through dirt when used (+Staff) + Level 3 (Gem of Crisis) (Dark): Clears a path through stone (+Staff) + Level 4 (Gem of Hiking) (Dark): Ascends surrounding blocks + + - Water Gems (Hydrology) + Level 1: No effect + Level 2: (Gem of Subnautica) (Neutral): + (light gem + air gem + materials) + Grants nearby (or holding) player with the ability to breath under water + Level 3: (Gem of Unfelling) (Neutral) + When placed collects energy from nearby water to produce clouds + + Deals heat damage to nearby entities + Level 4: (Gem of Felling) (Dark) + Drains moisture from nearby clouds to extract dew drops and matter + + - Mixed (Fire + Water) Gems + Level 3+2: (Gem of The Submariner) (Dark) + (inferno gem + air gem + materials) + Grants nearby (or holding) player with the ability to breath under lava + + Level 4+2: (Gem of Subhardina) (submariner + flame + materials) + Grants abilities of Submariner with added fire immunity + + - Apply to boats to harden them against heat and lava + - Hardened boats melt nearby ice when in water + + Earth: + tremor sense (which includes tapping the ground to hear through metal, rock, water, wood, and even web) + - Tap the ground with a gem and it produces a different sound depending what is underneath + + Loved + - Butterflies are normally timid, but will follow an Earth Pony when one is close + - If an Earth Pony is attached butterflies will come to their defense + - Killing Butterflies increases your corruption* level + - Wolves do not attach Earth Ponies, ever + + Pegasus + Molting + - As pegasi fly they will randomly leave a special feather in their wake. + - These feathers can be taken to the the Ceremonial Slab with cloud materials to create special cloud + blocks with intricate carvings + + Magic: + Corruption + Using/Unlocking dark magic increases your player's corruption. + Dark spells become more powerful as your corruption increases + - But a higher corruption makes you weaker against mobs + - Undead mobs will be more likely to spawn around the bed of a player who is corrupted + - The Anvil Head is only useable by corrupted pegasi + + Light spells become harder to use as your corruption increases + - Corrupted Pegasi cannot perform Sonic Rainbooms + - Corrupted players cannot see rainbows + - Butterflies fear corrupted players and will die in their presence + - Farm animals run from corrupted players and will die in their presence + - Corrupted pegasi cannot harvest cloudsdale tomatoes (they'll just be regular tomatoes) + + Objects: + + Ceremonial Slab + - It's a slab made of clouds + - That's about it. + + Heavenly Cloud Beds + - There's nothing like sleeping on a matress made of clouds + + Jars + + Lightning in a Jar + - Pegasi can collect lightning bolts from clouds + - Dropping the jar will cause it to break and unleash the thunder + + Banners for each major Equestrian Race + - Equestrian Flag (with Celestia and Luna) + - Old Equestrian Alliance + - Earth Tribe + - Unicorn Tribe + - Pegasus Tribe + + Major Hurricane's Shield + - A golden shield + - Grants the user immunity to blast damage + + 6 lock box + - A magical chest that requires 6 keys to unlock + + Mane 6 keys + - Keys for the 6 lock box forged using the spellbook + + Saddlebags + - Regular item that lets you carry an extra 18 slots + - Can be enchanted by unicorns to make the Bag o Holding + + The Crystal Heart + - It looks pretty + - Doesn't do much + + Medallion of Discord + - Discord's friendship medallion + - Offers protection from most direct physical damage + + Zap Apple Trees + - Seeds obtained from zap apples + - Will randomly spawn lightning bolts, thus dangerous to be around + + Carved Cloud Blocks + - Cloud blocks with patterns + - Same material as packed clouds + + Cloud pillars + - Pillar clouds with trimming + + Spikes for changeling hives + - Harm the player when touched + + Spears + - Thrown by pegasi. + - Will stick in the ground where they land, simillar to arrows. + - Deals damage to any entity near where it lands proportional to the distance it travelled. + - Supports vanilla enchants + + Moon Stone + - Grows during a full moon + - Looks like blue mossy stone + - Can be ground up into Moon Dust and mixed with water under the light of a full moon to create Princess Luna's favourite drink (Moonshine) + + Moonshine + - A temporary effect that alters the drinker's gravity + - Allows higher jumps and slower descents + - Used to craft the air gem + + Foods: + Mangoes (DEADLY) (by request) + Bananas (Toxic) + Oranges (Safe) + Strawberries (Toxic) + Pineapples (Safe) + Coconut (Safe) + Kiwis (Safe) + Lychee (Safe) + + Chocolate (Toxic)