背景交代
游戏开发中,角色属性系统设计是一个很重要的功能,本文对在历史项目中使用过的系统做一个总结和概括。本系统特点:
- 属性分为一级属性如体力,力量,敏捷等和二级属性,如攻击力,抵抗,HP上限等。
- 一级属性可以影响二级属性,如体力影响HP上限,力量可以提高物理攻击,智力影响魔法攻击。
- 属性可以支持按倍数百分比增益,按具体值增益。
属性定义
enum CHAR_ATTRIBUTE_TYPE {
catStrength = 0, // 力量
catIntelligence = 1, // 体力
catResillience = 2,
catAgility = 3,
catRunSpeed = 4,
catMaxHp = 5, // 最大血量
catMaxMp = 6,
catHpPercent = 7,
catMpPercent = 8,
catMinPhyAtk = 9,
catMaxPhyAtk = 10,
// ... 其他省略
catEnd = 32,
};
模块定义
定义CAttrModule角色模块,角色初始化时对模块进行初始化。
- 设置角色等级时,根据等级设置玩家的基础属性
- 遍历玩家穿戴装备,武器,首饰,设置SetAttrA,SetAttrB
// 万分比 分母
#define RATE_MAX 10000
// 属性类型允许最小最大值,通常在策划配置文件中定义,启动服务器时初始化
static INT32 m_nAttrMin[catEnd];
static INT32 m_nAttrMax[catEnd];
static bool isFirstLevelAttrType(nAttrType) {
return nAttrType >= catStrength && nAttrType <= catAgility;
}
// 模块定义
class CAttrModule
{
protected:
CCharacter* m_pOwner;
INT32 m_AttrList[catEnd]; // 属性最终值
INT32 m_AttrListBase[catEnd]; // 属性基础值
INT32 m_AttrListA[catEnd]; // 对应属性放大百分比
INT32 m_AttrListB[catEnd]; // 对应属性加成值
protected:
BOOL calcAttrType(INT32 nAttrType, BOOL bSync);
public:
BOOL Init(CCharacter* pOwner) { /* ...*/ }
BOOL UnInit() { /* ...*/ }
inline INT32 GetAttr(INT32 nAttrType) {
INT32 nVal = m_AttrList[nAttrType];
if (nVal < m_nAttrMin[nAttrType]) nVal = m_nAttrMin[nAttrType];
if (nVal > m_nAttrMax[nAttrType]) nVal = m_nAttrMax[nAttrType];
return nVal;
}
inline INT32 GetAttrBase(INT32 nAttrType) { return m_nAttrBase[nAttrType]; }
inline INT32 GetAttrA(INT32 nAttrType); { return m_nAttrA[nAttrType]; }
inline INT32 GetAttrB(INT32 nAttrType) { return m_nAttrB[nAttrType]; }
void SetAttrBase(INT32 nAttrType, INT32 nValue, BOOL bSync = TRUE);
void AddAttrA(INT32 nAttrType, INT32 nValue, BOOL bSync = TRUE);
void AddAttrB(INT32 nAttrType, INT32 nValue, BOOL bSync = TRUE);
};
void CAttrModule::SetAttrBase(INT32 nAttrType, INT32 nValue, BOOL bSync) {
// TODO 检查nAttrType合法性,越界
m_AttrListBase[nAttrType] = nValue;
calcAttrType(nAttrType, bSync);
}
void CAttrModule::AddAttrA(INT32 nAttrType, INT32 nValue, BOOL bSync) {
// TODO 检查nAttrType合法性,越界
m_AttrListA[nAttrType] += nValue;
calcAttrType(nAttrType, bSync);
}
void CAttrModule::AddAttrB(INT32 nAttrType, INT32 nValue, BOOL bSync) {
// TODO 检查nAttrType合法性,越界
m_AttrListB[nAttrType] += nValue;
calcAttrType(nAttrType, bSync);
}
void CAttrModule::calcAttrType(INT32 nAttrType, BOOL bSync) {
INT32 nOldValue = m_nAttrList[nAttrType];
// 总属性 = (基础属性 + 属性加成值) * (1 + 属性加成万分比 / 10000)
m_AttrList[nAttrType] = (m_nAttrListBase[nAttrType] + m_nAttrListB[nAttrType])
* (1.0 + (FLOAT)m_AttrListA[nAttrType] / RATE_MAX);
if (m_AttrList[nAttrType] < 0)
m_AttrList[nAttrType] = 0;
// TODO 属性变化同步
if (bSync) {
}
// TODO 取配置表种nAttrType影响其他哪些属性,影响数值并实施(百分比,数值)
if (isFirstLevelAttrType(nAttrType)) {
/*
for (INT32 i = 0; i < EffectAttrList.size(); ++i) {
// AddAttrA(EffectAttrList[i].nAddAttrA);
// AddAttrB(EffectAttrList[i].nAddAttrB);
}
*/
}
}