/******************************************************************
  
  Module:  stats.h
  
  Author: Sean Craig
  
  Description:  Contains statistics (like strength, max hit points,
  cur hit points, etc) for game objects.  

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

#ifndef STATS_H
#define STATS_H

//-------------------------------------------------------- Includes
#include "SyPropObject.h"
#include "nameid.h"
#include "rule.h"
#include "item.h"
#include "class.h"

//-------------------------------------------------------- Typedefs
//---------------------------------------------- Class Declarations
class cGameObject;

//static const int STATS_CLASSID           =  ;
//static const int STATSCHARACTER_CLASSID  =  0xFFFF2002;
static const int STATSPROP_CLASSID       =  0xFFFF2003;
static const int STATSITEM_CLASSID       =  0xFFFF2004;
static const int STATSPROJECTILE_CLASSID =  0xFFFF2005;

class cStats : public SyPropObject
{
public:

  typedef enum 
  {
    ACTIVATE_NONE,
    ACTIVATE_OPEN,
    ACTIVATE_TALKTO,
    ACTIVATE_IGNITE,
    ACTIVATE_TURN,
    ACTIVATE_FLIP,
    ACTIVATE_PICKUP,
    ACTIVATE_SAVEGAME,
  } eActivateType;

  cStats();
  virtual                     ~cStats(){};

  /* Property Class Support */
  static int                  InitPropClass();
  static SyPropObject*        Creator();

  // public interface

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

  virtual void                Reset(){};

  virtual void                SetOwner(cGameObject *owner){mOwner = owner;};
  virtual void                Update(float time){};
  virtual void                SetMaster(const char *master_name){};

  virtual int                 GetHealth(){return 0;};
  virtual int                 GetBlock(){return 0;};

  virtual bool                IsPushable(){return false;};
  virtual void                CalcRangedDefend(cDamagePacket* event);
  virtual void                ApplyDamage(cDamagePacket *event){};
  virtual void                ProcessRulePacket(cRulePacket *event){};

  virtual bool                IsDead(){return false;};

  virtual const char *        GetModel(){return NULL;};
  virtual tGameID             GetAnimSet(){return 0;};

  virtual void                NetworkReceiveBroadcast(const char *packet,int size){}; // the owner of this object has broadcast an update
  virtual void                NetworkReceiveMessage(const char *packet,int size){}; // someone is sending a message to this local object

  virtual const char *        GetMasterName(){return "Unknown";};
  virtual eActivateType       GetActivateType(){return ACTIVATE_NONE;};
  virtual void                GetActivateString(SyString *string);
  virtual void                SetActivateType(eActivateType type){};
  virtual void                GetTranslatedName(SyString *string);

  virtual void                Activate(cGameObject *activater){};
  virtual void                Die(tGameObjectID killer){};

  static const int            mCLASSID = 0xFFFF2001;
protected:

  cGameObject *               mOwner;
  
};


// to add a field: 
// 1) add it to db, export db
// 2) add default value in constructor
// 3) add to parser in stats.cpp
// 4) add to wiki page description

class cStatsCharacterMaster 
{
public:
  cStatsCharacterMaster();
  ~cStatsCharacterMaster();

  cNameID                     mID;
  char *                      mModel; // pathname of model to use
  char *                      mNameString;
  char *                      mDescriptionString;

  tGameID                     mClass;
  int                         mLevel;

  tGameID                     mAnimSet;

  tGameID                     mNaturalMelee;
  tGameID                     mNaturalRanged;
  tGameID                     mNaturalArmor;
  tGameID                     mTreasureSet;
  
  // melee/AI params
  float                       mAttackDelay;
  float                       mBlockDelay;
  float                       mMovementSpeed;
  float                       mCloseDistance;
  float                       mAccuracy;
  float                       mCollisionRadius;
  float                       mActivationRadius;
  float                       mDefendRadius;
  char                        mNPCBehaviorType;
  char                        mNPCFaction;

  static const int            MAX_ABILITIES = 6;
  tGameID                     mAbility[MAX_ABILITIES];

};

class cStatsCharacter : public cStats
{
public:
                              cStatsCharacter();
  virtual                     ~cStatsCharacter(){};

  /* Property Class Support */
  static int                  InitPropClass();
  static SyPropObject*        Creator();

  // public interface

  virtual void                Reset();
  virtual void                SetOwner(cGameObject *owner);
  virtual void                SetMaster(const char *newmaster);
  virtual void                Update(float time);

