code:
//=============================================================================
// Olivia Engine - State Tooltip Display - for RPG Maker MV version 1.6.1
// Olivia_StateOlivia_StateTooltipDisplay.js
//=============================================================================
 /*:
 * @plugindesc <Olivia_StateTooltipDisplay> for RPG Maker MV version 1.6.1.
 * @author Fallen Angel Olivia
 *
 * @help
 * This is a RPG Maker MV plugin that adds a tooltip window in battle (and other
 * scenes) dedicated to showing information regarding states. If the player
 * hovers the mouse over the state icons, the window will appear and display
 * descriptions about each of the states affecting the battler.
 *
 *
 *
 * ------------
 * Instructions
 * ------------
 *
 * <Help Description>
 * insert a help description here
 * insert another line if you want to
 * </Help Description>
 * - Place this in the states that you want to have appear in the tooltip
 * window. Text codes can be used for the description. If no description is
 * used, then the state will not appear in the tooltip window.
 *
 *
 *
 * -----------------
 * Plugin Parameters
 * -----------------
 *
 * Window Scale: Scale the size of the contents of the tooltip window down by
 * this much. Use 1.0 for regular size.
 *
 * Window Skin: Window skin used for Tooltip window. This can be used to help
 * tell the player at first glance that the information displayed there is
 * different from the normal window.
 *
 * Window Skin Opacity: Opacity of the window skin. Sometimes you don't want
 * the opacity to be too transparent, as it will make the text on the tooltip
 * window harder to read.
 *
 * Text Help Format: If you don't want to use the default text format for the
 * tooltip window entries, change it up to your liking.
 *
 * Buff Format, Debuff Format: Since buffs and debuffs don't have database
 * entries, you will change how they appear in the tooltips here.
 *
 * Turn Duration Format: Change how you want the turn duration to appear in
 * your tooltip window.
 *
 * Enabled Windows: You can disable which windows tooltips will appear from.
 * Decide which ones work best for you and which ones don't. Only certain types
 * of windows are compatible the tooltip window.
 *
 * 1. Window_Help: This requires YEP_BattleEngineCore and YEP_BuffsStatesCore.
 * Window_Help used in battle that shows the battler's name.
 *
 * 2. Window_SkillStatus: Shown in the skill menu. Also used in a variety of
 * Yanfly's menu revisions.
 *
 * 3. Window_BattleSideStates: Used with Olivia's Side Battle Status UI.
 *
 * 4. Window_BattleStatus: Used for the battle status window.
 * Only compatible with the default and Yanfly's.
 *
 *
 *
 * -------------
 * Compatibility
 * -------------
 *
 * This plugin is compatible with the following plugins:
 *
 * - YEP_CoreEngine.js
 * - YEP_BattleEngineCore.js
 * - YEP_BuffsStatesCore.js
 * - YEP_BattleStatusWindow.js
 * - YEP_ItemCore.js
 * - YEP_EquipCore.js
 * - YEP_SkillCore.js
 * - Olivia_OctoBattle.js
 * - Olivia_SideBattleUI.js
 *
 * Place this plugin under those in the Plugin Manager list.
 *
 *
 *
 * -------------------
 * W A R N I N G ! ! !
 * -------------------
 *
 * This plugin is made for RPG Maker MV versions 1.6.1 and below. If you update
 * RPG Maker MV past that and this plugin breaks, I am NOT responsible for it.
 *
 *
 *
 * ------------
 * Terms of Use
 * ------------
 *
 * 1. These plugins may be used in free or commercial games.
 * 2. 'Fallen Angel Olivia' must be given credit in your games.
 * 3. You are allowed to edit the code.
 * 4. Do NOT change the filename, parameters, and information of the plugin.
 * 5. You are NOT allowed to redistribute these Plugins.
 * 6. You may NOT take code for your own released Plugins.
 *
 *
 *
 * -------
 * Credits
 * -------
 *
 * If you are using this plugin, credit the following people:
 *
 * - Fallen Angel Olivia
 *
 * @param
 * @param
 * @param ATTENTION!!!
 * @default READ THE HELP FILE
 * @param
 * @param
 *
 * @param Tooltip Window
 *
 * @param WindowScale
 * @text Window Scale
 * @parent Tooltip Window
 * @desc Scale the size of the contents of the tooltip window down by this much
 * @default 0.6
 *
 * @param WindowSkin
 * @text Window Skin
 * @parent Tooltip Window
 * @type file
 * @dir img/system/
 * @desc Window skin used for Tooltip window
 * @default Window
 *
 * @param SkinOpacity
 * @text Window Skin Opacity
 * @parent WindowSkin
 * @type number
 * @min 0
 * @max 255
 * @desc Opacity of the window skin
 * @default 240
 *
 * @param TextFormat
 * @text Text Help Format
 * @parent Tooltip Window
 * @type note
 * @desc Can use text codes. %1: Icon, %2: Name, %3: Description,
 * %4: Duration
 * @default "\\c[27]%1%2:\\c[0] %3 %4"
 *
 * @param BuffFormat
 * @text Buff Format
 * @parent TextFormat
 * @type note
 * @desc Can use text codes. %1: Icon, %2: Parameter, %3: Percentage
 * %4: Duration
 * @default "\\c[27]%1%2 Up:\\c[0] Increases unit's %2 to %3% %4"
 *
 * @param DebuffFormat
 * @text Debuff Format
 * @parent TextFormat
 * @type note
 * @desc Can use text codes. %1: Icon, %2: Parameter, %3: Percentage
 * %4: Duration
 * @default "\\c[27]%1%2 Down:\\c[0] Decreases unit's %2 to %3% %4"
 *
 * @param DurationFormat
 * @text Turn Duration Format
 * @parent TextFormat
 * @type note
 * @desc Can use text codes. %1: Duration
 * @default "\\c[27](Remaining Turns: %1)\\c[0]"
 *
 * @param
 *
 * @param Enabled Windows
 *
 * @param Window_Help
 * @parent Enabled Windows
 * @type boolean
 * @on Enabled
 * @off Disabled
 * @desc Window_Help used in battle that shows the battler's name.
 * Requires YEP_BattleEngineCore and YEP_BuffsStatesCore.
 * @default false
 *
 * @param Window_SkillStatus
 * @parent Enabled Windows
 * @type boolean
 * @on Enabled
 * @off Disabled
 * @desc Shown in the skill menu. Also used in a variety of Yanfly's menu revisions.
 * @default true
 *
 * @param Window_BattleSideStates
 * @parent Enabled Windows
 * @type boolean
 * @on Enabled
 * @off Disabled
 * @desc Used with Olivia's Side Battle Status UI
 * @default true
 *
 * @param Window_BattleStatus
 * @parent Enabled Windows
 * @type boolean
 * @on Enabled
 * @off Disabled
 * @desc Used for the battle status window.
 * Only compatible with the default and Yanfly's
 * @default true
 *
 */
//=============================================================================

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

var Olivia = Olivia || {};
Olivia.StateTooltipDisplay = Olivia.StateTooltipDisplay || {};

var parameters = $plugins.filter(function(p) { return p.description.contains('<Olivia_StateTooltipDisplay>') })[0].parameters;

Olivia.StateTooltipDisplay.Window = {
    scaleRate: Number(parameters['WindowScale']),
    textFmt: JSON.parse(parameters['TextFormat']),
      buffFmt: JSON.parse(parameters['BuffFormat']),
      debuffFmt: JSON.parse(parameters['DebuffFormat']),
      durationFmt: JSON.parse(parameters['DurationFormat']),
    windowSkin: String(parameters['WindowSkin']),
      windowSkinOpacity: Number(parameters['SkinOpacity']),
};

Olivia.StateTooltipDisplay.Enabled = {
    windowHelp: eval(String(parameters['Window_Help'])),
    windowSkillStatus: eval(String(parameters['Window_SkillStatus'])),
    windowBattleSideStates: eval(String(parameters['Window_BattleSideStates'])),
    windowBattleStatus: eval(String(parameters['Window_BattleStatus'])),
};

Olivia.SetupStateIconTooltipDescription = function(obj) {
    if (!obj.description) {
        obj.description = '';
        var notedata = obj.note.split(/[\r\n]+/);
        var evalMode = 'none';
        for (var i = 0; i < notedata.length; i++) {
            var line = notedata[i];
            var descLength = 0;
            if (line.match(/<(?:HELP|DESCRIPTION|HELP DESCRIPTION)>/i)) {
                evalMode = 'help description';
            } else if (line.match(/<\/(?:HELP|DESCRIPTION|HELP DESCRIPTION)>/i)) {
                evalMode = 'none';
            } else if (evalMode === 'help description') {
                if (obj.description.length > 0) obj.description += '\n';
                obj.description += line;
            }
        }
    }
};

//-----------------------------------------------------------------------------
/**
 * The static class that handles input data from the mouse and touchscreen.
 *
 * @class TouchInput
 */

Olivia.StateTooltipDisplay.___TouchInput_onMouseMove___ = TouchInput._onMouseMove;
TouchInput._onMouseMove = function(event) {
    Olivia.StateTooltipDisplay.___TouchInput_onMouseMove___.call(this, event);
    this._mouseOverX = Graphics.pageToCanvasX(event.pageX);
    this._mouseOverY = Graphics.pageToCanvasY(event.pageY);
};

//-----------------------------------------------------------------------------
// Scene_Base
//
// The Superclass of all scene within the game.

Olivia.StateTooltipDisplay.___Scene_Base_createWindowLayer___ = Scene_Base.prototype.createWindowLayer;
Scene_Base.prototype.createWindowLayer = function() {
    Olivia.StateTooltipDisplay.___Scene_Base_createWindowLayer___.call(this);
    this.createStateIconTooltipWindow();
};

Scene_Base.prototype.createStateIconTooltipWindow = function() {
    this._stateIconTooltipWindow = new Window_StateIconTooltip();
    this.addChild(this._stateIconTooltipWindow);
};

//-----------------------------------------------------------------------------
// Sprite_StateIcon
//
// The sprite for displaying state icons.

Olivia.StateTooltipDisplay.___Sprite_StateIcon_update___ = Sprite_StateIcon.prototype.update;
Sprite_StateIcon.prototype.update = function() {
    Olivia.StateTooltipDisplay.___Sprite_StateIcon_update___.call(this);
    if (!!this.tooltipWindow() && this.isMouseOverStates()) {
        this.updateStateIconTooltipWindow();
    }
};

Sprite_StateIcon.prototype.updateStateIconTooltipWindow = function() {
    this.tooltipWindow().setTargetHost(this, true);
};

Sprite_StateIcon.prototype.tooltipWindow = function() {
    return SceneManager._scene._stateIconTooltipWindow;
};

Sprite_StateIcon.prototype.isMouseOverStates = function() {
    var x = this.canvasToLocalX(TouchInput._mouseOverX);
    var y = this.canvasToLocalY(TouchInput._mouseOverY);
    x += this.anchor.x * this.width;
    y += this.anchor.y * this.height;
    return this.isFullyVisible() && x >= 0 && y >= 0 && x < this.width && y < this.height;
};

Sprite_StateIcon.prototype.canvasToLocalX = function(x) {
    var node = this;
    while (node) {
        x -= node.x;
        node = node.parent;
    }
    return x;
};

Sprite_StateIcon.prototype.canvasToLocalY = function(y) {
    var node = this;
    while (node) {
        y -= node.y;
        node = node.parent;
    }
    return y;
};

Sprite_StateIcon.prototype.isFullyVisible = function() {
	if(Karryn.hasTachieCutInOnScreen()) return false;
    var node = this;
    while (node) {
        if (!this.visible) {
            return false;
        } else if (this.opacity <= 0) {
            return false;
        } else {
            node = node.parent;
        }
    }
    return true;
};

//-----------------------------------------------------------------------------
// Sprite_StateOverlay
//
// The sprite for displaying an overlay image for a state.

