package minefantasy.mf2.entity.mob;
import java.util.ArrayList;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import minefantasy.mf2.api.armour.IArmourPenetrationMob;
import minefantasy.mf2.api.armour.IArmouredEntity;
import minefantasy.mf2.api.helpers.ArmourCalculator;
import minefantasy.mf2.api.helpers.TacticalManager;
import minefantasy.mf2.config.ConfigMobs;
import minefantasy.mf2.item.list.ComponentListMF;
import minefantasy.mf2.item.list.ToolListMF;
import minefantasy.mf2.util.MFLogUtil;
import net.minecraft.block.Block;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackOnCollide;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveThroughVillage;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeModContainer;
public class EntityMinotaur extends EntityMob implements IArmouredEntity, IArmourPenetrationMob
{
public int swing;
private int grabCooldown;
public EntityMinotaur(World world)
{
super(world);
this.getNavigator().setBreakDoors(true);
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.0D, false));
this.tasks.addTask(4, new EntityAIAttackOnCollide(this, EntityVillager.class, 1.0D, true));
this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D));
this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false));
this.tasks.addTask(7, new EntityAIWander(this, 1.0D));
this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 0, true));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityVillager.class, 0, false));
this.setSize(1.5F, 3F);
this.stepHeight = 1.0F;
this.experienceValue = 40;
for (int i = 0; i < this.equipmentDropChances.length; ++i)
{
this.equipmentDropChances[i] = 1F;
}
int species = dimension == -1 ?1:0;
setSpecies((byte)species);
setBreed(MinotaurBreed.getRandomMinotaur(species));
}
@Override
public String getCommandSenderName()
{
return StatCollector.translateToLocal("entity." + getMinotaur().name + ".name");
}
@Override
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(40.0D);
this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.4F);
this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(ConfigMobs.minotaurMD);
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(ConfigMobs.minotaurHP);
}
@Override
protected boolean isAIEnabled()
{
return true;
}
private static final int dataID = 12;
protected void entityInit()
{
super.entityInit();
this.dataWatcher.addObject(dataID, Byte.valueOf((byte)0));
this.dataWatcher.addObject(dataID+1, Byte.valueOf((byte)1));
this.dataWatcher.addObject(dataID+2, Integer.valueOf(2));
}
@Override
public void onUpdate()
{
super.onUpdate();
if(!worldObj.isRemote)
{
if(grabCooldown > 0)
{
--grabCooldown;
}
if(specialAttackTime > 0)
{
--specialAttackTime;
}
if((getAttack() == (byte)1 || getAttack() == (byte)3) && specialAttackTime == 0)
{
initBasicAttack();
}
if(this.getAttackTarget() != null)
{
if(getAttack() != (byte)2 && getHeldItem() == null && rand.nextInt(100) == 0)
{
this.initHeadbutt();
}
EntityLivingBase target = getAttackTarget();
if(getAttack() !=2 && rand.nextInt(50) == 0 && onGround && target instanceof EntityPlayer && ((EntityPlayer)target).isBlocking() && this.getDistanceToEntity(target) < 4F)
{
this.jump();
this.initPowerAttack();
}
}
boolean bloodied = getHealth() < (getMaxHealth()* ((float)getMinotaur().beserkThreshold/100F));
if(getAttack() == (byte)2)
{
if(!bloodied)
{
initBasicAttack();
}
else
{
this.swingItem();
}
}
if(getAttack() != (byte)2 && bloodied)
{
initBeserk();
}
}
}
@Override
protected void dropFewItems(boolean playerKill, int looting)
{
int count = rand.nextInt(looting+getLootCount()+1);
for(int a = 0; a < count; a++)
{
Item drop = getLoot();
this.dropItem(drop, 1);
}
count = rand.nextInt(looting+4)+1;
for(int a = 0; a < count; a++)
{
this.dropItem(ComponentListMF.rawhideLarge, 1);
}
count = rand.nextInt(looting+2)+1;
for(int a = 0; a < count; a++)
{
this.dropItem(isBurning() ? Items.cooked_beef : Items.beef, 1);
}
}
private Item getLoot()
{
if(getSpecies() == 1)//NETHER
{
return rand.nextInt(5) == 0 ? ToolListMF.loot_sack_uc : ToolListMF.loot_sack;
}
return rand.nextInt(10) == 0 ? ToolListMF.loot_sack_uc : ToolListMF.loot_sack;
}
private int getLootCount()
{
return 2;
}
@Override
public boolean attackEntityFrom(DamageSource source, float damage)
{
if (!super.attackEntityFrom(source, damage))
{
return false;
}
else
{
EntityLivingBase entitylivingbase = this.getAttackTarget();
if (entitylivingbase == null && this.getEntityToAttack() instanceof EntityLivingBase)
{
entitylivingbase = (EntityLivingBase)this.getEntityToAttack();
}
if (entitylivingbase == null && source.getEntity() instanceof EntityLivingBase)
{
entitylivingbase = (EntityLivingBase)source.getEntity();
}
}
return true;
}
public void initBeserk()
{
TacticalManager.tryDisarm(this);
this.playSound("minefantasy2:mob.minotaur.beserk", 1.0F, 1.0F);
setSprinting(true);
setAttack((byte)2);
}
public void initPowerAttack()
{
setSprinting(true);
specialAttackTime = 30;
setAttack((byte)3);
}
public void initHeadbutt()
{
setSprinting(true);
specialAttackTime = 20;
setAttack((byte)1);
}
public void initBasicAttack()
{
setSprinting(false);
specialAttackTime = 0;
setAttack((byte)0);
}
@Override
protected String getLivingSound()
{
return "minefantasy2:mob.minotaur.say";
}
/**
* Returns the sound this mob makes when it is hurt.
*/
@Override
protected String getHurtSound()
{
return "minefantasy2:mob.minotaur.hurt";
}
/**
* Returns the sound this mob makes on death.
*/
@Override
protected String getDeathSound()
{
return "minefantasy2:mob.minotaur.death";
}
@Override
public float getSoundPitch()
{
return 1.0F;
}
protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_)
{
this.playSound("mob.cow.step", 0.75F, 0.9F);
}
protected Item getDropItem()
{
return ComponentListMF.hideLarge;
}
public double getHeadChargeAngle()
{
return getAttack() == (byte)1 ? 80F : 0F;
}
@Override
public float getThreshold(DamageSource src)
{
float[] armour = getValueResistences();
return ArmourCalculator.adjustACForDamage(src, getDT(), armour[0], armour[1], armour[2]);
}
@Override
public void writeEntityToNBT(NBTTagCompound nbt)
{
super.writeEntityToNBT(nbt);
nbt.setInteger("Attack", (int)getAttack());
nbt.setInteger("Species", (int)getSpecies());
nbt.setInteger("Breed", (int)getBreed());
}
@Override
public void readEntityFromNBT(NBTTagCompound nbt)
{
super.readEntityFromNBT(nbt);
setAttack((byte)nbt.getInteger("Attack"));
setSpecies((byte)nbt.getInteger("Species"));
setBreed(nbt.getInteger("Breed"));
}
private float getDT()
{
byte att = getAttack();
if(att == (byte)2)
{
return 5F;
}
return 2F;
}
/**
* Cutting, Blunt, Piercing
*/
private float[] getValueResistences()
{
return new float[]{0.75F, 1F, 0.5F};
}
/**
* 0=Normal, 1=Headbutt, 2=Beserk, 3=Power
*/
public byte getAttack()
{
return dataWatcher.getWatchableObjectByte(dataID);
}
/**
* 0=Normal, 1=Headbutt, 2=Beserk, 3=Power
*/
public void setAttack(byte type)
{
dataWatcher.updateObject(dataID, type);
}
/**
* 0=Normal, 1=Nether
*/
public byte getSpecies()
{
return dataWatcher.getWatchableObjectByte(dataID+1);
}
/**
* 0=Normal, 1=Nether
*/
public void setSpecies(byte type)
{
this.isImmuneToFire = type == 1;
dataWatcher.updateObject(dataID+1, type);
}
public int getBreed()
{
return dataWatcher.getWatchableObjectInt(dataID+2);
}
public void setBreed(int type)
{
dataWatcher.updateObject(dataID+2, type);
}
private int specialAttackTime;
private float[]punch = new float[]{0F, 1F, 0F};
private float[]headbutt = new float[]{0F, 1F, 4F};
@Override
public float[] getHitTraits()
{
byte att = getAttack();
if(att == (byte)1)
{
return headbutt;
}
return punch;
}
@Override
public boolean attackEntityAsMob(Entity target)
{
if(!canEntityBeSeen(target))
{
return false;
}
if(getAttack() == 3 && motionY > 0 && target.posY < posY)
{
return false;
}
float dam = getHitDamage();
if(getAttack() == 2 && this.riddenByEntity != null && this.riddenByEntity == target)
{
if(target instanceof EntityLivingBase && rand.nextInt(4) == 0)
{
ArmourCalculator.damageArmour((EntityLivingBase) target, (int)(dam*0.25F));
}
}
if(this.riddenByEntity == null)
{
if(grabCooldown <= 0 && rand.nextInt(100) < getGrabChance())
{
target.mountEntity(this);
}
}
else if(rand.nextInt(100) < ConfigMobs.minotaurTC && riddenByEntity == target)
{
riddenByEntity.mountEntity(null);
grabCooldown = 60;
TacticalManager.knockbackEntity(target, this, 4F, 1F);
}
if(getAttack() == 3 && fallDistance > 0 && target instanceof EntityPlayer && ((EntityPlayer)target).isBlocking() && rand.nextInt(100) < getDisarmChance())
{
TacticalManager.tryDisarm(this, (EntityLivingBase)target, true);
}
int i = getKnockbackBoost();
if (target instanceof EntityLivingBase)
{
dam += EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLivingBase)target);
i += EnchantmentHelper.getKnockbackModifier(this, (EntityLivingBase)target);
}
boolean flag = target.attackEntityFrom(new DamageSourceMobMF(getAttackType(), this), dam);
if (flag)
{
this.swingItem();
if (i > 0)
{
target.addVelocity((double)(-MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F) * (float)i * 0.5F), 0.1D, (double)(MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F) * (float)i * 0.5F));
this.motionX *= 0.6D;
this.motionZ *= 0.6D;
}
int j = EnchantmentHelper.getFireAspectModifier(this);
if (j > 0)
{
target.setFire(j * 4);
}
if (target instanceof EntityLivingBase)
{
EnchantmentHelper.func_151384_a((EntityLivingBase)target, this);
}
EnchantmentHelper.func_151385_b(this, target);
}
return flag;
}
public MinotaurBreed getMinotaur()
{
return MinotaurBreed.getBreed(getSpecies(), getBreed());
}
private int getDisarmChance()
{
return getMinotaur().disarmChance;
}
private int getGrabChance()
{
return (getAttack() == 2 ? getMinotaur().grabChanceBeserk : getMinotaur().grabChance);
}
private int getThrowChance()
{
return getMinotaur().throwChance;
}
private String getAttackType()
{
byte att = getAttack();
if(att == (byte)1)
{
return "gore";
}
if(att == (byte)2)
{
return "beserk";
}
return "pound";
}
private int getKnockbackBoost()
{
byte att = getAttack();
if(att == (byte)1)
{
return getSpecies() == 1 ? 4 : 2;
}
return 0;
}
private float getHitDamage()
{
MinotaurBreed breed = getMinotaur();
if(getHeldItem() != null)
{
return Math.max(2F, breed.poundDamage-2F);//Weapon Dam
}
byte att = getAttack();
if(att == (byte)1)
{
return breed.goreDamage;
}
if(att == (byte)2)
{
return breed.beserkDamage;
}
return breed.poundDamage;
}
public boolean isBloodied()
{
return getHealth() < (getMaxHealth()*0.4F);
}
@SideOnly(Side.CLIENT)
public String getTexture()
{
String tex = "minotaur" + getMinotaur().tex;
if(isBloodied())
{
tex += "_bloodied";
}
return tex;
}
}