#include "Titan.h"
#include "TitanInputHandler.h"
#include "TitanPeeringNetwork.h"
#include "TitanFXScriptDriver.h"
#include "SyAssert.h"
#include "SyDebug.h"
#include "SyESFParse.h"       
#include "registry.h"
#include "cameracontroller.h"
#include "stats.h"
#include "intel.h"

#include "animcontroller.h"
#include "SyCamera.h"
#include "SyScene.h"
#include "SyPerformanceStats.h"
#include "rule.h"
#include "rule_global.h"
#include "rule_inventory.h"
#include "rule_condition.h"
#include "inventory.h"
#include "tuning.h"
#include "graphic.h"
#include "script_pawn.h"
#include "database.h"
#include "graphic.h"

#include "ai.h"
#include "ai/lostable.h"
#include "ai/aidebugdraw.h"

#include "areaeffect.h"
#include "script_func.h"

#include "debris.h"

#ifdef WIN32
    #include <crtdbg.h>
#endif

/*static*/ TitanI* TitanI::Create( TitanUII* pTitanUI )
{
  return new Titan( pTitanUI );
}

// Initializes an instance of the Titan class.
Titan::Titan( TitanUII* pTitanUI ) :
mpTitanUI( pTitanUI ),
mpInputHandler(NULL ),
mCurTime(0),
mTimeScale(1.0f),
mBloomEnabled(false),
mBloomEffectHandle(-1),
mMultiPassEnabled(false),
mDrawMode(DrawModeNormal),
mCurFilename(NULL),
mDebugLabelEnabled(false),
mbUnfocused(false),
mbCheckArt(true)
{  
  //_CrtSetBreakAlloc(3882);  // break for debugging leaked memory
  RegPropClasses_Registry();

  mpRegistry = new cGameObjectRegistry();
  mpCameraController = new cCameraController( this);
  mpDatabaseSys = new cDatabaseSys(this);
  mpRuleSys = new cRuleSys();
  mpAnimControllerSys = new cAnimControllerSys();
  mpGlobalRules = new cRuleContainer();
  mpInventoryRules = new cInventoryRuleContainer();
  mpInventoryRules->SetTitan(this);
  mpTitanPeeringNetwork = new TitanPeeringNetwork(this);
  mpTitanFXScriptDriver = new TitanFXScriptDriver(this);
  mpScriptSys = new cScriptSys(this);
  mpAreaEffectSys = new cAreaEffectSys();
  mpDebrisSys = new cDebrisSys(this);
}

// Destroys an instance of the Titan class.
Titan::~Titan(void)
{
  if ( mBloomEffectHandle != -1 )
  {
    SyScene *scene = GetScene();
    scene->GetPostEffectSystem()->ReleaseEffect( mBloomEffectHandle );
    mBloomEffectHandle = -1;
  }
  delete mpTitanFXScriptDriver;
  delete mpTitanPeeringNetwork;
  delete mpInventoryRules;
  delete mpInputHandler;
  delete mpRegistry;
  delete mpCameraController;
  delete mpDatabaseSys;
  delete mpRuleSys;
  delete mpAnimControllerSys;
  delete mpGlobalRules;
  delete mCurFilename;
  delete mpScriptSys;
}


// Allocates resources required by the Titan object.
bool Titan::Init( uint64 time )
{
  // time management

  mbPaused = false;
  SyScene *scene = GetScene();
  mGameTime = 0;
  scene->SetTime(mGameTime);
  mCurTime = time;

  gTuningSys.Init();

  mpDatabaseSys->Init();
  mpRuleSys->Init();
  mpRegistry->Init(this);
  mpAnimControllerSys->Init();
  mpGlobalRules->SetTitan(this);
  AddGlobalRules(mpGlobalRules);
  mpCameraController->OnInit();
  cAiInterface::RegisterTuningVariables();
  scriptFuncs_RegisterTuningVars();
  Stats_RegisterTuningVariables();
  Debris_RegisterTuningVariables();

  gTuningSys.LoadValues();  // load tuning variables

  // register our driver with FXscripting system
  SyFXScriptSystem* fxScriptSystem = scene->GetFXScriptSystem();
  fxScriptSystem->SetDriver (*mpTitanFXScriptDriver);
  
  return true;
}