Olivia.StateTooltipDisplay.___Sprite_StateOverlay_update___ = Sprite_StateOverlay.prototype.update;
Sprite_StateOverlay.prototype.update = function() {
    Olivia.StateTooltipDisplay.___Sprite_StateOverlay_update___.call(this);
    if (!!this.tooltipWindow() && this.isMouseOverStates()) {
        this.updateStateIconTooltipWindow();
    }
};

Sprite_StateOverlay.prototype.updateStateIconTooltipWindow = function() {
    this.tooltipWindow().setTargetHost(this, true);
};

Sprite_StateOverlay.prototype.tooltipWindow = function() {
    return SceneManager._scene._stateIconTooltipWindow;
};

Sprite_StateOverlay.prototype.isMouseOverStates = function() {
    var x = this.canvasToLocalX(TouchInput._mouseOverX);
    var y = this.canvasToLocalY(TouchInput._mouseOverY);
    x += this.anchor.x * this.width;
    y += this.anchor.y * this.height;
    return this.isFullyVisible() && x >= 0 && y >= 0 && x < this.width && y < this.height;
};

Sprite_StateOverlay.prototype.canvasToLocalX = function(x) {
    var node = this;
    while (node) {
        x -= node.x;
        node = node.parent;
    }
    return x;
};

Sprite_StateOverlay.prototype.canvasToLocalY = function(y) {
    var node = this;
    while (node) {
        y -= node.y;
        node = node.parent;
    }
    return y;
};

Sprite_StateOverlay.prototype.isFullyVisible = function() {
	if(Karryn.hasTachieCutInOnScreen()) return false;
    var node = this;
    while (node) {
        if (!this.visible) {
            return false;
        } else if (this.opacity <= 0) {
            return false;
        } else {
            node = node.parent;
        }
    }
    return true;
};

//-----------------------------------------------------------------------------
// Window_StateIconTooltip
//
// New window to display State icon description data

function Window_StateIconTooltip() {
    this.initialize.apply(this, arguments);
}

Window_StateIconTooltip.prototype = Object.create(Window_Base.prototype);
Window_StateIconTooltip.prototype.constructor = Window_StateIconTooltip;

Window_StateIconTooltip.prototype.initialize = function() {
    this._text = '';
    this._targetHost = undefined;
    this._battler = undefined;
    this._visibilityTimer = 0;
	this._lastPosX = -1;
	this._lastPosY = -1;
	this._mousePosX_states = -1;
	this._mousePosY_states = -1;
	this._mousePosX_desires = -1;
	this._mousePosY_desires = -1;
	this._mousePosX_passives = -1;
	this._mousePosY_passives = -1;
    Window_Base.prototype.initialize.call(this, 0, 0, Graphics.boxWidth, Graphics.boxHeight);
};

Window_StateIconTooltip.prototype.loadWindowskin = function() {
    this.windowskin = ImageManager.loadSystem(Olivia.StateTooltipDisplay.Window.windowSkin);
};

Window_StateIconTooltip.prototype.updateTone = function() {
};

Window_StateIconTooltip.prototype.scaleRate = function() {
    return Olivia.StateTooltipDisplay.Window.scaleRate;
};

Window_StateIconTooltip.prototype.lineHeight = function() {
	return REM_OLIVIA_TOOLTIP_TEXT_LINEHEIGHT;
    //return Math.round(Window_Base.prototype.lineHeight.call(this) * this.scaleRate());
};

Window_StateIconTooltip.prototype.standardFontSize = function() {
    return Math.round(Window_Base.prototype.standardFontSize.call(this) * this.scaleRate());
};

Window_StateIconTooltip.prototype.standardPadding = function() {
    return Math.round(Window_Base.prototype.standardPadding.call(this) * this.scaleRate());
};

Window_StateIconTooltip.prototype.textPadding = function() {
    return Math.round(Window_Base.prototype.textPadding.call(this) * this.scaleRate());
};

Window_StateIconTooltip.prototype.standardBackOpacity = function() {
    return Olivia.StateTooltipDisplay.Window.windowSkinOpacity;
};

Window_StateIconTooltip.prototype.standardBackOpacity = function() {
    return Olivia.StateTooltipDisplay.Window.windowSkinOpacity;
};

Window_StateIconTooltip.prototype.processDrawIcon = function(iconIndex, textState) {
    this.drawIcon(iconIndex, textState.x + 2, textState.y + 2);
    textState.x += Math.round(Window_Base._iconWidth * this.scaleRate()) + 4;
};

Window_StateIconTooltip.prototype.processDrawLanguageIcon = function(iconIndex, textState) {
    this.drawLanguageIcon(iconIndex, textState.x + 2, textState.y + 2);
    textState.x += Math.round(Window_Base._iconWidth * this.scaleRate()) + 4;
};

Window_StateIconTooltip.prototype.makeFontBigger = function() {
    this.contents.fontSize += Math.ceil(12 * this.scaleRate());
};

Window_StateIconTooltip.prototype.makeFontSmaller = function() {
    this.contents.fontSize -= Math.ceil(12 * this.scaleRate());
};

Window_StateIconTooltip.prototype.drawIcon = function(iconIndex, x, y) {
    var bitmap = ImageManager.loadSystem('IconSet');
    var pw = Window_Base._iconWidth;
    var ph = Window_Base._iconHeight;
    var sx = iconIndex % 16 * pw;
    var sy = Math.floor(iconIndex / 16) * ph;
    var rate = this.scaleRate();
    this.contents.blt(bitmap, sx, sy, pw, ph, x, y, Math.round(pw * rate), Math.round(ph * rate));
};

Window_StateIconTooltip.prototype.update = function() {
    Window_Base.prototype.update.call(this);
    this.updateVisibility();
    this.updateCoordinates();
};

Window_StateIconTooltip.prototype.updateVisibility = function() {
    this.visible = this._visibilityTimer > 0;
    this._visibilityTimer--;
};

Window_StateIconTooltip.prototype.updateCoordinates = function() {
    if (this.visible && !!this._targetHost) {
        this.x = TouchInput._mouseOverX;
        if (this.x + this.width >= Graphics.boxWidth) {
            this.x = Graphics.boxWidth - this.width;
        }
        this.y = TouchInput._mouseOverY;
        if (this.y + this.height >= Graphics.boxHeight) {
            this.y = Graphics.boxHeight - this.height;
        }
    }
};

Window_StateIconTooltip.prototype.setTargetHost = function(target, dontCallUpdateNewData) {
    if (this._targetHost !== target && this._visibilityTimer !== 0) {
        this._targetHost = target;
        if(!dontCallUpdateNewData) this.updateNewData();
    }
    this._visibilityTimer = 1;
};

Window_StateIconTooltip.prototype.setXYPos_states = function(x, y) {
    this._mousePosX_states = x;
	this._mousePosY_states = y;
	this._mousePosX_desires = -1;
	this._mousePosY_desires = -1;
	this._mousePosX_passives = -1;
	this._mousePosY_passives = -1;
	this.updateNewData();
};
Window_StateIconTooltip.prototype.setXYPos_desires = function(x, y) {
    this._mousePosX_states = -1;
	this._mousePosY_states = -1;
	this._mousePosX_desires = x;
	this._mousePosY_desires = y;
	this._mousePosX_passives = -1;
	this._mousePosY_passives = -1;
	this.updateNewData();
};
Window_StateIconTooltip.prototype.setXYPos_passives = function(x, y) {
    this._mousePosX_states = -1;
	this._mousePosY_states = -1;
	this._mousePosX_desires = -1;
	this._mousePosY_desires = -1;
	this._mousePosX_passives = x;
	this._mousePosY_passives = y;
	this.updateNewData();
};

Window_StateIconTooltip.prototype.updateNewData = function() {
    this.setupWindow();
    this.setupDimensions();
    this.setupChildPosition();
    this.refresh();
};

Window_StateIconTooltip.prototype.setupWindow = function() {
    this.setupText();
};

Window_StateIconTooltip.prototype.setupText = function() {
    this._text = '';
    if (!!this._targetHost) {
        if (!!this._targetHost._battler) {
            this._battler = this._targetHost._battler;
        }
        if (!!this._battler) {
			this._text = '';
            this.setupStateText();
            //this.setupBuffText();
			this.setupDesireText();
			this.setupPassiveText();

			if(this._text == '') this._text = 'test';
        }
    }
};

Window_StateIconTooltip.prototype.setupBuffText = function() {
    var buffFmt = Olivia.StateTooltipDisplay.Window.buffFmt;
    var debuffFmt = Olivia.StateTooltipDisplay.Window.debuffFmt;
    var durationFmt = Olivia.StateTooltipDisplay.Window.durationFmt;
    for (var i = 0; i < 8; i++) {
        if (this._battler.isBuffAffected(i)) {
            var fmt = buffFmt;
        } else if (this._battler.isDebuffAffected(i)) {
            var fmt = debuffFmt;
        } else {
            continue;
        }
        var iconIndex = this._battler.buffIconIndex(this._battler._buffs[i], i);
        var icon = '\\i[' + iconIndex + ']';
        var name = TextManager.param(i);
        var percentage = Math.floor(this._battler.paramBuffRate(i) * 100);
        var duration = this._battler._buffTurns[i] || 0;
        var durText = durationFmt.format(duration);
        if (duration <= 0) durText = '';
        var text = fmt.format(icon, name, percentage, durText);
        this._text += text + '\n';
    }
};

Window_StateIconTooltip.prototype.setupStateText = function() {
	if(this._mousePosX_states < 0 || this._mousePosY_states < 0) return;

    var states = [];
	for(let i = 0; i < this._battler.states().length; i++) {
		if(this._battler.states()[i].iconIndex > 0) states.push(this._battler.states()[i]);
	}

    //var fmt = Olivia.StateTooltipDisplay.Window.textFmt;
	let fmt = "\\c[0]%1\n%2"
    let durationFmt = TextManager.StateTooltipsRemainingTurnsPlural;
	let statePos = 0;

	while(statePos < states.length) {
		if(this._battler.isActor()) {
			if(this._mousePosX_states >= statePos * (Window_Base._iconWidth + 4) && this._mousePosX_states <= (statePos + 1) * (Window_Base._iconWidth + 4)) {
				break;
			}
			else statePos++;
		}
		else if(this._battler.isEnemy()) {
			if(this._mousePosX_states >= statePos * (DreamX.Param.BSIIconWidth + DreamX.Param.BSISpaceX) && this._mousePosX_states <= (statePos + 1) * (DreamX.Param.BSIIconWidth + DreamX.Param.BSISpaceX)) {
				break;
			}
			else statePos++;
		}
	}

	if(statePos < states.length) {
		let state = states[statePos];
		Olivia.SetupStateIconTooltipDescription(state);

		if (this.meetStateTooltipRequirements(state)) {
			let icon = '\\i[' + state.iconIndex + ']';
			if(state.hasLanguageIcon) icon = '\\RLI[' + state.languageIconIndex + ']';
			let name = state.name;
			//let description = state.description;
			let description = TextManager.stateTooltipText(this._battler, state.id);
			let duration = this._battler._stateTurns[state.id] || 0;
			let durText = durationFmt.format(duration);
			if(state.autoRemovalTiming === 0 || duration <= 0 || !state.showTurns) durText = '';
			else if(duration === 1) durText = TextManager.StateTooltipsRemainingTurnsSingular;
			//let text = fmt.format(icon, name, description, durText);
			let text = fmt.format(description, durText);
			this._text += text + '\n';
		}
	}

	/*
    for (var i = 0; i < states.length; i++) {
        var state = states[i];
        Olivia.SetupStateIconTooltipDescription(state);
        if (this.meetStateTooltipRequirements(state)) {
            var icon = '\\i[' + state.iconIndex + ']';
            var name = state.name;
            var description = state.description;
            var duration = this._battler._stateTurns[state.id] || 0;
            var durText = durationFmt.format(duration);
            if (duration <= 0) durText = '';
            var text = fmt.format(icon, name, description, durText);
            this._text += text + '\n';
        }
    }*/
};