  virtual void                Init();
  virtual const char *        GetModel();
  virtual tGameID             GetAnimSet(){return mpMaster->mAnimSet;};
  virtual bool                IsPushable(){return true;};


  // called when our animation hits an attack frame
  virtual void                AttackFrame(tGameObjectID target,eComboType attackIndex);
  virtual bool                TargetInAttackRange(cGameObject *target, eComboType attackIndex);

  virtual void                CalcRangedAttack(cDamagePacket* event);
  virtual void                ApplyDamage(cDamagePacket *event);
                          
  virtual void                ActivateObject(tGameObjectID target);

  virtual void                ProcessRulePacket(cRulePacket *event);
  const cStatsCharacterMaster *GetMaster(){return mpMaster;};
  const cCharacterClass                *GetClass(){return mpClass;};
  const cCharacterLevel                *GetLevel(){return mpLevel;};
  virtual bool                IsDead() {return mbDead;};


  virtual int                 GetHealth();
  virtual int                 GetBlock();

  int                         CalcMaxHealth();
  int                         CalcMaxMana();
  int                         CalcHealthRegen();
  int                         CalcManaRegen();
  int                         CalcMaxBlock();
  int                         CalcBlockRegen();

  float                       GetAttackDelay();
  float                       GetBlockDelay();
  float                       GetMovementSpeed();
  float                       GetCloseDistance();
  float                       GetAccuracy();
  char                        GetBehaviorType();
  char                        GetFaction();

  tGameID                     GetProjectileTypeID();

  static const SyPropID PropId_MasterName     = 0x1000;
  static const SyPropID PropId_CurDamage    = 0x1001;
  static const SyPropID PropId_Dead         = 0x1002;

  virtual void                NetworkReceiveBroadcast(const char *packet,int size); // the peer which owns this object has broadcast an update
  bool                        NetworkHasAuthorityOver(cGameObject *obj); // returns if this obj can directly modify obj's internal state

  bool                        HasCondition(const char *name);
  void                        AddCondition(cRule *condition);
  void                        RemoveCondition(const char *name);


  void                        Shoot(const SyVect3& targetPos);
  void                        Shoot(cGameObject *target);
  void                        Shoot(const SyVect3& start, float heading, float distance);
  virtual const char *        GetMasterName(){return mMasterName.AsChar();};
  virtual cStats::eActivateType  GetActivateType();
  virtual void                SetActivateType(eActivateType type);
  virtual void                Die(tGameObjectID killer);

  static const int            mCLASSID = 0xFFFF2002;
protected:
  void                        Regenerate(float time);


  SyString                    mMasterName;
  const cStatsCharacterMaster *mpMaster;                                      
  const cCharacterClass                *mpClass;
  const cCharacterLevel                *mpLevel;

  int                         mCurDamage;
  int                         mCurPowerLoss;
  int                         mCurBlockLoss;
  float                       mHealthRegenFrac; 
  float                       mPowerRegenFrac; 
  float                       mBlockRegenFrac; 

  cRuleContainer              mAbilities;   // change on levelup (permanent)
  cRuleContainer              mConditions; // change over time
  
  bool                        mbDead;
  eActivateType               mActivateType;
};


class cStatsItem : public cStats  // item in world, on ground
{
public:
                              cStatsItem();
  virtual                     ~cStatsItem();
  
  /* Property Class Support */
  static int                  InitPropClass();
  static SyPropObject*        Creator();

  // public interface

  virtual void                Init();
  virtual void                Update(float time);

  void                        CreateItem(const char *master_name);
  void                        SetItem(cItem *item); // transfers ownership
  cItem *                     GetItem(){return mpItem;};
  cItem *                     TakeItem(); // destroys object.  Transfers ownership of item ptr.
  virtual void                SetMaster(const char *master_name);
  virtual const char *        GetModel();
  virtual void                NetworkReceiveMessage(const char *packet,int size); // someone is sending a message to this object i own
  virtual void                NetworkReceiveBroadcast(const char *packet,int size); // the owner peer of this object has broadcast an update
  virtual const char *        GetMasterName();
  virtual eActivateType       GetActivateType() {return ACTIVATE_PICKUP;};
  virtual void                Activate(cGameObject *activater);

  static const int            mCLASSID = 0xFFFF2004;

protected:
  cItem*                      mpItem;
};

class cStatsProjectileMaster 
{
public:
  cStatsProjectileMaster();
  ~cStatsProjectileMaster();

