Package com.flansmod.common.driveables

Source Code of com.flansmod.common.driveables.DriveablePart

package com.flansmod.common.driveables;

import net.minecraft.nbt.NBTTagCompound;

import com.flansmod.common.guns.EntityBullet;
import com.flansmod.common.guns.raytracing.DriveableHit;
import com.flansmod.common.vector.Vector3f;

public class DriveablePart
{
  public EnumDriveablePart type;
  public CollisionBox box;
  public int maxHealth;
  public int health;
  public int fireTime;
  public boolean onFire;
  /** Keeps track of whether death code has been called or not */
  public boolean dead;
 
  public DriveablePart(EnumDriveablePart e, CollisionBox b)
  {
    type = e;
    box = b;
    health = maxHealth = b == null ? 0 : b.health;
  }
 
  public void update(EntityDriveable driveable)
  {
    if(fireTime > 0)
      fireTime--;
    if(fireTime == 0)
      onFire = false;
    if(onFire)
      health--;
    if(health <= 0 && maxHealth > 0)
    {
      dead = true;
    }
  }
 
  public void writeToNBT(NBTTagCompound tags)
  {
    tags.setInteger(type.getShortName() + "_Health", health);
    tags.setBoolean(type.getShortName() + "_Fire", onFire);
  }
 
  public void readFromNBT(NBTTagCompound tags)
  {
    if(!tags.hasKey(type.getShortName() + "_Health"))
    {
      health = maxHealth;
      onFire = false;
      return;
    }
    health = tags.getInteger(type.getShortName() + "_Health");
    onFire = tags.getBoolean(type.getShortName() + "_Fire");
  }
 
  /** Called when a corner of this part hits the ground.
   * @return The amount of damage to do to the block */
  public float smashIntoGround(EntityDriveable driveable, float damage)
  {
    //In these cases, there was no collision, so don't damage this or the block
    if(box == null || dead)
      return 0;
    if(!driveable.canHitPart(type))
      return 0;
    //This part is immortal. Smash that block into oblivion
    if(maxHealth == 0)
      return damage;
    //As standard, take half damage and return the other half
    health -= (int)(damage / 2F);
    return damage / 2F;
  }
   
