code:
//==============================================================================
// PictureSpine.js ver.1.20a
//==============================================================================

/*:
 * @plugindesc Spineアニメーションプラグイン
 * @author 奏ねこま（おとぶきねこま）
 * @url http://makonet.sakura.ne.jp/rpg_tkool
 * @target MZ
 *
 * @param json file
 * @type string[]
 * @default []
 * @desc Spineファイル(*.json)
 *
 * @param disable auto loading
 * @type boolean
 * @default false
 * @desc Spineの自動読み込みを無効にする
 *
 * @help
 * 本プラグインの利用方法については下記マニュアルをご参照ください。
 * http://makonet.sakura.ne.jp/rpg_tkool/MVMZ/PictureSpine/document.html
 *
 * ------------------------------------------------------------------------------
 *   本プラグインの利用はRPGツクール/RPG Makerの正規ユーザーに限られます。
 *   商用、非商用、有償、無償、一般向け、成人向けを問わず利用可能です。
 *   ご利用の際に連絡や報告は必要ありません。また、製作者名の記載等も不要です。
 *   プラグインを導入した作品に同梱する形以外での再配布、転載はご遠慮ください。
 *   本プラグインにより生じたいかなる問題についても一切の責任を負いかねます。
 * ------------------------------------------------------------------------------
 *                                              Copylight (c) 2022 Nekoma Otobuki
 *                                         http://makonet.sakura.ne.jp/rpg_tkool/
 *                                                  https://twitter.com/koma_neko
 */

