add evil chickens, fix shouldFlee bug

This commit is contained in:
Sen 2025-06-11 23:11:26 +02:00
parent 46c73c8c46
commit 1258c07c1b
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
5 changed files with 172 additions and 203 deletions

View file

@ -27,8 +27,8 @@ public class RenderChicken extends RenderLiving<EntityChicken>
*/ */
protected float handleRotationFloat(EntityChicken livingBase, float partialTicks) protected float handleRotationFloat(EntityChicken livingBase, float partialTicks)
{ {
float f = livingBase.field_70888_h + (livingBase.wingRotation - livingBase.field_70888_h) * partialTicks; float f = livingBase.lastWingRotation + (livingBase.wingRotation - livingBase.lastWingRotation) * partialTicks;
float f1 = livingBase.field_70884_g + (livingBase.destPos - livingBase.field_70884_g) * partialTicks; float f1 = livingBase.lastDestPos + (livingBase.destPos - livingBase.lastDestPos) * partialTicks;
return (ExtMath.sin(f) + 1.0F) * f1; return (ExtMath.sin(f) + 1.0F) * f1;
} }
} }

View file

@ -1,14 +1,19 @@
package common.entity.animal; package common.entity.animal;
import common.ai.EntityAIAttackOnCollide;
import common.ai.EntityAIFollowParent; import common.ai.EntityAIFollowParent;
import common.ai.EntityAILookIdle; import common.ai.EntityAILookIdle;
import common.ai.EntityAIMate; import common.ai.EntityAIMate;
import common.ai.EntityAINearestAttackableTarget;
import common.ai.EntityAIPanic; import common.ai.EntityAIPanic;
import common.ai.EntityAISwimming; import common.ai.EntityAISwimming;
import common.ai.EntityAITempt; import common.ai.EntityAITempt;
import common.ai.EntityAIWander; import common.ai.EntityAIWander;
import common.ai.EntityAIWatchClosest; import common.ai.EntityAIWatchClosest;
import common.attributes.Attribute; 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.npc.EntityNPC;
import common.entity.types.EntityAnimal; import common.entity.types.EntityAnimal;
import common.entity.types.EntityLiving; import common.entity.types.EntityLiving;
@ -21,23 +26,23 @@ import common.util.ExtMath;
import common.vars.Vars; import common.vars.Vars;
import common.world.World; import common.world.World;
public class EntityChicken extends EntityAnimal 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 wingRotation;
public float lastWingRotation;
public float destPos; public float destPos;
public float field_70884_g; public float lastDestPos;
public float field_70888_h; private float wingRotDelta = 1.0F;
public float wingRotDelta = 1.0F; private int eggTimer;
private boolean noEggs;
private boolean attackSet;
/** The time until the next egg is spawned. */ public EntityChicken(World world) {
public int timeUntilNextEgg; super(world);
public boolean chickenJockey;
public EntityChicken(World worldIn)
{
super(worldIn);
this.setSize(0.4F, 0.7F); this.setSize(0.4F, 0.7F);
this.timeUntilNextEgg = worldIn.client || Vars.eggTimer <= 0 ? 1000 : this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2); 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(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityAIPanic(this, 1.4D)); this.tasks.addTask(1, new EntityAIPanic(this, 1.4D));
this.tasks.addTask(2, new EntityAIMate(this, 1.0D)); this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
@ -48,198 +53,158 @@ public class EntityChicken extends EntityAnimal
this.tasks.addTask(7, new EntityAILookIdle(this)); this.tasks.addTask(7, new EntityAILookIdle(this));
} }
public float getEyeHeight() public float getEyeHeight() {
{
return this.height; return this.height;
} }
protected void applyEntityAttributes() protected void entityInit() {
{ super.entityInit();
this.dataWatcher.addObject(18, Byte.valueOf((byte)0));
}
protected void applyEntityAttributes() {
super.applyEntityAttributes(); super.applyEntityAttributes();
this.setMaxHealth(4); this.setMaxHealth(4);
this.getEntityAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.25D); this.getEntityAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.25D);
} }
/** public void onLivingUpdate() {
* 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(); super.onLivingUpdate();
this.field_70888_h = this.wingRotation; this.lastWingRotation = this.wingRotation;
this.field_70884_g = this.destPos; this.lastDestPos = this.destPos;
this.destPos = (float)((double)this.destPos + (double)(this.onGround ? -1 : 4) * 0.3D); this.destPos = (float)((double)this.destPos + (double)(this.onGround ? -1 : 4) * 0.3D);
this.destPos = ExtMath.clampf(this.destPos, 0.0F, 1.0F); this.destPos = ExtMath.clampf(this.destPos, 0.0F, 1.0F);
if(!this.onGround && this.wingRotDelta < 1.0F) if(!this.onGround && this.wingRotDelta < 1.0F)
{
this.wingRotDelta = 1.0F; this.wingRotDelta = 1.0F;
}
this.wingRotDelta = (float)((double)this.wingRotDelta * 0.9D); this.wingRotDelta = (float)((double)this.wingRotDelta * 0.9D);
if(!this.onGround && this.motionY < 0.0D) if(!this.onGround && this.motionY < 0.0D)
{
this.motionY *= 0.6D; this.motionY *= 0.6D;
}
this.wingRotation += this.wingRotDelta * 2.0F; this.wingRotation += this.wingRotDelta * 2.0F;
if(!this.worldObj.client) {
if (!this.worldObj.client && Vars.eggTimer > 0 && !this.isChild() && !this.isChickenJockey() && --this.timeUntilNextEgg <= 0) if(Vars.eggTimer > 0 && !this.isChild() && !this.noEggs && --this.eggTimer <= 0) {
{
this.playSound(SoundEvent.PLOP, 1.0F); this.playSound(SoundEvent.PLOP, 1.0F);
this.dropItem(Items.egg, 1); this.dropItem(Items.egg, 1);
this.timeUntilNextEgg = this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2); 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;
}
} }
} }
public void fall(float distance, float damageMultiplier) public void fall(float distance, float damage) {
{
} }
/** protected SoundEvent getLivingSound() {
* Returns the sound this mob makes while it's alive.
*/
protected SoundEvent getLivingSound()
{
return SoundEvent.CHICKEN_IDLE; return SoundEvent.CHICKEN_IDLE;
} }
/** protected SoundEvent getHurtSound() {
* Returns the sound this mob makes when it is hurt.
*/
protected SoundEvent getHurtSound()
{
return SoundEvent.CHICKEN_HIT; return SoundEvent.CHICKEN_HIT;
} }
/** protected SoundEvent getDeathSound() {
* Returns the sound this mob makes on death.
*/
protected SoundEvent getDeathSound()
{
return SoundEvent.CHICKEN_HIT; return SoundEvent.CHICKEN_HIT;
} }
// protected void playStepSound(BlockPos pos, Block blockIn) protected Item getDropItem() {
// {
// this.playSound("mob.chicken.step", 0.15F, 1.0F);
// }
protected Item getDropItem()
{
return Items.feather; return Items.feather;
} }
/** protected void dropFewItems(boolean hit, int looting) {
* Drop 0-2 items of this living's type int amt = this.rand.zrange(3) + this.rand.zrange(1 + looting);
* for(int z = 0; z < amt; z++) {
* @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);
for (int j = 0; j < i; ++j)
{
this.dropItem(Items.feather, 1); this.dropItem(Items.feather, 1);
} }
this.dropItem(this.isBurning() ? Items.cooked_chicken : Items.chicken, 1);
if (this.isBurning())
{
this.dropItem(Items.cooked_chicken, 1);
}
else
{
this.dropItem(Items.chicken, 1);
}
} }
public EntityChicken createChild(EntityLiving ageable) public EntityChicken createChild(EntityLiving entity) {
{ EntityChicken chick = new EntityChicken(this.worldObj);
return new EntityChicken(this.worldObj); chick.setEvil(this.isEvil());
chick.setNotLaying(this.isNotLaying());
return chick;
} }
/** public boolean isBreedingItem(ItemStack stack) {
* 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; return stack != null && stack.getItem() == Items.wheat;
} }
/** public void readEntity(TagObject tag) {
* (abstract) Protected helper method to read subclass entity data from NBT. super.readEntity(tag);
*/ this.setEvil(tag.getBool("evil"));
public void readEntity(TagObject tagCompund) this.noEggs = tag.getBool("noEggs");
{ this.eggTimer = tag.getInt("eggTime");
super.readEntity(tagCompund);
this.chickenJockey = tagCompund.getBool("IsChickenJockey");
this.timeUntilNextEgg = tagCompund.getInt("EggLayTime");
} }
/** public void writeEntity(TagObject tag) {
* Get the experience points the entity currently has. super.writeEntity(tag);
*/ tag.setBool("evil", this.isEvil());
protected int getExperiencePoints(EntityNPC player) tag.setBool("noEggs", this.noEggs);
{ tag.setInt("eggTime", this.eggTimer);
return this.isChickenJockey() ? 10 : super.getExperiencePoints(player);
} }
/** public void updateRiderPosition() {
* (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(); super.updateRiderPosition();
float f = ExtMath.sin(this.yawOffset * (float)Math.PI / 180.0F); float x = ExtMath.sin(this.yawOffset * (float)Math.PI / 180.0F);
float f1 = ExtMath.cos(this.yawOffset * (float)Math.PI / 180.0F); float z = ExtMath.cos(this.yawOffset * (float)Math.PI / 180.0F);
float f2 = 0.1F; float mult = 0.1F;
float f3 = 0.0F; float off = 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)); 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) if(this.passenger instanceof EntityLiving)
{
((EntityLiving)this.passenger).yawOffset = this.yawOffset; ((EntityLiving)this.passenger).yawOffset = this.yawOffset;
} }
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) {
* Determines if this chicken is a jokey with a zombie riding it. livingdata = super.onInitialSpawn(livingdata);
*/ if(Vars.evilChickenChance > 0 && this.rand.chance(Vars.evilChickenChance))
public boolean isChickenJockey() this.setEvil(true);
{ if(this.rand.chance(15))
return this.chickenJockey; this.setGrowingAge(-24000);
return livingdata;
} }
/** protected boolean canBeEvil() {
* Sets whether this chicken is a jockey or not. return this.isEvil() || Vars.aggressiveChickens;
*/ }
public void setChickenJockey(boolean jockey)
{ public boolean isEvil() {
this.chickenJockey = jockey; return this.dataWatcher.getWatchableObjectByte(18) != 0;
}
public void setEvil(boolean evil) {
this.dataWatcher.updateObject(18, (byte)(evil ? 1 : 0));
}
public boolean isNotLaying() {
return this.noEggs;
}
public void setNotLaying(boolean noEggs) {
this.noEggs = noEggs;
} }
public int getColor() { public int getColor() {
return 0xdb5152; return 0xdb5152;
} }
public Alignment getAlignment() {
return this.isEvil() ? Alignment.CHAOTIC_EVIL : Alignment.CHAOTIC;
}
} }

