package com.flansmod.apocalypse.common.entity;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import com.flansmod.client.debug.EntityDebugVector;
import com.flansmod.client.gui.GuiDriveableController;
import com.flansmod.common.FlansMod;
import com.flansmod.common.driveables.DriveableData;
import com.flansmod.common.driveables.EnumDriveablePart;
import com.flansmod.common.driveables.mechas.EntityMecha;
import com.flansmod.common.driveables.mechas.MechaType;
import com.flansmod.common.network.PacketDriveableDamage;
import com.flansmod.common.teams.TeamsManager;
import com.flansmod.common.vector.Vector3f;
public class EntityAIMecha extends EntityMecha
{
private Entity target;
private float targetingRange = 20F;
private int targetAcquireInterval = 40;
private boolean usingLeft = false;
public EntityAIMecha(World world)
{
super(world);
}
public EntityAIMecha(World world, double x, double y, double z, MechaType type, DriveableData data, NBTTagCompound tags)
{
super(world, x, y, z, type, data, tags);
}
public void onUpdate()
{
throttle = 1F;
//float lookAheadDist = 20F;
//float targetHeight = getBiomeHeight(worldObj.getBiomeGenForCoords(new BlockPos((int)(posX + motionX * lookAheadDist), (int)(posY + motionY * lookAheadDist), (int)(posZ + motionZ * lookAheadDist))));
//float currentTargetHeight = getBiomeHeight(worldObj.getBiomeGenForCoords(new BlockPos((int)(posX), (int)(posY), (int)(posZ))));
//flapsPitchLeft = flapsPitchRight += (Math.max(currentTargetHeight, targetHeight) - (float)posY) * 0.1F;
super.onUpdate();
}
@Override
public boolean interactFirst(EntityPlayer entityplayer)
{
return false;
}
@Override
protected void moveAI(Vector3f actualMotion)
{
MechaType type = getMechaType();
DriveableData data = getDriveableData();
//Acquire target
if(target == null && (this.ticksExisted + this.getEntityId()) % targetAcquireInterval == 0)
{
double distToCurrentTarget = 999D;
for(Object obj : worldObj.getEntitiesWithinAABBExcludingEntity(this, getEntityBoundingBox().expand(targetingRange, targetingRange, targetingRange)))
{
double distToPotentialTarget = this.getDistanceSqToEntity((Entity)obj);
if(isBetterTarget(target, distToCurrentTarget, (Entity)obj, distToPotentialTarget))
{
target = (Entity)obj;
distToCurrentTarget = distToPotentialTarget;
}
}
}
//And if we have line of sight, shoot it
if(!worldObj.isRemote && target != null)
{
Vec3 rightArmOrigin = usingLeft ? axes.findLocalVectorGlobally(getMechaType().leftArmOrigin).toVec3().addVector(posX, posY, posZ) : axes.findLocalVectorGlobally(getMechaType().rightArmOrigin).toVec3().addVector(posX, posY, posZ);
Vec3 targetOrigin = new Vec3(target.posX, target.posY + target.getEyeHeight() / 2D, target.posZ);
double dX = targetOrigin.xCoord - rightArmOrigin.xCoord;
double dY = targetOrigin.yCoord - rightArmOrigin.yCoord;
double dZ = targetOrigin.zCoord - rightArmOrigin.zCoord;
axes.setAngles((float)Math.atan2(dZ, dX) * 180F / 3.14159F, 0F, 0F);
if(seats != null && seats[0] != null)
{
seats[0].looking.setAngles(0F, -(float)Math.atan2(dY, Math.sqrt(dX * dX + dZ * dZ)) * 180F / 3.14159F, 0F);
seats[0].prevLooking.setAngles(0F, -(float)Math.atan2(dY, Math.sqrt(dX * dX + dZ * dZ)) * 180F / 3.14159F, 0F);
}
MovingObjectPosition hit = worldObj.rayTraceBlocks(rightArmOrigin, targetOrigin, false);
if(worldObj.isRemote)
{
//worldObj.spawnEntityInWorld(new EntityDebugVector(worldObj, new Vector3f(rightArmOrigin), new Vector3f(dX, dY, dZ), 2));
}
{
double blockHitX = hit == null ? 0 : hit.hitVec.xCoord - rightArmOrigin.xCoord;
double blockHitY = hit == null ? 0 : hit.hitVec.yCoord - rightArmOrigin.yCoord;
double blockHitZ = hit == null ? 0 : hit.hitVec.zCoord - rightArmOrigin.zCoord;
//If the target is nearer than the block hit or there was no block
if(hit == null || hit.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK || dX * dX + dY * dY + dZ * dZ < blockHitX * blockHitX + blockHitY * blockHitY + blockHitZ * blockHitZ)
{
useItem(usingLeft);
if(rand.nextInt(5) == 0)
usingLeft = !usingLeft;
}
//Otherwise, move closer
else
{
//If we have a target, move towards it and look at it
moveX = (float)(target.posX - posX);
moveZ = (float)(target.posZ - posZ);
float mag = (float)Math.sqrt(moveX * moveX + moveZ * moveZ);
Vector3f intent = new Vector3f(moveX, 0, moveZ);
if(Math.abs(intent.lengthSquared()) > 0.1)
{
intent.normalise();
++legSwing;
//intent = axes.findLocalVectorGlobally(intent);
Vector3f intentOnLegAxes = legAxes.findGlobalVectorLocally(intent);
float intentAngle = (float)Math.atan2(intent.z, intent.x) * 180F / 3.14159265F;
float angleBetween = intentAngle - legAxes.getYaw();
if(angleBetween > 180F) angleBetween -= 360F;
if(angleBetween < -180F) angleBetween += 360F;
float signBetween = Math.signum(angleBetween);
angleBetween = Math.abs(angleBetween);
if(angleBetween > 0.1)
{
legAxes.rotateGlobalYaw(Math.min(angleBetween, type.rotateSpeed)*signBetween);
}
intent.scale((type.moveSpeed * data.engine.engineSpeed * speedMultiplier())*(4.3F/20F));
if(isPartIntact(EnumDriveablePart.hips))
{
//Move!
Vector3f.add(actualMotion, intent, actualMotion);
}
}
}
}
}
}
@Override
protected boolean creative()
{
return false;
}
private boolean isBetterTarget(Entity currentTarget, double distToCurrentTarget, Entity potentialTarget, double distToPotentialTarget)
{
if(potentialTarget instanceof EntityPlayer && distToPotentialTarget < distToCurrentTarget && distToPotentialTarget < targetingRange * targetingRange)
return true;
return false;
}
@Override
public boolean hasFuel()
{
return true;
}
@Override
public boolean hasEnoughFuel()
{
return true;
}
@Override
public boolean attackEntityFrom(DamageSource damagesource, float i)
{
if(worldObj.isRemote || isDead)
return true;
MechaType type = getMechaType();
if(damagesource.damageType.equals("player") && damagesource.getEntity().onGround && (seats[0] == null || seats[0].riddenByEntity == null))
{
return false;
}
else return super.attackEntityFrom(damagesource, i);
}
}