/*:
 * @target MZ
 * @plugindesc [MZ] スイッチ783がONの間、ステート43〜48・66〜68由来の「スキル封印」を無効化 v1.0
 * @author You
 * @help
 * 概要:
 *  スイッチ783がONの間だけ、指定ステート(43〜48, 66〜68)に登録されている
 *  「スキル封印／スキルタイプ封印」特徴を無効化します。
 *  それ以外（装備・職業・クラス・敵など）に由来する封印は通常どおり有効です。
 *
 *  対象:
 *   - アクター／敵いずれにも適用（共通ロジック）
 *   - 戦闘中／メニューいずれでも有効
 *
 *  備考:
 *   - 既存の canUse 判定や MP/TP/ステート等の通常判定は維持します。
 *   - 「封印元が指定ステートのみ」の場合に限って封印を解除します。
 *     ほかの要因でも封印されていれば、封印は継続します。
 */

(() => {
  "use strict";

  // 解除対象とするステートID群（43〜48, 66〜68）
  const EXEMPT_STATE_IDS = new Set([43, 44, 45, 46, 47, 48, 66, 67, 68]);
  const SWITCH_ID = 783; // 有効化スイッチ

  // 指定ステートを traitObjects() から除外した配列を作る
  function traitObjectsExcludingExemptStates(battler) {
    const ex = EXEMPT_STATE_IDS;
    // traitObjects() はデータベース上のオブジェクト（Actor/Class/Equip/State/Enemy）を返す
    return battler.traitObjects().filter(obj => {
      // ステートオブジェクトは $dataStates[id] と === で一致する
      for (const sid of ex) {
        if (obj === $dataStates[sid]) return false; // 指定ステートは除外
      }
      return true;
    });
  }

  // 指定の trait コード／データID が、指定ステート「以外」から来ているかを判定
  function hasTraitOutsideExemptStates(battler, code, dataId) {
    const objs = traitObjectsExcludingExemptStates(battler);
    for (const obj of objs) {
      const traits = obj?.traits || [];
      if (traits.some(t => t.code === code && t.dataId === dataId)) {
        return true;
      }
    }
    return false;
  }

  // 元メソッド退避
  const _isSkillSealed = Game_BattlerBase.prototype.isSkillSealed;
  const _isSkillTypeSealed = Game_BattlerBase.prototype.isSkillTypeSealed;

  // スキル個別封印の上書き
  Game_BattlerBase.prototype.isSkillSealed = function(skillId) {
    // まず既存ロジックで封印か判定
    const sealed = _isSkillSealed.call(this, skillId);
    if (!sealed) return false;

    // スイッチがOFFなら従来どおり封印
    if (!$gameSwitches.value(SWITCH_ID)) return true;

    // 指定ステート「以外」から封印されているなら封印は維持
    const cs = Game_BattlerBase.TRAIT_SKILL_SEAL;
    if (hasTraitOutsideExemptStates(this, cs, skillId)) return true;

    // スキルタイプ封印経由で封印されている可能性にも対応
    const skill = $dataSkills[skillId];
    if (skill) {
      const cstype = Game_BattlerBase.TRAIT_STYPE_SEAL;
      if (hasTraitOutsideExemptStates(this, cstype, skill.stypeId)) return true;
    }

    // ここまで来たら、封印の出所は「指定ステートのみ」なので封印無効化
    return false;
  };

  // スキルタイプ封印の上書き
  Game_BattlerBase.prototype.isSkillTypeSealed = function(stypeId) {
    const sealed = _isSkillTypeSealed.call(this, stypeId);
    if (!sealed) return false;
    if (!$gameSwitches.value(SWITCH_ID)) return true;

    const cstype = Game_BattlerBase.TRAIT_STYPE_SEAL;
    // 指定ステート以外から封印されていれば維持、そうでなければ解除
    return hasTraitOutsideExemptStates(this, cstype, stypeId);
  };
})();