// Releases resources acquired by the titan. object.
void Titan::Close()
{ 
}

void Titan::PauseGame()
{
  mbPaused = true;

  // whatever calls need to be made when the game is paused
}

void Titan::UnpauseGame()
{
  mbPaused = false;
}

bool Titan::IsPaused()
{
  return mbPaused;
}


void Titan::IncreaseTimeScale()
{
  mTimeScale *= 2.0f;
  if (mTimeScale > 1.0f)
  {
    mTimeScale = 1.0f;
  }
}

void Titan::DecreaseTimeScale()
{
  mTimeScale *= 0.5f;
}

void Titan::SetTimeScale(float scale)
{
  if (scale >= 0.0f)
  {
    mTimeScale = scale;
  }
}

float Titan::GetTimeScale()
{
  return mTimeScale;
}
// Updates the game state to the specified time.
void Titan::Update( uint64 time )
{
  if (mbUnfocused) // sgc happens when the game is stopped due to an open modal window
  {
    mCurTime = time;
    return;
  }
  uint64 delta_time_msec = time - mCurTime;
  if (mbPaused)
  {
    delta_time_msec = 0;
  }

  if (mTimeScale != 1.0f)
  {
    delta_time_msec = (int)((float)delta_time_msec * mTimeScale);
  }
  // clamp delta time to facilitate stepping through code in debugger
  if (delta_time_msec > 200) delta_time_msec = 200;
  float delta_time = ((float)delta_time_msec)/1000.0f;


  mpScriptSys->Update(delta_time);
  mpRegistry->Update(delta_time);
  mpCameraController->Update(delta_time);
  mpTitanPeeringNetwork->GiveTime();     // give processing time to the network layer

  cLOSTable::Update(GetScene());  // update our max line of sights per frame
  mpAreaEffectSys->Update(delta_time);
  mpDebrisSys->Update(delta_time);

  mGameTime += delta_time_msec;
  SyScene *scene = GetScene();
  scene->SetTime(mGameTime);
  
  mCurTime = time;
}
// Renders the scene.
// Scene::BeginScene must be called before this method is invoked.
// Scene::EndScene must be called after this method is invoked.
void Titan::Render()
{
  if (mbUnfocused) // sgc happens when the game is stopped due to an open modal window
  {
    return;
  }
  mpRegistry->Prerender();

  SyScene *scene = mpTitanUI->GetScene();

  SyCamera camera = *mpCameraController->GetCamera();

  SyRaster* raster = scene->GetRasterDev();
  float aspectRatio = (float)raster->GetScreenWidth() / (float)raster->GetScreenHeight();
  camera.SetAspectRatio( *raster, aspectRatio );

  float minAspectRatio = 960.0f / 624.0f;
  if ( aspectRatio < minAspectRatio )
  {
    // when the aspect ratio drops below minAspectRatio, start shaving off of the view angle
    camera.SetViewAngle( *raster, ( aspectRatio / minAspectRatio ) * camera.GetViewAngle() );
  }
  scene->SetFarPlane( camera );
  if ( mBloomEnabled )
  {
    if  ( mBloomEffectHandle == -1 )
    {
      mBloomEffectHandle = scene->GetPostEffectSystem()->CreateBloomEffect();
    }
    scene->RenderWithPostEffect( camera, mBloomEffectHandle );
  }
  else
  {
    scene->Render( camera );
  }

  scene->Listen( camera );

#ifdef _AIDEBUGDRAW
  cAIDebugDraw::Render(scene->GetRasterDev(), GetCameraController()->GetCamera());
#endif
}

TitanInputHandlerI* Titan::GetInputHandler( int controllerId )
{
  SyAssert( controllerId == 0 ); // only support one controller right now
  return mpInputHandler;
}

void                  
Titan::SaveGame()
{
  mpRegistry->SaveGame();
}

void                  
Titan::LoadGame()
{
  mpRegistry->LoadGame();
  // hook up camera / controller
  cGameObject *obj = mpRegistry->Fetch("Player");
  SyAssertf(obj!=NULL,"Can't Find Player");
  if (obj != NULL)
  {
    ((cIntelPlayer*)obj->GetIntel())->SetController(0);
    mpCameraController->SetTarget(obj->GetID());
    mpInputHandler->SetGameObject(obj);
  }
}

