code:
/*=============================================================================
 ApngPicture.js
----------------------------------------------------------------------------
 (C)2019 Triacontane
 This software is released under the MIT License.
 http://opensource.org/licenses/mit-license.php
----------------------------------------------------------------------------
 Version
 1.8.3 2021/01/18 1.8.2の修正でapngでないピクチャや敵キャラを表示しようとするとエラーになる問題を修正
 1.8.2 2021/01/17 キャッシュ方針を「あり」にした画像を再表示するとき、フレームを初期化するよう修正
 1.8.1 2021/01/17 キャッシュ方針を「あり」にしているとき、破棄のタイミングでエラーになる問題を修正
 1.8.0 2020/11/29 1セルごとのフレーム数をゲーム側で設定できるパラメータを追加
 1.7.2 2020/11/28 gifを使う場合はダミーのpngファイルが別途必要である旨の追記を追加
 1.7.1 2020/11/22 メニュー画面を開いたときに表示中のapngピクチャが消えないよう修正
 1.7.0 2020/11/11 APNGのアニメーションを停止、全停止できるスイッチを追加
 1.6.1 2020/11/03 プラグイン上でapng画像の高さを正しく取得できるよう修正
 1.6.0 2020/10/24 再生回数を指定したときに最初ではなく最後のフレームでアニメーションが止まる設定を追加
 1.5.0 2020/10/17 サイドビューの敵キャラをapng化できるよう修正。機能が不完全であることに変わりはありません。
 1.4.3 2020/03/17 ライブラリがpixi5.0対応によるバージョンアップで使用できなくなったのでヘルプの取得元を旧版に変更
 1.4.2 2020/03/07 キャッシュしない設定のapngを繰り返し表示、削除し続けるとメモリリークが発生する問題を修正
 1.4.1 2020/02/23 英語版のプラグインパラメータの記述が不足していたので修正
 1.4.0 2020/02/01 アニメーションのループ回数を指定できる機能を追加
 1.3.1 2019/12/31 画像を登録せずゲーム開始するとローディングが完了しない問題を修正
 1.3.0 2019/12/31 APNGのキャッシュ機能を追加
 1.2.1 2019/12/31 シーン追加画像でgifが表示されない問題を修正
 1.2.0 2019/12/31 APNGのみツクール本体の暗号化機能に対応
 1.1.0 2019/12/29 シーン追加画像の表示優先度を設定できる機能を追加
 1.0.0 2019/12/27 初版
----------------------------------------------------------------------------
 [Blog]   : https://triacontane.blogspot.jp/
 [Twitter]: https://twitter.com/triacontane/
 [GitHub] : https://github.com/triacontane/
=============================================================================*/

/*:
 * @plugindesc ApngSupportPlugin
 * @author triacontane
 *
 * @param PictureList
 * @desc List of picture images to be handled as APNG.
 * @default []
 * @type struct<PictureApngRecord>[]
 *
 * @param EnemyList
 * @desc List of enemy images to be handled as APNG.
 * @default []
 * @type struct<EnemyApngRecord>[]
 *
 * @param SideEnemyList
 * @desc List of enemy images to be handled as APNG.
 * @default []
 * @type struct<SideEnemyApngRecord>[]
 *
 * @param SceneApngList
 * @desc This is a list of APNG to be displayed for each scene.
 * @default []
 * @type struct<SceneApngRecord>[]
 *
 * @param DefaultLoopTimes
 * @desc The number of animation loops. It stops after looping the specified number of times.
 * @default 0
 * @type number
 *
 * @param AllStopSwitch
 * @desc All animations stop when the specified number switch is ON.
 * @default 0
 * @type switch
 *
 * @help ApngPicture.js
 * APNG or GIF is treated as a picture and animated on the screen.
 * From the parameters, select the file in which the APNG picture file is registered.
 * It will be animated if it is displayed in "Display Picture".
 *
 * The following libraries are required for use.
 * https://github.com/sbfkcel/pixi-apngAndGif
 *
 * Download the target file and import it from the plugin management screen.
 * https://github.com/sbfkcel/pixi-apngAndGif/blob/fd2e0fb3274bf2c360c608b42e527889d10a6330/dist/PixiApngAndGif.js
 *
 * In addition, the color tone change of the picture is not reflected.
 * Also, extensions by other plug-ins may not work.
 *
 * In addition, APNG registered from parameters can be additionally displayed for each scene.
 * Display can be controlled by switch.
 *
 * There is also a function to display APNG on the enemy character image, but this function
 * The image is incomplete because no flash is performed.
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc APNGピクチャプラグイン
 * @author トリアコンタン
 *
 * @param PictureList
 * @text APNGのピクチャリスト
 * @desc APNGとして扱うピクチャ画像のリストです。GIFを指定したい場合は拡張子付きで直接入力してください。
 * @default []
 * @type struct<PictureApngRecord>[]
 *
 * @param EnemyList
 * @text APNGの敵キャラリスト
 * @desc APNGとして扱う敵キャラ画像のリストです。GIFを指定したい場合は拡張子付きで直接入力してください。この機能は不完全です。
 * @default []
 * @type struct<EnemyApngRecord>[]
 *
 * @param SideEnemyList
 * @text APNGのSV敵キャラリスト
 * @desc APNGとして扱うSV敵キャラ画像のリストです。サイドビューの画像を使用したい場合はこちらから登録してください。
 * @default []
 * @type struct<SideEnemyApngRecord>[]
 *
 * @param SceneApngList
 * @text シーンAPNGのリスト
 * @desc シーンごとに表示するAPNGのリストです。GIFを指定したい場合は拡張子付きで直接入力してください。
 * @default []
 * @type struct<SceneApngRecord>[]
 *
 * @param DefaultLoopTimes
 * @text デフォルトループ回数
 * @desc アニメーションのループ回数です。指定した回数分ループ再生すると止まります。0を指定すると無限にアニメーションします。
 * @default 0
 * @type number
 *
 * @param StopLastFrame
 * @text 最終フレームで止める
 * @desc ループ回数が決まっているアニメーションを再生したとき最初のフレームではなく最後のフレームでアニメーションが止まります。
 * @default false
 * @type boolean
 *
 * @param AllStopSwitch
 * @text 全停止スイッチ
 * @desc 指定した番号スイッチがONのとき全てのアニメーションが停止します。
 * @default 0
 * @type switch
 *
 * @param FrameCount
 * @text 1セルのフレーム数
 * @desc 設定すると1セルごとのフレーム数をゲーム側で固定にできます。
 * @default 0
 * @type number
 *
 * @help ApngPicture.js
 * APNG、もしくはGIFアニメをピクチャとして画面上にアニメ表示します。
 * パラメータからAPNGのピクチャとして登録したファイルを
 * 「ピクチャの表示」で表示すればアニメーションされます。
 *
 * 使用には以下のライブラリが必要です。
 * https://github.com/sbfkcel/pixi-apngAndGif
 *
 * ただし、ライブラリの最新版はpixi5.0に対応した結果、ツクールMV側の最新である4.0では
 * 再生できなくなりました。よって最新版ではなく、下記の旧版を使用する必要があります。
 *
 * 対象ファイルをダウンロードしてプラグイン管理画面から取り込んでください。
 * https://github.com/sbfkcel/pixi-apngAndGif/blob/fd2e0fb3274bf2c360c608b42e527889d10a6330/dist/PixiApngAndGif.js
 *
 * なお、ピクチャの色調変更は反映されません。
 * また、他のプラグインによる拡張が機能しない場合があります。
 *
 * APNGをキャッシュすることで表示時の硬直を抑えることができますが、
 * キャッシュする量に比例して初回起動時に時間が掛かるようになります。
 * また、キャッシュした画像は1画面中で同時に2つ以上は表示できません。
 * 使用する場合はご注意ください。
 *
 * さらに、各シーンでパラメータから登録したAPNGを追加表示できます。
 * スイッチによる表示制御が可能です。
 *
 * 敵キャラ画像にAPNGを表示する機能もありますが、この機能は
 * 画像のフラッシュが一切行われないため不完全です。
 * また、画像サイズの大きいAPNGを読み込むと、表示が遅くなる場合があります。
 * 表示が遅い場合はGIFアニメもお試しください。
 *
 * GIFを使用したい場合、拡張子がgifのファイルはツクールMVで認識されないので
 * パラメータに拡張子付きのファイル名を直接入力してください。
 * 同一ファイル名のpngファイルが別途必要です。(中身は空の画像でOK)
 * また、GIFはツクールMVの暗号化機能の対象外となります。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

/*~struct~SceneApngRecord:ja
 *
 * @param SceneName
 * @text 対象シーン
 * @desc 画像を追加するシーンです。
 * @type select
 * @default Scene_Title
 * @option タイトル
 * @value Scene_Title
 * @option ゲームオーバー
 * @value Scene_Gameover
 * @option バトル
 * @value Scene_Battle
 * @option メインメニュー
 * @value Scene_Menu
 * @option アイテム
 * @value Scene_Item
 * @option スキル
 * @value Scene_Skill
 * @option 装備
 * @value Scene_Equip
 * @option ステータス
 * @value Scene_Status
 * @option オプション
 * @value Scene_Options
 * @option セーブ
 * @value Scene_Save
 * @option ロード
 * @value Scene_Load
 * @option ゲーム終了
 * @value Scene_End
 * @option ショップ
 * @value Scene_Shop
 * @option 名前入力
 * @value Scene_Name
 * @option デバッグ
 * @value Scene_Debug
 * @option サウンドテスト
 * @value Scene_SoundTest
 * @option 用語辞典
 * @value Scene_Glossary
 *
 * @param FileName
 * @text ファイル名
 * @desc 追加するAPNGのファイル名です。
 * @default
 * @require 1
 * @dir img/system/
 * @type file
 *
 * @param CachePolicy
 * @text キャッシュ方針
 * @desc 画像のキャッシュ方針です。大量にキャッシュするとメモリ使用量に影響が出る場合があります。
 * @default 0
 * @type select
 * @option キャッシュしない
 * @value 0
 * @option 初回表示時にキャッシュ
 * @value 1
 * @option ゲーム起動時にキャッシュ
 * @value 2
 *
 * @param X
 * @text X座標
 * @desc 追加するAPNGのX座標です。
 * @default 0
 * @type number
 *
 * @param Y
 * @text Y座標
 * @desc 追加するAPNGのY座標です。
 * @default 0
 * @type number
 *
 * @param Origin
 * @text 原点
 * @desc 追加するAPNGの原点です。
 * @default 0
 * @type select
 * @option 左上
 * @value 0
 * @option 中央
 * @value 1
 *
 * @param Priority
 * @text 優先度
 * @desc 画像の表示優先度です。最背面は画面上に表示されないことが多いので通常の使用では推奨しません。
 * @default 0
 * @type select
 * @option 最前面
 * @value 0
 * @option ウィンドウの下
 * @value 1
 * @option 最背面
 * @value 2
 *
 * @param Switch
 * @text 出現条件スイッチ
 * @desc 指定したスイッチがONのときのみ表示されます。指定しない場合、常に表示されます。
 * @default 0
 * @type switch
 *
 * @param LoopTimes
 * @text ループ回数
 * @desc アニメーションのループ回数です。0を指定するとデフォルト設定に従います。
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @text 停止スイッチ
 * @desc 指定した番号スイッチがONのときアニメーションが停止します。
 * @default 0
 * @type switch
 */

/*~struct~PictureApngRecord:ja
 *
 * @param FileName
 * @text ファイル名
 * @desc 追加するAPNGのファイル名です。
 * @default
 * @require 1
 * @dir img/pictures/
 * @type file
 *
 * @param CachePolicy
 * @text キャッシュ方針
 * @desc 画像のキャッシュ方針です。大量にキャッシュするとメモリ使用量に影響が出る場合があります。
 * @default 0
 * @type select
 * @option キャッシュしない
 * @value 0
 * @option 初回表示時にキャッシュ
 * @value 1
 * @option ゲーム起動時にキャッシュ
 * @value 2
 *
 * @param LoopTimes
 * @text ループ回数
 * @desc アニメーションのループ回数です。0を指定するとデフォルト設定に従います。
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @text 停止スイッチ
 * @desc 指定した番号スイッチがONのときアニメーションが停止します。
 * @default 0
 * @type switch
 */

/*~struct~EnemyApngRecord:ja
 *
 * @param FileName
 * @text ファイル名
 * @desc 追加するAPNGのファイル名です。
 * @default
 * @require 1
 * @dir img/enemies/
 * @type file
 *
 * @param CachePolicy
 * @text キャッシュ方針
 * @desc 画像のキャッシュ方針です。大量にキャッシュするとメモリ使用量に影響が出る場合があります。
 * @default 0
 * @type select
 * @option キャッシュしない
 * @value 0
 * @option 初回表示時にキャッシュ
 * @value 1
 * @option ゲーム起動時にキャッシュ
 * @value 2
 *
 * @param LoopTimes
 * @text ループ回数
 * @desc アニメーションのループ回数です。0を指定するとデフォルト設定に従います。
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @text 停止スイッチ
 * @desc 指定した番号スイッチがONのときアニメーションが停止します。
 * @default 0
 * @type switch
 */

