本Wiki包含与单机游戏《只狼:影逝二度》相关的各类内容,包括常用攻略、人物介绍、数据整理等。
只狼游戏相关内容交流群:1102710456、667938183,欢迎热爱只狼的小伙伴加群交流。
也非常欢迎对本Wiki中尚未新建的页面进行图片或文字投稿,编辑方法参见:编辑帮助

全站通知:

小泽笔记

阅读

    

2024-03-29更新

    

最新编辑:小泽1019

阅读:

  

更新日期:2024-03-29

  

最新编辑:小泽1019

来自只狼:影逝二度WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索
页面贡献者 :
小泽1019

本条目是玩家“小泽1019”在进行部分AI编辑时对只狼AI脚本中部分函数参数以及其作用的总结,以及包括各种其他在mod制作过程中的零碎问题的整理,不定期更新

AddSubGoal函数中各种类型的参数作用

调用格式:arg0:AddSubGoal (GoalType, ...)

其中调用的类为arg0还是arg1取决于调用该函数的函数将相应的类作为第几个参数,实际可以看原本是怎么写的

GoalType有数种类型,在之后慢慢补充或者自己摸索,后续的若干参数的作用在下面给出。


  • 类型SidewayMove

用于实现敌人在玩家面前的侧移,将会调用敌人的固定侧移动作(包括侧走和侧跑)。该类型的计划会使得该对象从DSA中Move类型JumpTable的TAE处输入侧移动作。

参数列表中的参数按顺序包括:寿命l,目标,右行指标flag_R,移动角度deg,步行指标flag_W,寿命指标flag_L,防御指标flag_G

  1. 寿命即为计划的通用寿命,在计划排入第一个位置(即当前准备执行或正在执行)时开始倒计时,倒计时结束之后清除当前的所有子计划,一般而言这将导致动作执行到下一个攻击类型JumpTable的TAE时重新调用主动计划,之后不再进行解释。

  2. 目标为SidewayMove执行计划时面向的对象,不出意外情况均为TARGET_ENE_0

  3. 右行指标flag_R决定了敌人向左走还是向右走,1表示向右侧移,0表示向左侧移。

  4. 移动角度deg表示本次侧移移动的最大角度,一旦相比较最初位置到达了此角度,则无论寿命还有多长时间强制结束该计划并默认成功。该角度应该是空间判断,即360与0实际上对应的是同一个位置。

  5. 步行指标flag_W表示本次侧移采用步行还是跑步,true表示步行,false表示跑步。这里要特别注意不是所有敌人都有侧跑,甚至侧面步行的动作,前者敌人只能采取步行,后者可能导致敌人AI卡住。

  6. 寿命指标flag_L取true时即便当寿命耗尽,也默认该计划执行成功(从而允许执行接下来的连招)。

  7. 防御指标flag_G取9910时敌人会在移动的过程中举刀进行防御(将会调用一系列特殊动作),注意敌人一般没有侧跑时防御的动作,也不是所有能防御的敌人都有一边移动一边防御的动作。本参数取-1表示不生效。

  • 类型SpinStep

用于实现敌人的闪避(垫步)类型动作,需要人为指定执行哪个动作。该类型的计划会使得动作在DSA中SpinStep类型JumpTable的TAE处输入,其中的旋转作用尚未清楚(可以参考下面的攻击类型中的旋转)。

参数列表中的参数按顺序包括:寿命l,动作,旋转目标,旋转时间,探查方向dir,安全距离d

  1. 动作为将要执行的SpinStep类型动作的编号。

  2. 目前对SpinStep类型还知之甚少,仅仅知道在执行动作之前会检查dir方向距离d内是否有移动空间,如果没有则AI会莫名其妙的卡住。

  • 类型LeaveTarget与ApproachTarget

这两类计划的参数基本完全相同因此放在一起讲。分别用于实现敌人接近玩家和远离玩家,将会调用敌人的固定前进和后退动作。该类型的计划会使得该对象从DSA中Move类型JumpTable的TAE处输入后退和前进动作。

参数列表中的参数按顺序包括:寿命l,目标,到达距离d,旋转对象,步行指标flag_W,防御指标flag_G

  1. d为一个移动的分界线,当移动到与目标距离d时(LeaveTarget则为至少远离到了d米位置,ApproachTarget则为至少接近到了d米位置)默认本计划成功执行,将该计划清除并且继续执行下一个子计划;否则如果一直没有成功,则会在动作执行到下一个攻击类型JumpTable的TAE时重新调用主动计划(对于移动动作来讲,因为通常全程都不会允许攻击动作的插入,因此这将会持续到寿命耗尽)。之后关于成功距离的概念将不再赘述

  2. flag_W和flag_G的作用与SideWayMove中完全相同,不再解释。

  3. 旋转对象的具体意义未知,对于ApproachTarget而言并未看出任何区别,对于LeaveTarget此处写TARGET_ENE_0会一边面对着敌人一边缓缓后退,写TARGET_SELF则转头离开

  • 类型AttackTunableSpin