Window_StateIconTooltip.prototype.setupDesireText = function() {
	if(this._mousePosX_desires < 0 || this._mousePosY_desires < 0) return;
	if(this._text === '' && this._battler.isActor()) {
		if(this._mousePosX_desires <= REM_BHD_MOUTH_METER_X) {
			this._text += this._battler._cacheCockDesireTooltip;
		}
		else if(this._mousePosX_desires <= REM_BHD_BOOBS_METER_X) {
			this._text += this._battler._cacheMouthDesireTooltip;
		}
		else if(this._mousePosX_desires <= REM_BHD_PUSSY_METER_X) {
			this._text += this._battler._cacheBoobsDesireTooltip;
		}
		else if(this._mousePosX_desires <= REM_BHD_BUTT_METER_X) {
			this._text += this._battler._cachePussyDesireTooltip;
		}
		else {
			this._text += this._battler._cacheButtDesireTooltip;
		}
	}
};

Window_StateIconTooltip.prototype.setupPassiveText = function() {
	if(this._mousePosX_passives < 0 || this._mousePosY_passives < 0) return;
	if(this._text === '' && this._battler.isActor()) {
		let lineheight = REM_OLIVIA_TOOLTIP_PASSIVE_LINEHEIGHT;

		let passivePos = 0;
		let newPassivesUnlockedArray = this._battler._newPassivesUnlocked;

		while(passivePos < Math.min(RESULTS_PASSIVES_MAX_LINES, newPassivesUnlockedArray.length)) {
			if(this._mousePosY_passives >= passivePos * lineheight && this._mousePosY_passives <= (passivePos + 1) * lineheight) {
				break;
			}
			else passivePos++;
		}

		if(passivePos < Math.min(RESULTS_PASSIVES_MAX_LINES, newPassivesUnlockedArray.length)) {
			let text = TextManager.skillDesc(newPassivesUnlockedArray[passivePos]);
			text = TextManager.convertEscapeCharacters(text);
			text = TextManager.convertExtraEscapeCharacters(text);
			text += '\n';
			this._text += text;
		}

	}
};

Window_StateIconTooltip.prototype.setupDimensions = function() {
    if (this._text === '') {
        this.width = 0;
        this.height = 0;
    } else {
        var lines = this._text.split(/[\r\n]+/);
        if (lines.length > 0) {
            var width = 0;
            for (var i = 0; i < lines.length; i++) {
                var line = lines[i];
                var lineWidth = Window_ChoiceList.prototype.textWidthEx.call(this, line);
                width = Math.max(lineWidth, width);
            }
            this.width = this.standardPadding() * 2 + this.textPadding() * 2 + width;
            //this.height = this.standardPadding() * 2 + (lines.length - 1) * this.lineHeight();
			this.height = this.standardPadding() + (lines.length) * this.lineHeight();
        } else {
            this.width = 0;
            this.height = 0;
        }
    }
};

Window_StateIconTooltip.prototype.setupChildPosition = function() {
    if (this.parent) {
        var arr = this.parent.children;
        arr.push(arr.splice(arr.indexOf(this), 1)[0]);
    }
};

Window_StateIconTooltip.prototype.meetStateTooltipRequirements = function(state) {
    if(!state) {
        return false;
	}
		/*
    else if (state.description === '') {
        return false;
		*/
	else if(state.iconIndex <= 0) {
        return false;
    }
	else {
        return true;
    }
};

Window_StateIconTooltip.prototype.refresh = function() {
	if(this._lastPosX !== this.x || this._lastPosY !== this.y) {
		this.createContents();
		this.contents.clear();
		if (this._text !== '') {
			var lines = this._text.split(/[\r\n]+/);
			var x = this.textPadding();
			var y = REM_OLIVIA_TOOLTIP_TEXT_STARTING_Y;
			for (var i = 0; i < lines.length; i++) {
				var line = lines[i];
				this.drawTextEx(line, x, y, true);
				y += this.lineHeight();
			}
		}
		this._lastPosX = this.x;
		this._lastPosY = this.y;
	}
};

//-----------------------------------------------------------------------------
// Window_Base
//
// The superclass of all windows within the game.

Window_Base.prototype.tooltipWindow = function() {
    return SceneManager._scene._stateIconTooltipWindow;
};

Window_Base.prototype.updateStateIconTooltipWindow = function() {
    this.tooltipWindow().setTargetHost(this, true);
    if (this._battler !== this.tooltipWindow()._battler) {
        this.tooltipWindow().updateNewData();
    }
};

Window_Base.prototype.isMouseOverStates = function() {
    var x = this.canvasToLocalX(TouchInput._mouseOverX);
    var y = this.canvasToLocalY(TouchInput._mouseOverY);
    return this.isFullyVisible() && x >= 0 && y >= 0 && x < this.width && y < this.height;
};

Window_Base.prototype.canvasToLocalX = function(x) {
    var node = this;
    while (node) {
        x -= node.x;
        node = node.parent;
    }
    return x;
};

Window_Base.prototype.canvasToLocalY = function(y) {
    var node = this;
    while (node) {
        y -= node.y;
        node = node.parent;
    }
    return y;
};

Window_Base.prototype.isFullyVisible = function() {
	if(Karryn.hasTachieCutInOnScreen()) return false;
    var node = this;
    while (node) {
        if (!this.visible) {
            return false;
        } else if (this.contentsOpacity <= 0) {
            return false;
        } else if (this.isClosed()) {
            return false;
        } else {
            node = node.parent;
        }
    }
    return true;
};

Window_Base.prototype.determineStateTooltipBattler = function() {
    this._battler = undefined;
};

//-----------------------------------------------------------------------------
// Window_Help
//
// The window for displaying the description of the selected item.
// Compatibility update with YEP_BattleEngineCore and YEP_BuffsStatesCore.

if (Imported.YEP_BattleEngineCore && Imported.YEP_BuffsStatesCore && Olivia.StateTooltipDisplay.Enabled.windowHelp) {

Olivia.StateTooltipDisplay.___Window_Help_clear___ = Window_Help.prototype.clear;
Window_Help.prototype.clear = function() {
    Olivia.StateTooltipDisplay.___Window_Help_clear___.call(this);
    this._battler = undefined;
};

Olivia.StateTooltipDisplay.___Window_Help_setBattler___ = Window_Help.prototype.setBattler;
Window_Help.prototype.setBattler = function(battler) {
    Olivia.StateTooltipDisplay.___Window_Help_setBattler___.call(this, battler);
    this._battler = battler;
};

Window_Help.prototype.update = function() {
    Window_Base.prototype.update.call(this);
    if (!!this._battler && !!this.tooltipWindow() && this.isMouseOverStates()) {
        this.updateStateIconTooltipWindow();
    }
};

} // Imported.YEP_BattleEngineCore && Imported.YEP_BuffsStatesCore && Olivia.StateTooltipDisplay.Enabled.windowHelp

//-----------------------------------------------------------------------------
// Window_SkillStatus
//
// The window for displaying the skill user's status on the skill screen.

if (Olivia.StateTooltipDisplay.Enabled.windowSkillStatus) {

Olivia.StateTooltipDisplay.___Window_SkillStatus_setActor___ = Window_SkillStatus.prototype.setActor;
Window_SkillStatus.prototype.setActor = function(actor) {
    Olivia.StateTooltipDisplay.___Window_SkillStatus_setActor___.call(this, actor);
    this._battler = this._actor;
};

Olivia.StateTooltipDisplay.___Window_SkillStatus_update___ = Window_SkillStatus.prototype.update;
Window_SkillStatus.prototype.update = function() {
    Olivia.StateTooltipDisplay.___Window_SkillStatus_update___.call(this);
    if (!!this._battler && !!this.tooltipWindow() && this.isMouseOverStates()) {
        this.updateStateIconTooltipWindow();
    }
};

} // Olivia.StateTooltipDisplay.Enabled.windowSkillStatus

//-----------------------------------------------------------------------------
// Window_BattleSideStates
//
// Draws the actor's states
// Compatibility update with Olivia's Side Battle UI
/*
if (Olivia.OctoBattle.SideBattleUI && Olivia.OctoBattle.SideBattleUI.Enabled && Olivia.StateTooltipDisplay.Enabled.windowBattleSideStates) {

Olivia.StateTooltipDisplay.___Window_BattleSideBase_setNewActor___ = Window_BattleSideBase.prototype.refresh;
Window_BattleSideBase.prototype.setNewActor = function() {
    Olivia.StateTooltipDisplay.___Window_BattleSideBase_setNewActor___.call(this);
    this._battler = this._actor;
};

Olivia.StateTooltipDisplay.___Window_BattleSideBase_refresh___ = Window_BattleSideBase.prototype.refresh;
Window_BattleSideBase.prototype.refresh = function() {
    Olivia.StateTooltipDisplay.___Window_BattleSideBase_refresh___.call(this);
    this._battler = this._actor;
};

Olivia.StateTooltipDisplay.___Window_BattleSideStates_update___ = Window_BattleSideStates.prototype.update;
Window_BattleSideStates.prototype.update = function() {
    Olivia.StateTooltipDisplay.___Window_BattleSideStates_update___.call(this);
    if (!!this._battler && !!this.tooltipWindow() && this.isMouseOverStates()) {
        this.updateStateIconTooltipWindow();
    }
};

} // Olivia.OctoBattle.SideBattleUI && Olivia.OctoBattle.SideBattleUI.Enabled && Olivia.StateTooltipDisplay.Enabled.windowBattleSideStates
*/

//-----------------------------------------------------------------------------
// Window_BattleStatus
//
// The window for displaying the status of party members on the battle screen.
// Compatibility Update

if (Olivia.StateTooltipDisplay.Enabled) {

Olivia.StateTooltipDisplay.___Window_BattleStatus_update___ = Window_BattleStatus.prototype.update;
Window_BattleStatus.prototype.update = function() {
    Olivia.StateTooltipDisplay.___Window_BattleStatus_update___.call(this);
    if (!!this.tooltipWindow() && this.isMouseOverStates()) {
        this.determineStateTooltipBattler();
        if (!!this._battler) {
            this.updateStateIconTooltipWindow();
        }
    }
};

Window_BattleStatus.prototype.determineStateTooltipBattler = function() {
    var x = this.canvasToLocalX(TouchInput._mouseOverX);
    var y = this.canvasToLocalY(TouchInput._mouseOverY);
    if (x <= this.standardPadding() || x >= this.width - this.standardPadding()) {
      this._battler = undefined;
    } else if (y <= this.standardPadding() || y >= this.height - this.standardPadding()) {
      this._battler = undefined;
    } else if (Imported.YEP_BattleStatusWindow) {
      var rectWidth = this.contentsWidth() / this.maxCols();
      var index = Math.floor((x - this.standardPadding()) / rectWidth);
      this._battler = $gameParty.members()[index];
    } else { // vanilla
      var rectHeight = this.basicAreaRect(index).height;
      var index = this.topIndex() + Math.floor((y - this.standardPadding()) / rectHeight);
      this._battler = $gameParty.members()[index];
    }
};

} // Olivia.StateTooltipDisplay.Enabled


code:
/*=============================================================================
 * Orange - Greenworks
 * By Hudell - www.hudell.com
 * OrangeGreenworks.js
 * Version: 1.2
 * Free for commercial and non commercial use.
 *=============================================================================*/
/*:
 * @plugindesc Steamworks Integration <OrangeGreenworks>
 * @author Hudell
 *
 * @help
 * ============================================================================
 * Hudell's Plugins
 * ============================================================================
 *
 * Check out my website to learn how to use this plugin:
 * http://hudell.com/blog/orangegreenworks/
 *
 *=============================================================================*/
var Imported = Imported || {};
var Hudell = Hudell || {};
Hudell.OrangeGreenworks = Hudell.OrangeGreenworks || {};