/*~struct~SideEnemyApngRecord:ja
 *
 * @param FileName
 * @text ファイル名
 * @desc 追加するAPNGのファイル名です。
 * @default
 * @require 1
 * @dir img/sv_enemies/
 * @type file
 *
 * @param CachePolicy
 * @text キャッシュ方針
 * @desc 画像のキャッシュ方針です。大量にキャッシュするとメモリ使用量に影響が出る場合があります。
 * @default 0
 * @type select
 * @option キャッシュしない
 * @value 0
 * @option 初回表示時にキャッシュ
 * @value 1
 * @option ゲーム起動時にキャッシュ
 * @value 2
 *
 * @param LoopTimes
 * @text ループ回数
 * @desc アニメーションのループ回数です。0を指定するとデフォルト設定に従います。
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @text 停止スイッチ
 * @desc 指定した番号スイッチがONのときアニメーションが停止します。
 * @default 0
 * @type switch
 */

/*~struct~SceneApngRecord:
 *
 * @param SceneName
 * @desc Target Scene
 * @type select
 * @default Scene_Title
 * @option Scene_Title
 * @option Scene_Gameover
 * @option Scene_Battle
 * @option Scene_Menu
 * @option Scene_Item
 * @option Scene_Skill
 * @option Scene_Equip
 * @option Scene_Status
 * @option Scene_Options
 * @option Scene_Save
 * @option Scene_Load
 * @option Scene_End
 * @option Scene_Shop
 * @option Scene_Name
 * @option Scene_Debug
 * @option Scene_SoundTest
 * @option Scene_Glossary
 *
 * @param FileName
 * @desc File name of apng
 * @default
 * @require 1
 * @dir img/system/
 * @type file
 *
 * @param CachePolicy
 * @desc Cache policy
 * @default 0
 * @type select
 * @option None
 * @value 0
 * @option Cache on first display
 * @value 1
 * @option Cache at game start
 * @value 2
 *
 * @param X
 * @desc X of apng
 * @default 0
 * @type number
 *
 * @param Y
 * @desc Y of apng
 * @default 0
 * @type number
 *
 * @param Origin
 * @desc Origin of apng
 * @default 0
 * @type select
 * @option Upper left
 * @value 0
 * @option Center
 * @value 1
 *
 * @param Priority
 * @desc Priority of apng
 * @default 0
 * @type select
 * @option Front
 * @value 0
 * @option Under window
 * @value 1
 * @option Back
 * @value 2
 *
 * @param Switch
 * @desc Displayed only when the specified switch is ON
 * @default 0
 * @type switch
 *
 * @param LoopTimes
 * @desc The number of animation loops. Specifying 0 follows the default setting.
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @desc The animation stops when the specified number switch is turned on.
 * @default 0
 * @type switch
 */

/*~struct~PictureApngRecord:
 *
 * @param FileName
 * @desc File name of apng
 * @default
 * @require 1
 * @dir img/pictures/
 * @type file
 *
 * @param CachePolicy
 * @desc Cache policy
 * @default 0
 * @type select
 * @option None
 * @value 0
 * @option Cache on first display
 * @value 1
 * @option Cache at game start
 * @value 2
 *
 * @param LoopTimes
 * @desc The number of animation loops. Specifying 0 follows the default setting.
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @desc The animation stops when the specified number switch is turned on.
 * @default 0
 * @type switch
 */

/*~struct~EnemyApngRecord:
 *
 * @param FileName
 * @desc File name of apng
 * @default
 * @require 1
 * @dir img/enemies/
 * @type file
 *
 * @param CachePolicy
 * @desc Cache policy
 * @default 0
 * @type select
 * @option None
 * @value 0
 * @option Cache on first display
 * @value 1
 * @option Cache at game start
 * @value 2
 *
 * @param LoopTimes
 * @desc The number of animation loops. Specifying 0 follows the default setting.
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @desc The animation stops when the specified number switch is turned on.
 * @default 0
 * @type switch
 */

/*~struct~SideEnemyApngRecord:
 *
 * @param FileName
 * @desc File name of apng
 * @default
 * @require 1
 * @dir img/sv_enemies/
 * @type file
 *
 * @param CachePolicy
 * @desc Cache policy
 * @default 0
 * @type select
 * @option None
 * @value 0
 * @option Cache on first display
 * @value 1
 * @option Cache at game start
 * @value 2
 *
 * @param LoopTimes
 * @desc The number of animation loops. Specifying 0 follows the default setting.
 * @default 0
 * @type number
 *
 * @param StopSwitch
 * @desc The animation stops when the specified number switch is turned on.
 * @default 0
 * @type switch
 */