int 
Titan::Random(int min,int max)
{
  int range = max - min;
  if (range == 0)
  {
    return min;
  }
  int value = rand() % range;
  return min + value;
}

float 
Titan::RandomFloat()
{
  int value = rand() % 2048;
  return ((float) value) / 2048;
}

void Titan::LoadLevel(const char *filename)
{
  if (filename != mCurFilename)
  {
    delete mCurFilename;
    mCurFilename = strdup(filename);
  }

  const char *extension = &filename[strlen(filename)];

  while (*extension != '.')
  {
    if (extension == filename)
    {
      assert(0);
      return;
    }
    extension--;
  }

  LoadLevelScript(filename);

  if (strcmp(extension,".xml")==0)
  {
    mpRegistry->LoadLevelXML(filename);
  }
  else
  {
    mpRegistry->LoadLevelBinary(filename);
  }

  mpDatabaseSys->LoadDebrisModels();
  PostLoad();
}


void Titan::LoadLevelScript(const char *filename)
{
  char script_name[256];


  strcpy(script_name,filename);
  char *extension = &script_name[strlen(filename)];

  while (*extension != '.')
  {
    if (extension == filename)
    {
      assert(0);
      return;
    }
    extension--;
  }
  strcpy(extension,".amx");

#if defined(_DEBUG)
  mpScriptSys->Compile(script_name);
  //mpScriptSys->Compile("default.amx");
#endif 

  if (!mpScriptSys->LoadScript(script_name))
  {
    //mpScriptSys->LoadScript("default.amx");
  }
  mpScriptSys->Startup();
}


void Titan::ScriptEnableDebugging()
{
  mpScriptSys->EnableDebugging();
}

void Titan::CheatKey(int key)
{
  // Use Wx key codes:  reproducing here instead of linking in to wx source.
  // get from defs.h 
  /*  Virtual keycodes */
  enum wxKeyCode
  {
    WXK_F12 =353,
    WXK_NUMPAD_ADD = 392,
    WXK_NUMPAD_SUBTRACT = 394,
  };
  switch (key)
  {
  case 'C': 
    PlayCutScene("PrototypeCutScene");
    break;

  case 'V': 
    PlayCutScene("PrototypeCutSceneNoCamera");
    break;

  case WXK_NUMPAD_ADD:
    IncreaseTimeScale();
    break;

  case WXK_NUMPAD_SUBTRACT:
    DecreaseTimeScale();
    break;

  case WXK_F12:
    gTuningSys.LoadValues();
    break;

  case 'P':
    mpScriptSys->Recompile();
    break;

  case 'I':
    mpScriptSys->EnableDebugging();
    break;

  case 'L':
    SetDebugLabel(!GetDebugLabel());
    break;

  case 'N':
    {
      static bool sbAIDisabled = false;
      sbAIDisabled = !sbAIDisabled;
      cAiInterface::DisableAll(sbAIDisabled);
    }
    break;

#ifdef _AIDEBUGDRAW
  case 'M':
    cAIDebugDraw::Toggle();
    break;

  case ',':
    cAIDebugDraw::SelectPrevNPC(GetRegistry(), GetCameraController()->GetCamera());
    break;

  case '.':
    cAIDebugDraw::SelectNextNPC(GetRegistry(), GetCameraController()->GetCamera());
    break;
#endif
  }
}

