05« 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.»07

スポンサーサイト 

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
スポンサー広告  /  tb: --  /  cm: --  /  △top

无寿の夢の毒に関する仕様報告書(タッグ対応版) 

・前置き
アフロン氏の麟の毒記述をお借りして无寿の毒を再現したわけだが、所謂永久ターゲットを
利用したLifeaddによる毒の詳しい解説をしているサイトは自分が探した限りではなかった。
なので今後キャラ制作に携わる方にわかりやすくこのシステムの説明をしようと考えた。
キャラを少しでも制作したことがある方ならだいたい理解できるんじゃないかと。
ヒット数などにバグがあったり等で未完成なため、改善策や別案等あればお願いします。
追記) 2010/02/26:一部記述を修正  2010/03/28:タッグ対応版に改訂
・永久ターゲットバグについて
まず永久ターゲットバグ自体の説明から始める。
簡単に言えば、ReversalDefを用いた当身技を一度当ててしまえばTargetLifeAdd等の
Target~の部分に相手が常時当てはまるようになるというもの…で合ってるのだろうか。
要は一度相手を当身で取ってしまえば好き放題できますよ、ということ。
神キャラとかがだいたい打撃技振らないのはこれを利用されると即死を食らうためだろう。

・毒への転用について
永久ターゲット自体の説明はこれで良いとして、これを実際にどう生かすかという話。
永久ターゲットで指定した相手に対しTargetLifeAddで時間ごとに一定体力を減らせば良いだけ。
ただし問題は永久ターゲット自体をどうやって取るか、ということになる。
当身を持つキャラにしても一度当身を取らないと毒ダメージが入らないのでは面倒だし、
そもそも当身を持たないキャラはどうしたら良いのだろうか、というのが疑問だった。
ここで解決策になるのが専用ステートである。

・専用ステートについて
専用ステートというのはロック技等で相手の動きを意のままに操るために使われるステートだ。
投げ技なんかはほぼ例外なく相手を専用ステートに引き入れることで作られている。
そして専用ステートでは、相手の食らい判定を自由に設定したり、攻撃させたりも可能だ。
そう、相手に攻撃させることが可能ならばそれを任意で当身することも可能だということ。
また当身するのは自分ではなく自分のヘルパーだったとしても永久ターゲットに指定できる。

・ここまでのまとめ
相手を専用ステートに引き入れる → 相手に攻撃させる → それをヘルパーに当身させる
→ 永久ターゲットに相手が設定される → TargetLifeAddで相手の体力を減らす → 毒


・実用例
ここで自分が「无寿の夢」の毒の再現のために改変した記述を要点だけ抜き出して見てみよう。
一応アフロン氏は改変自由、奏貴氏には改変許可を頂いているので問題無しとみて掲載。
ただし奏貴氏またはアフロン氏より万が一苦情があった場合削除される可能性あり。

;====================================================
;■霊符「无寿の夢」 射撃
;====================================================
[StateDef 4210];@  ← 実際に毒を与えたいステート(本体、ヘルパー問わず)の番号
MoveType = A
Physics = N

[State -1];@
Type = HitDef
Trigger1 = !(MoveContACT)
Attr = A, NP
Damage = 0,0     ← ステート変更時にダメージが適用されないため
AnimType = Light      LifeAddを用いて別枠でダメージを与える
HitFlag = MAF
GuardFlag = MA
Priority = 1, Miss
PauseTime = 0, 0
SparkNo = -1
Guard.SparkNo = -1
Sparkxy = -1
HitSound = s1,3
GuardSound = s2,0
Ground.Type = High
Ground.HitTime = 16
Ground.Velocity = -5,0
Ground.SlideTime = 7
Air.Type = High
Air.HitTime = 16
Air.Velocity = -5,-2
ID = 4210
Fall = 0
Air.Fall = 0
Fall.Recover = 0
Ground.CornerPush.veloff = 0
Air.CornerPush.Veloff = 0
Down.CornerPush.Veloff = 0
Guard.CornerPush.Veloff = 0
AirGuard.CornerPush.Veloff = 0
p2stateno = 4211          ← 相手を引き入れる専用ステートの番号を付け加える

[State -1];@
Type = null;ParentVarAdd   ← 元々使用されていた記述を無効化する
Trigger1 = MoveHit        無効化しておかないと二重に毒がかかる可能性があるため
V = 3
Value = 1

