//-----------------------------------------------------------------------------
//
//  $Logfile:: /Quake 2 Engine/Sin/code/game/ctf_turret.cpp                    $
// $Revision:: 14                                                             $
//   $Author:: Aldie                                                          $
//     $Date:: 3/19/99 5:50p                                                  $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/ctf_turret.cpp                        $
// 
// 14    3/19/99 5:50p Aldie
// Added MINLIGHT
// 
// 13    3/19/99 5:49p Aldie
// Added minlight
// 
// 12    3/19/99 5:13p Aldie
// Made turret non-droppable
// 
// 11    3/17/99 3:55p Aldie
// Incremental CTF update
// 
// 10    3/12/99 6:14p Markd
// added precaching and increased damages on heligun
// 
// 9     3/11/99 1:46p Aldie
// Fix movement of turrets
// 
// 8     3/05/99 5:51p Markd
// made vehicles respawn in CTF, fixed up turrets a bit more
// 
// 7     3/05/99 5:10p Markd
// Fixed turrets being able to shoot themselves
// 
// 6     2/26/99 7:42p Markd
// Fixed turrets some more
// 
// 5     2/26/99 5:53p Markd
// Fixed up turrets a lot more
// 
// 4     2/23/99 5:56p Markd
// 
// 3     2/22/99 5:45p Aldie
// Removed stray ;
// 
// 2     2/19/99 7:49p Markd
// implemented turret for CTF
// 
// 1     2/19/99 6:03p Markd
// 
// DESCRIPTION:
// CTF turret, usable turret
// 

#include "g_local.h"
#include "vehicle.h"
#include "ctf_turret.h"
#include "heligun.h"
#include "player.h"


CLASS_DECLARATION( DrivableVehicle, CTFTurret, "ctf_turret" );

ResponseDef CTFTurret::Responses[] =
	{
	   { &EV_Use,						      ( Response )&CTFTurret::DriverUse },
		{ NULL, NULL }
	};

CTFTurret::CTFTurret()
	{
   takedamage = DAMAGE_YES;
	setModel( "ctf_turret.def" );
   modelIndex( "ctf_turretgun.def" );
   modelIndex( "view_ctf_turretgun.def" );
   setOrigin( origin - Vector( "0 0 30") );
   drivable = false;
	setMoveType( MOVETYPE_NONE );
   setSize( "-24 -24 -64", "24 24 0" );
   edict->s.renderfx |= RF_MINLIGHT;
	}

void CTFTurret::DriverUse
	(
	Event *ev
	)

	{
   Entity * old_driver;

   old_driver = driver;
   DrivableVehicle::DriverUse( ev );
   if ( old_driver != driver )
      {
      if ( driver )
         {
         setSolidType( SOLID_NOT );
         takedamage = DAMAGE_NO;
         hideModel();
         }
      else
         {
         setSolidType( SOLID_BBOX );
         takedamage = DAMAGE_YES;
         showModel();
         }
      }
	setMoveType( MOVETYPE_NONE );
	}

#define MAX_PITCH 45
float CTFTurret::SetDriverPitch
	(
	float pitch
	)
   {
   if ( pitch > 180 )
      {
      if ( pitch < 360 - MAX_PITCH )
         {
         pitch = 360 - MAX_PITCH;
         }
      }
   else
      {
      if ( pitch > MAX_PITCH )
         {
         pitch = MAX_PITCH;
         }
      if ( pitch < -MAX_PITCH )
         {
         pitch = -MAX_PITCH;
         }
      }
   return pitch;
   }

CLASS_DECLARATION( HeliGun, CTFTurretGun, "ctf_weapon_turretgun" );

ResponseDef CTFTurretGun::Responses[] =
	{
		{ NULL, NULL }
	};

CTFTurretGun::CTFTurretGun
   (
   )
	
   {
	SetModels( "ctf_turretgun.def", "view_ctf_turretgun.def" );
	}

void CTFTurretGun::Shoot
	(
	Event *ev
	)

	{
   FireBullets( 1, "20 20 20", 48, 64, DAMAGE_BULLET, MOD_CTFTURRET, false );
	NextAttack( 0 );
	}

qboolean CTFTurretGun::IsDroppable
	(
	void
	)

   {
	return false;
   }


//
// CTF turret which is lagged but has angle limits set on it.
//
CLASS_DECLARATION( DrivableVehicle, CTFDrivableTurret, "ctf_fixedturret" );

ResponseDef CTFDrivableTurret::Responses[] =
	{
	   { &EV_Use,						      ( Response )&CTFDrivableTurret::DriverUse },
		{ NULL, NULL }
	};

CTFDrivableTurret::CTFDrivableTurret()
	{
	ClassDef		*cls;

   takedamage = DAMAGE_YES;
	setModel( "ctf_fixedturret.def" );
   setOrigin( origin - Vector( "0 0 30") );
   baseangles = angles;

	shotdamage = G_GetFloatArg( "shotdamage", 48 );
	maxpitch = G_GetFloatArg( "maxpitch", 30 );
	maxyaw = G_GetFloatArg( "maxyaw", 75 );

	cls = getClass( "Sentient" );
	if ( cls )
      {
		gunholder = ( Sentient * )cls->newInstance();
      gunholder->hideModel();
      }
	cls = getClass( "BulletWeapon" );
	if ( cls )
      {
		gun = ( BulletWeapon * )cls->newInstance();
   	gun->SetModels( "ctf_fixedturret.def", "ctf_fixedturret.def" );
      gun->SetOwner( gunholder );
      gun->hideModel();
      }

   setSize( "-24 -24 -64", "24 24 0" );
   lastbutton = -1;
   entertime = -1;
   exittime = -1;
	setMoveType( MOVETYPE_NONE );
   edict->s.renderfx |= RF_MINLIGHT;
	}

