package minefantasy.entity; import java.util.List; import minefantasy.block.BlockListMF; import minefantasy.system.cfg; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.boss.EntityDragonPart; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.util.EntityDamageSourceIndirect; import net.minecraft.util.MathHelper; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.ForgeDirection; /** * * @author Anonymous Productions * * Sources are provided for educational reasons. * though small bits of code, or methods can be used in your own creations. */ public class EntityFirebreath extends Entity { private int xTile = -1; private int yTile = -1; private int zTile = -1; private int inTile = 0; private boolean inGround = false; public EntityLiving shootingEntity; private int ticksAlive; private int ticksInAir = 0; public double accelerationX; public double accelerationY; private int lifespan = 40; public double accelerationZ; public EntityFirebreath(World world) { super(world); this.setSize(2.0F, 2.0F); } protected void entityInit() { dataWatcher.addObject(4, Integer.valueOf(0)); } public EntityFirebreath ice() { dataWatcher.updateObject(4, 1); return this; } /** * 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 */ public boolean isInRangeToRenderDist(double dist) { double var3 = this.boundingBox.getAverageEdgeLength() * 4.0D; var3 *= 64.0D; return dist < var3 * var3; } public EntityFirebreath(World world, double x, double y, double z, double xtar, double ytar, double ztar) { super(world); this.setSize(1.0F, 1.0F); this.setLocationAndAngles(x, y, z, this.rotationYaw, this.rotationPitch); this.setPosition(x, y, z); double var14 = (double) MathHelper.sqrt_double(xtar * xtar + ytar * ytar + ztar * ztar); this.accelerationX = xtar / var14 * 0.1D; this.accelerationY = ytar / var14 * 0.1D; this.accelerationZ = ztar / var14 * 0.1D; } public EntityFirebreath(World world, EntityLiving attacker, double xtar, double ytar, double ztar) { super(world); this.shootingEntity = attacker; this.setSize(1.0F, 1.0F); this.setLocationAndAngles(attacker.posX, attacker.posY, attacker.posZ, attacker.rotationYaw, attacker.rotationPitch); this.setPosition(this.posX, this.posY, this.posZ); this.yOffset = 0.0F; this.motionX = this.motionY = this.motionZ = 0.0D; xtar += this.rand.nextGaussian() * 0.4D; ytar += this.rand.nextGaussian() * 0.4D; ztar += this.rand.nextGaussian() * 0.4D; double var9 = (double) MathHelper.sqrt_double(xtar * xtar + ytar * ytar + ztar * ztar); this.accelerationX = xtar / var9 * 0.1D; this.accelerationY = ytar / var9 * 0.1D; this.accelerationZ = ztar / var9 * 0.1D; } public int getType() { return dataWatcher.getWatchableObjectInt(4); } public EntityFirebreath(World world, EntityLiving attacker, double xtar, double ytar, double ztar, int life) { this(world, attacker, xtar, ytar, ztar); lifespan = life; } /** * Called to update the entity's position/logic. */ public void onUpdate() { if(this.isWet() && rand.nextInt(40) == 0) setDead(); int var15_1 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile); if (var15_1 > 0) { Block.blocksList[var15_1].setBlockBoundsBasedOnState(this.worldObj, this.xTile, this.yTile, this.zTile); AxisAlignedBB var2 = Block.blocksList[var15_1].getCollisionBoundingBoxFromPool(this.worldObj, this.xTile, this.yTile, this.zTile); if (var2 != null && var2.isVecInside(this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ))) { setDead(); } } if (!this.worldObj.isRemote && (!this.worldObj.blockExists((int) this.posX, (int) this.posY, (int) this.posZ))) { this.setDead(); } else { super.onUpdate(); if(getType() == 0) this.setFire(1); ++this.ticksAlive; if (this.ticksAlive >= lifespan) { this.setDead(); } if (this.inGround) { int var1 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile); if (var1 == this.inTile) { this.setDead(); return; } this.inGround = false; this.motionX *= (double) (this.rand.nextFloat() * 0.2F); this.motionY *= (double) (this.rand.nextFloat() * 0.2F); this.motionZ *= (double) (this.rand.nextFloat() * 0.2F); this.ticksAlive = 0; this.ticksInAir = 0; } else { ++this.ticksInAir; } Vec3 var15 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ); Vec3 var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ); MovingObjectPosition var3 = this.worldObj.clip(var15, var2); var15 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ); var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ); if (var3 != null) { var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(var3.hitVec.xCoord, var3.hitVec.yCoord, var3.hitVec.zCoord); } Entity var4 = null; List var5 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D)); double var6 = 0.0D; for (int var8 = 0; var8 < var5.size(); ++var8) { Entity var9 = (Entity) var5.get(var8); if (var9.canBeCollidedWith() && (!var9.isEntityEqual(this.shootingEntity) || this.ticksInAir >= 25)) { float var10 = 0.3F; AxisAlignedBB var11 = var9.boundingBox.expand((double) var10, (double) var10, (double) var10); MovingObjectPosition var12 = var11.calculateIntercept(var15, var2); if (var12 != null) { double var13 = var15.distanceTo(var12.hitVec); if (var13 < var6 || var6 == 0.0D) { var4 = var9; var6 = var13; } } } } boolean isRider; if (canShoot(var4)) { var3 = new MovingObjectPosition(var4); var4.setFire(1); if (rand.nextInt(3) == 0 && (!var4.isImmuneToFire() || getType() != 0)) { DamageSource source = getDamageSource(); var4.attackEntityFrom(source, getDamage()); applyEffects(var4); } } if (var3 != null) { this.hitEntity(var3); } this.posX += this.motionX; this.posY += this.motionY; this.posZ += this.motionZ; float var16 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ); this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI); for (this.rotationPitch = (float) (Math.atan2(this.motionY, (double) var16) * 180.0D / Math.PI); 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 var17 = 0.95F; if (this.isInWater()) { for (int var19 = 0; var19 < 4; ++var19) { float var18 = 0.25F; this.worldObj.spawnParticle("smoke", this.posX - this.motionX * (double) var18, this.posY - this.motionY * (double) var18, this.posZ - this.motionZ * (double) var18, this.motionX, this.motionY, this.motionZ); } var17 = 0.8F; } this.motionX += this.accelerationX; this.motionY += this.accelerationY; this.motionZ += this.accelerationZ; this.motionX *= (double) var17; this.motionY *= (double) var17; this.motionZ *= (double) var17; this.worldObj.spawnParticle("snoke", this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D); this.setPosition(this.posX, this.posY, this.posZ); } AxisAlignedBB bb = this.boundingBox.expand(1D, 1D, 1D); if(!worldObj.isRemote) this.destroyBlocksInAABB(bb); } private DamageSource getDamageSource() { if(shootingEntity != null) { return new DamageSourceFirebreath(this, shootingEntity); } return new DamageSourceFirebreath(this, this); } private boolean canShoot(Entity en) { if(en == null) return false; if(shootingEntity != null) if(shootingEntity.riddenByEntity != null) { if(shootingEntity.riddenByEntity == en) return false; } return true; } private void applyEffects(Entity tar) { if(tar instanceof EntityLiving) { EntityLiving live = (EntityLiving)tar; if(getType() == 1) { //FROST EFFECT int id = Potion.moveSlowdown.id; int d = 20; int l = 0; if(live.getActivePotionEffect(Potion.moveSlowdown) != null) { id = live.getActivePotionEffect(Potion.moveSlowdown).getPotionID(); d = live.getActivePotionEffect(Potion.moveSlowdown).getDuration(); l = live.getActivePotionEffect(Potion.moveSlowdown).getAmplifier(); if(d < 1200) d += 30; if(rand.nextInt(10) == 0 && l < 5) { l ++; } } live.addPotionEffect(new PotionEffect(id, d, l)); } } } protected void hitEntity(MovingObjectPosition pos) { if (!this.worldObj.isRemote) { AxisAlignedBB var3 = this.boundingBox.expand(4.0D, 2.0D, 4.0D); List var4 = this.worldObj.getEntitiesWithinAABB(EntityLiving.class, var3); if (var4 != null && !var4.isEmpty()) { } if(rand.nextInt(60) == 0 && cfg.dragonGrief) { int id = 0; if(getType() == 0) id = Block.fire.blockID; if(getType() == 1) id = Block.snow.blockID; placeFire((int)posX, (int)posY, (int)posZ, id); placeFire((int)posX, (int)posY-1, (int)posZ, id); if(getType() == 3) { freezeBlock((int)posX, (int)posY, (int)posZ); } } if (pos.entityHit != null && pos.entityHit.attackEntityFrom(getDamageSource(), getDamage())) { applyEffects(pos.entityHit); } if (pos.entityHit != null && (pos.entityHit instanceof EntityDragonSmall || pos.entityHit instanceof EntityFirebreath)) { ; } else setDead(); } } private void placeFire(int x, int y, int z, int id) { if(worldObj.isAirBlock(x, y, z) || worldObj.getBlockMaterial(x, y, z) == Material.snow) { placeBlock(x, y, z, id); } } private int getDamage() { switch(getType()) { case 0: return 4; case 1: return 3; } return 4; } private void freezeBlock(int x, int y, int z) { int id; int repl = worldObj.getBlockId(x, y, z); if(repl == Block.waterStill.blockID)id = Block.ice.blockID; if(repl == Block.lavaStill.blockID)id = Block.obsidian.blockID; if(repl == Block.lavaMoving.blockID)id = Block.obsidian.blockID; if(worldObj.getBlockMaterial(x, y, z) == Material.leaves)id = BlockListMF.ice.blockID; if(worldObj.getBlockMaterial(x, y, z) == Material.plants)id = BlockListMF.ice.blockID; } private void placeBlock(int x, int y, int z, int id) { if(!worldObj.isAirBlock(x, y-1, z)) if(worldObj.isBlockNormalCube(x, y-1, z) || Block.blocksList[id].isOpaqueCube()) worldObj.setBlock(x, y, z, id, 0, 3); } /** * (abstract) Protected helper method to write subclass entity data to NBT. */ public void writeEntityToNBT(NBTTagCompound tag) { tag.setShort("xTile", (short) this.xTile); tag.setShort("yTile", (short) this.yTile); tag.setShort("zTile", (short) this.zTile); tag.setByte("inTile", (byte) this.inTile); tag.setByte("inGround", (byte) (this.inGround ? 1 : 0)); tag.setInteger("Type", getType()); } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ public void readEntityFromNBT(NBTTagCompound tag) { this.xTile = tag.getShort("xTile"); this.yTile = tag.getShort("yTile"); this.zTile = tag.getShort("zTile"); this.inTile = tag.getByte("inTile") & 255; this.inGround = tag.getByte("inGround") == 1; dataWatcher.updateObject(4, tag.getInteger("Type")); } /** * Returns true if other Entities should be prevented from moving through this Entity. */ public boolean canBeCollidedWith() { return true; } public float getCollisionBorderSize() { return 1.0F; } public float getShadowSize() { return 0.0F; } /** * Gets how bright this entity is. */ public float getBrightness(float amount) { return 1.0F; } public int getBrightnessForRender(float amount) { return 15728880; } private boolean destroyBlocksInAABB(AxisAlignedBB box) { int var2 = MathHelper.floor_double(box.minX); int var3 = MathHelper.floor_double(box.minY); int var4 = MathHelper.floor_double(box.minZ); int var5 = MathHelper.floor_double(box.maxX); int var6 = MathHelper.floor_double(box.maxY); int var7 = MathHelper.floor_double(box.maxZ); boolean var8 = false; boolean var9 = false; for (int var10 = var2; var10 <= var5; ++var10) { for (int var11 = var3; var11 <= var6; ++var11) { for (int var12 = var4; var12 <= var7; ++var12) { Material var13 = this.worldObj.getBlockMaterial(var10, var11, var12); if (var13 != null) { if (var13 == Material.glass) { var9 = true; this.worldObj.setBlockToAir(var10, var11, var12); } else if (var13 == Material.tnt) { var9 = true; this.worldObj.setBlockToAir(var10, var11, var12); this.worldObj.createExplosion(this, var10, var11, var12, 4.0F, true); } else { var8 = true; } } } } } if (var9) { double var16 = box.minX + (box.maxX - box.minX) * (double)this.rand.nextFloat(); double var17 = box.minY + (box.maxY - box.minY) * (double)this.rand.nextFloat(); double var14 = box.minZ + (box.maxZ - box.minZ) * (double)this.rand.nextFloat(); this.worldObj.spawnParticle("largeexplode", var16, var17, var14, 0.0D, 0.0D, 0.0D); for(int a = 0 ; a < 1+rand.nextInt(4); a ++) this.worldObj.playSoundAtEntity(this, "random.glass", 1F, 1F); } return var8; } public class DamageSourceFirebreath extends EntityDamageSourceIndirect { public DamageSourceFirebreath(EntityFirebreath breath, Entity shooter) { super("indirectMagic", breath, shooter); this.setFireDamage(); } } }