!(function () {
  "use strict";

  let $p = (function parse(param) {
    try {
      param = JSON.parse(param);
    } catch (e) {}
    if (Array.isArray(param)) {
      param = param.map((value) => parse(value));
    } else if (typeof param == "object") {
      for (let key in param) {
        param[key] = parse(param[key]);
      }
    }
    return param;
  })({
    ...PluginManager.parameters("PictureSpine"),
    "spine data": {},
  });

  function load() {
    let loader = new (PIXI.Loader || PIXI.loaders.Loader)();
    for (let file of $p["json file"]) {
      let name = String(file).replace(/\.json$/i, "");
      if (!$p["disable auto loading"]) {
        $p["spine data"][name] = null;
        loader.add(name, `img/spines/${name}.json`);
      } else {
        $p["spine data"][name] = {};
      }
    }
    loader.load((loader, resource) => {
      for (let name in $p["spine data"]) {
        if (resource[name]) {
          $p["spine data"][name] = resource[name].spineData;
        }
      }
    });
  }

  if (!PIXI.spine) {
    let js = null;
    for (let element of document.getElementsByTagName("script")) {
      if (element.src.match("pixi-spine.js")) {
        js = element;
      }
    }
    if (!js) {
      js = document.createElement("script");
      js.type = "text/javascript";
      js.src = "js/libs/pixi-spine.js";
      document.body.appendChild(js);
    }
    js.addEventListener("load", load);
  } else {
    load();
  }

  class MosaicFilter extends PIXI.Filter {
    constructor(size = 10) {
      let vertex =
        "attribute vec2 aVertexPosition;attribute vec2 aTextureCoord;uniform mat3 projectionMatrix;varying vec2 vTextureCoord;void main(void){gl_Position=vec4((projectionMatrix*vec3(aVertexPosition,1.0)).xy,0.0,1.0);vTextureCoord=aTextureCoord;}";
      let fragment =
        "precision mediump float;varying vec2 vTextureCoord;uniform vec2 size;uniform sampler2D uSampler;uniform vec4 filterArea;vec2 mapCoord(vec2 coord){coord*=filterArea.xy;coord+=filterArea.zw;return coord;}vec2 unmapCoord(vec2 coord){coord-=filterArea.zw;coord/=filterArea.xy;return coord;}vec2 pixelate(vec2 coord, vec2 size){return floor(coord / size) * size;}void main(void){vec2 coord=mapCoord(vTextureCoord);coord=pixelate(coord, size);coord=unmapCoord(coord);gl_FragColor=texture2D(uSampler, coord);}";
      super(vertex, fragment);
      this.uniforms.size = [size, size];
    }
  }

  function convars(obj) {
    if (typeof obj == "string") {
      let _obj = obj.replace(/\\v\[(\d+)\]/gi, (match, p1) => {
        return $gameVariables.value(Number(p1));
      });
      obj = _obj != obj ? convars(_obj) : _obj;
    } else if (obj instanceof Array) {
      obj = obj.map((value) => convars(value));
    } else if (typeof obj == "object") {
      obj = { ...obj };
      for (let key in obj) {
        obj[key] = convars(obj[key]);
      }
    }
    return obj;
  }

  //==============================================================================
  // JsonEx
  //==============================================================================

  ((___decode) => {
    JsonEx._decode = function (value, circular, registry) {
      let decode = ___decode.apply(this, arguments);
      if (decode instanceof Game_Spine) {
        if ("_visible" in decode == false) {
          decode._visible = true;
        }
        if ("_bone" in decode == false) {
          decode._bone = {};
        }
        if ("_callback" in decode == false) {
          decode._callback = {};
        }
        if (decode._skin instanceof Array == false) {
          decode._skin = [decode._skin];
        }
      }
      return decode;
    };
  })(JsonEx._decode);

  //==============================================================================
  // AudioManager
  //==============================================================================

  AudioManager._subFolder = "";

  ((__createBuffer) => {
    AudioManager.createBuffer = function (folder, name) {
      folder += this._subFolder.replace(/^\/?(?=.)/, "/");
      this._subFolder = "";
      return __createBuffer.call(this, folder, name);
    };
  })(AudioManager.createBuffer);

  //==============================================================================
  // Game_Screen
  //==============================================================================

  Game_Screen.prototype.spine = function (id) {
    let picture = this.picture(id);
    if (!picture._spine) {
      picture._spine = new Game_Spine();
    }
    return picture._spine;
  };

  //==============================================================================
  // Game_Picture
  //==============================================================================

  ((__initialize) => {
    Game_Picture.prototype.initialize = function () {
      __initialize.apply(this, arguments);
      this._spine = null;
    };
  })(Game_Picture.prototype.initialize);

  ((__erase) => {
    Game_Picture.prototype.erase = function () {
      __erase.apply(this, arguments);
      this._spine = null;
    };
  })(Game_Picture.prototype.erase);

  //==============================================================================
  // Sprite_Picture
  //==============================================================================

  ((__initialize) => {
    Sprite_Picture.prototype.initialize = function (pictureId) {
      __initialize.apply(this, arguments);
      this.addChild(new Sprite_Spine(pictureId));
    };
  })(Sprite_Picture.prototype.initialize);

  //==============================================================================
  // Game_Spine
  //==============================================================================

  class Game_Spine {
    constructor() {
      this.init();
    }

    static spineData() {
      return $p["spine data"];
    }

    static fullName(name = "") {
      for (let key in this.spineData()) {
        if (key.match(`(?:^|/)${name}$`)) {
          return key;
        }
      }
      return "";
    }

    static loadSkeleton(name) {
      let fullName = this.fullName(name);
      let data = $p["spine data"][fullName];
      if (!data || "animations" in data) return;
      $p["spine data"][fullName] = null;
      let loader = new (PIXI.Loader || PIXI.loaders.Loader)();
      loader.add(fullName, `img/spines/${fullName}.json`);
      loader.load((loader, resource) => {
        $p["spine data"][fullName] = resource[fullName].spineData;
      });
    }

    get skeleton() {
      return this._skeleton;
    }
    get skin() {
      return this._skin;
    }
    get track() {
      return this._track;
    }
    get timeScale() {
      return this._timeScale;
    }
    get alpha() {
      return this._alpha;
    }
    get mix() {
      return this._mix;
    }
    get color() {
      return this._color;
    }
    get mosaic() {
      return this._mosaic;
    }
    get offset() {
      return this._offset;
    }
    get scale() {
      return this._scale;
    }
    get visible() {
      return this._visible;
    }
    get bone() {
      return this._bone;
    }
    get callback() {
      return this._callback;
    }
    get playData() {
      return this._playData;
    }

    init() {
      this._skeleton = "";
      this._skin = [];
      this._track = {};
      this._timeScale = 1.0;
      this._alpha = {};
      this._mix = {};
      this._color = {};
      this._mosaic = {};
      this._offset = { x: 0, y: 0 };
      this._scale = { x: 1.0, y: 1.0 };
      this._visible = true;
      this._bone = {};
      this._callback = {};
      this._playData = [];
    }

    setSkeleton(name = "") {
      name = convars(name);
      this.init();
      this._skeleton = name + `_${Date.now()}`;
      return this;
    }

    setSkin(...args) {
      args = convars(args);
      this._skin = args;
      return this;
    }

    setAnimation(id, animations, ...args) {
      [id, animations, args] = convars([id, animations, args]);
      this._track = { ...this._track };
      let list, order, continuance, interrupt;
      if (typeof animations == "string") {
        list = [animations];
        order = "sequential";
        continuance = args[0] || "continue";
        interrupt = typeof args[1] == "boolean" ? args[1] : args[1] == "true";
      } else {
        list = animations;
        order = args[0] || "sequential";
        continuance = args[1] || "continue";
        interrupt = typeof args[2] == "boolean" ? args[2] : args[2] == "true";
      }
      this._track[id] = {
        list: [],
        order: order,
        continuance: continuance,
        interrupt: interrupt,
      };
      list.forEach((animation) => {
        let [name, options] = `${animation}/`.split(
          / *\/ *(?=(?:times|timeScale|alpha|$))/i
        );
        let times = 1;
        let timeScale = 1.0;
        let alpha = 1.0;
        for (let option of options.replace(/ +/, "").split(/,/)) {
          if (option.match(/^times=(\d+)$/i)) {
            times = Number(RegExp.$1);
          }
          if (option.match(/^timeScale=(\d+\.?\d*)$/i)) {
            timeScale = Number(RegExp.$1);
          }
          if (option.match(/^alpha=(\d+\.?\d*)$/i)) {
            alpha = Number(RegExp.$1);
          }
        }
        this._track[id].list.push({
          name: name,
          times: times,
          timeScale: timeScale,
          alpha: alpha,
        });
      });
      return this;
    }

    setTimeScale(value) {
      value = convars(value);
      this._timeScale = Number(value);
      return this;
    }

    setAlpha(id, value, overwrite = false) {
      [id, value, overwrite] = convars([id, value, overwrite]);
      this._alpha = { ...this._alpha };
      this._alpha[id] = {
        value: Number(value),
        overwrite:
          typeof overwrite == "boolean" ? overwrite : overwrite == "true",
      };
      return this;
    }

    setMix(...args) {
      args = convars(args);
      this._mix = { ...this._mix };
      let from, to, duration;
      if (args.length == 1) {
        from = "/default";
        to = "";
        duration = Number(args[0]);
      } else {
        from = args[0];
        to = args[1];
        duration = args.length > 2 ? Number(args[2]) : null;
      }
      if (duration !== null) {
        this._mix[`${from}/${to}`] = duration;
      } else {
        delete this._mix[`${from}/${to}`];
      }
      return this;
    }

    setColor(...args) {
      args = convars(args);
      this._color = { ...this._color };
      let image, r, g, b, a;
      if (args.length == 4) {
        image = "/default/";
        r = Number(args[0]);
        g = Number(args[1]);
        b = Number(args[2]);
        a = Number(args[3]);
      } else {
        image = args[0];
        r = Number(args[1]);
        g = Number(args[2]);
        b = Number(args[3]);
        a = Number(args[4]);
      }
      if (r != 1 || g != 1 || b != 1 || a != 1) {
        this._color[image] = [r, g, b, a];
      } else {
        delete this._color[image];
      }
      return this;
    }

    setMosaic(...args) {
      args = convars(args);
      this._mosaic = { ...this._mosaic };
      let image, size;
      if (args.length == 1) {
        image = "/default/";
        size = Number(args[0]);
      } else {
        image = args[0];
        size = Number(args[1]);
      }
      if (size > 1) {
        this._mosaic[image] = size;
      } else {
        delete this._mosaic[image];
      }
      return this;
    }

    setOffset(x, y) {
      [x, y] = convars([x, y]);
      this._offset = { x: Number(x), y: Number(y) };
      return this;
    }

    setScale(x, y) {
      [x, y] = convars([x, y]);
      this._scale = { x: Number(x), y: Number(y) };
      return this;
    }

    setVisible(visible) {
      this._visible = !!convars(visible);
      return this;
    }

    setBone(boneName, x, y, rotation, duration = 1, screen = true) {
      [boneName, x, y, rotation, duration, screen] = convars([
        boneName,
        x,
        y,
        rotation,
        duration,
        screen,
      ]);
      this._bone = { ...this._bone };
      this._bone[boneName] = {
        x: Number(x),
        y: Number(y),
        rotation: Number(rotation),
        duration: Number(duration) || 1,
        screen: typeof screen == "boolean" ? screen : screen == "true",
      };
      return this;
    }

    getBoneData(boneName, screen = true) {
      [boneName, screen] = convars([boneName, screen]);
      if (typeof screen == "string") {
        screen = screen == "true";
      }
      return this.executeCallback("getBoneData", boneName, screen);
    }

    getAttachmentData(slotName, screen = true) {
      [slotName, screen] = convars([slotName, screen]);
      if (typeof screen == "string") {
        screen = screen == "true";
      }
      return this.executeCallback("getAttachmentData", slotName, screen);
    }

    hitTest(x, y, screen = true) {
      [x, y, screen] = convars([x, y, screen]);
      if (typeof screen == "string") {
        screen = screen == "true";
      }
      return this.executeCallback("hitTest", Number(x), Number(y), screen);
    }

    executeCallback(symbol, ...args) {
      return ((callback) => {
        return callback(...args);
      })(this._callback[symbol] || new Function());
    }

    setPlayData(entry) {
      let id = entry.trackIndex;
      if (!this._playData[id]) {
        this._playData[id] = [];
      }
      this._playData[id].push({
        name: entry.animation.name,
        loop: entry.loop,
        mixDuration: entry.mixDuration,
        timeScale: entry.timeScale,
        alpha: entry.alpha,
        trackTime: 0,
        state: "ready",
      });
      for (let i = 0; i < this._playData[id].length - 1; i++) {
        this._playData[id][i].loop = false;
      }
    }

    updatePlayData(entry, reason) {
      let playData = this._playData[entry.trackIndex];
      if (!playData) return;
      let trackTime = entry.trackTime;
      let index = -1;
      let state;
      switch (reason) {
        case "start":
          index = playData.findIndex((data) => data.state == "ready");
          trackTime = 0;
          state = "play";
          break;
        case "interrupt":
          index = playData.findIndex((data) =>
            ["play", "repeat"].includes(data.state)
          );
          state = "suspend";
          break;
        case "complete":
          index = playData.findIndex((data) =>
            ["play", "suspend"].includes(data.state)
          );
          if (index >= 0) {
            if (playData[index].state == "play") {
              if (index == playData.length - 1) {
                state = entry.loop ? "repeat" : "done";
              } else {
                index = -1;
              }
            } else {
              state = "done";
            }
          }
          break;
        case "update":
          index = playData.findIndex((data) =>
            ["play", "repeat"].includes(data.state)
          );
          if (index >= 0) {
            state = playData[index].state;
          }
          break;
      }
      if (index >= 0) {
        playData[index].mixDuration = entry.mixDuration;
        playData[index].trackTime = trackTime;
        playData[index].state = state;
        if (index > 0 && ["suspend", "done", "repeat"].includes(state)) {
          playData.splice(0, index);
        }
      }
    }
  }

  window.Game_Spine = Game_Spine;

  //==============================================================================
  // Sprite_Spine
  //==============================================================================

  class Sprite_Spine extends Sprite {
    constructor(...args) {
      super();
      this._pictureId = typeof args[0] == "number" ? args[0] : 0;
      this._spine = args[0] instanceof Game_Spine ? args[0] : null;
      this._isRestore = false;
      this._isPostCall = false;
      this.init();
    }

    init() {
      this.removeChild(this._data);
      this._data = null;
      this._skeleton = "";
      this._skin = [];
      this._track = {};
      this._timeScale = 1.0;
      this._alpha = {};
      this._mix = {};
      this._color = {};
      this._mosaic = {};
      this._offset = null;
      this._scale = null;
      this._bone = null;
      this._postCall = [];
    }

    spine() {
      if (this._spine) {
        return this._spine;
      }
      let picture = $gameScreen.picture(this._pictureId);
      return picture ? picture._spine : null;
    }

    update() {
      let spine = this.spine();
      this.updateSkeleton(spine);
      if (this._data) {
        this.updateSkin(spine);
        this.updateTimeScale(spine);
        this.updateMix(spine);
        this.updateColor(spine);
        this.updateMosaic(spine);
        this.updateOffset(spine);
        this.updateScale(spine);
        this.updateVisible(spine);
        if (this._isRestore) {
          this.restoreAnimation(spine);
        } else {
          this.updateAnimation(spine);
        }
        this.updateAlpha(spine);
        this.updateBone(spine);
        this.executePostCall();
        for (let entry of this._data.state.tracks) {
          this.updatePlayData(entry, "update");
        }
      }
    }

    updateSkeleton(spine) {
      if (spine) {
        if (spine.skeleton != this._skeleton) {
          this.init();
          let skeleton = spine.skeleton.replace(/_\d+$/, "");
          if (skeleton) {
            let fullName = Game_Spine.fullName(skeleton);
            let data = Game_Spine.spineData()[fullName];
            if (data) {
              if ("animations" in data) {
                this._data = new PIXI.spine.Spine(data);
                this._data.destroy = function () {};
                this._data.state.addListener({
                  start: this.onStart.bind(this),
                  interrupt: this.onInterrupt.bind(this),
                  // end:       this.onEnd.bind(this),
                  // dispose:   this.onDispose.bind(this),
                  complete: this.onComplete.bind(this),
                  event: this.onEvent.bind(this),
                });
                this.addChild(this._data);
                if (spine.playData.length > 0) {
                  this._isRestore = true;
                }
                this.registerCallback(spine);
              } else {
                Game_Spine.loadSkeleton(skeleton);
              }
            } else if (fullName in Game_Spine.spineData() == false) {
              throw Error(`'${skeleton}' is unknown model.`);
            }
          }
          if (!skeleton || this._data) {
            this._skeleton = spine.skeleton;
          }
        }
      } else if (this._skeleton) {
        this.init();
      }
    }

    updateSkin(spine) {
      if (spine.skin == this._skin) return;
      this._skin = spine.skin;
      let Skin =
        (PIXI.spine.core || PIXI.spine).Skin ||
        this._data.spineData.skins[0].constructor;
      let skin = new Skin(" ");
      for (let name of this._skin) {
        if (name) {
          skin.addSkin(this._data.skeleton.data.findSkin(name));
        }
      }
      this._data.skeleton.setSkin(skin);
      this._data.skeleton.setSlotsToSetupPose();
    }

    updateTimeScale(spine) {
      if (spine.timeScale == this._timeScale) return;
      this._timeScale = spine.timeScale;
      this._data.state.timeScale = this._timeScale;
    }

    updateAlpha(spine) {
      this._alpha = spine.alpha;
      this._data.state.tracks.forEach((entry, id) => {
        let alpha = this._alpha[id];
        if (alpha && entry) {
          let value = alpha.value;
          let overwrite = alpha.overwrite;
          entry.alpha = overwrite ? value : entry.plainAlpha * value;
        }
      });
    }

    updateMix(spine) {
      if (spine.mix == this._mix) return;
      for (let key in spine.mix) {
        if (spine.mix[key] != this._mix[key]) {
          let duration = spine.mix[key];
          if (key == "/default/") {
            this._data.stateData.defaultMix = duration;
          } else {
            let [from, to] = key.split("/");
            this._data.stateData.setMix(from, to, duration);
          }
        }
      }
      for (let key in this._mix) {
        if (key in spine.mix == false) {
          let [from, to] = key.split("/");
          delete this._data.stateData.animationToMixTime[`${from}.${to}`];
        }
      }
      this._mix = spine.mix;
    }

    updateColor(spine) {
      if (spine.color == this._color) return;
      let retry = false;
      for (let image in spine.color) {
        if (spine.color[image] != this._color[image]) {
          let color = spine.color[image];
          let filter = new PIXI.filters.ColorMatrixFilter();
          filter.matrix = [
            color[0],
            0,
            0,
            0,
            0,
            0,
            color[1],
            0,
            0,
            0,
            0,
            0,
            color[2],
            0,
            0,
            0,
            0,
            0,
            color[3],
            0,
          ];
          let sprites =
            image == "/default/" ? [this._data] : this.getSpineSprites(image);
          for (let sprite of sprites) {
            let filters = (sprite.filters || []).filter((filter) => {
              return filter instanceof PIXI.filters.ColorMatrixFilter == false;
            });
            filters.push(filter);
            sprite.filters = filters;
          }
          if (image != "/default/") {
            let count =
              this.getAttachments(image, "MeshAttachment").length +
              this.getAttachments(image, "RegionAttachment").length;
            if (sprites.length < count) {
              retry = true;
            }
          }
        }
      }
      for (let image in this._color) {
        if (image in spine.color == false) {
          let sprites =
            image == "/default/" ? [this._data] : this.getSpineSprites(image);
          for (let sprite of sprites) {
            let filters = (sprite.filters || []).filter((filter) => {
              return filter instanceof PIXI.filters.ColorMatrixFilter == false;
            });
            sprite.filters = filters.length > 0 ? filters : null;
          }
        }
      }
      if (!retry) {
        this._color = spine.color;
      } else {
        setTimeout(this.updateColor.bind(this, spine));
      }
    }

    updateMosaic(spine) {
      if (spine.mosaic == this._mosaic) return;
      let retry = false;
      for (let image in spine.mosaic) {
        if (spine.mosaic[image] != this._mosaic[image]) {
          let size = spine.mosaic[image];
          let filter = new MosaicFilter(size);
          let sprites =
            image == "/default/" ? [this._data] : this.getSpineSprites(image);
          for (let sprite of sprites) {
            let filters = (sprite.filters || []).filter((filter) => {
              return filter instanceof MosaicFilter == false;
            });
            filters.push(filter);
            sprite.filters = filters;
          }
          if (image != "/default/") {
            let count =
              this.getAttachments(image, "MeshAttachment").length +
              this.getAttachments(image, "RegionAttachment").length;
            if (sprites.length < count) {
              retry = true;
            }
          }
        }
      }
      for (let image in this._mosaic) {
        if (image in spine.mosaic == false) {
          let sprites =
            image == "/default/" ? [this._data] : this.getSpineSprites(image);
          for (let sprite of sprites) {
            let filters = (sprite.filters || []).filter((filter) => {
              return filter instanceof MosaicFilter == false;
            });
            sprite.filters = filters.length > 0 ? filters : null;
          }
        }
      }
      if (!retry) {
        this._mosaic = spine.mosaic;
      } else {
        setTimeout(this.updateMosaic.bind(this, spine));
      }
    }

    updateOffset(spine) {
      if (spine.offset == this._offset) return;
      this._offset = spine.offset;
      this.x = this._offset.x;
      this.y = this._offset.y;
    }

    updateScale(spine) {
      if (spine.scale == this._scale) return;
      this._scale = spine.scale;
      this.scale.x = this._scale.x;
      this.scale.y = this._scale.y;
    }

    updateVisible(spine) {
      this.visible = spine.visible;
    }

    updateBone(spine) {
      if (spine.bone != this._bone) {
        this._bone = spine.bone;
      }
      for (let name in this._bone) {
        let bone = this._data.skeleton.findBone(name);
        if (!bone) continue;
        let _bone = { x: bone.worldX, y: bone.worldY, rotation: bone.rotation };
        let bone_p = this._bone[name];
        if ("x" in bone_p == false) {
          bone_p.x = _bone.x;
        }
        if ("y" in bone_p == false) {
          bone_p.y = _bone.y;
        }
        if ("rotation" in bone_p == false) {
          bone_p.rotation = _bone.rotation;
        }
        if (bone_p.screen) {
          [bone_p.x, bone_p.y] = this.computeLocalVertices([
            bone_p.x,
            bone_p.y,
          ]);
        }
        let duration = bone_p.duration || 1;
        let dx = (bone_p.x - _bone.x) / duration;
        let dy = (bone_p.y - _bone.y) / duration;
        let dr = (bone_p.rotation - _bone.rotation) / duration;
        let local = bone.worldToLocal({
          x: bone.worldX + dx,
          y: bone.worldY + dy,
        });
        bone.x += local.x;
        bone.y += local.y;
        bone.rotation += dr;
        bone_p.duration--;
        if (bone_p.duration <= 0) {
          delete this._bone[name];
        }
      }
    }

    updateAnimation(spine) {
      if (spine.track == this._track) return;
      for (let id in spine.track) {
        if (spine.track[id] != this._track[id]) {
          let track = spine.track[id];
          let list = [];
          let loop = track.continuance != "none";
          let state = this._data.state;
          for (let animation of track.list) {
            for (let j = 0; j < animation.times; j++) {
              list.push(animation);
            }
          }
          if (track.order == "shuffle") {
            let _list = [...list];
            list = [];
            while (_list.length > 0) {
              let index = Math.floor(Math.random() * _list.length);
              list.push(_list.splice(index, 1)[0]);
            }
          } else if (track.order == "random") {
            let index = Math.floor(Math.random() * list.length);
            list = [list[index]];
          }
          let entry = this._data.state.getCurrent(id);
          list.forEach((animation, index) => {
            let _loop = index < list.length - 1 ? false : loop;
            if (index == 0 && track.interrupt) {
              entry = state.setAnimation(id, animation.name, _loop);
            } else {
              entry = state.addAnimation(id, animation.name, _loop, 0);
            }
            entry.timeScale = animation.timeScale;
            entry.alpha = animation.alpha;
            entry.plainAlpha = animation.alpha;
            spine.setPlayData(entry);
          });
        }
      }
      this._track = spine.track;
    }

    restoreAnimation(spine) {
      let timeScale = this._data.state.timeScale;
      let animationToMixTime = this._data.stateData.animationToMixTime;
      let defaultMix = this._data.stateData.defaultMix;
      this._data.state.timeScale = 0;
      this._data.stateData.animationToMixTime = {};
      this._data.stateData.defaultMix = 0;
      let lastTimeScale = {};
      for (let playData of spine.playData.filter(Boolean)) {
        let id = spine.playData.indexOf(playData);
        for (let data of playData) {
          let entry;
          switch (data.state) {
            case "suspend":
            case "done":
              entry = this._data.state.setAnimation(id, data.name, false);
              entry.alpha = data.alpha;
              entry.plainAlpha = data.alpha;
              while (entry.trackTime < data.trackTime) {
                this._data.state.timeScale = Math.min(
                  data.trackTime - entry.trackTime,
                  0.01
                );
                this._data.update(1);
              }
              break;
            case "play":
            case "repeat":
              data.trackTime %= this._data.spineData.animations.find(
                (animation) => animation.name == data.name
              ).duration;
              this._data.stateData.defaultMix = data.mixDuration;
              entry = this._data.state.setAnimation(id, data.name, data.loop);
              entry.alpha = data.alpha;
              entry.plainAlpha = data.alpha;
              while (entry.trackTime < data.trackTime) {
                this._data.state.timeScale = Math.min(
                  data.trackTime - entry.trackTime,
                  0.01
                );
                this._data.update(1);
              }
              entry.timeScale = 0;
              lastTimeScale[id] = data.timeScale;
              break;
            default:
              this._data.stateData.defaultMix = data.mixDuration;
              entry = this._data.state.addAnimation(
                id,
                data.name,
                data.loop,
                0
              );
              entry.timeScale = data.timeScale;
              entry.alpha = data.alpha;
              entry.plainAlpha = data.alpha;
              break;
          }
        }
      }
      for (let id in lastTimeScale) {
        this._data.state.tracks[Number(id)].timeScale = lastTimeScale[id];
      }
      this._data.state.timeScale = timeScale;
      this._data.stateData.animationToMixTime = animationToMixTime;
      this._data.stateData.defaultMix = defaultMix;
      this._track = spine.track;
      this._isRestore = false;
    }

    updatePlayData(entry, reason) {
      let spine = this.spine();
      if (!entry || !spine) return;
      spine.updatePlayData(entry, reason);
    }

    registerCallback(spine) {
      spine.callback["getBoneData"] = this.getBoneData.bind(this);
      spine.callback["getAttachmentData"] = this.getAttachmentData.bind(this);
      spine.callback["hitTest"] = this.hitTest.bind(this);
    }

    getAttachments(name, type) {
      let attachments = [];
      if (this._data) {
        for (let slot of this._data.skeleton.slots) {
          let attachment = slot.attachment;
          if (attachment && (!type || attachment.constructor.name == type)) {
            if (attachment.name == name) {
              attachments.push(attachment);
            }
          }
        }
      }
      return attachments;
    }

    getSpineSprites(name) {
      let sprites = [];
      if (this._data) {
        for (let child1 of this._data.children) {
          for (let child2 of child1.children) {
            if (child2.region && child2.region.name == name) {
              sprites.push(child2);
            }
          }
        }
      }
      return sprites;
    }

    getBoneData(boneName, screen = true) {
      let bone = this._data.skeleton.findBone(boneName);
      if (!bone) return null;
      let data = {
        x: bone.worldX,
        y: bone.worldY,
        rotation: bone.rotation,
      };
      if (screen) {
        [data.x, data.y] = this.computeScreenVertices([data.x, data.y]);
      }
      return data;
    }

    getAttachmentData(slotName, screen = true) {
      let slot = this._data.skeleton.findSlot(slotName);
      if (!slot) return null;
      let attachment = slot.getAttachment();
      if (!attachment) return null;
      let attachmentType = attachment.constructor.name;
      let data = {};
      if (attachmentType.match(/^VertexAttachment/)) {
        if (attachment.vertices) {
          let vertices = [];
          attachment.computeWorldVertices(
            slot,
            0,
            attachment.worldVerticesLength,
            vertices,
            0,
            2
          );
          if (screen) {
            this.computeScreenVertices(vertices);
          }
          data.vertices = vertices;
        }
      }
      if (attachmentType.match(/^ClippingAttachment/)) {
        data.endSlotName = attachment.endSlot.name;
      }
      if (attachmentType.match(/^PathAttachment/)) {
        data.lengths = attachment.lengths;
        data.closed = attachment.closed;
        data.constantSpeed = attachment.constantSpeed;
      }
      if (attachmentType.match(/^PointAttachment/)) {
        let position = attachment.computeWorldPosition(slot.bone, {});
        let rotation = attachment.computeWorldRotation(slot.bone);
        if (screen) {
          [position.x, position.y] = this.computeScreenVertices([
            position.x,
            position.y,
          ]);
        }
        data.x = position.x;
        data.y = position.y;
        data.rotation = rotation;
      }
      return {
        slotName: slotName,
        attachmentName: attachment.name,
        data: data,
      };
    }

    hitTest(x, y, screen = true) {
      let SkeletonBounds = (PIXI.spine.core || PIXI.spine).SkeletonBounds;
      let hits = [];
      let bounds = new SkeletonBounds();
      bounds.update(this._data.skeleton, true);
      let polygons = bounds.polygons;
      for (let i = 0; i < polygons.length; i++) {
        let polygon = polygons[i];
        if (screen) {
          this.computeScreenVertices(polygon);
        }
        if (bounds.containsPointPolygon(polygon, x, y)) {
          let attachment = bounds.boundingBoxes[i];
          let slot = this._data.skeleton.slots.find(
            (slot) => slot.attachment == attachment
          );
          hits.push({
            slotName: slot.data.name,
            attachmentName: attachment.name,
            data: {
              vertices: polygon,
            },
          });
        }
      }
      return hits;
    }

    computeScreenVertices(vertices) {
      let parent = this;
      while (parent) {
        for (let i = 0; i < vertices.length; i += 2) {
          let [x, y] = [vertices[i], vertices[i + 1]];
          x *= parent.scale.x;
          y *= parent.scale.y;
          [x, y] = [
            Math.cos(parent.rotation) * x - Math.sin(parent.rotation) * y,
            Math.sin(parent.rotation) * x + Math.cos(parent.rotation) * y,
          ];
          x += parent.x;
          y += parent.y;
          [vertices[i], vertices[i + 1]] = [x, y];
        }
        parent = parent.parent;
      }
      return vertices;
    }

    computeLocalVertices(vertices) {
      !(function calc(parent) {
        if (parent.parent) {
          calc(parent.parent);
        }
        for (let i = 0; i < vertices.length; i += 2) {
          let [x, y] = [vertices[i], vertices[i + 1]];
          x -= parent.x;
          y -= parent.y;
          [x, y] = [
            Math.cos(-parent.rotation) * x - Math.sin(-parent.rotation) * y,
            Math.sin(-parent.rotation) * x + Math.cos(-parent.rotation) * y,
          ];
          x /= parent.scale.x;
          y /= parent.scale.y;
          [vertices[i], vertices[i + 1]] = [x, y];
        }
      })(this);
      return vertices;
    }

    reservePostCall(callback) {
      this._postCall.push(callback);
    }

    executePostCall() {
      this._isPostCall = true;
      while (this._postCall[0]) {
        let callback = this._postCall.shift();
        callback();
      }
      this._isPostCall = false;
    }

    onStart(entry) {
      if (this._isRestore) return;
      if (entry.trackTime == 0 && !this._isPostCall) {
        this.reservePostCall(this.onStart.bind(this, entry));
        return;
      }
      this.updatePlayData(entry, "start");
      if (!entry.next) {
        let spine = this.spine();
        let index = entry.trackIndex;
        if (spine && spine.track[index]) {
          if (spine.track[index] == this._track[index]) {
            if (this._track[index].continuance == "reset") {
              spine.track[index].interrupt = false;
              this._track = { ...this._track };
              this._track[index] = null;
            }
          }
        }
      }
    }

    onInterrupt(entry) {
      if (this._isRestore) return;
      if (entry.trackTime == 0 && !this._isPostCall) {
        this.reservePostCall(this.onInterrupt.bind(this, entry));
        return;
      }
      this.updatePlayData(entry, "interrupt");
    }

    onEnd(entry) {}

    onDispose(entry) {}

    onComplete(entry) {
      if (this._isRestore) return;
      if (entry.trackTime == 0 && !this._isPostCall) {
        this.reservePostCall(this.onComplete.bind(this, entry));
        return;
      }
      this.updatePlayData(entry, "complete");
    }

    onEvent(entry, event) {
      if (this._isRestore) return;
      let audioPath = event.data.audioPath;
      let audioData = event.data.audioData;
      if (audioPath) {
        if (!audioData) {
          let values = audioPath.replace(/\.[^.]+$/, "").split(/\/(?=[^/]+$)/);
          let [folder, file] =
            values.length > 1 ? [...values] : ["", ...values];
          let stringValue = event.data.stringValue;
          let volume = event.data.volume * 100;
          let balance = event.data.balance * 100;
          let volumeId, balanceId;
          for (let value of stringValue.replace(/ +/, "").split(/,/)) {
            if (value.match(/^volume:(\d+)$/i)) {
              volumeId = Number(RegExp.$1);
            }
            if (value.match(/^balance:(\d+)$/i)) {
              balanceId = Number(RegExp.$1);
            }
          }
          audioData = event.data.audioData = {
            folder: folder,
            file: file,
            volume: volume,
            volumeId: volumeId,
            balance: balance,
            balanceId: balanceId,
          };
        }
        let folder = audioData.folder;
        let file = audioData.file;
        let volumeId = audioData.volumeId;
        let balanceId = audioData.balanceId;
        let volume = volumeId
          ? $gameVariables.value(volumeId)
          : audioData.volume;
        let balance = balanceId
          ? $gameVariables.value(balanceId)
          : audioData.balance;
        AudioManager._subFolder = folder;
        AudioManager.playSe({
          name: file,
          volume: volume,
          pitch: 100,
          pan: balance,
        });
      }
      let switches = event.switches;
      if (switches == null) {
        switches = {};
        let stringValue = event.stringValue;
        for (let value of stringValue.replace(/ +/, "").split(/,/)) {
          if (value.match(/^([!~]?)switch:(\d+)$/i)) {
            let type =
              RegExp.$1.replace("!", "off").replace("~", "reverse") || "on";
            switches[RegExp.$2] = type;
          }
        }
        event.switches = switches;
      }
      for (let id in switches) {
        let type = switches[id];
        let value =
          type == "on"
            ? true
            : type == "off"
            ? false
            : !$gameSwitches.value(id);
        $gameSwitches.setValue(id, value);
      }
    }
  }

  window.Sprite_Spine = Sprite_Spine;
})();