void Titan::PostLoad()
{
  tGameObjectID  player1 = mpRegistry->Create(cGameObject::OBJ_PLAYER);
  cGameObject *player = mpRegistry->Fetch(player1);
  player->SetName("Player");
  cGameObject *playerMarker = mpRegistry->Fetch("playerSpawn");
  SyAssertf(playerMarker != NULL,"Unable to Find Player Spawn Marker");

  player->SetSafeLocation(playerMarker->GetLocation());
  player->SetHPR(playerMarker->GetHPR());
  player->GetStats()->SetMaster("Player");
  ((cIntelPlayer*)player->GetIntel())->SetController(0);
  delete mpInputHandler;
  mpInputHandler = new TitanInputHandler( mpTitanUI,player);

  // give player items.
   
  cInventoryCharacter *inv = (cInventoryCharacter *) player->GetInventory();
  cItem *item =inv->Add(SyHashResourceID("Sword"));
  inv->Equip(item,EQUIP_MELEE);

  // set up camera
  mpCameraController->SetTarget(player1);
  mpRegistry->InitObject(player->GetID(),true);
  mpCameraController->SetHeading(AngleNormalize(player->GetHeading()+SY_DEG_TO_RAD(180)));

  // register our driver with FXscripting system
  SyScene *scene = GetScene();
  SyFXScriptSystem* fxScriptSystem = scene->GetFXScriptSystem();
  fxScriptSystem->SetDriver (*mpTitanFXScriptDriver);
}

const cStatsItemMaster* Titan::GetItemMaster( int player, int item )
{
  cInventoryCharacter* ic = (cInventoryCharacter*)mpInputHandler->GetGameObject()->GetInventory();
  SyAssert( item < ic->GetNumItems() );
  const cStatsItemMaster* pItem = ic->GetItem(item)->GetMaster();
  return( pItem );
}

int Titan::SelectItemEquipSlot( cItem* pItem )
{
  eItemType type = pItem->GetMaster()->mType;
  switch( type )
  {
  case IT_MELEE:
    return( EQUIP_MELEE );
  case IT_RANGED:
    return( EQUIP_RANGED );
  case IT_HEAD:
    return( EQUIP_HEAD );
  case IT_BODY:
    return( EQUIP_BODY );
  case IT_FEET:
    return( EQUIP_FEET );
  case IT_ACCESSORY:
    return( EQUIP_ACCESSORY );
  default:
    return( EQUIP_UNEQUIPPED );
  }
}

void Titan::LoadSavedGame(const char *saveGameFilename)
{
}

void Titan::Restart()
{
  // clear out level...
  mpAreaEffectSys->Clear();
  mpRegistry->Clear();
  LoadLevel(mCurFilename);
}

void Titan::NetworkGameJoin(/*gift*/ PeeringNetwork::PeeringServerApi *api, int gameId)
{
    mpTitanPeeringNetwork->SetPeeringNetwork(api);
    mpTitanPeeringNetwork->GameJoin(gameId);

    while (mpRegistry->GetLevelObject() == NULL ||  mpRegistry->Fetch("playerSpawn")== NULL)
    {
        mpTitanPeeringNetwork->GiveTime();
        // wait for the level object
    };

    tGameObjectID  player2 = mpRegistry->Create(cGameObject::OBJ_PLAYER);
    cGameObject *player = mpRegistry->Fetch(player2);
    //player->SetName("Player2");
    cGameObject *playerMarker = mpRegistry->Fetch("playerSpawn");
    //SyAssertf(playerMarker != NULL,"Unable to Find Player Spawn Marker");

    player->SetSafeLocation(playerMarker->GetLocation());
    //player->SetLocation(SyVect3(-55.0f,0.5f,25.0f));

    //player->SetHPR(playerMarker->GetHPR());
    player->GetStats()->SetMaster("Player");
    ((cIntelPlayer*)player->GetIntel())->SetController(0);
    if (mpInputHandler == NULL)
    {
        mpInputHandler = new TitanInputHandler( mpTitanUI,player);
    }
    // set up camera
    mpCameraController->SetTarget(player2);
    mpRegistry->InitObject(player->GetID(),true);
}

void Titan::NetworkGameCreate(/*gift*/ PeeringNetwork::PeeringServerApi *api, const char *gameName)
{
    mpTitanPeeringNetwork->SetPeeringNetwork(api);
    mpTitanPeeringNetwork->GameCreate(gameName);
}

void Titan::HackStartupNetwork(const char *playerName, const char *gameName, const char *xmlFilename, const char *recordFilename, const char *playbackFilename)
{
    mpTitanPeeringNetwork->HackStartupNetwork(playerName, gameName, xmlFilename, recordFilename, playbackFilename);
}

//============================================================================
// Design Settings
//============================================================================

void          
Titan::SetLogMode(bool on)
{
  LogEnable(on);
}

