/******************************************************************
  
  Module:  Rule.h
  
  Author: Sean Craig
  
  Description:  Rules respond to rule packets -  
                they are the rules for the game.  For example, say 
                Dwarves get +1 to damage rolls.  All dwarves in the
                game would get a rule which responds to the calculate raw
                damage rule packet.  Note that only dwarves in the game would
                get a copy of this rule.

                A longer name for "rule" is "rule event handler."

  
  Rules come from:
  
  1) global rules (a players max health is 3 * his Constituion, for example)
  2) player's special abilities (this player's special ability grants him +10% damage with daggers)
  3) player's equipment (this magic item grants you +5 strength)
  4) temporary conditions on the player (spell buffs player's strength)
  5) environmental conditions from the game world (walking through water gives you -30% movement rate) 
  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/

#ifndef RULE_H
#define RULE_H

//-------------------------------------------------------- Includes
#include "rulepacket.h"
#include "script_func.h"
//-------------------------------------------------------- Typedefs
//---------------------------------------------- Class Declarations
class Titan;

class cRule
{
public:

                 cRule();
  virtual       ~cRule(){};

  virtual   void Update(float time){};
  virtual   void ProcessPacket(cRulePacket *packet);
  void           SetTitan(Titan *titan){mpTitan = titan;};


  // returns true if rule can be combined (for instance, the same invisibility spell cast twice...)
  virtual bool    Combine(cRule *other){return false;}; 
  virtual void    SetDisabled(); // disabled rules don't handle packets and will be removed at some point during an update...
          bool    IsDisabled(){return mDisabled;};

  virtual const char * GetName(){return "Unnamed";};

  virtual bool    OnAdded(tGameObjectID target){return true;};   // called when added to a player
  virtual bool    OnRemoved(tGameObjectID target){return true;}; // called when removed from a player

protected:

  // SGC: TODO
  // returns true if this blocks the rule from being added (for instance, the creature is immune to poison)
  // virtual bool    Block(cRule *other){return false;}; 
  // returns true if this removes the rule (for instance, a remove poison spell)
  // virtual bool    Remove(cRule *other){return false;}; 

  // these are query type packets, used to figure out a stat...
  virtual void    CalcHealthMax(cCalcPacket *packet){};
  virtual void    CalcHealthRegen(cCalcPacket *packet){};
  virtual void    CalcPowerMax(cCalcPacket *packet){};
  virtual void    CalcPowerRegen(cCalcPacket *packet){};
  virtual void    CalcBlockMax(cCalcPacket *packet){};
  virtual void    CalcBlockRegen(cCalcPacket *packet){};

  virtual void    CalcStrikethrough(cDamagePacket *packet){};
  virtual void    CalcDamageInitial(cDamagePacket *packet){};
  virtual void    CalcDamageRaw(cDamagePacket *packet){};
  virtual void    CalcDamageReduced(cDamagePacket *packet){};

  virtual void    CalcCriticalChance(cDamagePacket *packet){};
  virtual void    CalcDefense(cDamagePacket *packet){};

  virtual void    CalcCarryingCapacity(cCalcPacket *packet){}; 
  virtual void    CalcExperienceGain(cCalcPacket *packet){}; 

  virtual void    QueryFlag(cFlagPacket *packet){};

  // these are notification packets, used to tie in specific events...

  virtual void    OnHit(cHitPacket *packet){}; // additional effects
  virtual void    OnApplyDamage(cDamagePacket *packet){}; 

// variables
  bool            mDisabled;
  Titan          *mpTitan;

};


// this class holds a bunch of cRules.   
class cRuleContainer : public cRule
{
public:
          cRuleContainer();
  virtual ~cRuleContainer();
  bool    Add(cRule *rule);  // transfers ownership
  bool    Remove(const char *name); // deletes rule
  bool    Contains(const char *name); // true if we have a rule by that name
  void    Clear();
  void          Update(float time);   
  virtual void  ProcessPacket(cRulePacket *packet);

  void SetOwnerID(tGameObjectID ownerID);
protected:
  void    ClearDisabled();

  SyVector<cRule*>    mRules;
  tGameObjectID mOwnerID;
};


class cRule_Condition;

class cRuleSys : public cRule
{
public:
  cRuleSys();
  ~cRuleSys();

  void Init();

  cRule_Condition* CreateCondition(const char* conditionName, int numParams, cell* pParams);
  //void CreateEffect(const char* effectname);???

private:
  void Add(cRule_Condition* pRule);
  //void Add(cEffect* pEffect);???

  SyMap<tGameID, cRule_Condition*> mRules;
//  SyMap<tGameID, cEffect*> mEffects;???
};

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

#define LOG_PACKETS (1)
#if (LOG_PACKETS)
void LogEnable(bool log);
bool IsLogEnabled();
void Log(const char *format,...);
void LogPacketStart(cRulePacket *packet,Titan *titan);
void LogPacketEnd(cRulePacket *packet,Titan *titan);
#else 
#define LogEnable(x) ((void)0
#define Log
#define LogPacketStart(x,y) ((void)0)
#define LogPacketEnd(x,y) ((void) 0)
#endif
//--------------------------------------------------------- Globals
//------------------------------------------------ Inline Functions

#endif
