PlayerCharacter.java :  » Game » yarg-roguelike » creid » mythos » Java Open Source

Java Open Source » Game » yarg roguelike 
yarg roguelike » creid » mythos » PlayerCharacter.java
/*********************************************************************************
* PlayerCharacter.java
* Purpose: Defines additional info used by the game for the player character
*
* Copyright 2010 by Christopher Reid
*********************************************************************************/

package creid.mythos;

import creid.mythos.graphics.GameColors;

public class PlayerCharacter extends Creature
{
  //-----------------------------------------------------
  // Constants
  //-----------------------------------------------------
  
  //player move mask
  static final int PLAYER_MOVES = Actor.WALK + Actor.DROWN;
  
  //player abilities
  static final int PLAYER_OPS = Operations.OPEN_DOOR + Operations.CLOSE_DOOR;
  
  //Size of player's items
  public final static int PLAYER_INVENTORY_SIZE = 20;
  
  //-----------------------------------------------------
  // Attributes
  //-----------------------------------------------------

  //Our next action
  public Action nextAction;
  
  //-----------------------------------------------------
  // Constructor
  //-----------------------------------------------------
  
  public PlayerCharacter(String name)
  {
    super(
      "PLAYER",          //key
      name,                //Name
      Creature.CS_PERSON,         //Symbol
      GameColors.WHITE,         //color
      10,                 //Base Health
      0,                 //BodyParts stat
      0,                  //Coordination stat
      0,                  //Mind stat
      Actor.NORMAL_SPEED,       //Base Speed
      PLAYER_MOVES,          //Mobile mask
      PLAYER_OPS,            //Terrain op mask
      10,                  //Perception
      Mythos.FACTION_PLAYER,     //faction
      0l,                //turn of creation
      0,                  //level, class brings up to 1
      Entity.NEVER_SPAWN,    //rarity
      true,                //has body/equipment slots
      false                //has items, will be manually set next
    );
    
    mobuls = 0;
    itemActions = new ItemAction(this, ItemAction.PICKUP + ItemAction.DROP);
    inventory = new Inventory(this, PLAYER_INVENTORY_SIZE);
    nextAction = null;
    calcStats();
  }

  //-------------------------------------------------
  // calcStats:
  // calculate all modifiers and stats
  // Should be called whenever something happens that
  // alters the creature's abilities in any way
  // i.e. stat boost, equipping an item, spell effect, etc 
  //-------------------------------------------------

  public void calcStats()
  {
    calcPlayerMeleeHit();
    calcPlayerMeleeDamage();
    calcPlayerEvasion();
    calcPlayerArmor();
    calcPlayerRangedDamage();
  }

  void calcPlayerArmor()
  {
    //protection from worn items
    for (int i = 0; i < bodyParts.length; i++)
      if (bodyParts[i].hasEquippedItem())
      {
        Item item = bodyParts[i].equippedItem;
        
        if (item.hasProperty("armor"))
          armor += item.getNProperty("armor").value;
      }
  }

  void calcPlayerEvasion()
  {
    defense = coordination;
  }

  void calcPlayerMeleeHit()
  {
    meleeAttack.hit = Math.round(((float)(coordination + body)) / 2f);
  }

  protected void calcPlayerMeleeDamage()
  {
    int damage = body;
    
    //damage increased by using a weapon (or rings of damage, spiked armor, etc)
    for (int i = 0; i < bodyParts.length; i++)
      if (bodyParts[i].hasEquippedItem())
      {
        Item item = bodyParts[i].equippedItem;
        
        if (item.type == Item.I_WEAPON && item.hasProperty("damage"))
          damage += item.getNProperty("damage").value;
      }
      
    meleeAttack.damage = damage;
  }
  
  protected void calcPlayerRangedDamage()
  {
    int damage = 0;
    
    if (bodyParts[BodyPart.HUM_QUIVER].hasEquippedItem())
    {
      Item missile = bodyParts[BodyPart.HUM_QUIVER].equippedItem; 
      //impact = ranged damage
      if (missile.hasProperty(Property.RANGED_DAMAGE))
      damage = missile.getNProperty(Property.RANGED_DAMAGE).value;
      
      //unbalanced weapons can still cause some damage
      if (damage == 0 && missile.type == Item.I_WEAPON)
        damage += Math.max(1, missile.getNProperty(Property.MELEE_DAMAGE).value / 5);
      
      if (bodyParts[BodyPart.HUM_MAIN_HAND].hasEquippedItem())
      {
        Item weapon = bodyParts[BodyPart.HUM_MAIN_HAND].equippedItem; 
        
        if (weapon.type == Item.I_LAUNCHER && missile.hasProperty("ammo") &&
            weapon.getSProperty("ammo").value.equals(
                missile.getSProperty("ammo").value))
        {
          //TODO:setEffectiveRangedDamage(damage + weapon.getProperty("impact").getIVal());
          
        }
      }
    }
    
    //TODO:setEffectiveRangedDamage(damage);
  }
  
  @Override
  public void takeDamage(int damage, int type, String cause)
  {
    super.takeDamage(damage, type, cause);
  }
  
  //-----------------------------------------------------
  //checkLOS
  // trace a path from the player to the destination to
  // see if there is a valid LOS to it
  //-----------------------------------------------------
  public boolean checkLOS(Location destination)
  {
    return checkLOS(location, destination);
  }
  