[state a];@         ← 相手の攻撃を当身するためのヘルパーを射出する式
type = Helper
trigger1 = MoveHit = 1
trigger1 = playerID(root,var(14)),stateno = 4211  ← タッグ時の判別用
id = 4215                       var(14)には2PのIDを入れておく
name = "Poison"
pos = 14,12
postype = p2         ← 相手の位置に依存するヘルパーにしておく
stateno = 4215        ← ヘルパーのステート番号
helpertype = normal
pausemovetime = 0
keyctrl = 0
ownpal = 0
persistent = 0
igunorehitpause = 1

[state a];@          ← 上式に似たヘルパーをタッグ用にもう1つ出す
type = Helper
trigger1 = numenemy >= 2    ← タッグ判定
trigger1 = MoveHit = 1
trigger1 = playerID(root,var(15)),stateno = 4211  ← タッグ時の判別用
id = 4216                       var(15)には4PのIDを入れておく
name = "Poison"
pos = 14,12
postype = p4         ← 相手の位置に依存するヘルパーにしておく
stateno = 4216        ← ヘルパーのステート番号
helpertype = normal
pausemovetime = 0
keyctrl = 0
ownpal = 0
persistent = 0
igunorehitpause = 1

;================================================
;■霊符「无寿の夢」 敵ステート
;================================================
[StateDef 4211];@  ← 相手を引き入れるステートの番号、無ければ自分で適当に作ること
type = A
movetype= H
physics = N
sprpriority = 1
anim = 5020     ← 相手の食らい状態アニメの指定

[State 4211]     ← 上のHitDefで書いたダメージを与えるためのLifeAdd用の式
type = lifeadd
Trigger1 = time = 0
kill = 0       ← そのダメージで相手が死ぬことがないように
value = -20     ← 実際にLifeの数値を変動させる、マイナスで書くことでダメージ

[State 4211]     ← 下記のHitDefを有効にするために何もない画像に攻撃判定を
type = ChangeAnim2  小さくつけたものをAirに登録しておく必要がある
Trigger1 = Time = 0   攻撃判定が無いとHitDefを書いても無意味なため
value = 4215     ← 実際にその画像を指定し、相手が攻撃するための準備をする

[State 4211]     ← 実際に相手を攻撃させる
type = HitDef
trigger1 = time = 0
attr = C,HT,HP     ← タッグ判別用に攻撃属性を二種付与しておく
animtype = light
damage = 0
priority = 1, Hit
getpower = 0,0
givepower = 0,0
hitflag = F-     ← 普通には当たらないようにしておく
guardflag = N
pausetime = 0,0
sparkno = s-1
sparkxy = 0,0
hitsound = s-1,0
guardsound = s-1,0
guard.sparkno = s-1
ground.type = high
ground.slidetime = 0
ground.hittime = 9
ground.velocity = 0
guard.velocity = 0
air.velocity = 0,0
ID = 9999
nochainID = 9999
palfx.time =32
palfx.mul = 100,120,80
palfx.sinadd = 93,115,68,16
palfx.add = -30,-20,-50
air.fall = 1
fall.recover = 0
air.cornerpush.veloff = 0
airguard.cornerpush.veloff = 0

[State 4211]
type = ChangeState
trigger1 = time = 2  ← 攻撃終了後を指定、余裕を持たせる
value = 4212     ← 相手を次の専用ステートに送る

[StateDef 4212];@   ← 相手を強制ダウンさせるまでの専用ステート式
type = A         中身は受け身不能以外殆どcommonファイルの使いまわし
movetype= H      ダウンさせるのは直接ステートを相手に返すタイミングが難しいため
physics = N
sprpriority = 1
velset = -2,-1    ← 相手を斜め後ろに僅かに浮かせるよう速度設定
anim = 5030

[State 4212]     ← 相手に重力をかける式
type = Veladd
trigger1 = 1
Y = GetHitVar(yaccel)

[State 5035, 1]
type = ChangeAnim
trigger1 = Time = 0
trigger1 = SelfAnimExist(5035)
trigger1 = Anim != [5051,5059] ;Not if in hit up anim
trigger1 = Anim != 5090 ;Not if hit off ground anim
value = 5035

[State 5050, 1] ;Change anim when done with transition
type = ChangeAnim
trigger1 = AnimTime = 0
trigger1 = Anim = 5035
trigger2 = Time = 0 ;If no transition anim
trigger2 = Anim != 5035
trigger2 = (Anim != [5051, 5059]) && (Anim != [5061, 5069])
trigger2 = Anim != 5090 ;Not if hit off ground anim
value = 5050

