/******************************************************************
  
  Module:  Intel.h
  
  Author: Sean Craig
  
  Description:   Classes for deciding what a game character should
  do, either through AI, controller input or network update

  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/

#ifndef INTEL_H
#define INTEL_H

//-------------------------------------------------------- Includes
#include <stddef.h>
#include "SyPropObject.h"
#include "gameobj.h"
#include "ai.h"
#include "animdefs.h"
//-------------------------------------------------------- Typedefs
//---------------------------------------------- Class Declarations



class cIntel: public SyPropObject
{
public:
  cIntel();
  virtual ~cIntel(){};                

  /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();
  static const int     mCLASSID        =  0xFFFF1001;

  // public interface

  virtual void Init(){};
  virtual void Exit(){};
  virtual void Reset(){};

  virtual void Open(){};

  void SetOwner(cGameObject *owner){mOwner = owner;};
  virtual void Update(float time)=0;
  bool GetLocal(){return mLocal;}; // whether or not this is object is owned by this machine
  void SetLocal(bool local) {mLocal = local;};
  virtual tGameObjectID PickAttackTarget(eComboType combo){return ID_NONE;};
  virtual tGameObjectID PickAttackTargetRanged(){return ID_NONE;};
  virtual tGameObjectID PickActionTarget(){return ID_NONE;};

  virtual void          OnAttacked(tGameObjectID attacker,int damage){};
  virtual void          OnDeath() {};
  virtual void          OnWallCollision(const SyVect3& normal) {};

  virtual bool          CheckForDelete(){return false;};

  virtual bool          IsTargetable(cGameObject* pTarget) {return false;}
  virtual bool          IsFriendly(cGameObject* pTarget) {return false;}

  virtual void          OnWake() {}   // called when object comes inside update scope radius
  virtual void          OnSleep() {}  // called when object leaves update scope radius

protected:

  cGameObject       *mOwner;
  bool               mLocal;
};


class cIntelEntity : public cIntel
{
public:
  cIntelEntity();

  /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();
  static const int     mCLASSID  =  0xFFFF1002;

  virtual void          Init();
  virtual void          Reset(); // for example, when respawning
  virtual void          Update(float time){};

  virtual tGameObjectID PickAttackTarget(float dir, float max_distance);
  virtual tGameObjectID PickActionTargetDir(float dir);

  virtual const SyVect3 &GetStartLocation(){return mStartLocation;};

  virtual bool          IsTargetable(cGameObject* pTarget);
  virtual bool          IsFriendly(cGameObject* pTarget);

protected:
  SyVect3               mStartLocation; 
};

class cIntelPlayer: public cIntelEntity
{
public:
  cIntelPlayer(); 
  virtual ~cIntelPlayer(){};

  /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();
  static const int     mCLASSID  =  0xFFFF1003;

  void                 SetController(int controllerID){mControllerID = controllerID;};

  // public interface
  virtual void          Update(float time);
  virtual tGameObjectID PickAttackTarget(eComboType combo);
  virtual tGameObjectID PickActionTarget() { return mActionTarget;};
  virtual tGameObjectID PickAttackTargetRanged();

  float                GetControllerHeading(float time);
  float                GetControllerMagnitude();

  float                GetRightControllerHeading(float time);
  float                GetRightControllerMagnitude();

  void                 UpdateActionTarget();

protected:
  float                _ControllerHeading(float time,float forward,float right);
  float                _ControllerMagnitude(float forward, float right);

  int           mControllerID; // which controller controls this player (if local)
  static float  mDeadZone; // dead zone in center of controller, as a fraction
  float         mHeldDownTime;
  float         mPrevHeading;
  tGameObjectID mActionTarget;
};


class cIntelNPC: public cIntelEntity
{
public:
  cIntelNPC();
  virtual ~cIntelNPC();
  /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();
  static const int     mCLASSID     =  0xFFFF1004;

  // public interface
  virtual void          Init();
  virtual void          Exit();
  virtual void          Reset();

  void                  TurnTo(const SyVect3 &lookAt);
  void                  GoTo(const SyVect3 &dest, float speed = 0.75f);
  void                  AttackMelee(cGameObject *target, float distance);
  void                  AttackRanged(cGameObject *target);
  void                  AttackRanged(float heading, float range);
  void                  Stop();
  void                  Block(float blockTime);
  void                  StopBlock();
  void                  Jump();
  void                  Dodge(const SyVect3& dir);

  virtual void          Update(float time);
  virtual void          OnAttacked(tGameObjectID attacker,int damage);
  virtual void          OnWallCollision(const SyVect3& normal);

  virtual bool          IsTargetable(cGameObject* pTarget);

  bool                  IsMoving();
  bool                  IsAvoiding();

  cGameObject*          FindClosestObject(float minDist, float maxDist, 
                                          bool bIsNPC, bool bIsPlayer, bool bIsProp,
                                          bool bIsFriendly = false,
                                          bool bIsDamaged = false);

  cAiInterface*         GetAi() { return mAi; }

  static void RegisterTuningVariables();

  virtual void          OnWake();   // called when object comes inside update scope radius
  virtual void          OnSleep();  // called when object leaves update scope radius

protected:
  void                  UpdateMove(float time);
  void                  UpdateBlock(float time);
  void                  CalcAvoidDir(const SyVect3& hitNormal);
  void                  RequestLOSToGoal();

  cAiInterface         *mAi;

  // keep track of movement requests
  bool                  mbIsMoving;
  SyVect3               mGoalPos;
  float                 mMoveSpeed;

  // keep track of obstacle avoidance while moving
  bool                  mbIsAvoiding;
  bool                  mbHasLOSToGoal;
  SyVect3               mAvoidDir;
  int                   mLOSTicketToGoal;
  float                 mAvoidTimer;

  bool                  mbIsStuck;
  float                 mStuckTimer;
  SyVect3               mPrevLocation;
  bool                  mbStuckAvoid;

  float                 mBlockTimer;
};
 

class cIntelNone: public cIntel
{
public:
  cIntelNone();
  virtual ~cIntelNone(){};

  /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();
  static const int     mCLASSID    =  0xFFFF1005;

  // public interface


  virtual void Update(float time);
};

class cIntelProp: public cIntel
{
public:
  cIntelProp();
  virtual ~cIntelProp(){};

  /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();
  static const int     mCLASSID    =  0xFFFF1006;

  // public interface
  virtual void Update(float time);
  virtual void Open();

  virtual void OnDeath();
  virtual bool CheckForDelete();
private:
  bool mbOpened;
  bool mbDelete;
};

class cIntelProjectile: public cIntelEntity
{
public:
  cIntelProjectile();
  virtual ~cIntelProjectile(){};

  /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();
  static const int     mCLASSID =  0xFFFF1007;

  // public interface
  virtual void Update(float time);

  void SetTarget(tGameObjectID);

  virtual bool          IsTargetable(cGameObject* pTarget);

private:
  tGameObjectID mTargetID;
};

//------------------------------------------- Function Declarations

void RegPropClasses_Intel();
//--------------------------------------------------------- Globals
//------------------------------------------------ Inline Functions

#endif
