2016.02.2421:17

AI防御

Episode 4 防御

格斗里最重要的动作,防御,少了它,那就根本不是战斗(喂)

接下来看一个简单的例子

;---------------------------------------------------------------------------
[State -3,蹲防]
type = ChangeState
value = 131 ;蹲防的stateno
triggerall = var(59) && statetype !=A ;ai开启且自身不在空中
triggerall = p2statetype = C
triggerall = !EnemyNear,hitdefattr = SCA,AT,ST,NT ;对手不能出投技
triggerall = ctrl && p2statetype !=A ;这里加一个对手不在空中保险起见。
trigger1 = inguarddist ;inguarddist之前已经提到过了,大家仔细看的可能会注意到,不过待会还会讲
trigger1 = facing !=EnemyNear,facing ;facing 和 enemynear,facing的关系:enemynear,facing = facing为不面对对手,反之面对
trigger2 = p2bodydist x < 0 && p2movetype = A ;当对手在你背后时不算在inguarddist内
;---------------------------------------------------------------------------
[State -3,立防]
type = ChangeState
value = 130 ;站防stateno
triggerall = var(59) && statetype !=A
triggerall = p2statetype != C
triggerall = !EnemyNear,hitdefattr = SCA,AT,ST,NT ;对手不能出投技
triggerall = ctrl
trigger1 = inguarddist
trigger1 = facing!= EnemyNear,facing ;面对对手,并且inguarddist
trigger2 = facing = EnemyNear,facing
trigger2 = p2dist x > 0
trigger2 = p2bodydist x = [-10,60] ;距离
trigger2 = p2movetype = A ;不面对对手,但是对面这个时候可能是打逆的,最好使用站防
trigger3 = p2bodydist x < 0 && p2movetype = A ;同上
;---------------------------------------------------------------------------
[State -3,空防]
type = ChangeState
value = 132 ;空防stateno
triggerall = var(59)
triggerall = ctrl && statetype = A ;自身在空中
trigger1 = inguarddist
trigger2 = p2bodydist x < 0 && p2movetype = A ;同上
;---------------------------------------------------------------------------

INGUARDDIST

把这段英文拆开,in guard dist,意思是在防御距离内,那如何定义防御距离呢?

当敌人出招,你距离很远时,你按后,是后退,当处在一定距离内,敌人出招,虽然可能打不中,但此时你按后,就摆出防御姿势而不是后退了,我们讲这个距离以内就是防御距离,也就是inguarddist,对手不攻击或攻击离你太远,自然就!inguarddist

注意并不是说打得到你才是inguarddist,得看是不是在某个距离以内,这个要看对手攻击的attackdist的定义,没有的话就用默认的值(普通攻击默认160,飞行道具默认90)

如果有一招把attackdist定义为0,那这招就算不是投技也没法防御(一般投技无法防御就是因为这个,attackdist定义为0或者在hitdef下写guard.dist = 0(重新定义对面防御距离为0,也就是无法检测到防御)也是一样的效果),但其实实际运用时,你根本不需要知道inguarddist的定义,只需要写上这个条件就可以了

除了凹以外的招,最好加入!inguarddist,以免贸然进攻,或者再加一个对手背对时的距离 !inguarddist || enemynear,facing = facing && abs(enemynear,pos x - pos x) > A(这里的A自己判断了)

再提一下带KOF系统的GCF(防御前翻滚,KOF96以后的ADV系统都有的,消耗1气)(一般不用GBF,防御后翻滚),还有GCBA(防御下CD,同样耗1气),举例

[State -3, GCFRoll] ;防御前翻滚
Type = ChangeState
Value = 700
TriggerAll = var(59) = 1
TriggerAll = RoundState = 2
TriggerAll = Power >= 1000
TriggerAll = Random <= 250
TriggerAll = StateType != A
TriggerAll = StateNo = 150 || StateNo = 151 ;在防御时出
Trigger1 = P2BodyDist X = [-5,50]
Trigger1 = EnemyNear,StateNo >= 200 ;对面攻击状态,并且状态号 >= 200,抓对面硬直
Trigger1 = EnemyNear,StateType != A
Trigger1 = EnemyNear,MoveType = A
Trigger1 = EnemyNear,AnimTime < -23 AB的时间(减去superpause的时间)

[State -3, Guard Counter Blowback Attack]
Type = ChangeState
Value = 300
TriggerAll = var(59) = 1
TriggerAll = RoundState = 2
TriggerAll = Power >= 1000
TriggerAll = StateType != A
TriggerAll = EnemyNear,StateNo >= 200
TriggerAll = EnemyNear,StateType != L
TriggerAll = EnemyNear,MoveType = A
TriggerAll = StateNo = 150 || StateNo = 151 ;在防御时出
TriggerAll = P2BodyDist X = [-5,50]
Trigger1 = EnemyNear,StateType != A
Trigger1 = EnemyNear,AnimTime <= -5 ;自己的CD触发攻击时间减去CD的superpause时间
Trigger1 = Random <= 100
Trigger2 = EnemyNear(var(58)),StateType = A
Trigger2 = P2BodyDist Y = [-50-floor(5*(EnemyNear,Vel Y)+(5*(5+1)/2)*EnemyNear,Const(movement.yaccel)),0-floor(5*(EnemyNear,Vel Y)+(5*(5+1)/2)*EnemyNear,Const(movement.yaccel))] ;距离公式,以后会讲用法,距离需要自己耐心测量
Trigger2 = Random <= 200

蹲防和站防
对手在蹲下时,一般是对手蹲下时选择蹲防,其余选择站防,对手空中一般选择站防,极少数情况空中技能是下段的,对手蹲下时也一般不可能是中段
中段:蹲防不能,下段:站防不能,上段,二者皆可,基本概念不要混淆

问题来了,站立时可能是中段,也可能是下段,当然还有可能是上段,原因是对手的出招属性难以判断