[State 5050, 2] ;Coming down anim
type = ChangeAnim
trigger1 = anim = [5050,5059]
trigger1 = Vel Y >= ifelse(anim = 5050, 1, -2)
trigger1 = SelfAnimExist(anim+10)
value = anim+10
persistent = 0

[State 5050, 6]    ← ダウン時
type = SelfState    ← セルフステート、つまり相手にステートを返す
trigger1 = Vel Y > 0
trigger1 = Pos Y >= ifelse((anim = [5051,5059]) || (anim = [5061,5069]), 0, 25)
value = 5100 ;HIT_BOUNCE

;=============================================
;■霊符「无寿の夢」 ヘルパー
;=============================================
;(HELPER)攻撃用ヘルパー・Ⅰ;@
[Statedef 4215]  ← 相手の攻撃を当身するヘルパーの式、自分で作ること
type = A
ctrl = 0
anim = 4215    ← 相手が攻撃する位置と同じ位置に当身判定を出す
velset = 0,0
movetype = I
physics = N
sprpriority = 5

[state a];打撃防御  ← 実際に当身を出す式
type = reversaldef
trigger1 = time = 0
reversal.attr = C,HP
pausetime = 0,0
sparkno = s-1
sparkxy = 0,0
hitsound = s-1,0
numhits = 0

[state a]       ← 相手が動いている時にヘルパーの位置を修正する式
type = posset
trigger1 = time >= 1
x = floor(playerID(root,var(14)), pos x)
y = floor(playerID(root,var(14)), pos y)

[state a]        ← ヘルパーが毒で実際にダメージを与えるための式
type = targetlifeadd
trigger1 = time % 3 = 2 ← time%3=2は3で割って余り2、つまり3Fに1回ダメージ
value = -1        ← 実際に1回にダメージを与える量
kill = 0         ← 毒で相手が死なないように
absolute = 1

[state a]
type = hitadd      ← ヒット数がバグるので強制的にhit数を0にしておく
trigger1 = enemynear,movetype != H
value = -1

[state a]
Type = DestroySelf     ← ヘルパーが消える、つまり毒が消える条件式
TriggerAll = time != [0,1]   ← 後から撃ったヘルパーが消えないように
Trigger1 = NumHelper(4215) > 1 ← 毒用のヘルパーが2個以上出た時に消える
Trigger2 = time >= 540     ← 540F経過したときに自動で消失
Trigger3 = Root,Win = 1    この時 540F/3F × 1dmg/F = 180dmg
Trigger4 = Root,Lose = 1    180dmg + 20dmg(最初のLifeAdd) = 200dmg
Trigger5 = Root,DrawGame = 1
Trigger6 = Root,MoveType = H  ← 食らってもガードしても消える

;(HELPER)攻撃用ヘルパー・Ⅱ;@
[Statedef 4216] ← タッグ時用の当身ヘルパー式、中身はほぼ同じ
type = A
ctrl = 0
anim = 4215
velset = 0,0
movetype = I
physics = N
sprpriority = 5

[state a];打撃防御
type = reversaldef
trigger1 = time <= 1
reversal.attr = C,HT  ← 当たる攻撃の種類を変えることで対象を判別する
pausetime = 0,0
sparkno = s-1
sparkxy = 0,0
hitsound = s-1,0
numhits = 0
ID = 4210

[state a]
type = posset
trigger1 = time >= 1
x = floor(playerID(root,var(15)), pos x)
y = floor(playerID(root,var(15)), pos y)

[state a]
type = targetlifeadd
trigger1 = time % 3 = 2
value = -1
kill = 0
absolute = 1

[state a]
type = hitadd
trigger1 = enemynear,movetype != H
value = -1

[state a]
Type = DestroySelf
TriggerAll = time != [0,1]
Trigger1 = NumHelper(4216) > 1
Trigger2 = time >= 540
Trigger3 = Root,Win = 1
Trigger4 = Root,Lose = 1
Trigger5 = Root,DrawGame = 1
Trigger6 = Root,MoveType = H

以上、説明終わり。後はトライ&エラーで頑張るのみ。
重ねて言うがバグ報告、その解決策等お待ちしてます故。
スポンサーサイト
MUGENデータ集  /  tb: --  /  cm: 4  /  △top

この記事に対するコメント

何点か指摘があります

