问题表现
部分 BOSS 战斗到残血后持续显示“免疫”,但 BOSS 仍可移动、攻击玩家。
诊断日志:
MonsterImmunityTrace Reason=Unbreakable
MonsterImmunityTrace Monster ... HP=191884/292864 AIState=6 ...
UnbreakableDirty=0 ImpactCount=0
ImpactCount=0 表示效果列表已经没有无敌效果,但角色属性缓存仍处于无敌状态。
根因
文件:
Prj/GameCode/Server/Server/GameServer/Server/Skills/ImpactLogic/StdImpact014.cpp
旧代码把所有非零 UnbreakableRefix 都转换成 TRUE:
case CharBoolAttrs_T::ATTR_UNBREAKABLE:
{
if (0 != GetUnbreakableRefix(rImp))
{
rBoolAttrRefix = TRUE;
return TRUE;
}
}
break;
配置中的 UnbreakableRefix=-1 是无效值,不代表开启无敌。旧代码将 -1 当成非零值处理,最终错误地开启了无敌属性。
0.85 参考端 StdImpact014_T::GetBoolAttrRefix()(IDA 地址 0x83CD8EC)返回配置原值。上层调用使用 TRUE == 返回值 判断,因此只有 1 会生效,-1 不会生效。
修复代码
将 ATTR_UNBREAKABLE 分支修改为:
case CharBoolAttrs_T::ATTR_UNBREAKABLE:
{
INT const nUnbreakableRefix = GetUnbreakableRefix(rImp);
if (0 != nUnbreakableRefix)
{
rBoolAttrRefix = TRUE;
// 参考端返回配置原值。-1 表示无效,调用方的 TRUE == 返回值判断会将其排除。
return nUnbreakableRefix;
}
}
break;
返回值语义:
UnbreakableRefix |
处理结果 |
0 |
不修改无敌属性 |
1 |
开启无敌属性 |
-1 |
无效值,上层严格比较时不会生效 |
补丁
case CharBoolAttrs_T::ATTR_UNBREAKABLE:
{
- if (0 != GetUnbreakableRefix(rImp))
+ INT const nUnbreakableRefix = GetUnbreakableRefix(rImp);
+ if (0 != nUnbreakableRefix)
{
rBoolAttrRefix = TRUE;
- return TRUE;
+ // 参考端返回配置原值。-1 表示无效,调用方的 TRUE == 返回值判断会将其排除。
+ return nUnbreakableRefix;
}
}
break;
不要修改 StandardImpact.txt。问题来自 C++ 将 -1 错误归一化为 TRUE。
|