对手站立下段可能有5B,5D,站立中段可能是一些特殊技之类的,不过也有5D特殊的,比如97七伽社的5D就是中段技

如果防御破了怎么办呢?可以尝试用HELPER记录下防御段位,在以后的授课会给出防御HELPER记忆器,招式一旦被破,则可以记下来不被击飞或者不强制改变状态的招式

同样,你进攻对面的时候,可以在飞行道具掩护的有利情况下出中段技(前提是你有)让对手崩防

另外注意一下,前面的防御只是防御一次的,之后AI在连续的压制中要段位切换的,如果你不写的话,系统是随机切换站防蹲防的,所以要改common1.cns,一般就是前面所说的mugen的data下的那个系统默认的common1.cns
(不一定所有人物都用这个文件,看def里定义的stcommon)

如果是要改那个系统默认的common1.cns,请复制到此人物自己的目录里再改,最好再新建个文件夹(比如ai)
def里改一下stcommon = ai/common1.cns
因为这个common1是公用的,你改了这个会影响到所有人物

在common1里面找到120-155这段

[State 120, Hi to Lo]
type = StateTypeSet
trigger1 = statetype = S && command = "holddown"
statetype = C
physics = C

[State 120, Lo to Hi]
type = StateTypeSet
trigger1 = statetype = C && command != "holddown"
statetype = S
physics = S

我们改一下,设AI有强度等级,我们以A为界限,来调整防御等级

[state 120,AI Hi to Lo]
type = StateTypeSet
triggerall = statetype = S ;自身站立中
trigger1 = var(59) = 0
trigger1 = command = "holddown" ;指令按住下
trigger2 = var(59) = [1,A] ;AI启动并且AI强度在A级或者A级以下
trigger2 = enemynear,statetype != A ;对面非空中
trigger2 = Random <= 250 ;概率小于250,满值为1000,也就是说25%的概率了
trigger3 = var(59) > A ;A级以上的AI强度
trigger3 = enemynear,statetype = C ;对面蹲下时
trigger4 = var(59) > A ;A级以上的强度
trigger4 = enemynear,statetype = S ;对面站立
trigger4 = enemynear,time < 20 ;对面时间在20以下,中段技一般发生较慢,在那之前可以蹲防,后切站防
trigger4 = !enemynear,numproj ;对面不能有飞行道具
trigger5 = var(59) > A ;A级以上
trigger5 = enemynear,statetype = S ;对面站立
trigger5 = enemynear,numproj ;对面有飞行道具,有些飞行道具可能是下段的,比如KOFXI KING的波
statetype = C ;切换到蹲下状态
physics = C

[State 120, Lo to Hi]
type = StateTypeSet
triggerall = statetype = C ;自身蹲下中
trigger1 = var(59) = 0
trigger1 = command != "holddown" ;指令不能是按住下
trigger2 = var(59) = [1,A] ;1-A级之间的AI强度
trigger2 = enemynear,statetype = A ;对面是空中
trigger2 = Random <= 250 ;25%的概率
trigger3 = var(59) > A ;A级以上的AI强度
trigger3 = enemynear,statetype = A ;对面在空中
trigger4 = var(59) > A ;A级以上的强度
trigger4 = enemynear,statetype = S ;对面站立
trigger4 = enemynear,time >= 20 ;对面时间>= 20(这里20以上的技能已经很慢了,大概中段技就这么长时间)
trigger4 = !enemynear,numproj ;对面不能有飞行道具
statetype = S ;切换到站立状态
physics = S

然后再把
[State 120, Stop Guarding]
type = ChangeState
trigger1 = command != "holdback"
trigger2 = !inguarddist
value = 140

trigger1下面再加一行trigger1 = var(59) = 0
下面130-132的stop guarding也一样修改。就不多说了

接着看state 130和131
[State 130, Hi to Lo]
type = ChangeState
trigger1 = command = "holddown"
value = 131

这里改成
[State 130, Hi to Lo]
type = ChangeState
trigger1 = var(59) = 0
trigger1 = command = "holddown"
trigger2 = var(59) = [1,A]
trigger2 = enemynear,statetype != A
trigger2 = Random <= 250
trigger3 = var(59) > A
trigger3 = enemynear,statetype = C
trigger4 = var(59) > A
trigger4 = enemynear,statetype = S
trigger4 = enemynear,time < 20
trigger4 = !enemynear,numproj
trigger5 = var(59) > A
trigger5 = enemynear,statetype = S
trigger5 = enemynear,numproj
value = 131

同样
[State 131, Lo to Hi]
type = ChangeState
trigger1 = command != "holddown"
value = 130

改成
[State 131, Lo to Hi]
type = ChangeState
trigger1 = var(59) = 0
trigger1 = command != "holddown"
trigger2 = var(59) = [1,A]
trigger2 = enemynear,statetype = A
trigger2 = Random <= 250
trigger3 = var(59) > A
trigger3 = enemynear,statetype = A
trigger4 = var(59) > A
trigger4 = enemynear,statetype = S
trigger4 = enemynear,time >= 20
trigger4 = !enemynear,numproj
value = 130

下面的state 140-142,state 150-153的
hi to lo和lo to hi的改法和120的基本一致,就不说了,注意state号别写错就行

最后就是改state 150-155了

[State 150, 2]
type = ChangeState
trigger1 = HitShakeOver
value = 151 + 2*(command = "holddown")

这里改成
[State 150, 2]
type = ChangeState
trigger1 = HitShakeOver
value = 151 + 2*ifelse(var(59) = 0,(command = "holddown"),(enemynear,statetype = C || enemynear,time < 20 && enemynear,statetype = S))

这里也一样改掉,方法和上面一样
[State 152, 3]
type = ChangeState
trigger1 = HitShakeOver
value = 151 + 2*(command = "holddown")

