// DarkPlasma_FormationInBattle 3.0.0 // Copyright (c) 2020 DarkPlasma // This software is released under the MIT license. // http://opensource.org/licenses/mit-license.php /** * 2024/10/17 3.0.0 DarkPlasma_Formation 4.0.0対応 * 2024/03/07 2.1.2 DarkPlasma_Formationとの順序関係を明記 * 2023/08/06 2.1.1 特定条件下でカーソルの合っていないアクターが選択されてしまう不具合を修正 * 2023/07/29 2.1.0 DarkPlasma_Formation 2.1.0対応 * 2023/06/17 2.0.0 DarkPlasma_Formation 2.0.0対応 * TypeScript移行 * 2022/08/02 1.2.7 リファクタ * 1.2.6 リファクタ * 2022/08/01 1.2.5 DarkPlasma_Formation 1.3.2に対応 * 2022/03/31 1.2.4 TemplateEvent.jsと併用すると戦闘テストできない不具合を修正 * 2021/07/05 1.2.3 MZ 1.3.2に対応 * 2021/06/22 1.2.2 サブフォルダからの読み込みに対応 * 2021/05/09 1.2.1 戦闘テスト開始時にエラーが発生する不具合を修正 * 2021/05/05 1.2.0 特定マップで戦闘中の並び替えを禁止する機能追加 * 2020/12/30 1.1.4 DarkPlasma_Formation 1.2.0に対応 * 2020/12/16 1.1.3 DarkPlasma_Formation 1.0.5に対応 * 2020/12/14 1.1.2 強制入れ替え時にエラーで落ちる不具合を修正 * 2020/10/19 1.1.1 戦闘開始時の不要な処理を削除 * 2020/10/13 1.1.0 強制入れ替え時のクールダウン設定を追加 * 2020/09/21 1.0.1 並び替え確定時にパーティウィンドウがリフレッシュされない不具合を修正 * 2020/09/13 1.0.0 公開 */ /*: @target MZ @url https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release @plugindesc Added sorting to party commands in battle @author DarkPlasma @license MIT @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/DarkPlasma-MZ-Plugins ). Original plugin by DarkPlasma. Please check the latest official version at: https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release ----- version: 3.0.0 You can now change the order during battle. By adding to the map's memo field, you can disable the order change option during battle on that map. This plugin requires the following plugin: DarkPlasma_Formation version: 4.0.0 If using with the following plugin, add it below it. DarkPlasma_Formation @param cooldownTurnCount @text Cooldown @desc After rearranging, you cannot rearrange again until this number of turns has passed (you can change it immediately with 0) @type number @default 0 @param cooldownOnlyWhenSwapForwardAndBenchwarmer @text Cool only when swapping front and back @desc Cooldown is enabled only when switching between front and rear guards @type boolean @default true @param cooldownFormat @text Cooldown display format @desc Cooldown display format ({turn} is replaced with the number of turns) @type string @default (CT:{turn}) @param cooldownWithForceFormation @text Forced swap cooldown @desc Cooldown even when forced to swap @type boolean @default true */ /*:ja @plugindesc 戦闘のパーティコマンドに並び替えを追加 @author DarkPlasma @license MIT @target MZ @url https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release @base DarkPlasma_Formation @orderAfter DarkPlasma_Formation @param cooldownTurnCount @desc 並び替え後、このターン数が経過するまで再度並び替えできない(0で即時変更可能) @text クールタイム @type number @default 0 @param cooldownOnlyWhenSwapForwardAndBenchwarmer @desc 前衛後衛を入れ替えた場合のみクールタイムを有効にする @text 前後入れ替え時のみクール @type boolean @default true @param cooldownFormat @desc クールタイムの表示形式({turn}がターン数に置き換えられる) @text クールタイム表示形式 @type string @default (CT:{turn}) @param cooldownWithForceFormation @desc 強制入れ替え時にもクールダウンする @text 強制入れ替え時クールダウン @type boolean @default true @help version: 3.0.0 戦闘シーンで並び替えできるようになります。 マップのメモ欄にと記述することで、 対象マップでの戦闘中に並び替えを選択できなくなります。 本プラグインの利用には下記プラグインを必要とします。 DarkPlasma_Formation version:4.0.0 下記プラグインと共に利用する場合、それよりも下に追加してください。 DarkPlasma_Formation */ (() => { 'use strict'; /** * マップのメタデータを取得できるか * @return {boolean} */ function isMapMetaDataAvailable() { return $dataMap && $dataMap.meta; } const pluginName = document.currentScript.src.replace(/^.*\/(.*).js$/, function () { return arguments[1]; }); const pluginParametersOf = (pluginName) => PluginManager.parameters(pluginName); const pluginParameters = pluginParametersOf(pluginName); const settings = { cooldownTurnCount: Number(pluginParameters.cooldownTurnCount || 0), cooldownOnlyWhenSwapForwardAndBenchwarmer: String(pluginParameters.cooldownOnlyWhenSwapForwardAndBenchwarmer || true) === 'true', cooldownFormat: String(pluginParameters.cooldownFormat || `(CT:{turn})`), cooldownWithForceFormation: String(pluginParameters.cooldownWithForceFormation || true) === 'true', }; /** * 隊列変更のクールタイム */ class FormationCooldown { constructor() { this._cooldownTurn = 0; this._membersAtTurnStart = []; } /** * 戦闘開始時の初期化 */ initCooldown() { this._cooldownTurn = 0; this.storeMembersAtTurnStart(); } /** * ターン開始時のメンバー隊列を保持する */ storeMembersAtTurnStart() { this._membersAtTurnStart = settings.cooldownOnlyWhenSwapForwardAndBenchwarmer ? $gameParty.battleMembers().map((actor) => actor.actorId()) : $gameParty.allMembers().map((actor) => actor.actorId()); } /** * クールダウン開始の必要があるかどうか * @return {boolean} */ needCooldown() { /** * 強制入れ替え時にクールダウンしない */ if ( !settings.cooldownWithForceFormation && $gameParty.forceFormationChanged && $gameParty.forceFormationChanged() ) { $gameParty.resetForceFormationChanged(); return false; } if (settings.cooldownOnlyWhenSwapForwardAndBenchwarmer) { // 前衛後衛が入れ替わっている場合のみ const battleMembers = $gameParty.battleMembers().map((actor) => actor.actorId()); return battleMembers.some((actorId) => { return !this._membersAtTurnStart.includes(actorId); }); } else { // メンバーの順番がいずれか変わっていれば const members = $gameParty.allMembers().map((actor) => actor.actorId()); return this._membersAtTurnStart.some((actorId, index) => { return actorId !== members[index]; }); } } /** * クールダウンが必要なら開始する */ triggerCooldown() { if (this.needCooldown()) { this.startCooldown(); } this.storeMembersAtTurnStart(); } /** * クールダウン中かどうか */ isDuringCooldown() { return this._cooldownTurn > 0; } startCooldown() { this._cooldownTurn = settings.cooldownTurnCount + 1; } /** * クールダウンターン経過 */ decreaseCooldownTurn() { this._cooldownTurn--; } cooldownTurnCount() { return this._cooldownTurn; } } const formationCooldown = new FormationCooldown(); function BattleManager_FormationInBattleMixIn(battleManager) { const _startTurn = battleManager.startTurn; battleManager.startTurn = function () { _startTurn.call(this); formationCooldown.triggerCooldown(); }; const _endTurn = battleManager.endTurn; battleManager.endTurn = function () { _endTurn.call(this); /** * 強制入れ替えがあった場合 */ if ( !formationCooldown.isDuringCooldown() && settings.cooldownWithForceFormation && $gameParty.forceFormationChanged && $gameParty.forceFormationChanged() ) { formationCooldown.triggerCooldown(); } formationCooldown.decreaseCooldownTurn(); }; } BattleManager_FormationInBattleMixIn(BattleManager); function Game_Party_FormationInBattleMixIn(gameParty) { const _onBattleStart = gameParty.onBattleStart; gameParty.onBattleStart = function (advantageous) { _onBattleStart.call(this, advantageous); formationCooldown.initCooldown(); }; } Game_Party_FormationInBattleMixIn(Game_Party.prototype); function Game_Map_FormationInBattleMixIn(gameMap) { gameMap.isFormationInBattleEnabled = function () { return !isMapMetaDataAvailable() || !$dataMap?.meta.disableFormationInBattle; }; } Game_Map_FormationInBattleMixIn(Game_Map.prototype); /** * @param {Scene_Battle.prototype} sceneBattle */ function Scene_Battle_FormationMixIn(sceneBattle) { const baseClass = Scene_FormationMixIn(Scene_Base).prototype; const _createAllWindows = sceneBattle.createAllWindows; sceneBattle.createAllWindows = function () { _createAllWindows.call(this); this.createFormationWindows(); }; const _createPartyCommandWindow = sceneBattle.createPartyCommandWindow; sceneBattle.createPartyCommandWindow = function () { _createPartyCommandWindow.call(this); this._partyCommandWindow.setHandler('formation', this.commandFormation.bind(this)); }; sceneBattle.createFormationWindows = function () { this.createFormationHelpWindow(); this.createFormationBattleMemberWindow(); this.createFormationWaitingMemberWindow(); this.createFormationStatusWindow(); this.setupFormationWindows(); this.hideFormationWindows(); this._pendingWindow = undefined; this._currentWindow = this.formationBattleMemberWindow(); }; sceneBattle.pendingWindow = function () { return baseClass.pendingWindow.call(this); }; sceneBattle.currentActiveWindow = function () { return baseClass.currentActiveWindow.call(this); }; sceneBattle.setupFormationWindows = function () { baseClass.setupFormationWindows.call(this); }; sceneBattle.createFormationHelpWindow = function () { this._formationHelpWindow = new Window_Help(this.formationHelpWindowRect()); this._formationHelpWindow.setText(TextManager.formation); this.addWindow(this._formationHelpWindow); }; sceneBattle.formationHelpWindowRect = function () { return baseClass.helpWindowRect.call(this); }; sceneBattle.formationHelpWindow = function () { return this._formationHelpWindow; }; sceneBattle.cancelButtonWidth = function () { /** * 戦闘シーンではウィンドウ生成後にキャンセルボタンが生成されるため、 * サイズ計算のために一時的にインスタンスを作る */ const cancelButton = new Sprite_Button('cancel'); return cancelButton.width; }; sceneBattle.createFormationStatusWindow = function () { this._formationStatusWindow = new Window_FormationStatus(this.formationStatusWindowRect()); this.addWindow(this._formationStatusWindow); }; sceneBattle.formationStatusWindowRect = function () { return baseClass.statusWindowRect.call(this); }; sceneBattle.formationStatusWindowWidth = function () { return baseClass.formationStatusWindowWidth.call(this); }; sceneBattle.formationStatusWindowHeight = function () { return baseClass.formationStatusWindowHeight.call(this); }; sceneBattle.formationStatusWindow = function () { return this._formationStatusWindow; }; sceneBattle.createFormationBattleMemberWindow = function () { this._formationBattleMemberWindow = new Window_FormationBattleMember(this.formationBattleMemberWindowRect()); this.addWindow(this._formationBattleMemberWindow); }; sceneBattle.formationBattleMemberWindowRect = function () { return baseClass.battleMemberWindowRect.call(this); }; sceneBattle.battleMemberWindowWidth = function () { return baseClass.battleMemberWindowWidth.call(this); }; sceneBattle.formationBattleMemberWindow = function () { return this._formationBattleMemberWindow; }; sceneBattle.createFormationWaitingMemberWindow = function () { this._formationWaitingMemberWindow = new Window_FormationWaitingMember(this.formationWaitingMemberWindowRect()); this.addWindow(this._formationWaitingMemberWindow); }; sceneBattle.formationWaitingMemberWindowRect = function () { return baseClass.waitingMemberWindowRect.call(this); }; sceneBattle.waitingMemberWindowHeight = function () { return baseClass.waitingMemberWindowHeight.call(this); }; sceneBattle.formationWaitingMemberWindow = function () { return this._formationWaitingMemberWindow; }; sceneBattle.formationStatusParamsWindowHeight = function () { return 0; }; sceneBattle.formationStatusParamsWindow = function () { return null; }; sceneBattle.formationEquipStatusWindow = function () { return null; }; sceneBattle.moveCancelButtonToEdge = function () { if (this._cancelButton) { this._cancelButton.y = Math.floor((this.buttonAreaHeight() - 48) / 2); } }; sceneBattle.returnCancelButton = function () { if (this._cancelButton) { this._cancelButton.y = this.buttonY(); } }; sceneBattle.showFormationWindows = function () { this._formationHelpWindow.show(); this._formationStatusWindow.show(); this._formationBattleMemberWindow.show(); this._formationWaitingMemberWindow.show(); this._formationBattleMemberWindow.select(0); this._formationBattleMemberWindow.activate(); this.moveCancelButtonToEdge(); this._currentWindow = this._formationBattleMemberWindow; }; sceneBattle.hideFormationWindows = function () { this._formationHelpWindow.hide(); this._formationStatusWindow.hide(); this._formationBattleMemberWindow.hide(); this._formationWaitingMemberWindow.hide(); }; sceneBattle.commandFormation = function () { this.showFormationWindows(); }; sceneBattle.onFormationOk = function () { baseClass.onFormationOk.call(this); $gameTemp.requestBattleRefresh(); }; sceneBattle.onFormationCancel = function () { baseClass.onFormationCancel.call(this); }; sceneBattle.quitFromFormation = function () { this.hideFormationWindows(); this.startPartyCommandSelection(); /** * コマンド入力情報初期化 */ $gameParty.makeActions(); }; sceneBattle.activateBattleMemberWindow = function () { baseClass.activateBattleMemberWindow.call(this); }; sceneBattle.activateWaitingMemberWindow = function () { baseClass.activateWaitingMemberWindow.call(this); }; sceneBattle.targetIndexOfActivateBattleMember = function () { return baseClass.targetIndexOfActivateBattleMember.call(this); }; sceneBattle.targetIndexOfActivateWaitingMember = function () { return baseClass.targetIndexOfActivateWaitingMember.call(this); }; sceneBattle.activateBattleMemberWindowByHover = function () { baseClass.activateBattleMemberWindowByHover.call(this); }; sceneBattle.activateWaitingMemberWindowByHover = function () { baseClass.activateWaitingMemberWindowByHover.call(this); }; const _updateCancelButton = sceneBattle.updateCancelButton; sceneBattle.updateCancelButton = function () { _updateCancelButton.call(this); if (this._cancelButton && !this._cancelButton.visible) { /** * 非表示になってから元の位置に戻す */ this.returnCancelButton(); } }; } Scene_Battle_FormationMixIn(Scene_Battle.prototype); function Window_PartyCommand_FormationMixIn(windowClass) { windowClass.addCommandAt = function (index, name, symbol, enabled = true, ext = null) { this._list.splice(index, 0, { name: name, symbol: symbol, enabled: enabled, ext: ext, }); }; const _makeCommandList = windowClass.makeCommandList; windowClass.makeCommandList = function () { _makeCommandList.call(this); let commandName = TextManager.formation; if (!this.isFormationEnabled() && formationCooldown.isDuringCooldown()) { commandName += settings.cooldownFormat.replace(/\{turn\}/gi, `${formationCooldown.cooldownTurnCount()}`); } this.addCommandAt(1, commandName, 'formation', this.isFormationEnabled()); }; windowClass.isFormationEnabled = function () { return ( $gameParty.size() >= 2 && $gameSystem.isFormationEnabled() && !formationCooldown.isDuringCooldown() && $gameMap.isFormationInBattleEnabled() ); }; } Window_PartyCommand_FormationMixIn(Window_PartyCommand.prototype); })();