code:
/*:-----------------------------------------------------------------------------------
 * NUUN_MenuScreenEXBase.js
 *
 * Copyright (C) 2022 NUUN
 * This software is released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 * -------------------------------------------------------------------------------------
 */
/*:
 * @target MZ
 * @plugindesc Menu screen base
 * @author NUUN
 * @base NUUN_Base
 * @orderAfter NUUN_Base
 * @orderAfter NUUN_MenuScreen_default
 * @orderAfter NUUN_MenuScreen
 * @orderAfter NUUN_MenuScreen2
 * @version 2.0.6
 *
 * @help
 * A base plugin for processing menu screens.
 *
 *
 * Terms of Use
 * This plugin is distributed under the MIT license.
 *
 * Log
 * 12/1/2022 Ver.2.0.6
 * Fixed an issue where setting an actor front background image would cause an error.
 * 12/1/2022 Ver.2.0.5
 * Fixed to display at the height of the main area when the number of lines is set to 0 in window height mode.
 * 11/27/2022 Ver.2.0.4
 * Fixed an issue that caused an error when menu command display mode was set to left.
 * 11/26/2022 Ver.2.0.3
 * Fixed an issue where an error would occur if the actor image was set to Img with "ActorPictureEXApp" turned on.
 * Fixed the problem that APNG images remain displayed when scrolling.
 * 11/26/2022 Ver.2.0.2
 * Minor fix.
 * 11/26/2022 Ver.2.0.1
 * Fixed an issue where the window for selecting actors from items and skills was displayed in its original size and the status display was disturbed.
 * 11/25/2022 Ver.2.0.0
 * Separation of menu screen setting and processing.
 *
 */
/*:ja
 * @target MZ
 * @plugindesc メニュー画面ベース
 * @author NUUN
 * @base NUUN_Base
 * @orderAfter NUUN_Base
 * @orderAfter NUUN_MenuScreenEX
 * @version 2.0.6
 *
 * @help
 * メニュー画面を処理するためのベースプラグインです。
 *
 *
 * 利用規約
 * このプラグインはMITライセンスで配布しています。
 *
 * 更新履歴
 * 2023/1/7 Ver.2.0.6
 * アクター前面背景画像を設定するとエラーが出る問題を修正。
 * 2022/12/1 Ver.2.0.5
 * ウィンドウ高さモードで行数を0に設定している場合は、メインエリアの高さで表示するように修正。
 * 2022/11/27 Ver.2.0.4
 * コマンドモードを左側に設定したときにエラーが出る問題を修正。
 * 2022/11/26 Ver.2.0.3
 * 立ち絵、顔グラEX適用をONにしてアクター画像をImgに設定した場合、エラーが出る問題を修正。
 * スクロールした際にAPNG画像が表示されたままになってしまう問題を修正。
 * 2022/11/26 Ver.2.0.2
 * 微修正。
 * 2022/11/26 Ver.2.0.1
 * アイテム、スキルからアクターを選択するウィンドウが元のサイズで表示され、ステータスの表示が乱れる問題を修正。
 * 2022/11/25 Ver.2.0.0
 * メニュー画面の処理を統合し、設定用のみ分割。
 *
 */

var Imported = Imported || {};
Imported.NUUN_MenuScreenEXBase = true;

