code:
//=============================================================================
// EventReSpawn.js
// ----------------------------------------------------------------------------
// (C) 2016 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.11.5 2020/12/28 利用するプラグインによってイベント生成時にちらつく現象が発生しないよう修正
// 1.11.4 2020/09/19 MOG_EventIndicators.jsと併用したとき、動的生成イベントにインジケータが表示されるよう修正
// 1.11.3 2020/03/01 MOG_EventText.jsと併用したとき、動的生成イベントにイベントテキストが表示されるよう修正
// 1.11.2 2019/12/14 KMS_Minimap.jsと併用したとき、動的生成イベントがミニマップに表示されるよう修正（KMS_Minimap.js側も専用のコードを適用する必要あり）
// 1.11.1 2019/12/10 「確定出力方式」の条件式を修正
// 1.11.0 2019/12/07 ランダム生成で条件を満たす場所に確実に出力する「確定出力方式」で出力できる機能を追加しました。（by 澱粉（仮）さま）
//                   特定条件でテンプレートイベント生成するとエラーになる場合がある問題を修正
//                   ランダム生成する際の個数を指定できる機能を追加
// 1.10.3 2019/11/24 動的生成イベントを生成元として生成する場合、実際の生成元を、元々の生成元の動的イベントではなく、さらにその生成元である静的イベントになるよう仕様変更
// 1.10.2 2019/11/04 1.10.1の修正で「現在のマップに存在しないID」を指定して「ERS_テンプレート生成」を実行するとエラーになる問題を修正
// 1.10.1 2019/11/04 TemplateEvent.jsと併用した際、ERS_MAKEによる生成対象のイベントがテンプレートイベントの場合はテンプレートイベントを生成するよう仕様変更
// 1.9.4 2019/09/27 1.9.0以降、TemplateEvent.jsと併用した際「ERS_MAKE」を実行した場合でもテンプレートイベントが生成される問題を修正
// 1.9.3 2019/07/07 1.9.0以降、ランダム生成で地形とリージョンを指定せず実行するとエラーになっていた問題を修正
// 1.9.2 2019/06/30 イベントが存在しないマップに動的イベントを生成したとき、最初のイベントの一部の動作がおかしくなる問題を修正
// 1.9.1 2019/06/09 テンプレートイベントを生成したとき、getTemplateIdを取得できない問題を修正
// 1.9.0 2019/01/14 地形タグとリージョンを複数指定できる機能を追加
// 1.8.3 2018/10/25 YEP_EventMiniLabel.jsと併用した際、動的生成イベントを「イベント消去」するとエラーになる競合を修正
// 1.8.2 2018/05/17 ランダム生成の試行回数をパラメータから設定できるように仕様変更
// 1.8.1 2018/03/12 ランダム生成で対象座標が見付からず失敗した場合、エラーではなく警告になるよう仕様変更
// 1.8.0 2018/02/07 場所移動時にセルフスイッチがクリアされなくなる機能を追加
// 1.7.0 2017/09/17 プラグインコマンドにテンプレートイベントのセルフ変数「\sv[n]」が利用できる機能を追加
// 1.6.0 2017/09/15 座標を指定する際、小数を指定できるよう修正（半歩移動プラグイン等との組み合わせを想定）
// 1.5.3 2017/06/18 コピー対象のイベントを変数から指定する際、変数に文字列が入っていると正しく取得できない問題を修正（by 奏ねこまさま）
// 1.5.2 2017/05/28 イベントを配置したときアニメパターンが一瞬だけ初期化されてしまう問題を修正
// 1.5.1 2017/04/23 イベントを生成するプラグインコマンドで制御文字が無効になっていた問題を修正
// 1.5.0 2017/01/19 イベント生成の際にIDだけでなくイベント名の一致するイベントを動的生成できる機能を追加
// 1.4.4 2017/01/13 動的イベントの一時消去時にバルーンやアニメーションを表示中だった場合に表示が残ってしまう問題を修正
// 1.4.3 2017/01/12 1.4.2の対策に漏れがあったため再修正
// 1.4.2 2017/01/12 プロジェクトを再保存してバージョンIDが変化した場合は動的生成イベントを復元しないよう修正
// 1.4.1 2016/12/28 YEP_SaveEventLocations.jsとの競合を解消
// 1.4.0 2016/12/25 最後に動的生成したイベントのイベントIDを取得できるコマンドを追加
// 1.3.1 2016/11/08 動的イベント生成中に同一マップに場所移動するとエラーが発生する現象を修正
// 1.3.0 2016/11/03 ランダム生成機能で各種引数で文字で設定できる機能を追加＋境界値まわりのバグ修正（by くらむぼんさま）
// 1.2.0 2016/09/06 場所移動時、生成イベントを引き継いでしまう不具合を修正
//                  プラグインコマンド実行時にイベントIDを0にすることで「このイベント」を複製できる機能を追加
// 1.1.1 2016/08/11 動的イベント生成中にセーブした場合にロードできなくなる不具合を修正
// 1.1.0 2016/08/10 テンプレートイベントプラグインとの連携で、テンプレートマップからイベントを生成する機能を追加
//                  生成場所を条件付きランダムで設定できる機能を追加
// 1.0.1 2016/08/09 イベント生成後にメニューを開いて戻ってくるとエラーが発生する現象の修正
// 1.0.0 2016/08/08 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc イベント動的生成プラグイン
 * @author トリアコンタン
 *
 * @param keepSelfSwitch
 * @text セルフスイッチ維持
 * @desc 有効にすると場所移動時にセルフスイッチをクリアしなくなります。イベントの消去を実行した場合はクリアされます。
 * @default false
 * @type boolean
 *
 * @param tryRandomCount
 * @text 試行回数
 * @desc ランダム生成をする際の試行回数です。イベント生成に失敗する場合は数値を大きくしてください。
 * @default 1000
 * @type number
 *
 * @param CertainSpawnSwitch
 * @text 確定出力方式スイッチ
 * @desc 指定されたスイッチがONのとき、生成時に「確定出力方式」を使用します。詳細はヘルプを確認してください。
 * @default 0
 * @type switch
 *
 * @help イベントをコピーして動的に生成します。
 * コピーした一時イベントは、イベントコマンド「イベントの一時消去」によって
 * 完全に削除され、オブジェクトとスプライトの使用領域を解放します。
 * セルフスイッチは個別に管理され、生成されるたびに初期化されます。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * ERS_生成 1 5 10 # イベントID[1]のイベントをコピーしてX[5] Y[10]に配置
 * ERS_MAKE 1 5 10 # 同上
 *
 * イベントIDを「0」にすると実行中のイベント（このイベント）を複製します。
 *
 * ●追加機能●
 * イベントIDに「文字列」を指定するとイベント名が一致するイベントを
 * 複製対象にします。(対象が複数存在する場合は一番小さいIDになります)
 *
 * ERS_生成 aaa 5 10 # イベント名[aaa]のイベントをコピーしてX[5] Y[10]に配置
 * ERS_MAKE aaa 5 10 # 同上
 *
 * 他のプラグインコマンドも同様です。
 *
 * 生成位置をランダムにすることもできます。ただのランダムではなく
 * 以下の補助条件を指定したうえでのランダムです。
 *  a. 通行可能かどうか(0:判定なし 1:通行可能タイルのみ)
 *  b. 画面内 or 画面外(0:判定なし 1:画面内 2:画面外)
 *  c. 他のキャラとの重なり(0:判定なし 1:プレイヤー 2:イベント 3:両方)
 *  d. 地形タグ(0:判定なし 1..:指定した地形タグ)
 *  e. リージョン(0:判定なし 1..:指定したリージョン)
 *
 * ERS_ランダム生成 1 1 2 3 5 4 # イベントID[1]のイベントを下記の条件(※)で配置
 * ERS_MAKE_RANDOM 1 1 2 3 5 4  # 同上
 * ※ 通行可能かつ画面外かつプレイヤーもしくはイベントが存在せず
 *    地形タグが「5」でリージョンが「4」の位置の中からランダム
 *
 * 地形タグとリージョンは複数指定できます。
 * カンマで数値を指定してください。
 * ERS_MAKE_RANDOM 59 0 0 0 3,4 0 # 地形タグ[3][4]に配置
 *
 * また特に、a.b.c.の条件指定がやりにくかったため文章による指定も可能にしました。
 * 上記の条件は以下のように書き換えることができます。（順番入れ替えは不可）
 *
 * ERS_ランダム生成 1 通行可能タイルのみ 画面外 両方 5 4
 * ERS_MAKE_RANDOM 1 passonly offscreen both 5 4
 *
 * 以下は同じ意味で用いることが出来る同義語リストです。
 * 判定なし 条件なし none
 * 通行可能タイルのみ 通行のみ passonly
 * 画面内 onscreen screen
 * 画面外 offscreen
 * プレイヤー player
 * イベント event
 * 両方 both
 *
 * ランダム生成する個数を設定できます。7番目のパラメータから指定します。
 * ERS_MAKE_RANDOM 1 1 1 1 1 1 2 # [2]個のイベントをランダム生成します。
 *
 * 最後に動的生成したイベントのイベントIDを取得できます。
 * 指定した番号の変数に格納されます。
 *
 * ERS_最終生成イベントID取得 10  # 最後に生成したイベントIDを変数[10]に設定
 * ERS_GET_LAST_SPAWN_EVENT_ID 10 # 同上
 *
 * イベントIDを「0」にすると実行中のイベント（このイベント）を複製します。
 *
 * ・他プラグインとの連携
 * テンプレートイベントプラグイン「TemplateEvent.js」と組み合わせると
 * テンプレートマップに定義したイベントを直接、マップに生成することができます。
 * 「TemplateEvent.js」を適用せずにコマンドを実行するとエラーになります。
 *
 * ERS_テンプレート生成 1 5 10 # テンプレートマップのイベントID[1]を生成します。
 * ERS_MAKE_TEMPLATE 1 5 10    # 同上
 *
 * ERS_テンプレートランダム生成 1 1 2 3 5 4 # テンプレート[1]をランダム生成
 * ERS_MAKE_TEMPLATE_RANDOM 1 1 2 3 5 4     # 同上
 * ※ 補助条件に関しては「ERS_ランダム生成」と同様です。
 *
 * 「TemplateEvent.js」取得元
 * https://github.com/triacontane/RPGMakerMV
 *
 * YEP_EventMiniLabel.jsと併用する場合、当プラグインを下に配置してください。
 *
 * ・確定出力方式について
 * イベント生成位置を決定するとき、ランダム試行ではなく条件を満たす位置に確実に生成します。
 * 生成時にマップ全体を走査し条件を満たす場所を探します。
 * リージョンのみの指定など、生成場所の候補が少ない場合に有効です。
 * パラメータ「確定出力方式スイッチ」に対するスイッチがONになっているとこちらのモードで
 * 出力します。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

/**
 * 動的生成イベントを扱うクラスです。
 * @constructor
 */
function Game_PrefabEvent() {
    this.initialize.apply(this, arguments);
}

