/******************************************************************
  
  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"
#include "../animdefs.h"
#include "../animController.h"
#include "../item.h"

class cStatsProjectileMaster;

//
// 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 Update(float time);
  virtual void Exit();

  cGameObject* GetTarget();

  void BreakTargetBlock();

  static void RegisterTuningVariables();

protected:
  static int smMaxMeleeAttackers;
  static float smMaxRangedFiringDistance;

  virtual void AttackEnter() {}
  virtual void AttackExit() {}

  virtual void MeleeEnter() {}
  virtual void MeleeExit() {}
  virtual void RangedEnter() {}
  virtual void RangedExit() {}

  virtual void UpdateMelee(float time);
  virtual void UpdateRanged(float time);
  virtual void UpdateDelayed(float time);
  virtual bool MoveToMeleePosition(float speed); // true if we can attack
  virtual bool MoveToRangedPosition(float speed); // true if we can attack
  virtual void RefreshTargeting();


  void AttackMelee();
  virtual void AttackRanged(float heading, float pitch, float distance);
  void EquipItem(eEquipSlot slot);
  bool IsAttackDone();
  bool CheckAttackDelay(float time);
  bool CheckBlockOpportunity(float time, bool bInsideCloseDist);
  bool FindTarget(bool bHuntDown);
  bool GetRangedAttack(float& speed, float& gravMult, bool& bProjectileIgnoresAllies);
  bool IsAllyInWay(const SyVect3& targetLoc, SyVect3& avoidPos);
  void CalculateRangedTargeting(SyVect3& aimLoc,
                                float& heading,
                                float& pitch,
                                float& distance,
                                bool bFindExplodingProps);

  tGameObjectID mTargetID;
  eAnimState    mPrevAnimState;
  int           mNumAttacks;
  float         mAttackDelayTimer;
  bool          mbInsideCloseDist;
  bool          mbInsideMeleeRange;
  tGameID       mCurAttackAbilityID;

  float mMoveTimer;
  bool  mbUseMoveTimer;
  bool  mbBreakTargetBlock;

  SyVect3 mLastFrameTargetLoc;
  SyVect3 mTargetAvgVelocity;
  tGameObjectID mTargetExplodingPropID;
};

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

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

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

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

  tGameObjectID mFlankPartnerID;
  bool          mbRequestFlanking;
};


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

  virtual void Update(float time);

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

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

  virtual void Update(float time);

protected:
  virtual void AttackEnter();

  float mAttackTimer;
  cAIWanderSteering mWander;
};


//
// cGoal_AttackSentinel - attack with no/movement
//
class cGoal_AttackSentinel : public cGoal_Attack
{
public:
  cGoal_AttackSentinel(tGameObjectID target) : cGoal_Attack(target) {};

protected:
  virtual void UpdateDelayed(float time);
  virtual bool MoveToMeleePosition(float speed);
  virtual bool MoveToRangedPosition(float speed);
};

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

  virtual void Update(float time);

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

//
// cGoal_AttackStealth - attack with invisiblity
//
class cGoal_AttackStealth : public cGoal_Attack
{
public:
  cGoal_AttackStealth(tGameObjectID target);

  virtual void Update(float time);

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

  void SetInvisible(bool bEnable);

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

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

  virtual void Update(float time);

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

  bool IsThereAnotherStunner();
  bool DoesAbilityStun(tGameID abilityID);  

  bool mbCanIStun;
};


//
// cGoal_AttackCircle - Attackers will encircle you
//
class cGoal_AttackCircle : public cGoal_Attack
{
public:
  cGoal_AttackCircle(tGameObjectID target);

protected:
  virtual void MeleeEnter();
  virtual void MeleeExit();
  virtual void UpdateMelee(float time);
  virtual void UpdateDelayed(float time);
  virtual bool MoveToMeleePosition(float speed);
  virtual bool MoveToRangedPosition(float speed);

  bool FindNeighboringAttackerHeadings(float& lesserHeading, float& greaterHeading);

  enum State
  {
    MELEE_STATE_NONE,
    MELEE_STATE_ATTACK,
    MELEE_STATE_RETREAT,
    MELEE_STATE_CIRCLE_RIGHT,
    MELEE_STATE_CIRCLE_LEFT,
  };

  State mState;
  float mCircleToAttackTimer;
  float mCircleRepeatTimer;
  SyVect3 mRetreatDir;
};

//
// cGoal_AttackLine - Attackers will form a line to shoot
//
class cGoal_AttackLine : public cGoal_Attack
{
public:
  cGoal_AttackLine(tGameObjectID target);

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

class cSpellMaster;

class cGoal_AttackArea : public cGoal_Attack
{
public:
  cGoal_AttackArea(tGameObjectID target);

protected:
  virtual void AttackRanged(float heading, float pitch, float distance);
  virtual void UpdateRanged(float time);
  virtual bool MoveToRangedPosition(float speed);

  bool SelectRadiusPosition(SyVect3& targetPos);
  bool SelectWallPosition(SyVect3& targetPos);

  const cSpellMaster* GetSpell();

  cAILOSMemory mTargetAreaLOS;
  float        mLOSWaitTime;
  bool         mbFindNewArea;
};

class cGoal_DestroyProp : public cGoal_Attack
{
public:
  cGoal_DestroyProp(tGameObjectID propID): cGoal_Attack(propID) {};
  virtual void Update(float time);

protected:
};

#endif
