投稿記事

2021年 10月の記事 (3)

折尾楽太郎 2021/10/10 21:37

(0003)計算式でやりたい放題

概要

RPGツクールMZのデータベース「スキル」「アイテム」にある計算式で遊んだお話です。

計算式とは

RPGツクールMZでは、スキルやアイテムの効果のうち、ダメージや回復の量を計算式で指定することができます。計算式の入力欄にマウスカーソルを置いてしばらく待つと説明が表示され、記述方法のヒントを確認することができます。

内容としては以下の通りです。

<引用ここから>

使用者をa、対象者をbで表し、ドットに続けて以下のステータスを参照できます。たとえば「a.atk」は使用者の攻撃力を意味します。

atk 攻撃力
def 防御力
mat 魔法力
mdf 魔法防御
agi 敏捷性
luk 運
mhp 最大HP
mmp 最大MP
hp HP
mp MP
tp TP
level レベル

<引用ここまで>

これだけでも相当面白いスキルやアイテムが組めますね。敏捷性に依存した攻撃や運に依存した攻撃、レベルが上がると威力が下がる攻撃等々…。

ゲーム内変数を参照する

まずはこちらから。

  • $gameVariables.value(n) ※nは自然数

これでゲーム内変数n番の値だけダメージを与えられます。私の場合、預金残高を変数に持っているので、それを入れてみたところ、残高が100万G以上あったためエグいダメージを与えてしまいました。

Dateオブジェクト

もっとエグいのがこちら。計算式欄にもJavaScriptが使えるということで試してみたところ動きました。

  • Date.now()

DateはJavaScriptの標準組み込みオブジェクトで、.now()で現在時刻の世界標準時の1970年1月1日0時0分0秒からの経過時間(ミリ秒)(うるう秒は含まず)を取得できます。

執筆時点で約1,633,794,800,000でした。まさかの一兆超えです。ミリ秒(1000ミリ秒=1秒)だから仕方ないですね。興味があったらお試しください。笑えますよw

勿論後ろに「/1000/60/60/24」を付けることで単位を日にしたりも可能です。

三項演算子

いきなりプログラミング用語ですみません。でもこれ便利なんですよ。

三項演算子は【条件】?【条件に合う場合】:【条件に合わない場合】と記述します。
条件分岐といえばif文がメジャーですが、if文は一行に書くと可読性が下がるんですよね。
RPGツクールの計算式の入力欄は1行なので、三項演算子の方が相性が良い気がします。

