RPG游戏的单位属性类

属性因子的类型

  • 可以增加百分比值
  • 可以增加固定值
1
2
3
4
5
6
7
8
9
10
11
/**
* 属性值的因数类型
*
* @enum {number}
*/
enum AttrFactorType {
AFT_Base, // 基础值
AFT_Add_Constant, // 增加固定值
AFT_Add_Percentile, // 增加百分比
AFT_Max // 最大值
};

属性元素

  • 区分属性因子
  • 用于控制属性元素的类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* 属性元素
*
* @class UnitAttrElement
*/
class UnitAttrElement {
private m_aiValues: Array<number> = []; // 属性数组
private m_iResult: number = 0; // 结果
constructor() {
this.clear();
}

/**
* 清除
*
* @memberof SeUnitAttrElem
*/
clear() {
this.m_aiValues[AttrFactorType.AFT_Base] = 0;
this.m_aiValues[AttrFactorType.AFT_Add_Constant] = 0;
this.m_aiValues[AttrFactorType.AFT_Add_Percentile] = 0;
this.m_iResult = 0;
}

/**
* 元素
*
* @param {AttrFactorType} eType
* @memberof SeUnitAttrElem
*/
getFactor(eType: AttrFactorType) {
return this.m_aiValues[eType];
}

/**
* 设置元素
*
* @param {AttrFactorType} eType
* @param {number} val
* @memberof SeUnitAttrElem
*/
setFactor(eType: AttrFactorType, val: number) {
this.m_aiValues[eType] = val;
}

/**
* 设置结果
*
* @memberof SeUnitAttrElem
*/
set result(val: number) {
this.m_iResult = val;
}

/**
* 获取结果
*
* @memberof SeUnitAttrElem
*/
get result() {
return this.m_iResult;
}
}

单位属性值的类型

  • 单位拥有的属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 单位属性类型
*
* @enum {number}
*/
enum UnitAttrType {
UAT_ATK, // 攻击力
UAT_ATK_INTERVAL, // 攻击间隔
UAT_DEF, // 防御力
UAT_HP, // 当前生命值
UAT_HP_LIMIT, // 生命值上限
UAT_MP, // 当前的魔法值
UAT_MP_LIMIT, // 魔法值上限
UAT_SPEED, // 速度
UAT_DODGE, // 闪避
UAT_MAX,
}

