【ティラノスクリプト】テキスト表示ごとに既読にするプラグイン

以前、下記の記事を書きました。

【ティラノスクリプト】改ページクリック待ちごとに既読にするプラグインの作り方

ずっとそのまま弄らず使っていたら、最近不具合に気づいたので改善したいと思います。

経緯

以前から不具合があったのに気づいていなかったのか、最近ティラノスクリプト本体をアップデートしたから不具合になったのか定かではないのですけれど、v521f(2023/3/27 安定版)だと以下のような症状が出ていました。

手順

  1. 現在表示しているテキストが未読の状態でセーブする
  2. そのままテキストを読み進めて既読にする
  3. 手順 1 のセーブデータをロードする

この手順で、期待する結果は「セーブしたときに表示していたテキストの次のページのテキストは既読である」です。
しかし改ページクリック待ちごとに既読にするプラグインだと、次のページのテキストまで未読になっていました。

原因を探るため、テキストの既読判定を司る label タグの start 処理の様子を確認しました。
改ページクリック待ちごとに既読にするプラグインで生成したラベルがいつ label タグの start 処理を通過しているのか見てみると、生成したタイミングではなく、次のラベルを生成したタイミングで通過しているようでした。
私が思っていたよりワンテンポ遅れているというイメージです。

また改ページクリック待ちごとに既読にするプラグインを削除し、シナリオ内に手動で 1 行ずつラベルを配置したときの挙動を調べたところ、セーブデータをロードしたときは下記のような特徴があります。

  • 現在表示しているテキストが未読の状態でセーブした場合、その表示テキストがその後既読になっても、ロード時は必ず未読のテキストとして表示される(テキストの既読色の設定が適用されない)
  • テキストの既読判定を司る label タグの start 処理が、2 回改ページするまで呼ばれない
    • おそらく正確には「2 回改ページする」がトリガーではないのだが調べ切っていない

この挙動から考えるに、セーブしたときに表示していたテキストの既読判定はロード時には行われず、セーブ時の既読判定結果を再現するのだと推測しました。

そして私の改ページクリック待ちごとに既読にするプラグインの「私が思っていたよりワンテンポ遅れている」という点がロード時の仕様とうまくかみ合わず、次のページのテキストまでセーブ時の既読判定結果を再現してしまうのだと思います。

改善する

どうやって改善するかというと、結論としては既読判定用ラベルの生成処理を改ページクリック待ちごとではなくテキスト表示時に変更します。

なぜこれでうまくいくのか? はよくわかっていませんが、テキスト表示時にラベルを生成すると、既読判定がワンテンポ遅れないんですよね。
たぶんティラノスクリプトの処理の順番の問題なのでしょう。

ということで新しいプラグインはこれです。

(function ($) {
  (function () {
    // デフォルトの [text] を変数に保存する
    const _text = TYRANO.kag.ftag.master_tag.text;
    // デフォルトの [text] の showMessage を独自の関数で上書きする
    // showMessage 以外の定義は引き継ぐ
    TYRANO.kag.ftag.master_tag.text = $.extend(true, {}, _text, {
      // showMessage の引数の数はティラノスクリプトのバージョンアップで変わる可能性があるので Rest parameters で纏めて受ける
      // 引数は今のところ message_str,is_vertical
      showMessage: function (...args) {
        // 適当にメッセージの一部を使用し、ゲーム更新で行番号が変わってもなるべく既読情報が壊れないようにする
        // ラベル名に%が入っているとエラーになるので消す
        const prefix = encodeURIComponent(args[0].slice(1, 6)).replace(/%/g, "");
        TYRANO.kag.ftag.startTag("label", {
          label_name: `sk${prefix}_${TYRANO.kag.ftag.current_order_index}`,
          nextorder: "false",
        });
        // デフォルトの showMessage を実行する
        _text.showMessage.call(this, ...args);
      },
    });
  })();
})(jQuery);

中身は前回と大体同じです。

変えたのは、せっかくテキスト表示時のタイミングなのでラベル名にテキストの一部を使用し、ゲーム更新時に行番号がずれても既読判定がなるべく壊れないようにしたところです。
(ラベル名が長すぎてセーブデータを圧迫しないかどうかが不安なところです。)

また注意点として textshowMessage は引数を取ります。
今は message_str,is_vertical の 2 つが引数ですが、ティラノスクリプトの更新で引数が増えることは考えられるので、...args で纏めて全部受け取っています。

ただティラノスクリプトの更新を行ったときに引数が変わっていないか調べたほうがいいとは思いますね。
第一引数が表示テキストである前提でプラグイン書いてるので、この順番が変わったら壊れますからね。
showMessage の第一引数が表示するメッセージでなくなるような変更はあんまりやらないとは思いますが……。

おわり