FANDOM


The next step in animating is creating a non-automatic animation (don't worry, we'll get to the actual animations soon enough!). If you remember correctly, a non-automatic animation is one that is not triggered by something else, or in other words, it triggers itself. For example, if a dog is bored, it scratches its back. Since this triggered randomly, this can be triggered inside the AI class itself, similar to other EntityAIs.

Starting the Non-Automatic Animation AI

Creating a non-automatic animation AI is quite similar to creating an automatic one, with just a few differences. In our tutorial, we'll create a non-automatic AI that'll heal EntityTest, and we'll later make the animation look like the entity is shaking, so we'll call it AIShakeHead. Start out by creating the typical AI extending AIAnimation.

public class AIShakeHead extends AIAnimation {
	
	public AIShakeHead(IAnimatedEntity entity) {
		super(entity);
	}
	
	public int getAnimID() {
		return 2;
	}
	
	public boolean isAutomatic() {
		return false;
	}
	
	public int getDuration() {
		return 30;
	}
}

Note that we now return false in isAutomatic(), because we are no longer creating an automatic method. Also, since the AI is no longer triggered by something else, we must trigger it ourselves. We can do this by overriding AIAnimation's method, shouldAnimate().

public boolean shouldAnimate() {
	//accessor method in AIAnimation that gives access to the entity
	EntityLiving living = getEntity();
	
	//must have an attack target
	if(living.getAttackTarget() == null) return false;
	
	//should already have lost enough health for healing to be effective
	if(living.getHealth() > living.getMaxHealth() - 4) return false;
	
	IAnimatedEntity entity = (IAnimatedEntity)living;
	return entity.getAnimID() == 0 && living.getRNG().nextInt(30) == 0;
}

The method shouldAnimate() is called every tick when this animation is not running. When returned true, the AI will be triggered, and the animation will play (no need to call AnimationAPI.sendAnimPacket). This method is very similar to EntityAIBase's shouldExecute() method, in fact, it's defined inside of shouldExecute(). However, it's suggested not to override shouldExecute(), and to instead override this method.

Again, remember to check if EntityTest's getAnimID() == 0 to avoid animation collision. Since this method is called every tick, we use a random tick (getRNG().nextInt(30) == 0) to make the AI run at more random intervals.

Adding the Logic

Now that we've written the trigger, we have to add the actual logic, which we'll add in the resetTask():

public void resetTask() {
	//remember to super!
	super.resetTask();
	getEntity().heal(4);
}

The method resetTask() runs when the AI is finished, or basically when the animation has finished. We want EntityTest to heal at this point, so we add it into the code. And that's all you need for a non-automatic animation AI!

Last but not least, add the AI into EntityTest's tasks:

public EntityTest(World world) {
	super(world);
	texture = "nothing";
	animID = 0;
	animTick = 0;
	tasks.addTask(1, new EntityAISwimming(this));
	tasks.addTask(2, new AIHeadBang(this));
	
	//ADD THIS
	tasks.addTask(2, new AIShakeHead(this));
	
	tasks.addTask(3, new EntityAIAttackOnCollide(this, 0.24F, false));
	tasks.addTask(4, new EntityAIWander(this, 0.2F));
	tasks.addTask(5, new EntityAIWatchClosest(this, EntityPlayer.class, 8F));
	tasks.addTask(5, new EntityAILookIdle(this));
	targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
}

Finishing Up

Good job! You've finished all the logic you'll need for this tutorial! If you want to double check AIShakeHead, just look below. Otherwise, you can start the actual animating in Step 4: Creating the Basic Model.

AIShakeHead.java

public class AIShakeHead extends AIAnimation {
	
	public AIShakeHead(IAnimatedEntity entity) {
		super(entity);
	}
	
	public int getAnimID() {
		return 2;
	}
	
	public boolean isAutomatic() {
		return false;
	}
	
	public int getDuration() {
		return 30;
	}
	
	public boolean shouldAnimate() {
		EntityLiving living = getEntity();
		if(living.getAttackTarget() == null) return false;
		if(living.getHealth() > living.getMaxHealth() - 4) return false;
		IAnimatedEntity entity = (IAnimatedEntity)living;
		return entity.getAnimID() == 0 && living.getRNG().nextInt(30) == 0;
	}
	
	public void resetTask() {
		super.resetTask();
		getEntity().heal(4);
	}
}

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.