■演算子について

MUGENで使うことのできる数式・条件式用の演算子について
またTriggerの具体例を一部。

真偽について
  • Trigger「0以外(真)」か「0(偽)」で判定する。
  • 条件式は基本的に条件が合ってれば1(真)を、合わなけれ0(偽)を返す。
    • なおトリガー情報の形式によっては固有の演算を行うため
      そのままの状態で演算子を利用することはできない。
      • 例1:文字列を返すタイプ。Statetype = Enemy,StateTypeは不可。>T-/StateType
      • 例2:固有の演算処理を行うタイプ。5 = AnimElemは不可。>T-/AnimElem
    • 上記の情報でも条件式を()で囲えばその真偽の数値(1.0)に演算子を使うことはできる。
      • 例3:(MoveType=A)=(Enemy,Movetype=A)
計算と型について
  • 数値にはInt型とFloat型とが存在する。
  • Int型は正数のみを扱え、Float型は小数を扱えるが桁が大きくなると細かいズレが生じる。
    • Int型とInt型の計算はInt型、Float型とFloat型の計算はFloat型を返す。
    • Int型とFloat型での計算の場合、Float型が優先され、Float型になる。

使用出来る演算子
  • =,!=,>,<,>=,<= 等号・不等号 数値の比較
    • 数値情報と数値情報の間に挟み、左右の数値が等しいか・等しくないかを判定。
      • =」は左右の数値が等しいなら1(真)を、等しくないなら0(偽)を返す。
      • !=」は左右の数値が等しくないなら1(真)を、等しいなら0(偽)を返す。
      • >」は左が右より大きいなら1(真)、そうでないなら0(偽)を返す。
      • >=」は左が右以上(同じを含む)なら1(真)、そうでないなら0(偽)を返す。
      • <」は左が右より小さいなら1(真)、そうでないなら0(偽)を返す。
      • <=」は左が右以下(同じを含む)なら1(真)、そうでないなら0(偽)を返す。
      • 「!=,>=,<=」の=は右側。=>,=<はエラーで落ちる。
        • =!はエラーにならないが右をNOT処理する条件式になってしまう。
        • 例:「 10!=9 」は真(1)だが、「 10=!9 」は(!9)=(0)で(10=0)の偽(0)となる。
  • +,-,*,/ 算術演算子 指定の計算をする
    • +加算・-減算・*掛け算・/割り算のおなじみの数学記号。
    • 数値情報と数値情報の間に挟むことで計算を行う。
    • 割り算の右を「0」にしてはいけない。エラーが流れる。
      • また、割り算は整数のみで行うと上手く処理されない場合がある。
        • Int型とInt型同士の計算ではFloat型にならないため小数が切り捨てられる
        • その場合左右の数値に*1.0などを入れFloat型にすると処理されるようになる。
    • なお「-マイナス」は数値情報の冒頭に記述でき、
      プラス(正数)をマイナス(負数)に・マイナスをプラスに変換する。
  • % 剰余 ※MUGEN独自記述・算術演算子
    • %」はMUGEN特有の演算子で、割り算の余りを返す。
    • 10%5は余り0なので0を、14%4は余り2なので2を返す。
    • (xxx%10)と記述すれば1桁目のみを抽出できる。
    • 対応は整数型の数値のみ。小数型の数値に使うとエラーで落ちるため注意。
  • ** 冪(べき)乗 ※MUGEN独自記述・算術演算子
    • n乗算、のはずだが挙動がやや不安定のため基本使わないほうが良い。
      • Int型同士の冪乗の場合、計算が一部安定しない
      • 整数同士かつ片方か両方を*1.0などでFloat型にすると計算が安定しやすい。
        • ただしFloat型は7桁以上の数値になるとズレが生じるため要注意。
    • 検証不足※小数単位の数値の冪乗も計算が不安定らしいが、詳しくは不明。
    • ※-Float型を入れた正数同士うまく計算が行かないケースはあるのか?
  • !,&&,||,^^ 論理演算子 条件が合っているかを確認する。
    • !」はNOT。付けた右の情報を0(偽)を1(真)に、0以外(真)を0(偽)に変換する符号。
    • &&」はAND。左右の情報が両方共0以外(真)だった場合のみ、1(真)を返す。
    • ||」はOR。左右の情報どちらかでも0以外(真)なら、1(真)を返す。
    • ^^」はXOR。左右の情報どちらか片方のみが0以外(真)なら、1(真)を返す。
  • &,|,^ ビット演算子 整数の値のbit情報で演算を行う。
    • &」はAND
    • |」はOR
    • ^」はXOR
      • 説明はやや難しいのでbit演算のページを参照
