2022-11-26

RGSS-イベントスキップ機能

Comment ShareLink
«RGSS一覧/利用規約

周回RPGやマルチエンド型のアドベンチャーゲームを制作・プレイするにあたって「長いイベントや既に見たイベントはスキップしたい!」と思ったりしませんか?
度々創作界隈で話題に上がりますが、チュートリアルやオープニング、各所演出で時間をかけたくないプレイヤーさんが多数派だというお話があったり、デバッグを繰り返す身としても時間のかかるイベントはある程度飛ばしたいもの……

今回はちょっとフクザツな実装になるのですがイベントスキップ機能の組み込みをしていきます!!!
こちらの機能はSilverHearts作品ではちょいちょい実装していて、たらたら文字スクリプトにも同じように実装できます。
難点はあちこち追加したり、エラーチェックに手間がかかることでしょうか。
(メッセージ表示中や画面スクロール中にスキップしても問題ないか、などなど…)


【今回の変更点】
・Scene_Map
・Game_Map
・Window_Message
・Interpreter

■Scene_Map

ひとまず、Scene_Mapで形だけ「イベントスキップする?しない?」の選択肢を作ります。

スクリプトを追加するのはupdateメソッド。
def update内の$game_temp.message_window_showingの上あたりにでも書いておきましょう。
※下記記述はスペースを全角にしているのでご注意

#インタプリターが実行中でイベントスキップがnilではない場合
if $game_system.map_interpreter.running? and $eventskip != nil

 # Qキー(L)かWキー(R)が押されたら選択肢表示
 if Input.trigger?(Input::L) or Input.trigger?(Input::R)
  # コマンド表示
 select = Window_Command.new(240,["イベントスキップ","このまま続ける"])
 # 他の表示とかぶらないように奥行きを指定
  select.z = 999

  # 選択処理をループ
  loop do
   select.update
   Input.update
   Graphics.update
   # 決定ボタンが押されたら    if Input.trigger?(Input::C)
    case select.index
    when 0 # イベントスキップ
     # 決定音      $game_system.se_play($data_system.decision_se)
     # ★スキップするよーの合図。
     $skip_on = true

     # ラベルジャンプを実行 ※Interpreter参照
     $game_system.map_interpreter.command_119
    when 1 # このまま続ける
    # キャンセル音
     $game_system.se_play($data_system.cancel_se)
    end
    # ループ終了
    break
   end
   # キャンセルボタンが押されたら
   if Input.trigger?(Input::B)
    $game_system.se_play($data_system.cancel_se)
    break
   end
  end
  # ↑ループ終了

  # 選択ウィンドウを解放
  select.dispose
 end

end

青い文字に注目。
$skip_on
$eventskip
これは今回の機能実装でスイッチとなる変数です。
グローバル変数なので、ゲームをF12などでリセットした場合にそのままになってしまうので、Scene_TitleやGame_Tempなどわかりやすいところでゲーム開始前に初期化しておきます。
$skip_on = false
$eventskip = nil

こんな感じです。
$skip_on がスキップ実行したかの判定に使用する変数で、trueの時に各所で処理を終わらせる合図になります。
$eventskip がスキップするラベル名を格納する変数になります。使わない時はnil指定でスキップするかどうかの選択肢は無効化されるという仕組み。

ここまで、選択肢を出して「ラベルジャンプ」を実行するまではわかったと思います。
もちろんこのままでは対応しておらずエラーが起きるだけなので、Interpreterのほうもいじっていきます。

■Interpreter

「Interpreter 3」を開き、下にあるラベルジャンプのメソッド
def command_119 ここを改造。

# ラベル名を取得
# $skip_onのとき $eventskipで指定したラベル名にジャンプ、nilなら通常のコマンドからのラベルジャンプ適用
label_name = $skip_on ? $eventskip : @parameters[0]
# 実行したら$eventskipをnilにしてマップで選択肢を出さないようにする
$eventskip = nil

これで選択肢でイベントスキップを選ぶと、$eventskipで指定した名前のラベルにジャンプするようになりました。

……しかし
ラベルまでジャンプするだけで、ウェイトやメッセージ処理、キャラクター移動、スクロールなどの処理はこのままでは中断されません。

ウェイトに関する処理は同じくInterpreter内で行われているので、まずはそこを改造します。
いじるのは「Interpreter 1」の updateメソッド。
そのループ内にスクリプトを追加します。
目安としては「子インタプリタが存在する場合」の上あたり。

# スキップ処理が実行されたら
if $skip_on == true
 # ウェイトカウントを絶対的に残り1にする
 @wait_count = 1
 # 移動完了待機中フラグをクリア
 @move_route_waiting = false
end

これで実行中のウェイトや移動完了待機がキャンセルされます。
他にもイベントスキップのためにキャンセルしなければならない部分が残っているので、引き続き改造していきましょう。

■Game_Map

次に、スキップが実行されたらマップのスクロールを中断する仕組みを作ります。
updateメソッドの「スクロール中の場合」if @scroll_rest > 0…がスクロール処理となっているため、この上の行にイベントスキップ機能の処理を記入します。

# イベントスキップが実行された
if $skip_on == true
 # スクロール距離を0にしてスクロール終了
 @scroll_rest = 0
end

■Window_Message

メッセージ表示の最中にイベントスキップすると、ウィンドウが残ったりメッセージ処理が続行されたままになってしまうので、ここにも中断させる仕組みを作っておきましょう。

# イベントスキップが実行された
if $skip_on == true
 @fade_in = false
 # メッセージ終了処理
 terminate_message
end
SilverHeartsが配布している「たらたら文字スクリプト」の場合は、同じくupdateのsuperの下に記述して
@next_message = falseを追加すればOK(ウィンドウ続けて表示機能処理の変数)

★イベントコマンドで組み込む

以上でイベントスキップ実装の難しいところは終わりです。
あとはイベントコマンドで組み込んで、実際にイベントスキップさせてみましょう。

  1. イベントコマンドの最後にある「スクリプト」で、スキップラベルを指定
    例:$eventskip = "ここにスキップ"
  2. スキップ地点に指定した名前と同じ「ラベル」を設置
    上記例なら ここにスキップ
  3. イベントスキップが不自然にならないように適宜調整

適宜調整、と書きましたが
具体的な方法としては

通常では通らないように「条件分岐」にスキップ地点を入れて→「トランシジョン準備」で画面を固定→画面色調やキャラクター移動などの処理を入れる→「トランシジョン実行」

といったような処理を行えばスムーズかなと思います。
工夫してみるとより良い演出ができる……のではないでしょうか!(投げやり)


今回はあちこち追加したりと面倒ですが、うまくいけばプレイ時間やデバグの短縮に使えます。
これ自体がバグってしまうと困るので、しっかりバックアップをとったり、テキトーな新規プロジェクトを作って試してから実装するなどしてみてください。

エラーの対処として、どの変数が何に関係しているか、どう連動しているか考えて理解することもまた大事です。
理解しようとしてはいるものの、自分もよくわからなくなるんですが。。。

案の定、この機能は特にメッセージ処理中の部分に結構頭を痛めたもので、
一応配布中の「たらたら文字」にも対応してはいるのですが、お恥ずかしながらあれこれいじっている内にこんがらがってしまうことがあります(笑)
たぶん、配布しているものはシンプルにまとめているので大丈夫なはず。
まだまだWin11でもツクールXPは動くので、まだ愛用していけたらいいですね…

category:

コメントを投稿