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)
{
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;
}
}

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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")