(function($) {
  "use strict";

  $.getScreenName = function() {
    return 'Play Test';
  };

  $.getUILanguage = function() {
    return 'english';
  };

  $.getGameLanguage = function() {
    return 'english';
  };

  $.activateAchievement = function(achievementName) {
    console.log('Activate achievement ', achievementName);
  };

  $.getAchievement = function(achievementName) {
    return false;
  };

  $.clearAchievement = function(achievementName) {
    console.log('Clear achievement ', achievementName);
  };

  $.getNumberOfAchievements = function() {
    return 0;
  };

  $.isSteamRunning = function() {
    return false;
  };

  $.activateGameOverlay = function(option) {
  };

  $.isGameOverlayEnabled = function() {
    return false;
  };

  $.activateGameOverlayToWebPage = function(url) {
    console.log('Open URL');
  };

  $.getDLCCount = function() {
    return 0;
  };

  $.isDLCInstalled = function(dlcAppId) {
    return false;
  };

  $.installDLC = function(dlcAppId) {
  };

  $.uninstallDLC = function(dlcAppId) {
  };

  $.getStatInt = function(name) {
    return 0;
  };

  $.getStatFloat = function(name) {
    return 0;
  };

  $.setStat = function(name, value) {
    console.log('Change Stat', name, value);
    return false;
  };

  $.storeStats = function() {
    console.log('Store Stats');
    return false;
  };

  $.isSubscribedApp = function(appId) {
    return false;
  };

  if (Utils.isNwjs()) {
    $.initialized = false;

    try {
      $.greenworks = require('./greenworks');
    }
    catch(e) {
      $.greenworks = false;
      console.log('Greenworks failed to load. Make sure you copied all files from the Steamworks SDK to the right folders;');
      console.log('http://hudell.com/blog/orange-greenworks');
      //console.error(e);
    }

    if (!!$.greenworks) {
      $.initialized = $.greenworks.initAPI();

      if (!$.initialized) {
        console.log('Greenworks failed to initialize.');
        return;
      }

      $.steamId = $.greenworks.getSteamId();
      console.log('Steam User: ', $.steamId.screenName);

      $.getScreenName = function() {
        return $.steamId.screenName;
      };

      $.getUILanguage = function() {
        return $.greenworks.getCurrentUILanguage();
      };

      $.getGameLanguage = function() {
        return $.greenworks.getCurrentGameLanguage();
      };

      $.isSteamRunning = function() {
        return $.greenworks.isSteamRunning();
      };

      $._storeStatsSuccess = function(){
        console.log('Stored Stats Successfully', arguments);
      };

      $._storeStatsError = function(){
        console.log('Failed to Store Stats', arguments);
      };

      $._achievementSuccess = function(){
        console.log('Achievement activated', arguments);
      };

      $._achievementError = function(){
        console.log('Achievement activation error', arguments);
      };

      $._clearAchievementSuccess = function(){
        console.log('Successfully Cleared Achievement', arguments);
      };

      $._clearAchievementError = function(){
        console.log('Failed to Clear Achievement', arguments);
      };

      $._getAchievementSuccess = function(){
      };

      $._getAchievementError = function(){
        console.log('Failed to check Achievement', arguments);
      };

      $.activateAchievement = function(achievementName) {
        if (!achievementName) {
          console.log('Achievement name not provided.');
          return;
        }

        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return;
        }

        $.greenworks.activateAchievement(achievementName, $._achievementSuccess, $._achievementError);
      };

      $.getAchievement = function(achievementName) {
        if (!achievementName) {
          console.log('Achievement name not provided.');
          return false;
        }

        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        return $.greenworks.getAchievement(achievementName, $._getAchievementSuccess, $._getAchievementError);
      };

      $.clearAchievement = function(achievementName) {
        if (!achievementName) {
          console.log('Achievement name not provided.');
          return false;
        }

        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        $.greenworks.clearAchievement(achievementName, $._clearAchievementSuccess, $._clearAchievementError);
      };

      $.getNumberOfAchievements = function() {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        return $.greenworks.getNumberOfAchievements();
      };

      $.activateGameOverlay = function(option) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        $.greenworks.activateGameOverlay(option);
      };

      $.isGameOverlayEnabled = function() {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        return $.greenworks.isGameOverlayEnabled();
      };

      $.activateGameOverlayToWebPage = function(url) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        $.greenworks.activateGameOverlayToWebPage(url);
      };

      $.isSubscribedApp = function(appId) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        return $.greenworks.isSubscribedApp(appId);
      };

      $.getDLCCount = function() {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return 0;
        }

        return $.greenworks.getDLCCount();
      };

      $.isDLCInstalled = function(dlcAppId) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        return $.greenworks.isDLCInstalled(dlcAppId);
      };

      $.installDLC = function(dlcAppId) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        $.greenworks.installDLC(dlcAppId);
      };

      $.uninstallDLC = function(dlcAppId) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        $.greenworks.uninstallDLC(dlcAppId);
      };

      $.getStatInt = function(name) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return 0;
        }

        return $.greenworks.getStatInt(name);
      };

      $.getStatFloat = function(name) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return 0;
        }

        return $.greenworks.getStatFloat(name);
      };

      $.setStat = function(name, value) {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        return $.greenworks.setStat(name, value);
      };

      $.storeStats = function() {
        if (!$.isSteamRunning()) {
          console.log('Steam isn\'t running');
          return false;
        }

        return $.greenworks.setStat($._storeStatsSuccess, $._storeStatsError);
      };

      $.getFriendCount = function() {
        return $.greenworks.getFriendCount($.greenworks.FriendFlags.Immediate);
      };

      $.isCloudEnabled = function() {
        return $.greenworks.isCloudEnabled();
      };

      $.isCloudEnabledForUser = function() {
        return $.greenworks.isCloudEnabledForUser();
      };
    }
  }
})(Hudell.OrangeGreenworks);

OrangeGreenworks = Hudell.OrangeGreenworks;
Imported.OrangeGreenworks = 1.2;

repo_name: voidljb/karryn

license: unknown


code:
//=============================================================================
// PD_FootStepSound.js
//=============================================================================

/*:
 * @plugindesc Add to sound of player character footsteps.
 * @author Shio_inu
 *
 * @help 面倒なので誰か代わりに翻訳して。
 * last update : 29th Dec 2015 v1.0
 *
 * @param File Name
 * @desc ファイル名です。「ここに入力したファイル名+地形タグ」のファイルが再生されます。
 * @default foot_
 */

/*:ja
 * @plugindesc プレイヤーの移動に合わせて足音を再生するプラグインです。
 * @author しおいぬ
 *
 * @help 地形タグによって再生される足音が変化します。
 * last update : 2015/12/29 v1.0
 *
 * @param File Name
 * @desc ファイル名です。「ここに入力したファイル名+地形タグ」のファイルが再生されます。
 * @default foot_
 */
(function(){

    var parameters = PluginManager.parameters('PD_FootStepSound');
    var fileName = String(parameters['File Name'] || "foot_");

    var updatePlayer = Game_Player.prototype.update;
    Game_Player.prototype.update = function(sceneActive) {
        updatePlayer.call(this, sceneActive);

        if(!this._prevpattern){
            this._prevpattern = this.pattern();
        }

        if(this._prevpattern != this.pattern() && !this.isInVehicle()){
            var id = $gameMap.terrainTag(this._x, this._y);
			if($gameSwitches.value(SWITCH_FOOTSTEPS_SE_OFF_ID) || $gameActors.actor(ACTOR_KARRYN_ID).characterName() === 'C_Extra1') {

			}
            else if(this.pattern() != 1) {
                var seObj = {"name":fileName + id,"volume":90,"pitch":100 + (10 * this.pattern()),"pan":0};
                AudioManager.playSe(seObj);
            }

        }

        this._prevpattern = this.pattern();
    };
})();


