上記で確定したcommandを含むstateを全て上記で特定した[statedef-3]の下で他のstatedefの上にコピペする 配置は自由だが、すでに記述されてる内容の阻害をしないように最下段に挿入するのが望ましい また、statedef-3が存在しなかったり、良く分からないなら、[statedef-1]に挿入しても良い (-2ステートで行っている処理の内容によっては同一フレームにおける-3ステートと-1ステートの状況が異なる場合があるので、厳密にAIを作る場合は-1で行動用の記述を組む方が望ましい) //(AIには-3の方が向いているが、個人的には-1で問題ないと思う) 上記で把握した各種技の特性に合わせてtriggerを設定する (triggerの詳しい仕組みや内容などは、ググるか、和訳KFMを見れば把握できるので、ガンガレ) また、元からある条件は遵守すること。じゃないと技の性能が変わり、改変となるため ただし、元の条件に含まれているなら、記述そのものを変更して問題は無い <注意点> 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。ようするに「~か」「~、または、~の場合」 「(**&&**)」は括弧。括った範囲のみで答えが処理される 「[*,*]」は「~から~、までの範囲」 ※[~以上,~以下] 「!」は「~以外」付ける位置によって、エラーが出るので注意 「>」や[<]不等号。「~未満(同数は含まない)」または「~超える(同数は含まない)」 「=」イコール。一致した場合。「>=」や「>」などと、適時使い分けること 「<=」や「>=」不等号Ⅱ。「以下~(同数も含む)」または「~以上(同数も含む)」 <まとめ> 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。ようするにコントロール不能状態のため) !や><を記述する位置は=の左側 「!=」や「>=」などと記述。逆だとエラーになりやすい(例外あり) 「[*,*]」を用いた場合、その後に何か記述するとエラーになる。ただし「()」で括れば大丈夫 また、【】は「=」とのみ併用する事(ただし、「!=」は、おk) ---------- 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起動時に使わなく(使えなく)なる ---- [[<前へ>3:技特性とstatenoのチェック]] 4:AIトリガーの設定 [[次へ>>5:良く使われるトリガー]]