Added the sharedSkillSystem library

This commit is contained in:
Anonymous
2014-01-14 11:08:15 -07:00
parent 44a0133745
commit d69429aff8
21 changed files with 2292 additions and 0 deletions
+1
View File
@@ -17,6 +17,7 @@ add_subdirectory(sharedNetwork)
add_subdirectory(sharedNetworkMessages)
add_subdirectory(sharedObject)
add_subdirectory(sharedRandom)
add_subdirectory(sharedSkillSystem)
add_subdirectory(sharedSynchronization)
add_subdirectory(sharedTerrain)
add_subdirectory(sharedThread)
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 2.8)
project(sharedSkillSystem)
if(WIN32)
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
add_subdirectory(src)
@@ -0,0 +1 @@
#include "../../src/shared/ExpertiseManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/FirstSharedSkillSystem.h"
@@ -0,0 +1 @@
#include "../../src/shared/LevelManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/SkillManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/SkillObject.h"
@@ -0,0 +1 @@
#include "../../src/shared/SkillObjectArchive.h"
@@ -0,0 +1,40 @@
set(SHARED_SOURCES
shared/ExpertiseManager.cpp
shared/ExpertiseManager.h
shared/LevelManager.cpp
shared/LevelManager.h
shared/SkillManager.cpp
shared/SkillManager.h
shared/SkillObjectArchive.cpp
shared/SkillObjectArchive.h
shared/SkillObject.cpp
shared/SkillObject.h
)
if(WIN32)
set(PLATFORM_SOURCES
win32/FirstSharedSkillSystem.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
else()
set(PLATFORM_SOURCES "")
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/shared
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
)
add_library(sharedSkillSystem STATIC
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
@@ -0,0 +1,640 @@
//======================================================================
//
// ExpertiseManager.cpp
// copyright (c) 2006 Sony Online Entertainment
//
//======================================================================
#include "sharedSkillSystem/FirstSharedSkillSystem.h"
#include "sharedSkillSystem/ExpertiseManager.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedSkillSystem/SkillObject.h"
#include "sharedUtility/DataTable.h"
#include "sharedUtility/DataTableManager.h"
#include <map>
//======================================================================
namespace ExpertiseManagerNamespace
{
bool s_installed = false;
std::string const cs_expertiseSkillCategoryName("expertise");
int const cs_numExpertiseColumns = 7;
int const cs_numExpertiseTiers = 5;
std::string const cs_emptyString;
ExpertiseManager::TreeIdList const cs_emptyTreeIdList;
DataTable const cs_unusedDataTable;
// for direct access to expertise datatable
DataTable const * s_expertiseDatatable;
// grid x,y,z -> expertise skill name
typedef std::map<ExpertiseManager::ExpertiseCoord, std::string> ExpertiseGrid;
ExpertiseGrid s_expertiseGrid;
std::string const cs_expertiseDatatableName("datatables/expertise/expertise.iff");
void loadExpertiseTable(DataTable const & datatable);
// character level --> expertise points awarded
typedef std::map<int, int> LevelToPointsMap;
LevelToPointsMap s_expertisePointsForLevel;
std::string const cs_expertisePointsDatatableName("datatables/player/player_level.iff");
void loadExpertisePointsTable(DataTable const & datatable);
// expertise tree id --> string id
typedef std::map<int, std::string> TreeToStringIdMap;
TreeToStringIdMap s_expertiseStringForTree;
TreeToStringIdMap s_uiBackgroundIdForTree;
std::string const cs_expertiseTreesDatatableName("datatables/expertise/expertise_trees.iff");
void loadExpertiseTreesTable(DataTable const & datatable);
// skill template --> expertise tree id list
typedef std::map<std::string, ExpertiseManager::TreeIdList> ProfessionToTreeMap;
ProfessionToTreeMap s_expertiseTreesForProfession;
std::string const cs_skillTemplateDatatableName("datatables/skill_template/skill_template.iff");
void loadSkillTemplateTable(DataTable const & datatable);
void splitString(char delim, std::string const & source, std::vector<std::string> & result);
};
using namespace ExpertiseManagerNamespace;
//======================================================================
void ExpertiseManagerNamespace::loadExpertiseTable(DataTable const & datatable)
{
UNREF(datatable); // required for callback, but unused
s_expertiseGrid.clear();
s_expertiseDatatable = DataTableManager::getTable(cs_expertiseDatatableName, true);
DEBUG_FATAL(!s_expertiseDatatable, ("ExpertiseManager: failed to load %s", cs_expertiseDatatableName.c_str()));
int const numRows = s_expertiseDatatable->getNumRows();
int const nameColumn = s_expertiseDatatable->findColumnNumber("NAME");
int const treeColumn = s_expertiseDatatable->findColumnNumber("TREE");
int const tierColumn = s_expertiseDatatable->findColumnNumber("TIER");
int const gridColumn = s_expertiseDatatable->findColumnNumber("GRID");
int const rankColumn = s_expertiseDatatable->findColumnNumber("RANK");
for (int row = 0; row < numRows; ++row)
{
std::string const & name = s_expertiseDatatable->getStringValue(nameColumn, row);
SkillObject const * skill = SkillManager::getInstance().getSkill(name);
DEBUG_FATAL(!skill, ("ExpertiseManager: %s row %d: skill does not exist for %s", cs_expertiseDatatableName.c_str(), row, name.c_str()));
int tree = s_expertiseDatatable->getIntValue(treeColumn, row);
int tier = s_expertiseDatatable->getIntValue(tierColumn, row);
int grid = s_expertiseDatatable->getIntValue(gridColumn, row);
int rank = s_expertiseDatatable->getIntValue(rankColumn, row);
DEBUG_WARNING(s_expertiseStringForTree.find(tree) == s_expertiseStringForTree.end(),
("ExpertiseManager: %s row %d: expertise tree id %d for %s not defined in %s",
cs_expertiseDatatableName.c_str(), row, tree, name.c_str(), cs_expertiseTreesDatatableName.c_str()));
DEBUG_WARNING(tier > cs_numExpertiseTiers, ("ExpertiseManager: %s row %d: tier of %d for %s is greater than max of %d",
cs_expertiseDatatableName.c_str(), row, tier, name.c_str(), cs_numExpertiseTiers));
DEBUG_WARNING(grid > cs_numExpertiseColumns, ("ExpertiseManager: %s row %d: grid of %d for %s is greater than max of %d",
cs_expertiseDatatableName.c_str(), row, grid, name.c_str(), cs_numExpertiseColumns));
ExpertiseManager::ExpertiseCoord expertiseCoord(tree, tier, grid, rank);
std::string const & skillName = skill->getSkillName();
std::pair<ExpertiseGrid::iterator, bool> result = s_expertiseGrid.insert(std::make_pair(expertiseCoord, skillName));
UNREF(result);
DEBUG_WARNING(!result.second, ("ExpertiseManager: %s row %d: duplicate expertise: %s",
cs_expertiseDatatableName.c_str(), row, name.c_str()));
}
}
//----------------------------------------------------------------------
void ExpertiseManagerNamespace::loadExpertisePointsTable(DataTable const & datatable)
{
UNREF(datatable); // required for callback, but unused
s_expertisePointsForLevel.clear();
DataTable const * s_expertisePointsDatatable = DataTableManager::getTable(cs_expertisePointsDatatableName, true);
DEBUG_FATAL(!s_expertisePointsDatatable, ("ExpertiseManager: failed to load %s", cs_expertisePointsDatatableName.c_str()));
int const numRows = s_expertisePointsDatatable->getNumRows();
int const levelColumn = s_expertisePointsDatatable->findColumnNumber("level");
int const pointsColumn = s_expertisePointsDatatable->findColumnNumber("expertise_points");
for (int row = 0; row < numRows; ++row)
{
int level = s_expertisePointsDatatable->getIntValue(levelColumn, row);
int points = s_expertisePointsDatatable->getIntValue(pointsColumn, row);
s_expertisePointsForLevel[level] = points;
}
}
//----------------------------------------------------------------------
void ExpertiseManagerNamespace::loadExpertiseTreesTable(DataTable const & datatable)
{
UNREF(datatable); // required for callback, but unused
s_expertiseStringForTree.clear();
DataTable const * s_expertiseTreesDatatable = DataTableManager::getTable(cs_expertiseTreesDatatableName, true);
DEBUG_FATAL(!s_expertiseTreesDatatable, ("ExpertiseManager: failed to load %s", cs_expertiseTreesDatatableName.c_str()));
int const numRows = s_expertiseTreesDatatable->getNumRows();
int const treeIdColumn = s_expertiseTreesDatatable->findColumnNumber("expertise_tree_id");
int const stringIdColumn = s_expertiseTreesDatatable->findColumnNumber("expertise_tree_string_id");
int const uiBackgroundIdColumn = s_expertiseTreesDatatable->findColumnNumber("ui_background_id");
for (int row = 0; row < numRows; ++row)
{
int treeId = s_expertiseTreesDatatable->getIntValue(treeIdColumn, row);
std::string const & stringId = s_expertiseTreesDatatable->getStringValue(stringIdColumn, row);
s_expertiseStringForTree[treeId] = stringId;
std::string const & uiStringId = s_expertiseTreesDatatable->getStringValue(uiBackgroundIdColumn, row);
s_uiBackgroundIdForTree[treeId] = uiStringId;
}
}
//----------------------------------------------------------------------
void ExpertiseManagerNamespace::loadSkillTemplateTable(DataTable const & datatable)
{
UNREF(datatable); // required for callback, but unused
s_expertiseTreesForProfession.clear();
DataTable const * s_skillTemplateDatatable = DataTableManager::getTable(cs_skillTemplateDatatableName, true);
DEBUG_FATAL(!s_skillTemplateDatatable, ("ExpertiseManager: failed to load %s", cs_skillTemplateDatatableName.c_str()));
int const numRows = s_skillTemplateDatatable->getNumRows();
int const templateNameColumn = s_skillTemplateDatatable->findColumnNumber("templateName");
int const expertiseTreesColumn = s_skillTemplateDatatable->findColumnNumber("expertiseTrees");
for (int row = 0; row < numRows; ++row)
{
std::string const & templateName = s_skillTemplateDatatable->getStringValue(templateNameColumn, row);
std::string const & expertiseTrees = s_skillTemplateDatatable->getStringValue(expertiseTreesColumn, row);
if (expertiseTrees.empty())
{
continue;
}
ExpertiseManager::TreeIdList treeIdList;
std::vector<std::string> stringList;
splitString(',', expertiseTrees, stringList);
for (std::vector<std::string>::const_iterator i = stringList.begin(); i != stringList.end(); ++i)
{
int treeId = atoi((*i).c_str());
DEBUG_FATAL(treeId < 1, ("ExpertiseManager: %s row %d: invalid tree id %d", cs_skillTemplateDatatableName.c_str(), row, treeId));
treeIdList.push_back(treeId);
}
s_expertiseTreesForProfession.insert(std::make_pair(templateName, treeIdList));
}
}
//----------------------------------------------------------------------
void ExpertiseManagerNamespace::splitString(char delim, std::string const & source, std::vector<std::string> & result)
{
std::string::size_type curPos = 0;
while(curPos != std::string::npos)
{
std::string::size_type nextPos = source.find(delim, curPos);
std::string element = source.substr(curPos, nextPos - curPos);
result.push_back(element);
curPos = nextPos;
if(curPos != std::string::npos)
curPos++;
}
}
//======================================================================
void ExpertiseManager::install()
{
DEBUG_FATAL(s_installed, ("ExpertiseManager already installed"));
s_installed = true;
loadSkillTemplateTable(cs_unusedDataTable);
DataTableManager::addReloadCallback(cs_skillTemplateDatatableName, &loadSkillTemplateTable);
loadExpertisePointsTable(cs_unusedDataTable);
DataTableManager::addReloadCallback(cs_expertisePointsDatatableName, &loadExpertisePointsTable);
loadExpertiseTreesTable(cs_unusedDataTable);
DataTableManager::addReloadCallback(cs_expertiseTreesDatatableName, &loadExpertiseTreesTable);
loadExpertiseTable(cs_unusedDataTable);
DataTableManager::addReloadCallback(cs_expertiseDatatableName, &loadExpertiseTable);
ExitChain::add(ExpertiseManager::remove, "ExpertiseManager");
}
//----------------------------------------------------------------------
void ExpertiseManager::remove()
{
DEBUG_FATAL(!s_installed, ("ExpertiseManager not installed"));
s_installed = false;
}
//----------------------------------------------------------------------
/**
* @return the iff path of the expertise datatable
*/
std::string const & ExpertiseManager::getExpertiseDatatableName()
{
return cs_expertiseDatatableName;
}
//----------------------------------------------------------------------
/**
* @return int - the number of expertise columns in the grid
* (i.e. max x coordinate)
*/
int const ExpertiseManager::getNumExpertiseColumns()
{
return cs_numExpertiseColumns;
}
//----------------------------------------------------------------------
/**
* @return int - the number of expertise tiers in the grid
* (i.e. max y coordinate)
*/
int const ExpertiseManager::getNumExpertiseTiers()
{
return cs_numExpertiseTiers;
}
//----------------------------------------------------------------------
/**
* @param tree - tree id number
* @param tier - tier number (aka "y coordinate")
* @param grid - grid number (aka "x coordinate")
* @param rank - rank number (aka "z coordinate"). a rank
* of 1 is assumed when a particular rank is
* not needed, since rank 1 is guaranteed to
* exist.
*
* @return - skill object for expertise at grid location.
* returns NULL if none found
*/
SkillObject const * ExpertiseManager::getExpertiseSkillAt(int tree, int tier, int grid, int rank)
{
SkillObject const * skill = 0;
ExpertiseCoord expertiseCoord(tree, tier, grid, rank);
ExpertiseGrid::const_iterator i = s_expertiseGrid.find(expertiseCoord);
if (i != s_expertiseGrid.end())
{
std::string const & skillName = (*i).second;
skill = SkillManager::getInstance().getSkill(skillName);
}
return skill;
}
//----------------------------------------------------------------------
/**
* @param level - a character's combat level
*
* @return int - max Expertise Points available at that level
*/
int ExpertiseManager::getExpertisePointsForLevel(int level)
{
int totalPoints = 0;
for (LevelToPointsMap::const_iterator i = s_expertisePointsForLevel.begin(); i != s_expertisePointsForLevel.end(); ++i)
{
int const levelForRow = (*i).first;
int const pointsForRow = (*i).second;
if (levelForRow <= level)
{
totalPoints += pointsForRow;
}
}
return totalPoints;
}
//----------------------------------------------------------------------
/**
* @param empty list to populate with all existing tree ids
*/
void ExpertiseManager::getExpertiseTrees(ExpertiseManager::TreeIdList & treeIdList)
{
treeIdList.clear();
for (TreeToStringIdMap::const_iterator i = s_expertiseStringForTree.begin(); i != s_expertiseStringForTree.end(); ++i)
{
treeIdList.push_back((*i).first);
}
}
//----------------------------------------------------------------------
/**
* @param skillTemplate - a profession template name from skill_template table
*
* @return list of tree id ints for profession
*/
ExpertiseManager::TreeIdList const & ExpertiseManager::getExpertiseTreesForProfession(std::string const & skillTemplate)
{
ProfessionToTreeMap::const_iterator i = s_expertiseTreesForProfession.find(skillTemplate);
if (i != s_expertiseTreesForProfession.end())
{
return (*i).second;
}
return cs_emptyTreeIdList;
}
//----------------------------------------------------------------------
/**
* @param treeId - int id of expertise tree
*
* @return string name of expertise tree, suitable for use in
* creating a StringId and localizing
*/
std::string const & ExpertiseManager::getExpertiseTreeNameFromId(int treeId)
{
TreeToStringIdMap::const_iterator i = s_expertiseStringForTree.find(treeId);
if (i != s_expertiseStringForTree.end())
{
return (*i).second;
}
return cs_emptyString;
}
//----------------------------------------------------------------------
std::string const & ExpertiseManager::getExpertiseTreeUiBackgroundIdFromId(int treeId)
{
TreeToStringIdMap::const_iterator i = s_uiBackgroundIdForTree.find(treeId);
if (i != s_uiBackgroundIdForTree.end())
{
return (*i).second;
}
return cs_emptyString;
}
//----------------------------------------------------------------------
/**
* @param skill - pointer to a skill
*
* @return bool - true if skill is an Expertise skill
*/
bool ExpertiseManager::isExpertise(SkillObject const * skill)
{
bool result = false;
if (skill)
{
SkillObject const * category = skill->findCategory();
if (category)
{
std::string const & categoryName = category->getSkillName();
if (categoryName == cs_expertiseSkillCategoryName)
{
result = true;
}
}
}
return result;
}
//----------------------------------------------------------------------
/**
* @param expertiseName - name of the expertise
*
* @return int - the id number of the expertise
*/
int ExpertiseManager::getExpertiseTree(std::string const & expertiseName)
{
int result = 0;
if (s_expertiseDatatable)
{
int rowNum = s_expertiseDatatable->searchColumnString(0, expertiseName);
if(rowNum == -1)
{
DEBUG_WARNING(true, ("while looking for tree that expertise %s belongs to, could not find expertise", expertiseName.c_str()));
return -1;
}
result = s_expertiseDatatable->getIntValue("TREE", rowNum);
}
return result;
}
//----------------------------------------------------------------------
/**
* @param expertiseName - name of the expertise
*
* @return int - the grid (aka "x coordinate") of the expertise
*/
int ExpertiseManager::getExpertiseGrid(std::string const & expertiseName)
{
int result = 0;
if (s_expertiseDatatable)
{
int rowNum = s_expertiseDatatable->searchColumnString(0, expertiseName);
result = s_expertiseDatatable->getIntValue("GRID", rowNum);
}
return result;
}
//----------------------------------------------------------------------
/**
* @param expertiseName - name of the expertise
*
* @return int - the tier (aka "y coordinate") of the expertise
*/
int ExpertiseManager::getExpertiseTier(std::string const & expertiseName)
{
int result = 0;
if (s_expertiseDatatable)
{
int rowNum = s_expertiseDatatable->searchColumnString(0, expertiseName);
result = s_expertiseDatatable->getIntValue("TIER", rowNum);
}
return result;
}
//----------------------------------------------------------------------
/**
* @param expertiseName - name of the expertise
*
* @return int - the rank (aka "z coordinate") of the expertise
*/
int ExpertiseManager::getExpertiseRank(std::string const & expertiseName)
{
int result = 0;
if (s_expertiseDatatable)
{
int rowNum = s_expertiseDatatable->searchColumnString(0, expertiseName);
result = s_expertiseDatatable->getIntValue("RANK", rowNum);
}
return result;
}
//----------------------------------------------------------------------
/**
* @param expertiseName - name of the expertise
*
* @return int - the highest existing rank (aka "z coordinate") of the expertise
*/
int ExpertiseManager::getExpertiseRankMax(std::string const & expertiseName)
{
int result = 0;
int tree = getExpertiseTree(expertiseName);
int tier = getExpertiseTier(expertiseName);
int grid = getExpertiseGrid(expertiseName);
int rank = getExpertiseRank(expertiseName);
while (getExpertiseSkillAt(tree, tier, grid, rank) != 0)
{
result = rank;
++rank;
}
return result;
}
//======================================================================
ExpertiseManager::ExpertiseCoord::ExpertiseCoord() :
tree(1),
tier(1),
grid(1),
rank(1)
{
}
// ----------------------------------------------------------------------
ExpertiseManager::ExpertiseCoord::ExpertiseCoord(ExpertiseCoord const & rhs) :
tree(rhs.tree),
tier(rhs.tier),
grid(rhs.grid),
rank(rhs.rank)
{
}
// ----------------------------------------------------------------------
ExpertiseManager::ExpertiseCoord::ExpertiseCoord(int const treeValue, int const tierValue, int const gridValue) :
tree(treeValue),
tier(tierValue),
grid(gridValue),
rank(1)
{
}
// ----------------------------------------------------------------------
ExpertiseManager::ExpertiseCoord::ExpertiseCoord(int const treeValue, int const tierValue, int const gridValue, int const rankValue) :
tree(treeValue),
tier(tierValue),
grid(gridValue),
rank(rankValue)
{
}
// ----------------------------------------------------------------------
ExpertiseManager::ExpertiseCoord const & ExpertiseManager::ExpertiseCoord::operator=(ExpertiseManager::ExpertiseCoord const & rhs)
{
tree = rhs.tree;
tier = rhs.tier;
grid = rhs.grid;
rank = rhs.rank;
return *this;
}
// ----------------------------------------------------------------------
bool ExpertiseManager::ExpertiseCoord::operator==(ExpertiseManager::ExpertiseCoord const & rhs) const
{
return (tree == rhs.tree) && (tier == rhs.tier) && (grid == rhs.grid) && (rank == rhs.rank);
}
// ----------------------------------------------------------------------
bool ExpertiseManager::ExpertiseCoord::operator!=(ExpertiseManager::ExpertiseCoord const & rhs) const
{
return !((tree == rhs.tree) && (tier == rhs.tier) && (grid == rhs.grid) && (rank == rhs.rank));
}
// ----------------------------------------------------------------------
bool ExpertiseManager::ExpertiseCoord::operator<(ExpertiseManager::ExpertiseCoord const & rhs) const
{
if (tree < rhs.tree)
{
return true;
}
if (tree == rhs.tree)
{
if (tier < rhs.tier)
{
return true;
}
if (tier == rhs.tier)
{
if (grid < rhs.grid)
{
return true;
}
if (grid == rhs.grid)
{
return (rank < rhs.rank);
}
}
}
return false;
}
//======================================================================
@@ -0,0 +1,69 @@
//======================================================================
//
// ExpertiseManager.h
// copyright (c) 2006 Sony Online Entertainment
//
//======================================================================
#ifndef INCLUDED_ExpertiseManager_H
#define INCLUDED_ExpertiseManager_H
//======================================================================
class ExpertiseManager
{
public:
static void install();
static void remove();
static std::string const & getExpertiseDatatableName();
// Expertise Points
static int getExpertisePointsForLevel(int level);
// Expertise Trees
typedef std::vector<int> TreeIdList;
static void getExpertiseTrees(TreeIdList & treeIdList);
static TreeIdList const & getExpertiseTreesForProfession(std::string const & skillTemplate);
static std::string const & getExpertiseTreeNameFromId(int treeId);
static std::string const & getExpertiseTreeUiBackgroundIdFromId(int treeId);
// Individual Expertises
static bool isExpertise(SkillObject const * skill);
static int getExpertiseTree(std::string const & expertiseName);
static int getExpertiseGrid(std::string const & expertiseName);
static int getExpertiseTier(std::string const & expertiseName);
static int getExpertiseRank(std::string const & expertiseName);
static int getExpertiseRankMax(std::string const & expertiseName);
// Expertise Grid
static int const getNumExpertiseColumns();
static int const getNumExpertiseTiers();
static SkillObject const * getExpertiseSkillAt(int tree, int tier, int grid, int rank = 1);
struct ExpertiseCoord
{
int tree;
int tier;
int grid;
int rank;
ExpertiseCoord();
ExpertiseCoord(ExpertiseCoord const & rhs);
ExpertiseCoord(int const treeValue, int const tierValue, int const gridValue);
ExpertiseCoord(int const treeValue, int const tierValue, int const gridValue, int const rankValue);
ExpertiseCoord const & operator=(ExpertiseCoord const & rhs);
bool operator==(ExpertiseCoord const & rhs) const;
bool operator!=(ExpertiseCoord const & rhs) const;
bool operator<(ExpertiseCoord const & rhs) const;
};
};
//======================================================================
#endif
@@ -0,0 +1,16 @@
// FirstSharedSkillSystem.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_FirstSharedSkillSystem_H
#define _INCLUDED_FirstSharedSkillSystem_H
//-----------------------------------------------------------------------
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedSkillSystem/SkillManager.h"
#include "sharedSkillSystem/SkillObject.h"
//-----------------------------------------------------------------------
#endif // _INCLUDED_FirstSharedSkillSystem_H
@@ -0,0 +1,421 @@
//======================================================================
//
// LevelManager.cpp
// copyright (c) 2005 Sony Online Entertainment
//
//======================================================================
#include "sharedSkillSystem/FirstSharedSkillSystem.h"
#include "sharedSkillSystem/LevelManager.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/Crc.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedSkillSystem/SkillObject.h"
#include "sharedUtility/DataTable.h"
#include "sharedUtility/DataTableManager.h"
#include <map>
//======================================================================
namespace LevelManagerNamespace
{
bool m_installed = false;
// level data
struct LevelRecord
{
int16 level;
int xp_required;
int health;
};
std::map<int, LevelRecord> ms_levelRecords;
typedef std::map<int, LevelRecord>::iterator LevelRecordsIterator;
// xp multipliers
// map xp_type_nameCrc to multiplier
std::map<uint32, int> ms_xpTypeRecords;
typedef std::map<uint32, int>::iterator XpRecordsIterator;
// skill data
struct SkillRecord
{
uint32 xp_type_name_Crc;
int xp_cost;
};
std::map<uint32, SkillRecord> ms_skillRecords;
typedef std::map<uint32, SkillRecord>::iterator SkillRecordsIterator;
int ms_numLevels = 0;
int ms_maxLevel = 0;
LevelRecord const * getLevelRecord(int xp);
inline int getXpValueForType(uint32 expTypeCrc, int xpBaseValue)
{
int value = 0;
// look up the xp type and only add the xp if the type is found
XpRecordsIterator xpItr = ms_xpTypeRecords.find(expTypeCrc);
if (xpItr != ms_xpTypeRecords.end())
{
const int multiplier = (*xpItr).second;
value = xpBaseValue * multiplier;
}
return value;
}
};
using namespace LevelManagerNamespace;
//======================================================================
void LevelManager::install()
{
if(m_installed)
return;
m_installed = true;
DataTable *playerLevelDatatable = DataTableManager::getTable("datatables/player/player_level.iff", true);
if (playerLevelDatatable)
{
ms_numLevels = playerLevelDatatable->getNumRows();
const int levelColumn = playerLevelDatatable->findColumnNumber("level");
const int xp_requiredColumn = playerLevelDatatable->findColumnNumber("xp_required");
const int health_grantedColumn = playerLevelDatatable->findColumnNumber("health_granted");
const int xp_typeColumn = playerLevelDatatable->findColumnNumber("xp_type");
const int xp_multiplierColumn = playerLevelDatatable->findColumnNumber("xp_multiplier");
// @NOTE: there are basically two independent tables in this data file
// there is level information and xp type information
// these are independent and have diffent lengths, so I'm putting the info
// into two different data structures
int i;
for(i = 0; i < ms_numLevels; ++i)
{
LevelRecord levelRecord;
levelRecord.level = (int16) playerLevelDatatable->getIntValue(levelColumn, i);
levelRecord.xp_required = playerLevelDatatable->getIntValue(xp_requiredColumn, i);
levelRecord.health = playerLevelDatatable->getIntValue(health_grantedColumn, i);
ms_levelRecords.insert(std::make_pair(levelRecord.level, levelRecord));
std::string xpTypeName = playerLevelDatatable->getStringValue(xp_typeColumn, i);
if (!xpTypeName.empty())
{
const uint32 xpTypeNameCrc = Crc::calculate(xpTypeName.c_str());
const int xpMultiplier = playerLevelDatatable->getIntValue(xp_multiplierColumn, i);
ms_xpTypeRecords.insert(std::make_pair(xpTypeNameCrc, xpMultiplier));
}
if(levelRecord.level > ms_maxLevel)
ms_maxLevel = levelRecord.level;
}
DataTableManager::close("datatables/player/player_level.iff");
}
DataTable *skillDatatable = DataTableManager::getTable("datatables/skill/skills.iff", true);
if (skillDatatable)
{
const int numSkillRows = skillDatatable->getNumRows();
const int skill_nameColumn = skillDatatable->findColumnNumber("NAME");
const int type_nameColumn = skillDatatable->findColumnNumber("XP_TYPE");
const int xp_costColumn = skillDatatable->findColumnNumber("XP_COST");
int i;
for(i = 0; i < numSkillRows; i++)
{
SkillRecord skillRecord;
std::string skillName = skillDatatable->getStringValue(skill_nameColumn, i);
uint32 skillNameCrc = Crc::calculate(skillName.c_str());
std::string xpTypeName = skillDatatable->getStringValue(type_nameColumn, i);
skillRecord.xp_type_name_Crc = Crc::calculate(xpTypeName.c_str());
skillRecord.xp_cost = skillDatatable->getIntValue(xp_costColumn, i);
ms_skillRecords.insert(std::make_pair(skillNameCrc, skillRecord));
}
DataTableManager::close("datatables/skill/skills.iff");
}
ExitChain::add(LevelManager::remove, "LevelManager::remove", 0, false);
}
//======================================================================
void LevelManager::remove()
{
}
void LevelManager::setLevelDataFromXp(LevelData &levelData, int xp)
{
LevelRecord const * levelRecord = getLevelRecord(xp);
if (levelRecord)
{
levelData.currentLevel = levelRecord->level;
levelData.currentLevelXp = levelRecord->xp_required;
levelData.currentHealth = levelRecord->health;
}
else
{
// assume level 0
levelData.currentLevel = 0;
levelData.currentLevelXp = 0;
levelData.currentHealth = 0;
}
}
//======================================================================
// This method forces the specified level and sets the creatures
// levelxp and health based on the level (not the skills)
//
void LevelManager::setLevelDataFromLevel(LevelData &levelData, int newLevel)
{
LevelRecordsIterator it = ms_levelRecords.find(newLevel);
if(it == ms_levelRecords.end())
{
bool issueWarning = true;
if (!ms_levelRecords.empty())
{
// find the max level and set levelData to the max if possible
// assuming that we're asking for a level that is higher than
// possible
std::map<int, LevelRecord>::reverse_iterator last = ms_levelRecords.rbegin();
int const highestLevel = last->first;
if (newLevel > highestLevel)
{
LevelRecord const &levelRecord = last->second;
levelData.currentLevel = levelRecord.level;
levelData.currentLevelXp = levelRecord.xp_required;
levelData.currentHealth = levelRecord.health;
issueWarning = false;
}
}
WARNING(issueWarning, ("setLevelDataFromLevel: Invalid level specified[%d]\n", newLevel));
}
else
{
LevelRecord const &levelRecord = it->second;
levelData.currentLevel = levelRecord.level;
levelData.currentLevelXp = levelRecord.xp_required;
levelData.currentHealth = levelRecord.health;
}
}
//======================================================================
// This method calculates the level data based upon the level XP
//
void LevelManager::calculateLevelData(int currentLevelXp, LevelData &levelData)
{
levelData.currentLevelXp = currentLevelXp;
// get the health for this record
LevelRecord const * levelRecord = getLevelRecord(levelData.currentLevelXp);
if (levelRecord)
{
levelData.currentHealth = levelRecord->health;
levelData.currentLevel = levelRecord->level;
}
else
{
WARNING(true, ("calculateLevelData: Couldn't find level for xp value [%d]\n", levelData.currentLevelXp));
}
}
//======================================================================
// Updates the xp and, if necessary, the level and health based on the added skill
//
void LevelManager::addSkillToLevelData(LevelData &levelData, std::string const &skillName)
{
updateLevelDataWithSkill(levelData, skillName, false);
}
//======================================================================
// Updates the xp and, if necessary, the level and health based on the added skill
//
void LevelManager::removeSkillFromLevelData(LevelData &levelData, std::string const &skillName)
{
updateLevelDataWithSkill(levelData, skillName, true);
}
//======================================================================
// Updates the xp and, if necessary, the level and health based on the added skill
//
void LevelManager::addXpToLevelData(LevelData &levelData, std::string const &experienceType, int xp)
{
CrcLowerString crcExpType(experienceType.c_str());
levelData.currentLevelXp += getXpValueForType(crcExpType.getCrc(), xp);
LevelRecord const * levelRecord = getLevelRecord(levelData.currentLevelXp);
if (levelRecord)
{
levelData.currentLevel = levelRecord->level;
levelData.currentHealth = levelRecord->health;
}
else
{
WARNING(true, ("updateLevelDataWithSkill: Couldn't find level for xp value [%d]\n", levelData.currentLevelXp));
}
}
//======================================================================
// Returns the total xp for the specified skill
//
int LevelManager::getSkillXpValue(CrcLowerString const &skillName)
{
int value = 0;
SkillRecordsIterator itr = ms_skillRecords.find(skillName.getCrc());
if (itr != ms_skillRecords.end())
{
int xpBaseValue = (*itr).second.xp_cost;
uint32 xpTypeNameCrc = (*itr).second.xp_type_name_Crc;
value = getXpValueForType(xpTypeNameCrc, xpBaseValue);
}
return value;
}
//======================================================================
// Updates the xp and therefore level and health based on the specified
// skill (and whether it was revoked)
//
void LevelManager::updateLevelDataWithSkill(LevelData &levelData, std::string const &skillName, bool revoked)
{
CrcLowerString crcSkillName(skillName.c_str());
const int skillValue = getSkillXpValue(crcSkillName);
levelData.currentLevelXp += revoked ? -skillValue : skillValue;
LevelRecord const * levelRecord = getLevelRecord(levelData.currentLevelXp);
if (levelRecord)
{
levelData.currentLevel = levelRecord->level;
levelData.currentHealth = levelRecord->health;
}
else
{
WARNING(true, ("updateLevelDataWithSkill: Couldn't find level for xp value [%d]\n", levelData.currentLevelXp));
}
}
//======================================================================
// Find the level corresponding to the xp value and
// returns null if not found
LevelRecord const * LevelManagerNamespace::getLevelRecord(int xp)
{
LevelRecordsIterator itr = ms_levelRecords.begin();
LevelRecordsIterator nextItr = itr;
while (itr != ms_levelRecords.end())
{
LevelRecord const & currentRecord = (*itr).second;
++nextItr;
if (nextItr != ms_levelRecords.end())
{
const LevelRecord & nextRecord = (*nextItr).second;
{
if (xp < nextRecord.xp_required)
{
return &currentRecord;
}
}
}
else
{
// no more levels, so return this (the last) one
return &currentRecord;
}
++itr;
}
WARNING(true, ("getLevelRecord: Couldn't find level for xp value[%d]\n", xp));
return NULL;
}
//======================================================================
LevelManager::LevelData::LevelData()
: currentLevel(0)
, currentLevelXp(0)
, currentHealth(0)
{
}
//======================================================================
LevelManager::LevelData::LevelData(int16 level, int levelXp)
: currentLevel(level)
, currentLevelXp(levelXp)
, currentHealth(0)
{
}
//----------------------------------------------------------------------
int LevelManager::getRequiredXpToReachLevel(int16 level)
{
LevelData levelData;
setLevelDataFromLevel(levelData, level);
LevelRecord const * const levelRecord = getLevelRecord(levelData.currentLevelXp);
int const xp = (levelRecord != 0) ? levelRecord->xp_required : 0;
return xp;
}
//----------------------------------------------------------------------
bool LevelManager::canSkillIncreaseLevel(std::string const &skillName)
{
CrcLowerString crcExpType(skillName.c_str());
int const xp = getXpValueForType(crcExpType.getCrc(), 1);
return (xp >= 1);
}
//----------------------------------------------------------------------
int LevelManager::getMaxLevel()
{
return ms_maxLevel;
}
//======================================================================
@@ -0,0 +1,58 @@
//======================================================================
//
// LevelManager.h
// copyright (c) 2005 Sony Online Entertainment
//
//======================================================================
#ifndef INCLUDED_LevelManager_H
#define INCLUDED_LevelManager_H
//======================================================================
class CrcLowerString;
//----------------------------------------------------------------------
class LevelManager
{
public:
struct LevelData
{
LevelData();
LevelData(int16 level, int levelXp);
int16 currentLevel;
int currentLevelXp;
int currentHealth;
};
static void install();
static void remove();
static void setLevelDataFromXp(LevelData &levelData, int xp);
static void setLevelDataFromLevel(LevelData &levelData, int newLevel);
static void addXpToLevelData(LevelData &levelData, std::string const &experienceType, int xp);
static void calculateLevelData(int currentLevelXp, LevelData &levelData);
static void addSkillToLevelData(LevelData &levelData, std::string const &skillName);
static void removeSkillFromLevelData(LevelData &levelData, std::string const &skillName);
static bool canSkillIncreaseLevel(std::string const & skillName);
static int getRequiredXpToReachLevel(int16 level);
static int getMaxLevel();
static int getSkillXpValue(CrcLowerString const &skillName);
protected:
static void updateLevelDataWithSkill(LevelData &levelData, std::string const &skillName, bool revoked);
};
//======================================================================
#endif
@@ -0,0 +1,212 @@
// SkillManager.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedSkillSystem/FirstSharedSkillSystem.h"
#include "sharedSkillSystem/SkillManager.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedSkillSystem/SkillObject.h"
#include "sharedUtility/DataTable.h"
#include "sharedUtility/DataTableManager.h"
#include "sharedDebug/InstallTimer.h"
#include <algorithm>
#include <hash_map>
#include <string>
SkillManager *SkillManager::ms_instance = NULL;
const std::string &SkillManager::cms_skillsDatatableName = "datatables/skill/skills.iff";
//-----------------------------------------------------------------
namespace
{
bool ensureProperSkillName (const std::string & str)
{
static std::string valid;
static bool init = false;
if (!init)
{
valid.reserve (38);
int c = 0;
for (c = 'a'; c <= 'z'; ++c)
valid.append (1, c);
for (c = '0'; c <= '9'; ++c)
valid.append (1, c);
valid.append (1, '_');
valid.append (1, '-');
init = true;
}
return str.find_first_not_of (valid) == str.npos;
}
}
//---------------------------------------------------------------------
SkillManager::SkillManager() :
m_skillMap(new SkillMap),
m_skillTable(DataTableManager::getTable(cms_skillsDatatableName, true)/*new DataTable*/),
m_xpLimitMap(new XpLimitMap),
m_xpLimitTable(DataTableManager::getTable("datatables/skill/xp_limits.iff", true))
{
}
//---------------------------------------------------------------------
SkillManager::~SkillManager()
{
std::for_each (m_skillMap->begin(), m_skillMap->end(), PointerDeleterPairSecond ());
delete m_skillMap;
delete m_xpLimitMap;
m_skillMap = 0;
m_skillTable = 0;
m_xpLimitMap = 0;
m_xpLimitTable = 0;
}
//----------------------------------------------------------------------
void SkillManager::install()
{
InstallTimer const installTimer("SkillManager::install");
DEBUG_FATAL (ms_instance, ("SkillManager already installed"));
ms_instance = new SkillManager();
ms_instance->getRoot ();
ms_instance->initXpLimits();
ExitChain::add (SkillManager::remove, "SkillManager");
}
//----------------------------------------------------------------------
void SkillManager::remove()
{
DEBUG_FATAL (!ms_instance, ("SkillManager not installed"));
delete ms_instance;
ms_instance = NULL;
}
//----------------------------------------------------------------------
SkillManager & SkillManager::getInstance ()
{
//DEBUG_FATAL (!ms_instance, ("SkillManager not installed"));
if (!ms_instance)
{
install();
}
return *ms_instance;
}
//-----------------------------------------------------------------
const SkillObject * SkillManager::getRoot ()
{
static const std::string rootname ("skill_system_root");
return getSkill (rootname);
}
//---------------------------------------------------------------------
const SkillObject * SkillManager::getSkill(const std::string & skillName)
{
if (skillName.empty () || !ensureProperSkillName (skillName))
return 0;
const SkillMap::const_iterator f = m_skillMap->find(skillName);
if(f == m_skillMap->end())
return loadSkill(skillName);
else
return (*f).second;
}
//-----------------------------------------------------------------------
const SkillObject * SkillManager::loadSkill(const std::string & skillName)
{
if (skillName.empty () || !ensureProperSkillName (skillName))
return 0;
SkillObject * result = 0;
const SkillMap::const_iterator f = m_skillMap->find(skillName);
if(f != m_skillMap->end())
{
result = f->second;
}
else
{
SkillObject * const newSkill = new SkillObject;
m_skillMap->insert(std::make_pair (skillName, newSkill));
result = newSkill;
// Guard against skills table having been closed somewhere via DataTableManager.
m_skillTable = DataTableManager::getTable(cms_skillsDatatableName, true);
if (!newSkill->load(*m_skillTable, skillName))
{
WARNING (true, ("SkillManager failed to load skill [%s]", skillName.c_str ()));
delete newSkill;
result = 0;
m_skillMap->erase (skillName);
// (*skillMap) [skillName] = 0;
}
}
return result;
}
//---------------------------------------------------------------------
uint32 SkillManager::getDefaultXpLimit(const std::string & experienceType)
{
if (m_xpLimitMap != NULL)
{
XpLimitMap::const_iterator result = m_xpLimitMap->find(experienceType);
if (result != m_xpLimitMap->end())
return (*result).second;
}
return static_cast<uint32>(-1);
}
//---------------------------------------------------------------------
void SkillManager::initXpLimits()
{
if (m_xpLimitTable == NULL)
{
WARNING(true, ("SkillManager::initXpLimits, m_xpLimitTable not initialized"));
return;
}
if (m_xpLimitMap == NULL)
{
WARNING(true, ("SkillManager::initXpLimits, m_xpLimitMap not initialized"));
return;
}
int count = m_xpLimitTable->getNumRows();
for (int i = 0; i < count; ++i)
{
const std::string & xpType = m_xpLimitTable->getStringValue(0, i);
if (!xpType.empty())
{
if (xpType == "end")
break;
m_xpLimitMap->insert(std::make_pair(xpType, m_xpLimitTable->getIntValue(1, i)));
}
}
}
//---------------------------------------------------------------------
@@ -0,0 +1,60 @@
// SkillManager.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _SkillManager_H
#define _SkillManager_H
//---------------------------------------------------------------------
#pragma warning (disable : 4786 )
class SkillObject;
class DataTable;
//---------------------------------------------------------------------
class SkillManager
{
public:
typedef stdhash_map<std::string, SkillObject *>::fwd SkillMap;
typedef stdhash_map<std::string, uint32>::fwd XpLimitMap;
virtual ~SkillManager ();
const SkillObject * getSkill (const std::string & skillName);
const SkillMap & getSkillMap () const;
const SkillObject * getRoot ();
uint32 getDefaultXpLimit(const std::string & experienceType);
static SkillManager & getInstance ();
static void install ();
static void remove ();
protected:
SkillManager ();
private:
SkillManager (const SkillManager & source);
SkillManager & operator = (const SkillManager & rhs);
const SkillObject * loadSkill (const std::string & skillName);
void initXpLimits ();
private:
SkillMap * m_skillMap;
DataTable * m_skillTable;
XpLimitMap * m_xpLimitMap;
DataTable * m_xpLimitTable;
static SkillManager * ms_instance;
static const std::string & cms_skillsDatatableName;
};
//-----------------------------------------------------------------------
inline const SkillManager::SkillMap & SkillManager::getSkillMap() const
{
return *NON_NULL(m_skillMap);
}
//---------------------------------------------------------------------
#endif // _SkillManager_H
@@ -0,0 +1,561 @@
// SkillObject.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedSkillSystem/FirstSharedSkillSystem.h"
#include "sharedSkillSystem/SkillObject.h"
#include "sharedSkillSystem/SkillManager.h"
#include "sharedUtility/DataTable.h"
#include "UnicodeUtils.h"
#include <algorithm>
const std::string SkillObject::ms_skillLabel = "NAME";
const std::string SkillObject::ms_prerequisiteSkillsLabel = "SKILLS_REQUIRED";
const std::string SkillObject::ms_prerequisiteExperienceTypeLabel = "XP_TYPE";
const std::string SkillObject::ms_prerequisiteExperienceAmountLabel = "XP_COST";
const std::string SkillObject::ms_prerequisiteExperienceLimitLabel = "XP_CAP";
const std::string SkillObject::ms_prerequisiteSpeciesLabel = "SPECIES_REQUIRED";
const std::string SkillObject::ms_commandsLabel = "COMMANDS";
const std::string SkillObject::ms_statisticsModifiersLabel = "SKILL_MODS";
const std::string SkillObject::ms_parentLabel = "PARENT";
const std::string SkillObject::ms_schematicsGrantedLabel = "SCHEMATICS_GRANTED";
const std::string SkillObject::ms_isTitleLabel = "IS_TITLE";
const std::string SkillObject::ms_isProfessionLabel = "IS_PROFESSION";
const std::string SkillObject::ms_isSearchableLabel = "SEARCHABLE";
//-----------------------------------------------------------------
namespace
{
int s_recursionCountDepends = 0;
const int s_recursionCountDependsMax = 7;
//----------------------------------------------------------------------
typedef stdvector<std::string>::fwd StringVector;
inline void tokenizeList (const std::string & str, StringVector & sv, int row, const std::string & columnName)
{
UNREF (row);
UNREF (columnName);
size_t endpos = 0;
std::string token;
static const char * const whitespace = ",";
DEBUG_WARNING (str.find (" \n\r\t") != std::string::npos, ("SkillObject Cell string [%s] row %d column [%s] contains spaces or other invalid characters", row, columnName.c_str ()));
while (Unicode::getFirstToken (str, endpos, endpos, token, whitespace))
{
sv.push_back (token);
if (endpos == std::string::npos)
break;
++endpos;
}
}
}
//---------------------------------------------------------------------
SkillObject::SkillData::SkillData() :
prerequisiteSkills (),
prerequisiteExperience (),
prerequisiteSpecies (),
prerequisiteFactionStanding (),
skillName ("UNINITIALIZED SKILL"),
nextSkillBoxes (),
prevSkill (0),
commandsProvided (),
schematicsGranted (),
statisticModifiers (),
isProfession (false),
isTitle (false),
isSearchable (false)
{
}
//---------------------------------------------------------------------
SkillObject::SkillData::SkillData(const SkillData & source) :
prerequisiteSkills (source.prerequisiteSkills),
prerequisiteExperience (source.prerequisiteExperience),
prerequisiteSpecies (source.prerequisiteSpecies),
prerequisiteFactionStanding (source.prerequisiteFactionStanding),
skillName (source.skillName),
nextSkillBoxes (source.nextSkillBoxes),
prevSkill (0),
commandsProvided (source.commandsProvided),
schematicsGranted (source.schematicsGranted),
statisticModifiers (source.statisticModifiers),
isProfession (source.isProfession),
isTitle (source.isTitle),
isSearchable (source.isSearchable)
{
}
//---------------------------------------------------------------------
SkillObject::SkillData::~SkillData()
{
}
//---------------------------------------------------------------------
SkillObject::SkillData & SkillObject::SkillData::operator = (const SkillData & rhs)
{
if(&rhs != this)
{
prerequisiteSkills = rhs.prerequisiteSkills;
prerequisiteExperience = rhs.prerequisiteExperience;
prerequisiteSpecies = rhs.prerequisiteSpecies;
prerequisiteFactionStanding = rhs.prerequisiteFactionStanding;
skillName = rhs.skillName;
nextSkillBoxes = rhs.nextSkillBoxes;
commandsProvided = rhs.commandsProvided;
schematicsGranted = rhs.schematicsGranted;
statisticModifiers = rhs.statisticModifiers;
isProfession = rhs.isProfession;
isTitle = rhs.isTitle;
isSearchable = rhs.isSearchable;
}
return *this;
}
//---------------------------------------------------------------------
SkillObject::SkillObject() :
skillData()
{
}
//---------------------------------------------------------------------
SkillObject::~SkillObject()
{
}
//---------------------------------------------------------------------
const SkillObject::SkillVector & SkillObject::getNextSkillBoxes() const
{
return skillData.nextSkillBoxes;
}
//-----------------------------------------------------------------------
const SkillObject * SkillObject::getPrevSkill() const
{
return skillData.prevSkill;
}
//---------------------------------------------------------------------
const SkillObject::SkillData & SkillObject::getSkillData() const
{
return skillData;
}
//---------------------------------------------------------------------
const SkillObject::ExperienceVector & SkillObject::getPrerequisiteExperienceVector () const
{
return skillData.prerequisiteExperience;
}
//-----------------------------------------------------------------
const SkillObject::ExperiencePair * SkillObject::getPrerequisiteExperience () const
{
if (skillData.prerequisiteExperience.empty ())
return 0;
else
return &skillData.prerequisiteExperience.front ();
}
//---------------------------------------------------------------------
const SkillObject::SpeciesFlagVector & SkillObject::getPrerequisiteSpecies() const
{
return skillData.prerequisiteSpecies;
}
//---------------------------------------------------------------------
const SkillObject::GenericModVector & SkillObject::getPrerequisiteFactionStanding() const
{
return skillData.prerequisiteFactionStanding;
}
//---------------------------------------------------------------------
const SkillObject::SkillVector & SkillObject::getPrerequisiteSkills() const
{
return skillData.prerequisiteSkills;
}
//---------------------------------------------------------------------
const std::string & SkillObject::getSkillName() const
{
return skillData.skillName;
}
//---------------------------------------------------------------------
const SkillObject::StringVector & SkillObject::getCommandsProvided() const
{
return skillData.commandsProvided;
}
//---------------------------------------------------------------------
const SkillObject::StringVector & SkillObject::getSchematicsGranted() const
{
return skillData.schematicsGranted;
}
//---------------------------------------------------------------------
const std::vector<std::pair<std::string, int> > & SkillObject::getStatisticModifiers() const
{
return skillData.statisticModifiers;
}
//-----------------------------------------------------------------------
SkillObject::SkillData & SkillObject::getSkillData()
{
return skillData;
}
//-----------------------------------------------------------------------
const bool SkillObject::hasCommand(const std::string & commandName) const
{
return std::binary_search (skillData.commandsProvided.begin (), skillData.commandsProvided.end (), commandName);
}
//-----------------------------------------------------------------------
/** get primary category for this skill */
const SkillObject * SkillObject::findCategory() const
{
const SkillObject * p = this;
for (;;)
{
if (p)
{
//-- the categories are at the 2nd level of the heirarchy
if (p->skillData.prevSkill && p->skillData.prevSkill->skillData.prevSkill == 0)
{
return p;
}
p = p->skillData.prevSkill;
}
else
{
break;
}
}
return 0;
}
//-----------------------------------------------------------------------
const bool SkillObject::isProfession() const
{
return skillData.isProfession;
}
//-----------------------------------------------------------------------
const bool SkillObject::isTitle() const
{
return skillData.isTitle;
}
//-----------------------------------------------------------------------
const bool SkillObject::isSearchable() const
{
return skillData.isSearchable;
}
//---------------------------------------------------------------------
void SkillObject::loadPrerequisiteSkills(DataTable &dataTable, int skillRow)
{
const std::string & cellString = dataTable.getStringValue(SkillObject::ms_prerequisiteSkillsLabel, skillRow);
StringVector sv;
sv.clear ();
tokenizeList (cellString, sv, skillRow, SkillObject::ms_prerequisiteSkillsLabel);
skillData.prerequisiteSkills.reserve (sv.size ());
SkillManager & manager = SkillManager::getInstance ();
for (StringVector::const_iterator it = sv.begin (); it != sv.end (); ++it)
{
const std::string & skillName = *it;
const SkillObject * const skill = manager.getSkill (skillName);
if (skill)
skillData.prerequisiteSkills.push_back(skill);
else
WARNING (true, ("prerequisiteSkills skill [%s] does not exist", skillName.c_str ()));
}
std::sort (skillData.prerequisiteSkills.begin (), skillData.prerequisiteSkills.end ());
}
//----------------------------------------------------------------------
void SkillObject::loadPrerequisiteExperience(DataTable &dataTable, int skillRow)
{
const int xpAmount = dataTable.getIntValue(SkillObject::ms_prerequisiteExperienceAmountLabel, skillRow);
const int xpLimit = dataTable.getIntValue(SkillObject::ms_prerequisiteExperienceLimitLabel, skillRow);
if (xpAmount > 0 || xpLimit > 0)
{
const std::string & experienceType = dataTable.getStringValue(SkillObject::ms_prerequisiteExperienceTypeLabel, skillRow);
if (!experienceType.empty ())
skillData.prerequisiteExperience.push_back(std::make_pair(experienceType, std::make_pair(xpAmount, xpLimit)));
else
WARNING (true, ("Nonzero experience specified but empty experience name on row %d", skillRow));
}
}
//---------------------------------------------------------------------
void SkillObject::loadPrerequisiteSpecies(DataTable &dataTable, int skillRow)
{
const std::string & cellString = dataTable.getStringValue(SkillObject::ms_prerequisiteSpeciesLabel, skillRow);
static StringVector sv;
sv.clear ();
tokenizeList (cellString, sv, skillRow, SkillObject::ms_prerequisiteSpeciesLabel);
skillData.prerequisiteSpecies.reserve (sv.size ());
for (StringVector::const_iterator it = sv.begin (); it != sv.end (); ++it)
skillData.prerequisiteSpecies.push_back (std::make_pair (*it, true));
}
//---------------------------------------------------------------------
void SkillObject::loadCommands(DataTable &dataTable, int skillRow)
{
const std::string & cellString = dataTable.getStringValue(SkillObject::ms_commandsLabel, skillRow);
static StringVector sv;
sv.clear ();
tokenizeList (cellString, sv, skillRow, SkillObject::ms_commandsLabel);
skillData.commandsProvided.reserve (sv.size ());
for (StringVector::const_iterator it = sv.begin (); it != sv.end (); ++it)
skillData.commandsProvided.push_back (*it);
std::sort (skillData.commandsProvided.begin (), skillData.commandsProvided.end ());
}
//---------------------------------------------------------------------
void SkillObject::loadSchematicsGranted(DataTable &dataTable, int skillRow)
{
const std::string & cellString = dataTable.getStringValue(SkillObject::ms_schematicsGrantedLabel, skillRow);
static StringVector sv;
sv.clear ();
tokenizeList (cellString, sv, skillRow, SkillObject::ms_schematicsGrantedLabel);
skillData.schematicsGranted.reserve (sv.size ());
for (StringVector::const_iterator it = sv.begin (); it != sv.end (); ++it)
skillData.schematicsGranted.push_back (*it);
std::sort (skillData.schematicsGranted.begin (), skillData.schematicsGranted.end ());
}
//---------------------------------------------------------------------
void SkillObject::loadStatisticsModifiers(DataTable &dataTable, int skillRow)
{
const std::string & cellString = dataTable.getStringValue(SkillObject::ms_statisticsModifiersLabel, skillRow);
static StringVector sv;
sv.clear ();
tokenizeList (cellString, sv, skillRow, SkillObject::ms_statisticsModifiersLabel);
skillData.statisticModifiers.reserve (sv.size ());
for (StringVector::const_iterator it = sv.begin (); it != sv.end (); ++it)
{
const std::string & statEntry = *it;
const size_t splitPos = statEntry.find ('=');
if (splitPos == std::string::npos)
WARNING (true, ("Statistic modifier without an = [%s], skill=%s", statEntry.c_str(), skillData.skillName.c_str()));
else
{
const char * const statValueString = statEntry.c_str () + splitPos + 1;
const std::string & statValueName = statEntry.substr (0, splitPos);
const int32 modifier = atoi (statValueString);
skillData.statisticModifiers.push_back(std::make_pair(statValueName, modifier));
}
}
}
//---------------------------------------------------------------------
void SkillObject::connectLinks(DataTable &dataTable, const std::string & parentName)
{
if (!parentName.empty ())
{
const SkillObject * const parent = SkillManager::getInstance().getSkill (parentName);
if (parent)
{
skillData.prevSkill = parent;
}
}
std::string nextSkillSearchName = skillData.skillName;
if (nextSkillSearchName == "skill_system_root")
{
nextSkillSearchName.clear ();
}
int rows = dataTable.getNumRows();
for (int i = 0; i < rows; i++)
{
const std::string & tmpParent = dataTable.getStringValue(SkillObject::ms_parentLabel, i);
if (tmpParent == nextSkillSearchName)
{
const std::string & nextSkillName = dataTable.getStringValue(SkillObject::ms_skillLabel, i);
const SkillObject * const nextSkill = SkillManager::getInstance().getSkill(nextSkillName);
if (nextSkill)
{
skillData.nextSkillBoxes.push_back(nextSkill);
}
else
{
WARNING (true, ("Could not find skill %s in DataTable", nextSkillName.c_str()));
}
}
}
}
//---------------------------------------------------------------------
bool SkillObject::load(DataTable & dataTable, const std::string & skillName)
{
if (skillName == "skill_system_root")
{
skillData = SkillData();
skillData.skillName = skillName;
connectLinks (dataTable, "");
return true;
}
const int skillColumn = dataTable.findColumnNumber (SkillObject::ms_skillLabel);
if (skillColumn == -1)
{
WARNING (true, ("SkillObject::load Could not find column %s in DataTable", SkillObject::ms_skillLabel.c_str()));
return false;
}
const int skillRow = dataTable.searchColumnString (skillColumn, skillName);
if (skillRow == -1)
{
skillData = SkillData();
WARNING (true, ("SkillObject::load Could not find skill %s in DataTable", skillName.c_str()));
return false;
}
skillData = SkillData();
skillData.skillName = skillName;
loadPrerequisiteSkills (dataTable, skillRow);
loadPrerequisiteExperience (dataTable, skillRow);
loadPrerequisiteSpecies (dataTable, skillRow);
std::string parent = dataTable.getStringValue(SkillObject::ms_parentLabel, skillRow);
if (parent.empty ())
{
parent = "skill_system_root";
}
connectLinks (dataTable, parent);
loadCommands (dataTable, skillRow);
loadSchematicsGranted (dataTable, skillRow);
loadStatisticsModifiers (dataTable, skillRow);
skillData.isTitle = dataTable.getIntValue(SkillObject::ms_isTitleLabel, skillRow) != 0;
skillData.isProfession = dataTable.getIntValue(SkillObject::ms_isProfessionLabel, skillRow) != 0;
skillData.isSearchable = dataTable.getIntValue(SkillObject::ms_isSearchableLabel, skillRow) != 0;
return true;
}
//----------------------------------------------------------------------
const SkillObject * SkillObject::findProfessionForSkill () const
{
const SkillObject * s = this;
while (s)
{
if (s->isProfession ())
return s;
s = s->getPrevSkill ();
}
return 0;
}
//-----------------------------------------------------------------
bool SkillObject::dependsUponSkill (const SkillObject & skill, bool immediatePrereqsOnly) const
{
bool result = false;
++s_recursionCountDepends;
if (s_recursionCountDepends >= s_recursionCountDependsMax)
{
WARNING (true, ("recursion max hit in skill dependency check"));
}
else if (this == &skill)
{
result = true;
}
else
{
const SkillVector & preReqs = getPrerequisiteSkills();
for (SkillVector::const_iterator it = preReqs.begin (); it != preReqs.end (); ++it)
{
const SkillObject * const prereq = NON_NULL (*it);
if(immediatePrereqsOnly)
{
if(prereq == &skill)
result = true;
}
else
{
if (prereq->dependsUponSkill (skill))
{
result = true;
}
}
}
}
--s_recursionCountDepends;
return result;
}
//---------------------------------------------------------------------
@@ -0,0 +1,115 @@
// SkillObject.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _SkillObject_H
#define _SkillObject_H
#include <string>
#include <vector>
class DataTable;
//---------------------------------------------------------------------
class SkillObject
{
public:
SkillObject();
virtual ~SkillObject();
bool load(DataTable & file, const std::string & skillName);
typedef stdvector<const SkillObject *>::fwd SkillVector;
typedef std::pair<int, int> XpPair; // xp needed, xp limit
typedef std::pair<std::string, XpPair> ExperiencePair;
typedef stdvector<ExperiencePair>::fwd ExperienceVector;
typedef std::pair<std::string, int> GenericMod;
typedef stdvector<GenericMod>::fwd GenericModVector;
typedef stdvector<std::string>::fwd StringVector;
typedef std::pair<std::string, bool> SpeciesFlag;
typedef stdvector<SpeciesFlag>::fwd SpeciesFlagVector;
const SkillObject * findCategory () const;
const StringVector & getCommandsProvided () const;
const StringVector & getSchematicsGranted () const;
const SkillVector & getNextSkillBoxes () const;
const ExperienceVector & getPrerequisiteExperienceVector () const;
const ExperiencePair * getPrerequisiteExperience () const;
const GenericModVector & getPrerequisiteFactionStanding () const;
const SkillVector & getPrerequisiteSkills () const;
const SpeciesFlagVector & getPrerequisiteSpecies () const;
const SkillObject * getPrevSkill () const;
const std::string & getSkillName () const;
const GenericModVector & getStatisticModifiers () const;
const bool hasCommand (const std::string & commandName) const;
const bool isProfession () const;
const bool isTitle () const;
const bool isSearchable () const;
const SkillObject * findProfessionForSkill () const;
bool dependsUponSkill (const SkillObject & skill, bool immediatePrereqsOnly = false) const;
struct SkillData
{
SkillData();
SkillData(const SkillData & source);
~SkillData();
SkillData & operator = (const SkillData & rhs);
// prerequisites
SkillVector prerequisiteSkills;
ExperienceVector prerequisiteExperience;
SpeciesFlagVector prerequisiteSpecies;
GenericModVector prerequisiteFactionStanding;
// descriptors
std::string skillName;
SkillVector nextSkillBoxes;
const SkillObject * prevSkill;
// effects
StringVector commandsProvided;
StringVector schematicsGranted;
std::vector<std::pair<std::string, int> > statisticModifiers;
bool isProfession;
bool isTitle;
bool isSearchable;
};
const SkillData & getSkillData() const;
SkillData & getSkillData();
private:
SkillObject(const SkillObject & source);
SkillObject & operator = (const SkillObject & rhs);
SkillData skillData;
static const std::string ms_skillLabel;
static const std::string ms_prerequisiteSkillsLabel;
static const std::string ms_prerequisiteExperienceTypeLabel;
static const std::string ms_prerequisiteExperienceAmountLabel;
static const std::string ms_prerequisiteExperienceLimitLabel;
static const std::string ms_prerequisiteSpeciesLabel;
static const std::string ms_commandsLabel;
static const std::string ms_statisticsModifiersLabel;
static const std::string ms_parentLabel;
static const std::string ms_schematicsGrantedLabel;
static const std::string ms_isTitleLabel;
static const std::string ms_isProfessionLabel;
static const std::string ms_isSearchableLabel;
void loadPrerequisiteSkills (DataTable & file, int skillRow);
void loadPrerequisiteExperience (DataTable & file, int skillRow);
void loadPrerequisiteSpecies (DataTable & file, int skillRow);
void loadCommands (DataTable & file, int skillRow);
void loadSchematicsGranted (DataTable & file, int skillRow);
void loadStatisticsModifiers (DataTable & file, int skillRow);
void connectLinks (DataTable & file, const std::string & parentName);
};
//---------------------------------------------------------------------
#endif // _SkillObject_H
@@ -0,0 +1,45 @@
//======================================================================
//
// SkillObjectArchive.cpp
// copyright (c) 2002 Sony Online Entertainment
//
//======================================================================
#include "sharedSkillSystem/FirstSharedSkillSystem.h"
#include "sharedSkillSystem/SkillObjectArchive.h"
#include "sharedSkillSystem/SkillObject.h"
#include "sharedSkillSystem/SkillManager.h"
#include "Archive/Archive.h"
//======================================================================
namespace Archive
{
//----------------------------------------------------------------------
void get(ReadIterator & source, const SkillObject *& target)
{
std::string name;
Archive::get (source, name);
if (name.empty ())
target = 0;
else
{
target = SkillManager::getInstance ().getSkill (name);
}
}
//-----------------------------------------------------------------------
void put(ByteStream & target, const SkillObject * const & source)
{
if (source)
Archive::put (target, source->getSkillName ());
else
Archive::put (target, std::string ());
}
}
//======================================================================
@@ -0,0 +1,29 @@
//======================================================================
//
// SkillObjectArchive.h
// copyright (c) 2002 Sony Online Entertainment
//
//======================================================================
#ifndef INCLUDED_SkillObjectArchive_H
#define INCLUDED_SkillObjectArchive_H
//======================================================================
#if WIN32
#pragma warning (disable:4800) // forcing value to bool
#endif
#include "Archive/ByteStream.h"
class SkillObject;
namespace Archive
{
void get(ReadIterator & source, const SkillObject *& target);
void put(ByteStream & target, const SkillObject * const& source);
}
//======================================================================
#endif
@@ -0,0 +1,8 @@
// FirstSharedSkillSystem.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedSkillSystem/FirstSharedSkillSystem.h"