package com.hbm.entity.mob; import java.util.ArrayList; import java.util.List; import com.hbm.entity.projectile.EntityBulletBaseNT; import com.hbm.explosion.ExplosionNukeSmall; import com.hbm.handler.BulletConfigSyncingUtil; import com.hbm.items.ModItems; import com.hbm.lib.ModDamageSource; import com.hbm.main.MainRegistry; import com.hbm.packet.PacketDispatcher; import com.hbm.packet.toclient.AuxParticlePacketNT; import com.hbm.util.ContaminationUtil; import com.hbm.util.ContaminationUtil.ContaminationType; import com.hbm.util.ContaminationUtil.HazardType; import api.hbm.entity.IRadiationImmune; import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.boss.IBossDisplayData; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.Potion; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.util.Vec3; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; public class EntityUFO extends EntityFlying implements IMob, IBossDisplayData, IRadiationImmune { public int courseChangeCooldown; public int scanCooldown; /*public double waypointX; public double waypointY; public double waypointZ;*/ public int hurtCooldown; public int beamTimer; private Entity target; private List secondaries = new ArrayList(); public EntityUFO(World p_i1587_1_) { super(p_i1587_1_); this.setSize(15F, 4F); this.isImmuneToFire = true; this.experienceValue = 500; this.ignoreFrustumCheck = true; this.deathTime = -30; } @Override protected boolean canDespawn() { return false; } @Override public boolean attackEntityFrom(DamageSource source, float amount) { if(hurtCooldown > 0) return false; boolean hit = super.attackEntityFrom(source, amount); if(hit) hurtCooldown = 5; return hit; } @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(20000.0D); } @Override protected void updateEntityActionState() { if(!this.worldObj.isRemote) { if(this.worldObj.difficultySetting == EnumDifficulty.PEACEFUL) { this.setDead(); return; } if(this.hurtCooldown > 0) { this.hurtCooldown--; } } if(this.courseChangeCooldown > 0) { this.courseChangeCooldown--; } if(this.scanCooldown > 0) { this.scanCooldown--; } if(this.target != null && !this.target.isEntityAlive()) { this.target = null; } if(this.scanCooldown <= 0) { List entities = worldObj.getEntitiesWithinAABB(Entity.class, this.boundingBox.expand(100, 50, 100)); this.secondaries.clear(); this.target = null; for(Entity entity : entities) { if(!entity.isEntityAlive() || !canAttackClass(entity.getClass())) continue; if(entity instanceof EntityPlayer) { if(((EntityPlayer)entity).capabilities.isCreativeMode) continue; if(((EntityPlayer)entity).isPotionActive(Potion.invisibility.id)) continue; if(this.target == null) { this.target = entity; } else { if(this.getDistanceSqToEntity(entity) < this.getDistanceSqToEntity(this.target)) { this.target = entity; } } } if(entity instanceof EntityLivingBase && this.getDistanceSqToEntity(entity) < 100 * 100 && this.canEntityBeSeen(entity) && entity != this.target) { this.secondaries.add(entity); } } if(this.target == null && !this.secondaries.isEmpty()) this.target = this.secondaries.get(rand.nextInt(this.secondaries.size())); this.scanCooldown = 50; } if(this.target != null && this.courseChangeCooldown <= 0) { Vec3 vec = Vec3.createVectorHelper(this.posX - this.target.posX, 0, this.posZ - this.target.posZ); if(rand.nextInt(3) > 0) vec.rotateAroundY((float)Math.PI * 2 * rand.nextFloat()); double length = vec.lengthVector(); double overshoot = 35; int wX = (int)Math.floor(this.target.posX - vec.xCoord / length * overshoot); int wZ = (int)Math.floor(this.target.posZ - vec.zCoord / length * overshoot); this.setWaypoint(wX, Math.max(this.worldObj.getHeightValue(wX, wZ) + 20 + rand.nextInt(15), (int) this.target.posY + 15), wZ); this.courseChangeCooldown = 40 + rand.nextInt(20); } if(!worldObj.isRemote) { if(beamTimer <= 0 && this.getBeam()) { this.setBeam(false); } if(this.target != null) { double dist = Math.abs(this.target.posX - this.posX) + Math.abs(this.target.posZ - this.posZ); if(dist < 25) this.beamTimer = 30; } if(beamTimer > 0) { this.beamTimer--; if(!this.getBeam()) { worldObj.playSoundAtEntity(this, "hbm:entity.ufoBeam", 10.0F, 1.0F); this.setBeam(true); } int ix = (int)Math.floor(this.posX); int iz = (int)Math.floor(this.posZ); int iy = 0; for(int i = (int)Math.ceil(this.posY); i >= 0; i--) { if(this.worldObj.getBlock(ix, i, iz) != Blocks.air) { iy = i; break; } } if(iy < this.posY) { List entities = worldObj.getEntitiesWithinAABBExcludingEntity(this, AxisAlignedBB.getBoundingBox(this.posX, iy, this.posZ, this.posX, this.posY, this.posZ).expand(5, 0, 5)); for(Entity e : entities) { if(this.canAttackClass(e.getClass())) { e.attackEntityFrom(ModDamageSource.causeCombineDamage(this, e), 1000F); e.setFire(5); if(e instanceof EntityLivingBase) ContaminationUtil.contaminate((EntityLivingBase)e, HazardType.RADIATION, ContaminationType.CREATIVE, 5F); } } NBTTagCompound data = new NBTTagCompound(); data.setString("type", "ufo"); PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, iy + 0.5, posZ), new TargetPoint(dimension, posX, iy + 0.5, posZ, 150)); PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX + this.motionX * 0.5, iy + 0.5, posZ + this.motionZ * 0.5), new TargetPoint(dimension, posX + this.motionX * 0.5, iy + 0.5, posZ + this.motionZ * 0.5, 150)); } } if(this.ticksExisted % 300 < 200) { if(this.ticksExisted % 4 == 0) { if(!this.secondaries.isEmpty()){ Entity e = this.secondaries.get(rand.nextInt(this.secondaries.size())); if(!e.isEntityAlive()) this.secondaries.remove(e); else laserAttack(e); } else if(this.target != null) { laserAttack(this.target); } } else if(this.ticksExisted % 4 == 2) { if(this.target != null) { laserAttack(this.target); } } } else { if(this.ticksExisted % 20 == 0) { if(!this.secondaries.isEmpty()){ Entity e = this.secondaries.get(rand.nextInt(this.secondaries.size())); if(!e.isEntityAlive()) this.secondaries.remove(e); else rocketAttack(e); } else if(this.target != null) { rocketAttack(this.target); } } else if(this.ticksExisted % 20 == 10) { if(this.target != null) { rocketAttack(this.target); } } } } this.motionX = 0; this.motionY = 0; this.motionZ = 0; if(this.courseChangeCooldown > 0) { double deltaX = this.getX() - this.posX; double deltaY = this.getY() - this.posY; double deltaZ = this.getZ() - this.posZ; Vec3 delta = Vec3.createVectorHelper(deltaX, deltaY, deltaZ); double len = delta.lengthVector(); double speed = this.target instanceof EntityPlayer ? 5D : 2D; if(len > 5) { if(isCourseTraversable(this.getX(), this.getY(), this.getZ(), len)) { this.motionX = delta.xCoord * speed / len; this.motionY = delta.yCoord * speed / len; this.motionZ = delta.zCoord * speed / len; } else { this.courseChangeCooldown = 0; } } } } protected void onDeathUpdate() { if(this.getBeam()) this.setBeam(false); this.motionY -= 0.05D; if(this.deathTime == -10) { worldObj.playSoundAtEntity(this, "hbm:entity.chopperDamage", 10.0F, 1.0F); } if(this.deathTime == 19 && !worldObj.isRemote) { worldObj.newExplosion(this, posX, posY, posZ, 10F, true, true); ExplosionNukeSmall.explode(worldObj, posX, posY, posZ, ExplosionNukeSmall.PARAMS_MEDIUM); List players = worldObj.getEntitiesWithinAABB(EntityPlayer.class, this.boundingBox.expand(200, 200, 200)); for(EntityPlayer player : players) { player.triggerAchievement(MainRegistry.bossUFO); player.inventory.addItemStackToInventory(new ItemStack(ModItems.coin_ufo)); } } super.onDeathUpdate(); } private void laserAttack(Entity e) { Vec3 vec = Vec3.createVectorHelper(this.posX - e.posX, 0, this.posZ - e.posZ); vec.rotateAroundY((float) Math.toRadians(-80 + rand.nextInt(160))); vec = vec.normalize(); double pivotX = this.posX - vec.xCoord * 10; double pivotY = this.posY + 0.5; double pivotZ = this.posZ - vec.zCoord * 10; Vec3 heading = Vec3.createVectorHelper(e.posX - pivotX, e.posY + e.height / 2 - pivotY, e.posZ - pivotZ); heading = heading.normalize(); EntityBulletBaseNT bullet = new EntityBulletBaseNT(this.worldObj, BulletConfigSyncingUtil.WORM_LASER); bullet.setThrower(this); bullet.setPosition(pivotX, pivotY, pivotZ); bullet.setThrowableHeading(heading.xCoord, heading.yCoord, heading.zCoord, 2F, 0.02F); this.worldObj.spawnEntityInWorld(bullet); this.playSound("hbm:weapon.ballsLaser", 5.0F, 1.0F); } private void rocketAttack(Entity e) { Vec3 heading = Vec3.createVectorHelper(e.posX - this.posX, e.posY + e.height / 2 - posY - 0.5D, e.posZ - this.posZ); heading = heading.normalize(); EntityBulletBaseNT bullet = new EntityBulletBaseNT(this.worldObj, BulletConfigSyncingUtil.UFO_ROCKET); bullet.setThrower(this); bullet.setPosition(this.posX, this.posY - 0.5D, this.posZ); bullet.setThrowableHeading(heading.xCoord, heading.yCoord, heading.zCoord, 2F, 0.02F); bullet.getEntityData().setInteger("homingTarget", e.getEntityId()); this.worldObj.spawnEntityInWorld(bullet); this.playSound("hbm:turret.richard_fire", 5.0F, 1.0F); } @Override public boolean canAttackClass(Class clazz) { return clazz != this.getClass() && clazz != EntityBulletBaseNT.class; } @Override protected void entityInit() { super.entityInit(); this.dataWatcher.addObject(16, Byte.valueOf((byte) 0)); this.dataWatcher.addObject(17, 0); this.dataWatcher.addObject(18, 0); this.dataWatcher.addObject(19, 0); } private boolean isCourseTraversable(double p_70790_1_, double p_70790_3_, double p_70790_5_, double p_70790_7_) { double d4 = (this.getX() - this.posX) / p_70790_7_; double d5 = (this.getY() - this.posY) / p_70790_7_; double d6 = (this.getZ() - this.posZ) / p_70790_7_; AxisAlignedBB axisalignedbb = this.boundingBox.copy(); for(int i = 1; i < p_70790_7_; ++i) { axisalignedbb.offset(d4, d5, d6); if(!this.worldObj.getCollidingBoundingBoxes(this, axisalignedbb).isEmpty()) { return false; } } return true; } @Override protected float getSoundVolume() { return 10.0F; } @Override protected String getHurtSound() { return "mob.blaze.hit"; } @Override protected String getDeathSound() { return null; } @Override public void writeEntityToNBT(NBTTagCompound p_70014_1_) { super.writeEntityToNBT(p_70014_1_); } @Override public void readEntityFromNBT(NBTTagCompound p_70037_1_) { super.readEntityFromNBT(p_70037_1_); } public void setBeam(boolean b) { this.dataWatcher.updateObject(16, Byte.valueOf((byte) (b ? 1 : 0))); } public boolean getBeam() { return this.dataWatcher.getWatchableObjectByte(16) == 1; } public void setWaypoint(int x, int y, int z) { this.dataWatcher.updateObject(17, x); this.dataWatcher.updateObject(18, y); this.dataWatcher.updateObject(19, z); } public int getX() { return this.dataWatcher.getWatchableObjectInt(17); } public int getY() { return this.dataWatcher.getWatchableObjectInt(18); } public int getZ() { return this.dataWatcher.getWatchableObjectInt(19); } @Override @SideOnly(Side.CLIENT) public boolean isInRangeToRenderDist(double distance) { return distance < 500000; } }