(function () {
    'use strict';
    var metaTagPrefix = 'ERS_';

    /**
     * Create plugin parameter. param[paramName] ex. param.commandPrefix
     * @param pluginName plugin name(AltGlossary)
     * @returns {Object} Created parameter
     */
    var createPluginParameter = function (pluginName) {
        var paramReplacer = function (key, value) {
            if (value === 'null') {
                return value;
            }
            if (value[0] === '"' && value[value.length - 1] === '"') {
                return value;
            }
            try {
                return JSON.parse(value);
            } catch (e) {
                return value;
            }
        };
        var parameter = JSON.parse(JSON.stringify(PluginManager.parameters(pluginName), paramReplacer));
        PluginManager.setParameters(pluginName, parameter);
        return parameter;
    };

    var param = createPluginParameter('EventReSpawn');

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

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

    var makeRandomCompatible = {
        none: 0,
        判定なし: 0,
        条件なし: 0,
        passonly: 1,
        通行可能タイルのみ: 1,
        通行のみ: 1,
        screen: 1,
        onscreen: 1,
        画面内: 1,
        offscreen: 2,
        画面外: 2,
        player: 1,
        プレイヤー: 1,
        event: 2,
        イベント: 2,
        both: 3,
        両方: 3,
    };

    var convertEscapeCharacters = function (text) {
        if (isNotAString(text)) text = '';
        text = text.replace(/\\/g, '\x1b');
        text = text.replace(/\x1b\x1b/g, '\\');
        text = text.replace(/\x1bV\[(\d+)\]/gi, function () {
            return $gameVariables.value(parseInt(arguments[1]));
        }.bind(this));
        text = text.replace(/\x1bV\[(\d+)\]/gi, function () {
            return $gameVariables.value(parseInt(arguments[1]));
        }.bind(this));
        text = text.replace(/\x1bN\[(\d+)\]/gi, function () {
            var actor = parseInt(arguments[1]) >= 1 ? $gameActors.actor(parseInt(arguments[1])) : null;
            return actor ? actor.name() : '';
        }.bind(this));
        text = text.replace(/\x1bP\[(\d+)\]/gi, function () {
            var actor = parseInt(arguments[1]) >= 1 ? $gameParty.members()[parseInt(arguments[1]) - 1] : null;
            return actor ? actor.name() : '';
        }.bind(this));
        text = text.replace(/\x1bG/gi, TextManager.currencyUnit);
        return text;
    };

    var isNotAString = function (args) {
        return String(args) !== args;
    };

    var convertAllArguments = function (args) {
        return args.map(function (arg) {
            return convertEscapeCharacters(arg);
        });
    };

    var setPluginCommand = function (commandName, methodName) {
        pluginCommandMap.set(metaTagPrefix + commandName, methodName);
    };

    //=============================================================================
    // パラメータの取得と整形
    //=============================================================================
    var pluginCommandMap = new Map();
    setPluginCommand('MAKE', 'execMakeEvent');
    setPluginCommand('生成', 'execMakeEvent');
    setPluginCommand('MAKE_RANDOM', 'execMakeEventRandom');
    setPluginCommand('ランダム生成', 'execMakeEventRandom');
    setPluginCommand('テンプレート生成', 'execMakeTemplateEvent');
    setPluginCommand('MAKE_TEMPLATE', 'execMakeTemplateEvent');
    setPluginCommand('テンプレートランダム生成', 'execMakeTemplateEventRandom');
    setPluginCommand('MAKE_TEMPLATE_RANDOM', 'execMakeTemplateEventRandom');
    setPluginCommand('最終生成イベントID取得', 'execGetLastSpawnEventId');
    setPluginCommand('GET_LAST_SPAWN_EVENT_ID', 'execGetLastSpawnEventId');
    setPluginCommand('TRY_COUNT', 'changeTryCount');//追加

    //=============================================================================
    // DataManager
    //  データ検索用の共通処理です。
    //=============================================================================
    if (!DataManager.searchDataItem) {
        DataManager.searchDataItem = function (dataArray, columnName, columnValue) {
            var result = 0;
            dataArray.some(function (dataItem) {
                if (dataItem && dataItem[columnName] === columnValue) {
                    result = dataItem;
                    return true;
                }
                return false;
            });
            return result;
        };
    }

    //=============================================================================
    // Game_Interpreter
    //  プラグインコマンドを追加定義します。
    //=============================================================================
    var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.apply(this, arguments);
        var pluginCommandMethod = pluginCommandMap.get(command.toUpperCase());
        if (pluginCommandMethod) {
            args = convertAllArguments(args);
            if (this.convertAllSelfVariables) {
                args = this.convertAllSelfVariables(args);
            }
            this[pluginCommandMethod](args);
        }
    };

    Game_Interpreter.prototype.execMakeEvent = function (args, extend) {
        var x = getArgFloat(args[1]);
        var y = getArgFloat(args[2]);
        $gameMap.spawnEvent(this.getEventIdForEventReSpawn(args[0], extend), x, y, extend);
    };

    Game_Interpreter.prototype.execMakeEventRandom = function (args, extend) {
        var conditionMap = {};
        conditionMap.passable = getArgNumber(args[1], 0);
        conditionMap.screen = getArgNumber(args[2], 0);
        conditionMap.collided = getArgNumber(args[3], 0);
        conditionMap.terrainTags = (args[4] || '').split(',').map(function (value) {
            return getArgNumber(value, 0);
        });
        conditionMap.regionIds = (args[5] || '').split(',').map(function (value) {
            return getArgNumber(value, 0);
        });

        var makeCount = parseInt(args[6]) || 1;
        for (var i = 0; i < makeCount; ++i) {
            $gameMap.spawnEventRandom(this.getEventIdForEventReSpawn(args[0], extend), conditionMap, extend);
        }
    };

    Game_Interpreter.prototype.execMakeTemplateEvent = function (args) {
        this.execMakeEvent(args, true);
    };

    Game_Interpreter.prototype.execMakeTemplateEventRandom = function (args) {
        this.execMakeEventRandom(args, true);
    };

    Game_Interpreter.prototype.execGetLastSpawnEventId = function (args) {
        var eventId = $gameMap.getLastSpawnEventId();
        $gameVariables.setValue(getArgNumber(args[0], 0), eventId);
    };

    Game_Interpreter.prototype.getEventIdForEventReSpawn = function (arg, isTemplate) {
        var id = 0;
        if (!isNaN(convertEscapeCharacters(arg))) {
            id = getArgNumber(arg, 0);
        } else {
            var event = DataManager.searchDataItem(isTemplate ? $dataTemplateEvents : $dataMap.events, 'name', convertEscapeCharacters(arg));    // modified by nekoma.
            id = event ? event.id : 0;
        }
        return id > 0 ? id : this._eventId;
    };

    Game_Interpreter.prototype.changeTryCount = function (args) {
        if (args[0]) param.tryRandomCount = Number(args[0]);
    };

    //=============================================================================
    // Game_Map
    //  イベントのスポーン処理を追加定義します。
    //=============================================================================
    var _Game_Map_setupEvents = Game_Map.prototype.setupEvents;
    Game_Map.prototype.setupEvents = function () {
        if ($gamePlayer.isNeedMapReload()) {
            this.unlinkPrefabEvents();
        }
        _Game_Map_setupEvents.apply(this, arguments);
        this._eventIdSequence = this._events.length || 1;
    };

    Game_Map.prototype.spawnEvent = function (originalEventId, x, y, isTemplate) {
        if (this.isExistEventData(originalEventId, isTemplate) && $gameMap.isValid(x, y)) {
            var eventId = this.getEventIdSequence();
            if (!isTemplate) {
                var originalEvent = this.event(originalEventId);
                if (this.isTemplateSpawn(originalEventId)) {
                    isTemplate = true;
                    originalEventId = originalEvent.getTemplateId();
                }
                if (originalEvent.isPrefab()) {
                    originalEventId = originalEvent.getOriginalEventId();
                }
            }
            var event = new Game_PrefabEvent(this._mapId, eventId, originalEventId, x, y, isTemplate);

            this._lastSpawnEventId = eventId;
            this._events[eventId] = event;
        } else {
            throw new Error('無効なイベントIDもしくは座標のためイベントを作成できませんでした。');
        }
    };

    Game_Map.prototype.isTemplateSpawn = function (originalEventId) {
        var event = this.event(originalEventId);
        return event.hasTemplate && event.hasTemplate();
    };

    Game_Map.prototype.getLastSpawnEventId = function () {
        return this._lastSpawnEventId;
    };

    Game_Map.prototype.isExistEventData = function (eventId, isTemplate) {
        return isTemplate ? !!$dataTemplateEvents[eventId] : !!this.event(eventId);
    };

    Game_Map.prototype.spawnEventRandom = function (originalEventId, conditionMap, isTemplate) {
        var conditions = [];
        conditions.push(this.isValid.bind(this));
        if (conditionMap.passable) {
            conditions.push(this.isErsCheckAnyDirectionPassable.bind(this));
        }
        if (conditionMap.screen) {
            conditions.push(this.isErsCheckScreenInOut.bind(this, conditionMap.screen));
        }
        if (conditionMap.collided) {
            conditions.push(this.isErsCheckCollidedSomeone.bind(this, conditionMap.collided));
        }
        if (conditionMap.terrainTags) {
            conditions.push(this.isErsCheckTerrainTag.bind(this, conditionMap.terrainTags));
        }
        if (conditionMap.regionIds) {
            conditions.push(this.isErsCheckRegionId.bind(this, conditionMap.regionIds));
        }
        var position = this.getConditionalValidPosition(conditions);
        if (position) {
            this.spawnEvent(originalEventId, position.x, position.y, isTemplate);
        } else {
            console.log(conditionMap);
            console.warn('座標の取得に失敗しました。');
        }
    };

    var _Game_Map_eraseEvent = Game_Map.prototype.eraseEvent;
    Game_Map.prototype.eraseEvent = function (eventId) {
        _Game_Map_eraseEvent.apply(this, arguments);
        if (this._events[eventId].isExtinct()) {
            delete this._events[eventId];
        }
    };

    Game_Map.prototype.getEventIdSequence = function () {
        return this._eventIdSequence++;
    };

    Game_Map.prototype.getPrefabEvents = function () {
        return this.events().filter(function (event) {
            return event.isPrefab();
        });
    };

    Game_Map.prototype.resetSelfSwitchForPrefabEvent = function () {
        this.getPrefabEvents().forEach(function (prefabEvent) {
            prefabEvent.eraseSelfSwitch();
        });
    };

    Game_Map.prototype.restoreLinkPrefabEvents = function () {
        if (!this.isSameMapReload()) return;
        this.getPrefabEvents().forEach(function (prefabEvent) {
            prefabEvent.linkEventData();
        });
    };

    Game_Map.prototype.unlinkPrefabEvents = function () {
        this.getPrefabEvents().forEach(function (prefabEvent) {
            prefabEvent.unlinkEventData();
        });
    };

    Game_Map.prototype.isSameMapReload = function () {
        return !$gamePlayer.isTransferring() || this.mapId() === $gamePlayer.newMapId();
    };

    Game_Map.prototype.getConditionalValidPosition = function (conditions) {
        var tryCount = param.tryRandomCount || 1000;
        if (!$gameSwitches.value(param.CertainSpawnSwitch) && tryCount > 0) {
            var x, y, count = 0;
            do {
                x = Math.randomInt($dataMap.width);
                y = Math.randomInt($dataMap.height);
            } while (!conditions.every(this.checkValidPosition.bind(this, x, y)) && ++count < tryCount);
            return count < tryCount ? { x: x, y: y } : null;
        } else {
            var positions = [];
            for (var ix = 0; ix < $dataMap.width; ++ix) for (var iy = 0; iy < $dataMap.height; ++iy) {
                if (conditions.every(this.checkValidPosition.bind(this, ix, iy))) {
                    positions.push({ x: ix, y: iy });
                }
            }
            return positions.length ? positions[Math.randomInt(positions.length)] : null;
        }
    };

    Game_Map.prototype.checkValidPosition = function (x, y, condition) {
        return condition(x, y);
    };

    Game_Map.prototype.isErsCheckAnyDirectionPassable = function (x, y) {
        return [2, 4, 6, 8].some(function (direction) {
            return $gamePlayer.isMapPassable(x, y, direction);
        });
    };

    Game_Map.prototype.isErsCheckScreenInOut = function (type, x, y) {
        return type === 1 ? this.isErsCheckInnerScreen(x, y) : this.isErsCheckOuterScreen(x, y);
    };

    Game_Map.prototype.isErsCheckInnerScreen = function (x, y) {
        var ax = this.adjustX(x);
        var ay = this.adjustY(y);
        return ax >= 0 && ay >= 0 && ax <= this.screenTileX() - 1 && ay <= this.screenTileY() - 1;
    };

    Game_Map.prototype.isErsCheckOuterScreen = function (x, y) {
        var ax = this.adjustX(x);
        var ay = this.adjustY(y);
        return ax < -1 || ay < -1 || ax > this.screenTileX() || ay > this.screenTileY();
    };

    Game_Map.prototype.isErsCheckCollidedSomeone = function (type, x, y) {
        if ((type === 1 || type === 3) && $gamePlayer.isCollided(x, y)) {
            return false;
        }
        if ((type === 2 || type === 3) && $gameMap.eventIdXy(x, y) > 0) {
            return false;
        }
        return true;
    };

    Game_Map.prototype.isErsCheckTerrainTag = function (type, x, y) {
        return type.some(function (id) {
            return !id || id === this.terrainTag(x, y);
        }, this);
    };

    Game_Map.prototype.isErsCheckRegionId = function (type, x, y) {
        return type.some(function (id) {
            return !id || id === this.regionId(x, y);
        }, this);
    };

    //=============================================================================
    // Game_CharacterBase
    //   プレハブイベントとそうでないキャラクターを区別します。
    //=============================================================================
    Game_CharacterBase.prototype.isPrefab = function () {
        return false;
    };

    Game_CharacterBase.prototype.isExtinct = function () {
        return this.isPrefab() && this._erased;
    };

    //=============================================================================
    // Game_PrefabEvent
    //  動的に生成されるイベントオブジェクトです。
    //=============================================================================
    Game_PrefabEvent.prototype = Object.create(Game_Event.prototype);
    Game_PrefabEvent.prototype.constructor = Game_PrefabEvent;

    Game_PrefabEvent.prototype.initialize = function (mapId, eventId, originalEventId, x, y, isTemplate) {
        this._originalEventId = originalEventId;
        this._eventId = eventId;
        this._isTemplate = isTemplate;
        this.linkEventData();
        Game_Event.prototype.initialize.call(this, mapId, eventId);
        if (typeof Yanfly !== 'undefined' && Yanfly.SEL) {
            $gameTemp._bypassLoadLocation = true;
            this.locateWithoutStraighten(x, y);
            $gameTemp._bypassLoadLocation = undefined;
        } else {
            this.locateWithoutStraighten(x, y);
        }
        this._spritePrepared = false;
    };

    Game_PrefabEvent.prototype.locateWithoutStraighten = function (x, y) {
        this.setPosition(x, y);
        this.refreshBushDepth();
    };

    // for TemplateEvent.js
    Game_PrefabEvent.prototype.generateTemplateId = function (event) {
        return this._isTemplate ? this._originalEventId : null;
    };

    Game_PrefabEvent.prototype.linkEventData = function () {
        $dataMap.events[this._eventId] = (this._isTemplate ?
            $dataTemplateEvents[this._originalEventId] : $dataMap.events[this._originalEventId]);
    };

    Game_PrefabEvent.prototype.unlinkEventData = function () {
        $dataMap.events[this._eventId] = null;
    };

    Game_PrefabEvent.prototype.isPrefab = function () {
        return true;
    };

    Game_PrefabEvent.prototype.erase = function () {
        Game_Event.prototype.erase.call(this);
        this.eraseSelfSwitch();
        delete $dataMap.events[this._eventId];
    };

    Game_PrefabEvent.prototype.isSpritePrepared = function () {
        return this._spritePrepared;
    };

    Game_PrefabEvent.prototype.setSpritePrepared = function () {
        this._spritePrepared = true;
    };

    Game_PrefabEvent.prototype.eraseSelfSwitch = function () {
        ['A', 'B', 'C', 'D'].forEach(function (swCode) {
            var key = [this._mapId, this._eventId, swCode];
            $gameSelfSwitches.setValue(key, undefined);
        }.bind(this));
    };

    Game_PrefabEvent.prototype.getOriginalEventId = function () {
        return this._originalEventId;
    };

    Game_Event.prototype.getOriginalEventId = function () {
        return 0;
    };

    //=============================================================================
    // Game_Player
    //  プロジェクト再保存によるマップリロードかどうかの判定を取得します。
    //=============================================================================
    Game_Player.prototype.isNeedMapReload = function () {
        return this._needsMapReload;
    };

    //=============================================================================
    // Sprite
    //  SpriteIDの付与に使用するカウンターを取得します。
    //=============================================================================
    Sprite.getCounter = function () {
        return this._counter;
    };

    //=============================================================================
    // Sprite_Character
    //  対象キャラクターの消去判定を追加定義します。
    //=============================================================================
    Sprite_Character.prototype.isCharacterExtinct = function () {
        return this._character.isExtinct();
    };

    Sprite_Character.prototype.endAllEffect = function () {
        this.endBalloon();
        this.endAnimation();
    };

    Sprite_Character.prototype.endAnimation = function () {
        if (this._animationSprites.length > 0) {
            var sprites = this._animationSprites.clone();
            this._animationSprites = [];
            sprites.forEach(function (sprite) {
                sprite.remove();
            });
        }
    };

    //=============================================================================
    // Spriteset_Map
    //  プレハブイベントのスプライトを管理します。
    //=============================================================================
    var _Spriteset_Map_createCharacters = Spriteset_Map.prototype.createCharacters;
    Spriteset_Map.prototype.createCharacters = function () {
        this._prefabSpriteId = Sprite.getCounter() + 1;
        _Spriteset_Map_createCharacters.apply(this, arguments);
    };

    var _Spriteset_Map_update = Spriteset_Map.prototype.update;
    Spriteset_Map.prototype.update = function () {
        _Spriteset_Map_update.apply(this, arguments);
        this.updatePrefabEvent();
    };

    Spriteset_Map.prototype.updatePrefabEvent = function () {
        $gameMap.getPrefabEvents().forEach(function (event) {
            if (!event.isSpritePrepared()) {
                this.makePrefabEventSprite(event);
            }
        }.bind(this));
        for (var i = 0, n = this._characterSprites.length; i < n; i++) {
            if (this._characterSprites[i].isCharacterExtinct()) {
                this.removePrefabEventSprite(i--);
                n--;
            }
        }
    };

    Spriteset_Map.prototype.makePrefabEventSprite = function (event) {
        event.setSpritePrepared();
        var sprite = new Sprite_Character(event);
        sprite.spriteId = this._prefabSpriteId;
        this._characterSprites.push(sprite);
        this._tilemap.addChild(sprite);
        this._tilemap._sortChildren();
        if (this._minimap && this._minimap.addObjectSprites) {
            this._minimap.addObjectSprites(event);
        }
        // Resolve conflict by MOG_EventText.js
        if (this._etextField) {
            this.refresh_event_text_field();
        }
        // Resolve conflict by MOG_EventIndicators.js
        if (this._eventIndicators && typeof EventIndicators !== 'undefined') {
            var indicator = new EventIndicators(sprite);
            this._eventIndicators.push(indicator);
            this._indicatorsField.addChild(indicator);
        }
    };

    // Resolve conflict by MOG_EventText.js
    Spriteset_Map.prototype.refresh_event_text_field = function () {
        for (var i = 0; i < this._characterSprites.length; i++) {
            if (!this._sprite_char_text[i]) {
                this._sprite_char_text[i] = new Sprite_CharText(this._characterSprites[i]);
                this._etextField.addChild(this._sprite_char_text[i]);
            }
        }
    };

    Spriteset_Map.prototype.removePrefabEventSprite = function (index) {
        var sprite = this._characterSprites[index];
        this._characterSprites.splice(index, 1);
        sprite.endAllEffect();
        this._tilemap.removeChild(sprite);
        // Resolve conflict by MOG_EventText.js
        if (this._sprite_char_text && this._sprite_char_text[index]) {
            this._etextField.removeChild(this._sprite_char_text[index]);
            this._sprite_char_text.splice(index, 1);
        }
        // Resolve conflict by MOG_EventIndicators.js
        if (this._eventIndicators && typeof EventIndicators !== 'undefined') {
            var indicator = this._eventIndicators[index];
            this._eventIndicators.splice(index, 1);
            this._indicatorsField.removeChild(indicator);
        }
    };

    //=============================================================================
    // Scene_Map
    //  場所移動時にセルフスイッチの情報を初期化します。
    //=============================================================================
    var _Scene_Map_create = Scene_Map.prototype.create;
    Scene_Map.prototype.create = function () {
        _Scene_Map_create.apply(this, arguments);
        if (this._transfer && !param.keepSelfSwitch) {
            $gameMap.resetSelfSwitchForPrefabEvent();
        }
    };

    //=============================================================================
    // DataManager
    //  マップデータのロード完了時にプレハブイベントのリンク先を復元します。
    //=============================================================================
    var _DataManager_onLoad = DataManager.onLoad;
    DataManager.onLoad = function (object) {
        _DataManager_onLoad.apply(this, arguments);
        if (object === $dataMap && $gameMap) $gameMap.restoreLinkPrefabEvents();
    };

    if (typeof Window_EventMiniLabel !== 'undefined') {
        var _Window_EventMiniLabel_gatherDisplayData = Window_EventMiniLabel.prototype.gatherDisplayData
        Window_EventMiniLabel.prototype.gatherDisplayData = function () {
            if (!this._character.event()) {
                return;
            }
            _Window_EventMiniLabel_gatherDisplayData.apply(this, arguments);
        };
    }
})();


