163 lines
6.9 KiB
JavaScript
163 lines
6.9 KiB
JavaScript
/*:
|
||
* @target MZ
|
||
* @plugindesc 現在のステートを画面左下に表示するプラグイン(アイコン&丸い背景付き、行間空白調整、スイッチ31対応、戦闘画面対応)
|
||
* @author しろやぶ featCGPT
|
||
*
|
||
* @help
|
||
* このプラグインは、アクターの現在のステートを画面左下に最大5つまで表示します。
|
||
* 特徴:
|
||
* - ステートは下から順に表示され、解除時にリストを詰めて表示。
|
||
* - ステート名の前にアイコンを表示。
|
||
* - ステート名ごとに角丸背景を描画し、文字間に空白を追加。
|
||
* - スイッチ31がONのときのみ表示されます。
|
||
* - 戦闘画面にも対応しています。
|
||
*
|
||
*/
|
||
|
||
(() => {
|
||
const maxStates = 5; // 表示するステートの最大数
|
||
const stateLineHeight = 32; // ステートの行高さ
|
||
const stateFontSize = 18; // フォントサイズ
|
||
const stateBackgroundColor = "rgba(255, 255, 255, 0.3)"; // 背景色
|
||
const backgroundPadding = 3; // 背景の上下の余白
|
||
const cornerRadius = 6; // 背景の角の丸み
|
||
const windowWidth = 270; // ウィンドウの横幅
|
||
const windowHeight = 192; // ウィンドウの高さ
|
||
const stateWindowX = 900; // ウィンドウのX座標
|
||
const stateWindowY = 540; // ウィンドウのY座標
|
||
const displaySwitchID = 31; // 表示を制御するスイッチID
|
||
|
||
// 段ごとのテキストY座標のオフセット(全て-5に設定)
|
||
const textYOffset = [-5, -5, -5, -5, -5];
|
||
|
||
class StateDisplayWindow extends Window_Base {
|
||
constructor() {
|
||
super(new Rectangle(stateWindowX, stateWindowY, windowWidth, windowHeight));
|
||
this.opacity = 0; // 背景を透明にする
|
||
this._actor = null;
|
||
}
|
||
|
||
setActor(actor) {
|
||
this._actor = actor;
|
||
this.refresh();
|
||
}
|
||
|
||
refresh() {
|
||
this.contents.clear();
|
||
|
||
// スイッチ31がOFFの場合は描画しない
|
||
if (!this._actor || !$gameSwitches.value(displaySwitchID)) {
|
||
this.visible = false;
|
||
return;
|
||
}
|
||
|
||
this.visible = true; // スイッチがONの場合、ウィンドウを表示
|
||
|
||
// 現在のステートリストを取得し、最大数を制限
|
||
const states = this._actor.states().slice(0, maxStates);
|
||
const totalStates = states.length;
|
||
|
||
// 各ステートを描画(下から順に)
|
||
states.forEach((state, index) => {
|
||
const y = (totalStates - index - 1) * stateLineHeight;
|
||
this.drawState(state, y, index); // indexを渡して段ごとのオフセットを適用
|
||
});
|
||
}
|
||
|
||
drawState(state, y, index) {
|
||
const iconScale = 0.8; // アイコンのスケール
|
||
const iconWidth = ImageManager.iconWidth * iconScale;
|
||
const iconHeight = ImageManager.iconHeight * iconScale;
|
||
const textX = iconWidth + 6; // アイコンの右隣のテキスト開始位置
|
||
const bgHeight = stateFontSize + backgroundPadding * 2; // 背景の高さ
|
||
|
||
// 背景を描画
|
||
this.drawRoundedRect(0, y + (stateLineHeight - bgHeight) / 2, this.contents.width, bgHeight, cornerRadius, stateBackgroundColor);
|
||
|
||
// 背景中央の基準点を計算
|
||
const centerY = y + (stateLineHeight - bgHeight) / 2 + bgHeight / 2;
|
||
|
||
// アイコンのY座標を計算
|
||
const iconY = centerY - iconHeight / 2;
|
||
|
||
// テキストのY座標(段ごとのオフセットを適用)
|
||
const textY = iconY + (textYOffset[index] || 0); // 指定がない場合はデフォルト0
|
||
|
||
// アイコンを描画
|
||
this.drawIcon(state.iconIndex, 3, iconY, iconScale);
|
||
|
||
// フォントサイズを設定
|
||
this.contents.fontSize = stateFontSize;
|
||
|
||
// ステート名を描画
|
||
this.drawText(state.name, textX, textY, this.contents.width - textX);
|
||
}
|
||
|
||
drawRoundedRect(x, y, width, height, radius, color) {
|
||
const ctx = this.contents.context;
|
||
ctx.save();
|
||
ctx.fillStyle = color;
|
||
ctx.beginPath();
|
||
ctx.moveTo(x + radius, y);
|
||
ctx.lineTo(x + width - radius, y);
|
||
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
|
||
ctx.lineTo(x + width, y + height - radius);
|
||
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
|
||
ctx.lineTo(x + radius, y + height);
|
||
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
|
||
ctx.lineTo(x, y + radius);
|
||
ctx.quadraticCurveTo(x, y, x + radius, y);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
ctx.restore();
|
||
}
|
||
|
||
drawIcon(iconIndex, x, y, scale = 1) {
|
||
const bitmap = ImageManager.loadSystem("IconSet");
|
||
const iconWidth = ImageManager.iconWidth;
|
||
const iconHeight = ImageManager.iconHeight;
|
||
const sx = (iconIndex % 16) * iconWidth;
|
||
const sy = Math.floor(iconIndex / 16) * iconHeight;
|
||
this.contents.blt(bitmap, sx, sy, iconWidth, iconHeight, x, y, iconWidth * scale, iconHeight * scale);
|
||
}
|
||
|
||
update() {
|
||
super.update();
|
||
if (this._actor) {
|
||
this.refresh();
|
||
}
|
||
}
|
||
}
|
||
|
||
const _Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;
|
||
Scene_Map.prototype.createAllWindows = function() {
|
||
_Scene_Map_createAllWindows.call(this);
|
||
this.createStateDisplayWindow();
|
||
};
|
||
|
||
Scene_Map.prototype.createStateDisplayWindow = function() {
|
||
this._stateDisplayWindow = new StateDisplayWindow();
|
||
this._stateDisplayWindow.setActor($gameParty.leader()); // パーティリーダーを対象
|
||
this.addWindow(this._stateDisplayWindow);
|
||
};
|
||
|
||
const _Scene_Battle_createAllWindows = Scene_Battle.prototype.createAllWindows;
|
||
Scene_Battle.prototype.createAllWindows = function() {
|
||
_Scene_Battle_createAllWindows.call(this);
|
||
this.createStateDisplayWindow();
|
||
};
|
||
|
||
Scene_Battle.prototype.createStateDisplayWindow = function() {
|
||
this._stateDisplayWindow = new StateDisplayWindow();
|
||
this._stateDisplayWindow.setActor($gameParty.leader()); // パーティリーダーを対象
|
||
this.addWindow(this._stateDisplayWindow);
|
||
};
|
||
|
||
const _Game_Actor_refresh = Game_Actor.prototype.refresh;
|
||
Game_Actor.prototype.refresh = function() {
|
||
_Game_Actor_refresh.call(this);
|
||
if (SceneManager._scene._stateDisplayWindow) {
|
||
SceneManager._scene._stateDisplayWindow.setActor(this);
|
||
}
|
||
};
|
||
})();
|