Alright, so i have a custom mob that i want to sort of work like a skeleton. It will spawn with either a bow or a sword. or maybe in the future ill change it were it uses both, but for now i want it to either spawn with a bow or a sword, and obviously if it spawns with a bow it will shoot but if it spawns with a sword it will run and attack you. But the problem is that it doesnt do that and im not sure exactly how to get that to work. It may have something to do with the rendering code, but i dont spot anything about rendering bows/swords. And i want my mob to spawn with either a sword or a bow like skeletons do. heres my code, please help.
public class Entitychocolateninja extends EntityMob implements IRangedAttackMob
{
private EntityAIArrowAttack aiArrowAttack = new EntityAIArrowAttack(this, 2.0D, 20, 60, 15.0F);
private EntityAIAttackOnCollide aiAttackOnCollide = new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.2D, false);
private static final String __OBFID = "CL_00001697";
public Entitychocolateninja(World par1World)
{
super(par1World);
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIRestrictSun(this));
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(6, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 0, true));
if (par1World != null && !par1World.isRemote)
{
this.setCombatTask();
}
}
protected void entityInit()
{
super.entityInit();
this.dataWatcher.addObject(13, new Byte((byte)0));
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
/**
* Returns the sound this mob makes while it's alive.
*/
protected String getLivingSound()
{
return "mob.zombie.say";
}
/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "game.player.hurt";
}
/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "game.player.die";
}
protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_)
{
this.playSound("mob.zombie.step", 0.15F, 1.0F);
}
public boolean attackEntityAsMob(Entity par1Entity)
{
if (super.attackEntityAsMob(par1Entity))
{
if (this.getSkeletonType() == 1 && par1Entity instanceof EntityLivingBase)
{
}
return true;
}
else
{
return false;
}
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEFINED;
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
/**
* Handles updating while being ridden by an entity
*/
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource par1DamageSource)
{
super.onDeath(par1DamageSource);
/**
* Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param
* par2 - Level of Looting used to kill this mob.
*/
protected void dropFewItems(boolean par1, int par2)
{
int j;
int k;
for (k = 0; k < j; ++k)
{
this.dropItem(ItemRegistry.chocolateIngots, 1);
}
}
else
{
j = this.rand.nextInt(3 + par2);
for (k = 0; k < j; ++k)
{
this.dropItem(Items.arrow, 1);
}
}
j = this.rand.nextInt(3 + par2);
for (k = 0; k < j; ++k)
{
this.dropItem(FoodRegistry.chocolatebar1, 1);
}
}
/**
* Makes entity wear random armor based on difficulty
*/
protected void addRandomArmor()
{
super.addRandomArmor();
this.setCurrentItemOrArmor(0, new ItemStack(Tools.ChocolateBow));
}
public IEntityLivingData onSpawnWithEgg(IEntityLivingData par1EntityLivingData)
{
par1EntityLivingData = super.onSpawnWithEgg(par1EntityLivingData);
if (this.getRNG().nextInt(5) > 0)
{
this.tasks.addTask(4, this.aiAttackOnCollide);
this.setSkeletonType(1);
this.setCurrentItemOrArmor(0, new ItemStack(Tools.ChocolateSword));
this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(6.0D);
}
else
{
this.tasks.addTask(4, this.aiArrowAttack);
this.addRandomArmor();
this.enchantEquipment();
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readEntityFromNBT(par1NBTTagCompound);
if (par1NBTTagCompound.hasKey("SkeletonType", 99))
{
byte b0 = par1NBTTagCompound.getByte("SkeletonType");
this.setSkeletonType(b0);
}
this.setCombatTask();
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeEntityToNBT(par1NBTTagCompound);
par1NBTTagCompound.setByte("SkeletonType", (byte)this.getSkeletonType());
}
/**
* Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
*/
public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
{
super.setCurrentItemOrArmor(par1, par2ItemStack);
if (!this.worldObj.isRemote && par1 == 0)
{
this.setCombatTask();
}
}
/**
* Returns the Y Offset of this entity.
*/
public double getYOffset()
{
return super.getYOffset() - 0.5D;
}
}
public class Renderchocolateninja extends RenderLiving {
private static final ResourceLocation ninjaTextures = new ResourceLocation("killerjdog51:textures/entities/chocolateninja.png");
public Renderchocolateninja(ModelBase Model, float f) {
super(Model, f);
}
/**
* Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
*/
protected ResourceLocation getEntityTexture(Entitychocolateninja par1Entity)
{
return ninjaTextures;
}
/**
* Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
*/
protected ResourceLocation getEntityTexture(Entity par1Entity)
{
return this.getEntityTexture((Entitychocolateninja)par1Entity);
}
public void doRender(Entity var1, double var2, double var4, double var6,
float var8, float var9) {
// TODO Auto-generated method stub
}
}
Client Proxy
RenderingRegistry.registerEntityRenderingHandler(Entitychocolateninja.class, new Renderchocolateninja(new Modelchocolateninja(), 0.5F));
Mob Registry
int ChocolateNinjaID = EntityRegistry.findGlobalUniqueEntityId();
EntityRegistry.registerGlobalEntityID(Entitychocolateninja.class, "Chocolate Ninja", ChocolateNinjaID);
EntityRegistry.registerModEntity(Entitychocolateninja.class, "Chocolate Ninja", ChocolateNinjaID, MainRegistry.modInstance, 64, 1, true);
EntityList.entityEggs.put(Integer.valueOf(ChocolateNinjaID), new EntityList.EntityEggInfo(ChocolateNinjaID, 0x4A2709, 0x824611));
registerEntity(Entitychocolateninja.class, "Chocolate Ninja");
package com.chocolatemod.mobs;
import java.util.Calendar;
import com.chocolatemod.food.FoodRegistry;
import com.chocolatemod.item.ItemRegistry;
import com.chocolatemod.tools.Tools;
import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIArrowAttack;
import net.minecraft.entity.ai.EntityAIAttackOnCollide;
import net.minecraft.entity.ai.EntityAIFleeSun;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIRestrictSun;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.stats.AchievementList;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.WorldProviderHell;
public class Entitychocolateninja extends EntityMob implements IRangedAttackMob
{
private EntityAIArrowAttack aiArrowAttack = new EntityAIArrowAttack(this, 2.0D, 20, 60, 15.0F);
private EntityAIAttackOnCollide aiAttackOnCollide = new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.2D, false);
private static final String __OBFID = "CL_00001697";
public Entitychocolateninja(World par1World)
{
super(par1World);
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIRestrictSun(this));
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(6, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 0, true));
if (par1World != null && !par1World.isRemote)
{
this.setCombatTask();
}
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.3D);
}
protected void entityInit()
{
super.entityInit();
this.dataWatcher.addObject(13, new Byte((byte)0));
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
/**
* Returns the sound this mob makes while it's alive.
*/
protected String getLivingSound()
{
return "mob.zombie.say";
}
/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "game.player.hurt";
}
/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "game.player.die";
}
protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_)
{
this.playSound("mob.zombie.step", 0.15F, 1.0F);
}
public boolean attackEntityAsMob(Entity par1Entity)
{
if (super.attackEntityAsMob(par1Entity))
{
if (this.getSkeletonType() == 1 && par1Entity instanceof EntityLivingBase)
{
}
return true;
}
else
{
return false;
}
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEFINED;
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
/**
* Handles updating while being ridden by an entity
*/
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource par1DamageSource)
{
super.onDeath(par1DamageSource);
if (par1DamageSource.getSourceOfDamage() instanceof EntityArrow && par1DamageSource.getEntity() instanceof EntityPlayer)
{
EntityPlayer entityplayer = (EntityPlayer)par1DamageSource.getEntity();
double d0 = entityplayer.posX - this.posX;
double d1 = entityplayer.posZ - this.posZ;
if (d0 * d0 + d1 * d1 >= 2500.0D)
{
}
}
}
protected Item getDropItem()
{
return Items.arrow;
}
/**
* Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param
* par2 - Level of Looting used to kill this mob.
*/
protected void dropFewItems(boolean par1, int par2)
{
int j;
int k;
if (this.getSkeletonType() == 1)
{
j = this.rand.nextInt(3 + par2) - 1;
for (k = 0; k < j; ++k)
{
this.dropItem(ItemRegistry.chocolateIngots, 1);
}
}
else
{
j = this.rand.nextInt(3 + par2);
for (k = 0; k < j; ++k)
{
this.dropItem(Items.arrow, 1);
}
}
j = this.rand.nextInt(3 + par2);
for (k = 0; k < j; ++k)
{
this.dropItem(FoodRegistry.chocolatebar1, 1);
}
}
/**
* Makes entity wear random armor based on difficulty
*/
protected void addRandomArmor()
{
super.addRandomArmor();
this.setCurrentItemOrArmor(0, new ItemStack(Tools.ChocolateBow));
}
public IEntityLivingData onSpawnWithEgg(IEntityLivingData par1EntityLivingData)
{
par1EntityLivingData = super.onSpawnWithEgg(par1EntityLivingData);
if (this.getRNG().nextInt(5) > 0)
{
this.tasks.addTask(4, this.aiAttackOnCollide);
this.setSkeletonType(1);
this.setCurrentItemOrArmor(0, new ItemStack(Tools.ChocolateSword));
this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(6.0D);
}
else
{
this.tasks.addTask(4, this.aiArrowAttack);
this.addRandomArmor();
this.enchantEquipment();
}
this.setCanPickUpLoot(this.rand.nextFloat() < 0.55F * this.worldObj.func_147462_b(this.posX, this.posY, this.posZ));
if (this.getEquipmentInSlot(4) == null)
{
Calendar calendar = this.worldObj.getCurrentDate();
if (calendar.get(2) + 1 == 10 && calendar.get(5) == 31 && this.rand.nextFloat() < 0.25F)
{
}
}
return par1EntityLivingData;
}
/**
* sets this entity's combat AI.
*/
public void setCombatTask()
{
this.tasks.removeTask(this.aiAttackOnCollide);
this.tasks.removeTask(this.aiArrowAttack);
ItemStack itemstack = this.getHeldItem();
if (itemstack != null && itemstack.getItem() == Items.bow)
{
this.tasks.addTask(4, this.aiArrowAttack);
}
else
{
this.tasks.addTask(4, this.aiAttackOnCollide);
}
}
/**
* Attack the specified entity using a ranged attack.
*/
public void attackEntityWithRangedAttack(EntityLivingBase par1EntityLivingBase, float par2)
{
EntityArrow entityarrow = new EntityArrow(this.worldObj, this, par1EntityLivingBase, 1.6F, (float)(14 - this.worldObj.difficultySetting.getDifficultyId() * 4));
int i = EnchantmentHelper.getEnchantmentLevel(Enchantment.power.effectId, this.getHeldItem());
int j = EnchantmentHelper.getEnchantmentLevel(Enchantment.punch.effectId, this.getHeldItem());
entityarrow.setDamage((double)(par2 * 2.0F) + this.rand.nextGaussian() * 0.25D + (double)((float)this.worldObj.difficultySetting.getDifficultyId() * 0.11F));
if (i > 0)
{
entityarrow.setDamage(entityarrow.getDamage() + (double)i * 0.5D + 0.5D);
}
if (j > 0)
{
entityarrow.setKnockbackStrength(j);
}
if (EnchantmentHelper.getEnchantmentLevel(Enchantment.flame.effectId, this.getHeldItem()) > 0 || this.getSkeletonType() == 1)
{
entityarrow.setFire(100);
}
this.playSound("random.bow", 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
this.worldObj.spawnEntityInWorld(entityarrow);
}
/**
* Return this skeleton's type.
*/
public int getSkeletonType()
{
return this.dataWatcher.getWatchableObjectByte(13);
}
/**
* Set this skeleton's type.
*/
public void setSkeletonType(int par1)
{
this.dataWatcher.updateObject(13, Byte.valueOf((byte)par1));
this.isImmuneToFire = par1 == 1;
if (par1 == 1)
{
this.setSize(0.72F, 2.34F);
}
else
{
this.setSize(0.6F, 1.8F);
}
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readEntityFromNBT(par1NBTTagCompound);
if (par1NBTTagCompound.hasKey("SkeletonType", 99))
{
byte b0 = par1NBTTagCompound.getByte("SkeletonType");
this.setSkeletonType(b0);
}
this.setCombatTask();
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeEntityToNBT(par1NBTTagCompound);
par1NBTTagCompound.setByte("SkeletonType", (byte)this.getSkeletonType());
}
/**
* Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
*/
public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
{
super.setCurrentItemOrArmor(par1, par2ItemStack);
if (!this.worldObj.isRemote && par1 == 0)
{
this.setCombatTask();
}
}
/**
* Returns the Y Offset of this entity.
*/
public double getYOffset()
{
return super.getYOffset() - 0.5D;
}
}
package com.chocolatemod.mobs;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.MathHelper;
public class Modelchocolateninja extends ModelBase
{
//fields
ModelRenderer head;
ModelRenderer body;
ModelRenderer rightarm;
ModelRenderer leftarm;
ModelRenderer rightleg;
ModelRenderer leftleg;
public Modelchocolateninja()
{
textureWidth = 128;
textureHeight = 64;
head = new ModelRenderer(this, 0, 0);
head.addBox(-4F, -8F, -4F, 8, 8, 8);
head.setRotationPoint(0F, 0F, 0F);
head.setTextureSize(128, 64);
head.mirror = true;
setRotation(head, 0F, 0F, 0F);
body = new ModelRenderer(this, 16, 16);
body.addBox(-4F, 0F, -2F, 8, 12, 4);
body.setRotationPoint(0F, 0F, 0F);
body.setTextureSize(128, 64);
body.mirror = true;
setRotation(body, 0F, 0F, 0F);
rightarm = new ModelRenderer(this, 40, 16);
rightarm.addBox(-3F, -2F, -2F, 4, 12, 4);
rightarm.setRotationPoint(-5F, 2F, 0F);
rightarm.setTextureSize(128, 64);
rightarm.mirror = true;
setRotation(rightarm, 0F, 0F, 0F);
leftarm = new ModelRenderer(this, 40, 16);
leftarm.addBox(-1F, -2F, -2F, 4, 12, 4);
leftarm.setRotationPoint(5F, 2F, 0F);
leftarm.setTextureSize(128, 64);
leftarm.mirror = true;
setRotation(leftarm, 0F, 0F, 0F);
rightleg = new ModelRenderer(this, 0, 32);
rightleg.addBox(-2F, 0F, -2F, 4, 12, 4);
rightleg.setRotationPoint(-2F, 12F, 0F);
rightleg.setTextureSize(128, 64);
rightleg.mirror = true;
setRotation(rightleg, 0F, 0F, 0F);
leftleg = new ModelRenderer(this, 0, 16);
leftleg.addBox(-2F, 0F, -2F, 4, 12, 4);
leftleg.setRotationPoint(2F, 12F, 0F);
leftleg.setTextureSize(128, 64);
leftleg.mirror = true;
setRotation(leftleg, 0F, 0F, 0F);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5)
{
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5);
head.render(f5);
body.render(f5);
rightarm.render(f5);
leftarm.render(f5);
rightleg.render(f5);
leftleg.render(f5);
}
private void setRotation(ModelRenderer model, float x, float y, float z)
{
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5)
{
this.head.rotateAngleX = f4 / (180F / (float)Math.PI);
this.body.rotateAngleX = ((float)Math.PI / 2F);
this.rightarm.rotateAngleX = MathHelper.cos(f * 0.6662F) * 1.4F * f1;
this.leftarm.rotateAngleX = MathHelper.cos(f * 0.6662F + (float)Math.PI) * 1.4F * f1;
this.rightleg.rotateAngleX = MathHelper.cos(f * 0.6662F + (float)Math.PI) * 1.4F * f1;
this.leftleg.rotateAngleX = MathHelper.cos(f * 0.6662F) * 1.4F * f1; }
}
package com.chocolatemod.mobs;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
public class Renderchocolateninja extends RenderLiving {
private static final ResourceLocation ninjaTextures = new ResourceLocation("killerjdog51:textures/entities/chocolateninja.png");
public Renderchocolateninja(ModelBase Model, float f) {
super(Model, f);
}
/**
* Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
*/
protected ResourceLocation getEntityTexture(Entitychocolateninja par1Entity)
{
return ninjaTextures;
}
/**
* Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
*/
protected ResourceLocation getEntityTexture(Entity par1Entity)
{
return this.getEntityTexture((Entitychocolateninja)par1Entity);
}
public void doRender(Entity var1, double var2, double var4, double var6,
float var8, float var9) {
// TODO Auto-generated method stub
}
}
RenderingRegistry.registerEntityRenderingHandler(Entitychocolateninja.class, new Renderchocolateninja(new Modelchocolateninja(), 0.5F));