【ティラノスクリプト】プラグイン作成実績解除のどうでもいいかもしれない制作話(JavaScriptで新規タグ作るタイプのプラグインのテンプレアリ)
ティラノスクリプトのプラグイン作成実績解除!!!しかも二本!!!!
そして反応を見るにやはり通知表示は皆さまお待ちかねって感じだったのだろうか……(なお反応の感触にノミの心臓がビビっている)
入手は以下からどうぞ
1.なんでんなもん作ろうと思ったのか
↓こっちの「2.技術的実験周りについて」の①とか②とかでも触れてるんだけど
実況とか配信してくれる方いらっしゃるじゃないですか。
まあ、私はね、親が昔からゲームやる人(それこそDQ、FF、ポポロクロイスとか……クロノトリガーもあったな)で、それを見て育ったせいで逆にゲーム下手なタイプというあれなんで、個人的には自分のゲームが配信・実況されるの全然OKだし、なんなら自分の創作物で人がどういう反応するのか、あわよくば見たい、めっちゃ見たい、すんごい見たい、なので全然いい派なわけなんですけど……(なお一番ダメなのはアクション。某配管工すらダメ。ピンクの丸い悪魔ぐらいしかできない)
で、ノベコレのブラウザ版やってる場合なら、バッジ取得時は基本的には画面上にかぶさる形で「こんなバッジ取得できるぞなもし!」ってなるので、そのままでよくって、別にこの点は考えなくてもいいわけですよ。
ただ、DL版をやっていただく場合に、わざわざDL版でやる意味を考えると(もちろんDL版の方が動きがさくさくはするはずだけど)、ノベコレバッジ処理通過でブラウザ起動しちゃうのって……
「もしかしたら、実況する人的によっては邪魔なのでは!?」
ってなったわけですよ。
だって突然ブラウザ開くから普段使いのブラウザでタブ保存してたらそれ丸見えになっちゃうし、すでにブラウザ起動してても、たぶんゲームからブラウザにウィンドウのフォーカスも移っちゃうし……(そこは配信時のキャプチャ設定の指定によっても弊害の有無ありそうだけど)
だったら、DL版でだけノベコレバッジ取得処理ON/OFFできないかなってなって、そこから更に、「でもバッジ取得の条件自体は満たしてるんだからいわば実績解除って通知みたいなのも必要じゃね?」から通知表示プラグインも作ろうってなったわけだわさ。
2.それぞれのプラグイン構成のざっくり概要
①ノベコレブラウザ起動判定&バッジ機能ONOFFプラグイン
フォルダ階層としては
badge_checkフォルダ
└init.ks
これだけです。badge_checkフォルダをプロジェクトフォルダ>data>others>pluginに配置して、first.ksで[plugin name="badge_check"]ってすれば使える。
jsファイルやcssファイルがないので、つまり、ほぼティラノスクリプトのマクロとティラノ内に仕込んだちょっとのJavaScriptだけでできてる。
なのでこっちは作り方に迷うことはなかった。
まあ、init.ksのラベルからパラメータで渡ってきたシナリオファイル名とターゲットラベル名でjumpでscenarioフォルダの方に戻れるかちょっと心配はしたけど、サンプルシナリオ無事動いたから平気平気。
ただ、実際のバッジ取得処理には本家の配布してるnovecole.ksが必要だから、それはそれで別途必要なんだけど、配置場所はscenarioファイルって言われるからね、これ。
↓本家のnovecole.ks配布ページ
更に通知表示プラグイン側とも連動できるようにしております。これは同作者だからこその対応の速さよ、ふふふ。
まあ、実際の動きはプラグインと一緒に配布してるサンプルシナリオやってもらうのが一番速いんだぜ。
②通知表示プラグイン
こっちはある意味順当なフォルダ階層
notify_showフォルダ
├init.ks
├main.css
└main.js
たぶんティラノのタグ書き換え・タグ追加系プラグインではよくある構成。
notify_showフォルダをプロジェクトフォルダ>data>others>pluginに配置して、first.ksで[plugin name="notify_show"]ってすれば使える。
cssはともかく、jsの方は、うん、あのね、スキップ考慮や座標計算が難しかったよ……
3.プラグインの中身についてあれこれ――ノベコレブラウザ起動判定&バッジ機能ONOFFプラグイン編
①DL版かどうかの判定をどうやってやってるか
てってれ~♪、JavaScript~♪(某青いネコ型ロボット風)
いや、真面目に。
というのもJavaScriptの中にlocationという情報がいます。
なんというか、こいつはすでに最初から出来上がってるオブジェクトです。
ここに何が入ってるかというと、現在いるページのURL情報です。
サイトとしては、以下が詳しいかな。
で、今回必要なのは↑のページで書いてある内の「location.hostname」です。
ここにはURLのホスト名の部分が入ってきます。
といってもわからん人には何処だかよくわからんのはそうだよね。
というわけで自分の以下の記事でデバッグツール開いて実行した結果がこちら。
はい、というわけで「https://note.com/itksk_ayame_gsk/n/n6a91593215f1」というURL文字列の内、「https://」の後ろからその後の「/」までの間の「note.com」がホスト名というわけです。
で、そうなると、ノベコレはトップが「https://novelgame.jp/」で、各ノベルゲーのトップページは「https://novelgame.jp/games/show/10707」みたいになります。
なお、このURLは私のあれじゃ、リメイクした1作目じゃ↓
とまれ、ということは……「location.hostname」で取って来た文字列が「novelgame.jp」とイコールであればブラウザ版、そうでなければDL版って判断できるんじゃ!? となりますが、ここで落とし穴。
ノベコレの実際のプレイ画面URL=ゲーム実行時URLはこうなんじゃよ。
というわけでifの条件を単純比較する(つまりlocation.hostname=="novelgame.jp"ってする)のでは判別できません。
ただ、ホスト名にnovelgame.jpと入ってるのは間違いない……はず!
というわけで、チキチキ正規表現のお時間でーす。
はい、私、お仕事でもサクラエディタ使い、正規表現置換お手の物の民(∵)
上司に感心半分引かれたことがあるぐらい、ゴリゴリ正規表現置換でログからほしいデータ成形して引っこ抜いたりしてた。
正規表現とは、比較する文字列にある程度の範囲で揺れを持たせて判別する(よくある例だと「\d{3}\-\d{4}」で郵便番号チェックするとか)、みたいな感じですが、まあ、今回の正規表現くんは単純文字列ベース(その文字列含むかどうか)なのでそんな大したことない……もっとすげえ正規表現はあるし、作ったことある……
まあ、今回、ホスト名の中に指定した文字列が入ってるか、が論点で、その文字列自体は固定ですからね。
//正規表現作成(.は正規表現上で意味があるから\でエスケープする)
let rgx =/novelgame\.jp/;
//ティラノ一時変数(tf)のpb_m_novecole_chkってところに作成した
//正規表現オブジェクトでlocation.hostnameへのtest実行結果を格納する
tf.pb_m_novecole_chk = rgx.test(location.hostname);
JavaScript上、正規表現は文字列とは違って正規表現オブジェクトになります。
なので↑の処理でもクォーテーションで囲むんでなく、「/」で囲む。
この「/」を正規表現の範囲を示すためデリミタと呼んだりしますが、JavaScriptの正規表現オブジェクトはこの「/」デリミタ使用か new RegExp( "通常の文字列と同じ扱いでデリミタ無しの正規表現", 正規表現の検索フラグ )で作ります。
まあ、今回は特段検索フラグいらないから省いてるんだけど、「/」デリミタ使用で正規表現オブジェクトを作成する場合の検索フラグは「/正規表現文字列/フラグ」って感じで書きます、絶対にクォーテーションで囲っちゃだめ。
で、正規表現オブジェクトは最初からtestって関数を持ってます。
あんまプログラミング詳しくないよって人は関数はティラノのタグとか、マクロとかサブルーチンだと思っといて。
で、この「正規表現オブジェクト.test()」の「()」の中に「その正規表現で検索をかけたい文字列」を渡すと、検索に引っかかればtrue、引っかからなければfalseが返ってきます。
プログラミング詳しくない人に重要なのは、このtrueとfalseはクォーテーションで囲われないものであるって点ですからね。
いわゆるboolean値ないしbool値。または真偽値と言われるtrue/falseの二択の型です。
こいつを比較する時には、ifタグでの比較時にはexpのクォーテーションで囲われた中でもっかいクォーテーションでは囲っちゃだめ(〇「exp="tf.pb_m_novecole_chk==true"」、×「exp="tf.pb_m_novecole_chk=='true'"」)だぞ。
というわけで、↑の処理を使用すれば、DL版かノベコレのブラウザ版か、は判定できるはずで、実際できた(例の「ひとりかくれんぼの相談」で実験)
そしてこの実験結果を元に、今回のプラグインの作成をしました!
②そして立ちはだかる切替コンフィグと救済措置
が! 実際バッジ取得機能をON/OFFさせるってえなるとですね、コンフィグに追加が一番いいんだけど、場所がね……というわけで、プラグインに同梱してるサンプルにはコンフィグ用画像と対応したconfig.ksも一緒に入れてます、参考にしてくらはい。
後はバッジ回収救済措置。特に長いゲームだと余計に必要性が高いと思われ。
あれってブラウザ上に表示された後にちゃんと「取得する」を押さないとゲットできないから、うっかり消すと悲惨なんだわ。
ということで、一応プラグインのzipファイルの中に、個人的に自分の作るゲームで搭載するつもりの、バッジコレクションルーム(同時に救済措置搭載)のテンプレートを突っ込んどきました。
あれは戻るボタン画像のbuttonタグで用意したり文字表示をなんのページかをptextで表示したりしてるけど、たとえば制作ナンバリングが2のやつのコレクションのバッジページはこう↓(なお、うっかりノベコレバッジ上限知らなくて作り過ぎたので、他はゲーム内実績バッジとなっている故に3ページもある)
で、未回収バッジをクリックしたら、対象のヒントがメッセージウィンドウに表示されるのはコレクションの動きとして一般的だろうと思われるのでいいとして、回収済みでこの画面でバッジ画像が表示されるものについては、ここに救済措置をセットしました。
つまり、上のプラグインについてのところで話した、[pb_m_give_emblem]タグ(マクロ)を実行した場合に、「バッジ取得状況管理オブジェクト(sf.pb_m_getbadge_get_mng)」のバッジのid、pidに対応する部屋に「1(ノベコレバッジとしての回収表示がされた)」か「2(ノベコレバッジ取得がOFFだったけど回収箇所は通った)」が保存されるのは、この救済措置を実行するかどうか判別するための目安となるものとして、異なる数値を入れました。
そして「バッジ取得ON/OFFフラグ(sf.pb_m_getbadgeswitch)」が「0/1/2」の3パターンなのもそう。
そもそもの「バッジ取得ON/OFFフラグ(sf.pb_m_getbadgeswitch)」が「0:ずっとバッジ取得ON」であるならば、ノベコレブラウザでやっているか、DL版でも一度もバッジフラグをOFFにしなかったプレイヤーです。
うっかりしない限りは取り逃しはないはずだし、そのうっかりしちゃう人がどれだけいるか、と考えると普通、少数で、だからこそ切り捨てというのも(特にSE・PG的に工数とか納期があるものならば)考えなければならないと言えばならないのですが、まあ、そこは置いといて。
「0:ずっとバッジ取得ON」ではなく、「2:一度どこかでOFFにしたON」であるならば、OFFの必要性があるプレイを終えて、バッジを集めようとONにした可能性が考えられます。
であれば、この「2:一度どこかでOFFにしたON」の状態でバッジを求める人はよりいっそう、自身の意思でバッジ取得機能をOFFにしたものの、その時点では意図的にバッジを欲している、ということになります。
「0:ずっとバッジ取得ON」でのうっかり取り逃しは実はプレイヤー側の操作という非がプレイヤー側にある(責めてるわけではなくて、作る側の想定動作に対してという意味で)のに対して、「2:一度どこかでOFFにしたON」状態というのは意図的にバッジ取得ON/OFFすべて行っているわけで、そうなるとプレイヤー側に基本非はなく、であるならば、然るべき補填措置があるべき、となります。性善説に基づいた時の設計思想的に。
まあ、とはいえ、結局、「本当にそのプレイヤーがノベコレユーザとしてそのバッジを取得しているか」、というのはゲーム側では観測不可(実際観測するにはノベコレサーバへの通信とバッジの情報とプレイヤーのノベコレユーザ情報ががっつり必要になってくるし、さすがにサーバ通信するのはアレだし、ユーザ情報はそうそうわからないし)なので、うっかり取り逃しさんも一緒に救済措置にするというのが親切だし、ifタグ的には無駄が省ける。win-winまたは三方良し。
③実際のプラグイン外の手間について
正味、バッジコレクション画面の配置とコンフィグ画面の画像作りと位置調整がめんどいくらい、かと個人的には思います。
それでも、一度作れば使い回しはきくから楽(コンフィグ画像とかはデザイン変えるにしても、上から同じ位置に同じ項目配置してけばいいって話で)なので、同梱したやつをうまく使って欲しい。
そして、別にバッジ取得管理とかいらないって人も、これでブラウザ起動か/DL版起動かが判別できるので、メタ的なネタとか仕込めるよ!!!!
4.プラグインの中身についてあれこれ――通知表示プラグイン編
①(JSテンプレココ)そもそも、現動作にないことをするためのタグ作るプラグインってどないして作ればええんや……?
引数とか、必須項目とかってどないすんのや……?
出だしからこれである! 泣けるね。
とはいえ、ならば……先人の叡智の結晶を舐めつくして解析してお借りするのがプログラマー的腕の見せ所……!!!!(べろべろべろべろ)
というわけで以下のプラグインを参考にさせていただきました。感謝。
圧倒的感謝。
ねこの様 カスタムルビプラグイン
※参考ポイント ティラノ既存のrubyタグを根本から書き換えているため、rubyタグで必須となるパラメータtextの扱いやねこの様が追加された各種パラメータの扱い方がわかる。
脳硝子様 ウェイト追加機能プラグイン
※参考ポイント:「wait_plus」という既存にないタグの作成をしているため、既存にないタグの作成の仕方がわかる
おぎはら様 ポポポ音プラグイン
※参考ポイント:脳硝子様のウェイト追加機能プラグイン同様、「popopo」という既存にないタグの作成をしているため、既存にないタグの作成の仕方がわかる。また、タグ作成より前にタグの実行時の仕込み処理が含まれているため、その辺りの設定の仕方もわかる。
※なんなら、ポポポ音プラグインはV525対応(markとrubyの処理)するためにガチバトルもしたので、とてもとても理解が進みました。本当にありがとうございます。
ガチバトルの成果↓
結果:はーん、なるほど、メインのJavaScriptは読込後起動の処理にして、JSONに任意タグ名=キーでさらにJSONとパラメータの初期値とstartってキーでメイン処理の定数作って最終的にオブジェクトとしてティラノオブジェクトのタグ一覧の作成したい任意のタグ名の部屋に突っ込むのか〜、ふ〜む。
で、メイン処理ではパラメータ初期値一覧を引数受ける変数にまずセットしてから、引数の状況に応じて渡された値をセットと……なるほどね〜
これをひな形にするとこんな感じ↓
(function(){/*←この(function(){の中に書くことで、以下の処理が全体読み込み後の起動になる*/
//設定前処理するならココ
const 任意の定数名={
vital: [ここに必須にしたいパラメータを文字列配列にして記述],
version:"1.0",
pm:{
//デフォルトパラメータ
//必須じゃないパラメータを{}でくくってるのでJSON形式で「パラメータ名:初期値」で記述
},
start:function (pm) {
//デフォルトパラメータを任意の変数にぶっこ抜いて
let 任意の変数名=JSON.parse(JSON.stringify(任意の定数名.pm));
//引数に対象パラメータがいたら各項目上書きする
//(基本コピペで使うと短縮一行if文だけどパラメータの性質によってはちゃんとしたif文にした方が良い)
if (pm.対象のパラメータ名 !== "") 任意の変数名.対象のパラメータ名 = pm.対象のパラメータ名;
//↑の引数pm=引き渡されたパラメータを任意の変数に埋める処理が終わったら
//ここからJavaScriptの本処理書いてく↓
//JavaScript本処理
//最後になる処理の後に必ずティラノの次行実行の処理を呼び出す
//(つまりここからシナリオファイルの本処理に戻るってわけ)
TYRANO.kag.ftag.nextOrder();
}
//なお、この「任意の定数」JSON形式なので、もし関数を分けたりするなら普通に任意の名前で追加が可能。
//ただし、JavaScriptの処理を完結させてティラノ側に戻る場合は
//必ず「TYRANO.kag.ftag.nextOrder();」を実行しないとティラノ本処理に戻れなくてフリーズするので注意
};
TYRANO.kag.ftag.master_tag.作りたいタグ名 = object(任意の定数名);
TYRANO.kag.ftag.master_tag.作りたいタグ名.kag = TYRANO.kag;
})();
なお、複数タグをいっぺんに作りたい場合、任意の定数の内容を複数持つJSON定数作って(この時、任意の定数の部屋の名前は作りたいタグ名に合わせるべし)、最後にfor in使ってティラノのタグオブジェクトに突っ込んでくのが楽……うん、ひな形、こう↓
(function(){/*←この(function(){の中に書くことで、以下の処理が全体読み込み後の起動になる*/
//設定前処理するならココ
const 任意の定数名={
作りたいタグ名1:{
vital: [ここに必須にしたいパラメータを文字列配列にして記述],
version:"1.0",
pm:{
//デフォルトパラメータ
//必須じゃないパラメータを{}でくくってるのでJSON形式で「パラメータ名:初期値」で記述
},
start:function (pm) {
//デフォルトパラメータを任意の変数にぶっこ抜いて
let 任意の変数名=JSON.parse(JSON.stringify(任意の定数名.作りたいタグ名1.pm));
//引数に対象パラメータがいたら各項目上書きする
if (pm.対象のパラメータ名 !== "") 任意の変数名.対象のパラメータ名 = pm.対象のパラメータ名;
//↑の引数pm=引き渡されたパラメータを任意の変数に埋める処理が終わったら
//ここからJavaScriptの本処理書いてく↓
//JavaScript本処理
//最後になる処理の後に必ずティラノの次行実行の処理を呼び出す
//(つまりここからシナリオファイルの本処理に戻るってわけ)
TYRANO.kag.ftag.nextOrder();
}
//もちろんここもJSON形式なので、もし関数を分けたりするなら普通に任意の名前で追加が可能。
//ただし、JavaScriptの処理が完結する時には必ず「TYRANO.kag.ftag.nextOrder();」を実行しないと
//ティラノ本処理に戻れなくてフリーズするので注意
},
作りたいタグ名2:{
vital: [ここに必須にしたいパラメータを文字列配列にして記述],
version:"1.0",
pm:{
//デフォルトパラメータ
//必須じゃないパラメータを{}でくくってるのでJSON形式で「パラメータ名:初期値」で記述
},
start:function (pm) {
//デフォルトパラメータを任意の変数にぶっこ抜いて
let 任意の変数名=JSON.parse(JSON.stringify(任意の定数名.作りたいタグ名2.pm));
//引数に対象パラメータがいたら各項目上書きする
//(基本コピペで使うと短縮一行if文だけどパラメータの性質によってはちゃんとしたif文にした方が良い)
if (pm.対象のパラメータ名 !== "") 任意の変数名.対象のパラメータ名 = pm.対象のパラメータ名;
//↑の引数pm=引き渡されたパラメータを任意の変数に埋める処理が終わったら
//ここからJavaScriptの本処理書いてく↓
//JavaScript本処理
//上のJSON内に処理追加できるけど、最後になる部分で
//必ずティラノ処理に戻るやつ入れなきゃいけないってのは(↓finish参照)
任意の定数名.作りたいタグ名2.finish();
},
finish:function () {
//JavaScript本処理
//こういうこと(なおfinishは仮の名なので任意の名前でいいよ)
TYRANO.kag.ftag.nextOrder();
//逆にこれ以降になんかしらの処理おくなら動作的にsetTimeoutを挟む必要があるはず&
//ティラノの動きの流れとは別の動きの流れ(いわゆる非同期処理)となるので注意
}
},
任意の名前:function(引数){
//これでこのオブジェクト内の汎用関数も作れちゃう!!
}
};
//まあ、ここでしか使わない汎用関数ならこうしてもいいんだけどね。
//任意の定数名2.任意の名前(引数)で呼び出せる
const 任意の定数名2={
任意の名前:function(引数){
//これでこのオブジェクト内の汎用関数も作れちゃう!!
}
};
//ループでティラノのタグオブジェクトにぶちこんでく
for(let k in 任意の定数名){
TYRANO.kag.ftag.master_tag[k] = object(任意の定数名[k]);
TYRANO.kag.ftag.master_tag.[k].kag = TYRANO.kag;
}
})();
ね、簡単でしょ? なわけあるかい。
いや、理屈としての構造はね、まあね、わかった。こうしてテンプレ書けるぐらいに(なお個人の解析結果なのでなんか間違いあるかもしれないけど、ただ、大体はこう)
ただ……実際に私のやりたい挙動をJavaScriptで組むにあたっては……どうかな!? という問題があるだけ(実際計算地獄を見た)
②そして処理作成編――計算地獄とスキップ考慮で(頭が)ぽぽぽぽーん
さて、とりあえず、まずはやりたいことやらせるために必要な事をまとめました。
右上ににゅっと出す
通知したい文章と、パラメータで来てたら画像を出す。
↑をある程度の時間したら自動で引っ込ませたい(けどゲーム本体はこの間も進む)
文章だと簡単ですね。言うは易し行うは難し……かあ……
とはいえ、この羅列した動きの制御自体はある程度CSSでできます(最終的にパラメータ化した結果パラメータ地獄になってるけど)
ということで、ベースのHTML構造とCSSをざっくり構想して、ががっと簡易確認用HTMLファイル作ってCSSくんで様子見つつ、デフォルトのHTMLとCSS設定作成。
HTMLとCSSはね、簡単なんだ(吐血)
実際、HTMLとCSSとの仲は小突き合うレベルでJavaScriptは取っ組みあうレベル感だからな。
まあ、結局、デザインの自由度を鑑みた結果、なんと、最終的にパラメータがどちゃくそ多くなりました。
そしてここからが地獄のJavaScriptよ。
とはいえ、テストレベル、一つ表示するだけは簡単に行きましたとも、ええ。
問題はな、「連続使用に対する直感的動作」だった。
だって連続で使った時にはさ、こう、縦に並んで、最初のが引っ込んで、その次に表示されてるやつは上に位置ズレてほしいよね、それが直感的動作ってやつだよねー……
となると、まず、画面上に通知がいくつ出てるかと、どの通知が何って判別を付けられなきゃいけない。
そこで爆誕したのが内部グローバルのカウンタとそいつらのid的クラスを保管する配列。
横位置調整は基本は指定幅+左右padding、で画像が配置されてた時は画像の左右マージンも追加した最終的な表示時の幅を算出してマイナスにしたのを初期セットしてるんだけど、それに加えて縦位置を、現在表示されてる最後のやつのtop位置(こいつは要素の上辺縦軸座標になるので)と高さ(top位置+こいつで下辺縦軸座標になる)を取得して加算して、さらに間隔25pxを加算してそれで縦軸計算してstyleにセット。
後はsetTimeoutを利用して、表示のため(rightを0に設定したCSSと紐づいた)のクラスをパラメータの待機時間秒後に実行して、この時、変化が起きた時にアニメーションするプロパティがCSSでtopとrightを指定してるからぬるっと動く。
んで、さらにsetTimeoutで全体表示時間+アニメーション開始遅延時間分待ってから↑で追加したクラスを削除して引っ込ませる。 そしてさらにさらに(アニメーション開始遅延時間分+アニメーション時間分)×1.2ぐらいって感じで確実に画面上から消えるのを待ってから存在自体削除する。
と、こんなことをしております。
そしてその後にスキップに対しても何らかの対応が必要だと気付いたわけです。
まあ初期時点で、時間周りの計算がゲキヤバ(文系
SE故、数字・計算が大の苦手の民)だったんですが、このスキップ対応で更に頭を抱えましてよ。
更に考えなきゃ行けないのが、ティラノとプラグイン側の実行はタグでの開始(正確には見せる部分を画面のHTMLに追加した後)以降、互いに独立してるって点。setTimeoutは非同期処理させるからね……(要は並行で突然別の線路ができる感じ、場所取る=端末処理能力を圧迫する)
とはいえ、ティラノオブジェクトの中にスキップしてるかどうかは入ってるから……setTimeoutでセットした各処理で対象のsetTimeout前後でスキップ状態が変わったかチェックしつつ、変わってれば表示時間やアニメーションにかかる時間をパラメータでもらった1/nにするためのnで割って都度変更。
と、そんな感じなので、やっぱ使いすぎると重いかもしれん……この使いすぎがほんま怖いので、ほどほどにしたり、演出で使うならスキップ停止(skipstop)とかwaitも挟んでうまくやるといいかと思います。
5.作りたいプラグイン構想
一応ね、以下みたいなプラグインも作りたいなー、などと思うわけです。
文字判定・文字置換補助プラグイン(文字種判定やアルファベット大文字⇔小文字、半角カナ⇔全角カナ等同一文字の文字種変化レベル)
拡張pushlogプラグイン(キャラ名指定でログにぶち込む。これは構想いうけどなんか割とできてるから近々出す、かもしれない)
文字化けプラグイン(文字化けさせて表示、文字化けさせた内容取得、可能なら表示普通ログは文字化け、表示文字化けログ普通も入れたいけどこれはゴリゴリkag.js系の解析結果次第)
もうタイミング的に来年の抱負である。
あくまでまだ構想段階なので、誰かやってくれてもいいんですよ?(チラッチラッ)(有能な怠け者の顔)