code:
//=============================================================================
// ExcludeStatus.js
// ----------------------------------------------------------------------------
// <利用規約>
//  利用はRPGツクールMV/RPGMakerMVの正規ユーザーに限られます。
//  商用、非商用、ゲームの内容を問わず利用可能です。
//  ゲームへの利用の際、報告や出典元の記載等は必須ではありません。
//  二次配布や転載は禁止します。
//  ソースコードURL、ダウンロードURLへの直接リンクも禁止します。
//  不具合対応以外のサポートやリクエストは受け付けておりません。
//  スクリプト利用により生じたいかなる問題においても、一切責任を負いかねます。
// ----------------------------------------------------------------------------
//  Ver1.01  2016/01/30  装備画面に対応しました。
//  Ver1.00  2016/01/29  初版
//=============================================================================

/*:
 * @plugindesc 指定したステータス項目を、ステータス画面と装備画面に表示しないようにします。
 * @author こま
 *
 * @param Exclude Status
 * @desc ステータス画面と装備画面で表示しない項目を指定します。
 *（詳細はヘルプを参照）
 * @default 0
 *
 * @help Exclude Statusパラメータに、非表示にしたい項目を指定してください。
 * 項目はカンマ区切りで複数指定できます。
 *
 * 1：攻撃力
 * 2：防御力
 * 3：魔法力
 * 4：魔法防御
 * 5：敏捷性
 * 6：運
 *
 * 3,4と指定すると、魔法力と魔法防御を表示しなくなります。
 */