bool 
Titan::GetLogMode()
{
  return IsLogEnabled();
}


void          
Titan::SetCheckArt(bool on)
{
  mbCheckArt = on;
}

bool 
Titan::GetCheckArt()
{
  return mbCheckArt;
}

  // Sets whether player is invulnerable or not
void 
Titan::SetGodMode(bool on)
{
  SyAssertf(mpRegistry!=NULL,"Registry not initialized");
  cGameObject *obj = mpRegistry->Fetch("Player");
  SyAssertf(obj!=NULL,"Can't Find Player");
  if (obj != NULL)
  {
    if (on)
    {
      obj->AddCondition("Invulnerable", 0, NULL);
    }
    else
    {
      obj->RemoveCondition("Invulnerable");
    }
  }
}

bool 
Titan::GetGodMode()
{
  SyAssertf(mpRegistry!=NULL,"Registry not initialized");
  cGameObject *obj = mpRegistry->Fetch("Player");
  SyAssertf(obj!=NULL,"Can't Find Player");
  if (obj != NULL)
  {
    ((cStatsCharacter*)obj->GetStats())->HasCondition("Invulnerable");
  }
  return false;
}

  // Sets whether to log combat events and calculations to a file.
void 
Titan::SetInvisibleMode(bool on)
{
  SyAssertf(mpRegistry!=NULL,"Registry not initialized");
  cGameObject *obj = mpRegistry->Fetch("Player");
  SyAssertf(obj!=NULL,"Can't Find Player");
  if (obj != NULL)
  {
    if (on)
    {
      obj->AddCondition("Invisible", 0, NULL);
    }
    else
    {
      obj->RemoveCondition("Invisible");
    }
  }
}

bool 
Titan::GetInvisibleMode()
{
  SyAssertf(mpRegistry!=NULL,"Registry not initialized");
  cGameObject *obj = mpRegistry->Fetch("Player");
  SyAssertf(obj!=NULL,"Can't Find Player");
  if (obj != NULL)
  {
    ((cStatsCharacter*)obj->GetStats())->HasCondition("Invisible");
  }
  return false;
}

void 
Titan::OverloadPlayerModel(const char *modelname)
{
  SyAssertf(mpRegistry!=NULL,"Registry not initialized");
  cGameObject *obj = mpRegistry->Fetch("Player");
  SyAssertf(obj!=NULL,"Can't Find Player");
  if (obj != NULL)
  {
    const cStatsCharacterMaster *c_master = prop_cast<cStatsCharacter*>(obj->GetStats())->GetMaster();

    // here we go, breaking encapsulation...i feel dirty...
    cStatsCharacterMaster *master = const_cast<cStatsCharacterMaster *>(c_master);
    delete master->mModel;
    master->mModel = strdup(modelname); 

    cGraphicActor *actor = prop_cast<cGraphicActor*>(obj->GetGraphic());
    // release old actor,
    actor->Release();
    // init new one
    actor->Init();
  }
};

//============================================================================
// Player Inventory
//============================================================================

int Titan::InventoryGetItemCount(int player)
{
  cInventoryCharacter* ic = (cInventoryCharacter*)mpInputHandler->GetGameObject()->GetInventory();
  return ic->GetNumItems();
}

const char* Titan::InventoryGetItemName(int player,int item)
{
  const cStatsItemMaster* pItem = GetItemMaster( player, item );
  if ( pItem->mNameString == 0 )
  {
    return pItem->mID.GetName();
  }
  return pItem->mNameString;
}

const char* Titan::InventoryGetItemDescription( int player, int item )
{
  const cStatsItemMaster* pItem = GetItemMaster( player, item );
  if( pItem->mDescriptionString == 0 )
  {
    return pItem->mID.GetName();
  }
  return pItem->mDescriptionString;
}

int Titan::InventoryGetItemQuantity( int player, int item )
{
  cInventoryCharacter* ic = static_cast<cInventoryCharacter*>(mpInputHandler->GetGameObject()->GetInventory());
  SyAssert( item < ic->GetNumItems() );
  cItem* pItem = ic->GetItem( item );
  return( pItem->GetQuantity() );
}

