/**
Copyright (C) 2015 by jabelar
This file is part of jabelar's Minecraft Forge modding examples; 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.
For a copy of the GNU General Public License see <http://www.gnu.org/licenses/>.
*/
package com.blogspot.jabelarminecraft.wildanimals.entities.ai.birdofprey;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.util.Vec3;
import com.blogspot.jabelarminecraft.wildanimals.entities.birdsofprey.EntityBirdOfPrey;
import com.blogspot.jabelarminecraft.wildanimals.utilities.Utilities;
/**
* @author jabelar
*
*/
public class ProcessStateBirdOfPrey
{
EntityBirdOfPrey theBird;
public float yawChangeRate = 1.5F;
public float pitchChangeRate = 1.5F;
public float targetPitch = 0.0F;
public ProcessStateBirdOfPrey(EntityBirdOfPrey parBirdOfPrey)
{
theBird = parBirdOfPrey;
}
public void updateAITick()
{
// // DEBUG
// System.out.println("State = "+getState());
// regen
if (theBird.isTamed())
{
if (theBird.ticksExisted%50 == 0 && theBird.isEntityAlive())
{
theBird.setHealth(theBird.getHealth()+1.0F);
}
}
switch (theBird.getState())
{
case AIStates.STATE_PERCHED:
processPerched();
break;
case AIStates.STATE_TAKING_OFF:
processTakingOff();
break;
case AIStates.STATE_SOARING:
processSoaring();
break;
case AIStates.STATE_DIVING:
processDiving();
break;
case AIStates.STATE_LANDING:
processLanding();
break;
case AIStates.STATE_TRAVELLING:
processTravelling();
break;
case AIStates.STATE_ATTACKING:
processAttacking();
break;
case AIStates.STATE_SOARING_TAMED:
processSoaring();
break;
case AIStates.STATE_PERCHED_TAMED:
processPerched();
break;
case AIStates.STATE_SEEKING:
processSeeking();
break;
default:
// DEBUG
System.out.println("Unknown state");
break;
}
}
/**
*
*/
private void processSeeking()
{
updatePitch(0.0F);
if (theBird.getAttackTarget() != null)
{
updateYaw(Utilities.getYawFromVec(Vec3.createVectorHelper(
theBird.getAttackTarget().posX - theBird.posX,
theBird.getAttackTarget().posY - theBird.posY,
theBird.getAttackTarget().posZ - theBird.posZ)));
}
moveForward(1.0D);
}
/**
*
*/
protected void processLanding()
{
updatePitch(Math.max(0.0F, theBird.rotationPitch-pitchChangeRate*3));
theBird.motionX = theBird.getAnchorX() - theBird.posX;
theBird.motionZ = theBird.getAnchorZ() - theBird.posZ;
theBird.motionY = Math.min(-0.2F, theBird.motionY+0.2);
}
/**
*
*/
protected void processDiving()
{
updatePitch(90.0F);
theBird.motionX = theBird.getAnchorX() - theBird.posX;
theBird.motionZ = theBird.getAnchorZ() - theBird.posZ;
theBird.motionY = -1.0D;
}
protected void processTakingOff()
{
updatePitch(0.0F);
// climb to soaring height
if (theBird.posY < theBird.getSoarHeight())
{
theBird.motionY = 0.1D;
}
moveForward(1.0D);
// turn
if (theBird.getSoarClockwise())
{
updateYaw(theBird.rotationYaw + yawChangeRate);
}
else
{
updateYaw(theBird.rotationYaw - yawChangeRate);
}
}
/**
*
*/
protected void processPerched()
{
updatePitch(0.0F); // although the model is upright, want to make sure look vector and sense of motion preserved.
processFrictionAndGravity();
// stopMoving();
}
protected void processSoaring()
{
updatePitch(0.0F);
// drift down slowly
theBird.motionY = -0.01D;
moveForward(1.0D);
// turn
if (theBird.isTamed())
{
// turn towards owner
// got the dot product idea from https://github.com/chraft/c-raft/wiki/Vectors,-Location,-Yaw-and-Pitch-in-C%23raft
Vec3 vecToOwner = Vec3.createVectorHelper(
theBird.getOwner().posX - theBird.posX,
0,
theBird.getOwner().posZ - theBird.posZ).normalize();
if (theBird.getLookVec().dotProduct(vecToOwner) > 0.0D)
{
updateYaw(theBird.rotationYaw - yawChangeRate);
}
else
{
updateYaw(theBird.rotationYaw + yawChangeRate);
}
}
else
{
if (theBird.getSoarClockwise())
{
updateYaw(theBird.rotationYaw + yawChangeRate);
}
else
{
updateYaw(theBird.rotationYaw - yawChangeRate);
}
}
}
protected void processTravelling()
{
updatePitch(0.0F);
// climb to soaring height
if (theBird.posY < theBird.getSoarHeight())
{
theBird.motionY = 0.1D;
}
moveForward(1.0D);
}
protected void processAttacking()
{
if (theBird.getAttackTarget() != null)
{
theBird.motionY = -2.0D;
double ticksToHitTarget = (theBird.posY - theBird.getAttackTarget().posY) / Math.abs(theBird.motionY);
theBird.motionX = (theBird.getAttackTarget().posX - theBird.posX) / ticksToHitTarget;
theBird.motionZ = (theBird.getAttackTarget().posZ - theBird.posZ) / ticksToHitTarget;
updatePitch(Utilities.getPitchFromVec(Vec3.createVectorHelper(
theBird.motionX,
theBird.motionY,
theBird.motionZ)));
}
}
public void moveForward(double parSpeedFactor)
{
theBird.motionX = theBird.getLookVec().xCoord * parSpeedFactor * theBird.getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue();
theBird.motionZ = theBird.getLookVec().zCoord * parSpeedFactor * theBird.getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue();
}
protected void stopMoving()
{
theBird.motionX = 0;
theBird.motionY = 0;
theBird.motionZ = 0;
}
protected void processFrictionAndGravity()
{
theBird.motionX *= 0.93D;
theBird.motionZ *= 0.93D;
theBird.motionY -= 0.04D;
}
protected void updateYaw(float parYaw)
{
float angleDiff = parYaw - theBird.rotationYaw;
// handle possibility that shortest path is to rotate the other way
if (angleDiff > 0.0001F)
{
if (angleDiff > 180.0F)
{
angleDiff -= 360.0F;
}
theBird.rotationYaw += yawChangeRate;
}
else if (angleDiff < -0.0001F)
{
if (angleDiff < -180.0F)
{
angleDiff += 360.0F;
}
theBird.rotationYaw -= yawChangeRate;
}
// clamp to avoid oscillation around target
if (Math.abs(angleDiff) < yawChangeRate)
{
theBird.rotationYaw = parYaw;
}
}
protected void updatePitch(float parPitch)
{
float angleDiff = parPitch - theBird.rotationPitch;
// handle possibility that shortest path is to rotate the other way
if (angleDiff > 0.0001F)
{
if (angleDiff > 180.0F)
{
angleDiff -= 360.0F;
}
theBird.rotationPitch += pitchChangeRate;
}
else if (angleDiff < -0.0001F)
{
if (angleDiff < -180.0F)
{
angleDiff += 360.0F;
}
theBird.rotationPitch -= pitchChangeRate;
}
// clamp to avoid oscillation around target
if (Math.abs(angleDiff) < pitchChangeRate)
{
theBird.rotationPitch = parPitch;
}
}
}