code:
//=============================================================================
// PictureCallCommon.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015 Triacontane
// This plugin is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.10.1 2017/05/27 動的文字列ピクチャプラグインのウィンドウフレームクリックをピクチャクリックに対応
// 1.9.3 2017/05/27 競合の可能性のある記述（Objectクラスへのプロパティ追加）をリファクタリング（by liplyさん）
// 1.9.2 2017/03/16 1.9.0で戦闘中にコモンイベント実行が正しく動作していなかった問題を修正
// 1.9.1 2017/03/16 透明色を考慮する場合、不透明度が0のピクチャは一切反応しなくなるように仕様変更
// 1.9.0 2017/03/13 戦闘中常にピクチャクリックイベントを実行できる機能を追加
// 1.8.2 2017/02/14 1.8.0の修正により、ピクチャクリック時に変数に値を格納する機能が無効化されていたのを修正
// 1.8.1 2017/02/07 端末依存の記述を削除
// 1.8.0 2017/02/03 ピクチャクリックを任意のボタンにバインドできる機能を追加
// 1.7.0 2017/02/02 マップのズームおよびシェイク中でも正確にピクチャをクリックできるようになりました。
//                  マウスポインタがピクチャ内にあるかどうかをスクリプトで判定できる機能を追加。
// 1.6.0 2016/12/29 ピクチャクリックでイベントが発生したらマップタッチを無効化するよう仕様修正
// 1.5.1 2016/11/20 1.5.0で混入した不要なコードを削除
// 1.5.0 2016/11/19 ピクチャクリック時にコモンイベントではなくスイッチをONにできる機能を追加
// 1.4.0 2016/08/20 ピクチャごとに透明色を考慮するかどうかを設定できる機能を追加
//                  プラグインを適用していないセーブデータをロードした場合に発生するエラーを修正
// 1.3.5 2016/04/20 リファクタリングによりピクチャの優先順位が逆転していたのをもとに戻した
// 1.3.4 2016/04/08 ピクチャが隣接する状態でマウスオーバーとマウスアウトが正しく機能しない場合がある問題を修正
// 1.3.3 2016/03/19 トリガー条件を満たした場合に以後のタッチ処理を抑制するパラメータを追加
// 1.3.2 2016/02/28 処理の負荷を少し軽減
// 1.3.1 2016/02/21 トリガーにマウスを押したまま移動を追加
// 1.3.0 2016/01/24 ピクチャをなでなでする機能を追加
//                  トリガーにマウスムーブを追加
//                  ピクチャが回転しているときに正しく位置を補足できるよう修正
// 1.2.1 2016/01/21 呼び出すコモンイベントの上限を100から1000（DB上の最大値）に修正
//                  競合対策（YEP_MessageCore.js）
// 1.2.0 2016/01/14 ホイールクリック、ダブルクリックなどトリガーを10種類に拡充
// 1.1.3 2016/01/02 競合対策（TDDP_BindPicturesToMap.js）
// 1.1.2 2015/12/20 長押しイベント発生時に1秒間のインターバルを設定するよう仕様変更
// 1.1.1 2015/12/10 ピクチャを消去後にマウスオーバーするとエラーになる現象を修正
// 1.1.0 2015/11/23 コモンイベントを呼び出した対象のピクチャ番号を特定する機能を追加
//                  設定で透明色を考慮する機能を追加
//                  トリガーとして「右クリック」や「長押し」を追加
// 1.0.0 2015/11/14 初版
// ----------------------------------------------------------------------------
// [Blog]   : http://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:ja
 * @plugindesc ピクチャのボタン化プラグイン
 * @author トリアコンタン
 *
 * @param 透明色を考慮
 * @desc クリックされた箇所が透明色だった場合は、クリックを無効にする。
 * @default ON
 *
 * @param ピクチャ番号の変数番号
 * @desc ピクチャクリック時にピクチャ番号を格納するゲーム変数の番号。
 * @default 0
 *
 * @param ポインタX座標の変数番号
 * @desc マウスカーソルもしくはタッチした位置のX座標を常に格納するゲーム変数の番号
 * @default 0
 *
 * @param ポインタY座標の変数番号
 * @desc マウスカーソルもしくはタッチした位置のY座標を常に格納するゲーム変数の番号
 * @default 0
 *
 * @param タッチ操作抑制
 * @desc トリガー条件を満たした際にタッチ情報をクリアします。(ON/OFF)
 * 他のタッチ操作と動作が重複する場合にONにします。
 * @default OFF
 *
 * @param 戦闘中常にコモン実行
 * @desc 戦闘中にピクチャをクリックしたとき、常にコモンイベントを実行します。(ON/OFF)
 * @default OFF
 *
 * @help ピクチャをクリックすると、指定したコモンイベントが
 * 呼び出される、もしくは任意のスイッチをONにするプラグインコマンドを提供します。
 * このプラグインを利用すれば、JavaScriptの知識がなくても
 * 誰でも簡単にクリックやタッチを主体にしたゲームを作れます。
 *
 * 戦闘中でも実行可能ですが、ツクールMVの仕様により限られたタイミングでしか
 * イベントは実行されません。パラメータ「戦闘中常にコモン実行」を有効にすると
 * 常にイベントが実行されるようになりますが、
 * 一部イベントコマンドは正しく動作しない制約があります。
 *
 * 注意！
 * 一度関連づけたピクチャとコモンイベントはピクチャを消去しても有効です。
 * ピクチャが存在しなければどこをクリックしても反応しませんが、
 * 同じ番号で再度、ピクチャの表示を行うと反応するようになります。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （引数の間は半角スペースで区切る）
 *
 *  ピクチャのボタン化 or
 *  P_CALL_CE [ピクチャ番号] [コモンイベントID] [トリガー] [透明色を考慮]:
 *      ピクチャの領域内でトリガー条件を満たした場合に呼び出されるコモンイベントを関連づけます。
 *  　　トリガーは以下の通りです。(省略すると 1 になります)
 *      1  : クリックした場合
 *      2  : 右クリックした場合
 *      3  : 長押しした場合
 *      4  : マウスをピクチャに重ねた場合
 *      5  : マウスをピクチャから放した場合
 *      6  : クリックを解放（リリース）した場合
 *      7  : クリックした場合（かつ長押しの際の繰り返しを考慮）
 *      8  : クリックしている間ずっと
 *      9  : ホイールクリックした場合（PCの場合のみ有効）
 *      10 : ダブルクリックした場合
 *      11 : マウスをピクチャ内で移動した場合
 *      12 : マウスを押しつつピクチャ内で移動した場合
 *
 *      透明色を考慮のパラメータ(ON/OFF)を指定するとピクチャごとに透明色を考慮するかを
 *      設定できます。何も設定しないとプラグインパラメータの設定が適用されます。(従来の仕様)
 *
 *  例：P_CALL_CE 1 3 7 ON
 *  　：ピクチャのボタン化 \v[1] \v[2] \v[3] OFF
 *
 *  ピクチャのスイッチ化 or
 *  P_CALL_SWITCH [ピクチャ番号] [スイッチID] [トリガー] [透明色を考慮]:
 *  　　ピクチャの領域内でトリガー条件を満たした場合に、任意のスイッチをONにします。
 *  　　トリガーの設定などは、ピクチャのボタン化と同一です。
 *
 *  ピクチャのキーバインド or
 *  P_CALL_KEY_BIND [ピクチャ番号] [ボタン名称] [トリガー] [透明色を考慮]:
 *  　　ピクチャの領域内でトリガー条件を満たした場合に、任意のボタンを押したことにします。
 *  　　ボタン名の設定は以下の通りです。(Windows基準)
 *  ok      : Enter,Z
 *  shift   : Shift
 *  control : Ctrl,Alt
 *  escape  : Esc,X
 *  left    : ←
 *  up      : ↑
 *  right   : →
 *  down    : ↓
 *
 *  ピクチャのボタン化解除 or
 *  P_CALL_CE_REMOVE [ピクチャ番号] :
 *      ピクチャとコモンイベントもしくはスイッチの関連づけを解除します。
 *      全てのトリガーが削除対象です。
 *
 *  例：P_CALL_CE_REMOVE 1
 *  　：ピクチャのボタン化解除 \v[1]
 *
 *  ピクチャのなでなで設定 or
 *  P_STROKE [ピクチャ番号] [変数番号]
 *  　　指定したピクチャの上でマウスやタッチを動かすと、
 *  　　速さに応じた値が指定した変数に値が加算されるようになります。
 *  　　この設定はピクチャを差し替えたり、一時的に非表示にしても有効です。
 *  　　10秒でだいたい1000くらいまで溜まります。
 *
 *  例：P_STROKE 1 2
 *  　：ピクチャのなでなで設定 \v[1] \v[2]
 *
 *  ピクチャのなでなで解除 or
 *  P_STROKE_REMOVE [ピクチャ番号]
 *  　　指定したピクチャのなでなで設定を解除します。
 *
 *  例：P_STROKE_REMOVE 1
 *  　：ピクチャのなでなで解除 \v[1]
 *
 *  ピクチャのポインタ化 or
 *  P_POINTER [ピクチャ番号]
 *  　　指定したピクチャがタッチ座標を自動で追従するようになります。
 *  　　タッチしていないと自動で非表示になります。
 *
 *  例：P_POINTER 1
 *  　：ピクチャのポインタ化 \v[1]
 *
 *  ピクチャのポインタ化解除 or
 *  P_POINTER_REMOVE [ピクチャ番号]
 *  　　指定したピクチャのポインタ化を解除します。
 *
 *  例：P_POINTER_REMOVE 1
 *  　：ピクチャのポインタ化解除 \v[1]
 *
 *  ・スクリプト（上級者向け）
 *  $gameScreen.isPointerInnerPicture([ID]);
 *
 *  指定した[ID]のピクチャ内にマウスポインタもしくはタッチ座標が存在する場合に
 *  trueを返します。このスクリプトは[P_CALL_CE]を使用していなくても有効です。
 *
 *  例：$gameScreen.isPointerInnerPicture(5);
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */
/*:
 * @plugindesc Clickable picture plugin
 * @author triacontane
 *
 * @param TransparentConsideration
 * @desc if click position is transparent, click is disabled.
 * @default ON
 *
 * @param GameVariablePictureNum
 * @desc Game variable number that stores the picture number when common event called.
 * @default 0
 *
 * @param GameVariableTouchX
 * @desc Game variable number that stores touch x position
 * @default 0
 *
 * @param GameVariableTouchY
 * @desc Game variable number that stores touch y position
 * @default 0
 *
 * @param SuppressTouch
 * @desc Suppress touch event for others(ON/OFF)
 * @default OFF
 *
 * @param AlwaysCommonInBattle
 * @desc Always execute common event in battle(ON/OFF)
 * @default OFF
 *
 * @help When clicked picture, call common event.
 *
 * Plugin Command
 *
 *  P_CALL_CE [Picture number] [Common event ID] [Trigger] [TransparentConsideration]:
 *      When picture was clicked, assign common event id.
 *  　　Trigger are As below(if omit, It is specified to 1)
 *      1  : Left click
 *      2  : Right click
 *      3  : Long click
 *      4  : Mouse over
 *      5  : Mouse out
 *      6  : Mouse release
 *      7  : Mouse repeat click
 *      8  : Mouse press
 *      9  : Wheel click
 *      10 : Double click
 *      11 : Mouse move
 *      12 : Mouse move and press
 *
 *  P_CALL_CE_REMOVE [Picture number] :
 *      break relation from picture to common event.
 *
 *  - Script
 *  $gameScreen.isPointerInnerPicture([ID]);
 *
 *  If mouse pointer inner the picture, return true.
 *
 *  ex：$gameScreen.isPointerInnerPicture(5);
 *
 *  This plugin is released under the MIT License.
 */