[State 152, 2]
type = ChangeState
trigger1 = HitShakeOver
value = 151 + 2*ifelse(var(59) = 0,(command = "holddown"),(enemynear,statetype = C || enemynear,time < 20 && enemynear,statetype = S))

这样,防御中对敌人的中下段切换就会做出应对了,是不是很简单呢?

好了,今天的课就先到这,如果您有什么问题的话可以私信我,我会第一时间给您答复,或者把问题发到我的邮箱

mizore@kotori.moe, 谢谢大家!
2016.02.2319:32

确反(抓硬直),爆发(反应),凹和切反

Episode 3 确反,爆发,凹和切反

先来看一个例子

[State -3, 2A]
Type = ChangeState ;改变状态
Value = 400 ;状态号为400的技能
TriggerAll = var(59) = 1 ;AI启动
TriggerAll = Alive ;存活
TriggerAll = RoundState = 2 ;战斗中
TriggerAll = Random <= 600 ;概率
TriggerAll = StateType != A ;自己的状态,statetype分A(空中),S(站立),C(蹲下),L(倒地),这里statetype !=A也就是说自己不在空中触发
TriggerAll =!EnemyNear,Ctrl ;对面不可控时
TriggerAll = EnemyNear,StateNo >= 200 ;状态号>= 200,200以前一般不是战斗中的state (通常除了195 TAUNT)
TriggerAll = EnemyNear,StateType != A ;对面不在空中
TriggerAll = EnemyNear,StateType != L ;对面不倒地,也就是对面站立或者蹲下都可以
TriggerAll = EnemyNear,AnimTime <= -5 ;Animtime,这个理解为“自己这个技能的发生帧数”,比如说400的发生帧数为第5帧,你就写enemynear,animtime <= -5,概念有点抽象,以后细说
TriggerAll = EnemyNear,MoveType = I || EnemyNear,MoveType = A && EnemyNear,HitdefAttr != SCA,AA,AT,AP || EnemyNear,AnimTime = -5 && ((PrevStateNo = [130,155]) || EnemyNear,Facing = Facing) ;对面未作出动作,或者对面虽然是攻击状态,但未有任何攻击定义,或者是卡对面还剩5帧时候,自己之前的动作是防御来抓硬直,或者要么打背也可以
TriggerAll = EnemyNear,Time >= 0 ;对面TIME >= 0,反应时间,这里TIME >= 0就是超反应允许的意思
TriggerAll =!InGuardDist || EnemyNear,Facing = Facing || EnemyNear,AnimTime = -5 && (PrevStateNo = [130,155]) ;不处在防御范围内,或者背对对面(如果是Inguarddist再确认命中就是counter),或者是抓最后的硬直
TriggerAll = Ctrl || (StateNo = [20,22]) || (StateNo = [100,101]) || (StateNo = [120,149]) ; (这一行非常重要,特别是ctrl,少了这一行如果触发这个AI则人物会鬼畜)
Trigger1 = P2BodyDist X = [-10,40] ; (算好与对面的距离,确认反击)

这是一个很常见的确反(抓硬直)AI,可以看出,AI内包含 !InGuardDist || EnemyNear,Facing = Facing,也就是不在防御范围内,或者面对背面,当对面不可控并且处于没有判定出现的状态,即可做到攻击对面的破绽,一般是升龙挥空之类的

一般推荐自己起手为5帧以下的技能,或者你有个无敌,GP的话可以长一点,什么都没有还5帧以上的还是放弃吧

AI爆发(AI暴発)(反应)

语句中包含

triggerall = enemynear,movetype = A
triggerall = ctrl || (StateNo = [20,22]) || (StateNo = [100,101]) || (StateNo = [120,149])
triggerall = enemynear,time <= 1 ;重点是这句,必须在对手出手后1F以内,否则风险大增
trigger1 = random <= 100 ;概率不要太高,除非你很自信

AI反应,假如var(59)是AI等级,AI等级最高为10,那么可以举例
TriggerAll = EnemyNear,Time >= 50-5*var(59) || var(59) >= 10
那么当var(59) = 10的时候,条件为enemynear,time >= 0,也就是对面刚出招,自己就可以反应,也就是所谓的0帧反应
当AI为10时,也叫超反应,当你不加这句话的时候,CPU默认就是0帧反应

AI凹和切反
凹,大家应该都比较熟悉这个词,口中常说的“凹升龙”“凹182”之类的,其实就是利用无敌躲过对手判定来打中对手,前提不能是连段中,而是在立回中

切反,则不一定要是无敌技能,也可以是KOF系统的AB,BLACK OUT之类的技能来躲避对手攻击

二者之间的相同点是不能加 !inguarddist,对面movetype = A时对应出招,优先度必须大于防御(也就是必须写在防御的上面),不同点就是凹必须是攻击反击回去,而切反不一定要攻击

一般凹招必须再加一句triggerall = enemynear,animtime <= -X(X为判定出现的帧数,比如刚才的400,出现判定的帧数是第5帧,那么答案就是triggerall = enemynear,animtime <= -5),当然如果你包含低级AI的话,可以在这句话后面加一个 “ || var(59) <= B ” (B为你要低于的AI等级)

最好再用概率来限制一下
triggerall = Random <= 50 || Enemy,StateNo < 2000(概率小于50,或者对面状态号<= 2000)(2000以上的超必杀概率比较大,不好说超必杀的类型,所以还是尽量回避一下)
triggerall = Random <= ifelse((PrevStateNo = [140,155]),EnemyNear,Time*20,EnemyNear,Time*10)(概率随对面时间增加而增大,如果是撤防时概率翻倍,当然如果你有其他的想法可以改掉,这里只距离刚撤防时,其实还有被打,收招都可以用到)

好了,今天的课就先到这,大家写AI的时候一定要多看,看看别人的怎么写,总结自己的经验才有收获