int Titan::InventoryGetItemValue( int player, int item )
{
  const cStatsItemMaster* pItem = GetItemMaster( player, item );
  return( pItem->mValue );
}

int Titan::InventoryGetItemDamageBonus( int player, int item )
{
  const cStatsItemMaster* pItem = GetItemMaster( player, item );
  return( pItem->mBaseDamageBonus );
}

int Titan::InventoryGetItemDefenseBonus( int player, int item )
{
  const cStatsItemMaster* pItem = GetItemMaster( player, item );
  return( pItem->mDefenseBonus );
}

const char* Titan::InventoryGetItemIcon(int player, int item)
{
  const cStatsItemMaster* pItem = GetItemMaster( player, item );
  return( (pItem->mIcon == 0) ? pItem->mAttachModel : pItem->mIcon );
}

int Titan::InventoryGetItemType(int player, int item)
{
  const cStatsItemMaster* pItem = GetItemMaster( player, item );
  return( (int)pItem->mType );
}

int Titan::InventoryGetGold( int player )
{
  int result = 0;
  for( int i = 0; i < InventoryGetItemCount( player ); i++ )
  {
    if( InventoryGetItemType( player, i ) == IT_GOLD )
    {
      result += InventoryGetItemQuantity( player, i );
    }
  }

  return( result );
}

bool Titan::InventoryIsEquipped( int player, int item )
{
  cInventoryCharacter* ic = static_cast<cInventoryCharacter*>(mpInputHandler->GetGameObject()->GetInventory());
  if( item < ic->GetNumItems() )
  {
    cItem* pItem = ic->GetItem( item );
    return( pItem->GetEquipSlot() != EQUIP_UNEQUIPPED );
  }
  else
  {
    return( false );
  }
}

bool Titan::InventoryEquip( int player, int item )
{
  cInventoryCharacter* ic = static_cast<cInventoryCharacter*>(mpInputHandler->GetGameObject()->GetInventory());
  SyAssert( item < ic->GetNumItems() );
  cItem* pItem = ic->GetItem( item );
  eEquipSlot equipSlot = (eEquipSlot)SelectItemEquipSlot( pItem );

  if( equipSlot == EQUIP_UNEQUIPPED )
  {
    return( false );
  }
  else
  {
    return( ic->Equip( pItem, equipSlot ) );  
  }
}

void Titan::InventoryUnequip( int player, int item )
{
  cInventoryCharacter* ic = static_cast<cInventoryCharacter*>(mpInputHandler->GetGameObject()->GetInventory());
  SyAssert( item < ic->GetNumItems() );
  cItem* pItem = ic->GetItem( item );
  ic->Unequip( pItem->GetEquipSlot() );
}

bool Titan::InventoryDrop( int player, int item )
{
  cInventoryCharacter* ic = static_cast<cInventoryCharacter*>(mpInputHandler->GetGameObject()->GetInventory());
  SyAssert( item < ic->GetNumItems() );
  cItem* pItem = ic->GetItem( item );
  return( ic->Drop( pItem ) );
}

//============================================================================
// Scene options
//============================================================================

// Gets or sets a value that indicates whether the bloom post processing effect is enabled
bool Titan::GetBloom()
{
  return mBloomEnabled;
}
void Titan::SetBloom( bool value )
{
  if ( mBloomEnabled == value )
  {
    // no change
    return;
  }
  mBloomEnabled = value;
  if ( !mBloomEnabled && mBloomEffectHandle != -1 )
  {
    // free up the bloom effect
    SyScene* scene = mpTitanUI->GetScene();
    scene->GetPostEffectSystem()->ReleaseEffect( mBloomEffectHandle );
    mBloomEffectHandle = -1;
  }
}

bool Titan::GetMultiPass()
{
  return mMultiPassEnabled;
}
void Titan::SetMultiPass( bool value )
{
  if ( mMultiPassEnabled == value )
  {
    // no change
    return;
  }
  mMultiPassEnabled = value;
  SyScene* scene = mpTitanUI->GetScene();
  scene->SetMultiPass(mMultiPassEnabled);
}

TitanI::DrawMode Titan::GetDrawMode()
{
  return mDrawMode;
}

