5.变量Var简介、Cmd简介、AI开关设置及手操指令修改

本页内容由口水轩撰写. 由【softmgr】整理编辑.

==================================================
5.1变量Var简介
==================================================

--------------------------------------------------
在平时mugen的讨论当中总会出现变量也就是Var这个莫名其妙的词,出现频率高用途广,是制作者经常用到的东西。
但是不知道为什么这词总是给新人一种强烈的威慑力和压迫感,令新手们敬而远之。

其实变量(Variable,缩写为Var)并不可怕,就是一个任意赋值修改的数字。
变量分为Var、Fvar、Sysvar、Sysfvar等几种。Var和Sysvar是整型变量,Fvar和Sysfvar是浮点型变量(F的意思是float)。
一个人物里面共有60个Var(Var(0)~Var(59))、40个Fvar(Fvar(0)~Fvar(39)),Sysvar和Sysfvar各5个。
用途上来说Sysvar、Sysfvar是系统变量,一般不使用。所以平时通常使用的变量是Var和Fvar,共有100个。
本体的变量可以通过修改参数把留到下一局。在CNS的[Data]部分,修改IntPersistIndex和FloatPersistIndex的值。
在这两个值以上的本体Var和Fvar在下一局开局不会被重置为0。不过现在应该暂时用不到...
最后补充一句所有变量默认值为0。

--------------------------------------------------
(为了方便,下文用Var统称所有变量)
我们可以对变量进行各种各样的操作:例如查看数值(Var/Fvar)、增加(Varadd)、赋值(Varset/:=)等等。例如:

查看及对比:
trigger1 = Var(59) && Fvar(0) = 10086;查看Var的值和对比Fvar的值

增加/赋值:
[State -1]
type = Varadd/Varset;增加或者赋值
trigger1 = ...
V = XXX / FV = XXX;对哪一个变量进行操作
value = 1;需要操作的量

:= (赋值运算符):
[State -1]
...
trigger1 = Var(59) := 1|| 1;对Var(59)赋值并继续运行下面的代码
...
(Var(59) := 1的作用是和Varset把V = 59, value = 1一样。需要注意的是,:=赋值所返回的值是赋值的值,可能会影响以后的
trigger判断。后面可以根据实际需求加上 || 1 或者 && 0,分别用于确保后面语句触发或者不触发)
使用该运算符的好处是可以一次对多个Var进行赋值。

--------------------------------------------------
如果是懂得计算机的朋友,上面这么多废话说完就一句话:
变量即是用特殊函数赋值的初始值为0的int i[60]或者float j[40]。

--------------------------------------------------
Var相关的常用代码就上面这几种,但是这些简单的数字对作者来说具有非常重要的意义:
它像是纸+铅笔+橡皮擦,你可以任意修改里面的值;
又像是红绿灯,你可以根据里面的内容来分析下一步的应对方案;
又像是一本笔记本,你可以把需要记忆的东西记录下来。
虽然Var本身没有任何意义,但是会因为作者的不同需求而被赋予各种各样的意义。
当中的奇妙之处需要时间慢慢领悟,一大波变量Var使用实例会在15章详细介绍。
而下文将要介绍的就是Var最简单的用法之一,也是AI制作当中几乎一个必不可少的步骤――AI开关。

==================================================
5.2Cmd简介
==================================================

--------------------------------------------------
在讲解AI开关之前,因为涉及到手操指令的部分,就顺便把Cmd文件也简单介绍一下吧。
因为KFM的Cmd里面有Cmd的相关介绍,所以笔者就直接在MKII君翻译的中文KFM的Cmd文件提取并整理相关介绍了:

Cmd文件一共由两大部分组成――手操指令定义和切换相关状态。

--------------------------------------------------
手操指令定义部分用于定义人物可以接受到什么按键(及按键组合)。
按键一共有八种方向、六种攻击和一种挑衅。

八种方向(全大写):
B, DB, D, DF, F, UF, U, UB
后,下后,下,下前,前,前上,上,上后
(上面八个方向通常对应数字键盘上面的8个数字 4 1 2 3 6 9 8 7,剩下的5为没有方向按键)

六种攻击及一种挑衅(全小写):
a, b, c, x, y, z, s

此外还可以用特殊符号前缀来达到鉴别按住按键(/号)、松开按键(~号)、同时按多个键(+号)等等手操指令的,具体请看自己
查阅相关资料,在此不予赘言。