補足・数値範囲指定
  • 数値情報=(XX,XXX) (,)内の左数値より上・右数値未満の条件。
  • 数値情報=[XX,XXX] [,]内の左数値以上・右数値以下の条件。
    • 「=」は「!=」(範囲内でない)でも良い。
    • ()と[]は組み合わせることが可能。[XX,XXX)や(XX,XXX]でも良い。
    • ただし直後に別の演算子を配置してはならない。
      • 「情報=[X,XX]&&情報」などはエラーで落ちる。
      • 直後に演算子を指定したい場合は「(情報=[X,XX])&&情報」と()で囲う必要がある。
()の処理について
  • ()で囲った場合、内部の優先順位を高め、個別に処理をする。
    • 数式を囲えばちゃんと数式の答えをまとめる。
    • 条件式を囲った場合は真偽の数値(1.0)を数式に利用できる。
      • 例:130 + (Statetype=C) + 2*(Statetype=A)
        StateType=Cなら131,Aなら132、それ以外なら130になる式。
記述の優先度
  • Triggerは1行ごとに読み込みを行う。
  • 基本的に左から右の順で計算を行うが優先度により処理は前後する。
  • 上の方が優先順位が高い 同じ高さは記述時の読み込み基準。
    • 「 () 」:()内に書かれた式は優先される。()内部の順番は優先度に従う。
    • 「 ! 」「 - 」:情報の手前に付ける符号
    • 「 ** 」:n乗
    • 「 * 」「 / 」「 % 」」
    • 「 + 」「 - 」
    • 「 > 」「 >= 」「 < 」「 <= 」
    • 「 = 」「 != 」
    • 「 := 」:※後述
    • 「 & 」:(bit演算を:=するときは注意)
    • 「 ^ 」
    • 「 | 」
    • 「 && 」:論理演算子の順番には注意。
    • 「 ^^ 」
    • 「 || 」:()が無ければ「&&でまとめる→||でわける」の順番。
  • 記述例
    • 1 + 2 - 3 * 4:この数式は*が優先され3*4の12、その後1+2-12で-9となる。
    • (1 + 2 - 3)* 4:()で1+2-3を囲った場合、()内の計算が先で0*4となり0となる。
    • 1 || 1 && 0:ではまず1&&0が(0)、1||(0)は1なので、1(真)の記述。
    • (1 || 1)&& 0:だと()の比較が先で1||1が(1)だが、(1)&&0なので、0(偽)の記述。


■Lv1-具体例

基本的にCommonステートから参照
+具体例
120番ステート(ガード始動)

[State 120, 5]
type = ChangeState
trigger1 = AnimTime = 0
value = 130 + (statetype = C) + (statetype = A)*2

条件式を()で囲うことで条件の1(真),0(偽)を計算に使う記述の代表例。
Statetype=Cなら+(1)で131、Statetype=Aなら+(1)*2で132へ、それ以外なら130へ飛ぶ計算である。
ちなみにAnimTime=0は「アニメ表示が一周した」という条件。よく使われる。

122番ステート(空中ガード待機)

[State 132, 3]
type = VarSet
trigger1 = 1
sysvar(0) = (pos y >= 0) && (vel y > 0)

パラメーターへ条件式をそのまま指定すると条件の1(真),0(偽)を指定できる。
Pos Y >= 0は地面よりも下側、Vel Y > 0は速度が下向き、の条件。
&&で繋げているので、その両方が1(真)なら1を、どちらかが0(偽)なら0を、sysvar(0)へ代入する。

5000番ステート(通常くらい)

[State 5000, 5] ;State type gets set to aerial if getting hit up
type = StateTypeSet
trigger1 = Time = 0
trigger1 = GetHitVar(yvel) != 0 || GetHitVar(fall)
trigger2 = Pos Y != 0
statetype = a

Trigger1は!Time(ステートに移った直後)で、GetHitVar()(受けた攻撃の情報)が
yvel(縦のふっとばし速度)が0以外、あるいはfall(倒れ属性)の場合。
Trigger2は、Pos Y(縦の座標)が、地面(0)以外(!0)の場合。
どちらかが適合した場合、状態をStatetype=A、空中にするという命令。
ちなみに&&と||は、TriggerXと近い関係にあり、
それぞれを統合したり、分解したりすることもできる。
  • 統合した例

[State 5000, 5]
type = StateTypeSet
trigger1 = Time = 0 && ( GetHitVar(yvel) != 0 || GetHitVar(fall) ) || Pos Y != 0
statetype = a

  • 分解した例

[State 5000, 5]
type = StateTypeSet
trigger1 = Time = 0
trigger1 = GetHitVar(yvel) != 0
trigger2 = Time = 0
trigger2 = GetHitVar(fall)
trigger3 = Pos Y != 0
statetype = a