void Titan::SetDrawMode( DrawMode value )
{
  if ( mDrawMode == value )
  {
    // no change
    return;
  }
  mDrawMode = value;
  SyScene* scene = mpTitanUI->GetScene();
  switch ( mDrawMode )
  {
  case DrawModeNormal:
    scene->SetDrawMode( SYSCENEDRAWMODE_NORMAL );
    break;
  case DrawModeWire:
    scene->SetDrawMode( SYSCENEDRAWMODE_WIRE );
    break;
  case DrawModeSolid:
    scene->SetDrawMode( SYSCENEDRAWMODE_SOLIDFILL );
    break;
  }
}

//============================================================================
// Sky On/Off
//============================================================================

bool Titan::GetEnableSky()
{
  SyScene * scene = mpTitanUI->GetScene();
  return scene->IsSkyEnabled();
}

void Titan::SetEnableSky( bool b )
{
  SyScene* scene = mpTitanUI->GetScene();
  scene->EnableSky( b );
}

//============================================================================
// Performance Stats
//============================================================================

int Titan::GetFPS()
{
  return mpTitanUI->GetPerformanceStats()->GetFPS();
}
int Titan::GetBatches()
{
  return mpTitanUI->GetPerformanceStats()->GetBatchesPerFrame();
}
int Titan::GetVertexes()
{
  return mpTitanUI->GetPerformanceStats()->GetVertsPerFrame();
}
int Titan::GetTriangles()
{
  return mpTitanUI->GetPerformanceStats()->GetTrisPerFrame();
}
uint32 Titan::GetPixels()
{
    return mpTitanUI->GetPerformanceStats()->GetPixelsPerFrame();
}
int Titan::GetDegenerateTriangles()
{
  return mpTitanUI->GetPerformanceStats()->GetDegenerateTrisPerFrame();
}
int Titan::GetAverageFPS()
{
  return mpTitanUI->GetPerformanceStats()->GetAvgFPS();
}
int Titan::GetAverageBatches()
{
  return mpTitanUI->GetPerformanceStats()->GetAvgBatchesPerFrame();
}
int Titan::GetAverageVertexes()
{
  return mpTitanUI->GetPerformanceStats()->GetAvgVertsPerFrame();
}
int Titan::GetAverageTriangles()
{
  return mpTitanUI->GetPerformanceStats()->GetAvgTrisPerFrame();
}
int Titan::GetAverageDegenerateTriangles()
{
 return mpTitanUI->GetPerformanceStats()->GetAvgDegenerateTrisPerFrame();
}

//============================================================================
// Cut Scene Control
// For camera only cut-scenes do this: 
// fxScriptSystem->PlayScript (cameraScriptResourceHandle, 0,  (SyActorHandle*) NULL);
//
// This is mostly demo HOWTO code on using/running a cut scenes.  For now, we 
// can get one of 2 cut scenes, 
// 
//  1) "PrototypeCutScene", which has a Player, a Demon(Maya name), a camera.
//     This cut scene is triggered by hitting the C key on your keyboard.
//
//  2) "PrototypeCutSceneNoCamera", which only has a Demon(Maya name), & no camera.
//     This cut scene is triggered by hitting the V key on your keyboard.
//
//============================================================================

