/******************************************************************
  
  Module:  animcontroller.h
  
  Author: Sean Craig
  
  Description: Based on input from intel classes (controller input
  or AI), update the currently playing animation.

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

#ifndef ANIMCONTROLLER_H
#define ANIMCONTROLLER_H

//-------------------------------------------------------- Includes
#include "SyTypes.h"
#include "SyMap.h"
#include "gameobj.h"
#include "rulepacket.h" // for eComboType
//-------------------------------------------------------- Typedefs
//---------------------------------------------- Class Declarations

class cGameObject;
// Variables anim controller uses to determine which animation
// to play.  Part of the public interface; just set the variables
// and the anim controller will take care of the rest.

typedef enum 
{
  AS_STAND,
  AS_COMBAT_IDLE,
  AS_RUN,
  AS_ATTACK_L,
  AS_ATTACK_H,
  AS_ATTACK_LL,
  AS_ATTACK_LH,
  AS_ATTACK_HL,
  AS_ATTACK_HH,
  AS_ATTACK_LLL,
  AS_ATTACK_LLH,
  AS_ATTACK_LHL,
  AS_ATTACK_LHH,
  AS_ATTACK_HLL,
  AS_ATTACK_HLH,
  AS_ATTACK_HHL,
  AS_ATTACK_HHH,
  AS_ATTACK_LLLL,
  AS_ATTACK_RANGED,
  AS_ATTACK_JUMP,
  AS_JUMP,
  AS_IN_AIR,
  AS_LAND,
  AS_DEATH,
  AS_HITREACT,    
  AS_BLOCK,
  AS_OVERRIDE,
  AS_SCRIPT,
  AS_RUN_JUMP,
  AS_RUN_IN_AIR,
  AS_RUN_LAND,
  AS_DODGE,
  AS_EMOTE_ANGER,
  AS_KNOCKBACK,
  AS_KNOCKBACK_IN_AIR,
  AS_KNOCKBACK_LAND,
  AS_KNOCKBACK_GETUP,
  AS_KNOCKFORWARD,
  AS_KNOCKFORWARD_IN_AIR,
  AS_KNOCKFORWARD_LAND,
  AS_KNOCKFORWARD_GETUP,
  AS_FIDGET,
  AS_ATTACK_JUMP_LAND,
  AS_CAST_SPELL_A,
  AS_CAST_SPELL_B,
  AS_CAST_SPELL_C,
  AS_CAST_SPELL_D,
  AS_PICKUP_PROP,
  AS_STAND_CARRY_PROP,
  AS_RUN_CARRY_PROP,
  AS_THROW_PROP,
  AS_THROW_CHARACTER,
  AS_THROWN_BY_CHARACTER,
  AS_PUTDOWN_PROP,
  AS_PUSH_PROP,
  AS_STUNNED,
  AS_FLIP_LEVER,
  AS_WALK_WITH_FACING,
  AS_WALKTO,
  AS_TURNTO,

  NUM_ANIM_STATES
} eAnimState;

class cAnimCharControllerInput 
{
public:
  cAnimCharControllerInput();    
  void Clear();

  float         mHeadingRequest; // direction of travel, in radians; 0 = south (0,0,1)
                // PI/4 (90 degrees) = west (-1,0,0)
  float         mSpeedRequest; // 0-1 with 1.0f being a full run in that direction


  bool          mAttackRequestL;  
  bool          mAttackRequestS;  
  bool          mAttackRequestRanged;  
  eComboType    mNPCComboOverride;

  tGameObjectID mTarget;          // target of attack
  float         mTargetHeading;   // if there is no target, turn to face this angle
  float         mTargetPitch;     // used by NPC's to aim downwards
  float         mTargetRange;     // used for range attacks, how far away to fire
  bool          mBlockRequest;    // true if a block is requested
  bool          mJumpRequest;     // true if a block is requested
  bool          mHitReact;        // true if a block is requested
  tGameObjectID mHitReactTarget;  // target of attack
  float         mHitReactTime;
  bool          mDeath;
  bool          mFall;
  float         mHeight;          // for determining when we hit the ground
  float         mYVel;            // Y velocity

  bool          mActionRequest;
  tGameObjectID mActionTarget;

  int32         mAnimationOverride; // override whatever animation is playing with this AnimHandle.
  bool          mOverrideCancelEnd; // stop the override as soon as the animation is finished
  bool          mOverrideCancelImmediate; // stop the override immediately
  bool          mOverrideSetLocation; // pop to animation location on end of anim

  int32         mScriptAnimID; // override whatever animation is playing with this AnimID.
  bool          mScriptAnimAllowHitReactions; // override whatever animation is playing with this AnimID.

  bool          mDodging;
  float         mDodgeDirection;  // angle in radians  

  bool          mEmoteAnger;      // Play angry animation

  bool          mbThrown;
  bool          mbFloating;

  bool          mbKnockback;
  bool          mbKnockforward;
  bool          mbKnockdown;
  SyVect3       mKnockbackVect;
  float         mKnockbackHeading;

  tGameID       mCastSpellID;
  eAnimState    mCastAnimSettingOverride;

  bool          mbKeepFacing; // used for strafing NPCs
  float         mFaceHeading; // used for strafing NPCs

  bool          mWalkTo;
  SyVect3       mWalkToDestination;
  float         mWalkToHeading;
  float         mWalkToSpeed;
  float         mWalkToTurnSpeed;
  bool          mWalkToClear;
};


class cAnimControllerInterface
{
public:
  virtual ~cAnimControllerInterface() {}

  virtual void            Init(cGameObject *owner)=0;
  virtual void            Reset()=0;
  virtual void            Exit()=0;
  virtual void            Update(float time)=0;
  virtual cGameObject*    GetOwner()=0;
  virtual void            EnterScope()=0; // called when a character enters scope (inside simulation bubble)
  virtual void            ExitScope()=0;; // called when an object leaves scope (outside simulation bubble)
  virtual bool            CheckForDelete()=0;
  virtual void            NetworkReceiveBroadcast(const char *state, int statelen)=0;
};


class cAnimCharControllerInterface : public cAnimControllerInterface
{
public:
  virtual ~cAnimCharControllerInterface();

  cAnimCharControllerInput*   GetInput(){return &mInput;};
  virtual float               GetDamageMultiplier(eComboType combo)=0;
  virtual float               GetStrikethroughMultiplier(eComboType combo)=0;
  virtual float               GetTargetRecoveryTime(eComboType combo)=0;
  virtual float               GetRange(eComboType combo)=0;
  virtual eAnimState          GetAnimState() const = 0;
  virtual const char *        GetAnimStateName() const=0;
  virtual const char *        GetAnimName(int32 animID) const=0;
  virtual int                 GetContactNode() const=0;


  bool                        IsIdle() const;
  bool                        IsAttacking() const;
  bool                        IsBlocking();
  bool                        IsInAir() const;
  bool                        IsKnockedInAir() const;
  bool                        IsCasting();
  bool                        IsGettingUp();
  virtual bool                IsDodging() = 0;

  virtual eComboType          GetComboType();
  virtual tGameID             GetComboSpellID(eComboType combo)=0;

  virtual bool                IsAnimStateActive() = 0;
  virtual int                 GetHitPriority() = 0;

  virtual float               GetAnimTime()=0;
  virtual float               GetActionFrameTime()=0;
  virtual float               GetAnimDuration()=0;
  virtual float               GetAnimSpeed()=0;

  virtual tGameObjectID       GetCarriedObject()=0;
  virtual void                RefreshTargeting(float heading, float pitch, float distance) = 0;

  static cAnimCharControllerInterface *Allocate();
  virtual int32               GetAnimHandle(tAnimIDValues animNum){return 0;};

  static bool                 IsHeavyCombo(eComboType combo);              
  static bool                 IsLightCombo(eComboType combo);              
  static eComboType           GetComboTypeFromAnimState(eAnimState anim);
  static eAnimState           GetAnimStateFromComboType(eComboType combo);
protected:

  cAnimCharControllerInterface(); // call the static function Allocate instead;

  cAnimCharControllerInput mInput;
};

class cAnimPropControllerInterface
{
public:
  typedef enum 
  {
    PAS_BASE = 1,
    PAS_DESTROY,
    PAS_ACTIVATE,
    PAS_DEACTIVATE,
    PAS_MISC,
    PAS_DAMAGED1,
    PAS_MISC2,
    PAS_MISC3,
    PAS_NUM_STATES
  } PropAnimState;

  virtual ~cAnimPropControllerInterface() {}

  virtual void            Init(cGameObject *owner)=0;
  virtual void            Reset()=0;
  virtual void            Update(float time)=0;
  virtual cGameObject*    GetOwner()=0;
  virtual void            NetworkReceiveBroadcast(const char *state, int statelen)=0;

  virtual void            ChangeAnimState(PropAnimState newState)=0;
  virtual PropAnimState   GetAnimState() const = 0;
  virtual const char *    GetAnimStateName() const=0;

  static cAnimPropControllerInterface *Allocate();
};



typedef int32 tAnimSetID;

class cAnimControllerSetting;  // variables that vary between animation sets; for example, attack frame and timing information...
class cAnimControllerSys
{
public:
  cAnimControllerSys();
  ~cAnimControllerSys();

  void Init();
  void Reload();
  cAnimControllerSetting  *Fetch(tAnimSetID id,int animstate);

protected:
  static void RegisterTuningVariables();

  SyVector<cAnimControllerSetting *>  mSettings;

};
//------------------------------------------- Function Declarations

// todo : move these somewhere else (SyMath.h?)
float AngleDifference(float end, float start ); // end-start
float AngleNormalize(float angle);
//--------------------------------------------------------- Globals
//------------------------------------------------ Inline Functions

#endif
