package game.ai; import game.entity.attributes.AttributeInstance; import game.entity.attributes.Attributes; import game.entity.types.EntityLiving; import game.entity.types.IEntityOwnable; import game.init.Config; import game.pathfinding.PathEntity; import game.pathfinding.PathPoint; import game.util.ExtMath; import game.world.BlockPos; public abstract class EntityAITarget extends EntityAIBase { /** The entity that this task belongs to */ protected final EntityLiving taskOwner; /** * If true, EntityAI targets must be able to be seen (cannot be blocked by walls) to be suitable targets. */ protected boolean shouldCheckSight; /** * When true, only entities that can be reached with minimal effort will be targetted. */ private boolean nearbyOnly; /** * When nearbyOnly is true: 0 -> No target, but OK to search; 1 -> Nearby target found; 2 -> Target too far. */ private int targetSearchStatus; /** * When nearbyOnly is true, this throttles target searching to avoid excessive pathfinding. */ private int targetSearchDelay; /** * If @shouldCheckSight is true, the number of ticks before the interuption of this AITastk when the entity does't * see the target */ private int targetUnseenTicks; public EntityAITarget(EntityLiving creature, boolean checkSight) { this(creature, checkSight, false); } public EntityAITarget(EntityLiving creature, boolean checkSight, boolean onlyNearby) { this.taskOwner = creature; this.shouldCheckSight = checkSight; this.nearbyOnly = onlyNearby; } /** * Returns whether an in-progress EntityAIBase should continue executing */ public boolean continueExecuting() { EntityLiving entitylivingbase = this.taskOwner.getAttackTarget(); if (entitylivingbase == null) { return false; } else if (!entitylivingbase.isEntityAlive()) { return false; } else { // Team team = this.taskOwner.getTeam(); // Team team1 = entitylivingbase.getTeam(); // // if (team != null && team1 == team) // { // return false; // } // else // { double d0 = this.getTargetDistance(); if (this.taskOwner.getDistanceSqToEntity(entitylivingbase) > d0 * d0) { return false; } else { if (this.shouldCheckSight) { if (this.taskOwner.getEntitySenses().canSee(entitylivingbase)) { this.targetUnseenTicks = 0; } else if (++this.targetUnseenTicks > 60) { return false; } } return Config.mobAttacks; } // } } } protected double getTargetDistance() { AttributeInstance iattributeinstance = this.taskOwner.getEntityAttribute(Attributes.FOLLOW_RANGE); return iattributeinstance == null ? 16.0D : iattributeinstance.getAttributeValue(); } /** * Execute a one shot task or start executing a continuous task */ public void startExecuting() { this.targetSearchStatus = 0; this.targetSearchDelay = 0; this.targetUnseenTicks = 0; } /** * Resets the task */ public void resetTask() { this.taskOwner.setAttackTarget((EntityLiving)null); } /** * A static method used to see if an entity is a suitable target through a number of checks. */ public static boolean isSuitableTarget(EntityLiving attacker, EntityLiving target, boolean checkSight) { if (target == null) { return false; } else if (target == attacker) { return false; } else if (!target.isEntityAlive()) { return false; } else if (!Config.infight && target.getClass() == attacker.getClass()) { return false; } else { // Team team = attacker.getTeam(); // Team team1 = target.getTeam(); // // if (team != null && team1 == team) // { // return false; // } // else // { if (attacker instanceof IEntityOwnable // ) // && ((IEntityOwnable)attacker).getOwnerId() != null && !((IEntityOwnable)attacker).getOwnerId().isEmpty()) // { // if (target instanceof IEntityOwnable && ((IEntityOwnable)attacker).getOwnerId().equalsIgnoreCase(((IEntityOwnable)target).getOwnerId())) // { // return false; // } // if ( && target == ((IEntityOwnable)attacker).getOwner()) { return false; // } } else if (!Config.mobAttacks) { return false; } return !checkSight || attacker.getEntitySenses().canSee(target); // } } } /** * A method used to see if an entity is a suitable target through a number of checks. Args : entity, * canTargetInvinciblePlayer */ protected boolean isSuitableTarget(EntityLiving target) { if (!isSuitableTarget(this.taskOwner, target, this.shouldCheckSight)) { return false; } else if (!this.taskOwner.isWithinHomeDistanceFromPosition(new BlockPos(target))) { return false; } else { if (this.nearbyOnly) { if (--this.targetSearchDelay <= 0) { this.targetSearchStatus = 0; } if (this.targetSearchStatus == 0) { this.targetSearchStatus = this.canEasilyReach(target) ? 1 : 2; } if (this.targetSearchStatus == 2) { return false; } } return true; } } /** * Checks to see if this entity can find a short path to the given target. * * @param target the entity to find a path to */ private boolean canEasilyReach(EntityLiving target) { this.targetSearchDelay = 10 + this.taskOwner.getRNG().zrange(5); PathEntity pathentity = this.taskOwner.getNavigator().getPathToEntityLiving(target); if (pathentity == null) { return false; } else { PathPoint pathpoint = pathentity.getFinalPathPoint(); if (pathpoint == null) { return false; } else { int i = pathpoint.xCoord - ExtMath.floord(target.posX); int j = pathpoint.zCoord - ExtMath.floord(target.posZ); return (double)(i * i + j * j) <= 2.25D; } } } }