void Titan::PlayCutScene(char8* cutSceneName)
{
    SyScene *scene = mpTitanUI->GetScene();
    SyDictionary * sceneDictionary = scene->GetDictionary();
    SyResourceType cutSceneScriptResourceType;
    int32 cutSceneScriptResourceHandle = -1;
    int32 numCutSceneActors = 0;

    // get the fxScriptSystem for playing back cutscenes
    SyFXScriptSystem* fxScriptSystem = scene->GetFXScriptSystem();

    // get the cut scene
    SyResourceID scriptResourceID = SyHashResourceID(cutSceneName);
    sceneDictionary->Find (scriptResourceID, cutSceneScriptResourceType, cutSceneScriptResourceHandle);

    // Assemble SyFXScriptActorPair array, correlating in-game Scene actor names to "Maya"/art tool actor names.
    SyFXScriptActorPair  actorPair[2];


    // get Demon 
    cGameObject * demon = GetRegistry()->Fetch("CutSceneNPC"); // the in-game name of *ONE* of our NPCs (thx, design group)
    SyAssertf(demon!=NULL,"Can't Find Demon For Cut Scene");
    SyActorHandle demonActor = demon->GetGraphic()->GetActorHandle();

    // add it to our SyFXScriptActor pair argument structure. (Sean luvs this shit)
    actorPair[numCutSceneActors].mActorHandle = demonActor;
    actorPair[numCutSceneActors].mpArgName = strdup ("Demon"); // this is the name of it in the FXScript (Maya)
    numCutSceneActors++;



    // if We're doing CutScene #1 (see comment block, above), we got a Player too. (Sean luvs this shit)
    if (strcmp (cutSceneName, "PrototypeCutScene") == 0)
    {
      // get the hero
      cGameObject * gob = GetRegistry()->Fetch("Player");
      SyAssertf(gob!=NULL,"Can't Find Player For Cut Scene");
      SyActorHandle mainActor = gob->GetGraphic()->GetActorHandle();

      // add it to our SyFXScriptActor pair argument structure. (Sean luvs this shit)
      actorPair[numCutSceneActors].mActorHandle = mainActor;
      actorPair[numCutSceneActors].mpArgName = strdup ("Player"); // this is the name of it in the FXScript (Maya)
      numCutSceneActors++;
    }

    // fire off the script
    mpTitanFXScriptDriver->BeginCutScene();
    fxScriptSystem->PlayScript (cutSceneScriptResourceHandle, numCutSceneActors,  (const SyFXScriptActorPair *) actorPair);


    // Play CutScene soundtrack. Temp solution, pending streaming implementation.
    // CutScene sound file's name is derived from the name of the cut scene itself. It
    // is not exported from Maya, unlike all other CutScene elements. 
    // Question - need to free memory resources for sound file. How? =Bijan
    SyESFParse parser;
    char soundFileName[512];
    sprintf (soundFileName, "Sound\\CutSceneSoundtracks\\CutSceneSoundtrack_%s.esf", cutSceneName);
    int cutSceneSoundID = parser.ParseSound(soundFileName,*scene);  // load sound
    if (cutSceneSoundID != -1)
    {
      SySoundDevice *soundDevice = scene->GetSoundDev();
      soundDevice->Play(cutSceneSoundID,1,SySoundDevice::kUi);
    }
}

bool Titan::isCutScenePlaying()
{
  bool result = mpTitanFXScriptDriver->isCutScenePlaying();
  return result;
}

//============================================================================
// Player Stats
//============================================================================

int Titan::GetPlayerHealthMax()
{
  cGameObject* pObj = mpInputHandler->GetGameObject();
  cStatsCharacter* pStats = static_cast<cStatsCharacter*>(pObj->GetStats());
  return( pStats->CalcMaxHealth() );
}

int Titan::GetPlayerHealth()
{
  cGameObject* pObj = mpInputHandler->GetGameObject();
  cStatsCharacter* pStats = static_cast<cStatsCharacter*>(pObj->GetStats());
  return( pStats->GetHealth() );
}

int Titan::GetPlayerBlockMax()
{
  cGameObject* pObj = mpInputHandler->GetGameObject();
  cStatsCharacter* pStats = static_cast<cStatsCharacter*>(pObj->GetStats());
  return( pStats->CalcMaxBlock() );
}

int Titan::GetPlayerBlock()
{
  cGameObject* pObj = mpInputHandler->GetGameObject();
  cStatsCharacter* pStats = static_cast<cStatsCharacter*>(pObj->GetStats());
  return( pStats->GetBlock() );
}

//============================================================================
// UI Activate String
//============================================================================

bool 
Titan::GetActivateString(char *buffer,int buffLen)
{
  cGameObject* pObj = mpInputHandler->GetGameObject();

  cIntelPlayer* pIntel = static_cast<cIntelPlayer *>(pObj->GetIntel());

  cGameObject* selected = mpRegistry->Fetch(pIntel->PickActionTarget());


  if (selected == NULL)
  {
    return false;
  }

  cStats *stats = selected->GetStats();

  SyString str;
  stats->GetActivateString(&str);

  strncpy(buffer,str.AsChar(),buffLen);

  return true;
};

// EOF