  boolean checkLOS(Location source, Location destination)
  {
    boolean inLOS = false;
    
    boolean loop = true;
    while (loop)
    {
      //this grid is in LOS
      source.inLOS = true;
      
      //stop if this grid block further LOS, or if this is the destination
      if (source.terrain.opaque)
        loop = false;
      
      //calculate distance from target
      int diffX = destination.x - source.x;
      int diffY = destination.y - source.y;

      //we have arrived;
      if (diffX == 0 && diffY == 0)
      {
        inLOS = true;
        loop = false;
        break;
      }
      
      //Get the sign of the diffs
      int dx = 0;
      if (diffX > 0)
        dx++;
      else if (diffX < 0)
        dx--;
      
      int dy = 0;
      if (diffY > 0)
        dy++;
      else if (diffY < 0)
        dy--;
      
      //Is the line x-dominant
      if (Math.abs(diffX) - 2 * Math.abs(diffY) >= 0)
        dy = 0;
      //y-dominant
      else if (Math.abs(diffY) - 2 * Math.abs(diffX) >= 0)
        dx = 0;
      
      //move to the next square
      int x = source.x + dx;
      int y = source.y + dy;
      
      source = destination.map.map[x][y];
    }

    return inLOS;
  }
  
  //-----------------------------------------------------
  // updateLOS
  // fix square's inLOS flags after a player move
  //-----------------------------------------------------
  public void updateLOS()
  {
    Level map = location.map;
    
    for (int x = 0; x < map.xSize; x++)
    {
      for (int y = 0; y < map.ySize; y++)
      {
        Location cell = map.map[x][y];
        
        if (Mythos.DEBUG_SHOW_LEVEL)
          cell.updateDisplay();
        
        //basic check: is it even possible this square could be in LOS
        if (x < location.x - perception -1 ||
            x > location.x + perception + 1 ||
            y < location.y - perception - 1 ||
            y > location.y + perception + 1)
        {
          cell.inLOS = false;        
        }
        //otherwise see if we can trace a line from the player to the square
        else
        {
          if(checkLOS(cell))
          {
            cell.inLOS = true;
            cell.updateDisplay();
          }
          else
            cell.inLOS = false;
        }
      }
    }
  }
  
  //-----------------------------------------------------
  // shoot
  // Throw or shoot an item at a target
  //-----------------------------------------------------
  
  public boolean shoot()
  {
    //Turn the quivered item into a projectile
    Item item = bodyParts[BodyPart.HUM_QUIVER].takeOffOneItem();

    Projectile missile = new Projectile(item, 0 /*getEffectiveRangedHit()*/, //TODO 
        0/*getEffectiveRangedDamage()*/, location, //TODO
        Mythos.display.infoPanel.targetPanel.target.location, Actor.NORMAL_SPEED, 
        Projection.TRANSIENT, Mythos.game.turn - 1);
    
    Mythos.logger.debugLog("Created projectile " + missile.name);
    
    //start the projectile on our square
    location.projection = missile;
              
    //Add projectile to action queue
    Mythos.game.actionQueue.add(missile);
    
    //Warn the player if they are out of ammo
    if (!bodyParts[BodyPart.HUM_QUIVER].hasEquippedItem())
      Mythos.logger.messageLog("Your quiver is emptied!");

    return true;
  }
  
  //-----------------------------------------------------
  // die
  // override normal die method; if player dies the
  // game is over
  //-----------------------------------------------------
  @Override
  public void die(String cause)
  {
    Mythos.logger.messageLog("You were killed by " + cause);
    Mythos.game.state = Mythos.STATE_GAME_OVER;
  }
  
  //-----------------------------------------------------
  // freeAction
  // an action took no time, decrement next turn to ensure
  // player immediately gets to go again
  //-----------------------------------------------------
  public void freeAction()
  {
    nextAction = new FreeAction(this);
  }
  
  //-----------------------------------------------------
  // chooseAction
  //Instead of running AI, just use the player-selected
  //action
  //
  // Note that this method is blocking; it will wait until
  // nextAction is set to something (via player command)
  //-----------------------------------------------------
  
  public Action chooseAction()
  {
    Mythos.logger.debugLog("Now accepting player commands");
    Mythos.game.input.inputAllowed = true;
    while(nextAction == null)
      try
      {
        Thread.sleep(50);
      }
      catch (Exception ex)
      {
        System.err.println(ex);
      }
      
    Mythos.game.input.inputAllowed = false;
    Action act = nextAction;
    nextAction = null;
    Mythos.logger.debugLog("Got player command");
    return act;
  }
  
  //----------------------------------------------------------------
  // push
  // Try to move/operate/melee on an adjacent square
  //----------------------------------------------------------------
  
  public void push(int x, int y)
  {
    Location target = location;
    target = target.map.map[target.x + x][target.y + y];
    
    Action action = new Movement(move);
    action.target = location;

    //If we are staying put, just do the move and be done with it 
    if (x != Actor.STAY || y != Actor.STAY)
      //Is the target square occupied?
      if (target.isOccupied())
      {
        //Is the creature friendly?
        if (target.getOccupant().faction == faction)
        {
          //TODO: Place swapping
          //Do a swap instead
          //SwapAction swap
          //result =
          Mythos.logger.messageLog("You stop to avoid hitting the " + target.getOccupant().name);
        }
        else //Clobberin' Time
        {
          //Do a melee action instead
          //mover.meleeAttack(to.getOccupant(), Mythos.game.getTurn());
          action = new MeleeAttack(meleeAttack);
          action.target = target.getOccupant();
        }
      }
      //Is the target square passable?
      else if(target.terrain.isPassable(move))
        action.target = target;
      else if(target.terrain.isOperable(ops))
      {
        action = new Operations(ops);
        action.target = target;
      }
    
    nextAction = action;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.