/******************************************************************
  
  Module:  aigoal_attack.h
  
  Author: Borut Pfeifer
  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/
#ifndef AIGOAL_ATTACK_H
#define AIGOAL_ATTACK_H


//-------------------------------------------------------- Includes
#include "aigoal.h"

//
// cGoal_Attack - base attack behavior class
//
class cGoal_Attack : public cAiGoal
{
public:
  cGoal_Attack(tGameObjectID target);

  virtual eGoalType GetType(){return GOAL_ATTACK;};

  virtual void Enter();
  virtual void Exit();

  cGameObject* GetTarget();

protected:
  virtual bool MoveToAttackPosition(float speed) = 0; // true if we can attack
  virtual void AttackEnter() {}
  virtual void AttackExit() {}

  bool IsAttackDone();
  bool CheckAttackDelay(float time);
  bool CheckBlockOpportunity(float time);
  bool FindTarget(bool bHuntDown);

  tGameObjectID mTargetID;
  float         mAttackTime;
  float         mBlockTime;
  bool          mbTargetWasAttacking;
};

//
// cGoal_Melee - base *melee* behavior class
//
class cGoal_Melee : public cGoal_Attack
{
public:
  cGoal_Melee(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual bool MoveToAttackPosition(float speed);
  virtual void AttackExit();
};

//
// cGoal_MeleeSwarm - melee with positioning around target
//
class cGoal_MeleeSwarm : public cGoal_Melee
{
public:
  cGoal_MeleeSwarm(tGameObjectID target) : cGoal_Melee(target) {};

protected:
  virtual bool MoveToAttackPosition(float speed);

};

//
// cGoal_MeleeFlank - melee with advancing with
// teammates on sides of target
//
class cGoal_MeleeFlank : public cGoal_Melee
{
public:
  cGoal_MeleeFlank(tGameObjectID target);

protected:
  virtual bool MoveToAttackPosition(float speed);
  virtual void AttackExit();

  tGameObjectID mFlankPartnerID;
  bool          mbRequestFlanking;
};


//
// cGoal_MeleeChargeRetreat - melee + retreat after one attack
//
class cGoal_MeleeChargeRetreat : public cGoal_Melee
{
public:
  cGoal_MeleeChargeRetreat(tGameObjectID target);

  virtual void Update(float time);

protected:
  bool mbRetreating;
  float mRetreatTimer;
  cAIWanderSteering mWander;
};

//
// cGoal_MeleeWander - melee + randomwandering
//
class cGoal_MeleeWander : public cGoal_Melee
{
public:
  cGoal_MeleeWander(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual void AttackEnter();

  float mAttackTimer;
  cAIWanderSteering mWander;
};

//
// cGoal_MeleeEnrage - melee with a getting pissed state
//
class cGoal_MeleeEnrage : public cGoal_Melee
{
public:
  cGoal_MeleeEnrage(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual void AttackEnter();
  virtual bool MoveToAttackPosition(float speed);

private:
  bool mbEnraging;
  float mLastHealthPercent;
};

//
// cGoal_Kamikaze - run and blow up
//
class cGoal_Kamikaze : public cGoal_Melee
{
public:
  cGoal_Kamikaze(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual void AttackEnter();
  virtual void AttackExit();

  void Explode();
};

//
// cGoal_MeleeStealth - melee with invisiblity
//
class cGoal_MeleeStealth : public cGoal_Melee
{
public:
  cGoal_MeleeStealth(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual bool MoveToAttackPosition(float speed);
  virtual void AttackEnter();
  virtual void AttackExit();

  void SetInvisible(bool bEnable);

  bool mbStartedAttack;
  bool mbInvisible;
  bool mbWasAttacking;
  bool mTimerInvisible;
  float mInvisibleTimer;
};

//
// cGoal_MeleeStun - melee logic while others stun target
//
class cGoal_MeleeStun : public cGoal_Melee
{
public:
  cGoal_MeleeStun(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual void AttackEnter();
  virtual void AttackExit();

  bool IsThereAnotherStunner();

  bool mbCanIStun;
};

class cStatsProjectileMaster;
//
// cGoal_Ranged - base ranged combat class
//
class cGoal_Ranged : public cGoal_Attack
{
public:
  cGoal_Ranged(tGameObjectID target);

  virtual void Update(float time);

  static void RegisterTuningVariables();

  static float GetFleeDistance() { return smFleeDistance; }
  static float GetMaxFiringDistance() { return smMaxFiringDistance; }

protected:
  virtual void AttackEnter();
  virtual void AttackExit();

  void CalculateTargeting(SyVect3& aimLoc, float& heading, float& distance);
  bool IsFriendlyInWay(const SyVect3& targetLoc, SyVect3& avoidPos);

  virtual bool MoveToAttackPosition(float speed);

  static float smFleeDistance, smMaxFiringDistance;

  SyVect3 mLastFrameTargetLoc;
  SyVect3 mTargetAvgVelocity;
  const cStatsProjectileMaster* mpProjectileMasterStats;
};

//
// cGoal_RangedCircle - Archers will encircle you
//
class cGoal_RangedCircle : public cGoal_Ranged
{
public:
  cGoal_RangedCircle(tGameObjectID target);

protected:
  virtual bool MoveToAttackPosition(float speed);
};

//
// cGoal_RangedLine - Archers will form a line to shoot
//
class cGoal_RangedLine : public cGoal_Ranged
{
public:
  cGoal_RangedLine(tGameObjectID target);

protected:
  virtual void AttackEnter();
  virtual void AttackExit();
  virtual bool MoveToAttackPosition(float speed);
};

//
// cGoal_RangedStun - Firing projectiles that stun, 
//                    when they hit, rush in for melee.
//
class cGoal_RangedStun : public cGoal_Ranged
{
public:
  cGoal_RangedStun(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual void AttackExit();
};

//
// cGoal_RangedTeleport - Teleports when enemy too close
//
class cGoal_RangedTeleport : public cGoal_Ranged
{
public:
  cGoal_RangedTeleport(tGameObjectID target);

  virtual void Update(float time);

protected:
  virtual void AttackEnter();

  cAiLOSMemory mLOSTarget;
  bool mbFoundTeleport;
  float mTeleportHeading;
  float mTeleportTimer;
  float mTeleportTimeRandAdjust;
};

#endif
