開発日誌

プラグイン/スクリプト

[ テクニック ] [ 素材 ] [ プラグイン/スクリプト ] タイマーの不具合修正

2021-09-11 10:34:13

RPGツクールのタイマー機能には、想定より1秒早く終了判定されうるという不具合があります。

RPGツクールMV/MZにて、その不具合を修正するプラグインを作成しました。

RPGツクールシリーズにはタイマー機能があります。

昔のシリーズから存在する機能で、秒数を指定してのタイマーの始動と停止、タイマーの残り秒数による条件分岐、およびタイマーの残り秒数を変数に取得・操作することができます。また、タイマーの稼働中は画面内に残り秒数が表示されます。

この機能を使うと、1分以内に脱出!とか、30秒後に爆発する爆弾!とか、リアルの時間経過に依存するイベントを作成することができます。ミニゲームや時限イベントで活躍する機能です。

先日、星潟さんより、一部のツクールシリーズではこのタイマー機能に小数点以下の計算が行われない不具合がある旨、報告がありました。

こちらで調べたところMZでも同様の不具合があったので、修正プラグインを作成しました。

なお、VX Ace用の修正スクリプトは上記、星潟さんのサイトにあるので、そちらをご利用ください。

不具合の内容と原因

例えば右のように、タイマーを3秒で開始して、タイマーが0秒以下になるまでループさせるイベントを組んだ場合、実際には3秒ではなく2秒でループが終わってしまいます。

タイマーを1秒にすると一瞬で終わるので、より顕著に不具合が分かります。

不具合の原因は、条件分岐でタイマーの残り秒数の判定をする際に、小数点以下の秒数が切り捨てられている点です。

タイマーは内部ではフレーム数(1フレームは1/60秒)で管理されており、1フレーム経過するごとに残りフレーム数が1ずつカウントダウンされます。

そして残り秒数の判定や表示の際には、残りフレーム数を60で割って残り秒数として使用される仕組みになっているのですが、この時に小数点以下の秒数が「切り捨て」られるようになっています。

この時どうなるかというと、残り1秒から1フレーム経過して残り0.983秒(59/60秒)となった段階で、小数点以下が切り捨てられて0秒として判定されてしまいます。実際にはまだ0.983秒残っているにもかかわらず、1秒をわずかでも切った時点で0秒と判定されてしまうのです。

条件判定が「以上」の場合は正しく判定されますが、「以下」の場合は約1秒早く判定されてしまいます。たいていは「0秒以下」の条件で終了判定する使い方だと思うので、不具合の影響を受けることになります。

たった1秒ではありますが、たいていタイマー機能は制限時間内に何かせよ、というイベントやミニゲームで使用されるので、1秒といえどもかなり重要な意味を持つのではないでしょうか。

修正内容

このプラグインを導入すると、条件分岐のタイマー判定が小数点以下まで含めて正しく判定されます。

具体的には条件分岐のタイマー判定においては、小数点以下込みの数値で判定されます。例えば条件を「3秒以下」とした場合、正しく3.00秒になった瞬間に条件に合致します。従来は3.99秒になった瞬間に条件に合致してしまいました。

また、画面内に表示される残り秒数は、小数点以下を「切り上げ」て表示するように修正しています。従来は残り秒数が1秒を切って0.99秒になると、画面内の表示は0:00となっていましたが、上記不具合が修正されたことにより、このままだと画面上は0:00と表示されながらも、実際にはまだあと1秒弱の猶予があります。これだと紛らわしいため、表示が0:00になった瞬間にタイムアップとなるよう、小数点以下の秒数を「切り上げ」としています。

それから「変数の操作」にも、タイマーの残り秒数を代入・操作する機能があります。これは画面上に表示されている残り秒数と同じ秒数が取得できた方がよいと思うので、同じく「切り上げ」としています。

なお、既に修正前の状態で秒数の調整をされている場合は、本プラグインを導入して修正することによって、逆に想定よりも1秒長くなってしまうことになるため、タイマーを使用しているゲームに後から導入する場合は、ご注意ください。

質問やアドバイスなどはコメント欄まで、お気軽にお願いします。素材利用条件などについては、このサイトについての「提供素材について」の項目などをご覧ください。

[ テクニック ] [ 素材 ] [ プラグイン/スクリプト ] 複数回行動時の速度補正変更

