2067 lines
54 KiB
C++
2067 lines
54 KiB
C++
![]() |
//
|
||
|
// StatsDataMgr.cpp
|
||
|
//
|
||
|
// Copyright (C) 1999-2009 Rockstar Games. All Rights Reserved.
|
||
|
//
|
||
|
|
||
|
// --- Include Files ------------------------------------------------------------
|
||
|
|
||
|
// C headers
|
||
|
|
||
|
// Rage headers
|
||
|
#include "parser/tree.h"
|
||
|
#include "parser/treenode.h"
|
||
|
#include "parser/manager.h"
|
||
|
|
||
|
|
||
|
// Game Headers
|
||
|
#include "FrontendStatsMgr.h"
|
||
|
#include "frontend/ui_channel.h"
|
||
|
#include "Scene/DataFileMgr.h"
|
||
|
#include "scene/extracontent.h"
|
||
|
|
||
|
// Framework headers
|
||
|
#include "fwsys/timer.h"
|
||
|
#include "fwsys/gameskeleton.h"
|
||
|
|
||
|
// Stats headers
|
||
|
#include "Stats/StatsMgr.h"
|
||
|
#include "Stats/stats_channel.h"
|
||
|
#include "Stats/StatsInterface.h"
|
||
|
#include "Stats/StatsUtils.h"
|
||
|
|
||
|
#include "Text/TextConversion.h"
|
||
|
#include "Network/Live/livemanager.h"
|
||
|
#include "modelinfo/vehiclemodelinfo.h"
|
||
|
|
||
|
#if __PPU
|
||
|
#include <sysutil/sysutil_common.h>
|
||
|
#include <sysutil/sysutil_sysparam.h>
|
||
|
#endif
|
||
|
|
||
|
#if RSG_DURANGO || RSG_ORBIS
|
||
|
#define MAX_ASYNC_NAME_LOOKUPS 2
|
||
|
|
||
|
//OPTIMISATIONS_OFF()
|
||
|
|
||
|
bool CFrontendStatsMgr::m_bLookupRequired = false;
|
||
|
int CFrontendStatsMgr::m_iLookupId = CDisplayNamesFromHandles::INVALID_REQUEST_ID;
|
||
|
int CFrontendStatsMgr::m_iNumRequests = 0;
|
||
|
#endif // RSG_DURANGO
|
||
|
|
||
|
CFrontendStatsMgr::UIStatsList CFrontendStatsMgr::m_aSPStatsData;
|
||
|
CFrontendStatsMgr::UIStatsList CFrontendStatsMgr::m_aMPStatsData;
|
||
|
CFrontendStatsMgr::UIStatsList CFrontendStatsMgr::m_aSPSkillStats;
|
||
|
CFrontendStatsMgr::UICategoryList CFrontendStatsMgr::m_aCategoryList;
|
||
|
CFrontendStatsMgr::UIReplacementLabelMap CFrontendStatsMgr::m_ReplacementHashes;
|
||
|
CFrontendStatsMgr::UIStatNameCache CFrontendStatsMgr::m_AsyncStatCache;
|
||
|
CFrontendStatsMgr::MountedFilesHashList CFrontendStatsMgr::m_MountedFiles;
|
||
|
|
||
|
CFrontendStatsMgr::CFrontendStatsMgr() {}
|
||
|
CFrontendStatsMgr::~CFrontendStatsMgr() {}
|
||
|
|
||
|
int statSort(sUIStatData* const* a, sUIStatData* const* b);
|
||
|
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
sUIStatData::sUIStatData(const char* pName, const char* pDescription, u8 uCategory, int uVisible, StatType uType)
|
||
|
{
|
||
|
m_uHash = HASH_STAT_ID(pName);
|
||
|
m_uLocalizedKeyHash = HASH_STAT_ID(pDescription);
|
||
|
m_uCategory = uCategory;
|
||
|
m_iVisibilityRule = uVisible;
|
||
|
m_uStatType = uType;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
sUIStatDataSP::sUIStatDataSP(sUIStatDataSP::statNameList* pStatList, const char* pDescription, u8 uCategory, int uVisible, StatType uType)
|
||
|
{
|
||
|
m_uHash = HASH_STAT_ID(pStatList->szName[0]);
|
||
|
m_iStatHash[0] = HASH_STAT_ID(pStatList->szName[1]);
|
||
|
m_iStatHash[1] = HASH_STAT_ID(pStatList->szName[2]);
|
||
|
m_uLocalizedKeyHash = HASH_STAT_ID(pDescription);
|
||
|
m_uCategory = uCategory;
|
||
|
m_iVisibilityRule = uVisible;
|
||
|
m_uStatType = uType;
|
||
|
}
|
||
|
|
||
|
sUIStatDataSPDetailed::sUIStatDataSPDetailed(sUIStatDataSP::statNameList* pStatList, const char* pDescription, const char* pDetails, u8 uCategory, int uVisible, StatType uType)
|
||
|
: sUIStatDataSP(pStatList, pDescription, uCategory, uVisible, uType)
|
||
|
{
|
||
|
char buff[32];
|
||
|
sprintf(buff, "SP0_%s", pDetails);
|
||
|
m_uDetailHashes[0] = atStringHash(buff);
|
||
|
|
||
|
sprintf(buff, "SP1_%s", pDetails);
|
||
|
m_uDetailHashes[1] = atStringHash(buff);
|
||
|
|
||
|
sprintf(buff, "SP2_%s", pDetails);
|
||
|
m_uDetailHashes[2] = atStringHash(buff);
|
||
|
}
|
||
|
|
||
|
int sUIStatDataSP::GetStatHash(int i) const
|
||
|
{
|
||
|
int iResult = 0;
|
||
|
|
||
|
if (i > STAT_MP_CATEGORY_CHAR1)
|
||
|
return iResult;
|
||
|
|
||
|
if (i ==0)
|
||
|
iResult = m_uHash;
|
||
|
else
|
||
|
{
|
||
|
iResult = m_iStatHash[i-1];
|
||
|
}
|
||
|
|
||
|
return iResult;
|
||
|
}
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
sUIStatDataMP::sUIStatDataMP(sUIStatDataMP::statNameList* pStatList, const char* pDescription, u8 uCategory, int uVisible, StatType uType)
|
||
|
{
|
||
|
m_uHash = HASH_STAT_ID(pStatList->szName[0]);
|
||
|
|
||
|
for (int i=1; i<MAX_NUM_MP_ACTIVE_CHARS; i++)
|
||
|
{
|
||
|
m_iStatHash[i-1] = HASH_STAT_ID(pStatList->szName[i]);
|
||
|
}
|
||
|
|
||
|
m_uLocalizedKeyHash = HASH_STAT_ID(pDescription);
|
||
|
m_uCategory = uCategory;
|
||
|
m_iVisibilityRule = uVisible;
|
||
|
m_uStatType = uType;
|
||
|
}
|
||
|
|
||
|
int sUIStatDataMP::GetStatHash(int i) const
|
||
|
{
|
||
|
int iResult = 0;
|
||
|
|
||
|
if (i>=MAX_NUM_MP_CHARS)
|
||
|
return iResult;
|
||
|
|
||
|
if (i ==0)
|
||
|
iResult = m_uHash;
|
||
|
else
|
||
|
{
|
||
|
iResult = m_iStatHash[i-1];
|
||
|
}
|
||
|
|
||
|
return iResult;
|
||
|
}
|
||
|
|
||
|
class CStatsUIListFileMounter : public CDataFileMountInterface
|
||
|
{
|
||
|
virtual bool LoadDataFile(const CDataFileMgr::DataFile & file)
|
||
|
{
|
||
|
u32 uFileHash = atStringHash(file.m_filename);
|
||
|
if(CFrontendStatsMgr::GetMountedFileList().Find(uFileHash) != -1)
|
||
|
return false;
|
||
|
|
||
|
switch(file.m_fileType)
|
||
|
{
|
||
|
case CDataFileMgr::SP_STATS_UI_LIST_FILE:
|
||
|
CFrontendStatsMgr::LoadDataXMLFile(file.m_filename,true);
|
||
|
CFrontendStatsMgr::GetMountedFileList().PushAndGrow(uFileHash);
|
||
|
return true;
|
||
|
case CDataFileMgr::MP_STATS_UI_LIST_FILE:
|
||
|
CFrontendStatsMgr::LoadDataXMLFile(file.m_filename,false);
|
||
|
CFrontendStatsMgr::GetMountedFileList().PushAndGrow(uFileHash);
|
||
|
return true;
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void UnloadDataFile(const CDataFileMgr::DataFile & ) {}
|
||
|
} g_StatsUIListDataFileMounter;
|
||
|
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
//-----------------------------------------------------------------------------------------------
|
||
|
void CFrontendStatsMgr::Update()
|
||
|
{
|
||
|
#if __XENON
|
||
|
bool bChecking = false;
|
||
|
for(CFrontendStatsMgr::UIStatNameCache::Iterator iter = m_AsyncStatCache.CreateIterator(); !iter.AtEnd(); iter.Next())
|
||
|
{
|
||
|
sUIAsyncCacheData &data = iter.GetData();
|
||
|
bChecking |= data.m_bChecking;
|
||
|
if(!data.m_bReady)
|
||
|
{
|
||
|
if(!CLiveManager::GetFindGamerTag().Pending() && !bChecking)
|
||
|
{
|
||
|
CLiveManager::GetFindGamerTag().Start(data.m_hGamer);
|
||
|
data.m_bChecking = true;
|
||
|
bChecking = true;
|
||
|
}
|
||
|
|
||
|
if(CLiveManager::GetFindGamerTag().Succeeded())
|
||
|
{
|
||
|
sprintf(data.m_Name, "%s", CLiveManager::GetFindGamerTag().GetGamerTag(data.m_hGamer));
|
||
|
if(strcmp(data.m_Name, "") != 0)
|
||
|
{
|
||
|
data.m_bReady = true;
|
||
|
data.m_bChecking = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#elif RSG_DURANGO || RSG_ORBIS
|
||
|
if(m_iLookupId == CDisplayNamesFromHandles::INVALID_REQUEST_ID && m_bLookupRequired)
|
||
|
{
|
||
|
int iCount = 0;
|
||
|
rlGamerHandle gamerHandles[MAX_ASYNC_NAME_LOOKUPS];
|
||
|
for(CFrontendStatsMgr::UIStatNameCache::Iterator iter = m_AsyncStatCache.CreateIterator(); !iter.AtEnd(); iter.Next())
|
||
|
{
|
||
|
sUIAsyncCacheData &data = iter.GetData();
|
||
|
if(data.m_hGamer.IsValid())
|
||
|
{
|
||
|
gamerHandles[iCount] = data.m_hGamer;
|
||
|
data.m_bReady = false;
|
||
|
data.m_bChecking = true;
|
||
|
iCount++;
|
||
|
}
|
||
|
}
|
||
|
m_iNumRequests = iCount;
|
||
|
|
||
|
if(m_iNumRequests > 0)
|
||
|
{
|
||
|
m_iLookupId = CLiveManager::GetFindDisplayName().RequestDisplayNames(NetworkInterface::GetLocalGamerIndex(), gamerHandles, m_iNumRequests);
|
||
|
if(m_iLookupId == CDisplayNamesFromHandles::INVALID_REQUEST_ID)
|
||
|
{
|
||
|
CLiveManager::GetFindDisplayName().CancelRequest(m_iLookupId);
|
||
|
m_iLookupId = CDisplayNamesFromHandles::INVALID_REQUEST_ID;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(m_iLookupId != CDisplayNamesFromHandles::INVALID_REQUEST_ID)
|
||
|
{
|
||
|
rlDisplayName displayNames[CDisplayNamesFromHandles::MAX_DISPLAY_NAMES_PER_REQUEST];
|
||
|
int iStatus = CLiveManager::GetFindDisplayName().GetDisplayNames(m_iLookupId, displayNames, m_iNumRequests);
|
||
|
int iCount = 0;
|
||
|
switch(iStatus)
|
||
|
{
|
||
|
case CDisplayNamesFromHandles::DISPLAY_NAMES_SUCCEEDED:
|
||
|
for(CFrontendStatsMgr::UIStatNameCache::Iterator iter = m_AsyncStatCache.CreateIterator(); !iter.AtEnd(); iter.Next())
|
||
|
{
|
||
|
sUIAsyncCacheData &data = iter.GetData();
|
||
|
sprintf(data.m_Name, "%s", displayNames[iCount]);
|
||
|
if(strcmp(data.m_Name, "") != 0)
|
||
|
{
|
||
|
data.m_bReady = true;
|
||
|
data.m_bChecking = false;
|
||
|
}
|
||
|
iCount++;
|
||
|
}
|
||
|
case CDisplayNamesFromHandles::DISPLAY_NAMES_FAILED:
|
||
|
m_iLookupId = CDisplayNamesFromHandles::INVALID_REQUEST_ID;
|
||
|
m_bLookupRequired = false;
|
||
|
m_iNumRequests = 0;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#endif // RSG_DURANGO || RSG_ORBIS
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::Init(unsigned initMode)
|
||
|
{
|
||
|
m_aSPStatsData.clear();
|
||
|
m_aSPSkillStats.clear();
|
||
|
m_aMPStatsData.clear();
|
||
|
m_aCategoryList.Reset();
|
||
|
m_aCategoryList.Grow(16);
|
||
|
m_ReplacementHashes.Reset();
|
||
|
m_AsyncStatCache.Reset();
|
||
|
m_MountedFiles.Reset();
|
||
|
CDataFileMount::RegisterMountInterface(CDataFileMgr::SP_STATS_UI_LIST_FILE, &g_StatsUIListDataFileMounter);
|
||
|
CDataFileMount::RegisterMountInterface(CDataFileMgr::MP_STATS_UI_LIST_FILE, &g_StatsUIListDataFileMounter);
|
||
|
LoadDataXMLFile(initMode);
|
||
|
|
||
|
#if RSG_DURANGO || RSG_ORBIS
|
||
|
CancelDisplayNameLookup();
|
||
|
#endif // RSG_DURANGO
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::Shutdown(unsigned UNUSED_PARAM(shutdownMode) )
|
||
|
{
|
||
|
m_aSPStatsData.clear();
|
||
|
m_aSPSkillStats.clear();
|
||
|
m_aMPStatsData.clear();
|
||
|
m_aCategoryList.Reset();
|
||
|
m_ReplacementHashes.Reset();
|
||
|
m_AsyncStatCache.Reset();
|
||
|
m_MountedFiles.Reset();
|
||
|
|
||
|
#if RSG_DURANGO || RSG_ORBIS
|
||
|
CancelDisplayNameLookup();
|
||
|
#endif // RSG_DURANGO || RSG_ORBIS
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::LoadDataXMLFile(const unsigned initMode)
|
||
|
{
|
||
|
if (INIT_CORE == initMode)
|
||
|
{
|
||
|
Shutdown(SHUTDOWN_CORE);
|
||
|
|
||
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetLastFile(CDataFileMgr::SP_STATS_UI_LIST_FILE);
|
||
|
if (DATAFILEMGR.IsValid(pData))
|
||
|
{
|
||
|
// Read in this particular file
|
||
|
LoadDataXMLFile(pData->m_filename, true);
|
||
|
|
||
|
// Get next file
|
||
|
pData = DATAFILEMGR.GetPrevFile(pData);
|
||
|
|
||
|
DEV_ONLY(if (m_aSPStatsData.empty()) statWarningf("Single Player stats are empty");)
|
||
|
}
|
||
|
|
||
|
const CDataFileMgr::DataFile* pMPData = DATAFILEMGR.GetLastFile(CDataFileMgr::MP_STATS_UI_LIST_FILE);
|
||
|
if (DATAFILEMGR.IsValid(pMPData))
|
||
|
{
|
||
|
// Read in this particular file
|
||
|
LoadDataXMLFile(pMPData->m_filename, false);
|
||
|
|
||
|
// Get next file
|
||
|
pData = DATAFILEMGR.GetPrevFile(pMPData);
|
||
|
|
||
|
DEV_ONLY(if (m_aMPStatsData.empty()) statWarningf("Multiplayer stats are empty");)
|
||
|
}
|
||
|
|
||
|
|
||
|
statDebugf1("-----------------------------------------------------------------");
|
||
|
statDebugf1(" Number of UI stats = \"%d\"", m_aSPStatsData.size());
|
||
|
statDebugf1(" Sizeof UI Stats = \"%" SIZETFMT "d\"", m_aSPStatsData.size()*sizeof(sUIStatData));
|
||
|
statDebugf1("-----------------------------------------------------------------");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::LoadDataXMLFile(const char* pFileName, bool bSinglePlayer)
|
||
|
{
|
||
|
|
||
|
if (AssertVerify(pFileName))
|
||
|
{
|
||
|
parTree* pTree = PARSER.LoadTree(pFileName, "xml");
|
||
|
if(pTree)
|
||
|
{
|
||
|
parTreeNode* pRootNode = pTree->GetRoot();
|
||
|
if(pRootNode)
|
||
|
{
|
||
|
parTreeNode::ChildNodeIterator it = pRootNode->BeginChildren();
|
||
|
for(; it != pRootNode->EndChildren(); ++it)
|
||
|
{
|
||
|
if(stricmp((*it)->GetElement().GetName(), "stats") == 0)
|
||
|
{
|
||
|
LoadStatsData((*it), bSinglePlayer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Old stat sort. Uncomment if design wants stats sorted again.
|
||
|
// if (bSinglePlayer)
|
||
|
// {
|
||
|
// m_aSPStatsData.QSort(0,m_aSPStatsData.GetCount(), statSort);
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// m_aMPStatsData.QSort(0,m_aMPStatsData.GetCount(), statSort);
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
delete pTree;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::LoadStatsData(parTreeNode* pNode, bool bSinglePlayer)
|
||
|
{
|
||
|
if(pNode)
|
||
|
{
|
||
|
parTreeNode::ChildNodeIterator it = pNode->BeginChildren();
|
||
|
for(; it != pNode->EndChildren(); ++it)
|
||
|
{
|
||
|
u32 uCategory= 0;
|
||
|
// Verify Categories and add them to the list of categories.
|
||
|
if(stricmp((*it)->GetElement().GetName(), "Category") == 0)
|
||
|
{
|
||
|
Assertf((*it)->GetElement().FindAttribute("label"), "Missing attribute \"label\"");
|
||
|
|
||
|
if ((*it)->GetElement().FindAttribute("label"))
|
||
|
{
|
||
|
const char* pStatIdCategory = (*it)->GetElement().FindAttributeAnyCase("label")->GetStringValue();
|
||
|
|
||
|
if (AssertVerify(pStatIdCategory) )
|
||
|
{
|
||
|
sUICategoryData* pCategory = NULL;
|
||
|
for(u32 i = 0; i< m_aCategoryList.GetCount(); ++i)
|
||
|
{
|
||
|
if(strcmp(m_aCategoryList[i]->m_Name,pStatIdCategory)==0)
|
||
|
{
|
||
|
pCategory = m_aCategoryList[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(!pCategory)
|
||
|
{
|
||
|
pCategory = rage_new sUICategoryData(pStatIdCategory, bSinglePlayer);
|
||
|
m_aCategoryList.PushAndGrow(pCategory);
|
||
|
}
|
||
|
for(u32 i=0;i<m_aCategoryList.GetCount();i++)
|
||
|
{
|
||
|
if(pCategory == m_aCategoryList[i])
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
if(m_aCategoryList[i]->m_bSinglePlayer == bSinglePlayer)
|
||
|
uCategory++;
|
||
|
}
|
||
|
parTreeNode::ChildNodeIterator statIterator = (*it)->BeginChildren();
|
||
|
for(; statIterator != (*statIterator)->EndChildren(); ++statIterator )
|
||
|
{
|
||
|
// Check for individual stats.
|
||
|
if (stricmp((*statIterator)->GetElement().GetName(), "Stat") == 0)
|
||
|
{
|
||
|
Assertf((*statIterator)->GetElement().FindAttribute("name"), "Missing attribute \"name\"");
|
||
|
Assertf((*statIterator)->GetElement().FindAttribute("visible"), "Missing attribute \"visible\"");
|
||
|
Assertf((*statIterator)->GetElement().FindAttribute("type"), "Missing attribute \"type\"");
|
||
|
|
||
|
if ( (*statIterator)->GetElement().FindAttribute("name")
|
||
|
&& (*statIterator)->GetElement().FindAttribute("visible")
|
||
|
&& (*statIterator)->GetElement().FindAttribute("type") )
|
||
|
{
|
||
|
atArray<sUIReplacementTag> tags;
|
||
|
const char* pStatIdName = (*statIterator)->GetElement().FindAttributeAnyCase("name")->GetStringValue();
|
||
|
const char* pStatVisibility = (*statIterator)->GetElement().FindAttributeAnyCase("visible")->GetStringValue();
|
||
|
const char* pStatType = (*statIterator)->GetElement().FindAttributeAnyCase("type")->GetStringValue();
|
||
|
const char* pDetails = NULL;
|
||
|
const char* pDescription = NULL;
|
||
|
bool bCharacterStat = (*statIterator)->GetElement().FindAttributeBoolValue("characterStat",true);
|
||
|
bool bLabelAndValue = (*statIterator)->GetElement().FindAttributeBoolValue("labelAndValue",false);
|
||
|
|
||
|
if ((*statIterator)->GetElement().FindAttributeAnyCase("label"))
|
||
|
{
|
||
|
pDescription = (*statIterator)->GetElement().FindAttributeAnyCase("label")->GetStringValue();
|
||
|
}
|
||
|
|
||
|
if ((*statIterator)->GetElement().FindAttributeAnyCase("details"))
|
||
|
{
|
||
|
pDetails = (*statIterator)->GetElement().FindAttributeAnyCase("details")->GetStringValue();
|
||
|
}
|
||
|
|
||
|
parTreeNode::ChildNodeIterator replacementTagIter = (*statIterator)->BeginChildren();
|
||
|
for(; replacementTagIter != (*replacementTagIter)->EndChildren(); ++replacementTagIter)
|
||
|
{
|
||
|
Assertf((*replacementTagIter)->GetElement().FindAttribute("minValue"), "Missing attribute \"minValue\"");
|
||
|
Assertf((*replacementTagIter)->GetElement().FindAttribute("maxValue"), "Missing attribute \"maxValue\"");
|
||
|
Assertf((*replacementTagIter)->GetElement().FindAttribute("label"), "Missing attribute \"label\"");
|
||
|
|
||
|
if ( (*replacementTagIter)->GetElement().FindAttribute("minValue")
|
||
|
&& (*replacementTagIter)->GetElement().FindAttribute("maxValue")
|
||
|
&& (*replacementTagIter)->GetElement().FindAttribute("label") )
|
||
|
{
|
||
|
int minValue = (*replacementTagIter)->GetElement().FindAttributeIntValue("minValue", 0);
|
||
|
int maxValue = (*replacementTagIter)->GetElement().FindAttributeIntValue("maxValue", 0);
|
||
|
bool rawNumber = (*replacementTagIter)->GetElement().FindAttributeBoolValue("rawNumber", false);
|
||
|
char strLabel[32];
|
||
|
sprintf(strLabel, "%s", (*replacementTagIter)->GetElement().FindAttributeAnyCase("label")->GetStringValue());
|
||
|
u32 nameHash = rawNumber ? atoi(strLabel) : atStringHash(strLabel);
|
||
|
|
||
|
sUIReplacementTag replacementTag(minValue,maxValue,nameHash,bLabelAndValue);
|
||
|
tags.PushAndGrow(replacementTag);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bCharacterStat)
|
||
|
{
|
||
|
RegisterNewStatForEachCharacter(pStatIdName
|
||
|
, pDescription
|
||
|
, pDetails
|
||
|
, (u8)uCategory
|
||
|
, GetVisibilityFromXML(pStatVisibility)
|
||
|
, GetStatTypeFromXML(pStatType)
|
||
|
, tags
|
||
|
, bSinglePlayer );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RegisterNewStat( pStatIdName
|
||
|
, pDescription
|
||
|
, pDetails
|
||
|
, (u8)uCategory
|
||
|
, GetVisibilityFromXML(pStatVisibility)
|
||
|
, GetStatTypeFromXML(pStatType)
|
||
|
, tags
|
||
|
, bSinglePlayer );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CFrontendStatsMgr::RegisterNewStatForEachCharacter(const char* pName
|
||
|
,const char* pDescription
|
||
|
,const char* pDetails
|
||
|
,u8 uCategory
|
||
|
,int bVisible
|
||
|
,StatType uType
|
||
|
,atArray<sUIReplacementTag>& tags
|
||
|
,bool bSinglePlayer)
|
||
|
{
|
||
|
|
||
|
if (bSinglePlayer)
|
||
|
{
|
||
|
sUIStatDataSP::statNameList oNames;
|
||
|
|
||
|
for (int i= 0; i < STAT_SP_CATEGORY_CHAR2; i++)
|
||
|
{
|
||
|
snprintf(oNames.szName[i], MAX_STAT_LABEL_SIZE, "SP%d_%s", i, pName);
|
||
|
oNames.szName[i][MAX_STAT_LABEL_SIZE-1] = '\0';
|
||
|
|
||
|
#if __BANK
|
||
|
const CStatsDataMgr& statsDataMgr = CStatsMgr::GetStatsDataMgr();
|
||
|
const sStatData* stat = statsDataMgr.GetStat(atHashValue::ComputeHash(oNames.szName[i]));
|
||
|
if (!stat)
|
||
|
{
|
||
|
char szErrorMsg[128];
|
||
|
formatf(szErrorMsg,128,"FrontendStatManager - Stat %s doesn't exist.",oNames.szName[i]);
|
||
|
AssertMsg(0,szErrorMsg);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if(pDetails != NULL)
|
||
|
{
|
||
|
sUIStatDataSPDetailed* pStatSlot = rage_new sUIStatDataSPDetailed(&oNames
|
||
|
,pDescription ? pDescription : pName
|
||
|
,pDetails
|
||
|
,uCategory
|
||
|
,bVisible
|
||
|
,uType);
|
||
|
|
||
|
//Insert stat in StatsMap
|
||
|
if (pStatSlot)
|
||
|
{
|
||
|
m_aSPStatsData.PushAndGrow(pStatSlot);
|
||
|
m_aSPSkillStats.PushAndGrow(pStatSlot);
|
||
|
|
||
|
if(tags.GetCount() > 0)
|
||
|
{
|
||
|
m_ReplacementHashes.Insert(pStatSlot->GetStatHash(0), tags);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sUIStatDataSP* pStatSlot = rage_new sUIStatDataSP(&oNames
|
||
|
,pDescription ? pDescription : pName
|
||
|
,uCategory
|
||
|
,bVisible
|
||
|
,uType);
|
||
|
|
||
|
//Insert stat in StatsMap
|
||
|
if (pStatSlot)
|
||
|
{
|
||
|
m_aSPStatsData.PushAndGrow(pStatSlot);
|
||
|
|
||
|
if(tags.GetCount() > 0)
|
||
|
{
|
||
|
m_ReplacementHashes.Insert(pStatSlot->GetStatHash(0), tags);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sUIStatDataMP::statNameList oNames;
|
||
|
|
||
|
for (int i=0; i<MAX_NUM_MP_ACTIVE_CHARS; i++)
|
||
|
{
|
||
|
snprintf(oNames.szName[i], MAX_STAT_LABEL_SIZE, "MP%d_%s", i, pName);
|
||
|
oNames.szName[i][MAX_STAT_LABEL_SIZE-1] = '\0';
|
||
|
|
||
|
#if __BANK
|
||
|
const CStatsDataMgr& statsDataMgr = CStatsMgr::GetStatsDataMgr();
|
||
|
const sStatData* stat = statsDataMgr.GetStat(atHashValue::ComputeHash(oNames.szName[i]));
|
||
|
if (!stat)
|
||
|
{
|
||
|
char szErrorMsg[128];
|
||
|
formatf(szErrorMsg,128,"FrontendStatManager - Stat %s doesn't exist.",oNames.szName[i]);
|
||
|
AssertMsg(0,szErrorMsg);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
sUIStatDataMP* pStatSlot = rage_new sUIStatDataMP(&oNames
|
||
|
,pDescription ? pDescription : pName
|
||
|
,uCategory
|
||
|
,bVisible
|
||
|
,uType);
|
||
|
|
||
|
//Insert stat in StatsMap
|
||
|
if (pStatSlot)
|
||
|
{
|
||
|
m_aMPStatsData.PushAndGrow(pStatSlot);
|
||
|
|
||
|
if(tags.GetCount() > 0)
|
||
|
{
|
||
|
m_ReplacementHashes.Insert(pStatSlot->GetStatHash(0), tags);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
sUIStatData*
|
||
|
CFrontendStatsMgr::RegisterNewStat(const char* pName
|
||
|
,const char* pDescription
|
||
|
,const char* UNUSED_PARAM(pDetails)
|
||
|
,u8 uCategory
|
||
|
,int bVisible
|
||
|
,StatType uType
|
||
|
,atArray<sUIReplacementTag>& tags
|
||
|
,bool bSinglePlayer)
|
||
|
{
|
||
|
|
||
|
#if __BANK
|
||
|
const CStatsDataMgr& statsDataMgr = CStatsMgr::GetStatsDataMgr();
|
||
|
const sStatData* stat = statsDataMgr.GetStat(atHashValue::ComputeHash(pName));
|
||
|
if (!stat)
|
||
|
{
|
||
|
char szErrorMsg[128];
|
||
|
formatf(szErrorMsg,128,"FrontendStatManager - Stat %s doesn't exist.",pName);
|
||
|
AssertMsg(0,szErrorMsg);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
sUIStatData* pStatSlot = rage_new sUIStatData(pName
|
||
|
,pDescription ? pDescription : pName
|
||
|
,uCategory
|
||
|
,bVisible
|
||
|
,uType);
|
||
|
|
||
|
statAssert(pStatSlot);
|
||
|
if (!pStatSlot)
|
||
|
return NULL;
|
||
|
|
||
|
if(tags.GetCount() > 0)
|
||
|
{
|
||
|
m_ReplacementHashes.Insert(pStatSlot->GetStatHash(0), tags);
|
||
|
}
|
||
|
|
||
|
//Insert stat in StatsMap
|
||
|
if (bSinglePlayer)
|
||
|
{
|
||
|
m_aSPStatsData.PushAndGrow(pStatSlot);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_aMPStatsData.PushAndGrow(pStatSlot);
|
||
|
}
|
||
|
|
||
|
return pStatSlot;
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::GetDataAsString(const sStatDataPtr* ppStat, const sUIStatData* pStatUI, char* outBuffer, u32 bufferSize)
|
||
|
{
|
||
|
if (!pStatUI || !outBuffer )
|
||
|
return;
|
||
|
|
||
|
const sStatData* pStat = 0;
|
||
|
if (ppStat && ppStat->KeyIsvalid())
|
||
|
{
|
||
|
pStat = *ppStat;
|
||
|
}
|
||
|
|
||
|
if (!pStat)
|
||
|
return;
|
||
|
|
||
|
switch (pStat->GetType())
|
||
|
{
|
||
|
case STAT_TYPE_INT:
|
||
|
{
|
||
|
s32 sData = (s32)StatsInterface::GetIntStat(ppStat->GetKey());
|
||
|
FormatDataAsType(pStatUI, outBuffer, bufferSize, sData);
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_USERID:
|
||
|
{
|
||
|
if(pStatUI->GetType() == eStatType_PlayerID)
|
||
|
{
|
||
|
char pStatText[128];
|
||
|
bool bSuccess = pStat->GetUserId(pStatText, 128);
|
||
|
|
||
|
if(!bSuccess || strcmp(pStatText, "0") == 0)
|
||
|
{
|
||
|
char* str = TheText.Get(ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A), "STAT_TYPE_PLAYERID");
|
||
|
CText::FilterOutTokensFromString(str); // remove any markers
|
||
|
FormatDataAsType(outBuffer, bufferSize, str);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if __PS3 || RSG_PC
|
||
|
::sprintf(outBuffer, "%s", pStatText);
|
||
|
#elif __XENON || RSG_DURANGO || RSG_ORBIS
|
||
|
#if RSG_ORBIS
|
||
|
if (!rlGamerHandle::IsUsingAccountIdAsKey())
|
||
|
{
|
||
|
::sprintf(outBuffer, "%s", pStatText);
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
sUIAsyncCacheData* pCachedName = m_AsyncStatCache.Access(pStatUI->GetStatHash(0));
|
||
|
if (pCachedName)
|
||
|
{
|
||
|
if (strcmp(pCachedName->m_UID, pStatText) == 0)
|
||
|
{
|
||
|
::sprintf(outBuffer, "%s", pCachedName->m_Name);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprintf(pCachedName->m_UID, "%s", pStatText);
|
||
|
pCachedName->m_hGamer.FromUserId(pStatText);
|
||
|
|
||
|
if (!pCachedName->m_hGamer.IsValid())
|
||
|
{
|
||
|
sprintf(pCachedName->m_Name, "%s", TheText.Get(ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A), "STAT_TYPE_PLAYERID"));
|
||
|
::sprintf(outBuffer, "%s", pCachedName->m_Name);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pCachedName->m_bReady = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sUIAsyncCacheData cacheData;
|
||
|
cacheData.m_bReady = false;
|
||
|
cacheData.m_hGamer.FromUserId(pStatText);
|
||
|
sprintf(cacheData.m_UID, "%s", pStatText);
|
||
|
sprintf(cacheData.m_Name, "%s", TheText.Get(ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A), "STAT_TYPE_PLAYERID"));
|
||
|
|
||
|
m_AsyncStatCache.Insert(pStatUI->GetStatHash(0), cacheData);
|
||
|
::sprintf(outBuffer, "%s", TheText.Get(ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A), "STAT_TYPE_PLAYERID"));
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
// For when we have to handle this on other platforms
|
||
|
::sprintf(outBuffer, "%s", pStatText);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_PERCENT:
|
||
|
case STAT_TYPE_UINT32:
|
||
|
{
|
||
|
u32 uData = (u32)StatsInterface::GetUInt32Stat(ppStat->GetKey());
|
||
|
FormatDataAsType(pStatUI, outBuffer, bufferSize, uData);
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_PACKED:
|
||
|
case STAT_TYPE_UINT64:
|
||
|
case STAT_TYPE_DATE:
|
||
|
{
|
||
|
u64 uData = (u64)StatsInterface::GetUInt64Stat(ppStat->GetKey());
|
||
|
FormatDataAsType(pStatUI, outBuffer, bufferSize, uData);
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_INT64:
|
||
|
{
|
||
|
s64 uData = (s64)StatsInterface::GetInt64Stat(ppStat->GetKey());
|
||
|
FormatDataAsType(pStatUI, outBuffer, bufferSize, uData);
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_FLOAT:
|
||
|
{
|
||
|
float fData = StatsInterface::GetFloatStat(ppStat->GetKey());
|
||
|
FormatDataAsType(pStatUI, outBuffer, bufferSize, fData);
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_TEXTLABEL:
|
||
|
{ // number is string:
|
||
|
|
||
|
int iStatHash = ppStat->GetKey();
|
||
|
StatId statMissionName(iStatHash);
|
||
|
int iStatValue = StatsInterface::GetIntStat(statMissionName);
|
||
|
char* pStatText = NULL;
|
||
|
|
||
|
if (iStatValue)
|
||
|
{
|
||
|
pStatText = TheText.Get(iStatValue, "STAT_TYPE_TEXTLABEL");
|
||
|
CText::FilterOutTokensFromString(pStatText); // remove any markers
|
||
|
FormatDataAsType(outBuffer, bufferSize, pStatText);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iStatValue = ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A);
|
||
|
pStatText = TheText.Get(iStatValue, "STAT_TYPE_TEXTLABEL");
|
||
|
CText::FilterOutTokensFromString(pStatText); // remove any markers
|
||
|
FormatDataAsType(outBuffer, bufferSize, pStatText);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_BOOLEAN:
|
||
|
{
|
||
|
bool bData = StatsInterface::GetBooleanStat(ppStat->GetKey());
|
||
|
FormatDataAsType(pStatUI, outBuffer, bufferSize, bData);
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_STRING:
|
||
|
{
|
||
|
if(strcmp(pStat->GetString(), "") == 0)
|
||
|
{
|
||
|
char* str = TheText.Get(ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A), "STAT_TYPE_PLAYERID");
|
||
|
CText::FilterOutTokensFromString(str); // remove any markers
|
||
|
FormatDataAsType(outBuffer, bufferSize, str);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
formatf(outBuffer, bufferSize, "%s",pStat->GetString());
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_DEGREES:
|
||
|
case STAT_TYPE_WEIGHT:
|
||
|
case STAT_TYPE_CASH:
|
||
|
case STAT_TYPE_METERS:
|
||
|
case STAT_TYPE_TIME:
|
||
|
case STAT_TYPE_FEET:
|
||
|
case STAT_TYPE_MILES:
|
||
|
case STAT_TYPE_VELOCITY:
|
||
|
case STAT_TYPE_SECONDS:
|
||
|
{
|
||
|
AssertMsg(0,"STAT_TYPE unhandled. Please add to this switch statement or contact cconlon.");
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
::sprintf(outBuffer, "NOTYPE:%d", StatsInterface::GetStatType(ppStat->GetKey()));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
float CFrontendStatsMgr::GetDataAsPercent(const sStatDataPtr* ppStat, const sUIStatData* pStatUI)
|
||
|
{
|
||
|
if (!pStatUI)
|
||
|
return 0.0f;
|
||
|
|
||
|
const sStatData* pStat = 0;
|
||
|
if (ppStat && ppStat->KeyIsvalid())
|
||
|
{
|
||
|
pStat = *ppStat;
|
||
|
}
|
||
|
|
||
|
if (!pStat)
|
||
|
return 0.0f;
|
||
|
|
||
|
float percent = 0.0f;
|
||
|
switch (pStat->GetType())
|
||
|
{
|
||
|
case STAT_TYPE_INT:
|
||
|
{
|
||
|
if(pStatUI->GetType() != eStatType_Checklist)
|
||
|
{
|
||
|
s32 sData = (s32)StatsInterface::GetIntStat(ppStat->GetKey());
|
||
|
if(pStatUI->GetType() == eStatType_Percent)
|
||
|
{
|
||
|
percent = sData / 100.0f;
|
||
|
}
|
||
|
else if(pStatUI->GetType() == eStatType_Fraction)
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData)
|
||
|
{
|
||
|
float divisor = (float)GetReplacementLocalizedHash(statHash, sData);
|
||
|
percent = sData / divisor;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData && tagData->GetCount() == 2)
|
||
|
{
|
||
|
u32 uNumeratorHash = (*tagData)[0].m_uHash;
|
||
|
u32 uDenominatorHash = (*tagData)[1].m_uHash;
|
||
|
|
||
|
float fNumerator = (float)StatsInterface::GetIntStat(uNumeratorHash);
|
||
|
float fDenominator = (float)StatsInterface::GetIntStat(uDenominatorHash);
|
||
|
|
||
|
if(fDenominator != 0)
|
||
|
{
|
||
|
percent = fNumerator / fDenominator;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
percent = 0.0f;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_PERCENT:
|
||
|
case STAT_TYPE_UINT32:
|
||
|
{
|
||
|
if(pStatUI->GetType() != eStatType_Checklist)
|
||
|
{
|
||
|
u32 uData = (u32)StatsInterface::GetUInt32Stat(ppStat->GetKey());
|
||
|
if(pStatUI->GetType() == eStatType_Percent)
|
||
|
{
|
||
|
percent = uData / 100.0f;
|
||
|
}
|
||
|
else if(pStatUI->GetType() == eStatType_Fraction)
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData)
|
||
|
{
|
||
|
float divisor = (float)GetReplacementLocalizedHash(statHash, uData);
|
||
|
percent = uData / divisor;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData && tagData->GetCount() == 2)
|
||
|
{
|
||
|
u32 uNumeratorHash = (*tagData)[0].m_uHash;
|
||
|
u32 uDenominatorHash = (*tagData)[1].m_uHash;
|
||
|
|
||
|
float fNumerator = (float)StatsInterface::GetIntStat(uNumeratorHash);
|
||
|
float fDenominator = (float)StatsInterface::GetIntStat(uDenominatorHash);
|
||
|
|
||
|
if(fDenominator != 0)
|
||
|
{
|
||
|
percent = fNumerator / fDenominator;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
percent = 0.0f;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_FLOAT:
|
||
|
{
|
||
|
if(pStatUI->GetType() != eStatType_Checklist)
|
||
|
{
|
||
|
float fData = StatsInterface::GetFloatStat(ppStat->GetKey());
|
||
|
if(pStatUI->GetType() == eStatType_Percent)
|
||
|
{
|
||
|
percent = fData / 100.0f;
|
||
|
}
|
||
|
else if(pStatUI->GetType() == eStatType_Fraction)
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData)
|
||
|
{
|
||
|
float divisor = (float)GetReplacementLocalizedHash(statHash, (int)fData);
|
||
|
percent = fData / divisor;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData && tagData->GetCount() == 2)
|
||
|
{
|
||
|
u32 uNumeratorHash = (*tagData)[0].m_uHash;
|
||
|
u32 uDenominatorHash = (*tagData)[1].m_uHash;
|
||
|
|
||
|
float fNumerator = (float)StatsInterface::GetIntStat(uNumeratorHash);
|
||
|
float fDenominator = (float)StatsInterface::GetIntStat(uDenominatorHash);
|
||
|
|
||
|
if(fDenominator != 0)
|
||
|
{
|
||
|
percent = fNumerator / fDenominator;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
percent = 0.0f;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case STAT_TYPE_TEXTLABEL:
|
||
|
case STAT_TYPE_USERID:
|
||
|
case STAT_TYPE_PACKED:
|
||
|
case STAT_TYPE_UINT64:
|
||
|
case STAT_TYPE_INT64:
|
||
|
case STAT_TYPE_DATE:
|
||
|
case STAT_TYPE_BOOLEAN:
|
||
|
case STAT_TYPE_DEGREES:
|
||
|
case STAT_TYPE_WEIGHT:
|
||
|
case STAT_TYPE_CASH:
|
||
|
case STAT_TYPE_METERS:
|
||
|
case STAT_TYPE_TIME:
|
||
|
case STAT_TYPE_FEET:
|
||
|
case STAT_TYPE_MILES:
|
||
|
case STAT_TYPE_VELOCITY:
|
||
|
case STAT_TYPE_SECONDS:
|
||
|
case STAT_TYPE_STRING:
|
||
|
default:
|
||
|
{
|
||
|
AssertMsg(0,"STAT_TYPE unhandled. Please add to this switch statement or contact cconlon.");
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return percent;
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatDataAsType(const sUIStatData* pStatUI, char* outBuffer, u32 bufferSize, s32 sData)
|
||
|
{
|
||
|
switch(pStatUI->GetType())
|
||
|
{
|
||
|
case eStatType_Int:
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData)
|
||
|
{
|
||
|
char* gxt = 0;
|
||
|
gxt = TheText.Get(GetReplacementLocalizedHash(statHash, sData), "UNKNOWN");
|
||
|
|
||
|
if((*tagData)[0].m_bUseLabelAndValue)
|
||
|
{
|
||
|
::sprintf(outBuffer,"%s (%d)", gxt, sData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::sprintf(outBuffer,"%s", gxt);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int iData = (int)sData;
|
||
|
char humanIntBuff[32];
|
||
|
int stringSize = sizeof(humanIntBuff)/sizeof(humanIntBuff[0]);
|
||
|
CTextConversion::FormatIntForHumans(iData, humanIntBuff, stringSize, "%s");
|
||
|
::sprintf(outBuffer,"%s",humanIntBuff);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Float:
|
||
|
{
|
||
|
float fData = (float)sData;
|
||
|
::sprintf(outBuffer,"%.2f",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Percent:
|
||
|
{
|
||
|
float fData = (float)sData;
|
||
|
::sprintf(outBuffer,"%.2f%%",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Distance:
|
||
|
{
|
||
|
float fData = (float)sData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? METERS_TO_KILOMETERS(fData) : METERS_TO_MILES(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KILO") : TheText.Get("UNIT_MILES"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_ShortDistance:
|
||
|
{
|
||
|
float fData = (float)sData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? fData : METERS_TO_FEET(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_METERS") : TheText.Get("UNIT_FEET"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Speed:
|
||
|
{
|
||
|
float fData = (float)sData;
|
||
|
::sprintf(outBuffer,"%.2f%s",
|
||
|
ShouldUseMetric() ? fData : KPH_TO_MPH(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KPH") : TheText.Get("UNIT_MPH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Time:
|
||
|
{
|
||
|
CStatsUtils::GetTime(sData, outBuffer, bufferSize, true);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Cash:
|
||
|
{
|
||
|
s64 iData = (int)sData;
|
||
|
char cashBuff[32];
|
||
|
FormatInt64ToCash(iData, cashBuff, sizeof(cashBuff)/sizeof(cashBuff[0]));
|
||
|
::sprintf(outBuffer,"%s",cashBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_NameHash:
|
||
|
{
|
||
|
u32 uData = sData ? (u32)sData : ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A);
|
||
|
::sprintf(outBuffer, "%s", TheText.Get(uData, "NAME_HASH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_CarHash:
|
||
|
{
|
||
|
u32 uData = (u32)sData;
|
||
|
::sprintf(outBuffer, "%s", GetVehicleNameFromHashKey(uData));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bool:
|
||
|
{
|
||
|
bool bData = sData ? true : false ;
|
||
|
|
||
|
if (bData)
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_YES"));
|
||
|
else
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_NO"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Date:
|
||
|
{
|
||
|
u64 uData = (u64)sData;
|
||
|
int year;
|
||
|
int month;
|
||
|
int day;
|
||
|
int hour;
|
||
|
int minutes;
|
||
|
int seconds;
|
||
|
int milliseconds;
|
||
|
|
||
|
StatsInterface::UnPackDate(uData, year, month, day, hour, minutes,seconds, milliseconds);
|
||
|
::sprintf(outBuffer, "%04d / %02d / %02d",year,month,day);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bar:
|
||
|
{
|
||
|
::sprintf(outBuffer,"");
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Fraction:
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData)
|
||
|
{
|
||
|
int divisor = GetReplacementLocalizedHash(statHash, sData);
|
||
|
::sprintf(outBuffer,"%d / %d", sData, divisor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::sprintf(outBuffer,"%d", sData);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Checklist:
|
||
|
{
|
||
|
u32 statHash = pStatUI->GetStatHash(0);
|
||
|
int iNumerator = 0;
|
||
|
int iDenominator = 0;
|
||
|
atArray<sUIReplacementTag>* tagData = m_ReplacementHashes.Access(statHash);
|
||
|
if(tagData && tagData->GetCount() == 2)
|
||
|
{
|
||
|
u32 uNumeratorHash = (*tagData)[0].m_uHash;
|
||
|
u32 uDenominatorHash = (*tagData)[1].m_uHash;
|
||
|
|
||
|
iNumerator = StatsInterface::GetIntStat(uNumeratorHash);
|
||
|
iDenominator = StatsInterface::GetIntStat(uDenominatorHash);
|
||
|
}
|
||
|
|
||
|
::sprintf(outBuffer,"%d / %d", iNumerator, iDenominator);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
AssertMsg(0,"Unhandled Type.");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatDataAsType(const sUIStatData* pStatUI, char* outBuffer, u32 bufferSize, u32 uData)
|
||
|
{
|
||
|
switch(pStatUI->GetType())
|
||
|
{
|
||
|
case eStatType_Int:
|
||
|
{
|
||
|
int iData = (int)uData;
|
||
|
char humanIntBuff[32];
|
||
|
int stringSize = sizeof(humanIntBuff)/sizeof(humanIntBuff[0]);
|
||
|
CTextConversion::FormatIntForHumans(iData, humanIntBuff, stringSize, "%s");
|
||
|
::sprintf(outBuffer,"%s",humanIntBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Float:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Percent:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f%%",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Distance:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? METERS_TO_KILOMETERS(fData) : METERS_TO_MILES(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KILO") : TheText.Get("UNIT_MILES"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_ShortDistance:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? fData : METERS_TO_FEET(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_METERS") : TheText.Get("UNIT_FEET"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Speed:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f%s",
|
||
|
ShouldUseMetric() ? fData : KPH_TO_MPH(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KPH") : TheText.Get("UNIT_MPH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Time:
|
||
|
{
|
||
|
CStatsUtils::GetTime((s32)uData, outBuffer, bufferSize, true);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Cash:
|
||
|
{
|
||
|
s64 iData = (int)uData;
|
||
|
char cashBuff[32];
|
||
|
FormatInt64ToCash(iData, cashBuff, sizeof(cashBuff)/sizeof(cashBuff[0]));
|
||
|
::sprintf(outBuffer,"%s",cashBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_NameHash:
|
||
|
{
|
||
|
u32 hashData = uData ? uData : ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A);
|
||
|
::sprintf(outBuffer, "%s", TheText.Get(hashData, "NAME_HASH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_CarHash:
|
||
|
{
|
||
|
::sprintf(outBuffer, "%s", GetVehicleNameFromHashKey(uData));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bool:
|
||
|
{
|
||
|
bool bData = uData ? true : false;
|
||
|
if (bData)
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_YES"));
|
||
|
else
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_NO"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Date:
|
||
|
{
|
||
|
|
||
|
int year;
|
||
|
int month;
|
||
|
int day;
|
||
|
int hour;
|
||
|
int minutes;
|
||
|
int seconds;
|
||
|
int milliseconds;
|
||
|
|
||
|
StatsInterface::UnPackDate((u64)uData, year, month, day, hour, minutes,seconds, milliseconds);
|
||
|
::sprintf(outBuffer, "%04d / %02d / %02d",year,month,day);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bar:
|
||
|
{
|
||
|
::sprintf(outBuffer,"");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
AssertMsg(0,"Unhandled Type.");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatDataAsType(const sUIStatData* pStatUI, char* outBuffer, u32 bufferSize, bool bData)
|
||
|
{
|
||
|
switch(pStatUI->GetType())
|
||
|
{
|
||
|
case eStatType_Int:
|
||
|
{
|
||
|
int iData = bData ? 1 : 0;
|
||
|
|
||
|
::sprintf(outBuffer,"%d",iData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Float:
|
||
|
{
|
||
|
float fData = bData ? 1.0f : 0.0f;
|
||
|
::sprintf(outBuffer,"%.2f",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Percent:
|
||
|
{
|
||
|
float fData = bData ? 1.0f : 0.0f;
|
||
|
::sprintf(outBuffer,"%.2f%%",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Distance:
|
||
|
{
|
||
|
float fData = bData ? 1.0f : 0.0f;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? METERS_TO_KILOMETERS(fData) : METERS_TO_MILES(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KILO") : TheText.Get("UNIT_MILES"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_ShortDistance:
|
||
|
{
|
||
|
float fData = bData ? 1.0f : 0.0f;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? fData : METERS_TO_FEET(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_METERS") : TheText.Get("UNIT_FEET"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Speed:
|
||
|
{
|
||
|
float fData = bData ? 1.0f : 0.0f;
|
||
|
::sprintf(outBuffer,"%.2f%s",
|
||
|
ShouldUseMetric() ? fData : KPH_TO_MPH(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KPH") : TheText.Get("UNIT_MPH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Time:
|
||
|
{
|
||
|
s32 sData = bData ? 1 : 0;
|
||
|
CStatsUtils::GetTime(sData, outBuffer, bufferSize, true);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Cash:
|
||
|
{
|
||
|
s64 iData = bData ? 1 : 0;
|
||
|
char cashBuff[32];
|
||
|
FormatInt64ToCash(iData, cashBuff, sizeof(cashBuff)/sizeof(cashBuff[0]));
|
||
|
::sprintf(outBuffer,"%s",cashBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_NameHash:
|
||
|
{
|
||
|
u32 uData = bData ? (u32)bData : ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A);
|
||
|
::sprintf(outBuffer, "%s", TheText.Get(uData, "NAME_HASH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_CarHash:
|
||
|
{
|
||
|
u32 uData = (u32)bData;
|
||
|
::sprintf(outBuffer, "%s", GetVehicleNameFromHashKey(uData));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Date:
|
||
|
{
|
||
|
u64 uData = (u64)bData;
|
||
|
int year;
|
||
|
int month;
|
||
|
int day;
|
||
|
int hour;
|
||
|
int minutes;
|
||
|
int seconds;
|
||
|
int milliseconds;
|
||
|
|
||
|
StatsInterface::UnPackDate(uData, year, month, day, hour, minutes,seconds, milliseconds);
|
||
|
::sprintf(outBuffer, "%04d / %02d / %02d",year,month,day);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bool:
|
||
|
{
|
||
|
if (bData)
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_YES"));
|
||
|
else
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_NO"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bar:
|
||
|
{
|
||
|
::sprintf(outBuffer,"");
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
AssertMsg(0,"Unhandled Type.");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatDataAsType(const sUIStatData* pStatUI, char* outBuffer, u32 bufferSize, u64 uData)
|
||
|
{
|
||
|
switch(pStatUI->GetType())
|
||
|
{
|
||
|
case eStatType_Int:
|
||
|
{
|
||
|
int iData = (int)uData;
|
||
|
char humanIntBuff[32];
|
||
|
int stringSize = sizeof(humanIntBuff)/sizeof(humanIntBuff[0]);
|
||
|
CTextConversion::FormatIntForHumans(iData, humanIntBuff, stringSize, "%s");
|
||
|
::sprintf(outBuffer,"%s",humanIntBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Float:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Percent:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f%%",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Distance:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? METERS_TO_KILOMETERS(fData) : METERS_TO_MILES(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KILO") : TheText.Get("UNIT_MILES"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_ShortDistance:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? fData : METERS_TO_FEET(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_METERS") : TheText.Get("UNIT_FEET"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Speed:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f%s",
|
||
|
ShouldUseMetric() ? fData : KPH_TO_MPH(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KPH") : TheText.Get("UNIT_MPH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Time:
|
||
|
{
|
||
|
CStatsUtils::GetTime(uData, outBuffer, bufferSize, true);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Cash:
|
||
|
{
|
||
|
s64 iData = (int)uData;
|
||
|
char cashBuff[32];
|
||
|
FormatInt64ToCash(iData, cashBuff, sizeof(cashBuff)/sizeof(cashBuff[0]));
|
||
|
::sprintf(outBuffer,"%s",cashBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_NameHash:
|
||
|
{
|
||
|
u32 hashData = uData ? (u32)uData : ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A);
|
||
|
::sprintf(outBuffer, "%s", TheText.Get(hashData, "NAME_HASH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_CarHash:
|
||
|
{
|
||
|
::sprintf(outBuffer, "%s", GetVehicleNameFromHashKey((u32)uData));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bool:
|
||
|
{
|
||
|
bool bData = uData ? true : false;
|
||
|
if (bData)
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_YES"));
|
||
|
else
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_NO"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Date:
|
||
|
{
|
||
|
int year;
|
||
|
int month;
|
||
|
int day;
|
||
|
int hour;
|
||
|
int minutes;
|
||
|
int seconds;
|
||
|
int milliseconds;
|
||
|
|
||
|
StatsInterface::UnPackDate(uData, year, month, day, hour, minutes,seconds, milliseconds);
|
||
|
::sprintf(outBuffer, "%04d / %02d / %02d",year,month,day);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bar:
|
||
|
{
|
||
|
::sprintf(outBuffer,"");
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
AssertMsg(0,"Unhandled Type.");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatDataAsType(const sUIStatData* pStatUI, char* outBuffer, u32 bufferSize, s64 uData)
|
||
|
{
|
||
|
switch(pStatUI->GetType())
|
||
|
{
|
||
|
case eStatType_Int:
|
||
|
{
|
||
|
int iData = (int)uData;
|
||
|
char humanIntBuff[32];
|
||
|
int stringSize = sizeof(humanIntBuff)/sizeof(humanIntBuff[0]);
|
||
|
CTextConversion::FormatIntForHumans(iData, humanIntBuff, stringSize, "%s");
|
||
|
::sprintf(outBuffer,"%s",humanIntBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Float:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Percent:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f%%",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Distance:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? METERS_TO_KILOMETERS(fData) : METERS_TO_MILES(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KILO") : TheText.Get("UNIT_MILES"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_ShortDistance:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? fData : METERS_TO_FEET(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_METERS") : TheText.Get("UNIT_FEET"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Speed:
|
||
|
{
|
||
|
float fData = (float)uData;
|
||
|
::sprintf(outBuffer,"%.2f%s",
|
||
|
ShouldUseMetric() ? fData : KPH_TO_MPH(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KPH") : TheText.Get("UNIT_MPH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Time:
|
||
|
{
|
||
|
CStatsUtils::GetTime((u64)uData, outBuffer, bufferSize, true);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Cash:
|
||
|
{
|
||
|
s64 iData = (int)uData;
|
||
|
char cashBuff[32];
|
||
|
FormatInt64ToCash(iData, cashBuff, sizeof(cashBuff)/sizeof(cashBuff[0]));
|
||
|
::sprintf(outBuffer,"%s",cashBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_NameHash:
|
||
|
{
|
||
|
u32 hashData = uData ? (u32)uData : ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A);
|
||
|
::sprintf(outBuffer, "%s", TheText.Get(hashData, "NAME_HASH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_CarHash:
|
||
|
{
|
||
|
::sprintf(outBuffer, "%s", GetVehicleNameFromHashKey((u32)uData));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bool:
|
||
|
{
|
||
|
bool bData = uData ? true : false;
|
||
|
if (bData)
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_YES"));
|
||
|
else
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_NO"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Date:
|
||
|
{
|
||
|
int year;
|
||
|
int month;
|
||
|
int day;
|
||
|
int hour;
|
||
|
int minutes;
|
||
|
int seconds;
|
||
|
int milliseconds;
|
||
|
|
||
|
StatsInterface::UnPackDate(uData, year, month, day, hour, minutes,seconds, milliseconds);
|
||
|
::sprintf(outBuffer, "%04d / %02d / %02d",year,month,day);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bar:
|
||
|
{
|
||
|
::sprintf(outBuffer,"");
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
AssertMsg(0,"Unhandled Type.");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatDataAsType(const sUIStatData* pStatUI, char* outBuffer, u32 bufferSize, float fData)
|
||
|
{
|
||
|
switch(pStatUI->GetType())
|
||
|
{
|
||
|
case eStatType_Int:
|
||
|
{
|
||
|
int iData = (int)fData;
|
||
|
char humanIntBuff[32];
|
||
|
int stringSize = sizeof(humanIntBuff)/sizeof(humanIntBuff[0]);
|
||
|
CTextConversion::FormatIntForHumans(iData, humanIntBuff, stringSize, "%s");
|
||
|
::sprintf(outBuffer,"%s",humanIntBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Float:
|
||
|
{
|
||
|
::sprintf(outBuffer,"%.2f",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Percent:
|
||
|
{
|
||
|
::sprintf(outBuffer,"%.2f%%",fData);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Distance:
|
||
|
{
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? METERS_TO_KILOMETERS(fData) : METERS_TO_MILES(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KILO") : TheText.Get("UNIT_MILES"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_ShortDistance:
|
||
|
{
|
||
|
::sprintf(outBuffer,"%.2f %s",
|
||
|
ShouldUseMetric() ? fData : METERS_TO_FEET(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_METERS") : TheText.Get("UNIT_FEET"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Speed:
|
||
|
{
|
||
|
::sprintf(outBuffer,"%.2f%s",
|
||
|
ShouldUseMetric() ? fData : KPH_TO_MPH(fData),
|
||
|
ShouldUseMetric() ? TheText.Get("UNIT_KPH") : TheText.Get("UNIT_MPH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Time:
|
||
|
{
|
||
|
s32 sData = (s32)fData;
|
||
|
CStatsUtils::GetTime(sData, outBuffer, bufferSize, true);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Cash:
|
||
|
{
|
||
|
s64 iData = (int)fData;
|
||
|
char cashBuff[32];
|
||
|
FormatInt64ToCash(iData, cashBuff, sizeof(cashBuff)/sizeof(cashBuff[0]));
|
||
|
::sprintf(outBuffer,"%s",cashBuff);
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_NameHash:
|
||
|
{
|
||
|
u32 uData = fData ? (u32)fData : ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A);
|
||
|
::sprintf(outBuffer, "%s", TheText.Get(uData, "NAME_HASH"));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_CarHash:
|
||
|
{
|
||
|
u32 uData = (u32)fData;
|
||
|
::sprintf(outBuffer, "%s", GetVehicleNameFromHashKey(uData));
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bool:
|
||
|
{
|
||
|
bool bData = (fData >= 1.0f)? true : false;
|
||
|
|
||
|
if (bData)
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_YES"));
|
||
|
else
|
||
|
::sprintf(outBuffer,"%s",TheText.Get("MO_NO"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Date:
|
||
|
{
|
||
|
u64 uData = (u64)fData;
|
||
|
int year;
|
||
|
int month;
|
||
|
int day;
|
||
|
int hour;
|
||
|
int minutes;
|
||
|
int seconds;
|
||
|
int milliseconds;
|
||
|
|
||
|
StatsInterface::UnPackDate(uData, year, month, day, hour, minutes,seconds, milliseconds);
|
||
|
::sprintf(outBuffer, "%04d / %02d / %02d",year,month,day);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case eStatType_Bar:
|
||
|
{
|
||
|
::sprintf(outBuffer,"");
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
AssertMsg(0,"Unhandled Type.");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatDataAsType( char* outBuffer, u32 bufferSize, char* pData)
|
||
|
{
|
||
|
formatf(outBuffer, bufferSize, "%s", pData);
|
||
|
}
|
||
|
|
||
|
StatType CFrontendStatsMgr::GetStatTypeFromXML(const char* name)
|
||
|
{
|
||
|
|
||
|
int tagType = eStatType_Invalid;
|
||
|
|
||
|
if (AssertVerify(name))
|
||
|
{
|
||
|
if( stricmp(name, "int") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Int;
|
||
|
}
|
||
|
else if( stricmp(name, "float") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Float;
|
||
|
}
|
||
|
else if( stricmp(name, "percent") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Percent;
|
||
|
}
|
||
|
else if( stricmp(name, "time") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Time;
|
||
|
}
|
||
|
else if( stricmp(name, "date") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Date;
|
||
|
}
|
||
|
else if( stricmp(name, "distance") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Distance;
|
||
|
}
|
||
|
else if (stricmp(name, "short_distance") == 0)
|
||
|
{
|
||
|
tagType = eStatType_ShortDistance;
|
||
|
}
|
||
|
else if( stricmp(name, "speed") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Speed;
|
||
|
}
|
||
|
else if( stricmp(name, "bool") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Bool;
|
||
|
}
|
||
|
else if( stricmp(name, "bar") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_Bar;
|
||
|
}
|
||
|
else if( stricmp(name, "playerid") == 0 )
|
||
|
{
|
||
|
tagType = eStatType_PlayerID;
|
||
|
}
|
||
|
else if (stricmp(name, "cash") == 0)
|
||
|
{
|
||
|
tagType = eStatType_Cash;
|
||
|
}
|
||
|
else if (stricmp(name, "namehash") == 0)
|
||
|
{
|
||
|
tagType = eStatType_NameHash;
|
||
|
}
|
||
|
else if (stricmp(name, "carhash") == 0)
|
||
|
{
|
||
|
tagType = eStatType_CarHash;
|
||
|
}
|
||
|
else if (stricmp(name, "fraction") == 0)
|
||
|
{
|
||
|
tagType = eStatType_Fraction;
|
||
|
}
|
||
|
else if (stricmp(name, "checklist") == 0)
|
||
|
{
|
||
|
tagType = eStatType_Checklist;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return tagType;
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatIntToCash(int cash, char* cashString, int cashStringSize, bool bUseCommas)
|
||
|
{
|
||
|
CTextConversion::FormatIntForHumans(cash, cashString, cashStringSize, "$%s", bUseCommas);
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::FormatInt64ToCash(s64 cash, char* cashString, int cashStringSize, bool bUseCommas)
|
||
|
{
|
||
|
CTextConversion::FormatIntForHumans(cash, cashString, cashStringSize, "$%s", bUseCommas);
|
||
|
}
|
||
|
|
||
|
bool CFrontendStatsMgr::GetVisibilityFromRule(const sUIStatData* pUIStat, const sStatDataPtr* pActualStat)
|
||
|
{
|
||
|
const sStatData* pStat = *pActualStat;
|
||
|
if(!pUIStat || !pActualStat || !pStat)
|
||
|
{
|
||
|
Assertf(false, "Bad stat type exists in the frontend stats manager.");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int iVisibilityRule = pUIStat->GetVisibility();
|
||
|
switch (iVisibilityRule)
|
||
|
{
|
||
|
case eVisibility_AlwaysShow:
|
||
|
return true;
|
||
|
case eVisibility_NeverShown:
|
||
|
return false;
|
||
|
case eVisibility_AfterIncrement:
|
||
|
switch (pStat->GetType())
|
||
|
{
|
||
|
case STAT_TYPE_INT:
|
||
|
return StatsInterface::GetIntStat(pActualStat->GetKey()) > 0;
|
||
|
case STAT_TYPE_BOOLEAN:
|
||
|
return StatsInterface::GetBooleanStat(pActualStat->GetKey()) != false;
|
||
|
case STAT_TYPE_PERCENT:
|
||
|
case STAT_TYPE_UINT32:
|
||
|
return StatsInterface::GetUInt32Stat(pActualStat->GetKey()) > 0;
|
||
|
case STAT_TYPE_PACKED:
|
||
|
case STAT_TYPE_UINT64:
|
||
|
case STAT_TYPE_DATE:
|
||
|
return StatsInterface::GetUInt64Stat(pActualStat->GetKey()) > 0;
|
||
|
case STAT_TYPE_INT64:
|
||
|
return StatsInterface::GetInt64Stat(pActualStat->GetKey()) > 0;
|
||
|
case STAT_TYPE_FLOAT:
|
||
|
return StatsInterface::GetFloatStat(pActualStat->GetKey()) > 0.0f;
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
default:
|
||
|
return EXTRACONTENT.IsContentPresent((u32)iVisibilityRule);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool CFrontendStatsMgr::ShouldUseMetric()
|
||
|
{
|
||
|
const int METRIC_SYSTEM = 1;
|
||
|
return CPauseMenu::GetMenuPreference(PREF_MEASUREMENT_SYSTEM) == METRIC_SYSTEM;
|
||
|
}
|
||
|
|
||
|
u32 CFrontendStatsMgr::GetReplacementLocalizedHash(u32 statHash, int iValue)
|
||
|
{
|
||
|
u32 uHash = 0;
|
||
|
|
||
|
if(m_ReplacementHashes.Access(statHash))
|
||
|
{
|
||
|
atArray<sUIReplacementTag>* tags = m_ReplacementHashes.Access(statHash);
|
||
|
#if __ASSERT
|
||
|
bool bFoundReplacement = false;
|
||
|
#endif // __ASSERT
|
||
|
for(int i = 0; i < tags->GetCount(); ++i)
|
||
|
{
|
||
|
if( iValue >= (*tags)[i].m_iMin &&
|
||
|
iValue <= (*tags)[i].m_iMax )
|
||
|
{
|
||
|
uHash = (*tags)[i].m_uHash;
|
||
|
#if __ASSERT
|
||
|
bFoundReplacement = true;
|
||
|
#endif // __ASSERT
|
||
|
}
|
||
|
}
|
||
|
Assertf(bFoundReplacement, "CFrontendStatsMgr::GetReplacementLocalizedHash - failed to find a replacement for stat with hash %u. value = %d", statHash, iValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Assertf(false, "statHash is invalid. Probably because this stat does not use replacement labels.");
|
||
|
}
|
||
|
|
||
|
return uHash;
|
||
|
}
|
||
|
|
||
|
const char* CFrontendStatsMgr::GetVehicleNameFromHashKey(u32 uVehicleModelHashKey)
|
||
|
{
|
||
|
if(uVehicleModelHashKey == 0)
|
||
|
{
|
||
|
return TheText.Get(ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A), "VEHICLEN_NAME");
|
||
|
}
|
||
|
|
||
|
CBaseModelInfo* mi = CModelInfo::GetBaseModelInfoFromHashKey(uVehicleModelHashKey, NULL);
|
||
|
if(uiVerifyf(mi, "Invalid Vehicle Model Hash %d", uVehicleModelHashKey))
|
||
|
{
|
||
|
if(AssertVerify(mi->GetModelType() == MI_TYPE_VEHICLE))
|
||
|
{
|
||
|
return TheText.Get(atStringHash(((CVehicleModelInfo*)mi)->GetGameName()), "VEHICLEN_NAME");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TheText.Get(ATSTRINGHASH("SM_LCNONE", 0xD7DE0F3A), "VEHICLEN_NAME");
|
||
|
}
|
||
|
|
||
|
int CFrontendStatsMgr::GetVisibilityFromXML(const char* name)
|
||
|
{
|
||
|
|
||
|
int tagType = eVisibility_AlwaysShow;
|
||
|
|
||
|
if (AssertVerify(name))
|
||
|
{
|
||
|
if( stricmp(name, "ALWAYS_VISIBLE") == 0 )
|
||
|
{
|
||
|
tagType = eVisibility_AlwaysShow;
|
||
|
}
|
||
|
else if( stricmp(name, "NEVER_SHOW") == 0 )
|
||
|
{
|
||
|
tagType = eVisibility_NeverShown;
|
||
|
}
|
||
|
else if( stricmp(name, "AFTER_INCREMENT") == 0 )
|
||
|
{
|
||
|
tagType = eVisibility_AfterIncrement;
|
||
|
}
|
||
|
else if( stricmp(name, "PC_ONLY") == 0 )
|
||
|
{
|
||
|
#if RSG_PC
|
||
|
tagType = eVisibility_AlwaysShow;
|
||
|
#else
|
||
|
tagType = eVisibility_NeverShown;
|
||
|
#endif // RSG_PC
|
||
|
}
|
||
|
else if( stricmp(name, "CONSOLE_ONLY") == 0 )
|
||
|
{
|
||
|
#if RSG_PC
|
||
|
tagType = eVisibility_NeverShown;
|
||
|
#else
|
||
|
tagType = eVisibility_AlwaysShow;
|
||
|
#endif // RSG_PC
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tagType = atStringHash(name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return tagType;
|
||
|
}
|
||
|
|
||
|
#if RSG_DURANGO || RSG_ORBIS
|
||
|
void CFrontendStatsMgr::RequestDisplayNameLookup()
|
||
|
{
|
||
|
CancelDisplayNameLookup();
|
||
|
m_bLookupRequired = true;
|
||
|
}
|
||
|
|
||
|
void CFrontendStatsMgr::CancelDisplayNameLookup()
|
||
|
{
|
||
|
// Handle Canceled Requests
|
||
|
if (m_iLookupId != CDisplayNamesFromHandles::INVALID_REQUEST_ID)
|
||
|
{
|
||
|
CLiveManager::GetFindDisplayName().CancelRequest(m_iLookupId);
|
||
|
m_iLookupId = CDisplayNamesFromHandles::INVALID_REQUEST_ID;
|
||
|
}
|
||
|
|
||
|
m_bLookupRequired = false;
|
||
|
m_iLookupId = CDisplayNamesFromHandles::INVALID_REQUEST_ID;
|
||
|
m_iNumRequests = 0;
|
||
|
}
|
||
|
#endif // RSG_DURANGO || RSG_ORBIS
|
||
|
|
||
|
CFrontendStatsMgr::UIStatsList::const_iterator
|
||
|
CFrontendStatsMgr::SPStatsUiConstIterBegin()
|
||
|
{
|
||
|
return m_aSPStatsData.begin();
|
||
|
}
|
||
|
|
||
|
CFrontendStatsMgr::UIStatsList::const_iterator
|
||
|
CFrontendStatsMgr::SPStatsUiConstIterEnd()
|
||
|
{
|
||
|
return m_aSPStatsData.end();
|
||
|
}
|
||
|
|
||
|
CFrontendStatsMgr::UIStatsList::const_iterator
|
||
|
CFrontendStatsMgr::MPStatsUiConstIterBegin()
|
||
|
{
|
||
|
return m_aMPStatsData.begin();
|
||
|
}
|
||
|
|
||
|
CFrontendStatsMgr::UIStatsList::const_iterator
|
||
|
CFrontendStatsMgr::MPStatsUiConstIterEnd()
|
||
|
{
|
||
|
return m_aMPStatsData.end();
|
||
|
}
|
||
|
|
||
|
CFrontendStatsMgr::UICategoryList::const_iterator
|
||
|
CFrontendStatsMgr::CategoryConstIterBegin()
|
||
|
{
|
||
|
return m_aCategoryList.begin();
|
||
|
}
|
||
|
|
||
|
CFrontendStatsMgr::UICategoryList::const_iterator
|
||
|
CFrontendStatsMgr::CategoryConstIterEnd()
|
||
|
{
|
||
|
return m_aCategoryList.end();
|
||
|
}
|
||
|
|
||
|
int statSort(sUIStatData* const* a, sUIStatData* const* b)
|
||
|
{
|
||
|
statAssertf(TheText.DoesTextLabelExist((*a)->GetDescriptionHash()), "Stat Text label is missing \"%d:%s\"", (*a)->GetDescriptionHash(), StatsInterface::GetKeyName((*a)->GetStatHash(0)));
|
||
|
statAssertf(TheText.DoesTextLabelExist((*b)->GetDescriptionHash()), "Stat Text label is missing \"%d:%s\"", (*b)->GetDescriptionHash(), StatsInterface::GetKeyName((*b)->GetStatHash(0)));
|
||
|
|
||
|
const char* szLocalizedString1 = TheText.Get((*a)->GetDescriptionHash(), "HASH");
|
||
|
const char* szLocalizedString2 = TheText.Get((*b)->GetDescriptionHash(), "HASH");
|
||
|
|
||
|
int iMaxLength = Min(CTextConversion::GetCharacterCount(szLocalizedString1), CTextConversion::GetCharacterCount(szLocalizedString2));
|
||
|
|
||
|
for (int i = 0; i < iMaxLength; i++)
|
||
|
{
|
||
|
if (szLocalizedString1[i] > szLocalizedString2[i] )
|
||
|
return 1;
|
||
|
else if (szLocalizedString1[i] < szLocalizedString2[i] )
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|