欢迎光临散文网 会员登陆 & 注册

只狼AI初探

2020-10-24 00:04 作者:琐帝BNU  | 我要投稿

由于AI文件太复杂了,这次先从一个简单的入手,那就是弥山院的对空突刺和重挥

众所周知,弥山院的对空突刺仅在其出下段时,检测到只狼向后跳才变招,那么这是经验的部分,在程序中如何实现呢?以及实战中如何稳定触发呢?


以及重挥动作,可能很多人都没见过,甚至以为是废案

首先,定位数据:

圆真所在地图:m10_00_00_00(即平田宅邸)

圆真的单位编号:10500001

圆真的AI文件:105000

对空突刺动作编号:3003

下段危动作编号:3017

定位AI文件

这两个文件中,后缀battle的为战斗时的AI逻辑,解包并打开,然后直接搜3003,定位到下面一段代码,也就是关于“干扰(Interrupt)”的各种反应机制,建议直接跳过这段代码看后文

Goal.Interrupt = function (arg0, arg1, arg2)
    local local0 = arg1:GetDist(TARGET_ENE_0)
    local local1 = arg1:GetSpecialEffectActivateInterruptType(0)
    local local2 = arg1:GetRandam_Int(1, 100)
    if arg1:IsLadderAct(TARGET_SELF) then
        return false
    elseif not arg1:HasSpecialEffectId(TARGET_SELF, 200004) then
        return false
    elseif arg1:IsInterupt(INTERUPT_ParryTiming) and not arg1:HasSpecialEffectId(TARGET_SELF, 5028) then
        return Common_Parry(arg1, arg2, 50, 0)
    elseif arg1:IsInterupt(INTERUPT_Damaged) then
        return arg0.Damaged(arg1, arg2)
    elseif Interupt_PC_Break(arg1) then
        arg1:Replanning()
        return true
    elseif arg1:IsInterupt(INTERUPT_ActivateSpecialEffect) then
        local local3 = 5211 (此为一个后撤动作)
        if local1 == 110111 or local1 == 110115 or local1 == 110116 then
            if arg1:HasSpecialEffectId(TARGET_SELF, 5029) and local0 <= 6 then
                if arg1:IsInsideTarget(TARGET_ENE_0, AI_DIR_TYPE_F, 90) and arg1:HasSpecialEffectId(TARGET_SELF, 5020) then
                    arg2:ClearSubGoal()
                    arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.5, 3003, TARGET_ENE_0, 9999, 0)
                    return true
                end
            elseif local0 <= 2 then
                arg2:ClearSubGoal()
                arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, local3, TARGET_ENE_0, 9999, 0)
                return true
            elseif local0 <= 5 then
                if arg1:IsInsideTarget(TARGET_ENE_0, AI_DIR_TYPE_F, 90) then
                    if arg1:HasSpecialEffectId(TARGET_SELF, 5020) then
                        arg2:ClearSubGoal()
                        arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, 3003, TARGET_ENE_0, 9999, 0)
                        return true
                    end
                else
                    arg2:ClearSubGoal()
                    arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, local3, TARGET_ENE_0, 9999, 0)
                end
                return true
            end
        elseif local1 == 110112 or local1 == 110117 or local1 == 110118 then
            if local0 <= 3 then
                if arg1:HasSpecialEffectId(TARGET_SELF, 5020) then
                    arg2:ClearSubGoal()
                    arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, 3003, TARGET_ENE_0, 9999, 0)
                    return true
                else
                    return true
                end
            elseif local0 <= 8 then
                arg2:ClearSubGoal()
                arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 2, 5210, TARGET_ENE_0, 9999, 0)  (5210是一个往前垫步的动作)
                arg1:SetTimer(5, 2)
            end
        elseif local1 == 110113 then
            if local0 <= 3 then
                if arg1:HasSpecialEffectId(TARGET_SELF, 5020) then
                    arg2:ClearSubGoal()
                    arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, 3003, TARGET_ENE_0, 9999, 0)
                    return true
                end
            elseif local0 <= 10 and arg1:IsInsideTarget(TARGET_ENE_0, AI_DIR_TYPE_F, 90) then
                arg2:ClearSubGoal()
                arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, 5213, TARGET_ENE_0, 9999, 0)   (5213是弥山院向自己的右侧垫步)
                return true
            end
        elseif local1 == 110114 then
            if local0 <= 3 then
                if arg1:HasSpecialEffectId(TARGET_SELF, 5020) then
                    arg2:ClearSubGoal()
                    arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, 3003, TARGET_ENE_0, 9999, 0)
                    return true
                end
            elseif local0 <= 10 and arg1:IsInsideTarget(TARGET_ENE_0, AI_DIR_TYPE_F, 90) then
                arg2:ClearSubGoal()
                arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.1, 5212, TARGET_ENE_0, 9999, 0)   (5212是弥山院向自己的左侧垫步               

  return true
            end
        end
        if local1 == 107710 then
            arg2:ClearSubGoal()
            arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 2, 3024, TARGET_ENE_0, 9999, 0)   (3024是向背后突刺)
            return true
        elseif local1 == 5026 then
            if arg1:GetSpRate(TARGET_SELF) <= 0.3 then
                arg2:ClearSubGoal()
                arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 2, 3090, TARGET_ENE_0, 9999, 0)    (3090是很使劲的挥枪)
                return true
            end
        elseif local1 == 5027 then
            arg2:ClearSubGoal()
            arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 2, 3021, TARGET_ENE_0, 9999, 0)     (3021是投技)
            return true
        end
    end
    if arg1:IsInterupt(INTERUPT_ShootImpact) and arg0.ShootReaction(arg1, arg2) then
        return true
    elseif arg1:IsInterupt(INTERUPT_Inside_ObserveArea) then
        if arg1:IsInsideObserve(0) == true and arg1:IsFinishTimer(0) == true then
            arg2:ClearSubGoal()
            arg2:AddSubGoal(GOAL_COMMON_EndureAttack, 0.3, 3012, TARGET_ENE_0, 9999, 0)     (3012和3024很像)
            arg1:SetTimer(0, 5)
            arg1:DeleteObserve(0)
            return true
        elseif arg1:IsInsideObserve(1) == true then
            arg1:Replanning()
            arg1:DeleteObserve(1)
            return true
        end
    end
    return false
