//============================================================================= // RPG Maker MZ - Picture Event Cursor //============================================================================= /*: * @target MZ * @plugindesc PictureCallCommonのイベントをキー操作で呼び出します。 * @author ガバチョ(溟犬一六) * @url https://star-write-dream.com/ * @base PictureCallCommon * @orderAfter PictureCallCommon * * @help GABA_PictureEventCursor.js(ver1.0.0) * * PictureCallCommonのイベントをキー操作で呼び出します。 * * ・PictureCallCommonにて、 * 下記のトリガーに登録したピクチャイベントを呼び出せます。 * 1:クリック、2:右クリック、4:重ねる、5:離れる * * ■動作内容 * ・マップに表示中のトリガー登録済みの画像は、内部的なリストに登録されます。 * ・登録順は画像番号の小さい順です。 * ・矢印キー:リストを順番に選択し、次のコモンイベントを実行します。 * ・選択した画像のトリガー4 * ・選択が外れた画像のトリガー5 * ・決定キー:選択中の画像のトリガー1のコモンイベントを実行します。 * ・キャンセルキー:選択中の画像のトリガー2のコモンイベントを実行します。 * * ■機能制御 * ・特定のスイッチがONの時だけ動作します。 * ・スイッチがONでも、マウスが画像に重なっているときは動作しません。 * ☆マウス優先です。 * * ■備考 * ・内部的なリストは次のタイミングで更新されます。 * ・ピクチャの表示 * ・ピクチャの消去 * ・PictureCallCommonのピクチャイベント登録 * ・PictureCallCommonのピクチャイベント解除 * ・表示後に透明化された画像や画面外に移動した画像は表示中扱いです。 * * -------------------------- * Copyright (c) 2022 Gabacho(Ichiro Meiken) * Released under the MIT license * https://opensource.org/licenses/mit-license.php * -------------------------- * * @param enabledSwitchId * @text 動作スイッチ * @type switch * @desc このスイッチがONの時だけ機能します。 * @default 0 * * @command getIndex * @text 選択位置を取得 * @desc 選択位置を取得し、変数に保存します。0が先頭です。 * * @arg indexVariableId * @text 変数 * @type variable * @desc この変数に現在の選択位置を保存します。 * @default 0 * * * @command setIndex * @text 選択位置を設定 * @desc 選択位置を設定します。0が先頭です。 * * @arg indexVariableId * @text 変数 * @type variable * @desc 変数を指定します。 * @default 0 * */ (() => { "use strict"; const pluginName = "PictureEventCursor"; const parameters = PluginManager.parameters(pluginName); const enabledSwitchId = Number(parameters["enabledSwitchId"]) || 0; //------------ // プラグインコマンド // 取得 PluginManager.registerCommand(pluginName, "getIndex", (args) => { const vId = args.indexVariableId || 0; if (vId === 0) { return; } $gameVariables.setValue(vId, getCurrentIndex()); }); // 設定 PluginManager.registerCommand(pluginName, "setIndex", (args) => { const vId = args.indexVariableId || 0; if (vId === 0) { return; } setCurrentIndexForCommand($gameVariables.value(vId)); }); //---------------------------- // ピクチャーイベントカーソル function PictureEventCoursor() { this._currentIndex = 0; this._beforeIndex = 0; this._isReady = false; this._isActive = false; // トリガー登録されている画像すべて this._baseArray = []; // _baseArrayの内、画面に表示されているもの this._execArray = []; } // カーソル用データ function PecData() { this._pictureId = 0; this._okCEV = 0; this._cancelCEV = 0; this._hoverCEV = 0; this._leaveCEV = 0; } // カーソルオブジェクトを取得 function getCursor() { return $gameScreen._pictureEventCursor; } // 使用可能シーンか判定(マップのみ) function isUsableScene() { return SceneManager._scene.constructor === Scene_Map; } // 準備状態を設定 function setCursorReady(flg) { getCursor()._isReady = flg; } // 選択位置を取得 function getCurrentIndex() { return getCursor()._currentIndex; } // 前回の選択位置を取得 function getBeforeIndex() { return getCursor()._beforeIndex; } // 選択位置を直接指定 function setCurrentIndex(value) { getCursor()._currentIndex = value; } // 選択位置を直接指定(コマンド用) function setCurrentIndexForCommand(value) { getCursor()._currentIndex = value; if (isActive()) { triggerHoverEvent(); triggerLeaveEvent(); } } // 選択位置を増やす function incCurrentIndex() { getCursor()._currentIndex++; } // 選択位置を減らす function decCurrentIndex() { getCursor()._currentIndex--; } // カーソルオブジェクトを取得 function getCursorObject(id) { if (baseHas(id)) { return baseGet(id); } else { const resObj = new PecData(); resObj._pictureId = id; return resObj; } } // 実行配列を取得 function getExecArray() { return getCursor()._execArray; } // ベース配列に登録済み function baseHas(pId) { return getCursor()._baseArray.some((el) => { return el._pictureId === pId; }); } // ベース配列からデータ取得 function baseGet(pId) { return getCursor()._baseArray.find((el) => { return el._pictureId === pId; }); } // ベース配列にデータ設定 function baseSet(pId, pecData) { const data = getCursor()._baseArray.find((el) => { return el._pictureId === pId; }); if (data !== undefined) { setPecData(data, pecData); } else { getCursor()._baseArray.push(pecData); } } // ベース配列から削除 function baseDelete(pId) { const index = getCursor()._baseArray.findIndex((el) => { return el._pictureId === pId; }); if (index > -1) { getCursor()._baseArray.splice(index, 1); } } // 配列データの設定 function setPecData(target, value) { target._pictureId = value._pictureId; target._okCEV = value._okCEV; target._cancelCEV = value._cancelCEV; target._hoverCEV = value._hoverCEV; target._leaveCEV = value._leaveCEV; } // 消去判定:トリガーなし function pecDataNeedsDelete(target) { return ( target._okCEV === 0 && target._cancelCEV === 0 && target._leaveCEV === 0 && target._hoverCEV === 0 ); } // ---------------------------- // $gameScreenに保存させる const _Game_Screen_initialize = Game_Screen.prototype.initialize; Game_Screen.prototype.initialize = function () { _Game_Screen_initialize.apply(this, arguments); this.initPictureEventCursor(); }; // 初期化 Game_Screen.prototype.initPictureEventCursor = function () { if (!this._pictureEventCursor) { this._pictureEventCursor = new PictureEventCoursor(); } }; // ピクチャイベントの登録 const _Game_Screen_addPictureEvent = Game_Screen.prototype.addPictureEvent; Game_Screen.prototype.addPictureEvent = function (pictureId, trigger, param) { setCursorReady(false); _Game_Screen_addPictureEvent.apply(this, arguments); addPictureEventCursor(param); createExecArray(); }; // ベース配列に登録 function addPictureEventCursor(param) { const cursorObj = getCursorObject(param.pictureId); let needsSet = false; switch (param.triggerType) { case 1: cursorObj._okCEV = param.commonEventId; needsSet = true; break; case 2: cursorObj._cancelCEV = param.commonEventId; needsSet = true; break; case 4: cursorObj._hoverCEV = param.commonEventId; needsSet = true; break; case 5: cursorObj._leaveCEV = param.commonEventId; needsSet = true; break; default: break; } if (needsSet) { dataCheckAndRegister(param.pictureId, cursorObj); } } // ピクチャイベントの削除 const _Game_Screen_removePictureEvent = Game_Screen.prototype.removePictureEvent; Game_Screen.prototype.removePictureEvent = function ( pictureId, trigger = null ) { _Game_Screen_removePictureEvent.apply(this, arguments); setCursorReady(false); if (trigger === null) { baseDelete(pictureId); } else { // PictureCallCommon(v1.2.2)では発生しない removePictureEventCursor(pictureId, trigger); } createExecArray(); }; // カーソルイベントの除去 function removePictureEventCursor(pictureId, trigger) { const cursorObj = getCursorObject(pictureId); let needsSet = false; switch (trigger) { case 1: cursorObj._okCEV = 0; needsSet = true; break; case 2: cursorObj._cancelCEV = 0; needsSet = true; break; case 4: cursorObj._hoverCEV = 0; needsSet = true; break; case 5: cursorObj._leaveCEV = 0; needsSet = true; break; default: break; } if (needsSet) { dataCheckAndRegister(param.pictureId, cursorObj); } } // 値を確認して登録・削除します function dataCheckAndRegister(pictureId, pecData) { if (pecDataNeedsDelete(pecData)) { baseDelete(pictureId); } else { baseSet(pictureId, pecData); } } // ピクチャーの表示 const _Game_Screen_showPicture = Game_Screen.prototype.showPicture; Game_Screen.prototype.showPicture = function ( pictureId, name, origin, x, y, scaleX, scaleY, opacity, blendMode ) { _Game_Screen_showPicture.apply(this, arguments); createExecArray(); }; // ピクチャーの消去 const _Game_Screen_erasePicture = Game_Screen.prototype.erasePicture; Game_Screen.prototype.erasePicture = function (pictureId) { _Game_Screen_erasePicture.apply(this, arguments); createExecArray(); }; //実行用配列作成 function createExecArray() { const cursor = getCursor(); if (!cursor) { return; } setCursorReady(false); // ピクチャーIdを抜き取り並べ替え let arr = []; cursor._baseArray.forEach((el) => { arr.push(el._pictureId); }); arr.sort((a, b) => { return a - b; }); // 表示中の画像に限定 arr = arr.filter((el) => { return ( $gameScreen._pictures[el] != null && $gameScreen._pictures[el]._name !== "" ); }); cursor._execArray = []; arr.forEach((el) => { cursor._execArray.push(baseGet(el)); }); if (!isNoEvent()) { setCursorReady(true); } } //--------------------- //カーソル動作 const _Scene_Map_update = Scene_Map.prototype.update; Scene_Map.prototype.update = function () { _Scene_Map_update.apply(this, arguments); checkActive(); keyDown(); linkMouseIndex(); delayTrigger(); }; // キー操作 function keyDown() { if (!isActive()) { return; } if (Input.isRepeated("ok")) { // TouchInputは無視 triggerOkEvent(); } if (Input.isRepeated("cancel")) { triggerCancelEvent(); } if (Input.isRepeated("up")) { decrementCursorIndex(); } if (Input.isRepeated("down")) { incrementCursorIndex(); } if (Input.isRepeated("right")) { incrementCursorIndex(); } if (Input.isRepeated("left")) { decrementCursorIndex(); } } // トリガーイベントを実行 function triggerEvent() { if (!isActive()) { return; } triggerHoverEvent(); triggerLeaveEvent(); } // アクティブ状態 function isActive() { return getCursor()._isActive; } // アクティブ状態設定 function checkActive() { const oldValue = getCursor()._isActive; getCursor()._isActive = !isOnMousePictureCommand() && isUsableScene() && getCursor()._isReady && $gameSwitches.value(enabledSwitchId) && !$gameMessage.isBusy(); if (oldValue && !getCursor()._isActive) { // カーソル終了 allLeave(); } if (!oldValue && getCursor()._isActive) { // カーソル開始 allLeave(); // delayTrigger() delayCount = 2; } } // マウスが画像に乗っている function isOnMousePictureCommand() { if (SceneManager._scene._spriteset == null) { return false; } return getExecArray().some((el) => { return SceneManager._scene._spriteset._pictureContainer.children[ el._pictureId - 1 ]._touch.isOnPicturePos(); }); } // マウスが乗っている画像の配列添え字 function getOnMousePictureIndex() { if (SceneManager._scene._spriteset == null) { return false; } return getExecArray().findIndex((el) => { return SceneManager._scene._spriteset._pictureContainer.children[ el._pictureId - 1 ]._touch.isOnPicturePos(); }); } // マウス操作とのインデックス連動 function linkMouseIndex() { if (isOnMousePictureCommand()) { getCursor()._beforeIndex = getCursor()._currentIndex; getCursor()._currentIndex = getOnMousePictureIndex(); } } // 遅延させてホバートリガーを実行 let delayCount = 0; function delayTrigger() { if (delayCount === 1) { triggerHoverEvent(); } if (delayCount > 0) { delayCount--; } } // 離れるイベント実行(全件) function allLeave() { getCursor()._execArray.forEach((el) => { setUpCommonEvent(el._leaveCEV); }); } // 実行イベントなし function isNoEvent() { if (getExecArray() == null || getExecArray().length === 0) { getCursor()._isReady = false; setCurrentIndex(0); return true; } return false; } // カーソル移動不要 function isMovingUnnecessary() { if (isNoEvent()) { setCurrentIndex(null); return true; } if (getExecArray().length === 1) { setCurrentIndex(0); return true; } return false; } // カーソルを進める function incrementCursorIndex() { if (isMovingUnnecessary()) { return; } if (getCurrentIndex() < getExecArray().length - 1) { incCurrentIndex(); } else { setCurrentIndex(0); } triggerEvent(); } // カーソルを戻す function decrementCursorIndex() { if (isMovingUnnecessary()) { return; } if (getCurrentIndex() <= 0) { setCurrentIndex(getExecArray().length - 1); } else { decCurrentIndex(); } triggerEvent(); } // OKイベント実行 function triggerOkEvent() { if (isNoEvent()) { return; } try { setUpCommonEvent(getExecArray()[getCurrentIndex()]._okCEV); getCursor()._beforeIndex = getCursor()._currentIndex; } catch {} } // キャンセルイベント実行 function triggerCancelEvent() { if (isNoEvent()) { return; } try { setUpCommonEvent(getExecArray()[getCurrentIndex()]._cancelCEV); } catch {} } // 入ったイベント実行 // ※ホバー中ずっとではなく、操作があった時だけ実行 function triggerHoverEvent() { if (isNoEvent()) { return; } try { setUpCommonEvent(getExecArray()[getCurrentIndex()]._hoverCEV); } catch {} } // 離れたイベント実行 function triggerLeaveEvent() { if (getBeforeIndex() === getCurrentIndex()) { return; } try { setUpCommonEvent(getExecArray()[getBeforeIndex()]._leaveCEV); } catch {} getCursor()._beforeIndex = getCurrentIndex(); } // コモンイベント登録 function setUpCommonEvent(eventId) { if (eventId === 0) { return; } if ($gameParty.inBattle()) { $gameTroop.setupDynamicCommon(eventId); } else { $gameMap.setupDynamicCommon(eventId); } } })();