ただし条件式の統合・分解は分かりやすい・編集しやすい程度がいい。
上記の場合、統合すると一行が長すぎて分かりづらく、
分解も!Timeが2個もあり仮に編集するとき二箇所も変える必要が出てくる。
分かりやすい統合分解は後の編集も楽になるため意外と重要である。

5100番ステート(倒れ着地)

[State 5100, 3] ;Hit ground anim (for hit up)
type = ChangeAnim
trigger1 = time = 0
trigger1 = (anim = [5051,5059]) || (anim = [5061,5069])
trigger1 = SelfAnimExist(5100 + (anim % 10))
value = 5100 + (anim % 10)

「%」の剰余計算を利用したアニメ変更処理。
概要としては特殊な吹っ飛び状態から倒れた場合、専用の倒れ着地モーションにする処理。
SelfAnimExist()の中に指定するAnimを指定し、しっかりと存在するかを確認。
もし存在しなければ別の記述で通常の倒れモーションを使用するようになっている。

5100番ステート(倒れ着地)

[State 5100, 8]
type = GameMakeAnim
trigger1 = Time = 1
value = 60 + (sysvar(1) > 5) + (sysvar(1) > 14)
pos = 0, 0
under = sysvar(1) <= 14

条件式in数式の例2。sysvar(1)は接地時点(!Time)のVel Yが入っている。
基本は60番のエフェクトを、(Under=1)キャラの後ろ側へ表示するが、
倒れ着地までの速度が5より大きかったら、61番のエフェクトを使用。
更に14より大きかったら、62番のエフェクトを(Under=0)手前側に表示。





■Lv3-「:=]Var代入


+Lv3-「:=」条件式内でVar代入を行う演算子
※フォントの関係上「:」が見づらいです。

Lv3-「:=」条件式内でVar代入を行う演算子

  • :=」を使うことで、条件式の中でVarSetを行うことができる。
    • 参照された場合のみ代入を行える。
    • Trigger1 = var(1) := 1 ;参照した際、var(1)に1を代入する。
    • なお論理演算子とbit演算子よりも優先度は上である。
    • もちろん演算子のため、文字列指定のパラメーターには使えない。
      • 0,1指定のタイプでもIgnorehitpauseなどは文字列指定タイプなので注意
  • Sysvar()とSysfvar()には使うことができない。var()とfvar()のみ。
  • 数値情報としては代入した数値そのものとして扱う。
    • Trigger1 =(var(2) := 0)&&(var(3) := 20) ;情報としては(0)&&(20)の扱い。
    • 並べて用いるときは「1||」や「0&&」を前に書くと管理しやすい。
  • なおPersistent=0設定は一度実行した後の読み込み自体を停止させるため、
    参照されない=「;=」代入も行われないので要注意。

記述の比較例

[State a]
Type=varset
Trigger1=1
var(5)=1

[State a]
Type=null
Trigger1=var(5):=1

上記の二つのステートコントローラーの処理は同一と言える。
どちらもVar(5)へ1を代入する記述である。

記述の注意点

[State a]
Type=null
Trigger1=var(10):=1
Trigger1=var(11):=0
Trigger1=var(12):=5
Trigger2=var(13):=10
Trigger3=var(14):=500

こうした記述の場合var(12)とvar(14)の代入は行われない
「:=」の注意点として代入は参照した時だけ行うことを忘れないこと。

[State a];内約解説
Type=null
Trigger1=var(10):=1 ;○トリガー1・読み込み・真(0以外)なので次の同じ番号を参照
Trigger1=var(11):=0 ;△トリガー1・読み込み・偽(0)なので同じ番号を参照せず、次の番号を参照。
Trigger1=var(12):=5 ;×トリガー1・トリガー1で偽が出たので読み込まない
Trigger2=var(13):=10;○トリガー2・トリガー1が読み込まれて偽が出たので読み込み。
          ;真(0以外)だが、次の同じ番号がないので条件合致によりステートコントローラーを実行。
Trigger3=var(14):=500;×トリガー3・トリガー2は読み込まれたが真で終わったので読み込まれず。

「:=」による代入を行う場合はこうした読み込みの条件と順番に注意しないといけない。
もし全ての行を参照させたい場合は以下のようにすること。

[State a];1||を入れることで条件を真にし、同じ番号を読み込ませ続ける。
Type=null
Trigger1=1||var(10):=1
Trigger1=1||var(11):=0
Trigger1=1||var(12):=5
Trigger1=1||var(13):=10
Trigger1=1||var(14):=500
;1||と同じ番号のTriggerを利用する方法

