Takki
1
[MZ] QuickSaveSlot — メニューを開かずにワンキーでクイックセーブ/ロード
みなさん、こんにちは!
このたび、RPG Maker MZ 用の小さなクオリティオブライフ(QoL)プラグイン QuickSaveSlot をリリースしました。これは、セーブ/ロードメニューを開くことなく、ワンキーでクイックセーブやクイックロードを行えるようにするプラグインです。
機能概要
- 専用スロットへの即時セーブ/ロード — 通常のセーブデータやオートセーブとは独立しているため、それらを上書きすることがありません。
- 2つの設定可能なホットキー — デフォルトでは F5–F10 が割り当てられており、それぞれクイックセーブとクイックロードに対応しています。
- マップ画面限定の設計 — メニュー、戦闘中、イベントやメッセージ表示中などはトリガーされません。
- セーブ無効条件の尊重 —
$gameSystem.disableSave() の状態を正しく反映します。
- 画面上のトースト通知 — (オプション)確認メッセージを表示します。テキストは完全にカスタマイズ可能で、標準のセーブ/ロード音も再生されます。
- オプションのスイッチゲート — ストーリーの分岐フラグや設定切替スイッチによって、機能の有効/無効を切り替えることができます。
- プラグインコマンドの搭載 — イベントからトリガーするための
Quick Save / Quick Load コマンドが含まれています。
開発の経緯
チェックポイントでセーブするために毎回メニューを開くのは、ゲームのリズムを壊してしまうため、私は dedicated(専用)のクイックセーブスロットをホットキーに割り当てたいと考えました。このスロットは安全に保管され、戦闘中やイベント中に誤って発動することはありませんし、プレイヤーの実際のセーブデータには一切干渉しません。
ダウンロード
GitHub - LeonneBrito/rpmakermz-plugins · GitHub
— Takki
「いいね!」 1
CSAF
2
いいですね。saveGame における Promise の扱いが、よく間違われがちなポイントなので、then と catch がすでに設定されているのは良いことです。
読みながら気づいた小さな点が2つあります。
- savefileId の復元が、プレイヤーがキーを連打すると固まってしまう可能性があります。executeQuickSave は previousSavefileId を取得し、スロットを設定し、保存してから then 内で復元を行います。最初の Promise が解決する前に2回目の押下が行われると、previousSavefileId はクイックスロット自体として読み込まれてしまいます。その結果、復元処理はクイックスロットに戻してそこで停止してしまいます。これを防ぐには、進行中のフラグ(in-flight flag)でクリアする必要があります。
let saving = false;
const executeQuickSave = () => {
if (saving || !canQuickSave()) { /* toast + return */ }
saving = true;
...
.finally(() => { saving = false; });
};
- もう1つは、ロード時のバージョン不整合のブランチです。標準の MZ では、そこでは5つの引数が渡されます。
$gamePlayer.reserveTransfer(mapId, x, y, d, 0);
あなたのコードでは3つの引数しか渡されていないため、fadeType が undefined となり、fadeInForTransfer は 0 または 1 の場合にのみ有効になります。リロード自体は問題ありませんが、通常はフェードイン/アウトがあるところ、フェードなしで即座に表示されます。5番目の引数に 0 を渡すことで、通常のフェード動作が戻ります。
なお、4番目の引数を省略しても問題ありません。performTransfer はそれをそのまま setDirection に渡しますが、setDirection は値が真値である場合にのみガードします。
Game_CharacterBase.prototype.setDirection = function(d) {
if (!this.isDirectionFixed() && d) {
this._direction = d;
}
this.resetStopCount();
};
したがって、undefined は通過してしまい、プレイヤーは既存の向きを維持します。実際に問題になるのは5番目の引数だけです。
Takki
3
確かに、その通りですね。両方とも見逃しにくいポイントを見事に指摘されました。
saving による実行中のガードは、クイックセーブの競合状態に対する確かに正しい修正です。これを設定しないと、2回目の押下で既に上書きされた savefileId が取得され、間違ったスロットが復元されてしまいます。
また、バージョン不一致の分岐についてもその通りです。第五引数の reserveTransfer を見落としていました。0 を渡すことで、通常のフェード処理が復元されます:
$gamePlayer.reserveTransfer(mapId, x, y, d, 0);
第四引数に関するご指摘もその通りです。setDirection は if (d) でガードされているため、undefined は実質的に害がなく、既存の方向が保持されます。
これら2つの変更を行います:実行中のセーブガードと、バージョン不一致時のリロードにおける fadeType = 0 です。