用于实现敌人的攻击动作,需要人为指定动作。该类型的计划会使得该动作从DSA中Attack类型JumpTable的TAE处输入

参数列表中的参数按顺序包括:寿命l,动作,目标,成功距离d,旋转持续时间t,正面判定角度deg_F,上攻击角度deg_U,下攻击角度deg_L

  1. d的意义与先前的成功距离相同,将在下一个计划的输入时机检测与目标之间的距离来判定是否成功。

  2. 旋转持续时间t表示在该计划开始之前敌人会预先用多长时间尝试转身来保持正面面对目标。在开始转身之前将会检测目标是否在其左右deg_F角度内,如果在则会直接攻击,不在则会先转身

  3. 其余两个攻击角度意义类似,以deg_L为例。以敌人为水平,俯角deg_L向下搜索,如果目标在这个范围之下(也就是目标的位置过低)则不会执行攻击动作,将会原地等待直到目标的位置满足条件或者寿命耗尽为止。简单的测试表明写0表示不启用而不是0度以下皆不做动作(否则这将导致敌人永远无法攻击)。

  • 类型ComboAttackTunableSpin

同样用于实现敌人的攻击动作,需要人为指定动作,并且该类型的计划会使得该动作从DSA中Attack类型JumpTable的TAE处输入。与上一种类型的区别是上一种类型不会启用该动作中Combo类型JumpTable的TAE,也就是不允许用TAE进行动作连接;而AI中以这种计划类型输入的子计划则允许Combo进行动作连接。因此本类型一般用作一套连招的第一个动作。

  • 类型ComboRepeat

同样用于实现敌人的攻击动作,需要人为指定动作。该类型的计划会使得该动作从DSA中Combo类型JumpTable的TAE处输入,如果不允许则从Attack类型JumpTable的TAE处输入

参数列表中的参数按顺序包括:寿命l,动作,目标,成功距离d,上攻击角度deg_U,下攻击角度deg_L,成功角度deg_S

  1. 除deg_S以外所有的其它参数意义都讲过,但是测试并没能测出deg_S具体能真正起到什么作用,试了几个数也没能让玩家在敌人身后时敌人仍然继续攻击,这里姑且存疑。

  • 类型ComboFinal

同样用于实现敌人的攻击动作,需要人为指定动作。该类型与ComboRepeat基本完全相同,但是不允许下一个计划在当前计划动作中的Combo类型JumpTable的TAE处输入。一般用于实现一套连招的最后一个动作。

  • 类型EndureAttack

基本与AttackTunableSpin类型完全相同,区别在于该类型的计划会使得该动作从DSA中EndureAtk类型JumpTable的TAE处输入

关于实际编写AI的时候的一些简单个人感受
在输入类型的选择上,最基本的理念是遇事不决就采用ComboRepeat类型作为输入,因为这种输入类型会开启动作Combo类型的输入并且允许作为Combo类型输入到上一个动作中去,不太容易出现问题,而且其缺少的几个参数只在比较精细的AI编辑中才会用到,因此如果不想多思考的话就用这种输入就可以了。当然,一般的复杂Mod制作肯定需要对动作中的输入TAE进行编辑来使得敌人能够灵活自然地变招,这时一味采用该类型进行输入很容易导致主动计划提前输入等等的bug出现。一般来说,保证下面的良好习惯将会尽可能地发挥这些输入类型的作用并且避免出现bug。


一般来说,在攻击类型的主动计划中应当以AttackTunableSpin和ComboAttackTunableSpin类型进行第一个动作的输入,这样做是因为主动计划会在计划队列中最后一个动作执行到Attack或者Combo类型的输入TAE时进行调用,如果主动计划的第一个动作就采用ComboRepeat等会在Combo处输入的动作,而上一个执行的动作刚好是来自于变招计划或者交锋计划中经过了一次计划清除之后输入的ComboRepeat类型的话,这将导致主动计划提前输入,引发敌人出招上的bug。当然,这只是在没有特殊情况下的习惯性问题,一般来说如果想要做出某些特定效果当然可以依照自己想要做的方式来具体实现。