(function() {
    'use strict';
    var pluginName = 'PictureCallCommon';

    var getParamOther = function(paramNames) {
        if (!Array.isArray(paramNames)) paramNames = [paramNames];
        for (var i = 0; i < paramNames.length; i++) {
            var name = PluginManager.parameters(pluginName)[paramNames[i]];
            if (name) return name;
        }
        return null;
    };

    var getParamBoolean = function(paramNames) {
        var value = getParamOther(paramNames);
        return (value || '').toUpperCase() === 'ON';
    };

    var getParamNumber = function(paramNames, min, max) {
        var value = getParamOther(paramNames);
        if (arguments.length < 2) min = -Infinity;
        if (arguments.length < 3) max = Infinity;
        return (parseInt(value, 10) || 0).clamp(min, max);
    };

    var getCommandName = function(command) {
        return (command || '').toUpperCase();
    };

    var getArgNumber = function(arg, min, max) {
        if (arguments.length < 2) min = -Infinity;
        if (arguments.length < 3) max = Infinity;
        return (parseInt(convertEscapeCharacters(arg), 10) || 0).clamp(min, max);
    };

    var getArgBoolean = function(arg) {
        return (arg || '').toUpperCase() === 'ON';
    };

    var convertEscapeCharacters = function(text) {
        if (text == null) text = '';
        var window = SceneManager._scene._windowLayer.children[0];
        return window ? window.convertEscapeCharacters(text) : text;
    };

    var iterate = function(that, handler) {
        Object.keys(that).forEach(function(key, index) {
            handler.call(that, key, that[key], index);
        });
    };

    //=============================================================================
    // パラメータの取得とバリデーション
    //=============================================================================
    var paramGameVariableTouchX       = getParamNumber(['GameVariableTouchX', 'ポインタX座標の変数番号'], 0);
    var paramGameVariableTouchY       = getParamNumber(['GameVariableTouchY', 'ポインタY座標の変数番号'], 0);
    var paramGameVariablePictNum      = getParamNumber(['GameVariablePictureNum', 'ピクチャ番号の変数番号'], 0);
    var paramTransparentConsideration = getParamBoolean(['TransparentConsideration', '透明色を考慮']);
    var paramSuppressTouch            = getParamBoolean(['SuppressTouch', 'タッチ操作抑制']);
    var paramAlwaysCommonInBattle     = getParamBoolean(['AlwaysCommonInBattle', '戦闘中常にコモン実行']);

    //=============================================================================
    // Game_Interpreter
    //  プラグインコマンド[P_CALL_CE]などを追加定義します。
    //=============================================================================
    var _Game_Interpreter_pluginCommand      = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        _Game_Interpreter_pluginCommand.apply(this, arguments);
        var pictureId, touchParam, trigger, variableNum, transparent;
        switch (getCommandName(command)) {
            case 'P_CALL_CE' :
            case 'ピクチャのボタン化':
                pictureId   = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                touchParam  = getArgNumber(args[1], 1, $dataCommonEvents.length - 1);
                trigger     = getArgNumber(args[2], 1);
                transparent = (args.length > 3 ? getArgBoolean(args[3]) : null);
                $gameScreen.setPictureCallCommon(pictureId, touchParam, trigger, transparent);
                break;
            case 'P_CALL_SWITCH' :
            case 'ピクチャのスイッチ化':
                pictureId   = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                touchParam  = getArgNumber(args[1], 1);
                trigger     = getArgNumber(args[2], 1);
                transparent = (args.length > 3 ? getArgBoolean(args[3]) : null);
                $gameScreen.setPictureCallCommon(pictureId, touchParam * -1, trigger, transparent);
                break;
            case 'P_CALL_KEY_BIND' :
            case 'ピクチャのキーバインド':
                pictureId   = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                touchParam  = convertEscapeCharacters(args[1]).toLowerCase();
                trigger     = getArgNumber(args[2], 1);
                transparent = (args.length > 3 ? getArgBoolean(args[3]) : null);
                $gameScreen.setPictureCallCommon(pictureId, touchParam, trigger, transparent);
                break;
            case 'P_CALL_CE_REMOVE' :
            case 'ピクチャのボタン化解除':
                pictureId = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                $gameScreen.setPictureRemoveCommon(pictureId);
                break;
            case 'P_STROKE' :
            case 'ピクチャのなでなで設定':
                pictureId   = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                variableNum = getArgNumber(args[1], 1, $dataSystem.variables.length - 1);
                $gameScreen.setPictureStroke(pictureId, variableNum);
                break;
            case 'P_STROKE_REMOVE' :
            case 'ピクチャのなでなで解除':
                pictureId = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                $gameScreen.removePictureStroke(pictureId);
                break;
            case 'P_POINTER' :
            case 'ピクチャのポインタ化':
                pictureId = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                $gameScreen.setPicturePointer(pictureId);
                break;
            case 'P_POINTER_REMOVE' :
            case 'ピクチャのポインタ化解除':
                pictureId = getArgNumber(args[0], 1, $gameScreen.maxPictures());
                $gameScreen.removePicturePointer(pictureId);
                break;
        }
    };

    var _Game_Interpreter_terminate      = Game_Interpreter.prototype.terminate;
    Game_Interpreter.prototype.terminate = function() {
        _Game_Interpreter_terminate.apply(this, arguments);
        this._setupFromPicture = false;
    };

    Game_Interpreter.prototype.setupFromPicture = function(eventList) {
        this.setup(eventList, null);
        this._setupFromPicture = true;
    };

    Game_Interpreter.prototype.isSetupFromPicture = function() {
        return this._setupFromPicture;
    };

    //=============================================================================
    // Game_Temp
    //  呼び出し予定のコモンイベントIDのフィールドを追加定義します。
    //=============================================================================
    var _Game_Temp_initialize      = Game_Temp.prototype.initialize;
    Game_Temp.prototype.initialize = function() {
        _Game_Temp_initialize.call(this);
        this.clearPictureCallInfo();
    };

    Game_Temp.prototype.clearPictureCallInfo = function() {
        this.setPictureCallInfo(0);
    };

    Game_Temp.prototype.setPictureCallInfo = function(pictureCommonId) {
        this._pictureCommonId = pictureCommonId;
    };

    Game_Temp.prototype.pictureCommonId = function() {
        return this._pictureCommonId;
    };

    Game_Temp.prototype.onTouchPicture = function(param, pictureId) {
        this._touchPictureParam = param;
        if (this.isTouchPictureSetSwitch()) {
            $gameSwitches.setValue(param * -1, true);
        }
        if (this.isTouchPictureCallCommon()) {
            this.setPictureCallInfo(param);
        }
        if (this.isTouchPictureButtonTrigger()) {
            Input.bindKeyState(param);
        }
        if (paramGameVariablePictNum > 0) {
            $gameVariables.setValue(paramGameVariablePictNum, pictureId);
        }
    };

    Game_Temp.prototype.isTouchPictureButtonTrigger = function() {
        return isNaN(this._touchPictureParam);
    };

    Game_Temp.prototype.isTouchPictureSetSwitch = function() {
        return !isNaN(this._touchPictureParam) && this._touchPictureParam < 0;
    };

    Game_Temp.prototype.isTouchPictureCallCommon = function() {
        return !isNaN(this._touchPictureParam) && this._touchPictureParam > 0;
    };

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

    //=============================================================================
    // Game_Map
    //  ピクチャがタッチされたときのコモンイベント呼び出し処理を追加定義します。
    //=============================================================================
    var _Game_Map_setupStartingEvent      = Game_Map.prototype.setupStartingEvent;
    Game_Map.prototype.setupStartingEvent = function() {
        var result = _Game_Map_setupStartingEvent.call(this);
        return result || this.setupPictureCommonEvent();
    };

    Game_Map.prototype.setupPictureCommonEvent = function() {
        var commonId = $gameTemp.pictureCommonId();
        var event    = $dataCommonEvents[commonId];
        var result   = false;
        if (commonId > 0 && !this.isEventRunning() && event) {
            this._interpreter.setupFromPicture(event.list);
            result = true;
        }
        $gameTemp.clearPictureCallInfo();
        return result;
    };

    //=============================================================================
    // Game_Troop
    //  ピクチャがタッチされたときのコモンイベント呼び出し処理を追加定義します。
    //=============================================================================
    Game_Troop.prototype.setupPictureCommonEvent = Game_Map.prototype.setupPictureCommonEvent;

    Game_Troop.prototype.isExistPictureCommon = function() {
        return this._interpreter.isSetupFromPicture();
    };

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

    Game_Screen.prototype.initPictureArray = function() {
        this._pictureCidArray         = this._pictureCidArray || [];
        this._pictureSidArray         = this._pictureSidArray || [];
        this._picturePidArray         = this._picturePidArray || [];
        this._pictureTransparentArray = this._pictureTransparentArray || [];
    };

    var _Game_Screen_update      = Game_Screen.prototype.update;
    Game_Screen.prototype.update = function() {
        _Game_Screen_update.apply(this, arguments);
        this.updatePointer();
    };

    Game_Screen.prototype.updatePointer = function() {
        if (paramGameVariableTouchX)
            $gameVariables._data[paramGameVariableTouchX] = TouchInput.x;
        if (paramGameVariableTouchY)
            $gameVariables._data[paramGameVariableTouchY] = TouchInput.y;
    };

    Game_Screen.prototype.setPictureCallCommon = function(pictureId, touchParameter, trigger, transparent) {
        var realPictureId = this.realPictureId(pictureId);
        if (this._pictureCidArray[realPictureId] == null) this._pictureCidArray[realPictureId] = [];
        this._pictureCidArray[realPictureId][trigger] = touchParameter;
        this._pictureTransparentArray[realPictureId]  = transparent;
    };

    Game_Screen.prototype.setPictureRemoveCommon = function(pictureId) {
        this._pictureCidArray[this.realPictureId(pictureId)] = [];
    };

    Game_Screen.prototype.setPictureStroke = function(pictureId, variableNum) {
        this._pictureSidArray[this.realPictureId(pictureId)] = variableNum;
    };

    Game_Screen.prototype.removePictureStroke = function(pictureId) {
        this._pictureSidArray[this.realPictureId(pictureId)] = null;
    };

    Game_Screen.prototype.setPicturePointer = function(pictureId) {
        this._picturePidArray[this.realPictureId(pictureId)] = true;
    };

    Game_Screen.prototype.removePicturePointer = function(pictureId) {
        this._picturePidArray[this.realPictureId(pictureId)] = null;
    };

    Game_Screen.prototype.getPictureCid = function(pictureId) {
        return this._pictureCidArray[this.realPictureId(pictureId)];
    };

    Game_Screen.prototype.getPictureSid = function(pictureId) {
        return this._pictureSidArray[this.realPictureId(pictureId)];
    };

    Game_Screen.prototype.getPicturePid = function(pictureId) {
        return this._picturePidArray[this.realPictureId(pictureId)];
    };

    Game_Screen.prototype.getPictureTransparent = function(pictureId) {
        return this._pictureTransparentArray[this.realPictureId(pictureId)];
    };

    Game_Screen.prototype.disConvertPositionX = function(x) {
        return Math.round((x + this.zoomX() - this.shake()) / this.zoomScale());
    };

    Game_Screen.prototype.disConvertPositionY = function(y) {
        return Math.round((y + this.zoomY()) / this.zoomScale());
    };

    Game_Screen.prototype.disConvertPositionY = function(y) {
        return Math.round((y + this.zoomY()) / this.zoomScale());
    };

    Game_Screen.prototype.isPointerInnerPicture = function(pictureId) {
        var picture = SceneManager.getPictureSprite(pictureId);
        return picture ? picture.isIncludePointer() : false;
    };

    //=============================================================================
    // SceneManager
    //  ピクチャスプライトを取得します。
    //=============================================================================
    SceneManager.getPictureSprite = function(pictureId) {
        return this._scene.getPictureSprite(pictureId);
    };

    //=============================================================================
    // BattleManager
    //  ピクチャコモンを常に実行できるようにします。
    //=============================================================================
    BattleManager.updatePictureCommon = function() {
        if ($gameTroop.isExistPictureCommon() && paramAlwaysCommonInBattle) {
            this.updateEventMain();
            return true;
        }
        return false;
    };

    //=============================================================================
    // Scene_Base
    //  ピクチャに対する繰り返し処理を追加定義します。
    //=============================================================================
    Scene_Base.prototype.updateTouchPictures = function() {
        this._spriteset.iteratePictures(function(picture) {
            if (typeof picture.callTouch === 'function') picture.callTouch();
            return $gameTemp.pictureCommonId() === 0;
        });
    };

    Scene_Base.prototype.getPictureSprite = function(pictureId) {
        var result = null;
        this._spriteset.iteratePictures(function(picture) {
            if (picture.isIdEquals(pictureId)) {
                result = picture;
                return false;
            }
            return true;
        });
        return result;
    };

    //=============================================================================
    // Scene_Map
    //  ピクチャのタッチ状態からのコモンイベント呼び出し予約を追加定義します。
    //=============================================================================
    var _Scene_Map_update      = Scene_Map.prototype.update;
    Scene_Map.prototype.update = function() {
        this.updateTouchPictures();
        _Scene_Map_update.apply(this, arguments);
    };

    var _Scene_Map_processMapTouch      = Scene_Map.prototype.processMapTouch;
    Scene_Map.prototype.processMapTouch = function() {
        _Scene_Map_processMapTouch.apply(this, arguments);
        if ($gameTemp.isDestinationValid() && $gameTemp.pictureCommonId() > 0) {
            $gameTemp.clearDestination();
        }
    };

    //=============================================================================
    // Scene_Battle
    //  ピクチャのタッチ状態からのコモンイベント呼び出し予約を追加定義します。
    //=============================================================================
    var _Scene_Battle_update      = Scene_Battle.prototype.update;
    Scene_Battle.prototype.update = function() {
        this.updateTouchPictures();
        $gameTroop.setupPictureCommonEvent();
        _Scene_Battle_update.apply(this, arguments);
    };

    var _Scene_Battle_updateBattleProcess      = Scene_Battle.prototype.updateBattleProcess;
    Scene_Battle.prototype.updateBattleProcess = function() {
        var result = BattleManager.updatePictureCommon();
        if (result) return;
        _Scene_Battle_updateBattleProcess.apply(this, arguments);
    };

    //=============================================================================
    // Spriteset_Base
    //  ピクチャに対するイテレータを追加定義します。
    //=============================================================================
    Spriteset_Base.prototype.iteratePictures = function(callBackFund) {
        var containerChildren = this._pictureContainer.children;
        if (!Array.isArray(containerChildren)) {
            iterate(this._pictureContainer, function(property) {
                if (this._pictureContainer[property].hasOwnProperty('children')) {
                    containerChildren = this._pictureContainer[property].children;
                    this._iteratePicturesSub(containerChildren, callBackFund);
                }
            }.bind(this));
        } else {
            this._iteratePicturesSub(containerChildren, callBackFund);
        }
    };

    Spriteset_Base.prototype._iteratePicturesSub = function(containerChildren, callBackFund) {
        for (var i = containerChildren.length - 1; i >= 0; i--) {
            if (!callBackFund(containerChildren[i])) {
                break;
            }
        }
    };

    //=============================================================================
    // Sprite_Picture
    //  ピクチャのタッチ状態からのコモンイベント呼び出し予約を追加定義します。
    //=============================================================================
    var _Sprite_Picture_initialize      = Sprite_Picture.prototype.initialize;
    Sprite_Picture.prototype.initialize = function(pictureId) {
        _Sprite_Picture_initialize.call(this, pictureId);
        this._triggerHandler     = [];
        this._triggerHandler[1]  = this.isTriggered;
        this._triggerHandler[2]  = this.isCancelled;
        this._triggerHandler[3]  = this.isLongPressed;
        this._triggerHandler[4]  = this.isOnFocus;
        this._triggerHandler[5]  = this.isOutFocus;
        this._triggerHandler[6]  = this.isReleased;
        this._triggerHandler[7]  = this.isRepeated;
        this._triggerHandler[8]  = this.isPressed;
        this._triggerHandler[9]  = this.isWheelTriggered;
        this._triggerHandler[10] = this.isDoubleTriggered;
        this._triggerHandler[11] = this.isMoved;
        this._triggerHandler[12] = this.isMovedAndPressed;
        this._onMouse            = false;
        this._outMouse           = false;
        this._wasOnMouse         = false;
    };

    var _Sprite_update              = Sprite_Picture.prototype.update;
    Sprite_Picture.prototype.update = function() {
        _Sprite_update.apply(this, arguments);
        this.updateMouseMove();
        this.updateStroke();
        this.updatePointer();
    };

    Sprite_Picture.prototype.updateMouseMove = function() {
        if (this.isIncludePointer()) {
            if (!this._wasOnMouse) {
                this._onMouse    = true;
                this._wasOnMouse = true;
            }
        } else {
            if (this._wasOnMouse) {
                this._outMouse   = true;
                this._wasOnMouse = false;
            }
        }
    };

    Sprite_Picture.prototype.isIncludePointer = function() {
        return this.isTouchable() && this.isTouchPosInRect() && !this.isTransparent();
    };

    Sprite_Picture.prototype.updateStroke = function() {
        var strokeNum = $gameScreen.getPictureSid(this._pictureId);
        if (strokeNum > 0 && TouchInput.isPressed()) {
            var value = $gameVariables.value(strokeNum);
            $gameVariables.setValue(strokeNum, value + TouchInput.pressedDistance);
        }
    };

    Sprite_Picture.prototype.updatePointer = function() {
        var strokeNum = $gameScreen.getPicturePid(this._pictureId);
        if (strokeNum > 0) {
            this.opacity  = TouchInput.isPressed() ? 255 : 0;
            this.x        = TouchInput.x;
            this.y        = TouchInput.y;
            this.anchor.x = 0.5;
            this.anchor.y = 0.5;
        }
    };

    Sprite_Picture.prototype.callTouch = function() {
        var commandIds = $gameScreen.getPictureCid(this._pictureId);
        if (!commandIds) return;
        for (var i = 0, n = this._triggerHandler.length; i < n; i++) {
            var handler = this._triggerHandler[i];
            if (handler && commandIds[i] && handler.call(this) && (this.triggerIsFocus(i) || !this.isTransparent())) {
                this.fireTouchEvent(commandIds, i);
            }
        }
    };

    Sprite_Picture.prototype.fireTouchEvent = function(commandIds, i) {
        if (paramSuppressTouch) TouchInput.suppressEvents();
        if (this.triggerIsLongPressed(i)) TouchInput._pressedTime = -60;
        if (this.triggerIsOnFocus(i)) this._onMouse = false;
        if (this.triggerIsOutFocus(i)) this._outMouse = false;
        $gameTemp.onTouchPicture(commandIds[i], this._pictureId);
    };

    Sprite_Picture.prototype.triggerIsLongPressed = function(triggerId) {
        return triggerId === 3;
    };

    Sprite_Picture.prototype.triggerIsOnFocus = function(triggerId) {
        return triggerId === 4;
    };

    Sprite_Picture.prototype.triggerIsOutFocus = function(triggerId) {
        return triggerId === 5;
    };

    Sprite_Picture.prototype.triggerIsFocus = function(triggerId) {
        return this.triggerIsOnFocus(triggerId) || this.triggerIsOutFocus(triggerId);
    };

    Sprite_Picture.prototype.isTransparent = function() {
        if (this.isTouchPosInFrameWindow()) return false;
        if (!this.isValidTransparent()) return false;
        if (this.opacity === 0) return true;
        var dx  = this.getTouchScreenX() - this.x;
        var dy  = this.getTouchScreenY() - this.y;
        var sin = Math.sin(-this.rotation);
        var cos = Math.cos(-this.rotation);
        var bx  = Math.floor(dx * cos + dy * -sin) / this.scale.x + this.anchor.x * this.width;
        var by  = Math.floor(dx * sin + dy * cos) / this.scale.y + this.anchor.y * this.height;
        return this.bitmap.getAlphaPixel(bx, by) === 0;
    };

    Sprite_Picture.prototype.isValidTransparent = function() {
        var transparent = $gameScreen.getPictureTransparent(this._pictureId);
        return transparent !== null ? transparent : paramTransparentConsideration;
    };

    Sprite_Picture.prototype.screenWidth = function() {
        return (this.width || 0) * this.scale.x;
    };

    Sprite_Picture.prototype.screenHeight = function() {
        return (this.height || 0) * this.scale.y;
    };

    Sprite_Picture.prototype.screenX = function() {
        return (this.x || 0) - this.anchor.x * this.screenWidth();
    };

    Sprite_Picture.prototype.screenY = function() {
        return (this.y || 0) - this.anchor.y * this.screenHeight();
    };

    Sprite_Picture.prototype.minX = function() {
        return Math.min(this.screenX(), this.screenX() + this.screenWidth());
    };

    Sprite_Picture.prototype.minY = function() {
        return Math.min(this.screenY(), this.screenY() + this.screenHeight());
    };

    Sprite_Picture.prototype.maxX = function() {
        return Math.max(this.screenX(), this.screenX() + this.screenWidth());
    };

    Sprite_Picture.prototype.maxY = function() {
        return Math.max(this.screenY(), this.screenY() + this.screenHeight());
    };

    Sprite_Picture.prototype.isTouchPosInRect = function() {
        if (this.isTouchPosInFrameWindow()) return true;
        var dx  = this.getTouchScreenX() - this.x;
        var dy  = this.getTouchScreenY() - this.y;
        var sin = Math.sin(-this.rotation);
        var cos = Math.cos(-this.rotation);
        var rx  = this.x + Math.floor(dx * cos + dy * -sin);
        var ry  = this.y + Math.floor(dx * sin + dy * cos);
        return (rx >= this.minX() && rx <= this.maxX() && ry >= this.minY() && ry <= this.maxY());
    };

    Sprite_Picture.prototype.isTouchPosInFrameWindow = function() {
        if (!this._frameWindow) return false;
        var frame = this._frameWindow;
        var x  = this.getTouchScreenX();
        var y  = this.getTouchScreenY();
        return frame.x <= x && frame.x + frame.width >= x && frame.y <= y && frame.y + frame.height >= y;
    };

    Sprite_Picture.prototype.isTouchable = function() {
        return this.bitmap && this.visible && this.scale.x !== 0 && this.scale.y !== 0;
    };

    Sprite_Picture.prototype.isTriggered = function() {
        return this.isTouchEvent(TouchInput.isTriggered);
    };

    Sprite_Picture.prototype.isCancelled = function() {
        return this.isTouchEvent(TouchInput.isCancelled);
    };

    Sprite_Picture.prototype.isLongPressed = function() {
        return this.isTouchEvent(TouchInput.isLongPressed);
    };

    Sprite_Picture.prototype.isPressed = function() {
        return this.isTouchEvent(TouchInput.isPressed);
    };

    Sprite_Picture.prototype.isReleased = function() {
        return this.isTouchEvent(TouchInput.isReleased);
    };

    Sprite_Picture.prototype.isRepeated = function() {
        return this.isTouchEvent(TouchInput.isRepeated);
    };

    Sprite_Picture.prototype.isOnFocus = function() {
        return this._onMouse;
    };

    Sprite_Picture.prototype.isOutFocus = function() {
        return this._outMouse;
    };

    Sprite_Picture.prototype.isMoved = function() {
        return this.isTouchEvent(TouchInput.isMoved);
    };

    Sprite_Picture.prototype.isMovedAndPressed = function() {
        return this.isTouchEvent(TouchInput.isMoved) && TouchInput.isPressed();
    };

    Sprite_Picture.prototype.isWheelTriggered = function() {
        return this.isTouchEvent(TouchInput.isWheelTriggered);
    };

    Sprite_Picture.prototype.isDoubleTriggered = function() {
        return this.isTouchEvent(TouchInput.isDoubleTriggered);
    };

    Sprite_Picture.prototype.isTouchEvent = function(triggerFunc) {
        return this.isTouchable() && triggerFunc.call(TouchInput) && this.isTouchPosInRect();
    };

    Sprite_Picture.prototype.getTouchScreenX = function() {
        return $gameScreen.disConvertPositionX(TouchInput.x);
    };

    Sprite_Picture.prototype.getTouchScreenY = function() {
        return $gameScreen.disConvertPositionY(TouchInput.y);
    };

    Sprite_Picture.prototype.isIdEquals = function(pictureId) {
        return this._pictureId === pictureId;
    };

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

    var _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
    //  ホイールクリック、ダブルクリック等を実装
    //=============================================================================
    TouchInput.keyDoubleClickInterval = 300;
    TouchInput._pressedDistance       = 0;
    TouchInput._prevX                 = -1;
    TouchInput._prevY                 = -1;

    Object.defineProperty(TouchInput, 'pressedDistance', {
        get         : function() {
            return this._pressedDistance;
        },
        configurable: true
    });

    TouchInput.suppressEvents = function() {
        this._triggered       = false;
        this._cancelled       = false;
        this._released        = false;
        this._wheelTriggered  = false;
        this._doubleTriggered = false;
    };

    TouchInput._onMouseMove = function(event) {
        var x = Graphics.pageToCanvasX(event.pageX);
        var y = Graphics.pageToCanvasY(event.pageY);
        this._onMove(x, y);
    };

    var _TouchInput_clear = TouchInput.clear;
    TouchInput.clear      = function() {
        _TouchInput_clear.apply(this, arguments);
        this._events.wheelTriggered  = false;
        this._events.doubleTriggered = false;
    };

    var _TouchInput_update = TouchInput.update;
    TouchInput.update      = function() {
        _TouchInput_update.apply(this, arguments);
        this._wheelTriggered         = this._events.wheelTriggered;
        this._doubleTriggered        = this._events.doubleTriggered;
        this._events.wheelTriggered  = false;
        this._events.doubleTriggered = false;
    };

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

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

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

    TouchInput._onWheelTrigger = function(x, y) {
        this._events.wheelTriggered = true;
        this._x                     = x;
        this._y                     = y;
    };

    var _TouchInput_onTrigger = TouchInput._onTrigger;
    TouchInput._onTrigger     = function(x, y) {
        if (this._date && Date.now() - this._date < this.keyDoubleClickInterval)
            this._events.doubleTriggered = true;
        this._pressedDistance = 0;
        this._prevX           = x;
        this._prevY           = y;
        _TouchInput_onTrigger.apply(this, arguments);
    };

    var _TouchInput_onMove = TouchInput._onMove;
    TouchInput._onMove     = function(x, y) {
        if (this.isPressed()) this._pressedDistance = Math.abs(this._prevX - x) + Math.abs(this._prevY - y);
        this._prevX = x;
        this._prevY = y;
        _TouchInput_onMove.apply(this, arguments);
    };

    var _TouchInput_onRelease = TouchInput._onRelease;
    TouchInput._onRelease     = function(x, y) {
        this._pressedDistance = 0;
        this._prevX           = x;
        this._prevY           = y;
        _TouchInput_onRelease.apply(this, arguments);
    };
})();


