4:AI製作開始

上記で確定したcommandを含むstateを全て上記で特定した[statedef-3]の下で他のstatedefの上にコピペする。
配置は自由だが、既に記述されている内容の阻害をしないように最下段に挿入するのが望ましい。
また、statedef-3が存在しなかったり、良く分からないなら、[statedef-1]に挿入しても良い
(-2ステートで行っている処理の内容によっては同一フレームにおける-3ステートと-1ステートの状況が異なる場合があるので、
 厳密にAIを作る場合は-1で行動用の記述を組む方が望ましい)。

上記で把握した各種技の特性に合わせてtriggerを設定する。
triggerの詳しい仕組みや内容などは、ググるか和訳カンフーマンを見て把握されたし。

また、元からある条件は遵守すること。そうでなければ技の性能が変わり、改変となるため。
ただし元の条件に含まれているなら、記述そのものを変更して問題は無い。

<注意点>
AIを入れるのはコピペした方のみ。
元記述を直接変更すると、操作出来なくなる可能性が高い。

Before

;高火力、非固定の乱舞技。移動距離は短い。根元から当てないと安い
;三烈カンフー突き手(ゲージレベル1)
[State -1, Triple Kung Fu Palm]
type = ChangeState
value = 3000
triggerall = command = "TripleKFPalm"
triggerall = power >= 1000
trigger1 = statetype = S
trigger1 = ctrl
trigger2 = statetype != A
trigger2 = hitdefattr = SC, NA, SA, HA
trigger2 = stateno != [3000,3050]
trigger2 = movecontact


After

;高火力、非固定の乱舞技。移動距離は短い。根元から当てないと安い
;三烈カンフー突き手(ゲージレベル1)
[State -1, Triple Kung Fu Palm]
type = ChangeState
value = 3000
triggerall = var(59) = 1 && RoundState = 2
triggerall = power >= 1000
triggerall = statetype != A
triggerall = p2statetype != L && P2BodyDist X = [0,60]
trigger1 = ctrl && random<=20 && p2movetype != A
trigger2 = (stateno = [1000,1010]) || stateno = 210
trigger2 = stateno != [3000,3050]
trigger2 = movecontact


  • triggerall:共通条件。これが満たされて無いと起動しない
  • trigger1:基本トリガー。これが無いとエラーが出る
  • trigger2:3、4、5と増やせる
上記の場合カンフーマン(以下KFM)が地上に居て、相手がダウン時以外で、ゲージが足りていて、
ある程度的が近くに居る時に、低確率で発動。
または、カンフー突き手の弱&強や立ち強パンチが相手に当たった(ガード含む)時にキャンセルして発動する。

<内訳>
triggerall
var(59) = 1
AI発動スイッチ。要するにvar(59)の中が「1」の場合。
RoundState =2
戦闘中の意味。これが無いと戦闘終了後も動き続ける。
power >= 1000
パワーゲージが1本以上。つまり1000点以上溜まっている場合。
statetype != A
自分の体勢。空中にいる時以外の場合。ダウン中も含むので注意。
p2statetype != L && P2BodyDist X = [0,60]
相手の体勢。相手がダウン中以外の場合で、さらに、ある程度近く(60pixel以内)にいる場合。

trigger1
ctrl && random<=20 && p2movetype != A
キーコントロール可能な状態(自由行動可能な状態)で、さらに、0~999の乱数が20以下、
さらに、相手が攻撃状態以外の場合。

trigger2
(stateno = [1000,1010]) || stateno = 210
ステート番号1000から1010の間のステートにいる場合、または、ステート番号210にいる場合。
stateno != [3050,3100]
ステート番号3000から3100の間のステートにいる場合以外。
movecontact
攻撃が相手に接触(ガード&ヒット問わず)した場合。

<補足>
  • ステート番号1000~1010に該当するのは「カンフー突き手」の弱と強のみ
  • ステート番号210に該当するのは「立ち強パンチ」のみ
  • ステート番号3000~3050に該当するのは「三烈カンフー突き手」と「スマッシュカンフーアッパー」のみ
  • 「&&」はand。要するに「~と」「~で、~の場合」
  • 「||」はor。要するに「~か」「~、または、~の場合」
  • 「(**&&**)」は括弧。括った範囲のみで答えが処理される
  • 「[*,*]」は「~から~、までの範囲」 ※[~以上,~以下]
  • 「!」は「~以外」付ける位置によって、エラーが出るので注意
  • 「>」や[<]不等号。「~未満(同数は含まない)」または「~超える(同数は含まない)」
  • 「=」イコール。一致した場合。「>=」や「>」などと、適時使い分けること
  • 「<=」や「>=」不等号II。「以下~(同数も含む)」または「~以上(同数も含む)」

<まとめ>
  • triggerall