code:
/*---------------------------------------------------------------------------*
 * 2018/06/19 kido
 * https://kido0617.github.io/
 * Ver.1.0
 *---------------------------------------------------------------------------*/

/*:
 * @plugindesc BGMの保存・再開と同様に、BGSを保存・再開するプラグイン
 * @author kido
 * @help
 * プラグインコマンド
 *  ・BGSの保存
 *     SaveBGS
 *  ・BGSの再開
 *     ReplayBGS
 *
 */

(function () {
  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.call(this, command, args);
    if (command === "SaveBGS") {
      $gameSystem.saveBgs();
    } else if (command === "ReplayBGS") {
      $gameSystem.replayBgs();
    }
  };

  Game_System.prototype.saveBgs = function () {
    this._savedBgs = AudioManager.saveBgs();
  };

  Game_System.prototype.replayBgs = function () {
    if (this._savedBgs) {
      AudioManager.replayBgs(this._savedBgs);
    }
  };
})();

repo_name: dazed/translations

license: unknown


code:
//=============================================================================
// SideEffectSkill.js
// ----------------------------------------------------------------------------
// (C) 2016 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.4.2 2020/05/22 反撃された場合などスキルを使用しなかったケースで「弱点時のみ」などの判定が無条件で有効になってしまう問題を修正
// 1.4.1 2019/07/15 BattleEffectPopup.jsと併用したとき、フロントビューだと戦闘開始時などにInvalidポップが余分に表示される競合を解消
// 1.4.0 2019/02/16 行動が無効(ダメージ0)だった場合のみ副作用を適用できる機能を追加
//                  行動が反射された場合のみ副作用を適用できる機能を追加
// 1.3.0 2018/11/29 行動が会心だった場合のみ副作用を適用できる機能を追加
// 1.2.3 2017/10/10 0ターン目に戦闘行動の強制を実行するとエラーになる問題の修正
// 1.2.2 2017/10/07 ターン終了時の副作用を持つスキルでトドメをさした場合、次の戦闘のターン終了時に副作用が発生する問題を修正
// 1.2.1 2017/06/10 自動戦闘が有効なアクターがいる場合に一部機能が正常に動作しない問題を修正
// 1.2.0 2017/06/01 弱点時のみ副作用が適用できる機能を追加
// 1.1.1 2017/01/24 副作用設定時にターン終了時にダメージのポップアップ等が出なくなる問題を修正
// 1.1.0 2016/12/13 フロントビュー時にエフェクト効果のメッセージが重複して表示される問題を修正
// 1.0.2 2016/10/10 行動パターンが何も設定されていない敵キャラが行動しようとするとエラーになる問題を修正
// 1.0.1 2016/10/10 タイミングが「スキル使用時」「ターン開始時」以外のものについて、対象者にも効果が適用されていた問題を修正
// 1.0.0 2016/09/25 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc SideEffectSkillPlugin
 * @author triacontane
 *
 * @help スキル使用時に、使用者に対する副作用を設定できます。
 * 副作用が適用されるタイミングは以下の中から選択できます。
 *
 * ・スキル入力時(敵キャラ専用)
 * 味方の行動入力前に副作用が適用されます。敵キャラ専用です。
 *
 * ・スキル使用前
 * スキルを使用する直前に副作用が適用されます。スキルを使用する時点では
 * すでに適用済みの状態になっています。
 *
 * ・スキル使用時
 * スキルを使用して、相手に効果が適用されるのと同じタイミングで
 * 副作用が適用されます。
 *
 * ・スキル使用後
 * スキルを使用して、相手に効果が適用された後で、副作用が適用されます。
 * 微妙なタイミングの違い以外は、ほぼ「スキル使用時」と同じです。
 *
 * ・ターン開始時
 * 味方の行動入力が終わってターンが開始された瞬間に
 * 副作用が適用されます。
 *
 * ・ターン終了時
 * 全員の行動が完了してターンが終了した瞬間に
 * 副作用が適用されます。
 *
 * さらにスキルが「成功時のみ」「失敗時のみ」「弱点時のみ」の場合だけ
 * 副作用を適用することもできます。
 *
 * スキルのメモ欄に以下の通り指定してください。
 * 使用効果のうち、指定された番号の効果の適用対象がもとの効果範囲の対象者ではなく
 * スキル使用者に変更されます。（対象者には適用されなくなります）
 *
 * <SES_スキル入力時:4,3>  # スキル入力時、効果[4][3]を使用者に適用（敵専用）
 * <SES_OnSkillInput:4,3>  # 同上
 * <SES_スキル使用前:3>    # スキル使用前、効果[3]を使用者に適用
 * <SES_OnSkillBefore:3>   # 同上
 * <SES_スキル使用時:3>    # スキル使用時、効果[3]を使用者に適用
 * <SES_OnSkillUsing:3>    # 同上
 * <SES_スキル使用後:1,5>  # スキル使用後、効果[1][5]を使用者に適用（[,]区切り）
 * <SES_OnSkillAfter:1,5>  # 同上
 * <SES_ターン開始時:2,4>  # ターン開始時、効果[2][4]を使用者に適用
 * <SES_OnTurnStart:2,4>   # 同上
 * <SES_ターン終了時:8>    # ターン終了時、効果[8]を使用者に適用
 * <SES_OnTurnEnd:8>       # 同上
 * <SES_成功時のみ>        # 行動が成功した場合のみ副作用を適用
 * <SES_HitOnly>           # 同上
 * <SES_失敗時のみ>        # 行動が失敗した場合のみ副作用を適用
 * <SES_MissOnly>          # 同上
 * <SES_弱点時のみ>        # 行動が弱点を突いた場合のみ副作用を適用
 * <SES_EffectiveOnly>     # 同上
 * <SES_会心時のみ>        # 行動が会心だった場合のみ副作用を適用
 * <SES_CriticalOnly>      # 同上
 *
 * 複数指定する場合、[,]で区切ってください。効果の番号が[1]が先頭です。
 * また入力時副作用は敵キャラ専用です。
 *
 * 効果「コモンイベント」はタイミングが
 * 「ターン開始時」「スキル使用時」「スキル使用後」「ターン終了時」
 * の場合のみ適切なタイミングで実行されます。
 *
 * ・スクリプト（上級者向け）
 * 副作用でコモンイベントを実行した際、以下のスクリプトで
 * 副作用の対象バトラーを取得できます。
 * $gameTemp.getCommonEventSubjectBattler();
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc スキルの副作用プラグイン
 * @author トリアコンタン
 *
 * @help スキル使用時に、使用者に対する副作用を設定できます。
 * 副作用が適用されるタイミングは以下の中から選択できます。
 *
 * ・スキル入力時(敵キャラ専用)
 * 味方の行動入力前に副作用が適用されます。敵キャラ専用です。
 *
 * ・スキル使用前
 * スキルを使用する直前に副作用が適用されます。スキルを使用する時点では
 * すでに適用済みの状態になっています。
 *
 * ・スキル使用時
 * スキルを使用して、相手に効果が適用されるのと同じタイミングで
 * 副作用が適用されます。
 *
 * ・スキル使用後
 * スキルを使用して、相手に効果が適用された後で、副作用が適用されます。
 * 微妙なタイミングの違い以外は、ほぼ「スキル使用時」と同じです。
 *
 * ・ターン開始時
 * 味方の行動入力が終わってターンが開始された瞬間に
 * 副作用が適用されます。
 *
 * ・ターン終了時
 * 全員の行動が完了してターンが終了した瞬間に
 * 副作用が適用されます。
 *
 * さらにスキルが「成功時のみ」「失敗時のみ」「弱点時のみ」の場合だけ
 * 副作用を適用することもできます。
 *
 * スキルのメモ欄に以下の通り指定してください。
 * 使用効果のうち、指定された番号の効果の適用対象がもとの効果範囲の対象者ではなく
 * スキル使用者に変更されます。（対象者には適用されなくなります）
 *
 * <SES_スキル入力時:4,3>  # スキル入力時、効果[4][3]を使用者に適用（敵専用）
 * <SES_OnSkillInput:4,3>  # 同上
 * <SES_スキル使用前:3>    # スキル使用前、効果[3]を使用者に適用
 * <SES_OnSkillBefore:3>   # 同上
 * <SES_スキル使用時:3>    # スキル使用時、効果[3]を使用者に適用
 * <SES_OnSkillUsing:3>    # 同上
 * <SES_スキル使用後:1,5>  # スキル使用後、効果[1][5]を使用者に適用（[,]区切り）
 * <SES_OnSkillAfter:1,5>  # 同上
 * <SES_ターン開始時:2,4>  # ターン開始時、効果[2][4]を使用者に適用
 * <SES_OnTurnStart:2,4>   # 同上
 * <SES_ターン終了時:8>    # ターン終了時、効果[8]を使用者に適用
 * <SES_OnTurnEnd:8>       # 同上
 * <SES_成功時のみ>        # 行動が成功した場合のみ副作用を適用
 * <SES_HitOnly>           # 同上
 * <SES_失敗時のみ>        # 行動が失敗した場合のみ副作用を適用
 * <SES_MissOnly>          # 同上
 * <SES_弱点時のみ>        # 行動が弱点を突いた場合のみ副作用を適用
 * <SES_EffectiveOnly>     # 同上
 * <SES_会心時のみ>        # 行動が会心だった場合のみ副作用を適用
 * <SES_CriticalOnly>      # 同上
 * <SES_反射時のみ>        # 行動が魔法反射された場合のみ副作用を適用
 * <SES_ReflectionOnly>    # 同上
 * <SES_無効時のみ>        # 行動のダメージが0だった場合のみ副作用適用
 * <SES_InvalidOnly>       # 同上
 *
 * 複数指定する場合、[,]で区切ってください。効果の番号が[1]が先頭です。
 * また入力時副作用は敵キャラ専用です。
 *
 * 「成功時のみ」「失敗時のみ」といった条件は、以下のタイミングでは
 * スキルを実行前なので使用できません。
 * 　スキル入力時
 * 　スキル使用前
 * 　ターン開始時
 *
 * 効果「コモンイベント」はタイミングが
 * 「ターン開始時」「スキル使用時」「スキル使用後」「ターン終了時」
 * の場合のみ適切なタイミングで実行されます。
 *
 * ・スクリプト（上級者向け）
 * 副作用でコモンイベントを実行した際、以下のスクリプトで
 * 副作用の対象バトラーを取得できます。
 * $gameTemp.getCommonEventSubjectBattler();
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
  "use strict";
  var metaTagPrefix = "SES_";

  var getArgArrayString = function (args, upperFlg) {
    var values = getArgString(args, upperFlg).split(",");
    if (values[0] === "") values = [];
    for (var i = 0; i < values.length; i++) values[i] = values[i].trim();
    return values;
  };

  var getArgArrayEval = function (args, min, max) {
    var values = getArgArrayString(args, false);
    if (arguments.length < 2) min = -Infinity;
    if (arguments.length < 3) max = Infinity;
    for (var i = 0; i < values.length; i++)
      values[i] = eval(values[i]).clamp(min, max);
    return values;
  };

  var getArgString = function (arg, upperFlg) {
    arg = convertEscapeCharacters(arg);
    return upperFlg ? arg.toUpperCase() : arg;
  };

  var convertEscapeCharacters = function (text) {
    if (text == null || text === true) text = "";
    var windowLayer = SceneManager._scene._windowLayer;
    return windowLayer
      ? windowLayer.children[0].convertEscapeCharacters(text)
      : text;
  };

  var getMetaValue = function (object, name) {
    var metaTagName = metaTagPrefix + (name ? name : "");
    return object.meta.hasOwnProperty(metaTagName)
      ? object.meta[metaTagName]
      : undefined;
  };

  var getMetaValues = function (object, names) {
    if (!Array.isArray(names)) return getMetaValue(object, names);
    for (var i = 0, n = names.length; i < n; i++) {
      var value = getMetaValue(object, names[i]);
      if (value !== undefined) return value;
    }
    return undefined;
  };

  //=============================================================================
  // DataManager
  //  データベースのロード時にスキルとアイテムの使用効果から副作用対象を抜き取ります。
  //  以下のプロパティを新規で追加します。
  //   sideEffectOnInput  : スキル入力時副作用
  //   sideEffectOnBefore : スキル使用前副作用
  //   sideEffectOnAfter  : スキル使用後副作用
  //   sideEffectOnStart  : ターン開始時副作用
  //   sideEffectOnEnd    : ターン終了時副作用
  //=============================================================================
  var _DataManager_loadDatabase = DataManager.loadDatabase;
  DataManager.loadDatabase = function () {
    this._itemEffectsCategorize = false;
    _DataManager_loadDatabase.apply(this, arguments);
  };

  var _DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
  DataManager.isDatabaseLoaded = function () {
    var result = _DataManager_isDatabaseLoaded.apply(this, arguments);
    if (result && !this._itemEffectsCategorize) {
      this._itemEffectsCategorize = true;
      $dataItems.forEach(
        function (item) {
          this.categorizeItemEffects(item);
        }.bind(this)
      );
      $dataSkills.forEach(
        function (skill) {
          this.categorizeItemEffects(skill);
        }.bind(this)
      );
    }
    return result;
  };

  DataManager.categorizeItemEffects = function (data) {
    if (!data) return;
    var sideEffectOnEnd = [],
      sideEffectOnUsing = [],
      sideEffectOnBefore = [],
      sideEffectOnStart = [],
      sideEffectOnInput = [],
      sideEffectOnAfter = [];
    var numbersOnInput = this.getSideEffectNumbers(data, [
      "OnSkillInput",
      "スキル入力時",
    ]);
    var numbersOnBefore = this.getSideEffectNumbers(data, [
      "OnSkillBefore",
      "スキル使用前",
    ]);
    var numbersOnUsing = this.getSideEffectNumbers(data, [
      "OnSkillUsing",
      "スキル使用時",
    ]);
    var numbersOnAfter = this.getSideEffectNumbers(data, [
      "OnSkillAfter",
      "スキル使用後",
    ]);
    var numbersOnStart = this.getSideEffectNumbers(data, [
      "OnTurnStart",
      "ターン開始時",
    ]);
    var numbersOnEnd = this.getSideEffectNumbers(data, [
      "OnTurnEnd",
      "ターン終了時",
    ]);
    var effects = data.effects;
    for (var i = 0; i < effects.length; i++) {
      if (numbersOnInput.contains(i + 1)) {
        sideEffectOnInput.push(effects[i]);
        effects[i].sideEffect = true;
      }
      if (numbersOnBefore.contains(i + 1)) {
        sideEffectOnBefore.push(effects[i]);
        effects[i].sideEffect = true;
      }
      if (numbersOnUsing.contains(i + 1)) {
        sideEffectOnUsing.push(effects[i]);
        effects[i].sideEffect = true;
      }
      if (numbersOnAfter.contains(i + 1)) {
        sideEffectOnAfter.push(effects[i]);
        effects[i].sideEffect = true;
      }
      if (numbersOnStart.contains(i + 1)) {
        sideEffectOnStart.push(effects[i]);
        effects[i].sideEffect = true;
      }
      if (numbersOnEnd.contains(i + 1)) {
        sideEffectOnEnd.push(effects[i]);
        effects[i].sideEffect = true;
      }
    }
    data.effects = effects.filter(function (effect) {
      return !effect.sideEffect;
    });

    data.sideEffectOnInput = sideEffectOnInput;
    data.sideEffectOnBefore = sideEffectOnBefore;
    data.sideEffectOnUsing = sideEffectOnUsing;
    data.sideEffectOnAfter = sideEffectOnAfter;
    data.sideEffectOnStart = sideEffectOnStart;
    data.sideEffectOnEnd = sideEffectOnEnd;
  };

  DataManager.getSideEffectNumbers = function (data, names) {
    var metaValue = getMetaValues(data, names);
    if (metaValue) {
      return getArgArrayEval(metaValue, 1);
    }
    return [];
  };

  //=============================================================================
  // BattleManager
  //  ターン開始時に開始時副作用を適用します。
  //=============================================================================
  var _BattleManager_startTurn = BattleManager.startTurn;
  BattleManager.startTurn = function () {
    this.makeActionOrders();
    this._sideEffectBattlers = this._actionBattlers.clone();
    _BattleManager_startTurn.apply(this, arguments);
    this.applyItemSideEffectStart();
  };

  var _BattleManager_endTurn = BattleManager.endTurn;
  BattleManager.endTurn = function () {
    _BattleManager_endTurn.apply(this, arguments);
    if (this._sideEffectBattlers) {
      this.applyItemSideEffectEnd();
    }
  };

  var _BattleManager_startAction = BattleManager.startAction;
  BattleManager.startAction = function () {
    _BattleManager_startAction.apply(this, arguments);
    this._action.applyItemSideEffect("sideEffectOnBefore");
  };

  var _BattleManager_endAction = BattleManager.endAction;
  BattleManager.endAction = function () {
    _BattleManager_endAction.apply(this, arguments);
    if (this._action) {
      this._action.applyItemSideEffect("sideEffectOnAfter");
    }
  };

  BattleManager.applyItemSideEffectStart = function () {
    this._sideEffectBattlers.forEach(function (battler) {
      var number = battler.numActions();
      for (var i = 0; i < number; i++) {
        battler.action(i).applyItemSideEffect("sideEffectOnStart");
      }
    }, this);
  };

  BattleManager.applyItemSideEffectEnd = function () {
    this._sideEffectBattlers.forEach(function (battler) {
      var actions = battler.getEndActions();
      actions.forEach(function (action) {
        action.applyItemSideEffect("sideEffectOnEnd");
      }, this);
      battler.resetEndActions();
    }, this);
  };

  BattleManager.displaySideEffectResult = function (subject) {
    this._logWindow.displaySideEffectResult(subject);
    switch (this._phase) {
      case "input":
      case "turn":
        this._logWindow.waitForLong();
    }
  };

  //=============================================================================
  // Game_Battler
  //  終了した行動を別変数に保持します。
  //=============================================================================
  var _Game_Battler_removeCurrentAction =
    Game_Battler.prototype.removeCurrentAction;
  Game_Battler.prototype.removeCurrentAction = function () {
    var action = this.currentAction();
    if (action) {
      this._endActions = this.getEndActions();
      this._endActions.push(action);
    }
    _Game_Battler_removeCurrentAction.apply(this, arguments);
  };

  Game_Battler.prototype.getEndActions = function () {
    return this._endActions || [];
  };

  Game_Battler.prototype.resetEndActions = function () {
    this._endActions = null;
  };

  var _Game_Battler_onBattleEnd = Game_Battler.prototype.onBattleEnd;
  Game_Battler.prototype.onBattleEnd = function () {
    _Game_Battler_onBattleEnd.apply(this, arguments);
    this.resetEndActions();
  };

  //=============================================================================
  // Game_Enemy
  //  行動入力時に副作用を適用します。
  //=============================================================================
  var _Game_Enemy_makeActions = Game_Enemy.prototype.makeActions;
  Game_Enemy.prototype.makeActions = function () {
    _Game_Enemy_makeActions.apply(this, arguments);
    var number = this.numActions();
    for (var i = 0; i < number; i++) {
      this.action(i).applyItemSideEffect("sideEffectOnInput");
    }
    BattleManager.checkBattleEnd();
  };

  //=============================================================================
  // Game_Action
  //  副作用を適用します。
  //=============================================================================
  var _Game_Action_apply = Game_Action.prototype.apply;
  Game_Action.prototype.apply = function (target) {
    if (this._reflectionTarget) {
      this._reflectionForSideEffect = true;
    }
    _Game_Action_apply.apply(this, arguments);
    this.applyItemSideEffect("sideEffectOnUsing");
  };

  var _Game_Action_makeDamageValue = Game_Action.prototype.makeDamageValue;
  Game_Action.prototype.makeDamageValue = function (target, critical) {
    this._criticalForSideEffect = critical;
    return _Game_Action_makeDamageValue.apply(this, arguments);
  };

  var _Game_Action_applyItemUserEffect =
    Game_Action.prototype.applyItemUserEffect;
  Game_Action.prototype.applyItemUserEffect = function (target) {
    _Game_Action_applyItemUserEffect.apply(this, arguments);
    this._successForSideEffect = true;
  };

  var _Game_Action_calcElementRate = Game_Action.prototype.calcElementRate;
  Game_Action.prototype.calcElementRate = function (target) {
    var rate = _Game_Action_calcElementRate.apply(this, arguments);
    if (!BattleManager.isInputting() && rate >= 1.1) {
      this._effectiveForSideEffect = true;
    }
    return rate;
  };

  var _Game_Action_executeDamage = Game_Action.prototype.executeDamage;
  Game_Action.prototype.executeDamage = function (target, value) {
    if (value === 0) {
      this._invalidForSideEffect = true;
    }
    _Game_Action_executeDamage.apply(this, arguments);
  };

  Game_Action.prototype.applyItemSideEffect = function (property) {
    if (!this.isValidSideEffect()) return;
    if (this.isNeedDisplaySideEffect(property)) {
      this.subject().result().clear();
    }
    this.item()[property].forEach(function (effect) {
      this.applyItemEffect(this.subject(), effect);
    }, this);
    this.applyItemSideEffectGlobal(property);
  };

  Game_Action.prototype.isValidSideEffect = function () {
    if (!this.item()) {
      return false;
    } else {
      return (
        this.isValidSideEffectForSuccess() &&
        this.isValidSideEffectForFailure() &&
        this.isValidSideEffectForEffective() &&
        this.isValidSideEffectForCritical() &&
        this.isValidSideEffectForInvalid() &&
        this.isValidSideEffectForReflection()
      );
    }
  };

  Game_Action.prototype.isValidSideEffectForSuccess = function () {
    return (
      this._successForSideEffect ||
      !getMetaValues(this.item(), ["HitOnly", "成功時のみ"])
    );
  };

  Game_Action.prototype.isValidSideEffectForFailure = function () {
    return (
      !this._successForSideEffect ||
      !getMetaValues(this.item(), ["MissOnly", "失敗時のみ"])
    );
  };

  Game_Action.prototype.isValidSideEffectForEffective = function () {
    return (
      this._effectiveForSideEffect ||
      !getMetaValues(this.item(), ["EffectiveOnly", "弱点時のみ"])
    );
  };

  Game_Action.prototype.isValidSideEffectForCritical = function () {
    return (
      this._criticalForSideEffect ||
      !getMetaValues(this.item(), ["CriticalOnly", "会心時のみ"])
    );
  };

  Game_Action.prototype.isValidSideEffectForInvalid = function () {
    return (
      this._invalidForSideEffect ||
      !getMetaValues(this.item(), ["InvalidOnly", "無効時のみ"])
    );
  };

  Game_Action.prototype.isValidSideEffectForReflection = function () {
    return (
      this._reflectionForSideEffect ||
      !getMetaValues(this.item(), ["ReflectionOnly", "反射時のみ"])
    );
  };

  Game_Action.prototype.applyItemSideEffectGlobal = function (property) {
    this.item()[property].forEach(function (effect) {
      if (effect.code === Game_Action.EFFECT_COMMON_EVENT) {
        $gameTemp.reserveCommonEvent(effect.dataId);
        $gameTemp.setCommonEventSubject(this.subject());
      }
    }, this);
    if (this.isNeedDisplaySideEffect(property))
      BattleManager.displaySideEffectResult(this.subject());
  };

  Game_Action.prototype.isNeedDisplaySideEffect = function (property) {
    return property !== "sideEffectOnUsing" && property !== "sideEffectOnEnd";
  };

  //=============================================================================
  // Game_Temp
  //  コモンイベントの予約をスタックします。
  //=============================================================================
  var _Game_Temp_initialize = Game_Temp.prototype.initialize;
  Game_Temp.prototype.initialize = function () {
    _Game_Temp_initialize.apply(this, arguments);
    this._commonEventReserveStack = [];
    this._commonEventSubjects = [];
    this._commonEventSubjectBattler = null;
    this.getCommonEventSubjectBattler();
  };

  var _Game_Temp_reserveCommonEvent = Game_Temp.prototype.reserveCommonEvent;
  Game_Temp.prototype.reserveCommonEvent = function (commonEventId) {
    if (this.isCommonEventReserved()) {
      this._commonEventReserveStack.push(commonEventId);
    } else {
      _Game_Temp_reserveCommonEvent.apply(this, arguments);
    }
  };

  Game_Temp.prototype.setCommonEventSubject = function (battler) {
    this._commonEventSubjects.push(battler);
  };

  var _Game_Temp_clearCommonEvent = Game_Temp.prototype.clearCommonEvent;
  Game_Temp.prototype.clearCommonEvent = function () {
    _Game_Temp_clearCommonEvent.apply(this, arguments);
    if (this._commonEventReserveStack.length > 0) {
      this.reserveCommonEvent(this._commonEventReserveStack.shift());
    }
    if (this._commonEventSubjects.length > 0) {
      this._commonEventSubjectBattler = this._commonEventSubjects.shift();
    } else {
      this._commonEventSubjectBattler = null;
    }
  };

  Game_Temp.prototype.getCommonEventSubjectBattler = function () {
    return this._commonEventSubjectBattler;
  };

  //=============================================================================
  // Window_BattleLog
  //  副作用効果を出力します。
  //=============================================================================
  Window_BattleLog.prototype.displaySideEffectResult = function (subject) {
    this.displayChangedStates(subject);
    this.displayChangedBuffs(subject);
    subject.startDamagePopup();
    if (!$gameSystem.isSideView() && subject.result().used) {
      this.displayDamage(subject);
    }
  };

  Window_BattleLog.prototype.waitForLong = function () {
    if (this.countTextStack() > 0) {
      this.push("waitForSideEffectMessage");
      this.push("clear");
    }
  };

  Window_BattleLog.prototype.waitForSideEffectMessage = function () {
    this._waitCount = 30;
  };

  Window_BattleLog.prototype.countTextStack = function () {
    return this._methods.reduce(function (prevValue, method) {
      return prevValue + (method.name === "addText" ? 1 : 0);
    }, 0);
  };
})();