如果您有什么问题的话可以私信我,我会第一时间给您答复,或者把问题发到我的邮箱

mizore@kotori.moe, 谢谢大家!
2016.02.2314:36

AI走路,跑步,跳跃定义

Episode 2 走路,跑步,跳跃定义

我们先来改个东西,看到人物DATA下方
找到intpersistindex和floatpersistindex,改一下
改成这样
intpersistindex = 5
floatpersistindex = 20

什么意思呢,第一局结束后直接带到下一局的var,因为var是记忆的,有些var如果记忆一次后不赋值则会失去之前的数据,比如intpersistindex = 5,就是var(5)包括var(5)以后的var会直接带入下局,则之前的如果没有赋值会清空,很好理解吧,先记下来,以后用得上

接下来是正题
定义statedef 20为走路,anim = 20为前,21为后,statedef 40为跳跃,statedef 45为二次跳跃(一般KOF系统不使用,所以这里不讲),statedef 50为跳跃中,statedef 52为默认落地,statedef 100为跑步,statedef 105为后撤(后面就不说了,就用到这些)

需要修改和复制的有statedef 20 statedef 40 statedef 100,也就是,走,跳,跑

先说走路,定义一个前走

;-------------------------------------------------------------------------------
; Walk(前進)
[Statedef 19]
type = S
physics = S
sprpriority = 0

[State 20, 1]
type = VelSet
trigger1 = !var(59) ;非AI启动
trigger1 = command = "holdfwd" ;指令,按住前
trigger2 = var(59) ;AI启动
x = const(velocity.walk.fwd.x)

[State 20, 2]
type = VelSet
trigger1 = !var(59) ;非AI启动
trigger1 = command = "holdback" ;指令,按住后
x = const(velocity.walk.back.x)

[State 20, 3]
type = ChangeAnim
triggerall = vel x > 0
trigger1 = Anim != 20 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 20

[State 20, 4]
type = ChangeAnim
triggerall = vel x < 0
trigger1 = Anim != 21 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 21

于是这样就定义一个前走了,那么下面是泛用走路


;---------------------------------------------------------------------------
; Walk(AI、汎用)
[Statedef 21]
type = S
physics = S
sprpriority = 0
ctrl = 0

[State 20, Turn]
Type = Turn ;转向,走路中如果背对了对面转回去面对对面
Trigger1 =!Ctrl
Trigger1 = P2Dist X < 0
Trigger1 = Anim = 20 || Anim = 21

[State 20, AI 前進]
Type = VelSet ;前进AI部分
triggerall = var(59)
triggerall = Vel X >= 0
triggerall =(PrevStateNo != [140,155]) || P2BodyDist X > 140 ;不能是撤防时或者离对面较远时
trigger1 =(P2BodyDist X = [20,120]) || enemynear,facing = facing ;看上面的条件,第一个是在20-120距离,不满足上面的P2BodyDist X > 140条件,则必须满足(PrevStateNo != [140,155])条件才会触发,第二个是被对对面时触发
trigger2 = P2BodyDist X > 140 ;同上面主条件第二项
x = const(velocity.walk.fwd.x)

[State 20, AI 後退]
Type = VelSet
triggerall = var(59)
triggerall = Vel X <= 0
triggerall = enemynear,facing != facing ;面对对面
triggerall = enemynear,MoveType != H ;对面不能是不被打的情况
trigger1 = P2BodyDist X = [0,60] ;在0-60码的距离
trigger2 = P2BodyDist X = [90,160] ;在90-160码的距离
trigger3 = enemynear,MoveType = I || enemynear,StateNo >= 1000 ;对面未作出任何动作或者对面stateno >= 1000(通常是必杀技以上,也有可能是拳脚但概率不大)
trigger4 =(PrevStateNo = [140,155]) && P2BodyDist X <= 140 ;刚刚撤防且离对面140码内
x = const(velocity.walk.back.x)

[State 20, 1]
type = VelSet
triggerall = !var(59)
trigger1 = command = "holdfwd"
x = const(velocity.walk.fwd.x)

[State 20, 2]
type = VelSet
triggerall = !var(59)
trigger1 = command = "holdback"
x = const(velocity.walk.back.x)

[State 20, 3]
type = ChangeAnim
triggerall = vel x > 0
trigger1 = Anim != 20 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 20

[State 20, 4]
type = ChangeAnim
triggerall = vel x < 0
trigger1 = Anim != 21 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 21

[State 20, 5]
type = ChangeState
trigger1 = Vel X = 0
trigger2 = frontedgebodydist < 10 ;离版边太近时停止
trigger3 = roundstate != 2 ;回合结束后停止
trigger4 = inguarddist ;在对面的Inguarddist(这里的意思就是说,对面攻击,你在一定范围内会摆出防御姿势的距离)
trigger4 = EnemyNear,facing != facing ;不面对对手
value = 0
ctrl = 1

;---------------------------------------------------------------------------
; Walk(AI、起き攻め位置取り用) ;(这个,用在对面倒地起身时移动用的,以后再讲)
[Statedef 22]
Type = S
physics = S
sprpriority = 0
ctrl = 0

[State 20, Turn]
Type = Turn
Trigger1 =!Ctrl
Trigger1 = P2Dist X < 0
Trigger1 = Anim = 20 || Anim = 21

[State 20, 前進]
Type = VelSet
triggerall = var(59)
trigger1 = var(44) = 1
trigger1 = P2BodyDist X > 40
trigger2 = var(44) != 1
trigger2 = P2BodyDist X > 60
x = const(velocity.walk.fwd.x)

[State 20, 後退]
Type = VelSet
triggerall = var(59)
trigger1 = var(44) = 1
trigger1 = P2BodyDist X < 20
trigger2 = var(44) != 1
trigger2 = P2BodyDist X < 40
x = const(velocity.walk.back.x)

