diff --git a/src/main/java/WayofTime/bloodmagic/api/Constants.java b/src/main/java/WayofTime/bloodmagic/api/Constants.java index 92da1111..05967dfc 100644 --- a/src/main/java/WayofTime/bloodmagic/api/Constants.java +++ b/src/main/java/WayofTime/bloodmagic/api/Constants.java @@ -96,6 +96,7 @@ public class Constants public static final String SOUL_SWORD_HEALTH = "soulSwordHealth"; public static final String SOUL_SWORD_ATTACK_SPEED = "soulSwordAttackSpeed"; public static final String SOUL_SWORD_SPEED = "soulSwordSpeed"; + public static final String SOUL_SWORD_DIG_SPEED = "soulSwordDigSpeed"; public static final String WILL_TYPE = "demonWillType"; public static final String SOUL_FORGE_BURN = "burnTime"; @@ -195,7 +196,10 @@ public class Constants SENTIENT_ARMOR_LEGS("ItemSentientArmourLegs"), SENTIENT_ARMOR_BOOTS("ItemSentientArmourBoots"), SENTIENT_ARMOR_GEM("ItemSentientArmourGem"), + SENTIENT_AXE("ItemSentientAxe"), SENTIENT_BOW("ItemSentientBow"), + SENTIENT_PICKAXE("ItemSentientPickaxe"), + SENTIENT_SHOVEL("ItemSentientShovel"), SENTIENT_SWORD("ItemSentientSword"), SOUL_GEM("ItemSoulGem"), SOUL_SNARE("ItemSoulSnare"), @@ -225,8 +229,7 @@ public class Constants SIGIL_TRANSPOSITION("ItemSigilTransposition"), RITUAL_READER("ItemRitualReader"), SANGUINE_BOOK("ItemSanguineBook"), - SIGIL_HOLDING("ItemSigilHolding"), - ; + SIGIL_HOLDING("ItemSigilHolding"), ; @Getter private final String regName; diff --git a/src/main/java/WayofTime/bloodmagic/item/ItemBoundAxe.java b/src/main/java/WayofTime/bloodmagic/item/ItemBoundAxe.java index 1ef0fff7..cd6991c4 100644 --- a/src/main/java/WayofTime/bloodmagic/item/ItemBoundAxe.java +++ b/src/main/java/WayofTime/bloodmagic/item/ItemBoundAxe.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import javax.annotation.Nullable; + import net.minecraft.block.Block; import net.minecraft.block.BlockLeaves; import net.minecraft.block.material.Material; @@ -36,8 +38,6 @@ import com.google.common.collect.HashMultiset; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; -import javax.annotation.Nullable; - public class ItemBoundAxe extends ItemBoundTool implements IMeshProvider { private static final Set EFFECTIVE_ON = Sets.newHashSet(Blocks.PLANKS, Blocks.BOOKSHELF, Blocks.LOG, Blocks.LOG2, Blocks.CHEST, Blocks.PUMPKIN, Blocks.LIT_PUMPKIN, Blocks.MELON_BLOCK, Blocks.LADDER); diff --git a/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientAxe.java b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientAxe.java new file mode 100644 index 00000000..505868b4 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientAxe.java @@ -0,0 +1,541 @@ +package WayofTime.bloodmagic.item.soul; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.ItemMeshDefinition; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.monster.EntitySlime; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemAxe; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import WayofTime.bloodmagic.BloodMagic; +import WayofTime.bloodmagic.api.Constants; +import WayofTime.bloodmagic.api.iface.IMultiWillTool; +import WayofTime.bloodmagic.api.iface.ISentientSwordEffectProvider; +import WayofTime.bloodmagic.api.soul.EnumDemonWillType; +import WayofTime.bloodmagic.api.soul.IDemonWill; +import WayofTime.bloodmagic.api.soul.IDemonWillWeapon; +import WayofTime.bloodmagic.api.soul.PlayerDemonWillHandler; +import WayofTime.bloodmagic.api.util.helper.NBTHelper; +import WayofTime.bloodmagic.client.IMeshProvider; +import WayofTime.bloodmagic.client.mesh.CustomMeshDefinitionMultiWill; +import WayofTime.bloodmagic.registry.ModItems; +import WayofTime.bloodmagic.util.helper.TextHelper; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +public class ItemSentientAxe extends ItemAxe implements IDemonWillWeapon, IMeshProvider, IMultiWillTool +{ + public static int[] soulBracket = new int[] { 16, 60, 200, 400, 1000 }; + public static double[] defaultDamageAdded = new double[] { 1, 2, 3, 3.5, 4 }; + public static double[] destructiveDamageAdded = new double[] { 2, 3, 4, 5, 6 }; + public static double[] vengefulDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 }; + public static double[] steadfastDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 }; + public static double[] defaultDigSpeedAdded = new double[] { 1, 1.5, 2, 3, 4 }; + public static double[] soulDrainPerSwing = new double[] { 0.05, 0.1, 0.2, 0.4, 0.75 }; + public static double[] soulDrop = new double[] { 2, 4, 7, 10, 13 }; + public static double[] staticDrop = new double[] { 1, 1, 2, 3, 3 }; + + public static double[] healthBonus = new double[] { 0, 0, 0, 0, 0 }; //TODO: Think of implementing this later + public static double[] vengefulAttackSpeed = new double[] { -3, -2.8, -2.7, -2.6, -2.5 }; + public static double[] destructiveAttackSpeed = new double[] { -3.1, -3.1, -3.2, -3.3, -3.3 }; + + public static int[] absorptionTime = new int[] { 200, 300, 400, 500, 600 }; + + public static double maxAbsorptionHearts = 10; + + public static int[] poisonTime = new int[] { 25, 50, 60, 80, 100 }; + public static int[] poisonLevel = new int[] { 0, 0, 0, 1, 1 }; + + public static double[] movementSpeed = new double[] { 0.05, 0.1, 0.15, 0.2, 0.25 }; + + public final double baseAttackDamage = 8; + public final double baseAttackSpeed = -3; + + public ItemSentientAxe() + { + super(Item.ToolMaterial.IRON); + setMaxDamage(getMaxDamage() * 2); +// super(ModItems.soulToolMaterial); + + setUnlocalizedName(Constants.Mod.MODID + ".sentientAxe"); + setCreativeTab(BloodMagic.tabBloodMagic); + } + + @Override + public float getStrVsBlock(ItemStack stack, IBlockState state) + { + float value = super.getStrVsBlock(stack, state); + if (value > 1) + { + return (float) (value + getDigSpeedOfSword(stack)); + } else + { + return value; + } + } + + @Override + public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) + { + return ModItems.itemDemonCrystal == repair.getItem() ? true : super.getIsRepairable(toRepair, repair); + } + + public void recalculatePowers(ItemStack stack, World world, EntityPlayer player) + { + EnumDemonWillType type = PlayerDemonWillHandler.getLargestWillType(player); + double soulsRemaining = PlayerDemonWillHandler.getTotalDemonWill(type, player); + this.setCurrentType(stack, soulsRemaining > 0 ? type : EnumDemonWillType.DEFAULT); + int level = getLevel(stack, soulsRemaining); + + double drain = level >= 0 ? soulDrainPerSwing[level] : 0; + double extraDamage = getExtraDamage(type, level); + + setDrainOfActivatedSword(stack, drain); + setDamageOfActivatedSword(stack, baseAttackDamage + extraDamage); + setStaticDropOfActivatedSword(stack, level >= 0 ? staticDrop[level] : 1); + setDropOfActivatedSword(stack, level >= 0 ? soulDrop[level] : 0); + setAttackSpeedOfSword(stack, level >= 0 ? getAttackSpeed(type, level) : baseAttackSpeed); + setHealthBonusOfSword(stack, level >= 0 ? getHealthBonus(type, level) : 0); + setSpeedOfSword(stack, level >= 0 ? getMovementSpeed(type, level) : 0); + setDigSpeedOfSword(stack, level >= 0 ? getDigSpeed(type, level) : 0); + } + + public double getExtraDamage(EnumDemonWillType type, int willBracket) + { + if (willBracket < 0) + { + return 0; + } + + switch (type) + { + case CORROSIVE: + case DEFAULT: + return defaultDamageAdded[willBracket]; + case DESTRUCTIVE: + return destructiveDamageAdded[willBracket]; + case VENGEFUL: + return vengefulDamageAdded[willBracket]; + case STEADFAST: + return steadfastDamageAdded[willBracket]; + } + + return 0; + } + + public double getAttackSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: + return vengefulAttackSpeed[willBracket]; + case DESTRUCTIVE: + return destructiveAttackSpeed[willBracket]; + default: + return -2.9; + } + } + + public double getHealthBonus(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case STEADFAST: + return healthBonus[willBracket]; + default: + return 0; + } + } + + public double getMovementSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: + return movementSpeed[willBracket]; + default: + return 0; + } + } + + public double getDigSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: +// return movementSpeed[willBracket]; + default: + return defaultDigSpeedAdded[willBracket]; + } + } + + public void applyEffectToEntity(EnumDemonWillType type, int willBracket, EntityLivingBase target, EntityPlayer attacker) + { + switch (type) + { + case CORROSIVE: + target.addPotionEffect(new PotionEffect(MobEffects.WITHER, poisonTime[willBracket], poisonLevel[willBracket])); + break; + case DEFAULT: + break; + case DESTRUCTIVE: + break; + case STEADFAST: + if (!target.isEntityAlive()) + { + float absorption = attacker.getAbsorptionAmount(); + attacker.addPotionEffect(new PotionEffect(MobEffects.ABSORPTION, absorptionTime[willBracket], 127)); + attacker.setAbsorptionAmount((float) Math.min(absorption + target.getMaxHealth() * 0.05f, maxAbsorptionHearts)); + } + break; + case VENGEFUL: + break; + } + } + + @Override + public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) + { + if (super.hitEntity(stack, target, attacker)) + { + if (attacker instanceof EntityPlayer) + { + EntityPlayer attackerPlayer = (EntityPlayer) attacker; + this.recalculatePowers(stack, attackerPlayer.worldObj, attackerPlayer); + EnumDemonWillType type = this.getCurrentType(stack); + double will = PlayerDemonWillHandler.getTotalDemonWill(type, attackerPlayer); + int willBracket = this.getLevel(stack, will); + + applyEffectToEntity(type, willBracket, target, attackerPlayer); + + ItemStack offStack = attackerPlayer.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND); + if (offStack != null && offStack.getItem() instanceof ISentientSwordEffectProvider) + { + ISentientSwordEffectProvider provider = (ISentientSwordEffectProvider) offStack.getItem(); + if (provider.providesEffectForWill(type)) + { + provider.applyOnHitEffect(type, stack, offStack, attacker, target); + } + } + } + + return true; + } + + return false; + } + + @Override + public EnumDemonWillType getCurrentType(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + if (!tag.hasKey(Constants.NBT.WILL_TYPE)) + { + return EnumDemonWillType.DEFAULT; + } + + return EnumDemonWillType.valueOf(tag.getString(Constants.NBT.WILL_TYPE)); + } + + public void setCurrentType(ItemStack stack, EnumDemonWillType type) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setString(Constants.NBT.WILL_TYPE, type.toString()); + } + + @Override + public ActionResult onItemRightClick(ItemStack stack, World world, EntityPlayer player, EnumHand hand) + { + recalculatePowers(stack, world, player); + + return super.onItemRightClick(stack, world, player, hand); + } + + @Override + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) + { + return oldStack.getItem() != newStack.getItem(); + } + + private int getLevel(ItemStack stack, double soulsRemaining) + { + int lvl = -1; + for (int i = 0; i < soulBracket.length; i++) + { + if (soulsRemaining >= soulBracket[i]) + { + lvl = i; + } + } + + return lvl; + } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, EntityPlayer player, List tooltip, boolean advanced) + { + NBTHelper.checkNBT(stack); + + tooltip.addAll(Arrays.asList(TextHelper.cutLongString(TextHelper.localizeEffect("tooltip.BloodMagic.sentientAxe.desc")))); + + tooltip.add(TextHelper.localizeEffect("tooltip.BloodMagic.currentType." + getCurrentType(stack).getName().toLowerCase())); + } + + @Override + public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) + { + recalculatePowers(stack, player.worldObj, player); + + double drain = this.getDrainOfActivatedSword(stack); + if (drain > 0) + { + EnumDemonWillType type = getCurrentType(stack); + double soulsRemaining = PlayerDemonWillHandler.getTotalDemonWill(type, player); + + if (drain > soulsRemaining) + { + return false; + } else + { + PlayerDemonWillHandler.consumeDemonWill(type, player, drain); + } + } + + return super.onLeftClickEntity(stack, player, entity); + } + + @Override + @SideOnly(Side.CLIENT) + public ItemMeshDefinition getMeshDefinition() + { + return new CustomMeshDefinitionMultiWill("ItemSentientAxe"); + } + + @Nullable + @Override + public ResourceLocation getCustomLocation() + { + return null; + } + + @Override + public List getVariants() + { + List ret = new ArrayList(); + for (EnumDemonWillType type : EnumDemonWillType.values()) + { + ret.add("type=" + type.getName().toLowerCase()); + } + + return ret; + } + + @Override + public List getRandomDemonWillDrop(EntityLivingBase killedEntity, EntityLivingBase attackingEntity, ItemStack stack, int looting) + { + List soulList = new ArrayList(); + + if (killedEntity.worldObj.getDifficulty() != EnumDifficulty.PEACEFUL && !(killedEntity instanceof IMob)) + { + return soulList; + } + + double willModifier = killedEntity instanceof EntitySlime ? 0.67 : 1; + + IDemonWill soul = ((IDemonWill) ModItems.monsterSoul); + + for (int i = 0; i <= looting; i++) + { + if (i == 0 || attackingEntity.worldObj.rand.nextDouble() < 0.4) + { + ItemStack soulStack = soul.createWill(0, willModifier * (this.getDropOfActivatedSword(stack) * attackingEntity.worldObj.rand.nextDouble() + this.getStaticDropOfActivatedSword(stack)) * killedEntity.getMaxHealth() / 20d); + soulList.add(soulStack); + } + } + + return soulList; + } + + //TODO: Change attack speed. + @Override + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) + { + Multimap multimap = HashMultimap.create(); + if (slot == EntityEquipmentSlot.MAINHAND) + { + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", getDamageOfActivatedSword(stack), 0)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", this.getAttackSpeedOfSword(stack), 0)); + multimap.put(SharedMonsterAttributes.MAX_HEALTH.getAttributeUnlocalizedName(), new AttributeModifier(new UUID(0, 31818145), "Weapon modifier", this.getHealthBonusOfSword(stack), 0)); + multimap.put(SharedMonsterAttributes.MOVEMENT_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(new UUID(0, 4218052), "Weapon modifier", this.getSpeedOfSword(stack), 2)); + } + + return multimap; + } + + public double getDamageOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DAMAGE); + } + + public void setDamageOfActivatedSword(ItemStack stack, double damage) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DAMAGE, damage); + } + + public double getDrainOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_ACTIVE_DRAIN); + } + + public void setDrainOfActivatedSword(ItemStack stack, double drain) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_ACTIVE_DRAIN, drain); + } + + public double getStaticDropOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_STATIC_DROP); + } + + public void setStaticDropOfActivatedSword(ItemStack stack, double drop) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_STATIC_DROP, drop); + } + + public double getDropOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DROP); + } + + public void setDropOfActivatedSword(ItemStack stack, double drop) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DROP, drop); + } + + public double getHealthBonusOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_HEALTH); + } + + public void setHealthBonusOfSword(ItemStack stack, double hp) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_HEALTH, hp); + } + + public double getAttackSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_ATTACK_SPEED); + } + + public void setAttackSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_ATTACK_SPEED, speed); + } + + public double getSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_SPEED); + } + + public void setSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_SPEED, speed); + } + + public double getDigSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DIG_SPEED); + } + + public void setDigSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DIG_SPEED, speed); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientBow.java b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientBow.java index ee0bd7e5..62843ee8 100644 --- a/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientBow.java +++ b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientBow.java @@ -236,7 +236,7 @@ public class ItemSentientBow extends ItemBow implements IMultiWillTool//, IMeshP if ((double) arrowVelocity >= 0.1D) { - boolean flag1 = flag && itemstack.getItem() instanceof ItemArrow; //Forge: Fix consuming custom arrows. + boolean flag1 = flag && itemstack.getItem() == Items.ARROW; //Forge: Fix consuming custom arrows. if (!world.isRemote) { @@ -247,7 +247,7 @@ public class ItemSentientBow extends ItemBow implements IMultiWillTool//, IMeshP // ItemArrow itemarrow = ((ItemArrow) (itemstack.getItem() instanceof ItemArrow ? itemstack.getItem() : Items.arrow)); // EntityArrow entityArrow = itemarrow.createArrow(world, itemstack, player); float newArrowVelocity = arrowVelocity * getVelocityOfArrow(stack); - EntityArrow entityArrow = new EntitySentientArrow(world, entityLiving, type); + EntitySentientArrow entityArrow = new EntitySentientArrow(world, entityLiving, type); entityArrow.setAim(player, player.rotationPitch, player.rotationYaw, 0.0F, newArrowVelocity, 1.0F); if (newArrowVelocity == 0) diff --git a/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientPickaxe.java b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientPickaxe.java new file mode 100644 index 00000000..e4277123 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientPickaxe.java @@ -0,0 +1,541 @@ +package WayofTime.bloodmagic.item.soul; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.ItemMeshDefinition; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.monster.EntitySlime; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemPickaxe; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import WayofTime.bloodmagic.BloodMagic; +import WayofTime.bloodmagic.api.Constants; +import WayofTime.bloodmagic.api.iface.IMultiWillTool; +import WayofTime.bloodmagic.api.iface.ISentientSwordEffectProvider; +import WayofTime.bloodmagic.api.soul.EnumDemonWillType; +import WayofTime.bloodmagic.api.soul.IDemonWill; +import WayofTime.bloodmagic.api.soul.IDemonWillWeapon; +import WayofTime.bloodmagic.api.soul.PlayerDemonWillHandler; +import WayofTime.bloodmagic.api.util.helper.NBTHelper; +import WayofTime.bloodmagic.client.IMeshProvider; +import WayofTime.bloodmagic.client.mesh.CustomMeshDefinitionMultiWill; +import WayofTime.bloodmagic.registry.ModItems; +import WayofTime.bloodmagic.util.helper.TextHelper; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +public class ItemSentientPickaxe extends ItemPickaxe implements IDemonWillWeapon, IMeshProvider, IMultiWillTool +{ + public static int[] soulBracket = new int[] { 16, 60, 200, 400, 1000 }; + public static double[] defaultDamageAdded = new double[] { 1, 2, 3, 3.5, 4 }; + public static double[] destructiveDamageAdded = new double[] { 2, 3, 4, 5, 6 }; + public static double[] vengefulDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 }; + public static double[] steadfastDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 }; + public static double[] defaultDigSpeedAdded = new double[] { 1, 1.5, 2, 3, 4 }; + public static double[] soulDrainPerSwing = new double[] { 0.05, 0.1, 0.2, 0.4, 0.75 }; + public static double[] soulDrop = new double[] { 2, 4, 7, 10, 13 }; + public static double[] staticDrop = new double[] { 1, 1, 2, 3, 3 }; + + public static double[] healthBonus = new double[] { 0, 0, 0, 0, 0 }; //TODO: Think of implementing this later + public static double[] vengefulAttackSpeed = new double[] { -3, -2.8, -2.7, -2.6, -2.5 }; + public static double[] destructiveAttackSpeed = new double[] { -3.1, -3.1, -3.2, -3.3, -3.3 }; + + public static int[] absorptionTime = new int[] { 200, 300, 400, 500, 600 }; + + public static double maxAbsorptionHearts = 10; + + public static int[] poisonTime = new int[] { 25, 50, 60, 80, 100 }; + public static int[] poisonLevel = new int[] { 0, 0, 0, 1, 1 }; + + public static double[] movementSpeed = new double[] { 0.05, 0.1, 0.15, 0.2, 0.25 }; + + public final double baseAttackDamage = 3; + public final double baseAttackSpeed = -2.8; + + public ItemSentientPickaxe() + { + super(Item.ToolMaterial.IRON); + setMaxDamage(getMaxDamage() * 2); +// super(ModItems.soulToolMaterial); + + setUnlocalizedName(Constants.Mod.MODID + ".sentientPickaxe"); + setCreativeTab(BloodMagic.tabBloodMagic); + } + + @Override + public float getStrVsBlock(ItemStack stack, IBlockState state) + { + float value = super.getStrVsBlock(stack, state); + if (value > 1) + { + return (float) (value + getDigSpeedOfSword(stack)); + } else + { + return value; + } + } + + @Override + public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) + { + return ModItems.itemDemonCrystal == repair.getItem() ? true : super.getIsRepairable(toRepair, repair); + } + + public void recalculatePowers(ItemStack stack, World world, EntityPlayer player) + { + EnumDemonWillType type = PlayerDemonWillHandler.getLargestWillType(player); + double soulsRemaining = PlayerDemonWillHandler.getTotalDemonWill(type, player); + this.setCurrentType(stack, soulsRemaining > 0 ? type : EnumDemonWillType.DEFAULT); + int level = getLevel(stack, soulsRemaining); + + double drain = level >= 0 ? soulDrainPerSwing[level] : 0; + double extraDamage = getExtraDamage(type, level); + + setDrainOfActivatedSword(stack, drain); + setDamageOfActivatedSword(stack, baseAttackDamage + extraDamage); + setStaticDropOfActivatedSword(stack, level >= 0 ? staticDrop[level] : 1); + setDropOfActivatedSword(stack, level >= 0 ? soulDrop[level] : 0); + setAttackSpeedOfSword(stack, level >= 0 ? getAttackSpeed(type, level) : baseAttackSpeed); + setHealthBonusOfSword(stack, level >= 0 ? getHealthBonus(type, level) : 0); + setSpeedOfSword(stack, level >= 0 ? getMovementSpeed(type, level) : 0); + setDigSpeedOfSword(stack, level >= 0 ? getDigSpeed(type, level) : 0); + } + + public double getExtraDamage(EnumDemonWillType type, int willBracket) + { + if (willBracket < 0) + { + return 0; + } + + switch (type) + { + case CORROSIVE: + case DEFAULT: + return defaultDamageAdded[willBracket]; + case DESTRUCTIVE: + return destructiveDamageAdded[willBracket]; + case VENGEFUL: + return vengefulDamageAdded[willBracket]; + case STEADFAST: + return steadfastDamageAdded[willBracket]; + } + + return 0; + } + + public double getAttackSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: + return vengefulAttackSpeed[willBracket]; + case DESTRUCTIVE: + return destructiveAttackSpeed[willBracket]; + default: + return -2.9; + } + } + + public double getHealthBonus(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case STEADFAST: + return healthBonus[willBracket]; + default: + return 0; + } + } + + public double getMovementSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: + return movementSpeed[willBracket]; + default: + return 0; + } + } + + public double getDigSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: +// return movementSpeed[willBracket]; + default: + return defaultDigSpeedAdded[willBracket]; + } + } + + public void applyEffectToEntity(EnumDemonWillType type, int willBracket, EntityLivingBase target, EntityPlayer attacker) + { + switch (type) + { + case CORROSIVE: + target.addPotionEffect(new PotionEffect(MobEffects.WITHER, poisonTime[willBracket], poisonLevel[willBracket])); + break; + case DEFAULT: + break; + case DESTRUCTIVE: + break; + case STEADFAST: + if (!target.isEntityAlive()) + { + float absorption = attacker.getAbsorptionAmount(); + attacker.addPotionEffect(new PotionEffect(MobEffects.ABSORPTION, absorptionTime[willBracket], 127)); + attacker.setAbsorptionAmount((float) Math.min(absorption + target.getMaxHealth() * 0.05f, maxAbsorptionHearts)); + } + break; + case VENGEFUL: + break; + } + } + + @Override + public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) + { + if (super.hitEntity(stack, target, attacker)) + { + if (attacker instanceof EntityPlayer) + { + EntityPlayer attackerPlayer = (EntityPlayer) attacker; + this.recalculatePowers(stack, attackerPlayer.worldObj, attackerPlayer); + EnumDemonWillType type = this.getCurrentType(stack); + double will = PlayerDemonWillHandler.getTotalDemonWill(type, attackerPlayer); + int willBracket = this.getLevel(stack, will); + + applyEffectToEntity(type, willBracket, target, attackerPlayer); + + ItemStack offStack = attackerPlayer.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND); + if (offStack != null && offStack.getItem() instanceof ISentientSwordEffectProvider) + { + ISentientSwordEffectProvider provider = (ISentientSwordEffectProvider) offStack.getItem(); + if (provider.providesEffectForWill(type)) + { + provider.applyOnHitEffect(type, stack, offStack, attacker, target); + } + } + } + + return true; + } + + return false; + } + + @Override + public EnumDemonWillType getCurrentType(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + if (!tag.hasKey(Constants.NBT.WILL_TYPE)) + { + return EnumDemonWillType.DEFAULT; + } + + return EnumDemonWillType.valueOf(tag.getString(Constants.NBT.WILL_TYPE)); + } + + public void setCurrentType(ItemStack stack, EnumDemonWillType type) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setString(Constants.NBT.WILL_TYPE, type.toString()); + } + + @Override + public ActionResult onItemRightClick(ItemStack stack, World world, EntityPlayer player, EnumHand hand) + { + recalculatePowers(stack, world, player); + + return super.onItemRightClick(stack, world, player, hand); + } + + @Override + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) + { + return oldStack.getItem() != newStack.getItem(); + } + + private int getLevel(ItemStack stack, double soulsRemaining) + { + int lvl = -1; + for (int i = 0; i < soulBracket.length; i++) + { + if (soulsRemaining >= soulBracket[i]) + { + lvl = i; + } + } + + return lvl; + } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, EntityPlayer player, List tooltip, boolean advanced) + { + NBTHelper.checkNBT(stack); + + tooltip.addAll(Arrays.asList(TextHelper.cutLongString(TextHelper.localizeEffect("tooltip.BloodMagic.sentientPickaxe.desc")))); + + tooltip.add(TextHelper.localizeEffect("tooltip.BloodMagic.currentType." + getCurrentType(stack).getName().toLowerCase())); + } + + @Override + public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) + { + recalculatePowers(stack, player.worldObj, player); + + double drain = this.getDrainOfActivatedSword(stack); + if (drain > 0) + { + EnumDemonWillType type = getCurrentType(stack); + double soulsRemaining = PlayerDemonWillHandler.getTotalDemonWill(type, player); + + if (drain > soulsRemaining) + { + return false; + } else + { + PlayerDemonWillHandler.consumeDemonWill(type, player, drain); + } + } + + return super.onLeftClickEntity(stack, player, entity); + } + + @Override + @SideOnly(Side.CLIENT) + public ItemMeshDefinition getMeshDefinition() + { + return new CustomMeshDefinitionMultiWill("ItemSentientPickaxe"); + } + + @Nullable + @Override + public ResourceLocation getCustomLocation() + { + return null; + } + + @Override + public List getVariants() + { + List ret = new ArrayList(); + for (EnumDemonWillType type : EnumDemonWillType.values()) + { + ret.add("type=" + type.getName().toLowerCase()); + } + + return ret; + } + + @Override + public List getRandomDemonWillDrop(EntityLivingBase killedEntity, EntityLivingBase attackingEntity, ItemStack stack, int looting) + { + List soulList = new ArrayList(); + + if (killedEntity.worldObj.getDifficulty() != EnumDifficulty.PEACEFUL && !(killedEntity instanceof IMob)) + { + return soulList; + } + + double willModifier = killedEntity instanceof EntitySlime ? 0.67 : 1; + + IDemonWill soul = ((IDemonWill) ModItems.monsterSoul); + + for (int i = 0; i <= looting; i++) + { + if (i == 0 || attackingEntity.worldObj.rand.nextDouble() < 0.4) + { + ItemStack soulStack = soul.createWill(0, willModifier * (this.getDropOfActivatedSword(stack) * attackingEntity.worldObj.rand.nextDouble() + this.getStaticDropOfActivatedSword(stack)) * killedEntity.getMaxHealth() / 20d); + soulList.add(soulStack); + } + } + + return soulList; + } + + //TODO: Change attack speed. + @Override + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) + { + Multimap multimap = HashMultimap.create(); + if (slot == EntityEquipmentSlot.MAINHAND) + { + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", getDamageOfActivatedSword(stack), 0)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", this.getAttackSpeedOfSword(stack), 0)); + multimap.put(SharedMonsterAttributes.MAX_HEALTH.getAttributeUnlocalizedName(), new AttributeModifier(new UUID(0, 31818145), "Weapon modifier", this.getHealthBonusOfSword(stack), 0)); + multimap.put(SharedMonsterAttributes.MOVEMENT_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(new UUID(0, 4218052), "Weapon modifier", this.getSpeedOfSword(stack), 2)); + } + + return multimap; + } + + public double getDamageOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DAMAGE); + } + + public void setDamageOfActivatedSword(ItemStack stack, double damage) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DAMAGE, damage); + } + + public double getDrainOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_ACTIVE_DRAIN); + } + + public void setDrainOfActivatedSword(ItemStack stack, double drain) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_ACTIVE_DRAIN, drain); + } + + public double getStaticDropOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_STATIC_DROP); + } + + public void setStaticDropOfActivatedSword(ItemStack stack, double drop) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_STATIC_DROP, drop); + } + + public double getDropOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DROP); + } + + public void setDropOfActivatedSword(ItemStack stack, double drop) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DROP, drop); + } + + public double getHealthBonusOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_HEALTH); + } + + public void setHealthBonusOfSword(ItemStack stack, double hp) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_HEALTH, hp); + } + + public double getAttackSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_ATTACK_SPEED); + } + + public void setAttackSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_ATTACK_SPEED, speed); + } + + public double getSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_SPEED); + } + + public void setSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_SPEED, speed); + } + + public double getDigSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DIG_SPEED); + } + + public void setDigSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DIG_SPEED, speed); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientShovel.java b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientShovel.java new file mode 100644 index 00000000..8bddb2c3 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/item/soul/ItemSentientShovel.java @@ -0,0 +1,541 @@ +package WayofTime.bloodmagic.item.soul; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.ItemMeshDefinition; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.monster.EntitySlime; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemSpade; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import WayofTime.bloodmagic.BloodMagic; +import WayofTime.bloodmagic.api.Constants; +import WayofTime.bloodmagic.api.iface.IMultiWillTool; +import WayofTime.bloodmagic.api.iface.ISentientSwordEffectProvider; +import WayofTime.bloodmagic.api.soul.EnumDemonWillType; +import WayofTime.bloodmagic.api.soul.IDemonWill; +import WayofTime.bloodmagic.api.soul.IDemonWillWeapon; +import WayofTime.bloodmagic.api.soul.PlayerDemonWillHandler; +import WayofTime.bloodmagic.api.util.helper.NBTHelper; +import WayofTime.bloodmagic.client.IMeshProvider; +import WayofTime.bloodmagic.client.mesh.CustomMeshDefinitionMultiWill; +import WayofTime.bloodmagic.registry.ModItems; +import WayofTime.bloodmagic.util.helper.TextHelper; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +public class ItemSentientShovel extends ItemSpade implements IDemonWillWeapon, IMeshProvider, IMultiWillTool +{ + public static int[] soulBracket = new int[] { 16, 60, 200, 400, 1000 }; + public static double[] defaultDamageAdded = new double[] { 1, 2, 3, 3.5, 4 }; + public static double[] destructiveDamageAdded = new double[] { 2, 3, 4, 5, 6 }; + public static double[] vengefulDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 }; + public static double[] steadfastDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 }; + public static double[] defaultDigSpeedAdded = new double[] { 1, 1.5, 2, 3, 4 }; + public static double[] soulDrainPerSwing = new double[] { 0.05, 0.1, 0.2, 0.4, 0.75 }; + public static double[] soulDrop = new double[] { 2, 4, 7, 10, 13 }; + public static double[] staticDrop = new double[] { 1, 1, 2, 3, 3 }; + + public static double[] healthBonus = new double[] { 0, 0, 0, 0, 0 }; //TODO: Think of implementing this later + public static double[] vengefulAttackSpeed = new double[] { -3, -2.8, -2.7, -2.6, -2.5 }; + public static double[] destructiveAttackSpeed = new double[] { -3.1, -3.1, -3.2, -3.3, -3.3 }; + + public static int[] absorptionTime = new int[] { 200, 300, 400, 500, 600 }; + + public static double maxAbsorptionHearts = 10; + + public static int[] poisonTime = new int[] { 25, 50, 60, 80, 100 }; + public static int[] poisonLevel = new int[] { 0, 0, 0, 1, 1 }; + + public static double[] movementSpeed = new double[] { 0.05, 0.1, 0.15, 0.2, 0.25 }; + + public final double baseAttackDamage = 3; + public final double baseAttackSpeed = -2.8; + + public ItemSentientShovel() + { + super(Item.ToolMaterial.IRON); + setMaxDamage(getMaxDamage() * 2); +// super(ModItems.soulToolMaterial); + + setUnlocalizedName(Constants.Mod.MODID + ".sentientShovel"); + setCreativeTab(BloodMagic.tabBloodMagic); + } + + @Override + public float getStrVsBlock(ItemStack stack, IBlockState state) + { + float value = super.getStrVsBlock(stack, state); + if (value > 1) + { + return (float) (value + getDigSpeedOfSword(stack)); + } else + { + return value; + } + } + + @Override + public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) + { + return ModItems.itemDemonCrystal == repair.getItem() ? true : super.getIsRepairable(toRepair, repair); + } + + public void recalculatePowers(ItemStack stack, World world, EntityPlayer player) + { + EnumDemonWillType type = PlayerDemonWillHandler.getLargestWillType(player); + double soulsRemaining = PlayerDemonWillHandler.getTotalDemonWill(type, player); + this.setCurrentType(stack, soulsRemaining > 0 ? type : EnumDemonWillType.DEFAULT); + int level = getLevel(stack, soulsRemaining); + + double drain = level >= 0 ? soulDrainPerSwing[level] : 0; + double extraDamage = getExtraDamage(type, level); + + setDrainOfActivatedSword(stack, drain); + setDamageOfActivatedSword(stack, baseAttackDamage + extraDamage); + setStaticDropOfActivatedSword(stack, level >= 0 ? staticDrop[level] : 1); + setDropOfActivatedSword(stack, level >= 0 ? soulDrop[level] : 0); + setAttackSpeedOfSword(stack, level >= 0 ? getAttackSpeed(type, level) : baseAttackSpeed); + setHealthBonusOfSword(stack, level >= 0 ? getHealthBonus(type, level) : 0); + setSpeedOfSword(stack, level >= 0 ? getMovementSpeed(type, level) : 0); + setDigSpeedOfSword(stack, level >= 0 ? getDigSpeed(type, level) : 0); + } + + public double getExtraDamage(EnumDemonWillType type, int willBracket) + { + if (willBracket < 0) + { + return 0; + } + + switch (type) + { + case CORROSIVE: + case DEFAULT: + return defaultDamageAdded[willBracket]; + case DESTRUCTIVE: + return destructiveDamageAdded[willBracket]; + case VENGEFUL: + return vengefulDamageAdded[willBracket]; + case STEADFAST: + return steadfastDamageAdded[willBracket]; + } + + return 0; + } + + public double getAttackSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: + return vengefulAttackSpeed[willBracket]; + case DESTRUCTIVE: + return destructiveAttackSpeed[willBracket]; + default: + return -2.9; + } + } + + public double getHealthBonus(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case STEADFAST: + return healthBonus[willBracket]; + default: + return 0; + } + } + + public double getMovementSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: + return movementSpeed[willBracket]; + default: + return 0; + } + } + + public double getDigSpeed(EnumDemonWillType type, int willBracket) + { + switch (type) + { + case VENGEFUL: +// return movementSpeed[willBracket]; + default: + return defaultDigSpeedAdded[willBracket]; + } + } + + public void applyEffectToEntity(EnumDemonWillType type, int willBracket, EntityLivingBase target, EntityPlayer attacker) + { + switch (type) + { + case CORROSIVE: + target.addPotionEffect(new PotionEffect(MobEffects.WITHER, poisonTime[willBracket], poisonLevel[willBracket])); + break; + case DEFAULT: + break; + case DESTRUCTIVE: + break; + case STEADFAST: + if (!target.isEntityAlive()) + { + float absorption = attacker.getAbsorptionAmount(); + attacker.addPotionEffect(new PotionEffect(MobEffects.ABSORPTION, absorptionTime[willBracket], 127)); + attacker.setAbsorptionAmount((float) Math.min(absorption + target.getMaxHealth() * 0.05f, maxAbsorptionHearts)); + } + break; + case VENGEFUL: + break; + } + } + + @Override + public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) + { + if (super.hitEntity(stack, target, attacker)) + { + if (attacker instanceof EntityPlayer) + { + EntityPlayer attackerPlayer = (EntityPlayer) attacker; + this.recalculatePowers(stack, attackerPlayer.worldObj, attackerPlayer); + EnumDemonWillType type = this.getCurrentType(stack); + double will = PlayerDemonWillHandler.getTotalDemonWill(type, attackerPlayer); + int willBracket = this.getLevel(stack, will); + + applyEffectToEntity(type, willBracket, target, attackerPlayer); + + ItemStack offStack = attackerPlayer.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND); + if (offStack != null && offStack.getItem() instanceof ISentientSwordEffectProvider) + { + ISentientSwordEffectProvider provider = (ISentientSwordEffectProvider) offStack.getItem(); + if (provider.providesEffectForWill(type)) + { + provider.applyOnHitEffect(type, stack, offStack, attacker, target); + } + } + } + + return true; + } + + return false; + } + + @Override + public EnumDemonWillType getCurrentType(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + if (!tag.hasKey(Constants.NBT.WILL_TYPE)) + { + return EnumDemonWillType.DEFAULT; + } + + return EnumDemonWillType.valueOf(tag.getString(Constants.NBT.WILL_TYPE)); + } + + public void setCurrentType(ItemStack stack, EnumDemonWillType type) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setString(Constants.NBT.WILL_TYPE, type.toString()); + } + + @Override + public ActionResult onItemRightClick(ItemStack stack, World world, EntityPlayer player, EnumHand hand) + { + recalculatePowers(stack, world, player); + + return super.onItemRightClick(stack, world, player, hand); + } + + @Override + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) + { + return oldStack.getItem() != newStack.getItem(); + } + + private int getLevel(ItemStack stack, double soulsRemaining) + { + int lvl = -1; + for (int i = 0; i < soulBracket.length; i++) + { + if (soulsRemaining >= soulBracket[i]) + { + lvl = i; + } + } + + return lvl; + } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, EntityPlayer player, List tooltip, boolean advanced) + { + NBTHelper.checkNBT(stack); + + tooltip.addAll(Arrays.asList(TextHelper.cutLongString(TextHelper.localizeEffect("tooltip.BloodMagic.sentientShovel.desc")))); + + tooltip.add(TextHelper.localizeEffect("tooltip.BloodMagic.currentType." + getCurrentType(stack).getName().toLowerCase())); + } + + @Override + public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) + { + recalculatePowers(stack, player.worldObj, player); + + double drain = this.getDrainOfActivatedSword(stack); + if (drain > 0) + { + EnumDemonWillType type = getCurrentType(stack); + double soulsRemaining = PlayerDemonWillHandler.getTotalDemonWill(type, player); + + if (drain > soulsRemaining) + { + return false; + } else + { + PlayerDemonWillHandler.consumeDemonWill(type, player, drain); + } + } + + return super.onLeftClickEntity(stack, player, entity); + } + + @Override + @SideOnly(Side.CLIENT) + public ItemMeshDefinition getMeshDefinition() + { + return new CustomMeshDefinitionMultiWill("ItemSentientShovel"); + } + + @Nullable + @Override + public ResourceLocation getCustomLocation() + { + return null; + } + + @Override + public List getVariants() + { + List ret = new ArrayList(); + for (EnumDemonWillType type : EnumDemonWillType.values()) + { + ret.add("type=" + type.getName().toLowerCase()); + } + + return ret; + } + + @Override + public List getRandomDemonWillDrop(EntityLivingBase killedEntity, EntityLivingBase attackingEntity, ItemStack stack, int looting) + { + List soulList = new ArrayList(); + + if (killedEntity.worldObj.getDifficulty() != EnumDifficulty.PEACEFUL && !(killedEntity instanceof IMob)) + { + return soulList; + } + + double willModifier = killedEntity instanceof EntitySlime ? 0.67 : 1; + + IDemonWill soul = ((IDemonWill) ModItems.monsterSoul); + + for (int i = 0; i <= looting; i++) + { + if (i == 0 || attackingEntity.worldObj.rand.nextDouble() < 0.4) + { + ItemStack soulStack = soul.createWill(0, willModifier * (this.getDropOfActivatedSword(stack) * attackingEntity.worldObj.rand.nextDouble() + this.getStaticDropOfActivatedSword(stack)) * killedEntity.getMaxHealth() / 20d); + soulList.add(soulStack); + } + } + + return soulList; + } + + //TODO: Change attack speed. + @Override + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) + { + Multimap multimap = HashMultimap.create(); + if (slot == EntityEquipmentSlot.MAINHAND) + { + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", getDamageOfActivatedSword(stack), 0)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", this.getAttackSpeedOfSword(stack), 0)); + multimap.put(SharedMonsterAttributes.MAX_HEALTH.getAttributeUnlocalizedName(), new AttributeModifier(new UUID(0, 31818145), "Weapon modifier", this.getHealthBonusOfSword(stack), 0)); + multimap.put(SharedMonsterAttributes.MOVEMENT_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(new UUID(0, 4218052), "Weapon modifier", this.getSpeedOfSword(stack), 2)); + } + + return multimap; + } + + public double getDamageOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DAMAGE); + } + + public void setDamageOfActivatedSword(ItemStack stack, double damage) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DAMAGE, damage); + } + + public double getDrainOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_ACTIVE_DRAIN); + } + + public void setDrainOfActivatedSword(ItemStack stack, double drain) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_ACTIVE_DRAIN, drain); + } + + public double getStaticDropOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_STATIC_DROP); + } + + public void setStaticDropOfActivatedSword(ItemStack stack, double drop) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_STATIC_DROP, drop); + } + + public double getDropOfActivatedSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DROP); + } + + public void setDropOfActivatedSword(ItemStack stack, double drop) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DROP, drop); + } + + public double getHealthBonusOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_HEALTH); + } + + public void setHealthBonusOfSword(ItemStack stack, double hp) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_HEALTH, hp); + } + + public double getAttackSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_ATTACK_SPEED); + } + + public void setAttackSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_ATTACK_SPEED, speed); + } + + public double getSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_SPEED); + } + + public void setSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_SPEED, speed); + } + + public double getDigSpeedOfSword(ItemStack stack) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + return tag.getDouble(Constants.NBT.SOUL_SWORD_DIG_SPEED); + } + + public void setDigSpeedOfSword(ItemStack stack, double speed) + { + NBTHelper.checkNBT(stack); + + NBTTagCompound tag = stack.getTagCompound(); + + tag.setDouble(Constants.NBT.SOUL_SWORD_DIG_SPEED, speed); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/registry/ModItems.java b/src/main/java/WayofTime/bloodmagic/registry/ModItems.java index bc0f0fac..c4030034 100644 --- a/src/main/java/WayofTime/bloodmagic/registry/ModItems.java +++ b/src/main/java/WayofTime/bloodmagic/registry/ModItems.java @@ -69,7 +69,10 @@ import WayofTime.bloodmagic.item.sigil.ItemSigilWater; import WayofTime.bloodmagic.item.sigil.ItemSigilWhirlwind; import WayofTime.bloodmagic.item.soul.ItemMonsterSoul; import WayofTime.bloodmagic.item.soul.ItemSentientArmourGem; +import WayofTime.bloodmagic.item.soul.ItemSentientAxe; import WayofTime.bloodmagic.item.soul.ItemSentientBow; +import WayofTime.bloodmagic.item.soul.ItemSentientPickaxe; +import WayofTime.bloodmagic.item.soul.ItemSentientShovel; import WayofTime.bloodmagic.item.soul.ItemSentientSword; import WayofTime.bloodmagic.item.soul.ItemSoulGem; import WayofTime.bloodmagic.item.soul.ItemSoulSnare; @@ -154,6 +157,9 @@ public class ModItems public static Item sentientSword; public static Item sentientBow; public static Item sentientArmourGem; + public static Item sentientAxe; + public static Item sentientPickaxe; + public static Item sentientShovel; public static Item nodeRouter; public static Item baseItemFilter; @@ -252,6 +258,9 @@ public class ModItems sentientSword = registerItem(new ItemSentientSword(), Constants.BloodMagicItem.SENTIENT_SWORD.getRegName()); sentientBow = registerItem(new ItemSentientBow(), Constants.BloodMagicItem.SENTIENT_BOW.getRegName()); sentientArmourGem = registerItem(new ItemSentientArmourGem(), Constants.BloodMagicItem.SENTIENT_ARMOR_GEM.getRegName()); + sentientAxe = registerItem(new ItemSentientAxe(), Constants.BloodMagicItem.SENTIENT_AXE.getRegName()); + sentientPickaxe = registerItem(new ItemSentientPickaxe(), Constants.BloodMagicItem.SENTIENT_PICKAXE.getRegName()); + sentientShovel = registerItem(new ItemSentientShovel(), Constants.BloodMagicItem.SENTIENT_SHOVEL.getRegName()); nodeRouter = registerItem(new ItemNodeRouter(), Constants.BloodMagicItem.NODE_ROUTER.getRegName()); baseItemFilter = registerItem(new ItemRouterFilter(), Constants.BloodMagicItem.ROUTER_FILTER.getRegName()); diff --git a/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java b/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java index de94b558..4fb10e9f 100644 --- a/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java +++ b/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java @@ -247,6 +247,9 @@ public class ModRecipes TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.soulGem, 1, 3), 1000, 100, new ItemStack(ModItems.soulGem, 1, 2), new ItemStack(ModItems.slate, 1, 3), new ItemStack(ModItems.bloodShard), ItemDemonCrystal.getStack(ItemDemonCrystal.CRYSTAL_DEFAULT)); TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.soulGem, 1, 4), 4000, 500, new ItemStack(ModItems.soulGem, 1, 3), Items.NETHER_STAR); TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.sentientSword), 0, 0, new ItemStack(ModItems.soulGem), new ItemStack(Items.IRON_SWORD)); + TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.sentientAxe), 0, 0, new ItemStack(ModItems.soulGem), new ItemStack(Items.IRON_AXE)); + TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.sentientPickaxe), 0, 0, new ItemStack(ModItems.soulGem), new ItemStack(Items.IRON_PICKAXE)); + TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.sentientShovel), 0, 0, new ItemStack(ModItems.soulGem), new ItemStack(Items.IRON_SHOVEL)); TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.sentientBow), 70, 0, new ItemStack(Items.BOW), new ItemStack(ModItems.soulGem, 1, 1), Items.STRING, Items.STRING); TartaricForgeRecipeRegistry.registerRecipe(new ItemStack(ModItems.arcaneAshes), 0, 0, "dustRedstone", "dyeWhite", new ItemStack(Items.GUNPOWDER), Items.COAL); TartaricForgeRecipeRegistry.registerRecipe(ItemComponent.getStack(ItemComponent.REAGENT_WATER), 10, 3, new ItemStack(Items.SUGAR), new ItemStack(Items.WATER_BUCKET), new ItemStack(Items.WATER_BUCKET)); diff --git a/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientAxe.json b/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientAxe.json new file mode 100644 index 00000000..f93f679a --- /dev/null +++ b/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientAxe.json @@ -0,0 +1,36 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "builtin/generated", + "transform": "forge:default-tool" + }, + "variants": { + "type": { + "default": { + "textures": { + "layer0": "bloodmagic:items/SoulAxe" + } + }, + "corrosive": { + "textures": { + "layer0": "bloodmagic:items/SoulAxe_corrosive" + } + }, + "destructive": { + "textures": { + "layer0": "bloodmagic:items/SoulAxe_destructive" + } + }, + "vengeful": { + "textures": { + "layer0": "bloodmagic:items/SoulAxe_vengeful" + } + }, + "steadfast": { + "textures": { + "layer0": "bloodmagic:items/SoulAxe_steadfast" + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientPickaxe.json b/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientPickaxe.json new file mode 100644 index 00000000..fdf1b224 --- /dev/null +++ b/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientPickaxe.json @@ -0,0 +1,36 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "builtin/generated", + "transform": "forge:default-tool" + }, + "variants": { + "type": { + "default": { + "textures": { + "layer0": "bloodmagic:items/SoulPickaxe" + } + }, + "corrosive": { + "textures": { + "layer0": "bloodmagic:items/SoulPickaxe_corrosive" + } + }, + "destructive": { + "textures": { + "layer0": "bloodmagic:items/SoulPickaxe_destructive" + } + }, + "vengeful": { + "textures": { + "layer0": "bloodmagic:items/SoulPickaxe_vengeful" + } + }, + "steadfast": { + "textures": { + "layer0": "bloodmagic:items/SoulPickaxe_steadfast" + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientShovel.json b/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientShovel.json new file mode 100644 index 00000000..fe56d96d --- /dev/null +++ b/src/main/resources/assets/bloodmagic/blockstates/item/ItemSentientShovel.json @@ -0,0 +1,36 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "builtin/generated", + "transform": "forge:default-tool" + }, + "variants": { + "type": { + "default": { + "textures": { + "layer0": "bloodmagic:items/SoulShovel" + } + }, + "corrosive": { + "textures": { + "layer0": "bloodmagic:items/SoulShovel_corrosive" + } + }, + "destructive": { + "textures": { + "layer0": "bloodmagic:items/SoulShovel_destructive" + } + }, + "vengeful": { + "textures": { + "layer0": "bloodmagic:items/SoulShovel_vengeful" + } + }, + "steadfast": { + "textures": { + "layer0": "bloodmagic:items/SoulShovel_steadfast" + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bloodmagic/lang/en_US.lang b/src/main/resources/assets/bloodmagic/lang/en_US.lang index e470e5e3..96dcc6d7 100644 --- a/src/main/resources/assets/bloodmagic/lang/en_US.lang +++ b/src/main/resources/assets/bloodmagic/lang/en_US.lang @@ -156,6 +156,9 @@ item.BloodMagic.soulGem.grand.name=Grand Tartaric Gem item.BloodMagic.soulSnare.base.name=Rudimentary Snare item.BloodMagic.sentientBow.name=Sentient Bow item.BloodMagic.sentientArmourGem.name=Sentient Armour Gem +item.BloodMagic.sentientAxe.name=Sentient Axe +item.BloodMagic.sentientPickaxe.name=Sentient Pickaxe +item.BloodMagic.sentientShovel.name=Sentient Shovel item.BloodMagic.nodeRouter.name=Node Router item.BloodMagic.itemFilter.exact.name=Precise Item Filter @@ -359,6 +362,9 @@ tooltip.BloodMagic.livingArmour.upgrade.points=&6Upgrade points: %s / %s tooltip.BloodMagic.will=Will Quality: %1$,.2f tooltip.BloodMagic.sentientSword.desc=Uses demon will to unleash its full potential. +tooltip.BloodMagic.sentientAxe.desc=Uses demon will to unleash its full potential. +tooltip.BloodMagic.sentientPickaxe.desc=Uses demon will to unleash its full potential. +tooltip.BloodMagic.sentientShovel.desc=Uses demon will to unleash its full potential. tooltip.BloodMagic.soulGem.petty=A gem used to contain a little will tooltip.BloodMagic.soulGem.lesser=A gem used to contain some will tooltip.BloodMagic.soulGem.common=A gem used to contain more will diff --git a/src/main/resources/assets/bloodmagic/textures/items/SoulAxe_steafast.png b/src/main/resources/assets/bloodmagic/textures/items/SoulAxe_steadfast.png similarity index 100% rename from src/main/resources/assets/bloodmagic/textures/items/SoulAxe_steafast.png rename to src/main/resources/assets/bloodmagic/textures/items/SoulAxe_steadfast.png