code:
//=============================================================================
// SimpleMsgSideView.js
//=============================================================================

/*:
 * @plugindesc at sideview battle, only display item/skill names.
 * @author Sasuke KANNAZUKI
 *
 * @param displayAttack
 * @desc Whether to display normal attack. 1:yes 0:no
 * @default 0
 *
 * @param position
 * @desc Skill name display position. 0:left, 1:center
 * @default 1
 *
 * @help This plugin does not provide plugin commands.
 *
 * By not displaying the log and only displaying the skill name,
 * the speed of battle will increase slightly.
 */

/*:ja
 * @plugindesc サイドビューバトルで技/アイテムの名前のみ表示します。
 * @author 神無月サスケ
 *
 * @param displayAttack
 * @desc 通常攻撃も表示するか (1:する 0:しない)
 * @default 0
 *
 * @param position
 * @desc 技名を表示する位置 (0:左寄せ, 1:中央)
 * @default 1
 *
 * @help このプラグインには、プラグインコマンドはありません。
 *
 * ログを表示せず、技名のみを表示することで、戦闘のテンポが若干高速になります。
 */

(function () {
  var parameters = PluginManager.parameters("SimpleMsgSideView");
  var displayAttack = Number(parameters["displayAttack"]) != 0;
  var position = Number(parameters["position"] || 1);

  var _Window_BattleLog_addText = Window_BattleLog.prototype.addText;
  Window_BattleLog.prototype.addText = function (text) {
    if ($gameSystem.isSideView()) {
      this.refresh();
      this.wait();
      return; // not display battle log
    }
    _Window_BattleLog_addText.call(this, text);
  };

  // for sideview battle only
  Window_BattleLog.prototype.addItemNameText = function (itemName) {
    this._lines.push(itemName);
    this.refresh();
    this.wait();
  };

  var _Window_BattleLog_displayAction =
    Window_BattleLog.prototype.displayAction;
  Window_BattleLog.prototype.displayAction = function (subject, item) {
    if ($gameSystem.isSideView()) {
      if (
        displayAttack ||
        !(DataManager.isSkill(item) && item.id == subject.attackSkillId())
      ) {
        this.push("addItemNameText", item.name); // display item/skill name
      } else {
        this.push("wait");
      }
      return;
    }
    _Window_BattleLog_displayAction.call(this, subject, item);
  };

  // to put skill/item name at center
  var _Window_BattleLog_drawLineText = Window_BattleLog.prototype.drawLineText;
  Window_BattleLog.prototype.drawLineText = function (index) {
    if ($gameSystem.isSideView() && position == 1) {
      var rect = this.itemRectForText(index);
      this.contents.clearRect(rect.x, rect.y, rect.width, rect.height);
      this.drawText(this._lines[index], rect.x, rect.y, rect.width, "center");
      return;
    }
    _Window_BattleLog_drawLineText.call(this, index);
  };
})();