var(59)が1で、戦闘中で、パワーゲージが1000(1本)以上あり、自分が空中以外にいて、相手がダウン中以外の状態で、さらにある程度近くにいる場合。
  • trigger1
triggerallの条件に加えて、行動可能で、さらに乱数が指定した数値の範囲内の場合のみ、
valueのステートにジャンプ(移動)する(要するに技が発動する)。
  • trigger2
triggerallの条件に加えて、カンフー突き手(弱&強)、もしくは立ち強パンチが相手に接触した場合で自分が「スマッシュカンフーアッパー」を出していない時に、
現在の行動を中断してvalueのステートにジャンプする(要するに特定の行動をキャンセルして、技が発動する)。


既にお気付きかと思われるが、実は、

trigger2 = stateno != [3000,3050]

は、元の条件の、

trigger2 = hitdefattr = SC, NA, SA, HA

だと「スマッシュカンフーアッパー」や「三烈カンフー突き手」も条件に含まれるために、それを除外するために記述されたtriggerである。

故に元の条件から、

trigger2 = (stateno = [1000,1010]) || stateno = 210

に変えた時点で不要となっている。
要するに削除しても問題ないのだ(しなくても不具合は無い)。

また、ステートの1000、1010、210は全て、

trigger2 = hitdefattr = SC, NA, SA, HA

に含まれているため、「元の技の条件から外れないこと」という前提条件は崩れていない。

<注意点>
triggerallの記述は全てに適用される。
故にゲージ消費や繰り出せる姿勢などは、ここに記述される場合が多い。
また、ctrlをここに記述するとキャンセル出来なくなる
(state実行中は殆どの場合、ctrlが0。要するにコントロール不能状態のため)。

!や><を記述する位置は=の左側。
「!=」や「>=」などと記述。逆だとエラーになりやすい(例外あり)。

「[*,*]」を用いた場合、その後に何か記述するとエラーになる。ただし「()」で括れば大丈夫。
また、【】は「=」とのみ併用する事(ただし「!=」は問題無い)。

trigger1 = stateno = [1000,1010] || stateno = 210

だとエラー。

trigger1 = (stateno = [1000,1010]) || stateno = 210

や、

trigger1 = stateno = 210 || stateno = [1000,1010]

だと大丈夫。

また、trigger2は乱数を入れていないため、条件を満たすと100%発動する。
これが強すぎると判断するなら、

trigger2 = (stateno = [1000,1010]) || stateno = 210
trigger2 = stateno != [3050,3100]
trigger2 = movecontact && random <=400

に書き換えたり、

trigger2 = (stateno = [1000,1010]) || stateno = 210
trigger2 = stateno != [3050,3100]
trigger2 = movecontact
trigger2 = random <= 400

などと追記すれば良い。

Before

;立ち強パンチ
[State -1, Stand Strong Punch]
type = ChangeState
value = 210
triggerall = command = "y"
triggerall = command != "holddown"
trigger1 = statetype = S
trigger1 = ctrl
trigger2 = (stateno = 200) && time > 5 ; 「 && 」は両方が同時に成立( and )する時の意味です
trigger3 = (stateno = 230) && time > 6


after

;判定は並。リーチは短め。出は速め
;立ち強パンチ
[State -1, Stand Strong Punch]
type = ChangeState
value = 210
triggerall = var(59) = 1 && RoundState = 2
triggerall = statetype != A
triggerall = p2bodydist X <=30
trigger1 = ctrl && p2movetype != A && (p2statetype = S || p2statetype = A)
trigger2 = (stateno = 200) && time > 5
trigger3 = (stateno = 230) && time > 6


上記の場合、KFMが地上に居て、行動可能で、相手が近くで立っているか浮いている時に強パンチを繰り出す。
または、同条件で立ち弱パンチ、または立ち弱キックを出していたら、それをキャンセルして強パンチを繰り出す。

<内訳>
triggerall
var(59) = 1 && RoundState =2
AI発動スイッチ。要するにvar(59)の中が「1」の時で、戦闘中の場合。
statetype != A
自分の状態が空中以外。Sから変更した理由は、そのままだと屈み状態では反応しないため
(ただし、屈み状態から立ち状態に移行するのに異様に時間がかかるキャラならSのままにすること)。
p2bodydist X <=30
相手と自分の距離が(ぶつかり判定の位置から)30pixel以内の場合。
<=で指定しているので、飛び越されるなどして後ろに回られた場合でも、振り向くまでは条件が満たされるので注意。

trigger1
ctrl && p2movetype != A && (p2statetype = S || p2statetype = A)
キーコントロール可能な状態(自由行動可能な状態)で、相手が立ち、または屈み状態の場合。

trigger2
(stateno = 200) && time > 5
ステート番号200にいる状態で、5フレームを超えて経過している場合。

trigger3
(stateno = 230) && time > 6
ステート番号230にいる状態で、6フレームを超えて経過している場合。