View file

@ -440,8 +440,8 @@ public abstract class EntityNPC extends EntityLiving
public boolean shouldFlee(EntityLiving entity) { public boolean shouldFlee(EntityLiving entity) {
return (this.getHealth() <= (this.getMaxHealth() / 4) || !this.canCounter(entity)) && return (this.getHealth() <= (this.getMaxHealth() / 4) || !this.canCounter(entity)) &&
((entity instanceof EntityNPC && (((EntityNPC)entity).canAttack(this)) || ((entity instanceof EntityNPC && ((((EntityNPC)entity).canAttack(this)) ||
(entity == this.getAttackedBy() && ((EntityNPC)entity).canCounter(this)))); (entity == this.getAttackedBy() && ((EntityNPC)entity).canCounter(this)))));
} }
// public void setCombatTask() // public void setCombatTask()
@ -893,7 +893,7 @@ public abstract class EntityNPC extends EntityLiving
public void setAttackedBy(EntityLiving livingBase) public void setAttackedBy(EntityLiving livingBase)
{ {
if(livingBase != null && /* livingBase.isPlayer() && */ this.isEntityAlive() && /* !this.isPeaceful() && */ this.getAttackedBy() != 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); this.worldObj.setEntityState(this, (byte)13);
} }
super.setAttackedBy(livingBase); super.setAttackedBy(livingBase);