(function() {
    'use strict';

    var getClassName = function(object) {
        return object.constructor.toString().replace(/function\s+(.*)\s*\([\s\S]*/m, '$1');
    };

    /**
     * Create plugin parameter. param[paramName] ex. param.commandPrefix
     * @param script currentScript
     * @returns {Object} Created parameter
     */
    var createPluginParameter = function(script) {
        var pluginName = script.src.replace(/^.*\/(.*).js$/, function() {
            return arguments[1];
        });
        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(document.currentScript);

    /**
     * ApngLoader
     * APNGもしくはGIF画像を読み込んで保持します。
     */
    class ApngLoader {
        constructor(folder, paramList) {
            this._folder = folder;
            this._fileHash = {};
            this._cachePolicy = {};
            this._options = {};
            this._paramList = paramList;
            if (this._paramList && this._paramList.length > 0) {
                this.addAllImage();
            }
            this._spriteCache = {};
        }

        addAllImage() {
            var option = this.getLoadOption();
            this._paramList.forEach(function(item) {
                this.addImage(item, option);
            }, this);
            PIXI.loader.onComplete.add(this.cacheStartup.bind(this));
            ApngLoader.startLoading();
        }

        addImage(item, option) {
            var name = item.FileName || '';
            var ext = Decrypter.hasEncryptedImages ? 'rpgmvp' : 'png';
            name = name.replace(/\.gif$/gi, function() {
                ext = 'gif';
                return '';
            });
            var path = name.match(/http:/) ? name : `img/${this._folder}/${name}.${ext}`;
            if (!this._fileHash.hasOwnProperty(name)) {
                this._fileHash[name] = ApngLoader.convertDecryptExt(path);
                this._cachePolicy[name] = item.CachePolicy;
                this._options[name] = item;
                PIXI.loader.add(path, option);
            }
        }

        getLoadOption() {
            return {
                loadType   : PIXI.loaders.Resource.LOAD_TYPE.XHR,
                xhrType    : PIXI.loaders.Resource.XHR_RESPONSE_TYPE.BUFFER,
                crossOrigin: ''
            }
        }

        createSprite(name) {
            if (!this.isApng(name)) {
                return null;
            }
            if (this._isNeedCache(name)) {
                if (this._spriteCache[name]) {
                    return this._spriteCache[name];
                }
                var sprite = this._createPixiApngAndGif(name);
                this._spriteCache[name] = sprite;
                return sprite;
            } else {
                return this._createPixiApngAndGif(name);
            }
        }

        _createPixiApngAndGif(name) {
            var pixiApng = new PixiApngAndGif(this._fileHash[name], ApngLoader._resource);
            var loopCount = this._options[name].LoopTimes || param.DefaultLoopTimes;
            if (loopCount > 0) {
                pixiApng.play(loopCount);
            }
            var sprite = pixiApng.sprite;
            sprite.pixiApng = pixiApng;
            sprite.pixiApngOption = this._options[name]
            return sprite;
        }

        _isNeedCache(name) {
            return this._cachePolicy[name] > 0;
        }

        isApng(name) {
            return !!this._fileHash[name];
        }

        cacheStartup() {
            Object.keys(this._cachePolicy).forEach(function(name) {
                if (this._cachePolicy[name] === 2) {
                    this.createSprite(name)
                }
            }, this);
        }

        static startLoading() {
            this._loading = true;
        };

        static onLoadResource(progress, resource) {
            this._resource = resource;
            Object.keys(this._resource).forEach(function(key) {
                if (this._resource[key].extension === 'rpgmvp') {
                    ApngLoader.decryptResource(key);
                }
            }, this);
        }

        static decryptResource(key) {
            var resource = this._resource[key];
            resource.data = Decrypter.decryptArrayBuffer(resource.data);
            var newKey = ApngLoader.convertDecryptExt(key);
            resource.name = newKey;
            resource.url = newKey;
            resource.extension = 'png';
            this._resource[newKey] = resource;
            delete this._resource[key];
        };

        static isReady() {
            return !!this._resource || !this._loading;
        }

        static convertDecryptExt(key) {
            return key.replace(/\.rpgmvp$/, '.png');
        }
    }
    ApngLoader._resource = null;

    var _Scene_Boot_isReady = Scene_Boot.prototype.isReady;
    Scene_Boot.prototype.isReady = function() {
        var result = _Scene_Boot_isReady.apply(this, arguments);
        if (result) {
            SceneManager.setupApngLoaderIfNeed();
        }
        return result && ApngLoader.isReady();
    };

    var _Scene_Base_create = Scene_Base.prototype.create;
    Scene_Base.prototype.create = function() {
        _Scene_Base_create.apply(this, arguments);
        this.createSceneApng();
    };

    Scene_Base.prototype.createSceneApng = function() {
        this._apngList = this.findSceneApngList().map(function(item) {
            return new SpriteSceneApng(item);
        }, this);
    };

    var _Scene_Base_terminate = Scene_Base.prototype.terminate;
    Scene_Base.prototype.terminate = function() {
        _Scene_Base_terminate.apply(this, arguments);
        this.destroySceneApng();
        if (this._spriteset) {
            this._spriteset.destroyApngPicture();
        }
    };

    Scene_Base.prototype.destroySceneApng = function() {
        this._apngList.forEach(function(sprite) {
            sprite.destroyApngIfNeed();
        })
    };

    var _Scene_Base_start = Scene_Base.prototype.start;
    Scene_Base.prototype.start = function() {
        _Scene_Base_start.apply(this, arguments);
        this.setApngPriority();
    };

    Scene_Base.prototype.setApngPriority = function() {
        var windowLayerIndex = this._windowLayer ? this.getChildIndex(this._windowLayer) : 0;
        this._apngList.forEach(function(sprite) {
            switch (sprite.getPriority()) {
                case 0:
                    this.addChild(sprite);
                    break;
                case 1:
                    this.addChildAt(sprite, windowLayerIndex);
                    windowLayerIndex++;
                    break;
                default:
                    this.addChildAt(sprite, 0);
            }
        }, this);
    };

    Scene_Base.prototype.findSceneApngList = function() {
        var currentSceneName = getClassName(this);
        return (param.SceneApngList || []).filter(function(data) {
            return data.SceneName === currentSceneName;
        }, this);
    };

    Spriteset_Base.prototype.destroyApngPicture = function() {
        this.destroyApngPictureContainer(this._pictureContainer);
        // for PicturePriorityCustomize.js
        this.destroyApngPictureContainer(this._pictureContainerLower);
        this.destroyApngPictureContainer(this._pictureContainerMiddle);
        this.destroyApngPictureContainer(this._pictureContainerUpper);
    };

    Spriteset_Base.prototype.destroyApngPictureContainer = function(container) {
        if (!container) {
            return;
        }
        container.children.forEach(function(sprite) {
            if (sprite.destroyApngIfNeed) {
                sprite.destroyApngIfNeed();
            }
        });
    };

    Spriteset_Battle.prototype.destroyApngPicture = function() {
        Spriteset_Base.prototype.destroyApngPicture.call(this);
        this._enemySprites.forEach(function(sprite) {
            sprite.destroyApngIfNeed();
        });
    };

    /**
     * SceneManager
     * APNGのローダを管理します。
     */
    SceneManager.setupApngLoaderIfNeed = function() {
        if (this._apngLoaderPicture) {
            return;
        }
        PIXI.loader.onComplete.add(ApngLoader.onLoadResource.bind(ApngLoader));
        this._apngLoaderPicture = new ApngLoader('pictures', param.PictureList);
        this._apngLoaderEnemy = new ApngLoader('enemies', param.EnemyList);
        this._apngLoaderSideEnemy = new ApngLoader('sv_enemies', param.SideEnemyList);
        this._apngLoaderSystem = new ApngLoader('system', param.SceneApngList);
        PIXI.loader.load();
    };

    SceneManager.tryLoadApngPicture = function(name) {
        return this._apngLoaderPicture.createSprite(name);
    };

    SceneManager.tryLoadApngEnemy = function(name) {
        return this._apngLoaderEnemy.createSprite(name);
    };

    SceneManager.tryLoadApngSideEnemy = function(name) {
        return this._apngLoaderSideEnemy.createSprite(name);
    };

    SceneManager.tryLoadApngSystem = function(name) {
        return this._apngLoaderSystem.createSprite(name);
    };

    /**
     * Sprite
     * APNGの読み込み処理を追加します。
     */
    Sprite.prototype.addApngChild = function(name) {
        this.destroyApngIfNeed();
        this._apngSprite = this.loadApngSprite(name);
        if (this._apngSprite) {
            if (this.isApngCache()) {
                this._apngSprite.pixiApng.jumpToFrame(0);
                this._apngSprite.pixiApng.play();
            }
            this.addChild(this._apngSprite);
            const original = ImageManager.loadPicture(name);
            original.addLoadListener(function() {
                this.bitmap = new Bitmap(original.width, original.height);
            }.bind(this));
            this.updateApngAnchor();
            this.updateApngBlendMode();
        }
        this._apngLoopCount = 1;
        this._apngLoopFrame = 0;
    };

    Sprite.prototype.destroyApngIfNeed = function() {
        if (this._apngSprite) {
            if (!this.isApngCache()) {
                this.destroyApng();
            } else {
                this.removeApng();
            }
        }
    };

    Sprite.prototype.destroyApng = function() {
        var pixiApng = this._apngSprite.pixiApng;
        if (pixiApng) {
            pixiApng.textures.forEach(function(texture) {
                texture.baseTexture.destroy();
                texture.destroy();
            });
            pixiApng.stop();
        }
        this.removeApng();
    };

    Sprite.prototype.removeApng = function() {
        this.removeChild(this._apngSprite);
        this._apngSprite = null;
    };

    Sprite.prototype.isApngCache = function() {
        return this._apngSprite.pixiApngOption.CachePolicy !== 0;
    };

    Sprite.prototype.loadApngSprite = function() {
        return null;
    };

    Sprite.prototype.updateApngAnchor = function() {
        if (this._apngSprite) {
            this._apngSprite.anchor.x = this.anchor.x;
            this._apngSprite.anchor.y = this.anchor.y;
        }
    };

    Sprite.prototype.updateApngBlendMode = function() {
        if (this._apngSprite) {
            this._apngSprite.blendMode = this.blendMode;
        }
    };

    var _Sprite_update = Sprite.prototype.update;
    Sprite.prototype.update = function() {
        _Sprite_update.apply(this, arguments);
        if (this._apngSprite) {
            if (param.FrameCount > 0) {
                this.updateApngFrame();
            }
            this.updateApngSwitchStop();
            this.updateApngFrameStop();
        }
    };

    Sprite.prototype.updateApngFrame = function() {
        var frameLength = this._apngSprite.pixiApng.getFramesLength();
        var frame = Math.floor(Graphics.frameCount / param.FrameCount) % frameLength;
        this._apngSprite.pixiApng.jumpToFrame(frame);
    };

    Sprite.prototype.updateApngFrameStop = function() {
        if (!param.StopLastFrame) {
            return;
        }
        var frame = this._apngSprite.pixiApng.__status.frame;
        if (frame < this._apngLoopFrame) {
            this._apngLoopCount++;
        }
        this._apngLoopFrame = frame;
        var loopLimit = this.getLoopTimes();
        if (loopLimit <= 0) {
            return;
        }
        var frameLength = this._apngSprite.pixiApng.getFramesLength();
        if (loopLimit <= this._apngLoopCount && frameLength <= frame + 1) {
            this._apngSprite.pixiApng.stop();
        }
    };

    Sprite.prototype.updateApngSwitchStop = function() {
        if ($gameSwitches.value(param.AllStopSwitch)) {
            this._apngSprite.pixiApng.stop();
            this._apngSpritePause = true;
        } else if ($gameSwitches.value(this.getStopSwitch())){
        	var frame = this._apngSprite.pixiApng.__status.frame;
        	var cell = $gameVariables.value(152);
        	if((cell >= 0 )&&(cell == frame)){
            	this._apngSprite.pixiApng.stop();
            	this._apngSpritePause = true;
        	}
        } else if (this._apngSpritePause) {
            this._apngSprite.pixiApng.play();
            this._apngSpritePause = false;
        }
    };

    Sprite.prototype.getLoopTimes = function() {
        return this._apngSprite.pixiApngOption.LoopTimes || param.DefaultLoopTimes;
    };

    Sprite.prototype.getStopSwitch = function() {
        return this._apngSprite.pixiApngOption.StopSwitch;
    };

    /**
     * Sprite_Picture
     * APNGとして登録されているピクチャの読み込みを追加します。
     */
    var _Sprite_Picture_loadBitmap = Sprite_Picture.prototype.loadBitmap;
    Sprite_Picture.prototype.loadBitmap = function() {
        _Sprite_Picture_loadBitmap.apply(this, arguments);
        this.addApngChild(this._pictureName);
    };

    Sprite_Picture.prototype.loadApngSprite = function(name) {
        return SceneManager.tryLoadApngPicture(name);
    };

    var _Sprite_Picture_updateOrigin = Sprite_Picture.prototype.updateOrigin;
    Sprite_Picture.prototype.updateOrigin = function() {
        _Sprite_Picture_updateOrigin.apply(this, arguments);
        this.updateApngAnchor();
    };

    var _Sprite_Picture_updateOther = Sprite_Picture.prototype.updateOther;
    Sprite_Picture.prototype.updateOther = function() {
        _Sprite_Picture_updateOther.apply(this, arguments);
        this.updateApngBlendMode();
    };

    var _Sprite_Picture_updateBitmap =Sprite_Picture.prototype.updateBitmap;
    Sprite_Picture.prototype.updateBitmap = function() {
        _Sprite_Picture_updateBitmap.apply(this, arguments);
        var picture = this.picture();
        if (!picture && this._apngSprite) {
            this.destroyApngIfNeed();
        }
    };

    /**
     * Sprite_Enemy
     * APNGとして登録されている敵キャラの読み込みを追加します。
     */
    var _Sprite_Enemy_loadBitmap = Sprite_Enemy.prototype.loadBitmap;
    Sprite_Enemy.prototype.loadBitmap = function(name, hue) {
        _Sprite_Enemy_loadBitmap.apply(this, arguments);
        this.addApngChild(name);
    };

    Sprite_Enemy.prototype.loadApngSprite = function(name) {
        if ($gameSystem.isSideView()) {
            return SceneManager.tryLoadApngSideEnemy(name);
        } else {
            return SceneManager.tryLoadApngEnemy(name);
        }
    };

    /**
     * SpriteSceneApng
     * シーンに追加表示するAPNGスプライトです。
     */
    class SpriteSceneApng extends Sprite {
       constructor(item) {
           super();
           this.setup(item)
       }

       setup(item) {
           this.addApngChild(item.FileName);
           this.x = item.X;
           this.y = item.Y;
           if (item.Origin === 1) {
               this.anchor.x = 0.5;
               this.anchor.y = 0.5;
           }
           this._switch = item.Switch;
           this._priority = item.Priority;
       }

       loadApngSprite(name) {
           return SceneManager.tryLoadApngSystem(name.replace(/\..*/, ''));
       }

       update() {
           super.update();
           this.visible = this.isValid();
       }

       isValid() {
           return !this._switch || $gameSwitches.value(this._switch);
       }

       getPriority() {
           return this._priority;
       }
    }

    (() => {
        function convars(text = '') {
            do {
                RegExp.$_ = '';
                text = text.replace(/\\v\[(\d+)\]/i, () => {
                    return $gameVariables.value(Number(RegExp.$1));
                });
            } while (RegExp.$_);
            return text;
        }

        var _Game_Picture_erase = Game_Picture.prototype.erase;
        Game_Picture.prototype.erase = function() {
            _Game_Picture_erase.apply(this, arguments);
            this._apngSpeed = 1;
        };

        var _Sprite_Picture_loadApngSprite = Sprite_Picture.prototype.loadApngSprite;
        Sprite_Picture.prototype.loadApngSprite = function(name) {
            let sprite = _Sprite_Picture_loadApngSprite.apply(this, arguments);
            if (sprite && !sprite.pixiApng.framesDelay.isProxy) {
                let pictureId = this._pictureId;
                sprite.pixiApng.framesDelay = new Proxy(sprite.pixiApng.framesDelay, {
                    get: (t, p) => {
                        if (p == 'isProxy') {
                            return true;
                        }
                        if (!p.replace(/[0-9]+/, '')) {
                            let k = 1;
                            let picture = $gameScreen.picture(pictureId);
                            if (picture) {
                                let speed = picture._apngSpeed || 1;
                                k = 1 / speed;
                            }
                            return t[p] * k;
                        }
                        return t[p];
                    }
                });
            }
            return sprite;
        };

        var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
        Game_Interpreter.prototype.pluginCommand = function(command, args) {
            _Game_Interpreter_pluginCommand.apply(this, arguments);
            if (command.toLowerCase() == 'apng_set_speed') {
                let pictureId = Number(convars(args[0])) || 1;
                let speed     = Number(convars(args[1])) || 1;
                $gameScreen.picture(pictureId)._apngSpeed = speed;
            }
        };
    })();

})();


code:
//=============================================================================
// AudioStreaming.js
// MIT License (C) 2019 くらむぼん
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// 2019/06/02 ループタグの指定範囲が全長を超えた場合のループ処理を修正
// 2019/06/02 デコード結果がない場合にエラーになるのを修正
// 2019/06/15 Windows7のFirefoxでストリーミングが無効なバグの場合、フォールバック
// 2019/06/16 暗号化音声ファイル対応
// 2019/06/22 Safariでサンプルレート8000～22050に対応
// 2019/06/27 Safariで一部音声が二重に流れることがある不具合を修正
// 2019/06/29 Cordovaで動作するように修正
// 2019/10/20 ループタグがない場合に二周目以降の先頭が途切れることがある不具合を修正
//=============================================================================

/*:
 * @plugindesc Load audio faster and use only ogg files.
 * @author krmbn0576
 *
 * @param mode
 * @type select
 * @option Enable
 * @value 10
 * @option Enable, and measure performance
 * @value 11
 * @option Disable
 * @value 00
 * @option Disable, and measure performance
 * @value 01
 * @desc Sets whether audio streaming is enabled, and whether measure performance.
 * @default 10
 *
 * @param deleteM4a
 * @type boolean
 * @text Delete all m4a files
 * @desc Delete all m4a files the next time you playtest. Backup your files before execute.
 * @default false
 *
 * @help
 * Load audio faster by audio streaming whether on browsers or on standalones.
 * Use only ogg files to play the audio such as BGM and SE.
 * You need no longer to prepare m4a files.
 *
 * Usage:
 * Locate stbvorbis_stream.js, stbvorbis_stream_asm.js, and this plugin in plugins directory.
 * Turn ON Only this plugin, but DO NOT register the others to plugin manager.
 *
 *
 * License:
 * MIT License
 *
 * Library:
 * ogg decoder - stbvorbis.js (C) Hajime Hoshi, krmbn0576
 * https://github.com/hajimehoshi/stbvorbis.js
 */

/*:ja
 * @plugindesc 音声読み込みを高速化し、oggファイルのみを使用します。
 * @author くらむぼん
 *
 * @param mode
 * @type select
 * @option 有効
 * @value 10
 * @option 有効（読み込み速度を計測する）
 * @value 11
 * @option 無効
 * @value 00
 * @option 無効（読み込み速度を計測する）
 * @value 01
 * @text モード
 * @desc このプラグインを有効にするかどうか、読み込み速度を計測するかどうかを設定します。
 * @default 10
 *
 * @param deleteM4a
 * @type boolean
 * @text m4aファイルを消去
 * @desc 次にテストプレイを開始した時、すべてのm4aファイルを削除します。念の為バックアップを取った上でご活用ください。
 * @default false
 *
 * @help
 * 音声ストリーミングにより、音声読み込みを高速化します。
 * BGMや効果音などの音声ファイルにoggファイルのみを使用します。
 * 本プラグインを入れている場合、m4aファイルを用意しなくても音声を再生できます。
 *
 * 使い方：
 * pluginsフォルダに本プラグインとstbvorbis_stream.jsとstbvorbis_stream_asm.jsを配置してください。
 * ３つのうち本プラグイン「だけ」をプラグイン管理でONに設定してください。
 * 他の２つはOFFでも構いませんし、プラグイン管理に登録しなくても構いません。
 *
 *
 * ライセンス：
 * このプラグインを利用する時は、作者名をプラグインから削除しないでください。
 * それ以外の制限はありません。お好きなようにどうぞ。
 *
 * 使用ライブラリ：
 * oggデコーダー - stbvorbis.js (C) Hajime Hoshi, くらむぼん
 * https://github.com/hajimehoshi/stbvorbis.js
 */

if (function() {
    'use strict';
    const parameters = PluginManager.parameters('AudioStreaming');
    const enabled = parameters['mode'][0] === '1';
    const measured = parameters['mode'][1] === '1';
    const deleteM4a = parameters['deleteM4a'] === 'true';

    const isTest =
        location.search
            .slice(1)
            .split('&')
            .contains('test') ||
        (typeof window.nw !== 'undefined' &&
            nw.App.argv.length > 0 &&
            nw.App.argv[0].split('&').contains('test'));

    if (deleteM4a && isTest && Utils.isNwjs()) {
        const exec = require('child_process').exec;
        let messages, success, failure;
        if (navigator.language.contains('ja')) {
            messages = [
                'すべてのm4aファイルを削除しますか？',
                '本当に削除しますか？念のため、先にプロジェクトフォルダのバックアップをとっておくことをおすすめします。',
                'こうかいしませんね？'
            ];
            success = 'すべてのm4aファイルを削除しました。';
            failure = 'm4aファイルの削除中にエラーが発生しました。 ';
        } else {
            messages = [
                'Delete all m4a files?',
                'Are you sure?',
                'This cannot be undone. Are you really, REALLY sure?'
            ];
            success = 'All m4a files have been deleted.';
            failure = 'Error occured while deleting m4a files.';
        }
        if (messages.every(message => confirm(message))) {
            const command =
                process.platform === 'win32'
                    ? 'del /s *.m4a'
                    : 'find . -name "*.m4a" -delete';
            exec(command, error => alert(error ? failure : success));
        }
    }

    if (measured) {
        const div = document.createElement('div');
        div.style.backgroundColor = 'AliceBlue';
        div.style.position = 'fixed';
        div.style.left = 0;
        div.style.bottom = 0;
        document.body.appendChild(div);

        const updateInfo = info => {
            const decodeEndTime = Date.now();
            const content = `
                name: ${info.url.split('/').pop()}

                mode: ${enabled ? 'streaming' : 'legacy'}

                load time: ${info.loadEndTime - info.loadStartTime}ms

                decode time: ${decodeEndTime - info.loadEndTime}ms
`;

            if (div.innerHTML !== content) div.innerHTML = content;
            div.style.zIndex = 11;
        };

        const _SceneManager_updateManagers = SceneManager.updateManagers;
        SceneManager.updateManagers = function() {
            const _WebAudio__load = WebAudio.prototype._load;
            WebAudio.prototype._load = function(url) {
                _WebAudio__load.apply(this, arguments);
                this._info = { url, loadStartTime: Date.now() };
                this.addLoadListener(() => updateInfo(this._info));
            };

            const _WebAudio__readLoopComments =
                WebAudio.prototype._readLoopComments;
            WebAudio.prototype._readLoopComments = function() {
                this._info.loadEndTime = this._info.loadEndTime || Date.now();
                _WebAudio__readLoopComments.apply(this, arguments);
            };

            SceneManager.updateManagers = _SceneManager_updateManagers;
            SceneManager.updateManagers.apply(this, arguments);
        };
    }

    return enabled;
}()) {

PluginManager.loadScript('stbvorbis_stream.js');

AudioManager.audioFileExt = function() {
    return '.ogg';
};

fetch('').catch(_ => window.cordova = window.cordova || true);

if (window.ResourceHandler) {
    ResourceHandler.fetchWithRetry = async function(
        method,
        url,
        _retryCount = 0
    ) {
        let retry;
        try {
            const response = await (!window.cordova ?
                fetch(url, { credentials: 'same-origin' }) :
                new Promise((resolve, reject) => {
                    const xhr = new XMLHttpRequest();
                    xhr.responseType = 'blob';
                    xhr.onload = () => resolve(new Response(xhr.response, { status: xhr.status }));
                    xhr.onerror = reject;
                    xhr.open('GET', url);
                    xhr.send();
                })
            );
            if (response.ok) {
                switch (method) {
                    case 'stream':
                        if (response.body) {
                            return response.body.getReader();
                        }
                        const value = new Uint8Array(await response.arrayBuffer());
                        return {
                            _done: false,
                            read() {
                                if (!this._done) {
                                    this._done = true;
                                    return Promise.resolve({ done: false, value });
                                } else {
                                    return Promise.resolve({ done: true });
                                }
                            }
                        };
                    case 'arrayBuffer':
                    case 'blob':
                    case 'formData':
                    case 'json':
                    case 'text':
                        return await response[method]();
                    default:
                        return Promise.reject(new Error('method not allowed'));
                }
            } else if (response.status < 500) {
                // client error
                retry = false;
            } else {
                // server error
                retry = true;
            }
        } catch (error) {
            if (Utils.isNwjs() || window.cordova) {
                // local file error
                retry = false;
            } else {
                // network error
                retry = true;
            }
        }
        if (!retry) {
            const error = new Error('Failed to load: ' + url);
            SceneManager.catchException(error);
            throw error;
        } else if (_retryCount < this._defaultRetryInterval.length) {
            await new Promise(resolve =>
                setTimeout(resolve, this._defaultRetryInterval[_retryCount])
            );
            return this.fetchWithRetry(method, url, _retryCount + 1);
        } else {
            if (this._reloaders.length === 0) {
                Graphics.printLoadingError(url);
                SceneManager.stop();
            }
            return new Promise(resolve =>
                this._reloaders.push(() =>
                    resolve(this.fetchWithRetry(method, url, 0))
                )
            );
        }
    };
}

WebAudio.prototype.clear = function() {
    this.stop();
    this._chunks = [];
    this._gainNode = null;
    this._pannerNode = null;
    this._totalTime = 0;
    this._sampleRate = 0;
    this._loopStart = 0;
    this._loopLength = 0;
    this._startTime = 0;
    this._volume = 1;
    this._pitch = 1;
    this._pan = 0;
    this._loadedTime = 0;
    this._offset = 0;
    this._loadListeners = [];
    this._stopListeners = [];
    this._hasError = false;
    this._autoPlay = false;
    this._isReady = false;
    this._isPlaying = false;
    this._loop = false;
};

WebAudio.prototype._load = async function(url) {
    if (WebAudio._context) {
        if (Decrypter.hasEncryptedAudio) {
            url = Decrypter.extToEncryptExt(url);
        }
        const reader = await ResourceHandler.fetchWithRetry('stream', url);
        this._loading(reader);
    }
};

WebAudio.prototype._loading = async function(reader) {
    try {
        const decode = stbvorbis.decodeStream(result => this._onDecode(result));
        while (true) {
            const { done, value } = await reader.read();
            if (done) {
                decode({ eof: true });
                return;
            }
            let array = value;
            if (Decrypter.hasEncryptedAudio) {
                array = Decrypter.decryptUint8Array(array);
            }
            this._readLoopComments(array);
            decode({ data: array, eof: false });
        }
    } catch (error) {
        console.error(error);
        const autoPlay = this._autoPlay;
        const loop = this._loop;
        const pos = this.seek();
        this.initialize(this._url);
        if (autoPlay) {
            this.play(loop, pos);
        }
    }
};

WebAudio.prototype._onDecode = function(result) {
    if (result.error) {
        console.error(result.error);
        return;
    }
    if (result.eof) {
        this._totalTime = this._loadedTime;
        if (this._loopLength === 0) {
            this._loopStart = 0;
            this._loopLength = this._totalTime;
            if (this._loop) {
                this._createSourceNodes();
            }
        } else if (this._totalTime < this._loopStart + this._loopLength) {
            this._loopLength = this._totalTime - this._loopStart;
            if (this._loop) {
                this._createSourceNodes();
            }
        }
        if (this._totalTime <= this.seek()) {
            this.stop();
        }
        return;
    }
    if (result.data[0].length === 0) {
        return;
    }
    let buffer;
    try {
        buffer = WebAudio._context.createBuffer(
            result.data.length,
            result.data[0].length,
            result.sampleRate
        );
    } catch (error) {
        if (8000 <= result.sampleRate && result.sampleRate < 22050) {
            result.sampleRate *= 3;
            for (let i = 0; i < result.data.length; i++) {
                const old = result.data[i];
                result.data[i] = new Float32Array(result.data[i].length * 3);
                for (let j = 0; j < old.length; j++) {
                    result.data[i][j * 3] = old[j];
                    result.data[i][j * 3 + 1] = old[j];
                    result.data[i][j * 3 + 2] = old[j];
                }
            }
            buffer = WebAudio._context.createBuffer(
                result.data.length,
                result.data[0].length,
                result.sampleRate
            );
        } else {
            throw error;
        }
    }
    for (let i = 0; i < result.data.length; i++) {
        if (buffer.copyToChannel) {
            buffer.copyToChannel(result.data[i], i);
        } else {
            buffer.getChannelData(i).set(result.data[i]);
        }
    }
    const chunk = { buffer, sourceNode: null, when: this._loadedTime };
    this._chunks.push(chunk);
    this._loadedTime += buffer.duration;
    this._createSourceNode(chunk);
    if (!this._isReady && this._loadedTime >= this._offset) {
        this._isReady = true;
        this._onLoad();
    }
};

Object.defineProperty(WebAudio.prototype, 'pitch', {
    get: function() {
        return this._pitch;
    },
    set: function(value) {
        if (this._pitch !== value) {
            this._pitch = value;
            if (this.isPlaying()) {
                this.play(this._loop, 0);
            }
        }
    },
    configurable: true
});

WebAudio.prototype.isReady = function() {
    return this._isReady;
};

WebAudio.prototype.isPlaying = function() {
    return this._isPlaying;
};

WebAudio.prototype.play = function(loop, offset) {
    this._autoPlay = true;
    this._loop = loop;
    this._offset = offset || 0;
    if (this._loop && this._loopLength > 0) {
        while (this._offset >= this._loopStart + this._loopLength) {
            this._offset -= this._loopLength;
        }
    }
    if (this.isReady()) {
        this._startPlaying();
    }
};

WebAudio.prototype.stop = function() {
    const wasPlaying = this.isPlaying();
    this._isPlaying = false;
    this._autoPlay = false;
    this._removeNodes();
    if (this._stopListeners && wasPlaying) {
        this._stopListeners.forEach(listener => listener());
        this._stopListeners.length = 0;
    }
};

WebAudio.prototype.seek = function() {
    if (WebAudio._context && this.isPlaying()) {
        let pos =
            (WebAudio._context.currentTime - this._startTime) * this._pitch;
        if (this._loop && this._loopLength > 0) {
            while (pos >= this._loopStart + this._loopLength) {
                pos -= this._loopLength;
            }
        }
        return pos;
    } else {
        return 0;
    }
};

WebAudio.prototype._startPlaying = function() {
    this._isPlaying = true;
    this._startTime =
        WebAudio._context.currentTime - this._offset / this._pitch;
    this._removeNodes();
    this._createNodes();
    this._connectNodes();
    this._createSourceNodes();
};

WebAudio.prototype._calcSourceNodeParams = function(chunk) {
    const currentTime = WebAudio._context.currentTime;
    const chunkEnd = chunk.when + chunk.buffer.duration;
    const pos = this.seek();
    let when, offset, duration;
    if (this._loop && this._loopLength) {
        const loopEnd = this._loopStart + this._loopLength;
        if (pos <= chunk.when) {
            when = currentTime + (chunk.when - pos) / this._pitch;
        } else if (pos <= (window.AudioContext ? chunkEnd : chunkEnd - 0.0001)) {
            when = currentTime;
            offset = pos - chunk.when;
        } else if (this._loopStart <= pos) {
            when =
                currentTime +
                (chunk.when - pos + this._loopLength) / this._pitch;
        } else {
            return;
        }
        if (this._loopStart <= pos && chunk.when < this._loopStart) {
            if (!offset) {
                when += (this._loopStart - chunk.when) / this._pitch;
                offset = this._loopStart - chunk.when;
            }
            if (chunk.buffer.duration <= offset) {
                return;
            }
        }
        if (loopEnd < chunkEnd) {
            if (!offset) {
                offset = 0;
            }
            duration = loopEnd - chunk.when - offset;
            if (duration <= 0) {
                return;
            }
        }
    } else {
        if (pos <= chunk.when) {
            when = currentTime + (chunk.when - pos) / this._pitch;
        } else if (pos <= (window.AudioContext ? chunkEnd : chunkEnd - 0.0001)) {
            when = currentTime;
            offset = pos - chunk.when;
        } else {
            return;
        }
    }
    return { when, offset, duration };
};

WebAudio.prototype._createSourceNode = function(chunk) {
    if (!this.isPlaying() || !chunk) {
        return;
    }
    if (chunk.sourceNode) {
        chunk.sourceNode.onended = null;
        chunk.sourceNode.stop();
        chunk.sourceNode = null;
    }
    const params = this._calcSourceNodeParams(chunk);
    if (!params) {
        if (!this._reservedSeName && this._loopLength) {
            this._chunks[this._chunks.indexOf(chunk)] = null;
        }
        return;
    }
    const { when, offset, duration } = params;
    const context = WebAudio._context;
    const sourceNode = context.createBufferSource();
    sourceNode.onended = _ => {
        this._createSourceNode(chunk);
        if (this._totalTime && this._totalTime <= this.seek()) {
            this.stop();
        }
    };
    sourceNode.buffer = chunk.buffer;
    sourceNode.playbackRate.setValueAtTime(this._pitch, context.currentTime);
    sourceNode.connect(this._gainNode);
    sourceNode.start(when, offset, duration);
    chunk.sourceNode = sourceNode;
};

WebAudio.prototype._createSourceNodes = function() {
    this._chunks.forEach(chunk => this._createSourceNode(chunk));
};

WebAudio.prototype._createNodes = function() {
    const context = WebAudio._context;
    this._gainNode = context.createGain();
    this._gainNode.gain.setValueAtTime(this._volume, context.currentTime);
    this._pannerNode = context.createPanner();
    this._pannerNode.panningModel = 'equalpower';
    this._updatePanner();
};

WebAudio.prototype._connectNodes = function() {
    this._gainNode.connect(this._pannerNode);
    this._pannerNode.connect(WebAudio._masterGainNode);
};

WebAudio.prototype._removeNodes = function() {
    if (this._chunks) {
        this._chunks
            .filter(chunk => chunk && chunk.sourceNode)
            .forEach(chunk => {
                chunk.sourceNode.onended = null;
                chunk.sourceNode.stop();
                chunk.sourceNode = null;
            });
    }
    this._gainNode = null;
    this._pannerNode = null;
};

WebAudio.prototype._onLoad = function() {
    if (this._autoPlay) {
        this.play(this._loop, this._offset);
    }
    this._loadListeners.forEach(listener => listener());
    this._loadListeners.length = 0;
};

WebAudio.prototype._readLoopComments = function(array) {
    if (this._sampleRate === 0) {
        this._readOgg(array);
        if (this._loopLength > 0 && this._sampleRate > 0) {
            this._loopStart /= this._sampleRate;
            this._loopLength /= this._sampleRate;
        }
    }
};

Decrypter.decryptUint8Array = function(uint8Array) {
    const ref = this.SIGNATURE + this.VER + this.REMAIN;
    for (let i = 0; i < this._headerlength; i++) {
        if (uint8Array[i] !== parseInt('0x' + ref.substr(i * 2, 2), 16)) {
            return uint8Array;
        }
    }
    uint8Array = new Uint8Array(uint8Array.buffer, this._headerlength);
    this.readEncryptionkey();
    for (var i = 0; i < this._headerlength; i++) {
        uint8Array[i] = uint8Array[i] ^ parseInt(this._encryptionKey[i], 16);
    }
    return uint8Array;
};

}

repo_name: dazed/translations

license: unknown


code:
//=============================================================================
// BB_CustomSaveWindow.js
// Copyright (c) 2016 BB ENTERTAINMENT
//=============================================================================

/*:
 * @plugindesc セーブウインドウ改造プラグイン
 * @author ビービー
 *
 *
 * @param OutsideFrameColor
 * @desc 外枠の色を指定（テキストカラー0～31）
 * デフォルト：0
 * @default 0
 *
 * @param OutsideFrameOpacity
 * @desc 外枠の透明度を指定（0～255）
 * デフォルト：64
 * @default 64
 *
 * @param InsideFrameColor
 * @desc 内枠の色を指定（テキストカラー0～31）
 * デフォルト：0
 * @default 0
 *
 * @param InsideFrameOpacity
 * @desc 内枠の透明度を指定（0～255）
 * デフォルト：64
 * @default 64
 *
 * @param MaxItem
 * @desc 内枠の数を指定（1～4）
 * デフォルト：4（0で非表示）
 * @default 4
 *
 * @param Item0
 * @desc ファイルID右に表示される項目 0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * @default 1
 *
 * @param Item0Length
 * @desc ファイルID右に表示される項目の横幅（Item5(右上に表示される項目)に影響）
 * @default 300
 *
 * @param Item1title
 * @desc 右下に表示される項目のタイトル
 * デフォルト：プレイ時間
 * @default プレイ時間
 *
 * @param FileAutoSave
 * @desc オートセーブファイル1に追記される表記
 * デフォルト：[オートセーブ]
 * @default [オートセーブ]
 *
 * @param Item1
 * @desc 右下に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * @default 2
 *
 * @param Item2title
 * @desc 中央右に表示される項目のタイトル
 * デフォルト：現在地
 * @default 現在地
 *
 * @param Item2
 * @desc 中央右に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：3
 * @default 3
 *
 * @param Item3title
 * @desc 中央下に表示される項目のタイトル
 * デフォルト：所持金
 * @default 所持金
 *
 * @param Item3
 * @desc 中央下に表示される項  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：4
 * @default 4
 *
 * @param Item4title
 * @desc 中央に表示される項目のタイトル
 * デフォルト：セーブ回数
 * @default セーブ回数
 *
 * @param Item4
 * @desc 中央に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：5
 * @default 5
 *
 * @param Item5
 * @desc 右上に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：6
 * @default 6
 *
 * @param ItemValue1
 * @desc 変数項目1に入れる変数のID
 * デフォルト：1
 * @default 1
 *
 * @param ItemValue2
 * @desc 変数項目2に入れる変数のID
 * デフォルト：2
 * @default 2
 *
 * @param ItemValue3
 * @desc 変数項目3に入れる変数のID
 * デフォルト：3
 * @default 3
 *
 * @param ItemValue4
 * @desc 変数項目4に入れる変数のID
 * デフォルト：4
 * @default 4
 *
 * @param ItemValue1unit
 * @desc 変数項目1の単位
 * デフォルト：無し
 * @default
 *
 * @param ItemValue2unit
 * @desc 変数項目2の単位
 * デフォルト：無し
 * @default
 *
 * @param ItemValue3unit
 * @desc 変数項目3の単位
 * デフォルト：無し
 * @default
 *
 * @param ItemValue4unit
 * @desc 変数項目4の単位
 * デフォルト：無し
 * @default
 *
 * @param Subtitle0
 * @desc サブタイトル0
 * デフォルト：邂逅
 * @default 邂逅
 *
 * @param Subtitle1
 * @desc サブタイトル1（前半）
 * デフォルト：第1章「弱い人間、強い力(前編)」
 * @default 第1章「弱い人間、強い力(前編)」
 *
 * @param Subtitle2
 * @desc サブタイトル1(後編)
 * デフォルト：第1章「弱い人間、強い力(後編)」
 * @default 第1章「弱い人間、強い力(後編)」
 *
 * @param Subtitle3
 * @desc サブタイトル2（前半）
 * デフォルト：第2章「歓楽街と夜の王(前編)」
 * @default 第2章「歓楽街と夜の王(前編)」
 *
 * @param Subtitle4
 * @desc サブタイトル2(後編)
 * デフォルト：第2章「歓楽街と夜の王(後編)」
 * @default 第2章「歓楽街と夜の王(後編)」
 *
 * @param Subtitle5
 * @desc サブタイトル3（前半）
 * デフォルト：第3章「ドキッ！スケベだらけのナイトプール（前編）」
 * @default 第3章「ドキッ！スケベだらけのナイトプール（前編）」
 *
 * @param Subtitle6
 * @desc サブタイトル3(後編)
 * デフォルト：第3章「ドキッ！スケベだらけのナイトプール（後編）」
 * @default 第3章「ドキッ！スケベだらけのナイトプール（後編）」
 *
 * @param Subtitle7
 * @desc サブタイトル4（前半）
 * デフォルト：第4章「催眠学園（前編）」
 * @default 第4章「催眠学園（前編）」
 *
 * @param Subtitle8
 * @desc サブタイトル4(後編)
 * デフォルト：第4章「催眠学園（後編）」
 * @default 第4章「催眠学園（後編）」
 *
 * @param Subtitle9
 * @desc サブタイトル5（前半）
 * デフォルト：第5章「醒めない悪夢（前編）」
 * @default 第5章「醒めない悪夢（前編）」
 *
 * @param Subtitle10
 * @desc サブタイトル5(後編)
 * デフォルト：第5章「醒めない悪夢（後編）」
 * @default 第5章「醒めない悪夢（後編）」
 *
 * @param Subtitle11
 * @desc サブタイトル6
 * デフォルト：最終章「夢の果て」
 * @default 最終章「夢の果て」
 *
 * @param Subtitle12
 * @desc サブタイトル7
 * デフォルト：★クリアデータ
 * @default ★クリアデータ
 *
 * @param Subtitle13
 * @desc サブタイトル8
 * デフォルト：予備
 * @default 予備
 *
 * @param NoPlace
 * @desc セーブ場所が無記名の場合の表記
 * デフォルト：幕間
 * @default 幕間
 *
 * @param Day_Morning
 * @desc 日付の欄に表示する時間帯表記（朝）
 * デフォルト：朝
 * @default 朝
 *
 * @param Day_Afternoon
 * @desc 日付の欄に表示する時間帯表記（昼）
 * デフォルト：昼
 * @default 昼
 *
 * @param Day_Evening
 * @desc 日付の欄に表示する時間帯表記（昼）
 * デフォルト：夕
 * @default 夕
 *
 * @param Day_Night
 * @desc 日付の欄に表示する時間帯表記（夜）
 * デフォルト：夜
 * @default 夜
 *
 * @param Day_MidNight
 * @desc 日付の欄に表示する時間帯表記（深夜）
 * デフォルト：深夜
 * @default 深夜
 *
 * @param Day_Dream
 * @desc 日付の欄に表示する時間帯表記（夢）
 * デフォルト：夢
 * @default 夢
 *
 * @param TitleFramelength1
 * @desc 項目1のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param TitleFramelength2
 * @desc 項目2のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param TitleFramelength3
 * @desc 項目3のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param TitleFramelength4
 * @desc 項目4のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param CharacterPositionY
 * @desc キャラクターグラフィックのy座標（下=6 中央=12 上=20）
 * デフォルト：6
 * @default 6
 *
 * @param LevelPositionY
 * @desc レベルのy座標（下=72 上=23）
 * デフォルト：23
 * @default 23
 *
 * @param LevelOnOff
 * @desc レベルを表示するかしないかを指定（0＝非表示、1＝表示）
 * デフォルト：1
 * @default 1
 *
 * @help プラグインの説明
 *
 * ■各パラメータの説明
 * プラグイン内より少しだけ詳しくパラメータの説明をしていきます。
 *
 * OutsideFrameColor
 * 外枠の色をテキストカラーの0～31で指定できます。
 * デフォルト：0
 *
 * OutsideFrameOpacity
 * 外枠の透明度を0～255の数値で指定できます（0＝透明、255＝不透明）
 * デフォルト：64
 *
 * InsideFrameColor
 * 内枠の色をテキストカラーの0～31で指定できます。
 * デフォルト：0
 *
 * InsideFrameOpacity
 * 内枠の透明度を0～255の数値で指定できます（0＝透明、255＝不透明）
 * デフォルト：64
 *
 * MaxItem
 * 内枠の数を0から4のあいだで指定できます。
 * デフォルト：4（0で非表示）
 *
 * Item0
 * ファイルID右に表示される項目を0～9の数字で指定します。
 * 0＝非表示
 * 1＝ゲームタイトル
 * 2＝プレイ時間
 * 3＝マップ名
 * 4＝所持金（自動で通貨単位も表示されます）
 * 5＝セーブ回数
 * 6＝パラメータのItemValue1で指定した変数の値（パラメータのItemValue1unitで単位を指定できます）
 * 7＝パラメータのItemValue2で指定した変数の値（パラメータのItemValue2unitで単位を指定できます）
 * 8＝パラメータのItemValue3で指定した変数の値（パラメータのItemValue3unitで単位を指定できます）
 * 9＝パラメータのItemValue4で指定した変数の値（パラメータのItemValue4unitで単位を指定できます）
 *
 * Item0Length
 * ファイルID右に表示される項目の横幅を指定できます。（Item5(右上に表示される項目)に影響）
 * 指定したサイズより文字列の幅が大きい場合、指定したサイズに自動で文字幅が縮小されます。
 * default 300
 *
 * Item1title
 * 右下に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：プレイ時間
 *
 * Item1
 * 右下に表示される項目を0～9の数字で指定します。
 * デフォルト：2
 *
 * Item2title
 * 中央右に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：現在地
 *
 * Item2
 * 中央右に表示される項目を0～9の数字で指定します。
 * デフォルト：3
 *
 * Item3title
 * 中央下に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：所持金
 *
 * Item3
 * 中央下に表示される項を0～9の数字で指定します。
 * デフォルト：4
 *
 * Item4title
 * 中央に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：セーブ回数
 *
 * Item4
 * 中央に表示される項目を0～9の数字で指定します。
 * デフォルト：5
 *
 * Item5
 * 右上に表示される項目を0～9の数字で指定します。
 * デフォルト：6
 *
 * ItemValue1
 * 変数項目1に入れる変数のIDを指定します。
 * デフォルト：1
 *
 * ItemValue2
 * 変数項目2に入れる変数のIDを指定します。
 * デフォルト：2
 *
 * ItemValue3
 * 変数項目3に入れる変数のIDを指定します。
 * デフォルト：3
 *
 * ItemValue4
 * 変数項目4に入れる変数のIDを指定します。
 * デフォルト：4
 *
 * ItemValue1unit
 * 変数項目1の単位を指定します。
 * デフォルト：無し
 *
 * ItemValue2unit
 * 変数項目2の単位を指定します。
 * デフォルト：無し
 *
 * ItemValue3unit
 * 変数項目3の単位を指定します。
 * デフォルト：無し
 *
 * ItemValue4unit
 * 変数項目4の単位を指定します。
 * デフォルト：無し
 *
 * TitleFramelength1
 * 項目1のタイトル枠の横幅を0～274のあいだから指定します。
 * 文字数*20+10で文字の幅と同じ幅の枠を描画できます
 * 指定した枠幅より文字幅がはみ出る場合自動で文字幅が縮小されます。
 * デフォルト：110（5文字）
 *
 * TitleFramelength2
 * 項目2のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 *
 * TitleFramelength3
 * 項目3のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 *
 * TitleFramelength4
 * 項目4のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 *
 * CharacterPositionY
 * キャラクターグラフィックのy座標を指定します。
 * 下の方に表示したい場合は6、中央あたりなら12 上の方なら20が目安です。
 * デフォルト：6
 *
 * LevelPositionY
 * レベルのy座標を指定します。下の方なら72、上の方なら23が目安です。
 * レベルの表示はキャラクターグラフィックより手前に表示されます。
 * デフォルト：23
 *
 * LevelOnOff
 * レベルを表示するかしないかを指定（0＝非表示、1＝表示）
 * デフォルト：1
 *
 *
 * ■変数に文字列を代入する方法
 * 変数に文字列を代入するには
 * イベントコマンドの"タブ1"にある"ゲーム進行"内の"変数の操作"を実行し
 * 代入したい変数を選び、代入にチェックを入れ
 * スクリプトに書き込みます
 * このとき　'　←この記号ではじめと終わりを挟むのを忘れないでください。
 * （ ' ←この記号はキーボードが半角英数のときにshiftを押しながら７で打てます）
 *
 * ■BB ENTERTAINMENT BLOGにて画像付きで解説しています。
 * 記事：http://bb-entertainment-blog.blogspot.jp/2016/11/blog-post_27.html#more
 *
 * バージョン：
 * 1.0.2 2016/12/01 レベルの表示、非表示を切り替えるパラメータを追加
 * 1.0.1 2016/11/29 ヘルプを追記
 * 1.0.0 2016/11/27 初版
 *
 * 利用規約：
 * このプラグインは、MITライセンスのもとで公開されています。
 * Copyright (c) 2016 BB ENTERTAINMENT
 * Released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 *
 * コンタクト：
 * BB ENTERTAINMENT Twitter: https://twitter.com/BB_ENTER/
 * BB ENTERTAINMENT BLOG   : http://bb-entertainment-blog.blogspot.jp/
 */

(function() {
'use strict';
//-----------------------------------------------------------------------------
// プラグインパラメータ管理
//-----------------------------------------------------------------------------
var parameters = PluginManager.parameters('BB_CustomSaveWindow');
var BBSWInFC = Number(parameters['InsideFrameColor']);
var BBSWInFO = Number(parameters['InsideFrameOpacity']);
var BBSWOutFC = Number(parameters['OutsideFrameColor']);
var BBSWOutFO = Number(parameters['OutsideFrameOpacity']);
var BBSWMaxItem = Number(parameters['MaxItem']);
var BBSWFileAutoSave = String(parameters['FileAutoSave']);
var BBSWItem0 = Number(parameters['Item0']);
var BBSWItem0L = Number(parameters['Item0Length']);
var BBSWItem1T = String(parameters['Item1title']);
var BBSWItem1 = Number(parameters['Item1']);
var BBSWItem2T = String(parameters['Item2title']);
var BBSWItem2 = Number(parameters['Item2']);
var BBSWItem3T = String(parameters['Item3title']);
var BBSWItem3 = Number(parameters['Item3']);
var BBSWItem4T = String(parameters['Item4title']);
var BBSWItem4 = Number(parameters['Item4']);
var BBSWItem5 = Number(parameters['Item5']);
var BBSWV1 = Number(parameters['ItemValue1']);
var BBSWV2 = Number(parameters['ItemValue2']);
var BBSWV3 = Number(parameters['ItemValue3']);
var BBSWV4 = Number(parameters['ItemValue4']);
var BBSWV1u = String(parameters['ItemValue1unit']);
var BBSWV2u = String(parameters['ItemValue2unit']);
var BBSWV3u = String(parameters['ItemValue3unit']);
var BBSWV4u = String(parameters['ItemValue4unit']);
var BBSWTF1 = Number(parameters['TitleFramelength1']);
var BBSWTF2 = Number(parameters['TitleFramelength2']);
var BBSWTF3 = Number(parameters['TitleFramelength3']);
var BBSWTF4 = Number(parameters['TitleFramelength4']);
var BBSWCPY = Number(parameters['CharacterPositionY']);
var BBSWLPY = Number(parameters['LevelPositionY']);
var BBSWLOO = Number(parameters['LevelOnOff']);
var BBSWSubTitle0 = String(parameters['Subtitle0']);
var BBSWSubTitle1 = String(parameters['Subtitle1']);
var BBSWSubTitle2 = String(parameters['Subtitle2']);
var BBSWSubTitle3 = String(parameters['Subtitle3']);
var BBSWSubTitle4 = String(parameters['Subtitle4']);
var BBSWSubTitle5 = String(parameters['Subtitle5']);
var BBSWSubTitle6 = String(parameters['Subtitle6']);
var BBSWSubTitle7 = String(parameters['Subtitle7']);
var BBSWSubTitle8 = String(parameters['Subtitle8']);
var BBSWSubTitle9 = String(parameters['Subtitle9']);
var BBSWSubTitle10 = String(parameters['Subtitle10']);
var BBSWSubTitle11 = String(parameters['Subtitle11']);
var BBSWSubTitle12 = String(parameters['Subtitle12']);
var BBSWNoPlace = String(parameters['NoPlace']);
var BBSWDay_Morning = String(parameters['Day_Morning']);
var BBSWDay_Afternoon = String(parameters['Day_Afternoon']);
var BBSWDay_Evening = String(parameters['Day_Evening']);
var BBSWDay_Night = String(parameters['Day_Night']);
var BBSWDay_MidNight = String(parameters['Day_MidNight']);
var BBSWDay_Dream = String(parameters['Day_Dream']);

//-----------------------------------------------------------------------------
// セーブデータに名前を定義
//-----------------------------------------------------------------------------
var _DataManager_makeSavefileInfo = DataManager.makeSavefileInfo;
DataManager.makeSavefileInfo = function() {
    var info = {};
    info.globalId   = this._globalId;
    if($gameVariables.value(33)==0){
    	info.title = BBSWSubTitle0
    }else if($gameVariables.value(33)==1){
    	info.title = BBSWSubTitle1
    }else if($gameVariables.value(33)==2){
    	info.title = BBSWSubTitle2
    }else if($gameVariables.value(33)==3){
    	info.title = BBSWSubTitle3
    }else if($gameVariables.value(33)==4){
    	info.title = BBSWSubTitle4
    }else if($gameVariables.value(33)==5){
    	info.title = BBSWSubTitle5
    }else if($gameVariables.value(33)==6){
    	info.title = BBSWSubTitle6
    }else if($gameVariables.value(33)==7){
    	info.title = BBSWSubTitle7
    }else if($gameVariables.value(33)==8){
    	info.title = BBSWSubTitle8
    }else if($gameVariables.value(33)==9){
    	info.title = BBSWSubTitle9
    }else if($gameVariables.value(33)==10){
    	info.title = BBSWSubTitle10
    }else if($gameVariables.value(33)==11){
    	info.title = BBSWSubTitle11
    }else{
    	info.title = BBSWSubTitle12
    }
    info.characters = $gameParty.charactersForSavefile();
    info.faces      = $gameParty.facesForSavefile();
    info.playtime   = $gameSystem.playtimeText();
    info.timestamp  = Date.now();
//add--------------------------------------------------------------------------
    info.mapname    = $gameMap.displayName();
    info.gold       = $gameParty._gold;
    info.savecount  = $gameSystem._saveCount;
    info.value1     = $gameVariables.value(BBSWV1);
    info.value2     = $gameVariables.value(BBSWV2);
    info.value3     = $gameVariables.value(BBSWV3);
    info.value4     = $gameVariables.value(BBSWV4);
	info.level1 	= $gameParty.members()[0].level;
    if(info.mapname == ""){info.mapname = BBSWNoPlace}
//-----------------------------------------------------------------------------
    return info;
};

var _Window_SavefileList_prototype_drawItem = Window_SavefileList.prototype.drawItem;
Window_SavefileList.prototype.drawItem = function(index) {
    var id = index + 1;
    var valid = DataManager.isThisGameFile(id);
    var info = DataManager.loadSavefileInfo(id);
    var rect = this.itemRectForText(index);
//add--------------------------------------------------------------------------
    this.contents.fontSize = 20;
    this.contents.paintOpacity = BBSWInFO;
    this.contents.fillRect(rect.x - 5, rect.y + 2, rect.width + 10, 2, this.textColor(BBSWInFC));

    this.contents.fillRect(rect.x - 3, rect.y + 4, rect.width + 6, 28, this.textColor(BBSWInFC));
    this.contents.paintOpacity = BBSWOutFO;
    if (BBSWMaxItem >= 0) {
    }
    if (BBSWMaxItem >= 1) {
        this.contents.fillRect(rect.x + 595, rect.y + 95, BBSWTF1, 26, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 595, rect.y + 93, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 595, rect.y + 121, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 944, rect.y + 95, 2, 26, this.textColor(BBSWOutFC));

    } if (BBSWMaxItem >= 2) {
        this.contents.fillRect(rect.x + 595, rect.y + 44, BBSWTF2, 26, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 595, rect.y + 42, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 595, rect.y + 70, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 944, rect.y + 44, 2, 26, this.textColor(BBSWOutFC));

    } if (BBSWMaxItem >= 3) {
        this.contents.fillRect(rect.x + 210, rect.y + 95, BBSWTF3, 26, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 210, rect.y + 93, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 210, rect.y + 121, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 559, rect.y + 95, 2, 26, this.textColor(BBSWOutFC));
    } if (BBSWMaxItem >= 4) {
        this.contents.fillRect(rect.x + 210, rect.y + 44, BBSWTF4, 26, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 210, rect.y + 42, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 210, rect.y + 70, 351, 2, this.textColor(BBSWOutFC));
        this.contents.fillRect(rect.x + 559, rect.y + 44, 2, 26, this.textColor(BBSWOutFC));
    }
    this.contents.paintOpacity = 255;
//-----------------------------------------------------------------------------
    this.resetTextColor();
    if (this._mode === 'load') {
        this.changePaintOpacity(valid);
    }

    this.drawFileId(id, rect.x, rect.y);
    if(index == 0 && SceneManager._scene.constructor === Scene_Save){
        this.changePaintOpacity(false);
        this.drawContents(info, rect, valid);
        this.changePaintOpacity(true);
    }else if (info) {
        this.changePaintOpacity(valid);
        this.drawContents(info, rect, valid,id);
        this.changePaintOpacity(true);
    }
};
var _Window_SavefileList_prototype_drawContents = Window_SavefileList.prototype.drawContents;
Window_SavefileList.prototype.drawContents = function(info, rect, valid) {
    var bottom = rect.y + rect.height;
    if (rect.width >= 420) {
//項目0(タイトル表示)------------------------------------------------------------------------
		if(info.title == BBSWSubTitle12)this.changeTextColor(this.textColor(17))
        this.drawText(info.title, rect.x + 142, rect.y+5, BBSWItem0L+150);
		if(info.title == BBSWSubTitle12)this.resetTextColor ()

//-----------------------------------------------------------------------------
        if (valid) {
            this.drawPartyCharacters(info, rect.x + 125, bottom - 28);//-6 -12 -20
//レベル表示-------------------------------------------------------------------
        if (BBSWLOO == 1) {
            this.contents.fontSize = 16;
            this.drawText(TextManager.levelA + " " + info.level1, rect.x + 5, rect.y + BBSWLPY+10, 40);//72 23
            if (info.characters.length == 2) {
                this.drawText(TextManager.levelA + " " + info.level2, rect.x + 5 + 48 + 75, rect.y + BBSWLPY+10, 40);}
            this.contents.fontSize = 20;
        }
//-----------------------------------------------------------------------------
        }
    }
    var lineHeight = this.lineHeight();
    var y2 = bottom - lineHeight;
    if (y2 >= lineHeight) {
//項目1 右上（プレイ時間表示）-------------------------------------------------------------------
        this.drawText(BBSWItem1T, rect.x + 525 + 75, y2 - 52, BBSWTF1 - 10);
		this.drawText(info.playtime, rect.x + 525 + BBSWTF1 + 150, y2 - 52, 266 - BBSWTF1, 'right');

//-----------------------------------------------------------------------------
//項目2 右下（マップ名表示）-------------------------------------------------------------------
        this.drawText(BBSWItem2T, rect.x + 525 + 75, y2 - 1, BBSWTF2 - 10);

        //文字幅の自動調整が効かない範囲の時のみ動作
        //アルファベットや記号のあるマップの余白を詰める。Nu・menumeだけ余白が大きく残るので無理やり補正
        var x_ascii = 0;
        if(266 - BBSWTF2+ 75 > this.textWidth(info.mapname)){
			for (var i = 0; i < info.mapname.length; i++) {
			    if (info.mapname.charCodeAt(i) < 128) {
			    	if(info.mapname.charCodeAt(i) != 32){
				        x_ascii += 1;
				    }else{
				        x_ascii -= 4;
				    }
			    }else{
			        if(info.mapname[i]=="･")x_ascii+=16;
			    }
			}
		}
        this.drawText(info.mapname, rect.x + 525 + BBSWTF2 + 75 + x_ascii, y2 - 1, 266 - BBSWTF2+ 75, 'right');
//-----------------------------------------------------------------------------
//項目3 左上（所持金表示）-------------------------------------------------------------------
        this.drawText(BBSWItem3T, rect.x + 215, y2 - 52, BBSWTF3 - 10);
            this.drawText(info.gold + TextManager.currencyUnit, rect.x + 215 + BBSWTF3 + 75, y2 - 52, 266 - BBSWTF3, 'right');
//-----------------------------------------------------------------------------
//項目4 左下（日付表示）-------------------------------------------------------------------
        this.drawText(BBSWItem4T, rect.x + 215, y2 - 1, BBSWTF4 - 10);
		if(info.value2<=1)var time = BBSWDay_Morning
		if(info.value2==2)var time = BBSWDay_Evening
		if(info.value2==3)var time = BBSWDay_Night;
		if(info.value2==4)var time = BBSWDay_MidNight;
		if(info.value2>=5)var time = BBSWDay_Dream;

        this.drawText(info.value1 + "日目-" + time, rect.x + 215 + BBSWTF4 + 75, y2 - 1, 266 - BBSWTF4, 'right');

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
    }
};

var _Window_SavefileList_prototype_drawFileId = Window_SavefileList.prototype.drawFileId;
Window_SavefileList.prototype.drawFileId = function(id, x, y) {
	if(id==1){
        if(SceneManager._scene.constructor === Scene_Save)this.changePaintOpacity(false);
	    this.drawText(TextManager.file + ' ' + id, x, y, 120);
	    this.changeTextColor(this.textColor(16))
	    this.contents.fontSize = 10;
	    this.drawText(BBSWFileAutoSave, x+65, y+36, 120);//オートセーブの表示
	    this.resetTextColor ()
	    this.contents.fontSize = 20;
        if(SceneManager._scene.constructor === Scene_Save)this.changePaintOpacity(true);
	}else{
	    this.drawText(TextManager.file + ' ' + id, x, y, 120);
	}
};

})();


code:
//=============================================================================
// BB_IconChainTextEx.js
// Copyright (c) 2017 BB ENTERTAINMENT
//=============================================================================

/*:
 * @plugindesc アイコンを隙間なく連続で表示する制御文字を追加するプラグイン
 * @author ビービー
 *
 * @param DrawIconChain
 * @desc アイコンを連続して表示する個数
 * デフォルト：4
 * @default 4
 *
 * @help 【プラグインの説明】
 * アイコンをパラメータで指定した数だけ連続して表示する制御文字\D[n]と
 * アイコン表示後の隙間を無くし任意の数だけアイコンを連続して表示できる
 * 制御文字\E[n]を追加します。（nにはアイコン番号を指定）
 *
 * 【パラメータ】
 * DrawIconChain
 * 連続して表示するアイコンの数を指定します。
 *
 * 【使用例】
 * \D[5]
 * パラメータDrawIconChainが4のとき
 * アイコン番号5～8のアイコン4つが隙間なく連続して表示されます。
 *
 * \E[5]\E[6]\I[7]
 * アイコン番号5～7のアイコン3つが隙間なく連続して表示されます。
 * 末尾を\I[n]にしないと次の文字との隙間が無くなるので注意してください。
 *
 * 【利用規約】
 * このプラグインは、MITライセンスのもとで公開されています。
 * Copyright (c) 2017 BB ENTERTAINMENT
 * Released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 *
 * コンタクト：
 * BB ENTERTAINMENT Twitter: https://twitter.com/BB_ENTER/
 * BB ENTERTAINMENT BLOG   : http://bb-entertainment-blog.blogspot.jp/
 */

(function() {
    'use strict';
//-----------------------------------------------------------------------------
// プラグインパラメータ管理
var parameters = PluginManager.parameters('BB_IconChainTextEx');
var BBIC = Number(parameters['DrawIconChain']);

var _Window_Base_prototype_processEscapeCharacter = Window_Base.prototype.processEscapeCharacter;
Window_Base.prototype.processEscapeCharacter = function(code, textState) {
    _Window_Base_prototype_processEscapeCharacter.call(this, code, textState);
    switch (code) {
    case 'D':
        this.processDrawIconChain(this.obtainEscapeParam(textState), textState);
        break;
    case 'E':
        this.processDrawIconEach(this.obtainEscapeParam(textState), textState);
        break;
    }
};

Window_Base.prototype.processDrawIconChain = function(iconIndex, textState) {
    for(var i = 0; i < BBIC; i++){
        this.drawIcon(iconIndex + i, textState.x + 2, textState.y + 2);
        textState.x += Window_Base._iconWidth;
    }
    textState.x += 4;
};

Window_Base.prototype.processDrawIconEach = function(iconIndex, textState) {
    this.drawIcon(iconIndex, textState.x + 2, textState.y + 2);
    textState.x += Window_Base._iconWidth;
};

})();


code:
//=============================================================================
// rpg_managers.jsから抜き出し
//=============================================================================

/*:
 * @plugindesc 背景ぼかさないよ
 * @author ゆわか
 *
 * @help プラグインコマンドはありません。
 *
 * 戦闘背景を指定せずに戦闘をした時に戦闘背景として表示されたり
 * メニューを呼び出したときに表示されるマップ画像をぼかさないプラグインです。
 * [追記]戦闘時に背景のスナップを撮らないように追記
 *
 * 使用報告不要・クレジット不要・改変可・商用利用可
 * もし何か問題が起きても、当方は一切責任を負いません。ご了承ください。
 */

SceneManager.snapForBackground = function() {
    this._backgroundBitmap = this.snap();
	//this._backgroundBitmap.blur();
};

Spriteset_Battle.prototype.createLowerLayer = function() {
    Spriteset_Base.prototype.createLowerLayer.call(this);
    //this.createBackground();
    this.createBattleField();
    this.createBattleback();
    this.createEnemies();
    this.createActors();
};


code:
//=============================================================================
// BMSP.js (BMSPベースプラグイン)
//=============================================================================

/*:
 * @plugindesc BMSPベースプラグインです。
 * @author gentlawk
 * @website http://blueredzone.com
 * @url https://github.com/gentlawk/BMSP_MV
 * @license
 * Copyright(c) 2015 BlueRedZone, gentlawk
 * Released under the MIT license
 * https://github.com/gentlawk/BMSP_MV/blob/master/LICENSE
 *
 * @version 1.11
 *
 * @help
 * 使用方法:
 *   BMSPプラグインシリーズのベースとなるプラグインです。
 *
 * ●追加位置
 *   全てのBMSPプラグインシリーズより上に配置してください。
 */

function BMSP() {
    throw new Error('This is a static class');
}

/*
 * プラグインの導入チェック
 */
PluginManager._versions = {};

PluginManager.version = function (name) {
    if(!(name.toLowerCase() in this._versions)) return 0;
    return this._versions[name.toLowerCase()];
};

PluginManager.setVersion = function (name, version) {
    this._versions[name.toLowerCase()] = version;
};

BMSP.checkPluginName = function (name) {
    return PluginManager._scripts.indexOf(name) >= 0;
};

BMSP.checkPluginVersion = function (name, version) {
    var now = PluginManager.version(name);
    return now >= version;
};

BMSP.includedPlugin = function (name, version) {
    if (!this.checkPluginName(name)) return false;
    if (version === undefined) return true;
    return this.checkPluginVersion(name, version);
};

BMSP.requirePlugin = function (name, version) {
    if (!this.checkPluginName(name)) {
        throw new Error('no such plugin: ' + name);
    }
    if (version === undefined) return;
    if (!this.checkPluginVersion(name, version)){
        var now = PluginManager.version(name);
        throw new Error('need version ' + version + ' and over: ' + name + ' version ' + now);
    }
};

/*
 * プラグインバージョン
 */
PluginManager.setVersion('BMSP', 1.11);

/*
 * オブジェクトのユニークID管理
 */
BMSP.getUniqueId = function () {
    return new Date().getTime() + Math.floor(Math.random() * 1000);
};

BMSP.getObjectId = function (object) {
    if (!object){
        return 0;
    }
    if (!('_bmsp_object_id' in object)) {
        object._bmsp_object_id = BMSP.getUniqueId();
    }
    return object._bmsp_object_id;
};

/*
 * Ruby(他Perl等)ライクな剰余演算
 */
BMSP.rubyLikeMod = function (a, b) {
    return (a%b+b)%b;
};

/*
 * シャローコピー
 */
BMSP.shallowCopy = function (object) {
    if (object instanceof Array) {
        return [].concat(object);
    }
    var copy = {};
    for (var prop in object) {
        copy[prop] = object[prop];
    }
    return copy;
};


code:
//=============================================================================
// BMSP_MapFog.js (マップフォグ)
//=============================================================================

/*:
 * @plugindesc マップにフォグを表示します。
 * @author gentlawk
 * @website http://blueredzone.com
 * @url https://github.com/gentlawk/BMSP_MV
 * @license
 * Copyright(c) 2015 BlueRedZone, gentlawk
 * Released under the MIT license
 * https://github.com/gentlawk/BMSP_MV/blob/master/LICENSE
 *
 * @version 1.03
 *
 * @param Label
 * @desc マップフォグメモのラベルです。
 * @default フォグ
 *
 * @help
 * マップのメモ:
 *   <フォグ%n%:%name%, %sx%, %sy%, %opacity%, %z%, %blend%, %switchies%>  # マップにフォグを追加します。
 *     - %n% : フォグの番号です。1以上の整数を指定してください。
 *     - %name% : 使用するファイル名です。(初期値: '')
 *     - %sx% : X方向のスピードです。(初期値: 0)
 *     - %sy% : Y方向のスピードです。(初期値: 0)
 *     - %opacity% : 不透明度です。(初期値: 255)
 *     - %z% : Z座標です。0が遠景直上、1がピクチャ直下、2がピクチャ直上です。(初期値: 1)
 *     - %blend% : 合成方法です。0が通常、1が加算です。(初期値: 1)
 *     - %switchies% : 表示条件スイッチIDリストです。条件にしたいスイッチのIDを「:」区切りで指定します。(初期値: 指定無し※常に表示)
 *   ※メモのラベルはパラメータで変更可能です。
 *   ※フォグ番号はマップごとに1から順番に存在しなければなりません。
 *   ※%n%以外の各パラメータは省略可能です。省略した場合初期値が使用されます。
 *   　また、省略したパラメータ以降のパラメータも全て省略しなければなりません。
 *
 * プラグインコマンド:
 *   MapFog %n% name %value% # フォグ番号%n%に使用するファイルを%value%に変更します。
 *   MapFog %n% sx %value% # フォグ番号%n%のX方向速度を%value%に変更します。
 *   MapFog %n% sy %value% # フォグ番号%n%のY方向速度を%value%に変更します。
 *   MapFog %n% opacity %value% # フォグ番号%n%の不透明度を%value%に変更します。
 *   MapFog %n% blend %value% # フォグ番号%n%の合成方法を%value%に変更します。
 *   MapFog %n% visible %value% # フォグ番号%n%を%value%が1で表示、0で非表示にします。
 *
 * 使用方法:
 *   マップのメモにフォグ設定を記述すると、マップにフォグを表示できます。
 *   1つのマップに表示するフォグの数は任意ですが、フォグ番号は1から順番にふる必要があります。
 *   フォグの表示条件はマップ移動時のみ判定されます。
 *   同一マップ上でフォグの表示を切り替える場合はプラグインコマンドを使用して下さい。
 *   マップフォグ画像は以下のディレクトリに配置してください(fogsディレクトリは新規作成してください)。
 *   img/fogs
 *
 * ●使用例
 *   フォグを表示
 *     <フォグ1:fogfile>
 *
 *   フォグを2つ表示
 *     <フォグ1:fogfile1,1,0,255>
 *     <フォグ2:fogfile2,0,0,255,0,0>
 *
 *   スイッチ10がONの時フォグを表示
 *     <フォグ1:fogfile,0,0,255,1,1,10>
 *
 *   スイッチ10がONの時フォグ1を、スイッチ10と20がONの時フォグ2を表示
 *     <フォグ1:fogfile1,0,0,255,1,1,10>
 *     <フォグ2:fogfile2,0,0,255,1,1,10:20>
 */

(function() {

    /*
     * プラグインバージョン
     */
    PluginManager.setVersion('BMSP_MapFog', 1.03);

    /*
     * 必須プラグインチェック
     */
    var _Scene_Boot_start = Scene_Boot.prototype.start;
    Scene_Boot.prototype.start = function () {
        BMSP.requirePlugin('BMSP', 1.00);
        _Scene_Boot_start.call(this);
    };

    /*
     * プラグインコマンド
     */
    var _Game_Interpreter_pluginCommand =
            Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);
        if (command === 'MapFog') {
            $gameMap.setFogParameter(args[1], Number(args[0]), args[2]);
        }
    };

    /*
     * MapFog
     */
    BMSP.MapFog = function() {
        throw new Error('This is a static class');
    };

    var parameters = PluginManager.parameters('BMSP_MapFog');
    BMSP.MapFog._label  = parameters['Label'];

    BMSP.MapFog._cache_settings = {};

    BMSP.MapFog.getSettings = function(map) {
        var objectId = BMSP.getObjectId(map);
        if(objectId in this._cache_settings){
            return this._cache_settings[objectId];
        }
        var index = 1;
        var settings = {};
        while((this._label + index) in map.meta){
            settings[index] = map.meta[this._label + index].split(',');
            index++;
        }
        this._cache_settings[objectId] = settings;
        return settings;
    };

    BMSP.MapFog.getSprite = function(index) {
        if(!SceneManager._scene || SceneManager._scene.constructor !== Scene_Map) {
            return null;
        }
        var fogData = SceneManager._scene._spriteset._fogData;
        for(var i in fogData) {
            var data = fogData[i];
            if(data.index == index) return data.sprite;
        }
        return null;
    };

    /*
     * ImageManager
     */
    ImageManager.loadFog = function(filename, hue) {
        return this.loadBitmap('img/fogs/', filename, hue, true);
    };

    var _Game_Map_setup = Game_Map.prototype.setup;
    Game_Map.prototype.setup = function(mapId) {
        _Game_Map_setup.call(this, mapId);
        this.setupFogs();
    };

    Game_Map.prototype.setupFogs = function() {
        this._fogs = {};
        var settings = BMSP.MapFog.getSettings($dataMap);
        for(var index in settings) {
            var setting = settings[index];
            var cond = (setting[6] || '').split(':');
            var visible = true;
            if(cond[0] !== '') {
                visible = cond.every(function(id) {
                    return $gameSwitches.value(id);
                });
            }
            this._fogs[index] = {
                name:    setting[0] || '',
                sx:      Number(setting[1] || 0),
                sy:      Number(setting[2] || 0),
                opacity: Number(setting[3] || 255),
                z:       Number(setting[4] || 1),
                blend:   Number(setting[5] || 1),
                visible: visible,
                x:       0,
                y:       0,
            }
        }
    };

    Game_Map.prototype.fogs = function() {
        return this._fogs;
    }

    var _Game_Map_update = Game_Map.prototype.update;
    Game_Map.prototype.update = function(sceneActive) {
        _Game_Map_update.call(this, sceneActive);
        this.updateFogs();
    };

    Game_Map.prototype.updateFogs = function() {
        for(var index in this._fogs) {
            this._fogs[index].x += this._fogs[index].sx;
            this._fogs[index].y += this._fogs[index].sy;
        }
    };

    Game_Map.prototype.setFogParameter = function(name, index, value) {
        if(!(index in this._fogs)) return;
        if(value === undefined) return;
        var fog = this._fogs[index];
        switch(name) {
            case 'name':
                fog[name] = value;
                break;
            case 'sx':
            case 'sy':
            case 'opacity':
            case 'blend':
                fog[name] = Number(value);
                break;
            case 'visible':
                fog[name] = Boolean(Number(value));
                break;
        }
    };

    /*
     * Spriteset_Map
     */
    var _Spriteset_Map_initialize = Spriteset_Map.prototype.initialize;
    Spriteset_Map.prototype.initialize = function() {
        this._fogContainer = [];
        this._fogData = [];
        _Spriteset_Map_initialize.call(this);
    };

    var _Spriteset_Map_createParallax = Spriteset_Map.prototype.createParallax;
    Spriteset_Map.prototype.createParallax = function() {
        _Spriteset_Map_createParallax.call(this);
        this.createFogs(0);
    };

    var _Spriteset_Map_createPictures = Spriteset_Map.prototype.createPictures;
    Spriteset_Map.prototype.createPictures = function() {
        this.createFogs(1);
        _Spriteset_Map_createPictures.call(this);
        this.createFogs(2);
    };

    var _Spriteset_Map_update = Spriteset_Map.prototype.update;
    Spriteset_Map.prototype.update = function() {
        _Spriteset_Map_update.call(this);
        this.updateFogs();
    };

    Spriteset_Map.prototype.createFogs = function(z) {
        this._fogContainer[z] = new Sprite();
        var fogs = $gameMap.fogs();
        for(var index in fogs) {
            if(fogs[index].z !== z) continue;

            var fogSprite = new TilingSprite();
            fogSprite.move(0, 0, Graphics.width, Graphics.height);
            this._fogContainer[z].addChild(fogSprite);
            this._fogData.push({
                index: index,
                sprite: fogSprite,
                name: null,
            });
        }
        if(z === 2) {
            this.addChild(this._fogContainer[z]);
        } else {

            this._baseSprite.addChild(this._fogContainer[z]);
        }
    };

    Spriteset_Map.prototype.updateFogs = function() {
        var fogs = $gameMap.fogs();
        this._fogData.forEach(function(data) {
            var fog = fogs[data.index];
            var sprite = data.sprite;
            if(data.name !== fog.name) {
                data.name = fog.name;
                sprite.bitmap = ImageManager.loadFog(data.name);
            }
            if(sprite.bitmap) {
                sprite.origin.x = fog.x;
                sprite.origin.y = fog.y;
                sprite.opacity = fog.opacity;
                sprite.visible = fog.visible;
                sprite.blendMode = fog.blend;
            }
        }, this);
    };

})();


