pure-full-lily/js/plugins/TorigoyaMZ_NotifyMessage_AddonVariableChangeCenter.js
2025-09-16 10:12:44 -05:00

280 lines
No EOL
9.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*:
* @target MZ
* @plugindesc 通知メッセージアドオン: 変数変動通知(中央固定版) v2.1.1
* @author IvI, 改変: Google Gemini
*
* 監視したい複数の変数が増減したとき、自動で個別メッセージを表示します。
* ウィンドウは常に画面縦中央(既定 y = 360pxの上端に固定されます。
*
* ▼ 使い方
* 1. TorigoyaMZ_NotifyMessage.js の直下に配置してください。
* 2. 「監視リスト」で変数を追加し、メッセージとアイコンを設定してください。
* メッセージ中の {delta} が「±付き増減値」に置換されます。
* 3. ★変数ごとに個別の効果音を設定できるようになりました。
*
* ▼ 更新履歴
* v2.1.1 (Geminiによる改変) buildMessage関数の構文エラーを修正
* v2.1.0 (Geminiによる改変) 変数ごとに通知SEを設定できる機能を追加
* v2.0.0 複数変数対応/旧単一パラメータは自動移行に対応
* v1.5.2 初回だけ高さが異常になるバグを厳密に修正
* v1.5.1 パラメータ/ヘルプが表示されない不具合を修正
* v1.5.0 初版
*
* @param watchList
* @text 監視リスト
* @type struct<WatchItem>[]
* @default []
*
* @param centerY
* @text 表示Y座標
* @desc 通知ウィンドウの上端を合わせる Y 座標
* @type number
* @default 360
*
* @help
* 【概要】
* 指定した複数のゲーム変数が増減したとき、増減量を含む
* メッセージを画面中央にポップアップ表示します。
*
* 【メッセージテンプレート】
* - {delta} : 増減値(符号付き)に置換
*
* 【プラグインコマンド】
* ありません(自動動作のみ)。
*/
/*~struct~WatchItem:
* @param variableId
* @text 変数ID
* @type variable
* @default 5
*
* @param messageTemplate
* @text メッセージ
* @type string
* @default \c[1]値が {delta} した…
*
* @param iconId
* @text アイコンID
* @type number
* @default 0
*
* @param se
* @text ★通知効果音
* @desc この変数専用の効果音を設定します。
* 未設定の場合は基本設定のSEが再生されます。
* @type struct<Sound>
* @default
*/
/*~struct~Sound:
* @param name
* @text ファイル名
* @type file
* @dir audio/se
* @default
*
* @param volume
* @text 音量
* @type number
* @min 0
* @max 100
* @default 90
*
* @param pitch
* @text ピッチ
* @type number
* @min 50
* @max 150
* @default 100
*
* @param pan
* @text 位相
* @type number
* @min -100
* @max 100
* @default 0
*/
(() => {
'use strict';
// -------------------------------------------------------------------------
// パラメータ読み込み
const PLUGIN_NAME = 'TorigoyaMZ_NotifyMessage_AddonVariableChangeCenter';
const params = PluginManager.parameters(PLUGIN_NAME);
// 監視リスト(配列)
const watchListRaw = JSON.parse(params.watchList || '[]');
const WATCHERS = watchListRaw
.map((raw) => {
if (!raw) return null;
const obj = JSON.parse(raw);
const se = obj.se ? JSON.parse(obj.se) : null;
return {
variableId: Number(obj.variableId || 0),
messageTemplate: String(obj.messageTemplate || '\\c[1]値が {delta} した…'),
iconId: Number(obj.iconId || 0),
se: (se && se.name) ? {
name: String(se.name),
volume: Number(se.volume ?? 90),
pitch: Number(se.pitch ?? 100),
pan: Number(se.pan ?? 0),
} : null,
};
})
.filter(Boolean)
.filter((w) => w.variableId > 0);
// 旧バージョン(単一変数)パラメータが残っている場合は自動移行
if (WATCHERS.length === 0 && params.variableId) {
WATCHERS.push({
variableId: Number(params.variableId),
messageTemplate: String(params.messageTemplate || '\\c[1]値が {delta} した…'),
iconId: Number(params.iconId || 0),
se: null,
});
}
// id → watcher のハッシュ
const WATCH_TABLE = {};
for (const w of WATCHERS) WATCH_TABLE[w.variableId] = w;
const CENTER_Y = Number(params.centerY || 360);
// -------------------------------------------------------------------------
// 依存チェック
const Torigoya = (window.Torigoya = window.Torigoya || {});
if (!Torigoya.NotifyMessage) {
console.error('[%s] TorigoyaMZ_NotifyMessage が見つかりません。', PLUGIN_NAME);
return;
}
const Manager = Torigoya.NotifyMessage.Manager;
const NotifyItem = Torigoya.NotifyMessage.NotifyItem;
// -------------------------------------------------------------------------
// ★ NotifyItemのSE取得処理を上書きするパッチ
// -------------------------------------------------------------------------
if (NotifyItem && !NotifyItem.prototype._variableCenterSePatched) {
NotifyItem.prototype._variableCenterSePatched = true;
const _NotifyItem_getDisplaySe = NotifyItem.prototype.getDisplaySe;
NotifyItem.prototype.getDisplaySe = function() {
if (this.se && this.se.name) {
return this.se;
}
return _NotifyItem_getDisplaySe.apply(this, arguments);
};
}
// -------------------------------------------------------------------------
// ★ Window_NotifyMessage パッチ(元コードそのまま) ★
(function patchWindow() {
const W = Torigoya.NotifyMessage.Window;
if (!W || W.prototype._variableCenterPatched) return;
W.prototype._variableCenterPatched = true;
const _refreshContents = W.prototype.refreshContents;
W.prototype.refreshContents = function () {
const minW = Graphics.width - this.padding * 2;
this.contents.resize(minW, this.lineHeight());
_refreshContents.call(this);
};
const _refreshBackCoverSprite = W.prototype._refreshBackCoverSprite;
W.prototype._refreshBackCoverSprite = function () {
_refreshBackCoverSprite.call(this);
};
const _setup = W.prototype.setup;
W.prototype.setup = function (notifyItem) {
_setup.call(this, notifyItem);
setTimeout(() => {
if (!this.parent) return;
this.refresh();
});
};
})();
// -------------------------------------------------------------------------
// ユーティリティ
function placeAtCenter(stack) {
if (!stack?.window) return;
stack.y = CENTER_Y;
stack.window.y = CENTER_Y;
}
function buildMessage(template, delta) {
// ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
// ★ 修正点: ここにあった構文エラーを修正しました
// ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
const signed = delta > 0 ? `+${delta}` : `${delta}`;
return template.replace('{delta}', signed);
}
// -------------------------------------------------------------------------
// スクロールアニメーション パッチ(元コードそのまま)
if (!Manager._variableCenterScrollPatched) {
Manager._variableCenterScrollPatched = true;
const baseStartScroll = Manager.startScrollAnimation;
Manager.startScrollAnimation = function (newH) {
const locked = this._stacks.filter((s) => s.notifyItem?.note === '<type:variableChange>');
if (locked.length) this._stacks = this._stacks.filter((s) => !locked.includes(s));
baseStartScroll.call(this, newH);
locked.forEach((s) => {
placeAtCenter(s);
this._stacks.push(s);
});
};
}
// -------------------------------------------------------------------------
// 通知出現後に中央へ
Manager.on((item) => {
if (item.note !== '<type:variableChange>') return;
setTimeout(() => {
placeAtCenter(Manager._stacks.find((s) => s.notifyItem === item));
});
});
// -------------------------------------------------------------------------
// 内部ヘルパ
function findActiveStack(variableId) {
return Manager._stacks.find((s) => s.notifyItem?._watchVarId === variableId);
}
function createNew(watcher, delta) {
const notifyItem = new Torigoya.NotifyMessage.NotifyItem({
message: buildMessage(watcher.messageTemplate, delta),
icon: watcher.iconId,
note: '<type:variableChange>',
});
notifyItem._accumDelta = delta;
notifyItem._watchVarId = watcher.variableId;
notifyItem.se = watcher.se;
Manager.notify(notifyItem);
}
function handleNotify(watcher, delta) {
const stack = findActiveStack(watcher.variableId);
createNew(watcher, delta);
}
// -------------------------------------------------------------------------
// Game_Variables 拡張
const _setValue = Game_Variables.prototype.setValue;
Game_Variables.prototype.setValue = function (variableId, value) {
const old = this.value(variableId);
_setValue.apply(this, arguments);
const watcher = WATCH_TABLE[variableId];
if (!watcher) return;
const delta = value - old;
if (!delta) return;
handleNotify(watcher, delta);
};
})();