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

349 lines
No EOL
12 KiB
JavaScript
Raw 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 プレイヤー頭上イベント検出 → ピクチャ99 & タイトル表示 v2.1 ★スイッチ9で有効化★
* @author IvI
*
* ▼ 基本設定 --------------------------------------------------------------
*
* @param NotetagKey
* @text タグキー
* @desc ページ注釈に書く <●●:タイトル,ID> の “●●” 部分
* @default ShowPic
*
* @param PictureX
* @text ピクチャ X 座標
* @type number
* @default 920
*
* @param PictureY
* @text ピクチャ Y 座標
* @type number
* @default 0
*
* @param PictureScale
* @text ピクチャ拡大率(%)
* @type number
* @default 100
*
* @param TitleX
* @text タイトル X 座標
* @type number
* @default 940
*
* @param TitleY
* @text タイトル Y 座標
* @type number
* @default 20
*
* @param TitleFontSize
* @text タイトルフォントサイズ
* @type number
* @default 24
*
* ▼ 背景表示タイプ --------------------------------------------------------
*
* @param BackStyle
* @text 背景タイプ
* @desc 0: なし / 1: ウィンドウ / 2: 暗幕
* @type select
* @option なし
* @value 0
* @option ウィンドウ
* @value 1
* @option 暗幕
* @value 2
* @default 1
*
* @param BackOrigin
* @text 原点(ウィンドウ時のみ)
* @desc 0: 左上 / 1: 中央 (BackX/Y が中心座標)
* @type select
* @option 左上
* @value 0
* @option 中央
* @value 1
* @default 0
* @parent BackStyle
*
* @param BackX
* @text 背景X(ウィンドウ)
* @type number
* @default 900
* @parent BackStyle
*
* @param BackY
* @text 背景Y(ウィンドウ)
* @type number
* @default 0
* @parent BackStyle
*
* @param BackW
* @text 背景幅(ウィンドウ)
* @type number
* @default 200
* @parent BackStyle
*
* @param BackH
* @text 背景高(ウィンドウ)
* @type number
* @default 96
* @parent BackStyle
*
* @param BackOpacity
* @text 背景不透明度
* @type number
* @max 255
* @default 192
*
* ▼ ピクチャ ID → ファイル名対応表 ----------------------------------------
*
* @param PictureList
* @text ピクチャ対応表
* @type struct<PicItem>[]
* @default []
* * ▼ 一時非表示設定 --------------------------------------------------------
* @param TempHideSwitchId
* @text 一時非表示スイッチ番号
* @desc このスイッチがONの時、表示を一時的に隠します。0を指定すると無効になります。
* @type switch
* @default 0
*/
/*~struct~PicItem:
* @param id
* @text PictureID
* @type number
* @default 1
*
* @param file
* @text 画像ファイル名(拡張子不要)
* @type file
* @dir img/pictures
* @default
*/
(() => {
"use strict";
/* ------------------------------------------------------------------- */
/* パラメータ処理 */
/* ------------------------------------------------------------------- */
const PLUGIN_NAME = "EventPictureDisplay";
const PARAMS = PluginManager.parameters(PLUGIN_NAME);
// 有効化スイッチ番号(ここを書き換えれば好きなスイッチに変更可)
const ENABLE_SW = 9;
// ★★★ 追加ここから ★★★
// 一時非表示スイッチ番号
const TEMP_HIDE_SW = Number(PARAMS["TempHideSwitchId"] || 0);
// ★★★ 追加ここまで ★★★
const TAG_KEY = String(PARAMS["NotetagKey"] || "ShowPic");
const PIC_X = Number(PARAMS["PictureX"] || 920);
const PIC_Y = Number(PARAMS["PictureY"] || 0);
const PIC_SCALE = Number(PARAMS["PictureScale"] || 100);
const TITLE_X = Number(PARAMS["TitleX"] || 940);
const TITLE_Y = Number(PARAMS["TitleY"] || 20);
const TITLE_SIZE = Number(PARAMS["TitleFontSize"] || 24);
const BACK_STYLE = Number(PARAMS["BackStyle"] || 1); // 0:none 1:window 2:dim
const BACK_ORIGIN = Number(PARAMS["BackOrigin"] || 0);
const BACK_X = Number(PARAMS["BackX"] || 900);
const BACK_Y = Number(PARAMS["BackY"] || 0);
const BACK_W = Number(PARAMS["BackW"] || 200);
const BACK_H = Number(PARAMS["BackH"] || 96);
const BACK_OPA = Number(PARAMS["BackOpacity"] || 192);
const PIC_LIST = JSON.parse(PARAMS["PictureList"] || "[]").map(s => JSON.parse(s));
const picNameById = id => {
const item = PIC_LIST.find(e => Number(e.id) === id);
return item ? item.file : "";
};
/* ------------------------------------------------------------------- */
/* ユーティリティ */
/* ------------------------------------------------------------------- */
/** 注釈コメントからタグを抽出
* @return { title: string, picId: number, xOffset: number } | null */
// ▼▼▼ 変更点1 ▼▼▼
function extractTag(page) {
if (!page) return null;
// オフセット値(省略可能、マイナス値も許可)を取得できるように正規表現を変更
const re = new RegExp(`<${TAG_KEY}\\s*:\\s*([^,]+?)\\s*,\\s*(\\d+)(?:\\s*,\\s*(-?\\d+))?>`, "i");
let buf = "";
for (const cmd of page.list) {
if (cmd.code === 108) {
buf = cmd.parameters[0] + "\n";
} else if (cmd.code === 408) {
buf += cmd.parameters[0] + "\n";
} else {
const m = buf.match(re);
// m[3]がオフセット値。なければ0とする
if (m) return { title: m[1].trim(), picId: Number(m[2]), xOffset: Number(m[3] || 0) };
buf = "";
}
}
const m = buf.match(re);
return m ? { title: m[1].trim(), picId: Number(m[2]), xOffset: Number(m[3] || 0) } : null;
}
// ▲▲▲ 変更点1 ▲▲▲
/* ------------------------------------------------------------------- */
/* Scene_Map 拡張 */
/* ------------------------------------------------------------------- */
const _Scene_Map_create = Scene_Map.prototype.create;
Scene_Map.prototype.create = function() {
_Scene_Map_create.call(this);
// タイトルスプライト --------------------------------------------------
const bmp = new Bitmap(400, 64);
bmp.fontSize = TITLE_SIZE;
bmp.outlineWidth = 4;
bmp.outlineColor = "rgba(0,0,0,0.6)";
bmp.textColor = "#ffffff";
this._epdTitleSprite = new Sprite(bmp);
this._epdTitleSprite.anchor.x = 0;
this._epdTitleSprite.anchor.y = 0;
this._epdTitleSprite.x = TITLE_X;
this._epdTitleSprite.y = TITLE_Y;
this._epdTitleSprite.visible = false;
// 背景オブジェクト ----------------------------------------------------
this._epdBackObj = null;
if (BACK_STYLE === 1) {
// Window_Base
let wx = BACK_X, wy = BACK_Y;
if (BACK_ORIGIN === 1) { wx -= Math.round(BACK_W/2); wy -= Math.round(BACK_H/2); }
const rect = new Rectangle(wx, wy, BACK_W, BACK_H);
const win = new Window_Base(rect);
win.opacity = BACK_OPA;
this._epdBackObj = win;
} else if (BACK_STYLE === 2) {
let dx = BACK_X, dy = BACK_Y;
if (BACK_ORIGIN === 1) { dx -= Math.round(BACK_W/2); dy -= Math.round(BACK_H/2); }
const bmpDim = new Bitmap(BACK_W, BACK_H);
bmpDim.fillRect(0, 0, BACK_W, BACK_H, "#000000");
const dim = new Sprite(bmpDim);
dim.x = dx;
dim.y = dy;
dim.opacity = BACK_OPA;
this._epdBackObj = dim;
}
if (this._epdBackObj) {
if (this._spriteset && this._spriteset._pictureContainer) {
this._spriteset._pictureContainer.addChildAt(this._epdBackObj, 0);
} else {
// まだpictureContainerがない時点なので、仮配置 → 後で付け替える
this.addChild(this._epdBackObj);
this._epdBackObj._needReattach = true;
}
this._epdBackObj.visible = false;
}
this._epdLastPicName = ""; // 最後に表示したピクチャ名
};
const _Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;
Scene_Map.prototype.createAllWindows = function() {
_Scene_Map_createAllWindows.call(this);
// タイトルスプライトは windowLayer より上に置く
if (this._windowLayer) this._windowLayer.addChild(this._epdTitleSprite);
};
const _Scene_Map_update = Scene_Map.prototype.update;
Scene_Map.prototype.update = function() {
// pictureContainerが準備できたら背景を付け替え
if (this._epdBackObj && this._epdBackObj._needReattach && this._spriteset && this._spriteset._pictureContainer) {
this.removeChild(this._epdBackObj);
this._spriteset._pictureContainer.addChildAt(this._epdBackObj, 0);
delete this._epdBackObj._needReattach;
}
_Scene_Map_update.call(this);
this._epdUpdate();
};
/* ------------------------------------------------------------------- */
/* メイン表示更新 */
/* ------------------------------------------------------------------- */
// ▼▼▼ 変更点2 ▼▼▼
Scene_Map.prototype._epdUpdate = function() {
// スイッチがOFFなら即消去待機
if (!$gameSwitches.value(ENABLE_SW)) {
this._epdHideAll();
return;
}
// 一時非表示スイッチがONなら消去して待機
if (TEMP_HIDE_SW > 0 && $gameSwitches.value(TEMP_HIDE_SW)) {
this._epdHideAll();
return;
}
// プレイヤー頭上のイベントを取得
const playerX = $gamePlayer.x;
const playerY = $gamePlayer.y;
const evts = ($gameMap.eventsXyUnitNt ? $gameMap.eventsXyUnitNt(playerX, playerY - 1)
: $gameMap.eventsXy(playerX, playerY - 1));
const evt = evts[0];
if (evt && evt.page()) {
const tag = extractTag(evt.page());
if (tag) {
// xOffset を受け取る
const { title, picId, xOffset } = tag;
const picName = picNameById(picId);
if (picName) {
// _epdShow に xOffset を渡す
this._epdShow(picName, title, xOffset);
return; // 表示したので抜ける
}
}
}
// 表示条件に合わなければ隠す
this._epdHideAll();
};
// ▲▲▲ 変更点2 ▲▲▲
/* ------------------------------------------------------------------- */
/* 表示 / 非表示 */
/* ------------------------------------------------------------------- */
/** @param {string} picName 画像ファイル名
* @param {string} title タイトル文字列
* @param {number} xOffset X座標のオフセット */
// ▼▼▼ 変更点3 ▼▼▼
Scene_Map.prototype._epdShow = function(picName, title, xOffset) {
// ピクチャ-------------------------------------------------------------
if (this._epdLastPicName !== picName) {
// 別画像なら描画し直し
const origin = 0; // 左上固定
// X座標にオフセット値を加算
$gameScreen.showPicture(99, picName, origin, PIC_X + xOffset, PIC_Y, PIC_SCALE, PIC_SCALE, 255, 0);
this._epdLastPicName = picName;
}
// タイトルテキスト ----------------------------------------------------
const bmp = this._epdTitleSprite.bitmap;
bmp.clear();
bmp.drawText(title, 0, 0, bmp.width, bmp.height, "left");
this._epdTitleSprite.visible = true;
// 背景オブジェクト ----------------------------------------------------
if (this._epdBackObj) {
this._epdBackObj.visible = true;
}
};
// ▲▲▲ 変更点3 ▲▲▲
Scene_Map.prototype._epdHideAll = function() {
if (this._epdLastPicName) {
if ($gameScreen.picture(99)) $gameScreen.erasePicture(99);
this._epdLastPicName = "";
}
this._epdTitleSprite.visible = false;
if (this._epdBackObj) this._epdBackObj.visible = false;
};
})();