code:
//
//  ポップアップメッセージ ver1.02
//
// author yana
//

var Imported = Imported || {};
Imported['PopupMessage'] = 1.02;

if (!Imported.CommonPopupCore) {
	console.error('CommonPopupCoreを導入してください。')
}

/*:
 * @plugindesc ver1.02/メッセージの表示をポップアップに変更する制御文字_pum[delay,x,y,action]を追加します。
 * @author Yana
 *
 * @param Pop Message FontSize
 * @desc ポップアップメッセージのデフォルトフォントサイズです。
 * @default 28
 *
 * @param Pop Message Count
 * @desc ポップアップメッセージの表示時間です。
 * @default 120
 *
 * @help プラグインコマンドはありません。
 *
 * メッセージの表示のメッセージの中に_pum[delay,x,y,action,pattern]と記述することで、
 * メッセージをポップアップに変更します。
 * delayはディレイ値で、この値フレーム分待ってから、ポップアップを行います。
 * xは表示位置のX座標です。未指定の場合は、0が設定されます。
 * yは表示位置のY座標です。未指定の場合は、画面高さ-ポップアップの高さが設定されます。
 * actionはアクション形式です。1を指定すると、上から下にアクションします。
 * patternは動作パターンです。Normalで今まで通り、GrowUpでにょき、Stretchでうにょーんとなります。
 * ------------------------------------------------------
 * 利用規約：特になし。素材利用は自己責任でお願いします。
 * ------------------------------------------------------
 * このプラグインには「汎用ポップアップベース」のプラグインが必要です。
 * 汎用ポップアップベースより下に配置してください。
 * ------------------------------------------------------
 * 更新履歴:
 * ver1.02:
 * 動作パターンの設定を追加。
 * ver1.01:
 * 表示位置を調整する機能を追加。
 * ver1.00:
 * 公開
 */