1.敵ステートでMoveTypeの変更は不要
(MoveType=HでもReversalとれるのでタッグ等での巻き込みを防止策も兼ねて)
ついでに言うと、当身ヘルパーも最初からMoveType=IでOK

2.敵のHitDefはHitFlag=F-に設定しておくのが無難
(Reversalとる時はHitFlag関係ないのでタッグ等での巻き込みを防止策として)

3.HitAddのTriggerをTarget,MoveType!=Hにすれば少なくともSingleのときは表示通りになる
(タッグのときはTargetと非Targetで別々にカウントしてVar格納しないと恐らく無理)

4.Time%3=0でダメージのTime>=540でDestroyだとTime=0を含めて181回与えてしまうので
 ・TargetLifeAddをDestroySelfの下に持っていくか
 ・Time>=540をTime>=539やTime>=538に変更するか
 ・Time%3=0をTime%3=1かTime%3=2に変更する
のいずれかにした方が良いと思われます。

5.Helper呼び出しステコンにPersistent=0つけるか、トリガーのMoveHitをMoveHit=1にしないと
ステート切り替わるかMoveHitResetが実行されるまで1F毎呼び出してしまう
この例ではPauseTime=0,0なので要らないけどIgnoreHitPause=1が場合によって必要

6.Helper(4200)がどんなヘルパーか分からないので何とも言えませんが
右の説明見た感じNumHelper(4215)の間違い(毒攻撃の上書きの話?)だと思われるので
NumHelper(4215)>1にしないと自分自身がHelper(4215)なので即座にDestroyしてしまう


あと、タッグ相手で両方にヒットした場合も考えて
敵ステートのHitDefを
Trigger1 = !NumPartner
Trigger2 = NumPartner
Trigger2 = ID < Partner,ID
の条件でAttr=C,HP
Trigger1 = NumPartenr
Trigger1 = ID > Partner,ID
の条件でAttr=C,HTのように使い分けて
自分は当身ヘルパーを2つ呼び出して
片方はReversal.Attr=C,HPに、もう片方はReversal.Attr=C,HTに設定したReversalDefを実行させれば
お互いに干渉することなく2つのヘルパーに別々の敵を永タゲさせることもできます。

長文失礼

URL | #2sQQXnjA

2010/02/22 12:35 * 編集 *

コメント返信

>>名無しの方
御指摘ありがとうございます。
1.Movetypeの変更は不要…と。トリガーとしての利用以外の意図はあまり無いんですかね。
2.HitFlagに関しての完全な知識不足ですね、申し訳ありません。
3.Target,movetype!=Hを利用させてもらいましたがhit数が表示されません、何か別の記述が原因の可能性もあるので調べてみます。
4.ダメージ換算は実際に何度か試して200になることを確認していますが、理論上は仰る通りになるはずなので念のため変更しておきます。
5.MovehitとMovehit=1を同一視していたのですが違いがあったんですね、修正しておきます。
6.そのヘルパーは天寿射出直後のヘルパーですね、毒消失のタイミングがズレる等に対する苦肉の策として利用していました。修正しておきます。

別々の敵に対する記述に関してはp2が使えてp4が使えないトリガー等が多く、その辺の対応に苦戦しています。varに直接IDを記録してしまうのが一番確実なのでしょうが…。

URL | sekt #SFo5/nok

2010/02/23 00:13 * 編集 *

相手特定方法について

初めまして、最近製作者デビューした松梅魂といいます。

ブラッキーのどくどくを表現するためにこの記述を使わせてもらいました。ありがとうございます。

作っていて気がついたのですが、IDを使わなくてもEnemy(0)で2P、Enemy(1)で4Pを参照できると思います。

この方式ならID記憶用のVarが不要になると思うのですが、ひょっとしてこれでは何か不具合が出たりするのでしょうか?

URL | 松梅魂 #W4yECcMk

2010/06/26 19:59 * 編集 *

コメント返信

>>松梅魂氏
初めまして、この項がお役に立ったのなら幸いです。
相手特定方法に関してなのですが、pos絡みで何らかの不都合があった…気がします。
現verとは仕様が異なるので検証できませんが、あまり気にしなくても良いと思いますよ。
helperのvarは本体とは別枠なので、枠の無駄というわけでもないはずですし。
どうしてもhelperのvarを使いたくないのなら試してみる価値はあるかもしれませんが。

URL | sekt #SFo5/nok

2010/06/26 21:04 * 編集 *

△top

コメントの投稿

Secret

△top

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。