package net.minecraft.entity;
import net.minecraft.pathfinding.PathEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
public abstract class EntityCreature extends EntityLiving
{
private PathEntity pathToEntity;
/** The Entity this EntityCreature is set to attack. */
protected Entity entityToAttack;
/**
* returns true if a creature has attacked recently only used for creepers and skeletons
*/
protected boolean hasAttacked = false;
/** Used to make a creature speed up and wander away when hit. */
protected int fleeingTick = 0;
public EntityCreature(World par1World)
{
super(par1World);
}
/**
* Disables a mob's ability to move on its own while true.
*/
protected boolean isMovementCeased()
{
return false;
}
protected void updateEntityActionState()
{
this.worldObj.theProfiler.startSection("ai");
if (this.fleeingTick > 0)
{
--this.fleeingTick;
}
this.hasAttacked = this.isMovementCeased();
float var1 = 16.0F;
if (this.entityToAttack == null)
{
this.entityToAttack = this.findPlayerToAttack();
if (this.entityToAttack != null)
{
this.pathToEntity = this.worldObj.getPathEntityToEntity(this, this.entityToAttack, var1, true, false, false, true);
}
}
else if (this.entityToAttack.isEntityAlive())
{
float var2 = this.entityToAttack.getDistanceToEntity(this);
if (this.canEntityBeSeen(this.entityToAttack))
{
this.attackEntity(this.entityToAttack, var2);
}
}
else
{
this.entityToAttack = null;
}
this.worldObj.theProfiler.endSection();
if (!this.hasAttacked && this.entityToAttack != null && (this.pathToEntity == null || this.rand.nextInt(20) == 0))
{
this.pathToEntity = this.worldObj.getPathEntityToEntity(this, this.entityToAttack, var1, true, false, false, true);
}
else if (!this.hasAttacked && (this.pathToEntity == null && this.rand.nextInt(180) == 0 || this.rand.nextInt(120) == 0 || this.fleeingTick > 0) && this.entityAge < 100)
{
this.updateWanderPath();
}
int var21 = MathHelper.floor_double(this.boundingBox.minY + 0.5D);
boolean var3 = this.isInWater();
boolean var4 = this.handleLavaMovement();
this.rotationPitch = 0.0F;
if (this.pathToEntity != null && this.rand.nextInt(100) != 0)
{
this.worldObj.theProfiler.startSection("followpath");
Vec3 var5 = this.pathToEntity.getPosition(this);
double var6 = (double)(this.width * 2.0F);
while (var5 != null && var5.squareDistanceTo(this.posX, var5.yCoord, this.posZ) < var6 * var6)
{
this.pathToEntity.incrementPathIndex();
if (this.pathToEntity.isFinished())
{
var5 = null;
this.pathToEntity = null;
}
else
{
var5 = this.pathToEntity.getPosition(this);
}
}
this.isJumping = false;
if (var5 != null)
{
double var8 = var5.xCoord - this.posX;
double var10 = var5.zCoord - this.posZ;
double var12 = var5.yCoord - (double)var21;
float var14 = (float)(Math.atan2(var10, var8) * 180.0D / Math.PI) - 90.0F;
float var15 = MathHelper.wrapAngleTo180_float(var14 - this.rotationYaw);
this.moveForward = this.moveSpeed;
if (var15 > 30.0F)
{
var15 = 30.0F;
}
if (var15 < -30.0F)
{
var15 = -30.0F;
}
this.rotationYaw += var15;
if (this.hasAttacked && this.entityToAttack != null)
{
double var16 = this.entityToAttack.posX - this.posX;
double var18 = this.entityToAttack.posZ - this.posZ;
float var20 = this.rotationYaw;
this.rotationYaw = (float)(Math.atan2(var18, var16) * 180.0D / Math.PI) - 90.0F;
var15 = (var20 - this.rotationYaw + 90.0F) * (float)Math.PI / 180.0F;
this.moveStrafing = -MathHelper.sin(var15) * this.moveForward * 1.0F;
this.moveForward = MathHelper.cos(var15) * this.moveForward * 1.0F;
}
if (var12 > 0.0D)
{
this.isJumping = true;
}
}
if (this.entityToAttack != null)
{
this.faceEntity(this.entityToAttack, 30.0F, 30.0F);
}
if (this.isCollidedHorizontally && !this.hasPath())
{
this.isJumping = true;
}
if (this.rand.nextFloat() < 0.8F && (var3 || var4))
{
this.isJumping = true;
}
this.worldObj.theProfiler.endSection();
}
else
{
super.updateEntityActionState();
this.pathToEntity = null;
}
}
/**
* Time remaining during which the Animal is sped up and flees.
*/
protected void updateWanderPath()
{
this.worldObj.theProfiler.startSection("stroll");
boolean var1 = false;
int var2 = -1;
int var3 = -1;
int var4 = -1;
float var5 = -99999.0F;
for (int var6 = 0; var6 < 10; ++var6)
{
int var7 = MathHelper.floor_double(this.posX + (double)this.rand.nextInt(13) - 6.0D);
int var8 = MathHelper.floor_double(this.posY + (double)this.rand.nextInt(7) - 3.0D);
int var9 = MathHelper.floor_double(this.posZ + (double)this.rand.nextInt(13) - 6.0D);
float var10 = this.getBlockPathWeight(var7, var8, var9);
if (var10 > var5)
{
var5 = var10;
var2 = var7;
var3 = var8;
var4 = var9;
var1 = true;
}
}
if (var1)
{
this.pathToEntity = this.worldObj.getEntityPathToXYZ(this, var2, var3, var4, 10.0F, true, false, false, true);
}
this.worldObj.theProfiler.endSection();
}
/**
* Basic mob attack. Default to touch of death in EntityCreature. Overridden by each mob to define their attack.
*/
protected void attackEntity(Entity par1Entity, float par2) {}
/**
* Takes a coordinate in and returns a weight to determine how likely this creature will try to path to the block.
* Args: x, y, z
*/
public float getBlockPathWeight(int par1, int par2, int par3)
{
return 0.0F;
}
/**
* Finds the closest player within 16 blocks to attack, or null if this Entity isn't interested in attacking
* (Animals, Spiders at day, peaceful PigZombies).
*/
protected Entity findPlayerToAttack()
{
return null;
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
int var1 = MathHelper.floor_double(this.posX);
int var2 = MathHelper.floor_double(this.boundingBox.minY);
int var3 = MathHelper.floor_double(this.posZ);
return super.getCanSpawnHere() && this.getBlockPathWeight(var1, var2, var3) >= 0.0F;
}
/**
* Returns true if entity has a path to follow
*/
public boolean hasPath()
{
return this.pathToEntity != null;
}
/**
* sets the Entities walk path in EntityCreature
*/
public void setPathToEntity(PathEntity par1PathEntity)
{
this.pathToEntity = par1PathEntity;
}
/**
* Returns current entities target
*/
public Entity getEntityToAttack()
{
return this.entityToAttack;
}
/**
* Sets the entity which is to be attacked.
*/
public void setTarget(Entity par1Entity)
{
this.entityToAttack = par1Entity;
}
/**
* This method returns a value to be applied directly to entity speed, this factor is less than 1 when a slowdown
* potion effect is applied, more than 1 when a haste potion effect is applied and 2 for fleeing entities.
*/
public float getSpeedModifier()
{
float var1 = super.getSpeedModifier();
if (this.fleeingTick > 0 && !this.isAIEnabled())
{
var1 *= 2.0F;
}
return var1;
}
}