(() => {
    const parameters = PluginManager.parameters('NUUN_MenuScreenEXBase');
    const params = NuunManager.getMenuStatusParams();

    let maxGaugeWidth = 128;
    let menuTextMode = null;
    let menuAlign = null;
    let _commandName = '';
    let _commandText = '';

    function getPluginName() {
        if (Imported.NUUN_MenuScreen_default) {
            return "NUUN_MenuScreen_default";
        } else if (Imported.NUUN_MenuScreen) {
            return "NUUN_MenuScreen";
        } else if (Imported.NUUN_MenuScreen_2) {
            return "NUUN_MenuScreen_2";
        } else {
            return '';
        }
    };

    const pluginName = getPluginName();
    PluginManager.registerCommand(getPluginName(), 'ChangeBackgroundId', args => {
        $gameSystem.menuBackgroundId = Number(args.backgroundId);
    });

    Scene_Menu.prototype.create = function() {
        Scene_MenuBase.prototype.create.call(this);
        this.createCommandWindow();
        this.createStatusWindow();
        this.createInfoWindow();
    };

    Scene_Menu.prototype.isRightInputMode = function() {
        return params.MenuCommandPosition === 'right';
    };

    const _Scene_Menu_createCommandWindow = Scene_Menu.prototype.createCommandWindow;
    Scene_Menu.prototype.createCommandWindow = function() {
        _Scene_Menu_createCommandWindow.call(this);
        _commandName = null;
        if (params.CommandHeightMode) {
            this._commandWindow.maxItemsHeight();
        }
        if (!params.CommandWindowVisible) {
            this._commandWindow.opacity = 0;
        }
    };

    Scene_Menu.prototype.createInfoWindow = function() {
        const list = params.MenuInfoWindowSetting;
        list.forEach((data, i) => {
            if (data.ListDateSetting > 0) {
                const method = '_infoSideMenuWindow'+ !!params.MethodName ? params.MethodName : [i];
                const pageMethod = 'PageList' + data.ListDateSetting;
                const rect = this.infoWindowRect(data);
                const window = new Window_InfoMenu(rect);
                this[method] = window;
                this.addWindow(window);
                window.setup(params.infoContents[pageMethod], data.InfoCols, data.InfoFontSize);
                if (!data.WindowVisible) {
                    window.opacity = 0;
                }
            }
        });
    };

    const _Scene_Menu_createStatusWindow = Scene_Menu.prototype.createStatusWindow;
    Scene_Menu.prototype.createStatusWindow = function() {
        _Scene_Menu_createStatusWindow.call(this);
        if (!params.WindowVisible) {
            this._statusWindow.opacity = 0;
        }
    };

    Scene_Menu.prototype.infoWindowRect = function(data) {
        const wx = data.X_Position + (params.WindowUiIgnore ? (Graphics.boxWidth - Graphics.width) / 2 : 0);
        const ww = params.WindowUiIgnore ? (data.Width > 0 ? data.Width : Graphics.width) : (Math.min(data.Width > 0 ? data.Width : Graphics.boxWidth, Graphics.boxWidth - wx));
        const wy = (params.WindowUiIgnore ? 0 : this.nuun_menuHelpAreaHeight()) + data.Y_Position;
        const wh = data.InfoRows > 0 ? this.nuun_infoAreaHeight(data.InfoRows) : data.Height;
        return new Rectangle(wx, wy, ww, Math.min(wh, (params.WindowUiIgnore ? Graphics.height : Graphics.boxHeight) - wy));
    };

    Scene_Menu.prototype.commandWindowRect = function() {
        const wx = this.nuun_mainCommandX();
        const wy = this.nuun_mainCommandY();
        const ww = (Math.min(this.nuun_mainCommandWidth(), (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) - wx));
        const wh = this.nuun_mainCommandHeight();
        return new Rectangle(wx, wy, ww, wh);
    };

    Scene_Menu.prototype.statusWindowRect = function() {
        let rect = [];
        if (params.ArrangementMode === 0) {
            rect = this.statusWindowArrangementModeRect();
        } else {
            rect = this.statusWindowDefaultModeRect();
        }
        return new Rectangle(rect[0], rect[1], rect[2], rect[3]);
    };

    Scene_Menu.prototype.statusWindowDefaultModeRect = function() {
        const width = (params.MenuStatusWidth > 0 ? params.MenuStatusWidth : (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) - (!isBesideMenuCommand() ? this.nuun_mainCommandWidth() : 0));
        const height = params.MenuStatusHeight > 0 ? params.MenuStatusHeight : (params.WindowUiIgnore ? Graphics.height : (Graphics.boxHeight - this.nuun_menuHelpAreaHeight()));
        const wx = (params.MenuCommandPosition === 'left' ? this.nuun_mainCommandWidth() : 0) + (params.WindowUiIgnore ? (Graphics.boxWidth - Graphics.width) / 2 : 0) + params.MenuStatusX;
        const ww = Math.min(width, (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) - wx);
        const wh = Math.min(height, (isBesideMenuCommand() ? (params.WindowUiIgnore ? Graphics.height - this.nuun_mainCommandHeight() : Graphics.boxHeight - this.nuun_menuHelpAreaHeight() - this.nuun_mainCommandHeight()) : (params.WindowUiIgnore ? Graphics.height : Graphics.boxHeight)));
        const wy = (isBesideMenuCommand() ? this._commandWindow.y + (params.MenuCommandPosition === 'under' ? -wh : this.nuun_mainCommandHeight()) : (params.WindowUiIgnore ? (Graphics.boxHeight - Graphics.height) / 2 : this.nuun_menuHelpAreaHeight())) + params.MenuStatusY;
        return [wx, wy, ww, Math.min(wh, (params.WindowUiIgnore ? Graphics.height : Graphics.boxHeight) - wy)];
    };

    Scene_Menu.prototype.statusWindowArrangementModeRect = function() {
        const width = (params.MenuStatusWidth > 0 ? params.MenuStatusWidth : (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth));
        const height = params.MenuStatusHeight > 0 ? params.MenuStatusHeight : (params.WindowUiIgnore ? Graphics.height : (Graphics.boxHeight - this.nuun_menuHelpAreaHeight()));
        const wx = params.MenuStatusX + (params.WindowUiIgnore ? (Graphics.boxWidth - Graphics.width) / 2 : 0);
        const ww = Math.min(width, (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) - wx);
        const wy = (params.WindowUiIgnore ? (Graphics.boxHeight - Graphics.height) / 2 : this.nuun_menuHelpAreaHeight()) + params.MenuStatusY;
        const wh = Math.min(height, (params.WindowUiIgnore ? Graphics.height : Graphics.boxHeight) - wy);
        return [wx, wy, ww, wh];
    };

    function isBesideMenuCommand() {
        return params.MenuCommandPosition === 'under' || params.MenuCommandPosition === 'top';
    };

    Scene_MenuBase.prototype.nuun_mainCommandX = function() {
        switch (params.MenuCommandPosition) {
            case 'free':
            case 'left':
            case 'top':
            case 'under':
                return (params.WindowUiIgnore ? (Graphics.boxWidth - Graphics.width) / 2 : 0) + params.MenuCommandX;
            case 'right':
                return (params.WindowUiIgnore ? Graphics.width + (Graphics.boxWidth - Graphics.width) / 2 : Graphics.boxWidth) - this.nuun_mainCommandWidth() + params.MenuCommandX;
        }
    };

    Scene_MenuBase.prototype.nuun_mainCommandY = function() {
        switch (params.MenuCommandPosition) {
            case 'free':
            case 'left':
            case 'top':
            case 'right':
                return (params.WindowUiIgnore ? (Graphics.boxHeight - Graphics.height) / 2 : this.nuun_menuHelpAreaHeight()) + params.MenuCommandY;
            case 'under':
                return (params.WindowUiIgnore ? Graphics.height + ((Graphics.boxHeight - Graphics.height) / 2) : Graphics.boxHeight) - this.nuun_mainCommandHeight() + params.MenuCommandY;
        }
    };

    Scene_MenuBase.prototype.nuun_mainCommandWidth = function() {
        return params.MenuCommandWidth > 0 ? params.MenuCommandWidth : (params.MenuCommandCols > 1 ? (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) : 240);
    };

    Scene_MenuBase.prototype.nuun_mainCommandHeight = function() {
        return params.CommandHeightMode ? (params.MenuCommandRows > 0 ? this.nuun_mainCommandAreaHeight(params.MenuCommandRows) : this.mainAreaHeight()) : (params.MenuCommandHeight > 0 ? params.MenuCommandHeight : this.mainAreaHeight());
    };

    Scene_MenuBase.prototype.nuun_mainCommandAreaHeight = function(rows) {
        return this.calcWindowHeight(rows, true);
    };

    Scene_MenuBase.prototype.nuun_infoAreaHeight = function(rows) {
        return this.calcWindowHeight(rows, false);
    };

    Scene_MenuBase.prototype.nuun_menuHelpAreaHeight = function() {
        return this.mainAreaTop();
    };

    const _Scene_Menu_createBackground = Scene_Menu.prototype.createBackground;
    Scene_Menu.prototype.createBackground = function() {
        _Scene_Menu_createBackground.call(this);
        if (!$gameSystem.menuBackgroundId) {
            $gameSystem.menuBackgroundId = 0;
        }
        const data = $dataMap;
        const backgroundId = ($gameSystem.menuBackgroundId > 0 ? $gameSystem.menuBackgroundId : ($dataMap && $dataMap.meta.MenuBackgroundId ? Number(data.meta.MenuBackgroundId) : $gameSystem.menuBackgroundId)) || 1;
        const img = params.BackGroundImges ? params.BackGroundImges[backgroundId - 1] : null;
        if (img) {
            const sprite = new Sprite();
            sprite.bitmap = ImageManager.nuun_LoadPictures(img);
            this.addChild(sprite);
            if (sprite.bitmap && !sprite.bitmap.isReady()) {
                sprite.bitmap.addLoadListener(this.setBackGround.bind(this, sprite));
            } else {
                this.setBackGround(sprite, params.BackUiWidth1);
            }
        }
        if (params.BackGroundImg) {
            const sprite = new Sprite();
            sprite.bitmap = ImageManager.nuun_LoadPictures(params.BackGroundImg);
            this.addChild(sprite);
            if (sprite.bitmap && !sprite.bitmap.isReady()) {
                sprite.bitmap.addLoadListener(this.setBackGround.bind(this, sprite));
            } else {
                this.setBackGround(sprite, params.BackUiWidth);
            }
        }
    };

    Scene_Menu.prototype.setBackGround = function(sprite, mode) {
        if (mode) {
            sprite.x = (Graphics.width - (Graphics.boxWidth + 8)) / 2;
            sprite.y = (Graphics.height - (Graphics.boxHeight + 8)) / 2;
            sprite.scale.x = (Graphics.boxWidth + 8 !== sprite.bitmap.width ? (Graphics.boxWidth + 8) / sprite.bitmap.width : 1);
            sprite.scale.y = (Graphics.boxHeight + 8 !== sprite.bitmap.height ? (Graphics.boxHeight + 8) / sprite.bitmap.height : 1);
        } else {
            sprite.scale.x = (Graphics.width !== sprite.bitmap.width ? Graphics.width / sprite.bitmap.width : 1);
            sprite.scale.y = (Graphics.height !== sprite.bitmap.height ? Graphics.height / sprite.bitmap.height : 1);
        }
    };

    const _Scene_Menu_update = Scene_Menu.prototype.update;
    Scene_Menu.prototype.update = function() {
	    _Scene_Menu_update.call(this);
        const commandName = this._commandWindow.currentData().name;
        if (_commandName !== commandName) {
            _commandName = commandName;
            const find = params.HelpList.find(data => data.HelpCommandName === commandName);
            _commandText = find && find.HelpCommandText ? find.HelpCommandText : "";
        }
    };

    Scene_ItemBase.prototype.actorWindowRect = function() {
        let rect = [];
        if (params.ArrangementMode === 0) {
            rect = this.statusWindowArrangementModeRect();
        } else {
            rect = this.statusWindowDefaultModeRect();
        }
        return new Rectangle(rect[0], rect[1], rect[2], rect[3]);
    };

    Scene_ItemBase.prototype.statusWindowDefaultModeRect = function() {
        const width = (params.MenuStatusWidth > 0 ? params.MenuStatusWidth : (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) - (!isBesideMenuCommand() ? this.nuun_mainCommandWidth() : 0));
        const height = params.MenuStatusHeight > 0 ? params.MenuStatusHeight : (params.WindowUiIgnore ? Graphics.height : (Graphics.boxHeight - this.nuun_menuHelpAreaHeight()));
        const wx = (params.MenuCommandPosition === 'left' ? this.nuun_mainCommandWidth() : 0) + (params.WindowUiIgnore ? (Graphics.boxWidth - Graphics.width) / 2 : 0) + params.MenuStatusX;
        const ww = Math.min(width, (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) - wx);
        const wh = Math.min(height, (isBesideMenuCommand() ? (params.WindowUiIgnore ? Graphics.height - this.nuun_mainCommandHeight() : Graphics.boxHeight - this.nuun_menuHelpAreaHeight() - this.nuun_mainCommandHeight()) : (params.WindowUiIgnore ? Graphics.height : Graphics.boxHeight)));
        const wy = (isBesideMenuCommand() ? this.nuun_mainCommandY() + (params.MenuCommandPosition === 'under' ? -wh : this.nuun_mainCommandHeight()) : (params.WindowUiIgnore ? (Graphics.boxHeight - Graphics.height) / 2 : this.nuun_menuHelpAreaHeight())) + params.MenuStatusY;
        return [wx, wy, ww, Math.min(wh, (params.WindowUiIgnore ? Graphics.height : Graphics.boxHeight) - wy)];
    };

    Scene_ItemBase.prototype.statusWindowArrangementModeRect = function() {
        const width = (params.MenuStatusWidth > 0 ? params.MenuStatusWidth : (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth));
        const height = params.MenuStatusHeight > 0 ? params.MenuStatusHeight : (params.WindowUiIgnore ? Graphics.height : (Graphics.boxHeight - this.nuun_menuHelpAreaHeight()));
        const wx = params.MenuStatusX + (params.WindowUiIgnore ? (Graphics.boxWidth - Graphics.width) / 2 : 0);
        const ww = Math.min(width, (params.WindowUiIgnore ? Graphics.width : Graphics.boxWidth) - wx);
        const wy = (params.WindowUiIgnore ? (Graphics.boxHeight - Graphics.height) / 2 : this.nuun_menuHelpAreaHeight()) + params.MenuStatusY;
        const wh = Math.min(height, (params.WindowUiIgnore ? Graphics.height : Graphics.boxHeight) - wy);
        return [wx, wy, ww, wh];
    };

    const _Window_MenuCommand_initialize = Window_MenuCommand.prototype.initialize;
    Window_MenuCommand.prototype.initialize = function(rect) {
        _Window_MenuCommand_initialize.call(this, rect);
        this._homeHeight = this.height;
    };

    Window_MenuCommand.prototype.maxItemsHeight = function() {
        const maxItems = Math.max(1, this.maxItems());
        this.height = Math.min(this.fittingHeight(maxItems), this._homeHeight);
    };

    Window_MenuCommand.prototype.maxCols = function() {
        return params.MenuCommandCols;
    };

    const _Window_Selectable_paint =Window_Selectable.prototype.paint;
    Window_MenuStatus.prototype.paint = function() {
        if (String(this.constructor.name) === 'Window_MenuStatus' && this.contents && !!this._actorsBitmap) {
            for (const sprite of this._actorsBitmap) {
                sprite.resetMenuActorImg();
            }
        }
        _Window_Selectable_paint.call(this);
    };

    const _Window_MenuStatus_initialize = Window_MenuStatus.prototype.initialize;
    Window_MenuStatus.prototype.initialize = function(rect) {
        this._actorsBitmap = [];
        this.language_Jp = $gameSystem.isJapanese();
        _Window_MenuStatus_initialize.call(this, rect);
        this.loadMenuImages();
    };

    Window_MenuStatus.prototype.loadMenuImages = function() {
        for (const actor of $gameParty.allMembers()) {
            let data = null;
            if (Imported.NUUN_ActorPicture && params.ActorPictureEXApp) {
                actor.resetImgId();
                data = this.battlreActorPicture(actor.actorId());
                actor.loadActorFace();
                actor.loadActorGraphic();
            } else {
                data = this.getActorImgData(actor.actorId());
                ImageManager.loadFace(data.FaceImg);
                ImageManager.nuun_LoadPictures(data.ActorImg);
            }
            if (data && data.ActorBackImg) {
                ImageManager.nuun_LoadPictures(data.ActorBackImg);
            }
            if (data && data.ActorFrontImg) {
                ImageManager.nuun_LoadPictures(data.ActorFrontImg);
            }
        }
    };

    Window_MenuStatus.prototype.numVisibleRows = function() {
        return params.MenuRows;
    };

    Window_MenuStatus.prototype.maxCols = function() {
        return params.MenuCols;
    };

    Window_MenuStatus.prototype.maxContentsCols = function() {
        return 1;
    };

    Window_MenuStatus.prototype.itemContentsWidth = function(width) {
        return Math.floor(width / this.maxContentsCols()) - this.colSpacing() - 4;
    };

    Window_MenuStatus.prototype.drawItemBackground = function(index) {
        const actor = this.actor(index);
        const data = this.getActorData(actor);
        if (data && data.ActorBackImg) {
            const bitmap = ImageManager.nuun_LoadPictures(data.ActorBackImg);
            if (bitmap && !bitmap.isReady()) {
                bitmap.addLoadListener(this.drawActorBack.bind(this, bitmap, index));
            } else {
                this.drawActorBack(bitmap, index);
            }
        } else {
            Window_Selectable.prototype.drawItemBackground.call(this, index);
        }
    };

    Window_MenuStatus.prototype.drawActorBack = function(bitmap, index) {
        const rect = this.itemRect(index);
        try {
            this.contentsBack.nuun_contentsBackBlt(bitmap, 0, 0, rect.width, rect.height, rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2, 100, true);
            //this.contentsBack.blt(bitmap, 0, 0, rect.width, rect.height, rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2);
        } catch (e) {
            const log = $gameSystem.isJapanese() ? 'NUUN_BaseがVer.1.6.2以降ではありません。' : "'NUUN_Base' is not Ver.1.6.2 or later.";
            throw ["LoadError", log];
        }
    };

    Window_MenuStatus.prototype.createApngSprite = function(actor, index, data, rect) {
        if (!this._actorsBitmap[index]) {
            const rect = this.itemRect(index);
            const sprite = new Sprite_MenuActorImg();
            this._contentsBackSprite.addChild(sprite);
            this._actorsBitmap[index] = sprite;
        }
        const sprite = this._actorsBitmap[index];
        sprite.setup(actor, data);
        sprite.move(rect.x + 50, rect.y, rect.width, rect.height);
    };

    Window_MenuStatus.prototype.addChildToBack2 = function(child) {
        return this.contents.addChild(child);
    };

    Window_MenuStatus.prototype.drawItemImage = function(index) {
        const actor = this.actor(index);
        const rect = this.itemRect(index);
        let bitmap = null;
        const data = this.getActorData(actor);
        if (data && data.GraphicMode !== 'none') {
            if (data.GraphicMode === 'imgApng') {
                this.createApngSprite(actor, index, data, rect);
            } else if (Imported.NUUN_ActorPicture && params.ActorPictureEXApp) {
                bitmap = data.GraphicMode === 'face' ? actor.loadActorFace() : actor.loadActorGraphic();
            } else {
                bitmap = data.GraphicMode === 'face' ? ImageManager.nuun_LoadPictures(data.FaceImg) : ImageManager.nuun_LoadPictures(data.ActorImg);
            }
        }
        if (bitmap) {
            bitmap.addLoadListener(function() {
                this.drawActorGraphic(data, bitmap, rect.x, rect.y, rect.width, rect.height, actor);
            }.bind(this));
        } else {
            this.drawActorFront(data, rect.x, rect.y, rect.width, rect.height);
        }

    };

    Window_MenuStatus.prototype.drawActorGraphic = function(data, bitmap, x, y, width, height, actor) {
        this.changePaintOpacity(actor.isBattleMember());
        if (data.GraphicMode === 'face') {
            this.contentsDrawActorFace(actor, data, x, y, width, height);
        } else {
            this.contentsDrawActorGraphic(actor, data, bitmap, x, y, width, height);
        }
        this.changePaintOpacity(true);
        this.drawActorFront(data, x, y, width, height);
    };

    Window_MenuStatus.prototype.drawActorFront = function(data, x, y, width, height) {
        const frontBitmapImg = data ? data.ActorFrontImg : null;
        if (frontBitmapImg) {
            const frontBitmap = ImageManager.nuun_LoadPictures(frontBitmapImg);
            frontBitmap.addLoadListener(function() {
                this.drawContentsActorFront(frontBitmap, x, y, width, height);
            }.bind(this));
        }
    };

    Window_MenuStatus.prototype.contentsDrawActorFace = function(actor, data, x, y, width, height) {
        width = Math.min(width, ImageManager.faceWidth);
        height = height - 2;
        this.drawActorFace(actor, x, y, width, height, data);
    };

    Window_MenuStatus.prototype.drawContentsActorFront = function(bitmap, x, y, width, height) {
        this.contents.blt(bitmap, 0, 0, width, height, x, y);
    };

    Window_MenuStatus.prototype.drawItemStatus = function(index) {
        let bitmap = null;
        let loadBitmap = null;
        for (const data of params.StatusList) {
            switch (data.DateSelect) {
                case 200:
                    loadBitmap = this.loadContentsImg();
                    break;
            }
            if (loadBitmap && !loadBitmap.isReady()) {
                bitmap = loadBitmap;
            }
            if (bitmap && !bitmap.isReady()) {
                bitmap.addLoadListener(this.drawItemContentsStatus.bind(this, index))
                return;
            } else {
                this.drawItemContentsStatus(index);
            }
        }
    };

    Window_MenuStatus.prototype.loadContentsImg = function() {
        return ImageManager.nuun_LoadPictures(data.ImgData);
    };

    Window_MenuStatus.prototype.getActorImgData = function(actor) {
        return params.ActorsImgList.find(actorImg => actorImg.actorId === actor.actorId());
    };

    Window_MenuStatus.prototype.drawItemContentsStatus = function(index) {
        const actor = this.actor(index);
        const rect = this.itemRect(index);
        const itemWidth = this.itemContentsWidth(rect.width);
        const lineHeight = this.lineHeight();
        const colSpacing = this.colSpacing();
        maxGaugeWidth = itemWidth;
        for (const data of params.StatusList) {
        const x_Position = data.X_Position;
        const position = Math.min(x_Position, this.maxContentsCols());
        const contentsX = rect.x + (itemWidth + colSpacing) * (position - 1) + data.X_Coordinate + colSpacing;
        const contentsY = rect.y + lineHeight * (data.Y_Position - 1) + data.Y_Coordinate + this.itemPadding();
        const width = data.ItemWidth && data.ItemWidth > 0 ? Math.min(data.ItemWidth, itemWidth) : itemWidth;
        this.drawContentsBase(data, contentsX, contentsY, width - colSpacing / 2, actor);
        }
    };

    Window_MenuStatus.prototype.getActorImgData = function(actorId) {
        const actors = params.ActorsImgList;
        const find = actors.find(actor => actor.actorId === actorId);
        if (!find) {
        return {Actor_X: 0, Actor_Y: 0, Img_SX: 0, Img_SY: 0, Actor_Scale: 100, ActorBackImg: null,ActorFrontImg: null, GraphicMode: params.GraphicMode, FaceIndex : -1};
        } if (find.GraphicMode === 'default' || !find.GraphicMode) {
            find.GraphicMode = params.GraphicMode;
        }
        return find;
    };

    Window_MenuStatus.prototype.battlreActorPicture = function(id) {
        const actors = params.ActorPictureData;
        const find = actors.find(actor => actor.actorId === id);
        if (!find) {
        return {Actor_X: 0, Actor_Y: 0, Img_SX: 0, Img_SY: 0, Actor_Scale: 100, ActorBackImg: null,ActorFrontImg: null, GraphicMode: params.GraphicMode, FaceIndex : -1};
        } else if (find.GraphicMode === 'default' || !find.GraphicMode) {
            find.GraphicMode = params.GraphicMode;
        }
        return find;
    };

    Window_MenuStatus.prototype.getActorData = function(actor) {
        return Imported.NUUN_ActorPicture && params.ActorPictureEXApp ? this.battlreActorPicture(actor.actorId()) : this.getActorImgData(actor.actorId());
    };

    Window_MenuStatus.prototype.drawContentsBase = function(data, x, y, width, actor) {
        $gameTemp.menuParam = null;
        switch (data.DateSelect) {
        case 0:
            break;
        case 1:
            this.drawActorName(data, x, y, width, actor);
            break;
        case 2:
            this.drawActorNickname(data, x, y, width, actor);
            break;
        case 3:
            this.drawActorClass(data, x, y, width, actor);
            break;
        case 4:
            this.drawActorLevel(data, x, y, width, actor);
            break;
        case 5:
            this.drawActorIcons(data, x, y, width, actor);
            break;
        case 6:
            this.drawParam(data, x, y, width, actor);
            break;
        case 7:
            this.drawPlaceStateIcon(x, y, actor);
            break;
        case 11:
            $gameTemp.menuParam = data;
            this.placeHpGauge(x, y, actor);
            break;
        case 12:
            $gameTemp.menuParam = data;
            this.placeMpGauge(x, y, actor);
            break;
        case 13:
            $gameTemp.menuParam = data;
            this.placeTpGauge(x, y, actor);
            break;
        case 14:
            this.drawExp(data, x, y, width, actor);
            break;
        case 15:
            $gameTemp.menuParam = data;
            this.placeExpGauge(x, y, actor);
            break;
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
            this.drawParams(data, data.DateSelect, x, y, width, actor);
            break;
        case 30:
        case 31:
        case 32:
        case 33:
        case 34:
        case 35:
        case 36:
        case 37:
        case 38:
        case 39:
            this.drawXParams(data, data.DateSelect, x, y, width, actor);
            break;
        case 40:
        case 41:
        case 42:
        case 43:
        case 44:
        case 45:
        case 46:
        case 47:
        case 48:
        case 49:
            this.drawSParams(data, data.DateSelect, x, y, width, actor);
            break;
        case 100:
            $gameTemp.menuParam = data;
            this.placeUserGauge(data, x, y, actor);
            break;
        case 200:
            this.drawMenuStatusImg(data, x, y, actor);
            break;
        case 300:
            this.contentsDrawActorChip(data, x, y, width, actor);
            break;
        case 301:
            this.drawSvActorImg(data, x, y, width, actor);
            break;
        case 1000:
            this.horzLine(x, y, width, actor);
            break;
        }
    };

    Window_MenuStatus.prototype.paramNameData = function(data, actor, param) {
        if (data.ParamName) {
        return data.ParamName;
        }
        switch (param) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
            return TextManager.param(param);
        case 10:
        case 11:
        case 12:
            return this.language_Jp ? "会心率" : 'Critcal Rate';
        case 13:
            return this.language_Jp ? "会心回避率" : 'Critical Evade';
        case 14:
            return this.language_Jp ? "魔法回避率" : 'Magic Evade';
        case 15:
            return this.language_Jp ? "魔法反射率" : 'Magic Reflect';
        case 16:
            return this.language_Jp ? "反撃率" : 'Counter';
        case 17:
            return this.language_Jp ? "HP再生率" : 'HP Regen';
        case 18:
            return this.language_Jp ? "MP再生率" : 'MP Regen';
        case 19:
            return this.language_Jp ? "TP再生率" : 'TP Regen';
        case 20:
            return this.language_Jp ? "狙われ率" : 'Aggro';
        case 21:
            return this.language_Jp ? "防御効果率" : 'Guard';
        case 22:
            return this.language_Jp ? "回復効果率" : 'Recovery';
        case 23:
            return this.language_Jp ? "薬の知識" : 'Item Effect';
        case 24:
            return this.language_Jp ? "MP消費率" : 'MP Cost';
        case 25:
            return this.language_Jp ? "TPチャージ率" : 'TP Charge';
        case 26:
            return this.language_Jp ? "物理ダメージ率" : 'Physical Damage';
        case 27:
            return this.language_Jp ? "魔法ダメージ率" : 'Magical Damage';
        case 28:
            return this.language_Jp ? "床ダメージ率" : 'Floor Damage';
        case 29:
            return this.language_Jp ? "獲得経験率" : 'EXP Gain';
        case 42:
            return TextManager.param(0);
        case 43:
            return TextManager.param(1);
        default:
            return null;
        }
    };

    Window_MenuStatus.prototype.paramData = function(data, actor, param) {
        switch (param) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
            return actor.param(param);
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
            return actor.xparam(param - 10) * 100;
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29:
            return actor.sparam(param - 20) * 100;
        default:
            return null;
        }
    };

    Window_MenuStatus.prototype.contentsDrawActorChip = function(data, x, y, width, actor) {
        this.actorCharacterChip(actor, data, x + 24, y + 48);
    };

    Window_MenuStatus.prototype.drawParams = function(data, param, x, y, width, actor) {
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = this.paramNameData(data, actor, param - 20);
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        const textWidth = data.Align === 'left' && data.SystemItemWidth === 0 ? this.textWidth(nameText) : this.systemWidth(data.SystemItemWidth, width);
        this.drawText(nameText, x, y, textWidth);
        this.resetTextColor();
        const textParam = (data.DetaEval ? eval(data.DetaEval) : this.paramData(data, actor, param - 20)) + (data.paramUnit ? String(data.paramUnit) : "");
        this.drawText(textParam, x + textWidth + 8, y, width - (textWidth + 8), data.Align);
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.drawXParams = function(data, param, x, y, width, actor) {
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = this.paramNameData(data, actor, param - 20);
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        const textWidth = data.Align === 'left' && data.SystemItemWidth === 0 ? this.textWidth(nameText) : this.systemWidth(data.SystemItemWidth, width);
        this.drawText(nameText, x, y, textWidth);
        this.resetTextColor();
        let textParam = (data.DetaEval ? eval(data.DetaEval) : this.paramData(data, actor, param - 20));
        textParam = NuunManager.numPercentage(textParam, (data.Decimal - 2) || 0, params.DecimalMode);
        textParam += (data.paramUnit ? String(data.paramUnit) : "");
        this.drawText(textParam, x + textWidth + 8, y, width - (textWidth + 8), data.Align);
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.drawSParams = function(data, param, x, y, width, actor) {
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = this.paramNameData(data, actor, param - 20);
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        const textWidth = data.Align === 'left' && data.SystemItemWidth === 0 ? this.textWidth(nameText) : this.systemWidth(data.SystemItemWidth, width);
        this.drawText(nameText, x, y, textWidth);
        this.resetTextColor();
        let textParam = (data.DetaEval ? eval(data.DetaEval) : this.paramData(data, actor, param - 20));
        textParam = NuunManager.numPercentage(textParam, (data.Decimal - 2) || 0, params.DecimalMode);
        textParam += (data.paramUnit ? String(data.paramUnit) : "");
        this.drawText(textParam, x + textWidth + 8, y, width - (textWidth + 8), data.Align);
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.drawActorName = function(data, x, y, width, actor) {
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        menuTextMode = 'name';
        menuAlign = data.Align;
        Window_StatusBase.prototype.drawActorName.call(this, actor, x, y, width);
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.drawText = function(text, x, y, maxWidth, align) {
        if (menuTextMode === 'name') {
            align = menuAlign;
            menuTextMode = null;
        }
        Window_Base.prototype.drawText.call(this, text, x, y, maxWidth, align);
    };

    Window_MenuStatus.prototype.drawActorClass = function(data, x, y, width, actor) {
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        this.resetTextColor();
        this.drawText(actor.currentClass().name, x, y, width, data.Align);
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.drawActorNickname = function(data, x, y, width, actor) {
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        this.resetTextColor();
        this.drawText(actor.nickname(), x, y, width, data.Align);
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.drawActorLevel = function(data, x, y, width, actor) {
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        this.changeTextColor(ColorManager.systemColor());
        this.drawText(TextManager.levelA, x, y, 48);
        this.resetTextColor();
        this.drawText(actor.level, x + 60, y, width - 60, "right");
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.drawActorIcons = function(data, x, y, width, actor) {
        let icons = [];
        let states = [];
        const iconWidth = ImageManager.iconWidth;
        const dataEval = data.DetaEval;
        if (dataEval) {
            const stateList = dataEval.split(',');
            for (const id of stateList) {
                Array.prototype.push.apply(states, this.nuun_getListIdData(id));
            }
            icons = actor.allIcons().filter(icon => states.some(i => $dataStates[i].iconIndex === icon)).slice(0, Math.floor(width / iconWidth));
            let iconX = x;
            for (const icon of icons) {
                this.drawIcon(icon, iconX, y + 2);
                iconX += iconWidth;
            }
        } else {
            Window_StatusBase.prototype.drawActorIcons.call(this, actor, x, y, width);
        }
    };

    Window_MenuStatus.prototype.drawParam = function(data, x, y, width, actor) {
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = data.ParamName ? data.ParamName : '';
        const textWidth = data.Align === 'left' && data.SystemItemWidth === 0 ? this.textWidth(nameText) : this.systemWidth(data.SystemItemWidth, width);
        this.drawText(nameText, x, y, textWidth);
        this.resetTextColor();
        if (data.DetaEval) {
            const padding = textWidth > 0 ? 8 : 0;
            this.drawText(eval(data.DetaEval), x + textWidth + padding, y, width - (textWidth + padding), data.Align);
        }
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.systemWidth = function(swidth, width) {
        return swidth > 0 ? swidth : Math.floor(width / 3);
    };

    Window_MenuStatus.prototype.placeHpGauge = function(x, y, actor) {
        $gameTemp.menuGaugeType = "hp";
        this.placeGauge(actor, "hp", x, y);
    };

    Window_MenuStatus.prototype.placeMpGauge = function(x, y, actor) {
        $gameTemp.menuGaugeType = "mp";
        this.placeGauge(actor, "mp", x, y);
    };

    Window_MenuStatus.prototype.placeTpGauge = function(x, y, actor) {
        if ($dataSystem.optDisplayTp) {
            $gameTemp.menuGaugeType = "tp";
            this.placeGauge(actor, "tp", x, y);
        }
    };

    Window_MenuStatus.prototype.placeExpGauge = function(x, y, actor) {
        $gameTemp.menuGaugeType = "menuexp";
        this.placeGauge(actor, "menuexp", x, y);
    };

    Window_MenuStatus.prototype.drawPlaceStateIcon = function(x, y, actor) {
        const hw = Math.floor(ImageManager.iconWidth / 2);
        this.placeStateIcon(actor, x + hw, y + hw);
    };

    Window_MenuStatus.prototype.placeUserGauge = function(data, x, y, actor) {
        $gameTemp.menuGaugeType = data.GaugeID;
        this.placeGauge(actor, data.GaugeID, x, y);
    };

    Window_MenuStatus.prototype.drawExp = function(data, x, y, width, actor) {
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = data.ParamName ? data.ParamName : 'NextLv';
        this.contents.fontSize = $gameSystem.mainFontSize() + (data.FontSize || 0);
        const textWidth = data.Align === 'left' && data.SystemItemWidth === 0 ? this.textWidth(nameText) : this.systemWidth(data.SystemItemWidth, width);
        this.drawText(nameText, x + textWidth, y, textWidth);
        this.resetTextColor();
        let textParam = (data.DetaEval ? eval(data.DetaEval) : actor.nextLevelExp() - actor.currentLevelExp());
        this.drawText(textParam, x + textWidth + 8, y, width - (textWidth + 8), data.Align);
        this.contents.fontSize = $gameSystem.mainFontSize();
    };

    Window_MenuStatus.prototype.placeGauge = function(actor, type, x, y) {
        if (Imported.NUUN_GaugeImage) {
            this.placeGaugeImg(actor, type, x, y);
        }
        const key = "actor%1-gauge-%2".format(actor.actorId(), type);
        const sprite = this.createInnerSprite(key, Sprite_MenuGauge);
        sprite.setup(actor, type);
        sprite.move(x, y);
        sprite.show();
    };

    Window_MenuStatus.prototype.actorCharacterChip = function(actor, data, x, y) {
        const key = "actor%1-menuStatusCharacter".format(actor.actorId());
        const sprite = this.createInnerSprite(key, Sprite_MenuScreenCharacter);
        sprite.setup(actor, data);
        sprite._character.setPosition(0, 0);
        sprite.move(x, y);
        sprite.show();
    };

    Window_MenuStatus.prototype.drawSvActorImg = function(data, x, y, width, actor) {
        const key = "menuSvActor%1".format(actor.actorId());
        const sprite = this.createInnerSprite(key, Sprite_MenuSvActor);
        sprite.setup(actor, data);
        sprite.show();
        sprite.setHome(x + 64, y + 64);
        sprite.startMotion();
    };

    Window_MenuStatus.prototype.drawMenuStatusImg = function(data, x, y, actor) {
        if (data.ImgData) {
            const rect = this.itemRect(0);
            const bitmap = ImageManager.nuun_LoadPictures(data.ImgData);
            this.contents.blt(bitmap, 0, 0, rect.width, rect.height, x - this.colSpacing(), y - this.itemPadding());
        }
    };

    Window_MenuStatus.prototype.drawActorFace = function(actor, x, y, width, height, data) {
        x += (data ? data.Actor_X : 0) + params.ActorImg_X + 1;
        y += (data ? data.Actor_Y : 0) + params.ActorImg_Y + 1;
        if (Imported.NUUN_ActorPicture && params.ActorPictureEXApp) {
            this.drawFace(actor.getActorGraphicFace(), actor.getActorGraphicFaceIndex(), x, y, width, height);
        } else {
            let bitmap = null;
            if (data && data.FaceImg) {
                bitmap = data.FaceImg;
            } else {
                bitmap = actor.faceName();
            }
            const faceIndex = data && data.FaceIndex >= 0 ? data.FaceIndex : actor.faceIndex();
            this.drawFace(bitmap, faceIndex, x, y, width, height);
        }
    };

    Window_MenuStatus.prototype.contentsDrawActorGraphic = function(actor, data, bitmap, x, y, width, height) {
        width = Math.min(width - 2, bitmap.width);
        height = Math.min(height - 2, bitmap.height);
        const scale = (data.Actor_Scale || 100) / 100;
        const sw = width * scale;
        const sh = height * scale;
        const sx = data.Img_SX || 0;
        const sy = data.Img_SY || 0;
        x += 1 + data.Actor_X + params.ActorImg_X;
        y += 1 + data.Actor_Y + params.ActorImg_Y;
        this.contents.blt(bitmap, sx, sy, width + (width - sw), height + (height - sh), x, y, width, height);
    };

    function Window_InfoMenu() {
        this.initialize(...arguments);
    }

    Window_InfoMenu.prototype = Object.create(Window_Selectable.prototype);
    Window_InfoMenu.prototype.constructor = Window_InfoMenu;

    Window_InfoMenu.prototype.initialize = function(rect) {
        Window_Selectable.prototype.initialize.call(this, rect);
        this._text = '';
        this._commandName = _commandName;
        this._data = null;
        this._infoFontSize = 0;
        this._onPlayTime = false;
        this._onRefresh = false;
    };

    Window_InfoMenu.prototype.setup = function(data, cols, fontsize) {
        this._data = data;
        this._maxCols = cols;
        this._infoFontSize = fontsize;
        this.refresh();
    };

    Window_InfoMenu.prototype.maxCols = function() {
        return this._maxCols ? this._maxCols : 1;
    };

    Window_InfoMenu.prototype.itemHeight = function() {
        return this.lineHeight();
    };

    Window_InfoMenu.prototype.getInfoList = function() {
        return this._data || [];
    };

    Window_InfoMenu.prototype.refresh = function() {
        this.contents.clear();
        const listData = this.getInfoList();
        const lineHeight = this.lineHeight();
        for (const data of listData) {
            this.resetFontSettings();
            const x_Position = data.X_Position;
            const position = Math.min(x_Position, this.maxCols());
            const rect = this.itemRect(position - 1);
            const x = rect.x + (data.X_Coordinate || 0);
            const y = (data.Y_Position - 1) * lineHeight + rect.y + data.Y_Coordinate;
            const width = data.ItemWidth && data.ItemWidth > 0 ? data.ItemWidth : rect.width;
            this.dateDisplay(data, x, y, width);
        }
    };

    Window_InfoMenu.prototype.dateDisplay = function(data, x, y, width) {
        switch (data.DateSelect) {
        case 0:
            break;
        case 1:
            this.drawPlayTime(data, x, y, width);
            break;
        case 2:
            this.drawGold(data, x, y, width);
            break;
        case 3:
            this.drawLocation(data, x, y, width);
            break;
        case 4:
            this.drawParam(data, x, y, width);
            break;
        case 5:
            this.drawName(data, x, y, width);
            break;
        case 6:
            this.drawCommandExplanation(data, x, y, width);
            break;
        case 10:
            this.drawFreeText(data, x, y, width);
            break;
        case 11:
            this.drawDestination(data, x, y, width);
            break;
        case 12:
            this.drawChapter(data, x, y, width);
            break;
        default:
            break;
        }
    };

    Window_InfoMenu.prototype.drawGold = function(data, x, y, width) {
        let iconWidth = 0;
        if (data.InfoIcon > 0) {
            this.drawIcon(data.InfoIcon, x, y + 2);
            iconWidth = ImageManager.iconWidth + 6;
        }
        this.contents.fontSize = $gameSystem.mainFontSize() + this._infoFontSize + (data.ContentsFontSize || 0);
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = data.ParamName ? data.ParamName : '';
        const systemWidth = data.SystemItemWidth === 0 ? this.textWidth(nameText) : this.systemWidth(data.SystemItemWidth, width);
        this.drawText(nameText, x + iconWidth, y, systemWidth);
        this.resetTextColor();
        this.drawCurrencyValue(this.value(), this.currencyUnit(), x + systemWidth + 8 + iconWidth, y, width - (systemWidth + 8 + iconWidth));
    };

    Window_InfoMenu.prototype.drawPlayTime = function(data, x, y, width) {
        this.contents.fontSize = $gameSystem.mainFontSize() + this._infoFontSize + (data.ContentsFontSize || 0);
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = data.ParamName ? data.ParamName : '';
        const systemWidth = !!nameText ? (data.SystemItemWidth || 160) : 0;
        let iconWidth = 0;
        if (data.InfoIcon > 0) {
            this.drawIcon(data.InfoIcon, x, y + 2);
            iconWidth = ImageManager.iconWidth + 6;
        }
        this.drawText(nameText, x + iconWidth, y, systemWidth);
        this.resetTextColor();
        this.drawText($gameSystem.playtimeText(), x + systemWidth + iconWidth + this.itemPadding(), y, width - (systemWidth + 8 + iconWidth), data.Align);
        this._onPlayTime = true;
    };

    Window_InfoMenu.prototype.drawLocation = function(data, x, y, width) {
        this.contents.fontSize = $gameSystem.mainFontSize() + this._infoFontSize + (data.ContentsFontSize || 0);
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = data.ParamName ? data.ParamName : '';
        const systemWidth = !!nameText ? (data.SystemItemWidth || 160) : 0;
        let iconWidth = 0;
        if (data.InfoIcon > 0) {
            this.drawIcon(data.InfoIcon, x, y + 2);
            iconWidth = ImageManager.iconWidth + 6;
        }
        this.drawText(nameText, x + iconWidth, y, systemWidth);
        this.resetTextColor();
        const text = $gameMap.mapId() > 0 ? $gameMap.displayName() : '';
        this.drawText(text, x + systemWidth + iconWidth + this.itemPadding(), y, width - (systemWidth + 8 + iconWidth), data.Align);
    };

    Window_InfoMenu.prototype.drawParam = function(data, x, y, width) {
        this.contents.fontSize = $gameSystem.mainFontSize() + this._infoFontSize + (data.ContentsFontSize || 0);
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = data.ParamName ? data.ParamName : '';
        const systemWidth = !!nameText ? (data.SystemItemWidth || 160) : 0;
        let iconWidth = 0;
        if (data.InfoIcon > 0) {
            this.drawIcon(data.InfoIcon, x, y + 2);
            iconWidth = ImageManager.iconWidth + 6;
        }
        this.drawText(nameText, x + iconWidth, y, systemWidth);
        this.resetTextColor();
        if (data.DetaEval) {
            this.drawText(eval(data.DataEval), x + systemWidth + 8 + iconWidth, y, width - (systemWidth + 8 + iconWidth), data.Align);
        }
    };

    Window_InfoMenu.prototype.drawCommandExplanation = function(data, x, y, width) {
        this.drawTextEx(this._text, x, y, width);
    };

    Window_InfoMenu.prototype.drawFreeText = function(data, x, y, width) {
        this.drawTextEx(data.Text, x, y, width);
    };

    Window_InfoMenu.prototype.drawDestination = function(data, x, y, width) {
        if (!Imported.NUUN_Destination) {
            return;
        }
        let iconWidth = 0;
        let textWidth = 0;
        if (data.InfoIcon > 0) {
            this.drawIcon(data.InfoIcon, x, y + 2);
            iconWidth = ImageManager.iconWidth + 6;
        }
        this.contents.fontSize = $gameSystem.mainFontSize() + this._infoFontSize + (data.ContentsFontSize || 0);
        if (data.ParamName) {
            this.changeTextColor(NuunManager.getColorCode(data.NameColor));
            const nameText = data.ParamName ? data.ParamName : '';
            this.drawText(nameText, x + iconWidth, y, textWidth);
            textWidth = this.systemWidth(data.SystemItemWidth, width);
        }
        this.resetTextColor();
        const text = this.getDestinationList();
        if (text) {
            this.drawTextEx(text, x + iconWidth + textWidth, y, width - textWidth - iconWidth);
        }
        this.resetFontSettings();
    };

    Window_InfoMenu.prototype.drawChapter = function(data, x, y, width) {
        if (!Imported.NUUN_Chapter) {
            return;
        }
        let iconWidth = 0;
        let textWidth = 0;
        if (data.InfoIcon > 0) {
            this.drawIcon(data.InfoIcon, x, y + 2);
            iconWidth = ImageManager.iconWidth + 6;
        }
        this.contents.fontSize = $gameSystem.mainFontSize() + this._infoFontSize + (data.ContentsFontSize || 0);
        if (data.ParamName) {
            this.changeTextColor(NuunManager.getColorCode(data.NameColor));
            const nameText = data.ParamName ? data.ParamName : '';
            this.drawText(nameText, x + iconWidth, y, textWidth);
            textWidth = this.systemWidth(data.SystemItemWidth, width);
        }
        this.resetTextColor();
        const text = this.getChapter();
        if (text) {
            this.drawTextEx(text, x + iconWidth + textWidth, y, width - textWidth - iconWidth);
        }
        this.resetFontSettings();
    };

    Window_InfoMenu.prototype.drawName = function(data, x, y, width) {
        this.contents.fontSize = $gameSystem.mainFontSize() + this._infoFontSize + (data.ContentsFontSize || 0);
        this.changeTextColor(NuunManager.getColorCode(data.NameColor));
        const nameText = data.ParamName ? data.ParamName : '';
        this.drawText(nameText, x, y, width, data.Align);
    };

    Window_InfoMenu.prototype.systemWidth = function(swidth, width) {
        return swidth > 0 ? swidth : 120;
    };

    Window_InfoMenu.prototype.value = function() {
        return $gameParty.gold();
    };

    Window_InfoMenu.prototype.currencyUnit = function() {
        return TextManager.currencyUnit;
    };

    Window_InfoMenu.prototype.setText = function(str) {
        this._text = str;
        this._onRefresh = true;
    };

    Window_InfoMenu.prototype.update = function() {
        Window_Selectable.prototype.update.call(this);
        if (this._commandName !== _commandName) {
            this.setText(_commandText);
            this._commandName = _commandName;
        }
        if (this._onPlayTime || this._onRefresh) {
            this.refresh();
        }
    };

    function Sprite_MenuGauge() {
        this.initialize(...arguments);
    }

    Sprite_MenuGauge.prototype = Object.create(Sprite_Gauge.prototype);
    Sprite_MenuGauge.prototype.constructor = Sprite_MenuGauge;

    Sprite_MenuGauge.prototype.initialize = function() {
        this._statusType = $gameTemp.menuGaugeType;
        this.menuParam = $gameTemp.menuParam;
        this._gaugeWidth = Math.min(this.getMenuGaugeWidth(), maxGaugeWidth);
        this._gaugeHeight = this.getMenuGaugeHeight();
        Sprite_Gauge.prototype.initialize.call(this);
    };

    Sprite_MenuGauge.prototype.bitmapWidth = function() {
        return this._gaugeWidth;
    };

    Sprite_MenuGauge.prototype.gaugeHeight = function() {
        return this._gaugeHeight;
    };

    Sprite_MenuGauge.prototype.getMenuGaugeWidth = function() {
        switch (this._statusType) {
          case 'hp':
            return this.menuParam.ItemWidth > 0 ? this.menuParam.ItemWidth : params.HPGaugeWidth;
          case 'mp':
            return this.menuParam.ItemWidth > 0 ? this.menuParam.ItemWidth : params.MPGaugeWidth;
          case 'tp':
            return this.menuParam.ItemWidth > 0 ? this.menuParam.ItemWidth : params.TPGaugeWidth;
          case 'menuexp':
            return this.menuParam.ItemWidth > 0 ? this.menuParam.ItemWidth : params.ExpGaugeWidth;
          default:
            return this.menuParam.ItemWidth > 0 ? this.menuParam.ItemWidth : 128;
        }
    };

    Sprite_MenuGauge.prototype.getMenuGaugeHeight = function() {
        switch (this._statusType) {
            case 'hp':
              return this.menuParam.GaugeHeight > 0 ? this.menuParam.GaugeHeight : 12;
            case 'mp':
              return this.menuParam.GaugeHeight > 0 ? this.menuParam.GaugeHeight : 12;
            case 'tp':
              return this.menuParam.GaugeHeight > 0 ? this.menuParam.GaugeHeight : 12;
            case 'menuexp':
              return this.menuParam.GaugeHeight > 0 ? this.menuParam.GaugeHeight : 12;
            default:
              return this.menuParam.GaugeHeight > 0 ? this.menuParam.GaugeHeight : 128;
          }
    };

    Sprite_MenuGauge.prototype.gaugeColor1 = function() {
        if (this._battler && this.menuParam) {
          switch (this._statusType) {
            case "hp":
            case "mp":
            case "tp":
            case "time":
                return Sprite_Gauge.prototype.gaugeColor1.call(this);
            case "menuexp":
                return NuunManager.getColorCode(params.ExpGaugeColor1);
            default:
              return NuunManager.getColorCode(this.menuParam.Color1);
          }
        } else {
          return Sprite_Gauge.prototype.gaugeColor1.call(this);
        }
    };

    Sprite_MenuGauge.prototype.gaugeColor2 = function() {
        if (this._battler && this.menuParam) {
          switch (this._statusType) {
            case "hp":
            case "mp":
            case "tp":
            case "time":
                return Sprite_Gauge.prototype.gaugeColor2.call(this);
            case "menuexp":
                return NuunManager.getColorCode(params.ExpGaugeColor2);
            default:
              return NuunManager.getColorCode(this.menuParam.Color2);
          }
        } else {
          return Sprite_Gauge.prototype.gaugeColor2.call(this);
        }
    };

    Sprite_MenuGauge.prototype.displyaExp = function() {
        if (params.ExpDisplayMode === 1) {
            return this.currentMaxValue() - this.currentValue();
        } else if (params.ExpDisplayMode === 2) {
            return this.currentValue();
        } else if (params.ExpDisplayMode === 3) {
            return NuunManager.numPercentage(this.currentValue() / this.currentMaxValue() * 100, params.EXPDecimal, params.DecimalMode);
        }
        return this._battler.currentExp() - this._battler.currentLevelExp();
    };

    Sprite_MenuGauge.prototype.displyaMaxExp = function() {
        return this._battler.nextLevelExp() - this._battler.currentLevelExp();
    };

    Sprite_MenuGauge.prototype.currentValue = function() {
        if (this._battler && this.menuParam) {
        switch (this._statusType) {
            case "hp":
            case "mp":
            case "tp":
            case "time":
                return Sprite_Gauge.prototype.currentValue.call(this);
            case "menuexp":
                return this._battler.currentExp() - this._battler.currentLevelExp();
            default:
                const actor = this._battler;
                return eval(this.menuParam.DetaEval);
          }
        } else {
          return Sprite_Gauge.prototype.currentValue.call(this);
        }
    };

    Sprite_MenuGauge.prototype.currentMaxValue = function() {
        if (this._battler && this.menuParam) {
        switch (this._statusType) {
            case "hp":
            case "mp":
            case "tp":
            case "time":
                return Sprite_Gauge.prototype.currentMaxValue.call(this);
            case "menuexp":
                return this._battler.nextLevelExp() - this._battler.currentLevelExp();
            default:
                const actor = this._battler;
                return eval(this.menuParam.DetaEval2);
            }
        } else {
          return Sprite_Gauge.prototype.currentMaxValue.call(this);
        }
    };

    Sprite_MenuGauge.prototype.label = function() {
        if (this._battler && this.menuParam) {
            switch (this._statusType) {
            case "hp":
            case "mp":
            case "tp":
            case "time":
                return Sprite_Gauge.prototype.label.call(this);
            case "menuexp":
                return params.LabelShow ? TextManager.expA : '';
            default:
              return this.menuParam.ParamName;
            }
        } else {
          return Sprite_Gauge.prototype.label.call(this);
        }
    };

    Sprite_MenuGauge.prototype.drawValue = function() {
        if (this._statusType === "menuexp" && params.ExpDisplayMode !== 0) {
            let text = this.displyaExp();
            if (params.ExpDisplayMode === 3) {
                text += '%';
            }
            const width = this.bitmapWidth();
            const height = this.textHeight();
            this.setupValueFont();
            this.bitmap.drawText(text, 0, 0, width, height, "right");
        } else {
            Sprite_Gauge.prototype.drawValue.call(this);
        }
    };

    function Sprite_MenuScreenCharacter() {
        this.initialize(...arguments);
    }

    Sprite_MenuScreenCharacter.prototype = Object.create(Sprite_Character.prototype);
    Sprite_MenuScreenCharacter.prototype.constructor = Sprite_MenuScreenCharacter;

    Sprite_MenuScreenCharacter.prototype.initialize = function(character) {
        Sprite_Character.prototype.initialize.call(this, character);
        this._data = null;
        this._actor = null;
    };

    Sprite_MenuScreenCharacter.prototype.setup = function(battler, data) {
        const character = new Game_Character(battler);
        const characterName = battler.characterName();
        const characterIndex = battler.characterIndex();
        character.setImage(characterName, characterIndex);
        character.setStepAnime(true);
        this._data = data;
        this._actor = battler;
        this.setCharacter(character);
    };

    Sprite_MenuScreenCharacter.prototype.update = function() {
        if (this.visible) {
          Sprite_Character.prototype.update.call(this);
          this._character.updateAnimation();
          this.changePaintOpacity();
        }
    };

    Sprite_MenuScreenCharacter.prototype.changePaintOpacity = function() {
        const battleMemberOpacity = this._data.BattleMemberOpacity !== undefined ? this._data.BattleMemberOpacity : true;
        if (battleMemberOpacity) {
            this.opacity = this._actor.isBattleMember() ? 255 : Window_Base.prototype.translucentOpacity.call(this);
        }
    };

    Sprite_MenuScreenCharacter.prototype.updatePosition = function() {

    };

    function Sprite_MenuSvActor() {
        this.initialize(...arguments);
    }

    Sprite_MenuSvActor.prototype = Object.create(Sprite_Actor.prototype);
    Sprite_MenuSvActor.prototype.constructor = Sprite_MenuSvActor;

    Sprite_MenuSvActor.prototype.updateVisibility = function() {
        Sprite_Clickable.prototype.updateVisibility.call(this);
    };

    Sprite_MenuSvActor.prototype.initialize = function(battler) {
    Sprite_Actor.prototype.initialize.call(this, battler);
        this._data = null;
    };

    Sprite_MenuSvActor.prototype.setup = function(battler, data) {
        this.setBattler(battler);
        this._data = data;
    };

    Sprite_MenuSvActor.prototype.moveToStartPosition = function() {
        this.startMove(0, 0, 0);
    };

    Sprite_MenuSvActor.prototype.updateMain = function() {
        this.updateBitmap();
        this.updateFrame();
        this.updateMove();
        this.changePaintOpacity();
    };

    Sprite_MenuSvActor.prototype.changePaintOpacity = function() {
        const battleMemberOpacity = this._data.BattleMemberOpacity !== undefined ? this._data.BattleMemberOpacity : true;
        if (battleMemberOpacity) {
            this.opacity = this._actor.isBattleMember() ? 255 : Window_Base.prototype.translucentOpacity.call(this);
        }
    };

    Sprite_MenuSvActor.prototype.startMotion = function() {
        if (this._actor.isDead()) {
            motionType = 'dead';
        } else {
            motionType = 'walk';
        }
        Sprite_Actor.prototype.startMotion.call(this, motionType);
    };

    Sprite_MenuSvActor.prototype.setupWeaponAnimation = function() {

    };

    function Sprite_MenuActorImg() {
        this.initialize(...arguments);
    }

    Sprite_MenuActorImg.prototype = Object.create(Sprite.prototype);
    Sprite_MenuActorImg.prototype.constructor = Sprite_MenuActorImg;

    Sprite_MenuActorImg.prototype.initialize = function() {
        Sprite.prototype.initialize.call(this);
        this.initMembers();
    };

    Sprite_MenuActorImg.prototype.initMembers = function() {
        this._battler = null;
        this._apngMode = null;
        this._data = null;
        this._pictureName = null;
    };

    Sprite_MenuActorImg.prototype.setup = function(battler, data) {
        this._battler = battler;
        this._data = data;
        const name = Imported.NUUN_ActorPicture && params.ActorPictureEXApp ? battler.getActorGraphicImg() : data.ActorImg;
        this._pictureName = name.split('pictures/')[1];
        this.refresh();
    };

    Sprite_MenuActorImg.prototype.refresh = function() {
        if (this.addApngChild && this.loadApngSprite(this._pictureName)) {
            this.addApngChild(this._pictureName);
            this._apngMode = true;
        }
    };

    Sprite_MenuActorImg.prototype.destroy = function() {
        this.resetMenuActorImg();
        Sprite.prototype.destroy.call(this);
    };

    Sprite_MenuActorImg.prototype.resetMenuActorImg = function() {
        this._battler = null;
        if (this._apngMode) {
            this.destroyApngIfNeed();
            this._apngMode = null;
        }
    };

    Sprite_MenuActorImg.prototype.loadApngSprite = function(name) {
        return Sprite_Picture.prototype.loadApngSprite.call(this, name);
    };

})();


code:
//=============================================================================
// PictureCallCommon.js
// ----------------------------------------------------------------------------
// (C)2015 Triacontane
// This plugin is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.6.0 2023/11/16 プラグインコマンドを「ピクチャの操作拡張プラグイン」が提供する一括指定機能に対応させました。
// 1.5.1 2023/06/12 ピクチャイベント解除時に指定した番号以外の番号のピクチャイベントも一緒に解除される可能性がある問題を修正
// 1.5.0 2023/04/22 ピクチャイベントを発生させる際、透過部分に反応するかどうかを設定できる機能を追加
// 1.4.0 2022/10/22 DTextPicture.jsと組み合わせたとき、フレームウィンドウをクリックイベントの範囲に含めるよう変更
// 1.3.1 2022/05/19 ヘルプ微修正
// 1.3.0 2022/04/14 ピクチャクリック時に変数を操作する機能および任意スクリプトを実行する機能を追加
// 1.2.2 2021/11/07 異なるピクチャのトリガーを同一フレームで同時に満たした場合、すべてのタッチ処理が実行されるよう修正
// 1.2.1 2021/10/08 トリガー種別がマウスが重なった場合のとき無効スイッチ中に条件を満たしていると、無効スイッチがOFFになった瞬間にイベントが発生してしまう問題を修正
// 1.2.0 2021/05/20 APNGピクチャプラグインと組み合わせたときにAPNGピクチャをボタン化できるよう修正（ただし透過色は考慮されない）
// 1.1.2 2021/04/08 トリガー「マウスをピクチャ内で移動した場合」がマウスを押していないと反応しない問題を修正
// 1.1.1 2020/12/21 スクリプト$gameScreen.showPictureを使って未キャッシュのピクチャを表示しようとすると画像が表示されなくなる問題を修正
//                  セーブデータロード時にエラーになる問題を修正
// 1.1.0 2020/12/20 イベントごとに無効スイッチを指定できる機能を追加
// 1.0.0 2020/12/17 MZ版として新規作成
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc ピクチャのボタン化プラグイン
 * @target MZ
 * @url https://github.com/triacontane/RPGMakerMV/tree/mz_master/PictureCallCommon.js
 * @base PluginCommonBase
 * @author トリアコンタン
 *
 * @param PictureIdVariable
 * @text ピクチャ番号の変数
 * @desc 最後にイベントが発生したピクチャ番号を格納する変数IDです。
 * @default 0
 * @type variable
 *
 * @param InvalidSwitchId
 * @text 無効スイッチ
 * @desc 指定した番号のスイッチがONになっている場合、すべてのピクチャイベントが無効になります。
 * @default 0
 * @type switch
 *
 * @param FlickDistance
 * @text フリック有効距離
 * @desc フリック判定が有効になる距離(ピクセル数)です。
 * @default 60
 * @type number
 *
 * @param FlickTimeVariable
 * @text フリック時間の変数
 * @desc フリック判定が有効になるまでに掛かったフレーム数を格納する変数IDです。この値が小さいほど速いフリックです。
 * @default 0
 * @type variable
 *
 * @param FlickDegreeVariable
 * @text フリック角度の変数
 * @desc フリック判定が有効になったときのフリック方向を度数法で格納する変数IDです。
 * @default 0
 * @type variable
 *
 * @command ADD_PICTURE_EVENT
 * @text ピクチャイベント登録
 * @desc ピクチャ操作で発生するイベントを登録します。
 *
 * @arg pictureId
 * @text ピクチャ番号
 * @desc 操作対象のピクチャ番号です。
 * @default 1
 * @type number
 *
 * @arg commonEventId
 * @text コモンイベント番号
 * @desc イベント発生時に呼び出すコモンイベントです。
 * @default 0
 * @type common_event
 *
 * @arg switchId
 * @text スイッチ番号
 * @desc イベント発生時にONになるスイッチです。
 * @default 0
 * @type switch
 *
 * @arg variableId
 * @text 変数番号
 * @desc イベント発生時に値が加減される変数です。
 * @default 0
 * @type variable
 *
 * @arg operationType
 * @parent variableId
 * @text 操作種別
 * @desc イベント発生時に指定した変数の操作種別です。
 * @default 0
 * @type select
 * @option 代入
 * @value 0
 * @option 加算
 * @value 1
 * @option 減算
 * @value 2
 * @option 乗算
 * @value 3
 * @option 除算
 * @value 4
 * @option 剰余
 * @value 5
 *
 * @arg operand
 * @parent variableId
 * @text オペランド
 * @desc イベント発生時に指定した変数の操作値です。
 * @default 0
 * @type number
 * @min -99999999
 *
 * @arg script
 * @text スクリプト
 * @desc イベント発生時に実行されるスクリプトです。
 * @type multiline_string
 *
 * @arg buttonBind
 * @text ボタンバインド
 * @desc イベント発生時に押したことになるボタンです。
 * @default
 * @type combo
 * @option ok
 * @option shift
 * @option control
 * @option escape
 * @option left
 * @option up
 * @option right
 * @option down
 * @option pageup
 * @option pagedown
 *
 * @arg triggerType
 * @text トリガー種別
 * @desc トリガーとなるマウス、タッチ操作の種別です。
 * @default 1
 * @type select
 * @option 1:クリックした場合
 * @value 1
 * @option 2:右クリックした場合
 * @value 2
 * @option 3:長押しした場合
 * @value 3
 * @option 4:マウスをピクチャに重ねた場合
 * @value 4
 * @option 5:マウスをピクチャから放した場合
 * @value 5
 * @option 6:クリックを解放（リリース）した場合
 * @value 6
 * @option 7:クリックした場合（かつ長押しの際の繰り返しを考慮）
 * @value 7
 * @option 8:クリックしている間ずっと
 * @value 8
 * @option 9:ホイールクリックした場合（PCの場合のみ有効）
 * @value 9
 * @option 10:ダブルクリックした場合
 * @value 10
 * @option 11:マウスをピクチャ内で移動した場合
 * @value 11
 * @option 12:マウスを押しつつピクチャ内で移動した場合
 * @value 12
 * @option 13:フリック(マウス押下状態で指定距離以上動かす)した場合
 * @value 13
 *
 * @arg invalidSwitchId
 * @text 無効スイッチ
 * @desc 指定した番号のスイッチがONになっている場合、ピクチャイベントが無効になります。
 * @default 0
 * @type switch
 *
 * @command SET_PICTURE_PREFERENCE
 * @text ピクチャ設定
 * @desc　ピクチャイベントの設定を変更します。
 *
 * @arg pictureId
 * @text ピクチャ番号
 * @desc 変更対象のピクチャ番号です。
 * @default 1
 * @type number
 *
 * @arg includeOpacityZero
 * @text 透過部分も含む
 * @desc ピクチャの透明部分にも反応するかどうかです。
 * @default false
 * @type boolean
 *
 * @command REMOVE_PICTURE_EVENT
 * @text ピクチャイベント解除
 * @desc 登録したピクチャイベントを解除します。
 *
 * @arg pictureId
 * @text ピクチャ番号
 * @desc 操作対象のピクチャ番号です。
 * @default 1
 * @type number
 *
 * @help PictureCallCommon.js
 *
 * ピクチャに対する様々なマウス操作に反応してコモンイベント実行や
 * スイッチ制御ができます。（これをピクチャイベントと呼びます）
 * 一度登録したピクチャイベントはピクチャを消去しても有効です。
 * 解除は専用のプラグインコマンドから可能です。
 *
 * 各マウス操作について、ピクチャの透明部分には反応しません。
 *
 * ピクチャイベントはマップ画面でも戦闘画面でも
 * 他のイベントや状況の制限を受けずに速やかに並列実行されます。
 * また、ピクチャイベントが発生した瞬間のフレームでは他のクリック処理は
 * 無効となりタッチによるマップ移動やメッセージ送り等は行われません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function() {
    'use strict';
    const script = document.currentScript;
    const param  = PluginManagerEx.createParameter(script);

    PluginManagerEx.registerCommand(script, 'ADD_PICTURE_EVENT', args => {
        if ($gameScreen.iteratePictures) {
            $gameScreen.iteratePictures($gameScreen.addPictureEvent, [args.pictureId, args.triggerType, args]);
        } else {
            $gameScreen.addPictureEvent(args.pictureId, args.triggerType, args);
        }
    });

    PluginManagerEx.registerCommand(script, 'REMOVE_PICTURE_EVENT', args => {
        if ($gameScreen.iteratePictures) {
            $gameScreen.iteratePictures($gameScreen.removePictureEvent, [args.pictureId]);
        } else {
            $gameScreen.removePictureEvent(args.pictureId);
        }
    });

    PluginManagerEx.registerCommand(script, 'SET_PICTURE_PREFERENCE', args => {
        if ($gameScreen.iteratePictures) {
            $gameScreen.iteratePictures($gameScreen.setPicturePreference, [args.pictureId, args]);
        } else {
            $gameScreen.setPicturePreference(args.pictureId, args);
        }
    });

    //=============================================================================
    // Game_System
    //  ロード時にピクチャ関連メンバを初期化します。
    //=============================================================================
    const _Game_System_onAfterLoad    = Game_System.prototype.onAfterLoad;
    Game_System.prototype.onAfterLoad = function() {
        _Game_System_onAfterLoad.apply(this, arguments);
        $gameScreen.initPictureEventMap();
    };

    //=============================================================================
    // Game_Screen
    //  ピクチャに対応するコモンイベント呼び出し用のID配列を追加定義します。
    //=============================================================================
    const _Game_Screen_initialize    = Game_Screen.prototype.initialize;
    Game_Screen.prototype.initialize = function() {
        _Game_Screen_initialize.apply(this, arguments);
        this.initPictureEventMap();
    };

    Game_Screen.prototype.initPictureEventMap = function() {
        if (!this._pictureEventMap) {
            this._pictureEventMap = new Game_PictureEventMap();
        }
    };

    Game_Screen.prototype.addPictureEvent = function(pictureId, trigger, param) {
        const realPictureId = this.realPictureId(pictureId);
        this._pictureEventMap.append(realPictureId, trigger, param);
    };

    Game_Screen.prototype.removePictureEvent = function(pictureId, trigger = null) {
        const realPictureId = this.realPictureId(pictureId);
        if (trigger === null) {
            this._pictureEventMap.removeById(realPictureId);
        } else {
            this._pictureEventMap.remove(realPictureId, trigger);
        }
    };

    Game_Screen.prototype.findPictureEvent = function(pictureId, trigger) {
        const realPictureId = this.realPictureId(pictureId);
        return this._pictureEventMap.find(realPictureId, trigger);
    };

    Game_Screen.prototype.setPicturePreference = function(pictureId, param) {
        const realPictureId = this.realPictureId(pictureId);
        this._pictureEventMap.setPreference(realPictureId, param);
    };

    Game_Screen.prototype.getPicturePreference = function(pictureId) {
        const realPictureId = this.realPictureId(pictureId);
        return this._pictureEventMap.getPreference(realPictureId);
    }

    Game_Screen.prototype.disConvertPositionX = function(x) {
        const unshiftX = x - this.zoomX() * (1 - this.zoomScale());
        return Math.round(unshiftX / this.zoomScale());
    };

    Game_Screen.prototype.disConvertPositionY = function(y) {
        const unshiftY = y - this.zoomY() * (1 - this.zoomScale());
        return Math.round(unshiftY / this.zoomScale());
    };

    Game_Troop.prototype.setupDynamicCommon      = Game_Map.prototype.setupDynamicCommon;
    Game_Troop.prototype.setupDynamicInterpreter = Game_Map.prototype.setupDynamicInterpreter;

    const _Game_Troop_setup    = Game_Troop.prototype.setup;
    Game_Troop.prototype.setup = function(troopId) {
        _Game_Troop_setup.apply(this, arguments);
        if (!this._dynamicEvents) {
            this._dynamicEvents = [];
        }
    };

    Game_Troop.prototype.updateDynamicEvents = function() {
        this._dynamicEvents.forEach(interpreter => interpreter.update());
    };

    if (!Scene_Battle.prototype.hasOwnProperty('updateDynamicEvents')) {
        const _Scene_Battle_updateBattleProcess    = Scene_Battle.prototype.updateBattleProcess;
        Scene_Battle.prototype.updateBattleProcess = function() {
            _Scene_Battle_updateBattleProcess.apply(this, arguments);
            this.updateDynamicEvents();
        };

        Scene_Battle.prototype.updateDynamicEvents = function() {
            $gameTroop.updateDynamicEvents();
        };
    }

    /**
     * Game_PictureEventMap
     * ピクチャイベントの登録状態を管理するマップです。
     */
    class Game_PictureEventMap {
        constructor() {
            this._map = {}
            this._preference = {};
        }

        append(pictureId, trigger, option) {
            this._map[this.generateKey(pictureId, trigger)] = option;
        }

        find(pictureId, trigger) {
            return this._map[this.generateKey(pictureId, trigger)];
        }

        remove(pictureId, trigger) {
            delete this._map[this.generateKey(pictureId, trigger)];
        }

        removeById(pictureId) {
            const regExp = new RegExp(`^${pictureId}\:`);
            Object.keys(this._map).forEach(key => {
                if (key.match(regExp)) {
                    delete this._map[key];
                }
            });
        }

        generateKey(pictureId, trigger) {
            return `${pictureId}:${trigger}`;
        }

        setPreference(pictureId, option) {
            this._preference[pictureId] = option;
        }

        getPreference(pictureId) {
            return this._preference[pictureId];
        }
    }
    window.Game_PictureEventMap = Game_PictureEventMap;

    //=============================================================================
    // Sprite_Picture
    //  ピクチャのタッチ状態からのコモンイベント呼び出し予約を追加定義します。
    //=============================================================================
    const _Sprite_Picture_initialize    = Sprite_Picture.prototype.initialize;
    Sprite_Picture.prototype.initialize = function(pictureId) {
        _Sprite_Picture_initialize.call(this, pictureId);
        this._touch = new PictureTouch(this, pictureId);
    };

    const _Sprite_update            = Sprite_Picture.prototype.update;
    Sprite_Picture.prototype.update = function() {
        _Sprite_update.apply(this, arguments);
        if (this.picture() && this._touch && !$gameSwitches.value(param.InvalidSwitchId)) {
            this._touch.update();
        }
    };

    const _Spriteset_Base_update = Spriteset_Base.prototype.update;
    Spriteset_Base.prototype.update = function() {
        _Spriteset_Base_update.apply(this, arguments);
        TouchInput.suppressIfNeed();
    };

    /**
     * PictureTouch
     * ピクチャのタッチ状態を管理します。
     */
    class PictureTouch {
        constructor(picture, id) {
            this._picture      = picture;
            this._pictureId    = id;
            this._handlers     = [];
            this._handlers[1]  = () => this.isTouchEvent(TouchInput.isTriggered);
            this._handlers[2]  = () => this.isTouchEvent(TouchInput.isCancelled);
            this._handlers[3]  = () => this.isTouchEvent(TouchInput.isLongPressed);
            this._handlers[4]  = () => this._onMouse;
            this._handlers[5]  = () => this._outMouse;
            this._handlers[6]  = () => this.isTouchEvent(TouchInput.isReleased);
            this._handlers[7]  = () => this.isTouchEvent(TouchInput.isRepeated);
            this._handlers[8]  = () => this.isTouchEvent(TouchInput.isPressed);
            this._handlers[9]  = () => this.isTouchEvent(TouchInput.isWheelTriggered);
            this._handlers[10] = () => this.isTouchEvent(TouchInput.isDoubleTriggered);
            this._handlers[11] = () => this.isTouchEvent(TouchInput.isHovered);
            this._handlers[12] = () => this.isTouchEvent(TouchInput.isMoved);
            this._handlers[13] = () => this._flick;
            this._onMouse      = false;
            this._outMouse     = false;
            this._wasOnMouse   = false;
            this._flick        = false;
            this._interpreter  = new Game_Interpreter();
        }

        update() {
            this.updateFlick();
            this.updatePictureTouch();
            this.updateMouseMove();
        }

        updatePictureTouch() {
            if (SceneManager.isNextScene(Scene_Battle)) {
                return;
            }
            this._handlers.forEach((handler, trigger) => {
                if (this.isValidTrigger(handler, trigger)) {
                    const eventData = this.findPictureEvent(this._pictureId, trigger);
                    this.fireTouchEvent(eventData, trigger);
                }
            });
        }

        updateMouseMove() {
            if (this.isOnPicturePos()) {
                if (!this._wasOnMouse) {
                    this._outMouse   = false;
                    this._onMouse    = true;
                    this._wasOnMouse = true;
                }
            } else if (this._wasOnMouse) {
                this._outMouse   = true;
                this._wasOnMouse = false;
                this._onMouse    = false;
            }
        }

        updateFlick() {
            this._flick = false;
            const data  = TouchInput.createFlickData();
            if (!data) {
                return;
            }
            if (data.distance >= param.FlickDistance && this.isOnPicturePos(data.start.x, data.start.y)) {
                this._flick = true;
                if (param.FlickTimeVariable) {
                    $gameVariables.setValue(param.FlickTimeVariable, data.time);
                }
                if (param.FlickDegreeVariable) {
                    $gameVariables.setValue(param.FlickDegreeVariable, data.degree);
                }
            }
        }

        isValidTrigger(handler, trigger) {
            const eventData = this.findPictureEvent(this._pictureId, trigger);
            return  eventData && !$gameSwitches.value(eventData.invalidSwitchId) &&
                handler && handler.call(this);
        }

        findPictureEvent(pictureId, trigger) {
            return $gameScreen.findPictureEvent(pictureId, trigger);
        }

        fireTouchEvent(eventData, trigger) {
            TouchInput.requestSuppress();
            if (trigger === 3) {
                TouchInput._pressedTime = -60;
            }
            if (trigger === 4) {
                this._onMouse = false;
            }
            if (trigger === 5) {
                this._outMouse = false;
            }
            this.applyTouchEvent(eventData);
        }

        applyTouchEvent(eventData) {
            if (eventData.switchId) {
                $gameSwitches.setValue(eventData.switchId, true);
            }
            if (eventData.variableId) {
                this._interpreter.operateVariable(eventData.variableId, eventData.operationType, eventData.operand);
            }
            if (eventData.script) {
                try {
                    eval(eventData.script);
                } catch (e) {
                    console.error('Error Script:' + eventData.script);
                    PluginManagerEx.throwError(e.message, script);
                }
            }
            if (eventData.buttonBind) {
                Input.bindKeyState(eventData.buttonBind);
            }
            if (eventData.commonEventId) {
                if ($gameParty.inBattle()) {
                    $gameTroop.setupDynamicCommon(eventData.commonEventId);
                } else {
                    $gameMap.setupDynamicCommon(eventData.commonEventId);
                }
            }
            if (param.PictureIdVariable > 0) {
                $gameVariables.setValue(param.PictureIdVariable, this._pictureId);
            }
        }

        isOnPicturePos(x = TouchInput.x, y = TouchInput.y) {
            const pic = this._picture;
            if (!pic.bitmap || !pic.bitmap.isReady() || pic.scale.x === 0 || pic.scale.y === 0) {
                return false;
            }
            if (this.isTouchPosInFrameWindow(x, y)) {
                return true;
            }
            const dx  = this.getTouchScreenX(x) - pic.x;
            const dy  = this.getTouchScreenY(y) - pic.y;
            const sin = Math.sin(-pic.rotation);
            const cos = Math.cos(-pic.rotation);
            const bx = Math.floor(dx * cos + dy * -sin) / pic.scale.x + pic.anchor.x * pic.width;
            const by = Math.floor(dx * sin + dy * cos) / pic.scale.y + pic.anchor.y * pic.height;
            const preference = $gameScreen.getPicturePreference(this._pictureId);
            if (pic._apngSprite || preference?.includeOpacityZero) {
                return bx >= 0 && by >= 0 && bx <= pic.bitmap.width && by <= pic.bitmap.height;
            }
            return pic.bitmap.getAlphaPixel(bx, by) !== 0;
        }

        // for DTextPicture.js
        isTouchPosInFrameWindow(x, y) {
            if (!this._picture._frameWindow) {
                return false;
            }
            const frame = this._picture._frameWindow;
            const sx    = this.getTouchScreenX(x);
            const sy    = this.getTouchScreenY(y);
            return frame.x <= sx && frame.x + frame.width >= sx &&
                frame.y <= sy && frame.y + frame.height >= sy;
        }

        isTouchEvent(triggerFunc) {
            return triggerFunc.call(TouchInput) && this.isOnPicturePos();
        }

        getTouchScreenX(x) {
            return $gameScreen.disConvertPositionX(x);
        }

        getTouchScreenY(y) {
            return $gameScreen.disConvertPositionY(y);
        }
    }

    //=============================================================================
    // Input
    //  ピクチャクリックをキー入力に紐付けます。
    //=============================================================================
    Input._bindKeyStateFrames = new Map();
    Input.bindKeyState        = function(name) {
        this._currentState[name] = true;
        this._bindKeyStateFrames.set(name, 5);
    };

    const _Input_update = Input.update;
    Input.update        = function() {
        _Input_update.apply(this, arguments);
        this._updateBindKeyState();
    };

    Input._updateBindKeyState = function() {
        this._bindKeyStateFrames.forEach(function(frame, keyName) {
            frame--;
            if (frame === 0 || !this._currentState[keyName]) {
                this._currentState[keyName] = false;
                this._bindKeyStateFrames.delete(keyName);
            } else {
                this._bindKeyStateFrames.set(keyName, frame);
            }
        }, this);
    };

    //=============================================================================
    // TouchInput
    //  ホイールクリック、ダブルクリック等を実装
    //=============================================================================
    const _TouchInput__createNewState = TouchInput._createNewState;
    TouchInput._createNewState        = function() {
        const state           = _TouchInput__createNewState.apply(this, arguments);
        state.wheelTriggered  = false;
        state.doubleTriggered = false;
        return state;
    };

    TouchInput.requestSuppress = function() {
        this._requestSuppress = true;
    };

    TouchInput.suppressIfNeed = function() {
        if (this._requestSuppress) {
            this._currentState = this._createNewState();
            this._requestSuppress = false;
        }
    };

    TouchInput.isWheelTriggered = function() {
        return this._currentState.wheelTriggered;
    };

    TouchInput.isDoubleTriggered = function() {
        return this._currentState.doubleTriggered;
    };

    TouchInput.createFlickData = function() {
        if (!this.isPressed()) {
            return null;
        }
        const data    = {}
        const dx      = this._x - this._triggerX;
        const dy      = this._y - this._triggerY;
        data.distance = Math.round(Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)));
        data.time     = this._pressedTime;
        data.degree   = Math.round((Math.atan2(dy, -dx) + Math.PI) * 180 / Math.PI);
        data.start    = new Point(this._triggerX, this._triggerY);
        data.end      = new Point(this._x, this._y);
        return data;
    };

    const _TouchInput_onMiddleButtonDown = TouchInput._onMiddleButtonDown;
    TouchInput._onMiddleButtonDown       = function(event) {
        _TouchInput_onMiddleButtonDown.apply(this, arguments);
        const x = Graphics.pageToCanvasX(event.pageX);
        const y = Graphics.pageToCanvasY(event.pageY);
        if (Graphics.isInsideCanvas(x, y)) {
            this._newState.wheelTriggered = true;
        }
    };

    const _TouchInput_onTrigger = TouchInput._onTrigger;
    TouchInput._onTrigger       = function(x, y) {
        const prevDate = this._date;
        _TouchInput_onTrigger.apply(this, arguments);
        if (this._date - prevDate < 300) {
            this._newState.doubleTriggered = true;
        }
    };
})();

repo_name: agatutya/country

license: unknown