/******************************************************************
  
  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;
class cAbilityMaster;

//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:

  // NOTE THAT CORRESPONDING ENUM IN TITAN.INC HAS TO MATCH THIS ONE
  typedef enum 
  {
    ACTIVATE_NONE,
    ACTIVATE_OPEN,
    ACTIVATE_TALKTO,
    ACTIVATE_IGNITE,
    ACTIVATE_TURN,
    ACTIVATE_FLIP,
    ACTIVATE_PICKUP,  // goes straight to inventory if item, if prop we pick it up
    ACTIVATE_PUTDOWN, 
    ACTIVATE_PUSH, 
    ACTIVATE_SAVEGAME,
  } eActivateType;
  

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

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

  // public interface

  virtual void                Init(){};
  virtual void                PostInit(){}; // called after net create
  virtual void                Exit(){};

  virtual void                Reset();
  virtual void                Summon() {};

  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                IsPhysicsPushable(){return false;};
  virtual void                CalcRangedAttack(cDamagePacket* event);
  virtual void                CalcRangedDefend(cDamagePacket* event);
  virtual void                ApplyDamage(cDamagePacket *event) {};
  virtual void                ApplyHealing(cCalcPacket *event) {};
  virtual void                ApplyManaCost(cCalcPacket *event) {}
  virtual void                ProcessRulePacket(cRulePacket *event){};

  virtual bool                IsDead(){return false;};

  virtual const char *        GetModelName(){return NULL;}
  virtual const char *        GetRagdollName(){return NULL;}

  virtual const char *        GetModelOverride(){return "";}
  virtual float               GetModelScale(){return 1.0f;}
  virtual const char *        GetFileName(){return NULL;}
  virtual tGameID             GetAnimSet(){return 0;}

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

  virtual tGameID             GetRace() const { return ID_NONE; }
  virtual const char *        GetMasterName() const {return "Unknown";}
  virtual eActivateType       GetActivateType() const {return ACTIVATE_NONE;}
  virtual float               GetActivateRadius() const {return 2.0f;}
  virtual void                GetActivateString(SyString *string);
  virtual void                SetActivateType(eActivateType type){}
  virtual void                SetActivateStringOverride(uint32 stringID){mActivateStringOverride = stringID;}
  virtual void                T4_SetContext(char8 slot){}

  virtual void                Activate(cGameObject *activater);
  virtual void                Die(tGameObjectID killer){}
  virtual const char *        GetScriptName(){return "";}

  virtual void                SetHitScriptCallback( const char* ) {}
  virtual const char*         GetHitScriptCallback() const    { return ""; }

  virtual void                SetDeathScriptCallback( const char* ) {}
  virtual const char*         GetDeathScriptCallback() const  { return ""; }

  virtual bool                QueryFlag(const char* flagName) { return false; }
  virtual bool                HasCondition(const char* name) { return false; }
  virtual void                AddCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID, float duration, tGameID effectID, int param1 = 0, int param2 = 0);
  virtual void                RemoveCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID);
  virtual void                RemoveConditions(tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID);

  virtual void                Value_Set(tGameID id,int32 value);
  virtual int32               Value_Get(tGameID id);

  static const int            mCLASSID = 0xFFFF2001;

protected:
  virtual void                _PerformActivate(cGameObject *obj);

  virtual void                _PerformAddCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID, float duration, tGameID effectID, int param1 = 0, int param2 = 0) {}
  virtual void                _PerformRemoveCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID) {}
  virtual void                _PerformRemoveConditions(tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID) {}

  SyMap<tGameID, int32>       mValues;
  cGameObject *               mOwner;
  uint32                      mActivateStringOverride;
};


// 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();

  void                        changeNameString(const char *name);

  cNameID                     mID;
  tGameID                     mModelDataID;
  uint32                      mNameString;
  uint32                      mDescriptionString;

  tGameID                     mClass;
  int                         mLevel;
  int                         mLevelDiff;

  tGameID                     mAnimSet;

  tGameID                     mNaturalMelee;
  tGameID                     mNaturalRanged;
  tGameID                     mNaturalSpell;
  tGameID                     mNaturalArmor;
  tGameID                     mTreasureSet;
  
  // AI params
  float                       mMovementSpeed;
  float                       mCloseDistance;
  float                       mMeleeRange;
  float                       mAccuracy;
  float                       mCollisionRadius;
  float                       mActivationRadius;
  char                        mNPCBehaviorType;
  char                        mNPCFaction;

  tGameID                     mBlockBehavior;
  tGameID                     mAbilitySet;
  tGameID                     mRace;
  char *                      mScriptName;
  float                       mScale;
  float                       mWeight;

  static const int MAX_ATTACHMENTS = 7;

  SyString                    mAttachmentModelNames[MAX_ATTACHMENTS];
};

class cStatsBlockBehavior 
{
public:
  enum PlayerBlockStrategyType
  {
    PBS_IGNORE,
    PBS_SWITCH_TARGETS,
    PBS_PULL_BACK,
    PBS_CIRCLE,
    PBS_TRY_DIFFERENT_ATTACK,
    PBS_NUM_STRATEGIES
  };

  enum NPCBlockStrategyType
  {
    NPCBS_AFTER_HIT,
    NPCBS_NEXT_HIT,
    NPCBS_AFTER_ATTACK,
    NPCBS_ON_CLOSE,
    NPCBS_WHILE_CLOSE,
    NPCBS_NUM_STRATEGIES
  };

  enum BlockAttackTypes
  {
    BLOCK_ATTACK_LIGHT,
    BLOCK_ATTACK_HEAVY,
    BLOCK_ATTACK_RANGED,
    BLOCK_ATTACK_MAX
  };
  cStatsBlockBehavior();

  cNameID                     mID;

  int                         mBlockPercentChance[BLOCK_ATTACK_MAX];
  int                         mDodgePercentChance[BLOCK_ATTACK_MAX];
  int                         mRipostePercentChance[BLOCK_ATTACK_MAX];
  int                         mNumHitsBeforeBlock;
  PlayerBlockStrategyType     mPlayerBlockStrategy;
  NPCBlockStrategyType        mNPCBlockStrategy;

  float                       mBlockHoldTime;
  float                       mBlockReactTime;
};

class cStatsAbilitySet 
{
public:
  enum UsageCondition
  {
    ABILITY_CONDITION_ANY,
    ABILITY_CONDITION_MELEE_ATTACK,
    ABILITY_CONDITION_RANGED_ATTACK,
    ABILITY_CONDITION_BLOCK_BREAK,
    ABILITY_CONDITION_LOW_HEALTH,
    ABILITY_CONDITION_ALLY_WOUNDED,
    ABILITY_CONDITION_ALLY_DEAD,
    ABILITY_CONDITION_BUFF_ALLY_IN_COMBAT,
    ABILITY_CONDITION_MAX_TYPES
  };


  cStatsAbilitySet();
  ~cStatsAbilitySet();

  bool GetAbility(UsageCondition condition, tGameID curAbilityID, tGameID* pNextAbilityID) const;
  bool GetDelay(tGameID abilityID, float* pDelay) const;
  bool GetNextAbility(tGameID curAbilityID, tGameID* pNextAbilityID) const;
  bool HasAbilityForCondition(UsageCondition condition) const;

  struct Entry
  {
    Entry();

    UsageCondition   mCondition;
    float            mDelay;
    int              mWeight;
    tGameID          mAbilityID1;
    tGameID          mAbilityID2;
    tGameID          mAbilityID3;
  };

  cNameID                     mID;
  SyVector<Entry>             mEntries;
};

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);

          void                SetProperName(const char *properName);
  const SyString&             GetProperName() const { return mProperName; }
  virtual void                T4_SetContext(char8 slot);

  virtual void                Update(float time);

  virtual void                Init();
  virtual void                PostInit(); // called after net create
  virtual void                Summon();
  virtual const char *        GetModelName();
  virtual const char *        GetRagdollName();

  virtual float               GetModelScale();
  virtual const char *        GetFileName();
  virtual tGameID             GetAnimSet(){return mpMaster->mAnimSet;};
  virtual bool                IsPhysicsPushable(){return true;};


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

  virtual void                ApplyDamage(cDamagePacket *event);
  virtual void                ApplyHealing(cCalcPacket *event);
  virtual void                ApplyManaCost(cCalcPacket *event);
          void                AddEssence(cCalcPacket *event);
                          
  virtual bool                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 tGameID             GetRace() const;
  virtual int                 GetHealth();
  virtual int                 GetBlock();
          int                 GetMana();
          int                 GetEssence();

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

  int                         CalcAttackPower();
  int                         CalcMagicPower();
  int                         CalcMeleeDefense();
  int                         CalcSpellDefense();


  void                        AddHealth(int points);
  void                        AddMana(int points);
  void                        AddAttackPower(int points);
  void                        AddMagicPower(int points);
  void                        AddMeleeDefense(int points);
  void                        AddSpellDefense(int points);

  int                         GetBonusPoints(){return mBonusPoints;};
  int                         GetBonusHealth(){return mBonusHealth;};
  int                         GetBonusMana(){return mBonusMana;};
  int                         GetBonusAttackPower(){return mBonusAttackPower;};
  int                         GetBonusMagicPower(){return mBonusMagicPower;};
  int                         GetBonusMeleeDefense(){return mBonusMeleeDefense;};
  int                         GetBonusSpellDefense(){return mBonusSpellDefense;};

  const cStatsBlockBehavior*  GetBlockBehavior();
  const cStatsAbilitySet*     GetAbilitySet();
  const cAbilityMaster*       GetAbility(tGameID abilityID);
  void                        OverrideAbilitySet(tGameID abilitySetID);

  float                       GetAIMovementSpeed();
  float                       GetAICloseDistance();
  float                       GetAIMeleeRange();
  float                       GetAIAccuracy();
  char                        GetAIBehaviorType();
  char                        GetFaction();

  tGameID                     GetProjectileTypeID();

  void                        DisableHealthManaEssenceDrop(bool bDisable) { mbDisableDrop = bDisable; }

  static const SyPropID PropId_MasterName     = 0x1000;
  static const SyPropID PropId_CurDamage      = 0x1001;
  static const SyPropID PropId_Dead           = 0x1002;
  static const SyPropID PropId_AbilityIDs     = 0x1003;
  static const SyPropID PropId_AbilityRanks   = 0x1004;
  static const SyPropID PropId_CurLevel       = 0x1005;
  static const SyPropID PropId_BonusPoints    = 0x1006;
  static const SyPropID PropId_BonusHealth    = 0x1007;
  static const SyPropID PropId_BonusMana      = 0x1008;
  static const SyPropID PropId_BonusAttackPower = 0x1009;
  static const SyPropID PropId_BonusMagicPower  = 0x100A;
  static const SyPropID PropId_BonusMeleeDefense= 0x100B;
  static const SyPropID PropId_BonusSpellDefense= 0x100C;

  virtual bool                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 bool                QueryFlag(const char* flagName);
  virtual bool                HasCondition(const char* name);

  const SyVector<uint32>&     GetAbilityIDs() { return mAbilityIDs; }
  const SyVector<uint32>&     GetAbilityRanks() { return mAbilityRanks; }
  bool                        BuyAbility(tGameID abilityID, int rank);
  int                         GetNumAvailableAbilities();
  void                        GetAvailableAbility(int index, tGameID& abilityID, int& rank);
  int                         GetAbilityPoints() { return mAbilityPoints; }
  bool                        HasAbilityCombo(eComboType combo);

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


  bool                        CanLift(cGameObject* pProp);

  void                        LevelUp();
  void                        SetLevel(int lvl);
  void                        UpdateNPCLevels();
  int                         GetExperience()  { return mExperience; }
  void                        AwardExperience(int xp);
  static void                 AwardKillExperience(cGameObject* pDeadObj);
  static void                 AwardGroupExperience(cGameObjectRegistry* pRegistry, int xp);
  void                        HitReact(tGameObjectID attacker, int dmgAmt, float recoveryTime, bool bBlocked);
  virtual const char *        GetScriptName();

  virtual void                SetHitScriptCallback( const char* );
  virtual const char*         GetHitScriptCallback() const    { return mScriptCallback_onHit.AsChar(); }

  virtual void                SetDeathScriptCallback( const char* );
  virtual const char*         GetDeathScriptCallback() const  { return mScriptCallback_onDeath.AsChar(); }

  static const int            mCLASSID = 0xFFFF2002;
protected:
  virtual void                _PerformAddCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID, float duration, tGameID effectID, int param1 = 0, int param2 = 0);
  virtual void                _PerformRemoveCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID);
  virtual void                _PerformRemoveConditions(tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID);

  void                        Regenerate(float time);



  SyString                    mMasterName;
  const cStatsCharacterMaster *mpMaster;                                      

  cStatsCharacterMaster       *mpCustomMaster;

  const cCharacterClass       *mpClass;
  const cCharacterLevel       *mpLevel;

  int                         mCurDamage;
  int                         mCurManaLoss;
  int                         mCurBlockLoss;
  float                       mHealthRegenFrac; 
  float                       mManaRegenFrac; 
  float                       mBlockRegenFrac; 
  int                         mEssence;

  cRuleContainer              mAbilityRules;   // change on levelup (permanent)
  cRuleContainer              mConditionRules; // change over time
  
  int                         mExperience;
  int                         mAbilityPoints;

  bool                        mbDead;
  bool                        mbDisableDrop;
  eActivateType               mActivateType;
  
  SyVector<uint32>            mAbilityIDs;   // list of hashed ability names
  SyVector<uint32>            mAbilityRanks;   // list of ranks (same size as mAbilityIDs
  tGameID                     mAbilitySetOverrideID;

  int                         mCurLevel;
  SyString                    mProperName; 
  int                         mBonusPoints;
  int                         mBonusHealth; // from leveling
  int                         mBonusMana; // from leveling
  int                         mBonusAttackPower;
  int                         mBonusMagicPower;
  int                         mBonusMeleeDefense;
  int                         mBonusSpellDefense;
  float                       mDeadTime;

  SyString                    mScriptCallback_onHit;
  SyString                    mScriptCallback_onDeath;
};


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 *        GetModelName();
  virtual const char *        GetFileName();
  virtual const char *        GetMasterName() const;
  virtual eActivateType       GetActivateType() const {return ACTIVATE_PICKUP;}
  virtual void                T4_SetContext(char8 slot);

  static const int            mCLASSID = 0xFFFF2004;

protected:
  virtual void                _PerformActivate(cGameObject *obj);

  cItem*                      mpItem;
};

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

  cNameID                     mID;
  tGameID                     mModelDataID;

  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
  bool                        mPinCushion;  // whether it sticks on the enemy it hits
  float                       mCollisionRadius;
  int                         mNum;
  float                       mMaxArc;
  float                       mAcceleration;
  float                       mOrbiting;
  float                       mMeteor;
  float                       mVerticalWave;
  float                       mDamageMultiplier;
  float                       mHomingRange; 
  tGameID                     mCreationFXID;
  tGameID                     mAttachFXID;
  tGameID                     mImpactFXSetID;
  tGameID                     mImpactSoundSetID;
};

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 *        GetModelName();
  virtual const char *        GetFileName();
  void                        SetWeapon(tGameID id){mWeaponID = id;}
  tGameID                     GetWeapon(){return mWeaponID;}
  virtual const char *        GetMasterName() const {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:
  enum MobilityType
  {
    PROP_IMMOBILE,
    PROP_PUSHABLE,
    PROP_LIFTABLE,
    PROP_SIMULATABLE,
    PROP_NUM_MOBILITY_TYPES
  };

  cStatsPropMaster();
  ~cStatsPropMaster();

  cNameID                     mID;
  int                         mMaxHealth;
  tGameID                     mModelDataID;
  char *                      mName; 
  tGameID                     mAnimSet;

  tGameID                     mTreasureSet;
  MobilityType                mMobility;
  float                       mWeight;
  float                       mThrownDamageMultiplier;
  int                         mNumThrows;
  tGameID                     mThrowSpellID;
  float                       mSpeedThreshold;
  char *                      mScriptName;
  uint32                      mT4_NameID; // for in-game name
  float                       mScale;
  float                       mActivateRadius;
  char                        mFaction;  // used for determining enemies/allies when casting trap spells
  float                       mPhysicsMass;
  float                       mPhysicsFriction;
};             

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 *        GetModelName();
  virtual const char*         GetModelOverride();
  virtual float               GetModelScale();
  virtual const char *        GetFileName();
  virtual tGameID             GetAnimSet(){return mpMaster->mAnimSet;};
  virtual bool                IsPhysicsPushable(){return false;};
  virtual bool                IsPushable(){return cStatsPropMaster::PROP_PUSHABLE == mpMaster->mMobility;};
  virtual bool                IsLiftable(){return cStatsPropMaster::PROP_LIFTABLE == mpMaster->mMobility;};
  virtual bool                IsSimulatable(){return cStatsPropMaster::PROP_LIFTABLE == mpMaster->mMobility || cStatsPropMaster::PROP_SIMULATABLE == mpMaster->mMobility;};
  virtual const char *        GetScriptName(){return mpMaster->mScriptName;};

  virtual void                SetHitScriptCallback( const char* );
  virtual const char*         GetHitScriptCallback() const    { return mScriptCallback_onHit.AsChar(); }

  virtual void                SetDeathScriptCallback( const char* );
  virtual const char*         GetDeathScriptCallback() const  { return mScriptCallback_onDeath.AsChar(); }

  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();

  virtual bool                HasCondition(const char* name);

  virtual bool                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() const {return mMasterName.AsChar();}
  virtual eActivateType       GetActivateType() const {return mActivateType;}
  virtual float               GetActivateRadius() const;
  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;
  static const SyPropID PropId_ActivateType = 0x1003;
  static const SyPropID PropId_ModelOverride= 0x1004;
  virtual void                T4_SetContext(char8 slot);


protected:
  virtual void                _PerformAddCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID, float duration, tGameID effectID, int param1 = 0, int param2 = 0);
  virtual void                _PerformRemoveCondition(const char* name, tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID);
  virtual void                _PerformRemoveConditions(tGameID spellID, tGameObjectID sourceID, tGameID itemMasterID);


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

  cRuleContainer              mConditions; // change over time
  eActivateType               mActivateType;

  SyString                    mModelOverride;
  SyString                    mModelOverrideFullPath;

  SyString                    mScriptCallback_onHit;
  SyString                    mScriptCallback_onDeath;
};

class cStatsMarker: public cStats 
{
public:
  cStatsMarker();
  virtual                     ~cStatsMarker();

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

  virtual void                ProcessRulePacket(cRulePacket *event);

  float                       GetWidth(){return mWidth;};
  float                       GetHeight(){return mHeight;};
  float                       GetLength(){return mLength;};

  SyVect3                     GetMin();
  SyVect3                     GetMax();
  tGameID                     GetNext();
  tGameID                     GetBranch();
  float                       GetTime(){return mTime;};

  static const int            mCLASSID      = 0xFFFF2006;
  static const SyPropID PropId_Width        = 0x1000;
  static const SyPropID PropId_Length       = 0x1001;
  static const SyPropID PropId_Height       = 0x1002;
  static const SyPropID PropId_Next         = 0x1003;
  static const SyPropID PropId_Branch       = 0x1004;
  static const SyPropID PropId_Time         = 0x1005;

private:
  float                       mWidth; // in X
  float                       mHeight; // in X
  float                       mLength; // in Z

  SyString                    mNext;
  SyString                    mBranch;

  float                       mTime;
};

class cStatsDummy: public cStats 
{
public:
  cStatsDummy();
  virtual ~cStatsDummy();

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

  static const int            mCLASSID      = 0xFFFF2007;
//  static const SyPropID PropId_Width        = 0x1000;

private:
};


class cStatsModelData 
{
public:
  enum Type
  {
    MODELDATA_CHARACTER,
    MODELDATA_PROP,
    MODELDATA_ITEM,
    MODELDATA_MAXTYPES,
  };

  cStatsModelData();
  ~cStatsModelData();

  bool Die(cGameObject* pOwner, cGameObject* pKiller) const;
  bool Load(cGameObject* pOwner) const;

  cNameID                     mID;
  Type                        mType;
  char *                      mModelName;   // pathname of model to use - name without the extension
  char *                      mFileName;    // pathname of model to use - entire file name
  char *                      mSoundName;   
  char *                      mRagdollName; // path of havok ragdoll - name without directory  
  tGameID                     mDeathFXID;
  tGameID                     mSummonFXID;
  tGameID                     mDebrisID;
  tGameID                     mDefaultAnimSetID;
  char                        mSoundSurfaceType;
};

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

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

#endif