防御计划中应该尽可能采取EndureAttack类型的输入,因为在很多动作中前摇和后摇较早的部分都将允许该类型的输入,以达成敌人的一种“取消前后摇”的效果。同样的,如果想要在防御计划中实现一些独有的特性,也可以根据自己的喜好来。特别注意EndureAttack类型不会开启Combo类型的输入,因此不能够用来实现连招或者当作连招第一个动作的输入类型。

交锋计划和变招计划中一般需要先进行计划清除(ClearSubGoal)以做出及时出招的效果。交锋计划的时机比较固定,但是在变招计划中的这种检测往往要十分小心,尤其是检测玩家的某种行为的时候(例如检测玩家起跳),因为我们无法控制玩家在什么时机做出这种行为,因此这可能导致敌人的出招中断甚至AI出现问题。这个问题尤其在使用AttackImmediateAction类型输入的时候要格外小心,因为为了达成“瞬发”的效果,我们一般都需要先进行计划清除之后再输入瞬发计划(否则这个瞬发计划会排在计划队列的最后一位,做完前面所有计划之后再触发,没有“瞬发”的效果),因此如果我们用瞬发动作检测玩家的某种行为,这可能导致以外发生,例如敌人处于忍杀硬直的时候突然出招(当然也可以利用这个特性做出一些奇特的变招)。没有意外的情况下,变招计划中推荐使用ComboRepeat类型输入,以ComboFinal类型结尾,同样的道理也适用于主动计划中连招的中间和结尾,避免以外输入的发生。

一些带有多参数的函数的具体意义

  • Common_Parry

用于实现大部分敌人的防御行为

各个参数意义已经总结,见页面敌人的防御机制。很多敌人有自己特有的防御计划,用于实现一些特殊的防御。例如天守阁和平田佛堂义父针对玩家的突刺会采取识破进行防御,老一心在具有特定特效的时候会用心眼代替防御、同时其在防御计划中有针对秘传一心武技的特殊对策。再到比较不易察觉的敌人,例如弦一郎在一二阶段使用肘击的时候有特殊的防御动作,这将导致其防御后出现较大的后仰硬直。这些防御机制用来实现游戏的各种机制。

  • Approach_Act_Flex

用于实现在一定的条件下以某种特定方式接近敌人,是一个已经集成好各种功能的ApproachTarget的实现,一般被用在主动计划中。

参数列表中的参数按顺序包括:arg0,arg1,成功距离参考值d_S,相对分界距离d_R,绝对分界距离d_A,跑步概率p_R,防御概率p_G,步行寿命l_W,跑步寿命l_R,启用指示flag

  1. arg0和arg1是从上层传递下来的类参数,用于在本函数内实现一些功能,直接照抄即可,注意根据所处的位置进行灵活调整。

  2. 本函数最终的核心部分是添加一个ApproachTarget类型的计划,是否添加取决于d_S和flag:如果flag为正数则一定添加(flag默认为0),否则在d_S小于自己与TARGET_ENE_0的距离时添加(不满足条件时本函数什么都不会做)。

  3. 最终此ApproachTarget类型计划的寿命取决于l_W和l_R:如果接下来的一系列条件决定了以跑步形式接近则采用l_R,否则采用l_W,默认值l_W为3s,l_R为8s

  4. 如果自己与TARGET_ENE_0的距离超过了d_A,则采取跑步的形式接近(即将添加的ApproachTarget计划的步行指标置为false);否则如果距离超过了d_R,则有p_R的概率跑步接近。其余的情况均会步行接近。

  5. 接近计划的防御指标将会以p_G的概率取9910,否则取-1

  6. 最终计划的到达距离取决于d_S以及最终采取了步行还是跑步的形式,将会在d_S的基础上修正一个固定的值。

  • Interupt_PC_Break

该函数用于实现敌人AI中对于玩家处在崩条状态下进行的变招,一般只在部分有崩条检测的敌人的变招计划(Goal.Interupt,以后不再赘述)中才会出现。其有3个参数,按顺序记为:arg0,冷却计时器Timer,冷却时间CoolDown

  1. 与先前的情况相同,arg0是从上层传递下来的类参数,用于在本函数内实现一些功能,直接照抄即可,注意根据所处的位置进行灵活调整。

  2. 后两个参数可以不写,对本函数的核心功能没有影响。本函数的核心功能在于检验玩家获得特殊变招特效110125的时间点(在玩家任何被打崩躯干的动作都会带有该特效,由于本函数为变招特效检验,因此只会在玩家获得该特效,也就是崩条时生效一次)。如果该时间点当前敌人没有处于开始攻击的状态(如何判断该状态未知),则就会返回一个true,否则返回false

  3. 后两个参数Timer和CoolDown用来实现崩条检测的冷却,一般来说因为玩家不太可能在短时间内连续崩条,并且即便类似的状况发生,连续的崩条检测也不会带来什么问题,因此不太用得上,如果不输入这两个参数则崩条检测就没有冷却。否则AI将会采用计时器Timer来实现崩条检测的冷却,每次调用该函数的时候会检测Timer是否倒计时完成,未完成则直接返回false,若已经倒计时完成则让Timer开始时间为CoolDown的倒计时并且返回true。

  • Interupt_Use_Item

