天堂开发笔记(四)
开发记录
道具使用
能够喝药水、使用武器、使用装备、选择箭矢
[Recv C] C_OPCODE_USEITEM 请求使用道具
0000: 18 e8 0b 30 13 00 f3 04 ...0....
[Send C] S_OPCODE_SKILLSOUNDGFX 产生自身动画
0000: 56 e0 0b 30 13 bf 00 00 00 00 00 00 00 00 00 00 V..0............
[Send C] S_OPCODE_SKILLHASTE 魔法或物品产生的加速效果
0000: 0b e0 0b 30 13 01 08 07 ...0....
[Send C] S_OPCODE_ITEMSTATUS 物品状态更新
0000: 5f e8 0b 30 13 c7 bf bb af d7 d4 ce d2 bc d3 cb _..0............
0010: d9 d2 a9 cb ae 20 28 32 39 29 00 1d 00 00 00 00 ..... (29)......
[Send C] S_OPCODE_ITEMSTATUS 物品状态更新
0000: 5f e8 0b 30 13 c7 bf bb af d7 d4 ce d2 bc d3 cb _..0............
0010: d9 d2 a9 cb ae 20 28 32 39 29 00 1d 00 00 00 00 ..... (29)......
[Send C] S_OPCODE_ACTIVESPELLS 激活的符咒
0000: 64 0a 00 00 d...
[Handle] ==end==
0000: 18 e8 0b 30 13 00 f3 04 ...0....
[Recv C] C_OPCODE_USEITEM 请求使用道具
0000: 18 e9 0b 30 13 00 00 00 ...0....
[Send C] S_OPCODE_SKILLSOUNDGFX 产生自身动画
0000: 56 e0 0b 30 13 c5 00 00 00 00 00 00 00 00 00 00 V..0............
[Send C] S_OPCODE_SERVERMSG 系統訊息
0000: 78 4d 00 00 xM..
[Send C] S_OPCODE_HPUPDATE 體力與最大體力更新
0000: 26 10 00 10 00 00 00 00 &.......
[Send C] S_OPCODE_ITEMSTATUS 物品状态更新
0000: 5f e9 0b 30 13 b9 c5 b4 fa d6 d5 bc ab cc e5 c1 _..0............
0010: a6 bb d6 b8 b4 bc c1 20 28 31 39 39 29 00 c7 00 ....... (199)...
0020: 00 00 00 00 ....
[Send C] S_OPCODE_ITEMSTATUS 物品状态更新
0000: 5f e9 0b 30 13 b9 c5 b4 fa d6 d5 bc ab cc e5 c1 _..0............
0010: a6 bb d6 b8 b4 bc c1 20 28 31 39 39 29 00 c7 00 ....... (199)...
0020: 00 00 00 ...
[Send C] S_OPCODE_ACTIVESPELLS 激活的符咒
0000: 64 0a 00 00 d...
[Handle] ==end==
0000: 18 e9 0b 30 13 00 00 00 ...0....
[Recv C] C_OPCODE_USEITEM 请求使用道具
0000: 18 02 0c 30 13 00 f3 04 ...0....
[Send C] S_OPCODE_ITEMNAME 物品名稱
0000: 6e 02 0c 30 13 c1 d4 c8 cb d6 ae b9 ad 20 28 24 n..0......... ($
0010: 39 29 00 00 9)..
[Send C] S_OPCODE_OWNCHARSTATUS 角色屬性與能力值
0000: 22 e0 0b 30 13 01 00 00 00 00 14 08 09 0c 0e 0c "..0............
0010: 10 00 10 00 01 00 01 00 0a 10 65 99 97 28 00 00 ..........e..(..
0020: 00 00 00 00 00 .....
[Send C] S_OPCODE_CHARVISUALUPDATE 切換物件外觀動作
0000: 12 e0 0b 30 13 14 00 00 ...0....
[Handle] ==end==
0000: 18 02 0c 30 13 00 f3 04 ...0....
[Recv C] C_OPCODE_USEITEM 请求使用道具
0000: 18 fa 0b 30 13 00 fd 44 ...0...D
[Send C] S_OPCODE_SPMR 魔法攻擊力與魔法防禦力
0000: 53 00 0a 00 S...
[Send C] S_OPCODE_SPMR 魔法攻擊力與魔法防禦力
0000: 53 00 0a 00 S...
[Send C] S_OPCODE_ITEMNAME 物品名稱
0000: 6e fa 0b 30 13 c3 f0 c4 a7 bd e4 d6 b8 20 28 24 n..0......... ($
0010: 31 31 37 29 00 00 00 00 117)....
[Send C] S_OPCODE_OWNCHARSTATUS 角色屬性與能力值
0000: 22 e0 0b 30 13 01 00 00 00 00 14 08 09 0c 0e 0c "..0............
0010: 10 00 10 00 01 00 01 00 0a 10 65 99 97 28 00 00 ..........e..(..
0020: 00 00 00 00 00 .....
[Send C] S_OPCODE_OWNCHARATTRDEF 角色屬性值
0000: 51 0a 00 00 00 00 00 00 Q.......
[Send C] S_OPCODE_OWNCHARSTATUS 角色屬性與能力值
0000: 22 e0 0b 30 13 01 00 00 00 00 14 08 09 0c 0e 0c "..0............
0010: 10 00 10 00 01 00 01 00 0a 10 65 99 97 28 00 00 ..........e..(..
0020: 00 00 00 00 00 .....
[Send C] S_OPCODE_SPMR 魔法攻擊力與魔法防禦力
0000: 53 00 0a 00 S...
[Handle] ==end==
0000: 18 fa 0b 30 13 00 fd 44 ...0...D
[Recv C] C_OPCODE_USEITEM 请求使用道具
0000: 18 e2 0b 30 13 00 18 45 ...0...E
[Send C] S_OPCODE_SERVERMSG 系統訊息
0000: 78 c4 01 01 ba da c9 ab c3 d7 cb f7 c0 f2 bc fd x...............
0010: 20 28 31 30 30 30 29 00 (1000).
[Handle] ==end==
0000: 18 e2 0b 30 13 00 18 45 ...0...E
[Recv C] S_OPCODE_CHARRESET 角色重置
0000: 2b 00 00 00 +...
[Handle] ==end==
0000: 2b 00 00 00 +...
[Send C] S_OPCODE_DISCONNECT 立即中斷連線
0000: 58 f4 01 00 00 00 00 00 X.......
Java版本的道具使用将所有逻辑都写在了一个函数中,不方便后期添加和调试,于是我重构了下,道具使用分为材料道具使用(etcitem)、武器道具使用(weapon)和防具道具使用(armor)
C_ItemUse
道具使用主流程,做一些共性判断,检测玩家当前状态是否能够使用道具,然后根据请求使用的道具类型调用不同类型道具的处理函数C_ArmorItem、C_WeaponItem
C_ArmorItem
处理防具使用,先执行判断检测
- 检测是否存在等级限制
- 检测是否存在职业限制
- 检测装备槽是否有空位
- 检测是否和已经装备的防具有冲突
然后装备上或脱下道具,并更新玩家状态然后返回更新后的状态到客户端
EquipmentSlot
在实现武器/防具的使用前,需要先实现玩家装备槽
属性:
- 装备槽所属的角色
- 当前装备的套装
- 当前装备的道具
方法:
- 穿上道具,并更新角色属性
- 脱下道具,并更新角色属性
C_WeaponItem
处理武器使用,先执行判断检测
- 检测是否存在等级限制
- 检测是否存在职业限制
- 检测是否和已经装备的防具有冲突
然后装备上或脱下或切换道具,并更新玩家状态然后返回更新后的状态到客户端
C_EtcItem
处理材料使用,先执行判断检测
- 检测是否存在等级限制
- 特殊类型的道具特殊处理
- 根据道具模板ID选择对应的道具处理类
道具处理类
C_EtcItemBase
道具处理基类抽象
属性
- item_ids:标明当前类能处理的道具种类
方法
- 返回禁止使用道具信息到客户端
- 处理道具的使用
角色属性计算
力量、敏捷、体质、智力、精神、魅力
# 万能药水使用总数
_elixirStats = 0
# 力量
_str = 0
_trueStr = 0
_baseStr = 0
_originalStr = 0
# 体质
_con = 0
_trueCon = 0
_baseCon = 0
_originalCon = 0
# 敏捷
_dex = 0
_trueDex = 0
_baseDex = 0
_originalDex = 0
# 魅力
_cha = 0
_trueCha = 0
_baseCha = 0
_originalCha = 0
# 智力
_int = 0
_trueInt = 0
_baseInt = 0
_originalInt = 0
# 精神
_wis = 0
_trueWis = 0
_baseWis = 0
_originalWis = 0
为什么每种属性都用四种值表示?
以力量属性为例,角色力量属性的来源分为:职业的基础属性、创建角色奖励玩家的属性、50级以后的属性奖励、万能药水以及装备/武器的属性。
现在我们来看看如何描述这些属性来源:
- _originalStr(下面两项属PcInstance)
代表职业的基础属性+创建角色奖励玩家的属性,代表原始力量值,这个值只有在C_CreateChar和C_CharReset才会被改变 - _baseStr
代表_originalStr+万能药水+50级以后的属性奖励,这个值就是对应Characters的str字段值 - _trueStr(下面两项属characters)
代表_baseStr+装备/武器的属性,在装备或使用武器/装备造成的力量变动时候使用 - _str
代表角色力量属性有效值,确保_trueStr在[1,127]区间,为什么_str而不直接在_trueStr上设置[1,127]区间呢? 举个例子:假设当前_baseStr=125,准备使用的装备增加i=3点力量,那么_trueStr=_baseStr+i => 128、_str => 127,如果去掉_str,即_trueStr=127,那么当脱下装备的时候,_trueStr -= i => 124,把_baseStr也多扣了1,所以我们需要_trueStr来计算使用或脱下装备造成的属性改动,使用_str来表示力量属性的真正有效值
命中、伤害
# 近战伤害
_dmgup = 0
_trueDmgup = 0
_baseDmgup = 0
_originalDmgup = 0
_dmgModifierByArmor = 0
# 远程伤害
_bowDmgup = 0
_trueBowDmgup = 0
_baseBowDmgup = 0
_originalBowDmgup = 0
_bowDmgModifierByArmor = 0
# 近战命中
_hitup = 0
_trueHitup = 0
_baseHitup = 0
_originalHitup = 0
_hitModifierByArmor = 0
# 远程命中
_bowHitup = 0
_trueBowHitup = 0
_baseBowHitup = 0
_originalBowHitup = 0
_bowHitModifierByArmor = 0
# 魔法伤害
_originalMagicDamge = 0
# 魔法命中
_originalMagicHit = 0
# 魔法暴击
_originalMagicCritical = 0
和前面的力量属性很类似,这边的命中和伤害用了五种值表示
以伤害为例(命中同理),伤害加成的来源分为:人物属性值产生的伤害加成、武器产生的伤害加成、人物等级产生的伤害加成、魔法产生的伤害加成
- _dmgModifierByArmor(下面三项属PcInstance)
代表装备产生的伤害加成 - _originalDmgup
代表人物属性值产生的伤害,在resetOriginalDmgup函数中根据角色的_originalStr属性计算伤害加成 - _baseDmgup
代表人物等级产生的伤害加成,在resetBaseDmgup函数中根据角色等级计算伤害加成 - _trueDmgup(下面两项属characters)
代表_baseDmgup+魔法产生的伤害加成 - _dmgup
代表角色空手时的有效伤害加成和力量属性的_str一个意思 - _originalMagicHit
代表人物属性值产生的魔法命中,在resetOriginalMagicHit函数中根据角色的_originalInt属性计算魔法命中 - _originalMagicCritical
代表人物属性值产生的魔法暴击,在resetOriginalMagicCritical函数中根据角色的_originalInt属性计算魔法暴击
和力量属性不同的是,角色最终的伤害加成并不仅仅是简单的_dmgup + _originalDmgup + _dmgModifierByArmor,这个值是在calcPcPcDamage、calcPcNpcDamage、calcNpcPcDamage中动态计算出来的,和角色攻击对象也有关联,需要扣除攻击对象的伤害减免
防御
_ac = 0
_trueAc = 0
_baseAc = 0
_originalAc = 0
和前面的力量属性很类似,这边的防御也用了四种值表示
防御的来源分为:人物属性值产生的防御、装备产生的防御、人物等级产生的防御、魔法产生的防御
- _originalAc(下面两项属PcInstance)
代表人物属性值产生的防御,在resetOriginalAc函数中根据角色的_originalDex属性计算防御 - _baseAc
代表人物等级产生的防御,在resetBaseAc函数中根据角色等级和敏捷计算防御 - _trueAc(下面两项属characters)
代表_baseAc + _originalAc + 装备产生的防御 + 魔法产生的防御 - _ac
代表角色防御有效值
血量、魔量
# 血量
_currentHp = 0
_maxHp = 0
_trueMaxHp = 0
_baseMaxHp = 0
_originalHpup = 0
_advenHp = 0
# 魔量
_currentMp = 0
_maxMp = 0
_trueMaxMp = 0
_baseMaxMp = 0
_originalMpup = 0
_advenMp = 0
这些值的概念和防御非常类似
- _originalHpup(下面两项属PcInstance)
代表人物属性值产生的血量,在resetOriginalHpup函数中根据角色的_originalCon属性计算血量 - _baseMaxHp
代表random(_originalHpup) + 等级产生的血量,这个值就是对应Characters的MaxHp字段值 - _trueMaxHp(下面三项属characters)
代表_baseMaxHp + 装备产生的血量 + 魔法产生的血量 - _maxHp
代表角色血量上限,即_trueMaxHp的有效值 - _currentHp
代表角色当前血量值
体力回复量、魔力回复量
# 体力回复量
_hpr = 0
_trueHpr = 0
_originalHpr = 0
# 魔力回复量
_mpr = 0
_trueMpr = 0
_originalMpr = 0
以体力回复量为例,角色的体力回复量来源分为:人物属性产生的回复量、装备产生的回复量、药水产生的回复量(回血量和等级无关,所以没有_baseHpr)
- _originalHpr
代表人物属性值产生的体力回复量,在resetOriginalHpr函数中根据角色的_originalCon属性计算回血量 - _trueHpr
代表套装产生的回血量 - _hpr
代表角色体力回复量有效值
魔法防御、魔法攻击
# 魔防
_mr = 0
_trueMr = 0
_baseMr = 0
_originalMr = 0
# 魔攻
_sp = 0
魔防来源:人物属性产生的魔防、装备产生的魔防、魔法产生的魔防、人物等级产生的魔防
- _originalMr
代表人物属性值产生的魔防,在resetOriginalMr函数中根据角色的_originalWis属性计算魔防 - _baseMr
代表人物等级产生的魔防,在resetBaseMr函数中根据角色等级和精神计算魔防 - _trueMr
代表 _originalMr + _baseMr + 装备和魔法产生的魔防 - _mr
代表角色魔防有效值
魔攻本来也可以这么弄,但是原先的代码没这么设计,后期可以改成和魔防一样
重量减免、伤害减免、魔法消耗减免
# 重量减免
_weightReduction = 0
_originalStrWeightReduction = 0
_originalConWeightReduction = 0
# 伤害减免
_damageReductionByArmor = 0
# 魔法消耗减免
_originalMagicConsumeReduction = 0
负重减免可以提供角色更多的负重量,伤害减免可以使角色受到的伤害值减小,魔法消耗减免可以减少用户使用魔法时的魔量。其中伤害减免的来源:人物等级、防御值、魔法、装备,后期也可以改造成和前面的属性值一样的模式
属性防御、抗性
# 属性防御
_wind = 0
_trueWind = 0
_water = 0
_trueWater = 0
_fire = 0
_trueFire = 0
_earth = 0
_trueEarth = 0
# 眩晕抗性
_registStun = 0
_trueRegistStun = 0
# 石化抗性
_registStone = 0
_trueRegistStone = 0
# 睡眠抗性
_registSleep = 0
_trueRegistSleep = 0
# 冰冻抗性
_registFreeze = 0
_trueRegistFreeze = 0
# 支撑抗性
_registSustain = 0
_trueRegistSustain = 0
# 闇暗抗性
_registBlind = 0
_trueRegistBlind = 0
属性防御和抗性的来源基本就是装备和魔法
移速
# 一段加速
_moveSpeed
# 二段加速
_braveSpeed
一段就是绿色药水,二段就是勇敢药水,只有有和没有两种状态,没有其他特殊计算
其他属性
后期补充,目前对属性调整比较重要的就这些,其他的后面补充的时候再添加上
BUG修复
描述:灭魔戒子使用只加2点魔防,打印发送和接收数据包的日志,发现"没什么"不同
解决办法:新增日志打印加密和解密前后的数据包,发现两个数据包是没有发送出去的,仔细分析代码是自己自作聪明在不该填充0字节的时候给特殊数据包填充0字节导致数据包正常发送,导致后面的数据包解析出了问题