end

如果你已经跳到这里了,那么很好,我们要开始分析了

3003也就是对空突刺,一共出现了5次,第一次出现时AI做了这样一个判断:

AI机制

相信有中学数学基础的朋友一定是看得懂这个框图的,虽然我不知道5029和5020特效是啥,不过猜测5020应该是非精英怪(因为精英怪不会出这个,合情推理一下吧),5029可能和硬直有关。再说一下距离,距离6大概略长于狼的身高,也就是6英尺(既然长度单位是英尺,那还是可以估算狼的身高的,不过不是本文的重点)

这是在第一种干扰类型下的AI机制,虽然不是很清楚具体是什么,不过大概可以看出AI的思维要判断方位、距离、滞空三个要素。

第二类干扰下我就简单说说,如果距离<=3且玩家滞空,那么就会对空突刺,反正如果距离在3到8之间,则圆真会选择接近玩家

此外还有两类相似的干扰,都是满足玩家的距离在3以内且滞空,则对空突刺,反正距离在3到10则会选则往左/右侧向垫步

除了对空突刺外还有很多干扰类型,暂不讨论

注意:既然是对干扰的应对机制,那么硬直状态下肯定不会有反应,比如动作后摇和被识破被炎上等情况下的硬直。在视频:

中,两种方法都是在等弥山院的后摇和硬直结束再起跳,具体分析如下:

对于视频中方法一,后撤步有两个功能:等时间和拉开距离

在前面的分析中,对空突刺的触发条件要求非精英,并且距离在2到6之间,所以如果不后撤的话,干等一段时间再起跳会触发后撤机制,干等然后后跳则又可能打不到;如果不后撤并直接起跳,则弥山院处于后摇之中,无法实现对空应对机制。

对于视频中的方法二,也是类似的原理,不过距离和时机需要玩家自己把握(一次不成多试几次),好处在于完全不用拼刀hhh


除了对空突刺,上面还提到了3090动作,这个可能很少有玩家注意,它的条件是 local1==5026和if arg1:GetSpRate(TARGET_SELF) <= 0.3 ,也就是在玩家识破圆真后,如果他没有崩躯干,且躯干积累70%以上,则会在玩家识破后发动3090重挥(当然,玩家不能去进攻,不然会让他受伤触发其他变招,所以这一招很少见)

3090动作演示

关于AI的机制我也只是刚刚开始研究,先给大家拿一点出来玩玩吧~


只狼AI初探的评论 (共 条)

分享到微博请遵守国家法律