aboutsummaryrefslogtreecommitdiff
path: root/src/Java/gtPlusPlus/core
diff options
context:
space:
mode:
authorAlkalus <3060479+draknyte1@users.noreply.github.com>2019-08-02 17:36:00 +0100
committerAlkalus <3060479+draknyte1@users.noreply.github.com>2019-08-02 17:36:00 +0100
commit77a25b1f5fab73f8354ca842650ff86534804b8b (patch)
tree7d24faa067ea721bc5579d7b179070e7e222b7fc /src/Java/gtPlusPlus/core
parentc53e25d2e3887c483f6fb2999295eae788127188 (diff)
downloadGT5-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.java384
-rw-r--r--src/Java/gtPlusPlus/core/entity/monster/EntityBatKing.java820
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