[State 20, 1]
type = VelSet
triggerall = !var(59)
trigger1 = command = "holdfwd"
x = const(velocity.walk.fwd.x)

[State 20, 2]
type = VelSet
triggerall = !var(59)
trigger1 = command = "holdback"
x = const(velocity.walk.back.x)

[State 20, 3]
type = ChangeAnim
triggerall = vel x > 0
trigger1 = Anim != 20 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 20

[State 20, 4]
type = ChangeAnim
triggerall = vel x < 0
trigger1 = Anim != 21 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 21

[State 20, 5]
type = ChangeState
trigger1 = Vel X = 0
trigger2 = frontedgebodydist < 10
trigger3 = roundstate != 2
trigger4 = inguarddist
trigger4 = EnemyNear(var(58)),facing != facing
value = 0
ctrl = 1

那么 statedef 20呢?

它在这!

;---------------------------------------------------------------------------
; Walk
[Statedef 20]
type = S
physics = S
sprpriority = 0

[State 20, 0]
type = ChangeState
triggerall = var(59) = 1 ;为了防止乱走,直接限制AI启动时它自动回0
trigger1 = time = 0
value = 0
ctrl = 1

[State 20, 1]
type = VelSet
trigger1 = command = "holdfwd"
x = const(velocity.walk.fwd.x)

[State 20, 2]
type = VelSet
trigger1 = command = "holdback"
x = const(velocity.walk.back.x)

[State 20, 3]
type = ChangeAnim
triggerall = vel x > 0
trigger1 = Anim != 20 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 20

[State 20, 4]
type = ChangeAnim
triggerall = vel x < 0
trigger1 = Anim != 21 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0
value = 21

走路部分就到这里,接下来是跳跃,以KOF96以后的ADV系统为例子

;---------------------------------------------------------------------------
; Jump Start
[Statedef 40]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1
facep2 = 1

[State 40, 0]
type = ChangeState
triggerall = var(59) = 1 ;同样,防止AI乱跳,限制一下AI的动作
trigger1 = time = 0
value = 0
ctrl = 1

[State 40, 1] ;这里var(4)控制小,通常跳
type = VarSet
trigger1 = time = 0
var(4) = 0

[State 40, 1];小ジャンプ
type = VarSet
trigger1 = command != "holdup"
var(4) = 1

[State 40, 1] ;基本定义,sysvar(1) = 0为上跳, = 1为前,-1为后
type = VarSet
trigger1 = Time = 0
sysvar(1) = 0

[State 40, 2]
type = VarSet
trigger1 = command = "holdfwd"
sysvar(1) = 1

[State 40, 3]
type = VarSet
trigger1 = command = "holdback"
sysvar(1) = -1

[State 40, 4] ;通常跳速度定义
type = VelSet
trigger1 = AnimTime = 0
trigger1 = Var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ ;小跳速度定义
type = VelSet
trigger1 = AnimTime = 0
trigger1 = Var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up ;起跳时防投
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState ;跳转到50,也就是跳跃中
trigger1 = AnimTime = 0
value = 50
ctrl = 1

那么下面大家可以参考我使用的跳跃系统

30:通常前跳,31:通常后跳,32:小前跳,33:小后跳,34:影前跳,35:影后跳,36:大前跳,37:大后跳,38:通常上跳,39:小上跳

不同的人物系统不同的利用方法,这里自己理解了

以30为例子,后面就不说明了(笑)
;---------------------------------------------------------------------------
; AI前ジャンプ
[Statedef 30]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = 1 ;方向:前

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 0 ;定义通常跳

[State 40, 4]
type = VelSet ;因为是var(4) = 0,那么取这一部分
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;後ろジャンプ
[Statedef 31]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = -1

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 0

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;前小ジャンプ
[Statedef 32]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = 1

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 1

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;後ろ小ジャンプ
[Statedef 33]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = -1

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 1

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;前中ジャンプ
[Statedef 34]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = 1

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 1

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;後ろ中ジャンプ
[Statedef 35]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = -1

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 1

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;前大ジャンプ
[Statedef 36]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = 1

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 0

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;後ろ大ジャンプ
[Statedef 37]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = -1

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 0

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;上ジャンプ
[Statedef 38]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = 0

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 0

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

;---------------------------------------------------------------------------
;垂直小ジャンプ
[Statedef 39]
type = S
physics = S
anim = 40
ctrl = 0
sprpriority = 1

[State 40, 2]
type = VarSet
trigger1 = 1
sysvar(1) = 0

[State 40, 1]
type = VarSet
trigger1 = 1
var(4) = 1

[State 40, 4]
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 0
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = const(velocity.jump.y)

[State 40, 4];小ジャンプ
type = VelSet
trigger1 = AnimTime = 0
trigger1 = var(4) = 1
x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x)))
y = -6

[State 120, 5] ;Can't be thrown right after getting up
type = NotHitBy
trigger1 = time >= 0
value = , NT,ST,HT

[State 40, 6]
type = ChangeState
trigger1 = AnimTime = 0
value = 50
ctrl = 1

这么多跳跃,都是从40演变过来的,因为跳跃方式有这么多,所以AI用的话得一个个列举出来了

刚才注意到,人物是有残影跳的,那么怎么设置残影跳呢?

在statedef -3下加入这些东西,我们定义var(3)为控制残影跳和通常跳的变量

;-------------------------------------------------------------------------------
[Statedef -3]

[State -3, コマンドを入れたらVarをON]
Type = VarSet
TriggerAll = !var(59)
Trigger1 = Command = "jump" ;残影跳的指令,一般是269,247这些的,一会给出指令
Trigger1 = Ctrl
Trigger1 = StateType = S
Trigger2 = PrevStateNo = 100
Trigger2 = Command = "holdfwd" ;之前的动作为跑步,并且按住前,才可出现残影跳
V = 3
Value = 1

