/** Copyright (C) <2017> <coolAlias> This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package zeldaswordskills.item; import java.util.List; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityAgeable; import net.minecraft.entity.INpc; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import net.minecraft.util.StatCollector; import net.minecraft.village.MerchantRecipe; import net.minecraftforge.fml.common.eventhandler.Event.Result; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zeldaswordskills.api.entity.NpcHelper; import zeldaswordskills.api.item.IRightClickEntity; import zeldaswordskills.api.item.IUnenchantable; import zeldaswordskills.creativetab.ZSSCreativeTabs; import zeldaswordskills.entity.ZSSVillagerInfo; import zeldaswordskills.entity.npc.EntityNpcMaskTrader; import zeldaswordskills.entity.npc.EntityNpcOrca; import zeldaswordskills.entity.player.quests.IQuest; import zeldaswordskills.entity.player.quests.QuestBase; import zeldaswordskills.entity.player.quests.QuestBiggoronSword; import zeldaswordskills.entity.player.quests.QuestMaskSales; import zeldaswordskills.entity.player.quests.QuestMaskShop; import zeldaswordskills.entity.player.quests.ZSSQuests; import zeldaswordskills.ref.ModInfo; import zeldaswordskills.ref.Sounds; import zeldaswordskills.util.PlayerUtils; import zeldaswordskills.util.TimedAddItem; import zeldaswordskills.util.TimedChatDialogue; /** * * Rare items with no use other than as potential trades for upgrades * */ public class ItemTreasure extends BaseModItem implements IRightClickEntity, IUnenchantable { /** All the different treasure types */ public static enum Treasures { CLAIM_CHECK("claim_check", true), COJIRO("cojiro", true), EVIL_CRYSTAL("evil_crystal"), EYE_DROPS("eye_drops", true), EYEBALL_FROG("eyeball_frog", true), GORON_SWORD("goron_sword", true), JELLY_BLOB("jelly_blob", "generic", 32, 64, false), MONSTER_CLAW("monster_claw", "generic", 24, 64, false), ODD_MUSHROOM("odd_mushroom", true), ODD_POTION("odd_potion", true), POACHER_SAW("poacher_saw", true), POCKET_EGG("pocket_egg", true), PRESCRIPTION("prescription", true), TENTACLE("tentacle", "generic", 16, 64, true), ZELDAS_LETTER("zeldas_letter"), KNIGHTS_CREST("knights_crest", "knights_crest", 32, 64, false); public final String name; /** Unlocalized string used to retrieve chat comment when an NPC is not interested in trading */ public final String uninterested; private final int value; private final int maxStackSize; private final boolean isBiggoronTrade; private Treasures(String name) { this(name, "generic", 0, 1, false); } private Treasures(String name, boolean isBiggoronTrade) { this(name, "generic", 0, 1, isBiggoronTrade); } private Treasures(String name, int value) { this(name, "generic", value, 1, false); } private Treasures(String name, String uninterested, int value, int maxStackSize, boolean isBiggoronTrade) { this.name = name; this.uninterested = uninterested; this.value = value; this.maxStackSize = maxStackSize; this.isBiggoronTrade = isBiggoronTrade; } /** Whether this treasure is salable (currently used only for monster parts) */ public boolean canSell() { return value > 0; } /** The price at which the hunter will buy this treasure */ public int getValue() { return value; } /** The maximum stack size for this treasure */ public int getMaxStackSize() { return maxStackSize; } /** True for items that are part of Biggoron's Trading sequence */ public boolean isBiggoronTrade() { return isBiggoronTrade; } public static Treasures byDamage(int damage) { return values()[damage % values().length]; } }; public ItemTreasure() { super(); setMaxDamage(0); setMaxStackSize(1); setHasSubtypes(true); setCreativeTab(ZSSCreativeTabs.tabMisc); } @Override public int getItemStackLimit(ItemStack stack) { return Treasures.byDamage(stack.getItemDamage()).getMaxStackSize(); } @Override public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) { if (player.worldObj.isRemote) { return true; } else if (entity instanceof EntityNpcMaskTrader && ((EntityNpcMaskTrader) entity).checkShopStatus(player, false, true)) { return true; // allows quest to complete without having to convert a villager if Salesman already in town } else if (entity instanceof EntityVillager && Result.DEFAULT == NpcHelper.convertVillager(player, (EntityVillager) entity, false)) { // villager not converted, try other treasure interactions (note that conversion handles beginnings of several quests) handleTrade(stack, player, entity, true); } else if (entity instanceof INpc) { handleTrade(stack, player, entity, true); } return true; } @Override public boolean onRightClickEntity(ItemStack stack, EntityPlayer player, Entity entity) { return !player.worldObj.isRemote && handleTrade(stack, player, entity, false); } private boolean handleTrade(ItemStack stack, EntityPlayer player, Entity entity, boolean isLeftClick) { Treasures treasure = Treasures.byDamage(stack.getItemDamage()); if (treasure.isBiggoronTrade()) { return handleBiggoronQuest(stack, player, entity, isLeftClick); } else if (entity instanceof EntityVillager) { if (treasure == Treasures.ZELDAS_LETTER) { PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure." + treasure.name + (((EntityVillager) entity).isChild() ? ".child" : ".fail") + (isLeftClick ? ".give" : ".show")); } else if (!handleVillagerTrade(stack, player, (EntityVillager) entity, isLeftClick)) { PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure." + treasure.uninterested + ".uninterested"); } return true; } else if (entity instanceof INpc) { if (entity instanceof EntityAgeable && ((EntityAgeable) entity).isChild()) { handleChildTrade(stack, player, isLeftClick); } else if (treasure == Treasures.ZELDAS_LETTER && entity instanceof EntityNpcMaskTrader) { ZSSQuests quests = ZSSQuests.get(player); if (quests.hasCompleted(QuestMaskSales.class)) { PlayerUtils.sendTranslatedChat(player, "chat.zss.npc.mask_salesman.shop.open"); } else { IQuest quest = quests.get(QuestMaskShop.class); if (quest != null) { IChatComponent hint = quest.getHint(player); if (hint != null) { player.addChatMessage(hint); } } else { PlayerUtils.sendTranslatedChat(player, "chat.zss.npc.mask_salesman.shop.hint." + itemRand.nextInt(4)); } } } else if (treasure == Treasures.KNIGHTS_CREST && entity instanceof EntityNpcOrca) { PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure." + treasure.uninterested + ".uninterested.orca"); } else { PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure." + treasure.uninterested + ".uninterested"); } return true; } return false; } /** * Attempts to sell the item to a villager, returning true if any chat message occurred. * If the villager is a child, the child interaction is performed instead. * @return only false if {@link ZSSVillagerInfo#getTreasureTrade} returns null */ public boolean handleVillagerTrade(ItemStack stack, EntityPlayer player, EntityVillager villager, boolean isLeftClick) { Treasures treasure = Treasures.byDamage(stack.getItemDamage()); ZSSVillagerInfo villagerInfo = ZSSVillagerInfo.get(villager); MerchantRecipe trade = villagerInfo.getTreasureTrade(treasure); villager.playLivingSound(); if (villager.isChild()) { handleChildTrade(stack, player, isLeftClick); } else if (trade == null) { return false; } else if (isLeftClick) { // 1st item to buy is always the treasure itself, which is in hand and will be replaced ItemStack required = trade.getSecondItemToBuy(); if (required == null || PlayerUtils.consumeInventoryItem(player, required, required.stackSize)) { PlayerUtils.playSound(player, Sounds.SUCCESS, 1.0F, 1.0F); if (stack.stackSize > 1) { --stack.stackSize; PlayerUtils.addItemToInventory(player, trade.getItemToSell().copy()); } else { player.setCurrentItemOrArmor(0, trade.getItemToSell().copy()); } if (villagerInfo.isHunter()) { PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure.hunter.trade." + itemRand.nextInt(4)); } else { new TimedChatDialogue(player, 0, 500, new ChatComponentTranslation("chat.zss.treasure." + treasure.name + ".trade"), new ChatComponentTranslation("chat.zss.treasure.generic.received", new ChatComponentTranslation(trade.getItemToSell().getUnlocalizedName() + ".name"))); } } else { // can only be true when required stack is not null PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure.generic.trade.fail", required.stackSize, new ChatComponentTranslation(required.getUnlocalizedName() + ".name")); } } else if (villagerInfo.isHunter()) { new TimedChatDialogue(player, 0, 1000, new ChatComponentTranslation("chat.zss.treasure.hunter.interested.0", new ChatComponentTranslation(trade.getItemToBuy().getUnlocalizedName() + ".name")), new ChatComponentTranslation("chat.zss.treasure.hunter.interested.1", trade.getItemToSell().stackSize)); } else { PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure.generic.interested", new ChatComponentTranslation(trade.getItemToSell().getUnlocalizedName() + ".name")); } return true; } private boolean handleBiggoronQuest(ItemStack stack, EntityPlayer player, Entity entity, boolean isLeftClick) { ZSSQuests quests = ZSSQuests.get(player); IQuest quest = quests.get(QuestBiggoronSword.class); if (quest == null) { quest = new QuestBiggoronSword(); quests.add(quest); } if (QuestBase.checkQuestProgress(player, quest, QuestBase.DEFAULT_QUEST_HANDLER, entity, isLeftClick)) { return true; } else if (entity instanceof EntityVillager && ((EntityVillager) entity).isChild()) { handleChildTrade(stack, player, isLeftClick); // handle non-salable trading sequence treasures return true; } return false; } private void handleChildTrade(ItemStack stack, EntityPlayer player, boolean isLeftClick) { PlayerUtils.sendTranslatedChat(player, "chat.zss.treasure.generic.child" + (isLeftClick ? ".give" : ".show")); if (isLeftClick) { player.setCurrentItemOrArmor(0, null); if (itemRand.nextFloat() < 0.99F || Treasures.byDamage(stack.getItemDamage()).isBiggoronTrade()) { new TimedChatDialogue(player, 1500, 1250, new ChatComponentTranslation("chat.zss.treasure.generic.child.return")); new TimedAddItem(player, stack.copy(), 1500); } else { new TimedChatDialogue(player, 1500, 1250, new ChatComponentTranslation("chat.zss.treasure.generic.child.broken")); } } } @Override public String getUnlocalizedName(ItemStack stack) { return getUnlocalizedName() + "." + Treasures.byDamage(stack.getItemDamage()).name; } @Override public String[] getVariants() { String[] variants = new String[Treasures.values().length]; for (Treasures treasure : Treasures.values()) { variants[treasure.ordinal()] = ModInfo.ID + ":" + treasure.name; } return variants; } @Override @SideOnly(Side.CLIENT) public void getSubItems(Item item, CreativeTabs tab, List<ItemStack> list) { for (int i = 0; i < Treasures.values().length; ++i) { list.add(new ItemStack(item, 1, i)); } } @Override @SideOnly(Side.CLIENT) public void addInformation(ItemStack stack, EntityPlayer player, List<String> list, boolean advanced) { list.add(EnumChatFormatting.ITALIC + StatCollector.translateToLocal("tooltip." + getUnlocalizedName(stack).substring(5) + ".desc.0")); } }