
/*:
 * @target MZ
 * @plugindesc 変数に上限・下限を設定できるプラグイン（範囲対応版）★VariableLimiterRange.js
 * @author ChatGPT
 * 
 * @help
 * ◆概要：
 * 指定した「変数IDの範囲」に対して、上限・下限を一括で設定します。
 * 従来の個別指定も併用可能です。
 * 
 * ◆使い方：
 * 1. プラグインパラメータで「個別制限リスト」または「範囲制限リスト」を設定します。
 * 2. ゲーム中にその変数が変更されると、自動で上限・下限が適用されます。
 * 
 * ◆注意：
 * - 個別設定がある場合は個別設定が優先されます。
 * - 上限・下限のどちらかだけでも設定可能です。
 *
 * @param Limits
 * @text 個別制限リスト
 * @type struct<Limit>[]
 * @desc 各変数に設定する最大・最小値のリストです
 *
 * @param RangeLimits
 * @text 範囲制限リスト
 * @type struct<RangeLimit>[]
 * @desc 変数IDの範囲ごとに最大・最小値を一括設定できます
 */

/*~struct~Limit:
 * @param VariableID
 * @text 変数ID
 * @type variable
 * @desc 対象となる変数ID
 *
 * @param MaxValue
 * @text 最大値
 * @type number
 * @min -9999999
 * @max 9999999
 * @desc この変数の最大値（未設定で制限なし）
 *
 * @param MinValue
 * @text 最小値
 * @type number
 * @min -9999999
 * @max 9999999
 * @desc この変数の最小値（未設定で制限なし）
 */

/*~struct~RangeLimit:
 * @param StartID
 * @text 開始ID
 * @type variable
 * @desc 範囲の開始となる変数ID
 *
 * @param EndID
 * @text 終了ID
 * @type variable
 * @desc 範囲の終了となる変数ID
 *
 * @param MaxValue
 * @text 最大値
 * @type number
 * @min -9999999
 * @max 9999999
 * @desc この範囲の変数に設定する最大値（未設定で制限なし）
 *
 * @param MinValue
 * @text 最小値
 * @type number
 * @min -9999999
 * @max 9999999
 * @desc この範囲の変数に設定する最小値（未設定で制限なし）
 */

(() => {
    const pluginName = "VariableLimiterRange";
    const parameters = PluginManager.parameters(pluginName);

    const limitListRaw = JSON.parse(parameters["Limits"] || "[]");
    const rangeListRaw = JSON.parse(parameters["RangeLimits"] || "[]");

    /** 変数IDごとの制限を格納するオブジェクト */
    const variableLimits = {};

    // 個別指定の読み込み
    for (const entryRaw of limitListRaw) {
        const entry = JSON.parse(entryRaw);
        const varId = Number(entry.VariableID);
        if (!varId) continue;

        const max = entry.MaxValue !== "" ? Number(entry.MaxValue) : undefined;
        const min = entry.MinValue !== "" ? Number(entry.MinValue) : undefined;

        variableLimits[varId] = { max, min };
    }

    // 範囲指定の読み込み
    for (const entryRaw of rangeListRaw) {
        const entry = JSON.parse(entryRaw);
        const start = Number(entry.StartID);
        const end = Number(entry.EndID);
        if (!start || !end) continue;

        const max = entry.MaxValue !== "" ? Number(entry.MaxValue) : undefined;
        const min = entry.MinValue !== "" ? Number(entry.MinValue) : undefined;

        for (let i = start; i <= end; i++) {
            // 個別指定がある場合はそちらを優先
            if (!variableLimits[i]) {
                variableLimits[i] = { max, min };
            }
        }
    }

    // setValue をフックして制限を適用
    const _Game_Variables_setValue = Game_Variables.prototype.setValue;
    Game_Variables.prototype.setValue = function(variableId, value) {
        const limit = variableLimits[variableId];
        if (limit) {
            if (limit.max !== undefined) {
                value = Math.min(value, limit.max);
            }
            if (limit.min !== undefined) {
                value = Math.max(value, limit.min);
            }
        }
        _Game_Variables_setValue.call(this, variableId, value);
    };
})();