code:
//=============================================================================
// TMPlugin - メニューラベル
// バージョン: 1.1.1
// 最終更新日: 2017/02/07
// 配布元    : http://hikimoki.sakura.ne.jp/
//-----------------------------------------------------------------------------
// Copyright (c) 2016 tomoaky
// Released under the MIT license.
// http://opensource.org/licenses/mit-license.php
//=============================================================================

/*:
 * @plugindesc メニューシーンに変数の値を表示します。
 * 歩数や戦闘回数などを表示することもできます。
 *
 * @author tomoaky (http://hikimoki.sakura.ne.jp/)
 *
 * @param labelAName
 * @desc ラベルＡの名前
 * 初期値: ラベルＡ
 * @default ラベルＡ
 *
 * @param labelAId
 * @desc ラベルＡのゲーム変数番号
 * 初期値: 10（ 0 で非表示 / 1 以上で表示）
 * @default 10
 *
 * @param labelAMax
 * @desc ラベルＡの最大値
 * 初期値: 9999
 * @default 9999
 *
 * @param labelAFooter
 * @desc ラベルＡのフッターテキスト
 * 初期値:
 * @default
 *
 * @param labelBName
 * @desc ラベルＢの名前
 * 初期値: ラベルＢ
 * @default ラベルＢ
 *
 * @param labelBId
 * @desc ラベルＢのゲーム変数番号
 * 初期値: 0（ 0 で非表示 / 1 以上で表示）
 * @default 0
 *
 * @param labelBMax
 * @desc ラベルＢの最大値
 * 初期値: 9999
 * @default 9999
 *
 * @param labelBFooter
 * @desc ラベルＢのフッターテキスト
 * 初期値:
 * @default
 *
 * @param labelCName
 * @desc ラベルＣの名前
 * 初期値: ラベルＣ
 * @default ラベルＣ
 *
 * @param labelCId
 * @desc ラベルＣのゲーム変数番号
 * 初期値: 0（ 0 で非表示 / 1 以上で表示）
 * @default 0
 *
 * @param labelCMax
 * @desc ラベルＣの最大値
 * 初期値: 9999
 * @default 9999
 *
 * @param labelCFooter
 * @desc ラベルＣのフッターテキスト
 * 初期値:
 * @default
 *
 * @param labelDName
 * @desc ラベルＤの名前
 * 初期値: ラベルＤ
 * @default ラベルＤ
 *
 * @param labelDId
 * @desc ラベルＤのゲーム変数番号
 * 初期値: 0（ 0 で非表示 / 1 以上で表示）
 * @default 0
 *
 * @param labelDMax
 * @desc ラベルＤの最大値
 * 初期値: 9999
 * @default 9999
 *
 * @param labelDFooter
 * @desc ラベルＤのフッターテキスト
 * 初期値:
 * @default
 *
 * @param labelNameWidth
 * @desc ラベル名の表示幅
 * 初期値: 128
 * @default 128
 *
 * @param labelValueWidth
 * @desc ラベル値の表示幅
 * 初期値: 72
 * @default 72
 *
 * @param labelNameColorId
 * @desc ラベル名の文字色番号
 * 初期値: 16
 * @default 16
 *
 * @param labelValueColorId
 * @desc ラベル値の文字色番号
 * 初期値: 0
 * @default 0
 *
 * @param labelMaxColorId
 * @desc ラベル値が最大のときの文字色番号
 * 初期値: 2
 * @default 2
 *
 * @param labelFooterColorId
 * @desc フッターの文字色番号
 * 初期値: 0
 * @default 0
 *
 * @param footerSpace
 * @desc フッターとラベル値の間隔
 * 初期値: 0
 * @default 0
 *
 * @param reverseMenuWindow
 * @desc メニューシーンのウィンドウ配置を左右反転
 * 初期値: 0 ( 0 = 無効 / 1 = 有効)
 * @default 0
 *
 * @param menuTextAlign
 * @desc メニューコマンド項目の描画位置
 * 初期値: left ( left / center / right)
 * @default left
 *
 * @help
 * TMPlugin - メニューラベル ver1.1.1

 * 使い方:
 *
 *   このプラグインを導入するとメインメニューの左下にゲーム変数の
 *   値（以下ラベル）を最大で 4 つまで表示することができるようになります。
 *
 *   このプラグインは RPGツクールMV Version 1.3.4 で動作確認をしています。
 *
 *
 * プラグインコマンド:
 *
 *   stopMenuLabel
 *     メニューラベルを無効にします。この設定はセーブデータにも記録され、
 *     startMenuLabel コマンドが実行されるまでラベルが表示されなくなります。
 *
 *   startMenuLabel
 *     無効になっているメニューラベルを有効にします。
 *     ゲーム開始時の状態ではメニューラベルは有効になっています。
 *
 *
 * プラグインパラメータ補足:
 *
 *   labelAId ～ labelDId
 *     この値が 1 以上のときは変数の値が表示され、それ以外の場合は
 *     以下のようなルールで表示される値が変化します。
 *      0 … ラベルの無効化（何も表示しない）
 *     -1 … 歩数
 *     -2 … セーブ回数
 *     -3 … 戦闘回数
 *     -4 … 勝利回数
 *     -5 … 敗北回数
 *
 *   labelAMax ～ labelDMax
 *     ゲーム変数の値がこれらの値以上だった場合、ラベルに表示される値の
 *     文字色番号が labelValueColorId から labelMaxColorId に変化します。
 *     また、ゲーム変数の値が最大値よりも大きい場合は、最大値を表示します。
 *     0 を設定すると上記機能が無効になります。
 *
 *   labelAFooter ～ labelDFooter
 *     ラベル値の後ろに表示する文字列を設定します。
 *     『1234 点』、『12 日目』のような表示にするための機能です、値との間の
 *     スペースは半角スペースなどで調整してください。
 *
 *   labelNameColorId
 *   labelValueColorId
 *   labelMaxColorId
 *   labelFooterColorId
 *     ラベルの各部分ごとの文字色番号を設定します。
 *     番号はイベントコマンド『文章の表示』などで使う制御文字 \C[n] の
 *     n の部分と同じものになります。
 *
 *   footerSpace
 *     ラベル値とフッターの表示位置を所持金ウィンドウとそろえたいときは
 *     このパラメータを調節してください。フッターと通貨単位がともに
 *     全角 1 文字の場合は 6 を設定するとちょうど同じになります。
 */

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