  /** Called by bullets that may have hit the plane
   * @return A bullet hit if it hit. Otherwise null */
  public DriveableHit rayTrace(EntityDriveable driveable, Vector3f origin, Vector3f motion)
  {
    if(box == null || health <= 0 || dead)
      return null;
    if(!driveable.canHitPart(type))
      return null;

    //Complicated. Will explain later. Someone remind me.
    /*
    boolean enteringX = coordIsEntering(origin.x, origin.x + motion.x, box.x / 16F, (box.x + box.w) / 16F);
    boolean enteringY = coordIsEntering(origin.y, origin.y + motion.y, box.y / 16F, (box.y + box.h) / 16F);
    boolean enteringZ = coordIsEntering(origin.z, origin.z + motion.z, box.z / 16F, (box.z + box.d) / 16F);
    boolean inX = coordIsIn(origin.x, origin.x + motion.x, box.x / 16F, (box.x + box.w) / 16F);
    boolean inY = coordIsIn(origin.y, origin.y + motion.y, box.y / 16F, (box.y + box.h) / 16F);
    boolean inZ = coordIsIn(origin.z, origin.z + motion.z, box.z / 16F, (box.z + box.d) / 16F);
    boolean hit = (enteringX && inY && inZ) || (inX && enteringY && inZ) || (inX && inY && enteringZ);
    */
       
    //We now have an AABB starting at box(x, y, z) and with dimensions box(w, h, d) and our ray in the same coordinate system
    //We are looking for a point at which the ray enters the box, so we need only consider faces that the ray can see. Partition the space into 3 areas in each axis
   
    //X - axis and faces x = box.x and x = box.x + box.w
    if(motion.x != 0F)
    {
      if(origin.x < box.x) //Check face x = o.x
      {
        float intersectTime = (box.x - origin.x) / motion.x;
        float intersectY = origin.y + motion.y * intersectTime;
        float intersectZ = origin.z + motion.z * intersectTime;
        if(intersectY >= box.y && intersectY <= box.y + box.h && intersectZ >= box.z && intersectZ <= box.z + box.d)
          return new DriveableHit(driveable, type, intersectTime);
      }
      else if(origin.x > box.x + box.w) //Check face x = o.x + d.x
      {
        float intersectTime = (box.x + box.w - origin.x) / motion.x;
        float intersectY = origin.y + motion.y * intersectTime;
        float intersectZ = origin.z + motion.z * intersectTime;
        if(intersectY >= box.y && intersectY <= box.y + box.h && intersectZ >= box.z && intersectZ <= box.z + box.d)
          return new DriveableHit(driveable, type, intersectTime);
      }
    }
   
    //Z - axis and faces z = box.z and z = box.z + box.d
    if(motion.z != 0F)
    {
      if(origin.z < box.z) //Check face z = box.z
      {
        float intersectTime = (box.z - origin.z) / motion.z;
        float intersectX = origin.x + motion.x * intersectTime;
        float intersectY = origin.y + motion.y * intersectTime;
        if(intersectX >= box.x && intersectX <= box.x + box.w && intersectY >= box.y && intersectY <= box.y + box.h)
          return new DriveableHit(driveable, type, intersectTime);
      }
      else if(origin.z > box.z + box.d) //Check face z = box.z + box.d
      {
        float intersectTime = (box.z + box.d - origin.z) / motion.z;
        float intersectX = origin.x + motion.x * intersectTime;
        float intersectY = origin.y + motion.y * intersectTime;
        if(intersectX >= box.x && intersectX <= box.x + box.w && intersectY >= box.y && intersectY <= box.y + box.h)
          return new DriveableHit(driveable, type, intersectTime);
      }
    }
   
    //Y - axis and faces y = box.y and y = box.y + box.h
    if(motion.y != 0F)
    {
      if(origin.y < box.y) //Check face y = o.y
      {
        float intersectTime = (box.y - origin.y) / motion.y;
        float intersectX = origin.x + motion.x * intersectTime;
        float intersectZ = origin.z + motion.z * intersectTime;
        if(intersectX >= box.x && intersectX <= box.x + box.w && intersectZ >= box.z && intersectZ <= box.z + box.d)
          return new DriveableHit(driveable, type, intersectTime);
      }
      else if(origin.y > box.y + box.h) //Check face x = box.y + box.h
      {
        float intersectTime = (box.y + box.h - origin.y) / motion.y;
        float intersectX = origin.x + motion.x * intersectTime;
        float intersectZ = origin.z + motion.z * intersectTime;
        if(intersectX >= box.x && intersectX <= box.x + box.w && intersectZ >= box.z && intersectZ <= box.z + box.d)
          return new DriveableHit(driveable, type, intersectTime);
      }
    }

    return null;
  }
 
  /** Called when the bullet decided that it hit this driveable part */
  public void hitByBullet(EntityBullet bullet)
  {
    //Perform damage code
    if(bullet != null)
    {
      health -= bullet.damage * bullet.type.damageVsDriveable;
      if(bullet.type.setEntitiesOnFire)
      {
        fireTime = 20;
        onFire = true;
      }
    }
  }
 
  /** Ray traces a single co-ordinate
   * But only returns true once upon entering the box, and not while in or exiting
   * @param start The start of the ray in this co-ordinate
   * @param end The end of the ray in this co-ordinate
   * @param min The start of the box in this co-ordinate
   * @param max The end of the box in this co-ordinate
   * @return true if the ray hits in this co-ordinate */
  private boolean coordIsEntering(float start, float end, float min, float max)
  {
    //Check to see if ray entered from the left hand side
    if(start < min && end >= min)
      return true;
    //Check to see if ray entered from the right hand side
    if(start > max && end <= max)
      return true;
    return false
  }
 
  /** Ray traces a single co-ordinate
   * Returns true if the ray is in the bounds at some point along its length
   * @param start The start of the ray in this co-ordinate
   * @param end The end of the ray in this co-ordinate
   * @param min The start of the box in this co-ordinate
   * @param max The end of the box in this co-ordinate
   * @return true if the ray hits in this co-ordinate */
  private boolean coordIsIn(float start, float end, float min, float max)
  {
    //Check to see if the start point is in
    if(start >= min && start <= max)
      return true;
    //Check to see if the end point is in
    if(end >= min && end <= max)
      return true;
    //Check to see if the start and end points are either side of the interval
    if(start < min && end > max)
      return true;
    if(end < min && start > max)
      return true;
    return false
  }

  public boolean attack(float damage, boolean fireDamage)
  {
    health -= damage;
    if(fireDamage)
    {       
      fireTime = 20;
      onFire = true;
    }
    return health <= 0;
  }
}
TOP

Related Classes of com.flansmod.common.driveables.DriveablePart

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.