//============================================================================= // MM_RingCommand.js //============================================================================= // Copyright (c) 2025- 牛乳もなか // This software is released under the MIT License. // http://opensource.org/licenses/mit-license.php // // Twitter // https://x.com/milkmonaka_1 //============================================================================= // Version // 1.0.4 2025/2/5 1.0.3の修正の影響でメニュー時などのヘルプウインドウにも、位置設定などが反映されてしまう不具合を修正しました。 // 1.0.3 2025/2/4 コマンド操作の反転オプションが正常に動作していない不具合を修正しました。 // スキルコマンドの一部の関数が適切にオーバーライドされていない不具合を修正しました。 // useRingActorCommandをオフにした場合ネームウインドウが生成されずエラーが出る不具合を修正しました。 // コマンド種類毎にヘルプウインドウを使用するかしないかの設定を追加しました。 // 1.0.2 2025/1/30 アイテムとスキルアイコンの拡大率を変更すると整数化されず若干枠線が見えてしまう不具合を修正。 // アイテムのスキルの画像をメモ欄で指定しアイコン以外の画像を表示できる機能を追加。@help参照。 // アップデート中の処理を軽減しました(体感では解らないと思いますが) // アップデート中の処理を変更したため、一部プラグインとの競合が解消されるかもしれません。 // 1.0.1 2025/1/29 全体的にリファクタリング(動作や設定に変更無し) // 不要な処理を削減したのでパフォーマンスが向上していますが、 // 正直体感でわかるレベルではありません。 // 1.0.0 2025/1/28 テスト公開 //============================================================================= /*:ja * @target MZ * @plugindesc 戦闘中コマンドをリングコマンドに変更します。 * @url https://x.com/milkmonaka_1 * @author milkmonaka * @help * 戦闘中の任意のコマンドをリングコマンドに変更します。 * リングに使用する画像などはすべてimg/systemに配置します。 * このプラグインにコアスクリプトの直接的な書き換えはありません。 * * 【各種設定】 * 各プラグインパラメータの説明に全て書いてますので見れば大体わかると思います。 * * 【アクターコマンドアイコン設定】 * スキルやアイテムは元々アイコンがありますがアクターコマンドにはありませんので * 画像ファイルを用意する必要があります。 * コマンドに対応する画像ファイル名は下記です。 * 攻撃: attack.png * 防御: guard.png * スキル: skill1.png *1はスキルタイプIDを指す。2番目ならskill2.png * アイテム: item.png * 全てimg\systemに配置します。 * 独自でコマンドを追加している場合そのコマンドのSymbol名をファイル名とする。 * たとえばmoveというコマンドを追加するならmove.pngを用意してください。 * コアスクリプトに沿って拡張していない追加コマンドまでは保証できません。 * * 【アイテム・スキルでアイコン以外の画像を使用】 * アイテム・スキルのメモ欄にというタグを記載。 * ファイル名をskillIcon + Id, ItemIcon + Idとする * 例: アイテムID5であればItemIcon5.png * 配置はimg\ringIcons (専用のフォルダを作成してください) * 画像表示の場合アイコンの拡大率は適応されない、表示したいサイズで画像を作成する必要がある。 * タグがない場合はアイコン画像を使用します。 * * 【注意点】 * コマンドの最大数は99個としていますが、実際には99個も表示すると相当見づらいと思われる。 * せいぜい2~30個が限界と思うが、リングの直径やボタンの大きさ次第ではあります。 * 戦闘中に使用出来るアイテムが100種類あるという様なゲームには向いていない、 * そもそも、そういうゲームでリングコマンドを採用することが間違いで * そこまで多いなら通常のウインドウのリストの方が見やすいと思います。 * * 【綺麗に配置するコツ】 * ・リングの太さとコマンド画像の縦横を出来るだけ合わせる。 * ・リング画像は上下左右に均等に若干の余白を設けたほうが、カーソル画像が見切れづらい。 * * 【その他】 * このプラグインではリングコマンド本体のスキンや背景などは設定できますが、 * 名称ウインドウとヘルプウインドウのウインドウスキンや背景などは設定できません。 * しかし、トリアコンタン氏のWindowBackImageを使用して * Window_CommandNameとWindow_Helpに対して設定を行えば好きなものに変更できます。 * この機能をつけようかと思いましたが、既に汎用的なプラグインがあるのでそちらに任せることにします。 * * @param useRingActorCommand * @text アクターコマンドに使用 * @type boolean * @on 使用 * @off 不使用 * @desc アクターコマンドをリングコマンドにします。 * @default true * * @param hideOnEnemyTarget * @text 攻撃コマンド決定時に非表示 * @type boolean * @on 非表示 * @off 表示 * @desc 攻撃コマンド決定後にリングコマンドを非表示にします。対象選択中に非表示にするということです。 * @default false * * @param useRingSkillCommand * @text スキル選択に使用 * @type boolean * @on 使用 * @off 不使用 * @desc スキル選択リストをリングコマンドにします。 * @default true * * @param hideOnSkillTarget * @text スキル決定時に非表示 * @type boolean * @on 非表示 * @off 表示 * @desc スキル決定後にリングコマンドを非表示にします。対象選択中に非表示にするということです。 * @default false * * @param hideOnSkillHelp * @text アイテムコマンドでヘルプウインドウを使用 * @type boolean * @on 使用 * @off 不使用 * @desc スキルコマンドでヘルプウインドウを使用するか。 * @default true * * @param useRingItemCommand * @text アイテム選択に使用 * @type boolean * @on 使用 * @off 不使用 * @desc アイテム選択リストをリングコマンドにします。 * @default true * * @param hideOnItemTarget * @text アイテム決定時に非表示 * @type boolean * @on 非表示 * @off 表示 * @desc アイテム決定後にリングコマンドを非表示にします。対象選択中に非表示にするということです。 * @default false * * @param hideOnItemHelp * @text アイテムコマンドでヘルプウインドウを使用 * @type boolean * @on 使用 * @off 不使用 * @desc アイテムコマンドでヘルプウインドウを使用するか。 * @default true * * @param ringCommandSetting * @text リングコマンド設定 * @default ------------------------------ * @type string * @desc リングコマンドの共通設定をします。 * * @param ringWindowSkin * @parent ringCommandSetting * @text リングコマンドのフレーム画像 * @require 1 * @dir img/system/ * @type file * @desc リングコマンドのフレーム画像です、縦横比は1:1を推奨します。 * @default * * @param ringWindowButton * @parent ringCommandSetting * @text リングコマンドのボタン画像 * @require 1 * @dir img/system/ * @type file * @desc リングコマンドのボタン画像です、各コマンドの背景画像ということです。縦横比は1:1を推奨します。 * @default * * @param selectCursor * @parent ringCommandSetting * @text 選択項目のカーソル画像 * @require 1 * @dir img/system/ * @type file * @desc 選択項目のカーソル画像です。リングコマンドでは円周の真上の項目が選択項目になります。 * @default * * @param useActorCommandIcon * @parent ringCommandSetting * @text アクターコマンドにアイコンを使用 * @type boolean * @on 使用 * @off 不使用 * @desc アクターコマンドにアイコンを使用します。 * @default false * * @param rotationSpeed * @parent ringCommandSetting * @text 回転速度 * @type number * @min 0.01 * @max 1.00 * @decimals 2 * @desc リングコマンドの回転速度です。0.01~1.00 デフォルトは0.1 最大値の1は一瞬で次項目ということ。 * @default 0.1 * * @param reverseRingCommand * @parent ringCommandSetting * @text リング操作を反転 * @type boolean * @on 反転 * @off 反転しない * @desc リングのキー操作を反転します。 * @default false * * @param ringWidth * @parent ringCommandSetting * @text リングコマンドの横幅 * @type number * @min 0 * @desc リングコマンド全体の横幅です、使用するフレーム画像の横幅と一致させてください。縦横比は1:1を推奨。 * @default 400 * * @param ringHeight * @parent ringCommandSetting * @text リングコマンドの高さ * @type number * @min 0 * @desc リングコマンド全体の高さです、使用するフレーム画像の高さと一致させてください。縦横比は1:1を推奨。 * @default 400 * * @param commandWidth * @parent ringCommandSetting * @text コマンドの横幅 * @type number * @min 0 * @desc 1項目の横幅です、使用するボタン画像と合わせると良いでしょう。 * @default 64 * * @param commandHeight * @parent ringCommandSetting * @text コマンドの高さ * @type number * @min 0 * @desc 1項目の高さです、使用するボタン画像と合わせると良いでしょう。 * @default 64 * * @param adjustedPos * @parent ringCommandSetting * @text コマンド位置補正 * @type number * @min -9999 * @desc 項目の位置を補正します、正の値でリングが縮まり、負の値で広がります。通常設定しなくても合いますが微調整用です。 * @default 0 * * @param adjustCursorY * @parent ringCommandSetting * @text カーソル位置補正 * @type number * @min -9999 * @desc カーソル画像のY位置を補正します、カーソルの形や大きさによるのでこちらは微調整が必要です。正の値・負の値が使えます。 * @default 0 * * @param iconScale * @parent ringCommandSetting * @text アイコンの倍率 * @type number * @min 1 * @decimals 1 * @desc スキルやアイテムの表示アイコンの倍率を指定します。小数点可 * @default 1 * * @param useTrackRing * @parent ringCommandSetting * @text リングコマンドを自動移動 * @type boolean * @on 使用 * @off 不使用 * @desc リングコマンドの位置をSVバトラーの位置に自動的に移動させます。 * @default true * * @param ringCommandX * @parent ringCommandSetting * @text リングコマンドのX位置 * @type number * @min -9999 * @desc 自動移動が有効の場合は設定不要です、フロントビューなどでコマンド位置を固定したい場合ここで設定。 * @default 0 * * @param ringCommandY * @parent ringCommandSetting * @text リングコマンドのY位置 * @type number * @min -9999 * @desc 自動移動が有効の場合は設定不要です、フロントビューなどでコマンド位置を固定したい場合ここで設定。 * @default 0 * * @param ringOffsetX * @parent ringCommandSetting * @text リングコマンドXオフセット * @type number * @min -9999 * @desc リングコマンドのXオフセットです。自動移動が有効の時に更に微調整したい場合ここを使います。 * @default 0 * * @param ringOffsetY * @parent ringCommandSetting * @text リングコマンドYオフセット * @type number * @min -9999 * @desc リングコマンドのYオフセットです。自動移動が有効の時に更に微調整したい場合ここを使います。 * @default 0 * * @param nameWindowSetting * @text 名称ウインドウ設定 * @default ------------------------------ * @type string * @desc 名称ウインドウ関連の設定をします。 * * @param useNameWindow * @parent nameWindowSetting * @text 名称ウインドウを使用 * @type boolean * @on 使用 * @off 不使用 * @desc スキル・アイテムコマンド時に名称ウインドウを表示します。 * @default true * * @param useTrackName * @parent nameWindowSetting * @text 名称ウインドウを自動移動 * @type boolean * @on 使用 * @off 不使用 * @desc 名称ウインドウをリングコマンド上部に自動的に移動させます。 * @default true * * @param nameWindowX * @parent nameWindowSetting * @text 名称ウインドウX位置 * @type number * @min -9999 * @desc 名称ウインドウのX位置を設定します。自動移動が有効の場合は無視されます。 * @default 0 * * @param nameWindowY * @parent nameWindowSetting * @text 名称ウインドウY位置 * @type number * @min -9999 * @desc 名称ウインドウのY位置を設定します。自動移動が有効の場合は無視されます。 * @default 0 * * @param nameOffsetX * @parent nameWindowSetting * @text 名称ウインドウXオフセット * @type number * @min -9999 * @desc 名称ウインドウのXオフセットです。自動移動が有効の時に更に微調整したい場合ここを使います。 * @default 0 * * @param nameOffsetY * @parent nameWindowSetting * @text 名称ウインドウYオフセット * @type number * @min -9999 * @desc 名称ウインドウのYオフセットです。自動移動が有効の時に更に微調整したい場合ここを使います。 * @default 0 * * @param nameWindowWidth * @parent nameWindowSetting * @text 名称ウインドウ横幅 * @type number * @desc 名称ウインドウの横幅を設定します。 * @default * * @param nameWindowHeight * @parent nameWindowSetting * @text 名称ウインドウ高さ * @type number * @desc 名称ウインドウの高さを設定します。 * @default * * @param nameFontSize * @parent nameWindowSetting * @text 名称のフォントサイズ * @type number * @desc 名称ウインドウで使用するフォントサイズを設定します。指定しない場合メインフォントサイズを使用します。 * @default * * @param helpWindowSetting * @text ヘルプウインドウ設定 * @default ------------------------------ * @type string * @desc ヘルプウインドウ関連の設定をします。 * * @param useTrackHelp * @parent helpWindowSetting * @text ヘルプウインドウを自動移動 * @type boolean * @on 使用 * @off 不使用 * @desc ヘルプウインドウをリングコマンド下部に自動的に移動させます。戦闘中の全てのヘルプウインドウが対象です。 * @default true * * @param helpWindowWidth * @parent helpWindowSetting * @text ヘルプウインドウ横幅 * @type number * @desc 名称ウインドウの横幅を設定します。戦闘中の全てのヘルプウインドウが対象です。 * @default * * @param helpWindowHeight * @parent helpWindowSetting * @text ヘルプウインドウ高さ * @type number * @desc 名称ウインドウの高さを設定します。戦闘中の全てのヘルプウインドウが対象です。 * @default * * @param helpOffsetX * @parent helpWindowSetting * @text ヘルプウインドウXオフセット * @type number * @min -9999 * @desc ヘルプウインドウのXオフセットです。自動移動が有効の時に更に微調整したい場合ここを使います。 * @default 0 * * @param helpOffsetY * @parent helpWindowSetting * @text ヘルプウインドウYオフセット * @type number * @min -9999 * @desc ヘルプウインドウのYオフセットです。自動移動が有効の時に更に微調整したい場合ここを使います。 * @default 0 */ (() => { 'use strict'; const pluginName = decodeURIComponent(document.currentScript.src).match(/^.*\/js\/plugins\/(.+)\.js$/)[1]; const parameters = PluginManager.parameters(pluginName); const useRingActorCommand = parameters["useRingActorCommand"] === "true"; const useRingSkillCommand = parameters["useRingSkillCommand"] === "true"; const useRingItemCommand = parameters["useRingItemCommand"] === "true"; const hideOnEnemyTarget = parameters["hideOnEnemyTarget"] === "true"; const hideOnSkillTarget = parameters["hideOnSkillTarget"] === "true"; const hideOnItemTarget = parameters["hideOnItemTarget"] === "true"; const hideOnSkillHelp = parameters["hideOnSkillHelp"] === "true"; const hideOnItemHelp = parameters["hideOnItemHelp"] === "true"; const ringWindowSkin = parameters["ringWindowSkin"]; const ringWindowButton = parameters["ringWindowButton"] const selectCursor = parameters["selectCursor"] const useActorCommandIcon = parameters["useActorCommandIcon"] === "true"; const rotationSpeed = Number(parameters["rotationSpeed"] || 0.1); const isReverse = parameters["reverseRingCommand"] === "true"; const ringWidth = Number(parameters["ringWidth"] || 400); const ringHeight = Number(parameters["ringHeight"] || ringWidth); const commandWidth = Number(parameters["commandWidth"] || 64); const commandHeight = Number(parameters["commandHeight"] || commandWidth); const adjustedPos = Number(parameters["adjustedPos"] || 0); const adjustCursorY = Number(parameters["adjustCursorY"] || 0); const iconScale = Number(parameters["iconScale"] || 1); const useTrackRing = parameters["useTrackRing"] === "true"; const ringCommandX = Number(parameters["ringCommandX"] || 400); const ringCommandY = Number(parameters["ringCommandY"] || 300); const ringOffsetX = Number(parameters["ringOffsetX"] || 0); const ringOffsetY = Number(parameters["ringOffsetY"] || 0); const useNameWindow = parameters["useNameWindow"] === "true"; const useTrackName = parameters["useTrackName"] === "true"; const nameWindowX = Number(parameters["nameWindowX"] || 0); const nameWindowY = Number(parameters["nameWindowY"] || 0); const nameOffsetX = Number(parameters["nameOffsetX"] || 0); const nameOffsetY = Number(parameters["nameOffsetY"] || 0); const nameWindowWidth = Number(parameters["nameWindowWidth"]); const nameWindowHeight = Number(parameters["nameWindowHeight"]); const nameFontSize = Number(parameters["nameFontSize"]); const useTrackHelp = parameters["useTrackHelp"] === "true"; const helpWindowWidth = Number(parameters["helpWindowWidth"]); const helpWindowHeight = Number(parameters["helpWindowHeight"]); const helpOffsetX = Number(parameters["helpOffsetX"] || 0); const helpOffsetY = Number(parameters["helpOffsetY"] || 0); ImageManager.loadRingIcon = function(filename) { return this.loadBitmap("img/ringIcons/", filename); }; //----------------------------------------------------------------------------- // Scene_Battle // // const _Scene_Battle_createActorCommandWindow = Scene_Battle.prototype.createActorCommandWindow; Scene_Battle.prototype.createActorCommandWindow = function() { if (useRingActorCommand) { if (useNameWindow) this.createCommandNameWindow(); const rect = this.ringCommandWindowRect(); const commandWindow = new Window_RingActorCommand(rect); commandWindow.y = Graphics.boxHeight - commandWindow.height; commandWindow.setHandler("attack", this.commandAttack.bind(this)); commandWindow.setHandler("skill", this.commandSkill.bind(this)); commandWindow.setHandler("guard", this.commandGuard.bind(this)); commandWindow.setHandler("item", this.commandItem.bind(this)); commandWindow.setHandler("cancel", this.commandCancel.bind(this)); this.addWindow(commandWindow); this._actorCommandWindow = commandWindow; } else { if (useNameWindow) this.createCommandNameWindow(); _Scene_Battle_createActorCommandWindow.apply(this, arguments) } }; const _Scene_Battle_createSkillWindow = Scene_Battle.prototype.createSkillWindow; Scene_Battle.prototype.createSkillWindow = function() { if (useRingSkillCommand) { const rect = this.ringCommandWindowRect(); this._skillWindow = new Window_RingBattleSkill(rect); this._skillWindow.setHelpWindow(this._helpWindow); this._skillWindow.setHandler("ok", this.onSkillOk.bind(this)); this._skillWindow.setHandler("cancel", this.onSkillCancel.bind(this)); this.addWindow(this._skillWindow); } else { _Scene_Battle_createSkillWindow.apply(this, arguments) } }; const _Scene_Battle_createItemWindow = Scene_Battle.prototype.createItemWindow; Scene_Battle.prototype.createItemWindow = function() { if (useRingItemCommand) { const rect = this.ringCommandWindowRect(); this._itemWindow = new Window_RingBattleItem(rect); this._itemWindow.setHelpWindow(this._helpWindow); this._itemWindow.setHandler("ok", this.onItemOk.bind(this)); this._itemWindow.setHandler("cancel", this.onItemCancel.bind(this)); this.addWindow(this._itemWindow); } else { _Scene_Battle_createItemWindow.apply(this, arguments) } }; Scene_Battle.prototype.createCommandNameWindow = function() { const rect = this.commandNameWindowRect(); this._commandNameWindow = new Window_CommandName(rect); this.addWindow(this._commandNameWindow); this._commandNameWindow.hide(); }; Scene_Battle.prototype.ringCommandWindowRect = function() { const ww = ringWidth; const wh = ringHeight; const wx = useTrackRing ? 0 : ringCommandX; const wy = useTrackRing ? 0 : ringCommandY; return new Rectangle(wx, wy, ww, wh); }; Scene_Battle.prototype.commandNameWindowRect = function() { const ww = nameWindowWidth || Graphics.boxWidth / 5; const wh = nameWindowHeight || Window_Base.prototype.fittingHeight(1); const wx = nameWindowX; const wy = nameWindowY; return new Rectangle(wx, wy, ww, wh); }; const _Scene_Battle_helpWindowRect = Scene_Battle.prototype.helpWindowRect; Scene_Battle.prototype.helpWindowRect = function() { if (useTrackHelp) { const wx = 0; const wy = this.helpAreaTop(); const ww = helpWindowWidth || Graphics.boxWidth; const wh = helpWindowHeight || this.helpAreaHeight(); return new Rectangle(wx, wy, ww, wh); } return _Scene_Battle_helpWindowRect.apply(this, arguments) }; const _Scene_Battle_commandAttack = Scene_Battle.prototype.commandAttack; Scene_Battle.prototype.commandAttack = function() { if (hideOnEnemyTarget) this._actorCommandWindow.hide(); _Scene_Battle_commandAttack.apply(this, arguments) }; const _Scene_Battle_onSkillOk = Scene_Battle.prototype.onSkillOk; Scene_Battle.prototype.onSkillOk = function() { if (hideOnSkillTarget) { this._skillWindow.hide(); this._commandNameWindow.hide(); } _Scene_Battle_onSkillOk.apply(this, arguments) }; const _Scene_Battle_onItemOk = Scene_Battle.prototype.onItemOk; Scene_Battle.prototype.onItemOk = function() { if (hideOnItemTarget) { this._itemWindow.hide(); this._commandNameWindow.hide(); } _Scene_Battle_onItemOk.apply(this, arguments) }; const _Scene_Battle_onEnemyCancel = Scene_Battle.prototype.onEnemyCancel; Scene_Battle.prototype.onEnemyCancel = function() { _Scene_Battle_onEnemyCancel.apply(this, arguments) if (this._actorCommandWindow.currentSymbol() === "attack" && hideOnEnemyTarget) { this._actorCommandWindow.show(); } }; //============================================================================= // Create New Window_RingActorCommand // function Window_RingActorCommand() { this.initialize(...arguments); } Window_RingActorCommand.prototype = Object.create(Window_ActorCommand.prototype); Window_RingActorCommand.prototype.constructor = Window_RingActorCommand; Window_RingActorCommand.prototype.initialize = function(rect) { Window_ActorCommand.prototype.initialize.call(this, rect); this.resetIndex(); this._isWindow = false; this._threshold = 0.001; this._scene = SceneManager._scene; this._rotationSpeed = rotationSpeed; }; const _Window_RingActorCommand__createAllParts = Window_RingActorCommand.prototype._createAllParts; Window_RingActorCommand.prototype._createAllParts = function() { _Window_RingActorCommand__createAllParts.apply(this, arguments) this._createSelectCursorSprite(); }; Window_RingActorCommand.prototype.resetIndex = function() { this.forceSelect(0); this._selectIndex = 0; this._rotationIndex = 0; this._rotationTarget = 0; this._refreshFlag = true; }; Window_RingActorCommand.prototype.activate = function() { Window_ActorCommand.prototype.activate.call(this); this.resetIndex(); }; Window_RingActorCommand.prototype.select = function(index) { this._index = index; this.callUpdateHelp(); }; Window_RingActorCommand.prototype.updatePadding = function() { this.padding = 0; }; Window_RingActorCommand.prototype.update = function () { Window_ActorCommand.prototype.update.call(this); if (!this._actor) return; const sprite = this._scene._spriteset._actorSprites[$gameParty.battleMembers().indexOf(this._actor)]; if (sprite && useTrackRing) { const ww = this.width; const wh = this.height; const wx = (sprite.transform.worldTransform.tx - ww / 2) - this._margin + ringOffsetX; const wy = (sprite.transform.worldTransform.ty - wh / 2) - (sprite.height / 2) + ringOffsetY; if (this.x !== wx || this.y !== wy) { this.move(wx, wy, ww, wh); } } if (this._rotationIndex === this._rotationTarget && !this._refreshFlag) return; this._rotationIndex += (this._rotationTarget - this._rotationIndex) * this._rotationSpeed; if (Math.abs(this._rotationTarget - this._rotationIndex) < this._threshold) { this._rotationIndex = this._rotationTarget; this._refreshFlag = false; } this._refreshCursor(); this.refreshCursor(); Window_Selectable.prototype.refresh.call(this); }; Window_RingActorCommand.prototype._createBackSprite = function() { this._backSprite = new Sprite(); this._backSprite.visible = false; this._container.addChild(this._backSprite); }; Window_RingActorCommand.prototype._createFrameSprite = function() { const bitmap = ImageManager.loadSystem(ringWindowSkin); bitmap.addLoadListener(() => { this._frameSprite = new Sprite(bitmap); this._container.addChild(this._frameSprite); }); }; Window_RingActorCommand.prototype._createSelectCursorSprite = function() { const bitmap = ImageManager.loadSystem(selectCursor); bitmap.addLoadListener(() => { this._selectCursorSprite = new Sprite(bitmap); this._selectCursorSprite.anchor.x = 0.5; this._selectCursorSprite.x = ringWidth / 2; this._selectCursorSprite.y = adjustedPos + (adjustCursorY || 0); this._clientArea.addChild(this._selectCursorSprite); }); }; Window_RingActorCommand.prototype.paint = function() { Window_Selectable.prototype.paint.call(this); }; Window_RingActorCommand.prototype._refreshAllParts = function() { this._refreshCursor(); this._refreshArrows(); this._refreshPauseSign(); }; const _Window_RingActorCommand__createCursorSprite = Window_RingActorCommand.prototype._createCursorSprite; Window_RingActorCommand.prototype._createCursorSprite = function() { _Window_RingActorCommand__createCursorSprite.apply(this, arguments) this.createCursorMask(); // マスクを適用 }; const _Window_RingActorCommand__refreshCursor = Window_RingActorCommand.prototype._refreshCursor; Window_RingActorCommand.prototype._refreshCursor = function() { _Window_RingActorCommand__refreshCursor.apply(this, arguments) // マスクの位置とサイズを同期 if (this._cursorMask) { this._cursorMask.x = this._cursorRect.x; this._cursorMask.y = this._cursorRect.y; this._cursorMask.scale.x = this._cursorRect.width / this._cursorMask.bitmap.width; this._cursorMask.scale.y = this._cursorRect.height / this._cursorMask.bitmap.height; } }; Window_RingActorCommand.prototype.drawItemBackground = function(index) { const rect = this.itemRect(index); this.drawBackgroundRect(rect, index); }; Window_RingActorCommand.prototype.drawBackgroundRect = function(rect, index) { const backgroundBitmap = ImageManager.loadSystem(ringWindowButton); if (backgroundBitmap.isReady()) { this.contentsBack.blt(backgroundBitmap, 0, 0, backgroundBitmap.width, backgroundBitmap.height, rect.x, rect.y, rect.width, rect.height); } else { backgroundBitmap.addLoadListener(() => this.refresh()); } if (!useActorCommandIcon) return; const command = this._list[index]; const iconBitmap = this.getCommandIconBitmap(command); if (iconBitmap && iconBitmap.isReady()) { const iconSize = rect.width; const iconX = rect.x + (rect.width - iconSize) / 2; const iconY = rect.y + (rect.height - iconSize) / 2; this.contentsBack.blt(iconBitmap, 0, 0, iconBitmap.width, iconBitmap.height, iconX, iconY, iconSize, iconSize); } else if (iconBitmap) { iconBitmap.addLoadListener(() => this.refresh()); } }; Window_RingActorCommand.prototype.getCommandIconBitmap = function(command) { let imageName = command.symbol; if (command.symbol === "skill" && command.ext !== null) { imageName += command.ext; } return ImageManager.loadSystem(imageName); }; //============================================================================= // Create New Window_RingBattleSkill // function Window_RingBattleSkill() { this.initialize(...arguments); } Window_RingBattleSkill.prototype = Object.create(Window_BattleSkill.prototype); Window_RingBattleSkill.prototype.constructor = Window_RingBattleSkill; Window_RingBattleSkill.prototype.initialize = function(rect) { Window_BattleSkill.prototype.initialize.call(this, rect); this.resetIndex(); this._isWindow = false; this._threshold = 0.001; this._scene = SceneManager._scene; this._rotationSpeed = rotationSpeed; }; Window_RingBattleSkill.prototype.maxCols = function() { return 99; }; const _Window_RingBattleSkill__createAllParts = Window_RingBattleSkill.prototype._createAllParts; Window_RingBattleSkill.prototype._createAllParts = function() { _Window_RingBattleSkill__createAllParts.apply(this, arguments) this._createSelectCursorSprite(); }; Window_RingBattleSkill.prototype.resetIndex = function() { this.forceSelect(0); this._selectIndex = 0; this._rotationIndex = 0; this._rotationTarget = 0; this._refreshFlag = true; }; Window_RingBattleSkill.prototype.activate = function() { Window_BattleSkill.prototype.activate.call(this); this.resetIndex(); }; Window_RingBattleSkill.prototype.select = function(index) { this._index = index; this.callUpdateHelp(); }; Window_RingBattleSkill.prototype.show = function() { this.selectLast(); this.showHelpWindow(); Window_SkillList.prototype.show.call(this); const scene = SceneManager._scene; scene._commandNameWindow.clear(); scene._commandNameWindow.show(); scene._commandNameWindow.open(); }; Window_RingBattleSkill.prototype.hide = function() { this.hideHelpWindow(); Window_SkillList.prototype.hide.call(this); const scene = SceneManager._scene; scene._commandNameWindow.hide(); scene._commandNameWindow.close(); }; Window_RingBattleSkill.prototype.updatePadding = function() { this.padding = 0; }; Window_RingBattleSkill.prototype.update = function () { Window_BattleSkill.prototype.update.call(this); if (!this._actor) return; const sprite = this._scene._spriteset._actorSprites[$gameParty.battleMembers().indexOf(this._actor)]; if (sprite && useTrackRing) { const ww = this.width; const wh = this.height; const wx = (sprite.transform.worldTransform.tx - ww / 2) - this._margin + ringOffsetX; const wy = (sprite.transform.worldTransform.ty - wh / 2) - (sprite.height / 2) + ringOffsetY; if (this.x !== wx || this.y !== wy) { this.move(wx, wy, ww, wh); } } if (!this.item()) return; if (this._rotationIndex === this._rotationTarget && !this._refreshFlag) return; this._rotationIndex += (this._rotationTarget - this._rotationIndex) * this._rotationSpeed; if (Math.abs(this._rotationTarget - this._rotationIndex) < this._threshold) { this._rotationIndex = this._rotationTarget; this._refreshFlag = false; } this._refreshCursor(); this.refreshCursor(); Window_Selectable.prototype.refresh.call(this); }; Window_RingBattleSkill.prototype.drawItem = function(index) { const skill = this.itemAt(index); if (skill) { const costWidth = this.costWidth(); const rect = this.itemLineRect(index); this.changePaintOpacity(this.isEnabled(skill)); this.drawItemIcon(skill, rect.x, rect.y, rect.width); // アイコンのみ表示する(名称を入れると長いので別に表示) this.drawSkillCost(skill, rect.x, rect.y + 16, rect.width, rect.width, 'center'); this.changePaintOpacity(1); } }; // アイコンのみ表示する(スキルやアイテムは名称を入れると長いので別に表示) Window_RingBattleSkill.prototype.drawItemIcon = function(skill, x, y, width) { let fileName, bitmap, sx, sy, sw, sh, scale; if (skill && skill.meta.ringIcon) { fileName = "skillIcon" + skill.id; } const iconWidth = ImageManager.iconWidth; const iconHeight = ImageManager.iconHeight; if (fileName) { bitmap = ImageManager.loadRingIcon(fileName); sx = sy = 0; sw = bitmap.width; sh = bitmap.height; scale = 1; } else { const iconIndex = skill.iconIndex; bitmap = ImageManager.loadSystem("IconSet"); sx = (iconIndex % 16) * iconWidth; sy = Math.floor(iconIndex / 16) * iconHeight; sw = iconWidth; sh = iconHeight; scale = iconScale; } const scaledWidth = Math.floor(sw * scale); const scaledHeight = Math.floor(sh * scale); const drawX = Math.floor(x + (width - scaledWidth) / 2); const drawY = Math.floor(y + (this.lineHeight() - scaledHeight) / 2); if (bitmap.isReady()) { this.contents.blt(bitmap, sx, sy, sw, sh, drawX, drawY, scaledWidth, scaledHeight); } else { bitmap.addLoadListener(() => this.refresh()); } }; Window_RingBattleSkill.prototype._createBackSprite = function() { this._backSprite = new Sprite(); this._backSprite.visible = false; this._container.addChild(this._backSprite); }; Window_RingBattleSkill.prototype._createFrameSprite = function() { const bitmap = ImageManager.loadSystem(ringWindowSkin); bitmap.addLoadListener(() => { this._frameSprite = new Sprite(bitmap); this._container.addChild(this._frameSprite); }); }; Window_RingBattleSkill.prototype._createSelectCursorSprite = function() { const bitmap = ImageManager.loadSystem(selectCursor); bitmap.addLoadListener(() => { this._selectCursorSprite = new Sprite(bitmap); this._selectCursorSprite.anchor.x = 0.5; this._selectCursorSprite.x = ringWidth / 2; this._selectCursorSprite.y = adjustedPos + (adjustCursorY || 0); this._clientArea.addChild(this._selectCursorSprite); }); }; Window_RingBattleSkill.prototype._refreshAllParts = function() { this._refreshCursor(); this._refreshArrows(); this._refreshPauseSign(); }; const _Window_RingBattleSkill__createCursorSprite = Window_RingBattleSkill.prototype._createCursorSprite; Window_RingBattleSkill.prototype._createCursorSprite = function() { _Window_RingBattleSkill__createCursorSprite.apply(this, arguments) this.createCursorMask(); // マスクを適用 }; const _Window_RingBattleSkill__refreshCursor = Window_RingBattleSkill.prototype._refreshCursor; Window_RingBattleSkill.prototype._refreshCursor = function() { _Window_RingBattleSkill__refreshCursor.apply(this, arguments) // マスクの位置とサイズを同期 if (this._cursorMask) { this._cursorMask.x = this._cursorRect.x; this._cursorMask.y = this._cursorRect.y; this._cursorMask.scale.x = this._cursorRect.width / this._cursorMask.bitmap.width; this._cursorMask.scale.y = this._cursorRect.height / this._cursorMask.bitmap.height; } }; Window_RingBattleSkill.prototype.drawBackgroundRect = function(rect) { const bitmap = ImageManager.loadSystem(ringWindowButton); const x = rect.x; const y = rect.y; const w = rect.width; const h = rect.height; this.contentsBack.blt(bitmap, 0, 0, bitmap.width, bitmap.height, x, y, w, h); }; Window_RingBattleSkill.prototype.updateHelp = function() { this._helpWindow.clear(); this.setHelpWindowItem(this.item()); if (this.item()) SceneManager._scene._commandNameWindow.refresh(this.item().name) }; Window_RingBattleSkill.prototype.showHelpWindow = function() { if (this._helpWindow && hideOnSkillHelp) { this._helpWindow.show(); } }; //============================================================================= // Create New Window_RingBattleItem // function Window_RingBattleItem() { this.initialize(...arguments); } Window_RingBattleItem.prototype = Object.create(Window_BattleItem.prototype); Window_RingBattleItem.prototype.constructor = Window_RingBattleItem; Window_RingBattleItem.prototype.initialize = function(rect) { Window_BattleItem.prototype.initialize.call(this, rect); this.resetIndex(); this._isWindow = false; this._threshold = 0.001; this._scene = SceneManager._scene; this._rotationSpeed = rotationSpeed; }; Window_RingBattleItem.prototype.maxCols = function() { return 99; }; const _Window_RingBattleItem__createAllParts = Window_RingBattleItem.prototype._createAllParts; Window_RingBattleItem.prototype._createAllParts = function() { _Window_RingBattleItem__createAllParts.apply(this, arguments) this._createSelectCursorSprite(); }; Window_RingBattleItem.prototype.resetIndex = function() { if (!this.item()) return this.forceSelect(0); this._selectIndex = 0; this._rotationIndex = 0; this._rotationTarget = 0; this._refreshFlag = true; }; Window_RingBattleItem.prototype.activate = function() { Window_BattleItem.prototype.activate.call(this); this.resetIndex(); }; Window_RingBattleItem.prototype.select = function(index) { this._index = index; this.callUpdateHelp(); }; Window_RingBattleItem.prototype.show = function() { this.selectLast(); this.showHelpWindow(); Window_ItemList.prototype.show.call(this); const scene = SceneManager._scene; scene._commandNameWindow.clear(); scene._commandNameWindow.show(); scene._commandNameWindow.open(); }; Window_RingBattleItem.prototype.hide = function() { this.hideHelpWindow(); Window_ItemList.prototype.hide.call(this); const scene = SceneManager._scene; scene._commandNameWindow.hide(); scene._commandNameWindow.close(); }; Window_RingBattleItem.prototype.updatePadding = function() { this.padding = 0; }; Window_RingBattleItem.prototype.update = function () { Window_BattleItem.prototype.update.call(this); const actor = BattleManager.actor(); if (!actor) return; const sprite = this._scene._spriteset._actorSprites[$gameParty.battleMembers().indexOf(actor)]; if (sprite && useTrackRing) { const ww = this.width; const wh = this.height; const wx = (sprite.transform.worldTransform.tx - ww / 2) - this._margin + ringOffsetX; const wy = (sprite.transform.worldTransform.ty - wh / 2) - (sprite.height / 2) + ringOffsetY; if (this.x !== wx || this.y !== wy) { this.move(wx, wy, ww, wh); } } if (!this.item()) return; if (this._rotationIndex === this._rotationTarget && !this._refreshFlag) return; this._rotationIndex += (this._rotationTarget - this._rotationIndex) * this._rotationSpeed; if (Math.abs(this._rotationTarget - this._rotationIndex) < this._threshold) { this._rotationIndex = this._rotationTarget; this._refreshFlag = false; } this._refreshCursor(); this.refreshCursor(); Window_Selectable.prototype.refresh.call(this); }; Window_RingBattleItem.prototype.drawItem = function(index) { const item = this.itemAt(index); if (item) { const rect = this.itemLineRect(index); this.changePaintOpacity(this.isEnabled(item)); this.drawItemIcon(item, rect.x, rect.y, rect.width); // アイコンのみ表示する(名称を入れると長いので別に表示) this.drawItemNumber(item, rect.x, rect.y + 16, rect.width, rect.width, 'center'); this.changePaintOpacity(1); } }; Window_RingBattleItem.prototype.drawItemIcon = function(item, x, y, width) { let fileName, bitmap, sx, sy, sw, sh, scale; if (item && item.meta.ringIcon) { fileName = "ItemIcon" + item.id; } const iconWidth = ImageManager.iconWidth; const iconHeight = ImageManager.iconHeight; if (fileName) { bitmap = ImageManager.loadRingIcon(fileName); sx = sy = 0; sw = bitmap.width; sh = bitmap.height; scale = 1; } else { const iconIndex = item.iconIndex; bitmap = ImageManager.loadSystem("IconSet"); sx = (iconIndex % 16) * iconWidth; sy = Math.floor(iconIndex / 16) * iconHeight; sw = iconWidth; sh = iconHeight; scale = iconScale; } const scaledWidth = Math.floor(sw * scale); const scaledHeight = Math.floor(sh * scale); const drawX = Math.floor(x + (width - scaledWidth) / 2); const drawY = Math.floor(y + (this.lineHeight() - scaledHeight) / 2); if (bitmap.isReady()) { this.contents.blt(bitmap, sx, sy, sw, sh, drawX, drawY, scaledWidth, scaledHeight); } else { bitmap.addLoadListener(() => this.refresh()); } }; Window_RingBattleItem.prototype.drawItemNumber = function(item, x, y, width) { if (this.needsNumber()) { this.drawText($gameParty.numItems(item), x, y, width, "center"); } }; Window_RingBattleItem.prototype._createBackSprite = function() { this._backSprite = new Sprite(); this._backSprite.visible = false; this._container.addChild(this._backSprite); }; Window_RingBattleItem.prototype._createFrameSprite = function() { const bitmap = ImageManager.loadSystem(ringWindowSkin); bitmap.addLoadListener(() => { this._frameSprite = new Sprite(bitmap); this._container.addChild(this._frameSprite); }); }; Window_RingBattleItem.prototype._createSelectCursorSprite = function() { const bitmap = ImageManager.loadSystem(selectCursor); bitmap.addLoadListener(() => { this._selectCursorSprite = new Sprite(bitmap); this._selectCursorSprite.anchor.x = 0.5; this._selectCursorSprite.x = ringWidth / 2; this._selectCursorSprite.y = adjustedPos + (adjustCursorY || 0); this._clientArea.addChild(this._selectCursorSprite); }); }; Window_RingBattleItem.prototype._refreshAllParts = function() { this._refreshCursor(); this._refreshArrows(); this._refreshPauseSign(); }; const _Window_RingBattleItem__createCursorSprite = Window_RingBattleItem.prototype._createCursorSprite; Window_RingBattleItem.prototype._createCursorSprite = function() { _Window_RingBattleItem__createCursorSprite.apply(this, arguments) this.createCursorMask(); // マスクを適用 }; const _Window_RingBattleItem__refreshCursor = Window_RingBattleItem.prototype._refreshCursor; Window_RingBattleItem.prototype._refreshCursor = function() { _Window_RingBattleItem__refreshCursor.apply(this, arguments) // マスクの位置とサイズを同期 if (this._cursorMask) { this._cursorMask.x = this._cursorRect.x; this._cursorMask.y = this._cursorRect.y; this._cursorMask.scale.x = this._cursorRect.width / this._cursorMask.bitmap.width; this._cursorMask.scale.y = this._cursorRect.height / this._cursorMask.bitmap.height; } }; Window_RingBattleItem.prototype.drawBackgroundRect = function(rect) { const bitmap = ImageManager.loadSystem(ringWindowButton); const x = rect.x; const y = rect.y; const w = rect.width; const h = rect.height; this.contentsBack.blt(bitmap, 0, 0, bitmap.width, bitmap.height, x, y, w, h); }; Window_RingBattleItem.prototype.updateHelp = function() { this._helpWindow.clear(); this.setHelpWindowItem(this.item()); if (this.item()) SceneManager._scene._commandNameWindow.refresh(this.item().name) }; Window_RingBattleItem.prototype.showHelpWindow = function() { if (this._helpWindow && hideOnItemHelp) { this._helpWindow.show(); } }; //----------------------------------------------------------------------------- // Common process for ring commands // // const RingCommandProcess = { changeSelection: function(isReverse) { const max = this.maxItems(); if (max === 0) return; const direction = isReverse ? 1 : -1; this._selectIndex = (this._selectIndex + direction + max) % max; this.refresh(); this.select(this._selectIndex); this._rotationTarget -= direction; }, onTouchSelect: function(trigger) { this._doubleTouch = false; if (this.isCursorMovable()) { const lastIndex = this._selectIndex; const hitIndex = this._selectIndex; if (hitIndex >= 0) { if (hitIndex === this.index()) { this._doubleTouch = true; } this.select(hitIndex); } if (trigger && this.index() !== lastIndex) { this.playCursorSound(); } } }, itemRect: function(index) { const centerX = this.innerWidth / 2; const centerY = this.innerHeight / 2; const radius = Math.min(centerX, centerY) - (commandWidth / 2) - adjustedPos; const itemWidth = commandWidth; const itemHeight = commandHeight; // 角度計算 const totalItems = this.maxItems(); const baseAngle = ((index / totalItems) * Math.PI * 2) - (Math.PI / 2); const angle = baseAngle + (this._rotationIndex * (Math.PI * 2 / totalItems)); const x = Math.round(centerX + Math.cos(angle) * radius - itemWidth / 2); const y = Math.round(centerY + Math.sin(angle) * radius - itemHeight / 2); return new Rectangle(x, y, itemWidth, itemHeight); }, cursorRight: function() { this.changeSelection(!isReverse); }, cursorLeft: function() { this.changeSelection(isReverse); }, cursorUp: function() { this.changeSelection(!isReverse); }, cursorDown: function() { this.changeSelection(isReverse); }, smoothScrollUp: function(n) { this.changeSelection(!isReverse); }, smoothScrollDown: function(n) { this.changeSelection(isReverse); }, createCursorMask: function() { if (!ringWindowButton) { return; } this._cursorMask = new Sprite(); this._cursorMask.bitmap = ImageManager.loadSystem(ringWindowButton); this._cursorSprite.mask = this._cursorMask; this._clientArea.addChild(this._cursorMask); } }; Object.assign(Window_RingBattleItem.prototype, RingCommandProcess); Object.assign(Window_RingBattleSkill.prototype, RingCommandProcess); Object.assign(Window_RingActorCommand.prototype, RingCommandProcess); //----------------------------------------------------------------------------- // Fix Window_Help // //ヘルプウインドウの位置をリングコマンドに合わせて動的に変更する。 const _Window_Help_update = Window_Help.prototype.update; function battleHelpUpdate() { _Window_Help_update.call(this); if (!this.visible) return; const skillWindow = this._skillWindow; const itemWindow = this._itemWindow; const targetWindow = skillWindow?.visible ? skillWindow : (itemWindow?.visible ? itemWindow : null); if (targetWindow) { const ww = this.width; const wh = this.height; const wx = targetWindow.x + ((targetWindow.width - ww) / 2) + helpOffsetX; const wy = targetWindow.y + targetWindow.height + this._margin + helpOffsetY; this.move(wx, wy, ww, wh); } } const _Scene_Battle_createAllWindows = Scene_Battle.prototype.createAllWindows; Scene_Battle.prototype.createAllWindows = function() { _Scene_Battle_createAllWindows.apply(this, arguments); if (this._helpWindow && useTrackHelp) { this._helpWindow._skillWindow = this._skillWindow; this._helpWindow._itemWindow = this._itemWindow; this._helpWindow.update = battleHelpUpdate; } }; const _Scene_Battle_terminate = Scene_Battle.prototype.terminate; Scene_Battle.prototype.terminate = function() { if (this._helpWindow && useTrackHelp) { this._helpWindow.update = _Window_Help_update; this._helpWindow._skillWindow = null; this._helpWindow._itemWindow = null; } _Scene_Battle_terminate.apply(this, arguments); }; //----------------------------------------------------------------------------- // Create New Window_CommandName // // スキル・アイテム名表示用のウィンドウクラス function Window_CommandName() { this.initialize(...arguments); } Window_CommandName.prototype = Object.create(Window_Base.prototype); Window_CommandName.prototype.constructor = Window_CommandName; Window_CommandName.prototype.initialize = function(rect) { Window_Base.prototype.initialize.call(this, rect); this._scene = SceneManager._scene; }; Window_CommandName.prototype.drawSkillName = function(skillName) { this.contents.fontSize = nameFontSize || $gameSystem.mainFontSize(); this.drawText(skillName, 0, 0, this.contentsWidth(), 'center'); }; Window_CommandName.prototype.update = function() { Window_Base.prototype.update.call(this); if (!this.visible || !useTrackName) return; const skillWindow = this._scene._skillWindow; const itemWindow = this._scene._itemWindow; const targetWindow = skillWindow?.visible ? skillWindow : (itemWindow?.visible ? itemWindow : null); if (targetWindow) { const wx = targetWindow.x + ((targetWindow.width - this.width) / 2) + nameOffsetX; const wy = targetWindow.y - this.height - this._margin + nameOffsetY; this.move(wx, wy, this.width, this.height); } }; Window_CommandName.prototype.refresh = function(text = "") { this.contents.clear(); this.drawSkillName(text); }; Window_CommandName.prototype.clear = function() { this.contents.clear(); }; })();