[State -3, sysvarを引継ぐ] ;出现了残影跳以后,需要继续赋值
Type = VarSet
Trigger1 = Var(3) = 1 ;出现了残影跳
Trigger1 = StateNo = 40 ;ジャンプする前のステート
Trigger1 = AnimTime = 0 ;ジャンプ方向を決めるsysvarがリセットされる寸前
var(3) = ifelse(sysvar(1)=0, 2, ifelse(sysvar(1)=1, 3, 4)) ;利用sysvar来判断赋值,上跳赋值为2,前为3,后为4

[State -3, AI]
Type = VarSet
Trigger1 = var(59)
Trigger1 = StateNo = [34,37] ;定义34-37出现残影跳
Trigger1 = AnimTime = 0
var(3) = ifelse(sysvar(1)=0, 2, ifelse(sysvar(1)=1, 3, 4)) ;给AI定义赋值,和上面相同

[State -3, varをOFFにするステート] ;跳出去以后还原var(3) = 0
Type = VarSet
TriggerAll = Time = 2
Trigger1 = StateNo = 50
Trigger2 = StateNo != [40,59]
V = 3
Value = 0 ;还原

[State -3, 前にボタンを押してたら前にも加速] ;残影前跳加速
Type = VelAdd
Trigger1 = var(3) = 3
Trigger1 = StateNo = 50
y = -0.6
x = 1.8

[State -3, 後ろなら後ろに加速] ;残影后跳加速
Type = VelAdd
Trigger1 = var(3) = 4
Trigger1 = StateNo = 50
y = -0.6
x = -1.8

[State -3, 垂直ジャンプにveladdを使って上に加速] ;残影上跳加速
Type = VelAdd
Trigger1 = var(3) = 2
Trigger1 = StateNo = 50
y = -1.8

[State -3, 成功したときの残像] ;出现残影跳后的残影成分,这里自己设定吧
Type = AfterImage
Trigger1 = var(3) >= 1
Trigger1 = StateNo = 50
Trigger2 = AnimTime = 0
Trigger2 = PrevStateNo = 100 ;RUN_FWD
Trigger2 = Sysvar(1) = 1
Time = 2
Length = 7
PalBright = 0,0,0
PalContrast = 256,256,256
PalAdd = 0,0,0
PalMul = 1,1,1
FrameGap = 3

[State 2041, 2]
Type = AfterImageTime ;非残影跳时的残影,这里可以不要,看自己需要
TriggerAll = var(3) = 0
Trigger1 = StateNo = 50
Trigger1 = Time%2 = 0 && Time < 15
Time = 2

;---------------------------------------------------------------------------
[Command] ;这个是刚才说好的补充指令,影跳跃指令,请加在Statedef -1上方
name = "jump"
command = D, $U ;下蓄力上
time = 12

好了,以上就是定义跳跃的内容,如果有类似定义也可以按照定义进行修改

接下来是跑步,statedef 100,根据每个人anim不同,性能也会有些差距的

;---------------------------------------------------------------------------
; RUN_FWD
[Statedef 100]
type = S
physics = S
anim = 100
sprpriority = 1
ctrl = 0 ;一般是不可控

[State 100, 1]
type = VelSet
trigger1 = AnimElemtime(2) >= 0 ;第二张图后
x = const(velocity.run.fwd.x) ;跑步速度,在人物[Velocity]下可以更改,run.fwd.x项

[State 100, PlaySnd] ;跑步音效
type = PlaySnd
triggerall = time = 4
trigger1 = Alive
loop = 1 ;因为跑步声是循环的,所以写上loop = 1让声音循环
value = s5,0 ;声音
channel = 6 ;频道,有用,一会说明作用

[State 100, 2] ;Prevent run from canceling into walk
type = AssertSpecial
trigger1 = 1
flag = NoWalk ;是跑,所以断言不走

[State 100, 3] ;Prevent from turning
type = AssertSpecial
trigger1 = 1
flag = NoAutoTurn ;不能自动转向面对对手

[State 100, 4]
type = ChangeState
triggerall = var(59) != 1
trigger1 = command = "holdup"
value = 40 ;跑步中跳可以出现残影跳

[State 100, 4]
type = ChangeState
triggerall = var(59) != 1
triggerall = AnimElemtime(2) >= 0
trigger1 = command != "holdfwd"
value = 101 ;101为停止用statedef,我这里使用了,如果不想用,用回MUGEN原来的0也可以

[State 100, AI]
Type = ChangeState
TriggerAll = var(59) = 1
TriggerAll = AnimElemtime(2) >= 0
Trigger1 = Time = 60 ;60帧停一下
Trigger2 = P2BodyDist X <= 40
Trigger2 = P2BodyDist Y >= -120 ;X方向(横向)离40码以内,Y方向(纵向)离120码以内
Trigger2 = EnemyNear,MoveType != H ;对面不是被打状态
Trigger2 = EnemyNear,Facing != Facing || P2BodyDist X < 0 ;面对对面或者对面逆向停止跑动
Trigger3 = EnemyNear,MoveType = A ;对面处于攻击状态
Trigger3 = EnemyNear,Facing != Facing ;面对对面
Trigger4 = EnemyNear,StateType = L ;对面倒地了
Trigger4 = P2BodyDist X <= 60 ;60个距离点内停止跑动
Trigger5 = InGuardDist ;处在inguarddist范围内(之前有说过,inguarddist也就是对面攻击给自己产生的防御距离)
Trigger5 = EnemyNear,Facing != Facing ;面对对面
Trigger6 = Enemy,NumProj ;对面有飞行道具停止跑动
value = 101

[State 100, AI]
Type = ChangeState
triggerall = var(59) != 0
triggerall = AnimElemtime(2) >= 0
trigger1 = alive
trigger1 = life > 0
trigger1 = roundstate = 3 ;回合结束后停止前进
value = 101

