*シナリオ作成応用編 [#s470aea3]
#contents
----
**Q601. 敵を倒したら強化パーツを手に入れさせるにはどうすれば良いのですか? [#Q601]

 SRWなどでは、ボスを倒した時に強化パーツが手に入ります。
 これをSRCで再現するためには破壊ラベルを使いましょう。

 破壊 (破壊されたユニットのパイロット名):
 (強化パーツを手に入れるイベント)
 Exit

 強化パーツを手に入れるイベントに関して以下に例を挙げます。

 Item (強化パーツ名)
 Talk システム
 (強化パーツ名)を手に入れた
 End

 まとめ~
 ・敵を倒したかどうか判別するには…破壊ラベル~
 ・強化パーツを手に入れるには…Itemコマンド

**Q602. ステージ終了時の残りSPによる経験値ボーナスをやめることはできますか? [#Q602]

 SRCではステージを終了すると、~
 ステージ終了時点のSPx2が経験値ボーナスとして~
 自動で加算されるようになっています。

 ただ、毎回経験値が加算されてしまうと、~
 レベル調整するのが難しくなってしまうので、~
 これをやめたいという場合もあるかと思います。

 <経験値加算が行われる条件>
 ・Continueコマンドを使った時点で
 ・"出撃"or"格納"状態になっている味方ユニット

 つまり、Continueコマンドを使う直前に~
 Escapeコマンドで味方全体を"待機"状態にしてしまえば~
 経験値が加算されませんし、表示自体も行われなくなります。

 Escape 味方
 Continue シナリオ02.eve

 直後がContinueコマンドになっていますので、~
 味方の全滅イベントが発生する心配はありません。
 Destroyコマンドを使うと修理費がかかってしまうので~
 気をつけましょう。

''関連項目:''~
[[Q612. 戦闘時の獲得経験値をすべてゼロにする方法は?&br;      敵撃墜時の獲得資金をすべてゼロにする方法は?>#Q612]]


**Q603. 指定座標のビットマップ番号はどうやって調べれば良いですか? [#Q603]

 ChangeTerrainコマンドではビットマップ番号を指定する必要がありますが、~
 Info関数ではビットマップ名しか調べられません。~
  (ビットマップ名 = "remains1.bmp"、"base-1.bmp" など)

 ビットマップ名は必ず"文字列"+"数値"+"."+"拡張子"の順に並んでいますので、~
 SRCのイベントコマンドと関数を利用すれば、番号だけの抽出が可能です。

 # ビットマップ名取得
 # (Info関数を使用してください)
 mBMP = Info(マップ, X座標, Y座標, ビットマップ名)
 
 # 拡張子切捨て
 # ("文字列" + "ビットマップ番号" にする)
 mBMP = Mid(mBMP, 1, (Instr(mBMP,".") - 1)) 
 
 # ビットマップ番号抽出
 # (数値 or "-" 以降の部分を抽出する)
 For i = 1 To Len(mBMP)
  If Mid(mBMP,i,1) = "-" OR IsNumeric(Mid(mBMP,i,1)) Then
   mBMP_No = Mid(mBMP,i)
   Break
  Endif
 Next

 結果~
 ・"mBMP_No"がビットマップ番号になります。("1"とか"-1")

**Q604. 全ての味方、敵、または特定グループIDのユニットに対し何かをするには?[#Q604]

~ 「ForEach」コマンドを使います。
 # 全ての敵の気力を 10 下げる。
 ForEach 敵
   IncreaseMorale -10
 Next

 # 全ての味方ユニットに搭乗する全パイロットの SP を回復させる。
 ForEach 味方
   For i = 1 to CountPilot()
     RecoverSP Pilot(対象ユニットID,i) 100
   Next
 Next
~ ただし、ForEachループの中に ForEachを入れることはできないので、ご注意ください。

~ コマンドによっては、陣営名やグループIDをパラメータにすることによってまとめて処理できます。
 # 出撃中の全ての味方を脱出させる。
 Escape 味方
~ ただし、この方法はコマンドごとの仕様に依存します。特に慣れないうちはヘルプでしっかり確認してから使うことをおすすめします。

**Q605. ユニットが装備する全アイテムを調べ、処理するには?[#Q605]

~ 「CountItem」関数で装備アイテム数を調べ、「For〜Next」ループや「Do〜Loop」ループを使います。

~ 以下の例では、メインパイロット名が「パイロットA」のユニットのアイテムの名称を連想配列「Aアイテム」に入力します。
 Set Aアイテム
 For i = 1 To CountItem(パイロットA)
   Aアイテム[i] = Item(パイロットA, i)
 Next

~ ループの実行中にアイテムの番号が変化するかもしれないときは注意が必要です。以下は、パイロットAの持つアイテムのうち装備個所が「武器」であるアイテムを削除します。
 For i = CountItem(パイロットA) To 1 Step -1
   If Info(アイテム, Item(パイロットA, i), 装備個所) = "武器" Then
     RemoveItem パイロットA i
   EndIf
 Next

~ For〜Next、ForEach〜Next、Do〜Loop は繰り返し構造と呼ばれ、パラメータを変えながら繰り返し順番に実行していきます。しばしば誤解されますが、決して「当てはまる要素に対して一度に実行する」というものではありません。~
 したがって、上と同じ目的で以下のようにするのは誤りです。
 For i = 1 To CountItem(パイロットA)   // まちがい
   If Info(アイテム, Item(パイロットA, 1), 装備個所) = "武器" Then
     RemoveItem パイロットA 1
   EndIf
 Next
~ これだと、ループを繰り返すなかで RemoveItem されたときアイテムの番号がずれてしまい、チェックされないアイテムが出てきます。
~ あえて正順でやりたい場合は、たとえば次のようにします。
 Set i
 Do While i <= CountItem(パイロットA)
   If Info(アイテム, Item(パイロットA, i), 装備個所) = "武器" Then
     RemoveItem パイロットA i
   Else
     Incr i                // 順番がずれないときだけ、i を増やす
   EndIf
 Loop

**Q606. ユニットがマップの特定領域に入ったときに何かを起こすには?[#Q606]
~ ユニットが特定領域に存在するとき処理したい場合は、[[Q.607>#Q607]]を参照してください。

~ 「特定領域」がたった一つの座標の場合は、単純に「進入イベント」を使います。~
 # 味方ユニットが X = 5、Y = 7 に入ったときにイベントを起こす
 進入 味方 5 7:
   (イベント内容)
 Exit

~ 座標が複数あるときは、「進入イベントラベル」を並べます。
 # これらのイベントは合わせて1回しか起こらない。
 進入 味方 5 7:
 進入 味方 4 7:
 進入 味方 5 8:
   (イベント内容)
  ClearEvent "進入 味方 5 7"
  ClearEvent "進入 味方 4 7"
  ClearEvent "進入 味方 5 8"
 Exit
 ClearEventコマンドをパラメータを省略すると、イベント内容を引き起こしたイベントラベルだけを消去します。並べられたイベントラベルをすべて消去したい場合は、上のように記述してください。

~ 座標がもっと多い場合などには、「進入イベント」内部で座標を判別させます。~
 以下は「特定領域」の X座標が 5 以下、Y座標が 4 以上 8 未満の場合にイベントを起こします。
 進入 味方 全 全:
   If X() <= 5 And Y() >= 4 And Y() < 8 Then
     (イベント内容)
   EndIf
 Exit

~ 「特定領域」が特定の地形の場合には、以下のようになります。
 進入 味方 地形名称:
   (イベント内容)
 Exit

~ これを応用して、terrain.txt にイベント用の地形を記述してマップ上に配置するという手段もあります。


**Q607. ユニットがマップの特定領域に存在するときに何かを起こすには?[#Q607]
~ (この項は、[[Q606.ユニットがマップの特定領域に入ったときに何かを起こしたいときには?>#Q606]]と共通事項が多いので、そちらも参照してください)。

~ これには、X 関数と Y 関数を使ってユニットの表示位置を出し、それを判別します。~
 以下は、味方ターン冒頭に X座標が 5 以下、Y座標が 4 以上 8 未満のユニットの HP を回復させます。
 ターン 全 味方:
   ForEach 味方 出撃
     If X() <= 5 And Y() >= 4 And Y() < 8 Then
       RecoverHP 対象パイロット HP回復率
     EndIf
   Next
 Exit


**Q608. 発動に追加条件が付いたイベントを設定するには?[#Q608]
~ ここでは、~
「敵を破壊したとき、敵数が5体以下のときだけイベントを起こしたい」~
「敵全滅のとき、ボス登場済みかどうかで動作を変えたい」~
など、イベントラベルで表される条件以外の追加条件をイベントに付加する方法を説明します。

~ 最もよく使うのは ''「If」コマンド を使う方法''です。
 # 敵ユニットが5体以下になったときに何かを起こす
 破壊 敵:
   If 敵数 <= 5 Then
     (動作内容)
   EndIf
 Exit

 # パイロットAが出撃中かどうかを追加条件にする場合は、
 (イベントラベル):
   If パイロットA Then
     (動作内容)
   EndIf
 Exit
 # となります。「パイロットA」はパイロットの名称または愛称です。
 # (ザコ)または(汎用)でパイロットを特定できない場合、
 # 予想外の動作になることがあります。

 # 第3ターン以降毎ターンの味方フェイズに何かを起こします。
 ターン 全 味方:
   If ターン数 >= 3 Then
     (動作内容)
   EndIf
 Exit

 # 敵全滅時、まだボスが登場していなかったらボスを登場させ、
 # すでに登場していたら別 のできごとを起こしたいときには、
 # 次のようになります。
 全滅 敵:
   If ボス登場 = 0 Then
     (ボス登場動作内容)
     Set ボス登場
   Else
     (それ以外の時の動作内容)
   EndIf
 Exit

 # ターンによって勝利条件表示を変える例です。
 勝利条件:
   If ターン数 < 5 Then
     Talk
       (4ターンまでの勝利条件表示)
     End
   Else
     Talk
       (5ターン以降の勝利条件表示)
     End
   EndIf
 Exit
~ If コマンドを使うとき注意すべきは、「If の効果は EndIf を使うまでは有効だ」ということです。EndIf の書き忘れは非常によくあるミスなので、ご注意ください。このミスを減らすためにも「If」「ElseIf」「Else」「EndIf」のあいだの行は字下げすることを強くおすすめします。

~ パラメータの値によっていろいろなできごとを起こしたいときには、''「Switch」''が便利です。
 # 次の例は、敵全滅のたびに違ったできごとを起こします。
 全滅 敵:
   Incr 全滅回数
   Switch 全滅回数
   Case 1
    (全滅1回目で発生する動作)
   Case 2
    (全滅2回目で発生する動作)
   …(中略)
   EndSw
 Exit

 # 以下は、ユニットAが破壊されたとき、撃墜したパイロット
 # ごとに違ったできごとを起こします。
 破壊 ユニットA:
   Switch 相手パイロット
   Case パイロットA
     (パイロットAが撃墜したときの動作)
   Case パイロットB
     (パイロットBが撃墜したときの動作)
   …(中略)
   Case Else
     (それら以外のパイロットが撃墜したときの動作)
   EndSw
 Exit

''関連項目:''~
[[Q609.あるできごとが起こってから数ターン後にイベントを起動させるには?>#Q609]]~
[[Q610.敵と中立の両方が全滅したときにイベントを起こすには?>#Q610]]~
[[Q613.複雑な条件分岐を設定する方法は?>#Q613]]


**Q609. あるできごとが起こってから数ターン後にイベントを起動させるには?[#Q609]
~ これには、ターン判別用の変数を用意しておいて判定します。

~ 以下は、ユニットAが破壊された5ターン後にイベントを起こす二つの方法です。

<方法1>
 # まず、ステージの最初に、
 # ユニットA破壊まで条件が満たされないよう
 # 変数「イベント起動時」をセットします。
 # 変数未定義でも条件が満たされない場合、この部分は省略可能です
 # (実はこの例もそうです)。
 スタート:
   Set イベント起動時間 -1
 Exit
 
 # ユニットA破壊時、イベント起動予定ターンをセットします。
 破壊 ユニットA:
   イベント起動時間 = ターン数 + 5
 Exit
 
 # そして、ターンイベントで判別します。
 ターン イベント起動時間 味方:
   (イベント内容)
 Exit

<方法2>
 # ステージの最初に ClearEvent を使い
 # ターンイベントが起こらないようにします。
 スタート:
   ClearEvent "ターン イベント起動時間 味方"
 Exit
 
 # ユニットA破壊時、変数をセットし、
 # RestoreEvent でターンイベントを復活させます。
 破壊 ユニットA:
   イベント起動時間 = ターン数 + 5
   RestoreEvent "ターン イベント起動時間 味方"
 Exit
 
 ターン イベント起動時間 味方:
   (イベント内容)
 Exit

''関連項目:''~
[[Q608.発動に追加条件が付いたイベントを設定するには?>#Q608]]


**Q610. 敵と中立の両方が全滅したときにイベントを起こすには?[#Q610]
~ 「敵と中立の両方が全滅したときにイベントを起こす」ということは、「敵全滅時、もし中立が全滅していればイベントを起こし、中立全滅時、もし敵が全滅していれば同じイベントを起こす」と同じことです。したがって、「全滅 敵」と「全滅 中立」の二つのイベントを作り、もう一方がすでに全滅していることを追加条件にすればよいわけです。
 全滅 敵:
   If 中立全滅 = 1 Then
     Call 双方全滅イベント
   EndIf
   Set 敵全滅
 Exit
 
 全滅 中立:
   If 敵全滅 = 1 Then
     Call 双方全滅イベント
   EndIf
   Set 中立全滅
 Exit
 # 「Set 〜」は「If〜EndIf」内の「Else」節に入れても可です。
 
 双方全滅イベント:
   (イベント内容)
 Return

~ フラグ「敵全滅」「中立全滅」を Set して判別するかわりに、システム変数「敵数」「中立数」がゼロかどうかで判別する方法もあります。

~ 同じことをもっと短く書くこともできます。
 全滅 敵:
 全滅 中立:
   If 敵数 + 中立数 = 0 Then
     (イベント内容)
   EndIf
 Exit

''関連項目:''~
[[Q608.発動に追加条件が付いたイベントを設定するには?>#Q608]]


**Q611. 攻撃イベントや攻撃後イベントで味方の仕掛けた戦闘と敵が仕掛けた戦闘を判別するには?[#Q611]
~ よく使われる方法は二つあります。

~ <方法1>~
 以下のように、イベントを二つ作成する方法です。
 攻撃 ユニットA ユニットB:
   (AからBへの攻撃イベント内容)
 Exit
 
 攻撃 ユニットB ユニットA:
  (BからAへの攻撃イベント内容)
 Exit

~ <方法2>~
 システム変数「対象ユニットID」などを Party関数に入れ、陣営を判別します。攻撃イベントでは、「対象パイロット」「対象ユニットID」に攻撃を仕掛けた側のデータが、「相手パイロット」「相手ユニットID」に攻撃を仕掛けられた側のデータが入ります。
 攻撃 味方 敵:
   If Party(対象ユニットID) = 味方 Then
     (味方から敵への攻撃イベント内容)
   Else
     (敵から味方への攻撃イベント内容)
   EndIf
 Exit


**Q612. 戦闘時の獲得経験値をすべてゼロにする方法は?&br;      敵撃墜時の獲得資金をすべてゼロにする方法は?[#Q612]
~ 両方とも、おもに二つの方法があります。

(1) すべての敵ユニットの「修理費」または「経験値」をゼロにします。味方ユニットが暴走したり憑依されたり ChangeParty する可能性があるときは、味方ユニットも同様にします。~
(2) すべての味方メインパイロットにパイロット用特殊能力「資金獲得Lv-10」を付けます。またはすべての味方パイロットにパイロット用特殊能力「素質Lv-10」を付けます。(味方パイロットが獲得資金・経験値を増加させるスペシャルパワー・特殊能力を持っていればはずしておきます)

''関連項目:''~
[[Q602. ステージ終了時の残りSPによる経験値ボーナスをやめることはできますか?>#Q602]]


**Q613. 複雑な条件分岐を設定する方法は?[#Q613]

''(1)And や Or 、Not を使う''
~ 複数の条件をともに満たしたときに動作させたいのなら And演算子を、どちらかを満たしたときに操作させたいのなら Or演算子を、条件が満たされないときに動作させたいときは Not演算子を使います。
 # メインパイロットがパイロットPのユニットがアイテムAとアイテムBの両方を
 # 装備しているなら、何かを起こす
 If IsEquiped(パイロットP,アイテムA) = 1 And IsEquiped(パイロットP,アイテムB) = 1 Then
   (処理内容)
 EndIf

 # アイテムAかアイテムBのどちらかを装備しているなら何かを起こす
 If IsEquiped(パイロットP,アイテムA) = 1 Or IsEquiped(パイロットP,アイテムB) = 1 Then
   (処理内容)
 EndIf

 # 相手ユニットがユニットAでもユニットBでもないとき何かを起こす
 If Not (相手ユニット = ユニットA Or 相手ユニット = ユニットB) Then
   (処理内容)
 EndIf

 # パイロットAが出場していないとき何かを起こす
 If Not パイロットA Then
   (処理内容)
 EndIf

~ 以下はもっと複雑な例です。
 # パイロットAが座標 (2, 3) か座標 (5, 7)にいるなら何かを動作させます
 If X(パイロットA) = 2 And Y(パイロットA) = 3 Or X(パイロットA) = 5 And Y(パイロットA) = 7 Then
   (動作内容)
 EndIf

~ こうした場合注意したいのは、演算子の優先順位です。演算子は優先順位の高い順に処理され、この順番を変えるためには半角括弧「(」「)」でくくらなくてはなりません。~
 優先順位は、その他の演算子、Not、And、Or の順ですので、Or の項の中に And を入れる場合には括弧は不必要ですが、And の項の中に Or を入れる場合は項を括弧でくくらなくてはいけません。~
 演算子と優先順位の詳細は、ヘルプの「シナリオの作成」->「式」のページの「演算子」をご覧ください。


''(2)If の入れ子''
~ 「条件1が成立したとき動作1を行い、さらに条件2も成立するなら動作2も行う」など、追加動作がある場合に便利な方法です。
 # メインパイロットがパイロットPであるユニットがアイテムAの装備しているなら
 # 処理Aを起こし、さらにアイテムBも装備しているなら処理Bも起こす
 If IsEquiped(パイロットP,アイテムA) = 1 Then
   (処理内容A)
   If IsEquiped(パイロットP,アイテムB) = 1 Then
     (処理内容B)
   EndIf
 EndIf
~ (1)の方法とくらべ、個々の判別式は単純になるけれど行数は長く複雑になりがちです。場合により、(1)と使い分けます。


''(3)フラグを使う''
~ 特定のできごとがすでに起こったかどうかを条件にする場合は、フラグを使います。ヘルプの「シナリオの作成」->「変数」の最初のほうをご覧ください。~
 以前のステージのできごとを条件にするには、フラグをグローバル変数にします。Set コマンドは変数の値を 1 にセットしますが、Global コマンドは空文字列(数値として扱う場合は 0)がセットされます。


''(4)判別用変数を使う''
~ これはフラグの応用で、条件判別のための変数を準備し、この変数をさまざまなできごとや状態に応じて変化させ、判別時に使う方法です。
 # 味方ユニットの座標(2,3)への進入・ユニットAの破壊・
 # 味方ユニットBの母艦格納の3条件のうち二つを満たした後、
 # 最初の味方フェイズに何かを起こします
 スタート:
   Set 判別変数 0
 Exit
 
 進入 味方 2 3:
 破壊 ユニットA:
 収納 ユニットB:
   Incr 判別変数
   ClearEvent
 Exit
 
 ターン 全 味方:
   If 判別変数 >= 2 Then
     (できごと)
   EndIf
 Exit

 # 以下では、敵ユニットを倒すたびにそのランクに応じた勝利ポイントを
 # 与え、勝利ポイントが 20 以上でエピローグイベントに移ります
 スタート:
   Set 勝利P 0
 Exit
 
 破壊 敵:
   Incr 勝利P Rank(対象ユニットID)
   If 勝利P >= 20 Then
     Continue 次のイベントファイル名
   EndIf
 Exit
 
''(5)Switch を使う''
~ 変数の値によってさまざまに分岐させるには、「Switch」コマンドが便利です。
 # ターン数を判別し、第1〜3ターン、第4〜5ターン、それら以外、
 # で別の処理を行います
 Switch ターン数
   Case 1 2 3
     (1〜3ターンの処理)
   Case 4 5
     (4〜5ターンの処理)
   Case Else
     (その他のときの処理)
 EndSw

''(6)多くの条件の組み合わせで分岐させる''
~ これはさらに複雑な場合で、多くの条件がたがいにからみあいながら分岐させます。これには、諸条件の状態を工夫して一つの判別用変数に整理するとすっきりします。
 # 三つの条件、条件A・条件B・条件Cがあり、全て不成立・条件Aのみ成立・
 # ABが成立…などなどありえる組み合わせすべてで分岐させる
 
 # まず、判別用変数をセットします。
 判別変数 = IIf(判別式A, 1, 0) + IIf(判別式B, 2, 0) + IIf(判別式C, 4, 0)
 
 # これにより、たとえば条件BCのみが成立するとき「判別変数」の値は
 # 0 + 2 + 4 = 6 になります。
 # あとはこの変数を使って Switch か IF で分岐させればよいだけです。
 Switch 判別変数
   Case 0
     (全て不成立のときの処理)
   Case 1
     (Aのみ成立のときの処理)
   Case 2
     (Bのみ成立のときの処理)
   Case 3
     (AB成立のときの処理)
   …(中略)
 EndSw
 
 # 判別変数の値を文字列にする手もあります。
 判別変数 = IIf(判別式A, "o", "x") & IIf(判別式B, "o", "x") & IIf(判別式C, "o", "x")
 
 # この場合、たとえば条件BCだけが成立するとき「判別変数」の値は
 #  "xoo" になります。
 # この方法では、Like 演算子と If を組み合わせることによって、
 # 柔軟な判別が可能です。
 # たとえば以下は、条件ACが成立、Bはどちらでもよいときの判別です。
 
 If 判別変数 Like "o?o" Then
 …

''(7)複数の分岐で処理内容が重複している場合''
~ サブルーチンを活用します。
 # 一つ目の分岐では処理Aと処理B、二つ目では処理Bと処理C、
 # 三つ目では処理Cと処理Aを、この順番で行います。
 If (判別式1) Then
   Call 処理A
   Call 処理B
 ElseIf (判別式2) Then
   Call 処理B
   Call 処理C
 Else
   Call 処理C
   Call 処理A
 EndIf

~ もちろん同じコマンド群を繰り返して書いてもかまいませんが、変更や書き換え作業が煩雑になり、また行数が長くなる分プログラムの見通しが悪くなります。~
 しばしば、Call サブルーチンの代わりに Goto を使いたくなりますがおすすめできません。処理の流れが錯綜し、If〜EndIf や Switch〜EndSw などがどこで終了するのかもわかりづらい、非常にバグが出やすく検査のしにくいプログラムになってしまいます。