/**
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 java.util.UUID;
import net.minecraft.entity.Entity;
import net.minecraft.entity.INpc;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import zeldaswordskills.api.entity.CustomExplosion;
import zeldaswordskills.api.item.ArmorIndex;
import zeldaswordskills.api.item.IUnenchantable;
import zeldaswordskills.api.item.IZoomHelper;
import zeldaswordskills.creativetab.ZSSCreativeTabs;
import zeldaswordskills.entity.DirtyEntityAccessor;
import zeldaswordskills.entity.ZSSEntityInfo;
import zeldaswordskills.entity.ZSSVillagerInfo;
import zeldaswordskills.entity.ZSSVillagerInfo.EnumVillager;
import zeldaswordskills.entity.buff.Buff;
import zeldaswordskills.entity.npc.EntityNpcMaskTrader;
import zeldaswordskills.entity.player.ZSSPlayerInfo;
import zeldaswordskills.entity.player.quests.IQuest;
import zeldaswordskills.entity.player.quests.QuestMaskSales;
import zeldaswordskills.entity.player.quests.ZSSQuests;
import zeldaswordskills.entity.projectile.EntityBomb;
import zeldaswordskills.network.PacketDispatcher;
import zeldaswordskills.network.client.SyncQuestPacket;
import zeldaswordskills.ref.Sounds;
import zeldaswordskills.util.PlayerUtils;
import zeldaswordskills.util.TimedChatDialogue;
/**
*
* All types of Masks should use or extend this class
*
*/
public class ItemMask extends ItemModArmor implements IUnenchantable, IZoomHelper
{
/** Effect to add every 50 ticks */
protected PotionEffect tickingEffect = null;
/** Number of rupees to pay back to the Happy Mask Salesman */
private int buyPrice;
/** Number of rupees a villager will pay for this mask */
private int sellPrice;
/**
* Armor types as used on player: 0 boots, 1 legs, 2 chest, 3 helm
* Armor types as used in armor class: 0 helm, 1 chest, 2 legs, 3 boots
*/
public ItemMask(ArmorMaterial material, int renderIndex) {
super(material, renderIndex, ArmorIndex.TYPE_HELM);
setMaxDamage(0);
setCreativeTab(ZSSCreativeTabs.tabMasks);
}
/**
* Sets the buy and sell price for this mask; only for masks in the trading sequence
* @param buy price the player will pay for the mask
* @param sell price the player will receive for selling the mask
*/
public ItemMask setPrice(int buy, int sell) {
buyPrice = buy;
sellPrice = sell;
return this;
}
/** The number of rupees to pay back to the Happy Mask Salesman */
public int getBuyPrice() {
return buyPrice > 0 ? buyPrice : 16;
}
/** The number of rupees a villager will pay for this mask */
public int getSellPrice() {
return sellPrice > 0 ? sellPrice : 16;
}
/**
* Sets this mask to grant the specified potion effect every 50 ticks
*/
public ItemMask setEffect(PotionEffect effect) {
tickingEffect = effect;
return this;
}
@Override
@SideOnly(Side.CLIENT)
public float getMagnificationFactor() {
return 0.0F;
}
@Override
public void onArmorTick(World world, EntityPlayer player, ItemStack stack) {
ZSSPlayerInfo info = ZSSPlayerInfo.get(player);
if (!info.getFlag(ZSSPlayerInfo.IS_WEARING_HELM)) {
info.setWearingHelm(stack);
}
if (tickingEffect != null && world.getTotalWorldTime() % 50 == 0) {
player.addPotionEffect(new PotionEffect(tickingEffect));
}
}
@Override
public int getItemEnchantability() {
return 0;
}
@Override
public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) {
if (player.worldObj.isRemote) {
return true;
} else if (entity instanceof EntityNpcMaskTrader && ZSSQuests.get(player).hasCompleted(QuestMaskSales.class)) {
if (this == ZSSQuests.get(player).getBorrowedMask()) {
player.setCurrentItemOrArmor(0, null);
ZSSQuests.get(player).setBorrowedMask(null);
PlayerUtils.playSound(player, Sounds.POP, 1.0F, ((player.worldObj.rand.nextFloat() - player.worldObj.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
PlayerUtils.sendTranslatedChat(player, "chat.zss.npc.mask_salesman.returned");
}
} else if (entity instanceof EntityVillager) {
IQuest quest = ZSSQuests.get(player).get(QuestMaskSales.class);
EntityVillager villager = (EntityVillager) entity;
if (quest != null && ZSSVillagerInfo.get(villager).getMaskDesired() == this) {
// send extra parameter for left-click, then check if it needs to be sync'ed
if (quest.update(player, this, true) && quest.requiresSync() && player instanceof EntityPlayerMP) {
PacketDispatcher.sendTo(new SyncQuestPacket(quest), (EntityPlayerMP) player);
}
} else {
PlayerUtils.sendTranslatedChat(player, "chat.zss.mask.refuse." + player.worldObj.rand.nextInt(4));
}
}
return true;
}
/**
* Called when the player right-clicks on an entity while wearing a mask
* @return returning true will cancel the interact event (preventing trade
* gui from opening for villagers, for example)
*/
public boolean onInteract(ItemStack stack, EntityPlayer player, Entity entity) {
if (!player.worldObj.isRemote) {
if (entity instanceof EntityVillager) {
EntityVillager villager = (EntityVillager) entity;
if (entity.getClass() == EntityVillager.class && this == ZSSVillagerInfo.get(villager).getMaskDesired()) {
QuestMaskSales quest = (QuestMaskSales) ZSSQuests.get(player).get(QuestMaskSales.class);
if (!quest.hasSold(this)) {
new TimedChatDialogue(player,
new ChatComponentTranslation("chat.zss.npc.mask_salesman.sales.buyer.0"),
new ChatComponentTranslation("chat.zss.npc.mask_salesman.sales.buyer.1", getSellPrice()));
} else { // player already sold this mask
PlayerUtils.sendTranslatedChat(player, "chat.zss.npc.mask_salesman.sales.repeat." + player.worldObj.rand.nextInt(4));
}
} else {
// Custom villager professions all use the same chat message
int p = villager.getProfession();
String s = (p < 0 || p > EnumVillager.values().length) ? "custom" : String.valueOf(p);
PlayerUtils.sendTranslatedChat(player, "chat." + getUnlocalizedName().substring(5) + "." + s);
}
} else if (entity instanceof EntityNpcMaskTrader) {
PlayerUtils.sendTranslatedChat(player, "chat." + getUnlocalizedName().substring(5) + ".salesman");
} else if (entity instanceof INpc) {
PlayerUtils.sendTranslatedChat(player, "chat." + getUnlocalizedName().substring(5) + ".custom");
} else {
return false;
}
}
return true;
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, EntityPlayer player, List<String> list, boolean advanced) {
list.add(EnumChatFormatting.ITALIC + StatCollector.translateToLocal("tooltip." + getUnlocalizedName().substring(5) + ".desc.0"));
}
/**
* Applies modifiers for masks when equipped, first calling {@link #removeModifiers},
* then adding any potion effect, and finally calling {@link #applyCustomModifiers}
*/
public final void applyModifiers(ItemStack stack, EntityPlayer player) {
removeModifiers(stack, player);
if (tickingEffect != null) {
player.addPotionEffect(new PotionEffect(tickingEffect));
}
applyCustomModifiers(stack, player);
}
/**
* Called from {@link ItemMask#applyModifiers} to add any special modifiers when equipped
*/
protected void applyCustomModifiers(ItemStack stack, EntityPlayer player) {}
/**
* Called when a mask is unequipped to remove any modifiers
*/
public void removeModifiers(ItemStack stack, EntityPlayer player) {}
/**
* Used by the Blast Mask to cause an explosion; sets a short cooldown on the stack
*/
public void explode(EntityPlayer player, ItemStack stack, World world, double x, double y, double z) {}
//======================================================================//
// Static inner classes for Masks with custom behaviors //
//======================================================================//
public static class ItemMaskBlast extends ItemMask {
public ItemMaskBlast(ArmorMaterial material, int renderIndex) {
super(material, renderIndex);
}
@Override
public void explode(EntityPlayer player, ItemStack stack, World world, double x, double y, double z) {
if (player.capabilities.isCreativeMode || !isCooling(world, stack)) {
CustomExplosion.createExplosion(new EntityBomb(world), world, x, y, z, 3.0F, 10.0F, false);
setNextUse(world, stack, 40);
} else {
world.playSoundEffect(x, y, z, Sounds.CLICK, 0.3F, 0.6F);
}
}
/**
* Returns true if this Mask is cooling down
*/
private boolean isCooling(World world, ItemStack stack) {
return (stack.hasTagCompound() && world.getTotalWorldTime() < stack.getTagCompound().getInteger("nextUse"));
}
/**
* Sets the time, in ticks, which must pass before the stack may be used again
*/
private void setNextUse(World world, ItemStack stack, int time) {
if (!stack.hasTagCompound()) { stack.setTagCompound(new NBTTagCompound()); }
stack.getTagCompound().setLong("nextUse", world.getTotalWorldTime() + time);
}
}
public static class ItemMaskBunny extends ItemMask
{
/** Movement bonus for wearing the Bunny Hood */
private static final UUID bunnyHoodMoveBonusUUID = UUID.fromString("8412C9F7-9645-4C24-8FD1-6EFB8282E822");
private static final AttributeModifier bunnyHoodMoveBonus = (new AttributeModifier(bunnyHoodMoveBonusUUID, "Bunny Hood Speed Bonus", 0.3D, 2)).setSaved(false);
public ItemMaskBunny(ArmorMaterial material, int renderIndex) {
super(material, renderIndex);
}
@Override
public void applyCustomModifiers(ItemStack stack, EntityPlayer player) {
player.getEntityAttribute(SharedMonsterAttributes.movementSpeed).applyModifier(bunnyHoodMoveBonus);
ZSSPlayerInfo.get(player).setFlag(ZSSPlayerInfo.MOBILITY, true);
ZSSEntityInfo.get(player).applyBuff(Buff.EVADE_UP, Integer.MAX_VALUE, 25);
}
@Override
public void removeModifiers(ItemStack stack, EntityPlayer player) {
player.getEntityAttribute(SharedMonsterAttributes.movementSpeed).removeModifier(bunnyHoodMoveBonus);
ZSSPlayerInfo.get(player).setFlag(ZSSPlayerInfo.MOBILITY, true);
ZSSEntityInfo.get(player).removeBuff(Buff.EVADE_UP);
}
}
public static class ItemMaskCouples extends ItemMask {
public ItemMaskCouples(ArmorMaterial material, int renderIndex) {
super(material, renderIndex);
}
@Override
public void onArmorTick(World world, EntityPlayer player, ItemStack stack) {
super.onArmorTick(world, player, stack);
if (world.getTotalWorldTime() % 64 == 0) {
List<EntityVillager> villagers = world.getEntitiesWithinAABB(EntityVillager.class, player.getEntityBoundingBox().expand(8.0D, 3.0D, 8.0D));
for (EntityVillager villager : villagers) {
if (world.rand.nextFloat() < 0.5F) {
ZSSVillagerInfo.get(villager).setMating();
}
}
}
}
}
public static class ItemMaskGiants extends ItemMask {
public ItemMaskGiants(ArmorMaterial material, int renderIndex) {
super(material, renderIndex);
}
@Override
public void applyCustomModifiers(ItemStack stack, EntityPlayer player) {
/*
// TODO
DirtyEntityAccessor.setSize(player, player.width * 3.0F, player.height * 3.0F);
if (player.worldObj.isRemote) {
player.stepHeight += 1.0F;
}
*/
}
@Override
public void removeModifiers(ItemStack stack, EntityPlayer player) {
if (player.getEntityData().hasKey("origWidth")) {
DirtyEntityAccessor.restoreOriginalSize(player);
if (player.worldObj.isRemote) {
player.stepHeight -= 1.0F;
}
}
}
}
public static class ItemMaskGoron extends ItemMask {
public ItemMaskGoron(ArmorMaterial material, int renderIndex) {
super(material, renderIndex);
}
@Override
public void applyCustomModifiers(ItemStack stack, EntityPlayer player) {
ZSSEntityInfo.get(player).applyBuff(Buff.RESIST_FIRE, Integer.MAX_VALUE, 100);
}
@Override
public void removeModifiers(ItemStack stack, EntityPlayer player) {
ZSSEntityInfo.get(player).removeBuff(Buff.RESIST_FIRE);
}
}
public static class ItemMaskHawkeye extends ItemMask {
public ItemMaskHawkeye(ArmorMaterial material, int renderIndex) {
super(material, renderIndex);
}
@Override
@SideOnly(Side.CLIENT)
public float getMagnificationFactor() {
return 3.0F;
}
}
public static class ItemMaskMajora extends ItemMask {
public ItemMaskMajora(ArmorMaterial material, int renderIndex) {
super(material, renderIndex);
}
@Override
public void applyCustomModifiers(ItemStack stack, EntityPlayer player) {
ZSSEntityInfo.get(player).applyBuff(Buff.ATTACK_UP, Integer.MAX_VALUE, 100);
}
@Override
public void removeModifiers(ItemStack stack, EntityPlayer player) {
ZSSEntityInfo.get(player).removeBuff(Buff.ATTACK_UP);
}
}
}