;---------------------------------------------------------------------------
; RUN_FWD STOP ;跑步停止用statedef
[Statedef 101]
type = S
physics = S
anim = 101
sprpriority = 1

[State 101, 1]
type = turn
trigger1 = time = 0
trigger1 = p2dist x < 0

[State 100, 2]
type = VelSet
trigger1 = 1
x = 0

[State 101, 3]
type = CtrlSet
trigger1 = Time = 0
value = 1

[State 101, 4]
type = ChangeState
trigger1 = AnimTime = 0
value = 0
ctrl = 1

还可以按照自己的需要再补充其他的跑步statedef,那么接下来我们说下如何让跑步的声音彻底停止

在statedef -2下加入这行

[Statedef -2]

[State -2, StopSnd]
type = StopSnd ;停止跑步声音
trigger1 = var(59) = 0
trigger1 = command != "holdfwd"
trigger2 = Anim != 100
channel = 6 ;刚才的channel = 6对应了这里,如果动画不是100或者不按住前了,则声音停止

好了,状态号顺利载入,这节课你有没有理解呢?

如果您有什么问题,可以给我私信,我会第一时间给您解答,或者问题发到我的邮箱

mizore@kotori.moe,谢谢大家!
2016.02.2313:31

AI启动器

Episode 1 AI启动器,触发AI的必要元素之一,首先大家如果看过AI的话,肯定见过这么长的一串文字
;---------------------------------------------------------------------------
; AI switch -> ON
[State -3, AI] ;←Title
Type = VarSet ;←变量设置,少了这个不谈
TriggerAll = !IsHelper || IsHelper(30000) ;←本体或者helper(30000)存在
TriggerAll = var(59) != 1 ;←命令var(59) = 1为AI,那么不等于1的话AI则代表未启动
TriggerAll = RoundState = [1,2] ;←在比赛或者比赛开始前
Trigger1 = Command = "AI1" ;←指令1
Trigger2 = Command = "AI2" ;←指令2
Trigger3 = Command = "AI3" ;←指令3
Trigger4 = Command = "AI4" ;←指令4
Trigger5 = Command = "AI5" ;←指令5
Trigger6 = Command = "AI6" ;←指令6
Trigger7 = Command = "AI7" ;←指令7
Trigger8 = Command = "AI8" ;←指令8
Trigger9 = Command = "AI9" ;←指令9
Trigger10 = Command = "AI10" ;←指令10
Trigger11 = Command = "AI11" ;←指令11
Trigger12 = Command = "AI12" ;←指令12
Trigger13 = Command = "AI13" ;←指令13
Trigger14 = Command = "AI14" ;←指令14
Trigger15 = Command = "AI15" ;←指令15
Trigger16 = Command = "AI16" ;←指令16
Trigger17 = Command = "AI17" ;←指令17
Trigger18 = Command = "AI18" ;←指令18
Trigger19 = Command = "AI19" ;←指令19
Trigger20 = Command = "AI20" ;←指令20
Trigger21 = Command = "AI21" ;←指令21
Trigger22 = Command = "AI22" ;←指令22
Trigger23 = Command = "AI23" ;←指令23
Trigger24 = Command = "AI24" ;←指令24
Trigger25 = Command = "AI25" ;←指令25
Trigger26 = NumHelper(30000) ;←存在helper(30000),这里helper(30000)是AI启动的helper,一会会给出
Trigger26 = Helper(30000),var(59) ;←helper(30000)的var(59)不为0(相当于辅助)
Trigger26 = Helper(30000),Time > 5 ;←helper(30000)的出现时间在5F以上
Trigger27 = Helper(40000),var(0) ;←helper(40000)的var(0)不为0(自己写的常时AI开关)
var(59) = 1 ;←则这里启动AI

这里的AI指令有25个,那么25个指令,可以按照以下command来写
这里就顺便把25个指令也贴出来吧,这里载入到Statedef -1上方,和那群command一起的位置
;-------------------------------------------------------------------------------
[Command]
name = "AI1"
command = F, B, B, F, F, B, B, F, F, B, B, F, F, B ;←不用在意这些看得懂看不懂,其实就算你按不出来AI也按得出来,指令越多AI一次性触发的概率就越大
time = 1

[Command]
name = "AI2"
command = U, D, D, U, U, D, D, U, U, D, D, U, U, D
time = 1

[Command]
name = "AI3"
command = D, U, U, D, D, U, U, D, D, U, U, D, D, U
time = 1

[Command]
name = "AI4"
command = B, F, F, B, B, F, F, B, B, F, F, B, B, F
time = 1

[Command]
name = "AI5"
command = a, x, x, a, a, x, x, a, a, x, x, a, a, x
time = 1

[Command]
name = "AI6"
command = b, y, y, b, b, y, y, b, b, y, y, b, b, y
time = 1

[Command]
name = "AI7"
command = c, z, z, c, c, z, z, c, c, z, z, c, c, z
time = 1

[Command]
name = "AI8"
command = x, a, a, x, x, a, a, x, x, a, a, x, x, a
time = 1

[Command]
name = "AI9"
command = y, b, b, y, y, b, b, y, y, b, b, y, y, b
time = 1

[Command]
name = "AI10"
command = z, c, c, z, z, c, c, z, z, c, c, z, z, c
time = 1

[Command]
name = "AI11"
command = F, B, F, B, F, B, F, B, F, B, F, B, F, B
time = 1

[Command]
name = "AI12"
command = U, D, U, D, U, D, U, D, U, D, U, D, U, D
time = 1

[Command]
name = "AI13"
command = D, U, D, U, D, U, D, U, D, U, D, U, D, U
time = 1

[Command]
name = "AI14"
command = B, F, B, F, B, F, B, F, B, F, B, F, B, F
time = 1

[Command]
name = "AI15"
command = a, x, a, x, a, x, a, x, a, x, a, x, a, x
time = 1