2021-08-19 22:24:23

RPGツクールではスキルやアイテムに「速度補正」を設定でき、通常よりも先行して放てる技や、逆に発動に時間のかかる必殺技などを実現することができます。

代表的なのは「防御」や「かばう」のスキルです。これらの速度補正を1000や2000といった高い値にすることで、敵の攻撃よりも先に防御や身代わりの体勢をとることができるようになります。

しかし、RPGツクールのデフォルト機能では、1ターンに2回以上の行動をする場合、それぞれの行動の速度補正のうち最小値が採用されるようになっています。そのため、速度補正の高い「防御」や「かばう」と、速度補正が0の通常の行動とを同時に行うと、速度補正としては0が採用されて、真っ先に「防御」や「かばう」の行動をとってくれません。

そこで、複数回行動時の速度補正の算出方法を、最小値から変更するプラグインを作成しました。RPGツクールMVとRPGツクールMZの両方に対応しています。

このプラグインを導入すると、速度補正の算出方法を以下の6つから選択することができます。

  • 各行動の最小値(ツクールの標準と同じ)
  • 各行動の最大値
  • 各行動の平均値
  • 各行動の合計値
  • 最初の行動の速度補正値
  • 最後の行動の速度補正値

例えば3回行動で、それぞれの行動の速度補正が行動順に300、1000、-100だった時、算出結果は以下のようになります。

  • 最小値:-100
  • 最大値:1000
  • 平均値:400
  • 合計値:1200
  • 最初の行動の値:300
  • 最後の行動の値:-100

考え得る限りの算出方法は用意しましたが、どれが良いのかは議論の余地があります。

特に、速度補正がプラスのものとマイナスのものとを同時に行った場合、どうなるのが自然なのかによるのかなと思います。

プラスの方の速度補正は「防御」や「かばう」などそのターンの最初に発動しないと意味をなさない行動に使われるのに対して、マイナスの速度補正は単に詠唱時間が長いといったペナルティー要素として採用されるケースが多く、それを考えるとプラスの速度補正が重視された方が良さそうな気はします。

一方でマイナスの補正値が全く加味されないのも意味がないので、私は平均値を用いています。

他の方法を使いたいという要望があれば、可能な限り採用したいと思いますので、ぜひお寄せください。

質問やアドバイスなどはコメント欄まで、お気軽にお願いします。素材利用条件などについては、このサイトについての「提供素材について」の項目などをご覧ください。

[ テクニック ] [ プラグイン/スクリプト ] 名前欄に応じて顔グラを自動表示

2021-07-21 01:02:42

RPGツクールMZで登場した「文章の表示」の名前欄に、\N[1]のように制御文字でアクター名を入れると、そのアクターの顔グラが自動的に表示されるというプラグインです。

以前、公式フォーラムで要望を受けて作成したものですが、いろいろ応用力が高そうだったので改めて紹介します。

※ 2021-07-24追記:
選択肢の表示や数値入力の処理が重複して実行される不具合を修正しました。お手数ですが、Version 1.1.2にアップデートをお願いします。

このプラグインを導入すると、「文章の表示」で名前欄を\N[x]と設定した際に、x番のアクターの顔グラフィックが自動的に設定されるようになります。

xのところは変数を用いて、\N[\V[y]]のように記述することも可能です。この場合、y番の変数に格納されている番号のアクターとなります。

既に顔グラが設定されていたり、名前欄の形式が合わない場合は無視されます。

注意点としては、文章のプレビューでは顔グラが表示されない点と、テキストがメッセージウィンドウからはみ出さないようにする点です。

文章の入力欄にはメッセージウィンドウの横幅を示す目安のラインが引いてあります。このラインは顔グラなしの場合の横幅になっていますが、実際には顔グラありの場合の横幅にテキストを収めないといけません。このプラグインを使う際は、なるべく横幅ギリギリのメッセージは避けましょう。

単純にキャラクター名やキャラの顔グラの指定を横着したい場合にも使えますが、応用範囲はけっこう広そうです。

条件によってキャラクターの名前や顔グラを入れ替えたい場合は、指定用のアクターを用意しておいて、そのアクターの名前やグラフィックを変更してやれば、文章の表示で自動的に反映されます。