code:
//=============================================================================
// BalloonLoopWithoutSkip.js
// ----------------------------------------------------------------------------
// Copyright (c) 2018 Suzu
// This software is released under the MIT License.
// ----------------------------------------------------------------------------
// Version
// 1.0.0 2018/09/19 初版
//=============================================================================

/*:ja
 * @plugindesc 吹き出しをループ表示中スキップ無効プラグイン
 * @author すず
 *
 * @help
 *
 * tomoakyさんのプラグイン(TMBalloonLoop.js)がONの場合に
 * 桐原巳弥人(KIRIHARA Miyahito)さんのプラグイン(BalloonSkip.js)を無効にします。
 *
 * 使い方：
 *
 *    BalloonSkipを削除もしくはOFFにして本プラグインを追加します。
 *    このプラグインにはプラグインコマンドはありません。
 *
 *    以下、BalloonSkip.js引用です。
 *    " フキダシアイコンを表示している間、okキーあるいはctrlキーが押されたら
 *    （押されていたら）それを終了します。
 *    okキーが既に押しっぱなしだった場合は、フキダシアイコンが一瞬だけ見えます。"
 *
 * 利用規約：
 *    作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *    についても制限はありません。
 *
*/

(function(){
  'use strict';
  Sprite_Character.prototype.startBalloon = function(){
    if (!this._balloonSprite){
      var balloonLoop = (typeof this._character.balloonLoop == "function")
        ? this._character.balloonLoop() : false;
      this._balloonSprite = (!balloonLoop)
        ? new Sprite_BalloonEnableSkip() : new Sprite_Balloon();
    }
    this._balloonSprite.setup(this._character.balloonId());
    this.parent.addChild(this._balloonSprite);
  };

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

  Sprite_BalloonEnableSkip.prototype = Object.create(Sprite_Balloon.prototype);
  Sprite_BalloonEnableSkip.prototype.constructor = Sprite_BalloonEnableSkip;

  Sprite_BalloonEnableSkip.prototype.initialize = function(){
    Sprite_Balloon.prototype.initialize.call(this);
  }

  var _Sprite_Balloon_update = Sprite_Balloon.prototype.update;
  Sprite_BalloonEnableSkip.prototype.update = function(){
    if(Input.isTriggered("ok") || Input.isPressed("control")){
      this._duration = 0;
    }
    //if(Input.isPressed("ok")){
    //  this._duration -= 5;
    //}
    _Sprite_Balloon_update.apply(this);
  }
})();


