Hello everyone many people in this forum have had this question and well i have spent the past days searching the internet for an answer and thier all the same look in blaze look in bat look in ghast well i've done all of those things changed the code and nothing
i'm making a fairy i want it to fly like bats fly they are able to fly because of the on update principle and updateAitasks heres the code im using whenever its put into my mob file it doesnt work because of spawnpoint.posY having errors and also get is hanging i would like to delete the whole need of that but it just messes everything up.. heres the bat code for flying
public class EntityFairy extends EntityCreature implements IMCAnimatedEntity {
protected AnimationHandler animHandler = new AnimationHandlerFairy(this);
private float destPos;
private Object field_70888_h;
private Object field_70886_e;
private float field_70884_g;
private float field_70889_i;
private Object spawnPosition;
public EntityFairy(World par1World) {
super(par1World);
this.setSize(0.5F, 0.9F);
this.tasks.addTask(0, new EntityAIWander(this, 0.9D));
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(2, new EntityAILookIdle(this));
this.tasks.addTask(3, new EntityAILookIdle(this));}
[p]Okay, I assume you don't want your mob to hang like a bat, but just fly like a bat, right? In that case you want the code that executes when isHanging is false. You can delete the code for isHanging is true. When it is not hanging, the onUpdate() simply slows down the Y motion. So your onUpdate() can simply be:[/p]
[p]
[/p]
public void onUpdate()
{
super.onUpdate();[/p]
this.motionY *= 0.6D;
}
[/p]
[p]Next, a bat is supposed to sort of stay around a spawn position instead of flying around freely. So what the bat code is doing is the longer the bat is from the spawn, the more likely it is to head back towards the spawn. The movement is still random, but they are biasing it to head back to the spawn. Basically this is a "negative feedback" loop. Anyway, you don't really need that if you just want some random fluttering. I think you could simply do this in the updateAITasks():[/p]
[p]
[/p]
[p]Personally I would clean up this code a bit, and name all the variables meaningfully. Also there is no reason to create a variable like var8 and then simply assigne it to rotationYaw. Lastly, the long double numbers are (I think) just an artifact of the deobfuscation process -- you can round those numbers a bit. This gives:[/p]
[p]
[/p]
[p]I actually don't know why they do that code in the updateAITasks() method instead of the onUpdate() method, but both methods are called every tick so I guess it doesn't matter.[/p]
[p]I would keep the idea of a spawn position, because that is what makes the bat sort of swoop around. Otherwise, if you just had purely random motion it would just sort of be flapping erratically in one average place. But the spawn position doesn't have to be a block to hang on. It can simply be the position that you initially spawn the entity. So for example maybe you want to create a constructor for your entity that includes the spawn position and you can assign the spawnPosition variables (as well as the actual posX, posY, posZ) according to the parameters passed in. Or you can capture the spawn position during the first couple ticks that the entity exists.[/p]
[p]Anyway, the most important thing to learn is to make an entity fly, you mostly just have to give it some motion. For a bat that motion is sort of random and changing frequently, but hopefully you can see that you could make code that would let keep its motion longer and change less frequently.[/p]
Okay, I assume you don't want your mob to hang like a bat, but just fly like a bat, right? In that case you want the code that executes when isHanging is false. You can delete the code for isHanging is true. When it is not hanging, the onUpdate() simply slows down the Y motion. So your onUpdate() can simply be:
public void onUpdate()
{
super.onUpdate();
this.motionY *= 0.6D;
}
Next, a bat is supposed to sort of stay around a spawn position instead of flying around freely. So what the bat code is doing is the longer the bat is from the spawn, the more likely it is to head back towards the spawn. The movement is still random, but they are biasing it to head back to the spawn. Basically this is a "negative feedback" loop. Anyway, you don't really need that if you just want some random fluttering. I think you could simply do this in the updateAITasks():
Personally I would clean up this code a bit, and name all the variables meaningfully. Also there is no reason to create a variable like var8 and then simply assigne it to rotationYaw. Lastly, the long double numbers are (I think) just an artifact of the deobfuscation process -- you can round those numbers a bit. This gives:
I actually don't know why they do that code in the updateAITasks() method instead of the onUpdate() method, but both methods are called every tick so I guess it doesn't matter.
I would keep the idea of a spawn position, because that is what makes the bat sort of swoop around. Otherwise, if you just had purely random motion it would just sort of be flapping erratically in one average place. But the spawn position doesn't have to be a block to hang on. It can simply be the position that you initially spawn the entity. So for example maybe you want to create a constructor for your entity that includes the spawn position and you can assign the spawnPosition variables (as well as the actual posX, posY, posZ) according to the parameters passed in. Or you can capture the spawn position during the first couple ticks that the entity exists.
Anyway, the most important thing to learn is to make an entity fly, you mostly just have to give it some motion. For a bat that motion is sort of random and changing frequently, but hopefully you can see that you could make code that would let keep its motion longer and change less frequently.
thank you so much I've been looking all over this tutorial is very descriptive I love it!!! Hopefully other people can use it to if they are struggling your awesome jabelar I read a lot of. Your tutorials on your website they are so descriptive and really help me understand what I'm coding :). if I have any trouble I'll post again but it seems straightforward thanks again!!!
so i used your advice and added the code however i'm a little confused about making it fly where would i put the motion variables and what should i put because i inserted the code provided and my mob is still walking on ground do you know why?
public class EntityFairy extends EntityCreature implements IMCAnimatedEntity {
protected AnimationHandler animHandler = new AnimationHandlerFairy(this);
private float destPos;
private Object field_70888_h;
private Object field_70886_e;
private float field_70884_g;
private float field_70889_i;
private ChunkCoordinates spawnPosition;
public EntityFairy(World par1World) {
super(par1World);
this.setSize(0.5F, 0.9F);
this.tasks.addTask(0, new EntityAIWander(this, 0.9D));
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(2, new EntityAILookIdle(this));
this.tasks.addTask(3, new EntityAILookIdle(this));
}
I think there are two problems. You can't have AI like AIWander on your creature because it will also try to move the creature, and will do so along the ground like a cow might wander. You really shouldn't combine any AI that creates movement with your flying movement.
Secondly, your class extends EntityCreature, but you may want to extend EntityAmbientCreature instead like the bat does. I'm not sure, but EntityCreature may have functionality active that might interfere with what you're doing. But maybe it would work.
I think the main point to understand is that there are two types of "AI" used for Minecraft entities. Originally every entity just had code in the onUpdate() that would do everything including moving. However, then they added the AI where there are multiple AI classes with priority and mutual exclusion masking, etc. That is meant to be used instead of the onUpdate() moving.
The bat entity is coded with the older style, where it directly manipulates the motion rather than invoking a navigator. It is probably also possible to code a bat using the newer style but maybe that would be difficult.
Anyway, my point is the same: don't use AI that creates movement in an entity where you are controlling the movement directly.
Right. You can have AI and also tamable creatures that move on the ground, or creatures that are not tamable and have no AI that fly.
I have one mob in my mod that flies. I basically copied the blaze code like you hear everyone suggest. I even copied the sounds the blaze makes. It is essentially a blaze that looks like a small dragon.
Hmmm.. doesn't seem to be working i deleted the emit light code to see if that was the problem but still nothing with this code in game it just stands on ground doing well nothing
Are you spawning it in the air? I'm not convinced your code will get it to fly if it is already on the ground.
Also your destPos code doesn't seem logical. First you set it to either -1 or 4 times 0.3D and then immediately set it to either 0 or 1. And I don't think you even use it.
Lastly, you should rename (refactor) any weird field names that you copy so your code is easier to read and understand.
I would also recommend you clean out some of the redundant code too. I doubt it is causing a problem, but it makes you code harder to read and maintain. One thing I see in there is this:
@Override
public void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
}
@Override
public void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
}
Since this function is overridden, and all you are doing in calling the super, then it does nothing. If you don't understand how overriding or super works, you can read up on that here (or many other places):
The above might not apply to you, but the way I tackle this stuff, is that instead of just copying a bunch of stuff without knowing what it does, I try to learn about at least one new thing in the code that I don't understand each time I do something new. This keeps it from being overwhelming, and helps me later on.
thanks i found the problem seems like it only flies when the code is put under on update not update ai tasks hmmm but thank you sooo much!!! and illltry to clean up my code a bit
Hello everyone many people in this forum have had this question and well i have spent the past days searching the internet for an answer and thier all the same look in blaze look in bat look in ghast well i've done all of those things changed the code and nothing
i'm making a fairy i want it to fly like bats fly they are able to fly because of the on update principle and updateAitasks heres the code im using whenever its put into my mob file it doesnt work because of spawnpoint.posY having errors and also get is hanging i would like to delete the whole need of that but it just messes everything up.. heres the bat code for flying
public void onUpdate()
{
super.onUpdate();
if (this.getIsBatHanging())
{
this.motionX = this.motionY = this.motionZ = 0.0D;
this.posY = (double)MathHelper.floor_double(this.posY) + 1.0D - (double)this.height;
}
else
{
this.motionY *= 0.6000000238418579D;
}
}
protected void updateAITasks()
{
super.updateAITasks();
if (this.getIsBatHanging())
{
if (!this.worldObj.getBlock(MathHelper.floor_double(this.posX), (int)this.posY + 1, MathHelper.floor_double(this.posZ)).isNormalCube())
{
this.setIsBatHanging(false);
this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1015, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
}
else
{
if (this.rand.nextInt(200) == 0)
{
this.rotationYawHead = (float)this.rand.nextInt(360);
}
if (this.worldObj.getClosestPlayerToEntity(this, 4.0D) != null)
{
this.setIsBatHanging(false);
this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1015, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
}
}
}
else
{
if (this.spawnPosition != null && (!this.worldObj.isAirBlock(this.spawnPosition.posX, this.spawnPosition.posY, this.spawnPosition.posZ) || this.spawnPosition.posY < 1))
{
this.spawnPosition = null;
}
if (this.spawnPosition == null || this.rand.nextInt(30) == 0 || this.spawnPosition.getDistanceSquared((int)this.posX, (int)this.posY, (int)this.posZ) < 4.0F)
{
this.spawnPosition = new ChunkCoordinates((int)this.posX + this.rand.nextInt(7) - this.rand.nextInt(7), (int)this.posY + this.rand.nextInt(6) - 2, (int)this.posZ + this.rand.nextInt(7) - this.rand.nextInt(7));
}
double var1 = (double)this.spawnPosition.posX + 0.5D - this.posX;
double var3 = (double)this.spawnPosition.posY + 0.1D - this.posY;
double var5 = (double)this.spawnPosition.posZ + 0.5D - this.posZ;
this.motionX += (Math.signum(var1) * 0.5D - this.motionX) * 0.10000000149011612D;
this.motionY += (Math.signum(var3) * 0.699999988079071D - this.motionY) * 0.10000000149011612D;
this.motionZ += (Math.signum(var5) * 0.5D - this.motionZ) * 0.10000000149011612D;
float var7 = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
float var8 = MathHelper.wrapAngleTo180_float(var7 - this.rotationYaw);
this.moveForward = 0.5F;
this.rotationYaw += var8;
if (this.rand.nextInt(100) == 0 && this.worldObj.getBlock(MathHelper.floor_double(this.posX), (int)this.posY + 1, MathHelper.floor_double(this.posZ)).isNormalCube())
{
this.setIsBatHanging(true);
}
}
}
what can i do to make my mob fly like this heres my entity file
package com.Jizmo.mobs;
import com.Jizmo.MCACommonLibrary.IMCAnimatedEntity;
import com.Jizmo.MCACommonLibrary.animation.AnimationHandler;
import com.Jizmo.animations.Fairy.AnimationHandlerFairy;
import com.Jizmo.mobAI.EntityFairyMob;
import com.Jizmo.models.Fairy;
import cpw.mods.fml.common.registry.EntityRegistry;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityFlying;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.MathHelper;
import net.minecraft.util.WeightedRandom.Item;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
public class EntityFairy extends EntityCreature implements IMCAnimatedEntity {
protected AnimationHandler animHandler = new AnimationHandlerFairy(this);
private float destPos;
private Object field_70888_h;
private Object field_70886_e;
private float field_70884_g;
private float field_70889_i;
private Object spawnPosition;
public EntityFairy(World par1World) {
super(par1World);
this.setSize(0.5F, 0.9F);
this.tasks.addTask(0, new EntityAIWander(this, 0.9D));
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(2, new EntityAILookIdle(this));
this.tasks.addTask(3, new EntityAILookIdle(this));}
@Override
protected void entityInit() {
super.entityInit();
}
public AnimationHandler getAnimationHandler() {
return animHandler;
}
@Override
public void onUpdate()
{
super.onUpdate();
if (this.isAirBorne())
{
if(!this.getAnimationHandler().isAnimationActive("Flying")) {
this.getAnimationHandler().activateAnimation("Flying", 0);}}
if (this.getIsBatHanging())
{
this.motionX = this.motionY = this.motionZ = 0.0D;
this.posY = (double)MathHelper.floor_double(this.posY) + 1.0D - (double)this.height;
}
else
{
this.motionY *= 0.6000000238418579D;
private boolean isAirBorne() {
this.motionY = 0.001D;
return true;
}
@Override
public void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
}
@Override
public void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
}
private void addLight() {
this.worldObj.setLightValue(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ, 15);
this.worldObj.markBlockRangeForRenderUpdate((int)this.posX, (int)this.posY, (int)this.posX, 12, 12, 12);
this.worldObj.markBlockForUpdate((int)this.posX, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ -1);
}
public void onLivingUpdate(){
this.field_70888_h = this.field_70886_e;
this.field_70884_g = this.destPos;
this.destPos = (float)((double) this.destPos + (double)(this.onGround ? -1
: 4) * 0.3D);
addLight();
if (this.destPos < 0.0F)
{
this.destPos = 0.0F;
}
if (this.destPos > 1.0F)
{
this.destPos = 1.0F;
}
if (!this.onGround && this.field_70889_i < 1.0F)
{
this.field_70889_i = 1.0F;
}
this.field_70889_i = (float)((double) this.field_70889_i * 0.9D);
if (!this.onGround && this.motionY < 0.0D)
{
this.motionY *= 0.6D;
}
this.field_70886_e = this.field_70889_i * 2.0F;
if (this.isDead) {
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ);
}
worldObj.spawnParticle("reddust" , posX, posY, posZ, 82.0D ,255.0D ,100.0D);
super.onLivingUpdate();
super.onLivingUpdate();}
public static void registerEntity(){
createEntity(EntityFairyMob.class,"Fairy Mob" , 0x0004FF , 0xFF00E1);
protected void updateAITasks()
{
super.updateAITasks();
if (this.getIsBatHanging())
{
if (!this.worldObj.getBlock(MathHelper.floor_double(this.posX), (int)this.posY + 1, MathHelper.floor_double(this.posZ)).isNormalCube())
{
this.setIsBatHanging(false);
this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1015, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
}
else
{
if (this.rand.nextInt(200) == 0)
{
this.rotationYawHead = (float)this.rand.nextInt(360);
}
if (this.worldObj.getClosestPlayerToEntity(this, 4.0D) != null)
{
this.setIsBatHanging(false);
this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1015, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
}
}
}
else
{
if (this.spawnPosition != null && (!this.worldObj.isAirBlock(this.spawnPosition.posX, this.spawnPosition.posY, this.spawnPosition.posZ) || this.spawnPosition.posY < 1))
{
this.spawnPosition = null;
}
if (this.spawnPosition == null || this.rand.nextInt(30) == 0 || this.spawnPosition.getDistanceSquared((int)this.posX, (int)this.posY, (int)this.posZ) < 4.0F)
{
this.spawnPosition = new ChunkCoordinates((int)this.posX + this.rand.nextInt(7) - this.rand.nextInt(7), (int)this.posY + this.rand.nextInt(6) - 2, (int)this.posZ + this.rand.nextInt(7) - this.rand.nextInt(7));
}
double var1 = (double)this.spawnPosition.posX + 0.5D - this.posX;
double var3 = (double)this.spawnPosition.posY + 0.1D - this.posY;
double var5 = (double)this.spawnPosition.posZ + 0.5D - this.posZ;
this.motionX += (Math.signum(var1) * 0.5D - this.motionX) * 0.10000000149011612D;
this.motionY += (Math.signum(var3) * 0.699999988079071D - this.motionY) * 0.10000000149011612D;
this.motionZ += (Math.signum(var5) * 0.5D - this.motionZ) * 0.10000000149011612D;
float var7 = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
float var8 = MathHelper.wrapAngleTo180_float(var7 - this.rotationYaw);
this.moveForward = 0.5F;
this.rotationYaw += var8;
if (this.rand.nextInt(100) == 0 && this.worldObj.getBlock(MathHelper.floor_double(this.posX), (int)this.posY + 1, MathHelper.floor_double(this.posZ)).isNormalCube())
{
this.setIsBatHanging(true);
}
}
}
private static void createEntity(Class<EntityFairyMob> class1,
String string, int i, int j) {
// TODO Auto-generated method stub
}
{
}
}
I've seen excellent mods out there with birds and ghosts this is obviously my first time coding anything and any help would be appreciated
How much of this code do you understand?
Please don't PM me asking for help, I will just redirect you to the appropriate forum, where there are others who are far more skilled than me.
This is not the signature you are looking for.
Banners and such things
{
super.onUpdate();[/p] this.motionY *= 0.6D;
}
[p]Next, a bat is supposed to sort of stay around a spawn position instead of flying around freely. So what the bat code is doing is the longer the bat is from the spawn, the more likely it is to head back towards the spawn. The movement is still random, but they are biasing it to head back to the spawn. Basically this is a "negative feedback" loop. Anyway, you don't really need that if you just want some random fluttering. I think you could simply do this in the updateAITasks():[/p] [p]
{
super.updateAITasks();[/p] [p]double var1 = (double)this.spawnPosition.posX + 0.5D - this.posX;
double var3 = (double)this.spawnPosition.posY + 0.1D - this.posY;
double var5 = (double)this.spawnPosition.posZ + 0.5D - this.posZ;
this.motionX += (Math.signum(var1) * 0.5D - this.motionX) * 0.10000000149011612D;
this.motionY += (Math.signum(var3) * 0.699999988079071D - this.motionY) * 0.10000000149011612D;
this.motionZ += (Math.signum(var5) * 0.5D - this.motionZ) * 0.10000000149011612D;
float var7 = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
float var8 = MathHelper.wrapAngleTo180_float(var7 - this.rotationYaw);
this.moveForward = 0.5F;
this.rotationYaw += var8;
}[/p] [p]
[p]Personally I would clean up this code a bit, and name all the variables meaningfully. Also there is no reason to create a variable like var8 and then simply assigne it to rotationYaw. Lastly, the long double numbers are (I think) just an artifact of the deobfuscation process -- you can round those numbers a bit. This gives:[/p] [p]
{
super.updateAITasks();[/p] [p]double xDistFromSpawn = (double)this.spawnPosition.posX + 0.5D - this.posX;
double yDistFromSpawn = (double)this.spawnPosition.posY + 0.1D - this.posY;
double zDistFromSpawn = (double)this.spawnPosition.posZ + 0.5D - this.posZ;
this.motionX += (Math.signum(xDistFromSpawn) * 0.5D - this.motionX) * 0.1D;
this.motionY += (Math.signum(yDistFromSpawn) * 0.7D - this.motionY) * 0.1D;
this.motionZ += (Math.signum(zDistFromSpawn) * 0.5D - this.motionZ) * 0.1D;
float rotationAmount = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
this.rotationYaw += MathHelper.wrapAngleTo180_float(rotationAmount - this.rotationYaw);
this.moveForward = 0.5F;
}[/p] [p]
[p]I actually don't know why they do that code in the updateAITasks() method instead of the onUpdate() method, but both methods are called every tick so I guess it doesn't matter.[/p]
[p]I would keep the idea of a spawn position, because that is what makes the bat sort of swoop around. Otherwise, if you just had purely random motion it would just sort of be flapping erratically in one average place. But the spawn position doesn't have to be a block to hang on. It can simply be the position that you initially spawn the entity. So for example maybe you want to create a constructor for your entity that includes the spawn position and you can assign the spawnPosition variables (as well as the actual posX, posY, posZ) according to the parameters passed in. Or you can capture the spawn position during the first couple ticks that the entity exists.[/p]
[p]Anyway, the most important thing to learn is to make an entity fly, you mostly just have to give it some motion. For a bat that motion is sort of random and changing frequently, but hopefully you can see that you could make code that would let keep its motion longer and change less frequently.[/p]
thank you so much I've been looking all over this tutorial is very descriptive I love it!!! Hopefully other people can use it to if they are struggling your awesome jabelar I read a lot of. Your tutorials on your website they are so descriptive and really help me understand what I'm coding :). if I have any trouble I'll post again but it seems straightforward thanks again!!!
so i used your advice and added the code however i'm a little confused about making it fly where would i put the motion variables and what should i put because i inserted the code provided and my mob is still walking on ground do you know why?
package com.Jizmo.mobs;
import com.Jizmo.MCACommonLibrary.IMCAnimatedEntity;
import com.Jizmo.MCACommonLibrary.animation.AnimationHandler;
import com.Jizmo.animations.Fairy.AnimationHandlerFairy;
import com.Jizmo.mobAI.EntityFairyMob;
import com.Jizmo.models.Fairy;
import cpw.mods.fml.common.registry.EntityRegistry;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityFlying;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.WeightedRandom.Item;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
public class EntityFairy extends EntityCreature implements IMCAnimatedEntity {
protected AnimationHandler animHandler = new AnimationHandlerFairy(this);
private float destPos;
private Object field_70888_h;
private Object field_70886_e;
private float field_70884_g;
private float field_70889_i;
private ChunkCoordinates spawnPosition;
public EntityFairy(World par1World) {
super(par1World);
this.setSize(0.5F, 0.9F);
this.tasks.addTask(0, new EntityAIWander(this, 0.9D));
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(2, new EntityAILookIdle(this));
this.tasks.addTask(3, new EntityAILookIdle(this));
}
@Override
protected void entityInit() {
super.entityInit();
}
public AnimationHandler getAnimationHandler() {
return animHandler;
}
@Override
public void onUpdate(){
super.onUpdate();
this.motionY *= 0.6D;
}
@Override
public void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
}
@Override
public void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
}
private void addLight() {
this.worldObj.setLightValue(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ, 15);
this.worldObj.markBlockRangeForRenderUpdate((int)this.posX, (int)this.posY, (int)this.posX, 12, 12, 12);
this.worldObj.markBlockForUpdate((int)this.posX, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ -1);
}
public void onLivingUpdate(){
this.field_70888_h = this.field_70886_e;
this.field_70884_g = this.destPos;
this.destPos = (float)((double) this.destPos + (double)(this.onGround ? -1
: 4) * 0.3D);
addLight();
if (this.destPos < 0.0F)
{
this.destPos = 0.0F;
}
if (this.destPos > 1.0F)
{
this.destPos = 1.0F;
}
if (!this.onGround && this.field_70889_i < 1.0F)
{
this.field_70889_i = 1.0F;
}
this.field_70889_i = (float)((double) this.field_70889_i * 0.9D);
if (!this.onGround && this.motionY < 0.0D)
{
this.motionY *= 0.6D;
}
this.field_70886_e = this.field_70889_i * 2.0F;
worldObj.spawnParticle("happyVillager", posX, posY, posZ, 124.0D /*red*/, 252.0D /*green*/, 0.0D /*blue*/);
if (this.isDead) {
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ);
}
super.onLivingUpdate();
}
protected void updateAITasks()
{
super.updateAITasks();
double xDistFromSpawn = (double)this.spawnPosition.posX + 0.5D - this.posX;
double yDistFromSpawn = (double)this.spawnPosition.posY + 0.1D - this.posY;
double zDistFromSpawn = (double)this.spawnPosition.posZ + 0.5D - this.posZ;{
this.motionX += (Math.signum(xDistFromSpawn) * 0.5D - this.motionX) * 0.1D;
this.motionY += (Math.signum(yDistFromSpawn) * 0.7D - this.motionY) * 0.1D;
this.motionZ += (Math.signum(zDistFromSpawn) * 0.5D - this.motionZ) * 0.1D;
float rotationAmount = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
this.rotationYaw += MathHelper.wrapAngleTo180_float(rotationAmount - this.rotationYaw);
this.moveForward = 0.5F;
}
}
}
I think there are two problems. You can't have AI like AIWander on your creature because it will also try to move the creature, and will do so along the ground like a cow might wander. You really shouldn't combine any AI that creates movement with your flying movement.
Secondly, your class extends EntityCreature, but you may want to extend EntityAmbientCreature instead like the bat does. I'm not sure, but EntityCreature may have functionality active that might interfere with what you're doing. But maybe it would work.
I think the main point to understand is that there are two types of "AI" used for Minecraft entities. Originally every entity just had code in the onUpdate() that would do everything including moving. However, then they added the AI where there are multiple AI classes with priority and mutual exclusion masking, etc. That is meant to be used instead of the onUpdate() moving.
The bat entity is coded with the older style, where it directly manipulates the motion rather than invoking a navigator. It is probably also possible to code a bat using the newer style but maybe that would be difficult.
Anyway, my point is the same: don't use AI that creates movement in an entity where you are controlling the movement directly.
Right. You can have AI and also tamable creatures that move on the ground, or creatures that are not tamable and have no AI that fly.
I have one mob in my mod that flies. I basically copied the blaze code like you hear everyone suggest. I even copied the sounds the blaze makes. It is essentially a blaze that looks like a small dragon.
[url=2482915-wip-arkcraft-survival-evolved-dinos-taming]
Hmmm.. doesn't seem to be working i deleted the emit light code to see if that was the problem but still nothing with this code in game it just stands on ground doing well nothing
package com.Jizmo.mobs;
import com.Jizmo.MCACommonLibrary.IMCAnimatedEntity;
import com.Jizmo.MCACommonLibrary.animation.AnimationHandler;
import com.Jizmo.animations.Fairy.AnimationHandlerFairy;
import com.Jizmo.mobAI.EntityFairyMob;
import com.Jizmo.models.Fairy;
import cpw.mods.fml.common.registry.EntityRegistry;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityFlying;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.passive.EntityAmbientCreature;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.WeightedRandom.Item;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
public class EntityFairy extends EntityAmbientCreature implements IMCAnimatedEntity {
protected AnimationHandler animHandler = new AnimationHandlerFairy(this);
private float destPos;
private Object field_70888_h;
private Object field_70886_e;
private float field_70884_g;
private float field_70889_i;
private ChunkCoordinates spawnPosition;
public EntityFairy(World par1World) {
super(par1World);
this.setSize(0.5F, 0.9F);
}
@Override
protected void entityInit() {
super.entityInit();
}
public AnimationHandler getAnimationHandler() {
return animHandler;
}
public void onUpdate(){
super.onUpdate();
this.motionY *= 0.6D;
}
@Override
public void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
}
@Override
public void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
}
private void addLight() {
this.worldObj.setLightValue(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ, 15);
this.worldObj.markBlockRangeForRenderUpdate((int)this.posX, (int)this.posY, (int)this.posX, 12, 12, 12);
this.worldObj.markBlockForUpdate((int)this.posX, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY +1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY +1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY -1, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY -1, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX +1, (int)this.posY, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ -1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX -1, (int)this.posY, (int)this.posZ);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ +1);
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ -1);
}
public void onLivingUpdate(){
this.field_70888_h = this.field_70886_e;
this.field_70884_g = this.destPos;
this.destPos = (float)((double) this.destPos + (double)(this.onGround ? -1
: 4) * 0.3D);
addLight();
if (this.destPos < 0.0F)
{
this.destPos = 0.0F;
}
if (this.destPos > 1.0F)
{
this.destPos = 1.0F;
}
if (!this.onGround && this.field_70889_i < 1.0F)
{
this.field_70889_i = 1.0F;
}
this.field_70889_i = (float)((double) this.field_70889_i * 0.9D);
if (!this.onGround && this.motionY < 0.0D)
{
this.motionY *= 0.6D;
}
this.field_70886_e = this.field_70889_i * 2.0F;
worldObj.spawnParticle("happyVillager", posX, posY, posZ, 124.0D /*red*/, 252.0D /*green*/, 0.0D /*blue*/);
if (this.isDead) {
this.worldObj.updateLightByType(EnumSkyBlock.Block, (int)this.posX, (int)this.posY, (int)this.posZ);
}
super.onLivingUpdate();
}
protected void updateAITasks()
{
super.updateAITasks();
double xDistFromSpawn = (double)this.spawnPosition.posX + 0.5D - this.posX;
double yDistFromSpawn = (double)this.spawnPosition.posY + 0.1D - this.posY;
double zDistFromSpawn = (double)this.spawnPosition.posZ + 0.5D - this.posZ;{
this.motionX += (Math.signum(xDistFromSpawn) * 0.5D - this.motionX) * 0.1D;
this.motionY += (Math.signum(yDistFromSpawn) * 0.7D - this.motionY) * 0.1D;
this.motionZ += (Math.signum(zDistFromSpawn) * 0.5D - this.motionZ) * 0.1D;
float rotationAmount = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
this.rotationYaw += MathHelper.wrapAngleTo180_float(rotationAmount - this.rotationYaw);
this.moveForward = 0.5F;
}
}
}
imports have nothing to do with this right?
Are you spawning it in the air? I'm not convinced your code will get it to fly if it is already on the ground.
Also your destPos code doesn't seem logical. First you set it to either -1 or 4 times 0.3D and then immediately set it to either 0 or 1. And I don't think you even use it.
Lastly, you should rename (refactor) any weird field names that you copy so your code is easier to read and understand.
I would also recommend you clean out some of the redundant code too. I doubt it is causing a problem, but it makes you code harder to read and maintain. One thing I see in there is this:
@Override
public void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
}
@Override
public void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
}
Since this function is overridden, and all you are doing in calling the super, then it does nothing. If you don't understand how overriding or super works, you can read up on that here (or many other places):
http://docs.oracle.com/javase/tutorial/java/index.html
If you don't know what the NBT does, here:
http://www.minecraftforge.net/wiki/Creating_NBT_for_items
The above might not apply to you, but the way I tackle this stuff, is that instead of just copying a bunch of stuff without knowing what it does, I try to learn about at least one new thing in the code that I don't understand each time I do something new. This keeps it from being overwhelming, and helps me later on.
[url=2482915-wip-arkcraft-survival-evolved-dinos-taming]
thanks i found the problem seems like it only flies when the code is put under on update not update ai tasks hmmm but thank you sooo much!!! and illltry to clean up my code a bit