566 lines
24 KiB
JavaScript
566 lines
24 KiB
JavaScript
//=============================================================================
|
||
// RPG Maker MZ - IM_BattleLayout
|
||
//
|
||
// Copyright 2025 I'm moralist/min-pub.com All rights reserved.
|
||
// This source code or any portion thereof must not be
|
||
// reproduced or used without licensed in any manner whatsoever.
|
||
//=============================================================================
|
||
/*:
|
||
* @target MZ
|
||
* @plugindesc [v1.0.9] バトル画面レイアウト一元管理 + シングルステータスウィンドウ。ステートウィンドウ機能は廃止しました。
|
||
* @author
|
||
*
|
||
* @help
|
||
* =============================================================================
|
||
* ■ 概要
|
||
* =============================================================================
|
||
* - バトル画面のウィンドウ配置を一元管理するプラグインです。
|
||
* - 1) 標準ステータスウィンドウは削除せず、画面外(-9999,-9999)に移動して非表示。
|
||
* - 2) 先頭アクター用のHP/MP/TPウィンドウ(幅600)を左下に配置(名前/ステート非表示)。
|
||
* - 3) ver1.06でステート専用ウィンドウ関連機能を廃止しました。
|
||
* - 4) 「this.drawGauge is not a function」エラー回避のフォールバックを冒頭で定義。
|
||
*
|
||
* ■ バージョン情報
|
||
* v1.0.9 (2025/6/05) : 全体をリファクタリング&IM_BattleLayoutMarginをマージ
|
||
* v1.0.8 (2025/3/18) : プレイヤー行動時ゲージ再描画 + TPゲージ75%超過時にアニメ点滅 : プレイヤー行動時のゲージ再描画を追加
|
||
* v1.0.6 (2025/3/18) : ステートウィンドウ機能を廃止
|
||
* v1.0.5 (2025/3/18) : 左側メニューに修正
|
||
* (以下略)
|
||
*/
|
||
|
||
(() => {
|
||
"use strict";
|
||
|
||
//========================================================================
|
||
// プラグイン定義
|
||
//========================================================================
|
||
const pluginName = "IM_BattleLayout";
|
||
const script = document.currentScript;
|
||
const param = PluginManagerEx.createParameter(script);
|
||
|
||
//========================================================================
|
||
// 定数定義
|
||
//========================================================================
|
||
const PARTY_CMD_ROWS = 6;
|
||
const ACTOR_CMD_ROWS = 6;
|
||
const CMD_WINDOW_WIDTH = 240;
|
||
const SINGLE_STATUS_LINES = 3;
|
||
const SINGLE_STATUS_WIDTH = 592;
|
||
const SKILLITEM_ROWS = 6;
|
||
const SKILLITEM_WIDTH = 960;
|
||
|
||
const GAUGE_MARGIN_X = 40;
|
||
const LABEL_WIDTH = 60;
|
||
const LABEL_GAP = 10;
|
||
const TP_GAUGE_MARGIN_X = 40;
|
||
const TP_LABEL_WIDTH = 60;
|
||
const TP_LABEL_GAP = 10;
|
||
const GAUGE_HEIGHT = 6;
|
||
const TP_GAUGE_HEIGHT = 9;
|
||
|
||
// 横方向のマージン量
|
||
const LEFT_MARGIN = 50;
|
||
const RIGHT_MARGIN = 50;
|
||
|
||
const LARGER_FONT_SIZE = 36;
|
||
|
||
//========================================================================
|
||
// 共通基盤
|
||
//========================================================================
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (Window_Base)
|
||
//========================================================================
|
||
// drawGauge フォールバック
|
||
if (typeof Window_Base.prototype.drawGauge !== "function") {
|
||
if (typeof Window_Base.prototype.gaugeBackColor !== "function") {
|
||
Window_Base.prototype.gaugeBackColor = function() {
|
||
return "#808080";
|
||
};
|
||
}
|
||
Window_Base.prototype.drawGauge = function(x, y, width, rate, color1, color2) {
|
||
const gaugeH = 6;
|
||
const gaugeY = y + this.lineHeight() - gaugeH - 2;
|
||
this.contents.fillRect(x, gaugeY, width, gaugeH, this.gaugeBackColor());
|
||
const fillW = Math.floor(width * rate);
|
||
const c1 = color1 || "#ff6060";
|
||
const c2 = color2 || "#ffc0c0";
|
||
this.contents.gradientFillRect(x, gaugeY, fillW, gaugeH, c1, c2, false);
|
||
};
|
||
}
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (Window_PartyCommand)
|
||
//========================================================================
|
||
// パーティコマンド&アクターコマンドのウィンドウ変更
|
||
const _Window_PartyCommand_prototype_numVisibleRows = Window_PartyCommand.prototype.numVisibleRows;
|
||
Window_PartyCommand.prototype.numVisibleRows = function() {
|
||
return PARTY_CMD_ROWS;
|
||
};
|
||
|
||
const _Window_PartyCommand_prototype_hide = Window_PartyCommand.prototype.hide;
|
||
Window_PartyCommand.prototype.hide = function() {
|
||
// do nothing
|
||
};
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (Window_ActorCommand)
|
||
//========================================================================
|
||
// パーティコマンド&アクターコマンドのウィンドウ変更
|
||
const _Scene_Battle_prototype_createActorCommandWindow = Scene_Battle.prototype.createActorCommandWindow;
|
||
Scene_Battle.prototype.createActorCommandWindow = function() {
|
||
const rect = this.actorCommandWindowRect();
|
||
const commandWindow = new Window_ActorCommand(rect);
|
||
commandWindow.y = Graphics.boxHeight - commandWindow.height;
|
||
|
||
commandWindow.setHandler("skill", this.commandSkill.bind(this));
|
||
commandWindow.setHandler("guard", this.commandGuard.bind(this));
|
||
|
||
// キャンセル禁止(戦う・逃げるに戻さない)
|
||
|
||
this.addWindow(commandWindow);
|
||
this._actorCommandWindow = commandWindow;
|
||
};
|
||
|
||
const _Window_ActorCommand_prototype_numVisibleRows = Window_ActorCommand.prototype.numVisibleRows;
|
||
Window_ActorCommand.prototype.numVisibleRows = function() {
|
||
return ACTOR_CMD_ROWS;
|
||
};
|
||
|
||
const _Window_ActorCommand_prototype_hide = Window_ActorCommand.prototype.hide;
|
||
Window_ActorCommand.prototype.hide = function() {
|
||
// do nothing
|
||
};
|
||
|
||
// 通常攻撃は使わない
|
||
const _Window_ActorCommand_prototype_addAttackCommand = Window_ActorCommand.prototype.addAttackCommand;
|
||
Window_ActorCommand.prototype.addAttackCommand = function() {
|
||
// do noghing
|
||
};
|
||
|
||
// 無効になってるコマンドは表示しないように
|
||
const _Window_ActorCommand_prototype_addGuardCommand = Window_ActorCommand.prototype.addGuardCommand;
|
||
Window_ActorCommand.prototype.addGuardCommand = function() {
|
||
if (this._actor.canGuard()) {
|
||
this.addCommand(TextManager.guard, "guard", this._actor.canGuard());
|
||
}
|
||
};
|
||
|
||
const _Window_ActorCommand_prototype_addItemCommand = Window_ActorCommand.prototype.addItemCommand;
|
||
Window_ActorCommand.prototype.addItemCommand = function() {
|
||
// アイテムは今のところ使用予定無いので非表示
|
||
// do nothing
|
||
};
|
||
|
||
const _Window_ActorCommand_prototype_selectLast = Window_ActorCommand.prototype.selectLast;
|
||
Window_ActorCommand.prototype.selectLast = function() {
|
||
if ($gameSwitches.value(15) === false) {
|
||
_Window_ActorCommand_prototype_selectLast.apply(this, arguments);
|
||
} else {
|
||
this.forceSelect(0);
|
||
$gameSwitches.setValue(15, false);
|
||
}
|
||
};
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (Window_BattleLog)
|
||
//========================================================================
|
||
const _Window_BattleLog_prototype_resetFontSettings = Window_BattleLog.prototype.resetFontSettings;
|
||
Window_BattleLog.prototype.resetFontSettings = function() {
|
||
this.contents.fontFace = $gameSystem.mainFontFace();
|
||
this.contents.fontSize = LARGER_FONT_SIZE;
|
||
this.resetTextColor();
|
||
};
|
||
|
||
const _Window_BattleLog_prototype_lineHeight = Window_BattleLog.prototype.lineHeight;
|
||
Window_BattleLog.prototype.lineHeight = function() {
|
||
return 38;
|
||
};
|
||
|
||
const _Window_BattleLog_prototype_itemHeight = Window_BattleLog.prototype.itemHeight;
|
||
Window_BattleLog.prototype.itemHeight = function() {
|
||
return this.lineHeight() + 2;
|
||
};
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (Scene_Battle)
|
||
//========================================================================
|
||
const _Scene_Battle_prototype_partyCommandWindowRect = Scene_Battle.prototype.partyCommandWindowRect;
|
||
Scene_Battle.prototype.partyCommandWindowRect = function() {
|
||
const ww = CMD_WINDOW_WIDTH;
|
||
const wh = this.calcWindowHeight(PARTY_CMD_ROWS, true);
|
||
const wx = 0;
|
||
const wy = Graphics.boxHeight - wh;
|
||
return new Rectangle(wx, wy, ww, wh);
|
||
};
|
||
|
||
const _Scene_Battle_prototype_actorCommandWindowRect = Scene_Battle.prototype.actorCommandWindowRect;
|
||
Scene_Battle.prototype.actorCommandWindowRect = function() {
|
||
const ww = CMD_WINDOW_WIDTH;
|
||
const wh = this.calcWindowHeight(ACTOR_CMD_ROWS, true);
|
||
const wx = 0;
|
||
const wy = Graphics.boxHeight - wh;
|
||
return new Rectangle(wx, wy, ww, wh);
|
||
};
|
||
|
||
// バトルログの修正
|
||
const _Scene_Battle_prototype_logWindowRect = Scene_Battle.prototype.logWindowRect;
|
||
Scene_Battle.prototype.logWindowRect = function() {
|
||
const cmdRect = this.partyCommandWindowRect();
|
||
const wx = cmdRect.x + cmdRect.width + 10;
|
||
const wy = 0;
|
||
const ww = Graphics.boxWidth - ((cmdRect.x + cmdRect.width + 10) * 2);
|
||
const wh = this.calcWindowHeight(14, false);
|
||
return new Rectangle(wx, wy, ww, wh);
|
||
};
|
||
|
||
// シングルステータスウィンドウ (HP/MP/TP)
|
||
const _Scene_Battle_createAllWindows = Scene_Battle.prototype.createAllWindows;
|
||
Scene_Battle.prototype.createAllWindows = function() {
|
||
_Scene_Battle_createAllWindows.apply(this, arguments);
|
||
|
||
// メッセージウィンドウのフォントサイズ変更
|
||
this._messageWindow.contents.fontSize += 12;
|
||
|
||
// 旧ステータスウィンドウを画面外へ
|
||
if (this._statusWindow) {
|
||
this._statusWindow.x = -9999;
|
||
this._statusWindow.y = -9999;
|
||
this._statusWindow.visible = false;
|
||
}
|
||
|
||
// 新ステータス(HP/MP/TP)
|
||
this.createSingleActorWindow();
|
||
};
|
||
|
||
Scene_Battle.prototype.createSingleActorWindow = function() {
|
||
const rect = this.singleActorWindowRect();
|
||
this._singleActorWindow = new Window_SingleActorStatus(rect);
|
||
this.addWindow(this._singleActorWindow);
|
||
};
|
||
|
||
Scene_Battle.prototype.singleActorWindowRect = function() {
|
||
const ww = SINGLE_STATUS_WIDTH;
|
||
const wh = this.calcWindowHeight(SINGLE_STATUS_LINES, false);
|
||
const wx = Graphics.boxWidth - ww;
|
||
const wy = Graphics.boxHeight - wh;
|
||
return new Rectangle(wx, wy, ww, wh);
|
||
};
|
||
|
||
// スキル等の説明ウィンドウ
|
||
const _Scene_Battle_prototype_helpWindowRect = Scene_Battle.prototype.helpWindowRect;
|
||
Scene_Battle.prototype.helpWindowRect = function() {
|
||
const cmdRect = this.partyCommandWindowRect();
|
||
const ww = Graphics.boxWidth - ((cmdRect.x + cmdRect.width + 10) * 2);
|
||
const wh = this.helpAreaHeight();
|
||
const wx = cmdRect.x + cmdRect.width + 10;
|
||
const wy = this.helpAreaTop();
|
||
return new Rectangle(wx, wy, ww, wh);
|
||
};
|
||
|
||
const _Scene_Battle_prototype_helpAreaHeight = Scene_Battle.prototype.helpAreaHeight;
|
||
Scene_Battle.prototype.helpAreaHeight = function() {
|
||
const numLines = 2;
|
||
return numLines * (LARGER_FONT_SIZE + 4) + $gameSystem.windowPadding() * 2;
|
||
};
|
||
|
||
const _Scene_Battle_prototype_createHelpWindow = Scene_Battle.prototype.createHelpWindow;
|
||
Scene_Battle.prototype.createHelpWindow = function() {
|
||
const rect = this.helpWindowRect();
|
||
this._helpWindow = new Window_HelpInBattle(rect);
|
||
this._helpWindow.hide();
|
||
this.addWindow(this._helpWindow);
|
||
};
|
||
|
||
// スキル/アイテム/敵選択ウィンドウ
|
||
Scene_Battle.prototype.skillItemEnemyWindowRect = function() {
|
||
const cmdRect = this.partyCommandWindowRect();
|
||
const ww = SKILLITEM_WIDTH;
|
||
const wh = this.calcWindowHeight(SKILLITEM_ROWS, true);
|
||
const wx = cmdRect.x + cmdRect.width + 10;
|
||
const wy = cmdRect.y + cmdRect.height - wh;
|
||
return new Rectangle(wx, wy, ww, wh);
|
||
};
|
||
|
||
const _Scene_Battle_prototype_skillWindowRect = Scene_Battle.prototype.skillWindowRect;
|
||
Scene_Battle.prototype.skillWindowRect = function() {
|
||
return this.skillItemEnemyWindowRect();
|
||
};
|
||
|
||
const _Scene_Battle_prototype_itemWindowRect = Scene_Battle.prototype.itemWindowRect;
|
||
Scene_Battle.prototype.itemWindowRect = function() {
|
||
return this.skillItemEnemyWindowRect();
|
||
};
|
||
|
||
const _Scene_Battle_prototype_enemyWindowRect = Scene_Battle.prototype.enemyWindowRect;
|
||
Scene_Battle.prototype.enemyWindowRect = function() {
|
||
return this.skillItemEnemyWindowRect();
|
||
};
|
||
|
||
// バトルシーンに入ったときだけバトルウィンドウ類が生成される時点(createDisplayObjects)で
|
||
// boxWidth を書き換えて左右マージンを適用する
|
||
const _Scene_Battle_createDisplayObjects = Scene_Battle.prototype.createDisplayObjects;
|
||
Scene_Battle.prototype.createDisplayObjects = function() {
|
||
// バトルシーン開始処理(ウィンドウ生成前)
|
||
|
||
// いまの boxWidth を保持
|
||
this._originalBoxWidthIM = Graphics.boxWidth;
|
||
|
||
// boxWidth を狭める
|
||
const totalMargin = LEFT_MARGIN + RIGHT_MARGIN;
|
||
Graphics.boxWidth = Math.max(1, Graphics.boxWidth - totalMargin);
|
||
|
||
// ADV バックログ抑止
|
||
if (!!$gameTemp.adv) {
|
||
$gameTemp.adv.enableBackLog(false);
|
||
}
|
||
|
||
// 元メソッド実行 → バトルウィンドウ類は「狭めたwidth」で初期化される
|
||
_Scene_Battle_createDisplayObjects.call(this);
|
||
};
|
||
|
||
const _Scene_Battle_terminate = Scene_Battle.prototype.terminate;
|
||
Scene_Battle.prototype.terminate = function() {
|
||
// バトルシーン終了処理
|
||
|
||
// boxWidth を元に戻す
|
||
if (this._originalBoxWidthIM != null) {
|
||
Graphics.boxWidth = this._originalBoxWidthIM;
|
||
}
|
||
|
||
// ADV バックログ復帰
|
||
if (!!$gameTemp.adv) {
|
||
$gameTemp.adv.enableBackLog(true);
|
||
}
|
||
|
||
// 元メソッド実行
|
||
_Scene_Battle_terminate.call(this);
|
||
};
|
||
|
||
// タッチUI設定の再表示されるバックボタンの生成を抑止
|
||
const _Scene_Battle_prototype_createCancelButton = Scene_Battle.prototype.createCancelButton;
|
||
Scene_Battle.prototype.createCancelButton = function() {
|
||
// do nothing
|
||
};
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (BattleManager)
|
||
//========================================================================
|
||
// ★ ver1.07: プレイヤー行動終了時に再描画
|
||
const _BattleManager_endAction = BattleManager.endAction;
|
||
BattleManager.endAction = function() {
|
||
_BattleManager_endAction.apply(this, arguments);
|
||
if (!!SceneManager._scene && !!SceneManager._scene._singleActorWindow) {
|
||
SceneManager._scene._singleActorWindow.refresh();
|
||
}
|
||
};
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (Game_BattlerBase)
|
||
//========================================================================
|
||
// HP/MP/TP変動で先頭アクターのSingleActor再描画
|
||
const _Game_BattlerBase_setHp = Game_BattlerBase.prototype.setHp;
|
||
Game_BattlerBase.prototype.setHp = function(hp) {
|
||
const prevHp = this._hp;
|
||
_Game_BattlerBase_setHp.apply(this, arguments);
|
||
if (this === $gameParty.members()[0] && this._hp !== prevHp) {
|
||
if (SceneManager._scene && SceneManager._scene._singleActorWindow) {
|
||
SceneManager._scene._singleActorWindow.refresh();
|
||
}
|
||
}
|
||
};
|
||
|
||
const _Game_BattlerBase_setMp = Game_BattlerBase.prototype.setMp;
|
||
Game_BattlerBase.prototype.setMp = function(mp) {
|
||
const prevMp = this._mp;
|
||
_Game_BattlerBase_setMp.apply(this, arguments);
|
||
if (this === $gameParty.members()[0] && this._mp !== prevMp) {
|
||
if (SceneManager._scene && SceneManager._scene._singleActorWindow) {
|
||
SceneManager._scene._singleActorWindow.refresh();
|
||
}
|
||
}
|
||
};
|
||
|
||
const _Game_BattlerBase_setTp = Game_BattlerBase.prototype.setTp;
|
||
Game_BattlerBase.prototype.setTp = function(tp) {
|
||
const prevTp = this._tp;
|
||
_Game_BattlerBase_setTp.apply(this, arguments);
|
||
if (this === $gameParty.members()[0] && this._tp !== prevTp) {
|
||
if (SceneManager._scene && SceneManager._scene._singleActorWindow) {
|
||
SceneManager._scene._singleActorWindow.refresh();
|
||
}
|
||
}
|
||
};
|
||
|
||
//========================================================================
|
||
// コアスクリプト変更部 (Sprite_Enemy)
|
||
//========================================================================
|
||
// 敵消滅時のエフェクトをモノクロ化
|
||
const _Sprite_Enemy_prototype_updateCollapse = Sprite_Enemy.prototype.updateCollapse;
|
||
Sprite_Enemy.prototype.updateCollapse = function() {
|
||
this.blendMode = 1;
|
||
this.setBlendColor([255, 255, 255, 128]);
|
||
this.opacity *= this._effectDuration / (this._effectDuration + 1);
|
||
};
|
||
|
||
//========================================================================
|
||
// クラス定義 (Window_HelpInBattle)
|
||
//========================================================================
|
||
// スキル説明ウィンドウの文字サイズを変更
|
||
class Window_HelpInBattle extends Window_Help {
|
||
constructor() {
|
||
super(...arguments);
|
||
}
|
||
|
||
resetFontSettings() {
|
||
this.contents.fontFace = $gameSystem.mainFontFace();
|
||
this.contents.fontSize = LARGER_FONT_SIZE;
|
||
this.resetTextColor();
|
||
}
|
||
|
||
lineHeight() {
|
||
return LARGER_FONT_SIZE + 6;
|
||
}
|
||
|
||
calcTextHeight(textState) {
|
||
const lineSpacing = this.lineHeight() - LARGER_FONT_SIZE;
|
||
const lastFontSize = this.contents.fontSize;
|
||
const lines = textState.text.slice(textState.index).split("\n");
|
||
const textHeight = this.maxFontSizeInLine(lines[0]) + lineSpacing;
|
||
this.contents.fontSize = lastFontSize;
|
||
return textHeight;
|
||
}
|
||
};
|
||
|
||
//========================================================================
|
||
// クラス定義 (Window_SingleActorStatus)
|
||
//========================================================================
|
||
// Window_SingleActorStatus : 先頭アクターHP/MP/TPのみ表示
|
||
|
||
// ★ アニメ用フレームカウンタを保持する拡張
|
||
// Window_SingleActorStatus に _tpBlinkCount を追加し、
|
||
// 毎フレームアップデートして再描画を行う。
|
||
|
||
// 先にWindow_SingleActorStatus拡張のため、クラス定義の後にupdateメソッドを追加
|
||
class Window_SingleActorStatus extends Window_Base {
|
||
initialize(rect) {
|
||
super.initialize(rect);
|
||
this.openness = 0;
|
||
this.open();
|
||
// ★TPゲージ点滅用カウンタ
|
||
this._tpBlinkCount = 0;
|
||
this.refresh();
|
||
}
|
||
|
||
update() {
|
||
super.update();
|
||
// ゲージを毎フレームアニメするためにTPレートを監視
|
||
const actor = $gameParty.members()[0];
|
||
if (!actor) return;
|
||
const rate = actor.tpRate();
|
||
// TP 75%超えならカウンタを進め、一定間隔で再描画
|
||
if (rate >= 0.75) {
|
||
this._tpBlinkCount++;
|
||
// 例えば 4フレームごとに再描画
|
||
if (this._tpBlinkCount % 4 === 0) {
|
||
this.refresh();
|
||
}
|
||
} else {
|
||
// 75%未満になったら点滅をリセット
|
||
if (this._tpBlinkCount !== 0) {
|
||
this._tpBlinkCount = 0;
|
||
this.refresh();
|
||
}
|
||
}
|
||
}
|
||
|
||
refresh() {
|
||
this.contents.clear();
|
||
const actor = $gameParty.members()[0];
|
||
if (!actor) return;
|
||
|
||
let yy = 0;
|
||
const lh = this.lineHeight();
|
||
|
||
// HP
|
||
this.drawParamLineEx(TextManager.hpA, actor.hp, actor.mhp, actor.hpRate(), yy);
|
||
yy += lh;
|
||
// MP
|
||
this.drawParamLineEx(TextManager.mpA, actor.mp, actor.mmp, actor.mpRate(), yy);
|
||
yy += lh;
|
||
// TP
|
||
this.drawParamLineEx(TextManager.tpA, actor.tp, actor.maxTp(), actor.tpRate(), yy);
|
||
}
|
||
|
||
drawParamLineEx(label, cur, max, rate, y) {
|
||
this.contents.fontSize = this.lineHeight() - 8;
|
||
this.contents.textColor = ColorManager.normalColor();
|
||
|
||
let gaugeMarginX = GAUGE_MARGIN_X;
|
||
let labelWidth = LABEL_WIDTH;
|
||
let labelGap = LABEL_GAP;
|
||
let gaugeHeight = GAUGE_HEIGHT;
|
||
let color1 = ColorManager.hpGaugeColor1();
|
||
let color2 = ColorManager.hpGaugeColor2();
|
||
|
||
// TPゲージ用の設定
|
||
if (label === TextManager.tpA) {
|
||
gaugeMarginX = TP_GAUGE_MARGIN_X;
|
||
labelWidth = TP_LABEL_WIDTH;
|
||
labelGap = TP_LABEL_GAP;
|
||
gaugeHeight = TP_GAUGE_HEIGHT;
|
||
color1 = ColorManager.tpGaugeColor1();
|
||
color2 = ColorManager.tpGaugeColor2();
|
||
// ★TPゲージが75%以上ならアニメ点滅
|
||
if (rate >= 0.75) {
|
||
|
||
// 例: 60フレームで心臓ドキドキ風 (灰色→白→灰色)
|
||
const blinkPeriod = 40;
|
||
const c = this._tpBlinkCount % blinkPeriod;
|
||
// 0.0~1.0に正規化
|
||
const baseFrac = c / blinkPeriod;
|
||
// サイン波(1周期)で 0→1→0 と変化 => ドキドキ感を演出
|
||
const fraction = 0.5 - 0.5 * Math.cos(2 * Math.PI * baseFrac);
|
||
|
||
// 0x80(=128)~0xFF(=255)を fraction で補間 => 灰色→白
|
||
const grayVal = Math.round(0x80 + (0xFF - 0x80) * fraction);
|
||
const hexStr = grayVal.toString(16).padStart(2, "0");
|
||
color1 = "#" + hexStr + hexStr + hexStr;
|
||
// color2は常に白
|
||
color2 = "#FFFFFF";
|
||
}
|
||
} else if (label === TextManager.mpA) {
|
||
color1 = ColorManager.mpGaugeColor1();
|
||
color2 = ColorManager.mpGaugeColor2();
|
||
}
|
||
|
||
const totalW = this.contentsWidth();
|
||
const xLeft = gaugeMarginX;
|
||
const gaugeAll = totalW - gaugeMarginX * 2;
|
||
const gaugeW = gaugeAll - (labelWidth + labelGap);
|
||
|
||
this.drawText(label, xLeft, y, labelWidth, "left");
|
||
|
||
const gx = xLeft + labelWidth + labelGap;
|
||
this.drawCustomGauge(gx, y, gaugeW, rate, color1, color2, gaugeHeight);
|
||
|
||
const text = `${cur}/${max}`;
|
||
this.drawText(text, gx, y, gaugeW, "right");
|
||
}
|
||
|
||
drawCustomGauge(x, y, width, rate, color1, color2, gaugeH) {
|
||
const gaugeY = y + this.lineHeight() - gaugeH - 2;
|
||
this.contents.fillRect(x, gaugeY, width, gaugeH, this.gaugeBackColor());
|
||
const fillW = Math.floor(width * rate);
|
||
this.contents.gradientFillRect(x, gaugeY, fillW, gaugeH, color1, color2, false);
|
||
}
|
||
|
||
hide() {
|
||
// hide()無視
|
||
// do nothing
|
||
}
|
||
}
|
||
window.Window_SingleActorStatus = Window_SingleActorStatus;
|
||
})();
|
||
|
||
|