mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-29 23:15:56 -04:00
Added the sharedSkillSystem library
This commit is contained in:
@@ -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)
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ExpertiseManager.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FirstSharedSkillSystem.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/LevelManager.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/SkillManager.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/SkillObject.h"
|
||||
+1
@@ -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 ¤tRecord;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no more levels, so return this (the last) one
|
||||
return ¤tRecord;
|
||||
}
|
||||
|
||||
++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"
|
||||
|
||||
Reference in New Issue
Block a user