  cNameID                     mID;
  char *                      mModel; // pathname of model to use

  float                       mSpeed; // meters/sec
  float                       mSeeking; // seeking ability
  float                       mGravity; // degree to which this object is affect by gravity 
  bool                        mSpins;  // like a thrown dagger (otherwise flies, like an arrow)
  bool                        mPenetrates;  // whether it stops when it hits an enemy
  float                       mCollisionRadius;
  char *                      mAddCondition; // condition type to add to hit target
  int                         mAddConditionTimeMS; // time for condition to last
  int                         mNum;
  float                       mMaxArc;
  float                       mAcceleration;
  float                       mOrbiting;
};

class cStatsProjectile : public cStats  // item in world, on ground
{
public:
                              cStatsProjectile();
  virtual                     ~cStatsProjectile();
  
  /* Property Class Support */
  static int                  InitPropClass();
  static SyPropObject*        Creator();

  // public interface

  virtual void                Init();
  virtual void                Update(float time){};

  virtual void                SetMaster(tGameID projID);
  const cStatsProjectileMaster * GetMaster() const {return mpMaster;};
  virtual const char *        GetModel();
  void                        SetWeapon(tGameID id){mWeaponID = id;};
  tGameID                     GetWeapon(){return mWeaponID;};
  virtual const char *        GetMasterName(){return mpMaster->mID.GetName();};

  virtual bool                IsDead() {return mbDead;};
  virtual void                Die(tGameObjectID killer);

  static const int            mCLASSID      = 0xFFFF2005;
  static const SyPropID PropId_MasterID     = 0x1000;
protected:
  tGameID                     mMasterID;
  const cStatsProjectileMaster *mpMaster;
  tGameID                     mWeaponID;
  bool                        mbDead;

};


class cStatsPropMaster 
{
public:
  cStatsPropMaster();
  ~cStatsPropMaster();

  cNameID                     mID;
  int                         mMaxHealth;
  char *                      mModelName; // pathname of model to use
  tGameID                     mAnimSet;

  tGameID                     mTreasureSet;
  tGameID                     mDebris;
  bool                        mbActivates;
  bool                        mbExplodes;
  bool                        mbPushable;
  char *                      mScriptName;
};             

class cStatsProp : public cStats
{
public:
  cStatsProp();
  virtual                     ~cStatsProp(){};

  /* Property Class Support */
  static int                  InitPropClass();
  static SyPropObject*        Creator();

  // public interface
  virtual void                Reset();
  virtual void                SetOwner(cGameObject *owner);
  virtual void                SetMaster(const char *master_name);
  virtual void                Update(float time);

  virtual void                Init();
  virtual const char*         GetModel();
  virtual tGameID             GetAnimSet(){return mpMaster->mAnimSet;};
  virtual bool                IsPushable(){return mpMaster->mbPushable;};


  virtual void                ApplyDamage(cDamagePacket *event);
  virtual void                ProcessRulePacket(cRulePacket *event);

  const cStatsPropMaster*     GetMaster(){return mpMaster;};
  virtual bool                IsDead() {return mbDead;};
  virtual int                 GetHealth();

  int                         CalcMaxHealth();

  bool                        HasCondition(const char *name);
  void                        AddCondition(cRule *condition);
  void                        RemoveCondition(const char *name);

  virtual void                NetworkReceiveBroadcast(const char *packet,int size); // the peer which owns this object has broadcast an update
  bool                        NetworkHasAuthorityOver(cGameObject *obj); // returns if this obj can directly modify obj's internal state

  virtual const char *        GetMasterName(){return mMasterName.AsChar();};
  virtual eActivateType       GetActivateType(){return mActivateType;} ;
  virtual void                SetActivateType(eActivateType type){mActivateType = type;};
  virtual void                Die(tGameObjectID killer);

  static const int            mCLASSID      = 0xFFFF2003;
  static const SyPropID PropId_MasterName   = 0x1000;
  static const SyPropID PropId_CurDamage    = 0x1001;
  static const SyPropID PropId_Dead         = 0x1002;

protected:
  SyString                    mMasterName;
  const cStatsPropMaster     *mpMaster;
  int                         mCurDamage;
  int                         mCurState;
  bool                        mbDead;

  cRuleContainer              mConditions; // change over time
  eActivateType               mActivateType;
};



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

void RegPropClasses_Stats();
void Stats_RegisterTuningVariables();
//--------------------------------------------------------- Globals
//------------------------------------------------ Inline Functions

#endif