<補足>
  • stateno200に該当するのは立ち弱パンチのみ
  • stateno230に該当するのは立ち弱キックのみ
  • (p2statetype = S || p2statetype = A)とstatetype != A は似て非なる条件(後者は「L」。即ちダウン状態も含むため)。
    ただし、ctrlなどと併記している場合、ダウン中はctrl=0なので成立しないため、実質前者と同じ扱いとなる。
    また、statenoと併用する場合も、該当するstatenoに自分の状態が指定されているなら、実質前者と同じ扱いとなる。

<まとめ>
  • triggerall
AIが発動していて、戦闘中で、自分が地上にいて、敵が近くに居た場合。
  • trigger1
triggerallの条件に加えて、自分が行動可能で、さらに敵が攻撃状態以外で、立ち、または空中にいる場合。
  • trigger2
triggerallの条件に加えて、立ち弱パンチのモーション中で、モーションに入ってから4フレーム以上経過している場合。
  • trigger3
triggerallの条件に加えて、立ち弱キックのモーション中で、モーションに入ってから5フレーム以上経過している場合。

この場合、trigger2と3には、敵の状態やヒットの有無が条件に含まれてないため、
このままだと弱パンチ&キックの最中に敵が近くに居たら、敵がダウンしていても立ち強パンチを繰り出す。
さらにrandomなどの乱数を条件に入れていないので、100%発動する。
また、trigger1も同様に乱数を入れていないため、100%発動する。

このままでも大きな問題は無いが、これだとパターン化しやすいので、

;判定は並。リーチは短め。出は速め
;立ち強パンチ
[State -1, Stand Strong Punch]
type = ChangeState
value = 210
triggerall = var(59) = 1 && RoundState = 2
triggerall = statetype != A
triggerall = p2bodydist X <=30 && random <=700
trigger1 = ctrl && p2movetype != A && (p2statetype = S || p2statetype = A)
trigger2 = (stateno = 200) && time > 5
trigger3 = (stateno = 230) && time > 6

または、

;判定は並。リーチは短め。出は速め
;立ち強パンチ
[State -1, Stand Strong Punch]
type = ChangeState
value = 210
triggerall = var(59) = 1 && RoundState = 2
triggerall = statetype != A
triggerall = p2bodydist X <=30
trigger1 = ctrl && random <=400 && p2movetype != A && (p2statetype = S || p2statetype = A)
trigger2 = (stateno = 200) && time > 5 && random <=700
trigger3 = (stateno = 230) && time > 6 && random <=300

として、発動率を調整すると良い。
特に後者の場合、trigger毎に発動率を微調整できるので、コンボのパターン化けを避けられる。

さらに発展系として、

;判定は並。リーチは短め。出は速め
;立ち強パンチ
[State -1, Stand Strong Punch]
type = ChangeState
value = 210
triggerall = var(59) = 1 && RoundState = 2
triggerall = statetype != A
triggerall = p2bodydist X <=30
trigger1 = ctrl && random <=400 && p2movetype != A && (p2statetype = S || p2statetype = A)
trigger2 = (stateno = 200) && time > 5 && random <=700 && MoveHit
trigger3 = (stateno = 200) && time > 5 && random <=200 && !MoveHit
trigger4 = (stateno = 230) && time > 6 && random <=300

として、立ち弱パンチ攻撃がヒットした時は高確率で、逆に外した時やガードされた時は低確率で、立ち強パンチに繋げるようにできる。

<注意点>
(stateno = 200)などの「()」は、(stateno = [**,**])からコピペした時の名残と思われる。
よって、外しても外さなくても問題無い。
timeの単位はフレーム。ステートが変わる度にリセットされ0に戻る。
MoveHitは攻撃がヒットした場合を意味する。
逆に、!MoveHitは攻撃が当たらなかった場合を意味する(結果的に、外れたり、ガードされたりなどをした場合となる)。
MoveHitを使うならtimeは本来不要だが、元の技のキャンセル条件に含まれているため、削除せずそのまま使用すること
(削除すると技の性能の改変となるため)。


最後に動作を確認し、問題が泣ければ完成 \(^o^)/

<注意点>
動作チェックの時は、var(59)は常に1になるようにしておく。

[State -1, ai]
type = varset
triggerall = 1;var(59) = 0
trigger1 = Command = "AI0"
trigger2 = Command = "AI1"
    ~中略~
trigger50 = Command = "AI49"
trigger51 = Command = "AI50"
var(59) = 1

など。triggerの「1」は無条件に条件を満たしている状態を表す。
関係無いcommandが出ないように、確認したい技以外を一時的に封印しておくのも良い。


triggerall = var(59) = 1 && RoundState = 2

を、

triggerall = var(59) = 0 && RoundState = 2

にすれば、AI起動時に使わなく(使えなく)なる。


<前へ 4:AIトリガーの設定 次へ>
最終更新:2023年06月05日 01:58