[Command]
name = "AI16"
command = b, y, b, y, b, y, b, y, b, y, b, y, b, y
time = 1

[Command]
name = "AI17"
command = c, z, c, z, c, z, c, z, c, z, c, z, c, z
time = 1

[Command]
name = "AI18"
command = x, a, x, a, x, a, x, a, x, a, x, a, x, a
time = 1

[Command]
name = "AI19"
command = y, b, y, b, y, b, y, b, y, b, y, b, y, b
time = 1

[Command]
name = "AI20"
command = z, c, z, c, z, c, z, c, z, c, z, c, z, c
time = 1

[Command]
name = "AI21"
command = F, B, F, B, F, B, F, B, F, B
time = 1

[Command]
name = "AI22"
command = U, D, U, D, U, D, U, D, U, D
time = 1

[Command]
name = "AI23"
command = D, U, D, U, D, U, D, U, D, U
time = 1

[Command]
name = "AI24"
command = B, F, B, F, B, F, B, F, B, F
time = 1

[Command]
name = "AI25"
command = D, U, B, F, D, U, B, F, D
time = 1

然后就在Statedef -1或者Statedef -3下载入一个HELPER,一会HELPER给出(一般不建议在Statedef -2下写,不过很多整合在-2下写AI,当然是整合)

;------------------------------------------------------------------------------
[State -3, AI Helper]
Type = Helper
TriggerAll =!var(59)
Trigger1 =!NumHelper(30000)
Trigger1 =!IsHelper
Trigger1 = RoundState <= 2 && Alive
Trigger1 =!Ctrl && StateNo = 0
helperType = Normal
Name = "AI"
StateNo = 30000
ID = 30000
Pos = 0,0
keyCtrl = 1
PauseMoveTime = 9999999
SuperMoveTime = 9999999
Persistent = 0

接下来是刚才说好的AI HELPER,Statedef 30000

;------------------------------------------------------------------------------
[Statedef 30000]
anim = 0
ctrl = 0

[State 30000, AssertSpecial]
type = AssertSpecial ;这里让玩家无法看见helper
Trigger1 = 1
flag = NoShadow ;无影子
flag2 = invisible ;不可视

[State 30000, NotHitBy]
type = NotHitBy ;为了保证helper在战斗中不受某些类似AOE的影响,给helper写上无敌作为保险项
Trigger1 = 1
value = SCA

[State 30000, 間違いで本体が来たら立ちへ移行]
type = SelfState ;当这个statedef不是helper时转到0,并在statedef 0内写上destroyself,一会给出例子
trigger1 =!ishelper
value = 0

[State 30000, Turn]
type = Turn ;转向,其实没什么太大意义
trigger1 = Facing*ifelse((EnemyNear,Pos X-Pos X)>=0,1,-1) < 0
IgnoreHitPause = 1
supermovetime = 99999999
pausemovetime = 99999999

[State 30000, プレイヤー判定]
type = VarSet ;当玩家按到如下按键时,helper也检测到则关闭AI
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 30000, 立ったら消失]
Type = DestroySelf ;关闭AI后立即消去HELPER,给玩家手操
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 30000, フラグON]
type = VarSet ;AI未启动时如果检测到下列按钮,则触发AI
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

这里有几个command是需要补充的,也列出来

;------------------------------------------------------------------------------
;-| AI Helper |----------------------------------------------------------------
[command]
name = "fwd"
command = F
time = 1

[command]
name = "back"
command = B
time = 1

[command]
name = "up"
command = U
time = 1

[command]
name = "down"
command = D
time = 1

然后就是说好的Statedef 0的举例子,这里Statedef 0不仅代表站立,还可以给helper用作保险消去

;---------------------------------------------------------------------------
; Stand
[Statedef 0]
type = S
physics = S
sprpriority = 0

;分身バグ防止
[State 0, DestroySelf] ;这里是关键,当helper脱离到此状态时,因为helper的属性还是ishelper嘛,所以让helper自动消去,防止一些禁忌多重存在XDDD
type = DestroySelf
trigger1 = IsHelper

[State 0, 残像]
type = AfterImage
trigger1 = time = 0
time = 1

[State 0, 1]
type = ChangeAnim
trigger1 = Anim != 0 && Anim != 5
trigger2 = Anim = 5 && AnimTime = 0 ;Turn anim over
value = 0

[State 0, 2]
type = VelSet
trigger1 = Time = 0
y = 0

[State 0, 3] ;Stop moving if low velocity or 4 ticks pass
type = VelSet
trigger1 = abs(vel x) < 2
trigger2 = Time = 4
x = 0

[State 0, 4] ;Are you dead?
type = ChangeState
trigger1 = !alive
value = 5050

最后在statedef -1或者statedef -3下载入helper(个人一般把command和手操控制全部写在-1,AI全部写在-3,不过其实AI写在-1比较好,但个人只是为了方便查看才这么做的)

;---------------------------------------------------------------------------
; 関係無いステートに行かないように
;---------------------------------------------------------------------------
[State -3, 関係無いステートに行かないように]
Type = ChangeState
Trigger1 = IsHelper(30000)
Trigger1 = StateNo != 30000
Value = 30000

好了,AI顺利载入,嗯,写AI就这么简单,这节课你有没有理解呢?

如果您有什么问题,可以给我私信,我会第一时间给您解答,或者问题发到我的邮箱

mizore@kotori.moe,谢谢大家!
2016.02.2213:42

人物やAI作成公開 草薙京 と クリザリッド KOF99 Custom

C
B
A

配布者 = 白雪みぞれ,AI搭載

草薙京の原作者: JIN氏,クリザリッドの原作者:アフロン氏

感謝します! 制作物のDLは左下の“キャラ公開場所”をご覧ください。

Files Name : Kyo-99.7z ,Krizalid-0.7z

アクセス

オンライン