手操指令定义的例子:

[Command]
name = "236x";手操指令名称为"236x"
command = ~D, DF, F, x;需要按下的按键是:下 下前(过渡) 前 x
buffer.time = 1;输入缓存的时间为1f

[Command]
name = "x";手操指令名称为"x"
command = x;需要按下的按键是:x
time = 1;需要在这规定时间(1f)内完成输入

其模板为:

[Command]
name = "XXX"
command = X(, Y, Z, ....)
time = XXX;(可选参数,单位为帧,默认为15)
buffer.time = XXX;(可选参数,单位为帧,默认为1)

最后注意一下command的最大数量为128个...注意超过之后会报错...

--------------------------------------------------
切换相关状态部分用于接收到手操指令后决定人物切换到什么状态,全部写在[statedef -1]以下。
[statedef -1]我们在第2章已经提及过,每帧执行一次看看有没有适合的手操指令,并且切换到相关状态。
其语法即第3章提及的与St和Stcommon相同的写法(sctrl和trigger)。
不过这些sctrl都有相同的特点,也就是trigger里面都有一条写着要由手操指令来触发:

[State -1, XXX]
...
triggerall = command = "XXX"
...

最后要注意一下如果command A(例如"x")是command B(例如"236x")的子集的话,记得要把command B的sctrl放在command A的
前面,否则会因为command A的切换状态被优先读到而触发令command B的切换状态一直不能被触发。
(这个其实是人物制作的小技巧,不过AI里面也会有涉及,在第7章会详细讨论)

==================================================
5.3AI开关
==================================================

--------------------------------------------------
AI开关是一个用于判断AI是否开启的Var。
通过判断Var是否为0来辨别现在正处于手操控制还是AI控制,是Var最简单的用法之一。
通常来说作者们喜欢用Var(59)作为AI开关(虽然不是强制要求但是可以说是大家默认的潜规则)。
在AI开关还可以调整AI等级,给Var赋予不同的值,通过判断Var值的大小来辨别现在正在使用什么等级的AI。

例子(设定AI为5):

[State -1]
type = Varset
trigger1 = ...;相关条件
V = 59;假设选择Var(59)作为AI开关
value = 5;5级AI,共有多少个等级由作者自己决定

--------------------------------------------------
可能有读者会问:只有这么一个简单的Var赋值就可以让AI动起来吗?
当然不是了,设定好AI开关只是写AI的最开始一步而已。
在以后写AI语句的时候,都要补充上一句类似于triggerall = Var(59)的条件来让电脑知道,下面的代码是当AI开关打开的时候才
运作。
如果是有AI等级的话,则是使用类似于Var(59) = X的表达式。

用回第3章的例子:

;Stand Light Punch
[State -1, Stand Light Punch]
type = ChangeState
value = 200
triggerall = Var(59) > 2;AI等级大于2的时候才会触发
trigger1 = stateno = 200;状态号为200
trigger1 = time > 6;时间大于6

上面这个就是AI等级要大于2才会触发的例子,只要一旦出站轻拳就会鬼畜重复。
这就是识别自己AI开关是否开启的办法,至于详细AI的内容我们日后再谈。

--------------------------------------------------
在上面例子中,笔者仅介绍了如何设置AI开关,但是AI开关的具体条件没有讲。
在这个地方出现了一个难点――就是如何区分出手操和AI操作。
毕竟格斗游戏是用手来玩的,通常希望AI在适当的时候才接管控制权。
Mugen里面没有直接鉴别是否手操,为此作者们想出了不同类型的开关来解决这个问题,例如设计出人类按键输入做不到的事情,
一旦这种事情发生了,我们就知道控制的应该是AI而不是玩家了。
各种开关的区别主要在于启动速度和正确率,下文也会围绕这两点讨论各种AI开关。

--------------------------------------------------
5.3.1常时AI开关
--------------------------------------------------

最简单的一种AI开关。不管是手操还是AI操作直接常时打开AI开关。
常时AI开关实例:

;下面一段放到[Statedef -1]或[Statedef -3]下面
;--------------------------------------------------
[State -1]
type = Varset
trigger1 = 1
V = 59
value = 1

优点:因为常时启动,不用考虑启动慢的问题
缺点:希望手操时依然停不下来...

--------------------------------------------------
5.3.2Cmd乱数启动型AI开关
--------------------------------------------------