[State a];0&&を入れることで条件を偽にし、次の番号を読みこませる。
Type=null
Trigger1=0&&var(10):=1
Trigger2=0&&var(11):=0
Trigger3=0&&var(12):=5
Trigger4=0&&var(13):=10
Trigger5=0&&var(14):=500
;0&&と連続した番号のTriggerを利用する方法

上記のどちらも、全ての:=によるVarSetを行う処理である。
計算式・条件式を交えて代入を行うばあいは、こうした調整をするのが基本。
なお行の順番が前後していても同じ番号→次の番号の優先順位なので注意。

パラメーターでの代入
パラメーターの読み込みは基本ステートコントローラーの処理が行われる場合
またステートコントローラーで使用するパラメーターしか読み込まない
例としてはCommonステートページに書いたAI用の空中ジャンプ制御記述の一部。

■AI側の記述
[State -1, AI Air Jump]
Type = ChangeState
Value = 45 + ( Var(*AirJump用Var*):= (1+Var(*AirJump用Var*)) )*0;ジャンプ回数を加算
TriggerAll = Var(*AIフラグ*) ;AIフラグあり
TriggerAll = StateType = A && Ctrl && Pos Y < -1*Const(Movement.AirJump.Height);前提条件
TriggerAll =(Var(*AirJump用Var*)&1073741823)< *AirJump.Num* ;ジャンプ回数制限
Trigger1 = **** ;AI用の条件

処理が実行される場合にVar(*AirJump用Var*)に+1加算して代入を行うという記述
パラメーターは処理が実行されない場合は基本的に読み込みは行われない。
なおパラメーターによっては読み込み回数が増えるという話もあるので処理には要注意。
ちなみに条件式内で「:=」代入を行いパラメーターで指定すれば
計算したVarの数値をすぐパラメーターで使うことも可能。

複合Varset記述の例
  • 記述の一例。 Var(0),Var(1),Var(2)をTempVarとして使用。

[State -1]
type = varset
var(0) = 1
TriggerAll = 1 || var(0) := 0 ;tempリセット
TriggerAll = 1 || var(1) := 0
TriggerAll = 1 || var(2) := 0
triggerall = StateType!=L
Trigger1 = command = "b"
Trigger1 = 1 || var(1) := 55
Trigger2 = command = "a"
Trigger2 = 1 || var(1) := 50
Trigger3 = command = "y"
Trigger3 = 1 || var(1) := 5
Trigger4 = command = "x"
Trigger4 = 1 || var(1) := 0
ignorehitpause = 1
[State -1]
type = null
triggerall = StateType!=L
Triggerall = 1 || var(1) := var(1) + (StateType=A)*400 ;空中時600系に
TriggerAll = 1 || var(2) := 2 ;
Trigger1 = Command = "holddown" ;屈み
Trigger1 = 1 || var(1) := var(1) + 200*(StateType!=A) + 30*(StateType=A) ;空中時+30 地上時400系
Trigger1 = 1 || var(2) := ifelse(statetype!=A,1,4) ;空中ならLv4
Trigger2 = Command = "holdfwd" ;前
Trigger2 = 1 || var(1) := var(1) + 20 ;20系
Trigger2 = 1 || var(2) := ifelse(statetype!=A,4,3) ;空中ならLv3
Trigger3 = Command = "holdback";後ろ
Trigger3 = 1 || var(1) := var(1) + 10*(Statetype!=A) ;610系は無いので
Trigger3 = 1 || var(2) := 3 ;

「:=」による代入の応用に慣れるとこんな記述も可能になる。
  • 前半 Varset
    • まず全てのVarを0にする
    • 倒れ状態でない場合のみ下を処理する。
    • コマンドでbが押されたら55、aなら50、yなら5、xなら0の数値をvar(1)へ代入する。
    • 「baxy」のいずれかが押されていたらvar(0)に1を代入。
  • 後半 Null
    • 倒れ状態出ないことを確認する
    • var(1)を空中の場合+400加算する。またvar(2)へ2を代入する。
    • 方向キー下で、var(1)を空中でないなら+200、空中なら+30する。
      • さらにvar(2)を空中でないなら1、空中なら4にし、読み込みを終了させる。
    • ↑で読み込み終了せず、方向キー前ならVar(1)に+20する。
      • さらにvar(2)を空中でないなら4、空中なら3にし、読み込みを終了させる。
    • ↑で読み込み修旅せず、方向キー後ろならvar(2)を3にする
      • さらにvar(1)を空中でない場合は+10する。
ちなみにこのvar(1)の数値は+200してステート移動の指定番号に使われる。
これにより「28個の技への移動」を移動含め3つのステートコントローラーで制御している。
(とはいえ、普通のキャラに使う記述ではないのは確か。おとなしくステコンを並べよう。)