var TMPlugin = TMPlugin || {};
TMPlugin.MenuLabel = {};
TMPlugin.MenuLabel.Parameters = PluginManager.parameters("TMMenuLabel");
TMPlugin.MenuLabel.Labels = [];
TMPlugin.MenuLabel.Labels[0] = {
  name: TMPlugin.MenuLabel.Parameters["labelAName"],
  id: +(TMPlugin.MenuLabel.Parameters["labelAId"] || 10),
  max: +(TMPlugin.MenuLabel.Parameters["labelAMax"] || 9999),
  footer: TMPlugin.MenuLabel.Parameters["labelAFooter"],
};
TMPlugin.MenuLabel.Labels[1] = {
  name: TMPlugin.MenuLabel.Parameters["labelBName"],
  id: +(TMPlugin.MenuLabel.Parameters["labelBId"] || 10),
  max: +(TMPlugin.MenuLabel.Parameters["labelBMax"] || 9999),
  footer: TMPlugin.MenuLabel.Parameters["labelBFooter"],
};
TMPlugin.MenuLabel.Labels[2] = {
  name: TMPlugin.MenuLabel.Parameters["labelCName"],
  id: +(TMPlugin.MenuLabel.Parameters["labelCId"] || 10),
  max: +(TMPlugin.MenuLabel.Parameters["labelCMax"] || 9999),
  footer: TMPlugin.MenuLabel.Parameters["labelCFooter"],
};
TMPlugin.MenuLabel.Labels[3] = {
  name: TMPlugin.MenuLabel.Parameters["labelDName"],
  id: +(TMPlugin.MenuLabel.Parameters["labelDId"] || 10),
  max: +(TMPlugin.MenuLabel.Parameters["labelDMax"] || 9999),
  footer: TMPlugin.MenuLabel.Parameters["labelDFooter"],
};
TMPlugin.MenuLabel.NameWidth = +(
  TMPlugin.MenuLabel.Parameters["labelNameWidth"] || 160
);
TMPlugin.MenuLabel.ValueWidth = +(
  TMPlugin.MenuLabel.Parameters["labelValueWidth"] || 96
);
TMPlugin.MenuLabel.NameColorId = +(
  TMPlugin.MenuLabel.Parameters["labelNameColorId"] || 16
);
TMPlugin.MenuLabel.ValueColorId = +(
  TMPlugin.MenuLabel.Parameters["labelValueColorId"] || 0
);
TMPlugin.MenuLabel.MaxColorId = +(
  TMPlugin.MenuLabel.Parameters["labelMaxColorId"] || 2
);
TMPlugin.MenuLabel.FooterColorId = +(
  TMPlugin.MenuLabel.Parameters["labelFooterColorId"] || 0
);
TMPlugin.MenuLabel.FooterSpace = +(
  TMPlugin.MenuLabel.Parameters["footerSpace"] || 0
);
TMPlugin.MenuLabel.ReverseMenuWindow =
  TMPlugin.MenuLabel.Parameters["reverseMenuWindow"] === "1";
TMPlugin.MenuLabel.MenuTextAlign =
  TMPlugin.MenuLabel.Parameters["menuTextAlign"] || "left";

