// DarkPlasma_TYA_SymbolEncount 3.1.0
// Copyright (c) 2020 DarkPlasma

/**
 * 2022/03/22 3.1.0 敵シンボル判定を拡張プラグインへ移譲
 * 2021/12/11 3.0.1 先制時、一定確率で何もせずに1ターン経過してしまう不具合を修正
 * 2021/11/20 3.0.0 Again用に調整
 * 2020/09/08 2.0.0 パラメータ名を変更
 * 2020/09/06 1.0.0 初回
 */

/*:ja
 * @plugindesc シンボルエンカウント作成の補助
 * @author 茶の助, DarkPlasma
 * @license No License
 *
 * @target MZ
 *
 * @param situationVariables
 * @desc 敵接触時に接触した向きによって値を変える変数。通常:0 先制:1 不意打ち:2
 * @text 状況変数
 * @type variable
 * @default 1
 *
 * @param enableSurpriseAttack
 * @desc イベント戦闘（シンボルエンカウント含む）における先制攻撃/不意打ちを有効にする
 * @text 先制/不意打ち有効
 * @type boolean
 * @default true
 *
 * @param preemptiveRate
 * @desc 背後をとった際の先制攻撃率（％）
 * @text 先制攻撃率（％）
 * @type number
 * @default 100
 *
 * @param surpriseRate
 * @desc 背後をとられた際の不意打ち率（％）
 * @text 不意打ち率（％）
 * @type number
 * @default 100
 *
 * @help
 * version: 3.1.0
 * 特定タグがついたイベントとのシンボルエンカウント時の先制・不意打ちを制御します。
 * タグについては、拡張プラグインを参照してください。
 *
 * ■プレイヤーとそのイベントの向きに応じて、
 * 先制攻撃・不意打ちが起こるようになります。
 * 設定した変数に数値が代入され、
 * 0の場合は通常、1の場合は先制攻撃、2の場合は不意打ちになります。
 * 変数は戦闘後にリセットされます。
 */

(() => {
  'use strict';

  const pluginName = document.currentScript.src.replace(/^.*\/(.*).js$/, function () {
    return arguments[1];
  });

  const pluginParameters = PluginManager.parameters(pluginName);

  const settings = {
    situationVariables: Number(pluginParameters.situationVariables || 1),
    enableSurpriseAttack: String(pluginParameters.enableSurpriseAttack || true) === 'true',
    preemptiveRate: Number(pluginParameters.preemptiveRate || 100),
    surpriseRate: Number(pluginParameters.surpriseRate || 100),
  };

  const _BattleManager_onEncounter = BattleManager.onEncounter;
  BattleManager.onEncounter = function () {
    _BattleManager_onEncounter.call(this);

    if (settings.enableSurpriseAttack) {
      switch ($gameVariables.value(settings.situationVariables)) {
        case 0:
          this._preemptive = false;
          this._surprise = false;
          break;
        case 1:
          this._preemptive = true;
          this._surprise = false;
          break;
        case 2:
          this._preemptive = false;
          this._surprise = true;
          break;
      }
    }
  };

  /**
   * 戦闘開始状況
   */
  const ENCOUNTER_SITUATION = {
    DEFAULT: 0, // 何もなし
    PREEMPTIVE: 1, // プレイヤーの先制攻撃
    SURPRISE: 2, // 敵による不意打ち
  };

  /**
   * @param {Game_Event.prototype} gameEvent
   */
  function Game_Event_SymbolEncounterMixIn(gameEvent) {
    /**
     * プレイヤーの前方にいるかどうか
     * シンボルがプレイヤーの前方にいれば、プレイヤー側が先制攻撃する
     * @return {boolean}
     */
    gameEvent.isAheadOfPlayer = function () {
      switch (this._direction) {
        case 2: // 下向き
          return $gamePlayer.y <= this.y;
        case 8: // 上向き
          return $gamePlayer.y >= this.y;
        case 4: // 左向き
          return $gamePlayer.x >= this.x;
        case 6: // 右向き
          return $gamePlayer.x <= this.x;
        default:
          // 不明な状態（本来ここには来ないが、一応偽とする）
          return false;
      }
    };

    /**
     * プレイヤーとの位置関係、向きに応じて先制or不意打ち状況セット
     */
    gameEvent.encounterSituation = function () {
      if ($gamePlayer.direction() === this._direction) {
        if (this.isAheadOfPlayer()) {
          if (Math.randomInt(100) < settings.preemptiveRate) {
            $gameVariables.setValue(settings.situationVariables, ENCOUNTER_SITUATION.PREEMPTIVE);
          }
        } else {
          if (Math.randomInt(100) < settings.surpriseRate) {
            $gameVariables.setValue(settings.situationVariables, ENCOUNTER_SITUATION.SURPRISE);
          }
        }
      } else {
        $gameVariables.setValue(settings.situationVariables, ENCOUNTER_SITUATION.DEFAULT);
      }
    };

    /**
     * シンボル敵であるかどうか（拡張プラグインで上書きする）
     * @return {boolean}
     */
    gameEvent.isSymbolEnemy = function () {
      return false;
    };

    /**
     * 先制判定のため、上書き
     */
    gameEvent.lock = function () {
      if (!this._locked) {
        if (this.isSymbolEnemy()) {
          this.encounterSituation();
        }
        this._prelockDirection = this.direction();
        if (!this.isSymbolEnemy()) {
          this.turnTowardPlayer();
        }
        this._locked = true;
      }
    };
  }

  Game_Event_SymbolEncounterMixIn(Game_Event.prototype);

  /**
   * 戦闘の処理
   * イベントの戦闘の処理では本来、先制不意打ち判定が行われない
   * onEncounterで判定を挟むため、まるごと上書きする
   * @param {array} params パラメータ
   */
  Game_Interpreter.prototype.command301 = function (params) {
    if (!$gameParty.inBattle()) {
      let troopId;
      if (params[0] === 0) {
        // Direct designation
        troopId = params[1];
      } else if (params[0] === 1) {
        // Designation with a variable
        troopId = $gameVariables.value(params[1]);
      } else {
        // Same as Random Encounter
        troopId = $gamePlayer.makeEncounterTroopId();
      }
      if ($dataTroops[troopId]) {
        BattleManager.setup(troopId, params[2], params[3]);
        BattleManager.onEncounter();
        BattleManager.setEventCallback(
          function (n) {
            this._branch[this._indent] = n;
          }.bind(this)
        );
        $gamePlayer.makeEncounterCount();
        SceneManager.push(Scene_Battle);
      }
    }
    return true;
  };

  const _Scene_Battle_prototype_terminate = Scene_Battle.prototype.terminate;
  Scene_Battle.prototype.terminate = function () {
    _Scene_Battle_prototype_terminate.call(this);
    $gameVariables.setValue(settings.situationVariables, 0);
  };
})();