(function () {
    var parameters = PluginManager.parameters('ExcludeStatus');
    var ExcludeStatus = parameters['Exclude Status'];

    ExcludeStatus = ExcludeStatus.split(',');

    Window_Status.prototype.drawParameters = function (x, y) {
        var lineHeight = this.lineHeight();
        var line = 0;
        for (var i = 0; i < 6; i++) {
            if (!ExcludeStatus.some(function (s) { return i + 1 === Number(s); })) {
                var paramId = i + 2;
                var y2 = y + lineHeight * line;
                this.changeTextColor(this.systemColor());
                this.drawText(TextManager.param(paramId), x, y2, 160);
                this.resetTextColor();
                this.drawText(this._actor.param(paramId), x + 160, y2, 60, 'right');
                line++;
            }
        }
    };

    Window_EquipStatus.prototype.refresh = function () {
        this.contents.clear();
        if (this._actor) {
            this.drawActorName(this._actor, this.textPadding(), 0);
            var line = 0;
            for (var i = 0; i < 6; i++) {
                if (!ExcludeStatus.some(function (s) { return i + 1 === Number(s); })) {
                    this.drawItem(0, this.lineHeight() * (1 + line), 2 + i);
                    line++;
                }
            }
        }
    };
}());

repo_name: dazed/translations

license: unknown


code:
/*=============================================================================
 FixChoiceListWindowY.js
----------------------------------------------------------------------------
 (C)2020 Triacontane
 This software is released under the MIT License.
 http://opensource.org/licenses/mit-license.php
----------------------------------------------------------------------------
 Version
 1.0.1 2020/10/18 数値入力ウィンドウも同様の仕様に変更
 1.0.0 2020/10/18 初版
----------------------------------------------------------------------------
 [Blog]   : https://triacontane.blogspot.jp/
 [Twitter]: https://twitter.com/triacontane/
 [GitHub] : https://github.com/triacontane/
=============================================================================*/

/*:
 * @plugindesc FixChoiceListWindowYPlugin
 * @author triacontane
 *
 * @param y
 * @text Y座標
 * @desc Y of the choice window when the message window is not displayed
 * @default
 *
 * @help FixChoiceListWindowY.js
 *
 * Fix the Y of the choice window when the message window
 * is not displayed to the value set by the parameter.
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc 選択肢ウィンドウのY座標固定パッチ
 * @author トリアコンタン
 *
 * @param y
 * @text Y座標
 * @desc メッセージウィンドウが表示されていない状態での選択肢ウィンドウのY座標(原点は中央)
 * @default 312
 * @type number
 *
 * @help FixChoiceListWindowY.js
 *
 * メッセージウィンドウが表示されていない状態での
 * 選択肢ウィンドウのY座標をパラメータで設定した値に固定します。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
    'use strict';

    var paramY = parseInt(PluginManager.parameters('FixChoiceListWindowY').y);

    var _Window_ChoiceList_updatePlacement = Window_ChoiceList.prototype.updatePlacement;
    Window_ChoiceList.prototype.updatePlacement = function () {
        _Window_ChoiceList_updatePlacement.apply(this, arguments);
        if (this._messageWindow.isClosed()) {
            this.y = paramY - this.height / 2;
        }
    };

    var _Window_NumberInput_updatePlacement = Window_NumberInput.prototype.updatePlacement;
    Window_NumberInput.prototype.updatePlacement = function () {
        _Window_NumberInput_updatePlacement.apply(this, arguments);
        if (this._messageWindow.isClosed()) {
            this.y = paramY - this.height / 2;
        }
    };
})();


code:
//=============================================================================
// FloatVariables.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015-2016 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.1.0 2017/09/15 型指定機能に対応
// 1.0.0 2016/07/30 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc FloatVariablesPlugin
 * @author triacontane
 *
 * @param FloatVariableStart
 * @desc 小数演算を行う変数の開始位置です。
 * @default 0
 * @type variable
 *
 * @param FloatVariableEnd
 * @desc 小数演算を行う変数の終了位置です。
 * @default 0
 * @type variable
 *
 * @help FloatVariables.js
 *
 * 指定した範囲内の変数を小数演算可能にします。
 *
 * ・通常(整数演算)の場合
 * 3 / 2 = 1
 *
 * ・小数演算の場合
 * 3 / 2 = 1.5
 *
 * 小数が代入されている変数をイベントコマンドのオペランドとして
 * 使用すると予期しない問題が発生する可能性があります。
 * (HPに0.5を加算するなど)
 *
 * 注意して利用してください。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */
/*:
 * @plugindesc 変数の小数演算プラグイン
 * @author トリアコンタン
 *
 * @param 小数変数開始位置
 * @desc 小数演算を行う変数の開始位置です。
 * @default 0
 * @type variable
 *
 * @param 小数変数終了位置
 * @desc 小数演算を行う変数の終了位置です。
 * @default 0
 * @type variable
 *
 * @help FloatVariables.js
 *
 * 指定した範囲内の変数を小数演算可能にします。
 *
 * ・通常(整数演算)の場合
 * 3 / 2 = 1
 *
 * ・小数演算の場合
 * 3 / 2 = 1.5
 *
 * 小数が代入されている変数をイベントコマンドのオペランドとして
 * 使用すると予期しない問題が発生する可能性があります。
 * (HPに0.5を加算するなど)
 *
 * 注意して利用してください。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
    'use strict';
    var pluginName = 'FloatVariables';

    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 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 paramFloatVariableStart = getParamNumber(['FloatVariableStart', '小数変数開始位置']);
    var paramFloatVariableEnd = getParamNumber(['FloatVariableEnd', '小数変数終了位置']);

    var _Game_Variables_setValue = Game_Variables.prototype.setValue;
    Game_Variables.prototype.setValue = function (variableId, value) {
        if (variableId >= paramFloatVariableStart && variableId <= paramFloatVariableEnd) {
            if (variableId > 0 && variableId < $dataSystem.variables.length) {
                this._data[variableId] = value;
                this.onChange();
            }
        } else {
            _Game_Variables_setValue.apply(this, arguments);
        }
    };
})();


code:
//=============================================================================
// FloatingCharacter.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.1.1 2016/04/06 本プラグインを適用していないセーブデータをロードしたときも、正しく動作するよう修正
// 1.1.0 2016/04/03 一定以上の高度の場合のみ通行可能になる地形タグとリージョンを指定できる機能を追加
//                  着地可能な場合のみ着地する機能を追加、指定されたキャラクターが浮遊中かどうかの判定を追加
// 1.0.2 2016/03/31 隊列歩行でない場合のフォロワーや画像が指定されていないイベントでも影が表示される不具合を修正
// 1.0.1 2016/03/31 浮遊中に強制的に待機アニメが設定される仕様を撤廃
// 1.0.0 2016/03/29 初版
// ----------------------------------------------------------------------------
// [Blog]   : http://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc Floating character plugin
 * @author triacontane
 *
 * @param TerrainTags
 * @desc 浮遊時に通行可能になる地形タグです。カンマ区切りで指定
 * 例：1,2,3
 * @default
 *
 * @param RegionId
 * @desc 浮遊時に通行可能になるリージョンです。カンマ区切りで指定
 * 例：1,2,3
 * @default
 *
 * @param HighestTerrainTags
 * @desc 一定高度以上を浮遊時に通行可能になる地形タグです。
 * 例：1,2,3
 * @default
 *
 * @param HighestRegionId
 * @desc 一定高度以上を浮遊時に通行可能になるリージョンです。
 * 例：1,2,3
 * @default
 *
 * @param HighestThreshold
 * @desc 一定高度以上の条件となる敷居値です。
 * @default 48
 *
 * @help キャラクターを浮遊させます。
 * 浮遊中は以下の効果があります。
 *
 * 指定した地形タグ(複数)を通行可能にします。
 * 指定したリージョン(複数)を通行可能にします。
 * タイルの梯子属性、茂み属性、ダメージ床属性を無効にします。
 *
 * Script
 * 「移動ルートの指定」の「スクリプト」から以下を実行します。
 *
 * this.float([ウェイトフラグ], [高度(省略時はタイルサイズの半分)]);
 *  キャラクターを[高度]のピクセル分、浮遊させます。
 *  [ウェイトフラグ]に[true]を設定すると、浮遊完了まで次の命令に移行しません。
 *  例：this.float(true, 48);
 *
 * this.landing([ウェイトフラグ]);
 *  キャラクターを着地させます。
 *  [ウェイトフラグ]に[true]を設定すると、着地完了まで次の命令に移行しません。
 *  例：this.landing(true);
 *
 * this.landingIfOk([ウェイトフラグ]);
 *  着地可能な地形の場合、キャラクターを着地させます。
 *  着地可能かどうかは、飛行船が着地可能かどうかの条件と同一です。
 *  [ウェイトフラグ]に[true]を設定すると、着地完了まで次の命令に移行しません。
 *  例：this.landingIfOk(true);
 *
 * Script
 * 「条件分岐」の「スクリプト」から以下を実行します。
 *
 * this.isFloating([キャラクターID]);
 *  指定したキャラクターが浮遊中の場合に、分岐を実行します。
 *  キャラクターIDは以下の通り指定してください。
 *
 *  -1   : プレイヤー
 *  0    : 実行中のイベント
 *  1... : 指定したIDのイベント
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc キャラクターの浮遊プラグイン
 * @author トリアコンタン
 *
 * @param 通行可能地形タグ
 * @desc 浮遊時に通行可能になる地形タグです。カンマ区切りで指定
 * 例：1,2,3
 * @default
 *
 * @param 通行可能リージョン
 * @desc 浮遊時に通行可能になるリージョンです。カンマ区切りで指定
 * 例：1,2,3
 * @default
 *
 * @param 高度通行地形タグ
 * @desc 一定高度以上を浮遊時に通行可能になる地形タグです。
 * 例：1,2,3
 * @default
 *
 * @param 高度通行リージョン
 * @desc 一定高度以上を浮遊時に通行可能になるリージョンです。
 * 例：1,2,3
 * @default
 *
 * @param 高度敷居値
 * @desc 一定高度以上の条件となる敷居値です。
 * @default 48
 *
 * @help キャラクターを浮遊させます。
 * 浮遊中は以下の効果があります。
 *
 * 指定した地形タグ(複数)を通行可能にします。
 * 指定したリージョン(複数)を通行可能にします。
 * タイルの梯子属性、茂み属性、ダメージ床属性を無効にします。
 *
 * スクリプト
 * 「移動ルートの指定」の「スクリプト」から以下を実行します。
 *
 * this.float([ウェイトフラグ], [高度(省略時はタイルサイズの半分)]);
 *  キャラクターを[高度]のピクセル分、浮遊させます。
 *  [ウェイトフラグ]に[true]を設定すると、浮遊完了まで次の命令に移行しません。
 *  例：this.float(true, 48);
 *
 * this.landing([ウェイトフラグ]);
 *  キャラクターを着地させます。
 *  [ウェイトフラグ]に[true]を設定すると、着地完了まで次の命令に移行しません。
 *  例：this.landing(true);
 *
 * this.landingIfOk([ウェイトフラグ]);
 *  着地可能な地形の場合、キャラクターを着地させます。
 *  着地可能かどうかは、飛行船が着地可能かどうかの条件と同一です。
 *  [ウェイトフラグ]に[true]を設定すると、着地完了まで次の命令に移行しません。
 *  例：this.landingIfOk(true);
 *
 * スクリプト
 * 「条件分岐」の「スクリプト」から以下を実行します。
 *
 * this.isFloating([キャラクターID]);
 *  指定したキャラクターが浮遊中の場合に、分岐を実行します。
 *  キャラクターIDは以下の通り指定してください。
 *
 *  -1   : プレイヤー
 *  0    : 実行中のイベント
 *  1... : 指定したIDのイベント
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
    'use strict';
    var pluginName = 'FloatingCharacter';

    var getParamString = function (paramNames) {
        var value = getParamOther(paramNames);
        return value == null ? '' : value;
    };

    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 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 getParamArrayString = function (paramNames) {
        var values = getParamString(paramNames).split(',');
        for (var i = 0; i < values.length; i++) values[i] = values[i].trim();
        return values;
    };

    var getParamArrayNumber = function (paramNames, min, max) {
        var values = getParamArrayString(paramNames);
        if (arguments.length < 2) min = -Infinity;
        if (arguments.length < 3) max = Infinity;
        for (var i = 0; i < values.length; i++) {
            if (!isNaN(parseInt(values[i], 10))) {
                values[i] = (parseInt(values[i], 10) || 0).clamp(min, max);
            } else {
                values.splice(i--, 1);
            }
        }
        return values;
    };

    //=============================================================================
    // パラメータの取得と整形
    //=============================================================================
    var paramTerrainTags = getParamArrayNumber(['通行可能地形タグ', 'TerrainTags']);
    var paramRegionId = getParamArrayNumber(['通行可能リージョン', 'RegionId']);
    var paramHighestTerrainTags = getParamArrayNumber(['高度通行地形タグ', 'HighestTerrainTags']);
    var paramHighestRegionId = getParamArrayNumber(['高度通行リージョン', 'HighestRegionId']);
    var paramHighestThreshold = getParamNumber(['高度敷居値', 'HighestThreshold']);

    //=============================================================================
    // Game_Interpreter
    //  キャラクターの浮遊判定を追加定義します。
    //=============================================================================
    Game_Interpreter.prototype.isFloating = function (characterId) {
        var character = this.character(characterId);
        if (character !== null) {
            return character.isFloating();
        } else {
            return false;
        }
    };

    //=============================================================================
    // Game_CharacterBase
    //  キャラクターの浮遊関連情報を追加定義します。
    //=============================================================================
    var _Game_CharacterBase_initMembers = Game_CharacterBase.prototype.initMembers;
    Game_CharacterBase.prototype.initMembers = function () {
        _Game_CharacterBase_initMembers.apply(this, arguments);
        this.initFloatingInfo();
    };
    Game_CharacterBase.prototype.isLowest = Game_Vehicle.prototype.isLowest;
    Game_CharacterBase.prototype.isHighest = Game_Vehicle.prototype.isHighest;
    Game_CharacterBase.prototype.shadowOpacity = Game_Vehicle.prototype.shadowOpacity;

    Game_CharacterBase.prototype.initFloatingInfo = function () {
        this._altitude = 0;
        this._altitudeAnimeCount = 0;
        this._maxAltitude = 0;
        this._needFloat = false;
    };

    var _Game_CharacterBase_isMapPassable = Game_CharacterBase.prototype.isMapPassable;
    Game_CharacterBase.prototype.isMapPassable = function (x, y, d) {
        if (this.isNeedFloat()) {
            var x2 = $gameMap.roundXWithDirection(x, d);
            var y2 = $gameMap.roundYWithDirection(y, d);
            if (paramRegionId.some(function (id) {
                return id === $gameMap.regionId(x2, y2);
            }.bind(this))) return true;
            if (paramTerrainTags.some(function (id) {
                return id === $gameMap.terrainTag(x2, y2);
            }.bind(this))) return true;
            if (this._altitude >= paramHighestThreshold) {
                if (paramHighestRegionId.some(function (id) {
                    return id === $gameMap.regionId(x2, y2);
                }.bind(this))) return true;
                if (paramHighestTerrainTags.some(function (id) {
                    return id === $gameMap.terrainTag(x2, y2);
                }.bind(this))) return true;
            }
        }
        return _Game_CharacterBase_isMapPassable.apply(this, arguments);
    };

    var _Game_CharacterBase_screenY = Game_CharacterBase.prototype.screenY;
    Game_CharacterBase.prototype.screenY = function () {
        return _Game_CharacterBase_screenY.apply(this, arguments) +
            (this.isFloating() ? Math.floor(Math.sin(this._altitudeAnimeCount / 16) * 3) - this._altitude : 0);
    };

    var _Game_CharacterBase_screenZ = Game_CharacterBase.prototype.screenZ;
    Game_CharacterBase.prototype.screenZ = function () {
        return _Game_CharacterBase_screenZ.apply(this, arguments) +
            (this._altitude >= $gameMap.tileHeight() ? 1 : 0);
    };

    Game_CharacterBase.prototype.screenShadowY = function () {
        return _Game_CharacterBase_screenY.apply(this, arguments) - this.screenY();
    };

    var _Game_CharacterBase_isOnLadder = Game_CharacterBase.prototype.isOnLadder;
    Game_CharacterBase.prototype.isOnLadder = function () {
        return this.isFloating() ? false : _Game_CharacterBase_isOnLadder.apply(this, arguments);
    };

    var _Game_CharacterBase_isOnBush = Game_CharacterBase.prototype.isOnBush;
    Game_CharacterBase.prototype.isOnBush = function () {
        return this.isFloating() ? false : _Game_CharacterBase_isOnBush.apply(this, arguments);
    };

    var _Game_Player_isOnDamageFloor = Game_Player.prototype.isOnDamageFloor;
    Game_Player.prototype.isOnDamageFloor = function () {
        return this.isFloating() ? false : _Game_Player_isOnDamageFloor.apply(this, arguments);
    };

    Game_CharacterBase.prototype.maxAltitude = function () {
        return this._maxAltitude;
    };

    Game_CharacterBase.prototype.isFloating = function () {
        return this._altitude > 0;
    };

    Game_CharacterBase.prototype.isShadowVisible = function () {
        return this.isFloating() && (this._characterName || this._tileId);
    };

    Game_CharacterBase.prototype.isNeedFloat = function () {
        return this._needFloat;
    };

    Game_CharacterBase.prototype.float = function (waitFlg, max) {
        if (!this.hasOwnProperty('_altitude') || isNaN(this._altitude)) {
            this.initFloatingInfo();
        }
        if (!max) max = $gameMap.tileHeight() / 2;
        this._needFloat = true;
        this._maxAltitude = max;
        if (waitFlg) this._waitCount = Math.max(this.maxAltitude() - this._altitude, 0);
    };

    Game_Player.prototype.float = function (max) {
        Game_CharacterBase.prototype.float.apply(this, arguments);
        this.followers().forEach(function (follower) {
            follower.float(max);
            follower._altitude = -follower._memberIndex * 4;
        }.bind(this));
    };

    Game_CharacterBase.prototype.landing = function (waitFlg) {
        this._needFloat = false;
        if (waitFlg) this._waitCount = this.maxAltitude();
    };

    Game_CharacterBase.prototype.landingIfOk = function (waitFlg) {
        if ($gameMap.isAirshipLandOk(this.x, this.y)) this.landing(waitFlg);
    };

    Game_Player.prototype.landing = function () {
        Game_CharacterBase.prototype.landing.apply(this, arguments);
        this.followers().forEach(function (follower) {
            follower.landing();
        }.bind(this));
    };

    var _Game_CharacterBase_update = Game_CharacterBase.prototype.update;
    Game_CharacterBase.prototype.update = function () {
        _Game_CharacterBase_update.apply(this, arguments);
        this.updateFloating();
    };

    Game_CharacterBase.prototype.updateFloating = function () {
        this._floatingPrev = this.isFloating();
        if (this.isNeedFloat()) {
            if (this.isHighest()) {
                this._altitudeAnimeCount++;
            }
            this._altitude = Math.min(this._altitude + 1, this.maxAltitude());
        } else {
            if (this.isHighest()) {
                this._altitudeAnimeCount = 0;
            }
            this._altitude = Math.max(this._altitude - 1, 0);
        }
        if (this._floatingPrev != this.isFloating()) {
            this.refreshBushDepth();
        }
    };

    Game_Vehicle.prototype.updateFloating = function () { };
    Game_Vehicle.prototype.isFloating = function () {
        return false;
    };

    //=============================================================================
    // Game_CharacterBase
    //  キャラクターの浮遊関連情報を追加定義します。
    //=============================================================================
    var _Sprite_Character_initMembers = Sprite_Character.prototype.initMembers;
    Sprite_Character.prototype.initMembers = function () {
        _Sprite_Character_initMembers.apply(this, arguments);
        this._shadowSprite = null;
    };

    var _Sprite_Character_update = Sprite_Character.prototype.update;
    Sprite_Character.prototype.update = function () {
        _Sprite_Character_update.apply(this, arguments);
        this.updateFloating();
    };

    Sprite_Character.prototype.updateFloating = function () {
        if (this._character.isShadowVisible()) {
            if (!this._shadowSprite) this.createShadow();
            this._shadowSprite.y = this._character.screenShadowY();
            this._shadowSprite.opacity = this._character.shadowOpacity();
        } else {
            if (this._shadowSprite) this.disposeShadow();
        }
    };

    Sprite_Character.prototype.createShadow = function () {
        this._shadowSprite = new Sprite();
        this._shadowSprite.bitmap = ImageManager.loadSystem('Shadow1');
        this._shadowSprite.anchor.x = 0.5;
        this._shadowSprite.anchor.y = 1;
        this.addChild(this._shadowSprite);
    };

    Sprite_Character.prototype.disposeShadow = function () {
        this.removeChild(this._shadowSprite);
        this._shadowSprite = null;
    };
})();


code:
//=============================================================================
// FootstepSound.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.0.0 2016/02/18 初版
// ----------------------------------------------------------------------------
// [Blog]   : http://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc 足音プラグイン
 * @author トリアコンタン
 *
 * @param イベント実行中無効
 * @desc イベント実行中は足音を無効にする。（ON/OFF）
 * @default OFF
 *
 * @help 以下の状況下で指定した足音効果音を演奏します。
 * 数字の小さい方が優先度が高いです。
 * 1.  飛行船乗船時
 * 2.  大型船乗船時
 * 3.  小型船乗船時
 * 4.  指定リージョン通過時
 * 5.  ダメージ床属性通過時
 * 6.  茂み属性通過時
 * 7.  カウンター属性通過時
 * 8.  梯子属性通過時
 * 9.  指定地形タグ通過時
 * 10. 常に
 *
 * 効果音を指定する場合、当ファイル「FootstepSound.js」を
 * テキストエディタで開き「ユーザ書き換え領域」と書かれている
 * 部分を注釈に従って修正してください。
 *
 * 要注意！　指定した効果音は、デプロイメント時に
 * 未使用ファイルとして除外される可能性があります。
 * その場合、削除されたファイルを入れ直す等の対応が必要です。
 *
 * 足音が演奏されるのはプレイヤーのみですが、
 * 「移動ルートの指定」の「スクリプト」から以下を実行すると
 * イベントにも足音が演奏されるようになります。
 *
 * 足音を演奏する　：this.setStepSoundFlg(true);
 * 足音を演奏しない：this.setStepSoundFlg(false);
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （引数の間は半角スペースで区切る）
 *
 * 足音無効化 or FS_INVALID_SOUND
 *   一時的に全ての足音を無効にします。
 * 例：足音無効化
 *
 * 足音有効化 or FS_VALID_SOUND
 *   全ての足音を有効に戻します。
 * 例：足音有効化
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
    //=============================================================================
    // ユーザ書き換え領域 - 開始 -
    //  name   : 効果音名称(拡張子不要)
    //  volume : 音量(0...100)
    //  pitch  : ピッチ(50...150)
    //  pan    : 位相(-100...100)
    // ※コピー＆ペーストしやすくするために最後の項目にもカンマを付与しています。
    //=============================================================================
    var footStepJson = {
        // walk1:歩行時の効果音1
        // walk2:歩行時の効果音2
        // dash1:ダッシュ時の効果音1
        // dash2:ダッシュ時の効果音2
        // interval:効果音を演奏する間隔（1の場合は1歩ごと）

        // 常に演奏される足音
        always: {
            interval: 1,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash1: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // 梯子属性通過時の足音
        ladder: {
            interval: 1,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash1: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // カウンター属性通過時の足音
        counter: {
            interval: 1,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash1: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // 茂み属性通過時の足音
        bush: {
            interval: 1,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash1: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // ダメージ床属性通過時の足音
        damageFloor: {
            interval: 1,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash1: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // 小型船乗船時の足音
        boat: {
            interval: 4,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // 大型船乗船時の足音
        ship: {
            interval: 4,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // 飛行船船乗船時の足音
        airship: {
            interval: 4,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // 地形タグ 1 通過時の足音（2以降はコピーするか以下の通り値を変更してください）
        // terrainTag1 → terrainTag2
        terrainTag1: {
            interval: 1,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash1: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
        // リージョン 1 通過時の足音（2以降はコピーするか以下の通り値を変更してください）
        // region1 → region2
        region1: {
            interval: 1,
            walk1: { name: '', volume: 90, pitch: 100, pan: 0 },
            walk2: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash1: { name: '', volume: 90, pitch: 100, pan: 0 },
            dash2: { name: '', volume: 90, pitch: 100, pan: 0 },
        },
    };
    //=============================================================================
    // ユーザ書き換え領域 - 終了 -
    //=============================================================================
    var pluginName = 'FootstepSound';

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

    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 paramEventRunningInvalid = getParamBoolean(['イベント実行中無効', 'EventRunningInvalid']);

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

    //=============================================================================
    // Game_Interpreter
    //  プラグインコマンドを追加定義します。
    //=============================================================================
    var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.apply(this, arguments);
        try {
            this.pluginCommandFootstep(command, args);
        } catch (e) {
            if ($gameTemp.isPlaytest() && Utils.isNwjs()) {
                var window = require('nw.gui').Window.get();
                if (!window.isDevToolsOpen()) {
                    var devTool = window.showDevTools();
                    devTool.moveTo(0, 0);
                    devTool.resizeTo(Graphics.width, Graphics.height);
                    window.focus();
                }
            }
            console.log('プラグインコマンドの実行中にエラーが発生しました。');
            console.log('- コマンド名 　: ' + command);
            console.log('- コマンド引数 : ' + args);
            console.log('- エラー原因   : ' + e.toString());
        }
    };

    Game_Interpreter.prototype.pluginCommandFootstep = function (command, args) {
        switch (getCommandName(command)) {
            case 'FS_INVALID_SOUND':
            case '足音無効化':
                $gameSystem.footstepDisable = true;
                break;
            case 'FS_VALID_SOUND':
            case '足音有効化':
                $gameSystem.footstepDisable = false;
                break;
        }
    };

    //=============================================================================
    // Game_CharacterBase
    //  足音効果音の演奏処理を追加します。
    //=============================================================================
    var _Game_CharacterBase_initMembers = Game_CharacterBase.prototype.initMembers;
    Game_CharacterBase.prototype.initMembers = function () {
        _Game_CharacterBase_initMembers.apply(this, arguments);
        this.setStepSoundFlg(false);
        this._stepToggle = null;
        this._stepCountForSound = null;
    };

    var _Game_CharacterBase_increaseSteps = Game_CharacterBase.prototype.increaseSteps;
    Game_CharacterBase.prototype.increaseSteps = function () {
        _Game_CharacterBase_increaseSteps.apply(this, arguments);
        if (!this.isPlayStepSound() || $gameSystem.footstepDisable ||
            ($gameMap.isEventRunning() && paramEventRunningInvalid)) return;
        var soundsHash = [
            { key: 'airship', condition: this.isInAirship.bind(this) },
            { key: 'ship', condition: this.isInShip.bind(this) },
            { key: 'boat', condition: this.isInBoat.bind(this) },
            { key: 'region' + this.regionId(), condition: function () { return true; } },
            { key: 'damageFloor', condition: this.isOnDamageFloor.bind(this) },
            { key: 'bush', condition: this.isOnBush.bind(this) },
            { key: 'counter', condition: this.isOnCounter.bind(this) },
            { key: 'ladder', condition: this.isOnLadder.bind(this) },
            { key: 'terrainTag' + this.terrainTag(), condition: function () { return true; } },
            { key: 'always', condition: function () { return true; } }
        ];
        soundsHash.some(function (data) {
            return this.playStepSound(data.key, data.condition);
        }.bind(this));
    };

    Game_CharacterBase.prototype.playStepSound = function (typeKey, condition) {
        if (condition() && footStepJson.hasOwnProperty(typeKey)) {
            var soundHash = footStepJson[typeKey];
            if (this._stepCountForSound++ % soundHash.interval === 0) {
                var soundKey = this.isDashing() ? 'dash' : 'walk';
                soundKey += this._stepToggle ? '2' : '1';
                if (soundHash.hasOwnProperty(soundKey)) AudioManager.playSe(soundHash[soundKey]);
                this._stepToggle = !this._stepToggle;
            }
            return true;
        }
        return false;
    };

    Game_CharacterBase.prototype.isOnDamageFloor = function () {
        return $gameMap.isDamageFloor(this.x, this.y);
    };

    Game_CharacterBase.prototype.isOnCounter = function () {
        return $gameMap.isCounter(this.x, this.y);
    };

    Game_CharacterBase.prototype.isInBoat = function () {
        return false;
    };

    Game_CharacterBase.prototype.isInShip = function () {
        return false;
    };

    Game_CharacterBase.prototype.isInAirship = function () {
        return false;
    };

    Game_CharacterBase.prototype.isPlayStepSound = function () {
        return this._stepSoundFlg;
    };

    Game_CharacterBase.prototype.setStepSoundFlg = function (value) {
        this._stepSoundFlg = !!value;
    };

    //=============================================================================
    // Game_Player
    //  キャラクターごとの足音演奏フラグ（プレイヤーは常にON）
    //=============================================================================
    Game_Player.prototype.isPlayStepSound = function () {
        return true;
    };

    //=============================================================================
    // Game_System
    //  足音効果音の有効無効設定を追加定義します。
    //=============================================================================
    var _Game_System_initialize = Game_System.prototype.initialize;
    Game_System.prototype.initialize = function () {
        _Game_System_initialize.apply(this, arguments);
        this.footstepDisable = null;
    };
})();


code:
//=============================================================================
// Gacha.js
//
// (c)2016 KADOKAWA CORPORATION./YOJI OJIMA
//=============================================================================

/*:
 * @plugindesc Get the item at random
 * @author Takeya Kimura
 *
 * @param Help Message Text
 * @desc The help message for gacha window. "Required Amount" is replaced with the Required Amount.
 * @default 1回Required Amount\Gでガチャを引きます
 *
 * @param Button Text
 * @desc The button text for gacha commands.
 * @default ガチャを引く
 *
 * @param Get Message Text
 * @desc The message of After receiving. "Item Name" is replaced with the received item name.
 * @default GET Item Name
 *
 * @param Show Item Description
 * @desc The switch of item description display
 * @default 0
 *
 * @param Effect
 * @desc The animation number for get effect.
 * @default 119
 * @require 1
 * @type animation
 *
 * @param Rank1 Effect
 * @desc The animation number for rank 1 effect. If you specify -1, does not display the animation.
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank2 Effect
 * @desc The animation number for rank 2 effect. If you specify -1, does not display the animation.
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank3 Effect
 * @desc The animation number for rank 3 effect. If you specify -1, does not display the animation.
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank4 Effect
 * @desc The animation number for rank 4 effect. If you specify -1, does not display the animation.
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank5 Effect
 * @desc The animation number for rank 5 effect. If you specify -1, does not display the animation.
 * @default -1
 * @require 1
 * @type animation
 *
 * @param ME
 * @desc The ME name for get music effect.
 * @default Organ
 * @require 1
 * @dir audio/me/
 * @type file
 *
 * @param  Required Amount
 * @desc The Gold for gacha.
 * @default 100
 *
 * @noteParam gachaImage
 * @noteRequire 1
 * @noteDir img/gacha/
 * @noteType file
 * @noteData items
 *
 * @help
 *
 * Plugin Command:
 *   Gacha open                 # Open the Gacha screen
 *   Gacha add item 1           # Add item #1 to the Gacha
 *   Gacha remove item 1        # Remove item #1 from the Gacha
 *   Gacha clear                # Clear the Gacha
 *
 *
 * Item Note:
 *   <gachaImage:image>        # Gacha image file name. Please image put in "img/gacha/" folder.
 *   <gachaNumLot:10>          # The number of the lottery.
 *   <gachaRank:5>             # The rank of the item(1-5).
 */