该函数用于实现敌人AI中对于玩家喝药进行的变招,也就是所谓的“药检”,一般只在部分有喝药检测的敌人的变招计划中才会出现。其有3个参数,按顺序记为:arg0,冷却计时器Timer,冷却时间CoolDown

  1. 与先前的情况相同,arg0是从上层传递下来的类参数,用于在本函数内实现一些功能,直接照抄即可,注意根据所处的位置进行灵活调整。

  2. 后两个参数可以不写,对本函数的核心功能没有影响。本函数的核心功能在于检验玩家做出喝药的动作(包括和葫芦、药丸等的动作)。如果该时间点当前敌人没有处于开始攻击的状态(如何判断该状态未知),则就会返回一个true,否则返回false

  3. 后两个参数Timer和CoolDown用来实现喝药检测的冷却。这里特别注意与崩条检测不同,玩家非常有可能连续喝药,而且一旦玩家被敌人的药检打断喝药,玩家立即再喝药时如果会立即再触发敌人的药检则会使游戏不太人性化,因此这两个参数在大部分有药检的敌人身上都会用得到,如果不输入这两个参数则喝药检测就没有冷却。否则AI将会采用计时器Timer来实现喝药检测的冷却,每次调用该函数的时候会检测Timer是否倒计时完成,未完成则直接返回false,若已经倒计时完成则让Timer开始时间为CoolDown的倒计时并且返回true。

计数与计时

计数与计时是AI编辑中的重要进阶内容,在自己新建新的主动计划、交锋计划,以及想要实现各种复杂机制时,计数和计时都是无法避免的需要采用的核心机制。由于计数器和计时器的各种功能函数具有共性并且作用互相联系,在AI中扮演着重要角色,因此在这里进行单独介绍。

冷却时间的设置

在添加新的主动计划、交锋计划,或者对原版的计划进行修改的时候,设置冷却时间十分重要。这是因为在敌人的主动计划和交锋计划树中敌人会将自己和玩家当前所处的情况进行分类,最后从若干种可能出招中用随机数随机出其中一种进行出招。这将会不可避免地导致权重,也就是概率更高的招式将会更经常性地出现,而在可能性比较少的情况下,这往往会导致敌人不停地出相同的招式,即便不是如此也可能出现同一个招式连续出好几次地情况,导致战斗变得乏味(一个简单的冷却时间设置的不好的例子就是原版剑圣在其右手侧招架玩家之后经常会出一个快速的横斩,再加之剑圣的招架后对策很少,导致一拍一打法变得非常容易,而这个招式实际上冷却时间并没有设置正确)。因此为每个招式设置冷却时间,即便是非常短的只有数秒的冷却,也能够有效避免敌人同一个招式连续出好几次的情况,在AI编辑中十分重要。除此之外,对于部分招式,我们也希望它具有比较长的冷却,例如狮子猿的血吼、义父的召唤火鸟、破戒僧的大风车等,我们并不希望它短时间连续出好几次,对于这些招式往往需要设置较长的冷却,然后设置较高的权重或者在其冷却结束之后强制发动,来实现基本上是每隔一段时间就固定出的效果。

设置招式的冷却可以通过计时器,也可以通过计时该招式上一次发动是在什么时候来实现。后者是更加常用的实现方法,并且我们有用来实现的封装好的函数和固定格式,因为这就是一般的用来实现冷却的方法。但是个别情况下单单依靠检测招式什么时候发动过并不能实现我们全部想要的功能,例如我们想要实现主动计划和交锋计划中几个招式共用冷却这种跨函数的冷却设置(从而需要全局层面的工具,比如计时器,简单的例子如弦一郎的主动飞渡);某些招式的发动会影响另一个招式的冷却,但是反过来第二个招式却不会影响第一个招式(典型的例子仍然是飞渡,弦一郎的反击飞渡会暂时屏蔽掉主动飞渡,比主动飞渡自己发动时产生的冷却要短,但是主动飞渡不会影响反击飞渡的发动;狮子猿的拼刀短血吼和长血吼也是例子,后者会暂时屏蔽前者的发动,反之则不会);再例如我们需要一个招式在做完时,或者在其中某个节点处再进入冷却,而不是开始的时候就使之冷却(典型的例子如破戒僧的大风车)。这些特殊情况的实现不能简单地通过检验该招式上一次在什么时候发动,直接调用计时器进行处理会更加灵活。我们先介绍简单的用检测发动时间设置冷却的方法。

  • GetAttackPassedTime