メッセージ自体は共通のものにしたいが、対象のキャラによって名前や顔グラを変更したい場合は、対象となるキャラを示す変数を1つ用意して、その変数にアクター番号を代入します。あとはコモンイベントで、名前欄を\N[\V[x]]としたメッセージを表示してやれば、求める動作となります。

他にも応用できるシチュエーションはありそうです。顔グラを自動的に設定したいケースでは割と使えると思いますので、ぜひ利用をご検討ください。

なお、「文章の表示」の名前欄を使用する仕組みのため、RPGツクールMVでは利用できません。まあ、MVでは顔グラを変数等で設定できるプラグインが既にあったかと思いますが。

質問やアドバイスなどはコメント欄まで、お気軽にお願いします。素材利用条件などについては、このサイトについての「提供素材について」の項目などをご覧ください。

[ テクニック ] [ プラグイン/スクリプト ] サブフォルダ付きプラグインの仕様変更

2021-07-05 23:17:06

RPGツクールMZのバージョン1.3.2がリリースされました。

先々週公開のバージョン1.3.0で仕様追加されたサブフォルダ関連の改善がなされましたが、サブフォルダ内にjsファイルが格納されても正しくプラグインが動作するような修正対応「サブフォルダ内のプラグイン名取得」が、これによって逆に動作しなくなってしまいました。なんちゅうことしてくれた……。

当サイトのプラグインも再修正しました

というわけで、拙作プラグインも先日修正したものを再び修正しました。河原で積んだ石を鬼(公式)に壊された気分w

サブフォルダを使っていなければ特に影響はありませんが、6月23日以降にダウンロードされた方は、お手数ですが修正版を再度ダウンロードお願いします。

プラグイン名の自動取得

ただ元に戻すのは癪だったので、この機会にプラグイン名を自動的に取得できるようにしてみました。

具体的には、

const pluginName = decodeURIComponent(document.currentScript.src).match(/([^\/]+)\.js$/)[1];

として、自分のファイルパスからファイル名を取得しています。

従来はプラグインのファイル名を変更すると動作しなくなっていたのですが、これによりファイル名を変更しても動作するようになります。

ただ、プラグインファイル名については、ユーザーで勝手に変更することを想定していないケースが多く、特にMZ以降、@base@orderAfterなどのプラグインの依存関係を定義するアノテーションも登場したため、ある程度の知識がないとファイル名の変更は推奨されません。

1.3.2修正の要点

結局のところプラグインのサブフォルダ問題は、

  • プラグインパラメータやプラグインコマンドはサブフォルダ名を含まない、プラグインファイル名のみをキーにして取得
  • 同名のプラグインが別フォルダに存在する場合は重複している旨の警告が出る

という形で対応がなされたようです。

つまり、プラグイン名は別フォルダであっても同名のファイルを避けるようにするべきで、サブフォルダは純粋に、ユーザーが多数のプラグインファイルを分類して整理できるようにした便利機能と位置づけられた模様です。

既に1.3.0の時点で対応修正した分が無駄にならないように、とか、プラグインIDとファイルパスを別々に指定できるように、とかの提案もあったようですが、結局1.3.0対応の修正は思いっきり無視されて、最小限の修正で済むような対応となった模様です。

まあ、一時のマズい仕様に対応するために余計なコードを増やしてもしょうがないので、これはこれで仕方ないかと。明らかに影響範囲の広すぎる仕様変更だったので、性急に個人で対応せず、公式の発表を待てばよかったかもしれませんね。我々が騒いだから、公式も影響の大きさに気付いた、という面もありそうですが……。

お陰でコアスクリプトの理解も進んだし、.match( )に入れた部分を簡単に取得する方法も今回の修正を通じて知れたので、収穫もあった……とポジティブ思考。

[ テクニック ] [ プラグイン/スクリプト ] サブフォルダ内のプラグイン名取得

2021-06-22 23:14:17

※追記:
バージョン1.3.2の修正で、本対応は不要となりました。逆に動作しない原因となるため、お手数ですが各プラグインの再ダウンロードをお願いします。
サブフォルダ付きプラグインの仕様変更」記事参照。

RPGツクールMZのバージョン1.3.0(1.3.1)がリリースされ、プラグインフォルダにサブフォルダを作れるようになりました。

多くのプラグインは、プラグインパラメータやプラグインコマンドの取得のため、自分のプラグイン名を指定する必要がありますが、jsファイルをサブフォルダ内に入れることは基本的に想定されていないため、このままだと動作しなくなってしまいます。

