167 lines
5.4 KiB
Java
Executable file
167 lines
5.4 KiB
Java
Executable file
package common.ai;
|
|
|
|
import common.entity.Entity;
|
|
import common.entity.types.EntityLiving;
|
|
import common.pathfinding.PathEntity;
|
|
import common.util.BlockPos;
|
|
import common.world.World;
|
|
|
|
public class EntityAIAttackOnCollide extends EntityAIBase
|
|
{
|
|
World worldObj;
|
|
protected EntityLiving attacker;
|
|
|
|
/**
|
|
* An amount of decrementing ticks that allows the entity to attack once the tick reaches 0.
|
|
*/
|
|
int attackTick;
|
|
|
|
/** The speed with which the mob will approach the target */
|
|
double speedTowardsTarget;
|
|
|
|
/**
|
|
* When true, the mob will continue chasing its target, even if it can't find a path to them right now.
|
|
*/
|
|
boolean longMemory;
|
|
private final boolean swing;
|
|
|
|
/** The PathEntity of our entity. */
|
|
PathEntity entityPathEntity;
|
|
Class <? extends Entity > classTarget;
|
|
private int delayCounter;
|
|
private double targetX;
|
|
private double targetY;
|
|
private double targetZ;
|
|
|
|
public EntityAIAttackOnCollide(EntityLiving creature, Class <? extends Entity > targetClass, double speedIn, boolean useLongMemory, boolean swingItem)
|
|
{
|
|
this(creature, speedIn, useLongMemory, swingItem);
|
|
this.classTarget = targetClass;
|
|
}
|
|
|
|
public EntityAIAttackOnCollide(EntityLiving creature, double speedIn, boolean useLongMemory, boolean swingItem)
|
|
{
|
|
this.attacker = creature;
|
|
this.worldObj = creature.worldObj;
|
|
this.speedTowardsTarget = speedIn;
|
|
this.longMemory = useLongMemory;
|
|
this.swing = swingItem;
|
|
this.setMutexBits(3);
|
|
}
|
|
|
|
public EntityAIAttackOnCollide(EntityLiving creature, Class <? extends Entity > targetClass, double speedIn, boolean useLongMemory)
|
|
{
|
|
this(creature, speedIn, useLongMemory);
|
|
this.classTarget = targetClass;
|
|
}
|
|
|
|
public EntityAIAttackOnCollide(EntityLiving creature, double speedIn, boolean useLongMemory)
|
|
{
|
|
this(creature, speedIn, useLongMemory, false);
|
|
}
|
|
|
|
/**
|
|
* Returns whether the EntityAIBase should begin execution.
|
|
*/
|
|
public boolean shouldExecute()
|
|
{
|
|
EntityLiving entitylivingbase = this.attacker.getAttackTarget();
|
|
|
|
if (entitylivingbase == null)
|
|
{
|
|
return false;
|
|
}
|
|
else if (!entitylivingbase.isEntityAlive())
|
|
{
|
|
return false;
|
|
}
|
|
else if (this.classTarget != null && !this.classTarget.isAssignableFrom(entitylivingbase.getClass()))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
this.entityPathEntity = this.attacker.getNavigator().getPathToEntityLiving(entitylivingbase);
|
|
return this.entityPathEntity != null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns whether an in-progress EntityAIBase should continue executing
|
|
*/
|
|
public boolean continueExecuting()
|
|
{
|
|
EntityLiving entitylivingbase = this.attacker.getAttackTarget();
|
|
return entitylivingbase == null ? false : (!entitylivingbase.isEntityAlive() ? false : (!this.longMemory ? !this.attacker.getNavigator().noPath() : this.attacker.isWithinHomeDistanceFromPosition(new BlockPos(entitylivingbase))));
|
|
}
|
|
|
|
/**
|
|
* Execute a one shot task or start executing a continuous task
|
|
*/
|
|
public void startExecuting()
|
|
{
|
|
this.attacker.getNavigator().setPath(this.entityPathEntity, this.speedTowardsTarget);
|
|
this.delayCounter = 0;
|
|
}
|
|
|
|
/**
|
|
* Resets the task
|
|
*/
|
|
public void resetTask()
|
|
{
|
|
this.attacker.getNavigator().clearPathEntity();
|
|
}
|
|
|
|
/**
|
|
* Updates the task
|
|
*/
|
|
public void updateTask()
|
|
{
|
|
EntityLiving entitylivingbase = this.attacker.getAttackTarget();
|
|
this.attacker.getLookHelper().setLookPositionWithEntity(entitylivingbase, 30.0F, 30.0F);
|
|
double d0 = this.attacker.getDistanceSq(entitylivingbase.posX, entitylivingbase.getEntityBoundingBox().minY, entitylivingbase.posZ);
|
|
double d1 = this.getAttackRange(entitylivingbase);
|
|
--this.delayCounter;
|
|
|
|
if ((this.longMemory || this.attacker.getEntitySenses().canSee(entitylivingbase)) && this.delayCounter <= 0 && (this.targetX == 0.0D && this.targetY == 0.0D && this.targetZ == 0.0D || entitylivingbase.getDistanceSq(this.targetX, this.targetY, this.targetZ) >= 1.0D || this.attacker.getRNG().floatv() < 0.05F))
|
|
{
|
|
this.targetX = entitylivingbase.posX;
|
|
this.targetY = entitylivingbase.getEntityBoundingBox().minY;
|
|
this.targetZ = entitylivingbase.posZ;
|
|
this.delayCounter = 4 + this.attacker.getRNG().zrange(7);
|
|
|
|
if (d0 > 1024.0D)
|
|
{
|
|
this.delayCounter += 10;
|
|
}
|
|
else if (d0 > 256.0D)
|
|
{
|
|
this.delayCounter += 5;
|
|
}
|
|
|
|
if (!this.attacker.getNavigator().tryMoveToEntityLiving(entitylivingbase, this.speedTowardsTarget))
|
|
{
|
|
this.delayCounter += 15;
|
|
}
|
|
}
|
|
|
|
this.attackTick = Math.max(this.attackTick - 1, 0);
|
|
|
|
if (d0 <= d1 && this.attackTick <= 0)
|
|
{
|
|
this.attackTick = 20;
|
|
|
|
// if (this.attacker.getHeldItem() != null)
|
|
// {
|
|
this.attacker.swingItem();
|
|
// }
|
|
|
|
this.attacker.attackEntityAsMob(entitylivingbase);
|
|
}
|
|
}
|
|
|
|
protected double getAttackRange(EntityLiving attackTarget)
|
|
{
|
|
return (double)(this.attacker.width * 2.0F * this.attacker.width * 2.0F + attackTarget.width);
|
|
}
|
|
}
|