/*: * @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[] * @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; }; })();