尚、if文で書くとif(【条件】){【条件に合う場合】}else{【条件に合わない場合】}です。括弧の種類を間違えたり、過不足があると、通常は「unexpected token (」みたいにエラーが出て気づけますが、計算式の場合は問答無用でダメージが0になります。

例えばこんな計算式が考えられますね。

  • a.level % 2 == 0 ? 200 : 1000

a.levelは「計算式とは」で記載した通り使用者のレベル、%は剰余の演算子なので、「a.level % 2」の部分は使用者のレベルが偶数なら0、奇数なら1になります。

これまたプログラミング独特の記述ですが、==は「左辺と右辺が等しいかどうか」という意味です。つまり「a.level % 2 == 0」は使用者のレベルが偶数なら条件が成り立つ(true)、奇数なら条件が成り立たない(false)になり、前者の場合は:よりも前の200が、後者の場合は:よりも後ろの1000が採用されます。

使用者のレベルが奇数か偶数かによってダメージが5倍も違ってしまう、トリッキーなスキル/アイテムの出来上がりですね。Dateオブジェクトと組み合わせると、b.level % 5 == 0 ? Date().now : 0と記載することで、対象のレベルが5の倍数のときだけ1兆超えのダメージを与えるレベル5デスのようなスキルも作れますね。

因みに条件の部分はboolean(true/false(ツクール側でいうスイッチのON/OFF))の場合は比較演算子系(==、===、!=、!==、<、<=、>、>=)を使わなくても分岐できます。

なので、こういう記述も可能です。

  • $gameSwitches.value(n) ? (a.mat * 4 - b.mdf * 2) : (a.atk * 4 - b.def * 2)※nは自然数

以下と同じ意味になります。

  • $gameSwitches.value(n) == true ? (a.mat * 4 - b.mdf * 2) : (a.atk * 4 - b.def * 2)※nは自然数

これでn番のスイッチがONの場合はa.matとb.mdf、つまり使用者の魔法力と攻撃対象の魔法防御依存の攻撃になり、OFFの場合はデフォルトの攻撃と同じ計算が採用されます。

前回の記事で触れた、物語の途中で魔術師の通常攻撃を物理攻撃力依存から魔法攻撃力依存に変えることが可能になりますね。(攻撃アニメーション等は変更できませんが…)

尚、boolean(true/false(ツクール側でいうスイッチのON/OFF))は計算に使うときはtrue(ON)は1、false(OFF)は0として扱われるので、例えば

  • $gameSwitches.value(1) * 100 + $gameSwitches.value(2) * 10 + $gameSwitches.value(3)

にすると、スイッチ1がON、スイッチ2がOFF、スイッチ3がONなら101、スイッチ1がOFF、スイッチ2がON、スイッチ3がONなら11になります。

使えそうなJavaScript標準組み込みオブジェクト他

個人的に思う、使えそうなJavaScriptに搭載されているオブジェクトやメソッドを列挙します。

  • Math.abs(x):xの絶対値(計算結果がマイナスの場合一律0として処理されるので)
  • Math.ceil(x):x以上の最小の整数(小数点以下切り捨て処理をしたい場合に便利。ツクールの計算式は最終的な計算結果に小数点以下が含まれる場合、小数第一位が四捨五入される仕様の模様)
  • Math.floor(x):x以下の最大の整数(小数点以下切り上げ処理をしたい場合に便利。ツクールの計算式は最終的な計算結果に小数点以下が含まれる場合、小数第一位が四捨五入される仕様の模様)
  • Math.round(x):xの小数第一位を四捨五入
  • Math.log10(x):xの常用対数(10を底とした対数)(うまく使うと何桁かを得られる)
  • Math.max(x, …):引数の中で最大の値(上限値を設定したい場合に便利)
  • Math.min(x, …):引数の中で最小の値(下限値を設定したい場合に便利)
  • Math.random():0以上1未満の疑似乱数
  • Array.length:配列に対して.lengthを付けるとその配列の要素数を得られる

面白そうな変数・取得スクリプト

個人的に思う、使ったら面白そうなゲームデータを列挙します。

※公式さんのプラグイン講座から参照できるリファレンスより

  • $dataWeapons[id].price:武器の価格
  • $dataArmors[id].price:防具の価格
  • $dataEnemies[id].exp:敵キャラを倒したときに得られる経験値
  • $dataEnemies[id].gold:敵キャラを倒したときに得られるお金
  • $gameSystem.battleCount():戦闘回数
  • $gameSystem.winCount():勝利回数
  • $gameSystem.escapeCount():逃走回数
  • $gameSystem.playtime():プレイ時間(秒数)
  • a.isStateAffected(id):使用者が指定したidのステートになっているかどうか
  • b.isStateAffected(id):対象者が指定したidのステートになっているかどうか
  • $gameParty.members[n].isGuard():n番目の味方キャラが防御中かどうか
  • $gameParty.members[n].currentExp():n番目の味方キャラのこれまでに獲得した経験値
  • $gameParty.members[n].hasNoWeapons():n番目の味方キャラが素手かどうか
  • $gameParty.steps():現在の歩数
  • $gameParty.numItems(item):指定したアイテムの所持数

終わりに

計算式をいじれば、とんでもないぶっ壊れ性能のスキル/アイテムから、複雑な効果のスキル/アイテム、効果をフラグ管理できるスキル/アイテムなど幅広く作れそうですね。皆様も制作されているゲームに合った、面白い/興味深い計算式を考えてみては如何でしょうか。

ただ、お気をつけいただきたいのが、前述の通り計算式の入力欄は改行ができません。見たところ44文字辺りを超えると枠からはみ出るので一目で記述が確認できなくなってきます。

通常プログラミングをする際には、インデントや適度なスペース、改行を入れて可読性を確保(可読性:記述を読んで何をしているのかの把握のしやすさ)しますが、この入力欄では複雑な記述をするとあっという間に可読性が低下します。

恐らく外部エディターで記述を作り、別途メモとして保存した上で、最後に改行だけ削除し、コピペして反映する方が無難な気がしますね。

また、これも先述しましたが、通常JavaScriptで誤記があった場合はエラーで動かなかったり、DevToolsのコンソールでエラーが確認できますが、計算式の場合は単純にダメージが0になるだけです。

条件分岐でダメージが0になる可能性がある計算式の場合、正常に動作した結果、条件分岐でダメージが0になったのか、記述が間違っていてその結果ダメージが0になったのかが判別しづらいので、動作確認は慎重に行う必要がありそうです。

ではでは。

折尾楽太郎 2021/10/03 18:28

(0002)特徴の追加作戦

概要

RPGツクールはデータベースの以下の項目に「特徴」という設定項目が備わっています。

  • アクター
  • 職業
  • 武器
  • 防具
  • 敵キャラ
  • ステート

一方、イベントコマンドに特徴を編集するコマンドは備わっていません。
そのため、例えばこういったことができなさそうです。(以下例)

  • 修行の結果、通常攻撃が全体攻撃になる
  • 物語の途中で魔法使いの通常攻撃を攻撃力依存から魔力依存に切り替える
  • クエストをこなすことで戦闘の獲得金額が2倍になる

代替策として、同名の職業をコピペして特徴だけ異なるものを用意し、裏で職業を切り替えたり、プレイヤーが操作できない装備のつけ外しをしたりで実現できなくはないですが、前者は

  • 職業の数が肥大化する
  • 転職システムを導入していると簡単に破綻する
  • 習得の順序が複数ある場合も破綻する

後者は

  • 変更不可の装備がプレイヤーに見えてしまうので違和感が生まれる
     (プレイヤーに見えない装備欄って作れるのかな…)
  • プラグインを使わない場合、装備枠が一つこれに持っていかれる
  • こちらも習得の順序が複数ある場合に破綻する
  • 優先順位が強すぎてプレイヤーの自由度が下がる※

※特徴の優先順位については別記事「(0001)特徴の適用される優先順位」で言及していますのでご興味があれば併せてご確認ください。

といった難点があります。

そこで、イベントコマンドの「プラグインコマンド」から特徴を編集できるようにプラグインを自作してみようと考えました。

尚、当記事執筆時点では完成していませんので悪しからず。

後で気づいた本来の前提情報

本来なら前提条件として把握した上で取り組むべきところを後で気づいた情報を先に記載していきます。

グローバル変数の命名規則

最初にアクターの特徴編集プラグインを作り始めましたが、実はアクターの情報が入っているグローバル変数には以下の2種類があります。

  • $dataActors
  • $gameActors

です。データベースの情報が入っているのが$dataActorsということで、$gameActorsの方の存在にすら気づかず$dataActorsの方を編集して「できた!」ってなっていたわけですが、実は$dataから始まるグローバル変数と$gameから始まる変数には大まかに以下の違いがあります。

  • $data~

ゲーム起動時にデータベースに設定されている情報を格納する。ゲーム起動時以外は更新されず全セーブデータで参照される。セーブデータ側には保持されない

  • $game~

ゲームの進行状況によって変化する系統の情報が格納される。$gameActorsの場合はセーブ時点でパーティーにいるアクターとそれぞれのステータス等。セーブデータに含まれる(例外あり)が特徴は含まれない


というわけで、$dataActorsの方を編集するようにプラグインを設計してしまったため、特徴を追加しても以下のような現象が発生しました。

  • プラグインコマンドを発火させると、タイトルに戻って発火させていないセーブデータをロードしても特徴が編集された状態が保持されてしまう
  • プラグインコマンドを発火させてセーブしても、一旦ゲームを閉じて起動しなおすと、発火後にセーブしたデータをロードしても特徴が元に戻ってしまっている

これを把握した私はこう思いました。「だからイベントコマンドにないのか~」

打開策と執筆時点の状況

課題を列挙すると

  • $dataActorsがゲーム起動時にしか読み込まれない
  • $dataActorsの内容がセーブデータに保存されない

です。というわけで、最早コアスクリプトをいじるしかないという結論に至りました。悪手ですが致し方ありません。

※コアスクリプトを編集すると簡単にゲームが起動しなくなるなど重大なエラーが発生します。編集は自己責任にて行ってください。

コアスクリプト(v1.1.0時点…プラグイン開発用のプロジェクトのバージョンアップをし忘れてました)の中を探すと、rmmz_manager.jsにDataManager.makeSaveContentsというメソッドがあり、ここでセーブデータに格納するデータを用意しているようです。

そのため、return contents;の直前にcontents.modifiedDataActors = $dataActors;を挿入してみました。

更にセーブデータを読み込む処理が同じくrmmz_manager.jsにあるDataManager.extractSaveContentsというメソッドで行われているようなので、最終行に$dataActors = contents.modifiedDataActors;を挿入してみました。

これにより、セーブデータにセーブ時点での$dataActorsのデータを保存し、ロード時に$dataActorsをセーブデータに格納されているデータで上書きすることができました。

どやっ('ω')

となるのはまだ早い!

おわかりいただけただろうか。「ロード時に」と記載したことを。

そうです。以下の手順を踏むと残念なことになります。

  • ゲームを開始する
  • イベントコマンドで特徴を編集する
  • タイトルに戻る
  • ニューゲームを開始する

ニューゲームはロード処理を伴わないので、$dataActorsが更新されません。よって、特徴が編集された$dataActorsがそのまま保持された状態でゲームが開始されてしまいます。

実は(執筆時点では)この問題は解決できていません。ゲーム起動時に実行される、Actors.jsonを読み込んで$dataActorsに格納する処理をニューゲームの処理時に再度実行するように記述してみましたが、$dataActorsがnullになってしまい、エラーになってしまいました。

「まあ、不利な特徴編集をしなければ、プレイヤーに損はないから良いか~」と無理やり理由をこじつけて一旦諦めました。

ではでは。

折尾楽太郎 2021/10/03 18:26

(0001)特徴の適用される優先順位

概要

RPGツクールの特徴欄は同じ種類のものでも複数設定することができます。また、データベースの以下の項目に設定項目として備わっています。

  • アクター
  • 職業
  • 武器
  • 防具
  • 敵キャラ
  • ステート

特徴の種類によっては、複数設定すると重複するものもあれば、いずれかが適用されるものもあります。では、後者はどういったルールで適用されるのか?という疑問について検証した結果が今回のお話です。(検証はRPGツクールMZで行いました。MV等も同じではないかと想像しますが確認はしていません)

おそらく

実際に試してみた結果、恐らくこうだろうという推測ができました。

同じ項目内であれば下にあるものが先

例えばアクターに…

  • 攻撃スキル「攻撃」
  • 攻撃スキル「全体攻撃」

が設定されている場合、「全体攻撃」の方が優先度が高い

項目間では下にあるものが先

データベースの表示に並んでいる順番、つまり

  • アクター
  • 職業
  • 武器
  • 防具
  • (敵キャラ)
  • ステート

の順に優先度が高い。例えばアクター、職業、防具に…

  • アクター:攻撃スキル「攻撃」
  • 職業:攻撃スキル「全体攻撃」
  • 防具:攻撃スキル「連続攻撃」

が設定されている場合、当該防具を装備していれば「連続攻撃」が優先度が高く、装備していない場合は「全体攻撃」が優先順位が高い

優先度が高い方から順番に参照して実行可/不可を判定

優先度が高いものから順番に参照し、実行可能なら実行され、消費MPや消費TP、その他条件により当該スキルが実行不能の場合は次に優先度が高いものを参照…を繰り返す

尚、攻撃スキルの場合、最後まで実行できるものがなかった場合は「攻撃」の選択肢が薄くなって選択できなくなる。

という感じです。

つまり

アクターや職業よりも武器。武器よりも防具の方が優先されるので、武器や防具に「攻撃スキル」を付けておくと、プレイヤーが自身の好みに応じて使い分けることが可能な一方、装備固定「装飾品」が設定されている状態で攻撃スキル「防御」がついている装飾品を装備させてしまうと、攻撃スキルが変更できる職業への転職や、攻撃スキルが変更できる武器を装備しても攻撃スキルが変更できない…。といった状態が発生しそうですね。

うまく活用すればゲームシステムを面白くできそうですが、一歩間違えるとプレイヤーの自由度を損ないかねない気がします。良かったら参考にしていただければ。

ではでは。

月別アーカイブ

限定特典から探す

記事を検索