(function () {
  //-----------------------------------------------------------------------------
  // Game_System
  //

  Game_System.prototype.isMenuLabelEnabled = function () {
    if (this._menuLabelEnabled === undefined) this._menuLabelEnabled = true;
    return this._menuLabelEnabled;
  };

  Game_System.prototype.setMenuLabel = function (flag) {
    this._menuLabelEnabled = flag;
  };

  //-----------------------------------------------------------------------------
  // Game_Interpreter
  //

  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.call(this, command, args);
    if (command === "startMenuLabel") {
      $gameSystem.setMenuLabel(true);
    } else if (command === "stopMenuLabel") {
      $gameSystem.setMenuLabel(false);
    }
  };

  //-----------------------------------------------------------------------------
  // Window_MenuCommand
  //

  Window_MenuCommand.prototype.itemTextAlign = function () {
    return TMPlugin.MenuLabel.MenuTextAlign;
  };

  //-----------------------------------------------------------------------------
  // Window_MenuLabel
  //

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

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

  Window_MenuLabel.prototype.initialize = function (x, y) {
    var width = this.windowWidth();
    var height = this.windowHeight();
    Window_Base.prototype.initialize.call(this, x, y, width, height);
    this.refresh();
  };

  Window_MenuLabel.prototype.maxItems = function () {
    var n = 0;
    for (var i = 0; i < 4; i++) {
      if (TMPlugin.MenuLabel.Labels[i].id !== 0) n++;
    }
    return n;
  };

  Window_MenuLabel.prototype.windowWidth = function () {
    return 240;
  };

  Window_MenuLabel.prototype.windowHeight = function () {
    return this.fittingHeight(this.maxItems());
  };

  Window_MenuLabel.prototype.refresh = function () {
    var x = this.textPadding();
    var width = this.contents.width - this.textPadding() * 2;
    var lineHeight = this.lineHeight();
    this.contents.clear();
    var x = this.contents.width - this.textPadding();
    var y = 0;
    for (var i = 0; i < 4; i++) {
      var label = TMPlugin.MenuLabel.Labels[i];
      var value = this.labelValue(label.id);
      if (value != null) {
        this.drawMenuLabel(x, y, label, value);
        y += lineHeight;
      }
    }
  };

  Window_MenuLabel.prototype.labelValue = function (id) {
    if (id > 0) {
      return $gameVariables.value(id);
    } else if (id === -1) {
      return $gameParty.steps();
    } else if (id === -2) {
      return $gameSystem.saveCount();
    } else if (id === -3) {
      return $gameSystem.battleCount();
    } else if (id === -4) {
      return $gameSystem.winCount();
    } else if (id === -5) {
      return $gameSystem.escapeCount();
    }
    return null;
  };

  Window_MenuLabel.prototype.drawMenuLabel = function (x, y, label, value) {
    if (label.footer) {
      var footerWidth = this.textWidth(label.footer);
      x -= footerWidth;
      this.changeTextColor(this.textColor(TMPlugin.MenuLabel.FooterColorId));
      this.drawText(label.footer, x, y, footerWidth);
      x -= TMPlugin.MenuLabel.FooterSpace;
    }
    x -= TMPlugin.MenuLabel.ValueWidth;
    this.changeTextColor(this.textColor(TMPlugin.MenuLabel.ValueColorId));
    if (label.max && value >= label.max) {
      value = label.max;
      this.changeTextColor(this.textColor(TMPlugin.MenuLabel.MaxColorId));
    }
    this.drawText(value, x, y, TMPlugin.MenuLabel.ValueWidth, "right");
    if (label.name) {
      this.changeTextColor(this.textColor(TMPlugin.MenuLabel.NameColorId));
      this.drawText(
        label.name,
        this.textPadding(),
        y,
        TMPlugin.MenuLabel.NameWidth
      );
    }
  };

  //-----------------------------------------------------------------------------
  // Scene_Menu
  //

  var _Scene_Menu_create = Scene_Menu.prototype.create;
  Scene_Menu.prototype.create = function () {
    _Scene_Menu_create.call(this);
    if ($gameSystem.isMenuLabelEnabled()) this.createMenuLabelWindow();
    if (TMPlugin.MenuLabel.ReverseMenuWindow) {
      this._statusWindow.x = 0;
      this._commandWindow.x = this._statusWindow.width;
      this._goldWindow.x = this._commandWindow.x;
      if (this._menuLabelWindow)
        this._menuLabelWindow.x = this._commandWindow.x;
    }
  };

  Scene_Menu.prototype.createMenuLabelWindow = function () {
    this._menuLabelWindow = new Window_MenuLabel(0, 0);
    this._menuLabelWindow.y = this._goldWindow.y - this._menuLabelWindow.height;
    this.addWindow(this._menuLabelWindow);
  };
})();