ここではプラグイン作者向けに、サブフォルダ内に格納された場合でも、自分のプラグイン名を正しく取得するスクリプトを紹介します。

サブフォルダでプラグイン整理

RPGツクールでプラグインとして提供されるjsファイルは、プロジェクトフォルダの中にある js/pluins フォルダの中に格納する決まりになっています。

しかし、プラグインは何十個と導入するケースも珍しくなく、pluginsフォルダの中に大量のファイルが存在することになってしまいます。

このことから、RPGツクールMZバージョン1.3.0では、pluginsフォルダの中にサブフォルダを作ることができるようになりました。これによって、プラグイン作者別に整理したり、戦闘系・マップ系・メニュー系・立ち絵系……などとジャンル別に整理したり、といったことが可能になりました。

非常に便利ですね!

▲フォルダ内に雑然とあったファイルが…

▲この通りフォルダ分けされてスッキリ!

プラグイン作者泣かせの変更

しかし、この変更はプラグイン作者にとってはかなり厄介です。

プラグインパラメータやプラグインコマンドの実装の際、自分のプラグイン名を指定する必要があります。サブフォルダ内に格納されたプラグインの場合は、このプラグイン名が「サブフォルダ名/プラグイン名」となります。

もともとサブフォルダ内に格納できる仕様ではなかったため、多くのプラグインでは冒頭で、

const pluginName = 'プラグイン名';

のように自プラグイン名を直接指定しており、「プラグインのファイル名は変えないでください」で通していました。しかし、サブフォルダ名はユーザーの任意で付けられるので、プラグイン作者の方で事前に指定することができません。

document.currentScript.scrで自ファイル名を自動的に取得する方法もありますが、現在普及している書き方はやはり、サブフォルダ内に格納されることを想定していないため、正常に動作しません。

また、サブフォルダの中にさらにサブフォルダを作ることも可能となっており、全てのパターンに対応しようとすると、けっこう一筋縄ではいきません。

自分のプラグイン名を取得する

というわけで、自分のプラグイン名を取得するのにどう書けばいいのかということですが、トリアコンタンさんが真っ先に取得方法を上げてくださっていました。ありがとうございます。

https://gist.github.com/triacontane/71064daf535160d4d355aeb9bc3c49f9

以下は、それを参考に少しアレンジしたコードです。ご自由にお使いください。

const pluginName = decodeURIComponent(document.currentScript.src).replace(/^.*?\/plugins\/(.*).js$/, "$1");

※追記:
さらに、うなぎおおとろさんが改良版を上げていらっしゃったので、それを採用しました。ありがとうございます。

https://github.com/unagiootoro/RPGMZ

const pluginName = decodeURIComponent(document.currentScript.src).match(/^.*\/js\/plugins\/(.+)\.js$/)[1];

少し詳しく解説すると、decodeURIComponentは、フォルダ名やファイル名が日本語(非ASCII文字)の場合に、正しく日本語に変換(デコード処理)するための関数です。

document.currentScript.srcで自分のjsファイル名を取得できますが、これで取得できるのはフルURIのため、ここからプラグイン名のみを抽出する必要があります。

抽出は正規表現を使って、/js/plugins/から末尾の.jsまでの間の文字をプラグイン名として取得しています。

※さらに追記:
当初、正規表現の冒頭を^.*?として最短マッチを使うことで、サブフォルダ名に「plugins」が使われても正しくマッチさせるようにしていましたが、逆に配信サイトのURLに万一「plugins」が入っていた場合に動かなくなるとの指摘をいただいたため、修正しました。そんなことする人もいないと思いますが、サブフォルダをjs/pluginsにはしないようにしてください。

他に、もっとスマートな書き方とか、この書き方だと正常に動作しないケースとかがあれば、教えてください。

当サイトのプラグインも修正しました

というわけで、プラグインパラメータもプラグインコマンドも使っていないプラグイン以外は、現在出回っているほとんどのプラグインに影響が出ると思います。厄介なことしてくれちゃって……。

まあ、フォルダ分けしなければ影響は出ないので、使えなくなるというわけでもありませんし、修正はごくわずかです。ユーザーの方でも難しい修正では全然ありません。

拙作プラグインもほとんど影響が出るので、全て修正しました。めんどくさかった……。