/*:ja
 * @plugindesc ランダムにアイテムを取得します。
 * @author Takeya Kimura
 *
 * @param Help Message Text
 * @desc ガチャ画面のヘルプメッセージです。「Required Amount」は消費Gと置換されます。
 * @default 1回Required Amount\Gでガチャを引きます
 *
 * @param Button Text
 * @desc ガチャボタンに表示するテキストです。
 * @default ガチャを引く
 *
 * @param Get Message Text
 * @desc ガチャを引いた後のメッセージです。「Item Name」は取得アイテム名と置換されます。
 * @default GET Item Name
 *
 * @param Show Item Description
 * @desc 1でアイテム取得時に説明を表示します。[0: 説明非表示 1: 説明表示]
 * @default 0
 *
 * @param Effect
 * @desc アイテム取得時のアニメーションIDを指定します。
 * @default 119
 * @require 1
 * @type animation
 *
 * @param Rank1 Effect
 * @desc ランク1の時のアニメーションIDを指定します。-1を指定するとアニメーションを表示しません。
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank2 Effect
 * @desc ランク2の時のアニメーションIDを指定します。-1を指定するとアニメーションを表示しません。
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank3 Effect
 * @desc ランク3の時のアニメーションIDを指定します。-1を指定するとアニメーションを表示しません。
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank4 Effect
 * @desc ランク4の時のアニメーションIDを指定します。-1を指定するとアニメーションを表示しません。
 * @default -1
 * @require 1
 * @type animation
 *
 * @param Rank5 Effect
 * @desc ランク5の時のアニメーションIDを指定します。-1を指定するとアニメーションを表示しません。
 * @default -1
 * @require 1
 * @type animation
 *
 * @param ME
 * @desc アイテム取得時のMEを指定します。
 * @default Organ
 * @require 1
 * @dir audio/me/
 * @type file
 *
 * @param  Required Amount
 * @desc ガチャを引くのに必要なGです。
 * @default 100
 *
 * @noteParam gachaImage
 * @noteRequire 1
 * @noteDir img/gacha/
 * @noteType file
 * @noteData items
 *
 * @help
 *
 * Plugin Command:
 *   Gacha open                 # ガチャ画面を開きます。
 *   Gacha add item 1           # アイテム番号1をガチャ対象に追加します。
 *   Gacha remove item 1        # アイテム番号1をガチャ対象から外します。
 *   Gacha clear                # 全てのガチャ対象をクリアします。
 *
 *
 * Item Note:
 *   <gachaImage:image>        # ガチャアイテムの画像を指定します。画像はimg/gacha/フォルダ内に入れてください。
 *   <gachaNumLot:10>          # ガチャアイテムのくじ数を指定します。
 *   <gachaRank:5>             # ガチャアイテムのランクを1から5の間で指定します。
 */

