add evil chickens, fix shouldFlee bug
This commit is contained in:
parent
46c73c8c46
commit
1258c07c1b
5 changed files with 172 additions and 203 deletions
|
@ -27,8 +27,8 @@ public class RenderChicken extends RenderLiving<EntityChicken>
|
|||
*/
|
||||
protected float handleRotationFloat(EntityChicken livingBase, float partialTicks)
|
||||
{
|
||||
float f = livingBase.field_70888_h + (livingBase.wingRotation - livingBase.field_70888_h) * partialTicks;
|
||||
float f1 = livingBase.field_70884_g + (livingBase.destPos - livingBase.field_70884_g) * partialTicks;
|
||||
float f = livingBase.lastWingRotation + (livingBase.wingRotation - livingBase.lastWingRotation) * partialTicks;
|
||||
float f1 = livingBase.lastDestPos + (livingBase.destPos - livingBase.lastDestPos) * partialTicks;
|
||||
return (ExtMath.sin(f) + 1.0F) * f1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package common.entity.animal;
|
||||
|
||||
import common.ai.EntityAIAttackOnCollide;
|
||||
import common.ai.EntityAIFollowParent;
|
||||
import common.ai.EntityAILookIdle;
|
||||
import common.ai.EntityAIMate;
|
||||
import common.ai.EntityAINearestAttackableTarget;
|
||||
import common.ai.EntityAIPanic;
|
||||
import common.ai.EntityAISwimming;
|
||||
import common.ai.EntityAITempt;
|
||||
import common.ai.EntityAIWander;
|
||||
import common.ai.EntityAIWatchClosest;
|
||||
import common.attributes.Attribute;
|
||||
import common.entity.DamageSource;
|
||||
import common.entity.Entity;
|
||||
import common.entity.npc.Alignment;
|
||||
import common.entity.npc.EntityNPC;
|
||||
import common.entity.types.EntityAnimal;
|
||||
import common.entity.types.EntityLiving;
|
||||
|
@ -21,225 +26,185 @@ import common.util.ExtMath;
|
|||
import common.vars.Vars;
|
||||
import common.world.World;
|
||||
|
||||
public class EntityChicken extends EntityAnimal
|
||||
{
|
||||
public float wingRotation;
|
||||
public float destPos;
|
||||
public float field_70884_g;
|
||||
public float field_70888_h;
|
||||
public float wingRotDelta = 1.0F;
|
||||
public class EntityChicken extends EntityAnimal {
|
||||
private final EntityAIAttackOnCollide attack = new EntityAIAttackOnCollide(this, EntityNPC.class, 1.4, false);
|
||||
private final EntityAINearestAttackableTarget targetter = new EntityAINearestAttackableTarget(this, EntityNPC.class, true);
|
||||
|
||||
public float wingRotation;
|
||||
public float lastWingRotation;
|
||||
public float destPos;
|
||||
public float lastDestPos;
|
||||
private float wingRotDelta = 1.0F;
|
||||
private int eggTimer;
|
||||
private boolean noEggs;
|
||||
private boolean attackSet;
|
||||
|
||||
/** The time until the next egg is spawned. */
|
||||
public int timeUntilNextEgg;
|
||||
public boolean chickenJockey;
|
||||
public EntityChicken(World world) {
|
||||
super(world);
|
||||
this.setSize(0.4F, 0.7F);
|
||||
this.eggTimer = world.client || Vars.eggTimer <= 0 ? 1000 : this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2);
|
||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
||||
this.tasks.addTask(1, new EntityAIPanic(this, 1.4D));
|
||||
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(3, new EntityAITempt(this, 1.0D, Items.wheat, false));
|
||||
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
|
||||
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(6, new EntityAIWatchClosest(this, null, 6.0F));
|
||||
this.tasks.addTask(7, new EntityAILookIdle(this));
|
||||
}
|
||||
|
||||
public EntityChicken(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.4F, 0.7F);
|
||||
this.timeUntilNextEgg = worldIn.client || Vars.eggTimer <= 0 ? 1000 : this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2);
|
||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
||||
this.tasks.addTask(1, new EntityAIPanic(this, 1.4D));
|
||||
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(3, new EntityAITempt(this, 1.0D, Items.wheat, false));
|
||||
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
|
||||
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(6, new EntityAIWatchClosest(this, null, 6.0F));
|
||||
this.tasks.addTask(7, new EntityAILookIdle(this));
|
||||
}
|
||||
public float getEyeHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return this.height;
|
||||
}
|
||||
protected void entityInit() {
|
||||
super.entityInit();
|
||||
this.dataWatcher.addObject(18, Byte.valueOf((byte)0));
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(4);
|
||||
this.getEntityAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.25D);
|
||||
}
|
||||
protected void applyEntityAttributes() {
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(4);
|
||||
this.getEntityAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.25D);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void onLivingUpdate()
|
||||
{
|
||||
super.onLivingUpdate();
|
||||
this.field_70888_h = this.wingRotation;
|
||||
this.field_70884_g = this.destPos;
|
||||
this.destPos = (float)((double)this.destPos + (double)(this.onGround ? -1 : 4) * 0.3D);
|
||||
this.destPos = ExtMath.clampf(this.destPos, 0.0F, 1.0F);
|
||||
public void onLivingUpdate() {
|
||||
super.onLivingUpdate();
|
||||
this.lastWingRotation = this.wingRotation;
|
||||
this.lastDestPos = this.destPos;
|
||||
this.destPos = (float)((double)this.destPos + (double)(this.onGround ? -1 : 4) * 0.3D);
|
||||
this.destPos = ExtMath.clampf(this.destPos, 0.0F, 1.0F);
|
||||
if(!this.onGround && this.wingRotDelta < 1.0F)
|
||||
this.wingRotDelta = 1.0F;
|
||||
this.wingRotDelta = (float)((double)this.wingRotDelta * 0.9D);
|
||||
if(!this.onGround && this.motionY < 0.0D)
|
||||
this.motionY *= 0.6D;
|
||||
this.wingRotation += this.wingRotDelta * 2.0F;
|
||||
if(!this.worldObj.client) {
|
||||
if(Vars.eggTimer > 0 && !this.isChild() && !this.noEggs && --this.eggTimer <= 0) {
|
||||
this.playSound(SoundEvent.PLOP, 1.0F);
|
||||
this.dropItem(Items.egg, 1);
|
||||
this.eggTimer = this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2);
|
||||
}
|
||||
boolean evil = this.canBeEvil();
|
||||
if(evil != this.attackSet) {
|
||||
if(evil) {
|
||||
this.tasks.addTask(1, this.attack);
|
||||
this.targets.addTask(1, this.targetter);
|
||||
}
|
||||
else {
|
||||
this.tasks.removeTask(this.attack);
|
||||
this.targets.removeTask(this.targetter);
|
||||
}
|
||||
this.attackSet = evil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.onGround && this.wingRotDelta < 1.0F)
|
||||
{
|
||||
this.wingRotDelta = 1.0F;
|
||||
}
|
||||
public void fall(float distance, float damage) {
|
||||
}
|
||||
|
||||
this.wingRotDelta = (float)((double)this.wingRotDelta * 0.9D);
|
||||
protected SoundEvent getLivingSound() {
|
||||
return SoundEvent.CHICKEN_IDLE;
|
||||
}
|
||||
|
||||
if (!this.onGround && this.motionY < 0.0D)
|
||||
{
|
||||
this.motionY *= 0.6D;
|
||||
}
|
||||
protected SoundEvent getHurtSound() {
|
||||
return SoundEvent.CHICKEN_HIT;
|
||||
}
|
||||
|
||||
this.wingRotation += this.wingRotDelta * 2.0F;
|
||||
protected SoundEvent getDeathSound() {
|
||||
return SoundEvent.CHICKEN_HIT;
|
||||
}
|
||||
|
||||
if (!this.worldObj.client && Vars.eggTimer > 0 && !this.isChild() && !this.isChickenJockey() && --this.timeUntilNextEgg <= 0)
|
||||
{
|
||||
this.playSound(SoundEvent.PLOP, 1.0F);
|
||||
this.dropItem(Items.egg, 1);
|
||||
this.timeUntilNextEgg = this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2);
|
||||
}
|
||||
}
|
||||
protected Item getDropItem() {
|
||||
return Items.feather;
|
||||
}
|
||||
|
||||
public void fall(float distance, float damageMultiplier)
|
||||
{
|
||||
}
|
||||
protected void dropFewItems(boolean hit, int looting) {
|
||||
int amt = this.rand.zrange(3) + this.rand.zrange(1 + looting);
|
||||
for(int z = 0; z < amt; z++) {
|
||||
this.dropItem(Items.feather, 1);
|
||||
}
|
||||
this.dropItem(this.isBurning() ? Items.cooked_chicken : Items.chicken, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return SoundEvent.CHICKEN_IDLE;
|
||||
}
|
||||
public EntityChicken createChild(EntityLiving entity) {
|
||||
EntityChicken chick = new EntityChicken(this.worldObj);
|
||||
chick.setEvil(this.isEvil());
|
||||
chick.setNotLaying(this.isNotLaying());
|
||||
return chick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.CHICKEN_HIT;
|
||||
}
|
||||
public boolean isBreedingItem(ItemStack stack) {
|
||||
return stack != null && stack.getItem() == Items.wheat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.CHICKEN_HIT;
|
||||
}
|
||||
public void readEntity(TagObject tag) {
|
||||
super.readEntity(tag);
|
||||
this.setEvil(tag.getBool("evil"));
|
||||
this.noEggs = tag.getBool("noEggs");
|
||||
this.eggTimer = tag.getInt("eggTime");
|
||||
}
|
||||
|
||||
// protected void playStepSound(BlockPos pos, Block blockIn)
|
||||
// {
|
||||
// this.playSound("mob.chicken.step", 0.15F, 1.0F);
|
||||
// }
|
||||
public void writeEntity(TagObject tag) {
|
||||
super.writeEntity(tag);
|
||||
tag.setBool("evil", this.isEvil());
|
||||
tag.setBool("noEggs", this.noEggs);
|
||||
tag.setInt("eggTime", this.eggTimer);
|
||||
}
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return Items.feather;
|
||||
}
|
||||
public void updateRiderPosition() {
|
||||
super.updateRiderPosition();
|
||||
float x = ExtMath.sin(this.yawOffset * (float)Math.PI / 180.0F);
|
||||
float z = ExtMath.cos(this.yawOffset * (float)Math.PI / 180.0F);
|
||||
float mult = 0.1F;
|
||||
float off = 0.0F;
|
||||
this.passenger.setPosition(this.posX + (double)(mult * x),
|
||||
this.posY + (double)(this.height * 0.5F) + this.passenger.getYOffset() + (double)off, this.posZ - (double)(mult * z));
|
||||
if(this.passenger instanceof EntityLiving)
|
||||
((EntityLiving)this.passenger).yawOffset = this.yawOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop 0-2 items of this living's type
|
||||
*
|
||||
* @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player
|
||||
* or tameable)
|
||||
* @param lootingModifier level of enchanment to be applied to this drop
|
||||
*/
|
||||
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier)
|
||||
{
|
||||
int i = this.rand.zrange(3) + this.rand.zrange(1 + lootingModifier);
|
||||
public boolean attackEntityAsMob(Entity entityIn) {
|
||||
if(!this.worldObj.client && !Vars.damageMobs)
|
||||
return false;
|
||||
return entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), this.isChild() ? 1 : 2);
|
||||
}
|
||||
|
||||
public Object onInitialSpawn(Object livingdata) {
|
||||
livingdata = super.onInitialSpawn(livingdata);
|
||||
if(Vars.evilChickenChance > 0 && this.rand.chance(Vars.evilChickenChance))
|
||||
this.setEvil(true);
|
||||
if(this.rand.chance(15))
|
||||
this.setGrowingAge(-24000);
|
||||
return livingdata;
|
||||
}
|
||||
|
||||
protected boolean canBeEvil() {
|
||||
return this.isEvil() || Vars.aggressiveChickens;
|
||||
}
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
this.dropItem(Items.feather, 1);
|
||||
}
|
||||
public boolean isEvil() {
|
||||
return this.dataWatcher.getWatchableObjectByte(18) != 0;
|
||||
}
|
||||
|
||||
if (this.isBurning())
|
||||
{
|
||||
this.dropItem(Items.cooked_chicken, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dropItem(Items.chicken, 1);
|
||||
}
|
||||
}
|
||||
public void setEvil(boolean evil) {
|
||||
this.dataWatcher.updateObject(18, (byte)(evil ? 1 : 0));
|
||||
}
|
||||
|
||||
public EntityChicken createChild(EntityLiving ageable)
|
||||
{
|
||||
return new EntityChicken(this.worldObj);
|
||||
}
|
||||
public boolean isNotLaying() {
|
||||
return this.noEggs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
|
||||
* the animal type)
|
||||
*/
|
||||
public boolean isBreedingItem(ItemStack stack)
|
||||
{
|
||||
return stack != null && stack.getItem() == Items.wheat;
|
||||
}
|
||||
public void setNotLaying(boolean noEggs) {
|
||||
this.noEggs = noEggs;
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntity(TagObject tagCompund)
|
||||
{
|
||||
super.readEntity(tagCompund);
|
||||
this.chickenJockey = tagCompund.getBool("IsChickenJockey");
|
||||
this.timeUntilNextEgg = tagCompund.getInt("EggLayTime");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the experience points the entity currently has.
|
||||
*/
|
||||
protected int getExperiencePoints(EntityNPC player)
|
||||
{
|
||||
return this.isChickenJockey() ? 10 : super.getExperiencePoints(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntity(TagObject tagCompound)
|
||||
{
|
||||
super.writeEntity(tagCompound);
|
||||
tagCompound.setBool("IsChickenJockey", this.chickenJockey);
|
||||
tagCompound.setInt("EggLayTime", this.timeUntilNextEgg);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Determines if an entity can be despawned, used on idle far away entities
|
||||
// */
|
||||
// protected boolean canDespawn()
|
||||
// {
|
||||
// return this.isChickenJockey() && this.passenger == null;
|
||||
// }
|
||||
|
||||
public void updateRiderPosition()
|
||||
{
|
||||
super.updateRiderPosition();
|
||||
float f = ExtMath.sin(this.yawOffset * (float)Math.PI / 180.0F);
|
||||
float f1 = ExtMath.cos(this.yawOffset * (float)Math.PI / 180.0F);
|
||||
float f2 = 0.1F;
|
||||
float f3 = 0.0F;
|
||||
this.passenger.setPosition(this.posX + (double)(f2 * f), this.posY + (double)(this.height * 0.5F) + this.passenger.getYOffset() + (double)f3, this.posZ - (double)(f2 * f1));
|
||||
|
||||
if (this.passenger instanceof EntityLiving)
|
||||
{
|
||||
((EntityLiving)this.passenger).yawOffset = this.yawOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this chicken is a jokey with a zombie riding it.
|
||||
*/
|
||||
public boolean isChickenJockey()
|
||||
{
|
||||
return this.chickenJockey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this chicken is a jockey or not.
|
||||
*/
|
||||
public void setChickenJockey(boolean jockey)
|
||||
{
|
||||
this.chickenJockey = jockey;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0xdb5152;
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return this.isEvil() ? Alignment.CHAOTIC_EVIL : Alignment.CHAOTIC;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -440,8 +440,8 @@ public abstract class EntityNPC extends EntityLiving
|
|||
|
||||
public boolean shouldFlee(EntityLiving entity) {
|
||||
return (this.getHealth() <= (this.getMaxHealth() / 4) || !this.canCounter(entity)) &&
|
||||
((entity instanceof EntityNPC && (((EntityNPC)entity).canAttack(this)) ||
|
||||
(entity == this.getAttackedBy() && ((EntityNPC)entity).canCounter(this))));
|
||||
((entity instanceof EntityNPC && ((((EntityNPC)entity).canAttack(this)) ||
|
||||
(entity == this.getAttackedBy() && ((EntityNPC)entity).canCounter(this)))));
|
||||
}
|
||||
|
||||
// public void setCombatTask()
|
||||
|
@ -893,7 +893,7 @@ public abstract class EntityNPC extends EntityLiving
|
|||
public void setAttackedBy(EntityLiving livingBase)
|
||||
{
|
||||
if(livingBase != null && /* livingBase.isPlayer() && */ this.isEntityAlive() && /* !this.isPeaceful() && */ this.getAttackedBy() != livingBase &&
|
||||
Vars.mobAttacks) {
|
||||
Vars.mobAttacks && !this.isPlayer()) {
|
||||
this.worldObj.setEntityState(this, (byte)13);
|
||||
}
|
||||
super.setAttackedBy(livingBase);
|
||||
|
|
|
@ -219,7 +219,7 @@ public class EntityZombie extends EntityNPC
|
|||
if (!list.isEmpty())
|
||||
{
|
||||
EntityChicken entitychicken = (EntityChicken)list.get(0);
|
||||
entitychicken.setChickenJockey(true);
|
||||
entitychicken.setNotLaying(true);
|
||||
this.mountEntity(entitychicken);
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ public class EntityZombie extends EntityNPC
|
|||
EntityChicken entitychicken1 = new EntityChicken(this.worldObj);
|
||||
entitychicken1.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotYaw, 0.0F);
|
||||
entitychicken1.onInitialSpawn(null);
|
||||
entitychicken1.setChickenJockey(true);
|
||||
entitychicken1.setNotLaying(true);
|
||||
this.worldObj.spawnEntityInWorld(entitychicken1);
|
||||
this.mountEntity(entitychicken1);
|
||||
}
|
||||
|
|
|
@ -200,6 +200,8 @@ public abstract class Vars {
|
|||
public static boolean mergeFinite = false;
|
||||
@Var(name = "veryHungryRabbits")
|
||||
public static boolean rabidRabbits = false;
|
||||
@Var(name = "evilFowl")
|
||||
public static boolean aggressiveChickens = false;
|
||||
|
||||
@Var(name = "hurtCooldown")
|
||||
public static int hurtDelay = 20;
|
||||
|
@ -213,6 +215,8 @@ public abstract class Vars {
|
|||
public static int rabbitMateChance = 10;
|
||||
@Var(name = "killerBunnyChance")
|
||||
public static int killerBunnyChance = 1000;
|
||||
@Var(name = "evilChickenChance")
|
||||
public static int evilChickenChance = 700;
|
||||
@Var(name = "fallPortalHeight")
|
||||
public static int portalHeight = 256;
|
||||
@Var(name = "damageOrb")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue