aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDraknyte1 <Draknyte1@hotmail.com>2017-08-29 22:26:20 +1000
committerDraknyte1 <Draknyte1@hotmail.com>2017-08-29 22:26:20 +1000
commit0a61c7e5a9c26770a54f9aa9221e0f47e8696f0b (patch)
tree59192227d60b464104630be5751c114ef3cbf8d9 /src
parent90e409d3c7087fc99ec12ab2edb50b38ed0e5c8e (diff)
downloadGT5-Unofficial-0a61c7e5a9c26770a54f9aa9221e0f47e8696f0b.tar.gz
GT5-Unofficial-0a61c7e5a9c26770a54f9aa9221e0f47e8696f0b.tar.bz2
GT5-Unofficial-0a61c7e5a9c26770a54f9aa9221e0f47e8696f0b.zip
+ Added some random entities.
Diffstat (limited to 'src')
-rw-r--r--src/Java/gtPlusPlus/core/entity/monster/EntitySickBlaze.java236
-rw-r--r--src/Java/gtPlusPlus/core/entity/monster/EntityStaballoyWarrior.java283
-rw-r--r--src/Java/gtPlusPlus/core/entity/projectile/EntityToxinball.java330
-rw-r--r--src/Java/gtPlusPlus/core/entity/projectile/EntityToxinballSmall.java88
4 files changed, 937 insertions, 0 deletions
diff --git a/src/Java/gtPlusPlus/core/entity/monster/EntitySickBlaze.java b/src/Java/gtPlusPlus/core/entity/monster/EntitySickBlaze.java
new file mode 100644
index 0000000000..4d46c0a5ca
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/entity/monster/EntitySickBlaze.java
@@ -0,0 +1,236 @@
+package gtPlusPlus.core.entity.monster;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gtPlusPlus.core.entity.projectile.EntityToxinballSmall;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.SharedMonsterAttributes;
+import net.minecraft.entity.monster.EntityBlaze;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.World;
+
+public class EntitySickBlaze extends EntityBlaze {
+ /** Random offset used in floating behaviour */
+ private float heightOffset = 0.5F;
+ /** ticks until heightOffset is randomized */
+ private int heightOffsetUpdateTime;
+ private int field_70846_g;
+
+ public EntitySickBlaze(World p_i1731_1_) {
+ super(p_i1731_1_);
+ this.isImmuneToFire = true;
+ this.experienceValue = 10;
+ }
+
+ @Override
+ protected void applyEntityAttributes() {
+ super.applyEntityAttributes();
+ this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(6.0D);
+ }
+
+ @Override
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, new Byte((byte) 0));
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ @Override
+ protected String getLivingSound() {
+ return "mob.blaze.breathe";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ @Override
+ protected String getHurtSound() {
+ return "mob.blaze.hit";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ @Override
+ protected String getDeathSound() {
+ return "mob.blaze.death";
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public int getBrightnessForRender(float p_70070_1_) {
+ return 15728880;
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ @Override
+ public float getBrightness(float p_70013_1_) {
+ return 1.0F;
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ public void onLivingUpdate() {
+ if (!this.worldObj.isRemote) {
+ if (this.isWet()) {
+ this.attackEntityFrom(DamageSource.drown, 1.0F);
+ }
+
+ --this.heightOffsetUpdateTime;
+
+ if (this.heightOffsetUpdateTime <= 0) {
+ this.heightOffsetUpdateTime = 100;
+ this.heightOffset = 0.5F + (float) this.rand.nextGaussian() * 3.0F;
+ }
+
+ if (this.getEntityToAttack() != null && this.getEntityToAttack().posY
+ + this.getEntityToAttack().getEyeHeight() > this.posY + this.getEyeHeight() + this.heightOffset) {
+ this.motionY += (0.30000001192092896D - this.motionY) * 0.30000001192092896D;
+ }
+ }
+
+ if (this.rand.nextInt(24) == 0) {
+ this.worldObj.playSoundEffect(this.posX + 0.5D, this.posY + 0.5D, this.posZ + 0.5D, "fire.fire",
+ 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F);
+ }
+
+ if (!this.onGround && this.motionY < 0.0D) {
+ this.motionY *= 0.6D;
+ }
+
+ for (int i = 0; i < 2; ++i) {
+ this.worldObj.spawnParticle("largesmoke", this.posX + (this.rand.nextDouble() - 0.5D) * this.width,
+ this.posY + this.rand.nextDouble() * this.height,
+ this.posZ + (this.rand.nextDouble() - 0.5D) * this.width, 0.0D, 0.0D, 0.0D);
+ }
+
+ super.onLivingUpdate();
+ }
+
+ /**
+ * Basic mob attack. Default to touch of death in EntityCreature. Overridden
+ * by each mob to define their attack.
+ */
+ @Override
+ protected void attackEntity(Entity entity, float p_70785_2_) {
+ if (this.attackTime <= 0 && p_70785_2_ < 2.0F && entity.boundingBox.maxY > this.boundingBox.minY
+ && entity.boundingBox.minY < this.boundingBox.maxY) {
+ this.attackTime = 20;
+ this.attackEntityAsMob(entity);
+ }
+ else if (p_70785_2_ < 30.0F) {
+ double d0 = entity.posX - this.posX;
+ double d1 = entity.boundingBox.minY + entity.height / 2.0F - (this.posY + this.height / 2.0F);
+ double d2 = entity.posZ - this.posZ;
+
+ if (this.attackTime == 0) {
+ ++this.field_70846_g;
+
+ if (this.field_70846_g == 1) {
+ this.attackTime = 60;
+ this.func_70844_e(true);
+ }
+ else if (this.field_70846_g <= 4) {
+ this.attackTime = 6;
+ }
+ else {
+ this.attackTime = 100;
+ this.field_70846_g = 0;
+ this.func_70844_e(false);
+ }
+
+ if (this.field_70846_g > 1) {
+ float f1 = MathHelper.sqrt_float(p_70785_2_) * 0.5F;
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1009, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+
+ for (int i = 0; i < 1; ++i) {
+ EntityToxinballSmall entitysmalltoxinball = new EntityToxinballSmall(this.worldObj, this,
+ d0 + this.rand.nextGaussian() * f1, d1, d2 + this.rand.nextGaussian() * f1);
+ entitysmalltoxinball.posY = this.posY + this.height / 2.0F + 0.5D;
+ this.worldObj.spawnEntityInWorld(entitysmalltoxinball);
+ }
+ }
+ }
+
+ this.rotationYaw = (float) (Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F;
+ this.hasAttacked = true;
+ }
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ @Override
+ protected void fall(float p_70069_1_) {
+ }
+
+ @Override
+ protected Item getDropItem() {
+ return Items.blaze_rod;
+ }
+
+ /**
+ * Returns true if the entity is on fire. Used by render to add the fire
+ * effect on rendering.
+ */
+ @Override
+ public boolean isBurning() {
+ return this.func_70845_n();
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ protected void dropFewItems(boolean p_70628_1_, int p_70628_2_) {
+ if (p_70628_1_) {
+ int j = this.rand.nextInt(2 + p_70628_2_);
+
+ for (int k = 0; k < j; ++k) {
+ this.dropItem(Items.blaze_rod, 1);
+ }
+ }
+ }
+
+ @Override
+ public boolean func_70845_n() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ @Override
+ public void func_70844_e(boolean p_70844_1_) {
+ byte b0 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (p_70844_1_) {
+ b0 = (byte) (b0 | 1);
+ }
+ else {
+ b0 &= -2;
+ }
+
+ this.dataWatcher.updateObject(16, Byte.valueOf(b0));
+ }
+
+ /**
+ * Checks to make sure the light is not too bright where the mob is spawning
+ */
+ @Override
+ protected boolean isValidLightLevel() {
+ return true;
+ }
+} \ No newline at end of file
diff --git a/src/Java/gtPlusPlus/core/entity/monster/EntityStaballoyWarrior.java b/src/Java/gtPlusPlus/core/entity/monster/EntityStaballoyWarrior.java
new file mode 100644
index 0000000000..b6829f6985
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/entity/monster/EntityStaballoyWarrior.java
@@ -0,0 +1,283 @@
+package gtPlusPlus.core.entity.monster;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.*;
+import net.minecraft.entity.ai.*;
+import net.minecraft.entity.monster.EntityGolem;
+import net.minecraft.entity.monster.IMob;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.*;
+import net.minecraft.village.Village;
+import net.minecraft.world.World;
+
+public class EntityStaballoyWarrior extends EntityGolem {
+ /** deincrements, and a distance-to-home check is done at 0 */
+ private int homeCheckTimer;
+ Village villageObj;
+ private int attackTimer;
+ private int holdRoseTick;
+
+ public EntityStaballoyWarrior(World world) {
+ super(world);
+ this.setSize(1.4F, 2.9F);
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(1, new EntityAIAttackOnCollide(this, 1.0D, true));
+ this.tasks.addTask(2, new EntityAIMoveTowardsTarget(this, 0.9D, 32.0F));
+ this.tasks.addTask(3, new EntityAIMoveThroughVillage(this, 0.6D, true));
+ this.tasks.addTask(4, new EntityAIMoveTowardsRestriction(this, 1.0D));
+ this.tasks.addTask(5, new EntityAIWander(this, 0.6D));
+ this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
+ this.tasks.addTask(7, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
+ this.targetTasks.addTask(2,
+ new EntityAINearestAttackableTarget(this, EntityLiving.class, 0, false, true, IMob.mobSelector));
+ }
+
+ @Override
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ @Override
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ /**
+ * main AI tick function, replaces updateEntityActionState
+ */
+ @Override
+ protected void updateAITick() {
+ if (--this.homeCheckTimer <= 0) {
+ this.homeCheckTimer = 70 + this.rand.nextInt(50);
+ this.villageObj = this.worldObj.villageCollectionObj.findNearestVillage(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ), 32);
+
+ if (this.villageObj == null) {
+ this.detachHome();
+ }
+ else {
+ ChunkCoordinates chunkcoordinates = this.villageObj.getCenter();
+ this.setHomeArea(chunkcoordinates.posX, chunkcoordinates.posY, chunkcoordinates.posZ,
+ (int) (this.villageObj.getVillageRadius() * 0.6F));
+ }
+ }
+
+ super.updateAITick();
+ }
+
+ @Override
+ protected void applyEntityAttributes() {
+ super.applyEntityAttributes();
+ this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(100.0D);
+ this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.25D);
+ }
+
+ /**
+ * Decrements the entity's air supply when underwater
+ */
+ @Override
+ protected int decreaseAirSupply(int p_70682_1_) {
+ return p_70682_1_;
+ }
+
+ @Override
+ protected void collideWithEntity(Entity p_82167_1_) {
+ if (p_82167_1_ instanceof IMob && this.getRNG().nextInt(20) == 0) {
+ this.setAttackTarget((EntityLivingBase) p_82167_1_);
+ }
+
+ super.collideWithEntity(p_82167_1_);
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+
+ if (this.attackTimer > 0) {
+ --this.attackTimer;
+ }
+
+ if (this.holdRoseTick > 0) {
+ --this.holdRoseTick;
+ }
+
+ if (this.motionX * this.motionX + this.motionZ * this.motionZ > 2.500000277905201E-7D
+ && this.rand.nextInt(5) == 0) {
+ int i = MathHelper.floor_double(this.posX);
+ int j = MathHelper.floor_double(this.posY - 0.20000000298023224D - this.yOffset);
+ int k = MathHelper.floor_double(this.posZ);
+ Block block = this.worldObj.getBlock(i, j, k);
+
+ if (block.getMaterial() != Material.air) {
+ this.worldObj.spawnParticle(
+ "blockcrack_" + Block.getIdFromBlock(block) + "_" + this.worldObj.getBlockMetadata(i, j, k),
+ this.posX + (this.rand.nextFloat() - 0.5D) * this.width,
+ this.boundingBox.minY + 0.1D,
+ this.posZ + (this.rand.nextFloat() - 0.5D) * this.width,
+ 4.0D * (this.rand.nextFloat() - 0.5D), 0.5D,
+ (this.rand.nextFloat() - 0.5D) * 4.0D);
+ }
+ }
+ }
+
+ /**
+ * Returns true if this entity can attack entities of the specified class.
+ */
+ @Override
+ public boolean canAttackClass(Class p_70686_1_) {
+ return this.isPlayerCreated() && EntityPlayer.class.isAssignableFrom(p_70686_1_) ? false
+ : super.canAttackClass(p_70686_1_);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ @Override
+ public void writeEntityToNBT(NBTTagCompound p_70014_1_) {
+ super.writeEntityToNBT(p_70014_1_);
+ p_70014_1_.setBoolean("PlayerCreated", this.isPlayerCreated());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ @Override
+ public void readEntityFromNBT(NBTTagCompound p_70037_1_) {
+ super.readEntityFromNBT(p_70037_1_);
+ this.setPlayerCreated(p_70037_1_.getBoolean("PlayerCreated"));
+ }
+
+ @Override
+ public boolean attackEntityAsMob(Entity p_70652_1_) {
+ this.attackTimer = 10;
+ this.worldObj.setEntityState(this, (byte) 4);
+ boolean flag = p_70652_1_.attackEntityFrom(DamageSource.causeMobDamage(this),
+ 7 + this.rand.nextInt(15));
+
+ if (flag) {
+ p_70652_1_.motionY += 0.4000000059604645D;
+ }
+
+ this.playSound("mob.irongolem.throw", 1.0F, 1.0F);
+ return flag;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void handleHealthUpdate(byte p_70103_1_) {
+ if (p_70103_1_ == 4) {
+ this.attackTimer = 10;
+ this.playSound("mob.irongolem.throw", 1.0F, 1.0F);
+ }
+ else if (p_70103_1_ == 11) {
+ this.holdRoseTick = 400;
+ }
+ else {
+ super.handleHealthUpdate(p_70103_1_);
+ }
+ }
+
+ public Village getVillage() {
+ return this.villageObj;
+ }
+
+ @SideOnly(Side.CLIENT)
+ public int getAttackTimer() {
+ return this.attackTimer;
+ }
+
+ public void setHoldingRose(boolean p_70851_1_) {
+ this.holdRoseTick = p_70851_1_ ? 400 : 0;
+ this.worldObj.setEntityState(this, (byte) 11);
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ @Override
+ protected String getHurtSound() {
+ return "mob.irongolem.hit";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ @Override
+ protected String getDeathSound() {
+ return "mob.irongolem.death";
+ }
+
+ @Override
+ protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_) {
+ this.playSound("mob.irongolem.walk", 1.0F, 1.0F);
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ protected void dropFewItems(boolean p_70628_1_, int p_70628_2_) {
+ int j = this.rand.nextInt(3);
+ int k;
+
+ for (k = 0; k < j; ++k) {
+ this.func_145778_a(Item.getItemFromBlock(Blocks.red_flower), 1, 0.0F);
+ }
+
+ k = 3 + this.rand.nextInt(3);
+
+ for (int l = 0; l < k; ++l) {
+ this.dropItem(Items.iron_ingot, 1);
+ }
+ }
+
+ public int getHoldRoseTick() {
+ return this.holdRoseTick;
+ }
+
+ public boolean isPlayerCreated() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ public void setPlayerCreated(boolean p_70849_1_) {
+ byte b0 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (p_70849_1_) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (b0 | 1)));
+ }
+ else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (b0 & -2)));
+ }
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ @Override
+ public void onDeath(DamageSource p_70645_1_) {
+ if (!this.isPlayerCreated() && this.attackingPlayer != null && this.villageObj != null) {
+ this.villageObj.setReputationForPlayer(this.attackingPlayer.getCommandSenderName(), -5);
+ }
+
+ super.onDeath(p_70645_1_);
+ }
+} \ No newline at end of file
diff --git a/src/Java/gtPlusPlus/core/entity/projectile/EntityToxinball.java b/src/Java/gtPlusPlus/core/entity/projectile/EntityToxinball.java
new file mode 100644
index 0000000000..5fcdc67ed6
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/entity/projectile/EntityToxinball.java
@@ -0,0 +1,330 @@
+package gtPlusPlus.core.entity.projectile;
+
+import java.util.List;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import net.minecraft.block.Block;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.projectile.EntityFireball;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.*;
+import net.minecraft.world.World;
+
+public abstract class EntityToxinball extends EntityFireball {
+ protected int entityX = -1;
+ protected int entityY = -1;
+ protected int entityZ = -1;
+ private Block block;
+ private boolean inGround;
+ public EntityLivingBase shootingEntity;
+ private int ticksAlive;
+ private int ticksInAir;
+ public double accelerationX;
+ public double accelerationY;
+ public double accelerationZ;
+
+ public EntityToxinball(World world) {
+ super(world);
+ this.setSize(1.0F, 1.0F);
+ }
+
+ @Override
+ protected void entityInit() {
+ }
+
+ /**
+ * Checks if the entity is in range to render by using the past in distance
+ * and comparing it to its average edge length * 64 * renderDistanceWeight
+ * Args: distance
+ */
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean isInRangeToRenderDist(double p_70112_1_) {
+ double d1 = this.boundingBox.getAverageEdgeLength() * 4.0D;
+ d1 *= 64.0D;
+ return p_70112_1_ < d1 * d1;
+ }
+
+ public EntityToxinball(World world, double x, double y, double z, double f1, double f2, double f3) {
+ super(world);
+ this.setSize(1.0F, 1.0F);
+ this.setLocationAndAngles(x, y, z, this.rotationYaw, this.rotationPitch);
+ this.setPosition(x, y, z);
+ double d6 = MathHelper
+ .sqrt_double(f1 * f1 + f2 * f2 + f3 * f3);
+ this.accelerationX = f1 / d6 * 0.1D;
+ this.accelerationY = f2 / d6 * 0.1D;
+ this.accelerationZ = f3 / d6 * 0.1D;
+ }
+
+ public EntityToxinball(World world, EntityLivingBase entity, double x, double y, double z) {
+ super(world);
+ this.shootingEntity = entity;
+ this.setSize(1.0F, 1.0F);
+ this.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw,
+ entity.rotationPitch);
+ this.setPosition(this.entityX, this.entityY, this.entityZ);
+ this.yOffset = 0.0F;
+ this.motionX = this.motionY = this.motionZ = 0.0D;
+ x += this.rand.nextGaussian() * 0.4D;
+ y += this.rand.nextGaussian() * 0.4D;
+ z += this.rand.nextGaussian() * 0.4D;
+ double d3 = MathHelper.sqrt_double(x * x + y * y + z * z);
+ this.accelerationX = x / d3 * 0.1D;
+ this.accelerationY = y / d3 * 0.1D;
+ this.accelerationZ = z / d3 * 0.1D;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ @Override
+ public void onUpdate() {
+ if (!this.worldObj.isRemote && (this.shootingEntity != null && this.shootingEntity.isDead
+ || !this.worldObj.blockExists(this.entityX, this.entityY, this.entityZ))) {
+ this.setDead();
+ }
+ else {
+ super.onUpdate();
+ this.setFire(1);
+
+ if (this.inGround) {
+ if (this.worldObj.getBlock(this.entityX, this.entityY,
+ this.entityZ) == this.block) {
+ ++this.ticksAlive;
+
+ if (this.ticksAlive == 600) {
+ this.setDead();
+ }
+
+ return;
+ }
+
+ this.inGround = false;
+ this.motionX *= this.rand.nextFloat() * 0.2F;
+ this.motionY *= this.rand.nextFloat() * 0.2F;
+ this.motionZ *= this.rand.nextFloat() * 0.2F;
+ this.ticksAlive = 0;
+ this.ticksInAir = 0;
+ }
+ else {
+ ++this.ticksInAir;
+ }
+
+ Vec3 vec3 = Vec3.createVectorHelper(this.entityX, this.entityY, this.entityZ);
+ Vec3 vec31 = Vec3.createVectorHelper(this.entityX + this.motionX, this.entityY + this.motionY,
+ this.entityZ + this.motionZ);
+ MovingObjectPosition movingobjectposition = this.worldObj.rayTraceBlocks(vec3, vec31);
+ vec3 = Vec3.createVectorHelper(this.entityX, this.entityY, this.entityZ);
+ vec31 = Vec3.createVectorHelper(this.entityX + this.motionX, this.entityY + this.motionY,
+ this.entityZ + this.motionZ);
+
+ if (movingobjectposition != null) {
+ vec31 = Vec3.createVectorHelper(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord,
+ movingobjectposition.hitVec.zCoord);
+ }
+
+ Entity entity = null;
+ List<?> list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
+ double d0 = 0.0D;
+
+ for (int i = 0; i < list.size(); ++i) {
+ Entity entity1 = (Entity) list.get(i);
+
+ if (entity1.canBeCollidedWith()
+ && (!entity1.isEntityEqual(this.shootingEntity) || this.ticksInAir >= 25)) {
+ float f = 0.3F;
+ AxisAlignedBB axisalignedbb = entity1.boundingBox.expand(f, f, f);
+ MovingObjectPosition movingobjectposition1 = axisalignedbb.calculateIntercept(vec3, vec31);
+
+ if (movingobjectposition1 != null) {
+ double d1 = vec3.distanceTo(movingobjectposition1.hitVec);
+
+ if (d1 < d0 || d0 == 0.0D) {
+ entity = entity1;
+ d0 = d1;
+ }
+ }
+ }
+ }
+
+ if (entity != null) {
+ movingobjectposition = new MovingObjectPosition(entity);
+ }
+
+ if (movingobjectposition != null) {
+ this.onImpact(movingobjectposition);
+ }
+
+ this.entityX += this.motionX;
+ this.entityY += this.motionY;
+ this.entityZ += this.motionZ;
+ float f1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.rotationYaw = (float) (Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) + 90.0F;
+
+ for (this.rotationPitch = (float) (Math.atan2(f1, this.motionY) * 180.0D / Math.PI)
+ - 90.0F; this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
+ ;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
+ this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
+ float f2 = this.getMotionFactor();
+
+ if (this.isInWater()) {
+ for (int j = 0; j < 4; ++j) {
+ float f3 = 0.25F;
+ this.worldObj.spawnParticle("bubble", this.entityX - this.motionX * f3, this.entityY - this.motionY * f3,
+ this.entityZ - this.motionZ * f3, this.motionX, this.motionY, this.motionZ);
+ }
+
+ f2 = 0.8F;
+ }
+
+ this.motionX += this.accelerationX;
+ this.motionY += this.accelerationY;
+ this.motionZ += this.accelerationZ;
+ this.motionX *= f2;
+ this.motionY *= f2;
+ this.motionZ *= f2;
+ this.worldObj.spawnParticle("smoke", this.entityX, this.entityY + 0.5D, this.entityZ, 0.0D, 0.0D, 0.0D);
+ this.setPosition(this.entityX, this.entityY, this.entityZ);
+ }
+ }
+
+ /**
+ * Return the motion factor for this projectile. The factor is multiplied by
+ * the original motion.
+ */
+ @Override
+ protected float getMotionFactor() {
+ return 0.95F;
+ }
+
+ /**
+ * Called when this EntityFireball hits a block or entity.
+ */
+ @Override
+ protected abstract void onImpact(MovingObjectPosition p_70227_1_);
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ @Override
+ public void writeEntityToNBT(NBTTagCompound aTag) {
+ aTag.setShort("xTile", (short) this.entityX);
+ aTag.setShort("yTile", (short) this.entityY);
+ aTag.setShort("zTile", (short) this.entityZ);
+ aTag.setByte("inTile", (byte) Block.getIdFromBlock(this.block));
+ aTag.setByte("inGround", (byte) (this.inGround ? 1 : 0));
+ aTag.setTag("direction",
+ this.newDoubleNBTList(new double[] { this.motionX, this.motionY, this.motionZ }));
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ @Override
+ public void readEntityFromNBT(NBTTagCompound aTag) {
+ this.entityX = aTag.getShort("xTile");
+ this.entityY = aTag.getShort("yTile");
+ this.entityZ = aTag.getShort("zTile");
+ this.block = Block.getBlockById(aTag.getByte("inTile") & 255);
+ this.inGround = aTag.getByte("inGround") == 1;
+
+ if (aTag.hasKey("direction", 9)) {
+ NBTTagList nbttaglist = aTag.getTagList("direction", 6);
+ this.motionX = nbttaglist.func_150309_d(0);
+ this.motionY = nbttaglist.func_150309_d(1);
+ this.motionZ = nbttaglist.func_150309_d(2);
+ }
+ else {
+ this.setDead();
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through
+ * this Entity.
+ */
+ @Override
+ public boolean canBeCollidedWith() {
+ return true;
+ }
+
+ @Override
+ public float getCollisionBorderSize() {
+ return 1.0F;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ @Override
+ public boolean attackEntityFrom(DamageSource damage, float p_70097_2_) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ }
+ else {
+ this.setBeenAttacked();
+
+ if (damage.getEntity() != null) {
+ Vec3 vec3 = damage.getEntity().getLookVec();
+
+ if (vec3 != null) {
+ this.motionX = vec3.xCoord;
+ this.motionY = vec3.yCoord;
+ this.motionZ = vec3.zCoord;
+ this.accelerationX = this.motionX * 0.1D;
+ this.accelerationY = this.motionY * 0.1D;
+ this.accelerationZ = this.motionZ * 0.1D;
+ }
+
+ if (damage.getEntity() instanceof EntityLivingBase) {
+ this.shootingEntity = (EntityLivingBase) damage.getEntity();
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public float getShadowSize() {
+ return 0.0F;
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ @Override
+ public float getBrightness(float p_70013_1_) {
+ return 1.0F;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public int getBrightnessForRender(float p_70070_1_) {
+ return 15728880;
+ }
+} \ No newline at end of file
diff --git a/src/Java/gtPlusPlus/core/entity/projectile/EntityToxinballSmall.java b/src/Java/gtPlusPlus/core/entity/projectile/EntityToxinballSmall.java
new file mode 100644
index 0000000000..78469c9dad
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/entity/projectile/EntityToxinballSmall.java
@@ -0,0 +1,88 @@
+package gtPlusPlus.core.entity.projectile;
+
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.world.World;
+
+public class EntityToxinballSmall extends EntityToxinball {
+
+ public EntityToxinballSmall(World p_i1770_1_) {
+ super(p_i1770_1_);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ public EntityToxinballSmall(World world, EntityLivingBase entity, double x, double y, double z) {
+ super(world, entity, x, y, z);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ public EntityToxinballSmall(World p_i1772_1_, double p_i1772_2_, double p_i1772_4_, double p_i1772_6_, double p_i1772_8_, double p_i1772_10_, double p_i1772_12_) {
+ super(p_i1772_1_, p_i1772_2_, p_i1772_4_, p_i1772_6_, p_i1772_8_, p_i1772_10_, p_i1772_12_);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ /**
+ * Called when this EntityFireball hits a block or entity.
+ */
+ @Override
+ protected void onImpact(MovingObjectPosition MoP) {
+ if (!this.worldObj.isRemote) {
+ if (MoP.entityHit != null) {
+ if (!MoP.entityHit.isImmuneToFire() && MoP.entityHit
+ .attackEntityFrom(DamageSource.causeFireballDamage(this, this.shootingEntity), 5.0F)) {
+ MoP.entityHit.setFire(5);
+ }
+ }
+ else {
+ int i = MoP.blockX;
+ int j = MoP.blockY;
+ int k = MoP.blockZ;
+
+ switch (MoP.sideHit) {
+ case 0:
+ --j;
+ break;
+ case 1:
+ ++j;
+ break;
+ case 2:
+ --k;
+ break;
+ case 3:
+ ++k;
+ break;
+ case 4:
+ --i;
+ break;
+ case 5:
+ ++i;
+ }
+
+ if (this.worldObj.isAirBlock(i, j, k)) {
+ this.worldObj.setBlock(i, j, k, Blocks.fire);
+ }
+ }
+
+ this.setDead();
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through
+ * this Entity.
+ */
+ @Override
+ public boolean canBeCollidedWith() {
+ return false;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ @Override
+ public boolean attackEntityFrom(DamageSource p_70097_1_, float p_70097_2_) {
+ return false;
+ }
+} \ No newline at end of file