较为简单的一种AI开关。
Mugen.cfg内有项参数叫做AI.cheat,默认为1。
其作用是即使电脑没有确实按到整套手操指令也可以用类似作弊的方法强制发动一个手操指令。
我们可以利用这一点来作为辨别是否手操。
AI作者在Cmd文件里的手操指令定义加入多个人类不可能完成的command,比较常用的是要在0f以内输入几个带有重复按键的指令。
因为就算是打寒颤的情况人类的手抖速度也不可能在六十分之一秒里面完成多次重复输入(交流电也就50Hz而已人怎可可能有这么
鬼畜...),所以可以认定并非玩家在操作。
而AI.cheat拥有无论多难的手操指令都有可能直接强制发动的特性,所以依旧可以输入看似不可能完成的指令。
Cmd乱数启动型AI开关实例:

;下面一段放到Cmd文件的手操指令定义部分
;--------------------------------------------------
[Command]
name = "AI0"
command = a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
time = 0
[Command]
name = "AI1"
command = b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b
time = 0
[Command]
name = "AI2"
command = c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
time = 0
[Command]
name = "AI3"
command = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x
time = 0
[Command]
name = "AI4"
command = y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y
time = 0
[Command]
name = "AI5"
command = z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI6"
command = s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s
time = 0
[Command]
name = "AI7"
command = F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F
time = 0
[Command]
name = "AI8"
command = D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D
time = 0
[Command]
name = "AI9"
command = B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B
time = 0
[Command]
name = "AI10"
command = U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U
time = 0
[Command]
name = "AI11"
command = a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
time = 0
[Command]
name = "AI12"
command = c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
time = 0
[Command]
name = "AI13"
command = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x
time = 0
[Command]
name = "AI14"
command = y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y
time = 0
[Command]
name = "AI15"
command = z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI16"
command = s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s
time = 0
[Command]
name = "AI17"
command = a,B,c,x,y,z,s,B,D,F,U,a,b,c,x,y,z,s,s
time = 0
[Command]
name = "AI18"
command = a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
time = 0
[Command]
name = "AI19"
command = b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b
time = 0
[Command]
name = "AI20"
command = c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
time = 0
[Command]
name = "AI21"
command = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x
time = 0
[Command]
name = "AI22"
command = y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y
time = 0
[Command]
name = "AI23"
command = z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI24"
command = s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s
time = 0
[Command]
name = "AI25"
command = F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F
time = 0
[Command]
name = "AI26"
command = D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D
time = 0
[Command]
name = "AI27"
command = B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B
time = 0
[Command]
name = "AI28"
command = U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U
time = 0
[Command]
name = "AI29"
command = a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
time = 0
[Command]
name = "AI30"
command = c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
time = 0
[Command]
name = "AI31"
command = x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x
time = 0
[Command]
name = "AI32"
command = y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y
time = 0
[Command]
name = "AI33"
command = z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI34"
command = s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s
time = 0
[Command]
name = "AI35"
command = z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI36"
command = z,z,z,z,z,z,a,a,a,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI37"
command = z,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,z,z,z
time = 0
[Command]
name = "AI38"
command = z,z,z,z,z,a,a,a,z,z,z,z,z,a,a,a,z,z,z
time = 0
[Command]
name = "AI39"
command = z,z,z,z,z,a,a,a,z,z,z,z,z,z,a,a,z,z,z
time = 0
[Command]
name = "AI40"
command = z,z,z,z,a,a,a,z,z,z,z,a,z,z,a,a,z,z,z
time = 0
[Command]
name = "AI41"
command = z,z,z,a,z,z,z,z,z,z,z,z,z,a,a,z,z,z,z
time = 0
[Command]
name = "AI42"
command = z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI43"
command = z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,a,a,z
time = 0
[Command]
name = "AI44"
command = z,z,a,a,a,a,z,z,z,z,z,z,z,z,z,a,a,a,z
time = 0
[Command]
name = "AI45"
command = z,z,z,z,z,z,a,a,z,z,z,z,z,a,a,a,a,z,z
time = 0
[Command]
name = "AI46"
command = z,z,z,z,z,z,z,z,a,a,a,a,a,a,z,z,z,z,z
time = 0
[Command]
name = "AI47"
command = z,z,z,a,a,a,a,z,z,z,z,z,z,z,z,z,z,z,z
time = 0
[Command]
name = "AI48"
command = z,z,z,z,z,a,a,a,z,z,z,a,a,a,z,z,a,z,a
time = 0
[Command]
name = "AI49"
command = z,z,z,z,a,a,a,z,z,z,z,z,a,a,a,z,z,z,z
time = 0
[Command]
name = "AI50"
command = z,z,z,a,a,z,z,z,z,z,z,z,z,z,a,a,z,z,z
time = 0

