package slimeknights.tconstruct.tools.modifiers; import net.minecraft.block.state.IBlockState; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Enchantments; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import slimeknights.tconstruct.library.modifiers.IModifier; import slimeknights.tconstruct.library.modifiers.ModifierAspect; import slimeknights.tconstruct.library.modifiers.ModifierNBT; import slimeknights.tconstruct.library.modifiers.ModifierTrait; import slimeknights.tconstruct.library.modifiers.TinkerGuiException; import slimeknights.tconstruct.library.tinkering.Category; import slimeknights.tconstruct.library.utils.TagUtil; import slimeknights.tconstruct.library.utils.TinkerUtil; import slimeknights.tconstruct.library.utils.ToolBuilder; public class ModLuck extends ModifierTrait { protected static final int baseCount = 60; protected static final int maxLevel = 3; // we have a bit of redundancy going on here with the luckAspect and the trait class private final LuckAspect aspect; public ModLuck() { super("luck", 0x2d51e2, maxLevel, 0); aspects.clear(); aspect = new LuckAspect(this); addAspects(aspect, new ModifierAspect.CategoryAnyAspect(Category.HARVEST, Category.WEAPON, Category.PROJECTILE)); } public int getLuckLevel(ItemStack itemStack) { return getLuckLevel(TinkerUtil.getModifierTag(itemStack, getModifierIdentifier())); } public int getLuckLevel(NBTTagCompound modifierTag) { ModifierNBT.IntegerNBT data = ModifierNBT.readInteger(modifierTag); return aspect.getLevel(data.current); } @Override public boolean canApplyTogether(Enchantment enchantment) { return enchantment != Enchantments.SILK_TOUCH; } @Override public void applyEffect(NBTTagCompound rootCompound, NBTTagCompound modifierTag) { super.applyEffect(rootCompound, modifierTag); int lvl = getLuckLevel(modifierTag); applyEnchantments(rootCompound, lvl); } @Override public void afterBlockBreak(ItemStack tool, World world, IBlockState state, BlockPos pos, EntityLivingBase player, boolean wasEffective) { rewardProgress(tool); } @Override public void afterHit(ItemStack tool, EntityLivingBase player, EntityLivingBase target, float damageDealt, boolean wasCritical, boolean wasHit) { if(player.world.isRemote || !wasHit) { return; } // we reward one chance per full heart damage dealt. No chance for 0.5 heart hits, sorry :( for(int i = (int) (damageDealt / 2f); i > 0; i--) { rewardProgress(tool); } } public void rewardProgress(ItemStack tool) { // 3% chance if(random.nextFloat() > 0.03f) { return; } try { if(canApply(tool, tool)) { apply(tool); } } catch(TinkerGuiException e) { // no user feedback } } protected void applyEnchantments(NBTTagCompound rootCompound, int lvl) { boolean harvest = false; boolean weapon = false; lvl = Math.min(lvl, Enchantments.LOOTING.getMaxLevel()); for(Category category : TagUtil.getCategories(rootCompound)) { if(category == Category.HARVEST) { harvest = true; } if(category == Category.WEAPON) { weapon = true; } } // weapons get looting if(weapon) { while(lvl > ToolBuilder.getEnchantmentLevel(rootCompound, Enchantments.LOOTING)) { ToolBuilder.addEnchantment(rootCompound, Enchantments.LOOTING); } } // harvest tools get fortune if(harvest) { while(lvl > ToolBuilder.getEnchantmentLevel(rootCompound, Enchantments.FORTUNE)) { ToolBuilder.addEnchantment(rootCompound, Enchantments.FORTUNE); } } } @Override public String getTooltip(NBTTagCompound modifierTag, boolean detailed) { int level = getLuckLevel(modifierTag); String tooltip = getLocalizedName(); if(level > 0) { tooltip += " " + TinkerUtil.getRomanNumeral(level); } if(detailed) { ModifierNBT data = ModifierNBT.readInteger(modifierTag); tooltip += " " + data.extraInfo; } return tooltip; } public static class LuckAspect extends ModifierAspect.MultiAspect { public LuckAspect(IModifier parent) { super(parent, 0x5a82e2, maxLevel, baseCount, 1); freeModifierAspect = new FreeFirstModifierAspect(parent, 1); } @Override protected int getMaxForLevel(int level) { return (countPerLevel * level * (level + 1)) / 2; // sum(n) } public int getLevel(int current) { int i = 0; while(current >= getMaxForLevel(i + 1)) { i++; } return i; } } }