(function() {
	var parameters = PluginManager.parameters('PopupMessage');
	var popMesFontSize = Number(parameters['Pop Message FontSize'] || 28);
	var popMesCount = Number(parameters['Pop Message Count'] || 120);
	var popMesSlide = Number(parameters['Pop Message Slide'] || 60);
	var popMesRegExp = /_PUM\[(\d+),?(\d+)?,?(\d+)?,?(\d+)?,?(.+?)?\]/gi;

	var _pMes_GInterpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
	Game_Interpreter.prototype.pluginCommand = function(command, args) {
		_pMes_GInterpreter_pluginCommand.call(this, command, args);
		if (command === 'PopupMessage') {
		}
	};

	var _pMes_GInterpreter_c101 = Game_Interpreter.prototype.command101;
	Game_Interpreter.prototype.command101 = function(){
		var texts = [];
		var pIndex = this._index;
		var param = {'delay':null};
		while (this.nextEventCode() === 401){
			this._index++;
			texts.push(this.currentCommand().parameters[0]);
		}
    	for(var i=0;i<texts.length;i++){
    		if (texts[i].match(popMesRegExp)){
    			var ary = [0,null,null,0];
        		text = texts[i].replace(popMesRegExp,function(){
        			ary[0] = Number(arguments[1]);
        			if (arguments[2]){ ary[1] = Number(arguments[2]) }
        			if (arguments[3]){ ary[2] = Number(arguments[3]) }
        			if (arguments[4]){ ary[3] = Number(arguments[4]) }
                    if (arguments[5]){ ary[4] = arguments[5] }
        			return '';
        		}.bind(this));
        		texts[i] = text;
        		CommonPopupManager.setPopupMessage(this._params, texts, ary);
        		return true;
    		}
    	}
		this._index = pIndex;
		var result = _pMes_GInterpreter_c101.call(this);
		return result;
	};

	var _pMes_GMessage_add = Game_Message.prototype.add;
	Game_Message.prototype.add = function(text){
		text = text.replace(popMesRegExp,'');
		_pMes_GMessage_add.call(this,text);
	};

	CommonPopupManager.setPopupMessage = function(params,texts,ary){
		this._readyPopup = this._readyPopup || [];
		var bitmap = ImageManager.loadFace(params[0]);
		this.bltCheck(bitmap);
		this._readyPopup.push([params, texts, ary, 'pMessage']);
	};

	var _pMes_CPManager_makeBitmap = CommonPopupManager.makeBitmap;
	CommonPopupManager.makeBitmap = function(arg){
		if (arg[3] === 'pMessage'){
			return ImageManager.loadFace(arg[0][0]);
		}else{
			return _pMes_CPManager_makeBitmap.call(this,arg);
		}
	};

	var _pMes_CPManager_startPopup = CommonPopupManager.startPopup;
	CommonPopupManager.startPopup = function(arg){
		if (arg[3] === 'pMessage'){
			this.startPopupMessage(arg[0],arg[1],arg[2]);
		}else{
			_pMes_CPManager_startPopup.call(this,arg);
		}
	};

	CommonPopupManager.startPopupMessage = function(params,texts,arg){
		var fontSize = popMesFontSize;
		var oneHeight = (fontSize + 8)
		var height = params[0] ? 144 : oneHeight * texts.length;
		var bitmap = new Bitmap(Graphics.boxWidth, height);
		var faceSize = params[0] === '' ? 0 : 144;
		var delay = arg[0];
		var x = arg[1];
		var y = arg[2];
		var action = arg[3];
        var pattern = arg[4];
		bitmap.fillRect(0, 0, bitmap.width / 2, bitmap.height, 'rgba(0,0,0,0.5)');
		bitmap.gradientFillRect(bitmap.width / 2, 0, bitmap.width / 2, bitmap.height, 'rgba(0,0,0,0.5)', 'rgba(0,0,0,0)');
		this.window().contents = bitmap;
		this.window().drawTextEx('\\FS[' + fontSize + ']', 0, 0);
		this.window().drawFace(params[0],params[1],0,0);
		var iFontSize = fontSize;
		for (var i = 0; i < texts.length; i++) {
			var text = '\\FS[' + iFontSize + ']' + texts[i]
			this.window().drawTextEx(text, 8 + faceSize, i * oneHeight);
			iFontSize = this.window().contents.fontSize;
		}
		var arg = this.setPopup([]);
		arg.bitmap = bitmap;
        if (pattern === 'GrowUp') {
            arg.x = 0;
            arg.y = Graphics.boxHeight;
            arg.moveX = 0;
            arg.anchorX = 0;
            arg.anchorY = 1.0;
            arg.pattern = -2;
        } else if (pattern === 'Stretch'){
            arg.x = 0;
            arg.y = Graphics.boxHeight - height;
            arg.moveX = 0;
            arg.anchorX = 0;
            arg.anchorY = 0;
            arg.pattern = -1;
        } else {
            arg.x = Graphics.boxWidth * -1;
            arg.y = Graphics.boxHeight - height;
            arg.moveX = Graphics.boxWidth;
            arg.anchorX = 0;
            arg.anchorY = 0;
        }
		if (x){ arg.x += x }
		if (y){ arg.y = y }
		if ($gameParty.inBattle()){ arg.y = Math.min(Graphics.boxHeight - 180,arg.y) }
		arg.moveY = 0;
		arg.count = popMesCount;
		arg.fixed = false;
		arg.slideCount = popMesSlide;
		if (action === 1){ arg.slideAction = 'Down' }
		arg.delay = delay;
		this._tempCommonSprites.setNullPos(arg);
	}
})();


code:
/*:
* @plugindesc (v1.0.6) This plugin allows you to align the text in the message system.
* @author biud436
* @help
* =============================================================================
* Usage
* -----------------------------------------------------------------------------
* That plugin is an addon, so it should be installed the plugin somewhere
* below 'YEP_MessageCore'.
*
* All text codes process before drawn the text.
* For each line you can set a different text alignment.
*
* \TA[0] - LEFT
* \TA[1] - CENTER
* \TA[2] - RIGHT
*
* When using Yanfly Message Core :
* - Do not use the text code like as 'px' and 'py'.
* - Do not use the wordwrapping.
*
* =============================================================================
* Change Log
* -----------------------------------------------------------------------------
* 2017.01.25 (v1.0.0) - First Release
* 2017.06.25 (v1.0.1) - Fixed an issue that resets a font setting at each line
* 2017.07.23 (v1.0.2) - Fixed a bug that the alignment is not processing in a newly line
* 2017.10.13 (v1.0.3) - Fixed the class name.
* 2018.05.09 (v1.0.4) - Added a variable that stores a last alignment value.
* 2018.07.09 (v1.0.5) :
* - Fixed the text padding for left, center, right alignment.
* - Now it is worked fine even without YEP Message Core.
* 2018.08.14 (v1.0.6) - Fixed the LF(line feed) and CR(carriage return)
*/

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

(function() {

    //============================================================================
    // Game_Message
    //============================================================================

    var alias_Game_Message_clear = Game_Message.prototype.clear;
    Game_Message.prototype.clear = function() {
        alias_Game_Message_clear.call(this);
        this._align = [];
        this._alignLast = 0;
    };

    Game_Message.prototype.setAlign = function(n) {
        this._align = this._align || [];
        this._alignLast = n;
        this._align.push(n);
    };

    Game_Message.prototype.getAlign = function(n) {
        return this._align.shift() || this._alignLast;
    };

    //============================================================================
    // Window_Message
    //============================================================================

    var alias_Window_Message_convertEscapeCharacters = Window_Message.prototype.convertEscapeCharacters;
    Window_Message.prototype.convertEscapeCharacters = function(text) {
        text = alias_Window_Message_convertEscapeCharacters.call(this, text);
        text = text.replace(/\x1bTA\[(\d+)\]/gi, function() {
            $gameMessage.setAlign(Number(arguments[1] || 0));
            return "";
        }.bind(this));
        return text;
    };

    Window_Message.prototype.processAlign = function(textState) {
        textState = textState || this._textState;
        switch($gameMessage.getAlign()) {
            case 1:
            this.setAlignCenter(textState);
            break;
            case 2:
            this.setAlignRight(textState);
            break;
            default:
            this.setAlignLeft(textState);
        }
    }

    var alias_Window_Message_processNewLine = Window_Message.prototype.processNewLine;
    Window_Message.prototype.processNewLine = function(textState) {
        alias_Window_Message_processNewLine.call(this, textState);
        this.processAlign(textState);
    };

    if(!Imported.YEP_MessageCore) {

        Window_Message.prototype.saveFontSettings = function() {
            this._messageDesc = {};
            this._messageDesc.fontFace = this.contents.fontFace;
            this._messageDesc.fontSize = this.contents.fontSize;
            this._messageDesc.textColor = this.contents.textColor;
        };

        Window_Message.prototype.restoreFontSettings = function() {
            if(!this._messageDesc) return;
            this.contents.fontFace = this._messageDesc.fontFace;
            this.contents.fontSize = this._messageDesc.fontSize;
            this.contents.textColor = this._messageDesc.textColor;
            this._messageDesc = undefined;
        };

    }

    Window_Message.prototype.calcTextWidth = function(text) {

        var tempText = text; tempText = tempText.split(/[\r\n]+/);
        var textWidth;

        // This makes it easier to get the text width.
        // But it will be drawn the text many times inside invisible area.
        if(Imported.YEP_MessageCore) {

            textWidth = this.textWidthExCheck(tempText[0]);

        } else {

            this.saveFontSettings();
            textWidth = this.drawTextEx(tempText[0], 0, this.contents.height);
            this.restoreFontSettings();

        }

        return textWidth;

    };

    Window_Message.prototype.setAlignLeft = function(textState) {
        //var padding = this.textPadding();
        textState.tx = this.calcTextWidth(textState.text.slice(textState.index));
        //textState.x = ( this.newLineX() + padding );
        //textState.left = textState.x;
    };

    Window_Message.prototype.setAlignCenter = function(textState) {
        var padding = this.textPadding();
        textState.tx = this.calcTextWidth(textState.text.slice(textState.index));
        textState.x = ( this.newLineX() + this.contentsWidth() + padding) / 2 - textState.tx / 2;
        textState.left = textState.x;
    };

    Window_Message.prototype.setAlignRight = function(textState) {
        var padding = this.textPadding();
        textState.tx = this.calcTextWidth(textState.text.slice(textState.index));
        textState.x = ( this.contentsWidth() - padding) - textState.tx;
        textState.left = textState.x;
    };

    var alias_Window_Message_startMessage_setAlignCenter = Window_Message.prototype.startMessage;
    Window_Message.prototype.startMessage = function() {
        alias_Window_Message_startMessage_setAlignCenter.call(this);
        this.processAlign();
    };

})();