MUGEN ( フォント環境:MS ゴシック 標準 サイズ10 )    AI用ヘルパーに関してのメモ (byADI) 6:57 2016/11/19 HelperのInGuardDist補助の説明文の間違いを修正→-100 +100が反対だった。 22:59 2011/10/31 movetype=Aの時の処理順 21:48 2011/09/16 いまさら追記 23:04 2011/07/09 DestroySelfバグを追記 0:44 2011/01/07 処理順番に関するところへ追記 18:28 2010/09/27 PalNo 22:23 2010/09/20 ヘルパーの順番に関する話 11:03 2010/09/09 KeyCtrl=1→Ctrl=1 0:48 2010/09/09 イントロ飛ばしで 2:55 2010/06/23 109 16:31 2010/05/22 ちょい 14:11 2010/05/10 対飛び道具の案 19:25 2010/04/22 対めくり用を応用した対飛び道具 21:51 2010/04/20 対めくり用InGuardDist補助 を。 19:48 2010/03/27 リダイレクトのことをちょっと 06:21 2010/01/31 10:36 2009/10/15 再修正。これでいいけど、別にヘルパーである必要が無い・・・。 8:22 2009/10/15 距離記録装置の確認+修正 22:01 2009/10/08 ちょいちょい。 2:14 2009/10/08 メモ。 いわゆるwin版基準  特殊な動作を行う飛び道具やエフェクトなどに使われているヘルパー。  そうした使用方法が基本だが、AIにも使われることがある。  主に本体だけでは出来ない事を行うのがヘルパーの役目になる。  なおこれらは、Cns記述に慣れていないのであれば手を出すべきでない。   基本を知っていてこそ、使っていいものである。  ■■■ヘルパーの性質 ■簡単な説明  本体とは別に、本体とほぼ同じようなものを出せるのがヘルパー。合計数に上限あり。  本体と同じようにステート番号を設定でき、その設定された番号のステートを処理する。   ヘルパーの制御はヘルパー専用のステートを作り、そこに制御記述を行う。  座標位置からVarなど、本体とは別に持っているので、   座標を動かしてInGuardDistを本体の座標以外で調べたり、   Varを本体とは別に100個分持たせたりすることもできます。 ■射出と数  ヘルパーは、Type=Helperによって射出され、ラウンドの終了まで存在することができ、   Type=DestroySelfによって消すことも可能である。  ※ただしイントロ中(RoundState<2)に射出されたHelperは、    イントロが飛ばされる(ボタンなどが押されて強制的に試合がはじまる)と消えます。  ※NumHelper(**)=0の条件であれば、無いのを感知して再度射出しますが。  また、ヘルパーはMUGENによって上限数が決められており、   MUGENのコンフィグによって調節はできるが、最大合計56個までしか存在できない。  上限の数までヘルパーが存在する時に、Type=Helperを行ってもヘルパーは出現しない。  しかも、この56個は「全てのプレイヤーの出したヘルパー」であり、   1対1の場合は28個ずつ使えるが、タッグ対タッグの場合は一人あたり14個である。  それも、あくまで設定を最大値にした場合のみであって、   ヘルパーの上限が少ない場合、それよりも少ない数に限定されてしまう。  その為、ヘルパーを一切使わないキャラでも5つ程度まで、   ヘルパーを大量に使うキャラであれば1、2つに限定し、可能であれば使わないこと。  限界に達してしまうのは、他のキャラの迷惑となるので注意しよう。 ■射出方法・参照  ttp://homotaro.s44.xrea.com/scr2.htm  のHelperの項を参照 しながら一応書いておく。 [State a] Type = Helper ;命令:ヘルパー射出 Trigger1 = *適当な条件*; Trigger1 = !NumHelper(**) ;射出制限(自分の出したヘルパーID,**のヘルパーが0である。) ;◇ヘルパータイプ HelperType = Normal ;基本(省略時):Normal (基本使わない擬似プレイヤー:Player) ; ここをPlayerにすると、相手がP2で反応するようになり、また自身の-2,-3ステートを読み込むようになる。 ;◇キーコントロール KeyCtrl = 0 ;基本(省略時):0(無し) (特殊な場合にしか使わない あり:1) ;ここを1にするとCtrl=1の状態で射出される。(ステートですぐ変更は可能) ;またCtrl状態では基本動作を受け付け、-1ステートを読み込むようになる(基本使わない) ;◇ヘルパー基本情報 Name = "ヘルパー名" ;ヘルパーの名前を指定。(省略時 "*親の名前*'S HELPER"らしい) ID = *ヘルパーID* ;ヘルパーのIDを数値で指定。(省略時0 ※ヘルパーIDは参照時に使う為AIには必須。) ;◇出現情報 Pos = *X座標*,*Y座標*;出現位置を指定(省略時は0,0) Xは正方向が+ Yは下が+上が-。 PosType = *基準位置* ;Posの基準位置を指定。下の表参照(省略時P1) ; P1 ;自分の位置 向いている方が正方向。 ; P2 ;直近の位置 相手の向いている方が正方向。 ; Front ;向いている方向画面端 向いている方が正方向 ; Back ;向いている方と反対の画面端 向いている方が正方向 ; Left ;画面左端 右が正方向 ; Right ;画面右端 右が正方向 Facing = *向き* ;正1 逆-1 の方向。PosTypeに準拠。 StateNo = *ステート番号* ;読み込ませるステート OwnPal = *独自パレットフラグ* ;0で親と共通。1で独自パレット。AI用の場合あまり関係ないが。 ;◇時間停止の無視可能時間(省略時:0 AI用の場合はとても大きい数を指定) SuperMoveTime = 999999999 ;SuperPause中に動ける時間 PauseMoveTime = 999999999 ;Pause中に動ける時間 ;◇ヘルパーサイズ(省略時・本体準拠? AI用の場合ほぼ必要なし) Size.XScale = 横縮尺 Size.YScale = 縦 Size.Proj.DoScale = Proj縮尺 Size.Ground.Back = 後ろ衝突判定 Size.Ground.Front = 前衝突判定 Size.Air.Back = 空中後ろ衝突判定 Size.Air.Front = 空中前衝突判定 Size.Height = 衝突高さ判定 Size.Head.Pos = 頭の位置 Size.Mid.Pos = 体の中心の位置 Size.ShadowOffset =影の位置 ;本体の設定時と同様。ちなみに衝突判定を行わせる場合PlayerPushも必要。 ;◇最低限の記述ではこんな感じ。 [State a] Type = Helper ; Trigger1 = *適当な条件*; Trigger1 = !NumHelper(**) ;射出制限 ID = *ヘルパーID* ;ヘルパーのID Pos = 0,-1000; StateNo = *ステート番号* ; OwnPal = 1 Size.XScale = 0 Size.YScale = 0 SuperMoveTime = 999999999 ;SuperPause中に動ける時間 PauseMoveTime = 999999999 ;Pause中に動ける時間   参照方法  NumHelper(*ヘルパーID*) 出したヘルパーの数を参照  Helper(*ヘルパーID*), 出したヘルパーへのリダイレクト。  ● Helper(**),を使う場合、その前の行でNumHelper(**)を必ず用いること。 ●  ( ※デバッグを表示したとき、エラーを出さない為。 )  これらは自ら出したヘルパーのみ参照可能で、相手などのヘルパーは不可。  自分が出したヘルパーの出したヘルパー(本体→ヘルパー→ヘルパー)であれば、   自分の出したヘルパーとNumHelper(**)とHelper(**)は同様。 ( そのヘルパーからのRoot Parentは若干異なるが。 )  また自分が出した同じヘルパーIDのヘルパーが複数いる場合、   どのヘルパーを参照するかは選べず、1つだけ勝手に選ばれます。  その為、ヘルパーIDはそれぞれ異なるようにすること。  ※補足 HelperType = player は基本的な敵への動作(振り向き)とP2***の情報に反応するようになる。  だが、NumEnemyやEnemy,などP2以外の方法では一切反応しない。NumPartnerも同様。  またHelperType=Playerでも、ヘルパーがStateNo=5150なら反応しない。 ( 5150で反応しないのは、通常のプレイヤーキャラも同様。ちなみにState,5150は「死亡ステート」 ) ■ヘルパーの変数管理  ヘルパーはプレイヤーと同じように計100スロット(Var60,Fvar40)の変数スロットを持っている。  Type=VarSetなどは、自身が保有する変数を変更し、  Type=ParentVarSetなどで、親が保有している変数を変更することができる。  AI用ヘルパーはまずこれの為にあるといっても過言ではないかもしれない。  InGuardDistの補助だけであればいらないのだが、   PosAddとVarの使いようでより広い範囲のGuardDistを判定できる為、いわば使いよう。 ■射出管理  AIに使うヘルパーはそれ専用のステートで管理することとなるが、   ステートの記述はステートの基本と同じである為、その為の知識は必須。  状況に応じてステートをかえることもありうるが、基本は一つのステートだろう。 ;◇AI用ヘルパー先頭記述 [Statedef ****];****は他のステートと重複しない数値。(ステートファイルに[StateDef ****]で検索をかければいい。) Type = A ;ステートタイプ*必須記述* 影響は無い為何でも良い MoveType = I ;ムーブタイプ 一応しらふ。 Physics = N ;摩擦・重力状態 一応無影響。 Ctrl = 0 ;コントロール 一応0。 Anim = 0 ;アニメーション番号・0でもいいが、当たり判定・攻撃判定のないもの SprPriority = -5 ;スプライト優先度 一応-5 [State a, AssertSpecial];特殊処理 Type = AssertSpecial Trigger1 = 1 flag = Invisible ;インヴィシブル 見えなくする。 flag2 = Noshadow ;ノーシャドウ 影を表示しない。 ignorehitpause=1 ;ヒットポーズ影響無し。 [State a, NotHitBy];攻撃に当たらないよう。 Type = NotHitBy Value = SCA Trigger1 = 1 IgnoreHitPause = 1 ;◇ここまで  こんな感じで始めておくと、見えない+当たらない為、   AI用ヘルパーは見えないし他へ干渉しなくなる、はず。  そのステートにいなければその処理を行わないが、   そのステートにいれば毎フレーム処理を行うという感じである。  記述方法は-3ステートや-1ステートと同様。上から順に、です。  ただしChangeStateを行っても、変化するのはヘルパー自身のステートですので注意。  反対に言えばChangeStateで別の処理欄にいく、という事も可能ですし、   同じステートを何度か繰り返す、といった処理も可能です。 ( ループからしばらく出られない場合はエラーを返しますが )  注意点は、プレイヤー達のステート処理→ヘルパー達のステート処理であること。  その為、そのフレーム内の1P2P3P4Pの処理を監視することはできますが、   それをそのフレーム内で本体の行動に反映することはできません。  ○ -3,-2,-1ステートのまとめ ○ -1 KeyCtrl=1 状態で自身のステート内常時。 -2 Type=Player で常時。相手のステート内でも参照。 -3 Type=Player で自身のステート内常時。  参照の順番は-3,-2,-1,現在のステート。 ( -3,-2でChangeStateを行ってもStateNoが変化しているだけ )  AIだけの制作であれば使いません。使いませんが。 ■ヘルパーからのリダイレクト  Parent, :ヘルパーから呼び出した親へのリダイレクト  Root,  :ヘルパーから本体へのリダイレクト   本体から呼び出したヘルパーであれば違いはありません。   ヘルパーから呼び出されたヘルパーではParent,が異なります。  PlayerID(***),:指定したIDの特定ユニットへのリダイレクト   本体が、戦っている相手のIDをVarに記録し、   PlayerID(root,Var(**)),で、その相手へリダイレクト可能。  Enemy,   :本体からのEnemy,と変わらず。  EnemyNear, :Helperの座標からのEnemyNear,。  Helper(***),:本体からのHelper(***),と変わらず。  Target(***),:Helper自身のTargetしか認識しません。 ■10/09/20追記■ヘルパーの順番に関する話。  全てのユニットにはID番号とは別に「ユニット番号」が割り振られています。  デバッグ表示にあるName ID (x)←この()内の数値がユニット番号であり、   この数値が少ないほうから処理が行われるのですが、   「ユニット番号は割り振られてから変化することがない」ため   ユニット番号が空白になることも、そこに新しいユニットが割り振られることも。  分かりやすく説明すると   ABCという順番でヘルパーを射出した後、ヘルパーAが消失(DestroySelf)すると、   ・BCという状態になり、その状態で新しいヘルパーDが射出されると、   DBCという風にAの空白へDが割り振られ、DBCの順番で処理が行われます。  「同一ユニットが同一フレーム内で複数のヘルパーを射出」した場合は、   必ず射出した(記述されている)順番で処理されるのですが、  異なるユニット、また時間をおいたフレームで射出した場合、   その前よりも射出したヘルパーより先に処理される可能が出ます。  ▲11/01/07追記※射出した時点フレームでは、   最初のほうに射出したヘルパーの処理が飛ばされる可能性がありそうです。   理由:「・BC」の例で、CからDEFを射出した場合、      「DBCEF」という風になりCの次の処理はDでなくEになるかと。  ですのでヘルパー同士の間で処理の順番を確実にしたい場合は、   同じユニットから同じフレーム内で(同時に)射出しましょう。  ▲11/09/16追記※MoveTypeによって処理の順番が変化する可能性があるみたいです。よくわからん。。。  ▲11/10/31追記※Movetype=Aだと処理順が先の方になるみたい。つまり   「フレーム開始時にMovetype=Aのユニット達→Movetype!=Aのユニット達」という順番、かな。 ■10/09/27追記■PalNoなどの情報  HelperからPalNoを参照すると本体と同じ番号ではなく1を返します。 ■11/07/09追記■DestroySelfによる強制終了バグについて  ヘルパーはステートコントローラー「DestroySelf」で自分を消去できますが、   ChangeStateなどとは違い「その後の命令を読み込む」性質を持っています。  その上「DestroySelf(自分を消す)」の命令を出したフレームで   「Helper」の命令を出すと、エラーメッセージの出ない強制終了が発生するようです。   「Helper」の後に「DestroySelf」なら、問題ないようですが。  なので、「DestroySelf」の記述は一番最後へ置くようにすること。  ※「DestroySelf」をした後「ChangeState」して「Helper」を射出してもアウト。 ■■■■■使い方  色々と使い方はあります。  Var増設以外の使い道として例えば、  本体の後ろ側に置きInGuardDistの行き届かない   後ろ側への攻撃に対応するといった簡単な事から、  記憶システムなどの複雑な情報を必要とすることなど。   様々です。 ;2〜3つ以上のステートを記憶すること+PrevStateNoに頼らないようにする為。 ;■■■StateNoの記憶。 ;Helper(**),Var(21) ;直前〜現在 ;Helper(**),Var(22) ;一つ前 ;Helper(**),Var(23) ;二つ前 [State xxxx, Rec-StateNo] Type = Null TriggerAll = Var(22) != Root,StateNo ;重複回避+更新タイミング感知 TriggerAll = Root,Time = 1 ; Trigger1 = 0&& Var(23) := Var(22) ;2番目を3番目に Trigger2 = 0&& Var(22) := Var(21) ;1番目を2番目に Trigger3 = 0&& Var(21) := Root,StateNo ;1番目を上書き IgnoreHitPause = 1 ;■ 確認済み ■ ※1F分反応は遅れる。 ;■■■対めくり用InGuardDist補助 ;開始状態条件・無し ;終了状態・本体と同じ向き。Pos Xが本体と重なる。 ;Helper(**),Var(40) = Pos X+100のInGuardDist ;Helper(**),Var(41) = Pos X-100のInGuardDist ; ※主にInGuardDistと複合して使います。 ;■ここから [State xxxx, Turn];振り向き Type = turn Trigger1 = Facing != root,Facing ;本体と異なる向きなら [State xxxx, Posset in Root];座標Xを本体にあわせる Type = Posset Trigger1 = 1 X = Root,Pos X [State xxxx, Posadd 100];座標+100(本体から+100へずらす) Type = Posadd Trigger1 = 1 X = 100 [State xxxx, Front GuardDist varset];前側のInGuardDistを代入 Type = Varset var(40) = InGuardDist Trigger1 = 1 [State xxxx, Posadd -200];座標-200(本体から-100へずらす) Type = Posadd Trigger1 = 1 X = -200 [State xxxx, Back GuardDist varset];後ろ側のInGuardDistを代入 Type = Varset var(41) = InGuardDist Trigger1 = 1 [State xxxx, Posadd 100];座標+100(本体と同座標にもどす) Type = Posadd Trigger1 = 1 X = 100 ;■ここまで ;■本体側の記述■ TriggerAll = InGuardDist ;この条件を ↓ TriggerAll = NumHelper(xxxx) ;ヘルパーの有無を確認 TriggerAll = InGuardDist || ( (Helper(**),Var(40)) && (EnemyNear,P2Dist X<0) ) || (Helper(**),Var(41)) ;InGuardDist(+Var補助) ;Var(40)の条件は「相手の相手が後ろ側(相手が自分からみて後ろ向き)+前側のInGuardDistに引っかかる状態」 ; めくりに対して振り向いた状態への対応に限定する為( [ x 【←]敵←自】 [AttackDist]【当たり判定】) ; めくりへ適度に引っかからせる場合は、EnemyNear,P2Dist X<0の場合にガードの確率を下げるなど。 ;なおより早くからInGuardDistを察知させたいのであれば、EnemyNear,P2Dist X不要。 ;ちなみにParentVarsetで本体のVarをセットすれば、ヘルパー数を確認する必要は無い。 ;>対飛び道具の情報として ; 実はこの情報を使うことで、単発の飛び道具はある程度感知することが可能。 ;( P2Dist X > 100 && InGuardDist && !(前側のInGuardDist) )こう記述することで、 ; 「  敵 | [● 自]  」 |←前方InGuardDistライン ●弾 [AttackDist] ; 上の図のような状態を確認できる。つまり、 ;  相手が遠いのに、前側のInGuardDistに引っかからずInGuardDistになってるので ;  前側のInGuardDistよりも近くに、InGuardDistを発生させるものが存在する、という事。 ; 勿論、弾速などは分からない為、確実とは言えないが、 ;  P2MoveType!=A && InGuardDistよりも距離を感知している分、 ;  飛び道具反射技などに使いやすくなる。 ;■※ 未確認 ※■ ; もっと確実な飛び道具感知方法の案としては、 ; InGuadDistが前進することを前提にInGuardDistの切っ先を測定し、 ;  次のフレームでどの程度前進しているのかを再判定させるとか。 ; もちろんそれだけだと1F分の速度しか分からないから加速に対応できないし、 ;  相手の状態をしっかりと認識してやらないと意味が無い。 ;■ 確認済 ■ ※1F分不正確 ;[VarDist.txt]に本体で計算する方式を記述してあります。 ;■■■対タッグ時、両プレイヤーBodyDist確認 + タッグ時パートナーDist確認 ;開始状態条件・無し ; ※記録数値は1F分遅れてしまう為、その分速度で補整を加えているが、Pos式の移動は感知不可※ ;Helper(**),Var(10) = Enemy0 BodyDist X  ※P2BodyDistと異なり、これらはそれぞれ特定の相手に順ずる。 ;Helper(**),Var(11) = Enemy0 BodyDist Y  ※ P2BodyDist X = Helper(**),Var(10)などで相手を確認すること。 ;Helper(**),Var(12) = Enemy1 BodyDist X いなければ「999999999」 ;Helper(**),Var(13) = Enemy1 BodyDist Y 同上 ;Helper(**),Var(14) = Partner Dist X  .同上 ;Helper(**),Var(15) = Partner Dist Y  .同上 ;終了状態・本体と反対向き。相手と同座標。いるなら二人目の同座標。いるならパートナーの同座標。 ;■ここから [State xxxx, turn];振り向き処理(RootDist-(a) = BodyDist にする為、向きは本体と反対に) Type = Turn Trigger1 = Root,Facing=Facing ;同じ場合振り向く。 [State xxxx, Enemy0 PosSet];1人目の相手 Type = PosSet;座標指定移動 Trigger1 = 1;無条件真 X = Enemy(0),Pos X ;座標Xを一人目の相手の座標Xに Y = Root,Pos Y*2-(Enemy(0),Pos Y) ;自分の座標*2から座標Yを一人目の相手の-(座標Y)に(代入の為に+-を反転) [State xxxx, Enemy0 DistSet] Type = Null; Varset TriggerAll = 1 || Var(11):=Floor(RootDist Y+Enemy(0),Vel Y+Root,Vel Y);セット Trigger1 = 0 && Var(10):=IfElse(RootDist X >= 0, Floor(Root,const(Size.Ground.front)-(Root,Vel X)), Floor(Root,const(Size.Ground.back)+(Root,Vel X))) Trigger2 = Root,StateType = A ;基本地上・空中なら空中のものを。 Trigger2 = 0 && Var(10):=IfElse(RootDist X >= 0, Floor(Root,const(Size.air.front)-(Root,Vel X)), Floor(Root,const(Size.air.back)+(Root,Vel X)) ) ; 本体が前ならFront 後ろならBackになる判断式。 Trigger3 = Enemy(0),StateType!=A;地上なら地上 Trigger3 = 0 && Var(10):=Var(10)+IfElse(!(Enemy(0),Facing!=Facing ^^ RootDist X<0), Floor(Enemy(0),const(Size.Ground.front)+(Enemy(0),Vel X)), Floor(Enemy(0),const(Size.Ground.back)-(Enemy(0),Vel X)) ) Trigger4 = Enemy(0),StateType=A;空中なら空中 Trigger4 = 0 && Var(10):=Var(10)+IfElse(!(Enemy(0),Facing!=Facing ^^ RootDist X<0), Floor(Enemy(0),const(Size.air.front)+(Enemy(0),Vel X)), Floor(Enemy(0),const(Size.air.back)-(Enemy(0),Vel X)) ); 本体が後ろ・向きが異なる、どちらかだけならBack、そうでなければFront。 Trigger5 = 1 || Var(10):=Var(10)*IfElse(RootDist X<0,1, -1);前なら+ 後ろなら− Trigger5 = 1 || Var(10):=Floor(RootDist X+Var(10));セット [State xxxx, Enemy1 PosSet];2人目の相手 Type = PosSet;座標指定移動 Trigger1 = NumEnemy > 1;相手が二人以上 X = Enemy(1),Pos X ;座標Xを二人目の相手の座標Xに Y = Root,Pos Y*2-(Enemy(1),Pos Y) ;自分の座標*2から座標Yを二人目の相手の-(座標Y)に(代入の為に+-を反転) [State xxxx, Enemy1 DistSet] Type = Null; Varset TriggerAll = NumEnemy > 1;相手が二人以上 TriggerAll = 1 || Var(13):=Floor(RootDist Y+Enemy(1),Vel Y+Root,Vel Y);セット Trigger1 = 0 && Var(12):=IfElse(RootDist X >= 0, Floor(Root,const(Size.Ground.front)-(Root,Vel X)), Floor(Root,const(Size.Ground.back)+(Root,Vel X))) Trigger2 = Root,StateType = A ;基本地上・空中なら空中のものを。 Trigger2 = 0 && Var(12):=IfElse(RootDist X >= 0, Floor(Root,const(Size.air.front)-(Root,Vel X)), Floor(Root,const(Size.air.back)+(Root,Vel X)) ) ; 本体が前ならFront 後ろならBackになる判断式。 Trigger3 = Enemy(1),StateType!=A;地上なら地上 Trigger3 = 0 && Var(12):=Var(12)+IfElse(!(Enemy(1),Facing!=Facing ^^ RootDist X<0), Floor(Enemy(1),const(Size.Ground.front)+(Enemy(1),Vel X)), Floor(Enemy(1),const(Size.Ground.back)-(Enemy(1),Vel X)) ) Trigger4 = Enemy(1),StateType=A;空中なら空中 Trigger4 = 0 && Var(12):=Var(12)+IfElse(!(Enemy(1),Facing!=Facing ^^ RootDist X<0), Floor(Enemy(1),const(Size.air.front)+(Enemy(1),Vel X)), Floor(Enemy(1),const(Size.air.back)-(Enemy(1),Vel X)) ); 本体が後ろ・向きが異なる、どちらかだけならBack、そうでなければFront。 Trigger5 = 1 || Var(12):=Var(12)*IfElse(RootDist X<0,1, -1);前なら− 後ろなら+ Trigger5 = 1 || Var(12):=Floor(RootDist X+Var(12));セット [State xxxx, Enemy1 nore] Type = Null TriggerAll = NumEnemy = 1;相手が一人の場合 Trigger1 = Var(12):= Var(13):= 999999999;無し [State xxxx, Partner PosSet];パートナー Type = PosSet;座標指定移動 Trigger1 = NumPartner;パートナーがいる X = Partner,Pos X ;座標Xをパートナーの座標Xに Y = Root,Pos Y*2-(Partner,Pos Y) ;自分の座標*2から座標Yをパートナーの-(座標Y)に(代入の為に+-を反転) [State xxxx, Partner DistSet] Type = Null; Varset TriggerAll = NumPartner;パートナーがいる Trigger1 = 1 || Var(15):=Floor(RootDist Y) || Var(14):=Floor(RootDist X);座標記録 [State xxxx, Enemy1 nore] Type = Null TriggerAll = NumPartner = 0;パートナーがいない場合 Trigger1 = Var(14):= Var(15):= 999999999;無し ;■ここまで  ・解説・ 前提:PosSetを行った場合、座標はその処理時点で移動している為、     >1フレーム内でPosSet→処理→PosSet→処理ということが可能。 情報:・RootDistによってヘルパーから自分への距離は計ることが出来る。     >PosSetによって相手の座標を参考に座標を設定しRootDistで取得する。      >本体と異なる向きにすれば、Xは前なら+、後ろ側なら−とできる。      >「本体のY座標*2−相手のY座標」という計算式で、Y相手が上側で−、本体が上側で+となる。       >*2は本体の高さの分もある為、相対座標が「本体のY座標-相手のY座標」ということ。       >Y座標を相手のY座標分減らすことで、本体より上なら、本体より低い座標になる。    ・Const(Size.***.***)によってBodyDistで差し引かれる量を計算できる。     >Root,StateType=AでRoot,Const(Size.Air.***) それ以外でRoot,Const(Size.Ground.***)。     >RootDist X >= 0でRoot,Const(Size.***.Front) <0でRoot,Const(Size.***.Back)     >本体と異なる向きに向かせておき、!(Enemy(1),Facing!=Facing ^^ RootDist X<0)を用いて、      >本体が後ろ側・向きが異なる(本体と同じ向き)のどちらかが当てはまっている場合Size.***.Back      >当てはまらない、もしくは両方当てはまっている場合はEnemy,Const(Size.***.Front)    ・本体が後ろの場合は、基本値がマイナスの為、Const(Size.***.***)での補整は+なるように。     >Var(xx)*IfElse(RootDist X<0, 1, -1)として距離+Var(xx)を行えば、前なら+(-)、後ろなら+(+)となる。    ・補整として使っている速度は、よく分からない。それっぽい数値入れてるだけ。 処理:・そしてIfElseなども駆使して、10行程度に抑える。     >がんばった。 欠点:・P2よりも1F分遅れる。P2の情報取得がキャラのステート処理の前の為かと。     >対処法は、本末転倒ながら本体でPosだけを頼りに座標計算を行う。     >即座に消えるヘルパーを射出し計算するなんて方法もありうるが、ヘルパーの量が増える。    ・ちなみに本体でもabs((Enemy,Pos X+1000)-(Pos X+1000))といった計算式で距離の算出はできる。     >その為、高速移動を感知できない不正確なヘルパーを使う必要性は無かったりする。     >absは絶対値を算出する。IfElse(x<0, x*-1, x)はこれで出来ます。  後で書こう。 ■■■地味な使い方  あと、コンフィグ設定とかファイルを個別にする為にヘルパーを用いるとか。  Type = ParentVarSet を使うことで、いくらでも設定可能なはず。  ただし、ラウンドを持ち越して管理しなければ行けないものには使えませんが。  ちなみに射出後すぐにDestroySelfを行うと、画面上に表示されません。   記述に存在を消す項目を書く必要がなくなり、記述の圧縮にもなります。  画面上に表示されはしませんが、ヘルパーの数はそのフレームだけ1増えていますので注意。 ( 処理としては、そのフレームの全てのステート処理を行ってから、    画面上の画像を変更しているのだと思われる。 ) [State -2, Helper];コンフィグヘルパー射出 Type = Helper Trigger1 = RoundState = 2 StateNo = **コンフィグヘルパーステート** SuperMoveTime = 999;保険として高い数。 PaiseMoveTime = 999 IgnoreHitPause = 1 ** [Statedef **コンフィグヘルパーステート**] Type = A [State a, ParentVarSet] Type = ParentVarSet var(**) = Trigger1 = 1 [State a, DestroySelf];ヘルパー消去 Type=DestroySelf Trigger1 = 1 ■メモ■[22]複数設置できる設置Helperの参照  HelperIDを使うことでHelper(*HelperID*),***という   ヘルパーへのリダイレクトを使うことはできるが、  同じIDが複数存在しても、参照できるのはその中の1つだけだ。   それも自分で選ぶことはできない。  その為、HelperIDをいじる必要性がある。  一番簡易的な方法としてはHelperIDに、   NumHelper(**) の分を足してしまうという方法。  しかし、まず二個出し一個目が消えてから3個目を出すと、   二個目のIDと重複してしまう欠点がある。  Varを使う方法としてはHelperを射出する度にVarを1加算し、   そのVarをHelperのIDに足して、 Varを参考にHelperIDを参照するもの。  こちらの方が確実ではあるが、管理を間違えると参照できない。  参照を行う際はもういくつかVarがあると、   NumHelperの確認をVarで行い、参照するべきHelperをVarで指定できる。  またどちらにも言えることだが[Helperの射出上限管理]が難しくなる。  方法としてはHelperから、上限管理用のIDを設定したExplod を出し、   そのExplodの数を技の条件に差し替えるというものがまあ簡単か。  >全てのNumHelper(**)から、射出HelperIDを管理する方がいいか。  >それならば射出数の上限管理も容易い。 ( !NumHelper(**) ) ;0 ( NumHelper(**) && !NumHelper(**+1) ) ;1 ( NumHelper(**) && NumHelper(**+1) && !NumHelper(**+2) ) ;2 ■メモ■[109]ヘルパーからの距離を本体だけで感知する  絶対距離であればAbs( Helper(xx),RootDist X )で構わないが、   自分から見て前か後ろかを判別させたい場合は向きを計算に加える必要がある。  例によって向き数値であるFacingを利用し  ( Facing * Helper(xx),Facing * Helper(xx),RootDist X * -1 )   これで「HelperDist X」みたいなものを参照できる。