;下面一段放到[Statedef -1]或[Statedef -3]下面
;--------------------------------------------------
[State -3, AIフラグセット]
type = VarSet
triggerall = !var(59)
triggerall = RoundState = [1,2]
trigger1 = Command = "AI0"
trigger2 = Command = "AI1"
trigger3 = Command = "AI2"
trigger4 = Command = "AI3"
trigger5 = Command = "AI4"
trigger6 = Command = "AI5"
trigger7 = Command = "AI6"
trigger8 = Command = "AI7"
trigger9 = Command = "AI8"
trigger10 = Command = "AI9"
trigger11 = Command = "AI10"
trigger12 = Command = "AI11"
trigger13 = Command = "AI12"
trigger14 = Command = "AI13"
trigger15 = Command = "AI14"
trigger16 = Command = "AI15"
trigger17 = Command = "AI16"
trigger18 = Command = "AI17"
trigger19 = Command = "AI18"
trigger20 = Command = "AI19"
trigger21 = Command = "AI20"
trigger22 = Command = "AI21"
trigger23 = Command = "AI22"
trigger24 = Command = "AI23"
trigger25 = Command = "AI24"
trigger26 = Command = "AI25"
trigger27 = Command = "AI26"
trigger28 = Command = "AI27"
trigger29 = Command = "AI28"
trigger30 = Command = "AI29"
trigger31 = Command = "AI30"
trigger32 = Command = "AI31"
trigger33 = Command = "AI32"
trigger34 = Command = "AI33"
trigger35 = Command = "AI34"
trigger36 = Command = "AI35"
trigger37 = Command = "AI36"
trigger38 = Command = "AI37"
trigger39 = Command = "AI38"
trigger40 = Command = "AI39"
trigger41 = Command = "AI40"
trigger42 = Command = "AI41"
trigger43 = Command = "AI42"
trigger44 = Command = "AI43"
trigger45 = Command = "AI44"
trigger46 = Command = "AI45"
trigger47 = Command = "AI46"
trigger48 = Command = "AI47"
trigger49 = Command = "AI48"
trigger50 = Command = "AI49"
trigger51 = Command = "AI50"
var(59) = 1

优点:误触发率低
缺点:启动速度慢(因为不知道AI何时才会碰巧执行你写的command...可以说是碰运气),需要新增较多command(数量越多效果越
好),AI.cheat需要打开(默认打开)

--------------------------------------------------
5.3.3Helper型AI开关
--------------------------------------------------

此开关需要创建一个可以接受手操指令(keyctrl = 1)的Helper。
在手操时,玩家输入手操指令,人物本体和创建的Helper会同时接收到玩家的指令;
但若是AI操作的情况,AI可以做到单独触发人物本体的command但是不触发Helper的command。
一旦遇到人物本体的command和Helper的command不一致的情况,便可以察觉出并非玩家在操作。
注意使用时最好不要跳开场(跳开场会增大误触发的几率)。
(下面的例子直接复制被广泛使用的平成氏AI教程里面的AI开关...呃...其实删了一个ctrl)
Helper型AI开关实例:

;下面一段放到[Statedef -1]或[Statedef -3]下面
;--------------------------------------------------
[State -3, 创建AI启动用Helper]
type=helper
trigger1=!NumHelper(10000)
trigger1=roundstate=2
trigger1=alive
trigger1=var(59)=0
Trigger1=PrevStateNo=(开场前状态号)||PrevStateNo=5900
Trigger1=stateno=0
helpertype=normal
name="AI"
stateno=10000
ID=10000
pos=9999,9999
keyctrl=1;令Helper接受手操指令
pausemovetime=2147483647
supermovetime=2147483647
persistent = 0

[State -3, Helper持续保持在状态10000]
type=changestate
trigger1= ishelper(10000)
trigger1= stateno!=10000
value=10000

