UNPKG

isaacscript-common

Version:

Helper functions and features for IsaacScript mods.

129 lines (128 loc) 6.29 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CustomItemPools = void 0; const isaac_typescript_definitions_1 = require("isaac-typescript-definitions"); const decorators_1 = require("../../../decorators"); const ModCallbackCustom_1 = require("../../../enums/ModCallbackCustom"); const array_1 = require("../../../functions/array"); const map_1 = require("../../../functions/map"); const utils_1 = require("../../../functions/utils"); const weighted_1 = require("../../../functions/weighted"); const ReadonlyMap_1 = require("../../../types/ReadonlyMap"); const Feature_1 = require("../../private/Feature"); const v = { run: { customItemPools: new ReadonlyMap_1.ReadonlyMap(), }, }; const customItemPoolMap = new Map(); class CustomItemPools extends Feature_1.Feature { /** @internal */ v = v; /** @internal */ constructor() { super(); this.customCallbacksUsed = [ [ ModCallbackCustom_1.ModCallbackCustom.POST_GAME_STARTED_REORDERED, this.postGameStartedReorderedFalse, [false], ], ]; } // ModCallbackCustom.POST_GAME_STARTED_REORDERED // false postGameStartedReorderedFalse = () => { v.run.customItemPools = (0, map_1.copyMap)(customItemPoolMap); }; /** * Helper function to register a custom item pool. Use this function once when your mod first * loads to declare the items that you want to be in the item pools. Then, in the middle of a run, * you can use `getCustomItemPoolCollectible`. * * For example: * * ```ts * const ItemPoolTypeCustom = { * FOO = 0 as ItemPoolType, * } as const; * * const FOO_ITEM_POOL = [ * [CollectibleType.SAD_ONION, 1], * [CollectibleType.INNER_EYE, 0.5], * ]; * * registerCustomItemPool(ItemPoolTypeCustom.FOO, FOO_ITEM_POOL); * ``` * * Note that custom item pools do not currently support partial weight decrementation on sight. * * In order to use this function, you must upgrade your mod with `ISCFeature.CUSTOM_ITEM_POOLS`. * * @param itemPoolTypeCustom An integer that identifies what kind of item pool you are creating. * It should correspond to a local `ItemPoolTypeCustom` enum in your * mod. The integer can be any unique value and can safely overlap with * the vanilla item pool type values (or values chosen by other mods). * @param collectibles An array of weighted collectible tuples that represent the item pool that * you are creating. The first element in he tuple is the `CollectibleType`, * and the second element in the tuple is the float that represents the weight * of the collectible. * @public */ registerCustomItemPool(itemPoolTypeCustom, collectibles) { if (customItemPoolMap.has(itemPoolTypeCustom)) { error(`Failed to register a custom item pool since the provided type of ${itemPoolTypeCustom} was already registered.`); } customItemPoolMap.set(itemPoolTypeCustom, collectibles); } /** * Helper function to get a new collectible from a custom item pool created with the * `registerCustomItemPool` function. This function has the same format as the * `ItemPool.GetCollectible` method. * * By default, a collectible will not be removed from the pool once it is selected, unless the * `decrease` argument is set to true (similar to how a vanilla item pool works). * * If you want to get an unseeded collectible type, you must explicitly pass `undefined` to the * `seedOrRNG` parameter. * * In order to use this function, you must upgrade your mod with `ISCFeature.CUSTOM_ITEM_POOLS`. * * @param itemPoolTypeCustom An integer representing the custom item pool to use. * @param seedOrRNG The `Seed` or `RNG` object to use. If an `RNG` object is provided, the * `RNG.Next` method will be called. If `undefined` is provided, it will default * to a random seed. * @param decrease Optional. Whether to remove the selected collectible from the item pool. * Default is true. * @param defaultItem Optional. The collectible to return if the item pool is depleted. Default is * `CollectibleType.NULL`. * @public */ getCustomItemPoolCollectible(itemPoolTypeCustom, seedOrRNG, decrease = false, defaultItem = isaac_typescript_definitions_1.CollectibleType.NULL) { const customItemPool = v.run.customItemPools.get(itemPoolTypeCustom); (0, utils_1.assertDefined)(customItemPool, `Failed to find the custom item pool of: ${itemPoolTypeCustom}`); if (customItemPool.length === 0) { return defaultItem; } const randomIndex = (0, weighted_1.getRandomIndexFromWeightedArray)(customItemPool, seedOrRNG); const tuple = customItemPool[randomIndex]; (0, utils_1.assertDefined)(tuple, `Failed to get an element from a custom item pool using a random index of: ${randomIndex}`); if (decrease) { (0, array_1.arrayRemoveIndexInPlace)(customItemPool, randomIndex); } return tuple[0]; } } exports.CustomItemPools = CustomItemPools; __decorate([ decorators_1.Exported ], CustomItemPools.prototype, "registerCustomItemPool", null); __decorate([ decorators_1.Exported ], CustomItemPools.prototype, "getCustomItemPoolCollectible", null);