/******************************************************************
  
  Module:  droplist.cpp
  
  Author: Sean Craig
  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/

//-------------------------------------------------------- Includes
#include "droplist.h"
#include "tinyxml.h"
#include "database.h"
#include "item.h"
#include "registry.h"
#include "physics.h"
#include "stats.h"

//---------------------------------------------- Class Declarations
//----------------------------------------- Functions Declarations
//------------------------------------ Member Functions Definitions
//------------------------------------------------  cDropListElement

cDropListElement::cDropListElement() :
  mType(DROP_ITEM),
  mWeight(1),
  mMinAmount(1),
  mMaxAmount(1)
{
}

cDropListElement::~cDropListElement()
{
};

bool                        
cDropListElement::Drop(Titan *titan,SyVect3 location)
{
  if (mType == DROP_ITEM)
  {
    const cStatsItemMaster * itemmaster = titan->GetDatabaseSys()->GetItemMaster(mDropID);
    if (itemmaster != NULL)
    {
      cGameObjectRegistry *reg= titan->GetRegistry();
      tGameObjectID  item_id = reg->Create(cGameObject::OBJ_ITEM);
      cItem *pItem = new cItem;
      pItem->SetMaster(itemmaster);
      pItem->SetQuantity(titan->Random(mMinAmount,mMaxAmount));
      cGameObject *item_obj = reg->Fetch(item_id);
      item_obj->SetLocation(location);
      prop_cast<cStatsItem*>(item_obj->GetStats())->SetItem(pItem);
    
      float angle = SY_DEG_TO_RAD(titan->Random(-180,180));

      static const float VEL_XZ = 2.0f;
      static const float VEL_Y = 2.0f;
      SyVect3 vel;
      vel.X = SY_SIN(angle) * VEL_XZ;
      vel.Y = VEL_Y;
      vel.Z = SY_COS(angle) * VEL_XZ;

      prop_cast<cPhysicsDynamic *>(item_obj->GetPhysics())->SetVelocity(vel);
      reg->InitObject(item_obj->GetID(),false);
      return true;
    }
  }
  else
  {
    cDropList * droplist = titan->GetDatabaseSys()->GetDropList(mDropID);
    if (droplist != NULL)
    {
      droplist->Drop(titan,location);
      return true;
    }
  }

  return false;
};


//--------------------------------------------------  cDropList

cDropList::cDropList()
{
}

cDropList::~cDropList()
{
}

void                        
cDropList::Drop(Titan *titan,SyVect3 location)
{
  int total =0;
  for (int ii=0;ii<mElements.Size();++ii)
  {
    total += mElements(ii).mWeight;
  }

  if (total <= 0)
  {
    SyAssert(0);
    return;
  }
  int index = titan->Random(0,total);

  for (int ii=0;ii<mElements.Size();++ii)
  {
    index -= mElements(ii).mWeight;
    if (index <= 0)
    {
      if (!mElements(ii).Drop(titan,location))
      {
        SyAssertf(0, "Unknown item in droplist : %s",mName.GetName()); 
      }
      return;
    }
  }
};


//----------------------------------------------  cTresureSetItem
cTreasureSetElement::cTreasureSetElement()
{
}

cTreasureSetElement::~cTreasureSetElement()
{
}

void                        
cTreasureSetElement::Drop(Titan *titan,SyVect3 location)
{
  cDropList * droplist = titan->GetDatabaseSys()->GetDropList(mDropID);
  if (droplist != NULL)
  {
    droplist->Drop(titan,location);
  }
};


//----------------------------------------------  cTresureSet

 cTreasureSet::cTreasureSet()
 {
 }

 cTreasureSet::~cTreasureSet()
 {
 }

 void                        
 cTreasureSet::Drop(Titan *titan,SyVect3 location)
 {
   for (int ii=0;ii < mElements.Size();++ii)
   {
     double roll = rand()/((double)RAND_MAX+1); 
     if (roll < mElements(ii).mChance)
     {
       mElements(ii).Drop(titan,location);
     }
   }
 }


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

cDropList *
ParseDropList(cDatabaseSys *db,TiXmlNode* node)
{
  TiXmlNode* data_node;
  data_node = node->FirstChild("Name");
  SyAssert(data_node);
  const char *name = data_node->FirstChild()->Value();

  cDropList *retval = NULL;
  cDropList *master = db->GetDropList(SyHashResourceID(name));


  if (master == NULL)
  {
    master = new cDropList;
    master->mName.SetName(name);
    retval = master;
  }

  cDropListElement element;

  const char *l_DropTypeNames[] = 
  {
    "Item",
    "DropList"
  };

  static const int NUM_DROP_TYPENAMES = sizeof(l_DropTypeNames)/sizeof(l_DropTypeNames[0]);

  data_node = node->FirstChild("Type");
  if (data_node != NULL)
  {
    int enumVal = 0;
    const char *type = data_node->FirstChild()->Value();
    bool result = ChooseEnum(type,l_DropTypeNames,NUM_DROP_TYPENAMES, enumVal);

    element.mType = (cDropListElement::eDropType)enumVal;
  }

  data_node = node->FirstChild("DropName");
  if (data_node == NULL)
  {
    SyAssertf(0,"Can't parse record %s",master->mName.GetName());
    return retval;
  }

  element.mDropID = SyHashResourceID(data_node->FirstChild()->Value());

  if (element.mType == cDropListElement::DROP_ITEM)
  {
    // check to see if item exists...
    SyAssertf(db->GetItemMaster(element.mDropID)!=NULL,"Bad Item Drop %s in %s",
              data_node->FirstChild()->Value(),master->mName.GetName());
  }

  data_node = node->FirstChild("Weight");
  SyAssertf(data_node!=NULL,"Missing Data Field 'Weight' in drop list database XML file");
  if (data_node != NULL)
  {
    element.mWeight = atoi(data_node->FirstChild()->Value());
  }
  data_node = node->FirstChild("MinAmount");
  if (data_node != NULL)
  {
    element.mMinAmount = atoi(data_node->FirstChild()->Value());
  }

  data_node = node->FirstChild("MaxAmount");
  if (data_node != NULL)
  {
    element.mMaxAmount = atoi(data_node->FirstChild()->Value());
  }
  master->mElements.Add(element);

  return retval;
};

cTreasureSet *
ParseTreasureSet(cDatabaseSys *db, TiXmlNode* node)
{
  TiXmlNode* data_node;
  data_node = node->FirstChild("Name");
  SyAssert(data_node);
  const char *name = data_node->FirstChild()->Value();

  cTreasureSet *retval = NULL;
  cTreasureSet *master = db->GetTreasureSet(SyHashResourceID(name));


  if (master == NULL)
  {
    master = new cTreasureSet;
    master->mName.SetName(name);
    retval = master;
  }

  cTreasureSetElement element;

  data_node = node->FirstChild("DropName");
  if (data_node == NULL)
  {
    SyAssertf(0,"Can't parse record %s",master->mName.GetName());
    return retval;
  }

  element.mDropID = SyHashResourceID(data_node->FirstChild()->Value());

    // check to see if item exists...
  SyAssertf(db->GetDropList(element.mDropID)!=NULL,"Bad Item Drop %s in %s",
              data_node->FirstChild()->Value(),master->mName.GetName());

  data_node = node->FirstChild("Chance");
  SyAssertf(data_node!=NULL,"Missing Data Field 'Chance' in drop list database XML file");
  if (data_node != NULL)
  {
    element.mChance = (float) atof(data_node->FirstChild()->Value());
    element.mChance /= 100; // from percent
  }
  master->mElements.Add(element);
  return retval;
};



// EOF
