//============================================================================= // RetryBattle.js // ---------------------------------------------------------------------------- // (C) 2016 Triacontane // This software is released under the MIT License. // http://opensource.org/licenses/mit-license.php // ---------------------------------------------------------------------------- // Version // 1.4.0 2021/12/26 リトライコストに任意の変数、アイテムを設定できる機能を追加 // 1.3.0 2021/12/16 リトライにコスト(お金)を設定できる機能を追加 // 1.2.1 2021/02/09 戦闘中に戦闘背景を変更したとにリトライすると変更後の背景で再戦してしまう不具合を修正 // 1.2.0 2020/10/14 マップイベントからゲームオーバーになったときもリトライコマンドが表示される場合がある不具合を修正 // パラメータの型指定機能に対応 // 1.1.3 2020/09/10 強制リトライで戦闘開始に戻ったとき、HPなどの状態が復元されない問題を修正 // ReviceBattleItemNumber.jsと併用したとき、リトライ後にアイテム画面を開くとエラーになる競合を修正 // 1.1.2 2018/12/25 リトライを経て勝った、もしくは逃げた場合、それぞれの分岐を正常に通らない場合がある問題を修正 // 1.1.1 2017/03/20 本体v1.3.4以降で、リトライ後のメニュー画面でコモンイベントアイテムが実行できていた問題を修正 // 1.1.0 2016/07/26 リトライ後のメニュー画面でコモンイベントを実行するアイテム・スキルを実行すると正常に動作しない問題を修正 // リトライ後のメニュー画面でゲーム終了を選択できないように修正 // リトライ回数をカウントして、スクリプトから取得できる機能を追加 // 1.0.0 2016/07/26 初版 // ---------------------------------------------------------------------------- // [Blog] : https://triacontane.blogspot.jp/ // [Twitter]: https://twitter.com/triacontane/ // [GitHub] : https://github.com/triacontane/ //============================================================================= /*: @url https://triacontane.blogspot.com/ @plugindesc Battle Retry Plugin @author Triacontane @license MIT License @help English Help Translator: munokura This is an unofficial English translation of the plugin help, created to support global RPG Maker users. Feedback is welcome to improve translation quality (see: https://github.com/munokura/triacontane-MV-plugins ). Original plugin by Triacontane. Please check the latest official version at: https://triacontane.blogspot.com ----- After a battle, you can retry from the Game Over screen. You can set whether or not to allow retry for minor enemies and boss enemies. Selecting Retry allows you to retry after opening the menu screen only once. You cannot save from the menu screen, and items and skills that trigger common events cannot be used. Enemy status is determined as follows: - Minor enemies Select "Random Encounter" or "Same as Random Encounter" in "Battle Processing" - Boss enemies Other than the above As an added bonus, a plugin command is provided that, when executed during battle, forces the battle to restart from the beginning. Plugin Command Details Execute from the "Plugin Command" event command. (Parameters are separated by a space.) RB_RETRY_DISABLE - Temporarily disables retries. RB_RETRY_ENABLE - Re-enables retries. RB_FORCE_RETRY - Use during battle to force a retry. Script Details Execute from the "Variable Operation" event command. $gameSystem.getRetryCount(); - Gets the retry count and stores it in a variable. This plugin is released under the MIT License. @param RetryNormalEnemy @text Retry possible with weak enemies @desc You can retry after getting a game over from a weak enemy. @type boolean @default true @param RetryBossEnemy @text Retry possible with boss enemies @desc You can retry after a game over from a boss enemy. @type boolean @default true @param CommandRetry @text Command Retry @desc This is the command string for "retry" that is displayed on the game over screen. @default Retry @param CommandLoad @text Command Load @desc This is the command string to "go to the loading screen" that is displayed on the game over screen. @default Load @param CommandTitle @text Command Title @desc This is the command string to "Go to the title screen" that is displayed on the game over screen. @default To Title @param WindowY @text Window Y coordinate @desc The Y coordinate of the retry window display. @type number @default 464 @param ShowMenu @text Display the menu screen @desc After selecting retry, a menu screen will be displayed before the battle begins. @type boolean @default true @param Message @text message @desc Displays a message at the top of the window. @default \c[2]You died.\c[0] @param MessageY @desc The Y coordinate of the message display. @type number @default 360 @param FontSize @text Font size @desc The font size of the message. @type number @default 32 @param RetryCostGold @text Retry cost (money) @desc This is the money you will need when retrying. If you don't have enough, you won't be able to retry. @type number @default 0 @param RetryCostVariable @text Retry cost (variable) @desc The variable number required for retrying. @type variable @default 0 @param RetryCostValue @text Retry cost (variable value) @desc This is the variable value required for retrying. If it is insufficient, retrying will not be possible. @type number @default 0 @parent RetryCostVariable @param RetryCostItem @text Retry Cost (Item) @desc These are items required when retrying. If you do not have one, you will not be able to retry. @type item @default 0 @param CostItemVariable @text Cost item possession variable @desc This variable stores the number of retry cost items you have. It is used when outputting the number in a message. @type variable @default 0 @parent RetryCostItem */ /*:ja @plugindesc 戦闘リトライプラグイン @author triacontane @param RetryNormalEnemy @text 雑魚敵でリトライ可能 @desc 雑魚敵でゲームオーバーになったあとにリトライできます。 @default true @type boolean @param RetryBossEnemy @text ボス敵でリトライ可能 @desc ボス敵でゲームオーバーになったあとにリトライできます。 @default true @type boolean @param CommandRetry @text コマンドリトライ @desc ゲームオーバー画面で表示する「リトライする」ためのコマンド文字列です。 @default リトライ @param CommandLoad @text コマンドロード @desc ゲームオーバー画面で表示する「ロード画面に移行する」ためのコマンド文字列です。 @default ロード @param CommandTitle @text コマンドタイトル @desc ゲームオーバー画面で表示する「タイトル画面に移行する」ためのコマンド文字列です。 @default タイトルへ @param WindowY @text ウィンドウY座標 @desc リトライウィンドウの表示Y座標です。 @default 464 @type number @param ShowMenu @text メニュー画面を表示 @desc リトライ選択後、戦闘開始前にメニュー画面を表示します。 @default true @type boolean @param Message @text メッセージ @desc ウィンドウの上部にメッセージを表示します。 @default \c[2]あなたは死にました。\c[0] @param MessageY @textメッセージY座標 @desc メッセージの表示Y座標です。 @default 360 @type number @param FontSize @text フォントサイズ @desc メッセージのフォントサイズです。 @default 32 @type number @param RetryCostGold @text リトライコスト(お金) @desc リトライする際に必要になるお金です。足りないとリトライできません。 @default 0 @type number @param RetryCostVariable @text リトライコスト(変数) @desc リトライする際に必要になる変数の番号です。 @default 0 @type variable @param RetryCostValue @text リトライコスト(変数の値) @desc リトライする際に必要になる変数の値です。足りないとリトライできません。 @default 0 @type number @parent RetryCostVariable @param RetryCostItem @text リトライコスト(アイテム) @desc リトライする際に必要になるアイテムです。ひとつも所持していないとリトライできません。 @default 0 @type item @param CostItemVariable @text コストアイテム所持変数 @desc リトライコストアイテムの所持数が格納される変数です。メッセージに所持数を出力する場合などに使います。 @default 0 @type variable @parent RetryCostItem @help 戦闘でゲームオーバーになったあとのゲームオーバー画面でリトライ可能になります。 雑魚敵とボス敵とでリトライ可能かどうかを分けることができます。 リトライを選択すると一度だけメニュー画面を開いた後で、再戦することができます。 メニュー画面ではセーブ及びコモンイベントを実行するアイテム、スキルの使用ができません。 雑魚敵かボス敵かは以下の通り判定されます。 ・雑魚敵 ランダムエンカウントか「戦闘の処理」で「ランダムエンカウントと同じ」を選択 ・ボス敵 上記以外 さらにオマケ機能として、戦闘中に実行すると強制的に戦闘を最初からやり直す プラグインコマンドを提供します。有名RPGの某魔法が再現できます。 プラグインコマンド詳細 イベントコマンド「プラグインコマンド」から実行。 (パラメータの間は半角スペースで区切る) RB_リトライ禁止 # 一時的にリトライを禁止します。 RB_RETRY_DISABLE # 同上 RB_リトライ許可 # リトライを再度許可します。 RB_RETRY_ENABLE # 同上 RB_強制リトライ # 戦闘中に使用すると強制的にリトライします。 RB_FORCE_RETRY # 同上 スクリプト詳細 イベントコマンド「変数の操作」から実行 $gameSystem.getRetryCount(); # リトライ回数を取得して変数に保持します。 This plugin is released under the MIT License. */ (function () { 'use strict'; var metaTagPrefix = 'RB_'; var getCommandName = function (command) { return (command || '').toUpperCase(); }; var createPluginParameter = function (pluginName) { var paramReplacer = function (key, value) { if (value === 'null') { return value; } if (value[0] === '"' && value[value.length - 1] === '"') { return value; } try { return JSON.parse(value); } catch (e) { return value; } }; var parameter = JSON.parse(JSON.stringify(PluginManager.parameters(pluginName), paramReplacer)); PluginManager.setParameters(pluginName, parameter); return parameter; }; var param = createPluginParameter('RetryBattle'); //============================================================================= // Game_Interpreter // プラグインコマンドを追加定義します。 //============================================================================= var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand; Game_Interpreter.prototype.pluginCommand = function (command, args) { _Game_Interpreter_pluginCommand.apply(this, arguments); var commandPrefix = new RegExp('^' + metaTagPrefix); if (!command.match(commandPrefix)) return; this.pluginCommandRetryBattle(command.replace(commandPrefix, ''), args); }; Game_Interpreter.prototype.pluginCommandRetryBattle = function (command) { switch (getCommandName(command)) { case '強制リトライ': case 'FORCE_RETRY': if ($gameParty.inBattle()) SceneManager.push(Scene_BattleReturn); break; case 'リトライ禁止': case 'RETRY_DISABLE': $gameSystem.setRetryDisable(true); break; case 'リトライ許可': case 'RETRY_ENABLE': $gameSystem.setRetryDisable(false); break; } }; var _Game_Interpreter_command353 = Game_Interpreter.prototype.command353; Game_Interpreter.prototype.command353 = function () { var result = _Game_Interpreter_command353.apply(this, arguments); BattleManager.goToGameover(); return result; }; var _Game_Interpreter_command301 = Game_Interpreter.prototype.command301; Game_Interpreter.prototype.command301 = function () { var result = _Game_Interpreter_command301.apply(this, arguments); if (!$gameParty.inBattle()) { BattleManager.setBossBattle(this._params[0] <= 1); } return result; }; //============================================================================= // Game_Player // 雑魚敵の設定処理をします。 //============================================================================= var _Game_Player_executeEncounter = Game_Player.prototype.executeEncounter; Game_Player.prototype.executeEncounter = function () { var result = _Game_Player_executeEncounter.apply(this, arguments); if (result) { BattleManager.setBossBattle(false); } return result; }; //============================================================================= // Game_System // リトライ禁止フラグを管理します。 //============================================================================= var _Game_System_initialize = Game_System.prototype.initialize; Game_System.prototype.initialize = function () { _Game_System_initialize.apply(this, arguments); this._retryDisable = false; this._retryCount = 0; }; Game_System.prototype.setRetryDisable = function (value) { this._retryDisable = !!value; }; Game_System.prototype.isRetryDisable = function () { return this._retryDisable; }; Game_System.prototype.addRetryCount = function () { this._retryCount = this.getRetryCount() + 1; }; Game_System.prototype.getRetryCount = function () { return this._retryCount || 0; }; //============================================================================= // Game_BattlerBase // リトライ時はコモンイベント使用を含むアイテムを使用禁止にします。 //============================================================================= var _Game_BattlerBase_meetsUsableItemConditions = Game_BattlerBase.prototype.meetsUsableItemConditions; Game_BattlerBase.prototype.meetsUsableItemConditions = function (item) { return _Game_BattlerBase_meetsUsableItemConditions.apply(this, arguments) && this.meetsUsableItemConditionsForRetry(item); }; Game_BattlerBase.prototype.meetsUsableItemConditionsForRetry = function (item) { return !(SceneManager.isSceneRetry() && this.isCommonEventItemOf(item)); }; Game_BattlerBase.prototype.isCommonEventItemOf = function (item) { return item.effects.some(function (effect) { return effect.code === Game_Action.EFFECT_COMMON_EVENT; }); }; //============================================================================= // Game_Actor // リトライ時はコモンイベント使用を含むアイテムを使用禁止にします。 //============================================================================= var _Game_Actor_meetsUsableItemConditions = Game_Actor.prototype.meetsUsableItemConditions; Game_Actor.prototype.meetsUsableItemConditions = function (item) { return _Game_Actor_meetsUsableItemConditions.apply(this, arguments) && this.meetsUsableItemConditionsForRetry(item); }; //============================================================================= // Game_Map // リトライ時に再戦前の状態を復帰します。 //============================================================================= Game_Map.prototype.restoreForBattleRetry = function (oldMap) { this._battleback1Name = oldMap.battleback1Name(); this._battleback2Name = oldMap.battleback2Name(); }; //============================================================================= // BattleManager // リトライ関連処理を追加定義します。 //============================================================================= BattleManager.setupRetry = function () { SoundManager.playBattleStart(); $gameTemp.clearCommonEvent(); $gameTroop.setup($gameTroop.troop().id); $gameSystem.addRetryCount(); this.payRetryCost(); // for ReviceBattleItemNumber.js if (this.reservedItem === null) { this.reservedItem = new Array($dataItems.length); } }; BattleManager.payRetryCost = function () { if (param.RetryCostGold > 0) { $gameParty.gainGold(-param.RetryCostGold); } if (param.RetryCostVariable > 0) { var prevValue = $gameVariables.value(param.RetryCostVariable); $gameVariables.setValue(param.RetryCostVariable, prevValue - param.RetryCostValue); } if (param.RetryCostItem > 0) { $gameParty.loseItem($dataItems[param.RetryCostItem], 1, false); } }; BattleManager.setBossBattle = function (value) { this._bossBattle = !!value; }; var _BattleManager_startBattle = BattleManager.startBattle; BattleManager.startBattle = function () { DataManager.saveGameForRetry(); _BattleManager_startBattle.apply(this, arguments); }; var _BattleManager_updateBattleEnd = BattleManager.updateBattleEnd; BattleManager.updateBattleEnd = function () { _BattleManager_updateBattleEnd.apply(this, arguments); this.goToGameover(); }; BattleManager.goToGameover = function () { if (SceneManager.isNextScene(Scene_Gameover)) { Scene_Gameover.firstShow = true; SceneManager.push(Scene_Gameover); } }; BattleManager.canRetry = function () { return !$gameSystem.isRetryDisable() && this.checkBattleType() && param.CommandRetry && DataManager.hasRetryData() && !SceneManager.isPreviousScene(Scene_Map); }; BattleManager.checkBattleType = function () { return (param.RetryNormalEnemy && !this._bossBattle) || (param.RetryBossEnemy && this._bossBattle); }; //============================================================================= // DataManager // リトライ用データのセーブとロードを行います。 //============================================================================= DataManager.saveGameForRetry = function () { var json = JsonEx.stringify(this.makeSaveContents()); if (json.length >= 200000) { console.warn('Save data too big!'); } this._retryData = LZString.compressToBase64(json); }; DataManager.hasRetryData = function () { return !!this._retryData; }; DataManager.loadGameForRetry = function () { if (this._retryData) { var json = LZString.decompressFromBase64(this._retryData); // without $gameMap because of 'victory or defeat' var prevGameMap = $gameMap; this.extractSaveContents(JsonEx.parse(json)); prevGameMap.restoreForBattleRetry($gameMap); $gameMap = prevGameMap; } }; //============================================================================= // SceneManager // リトライ中かどうかの判定を行います。 //============================================================================= SceneManager.isSceneRetry = function () { return this._stack.some(function (scene) { return scene === Scene_Gameover; }); }; //============================================================================= // Window_MenuCommand // リトライ用のメニューでセーブを禁止します。 //============================================================================= var _Window_MenuCommand_isSaveEnabled = Window_MenuCommand.prototype.isSaveEnabled; Window_MenuCommand.prototype.isSaveEnabled = function () { return _Window_MenuCommand_isSaveEnabled.apply(this, arguments) && !SceneManager.isSceneRetry(); }; var _Window_MenuCommand_isGameEndEnabled = Window_MenuCommand.prototype.isGameEndEnabled; Window_MenuCommand.prototype.isGameEndEnabled = function () { return _Window_MenuCommand_isGameEndEnabled.apply(this, arguments) && !SceneManager.isSceneRetry(); }; //============================================================================= // Scene_Gameover // リトライ用データのセーブとロードを行います。 //============================================================================= Scene_Gameover.firstShow = false; var _Scene_Gameover_create = Scene_Gameover.prototype.create; Scene_Gameover.prototype.create = function () { _Scene_Gameover_create.apply(this, arguments); this.createWindowLayer(); this.createForeground(); this.createRetryWindow(); if (param.RetryCostGold > 0) { this.createGoldWindow(); } }; Scene_Gameover.prototype.createGoldWindow = function () { this._goldWindow = new Window_Gold(0, 0); this._goldWindow.x = Graphics.boxWidth - this._goldWindow.width; this.addWindow(this._goldWindow); }; var _Scene_Gameover_start = Scene_Gameover.prototype.start; Scene_Gameover.prototype.start = function () { _Scene_Gameover_start.apply(this, arguments); if (!Scene_Gameover.firstShow) { if (SceneManager.isPreviousScene(Scene_Menu)) { this.executeRetry(1); } if (SceneManager.isPreviousScene(Scene_Load)) { this.startFadeIn(this.fadeSpeed(), false); } } if (param.RetryCostGold > 0) { this._goldWindow.open(); } Scene_Gameover.firstShow = false; }; var _Scene_Gameover_stop = Scene_Gameover.prototype.stop; Scene_Gameover.prototype.stop = function () { if (!SceneManager.isNextScene(Scene_Load) && !SceneManager.isNextScene(Scene_Menu)) { _Scene_Gameover_stop.apply(this, arguments); } else { Scene_Base.prototype.stop.call(this); } }; var _Scene_Gameover_terminate = Scene_Gameover.prototype.terminate; Scene_Gameover.prototype.terminate = function () { if (!SceneManager.isNextScene(Scene_Load) && !SceneManager.isNextScene(Scene_Menu)) { _Scene_Gameover_terminate.apply(this, arguments); } else { Scene_Base.prototype.terminate.call(this); } }; var _Scene_Gameover_playGameoverMusic = Scene_Gameover.prototype.playGameoverMusic; Scene_Gameover.prototype.playGameoverMusic = function () { if (!SceneManager.isPreviousScene(Scene_Load)) { _Scene_Gameover_playGameoverMusic.apply(this, arguments); } }; Scene_Gameover.prototype.createRetryWindow = function () { this._retryWindow = new Window_RetryCommand(); this._retryWindow.setHandler('retry', this.commandRetry.bind(this)); this._retryWindow.setHandler('load', this.commandLoad.bind(this)); this._retryWindow.setHandler('title', this.commandTitle.bind(this)); if (BattleManager.canRetry()) { this.addWindow(this._retryWindow); } else { this._noRetry = true; } }; Scene_Gameover.prototype.createForeground = function () { this._messageWindow = new Window_Base(0, 0, 0, 0); this._messageWindow.opacity = 0; this._messageWindow.contents.fontSize = param.FontSize; this.addWindow(this._messageWindow); if (param.Message) { this.drawMessage(); } }; Scene_Gameover.prototype.drawMessage = function () { var padding = this._messageWindow.padding; var width = this._messageWindow.drawTextEx(param.Message, 0, 0) + padding * 2; var height = param.FontSize + 8 + padding * 2; var x = Graphics.boxWidth / 2 - width / 2; this._messageWindow.move(x, param.MessageY, width, height); this._messageWindow.createContents(); if (param.CostItemVariable > 0 && param.RetryCostItem > 0) { $gameVariables.setValue(param.CostItemVariable, $gameParty.numItems($dataItems[param.RetryCostItem])); } this._messageWindow.drawTextEx(param.Message, 0, 0); }; Scene_Gameover.prototype.commandRetry = function () { DataManager.loadGameForRetry(); if (param.ShowMenu) { SceneManager.push(Scene_Menu); } else { this._retryWindow.close(); this.executeRetry(this.fadeSpeed()); } }; Scene_Gameover.prototype.commandLoad = function () { this._retryWindow.close(); SceneManager.push(Scene_Load); }; Scene_Gameover.prototype.commandTitle = function () { this._retryWindow.close(); this.gotoTitle(); }; Scene_Gameover.prototype.executeRetry = function (fade) { BattleManager.setupRetry(); this.popScene(); this.startFadeOut(fade, true); }; var _Scene_Gameover_update = Scene_Gameover.prototype.update; Scene_Gameover.prototype.update = function () { if (this._noRetry) { _Scene_Gameover_update.apply(this, arguments); return; } if (!this.isBusy()) { this._retryWindow.open(); } Scene_Base.prototype.update.call(this); }; Scene_Gameover.prototype.isBusy = function () { return this._retryWindow.isClosing() || Scene_Base.prototype.isBusy.call(this); }; //============================================================================= // Scene_Base // リトライ状態からの再ゲームオーバーを禁止します。 //============================================================================= var _Scene_Base_checkGameover = Scene_Base.prototype.checkGameover; Scene_Base.prototype.checkGameover = function () { return !SceneManager.isSceneRetry() && _Scene_Base_checkGameover.apply(this, arguments); }; //============================================================================= // Scene_Load // ロード時にゲームオーバーMEを止めます。 //============================================================================= var _Scene_Load_onLoadSuccess = Scene_Load.prototype.onLoadSuccess; Scene_Load.prototype.onLoadSuccess = function () { if (SceneManager.isSceneRetry()) { AudioManager.stopAll(); } _Scene_Load_onLoadSuccess.apply(this, arguments); }; //============================================================================= // Scene_BattleReturn // そのまま戦闘画面に戻ります。 //============================================================================= function Scene_BattleReturn() { this.initialize.apply(this, arguments); } Scene_BattleReturn.prototype = Object.create(Scene_Gameover.prototype); Scene_BattleReturn.prototype.constructor = Scene_BattleReturn; Scene_BattleReturn.prototype.create = function () { }; Scene_BattleReturn.prototype.start = function () { DataManager.loadGameForRetry(); this.executeRetry(this.fadeSpeed()); }; Scene_BattleReturn.prototype.isBusy = function () { return Scene_Base.prototype.isBusy.call(this); }; //============================================================================= // Window_RetryCommand // リトライ用コマンドウィンドウです。 //============================================================================= function Window_RetryCommand() { this.initialize.apply(this, arguments); } Window_RetryCommand.prototype = Object.create(Window_Command.prototype); Window_RetryCommand.prototype.constructor = Window_RetryCommand; Window_RetryCommand.prototype.initialize = function () { Window_Command.prototype.initialize.call(this, 0, 0); this.updatePlacement(); this.openness = 0; }; Window_RetryCommand.prototype.windowWidth = function () { return 180; }; Window_RetryCommand.prototype.updatePlacement = function () { this.x = (Graphics.boxWidth - this.width) / 2; this.y = param.WindowY; }; Window_RetryCommand.prototype.makeCommandList = function () { this.addCommand(param.CommandRetry, 'retry', this.canPayRetryCost()); if (param.CommandLoad) { this.addCommand(param.CommandLoad, 'load'); } this.addCommand(param.CommandTitle, 'title'); }; Window_RetryCommand.prototype.canPayRetryCost = function () { if (param.RetryCostGold > 0 && $gameParty.gold() < param.RetryCostGold) { return false; } if (param.RetryCostVariable > 0 && $gameVariables.value(param.RetryCostVariable) < param.RetryCostValue) { return false; } if (param.RetryCostItem > 0 && !$gameParty.hasItem($dataItems[param.RetryCostItem])) { return false; } return true; }; })();