[State -3, AIフラグセット]
type = VarSet
triggerall = !var(59)
triggerall = RoundState = [1,2]
Trigger1 = Helper(10000),var(59);Helper里面的开关打开时,本体AI开关打开
var(59) = 1

;下面五段放到St文件里任意一个合适的地方
;--------------------------------------------------
[Statedef 10000];Helper的状态定义
anim=10000 ;请保证修改Air文件使得存在一个动画(例如10000)是无任何框的空白动画
ctrl=0

[State 10000, 如果本体错误跳进状态10000就切换回站姿]
type=selfstate
trigger1=!ishelper
value=0

[State 10000, 人物本体和Helper的command相同时返回赋值Var(59)为-1]
type=varset
trigger1=command="up"&&root,command="up"
trigger2=command="down"&&root,command="down"
trigger3=command="back"&&root,command="back"
trigger4=command="fwd"&&root,command="fwd"
trigger5=command="a"&&root,command="a"
trigger6=command="b"&&root,command="b"
trigger7=command="c"&&root,command="c"
trigger8=command="x"&&root,command="x"
trigger9=command="y"&&root,command="y"
trigger10=command="z"&&root,command="z"
trigger11=command="start"&&root,command="start"
var(59)=-1

[State 10000, AI已开启或者人物本体和Helper的command相同时销毁Helper]
Type = DestroySelf
triggerAll = isHelper
Trigger1 = root,var(59)||var(59)=-1
trigger2=command="up"&&root,command="up"
trigger3=command="down"&&root,command="down"
trigger4=command="back"&&root,command="back"
trigger5=command="fwd"&&root,command="fwd"
trigger6=command="a"&&root,command="a"
trigger7=command="b"&&root,command="b"
trigger8=command="c"&&root,command="c"
trigger9=command="x"&&root,command="x"
trigger10=command="y"&&root,command="y"
trigger11=command="z"&&root,command="z"
trigger12=command="start"&&root,command="start"

[State 10000, 当Helper的Var(59)不为-1(意味着两者command没有相同的)而且本体有command时打开AI开关]
type=varset
triggerall=var(59)!=-1
trigger1=root,command="up"
trigger2=root,command="down"
trigger3=root,command="back"
trigger4=root,command="fwd"
trigger5=root,command="a"
trigger6=root,command="b"
trigger7=root,command="c"
trigger8=root,command="x"
trigger9=root,command="y"
trigger10=root,command="z"
trigger11=root,command="start"
var(59)=1

优点:启动速度快
缺点:误触发率较高,需要占用一个Helper

--------------------------------------------------
5.3.4XOR型AI开关
--------------------------------------------------

此AI开关与Cmd乱数启动型AI开关比较类似,无论是对AI.cheat的依赖还是两种AI开关的优缺点。
XOR即是异或运算符,A ^^ B,AB只有一个为真才为真,否则为假。
此开关需要创建多个与原来已经存在的手操指令重复的手操指令(例如名为"x"和"x2"的两个指令都是按x键)。
在手操时,玩家输入手操指令,两个要求相同输入的command会被同时鉴别为真;
但若是AI操作的情况,AI可以做到单独发动其中一个command。
一旦遇到只发动其中一个command的情况,便可以察觉出并非玩家在操作。
(下面的例子直接引用鱼姐(muigoloroh)在tieba.baidu.com/p/1440470506的实例)
XOR型AI开关实例:

;下面一段放到Cmd文件的手操指令定义部分
;--------------------------------------------------
[Command]
name = "a2"
command = a
time = 1
[Command]
name = "b2"
command = b
time = 1
[Command]
name = "c2"
command = c
time = 1
[Command]
name = "x2"
command = x
time = 1
[Command]
name = "y2"
command = y
time = 1
[Command]
name = "z2"
command = z
time = 1
[Command]
name = "start2"
command = s
time = 1
[Command]
name = "holdfwd2"
command = /$F
time = 1
[Command]
name = "holdback2"
command = /$B
time = 1
[Command]
name = "holdup2"
command = /$U
time = 1
[Command]
name = "holddown2"
command = /$D
time = 1

