找回密码
 注册
查看: 2443|回复: 6

[资料] 原版AI中两个造成NPC不动作的BUG

[复制链接]
发表于 2011-10-15 09:54:33 | 显示全部楼层 |阅读模式
BUG 1:
文件:x0_i0_talent

位置:

// Try a given talent.
// This will only cast spells and feats if the targets do not already
// have the effects of those feats, and will funnel all talents
// through bkTalentFilter for a final check.
int TryTalent(talent tUse, object oTarget=OBJECT_SELF, object oCaster=OBJECT_SELF)
{
    int nType = GetTypeFromTalent(tUse);
    int nIndex = GetIdFromTalent(tUse);
    if(nType == TALENT_TYPE_SPELL  && GetHasSpellEffect(nIndex, oTarget))
    {
        return FALSE;
    }
    else if(nType == TALENT_TYPE_FEAT && GetHasFeatEffect(nIndex, oTarget))
    {
        return FALSE;

    }
    // MODIFIED February 7 2003. Implicit else, implies success.
    bkTalentFilter(tUse, OBJECT_SELF);
    //MyPrintString("TryTalent Successful Exit");
    return TRUE;

    return FALSE;
}

虽然有注释(Implicit else),但这个"Implicit else"怎么看也明显不对。它在bkTalentFilter完成后无条件返回,后面的return FALSE永远不可能执行。并且,如果bkTalentFilter如果返回FALSE,即调用失败的话,那么在当前tryTalent返回TRUE将导致其在DeterminCombatRound中的后续备选talent全部被忽略,角色在当前round和之后的所有round中将一直发呆,直到下一次onPercepition或onAttacked被触发;而一旦之后每一次触发onPerception或onAttacked都陷在此处,角色将在战斗中作壁上观,看着你的PC人物被一群敌人围攻而丝毫不行动。

修正的方法也很简单,if语句把bkTalentFilter括起来即可:

    // MODIFIED February 7 2003. Implicit else, implies success.
    if(bkTalentFilter(tUse, OBJECT_SELF))
    {
        //MyPrintString("TryTalent Successful Exit");
        return TRUE;
    }

    return FALSE;


BUG2:
文件:x0_inc_generic

位置:

    if (GetTypeFromTalent(tUse) == TALENT_TYPE_FEAT)
    {
        //MyPrintString("Using feat: " + IntToString(iId));
        nNotValid = TRUE;
        if (VerifyCombatMeleeTalent(tUse, oTarget)
            && VerifyDisarm(tUse, oTarget))
        {
            //MyPrintString("combat melee & disarm OK");
            nNotValid = FALSE;
        }
    }

这段的意思,是确保角色如果打算使用卸除武器时,卸除武器能被正确地使用。VerifyDisarm的作用是判断卸除武器在当前情况下是否合法:要么tUse和oTarget都正确(即可以正确使用),要么根本没有用卸除武器这个技能(即tUse不等于卸除武器)。单看这一句看不出什么问题,我们先往下看二十行左右:

    // * BK: My talent was not appropriate to use
    // *     will attack this round instead
    if (nNotValid)
    {
        //MyPrintString("Invalid talent, id: " + IntToString(iId)
        //              + ", type: " + IntToString(GetTypeFromTalent(tUse)));

        if (bJustTest == FALSE)
          WrapperActionAttack(oTarget);
    }
    else
    {
        if (bJustTest == FALSE)
         ActionUseTalentOnObject(tFinal, oTarget);
         return TRUE;
    }

这下问题来了:如果前面一段中tUse不是disarm的话,bNotValid也会等于FALSE,那么在后面这段中,如果使用tUse的动机检查失败之后,直接进行物理攻击的逻辑将会错误地执行,将一个不是disarm的talent用到oTarget身上。当然如果tUse是一个可指定目标的talent,我们还可以装聋作哑,因为实际执行时什么也看不出来;但是假如tUse是一个selftarget的talent,ActionUseTalentOnObject(tFinal, oTarget)将卡死这个NPC,其后果同BUG1。

因此,我们必须在前面一段的检测中对检测条件作进一步的限制:

    if (GetTypeFromTalent(tUse) == TALENT_TYPE_FEAT)
    {
        //MyPrintString("Using feat: " + IntToString(iId));
        nNotValid = TRUE;
        if (VerifyCombatMeleeTalent(tUse, oTarget)
                        && FEAT_DISARM == GetIdFromTalent(tUse)
            && VerifyDisarm(tUse, oTarget))
        {
            //MyPrintString("combat melee & disarm OK");
            nNotValid = FALSE;
        }
    }

以上。我表达能力有限,可能不太容易看懂。没关系,你只要知道它们在官方战役中不会导致任何问题,但如果你打算使用自己制作一些“牛×”或者“滥强”的佣兵时,这两个BUG可能会让你的这些勇猛的跟班全部罢工。根据我自己测试的结果,它们在魔武双修或者主动专长比较多的NPC上发生的几率相当大,尤其是圣武士这类角色(恶意猜测:为什么SOU不让我用paladin MM,大概官方早就知道这个BUG了)。另外说一句,第三方的AI补丁中,如果重用了官方的DeterminCombatRound接口,那么这两个BUG在补丁中也存在。

我把修改后的文件贴在下面。请注意这两个文件是中间脚本,没有main函数,是不能直接编译的。要使用它们,你需要找出所有调用了它们的脚本文件,并进行编译,然后把编译后的ncs文件覆盖原来的。强烈建议,最好是解出全部脚本文件,自己维护它们。这样做的好处是,游戏中所有与脚本相关的控制都在自己的掌握之下,并且可以很方便地把自己的一些新主意加进去(比如hook一下GetCasterLevel什么的)。当然,那是另一个故事了^_^。

fix.rar

15.03 KB, 下载次数: 4, 下载积分: 奥币 -1

发表于 2011-10-15 23:23:36 | 显示全部楼层
请允许在百度无冬吧转帖。
 楼主| 发表于 2011-10-16 07:22:31 | 显示全部楼层
没问题。转载请注明出处。如果有bioware账户的话最好能贴到官方论坛。我没有账户。
发表于 2011-10-17 09:44:53 | 显示全部楼层
看来该直接试试SOLO一把
发表于 2011-10-17 12:23:27 | 显示全部楼层
bioware服务器前不久遭受攻击挂掉了。不知道好了没,我的帐号已然忘了。。。有机会看能让朋友帖那里不。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|奥德赛公会

GMT+8, 2026-6-16 23:09 , Processed in 0.014301 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表