code:
/*=============================================================================
 BalloonPosition.js
----------------------------------------------------------------------------
 (C)2021 Triacontane
 This software is released under the MIT License.
 http://opensource.org/licenses/mit-license.php
----------------------------------------------------------------------------
 Version
 1.0.1 2021/01/28 英語ヘルプを記述
 1.0.0 2021/01/27 初版
----------------------------------------------------------------------------
 [Blog]   : https://triacontane.blogspot.jp/
 [Twitter]: https://twitter.com/triacontane/
 [GitHub] : https://github.com/triacontane/
=============================================================================*/

/*:
 * @plugindesc BalloonPositionPlugin
 * @author triacontane
 *
 * @param BalloonXNoImage
 * @desc Uniformly adjusts the x of balloon for events where no image is specified.
 * @default 0
 * @type number
 * @min -2000
 * @max 2000
 *
 * @param BalloonYNoImage
 * @desc Uniformly adjusts the y of balloon for events where no image is specified.
 * @default 0
 * @min -2000
 * @max 2000
 *
 * @help BalloonPosition.js
 *
 * Adjusts the display coordinates of balloon
 * <BalloonX:5>
 * <BalloonY:-5>
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc フキダシ位置調整プラグイン
 * @author トリアコンタン
 *
 * @param BalloonXNoImage
 * @text 画像なしX座標
 * @desc 画像が指定されていないイベントのフキダシX座標を一律で調整します。
 * @default 0
 * @type number
 * @min -2000
 * @max 2000
 *
 * @param BalloonYNoImage
 * @text 画像なしY座標
 * @desc 画像が指定されていないイベントのフキダシY座標を一律で調整します。
 * @default 0
 * @min -2000
 * @max 2000
 *
 * @help BalloonPosition.js
 *
 * フキダシの表示座標を調整します。
 * イベントのメモ欄に以下の通り入力してください。
 * <BalloonX:5>  # フキダシのX座標を右に[5]ずらします。
 * <BalloonY:-5> # フキダシのY座標を上に[5]ずらします。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function() {
    'use strict';

    /**
     * Get database meta information.
     * @param object Database item
     * @param name Meta name
     * @returns {String} meta value
     */
    var getMetaValue = function(object, name) {
        return object.meta.hasOwnProperty(name) ? convertEscapeCharacters(object.meta[name]) : null;
    };

    /**
     * Convert escape characters.(require any window object)
     * @param text Target text
     * @returns {String} Converted text
     */
    var convertEscapeCharacters = function(text) {
        var windowLayer = SceneManager._scene._windowLayer;
        return windowLayer ? windowLayer.children[0].convertEscapeCharacters(text.toString()) : text;
    };

    /**
     * Create plugin parameter. param[paramName] ex. param.commandPrefix
     * @param pluginName plugin name(EncounterSwitchConditions)
     * @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('BalloonPosition');

    /**
     * Game_CharacterBase
     * フキダシの座標を取得可能にします。
     */
    Game_CharacterBase.prototype.isNoImage = function() {
        return !this._tileId && !this._characterName;
    };

    Game_CharacterBase.prototype.findBalloonX = function() {
        return 0;
    };

    Game_CharacterBase.prototype.findBalloonY = function() {
        return 0;
    };

    /**
     * Game_Event
     * フキダシの座標をメモ欄から取得します。
     */
    Game_Event.prototype.findBalloonX = function() {
        const x = parseInt(getMetaValue(this.event(),'BalloonX'));
        if (x) {
            return x;
        } else if (this.isNoImage()) {
            return param.BalloonXNoImage;
        } else {
            return 0;
        }
    };

    Game_Event.prototype.findBalloonY = function() {
        const y = parseInt(getMetaValue(this.event(),'BalloonY'));
        if (y) {
            return y;
        } else if (this.isNoImage()) {
            return param.BalloonYNoImage;
        } else {
            return 0;
        }
    };

    /**
     * Sprite_Character
     * フキダシの表示位置を調整します。
     */
    var _Sprite_Character_updateBalloon = Sprite_Character.prototype.updateBalloon;
    Sprite_Character.prototype.updateBalloon = function() {
        _Sprite_Character_updateBalloon.apply(this, arguments);
        if (this._character && this.isBalloonPlaying()) {
            this._balloonSprite.x += this._character.findBalloonX();
            this._balloonSprite.y += this._character.findBalloonY();
        }
    };
})();