【ココフォリア】疑似カスタムダイス(ブックマークレット)


 ココフォリアでソード・ワールド2.5を遊んでいて、ルールブック掲載の表とチャットログの行ったり来たりが非常に煩わしくなってしまったので事前に作ったダイス表結果をすぐに取得できるようなブックマークレットを考えます。山札作るとかやりようはありますけど、個人的にソレで解決しない場面もあったので……あくまで公式さんがカスタムダイスを導入してくれるまでの場つなぎ案です。

 尚、確認した実行環境はGoogle Chromeだけっす。3万字ほどの文字数制限があったはずなので、長文登録する場合はブックマークレットを分けるなど工夫が必要かも。

ブックマークレットはブラウザのブックマークに仕込めるスクリプトです。当方はchromeユーザーなのですが、ブラウザ上部に表示されているブックマークバーから実行できるというのがスマートで愛用しています。用意したコードをブックマークの本来URLを入れる所に仕込んでおき、実行したいサイト上(今回はココフォリア)で実行するだけで機能します。

 ブックマークレット上でランダムな値を求めてもいいのですが、ダイスがコロコロするのが好きなのでチャットログ上で一度ダイスは振るようにしたいです。なのでチャットログの最後の行を取得し、その値が事前に設定したパターンにマッチしたら結果を返すという形式をとります。

 具体的には「1d4 天気表」といったコメント付きのダイスを普通にチャット上で実行し、これをブックマークレットで取得して「天気表」というコマンドが存在すれば出目に応じた結果を返します(現状「results」に値を格納してますけど、説明(description)みたいな他項目を含めようとしてた名残なのでここはお好みで改修)。

    /* コマンド設定を定義(例) */
    const commandConfig = {
        "天気表": {
            "results": {
                "1": "晴れ",
                "2": "曇り",
                "3": "雨",
                "4": "嵐"
            }
        },
    };

 BCDiceの表示結果は「1d4 天気表 (1D4) > 4」となるので、ダイス部分(1d4)とコメント部分(天気表)と最終的な出目(> 4)の部分を取得……と言った形でコードを実行します。

 ただ、チャットログが流れた場合も踏まえて結果をコピペして入力する用のpromptも仕込んでおこうと思います。

    /* チャット取得 */
    const chatLog = document.querySelector('.MuiList-root');
    if (!chatLog) {
        alert('チャットログが見つかりません。');
        return;
    }
    const messages = chatLog.querySelectorAll('.MuiListItemText-root p');
    if (!messages || messages.length === 0) {
        alert('メッセージが見つかりません。');
        return;
    }
    const lastMessage = messages[messages.length - 1].innerText.trim();

    /* ダイスログを検知 */
    const commandPattern = /^([0-9]+d[0-9]+|[0-9]+d|d[0-9]+) ([^\s]+).*> ([0-9]+)$/;
    let commandMatch = lastMessage.match(commandPattern);
    if (!commandMatch) {
        userInput = prompt('カスタムコマンドが見つかりません。ダイス結果を直接入力することもできます。');
        if(userInput){
            commandMatch  = userInput.match(commandPattern);
            if (!commandMatch) {
                alert('カスタムコマンドが見つかりません。');
                return;
            }
        }else{
            return;
        }
    }

 チャットログからコマンドを検出出来たら事前に用意したカスタムダイスの値を取得。

    /* コマンドを取得 */
    const command = commandMatch[2];
    const resultIndex = commandMatch[3];
    const config = commandConfig[command];

    if (!config) {
        alert(`コマンド「${command}」が見つかりません。`);
        return;
    }

    /* 結果を取得 */
    const result = config.results[resultIndex];
    if (!result) {
        alert(`【${command}(${resultIndex})】\n対応する結果が見つかりません。`);
        return;
    }

 結果を直接ココフォリアのチャット入力フォームに出力したいところでしたが、シンプルにスクリプトで挿入したら上手くチャット上に送信できなかったのでクリップボードに出力されるように。

    /* 結果を出力 */
    const output = `【${command}(${resultIndex})】\n${result}`;
    navigator.clipboard.writeText(output).then(() => {
        alert(`${output}`);
    }).catch(err => {
        alert('クリップボードへのコピーに失敗しました。: ' + err);
    });

 最終的なコードは以下の通り。

javascript:(function(){
    /* コマンド設定を定義 */
    const commandConfig = {
        "天気表": {
            "results": {
                "1": "晴れ",
                "2": "曇り",
                "3": "雨",
                "4": "嵐"
            }
        },
    };

    /* チャット取得 */
    const chatLog = document.querySelector('.MuiList-root');
    if (!chatLog) {
        alert('チャットログが見つかりません。');
        return;
    }
    const messages = chatLog.querySelectorAll('.MuiListItemText-root p');
    if (!messages || messages.length === 0) {
        alert('メッセージが見つかりません。');
        return;
    }
    const lastMessage = messages[messages.length - 1].innerText.trim();

    /* ダイスログを検知 */
    const commandPattern = /^([0-9]+d[0-9]+|[0-9]+d|d[0-9]+) ([^\s]+).*> ([0-9]+)$/;
    let commandMatch = lastMessage.match(commandPattern);
    if (!commandMatch) {
        userInput = prompt('カスタムコマンドが見つかりません。ダイス結果を直接入力することもできます。');
        if(userInput){
            commandMatch  = userInput.match(commandPattern);
            if (!commandMatch) {
                alert('カスタムコマンドが見つかりません。');
                return;
            }
        }else{
            return;
        }
    }

    /* コマンドを取得 */
    const command = commandMatch[2];
    const resultIndex = commandMatch[3];
    const config = commandConfig[command];

    if (!config) {
        alert(`コマンド「${command}」が見つかりません。`);
        return;
    }

    /* 結果を取得 */
    const result = config.results[resultIndex];
    if (!result) {
        alert(`【${command}(${resultIndex})】\n対応する結果が見つかりません。`);
        return;
    }

    /* 結果を出力 */
    const output = `【${command}(${resultIndex})】\n${result}`;
    navigator.clipboard.writeText(output).then(() => {
        alert(`${output}`);
    }).catch(err => {
        alert('クリップボードへのコピーに失敗しました。: ' + err);
    });
})();

 commandConfigの値を追記することでカスタムダイスの種別を増やす事ができる。改行コード「\n」も使える。「ダイスを振る→ブックマークレットを実行→結果を投稿する」の3ステップで結果を共有できる。これでルールブックとの往復をする必要はなくなるかな。

 本当はJSONを外部サイトから取得したかったけど、クロススクリプト対策の都合できません。致し方なし。作ったブックマークレットをGM・PL間で共有すれば多分便利なはず。

 自由に改良・再配布してOK(プロンプトやアラートのポップアップを消したり表示内容を変えたりなどはお好みで)。使えると思ったら卓に役立ててくださいませ。

Posted in TRPG