单位属性类

  • 可以挂在单位类上,用于计算属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/**
* 单位属性类
*
* @class UnitAttr
*/
class UnitAttr {
private m_akUnitAttr: Array<UnitAttrElement> = []; // 属性数组
static SCALE = 1; // 缩放数据用于去除小数 转化为定点数
static PERCENTAGE_100 = 100 * UnitAttr.SCALE; // 百分百
static MIN_ATTACK_VALUE = 1 * UnitAttr.SCALE; // 攻击力最小值为1
static MIN_HP_LIMIT = 1 * UnitAttr.SCALE; // 最小生命值
static MIN_MP_LIMIT = 1 * UnitAttr.SCALE; // 最小魔法值
static MIN_ATK_INTERVAL_PERCENTAGE = -50 * UnitAttr.SCALE; // 最小攻击间隔
static MIN_ATK_INTERVAL_VALUE = 150 * UnitAttr.SCALE; // 最小攻击间隔值
static MAX_DODGE_CHANCE = 95 * UnitAttr.SCALE; // 最大闪避百分比
static MIN_MOVE_SPEED = 15 * UnitAttr.SCALE; // 最小移动速度

constructor() {
// 初始化当前的属性数组
for (let i = 0; i < UnitAttrType.UAT_MAX; i++) {
this.m_akUnitAttr[i] = new UnitAttrElement();
}
}

/**
* 根据配置文件的内容设置当前单位属性
*
* @param {*} res
* @memberof UnitAttr
*/
init(res: any) {
// 初始化单位的相关基础属性
}

/**
* 清理属性
*
* @param {UnitAttrType} eType
* @memberof UnitAttr
*/
clear(eType: UnitAttrType) {
this.m_akUnitAttr[eType].clear();
}

/**
* 重置当前属性因子
*
* @param {UnitAttrType} eAttrType
* @param {AttrFactorType} eFactorType
* @param {number} iValue
* @memberof UnitAttr
*/
resetCommonAttrFactor(eAttrType: UnitAttrType, eFactorType: AttrFactorType, iValue: number) {
this.m_akUnitAttr[eAttrType].setFactor(eFactorType, iValue);
this.updateCascade(eAttrType);
}

/**
* 修改属性因子
*
* @param {UnitAttrType} eAttrType
* @param {AttrFactorType} eFactorType
* @param {number} iValue
* @memberof UnitAttr
*/
incrementCommonAttrFactor(eAttrType: UnitAttrType, eFactorType: AttrFactorType, iValue: number) {
let old = this.m_akUnitAttr[eAttrType].getFactor(eFactorType);
this.m_akUnitAttr[eAttrType].setFactor(eFactorType, old + iValue);
// 立即更新本属性以及它的相关属性,不等到Update
this.updateCascade(eAttrType);
}

/**
* 读取当前属性结果
*
* @param {UnitAttrType} eType
* @returns
* @memberof UnitAttr
*/
readCommonAttrResult(eType: UnitAttrType) {
return this.m_akUnitAttr[eType].result;
}

/**
* 获取因子
*
* @param {UnitAttrType} eAttrType
* @param {AttrFactorType} eFactorType
* @returns
* @memberof UnitAttr
*/
readCommonAttrFactor(eAttrType: UnitAttrType, eFactorType: AttrFactorType) {
return this.m_akUnitAttr[eAttrType].getFactor(eFactorType);
}

/**
* 更新需要修改的主属性并修改相关的属性
* 每一点防御力增加一点血量之类的
* @param {UnitAttrType} ePrimaryAttr
* @memberof UnitAttr
*/
updateCascade(ePrimaryAttr: UnitAttrType) {
// 先更新主属性
this.updateSingle(ePrimaryAttr);
}

/**
* 刷新所有属性值
*
* @memberof UnitAttr
*/
updateAllAttrs() {
for (let i = 0; i < UnitAttrType.UAT_MAX; i++) {
this.updateCascade(i);
}
}

/**
* 只更新当前自己的主属性
*
* @param {UnitAttrType} eType
* @memberof UnitAttr
*/
private updateSingle(eType: UnitAttrType) {
// 获取属性元素
let attrElem = this.m_akUnitAttr[eType];
switch(eType) {
case UnitAttrType.UAT_ATK: {
attrElem.result = this.updateATK(attrElem);
break;
}
case UnitAttrType.UAT_ATK_INTERVAL: {
attrElem.result = this.updateATK_INTERVAL(attrElem);
break;
}
case UnitAttrType.UAT_DEF: {
attrElem.result = this.updateDEF(attrElem);
break;
}
case UnitAttrType.UAT_HP: {
attrElem.result = this.updateHP(attrElem);
break;
}
case UnitAttrType.UAT_HP_LIMIT: {
attrElem.result = this.updateHP_LIMIT(attrElem);
break;
}
case UnitAttrType.UAT_MP: {
attrElem.result = this.updateMP(attrElem);
break;
}
case UnitAttrType.UAT_MP_LIMIT: {
attrElem.result = this.updateMP_LIMIT(attrElem);
break;
}
case UnitAttrType.UAT_SPEED: {
attrElem.result = this.updateSPEED(attrElem);
break;
}
case UnitAttrType.UAT_DODGE: {
attrElem.result = this.updateDODGE(attrElem);
break;
}
}
}

/**
* 更新攻击力
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateATK(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
if (iResult < UnitAttr.MIN_ATTACK_VALUE) {
iResult = UnitAttr.MIN_ATTACK_VALUE;
}
return iResult;
}

/**
* 更新攻击间隔
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateATK_INTERVAL(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
if (iAddPer < UnitAttr.MIN_ATK_INTERVAL_PERCENTAGE) {
iAddPer = UnitAttr.MIN_ATK_INTERVAL_PERCENTAGE;
}
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
if (iResult < UnitAttr.MIN_ATK_INTERVAL_VALUE) {
iResult = UnitAttr.MIN_ATK_INTERVAL_VALUE;
}
return iResult;
}

/**
* 更新防御力
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateDEF(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
return iResult;
}

/**
* 更新当前生命值
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateHP(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
if (iResult < 0) {
iResult = 0;
}
return iResult;
}

/**
* 更新最大生命值
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateHP_LIMIT(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
if (iResult < UnitAttr.MIN_HP_LIMIT) {
iResult = UnitAttr.MIN_HP_LIMIT;
}
return iResult;
}

/**
* 更新当前魔法值
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateMP(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
if (iResult < 0) {
iResult = 0;
}
return iResult;
}

/**
* 更新最大魔法值
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateMP_LIMIT(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
if (iResult < UnitAttr.MIN_MP_LIMIT) {
iResult = UnitAttr.MIN_MP_LIMIT;
}
return iResult;
}

/**
* 更新速度
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateSPEED(rkAttr: UnitAttrElement) : number {
let iBase = rkAttr.getFactor(AttrFactorType.AFT_Base);
let iAddValue = rkAttr.getFactor(AttrFactorType.AFT_Add_Constant);
let iAddPer = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
let iResult = (iBase + iAddValue) * (1 + iAddPer / UnitAttr.PERCENTAGE_100);
if (iResult < UnitAttr.MIN_MOVE_SPEED) {
iResult = UnitAttr.MIN_MOVE_SPEED;
}
return iResult;
}

/**
* 更新闪避几率
*
* @param {UnitAttrElement} rkAttr
* @memberof UnitAttr
*/
private updateDODGE(rkAttr: UnitAttrElement) : number {
let iResult = rkAttr.getFactor(AttrFactorType.AFT_Add_Percentile);
if (iResult < 0) {
iResult = 0;
}
if (iResult > UnitAttr.MAX_DODGE_CHANCE) {
iResult = UnitAttr.MAX_DODGE_CHANCE;
}
return iResult;
}
}