void CTFDrivableTurret::Postthink
	(
	void
	)

	{
   Vector temp;
   Vector diff;

   // make sure we don't move
   velocity = vec_zero;

   if ( cmd_angles[ 0 ] > maxturnrate )
      {
      cmd_angles[ 0 ] = maxturnrate;
      }
   else if ( cmd_angles[ 0 ] < -maxturnrate )
      {
      cmd_angles[ 0 ] = -maxturnrate;
      }
   if ( cmd_angles[ 1 ] > maxturnrate )
      {
      cmd_angles[ 1 ] = maxturnrate;
      }
   else if ( cmd_angles[ 1 ] < -maxturnrate )
      {
      cmd_angles[ 1 ] = -maxturnrate;
      }

   temp = angles + cmd_angles;

   diff = temp - baseangles;
   diff.x = angledist( diff.x );
   diff.y = angledist( diff.y );
	gi.dprintf( "diff x%5.2f y%5.2f\n", diff.x, diff.y );

   if ( diff.x > maxpitch )
      {
      temp.x = baseangles.x + maxpitch;
      }
   else if ( diff.x < -maxpitch )
      {
      temp.x = baseangles.x - maxpitch;
      }

   if ( maxyaw < 180 )
      {
      if ( diff.y > maxyaw )
         {
         temp.y = baseangles.y + maxyaw;
         }
      else if ( diff.y < -maxyaw )
         {
         temp.y = baseangles.y - maxyaw;
         }
      }

	setAngles( temp );


	if ( driver )
		{
      Vector i,j,k;
      Player * player;

	   i = Vector( orientation[ 0 ] );
	   j = Vector( orientation[ 1 ] );
	   k = Vector( orientation[ 2 ] );

      player = ( Player * )( Sentient * )driver;
		player->setOrigin( worldorigin + i * driveroffset[0] + j * driveroffset[1] + k * driveroffset[2] );
      if ( drivable )
         {
         player->velocity = vec_zero;
         player->setAngles( angles );
         player->SetViewAngles( angles );
         player->SetDeltaAngles();
         }
		}

   CheckWater();
   WorldEffects();

   // save off last origin
   last_origin = worldorigin;

	if ( !driver && !velocity.length() && groundentity && !( watertype & CONTENTS_LAVA ) )
		{
		flags &= ~FL_POSTTHINK;
      if ( drivable )
   	   setMoveType( MOVETYPE_NONE );
		}
   if ( driver )
      {
      if ( buttons & BUTTON_ATTACK )
         {
         if ( !lastbutton )
            {
            lastbutton = 1;
            RandomAnimate( "fire", NULL );
            }
         Fire();
         }
      else if ( buttons & BUTTON_USE )
         {
         Event * event;

         if ( level.time > ( entertime + 0.5f ) )
            {
            event = new Event( EV_Use );
            event->AddEntity( driver );
            ProcessEvent( event );
            }
         }
      else
         {
         if ( lastbutton )
            {
            lastbutton = 0;
            RandomAnimate( "idle", NULL );
            }
         }
      }
   }

void CTFDrivableTurret::Fire
	(
	void
	)

	{
   setSolidType( SOLID_NOT );
   gunholder->setOrigin( origin );
   gunholder->setAngles( angles );
   gun->FireBullets( 1, "20 20 20", shotdamage, shotdamage * 1.5f, DAMAGE_BULLET, MOD_CTFTURRET, true );
   setSolidType( SOLID_BBOX );
   }

float CTFDrivableTurret::SetDriverPitch
	(
	float pitch
	)
   {
   return pitch;
   }

qboolean CTFDrivableTurret::Drive
	(
	usercmd_t *ucmd
	)

	{
	if ( !driver || !driver->isClient() )
		{
		return false;
		}
   else
      {
      DrivableVehicle::Drive( ucmd );
      ucmd->buttons &= ~BUTTON_ATTACK;
      ucmd->buttons &= ~BUTTON_USE;
      return true;
      }
	}

void CTFDrivableTurret::DriverUse
	(
	Event *ev
	)

	{
   Entity * old_driver;

   if ( !driver && ( level.time < ( exittime + 0.5f ) ) )
      return;

   cmd_angles[ 0 ] = 0;
   cmd_angles[ 1 ] = 0;
   cmd_angles[ 2 ] = 0;
   buttons = 0;
   lastbutton = -1;
   setMoveType( MOVETYPE_NONE );
   RandomAnimate( "idle", NULL );

   old_driver = driver;

   DrivableVehicle::DriverUse( ev );

   if ( old_driver != driver )
      {
      if ( driver )
         {
         entertime = level.time;
         }
      else
         {
         exittime = level.time;
         }
      }
	}
