/* XRACER (C) 1999-2000 Richard W.M. Jones <rich@annexia.org> and other AUTHORS
 *
 * This program is free software; 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Id: xracer-player.h,v 1.11 2000/03/19 23:48:47 rich Exp $
 */

#ifndef __xracer_player_h__
#define __xracer_player_h__

#include "xracer.h"
#include "xracer-craft.h"
#include "xracer-game.h"
#include "xracer-math.h"

/* This is the information we store about each player (pilot and
 * opponents). Do not access this structure directly. Use the
 * accessor functions defined below instead.
 */
struct xrPlayer
{
  /* As in xracer <= 0.94, the craft is modelled by three points
   * with springs between them. Point 0 is always the front point,
   * point 1 is the left back point and point 2 is the right back
   * point.
   */
  GLfloat posn[3][3];

  /* This is the position of the craft in the previous frame. */
  GLfloat old_posn[3][3];

  /* Each point exists in exactly one segment. */
  int seg[3];

  /* Segment in previous frame. */
  int old_seg[3];

  /* These are updated on each frame. */
  GLfloat eye_oobe[3], centre_oobe[3], up[3];
  GLfloat backline_midpoint[3];

  /* Current momentum (differential of position). */
  GLfloat momentum[3][3];

  /* Magnitude of forward thrust. */
  GLfloat thrust;

  /* This is either 1, or a multiple > 1 if we go over a faster spot. */
  GLfloat faster;

  /* Roll magnitude (< 0 left). */
  GLfloat roll;

  /* Pitch magnitude (< 0 up). */
  GLfloat pitch;

  /* Yaw magnitude (< 0 left). */
  GLfloat yaw;

  /* Strength of shield (range 0-1). */
  GLfloat shield;

  /* Keyboard position (range -1 to 1). */
  float keyboard_x, keyboard_y;

  /* External shield. */
  int has_external_shield;
  double external_shield_start_time;

  /* Autopilot. */
  int has_autopilot;
  double autopilot_start_time;

  /* Current powerup (or 0 if no powerup is held). */
  int powerup;

  /* These are used to determine the current lap and position in the race.
   * Note that laps stored here count from 0 to NR_LAPS - 1. However,
   * lap numbers returned by xrPlayerGetCurrentLap count from 1 to NR_LAPS.
   */
  int current_lap, displayed_current_lap;
  int start_segment, start_segment_minus_one;

  /* Time when the player started their current lap. */
  double start_of_lap_time;

  /* Lap times. */
  GLfloat *lap_time;

  /* Pointer to the craft description. */
  const struct xrCraft *craft;
};

/* The person at the controls is the pilot. Information about them
 * is stored here. Since there is only ever one pilot, this is a global
 * variable. Do not access this structure directly. Use the accessor
 * functions defined below instead.
 */
extern struct xrPlayer xrPilot;

/* In arcade mode (and possibly in network play mode), this is a list
 * of the drone players.
 */
extern struct xrPlayer *xrDrones;
extern int xrNrDrones;

/* In network play mode, this is a list of the other network players.
 * The xrPlayer structure is only partially complete for these
 * players.
 */
extern struct xrPlayer *xrNetworkPlayers;
extern int xrNrNetworkPlayers;

/* Functions. */
extern void xrPlayerInit (void);
extern void xrPlayerStartGame (int game_mode, int nr_laps);
extern void xrPlayerEndGame (void);
extern void xrPlayerUpdate (const struct xrGameControls *controls);

/* Inline structure accessors. */
extern int xrPlayerHasExternalShield (const struct xrPlayer *player);

extern inline int
xrPlayerHasExternalShield (const struct xrPlayer *player)
{
  return player->has_external_shield;
}

extern int xrPlayerHasAutoPilot (const struct xrPlayer *player);

extern inline int
xrPlayerHasAutoPilot (const struct xrPlayer *player)
{
  return player->has_autopilot;
}

/* This always returns the position of the midpoint of the back line. */
extern const GLfloat *xrPlayerGetPosition (const struct xrPlayer *player);

extern inline const GLfloat *
xrPlayerGetPosition (const struct xrPlayer *player)
{
  return player->backline_midpoint;
}

extern int xrPlayerGetSegment (const struct xrPlayer *player);

extern inline int
xrPlayerGetSegment (const struct xrPlayer *player)
{
  return player->seg[0];
}

/* Return the eye position, accounting for OOBE, if necessary. */
extern const GLfloat *xrPlayerGetCameraEye (const struct xrPlayer *player,
					    int oobe);

extern inline const GLfloat *
xrPlayerGetCameraEye (const struct xrPlayer *player, int oobe)
{
  return oobe ? player->eye_oobe : player->backline_midpoint;
}

/* Return the camera centre point, accounting for OOBE, if necessary. */
extern const GLfloat *xrPlayerGetCameraCentre (const struct xrPlayer *player,
					       int oobe);

extern inline const GLfloat *
xrPlayerGetCameraCentre (const struct xrPlayer *player, int oobe)
{
  return oobe ? player->centre_oobe : player->posn[0];
}

/* Return the camera up vector (this is unaffected by OOBE). */
extern const GLfloat *xrPlayerGetCameraUp (const struct xrPlayer *player);

extern inline const GLfloat *
xrPlayerGetCameraUp (const struct xrPlayer *player)
{
  return player->up;
}

extern int xrPlayerGetSpeed (const struct xrPlayer *player);

extern inline int
xrPlayerGetSpeed (const struct xrPlayer *player)
{
  return xrMagnitude (player->momentum[0]) * 500.;
}

extern int xrPlayerGetPowerup (const struct xrPlayer *player);

extern inline int
xrPlayerGetPowerup (const struct xrPlayer *player)
{
  return player->powerup;
}

/* Return the player's current lap, counting from 1. After the player has
 * completed the game, this can return NR_LAPS + 1, so beware.
 */
extern int xrPlayerGetCurrentLap (const struct xrPlayer *player);

extern inline int
xrPlayerGetCurrentLap (const struct xrPlayer *player)
{
  return player->displayed_current_lap + 1;
}

/* Return the player's current lap time. */
extern double xrPlayerGetCurrentLapTime (const struct xrPlayer *player);

extern inline double
xrPlayerGetCurrentLapTime (const struct xrPlayer *player)
{
  return xrCurrentTime - player->start_of_lap_time;
}

/* Return the lap time for a particular lap.
 * Note: the LAP argument starts counting from 1, and must be <= NR_LAPS.
 * This function does not return the current lap time.
 */
extern double xrPlayerGetLapTime (const struct xrPlayer *player, int lap);

extern inline double
xrPlayerGetLapTime (const struct xrPlayer *player, int lap)
{
  lap--;
  return player->lap_time[lap];
}

/* When debugging, these functions are used to alter some internal constants.*/
extern void xrPlayerDebugSnapshotSettings (void);
extern void xrPlayerDebugGravityUp (void);
extern void xrPlayerDebugGravityDown (void);
extern void xrPlayerDebugSpringDampingUp (void);
extern void xrPlayerDebugSpringDampingDown (void);
extern void xrPlayerDebugMomentumDampingUp (void);
extern void xrPlayerDebugMomentumDampingDown (void);
extern void xrPlayerDebugLevitateDistUp (void);
extern void xrPlayerDebugLevitateDistDown (void);
extern void xrPlayerDebugLevitateDampingUp (void);
extern void xrPlayerDebugLevitateDampingDown (void);

#endif /* __xracer_player_h__ */
