/** Copyright (C) <2015> <coolAlias> This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package zeldaswordskills.entity.projectile; import io.netty.buffer.ByteBuf; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.projectile.EntityThrowable; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; /** * * Abstract class that provides constructor for throwing entity as a mob * */ public abstract class EntityMobThrowable extends EntityThrowable implements IEntityAdditionalSpawnData { /** The throwing entity's ID, in case it is not a player. Only used after loading from NBT */ private int throwerId; /** Usually the damage this entity will cause upon impact */ private float damage; /** Projectile gravity velocity */ private float gravity = 0.03F; public EntityMobThrowable(World world) { super(world); } public EntityMobThrowable(World world, EntityLivingBase entity) { super(world, entity); } public EntityMobThrowable(World world, double x, double y, double z) { super(world, x, y, z); } /** * Constructs a throwable entity heading towards target's initial position with given velocity, with possible abnormal trajectory; * @param inaccuracy amount of deviation from base trajectory, used by Skeletons and the like; set to 0.0F for no x/z deviation */ public EntityMobThrowable(World world, EntityLivingBase shooter, EntityLivingBase target, float velocity, float inaccuracy) { super(world, shooter); this.posY = shooter.posY + (double) shooter.getEyeHeight() - 0.10000000149011612D; double d0 = target.posX - shooter.posX; double d1 = target.getEntityBoundingBox().minY + (double)(target.height / 3.0F) - this.posY; double d2 = target.posZ - shooter.posZ; double d3 = (double) MathHelper.sqrt_double(d0 * d0 + d2 * d2); if (d3 >= 1.0E-7D) { float f2 = (float)(Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F; float f3 = (float)(-(Math.atan2(d1, d3) * 180.0D / Math.PI)); double d4 = d0 / d3; double d5 = d2 / d3; setLocationAndAngles(shooter.posX + d4, this.posY, shooter.posZ + d5, f2, f3); float f4 = (float) d3 * 0.2F; setThrowableHeading(d0, d1 + (double) f4, d2, velocity, inaccuracy); } } @Override public EntityLivingBase getThrower() { EntityLivingBase thrower = super.getThrower(); if (thrower == null) { Entity entity = worldObj.getEntityByID(throwerId); return (entity instanceof EntityLivingBase ? (EntityLivingBase) entity : null); } return thrower; } /** Returns the amount of damage this entity will cause upon impact */ public float getDamage() { return damage; } /** * Sets the damage this entity will cause upon impact */ public EntityMobThrowable setDamage(float amount) { this.damage = amount; return this; } /** * Re-sets the projectile's heading on the exact same trajectory but using the given velocity */ public EntityMobThrowable setProjectileVelocity(float velocity) { this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, velocity, 0.0F); return this; } @Override protected float getGravityVelocity() { return gravity; } /** * Sets the projectile's gravity velocity */ public EntityMobThrowable setGravityVelocity(float amount) { this.gravity = amount; return this; } @Override public void onUpdate() { super.onUpdate(); if ((!gravityCheck() || posY > 255.0F) && !worldObj.isRemote) { setDead(); } } /** * Sanity check for gravity - return true if the entity can stay alive. * Note that it will be killed anyway once it surpasses y=255. */ protected boolean gravityCheck() { return getGravityVelocity() > 0.0F || ticksExisted < 60; } @Override public void writeEntityToNBT(NBTTagCompound compound) { super.writeEntityToNBT(compound); compound.setInteger("throwerId", (getThrower() == null ? -1 : getThrower().getEntityId())); compound.setFloat("damage", damage); compound.setFloat("gravity", gravity); } @Override public void readEntityFromNBT(NBTTagCompound compound) { super.readEntityFromNBT(compound); throwerId = compound.getInteger("throwerId"); damage = compound.getFloat("damage"); gravity = compound.getFloat("gravity"); } @Override public void writeSpawnData(ByteBuf buffer) { buffer.writeFloat(gravity); } @Override public void readSpawnData(ByteBuf buffer) { gravity = buffer.readFloat(); } }