该函数用于返回距离上一次某动作开始执行所经过的时间,可以在AI中各处加以灵活运用。该函数只有1个参数,即想要调用所经过执行时间的动作的编号。

  • SetCoolTime

用于实现最一般的冷却时间的设置,因为其作用是根据距离某一动作上一次执行所经过的时间来修改某一个计划的权重,因此只能够用在主动计划和交锋计划中。该函数调用时不需要作为某一个类的方法,直接写函数名调用即可,考虑到冷却时间对某个计划权重产生的影响,基本上都是直接默认统一写在主动计划或者交锋计划的结尾处(可以见原版AI的使用方法)。该函数一共有6个参数,按顺序分别为:arg0,arg1,冷却动作,冷却时间t,未冷却权重W1,冷却权重W2

  1. arg0和arg1是从上层传递下来的类参数,用于在本函数内实现一些功能,直接照抄即可,注意根据所处的位置进行灵活调整。

  2. 注意该函数返回的是一个权重,因此可以用该函数给计划权重列表中的某一个权重进行赋值(具体见原版AI是怎么写的,这需要对主动计划和交锋计划树的基本运作方式有一定的概念),返回的值是W1或者W2。

  3. 该函数的具体运作方式为,调用GetAttackPassedTime检验距离冷却动作上一次执行的时间是否已经超过t,如果超过则返回W1,否则返回W2。

  4. 该函数的原理可以简单如下理解:对于我们想要设置冷却的计划来说,参数中的冷却动作一般应该填写这个计划中我们想要使该计划进入冷却的关键性动作(例如该计划是三个动作组成的小连招,我们一般就在这里写第一个动作的编号,这就表明只要敌人做出了第一个动作,这个计划就会进入冷却);而冷却时间t处则应该填写我们想要让该计划进入多长时间的冷却(还是上一个括号里的例子,例如填了20,就代表只要敌人做出了第一个动作,这个小连招就会进入20秒的冷却)。注意这个函数会给权重重新赋值,因此不出意外的话W1应该填原本的权重,也就是照抄被赋值变量,按照常理而言W2应该填0,来表示计划进入冷却之后它就没有权重了。但是实际上考虑到有可能出现所有计划都进入冷却的情况,都填0将会导致敌人有时候无招可出,因此一般W2填1,表明冷却的招式一般来说几乎不可能出;而如果所有可能出的招式都在冷却,它们的权重就都为1,此时也会平等地随机出一个合适的招式。

  5. 该函数的常规用法就如上所述,给计划设置一个根据某个关键动作启动其进入冷却。当然我们知道原理之后可以有更多用法,例如原版中也会用到的,一个计划可能会被好几个动作控制冷却,这里全部以义父的招式为例。义父在主动计划和交锋计划中有不同的后跳撒鞭炮动作(制作动作的时候要考虑到动作衔接的流畅性以及快慢、时机等问题,同一个动作有很多个具有微小差异的不同版本非常正常),那么对于主动计划中主动后跳撒鞭炮的计划,我们想要让交锋的后跳撒鞭炮动作也启动其CD,这样我们就连续调用两次SetCoolTime函数,写不同的冷却动作,就实现了两个动作都能启动该计划的CD的效果。当然,我们还能让不同计划之间通过动作来简单实现互相启动CD的效果,以及不同的动作会启动同一个计划不同冷却时间的效果(义父这里也有一个简单的例子,他的踩头在踩到和没有踩到玩家时会具有不同的冷却时间,前者更长,这是用后跳动作启动踩头的CD来实现的)。

计时器的设置

计时器的设置是游戏中最基本的机制之一,其最基本的用途在于强制使得部分招式无论在何计划当中一旦出现就会出现较长的冷却时间;或者用于部分具有相同特点的不同招式跨计划共同冷却,例如狮子猿的长短血吼,弦一郎和一心的各种巴之雷等。游戏中的计时器以编号1至15排列,这里要注意计时器14和15被用于防御计划不要轻易调用或者修改,建议使用时优先使用编号较小的计时器。