code:
//=============================================================================
// ThroughFailedToLoad.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015-2017 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 2.3.1 2017/10/30 アニメーション画像に対するエラーが無視が無効になっていた問題を修正
// 2.3.0 2017/10/29 音声ファイルと画像ファイルのいずれかのみ無視する機能を追加
// 2.2.0 2017/06/18 本体v1.5.0で機能しなくなる問題を修正
// 2.1.1 2017/03/11 通常版1.3.5でエラーになる問題を修正
// 2.1.0 2017/03/11 本体v1.3.5(コミュニティ版)で機能しなくなる問題を修正
// 2.0.0 2016/08/05 本体v1.3.0対応（1.2.0では使えなくなります）
// 1.0.0 2016/06/25 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc Through Failed to load
 * @author triacontane
 *
 * @param InvalidIfTest
 * @desc Not through if test play.
 * @default true
 * @type boolean
 *
 * @param InvalidIfWeb
 * @desc Not through if Web mode.
 * @default false
 * @type boolean
 *
 * @param ThroughType
 * @desc 無視する素材の種別です。
 * @default 3
 * @type select
 * @option Audio Only
 * @value 1
 * @option Image Only
 * @value 2
 * @option All
 * @value 3
 *
 * @help Through error of Failed to load.
 * Image not found, Audio not found.
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc ロード失敗エラーのすり抜けプラグイン
 * @author トリアコンタン
 *
 * @param テストプレー時無効
 * @desc テストプレー時は本プラグインの機能が無効になります。
 * @default true
 * @type boolean
 *
 * @param Web版で無効
 * @desc Web版実行時は本プラグインの機能が無効になります。
 * @default false
 * @type boolean
 *
 * @param 無視種別
 * @desc 無視する素材の種別です。
 * @default 3
 * @type select
 * @option 音声のみ
 * @value 1
 * @option 画像のみ
 * @value 2
 * @option 全て
 * @value 3
 *
 * @help 存在しない画像、音声素材が指定された場合に発生するエラーを無視します。
 * 音声の場合は何も再生されず、画像の場合は空の透明画像がセットされます。
 *
 * エラーログは通常通り出力されます。
 *
 * 本体v1.5.0より正式に実装されたロード失敗時に3回までリロードする機能については
 * 当プラグインの機能と競合するため、無効化されます。
 *
 * フォント、データベースまたはプラグインで追加されたファイルの読み込みに
 * 失敗した場合は、通常通りエラーが発生します。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
  "use strict";
  var pluginName = "ThroughFailedToLoad";

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

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

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

  //=============================================================================
  // パラメータの取得と整形
  //=============================================================================
  var paramInvalidIfTest = getParamBoolean([
    "InvalidIfTest",
    "テストプレー時無効",
  ]);
  var paramInvalidIfWeb = getParamBoolean(["InvalidIfWeb", "Web版で無効"]);
  var paramThroughType = getParamNumber(["ThroughType", "無視種別"], 1, 3);

  //=============================================================================
  // プラグイン無効条件の判定
  //=============================================================================
  if (paramInvalidIfTest && Utils.isOptionValid("test")) {
    return;
  } else if (paramInvalidIfWeb && !Utils.isNwjs()) {
    return;
  }

  if (paramThroughType !== 1) {
    //=============================================================================
    // Bitmap
    //  エラー発生用のフラグをキャンセルします。
    //=============================================================================
    var _Bitmap_isReady = Bitmap.prototype.isReady;
    Bitmap.prototype.isReady = function () {
      if (this.isError()) {
        this.eraseError();
      }
      return _Bitmap_isReady.apply(this, arguments);
    };

    var _Bitmap_decode = Bitmap.prototype.decode;
    Bitmap.prototype.decode = function () {
      _Bitmap_decode.apply(this, arguments);
      if (this._loadingState === "requesting") {
        this._image.addEventListener("error", this._onError.bind(this));
      }
    };

    Bitmap.prototype.eraseError = function () {
      this._hasError = false;
      this._isLoading = false;
      this._loadingState = "loaded";
    };

    //=============================================================================
    // Graphics
    //  エラーイベントを登録します。
    //=============================================================================
    var _Graphics__playVideo = Graphics._playVideo;
    Graphics._playVideo = function (src) {
      _Graphics__playVideo.apply(this, arguments);
      this._video.onerror = this._videoLoader || this._onVideoError.bind(this);
    };
  }

  if (paramThroughType !== 2) {
    //=============================================================================
    // AudioManager
    //  エラーチェック処理を無視します。
    //=============================================================================
    AudioManager.checkErrors = function () {};
  }

  if (typeof ResourceHandler !== "undefined") {
    //=============================================================================
    // ResourceHandler
    //  リトライ機能の仕様を変更します。
    //=============================================================================
    var _ResourceHandler_createLoader = ResourceHandler.createLoader;
    ResourceHandler.createLoader = function (
      url,
      retryMethod,
      resignMethod,
      retryInterval
    ) {
      return this.isNeedLoader(url)
        ? _ResourceHandler_createLoader.apply(this, arguments)
        : null;
    };

    ResourceHandler.isNeedLoader = function (url) {
      if (paramThroughType === 1 && !url.match(/^audio\//)) {
        return true;
      } else if (
        paramThroughType === 2 &&
        !url.match(/^img\//) &&
        !url.match(/^movie\//)
      ) {
        return true;
      } else {
        return false;
      }
    };
  }
})();


code:
//=============================================================================
// TinyGetInfoWnd.js
//=============================================================================

/*:
 * @plugindesc Display tiny window of gaining/losing items information on map
 * @author Sasuke KANNAZUKI
 *
 * @param Event Command Switch
 * @desc If the switch on, display window when change an item number by an
 *  event command (only map scene, not on battle).
 * @default 22
 *
 * @param Y position type
 * @desc Windows' position. 0:top 1:bottom
 * @default 1
 *
 * @param textGainItem
 * @desc title text display on the window when gain item(s).
 * %1 is replaced to the item's kind(weapon/armor/item).
 * @default You got %1
 *
 * @param textLoseItem
 * @desc title text display on the window when lose item(s).
 * %1 is replaced to the item's kind(weapon/armor/item).
 * @default You lost %1
 *
 * @param SE filename
 * @desc the filename of the SE that plays when you gain item(s).
 * note: It doesn't play when you lose item(s).
 * @default Chime2
 *
 * @param SE volume
 * @desc the volume of the SE that plays when you gain item(s).
 * @default 90
 *
 * @param SE pitch
 * @desc the pitch of the SE that plays when you gain item(s).
 * @default 100
 *
 * @help
 * Plugin Commands:
 * TinyGetInfoWnd arg0 arg1 arg2 arg3
 * arg0 must be 'item', 'weapon', or 'armor'.
 * arg1 must be the ID of the item(or equipment),
 *  or 'V' + number(ex. 'V20') where the number is the variable ID for item ID.
 * arg2 must be 'gain' or 'lose'. (default value is 'gain').
 * arg3 must be the number of gain/lose. (defalut value is 1).
 *  (arg3 also accepts the same notation as the arg1 like 'V15')
 * ex.
 * TinyGetInfoWnd weapon 14 gain 2  # gain 2 weapons whose id is 14.
 * TinyGetInfoWnd armor 20 lose 1   # lose an armor whose id is 20.
 *   (if you equip the armor, it will not be lost.)
 * TinyGetInfoWnd item 7    # gain an item whose id is 7.
 *   (default value, arg2='gain' and arg3='1' is applied.)
 * TinyGetInfoWnd item V10 gain 3   # gain 3 items whose ID is variable #10.
 *
 * note description:
 * <info:the_explanation> : the_explanation is displayed when gain or lose
 *  the item. If it isn't written down, the first line of the item's
 *  description is displayed.
 *
 * Item lost is not more than the party has.
 * When you have only 3 and execute 'lose 5' for the item,
 * it will display 'lost 3'.
 * When you have the item none, even if execute 'lose', do not display window.
 */
/*:ja
 * @plugindesc マップ上でアイテムの入手/消失を小さなウィンドウで表示します。
 * @author 神無月サスケ
 *
 * @param Event Command Switch
 * @desc このスイッチがONの時、イベントコマンド「アイテム/武器/防具の増減」を行った時にウィンドウが表示されます(マップのみ)
 * @default 22
 *
 * @param Y position type
 * @desc 複数のウィンドウを並べる位置です。0:上部 1:下部
 * @default 1
 *
 * @param textGainItem
 * @desc アイテムを入手した時に表示するタイトルです。
 * %1がアイテム種別(アイテム/武器/防具)に置き換わります。
 * @default %1入手！
 *
 * @param textLoseItem
 * @desc アイテムを消失した時に表示するタイトルです。
 * %1がアイテム種別(アイテム/武器/防具)に置き換わります。
 * @default %1消失……。
 *
 * @param SE filename
 * @desc アイテムを入手した時に演奏されるSEのファイル名です。
 * 注意：消失した時は演奏されません。
 * @default Chime2
 *
 * @param SE volume
 * @desc アイテムを入手した時に演奏されるSEのボリュームです。
 * @default 90
 *
 * @param SE pitch
 * @desc アイテムを入手した時に演奏されるSEのピッチです。
 * @default 100
 *
 * @help
 * プラグインコマンドの書式:
 * TinyGetInfoWnd arg0 arg1 arg2 arg3
 * arg0 は item, weapon, armor のいずれかにします。
 * arg1 は アイテム(または武器防具)のID、
 *  または V20 のようにVで始まる数字にします。
 *  後者の場合数字の番号(ここでは20)の変数の値がアイテムのIDになります。
 * arg2 は gain, lose のいずれかにします。(省略時はgain)
 * arg3 は 個数にします。(省略時は1, arg2を省略してarg3を書くことは出来ません)
 * (arg3 でも arg1 と同等の、V15 のような Vで始まる記法が利用可能です)
 * ex.
 * TinyGetInfoWnd weapon 14 gain 2  # ID14の武器を2個得る。
 * TinyGetInfoWnd armor 20 lose 1   # ID20の鎧を1個失う
 *   (ただし装備していた場合は失わない)
 * TinyGetInfoWnd item 7            # ID7のアイテムを1個得る。
 *   (パラメータを省略したので、arg2はgainに、arg3は1になります。)
 * TinyGetInfoWnd item V10 gain 3   # 変数10番の値のIDのアイテムを3個得る。
 *
 * メモの書式：
 * <info:the_explanation> : the_explanation の文章が、アイテムの説明として
 *   入手/消失時に表示されます。省略した場合は、アイテムの説明の1行目が
 *   表示されます。
 *
 * アイテムの消失は、所持している数に関連します。
 * 例えば5個消失コマンドを実行して、3個しか持っていない場合「3個消失」と
 * 表示されます。また、該当アイテムをひとつも持っていない場合は、
 * 消失ウィンドウは表示されません。
 */

(function () {
  //
  // process parameters
  //
  var parameters = PluginManager.parameters("TinyGetInfoWnd");
  var dispSwitchID = Number(parameters["Event Command Switch"] || 22);
  var yPosType = Number(parameters["Y position type"] || 1);
  var textGainItem = parameters["textGainItem"] || "You got %1";
  var textLoseItem = parameters["textLoseItem"] || "You lost %1";
  var seFilename = parameters["SE filename"] || "Chime2";
  var seVolume = Number(parameters["SE volume"] || 90);
  var sePitch = Number(parameters["SE pitch"] || 100);

  //
  // process plugin commands
  //
  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.call(this, command, args);
    if (command === "TinyGetInfoWnd") {
      // find args[1]
      var itemId = 0;
      var reg = /^V([0-9]+)/i.exec(args[1]);
      if (reg) {
        itemId = $gameVariables.value(Number(reg[1])) || 0;
      } else {
        itemId = Number(args[1]) || 0;
      }
      // find args[3]
      var itemNumber = 0;
      reg = /^V([0-9]+)/i.exec(args[3]);
      if (reg) {
        itemNumber = $gameVariables.value(Number(reg[1])) || 1;
      } else {
        itemNumber = Number(args[3]) || 1;
      }
      // get current spriteset
      var spriteSet = null;
      if (!$gameParty.inBattle()) {
        spriteSet = SceneManager._scene._spriteset;
      }
      // parse parameters
      switch (args[0]) {
        case "item":
          if (!!$dataItems[itemId] && !!spriteSet) {
            switch (args[2]) {
              case "gain":
              case undefined:
                // gain item process
                var text = textGainItem.format(TextManager.item);
                spriteSet.addGetInfoWindow(itemId, 0, text, itemNumber);
                break;
              case "lose":
                // lose item process
                var text = textLoseItem.format(TextManager.item);
                spriteSet.addGetInfoWindow(itemId, 0, text, -itemNumber);
                break;
            }
          }
          break;
        case "weapon":
          if (!!$dataWeapons[itemId] && !!spriteSet) {
            switch (args[2]) {
              case "gain":
              case undefined:
                // gain weapon process
                var text = textGainItem.format(TextManager.weapon);
                spriteSet.addGetInfoWindow(itemId, 1, text, itemNumber);
                break;
              case "lose":
                // lose weapon process
                var text = textLoseItem.format(TextManager.weapon);
                spriteSet.addGetInfoWindow(itemId, 1, text, -itemNumber);
                break;
            }
          }
          break;
        case "armor":
          if (!!$dataArmors[itemId] && !!spriteSet) {
            switch (args[2]) {
              case "gain":
              case undefined:
                // gain armor process
                var text = textGainItem.format(TextManager.armor);
                spriteSet.addGetInfoWindow(itemId, 2, text, itemNumber);
                break;
              case "lose":
                // lose armor process
                var text = textLoseItem.format(TextManager.armor);
                spriteSet.addGetInfoWindow(itemId, 2, text, -itemNumber);
                break;
            }
          }
          break;
      }
    }
  };

  //
  // variable initialization
  //
  var _Game_Temp_initialize = Game_Temp.prototype.initialize;
  Game_Temp.prototype.initialize = function () {
    _Game_Temp_initialize.call(this);
    this.strEffect = [];
    this.getInfoOccupied = [];
  };

  //
  // process spriteset
  //
  var _Scene_Map_onMapLoaded = Scene_Map.prototype.onMapLoaded;
  Scene_Map.prototype.onMapLoaded = function () {
    $gameTemp.strEffect = [];
    $gameTemp.getInfoOccupied = [];
    _Scene_Map_onMapLoaded.call(this);
  };

  Spriteset_Map.prototype.addGetInfoWindow = function (id, type, text, value) {
    var w = new Window_GetInfo(id, type, text, value);
    $gameTemp.strEffect.push(w);
    this._baseSprite.addChild(w);
  };

  var _Spriteset_Map_update = Spriteset_Map.prototype.update;
  Spriteset_Map.prototype.update = function () {
    _Spriteset_Map_update.call(this);
    for (var i = 0; i < $gameTemp.strEffect.length; i++) {
      if ($gameTemp.strEffect[i].disposed) {
        $gameTemp.strEffect[i] = null;
        continue;
      }
      $gameTemp.strEffect[i].update();
    }
    $gameTemp.strEffect = $gameTemp.strEffect.filter(function (window) {
      return window != null;
    });
  };

  var _Scene_Map_terminate = Scene_Map.prototype.terminate;
  Scene_Map.prototype.terminate = function () {
    $gameTemp.strEffect = [];
    $gameTemp.getInfoOccupied = [];
    _Scene_Map_terminate.call(this);
  };

  // -------------------------------------------------------------------------
  // Window_GetInfo
  //
  // The tiny window to display item gain/lose situation on map.

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

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

  Window_GetInfo.prototype.initialize = function (id, type, text, value) {
    Window_Base.prototype.initialize.call(this, -24, 0, 864, 105);
    this.disposed = false;
    // set opacities
    this.opacity = 0;
    this.backOpacity = 0;
    this.contentsOpacity = 0;
    // set count
    this.count = 0;
    // make room for new index
    this.index = $gameTemp.getInfoOccupied.indexOf(null);
    if (this.index === -1) {
      this.index = $gameTemp.getInfoOccupied.length;
    }
    $gameTemp.getInfoOccupied[this.index] = true;
    // set Y position
    if (yPosType == 0) {
      this.y = this.index * 60;
    } else {
      this.y = 520 - this.index * 60;
    }
    // draw and get item
    this.setup(id, type, text, value);
    // play SE
    switch (type) {
      case 0: // item
      case 1: // weapon
      case 2: // armor
        if (value >= 1) {
          // play when gain, not play when lose.
          if (seFilename) {
            var audio = {};
            audio.name = seFilename;
            audio.volume = seVolume;
            audio.pitch = sePitch;
            AudioManager.playSe(audio);
          }
        }
        break;
      default: // not supported
        break;
    }
  };

  Window_GetInfo.prototype.setup = function (id, type, text, value) {
    // determine item data
    var data = "";
    switch (type) {
      case 0:
        data = $dataItems[id];
        break;
      case 1:
        data = $dataWeapons[id];
        break;
      case 2:
        data = $dataArmors[id];
        break;
    }
    // check number (whether the party has the number of item to lose)
    if (type >= 0 && type <= 2) {
      if (value < 0) {
        if (-value > $gameParty.numItems(data)) {
          value = -$gameParty.numItems(data);
        }
      }
      if (value == 0) {
        return;
      }
    }
    // fill background
    this.contents.paintOpacity = 160;
    this.contents.fillRect(0, 21, 816, 36, "#000000");
    // draw item name, number, description
    if (type >= 0 && type <= 2) {
      this.contents.paintOpacity = 255;
      this.changeTextColor(this.normalColor());
      if (value < 0) {
        this.contents.paintOpacity = 160;
      }
      this.drawItemName(data, 6, 21, 300);
      this.drawText("\xd7", 306, 21, 24, "center");
      this.drawText(String(Math.abs(value)), 330, 21, 32, "right");
      this.drawText(this.description(data), 384, 21, 432, "left");
    }
    // draw guide string
    this.contents.paintOpacity = 160;
    this.contents.fontSize = 20;
    this.contents.fillRect(0, 0, this.textWidth(text) + 6, 22, "#000000");
    this.contents.paintOpacity = 255;
    this.changeTextColor(this.normalColor());
    this.drawText(text, 6, -8, 510, "left");
    // gain item
    if (type >= 0 && type <= 2) {
      $gameParty.gainItem(data, value);
    }
  };

  Window_GetInfo.prototype.description = function (data) {
    if (data.meta.info) {
      return data.meta.info;
    }
    return data.description.replace(/[\r\n]+.*/m, "");
  };

  Window_GetInfo.prototype.update = function () {
    Window_Base.prototype.update.call(this);
    if (++this.count < 180) {
      this.contentsOpacity += 32;
    } else {
      if (yPosType == 0) {
        this.y -= 2;
      } else {
        this.y += 2;
      }
      this.contentsOpacity -= 32;
      if (this.contentsOpacity == 0) {
        this.remove();
      }
    }
  };

  Window_GetInfo.prototype.remove = function () {
    $gameTemp.getInfoOccupied[this.index] = null;
    this.parent.removeChild(this);
    this.disposed = true;
  };

  //
  // interpreter commands
  // *** note *** : To prevent multiple exection of operateValue,
  // not to alias but overwriting functions.

  // Change Items
  Game_Interpreter.prototype.command126 = function () {
    var value = this.operateValue(
      this._params[1],
      this._params[2],
      this._params[3]
    );
    if (
      $gameSwitches.value(dispSwitchID) &&
      !$gameParty.inBattle() &&
      value != 0
    ) {
      var text = "";
      var spriteSet = SceneManager._scene._spriteset;
      if (value > 0) {
        text = textGainItem.format(TextManager.item);
      } else {
        text = textLoseItem.format(TextManager.item);
      }
      spriteSet.addGetInfoWindow(this._params[0], 0, text, value);
    } else {
      $gameParty.gainItem($dataItems[this._params[0]], value);
    }
    return true;
  };

  // Change Weapons
  Game_Interpreter.prototype.command127 = function () {
    var value = this.operateValue(
      this._params[1],
      this._params[2],
      this._params[3]
    );
    if (
      $gameSwitches.value(dispSwitchID) &&
      !$gameParty.inBattle() &&
      value != 0
    ) {
      var text = "";
      var spriteSet = SceneManager._scene._spriteset;
      if (value > 0) {
        text = textGainItem.format(TextManager.weapon);
      } else {
        text = textLoseItem.format(TextManager.weapon);
      }
      spriteSet.addGetInfoWindow(this._params[0], 1, text, value);
    } else {
      $gameParty.gainItem(
        $dataWeapons[this._params[0]],
        value,
        this._params[4]
      );
    }
    return true;
  };

  // Change Armors
  Game_Interpreter.prototype.command128 = function () {
    var value = this.operateValue(
      this._params[1],
      this._params[2],
      this._params[3]
    );
    if (
      $gameSwitches.value(dispSwitchID) &&
      !$gameParty.inBattle() &&
      value != 0
    ) {
      var text = "";
      var spriteSet = SceneManager._scene._spriteset;
      if (value > 0) {
        text = textGainItem.format(TextManager.armor);
      } else {
        text = textLoseItem.format(TextManager.armor);
      }
      spriteSet.addGetInfoWindow(this._params[0], 2, text, value);
    } else {
      $gameParty.gainItem($dataArmors[this._params[0]], value, this._params[4]);
    }
    return true;
  };
})();