(function () {

    var parameters = PluginManager.parameters('Gacha');
    var message = String(parameters['Help Message Text'] || '1回Required Amount\\Gでガチャを引きます');
    var buttonText = String(parameters['Button Text'] || 'ガチャを引く');
    var getText = String(parameters['Get Message Text'] || 'GET Item Name');
    var itemDescEnable = !!Number(parameters['Show Item Description'] || 0);
    var effect = Number(parameters['Effect'] || '119');
    var rankEffect = [];
    rankEffect.push(Number(parameters['Rank1 Effect'] || '-1'));
    rankEffect.push(Number(parameters['Rank2 Effect'] || '-1'));
    rankEffect.push(Number(parameters['Rank3 Effect'] || '-1'));
    rankEffect.push(Number(parameters['Rank4 Effect'] || '-1'));
    rankEffect.push(Number(parameters['Rank5 Effect'] || '-1'));
    var me = String(parameters['ME'] || 'Organ');
    var amount = Number(parameters['Required Amount'] || '100');
    var reg = /Required Amount/gi;
    message = message.replace(reg, String(amount));

    var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);
        if (command === "Gacha") {
            switch (args[0]) {
                case "open":
                    SceneManager.push(Scene_Gacha);
                    break;

                case 'add':
                    $gameSystem.addToGacha(args[1], Number(args[2]));
                    break;

                case 'remove':
                    $gameSystem.removeFromGacha(args[1], Number(args[2]));
                    break;

                case 'clear':
                    $gameSystem.clearGacha();
                    break;
            }
        }
    };

    Game_System.prototype.addToGacha = function (type, dataId) {
        if (!this._GachaFlags) {
            this.clearGacha();
        }
        var typeIndex = this.gachaTypeToIndex(type);
        if (typeIndex >= 0) {
            this._GachaFlags[typeIndex][dataId] = true;
        }
    };

    Game_System.prototype.removeFromGacha = function (type, dataId) {
        if (this._GachaFlags) {
            var typeIndex = this.gachaTypeToIndex(type);
            if (typeIndex >= 0) {
                this._GachaFlags[typeIndex][dataId] = false;
            }
        }
    };

    Game_System.prototype.gachaTypeToIndex = function (type) {
        switch (type) {
            case 'item':
                return 0;
            case 'weapon':
                return 1;
            case 'armor':
                return 2;
            default:
                return -1;
        }
    };

    Game_System.prototype.clearGacha = function () {
        this._GachaFlags = [[], [], []];
    };

    Game_System.prototype.isInGacha = function (item) {
        if (this._GachaFlags && item) {
            var typeIndex = -1;
            if (DataManager.isItem(item)) {
                typeIndex = 0;
            } else if (DataManager.isWeapon(item)) {
                typeIndex = 1;
            } else if (DataManager.isArmor(item)) {
                typeIndex = 2;
            }
            if (typeIndex >= 0) {
                return !!this._GachaFlags[typeIndex][item.id];
            } else {
                return false;
            }
        } else {
            return false;
        }
    };

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

    Scene_Gacha.prototype = Object.create(Scene_MenuBase.prototype);
    Scene_Gacha.prototype.constructor = Scene_Gacha;

    Scene_Gacha.prototype.initialize = function () {
        Scene_MenuBase.prototype.initialize.call(this);
        this._item = null;
        this._effectPlaying = false;
        this._resultShowing = false;
        this._wait = 0;
        this._effectSprite = null;
        this._windowFadeSprite = null;
        this._screenFadeOutDuration = 0;
        this._screenFadeInDuration = 0;

        this._lot = [];
        var numLot;
        var item, i, j;
        for (i = 1; i < $dataItems.length; i++) {
            item = $dataItems[i];
            if ($gameSystem.isInGacha(item)) {
                numLot = Number(item.meta.gachaNumLot || '0');
                for (j = 0; j < numLot; j++) {
                    this._lot.push(item);
                }
            }
        }
        for (i = 1; i < $dataWeapons.length; i++) {
            item = $dataWeapons[i];
            if ($gameSystem.isInGacha(item)) {
                numLot = Number(item.meta.gachaNumLot || '0');
                for (j = 0; j < numLot; j++) {
                    this._lot.push(item);
                }
            }
        }
        for (i = 1; i < $dataArmors.length; i++) {
            item = $dataArmors[i];
            if ($gameSystem.isInGacha(item)) {
                numLot = Number(item.meta.gachaNumLot || '0');
                for (j = 0; j < numLot; j++) {
                    this._lot.push(item);
                }
            }
        }
    };

    Scene_Gacha.prototype.create = function () {
        Scene_MenuBase.prototype.create.call(this);

        this.createHelpWindow();
        this.createGoldWindow();
        this.createCommandWindow();
        this.createDummyWindow();
        this.createGetCommandWindow();
        this.createGetWindow();

        this._rankSprite = new Sprite_GachaEffect();
        this._rankSprite.keepDisplay(true);
        this.addChild(this._rankSprite);

        this._windowFadeSprite = new ScreenSprite();
        this._windowFadeSprite.setColor(0, 0, 0);
        this._windowFadeSprite.opacity = 0;
        this._windowFadeSprite.visible = false;
        this.addChild(this._windowFadeSprite);

        this._effectSprite = new Sprite_GachaEffect();
        this._effectSprite.x = Graphics.boxWidth / 2;
        this._effectSprite.y = Graphics.boxHeight / 2;
        this.addChild(this._effectSprite);

        this._helpWindow.setText(message);
    };

    Scene_Gacha.prototype.createGoldWindow = function () {
        this._goldWindow = new Window_Gold(0, this._helpWindow.height);
        this._goldWindow.x = Graphics.boxWidth - this._goldWindow.width;
        this.addWindow(this._goldWindow);
    };

    Scene_Gacha.prototype.createCommandWindow = function () {
        this._commandWindow = new Window_GachaCommand(this._goldWindow.x, this._purchaseOnly);
        this._commandWindow.y = this._helpWindow.height;
        this._commandWindow.setHandler('gacha', this.commandGacha.bind(this));
        this._commandWindow.setHandler('cancel', this.popScene.bind(this));
        this._commandWindow.lotIsValid(this._lot.length > 0);
        this._commandWindow.clearCommandList();
        this._commandWindow.makeCommandList();
        this._commandWindow.refresh();
        this.addWindow(this._commandWindow);
    };

    Scene_Gacha.prototype.createDummyWindow = function () {
        var wy = this._commandWindow.y + this._commandWindow.height;
        var wh = Graphics.boxHeight - wy;
        this._dummyWindow = new Window_Base(0, wy, Graphics.boxWidth, wh);
        this.addWindow(this._dummyWindow);
    };

    Scene_Gacha.prototype.createGetCommandWindow = function () {
        this._getCommandWindow = new Window_GachaGetCommand(Graphics.boxWidth, false);
        this._getCommandWindow.y = Graphics.boxHeight - this._getCommandWindow.height;
        this._getCommandWindow.setHandler('cancel', this.commandOk.bind(this));
        this._getCommandWindow.hide();
        this.addWindow(this._getCommandWindow);
    };

    Scene_Gacha.prototype.createGetWindow = function () {
        var wy = this._helpWindow.height;
        var wh = Graphics.boxHeight - wy - this._getCommandWindow.height;
        this._getWindow = new Window_GachaGet(0, wy, Graphics.boxWidth, wh);
        this._getWindow.itemDescEnable(itemDescEnable);
        this._getWindow.hide();
        this.addWindow(this._getWindow);
    };

    Scene_Gacha.prototype.commandGacha = function () {
        // Draw lots
        if (this._lot.length <= 0) {
            this._item = null;
        }
        else {
            this._item = this._lot[(Math.random() * this._lot.length) >> 0];
            $gameParty.loseGold(amount);
            $gameParty.gainItem(this._item, 1);
            this._goldWindow.refresh();

        }

        this._commandWindow.deactivate();
        this._getCommandWindow.deactivate();

        if (this._item) {
            this._getWindow.setItem(this._item);

            this._screenFadeOut();
            this._effectPlaying = true;
            this._wait = 0;

            var animation = $dataAnimations[effect];
            this._effectSprite.startAnimation(animation, false, 0);

            AudioManager.playMe({ "name": me, "volume": 90, "pitch": 100, "pan": 0 });
        }
        else {
            this._commandWindow.activate();
        }

    };

    Scene_Gacha.prototype.commandOk = function () {
        this._effectSprite.allRemove();
        this._rankSprite.allRemove();
        this._goldWindow.show();
        this._commandWindow.show();
        this._commandWindow.activate();
        this._dummyWindow.show();
        this._getCommandWindow.hide();
        this._getWindow.hide();
        this._helpWindow.setText(message);
        this._item = null;

        this._commandWindow.clearCommandList();
        this._commandWindow.makeCommandList();
        this._commandWindow.refresh();
    };

    Scene_Gacha.prototype.update = function () {
        Scene_Menu.prototype.update.call(this);
        this._updateScreenFlashSprite();

        this._wait++;
        if (this._wait > 12) {
            if (this._effectPlaying) {
                if (!this._effectSprite.isAnimationPlaying()) {
                    this._screenFadeIn();
                    if (!!this._item.meta.gachaImage) {
                        var rank = Number(this._item.meta.gachaRank || '-1');
                        if (rank > 0 && rank < 6) {
                            if (rankEffect[rank - 1] > 0) {
                                var animation = $dataAnimations[rankEffect[rank - 1]];
                                this._rankSprite.x = this._getWindow.width / 2 + this._getWindow.x - 20;
                                this._rankSprite.y = this._getWindow.contentsHeight() + this._getWindow.y;
                                if (itemDescEnable) {
                                    this._rankSprite.y -= this._getWindow.lineHeight() * 3;
                                }
                                this._rankSprite.startAnimation(animation, false, 0);
                            }
                        }
                    }

                    this._effectPlaying = false;
                    this._goldWindow.hide();
                    this._commandWindow.hide();
                    this._dummyWindow.hide();
                    this._getCommandWindow.show();
                    this._getWindow.show();
                    var message = getText;
                    var reg = /Item Name/gi;
                    message = message.replace(reg, String(this._item.name));
                    this._helpWindow.setText(message);
                    this._wait = 0;
                    this._resultShowing = true;
                }
                else {
                    if (TouchInput.isTriggered() || Input.isTriggered("ok")) {
                        this._effectSprite.allRemove();
                    }
                }
            }
            else if (this._resultShowing) {
                this._resultShowing = false;
                this._getCommandWindow.activate();
            }
        }
    };

    Scene_Gacha.prototype._updateScreenFlashSprite = function () {
        var d;
        if (this._screenFadeOutDuration > 0) {
            d = this._screenFadeOutDuration--;
            this._windowFadeSprite.opacity += 255 * (1 - (d - 1) / d);
        }
        if (this._screenFadeInDuration > 0) {
            d = this._screenFadeInDuration--;
            this._windowFadeSprite.opacity *= (d - 1) / d;
            this._windowFadeSprite.visible = (this._screenFadeInDuration > 0);
        }
    };

    Scene_Gacha.prototype._screenFadeOut = function () {
        this._windowFadeSprite.visible = true;
        this._screenFadeOutDuration = 15;
        this._screenFadeInDuration = 0;
    };

    Scene_Gacha.prototype._screenFadeIn = function () {
        this._windowFadeSprite.visible = true;
        this._screenFadeOutDuration = 0;
        this._screenFadeInDuration = 15;
    };

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

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

    Window_Gacha.prototype.initialize = function (x, y) {
        var width = Graphics.boxWidth;
        var height = this.fittingHeight(6);
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this.refresh();
        this.activate();
    };

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

    Window_GachaCommand.prototype = Object.create(Window_HorzCommand.prototype);
    Window_GachaCommand.prototype.constructor = Window_GachaCommand;

    Window_GachaCommand.prototype.initialize = function (width, purchaseOnly) {
        this._windowWidth = width;
        this._purchaseOnly = purchaseOnly;
        Window_HorzCommand.prototype.initialize.call(this, 0, 0);
    };

    Window_GachaCommand.prototype.windowWidth = function () {
        return this._windowWidth;
    };

    Window_GachaCommand.prototype.maxCols = function () {
        return 2;
    };

    Window_GachaCommand.prototype.makeCommandList = function () {
        this.addCommand(buttonText, 'gacha', $gameParty.gold() >= amount && !!this._lotIsValid);
        this.addCommand(TextManager.cancel, 'cancel');
    };

    Window_GachaCommand.prototype.lotIsValid = function (value) {
        this._lotIsValid = value;
    };

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

    Window_GachaGetCommand.prototype = Object.create(Window_HorzCommand.prototype);
    Window_GachaGetCommand.prototype.constructor = Window_GachaGetCommand;

    Window_GachaGetCommand.prototype.initialize = function (width, purchaseOnly) {
        this._windowWidth = width;
        this._purchaseOnly = purchaseOnly;
        Window_HorzCommand.prototype.initialize.call(this, 0, 0);
    };

    Window_GachaGetCommand.prototype.windowWidth = function () {
        return this._windowWidth;
    };

    Window_GachaGetCommand.prototype.maxCols = function () {
        return 1;
    };

    Window_GachaGetCommand.prototype.makeCommandList = function () {
        this.addCommand('OK', 'cancel');
    };

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

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

    Window_GachaGet.prototype.initialize = function (x, y, width, height) {
        Window_Base.prototype.initialize.call(this, x, y, width, height);
        this._item = null;
        this._itemDescEnable = true;
        this._gachaSprite = new Sprite();
        this._gachaSprite.anchor.x = 0.5;
        this._gachaSprite.anchor.y = 0;
        this._gachaSprite.x = width / 2 - 20;
        this._gachaSprite.y = this.padding;
        this.addChildToBack(this._gachaSprite);
        this.refresh();
    };

    Window_GachaGet.prototype.itemDescEnable = function (value) {
        if (this._itemDescEnable !== value) {
            this._itemDescEnable = value;
            this.refresh();
        }
    };

    Window_GachaGet.prototype.setItem = function (item) {
        if (this._item !== item) {
            this._item = item;
            this.refresh();
        }
    };

    Window_GachaGet.prototype.update = function () {
        Window_Base.prototype.update.call(this);
        if (this._gachaSprite.bitmap) {
            var bitmapHeight = this._gachaSprite.bitmap.height;
            var contentsHeight = this.contents.height;
            if (this._itemDescEnable) {
                contentsHeight -= this.lineHeight() * 3
            }
            var scale = 1;
            if (bitmapHeight > contentsHeight) {
                scale = contentsHeight / bitmapHeight;
            }
            this._gachaSprite.scale.x = scale;
            this._gachaSprite.scale.y = scale;
        }
    };

    Window_GachaGet.prototype.refresh = function () {
        var item = this._item;
        this.contents.clear();

        if (this._itemDescEnable) {
            var y = this.contentsHeight() - this.lineHeight() * 3;
            this.drawHorzLine(y);
            this.drawDescription(0, y + this.lineHeight());
        }

        if (!item || !item.meta.gachaImage) {
            this._gachaSprite.bitmap = null;
            return;
        }
        else {
            var bitmap;
            bitmap = ImageManager.loadBitmap("img/gacha/", this._item.meta.gachaImage);
            this._gachaSprite.bitmap = bitmap;
            bitmap.smooth = true;
        }
    };

    Window_GachaGet.prototype.drawDescription = function (x, y) {
        if (this._item) this.drawTextEx(this._item.description, x, y);
    };

    Window_GachaGet.prototype.drawHorzLine = function (y) {
        var lineY = y + this.lineHeight() / 2 - 1;
        this.contents.paintOpacity = 48;
        this.contents.fillRect(0, lineY, this.contentsWidth(), 2, this.lineColor());
        this.contents.paintOpacity = 255;
    };

    Window_GachaGet.prototype.lineColor = function () {
        return this.normalColor();
    };

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

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

    Sprite_GachaEffect.prototype.initialize = function () {
        Sprite.prototype.initialize.call(this);
        this._animationSprites = [];
        this._endSprites = [];
        this._effectTarget = this;
        this._hiding = false;
        this._keepDisplay = false;
    };

    Sprite_GachaEffect.prototype.keepDisplay = function (value) {
        this._keepDisplay = value;
    };

    Sprite_GachaEffect.prototype.update = function () {
        Sprite.prototype.update.call(this);
        this.updateVisibility();
        this.updateAnimationSprites();
    };

    Sprite_GachaEffect.prototype.hide = function () {
        this._hiding = true;
        this.updateVisibility();
    };

    Sprite_GachaEffect.prototype.show = function () {
        this._hiding = false;
        this.updateVisibility();
    };

    Sprite_GachaEffect.prototype.updateVisibility = function () {
        this.visible = !this._hiding;
    };

    Sprite_GachaEffect.prototype.updateAnimationSprites = function () {
        if (this._animationSprites.length > 0) {
            var sprites = this._animationSprites.clone();
            this._animationSprites = [];
            for (var i = 0; i < sprites.length; i++) {
                var sprite = sprites[i];
                if (sprite.isPlaying()) {
                    this._animationSprites.push(sprite);
                } else {
                    if (!this._keepDisplay) {
                        sprite.remove();
                    }
                    else {
                        this._endSprites.push(sprite);
                    }
                }
            }
        }
    };

    Sprite_GachaEffect.prototype.startAnimation = function (animation, mirror, delay) {
        var sprite = new Sprite_Animation();
        sprite.setup(this._effectTarget, animation, mirror, delay);
        this.parent.addChild(sprite);
        this._animationSprites.push(sprite);
    };

    Sprite_GachaEffect.prototype.isAnimationPlaying = function () {
        return this._animationSprites.length > 0;
    };

    Sprite_GachaEffect.prototype.allRemove = function () {
        var sprites, sprite, i;
        if (this._animationSprites.length > 0) {
            sprites = this._animationSprites.clone();
            this._animationSprites = [];
            for (i = 0; i < sprites.length; i++) {
                sprite = sprites[i];
                sprite.remove();
            }
        }
        if (this._endSprites.length > 0) {
            sprites = this._endSprites.clone();
            this._endSprites = [];
            for (i = 0; i < sprites.length; i++) {
                sprite = sprites[i];
                sprite.remove();
            }
        }
    };

})();