FF14棒読みちゃん:スクリプト設定アラーム
スクリプトモードでは、HTML/JavaScript/CSS という、Webページを作成する技術を利用して、
自由度の高いアラーム制御を簡単に行うことができます。
デバッグコンソールも利用可能なので、アラーム開発もスムーズにできます。
※ここではHTML等の各言語に関する説明は行いませんので、ご了承ください。
スクリプト設定アラームの利用時の注意点
特に野良で配布(あるのかな…)されているようなものは、内容を確認してから利用するようにしてください。
アラームマネージャ経由で配布されているものは、作者がチェックしているので安全です。
(まぁ俺が安全だって宣言するのにどんだけ価値があるかわからんですが、少なくとも悪意のあるコードは設定しません。自分のアプリ蹴落とすようなことは意味ないしねぇ)
セキュリティ対策として、ページ移動禁止、隠しフレームや音声再生の禁止、マイク・カメラ禁止などを行っていますが、
それでも完全ではありません。予めご了承ください。
新規作成時
ルートファイル | アラームを稼働させるメインファイルです。作成方法は後述。 |
ウィンドウ | 棒読みやサウンド再生のみの場合は、チェックをはずすと画面表示がなくなります。 |
背景 | 背景色及び透過度を設定します。透過度は「0で透過しない」形になります。 |
開始条件 | FF14のログに、ここで定義したメッセージが出てきたら、アラームが起動します。 「極***の攻略を開始します。」などのメッセージを指定してください。 空の場合は常時起動となります。 |
終了条件 | 同じく、ここで定義したメッセージが出てきたら、アラームが終了します。 空の場合は停止方法がなくなります。 |
アラームファイルの作成
ファイル構成
script_alarms ├ do_not_edit_base.js ├ sample │ ├ sample01.html ★ルートファイル │ ├ sample01.js │ ├ sample01.css │ ... ├ [任意のアラームフォルダ] │ ├ 任意のファイル名.html ★ルートファイル
HTMLからはじまって、そこからJSやCSSを読み込みます。
読み込み元となる HTML を「ルートファイル」と呼びます。
新しくアラームを作る場合は、専用フォルダを1つ作成し、その中に必要なリソースを用意してください。
複数のウィンドウを制御することも可能です。
作成方法(考え方)
・初期表示しておきたいHTML(とCSS)をはじめに書いておく(これはあまりない)
・イベント(ログとか)がくるので、それに応じてコンテンツを書き換える。
後者の書き換えで色々とインタラクティブなコンテンツを作ることで、リッチなアラームを作ることができます。
とはいえ作るの大変なので「このログが出てきたら読み上げする」だけを並べるだけでも、必要なものは作れると思います。
ただし、ユーザ操作は出来ません。alertすると動きますが閉じられないのでご注意。
デバッグ方法
メイン画面の「補助ツール起動」から、「スクリプトアラーム詳細設定」を開きます。
色々な条件がありますが、まずは「アラーム試験」タブにある「デバッグ機能を有効にする」にチェックをいれて、ツールを再起動しましょう。
この状態でアラームが起動すると、edge の開発者コンソールが表示されます。
ff14textreader.vhn というドメインの配下に作成したコードがあります。
あとはブレークポイント入れたり変数の参照したり、開発者コンソールの普通の使い方でデバッグができます。
注意点として、未定義の関数・メソッドや、変数の参照によるエラーが発生しません。
なんでかわかんねぇ…。しれっと処理が中断されます。
特に typo するとハマります。大文字小文字の差で参照できないとかもあります。ご注意ください。
とりあえずガワを用意しよう
・sample01 とかのフォルダをまるまるコピーする。
・フォルダ名と、とりあえずルートファイルである sample01/sample01-a.html だけ、ちゃんとした名前にかえましょう。
とりあえずこれで何かができるので、この時点でアラーム定義の「新規作成時」の作業をしてください。
上から読んでる場合は「後述」って書いてあったのがここの話になります。
ルートファイルのHTMLを見てみよう
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- UTF8で保存してください -->
<!-- ここから編集不可 -->
<meta charset="UTF-8">
<base href="http://ff14textreader.vhn/">
<script src="/do_not_edit_base.js" type="text/javascript"></script>
<link href="/do_not_edit_base.css" rel="stylesheet">
<!-- ここまで -->
<script>
//自分のウィンドウIDを定義
//このHTMLは親ウィンドウなので、空文字列。
//どのアラームでも親ウィンドウはこの値。子ウィンドウを利用する場合は、
//ウィンドウ生成時に指定する。
var ownWindowId = "";
</script>
<!-- 例:処理用JSの読み込み
パスは script_alarms フォルダをルートとした絶対パス表記で記述する。-->
<!-- サンプル:ログ読み上げ -->
<script src="/sample01/sample01-a1.js" type="text/javascript"></script>
<!-- サンプル:リキャスト管理 -->
<script src="/sample01/sample01-a2.js" type="text/javascript"></script>
<!-- サンプル:別ウィンドウ連携 -->
<script src="/sample01/sample01-a3.js" type="text/javascript"></script>
<!-- 例:ローカル以外のファイルを読み込む
普通に読めます。このサンプルでは jquery を多用しています -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
<!-- 例;このアラーム専用のCSSの読み込み
同じようにパス指定する。-->
<link href="/sample01/sample01-a.css" rel="stylesheet">
</head>
<body>
<!-- タイトル -->
<h1>リキャスト管理</h1>
<!-- リキャスト表示領域 -->
<div id="recastArea"></div>
<!-- リキャスト用HTML デザイン例その1 -->
<div id="recastLineTemplate" style="display: none">
<div class="recastLine01-a" id="{ID}">
<div class="titleLine">
<span class="name">旅神のメヌエット</span>
<span class="time">23.4 / 20.3</span>
</div>
<div class="barLine">
<div class="barInner" style="width: 45%"></div>
</div>
</div>
</div>
</body>
</html>
・ウィンドウIDも、とりあえず1ウィンドウで始めると思うので、そのまま残しておく。
・JSとCSSの読み込みを定義する。
※パスの書き方は注意が必要。
・HTML作る。
サンプルで入っているのはリキャスト管理のHTMLなので、
表示領域と、アクション1個分のHTMLのテンプレが書いてあります。
もちろんJSでHTML書いて入れてもOK。
ここは本当にふつーにHTML書く気分でかくだけ。
CSSを見てみよう(自分で)
書くことないくらい普通にCSS定義してるだけ!
JSを見てみよう
表示の都合上、ちょっとコメントとか省略してます。
//サンプル:ログからのテキスト読み上げ
//UTF8で保存してください。
/**
* 初期化
*/
document.addEventListener("DOMContentLoaded", function() {
//イベント受信関数の登録
document.addEventListener("alarm.log", onReceiveLogForReadText);
});
/**
* イベント:ログ受信>テキスト読み上げ
*
* @param {object} e イベントデータ
*/
function onReceiveLogForReadText(e) {
//ログはタイミングにより複数同時に来るので、
//ループしてきたものをすべて処理
for (var i in e.detail) {
//とりあえず1個参照して…
var log = e.detail[i];
//logType1 が18(LS3)であれば
if (18 == log.logType1) {
//読み上げを行う。
AP_ReadBouyomi(log.message, true);
}
}
}
・何か表示変えたりする。
・標準で用意してる特殊な関数も使えるよ。
です。
まずはとにかくイベントドリブンです。
「条件によって色々と画面が変わるHTML(とJS)」を作るわけですが、
その「条件」がイベントです。
それに加えて、このスクリプトアラーム特有の機能が用意されています。
テキストの読み上げとかです。
イベントの拾い方
document.addEventListener("DOMContentLoaded", function() {
//イベント受信関数の登録
document.addEventListener("alarm.log", onReceiveLogForReadText);
});
//イベント受けるほう
function onReceiveLogForReadText(e) { ... }
・どこで定義してもよいですが、まぁDOMContentLoadedかなと。
イベントの種類は複数あります。
また、イベントごとに e.detail にデータが入っています。
詳しくは console.log して確認してください。
概要は以下となります。
イベント名 | データ概要 |
log |
[ { logType0: 0, logType1: 16, name: "Test Tarou", message: "テスト", time: 63783029828920 } ] ・一度に複数のログ情報がくる場合があります。 ・logType については、このページにある「ログ種類の指定方法」をご確認ください。 ・time については、標準で用意している ticksToDate 関数に与えると Date オブジェクトが得られます。 |
player |
{ job: "PLD", name: "Test Jiro" } ・タイミングによっては Unknown とか出てくる場合もあります。 ・name が空なら無視しましょう。 |
pop unpop |
pop はキャラの出現検知、unpop は削除検知です。 いずれも以下のフォーマットです。 [ { name: "Test Saburou", id: 10293940, hpCurrent: 20293, castingId: 0, job: "AST", statusList: [ ... ] } ] ・項目いっぱいあるので記載は省略します。大体キー名からわかるはず! |
update |
ステータス(バフとか)の変動、アクション詠唱を検知します。 ちょっと複雑。 { update: [ { type: 'Add', status: 'Status', statusId: 12345, castingId: 0, actorId: 298372123 } ... ], actor: { 298372123: { name: "Test Shirou", id: 10232832, hpCurrent: 29123, ... } } } update は、ステータスの追加/削除、または詠唱中アクションの変更を表します。 status が 'Status' であれば前者、'CastingID' であれば後者です。 type は Add/Remove/Change(追加とか削除とか)、 statusId/castingId に変更後の値が入ります。 actorId はキャラIDです。この値をキーとして actor にあるデータを参照すると、 そのキャラの各情報が取得できます。 |
特有の機能ってなに?
・全ユーザ情報のリクエスト(通常のイベントでは全部は来ないので)
・テキスト読み上げ
・子ウィンドウ制御(window.open とかは出来ません)
。代わりにこの機能でサブ胃画面的なもの作れます。
・日付変換、ランダム文字列などのユーティリティ
...
などが用意されています。全部グローバル定義。
こちらの詳細については、script_alarms フォルダ直下に置いてある、
do_not_edit_base.js に定義があるので、参照ください。
結局これを使って何ができるの?
出力:HTML上で表現できるものの大半
です。いや出力は結構制限してるけど。その先はアイデア次第。
・特定のチャネルにログが来たら読み上げる(サンプルで作ってあるよ)
・シナジー系アクション発動したら目立たせる(これもあるよ)
・難しいギミックが来たら、あんチョコ画像作っておいて表示させる
・GP全快したら声でおしらせ。
色々できると思います。コーディング大変だけど、興味ある方はいろいろやってみてください(’’
ガチ攻略用にはやっぱり音声がおすすめ。
このツール作るのに「攻略における情報量の強化」があったんだけど、
聴覚を使ってないのもったいなくね?の思いがあった。だから「FF14棒読みちゃん」。
嗅覚とか触覚とかは無理。大技来たら臭くなるとか面白いかもしれんけどさ(’’
ログについて
スクリプトアラーム詳細設定の、その他項において、保存有無や保存フォルダが設定できます。
ログは大きく2種類あります。読みやすい版と詳細版。
読みやすい版の構成
内容はTSVになっており、1-4列目がその行が表すデータの種類など、5列目以降がデータ本体になっています。
全選択してEXCELとかスプレッドシートにコピペすると見やすいです。
各列の情報はイベントの種類によって変わります。
以下の通りとなります。
イベント種類 | 1列目 | 2列目 | 3列目 | 4列目 | 5列目 | 6列目 | 7列目 |
ログ | 時間 | イベント名("log") | logType0 | logType1 | 発言者名 | メッセージ内容 | (空) |
プレイヤー情報 | 時間 | イベント名("player") | (空) | (空) | プレイヤー名 | ジョブ | (空) |
キャラ出現情報 | 時間 | イベント名("pop") | (空) | (空) | キャラ名 | キャラID | (空) |
キャラ削除情報 | 時間 | イベント名("unpop") | (空) | (空) | キャラ名 | キャラID | (空) |
ステータス更新 | 時間 | イベント名("update") | CastingID(詠唱) またはStatus(ステータス変更) | Add/Remove/Change | キャストまたは ステータスID | キャラ名 | キャラID |
詳細版の構成
内容はTSVになっていますが、実際にJS側で受け取るデータがすべて記録されています。
データ量が多いので、何か調査したい場合は、通常ログであたりをつけてから詳細ログを見るようにするとやりやすいです。
各列の情報は以下で共通になります。
イベント種類 | 1列目 | 2列目 | 3列目 |
共通 | 時間 | イベント名 | JSONデータ |