View file

@ -219,7 +219,7 @@ public class EntityZombie extends EntityNPC
if (!list.isEmpty()) if (!list.isEmpty())
{ {
EntityChicken entitychicken = (EntityChicken)list.get(0); EntityChicken entitychicken = (EntityChicken)list.get(0);
entitychicken.setChickenJockey(true); entitychicken.setNotLaying(true);
this.mountEntity(entitychicken); this.mountEntity(entitychicken);
} }
} }
@ -228,7 +228,7 @@ public class EntityZombie extends EntityNPC
EntityChicken entitychicken1 = new EntityChicken(this.worldObj); EntityChicken entitychicken1 = new EntityChicken(this.worldObj);
entitychicken1.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotYaw, 0.0F); entitychicken1.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotYaw, 0.0F);
entitychicken1.onInitialSpawn(null); entitychicken1.onInitialSpawn(null);
entitychicken1.setChickenJockey(true); entitychicken1.setNotLaying(true);
this.worldObj.spawnEntityInWorld(entitychicken1); this.worldObj.spawnEntityInWorld(entitychicken1);
this.mountEntity(entitychicken1); this.mountEntity(entitychicken1);
} }

View file

@ -200,6 +200,8 @@ public abstract class Vars {
public static boolean mergeFinite = false; public static boolean mergeFinite = false;
@Var(name = "veryHungryRabbits") @Var(name = "veryHungryRabbits")
public static boolean rabidRabbits = false; public static boolean rabidRabbits = false;
@Var(name = "evilFowl")
public static boolean aggressiveChickens = false;
@Var(name = "hurtCooldown") @Var(name = "hurtCooldown")
public static int hurtDelay = 20; public static int hurtDelay = 20;
@ -213,6 +215,8 @@ public abstract class Vars {
public static int rabbitMateChance = 10; public static int rabbitMateChance = 10;
@Var(name = "killerBunnyChance") @Var(name = "killerBunnyChance")
public static int killerBunnyChance = 1000; public static int killerBunnyChance = 1000;
@Var(name = "evilChickenChance")
public static int evilChickenChance = 700;
@Var(name = "fallPortalHeight") @Var(name = "fallPortalHeight")
public static int portalHeight = 256; public static int portalHeight = 256;
@Var(name = "damageOrb") @Var(name = "damageOrb")