;下面一段放到[Statedef -1]或[Statedef -3]下面
;--------------------------------------------------
[State -1, XOR AI开关]
type = VarSet
triggerall = var(59) = 0 && !hitpausetime
trigger1 = command = "a" ^^ command = "a2"
trigger2 = command = "b" ^^ command = "b2"
trigger3 = command = "c" ^^ command = "c2"
trigger4 = command = "x" ^^ command = "x2"
trigger5 = command = "y" ^^ command = "y2"
trigger6 = command = "z" ^^ command = "z2"
trigger7 = command = "holdfwd" ^^ command = "holdfwd2"
trigger8 = command = "holdback" ^^ command = "holdback2"
trigger9 = command = "holdup" ^^ command = "holdup2"
trigger10 = command = "holddown" ^^ command = "holddown2"
trigger11 = command = "start" ^^ command = "start2"
var(59) = 1

优点:误触发率低
缺点:启动速度慢(因为不知道AI何时才会碰巧执行你写的command...可以说是碰运气),需要新增较多command(数量越多效果越
好),AI.cheat需要打开(默认打开)

--------------------------------------------------
5.3.5AILevel型AI开关
--------------------------------------------------

1.0及以上的版本Mugen新增了一个trigger――AILevel。
当AI控制的时候,AILevel返回option里面设置的难度(1~8);而玩家控制的时候,会因为不是AI控制而返回0。
自此,AI开关问题被新增的内容完美解决。AI作者不必再为AI开关的准确性和速度而纠结。
AILevel型AI开关实例:

;下面一段放到[Statedef -1]或[Statedef -3]下面
;--------------------------------------------------
[State -1]
type = Varset
trigger1 = AILevel
V = 59
value = 1

优点:必定以最快速度准确地启动AI
缺点:仅能在1.0或以上的专用人物使用(1.0+大法好,退Win保平安...这不是缺点是优点你懂吗!)

==================================================
5.4手操指令修改
==================================================

--------------------------------------------------
当人物处于非手操场合,Mugen里面有自带的脸滚键盘式(如k87uy6ttfr4567yu8rgtf54...啊,脸好痛)的随机按键,
而Cmd文件里面切换相关状态部分会根据command切换状态。
那么问题来了,AI技术哪家强...不对...重新来一遍。
那么问题来了,Mugen的随机按键会随机触发Cmd里面的状态切换,
那么人物将会在我们控制之外随机做不同的动作,但是这种乱出招并不是我们所希望看到的。
于是,我们既然设好了AI开关,紧跟着就要修改相关的sctrl,使得他们在AI开启的情况下不再乱动。

用回第3章的例子:

;Stand Light Punch
[State -1, Stand Light Punch]
type = ChangeState
value = 200
triggerall = !Var(59);只有Var(59)为0,也就是AI开关关闭的时候才能用手操触发
triggerall = command = "x"
triggerall = command != "holddown"
trigger1 = statetype = S
trigger1 = ctrl
trigger2 = stateno = 200
trigger2 = time > 6

在前面加上triggerall = !Var(59)即可。所有带有command的sctrl都需要加上限制以免被随机按键触发。
另外,带有command的sctrl绝大多数情况出现在Cmd文件里面,但是在其他文件例如St和Stcommon文件里面同样可能存在不少带有
command的sctrl。以下这段是在kfm.cns里面出现的sctrl:

;------------------
; Light Kung Fu Knee - jump
...
[Statedef 1051]
...
[State 1051, 2]
type = ChangeState
trigger1 = Command = "a" || Command = "b"
trigger1 = Vel y < -1
value = 1055

跟Cmd文件的处理方式一样,加上一条triggerall = !Var(59)即可。

--------------------------------------------------
在所有带有command的sctrl前加完了triggerall = !Var(59)...这样总算是告一段落了......唉?还没完事?
没错,除了带有command的sctrl以外,Mugen里面还存在内置的隐性的用手操指令切换状态,
例如下蹲(Stateno 10)、走动(Stateno 20)和跳跃(Stateno 40)。
理论上来说,人物只要处于可控状态(例如站姿),按下会下蹲,按前后会走动,按上会跳跃。
但是无论在什么地方,我们都找不到这些状态是如何切换的,这情况相当难处理。
当然,AI作者们已经早已解决了这个难题,具体解决方法较麻烦,所以在第8章我们再慢慢讨论解决方案。

==================================================
课后作业:

1.
为什么Cmd乱数启动型AI开关与XOR型AI开关新增command数量越多效果越好?

2.
以上谈及的3种AI开关――Cmd乱数启动型AI开关、Helper型AI开关和XOR型AI开关,是否可以混合使用?为什么?