diff options
author | Alkalus <3060479+draknyte1@users.noreply.github.com> | 2019-08-02 17:36:00 +0100 |
---|---|---|
committer | Alkalus <3060479+draknyte1@users.noreply.github.com> | 2019-08-02 17:36:00 +0100 |
commit | 77a25b1f5fab73f8354ca842650ff86534804b8b (patch) | |
tree | 7d24faa067ea721bc5579d7b179070e7e222b7fc /src/Java/gtPlusPlus/core | |
parent | c53e25d2e3887c483f6fb2999295eae788127188 (diff) | |
download | GT5-Unofficial-77a25b1f5fab73f8354ca842650ff86534804b8b.tar.gz GT5-Unofficial-77a25b1f5fab73f8354ca842650ff86534804b8b.tar.bz2 GT5-Unofficial-77a25b1f5fab73f8354ca842650ff86534804b8b.zip |
% More work on the Bat King.
Diffstat (limited to 'src/Java/gtPlusPlus/core')
-rw-r--r-- | src/Java/gtPlusPlus/core/entity/ai/batking/EntityAIBatKingAttack.java | 384 | ||||
-rw-r--r-- | src/Java/gtPlusPlus/core/entity/monster/EntityBatKing.java | 820 |
2 files changed, 923 insertions, 281 deletions
diff --git a/src/Java/gtPlusPlus/core/entity/ai/batking/EntityAIBatKingAttack.java b/src/Java/gtPlusPlus/core/entity/ai/batking/EntityAIBatKingAttack.java new file mode 100644 index 0000000000..bad7030c88 --- /dev/null +++ b/src/Java/gtPlusPlus/core/entity/ai/batking/EntityAIBatKingAttack.java @@ -0,0 +1,384 @@ +package gtPlusPlus.core.entity.ai.batking; + +import gtPlusPlus.core.entity.monster.EntityBatKing; +import gtPlusPlus.core.util.minecraft.EntityUtils; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IRangedAttackMob; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.pathfinding.PathEntity; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.MathHelper; + +public class EntityAIBatKingAttack extends EntityAIBase { + + private final Ranged mRangedAI; + private final Melee mMeleeAI; + private boolean mIsMelee = false; + + /** The Bat King in control of this AI. */ + private final EntityBatKing mAttackingEntity; + + /** The PathEntity of our entity. */ + private PathEntity mEntityPathEntity; + + /** The current target of Bat King in control of this AI. */ + private EntityLivingBase mEntityTarget; + + private final Class mClassTarget; + + public EntityAIBatKingAttack(EntityAIBatKingAttack aParent, EntityBatKing aAttacker, Class aClassTarget, + double aMovementSpeed, int someInt, int aMaxRangedAttackTime, float someFloat, boolean aLongMemory) { + mRangedAI = new Ranged(aParent, aMovementSpeed, someInt, aMaxRangedAttackTime, someFloat); + mMeleeAI = new Melee(aParent, aClassTarget, aMovementSpeed, aLongMemory); + mAttackingEntity = aAttacker; + mClassTarget = aClassTarget; + } + + @Override + public boolean shouldExecute() { + EntityLivingBase entitylivingbase = this.mAttackingEntity.getAttackTarget(); + if (entitylivingbase == null) { + this.mEntityTarget = null; + return false; + } else if (!entitylivingbase.isEntityAlive()) { + return false; + } else if (this.mClassTarget != null && !this.mClassTarget.isAssignableFrom(entitylivingbase.getClass())) { + return false; + } else { + if (this.mIsMelee) { + return this.mMeleeAI.shouldExecute(); + } + else { + this.mEntityTarget = entitylivingbase; + this.mEntityPathEntity = this.mAttackingEntity.getNavigator().getPathToEntityLiving(entitylivingbase); + return mRangedAI != null && mMeleeAI != null && hasValidTarget(); + } + } + } + + public EntityBatKing getBatKing() { + return this.mAttackingEntity; + } + + public IRangedAttackMob getBatKingAsIRangedAttackMob() { + return this.mAttackingEntity; + } + + public boolean hasValidTarget() { + return this.mEntityTarget != null; + } + + public EntityLivingBase getTarget() { + return mEntityTarget; + } + + @Override + public boolean continueExecuting() { + if (mIsMelee) { + return mMeleeAI.continueExecuting(); + } else { + return mRangedAI.continueExecuting(); + } + } + + @Override + public boolean isInterruptible() { + if (mIsMelee) { + + } else { + + } + return super.isInterruptible(); + } + + @Override + public void startExecuting() { + if (mIsMelee) { + mMeleeAI.startExecuting(); + } else { + mRangedAI.startExecuting(); + } + } + + @Override + public void resetTask() { + if (mIsMelee) { + mMeleeAI.resetTask(); + } else { + mRangedAI.resetTask(); + } + } + + @Override + public void updateTask() { + determineCombatStyle(); + if (mIsMelee) { + mMeleeAI.updateTask(); + } else { + mRangedAI.updateTask(); + } + } + + + private final void determineCombatStyle() { + if (this.mEntityTarget != null && EntityUtils.getDistance(getBatKing(), mEntityTarget) < 4) { + this.mIsMelee = true; + } + else { + this.mIsMelee = false; + } + } + + private class Ranged { + + private final EntityAIBatKingAttack parentAI; + + /** + * A decrementing tick that spawns a ranged attack once this value reaches 0. It + * is then set back to the maxRangedAttackTime. + */ + private int rangedAttackTime; + private double entityMoveSpeed; + private int mCooldownTime; + private int field_96561_g; + /** + * The maximum time the AI has to wait before performing another ranged attack. + */ + private int maxRangedAttackTime; + private float field_96562_i; + private float field_82642_h; + + public Ranged(EntityAIBatKingAttack aParent, double aMovementSpeed, int someInt, + int aMaxRangedAttackTime, float someFloat) { + this.rangedAttackTime = -1; + this.parentAI = aParent; + this.entityMoveSpeed = aMovementSpeed; + this.field_96561_g = someInt; + this.maxRangedAttackTime = aMaxRangedAttackTime; + this.field_96562_i = someFloat; + this.field_82642_h = someFloat * someFloat; + parentAI.setMutexBits(3); + + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() { + parentAI.getBatKing().getNavigator().setPath(parentAI.mEntityPathEntity, this.entityMoveSpeed); + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + public boolean continueExecuting() { + return parentAI.shouldExecute() || !parentAI.getBatKing().getNavigator().noPath(); + } + + /** + * Resets the task + */ + public void resetTask() { + parentAI.mEntityTarget = null; + this.mCooldownTime = 0; + this.rangedAttackTime = -1; + } + + /** + * Updates the task + */ + public void updateTask() { + double d0 = parentAI.getBatKing().getDistanceSq(parentAI.mEntityTarget.posX, parentAI.mEntityTarget.boundingBox.minY, + parentAI.mEntityTarget.posZ); + boolean flag = parentAI.getBatKing().getEntitySenses().canSee(parentAI.mEntityTarget); + + if (flag) { + ++this.mCooldownTime; + } else { + this.mCooldownTime = 0; + } + + if (d0 <= (double) this.field_82642_h && this.mCooldownTime >= 20) { + parentAI.getBatKing().getNavigator().clearPathEntity(); + } else { + parentAI.getBatKing().getNavigator().tryMoveToEntityLiving(parentAI.mEntityTarget, this.entityMoveSpeed); + } + + parentAI.getBatKing().getLookHelper().setLookPositionWithEntity(parentAI.mEntityTarget, 30.0F, 30.0F); + float f; + + if (--this.rangedAttackTime == 0) { + if (d0 > (double) this.field_82642_h || !flag) { + return; + } + + f = MathHelper.sqrt_double(d0) / this.field_96562_i; + float f1 = f; + + if (f < 0.1F) { + f1 = 0.1F; + } + + if (f1 > 1.0F) { + f1 = 1.0F; + } + + parentAI.getBatKingAsIRangedAttackMob().attackEntityWithRangedAttack(parentAI.mEntityTarget, f1); + this.rangedAttackTime = MathHelper.floor_float( + f * (float) (this.maxRangedAttackTime - this.field_96561_g) + (float) this.field_96561_g); + } else if (this.rangedAttackTime < 0) { + f = MathHelper.sqrt_double(d0) / this.field_96562_i; + this.rangedAttackTime = MathHelper.floor_float( + f * (float) (this.maxRangedAttackTime - this.field_96561_g) + (float) this.field_96561_g); + } + } + + } + + private class Melee { + + private final EntityAIBatKingAttack parentAI; + + /** + * An amount of decrementing ticks that allows the entity to attack once the + * tick reaches 0. + */ + int attackTick; + /** The speed with which the mob will approach the target */ + double speedTowardsTarget; + /** + * When true, the mob will continue chasing its target, even if it can't find a + * path to them right now. + */ + boolean longMemory; + Class classTarget; + private int field_75445_i; + private double field_151497_i; + private double field_151495_j; + private double field_151496_k; + + private int failedPathFindingPenalty; + + public Melee(EntityAIBatKingAttack aParent, Class aClassTarget, + double aMoveToTargetSpeed, boolean aLongMemory) { + this.parentAI = aParent; + this.classTarget = aClassTarget; + this.speedTowardsTarget = aMoveToTargetSpeed; + this.longMemory = aLongMemory; + parentAI.setMutexBits(3); + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + public boolean shouldExecute() { + if (!parentAI.hasValidTarget()) { + return false; + } + EntityLivingBase entitylivingbase = parentAI.getTarget(); + + if (entitylivingbase == null) { + return false; + } else if (!entitylivingbase.isEntityAlive()) { + return false; + } else if (this.classTarget != null && !this.classTarget.isAssignableFrom(entitylivingbase.getClass())) { + return false; + } else { + if (--this.field_75445_i <= 0) { + parentAI.mEntityPathEntity = parentAI.mAttackingEntity.getNavigator().getPathToEntityLiving(entitylivingbase); + this.field_75445_i = 4 + parentAI.mAttackingEntity.getRNG().nextInt(7); + return parentAI.mEntityPathEntity != null; + } else { + return true; + } + } + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + public boolean continueExecuting() { + EntityLivingBase entitylivingbase = parentAI.mAttackingEntity.getAttackTarget(); + return entitylivingbase == null ? false + : (!entitylivingbase.isEntityAlive() ? false + : (!this.longMemory ? !parentAI.mAttackingEntity.getNavigator().noPath() + : parentAI.mAttackingEntity.isWithinHomeDistance(MathHelper.floor_double(entitylivingbase.posX), + MathHelper.floor_double(entitylivingbase.posY), + MathHelper.floor_double(entitylivingbase.posZ)))); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() { + parentAI.mAttackingEntity.getNavigator().setPath(parentAI.mEntityPathEntity, this.speedTowardsTarget); + this.field_75445_i = 0; + } + + /** + * Resets the task + */ + public void resetTask() { + parentAI.mAttackingEntity.getNavigator().clearPathEntity(); + } + + /** + * Updates the task + */ + public void updateTask() { + EntityLivingBase entitylivingbase = parentAI.mAttackingEntity.getAttackTarget(); + parentAI.mAttackingEntity.getLookHelper().setLookPositionWithEntity(entitylivingbase, 30.0F, 30.0F); + double d0 = parentAI.mAttackingEntity.getDistanceSq(entitylivingbase.posX, entitylivingbase.boundingBox.minY, + entitylivingbase.posZ); + double d1 = (double) (parentAI.mAttackingEntity.width * 2.0F * parentAI.mAttackingEntity.width * 2.0F + entitylivingbase.width); + --this.field_75445_i; + + if ((this.longMemory || parentAI.mAttackingEntity.getEntitySenses().canSee(entitylivingbase)) && this.field_75445_i <= 0 + && (this.field_151497_i == 0.0D && this.field_151495_j == 0.0D && this.field_151496_k == 0.0D + || entitylivingbase.getDistanceSq(this.field_151497_i, this.field_151495_j, + this.field_151496_k) >= 1.0D + || parentAI.mAttackingEntity.getRNG().nextFloat() < 0.05F)) { + this.field_151497_i = entitylivingbase.posX; + this.field_151495_j = entitylivingbase.boundingBox.minY; + this.field_151496_k = entitylivingbase.posZ; + this.field_75445_i = failedPathFindingPenalty + 4 + parentAI.mAttackingEntity.getRNG().nextInt(7); + + if (parentAI.mAttackingEntity.getNavigator().getPath() != null) { + PathPoint finalPathPoint = parentAI.mAttackingEntity.getNavigator().getPath().getFinalPathPoint(); + if (finalPathPoint != null && entitylivingbase.getDistanceSq(finalPathPoint.xCoord, + finalPathPoint.yCoord, finalPathPoint.zCoord) < 1) { + failedPathFindingPenalty = 0; + } else { + failedPathFindingPenalty += 10; + } + } else { + failedPathFindingPenalty += 10; + } + + if (d0 > 1024.0D) { + this.field_75445_i += 10; + } else if (d0 > 256.0D) { + this.field_75445_i += 5; + } + + if (!parentAI.mAttackingEntity.getNavigator().tryMoveToEntityLiving(entitylivingbase, this.speedTowardsTarget)) { + this.field_75445_i += 15; + } + } + + this.attackTick = Math.max(this.attackTick - 1, 0); + + if (d0 <= d1 && this.attackTick <= 20) { + this.attackTick = 20; + + if (parentAI.mAttackingEntity.getHeldItem() != null) { + parentAI.mAttackingEntity.swingItem(); + } + + parentAI.mAttackingEntity.attackEntityAsMob(entitylivingbase); + } + } + + } + +}
\ No newline at end of file diff --git a/src/Java/gtPlusPlus/core/entity/monster/EntityBatKing.java b/src/Java/gtPlusPlus/core/entity/monster/EntityBatKing.java index ae8c8f38b8..d48137e6af 100644 --- a/src/Java/gtPlusPlus/core/entity/monster/EntityBatKing.java +++ b/src/Java/gtPlusPlus/core/entity/monster/EntityBatKing.java @@ -1,7 +1,5 @@ package gtPlusPlus.core.entity.monster; -import java.util.Calendar; - import gtPlusPlus.api.objects.minecraft.BlockPos; import gtPlusPlus.core.util.math.MathUtils; import gtPlusPlus.core.util.minecraft.EntityUtils; @@ -12,27 +10,41 @@ 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.EntityAIWander; import net.minecraft.entity.ai.EntityAIWatchClosest; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.passive.EntityBat; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.entity.projectile.EntityLargeFireball; +import net.minecraft.init.Items; +import net.minecraft.item.Item; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; public class EntityBatKing extends EntityMob implements IRangedAttackMob { + public int courseChangeCooldown; + public double waypointX; + public double waypointY; + public double waypointZ; + private Entity targetedEntity; + private int aggroCooldown; + public int prevAttackCounter; + public int attackCounter; + private int explosionStrength = 1; private EntityAIArrowAttack aiArrowAttack = new EntityAIArrowAttack(this, 1.0D, 20, 60, 15.0F); - private EntityAIAttackOnCollide aiAttackOnCollide = new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.2D, false); + private EntityAIAttackOnCollide aiAttackOnCollide = new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.2D, + false); public EntityBatKing(World p_i1680_1_) { super(p_i1680_1_); @@ -42,10 +54,10 @@ public class EntityBatKing extends EntityMob implements IRangedAttackMob { this.isImmuneToFire = true; this.experienceValue = 1000; - this.tasks.addTask(3, this.aiArrowAttack); - this.tasks.addTask(4, this.aiAttackOnCollide); - this.tasks.addTask(4, new EntityAIRestrictSun(this)); - this.tasks.addTask(5, new EntityAIFleeSun(this, 1.0D)); + //this.tasks.addTask(3, this.aiArrowAttack); + //this.tasks.addTask(4, this.aiAttackOnCollide); + //this.tasks.addTask(4, new EntityAIRestrictSun(this)); + //this.tasks.addTask(5, new EntityAIFleeSun(this, 1.0D)); 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)); @@ -63,276 +75,522 @@ public class EntityBatKing extends EntityMob implements IRangedAttackMob { /** * Get this Entity's EnumCreatureAttribute */ - public EnumCreatureAttribute getCreatureAttribute() - { - return EnumCreatureAttribute.UNDEAD; - } - - /** - * Returns the volume for the sounds this mob makes. - */ - protected float getSoundVolume() { - return 0.45F; - } - - /** - * Gets the pitch of living sounds in living entities. - */ - protected float getSoundPitch() { - return super.getSoundPitch() * 0.15F; - } - - /** - * Returns the sound this mob makes while it's alive. - */ - protected String getLivingSound() { - int aRand = MathUtils.randInt(0, 10); - if (aRand < 6) { - return null; - } else if (aRand <= 8) { - return "mob.bat.idle"; - } else { - return "mob.blaze.breathe"; - } - } - - /** - * Returns the sound this mob makes when it is hurt. - */ - protected String getHurtSound() { - return "mob.blaze.hit"; - } - - /** - * Returns the sound this mob makes on death. - */ - protected String getDeathSound() { - return "mob.bat.death"; - } - - /** - * Returns true if this entity should push and be pushed by other entities when - * colliding. - */ - public boolean canBePushed() { - return false; - } - - protected void collideWithEntity(Entity aEntity) { - if (aEntity != null) { - if (aEntity instanceof EntityPlayer) { - EntityUtils.doDamage(aEntity, DamageSource.magic, (int) (((EntityPlayer) aEntity).getHealth() / 20)); - } - } - } - - protected void collideWithNearbyEntities() { - } - - protected void applyEntityAttributes() { - - this.getAttributeMap().registerAttribute(SharedMonsterAttributes.maxHealth); - this.getAttributeMap().registerAttribute(SharedMonsterAttributes.attackDamage); - this.getAttributeMap().registerAttribute(SharedMonsterAttributes.knockbackResistance); - this.getAttributeMap().registerAttribute(SharedMonsterAttributes.movementSpeed); - this.getAttributeMap().registerAttribute(SharedMonsterAttributes.followRange); - - this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(60.0D); - this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(6.0D); - this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.25D); - this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(32.0D); - } - - public boolean getIsBatHanging() { - return false; - } - - public void setIsBatHanging(boolean p_82236_1_) { - - } - - /** - * Returns true if the newer Entity AI code should be run - */ - protected boolean isAIEnabled() { - return true; - } - - /** - * Called to update the entity's position/logic. - */ - public void onUpdate() { - super.onUpdate(); - - for (int i = 0; i < 2; ++i) { - this.worldObj.spawnParticle("largesmoke", this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.width, - this.posY + this.rand.nextDouble() * (double) this.height, - this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.width, 0.0D, 0.0D, 0.0D); - } - - if (!isFlying()) { - this.jump(); - } - /* - * if (!hasAir()) { if (isFlying()) { this.jump(); this.jump(); } } - */ - - if (!this.onGround && this.motionY < 0.0D) - { - this.motionY *= 0.0001D; - } - - } - - protected void updateAITasks() { - super.updateAITasks(); - } - - private boolean isFlying() { - if (this.onGround) { - return false; - } - return true; - } - - private boolean hasAir() { - BlockPos p = EntityUtils.findBlockPosUnderEntity(this); - int y = p.yPos; - int yOriginal = p.yPos; - int breaker = 0; - while (y > 0) { - if (breaker > 50) { - break; - } - if (!this.worldObj.isAirBlock(p.xPos, y, p.zPos)) { - break; - } - y--; - breaker++; - } - if (yOriginal - y < 3) { - for (int i=0;i<y;y++) { - this.jump(); - } - return true; - } - return false; - } - - /** - * returns if this entity triggers Block.onEntityWalking on the blocks they walk - * on. used for spiders and wolves to prevent them from trampling crops - */ - protected boolean canTriggerWalking() { - return false; - } - - /** - * Called when the mob is falling. Calculates and applies fall damage. - */ - protected void fall(float p_70069_1_) { - } - - /** - * Takes in the distance the entity has fallen this tick and whether its on the - * ground to update the fall distance and deal fall damage if landing on the - * ground. Args: distanceFallenThisTick, onGround - */ - protected void updateFallState(double p_70064_1_, boolean p_70064_3_) { - } - - /** - * Return whether this entity should NOT trigger a pressure plate or a tripwire. - */ - public boolean doesEntityNotTriggerPressurePlate() { - return true; - } - - /** - * Called when the entity is attacked. - */ - public boolean attackEntityFrom(DamageSource p_70097_1_, float p_70097_2_) { - if (this.isEntityInvulnerable()) { - return false; - } else { - if (!this.worldObj.isRemote && this.getIsBatHanging()) { - this.setIsBatHanging(false); - } - - return super.attackEntityFrom(p_70097_1_, p_70097_2_); - } - } - - /** - * (abstract) Protected helper method to read subclass entity data from NBT. - */ - public void readEntityFromNBT(NBTTagCompound p_70037_1_) { - super.readEntityFromNBT(p_70037_1_); - } - - /** - * (abstract) Protected helper method to write subclass entity data to NBT. - */ - public void writeEntityToNBT(NBTTagCompound p_70014_1_) { - super.writeEntityToNBT(p_70014_1_); - } - - /** - * Checks if the entity's current position is a valid location to spawn this - * entity. - */ - public boolean getCanSpawnHere() { - int i = MathHelper.floor_double(this.boundingBox.minY); - - if (i >= 63) { - return false; - } else { - int j = MathHelper.floor_double(this.posX); - int k = MathHelper.floor_double(this.posZ); - int l = this.worldObj.getBlockLightValue(j, i, k); - byte b0 = 4; - Calendar calendar = this.worldObj.getCurrentDate(); - - if ((calendar.get(2) + 1 != 10 || calendar.get(5) < 20) - && (calendar.get(2) + 1 != 11 || calendar.get(5) > 3)) { - if (this.rand.nextBoolean()) { - return false; - } - } else { - b0 = 7; - } - - return l > this.rand.nextInt(b0) ? false : super.getCanSpawnHere(); - } - } - - /** - * Attack the specified entity using a ranged attack. - */ - @Override - public void attackEntityWithRangedAttack(EntityLivingBase p_82196_1_, float p_82196_2_) - { - EntityArrow entityarrow = new EntityArrow(this.worldObj, this, p_82196_1_, 1.6F, (float)(14 - this.worldObj.difficultySetting.getDifficultyId() * 4)); - int i = MathUtils.randInt(0, 4); - int j = MathUtils.randInt(0, 3); - int k = MathUtils.randInt(0, 3); - entityarrow.setDamage((double)(p_82196_2_ * 2.0F) + this.rand.nextGaussian() * 0.25D + (double)((float)this.worldObj.difficultySetting.getDifficultyId() * 0.11F)); - - boolean boostAttack = MathUtils.randInt(0, 100) <= 21; - if (boostAttack) { - if (i > 0) { - entityarrow.setDamage(entityarrow.getDamage() + (double) i * 0.5D + 0.5D); - } - - if (j > 0) { - entityarrow.setKnockbackStrength(j); - } - if (k > 0) { - entityarrow.setFire(50 * k); - } - } - - this.playSound("mob.skeleton.say", 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F)); - this.worldObj.spawnEntityInWorld(entityarrow); - } + public EnumCreatureAttribute getCreatureAttribute() { + return EnumCreatureAttribute.UNDEAD; + } + + /** + * Gets the pitch of living sounds in living entities. + */ + protected float getSoundPitch() { + return super.getSoundPitch() * 0.15F; + } + + /** + * Returns the sound this mob makes while it's alive. + */ + protected String getLivingSound() { + int aRand = MathUtils.randInt(0, 10); + if (aRand < 6) { + return null; + } else if (aRand <= 8) { + return "mob.bat.idle"; + } else { + return "mob.blaze.breathe"; + } + } + + /** + * Returns the sound this mob makes when it is hurt. + */ + protected String getHurtSound() { + return "mob.blaze.hit"; + } + + /** + * Returns the sound this mob makes on death. + */ + protected String getDeathSound() { + return "mob.bat.death"; + } + + /** + * Returns true if this entity should push and be pushed by other entities when + * colliding. + */ + public boolean canBePushed() { + return false; + } + + protected void collideWithEntity(Entity aEntity) { + if (aEntity != null) { + if (aEntity instanceof EntityPlayer) { + EntityUtils.doDamage(aEntity, DamageSource.magic, (int) (((EntityPlayer) aEntity).getHealth() / 20)); + } + } + } + + protected void collideWithNearbyEntities() { + } + + protected void applyEntityAttributes() { + + this.getAttributeMap().registerAttribute(SharedMonsterAttributes.maxHealth); + this.getAttributeMap().registerAttribute(SharedMonsterAttributes.attackDamage); + this.getAttributeMap().registerAttribute(SharedMonsterAttributes.knockbackResistance); + this.getAttributeMap().registerAttribute(SharedMonsterAttributes.movementSpeed); + this.getAttributeMap().registerAttribute(SharedMonsterAttributes.followRange); + + this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(60.0D); + this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(6.0D); + this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.25D); + this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(32.0D); + } + + public boolean getIsBatHanging() { + return false; + } + + public void setIsBatHanging(boolean p_82236_1_) { + + } + + /** + * Returns true if the newer Entity AI code should be run + */ + protected boolean isAIEnabled() { + return true; + } + + /** + * Called to update the entity's position/logic. + */ + public void onUpdate() { + super.onUpdate(); + generateParticles(this); + } + + private static void generateParticles(EntityBatKing aKing) { + for (int i = 0; i < 20; ++i) { + // + if (MathUtils.randInt(0, 50) <= 1) { + String particleName = "smoke"; + if (MathUtils.randInt(0, 3) <= 2) { + particleName = "largesmoke"; + } + aKing.worldObj.spawnParticle(particleName, + aKing.posX + (aKing.rand.nextDouble() - 0.5D) * (double) aKing.width, + aKing.posY + aKing.rand.nextDouble() * (double) aKing.height, + aKing.posZ + (aKing.rand.nextDouble() - 0.5D) * (double) aKing.width, 0.0D, 0.0D, 0.0D); + } + if (MathUtils.randInt(0, 100) <= 1) { + String particleName = "smoke"; + int test2 = MathUtils.randInt(0, 3); + if (test2 == 2) { + particleName = "dripLava"; + } else if (test2 == 3) { + particleName = "portal"; + } + aKing.worldObj.spawnParticle(particleName, + aKing.posX + (aKing.rand.nextDouble() - 0.5D) * (double) aKing.width, + aKing.posY + aKing.rand.nextDouble() * (double) aKing.height, + aKing.posZ + (aKing.rand.nextDouble() - 0.5D) * (double) aKing.width, 0.0D, 0.0D, 0.0D); + } + } + } + + protected void updateAITasks() { + super.updateAITasks(); + } + + private boolean isFlying() { + if (this.onGround) { + return false; + } + return true; + } + + private boolean hasAir() { + BlockPos p = EntityUtils.findBlockPosUnderEntity(this); + int y = p.yPos; + int yOriginal = p.yPos; + int breaker = 0; + while (y > 0) { + if (breaker > 50) { + break; + } + if (!this.worldObj.isAirBlock(p.xPos, y, p.zPos)) { + break; + } + y--; + breaker++; + } + if (yOriginal - y < 3) { + for (int i = 0; i < y; y++) { + this.jump(); + } + return true; + } + return false; + } + + /** + * returns if this entity triggers Block.onEntityWalking on the blocks they walk + * on. used for spiders and wolves to prevent them from trampling crops + */ + protected boolean canTriggerWalking() { + return false; + } + + /** + * Return whether this entity should NOT trigger a pressure plate or a tripwire. + */ + public boolean doesEntityNotTriggerPressurePlate() { + return true; + } + + /** + * Called when the entity is attacked. + */ + public boolean attackEntityFrom(DamageSource p_70097_1_, float p_70097_2_) { + if (this.isEntityInvulnerable()) { + return false; + } else { + if (!this.worldObj.isRemote && this.getIsBatHanging()) { + this.setIsBatHanging(false); + } + + return super.attackEntityFrom(p_70097_1_, p_70097_2_); + } + } + + /** + * (abstract) Protected helper method to read subclass entity data from NBT. + */ + public void readEntityFromNBT(NBTTagCompound p_70037_1_) { + super.readEntityFromNBT(p_70037_1_); + if (p_70037_1_.hasKey("ExplosionPower", 99)) { + this.explosionStrength = p_70037_1_.getInteger("ExplosionPower"); + } + } + + /** + * (abstract) Protected helper method to write subclass entity data to NBT. + */ + public void writeEntityToNBT(NBTTagCompound p_70014_1_) { + super.writeEntityToNBT(p_70014_1_); + p_70014_1_.setInteger("ExplosionPower", this.explosionStrength); + } + + /** + * Attack the specified entity using a ranged attack. + */ + @Override + public void attackEntityWithRangedAttack(EntityLivingBase p_82196_1_, float p_82196_2_) { + + double d4 = 64.0D; + if (this.targetedEntity != null && this.targetedEntity.getDistanceSqToEntity(this) < d4 * d4) { + double d5 = this.targetedEntity.posX - this.posX; + double d6 = this.targetedEntity.boundingBox.minY + (double) (this.targetedEntity.height / 2.0F) + - (this.posY + (double) (this.height / 2.0F)); + double d7 = this.targetedEntity.posZ - this.posZ; + this.renderYawOffset = this.rotationYaw = -((float) Math.atan2(d5, d7)) * 180.0F / (float) Math.PI; + + ++this.attackCounter; + + if (this.canEntityBeSeen(this.targetedEntity)) { + + + if (this.attackCounter == 20) { + this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1008, (int) this.posX, (int) this.posY, + (int) this.posZ, 0); + EntityLargeFireball entitylargefireball = new EntityLargeFireball(this.worldObj, this, d5, d6, d7); + entitylargefireball.field_92057_e = this.explosionStrength; + double d8 = 4.0D; + Vec3 vec3 = this.getLook(1.0F); + entitylargefireball.posX = this.posX + vec3.xCoord * d8; + entitylargefireball.posY = this.posY + (double) (this.height / 2.0F) + 0.5D; + entitylargefireball.posZ = this.posZ + vec3.zCoord * d8; + this.worldObj.spawnEntityInWorld(entitylargefireball); + this.attackCounter = -40; + } + } else if (this.attackCounter > 0) { + --this.attackCounter; + } + } else { + this.renderYawOffset = this.rotationYaw = -((float) Math.atan2(this.motionX, this.motionZ)) * 180.0F + / (float) Math.PI; + + if (this.attackCounter > 0) { + --this.attackCounter; + EntityArrow entityarrow = new EntityArrow(this.worldObj, this, p_82196_1_, 1.6F, + (float) (14 - this.worldObj.difficultySetting.getDifficultyId() * 4)); + int i = MathUtils.randInt(0, 4); + int j = MathUtils.randInt(0, 3); + int k = MathUtils.randInt(0, 3); + entityarrow.setDamage((double) (p_82196_2_ * 2.0F) + this.rand.nextGaussian() * 0.25D + + (double) ((float) this.worldObj.difficultySetting.getDifficultyId() * 0.11F)); + + boolean boostAttack = MathUtils.randInt(0, 100) <= 21; + if (boostAttack) { + if (i > 0) { + entityarrow.setDamage(entityarrow.getDamage() + (double) i * 0.5D + 0.5D); + } + + if (j > 0) { + entityarrow.setKnockbackStrength(j); + } + if (k > 0) { + entityarrow.setFire(50 * k); + } + } + + this.playSound("mob.skeleton.say", 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F)); + this.worldObj.spawnEntityInWorld(entityarrow); + } + + } + + } + + /** + * Returns the volume for the sounds this mob makes. + */ + protected float getSoundVolume() { + return 10.0F; + } + + /** + * Checks if the entity's current position is a valid location to spawn this + * entity. + */ + public boolean getCanSpawnHere() { + return super.getCanSpawnHere() && this.worldObj.difficultySetting != EnumDifficulty.PEACEFUL; + } + + /** + * Will return how many at most can spawn in a chunk at once. + */ + public int getMaxSpawnedInChunk() { + return 1; + } + + protected Item getDropItem() { + return Items.gunpowder; + } + + /** + * 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 p_70628_1_, int p_70628_2_) { + int j = this.rand.nextInt(2) + this.rand.nextInt(1 + p_70628_2_); + int k; + + for (k = 0; k < j; ++k) { + this.dropItem(Items.ghast_tear, 1); + } + + j = this.rand.nextInt(3) + this.rand.nextInt(1 + p_70628_2_); + + for (k = 0; k < j; ++k) { + this.dropItem(Items.gunpowder, 1); + } + } + + @Override + protected void updateEntityActionState() { + if (!this.worldObj.isRemote && this.worldObj.difficultySetting == EnumDifficulty.PEACEFUL) { + this.setDead(); + } + + this.despawnEntity(); + this.prevAttackCounter = this.attackCounter; + double d0 = this.waypointX - this.posX; + double d1 = this.waypointY - this.posY; + double d2 = this.waypointZ - this.posZ; + double d3 = d0 * d0 + d1 * d1 + d2 * d2; + + if (d3 < 1.0D || d3 > 3600.0D) { + this.waypointX = this.posX + (double) ((this.rand.nextFloat() * 2.0F - 1.0F) * 16.0F); + this.waypointY = this.posY + (double) ((this.rand.nextFloat() * 2.0F - 1.0F) * 16.0F); + this.waypointZ = this.posZ + (double) ((this.rand.nextFloat() * 2.0F - 1.0F) * 16.0F); + } + + if (this.courseChangeCooldown-- <= 0) { + this.courseChangeCooldown += this.rand.nextInt(5) + 2; + d3 = (double) MathHelper.sqrt_double(d3); + + if (this.isCourseTraversable(this.waypointX, this.waypointY, this.waypointZ, d3)) { + this.motionX += d0 / d3 * 0.1D; + this.motionY += d1 / d3 * 0.1D; + this.motionZ += d2 / d3 * 0.1D; + } else { + this.waypointX = this.posX; + this.waypointY = this.posY; + this.waypointZ = this.posZ; + } + } + + if (this.targetedEntity != null && this.targetedEntity.isDead) { + this.targetedEntity = null; + } + + if (this.targetedEntity == null || this.aggroCooldown-- <= 0) { + this.targetedEntity = this.worldObj.getClosestVulnerablePlayerToEntity(this, 100.0D); + + if (this.targetedEntity != null) { + this.aggroCooldown = 20; + } + } + + double d4 = 64.0D; + + if (this.targetedEntity != null && this.targetedEntity.getDistanceSqToEntity(this) < d4 * d4) { + double d5 = this.targetedEntity.posX - this.posX; + double d6 = this.targetedEntity.boundingBox.minY + (double) (this.targetedEntity.height / 2.0F) + - (this.posY + (double) (this.height / 2.0F)); + double d7 = this.targetedEntity.posZ - this.posZ; + this.renderYawOffset = this.rotationYaw = -((float) Math.atan2(d5, d7)) * 180.0F / (float) Math.PI; + + if (this.canEntityBeSeen(this.targetedEntity)) { + if (this.attackCounter == 10) { + this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1007, (int) this.posX, (int) this.posY, + (int) this.posZ, 0); + } + + ++this.attackCounter; + + if (this.attackCounter == 20) { + this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1008, (int) this.posX, (int) this.posY, + (int) this.posZ, 0); + EntityLargeFireball entitylargefireball = new EntityLargeFireball(this.worldObj, this, d5, d6, d7); + entitylargefireball.field_92057_e = this.explosionStrength; + double d8 = 4.0D; + Vec3 vec3 = this.getLook(1.0F); + entitylargefireball.posX = this.posX + vec3.xCoord * d8; + entitylargefireball.posY = this.posY + (double) (this.height / 2.0F) + 0.5D; + entitylargefireball.posZ = this.posZ + vec3.zCoord * d8; + this.worldObj.spawnEntityInWorld(entitylargefireball); + this.attackCounter = -40; + } + } else if (this.attackCounter > 0) { + --this.attackCounter; + } + } else { + this.renderYawOffset = this.rotationYaw = -((float) Math.atan2(this.motionX, this.motionZ)) * 180.0F + / (float) Math.PI; + + if (this.attackCounter > 0) { + --this.attackCounter; + } + } + + if (!this.worldObj.isRemote) { + byte b1 = this.dataWatcher.getWatchableObjectByte(16); + byte b0 = (byte) (this.attackCounter > 10 ? 1 : 0); + + if (b1 != b0) { + this.dataWatcher.updateObject(16, Byte.valueOf(b0)); + } + } + } + + /** + * True if the ghast has an unobstructed line of travel to the waypoint. + */ + private boolean isCourseTraversable(double p_70790_1_, double p_70790_3_, double p_70790_5_, double p_70790_7_) { + double d4 = (this.waypointX - this.posX) / p_70790_7_; + double d5 = (this.waypointY - this.posY) / p_70790_7_; + double d6 = (this.waypointZ - this.posZ) / p_70790_7_; + AxisAlignedBB axisalignedbb = this.boundingBox.copy(); + + for (int i = 1; (double) i < p_70790_7_; ++i) { + axisalignedbb.offset(d4, d5, d6); + + /* + * if (!this.worldObj.getCollidingBoundingBoxes(this, axisalignedbb).isEmpty()) + * { return false; } + */ + } + + return true; + } + + /** + * Called when the mob is falling. Calculates and applies fall damage. + */ + protected void fall(float p_70069_1_) { + } + + /** + * Takes in the distance the entity has fallen this tick and whether its on the + * ground to update the fall distance and deal fall damage if landing on the + * ground. Args: distanceFallenThisTick, onGround + */ + protected void updateFallState(double p_70064_1_, boolean p_70064_3_) { + } + + /** + * Moves the entity based on the specified heading. Args: strafe, forward + */ + public void moveEntityWithHeading(float p_70612_1_, float p_70612_2_) { + if (this.isInWater()) { + this.moveFlying(p_70612_1_, p_70612_2_, 0.02F); + this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.motionX *= 0.800000011920929D; + this.motionY *= 0.800000011920929D; + this.motionZ *= 0.800000011920929D; + } else if (this.handleLavaMovement()) { + this.moveFlying(p_70612_1_, p_70612_2_, 0.02F); + this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.motionX *= 0.5D; + this.motionY *= 0.5D; + this.motionZ *= 0.5D; + } else { + float f2 = 0.91F; + + if (this.onGround) { + f2 = this.worldObj.getBlock(MathHelper.floor_double(this.posX), + MathHelper.floor_double(this.boundingBox.minY) - 1, + MathHelper.floor_double(this.posZ)).slipperiness * 0.91F; + } + + float f3 = 0.16277136F / (f2 * f2 * f2); + this.moveFlying(p_70612_1_, p_70612_2_, this.onGround ? 0.1F * f3 : 0.02F); + f2 = 0.91F; + + if (this.onGround) { + f2 = this.worldObj.getBlock(MathHelper.floor_double(this.posX), + MathHelper.floor_double(this.boundingBox.minY) - 1, + MathHelper.floor_double(this.posZ)).slipperiness * 0.91F; + } + + this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.motionX *= (double) f2; + this.motionY *= (double) f2; + this.motionZ *= (double) f2; + } + + this.prevLimbSwingAmount = this.limbSwingAmount; + double d1 = this.posX - this.prevPosX; + double d0 = this.posZ - this.prevPosZ; + float f4 = MathHelper.sqrt_double(d1 * d1 + d0 * d0) * 4.0F; + + if (f4 > 1.0F) { + f4 = 1.0F; + } + + this.limbSwingAmount += (f4 - this.limbSwingAmount) * 0.4F; + this.limbSwing += this.limbSwingAmount; + } + + /** + * returns true if this entity is by a ladder, false otherwise + */ + public boolean isOnLadder() { + return false; + } + }
\ No newline at end of file |