isaacscript-common 16.1.7 → 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/index.d.ts +191 -49
  2. package/dist/isaacscript-common.lua +517 -508
  3. package/dist/src/classes/ModUpgradedBase.d.ts +3 -1
  4. package/dist/src/classes/ModUpgradedBase.d.ts.map +1 -1
  5. package/dist/src/classes/ModUpgradedBase.lua +16 -8
  6. package/dist/src/classes/features/other/ModdedElementSets.d.ts +172 -5
  7. package/dist/src/classes/features/other/ModdedElementSets.d.ts.map +1 -1
  8. package/dist/src/classes/features/other/ModdedElementSets.lua +161 -5
  9. package/dist/src/classes/features/other/Pause.d.ts +1 -0
  10. package/dist/src/classes/features/other/Pause.d.ts.map +1 -1
  11. package/dist/src/classes/features/other/Pause.lua +5 -1
  12. package/dist/src/core/constants.d.ts +3 -1
  13. package/dist/src/core/constants.d.ts.map +1 -1
  14. package/dist/src/core/constants.lua +6 -0
  15. package/dist/src/core/upgradeMod.d.ts.map +1 -1
  16. package/dist/src/core/upgradeMod.lua +7 -0
  17. package/dist/src/functions/cards.d.ts +7 -34
  18. package/dist/src/functions/cards.d.ts.map +1 -1
  19. package/dist/src/functions/cards.lua +20 -119
  20. package/dist/src/functions/globals.d.ts.map +1 -1
  21. package/dist/src/functions/globals.lua +0 -1
  22. package/dist/src/functions/positionVelocity.d.ts.map +1 -1
  23. package/dist/src/functions/positionVelocity.lua +5 -5
  24. package/package.json +2 -2
  25. package/src/classes/ModUpgradedBase.ts +24 -9
  26. package/src/classes/features/other/ModdedElementSets.ts +346 -5
  27. package/src/classes/features/other/Pause.ts +5 -0
  28. package/src/core/constants.ts +9 -0
  29. package/src/core/upgradeMod.ts +10 -0
  30. package/src/functions/cards.ts +20 -139
  31. package/src/functions/globals.ts +0 -1
  32. package/src/functions/positionVelocity.ts +1 -7
  33. package/dist/src/objects/cardTypeToItemConfigCardType.d.ts +0 -6
  34. package/dist/src/objects/cardTypeToItemConfigCardType.d.ts.map +0 -1
  35. package/dist/src/objects/cardTypeToItemConfigCardType.lua +0 -106
  36. package/src/objects/cardTypeToItemConfigCardType.ts +0 -106
@@ -142,7 +142,6 @@ local DEFAULT_GLOBALS = __TS__New(Set, {
142
142
  "SackSubType",
143
143
  "SeedEffect",
144
144
  "Seeds",
145
- "ShockwaveParams",
146
145
  "SkinColor",
147
146
  "SortingLayer",
148
147
  "SoundEffect",
@@ -1 +1 @@
1
- {"version":3,"file":"positionVelocity.d.ts","sourceRoot":"","sources":["../../../src/functions/positionVelocity.ts"],"names":[],"mappings":";;;;AAaA,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,GAAG,GACZ,OAAO,CAIT;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,KAAK,GACd,OAAO,CAKT;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,gBAAgB,EAAE,MAAM,EACxB,mBAAmB,UAAQ,EAC3B,eAAe,CAAC,EAAE,KAAK,GACtB,MAAM,CA8CR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAY5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAY7E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,eAAe,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,IAAI,CAYN;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EACtC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,IAAI,CAYN"}
1
+ {"version":3,"file":"positionVelocity.d.ts","sourceRoot":"","sources":["../../../src/functions/positionVelocity.ts"],"names":[],"mappings":";;;;AAaA,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,GAAG,GACZ,OAAO,CAIT;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,KAAK,GACd,OAAO,CAKT;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,gBAAgB,EAAE,MAAM,EACxB,mBAAmB,UAAQ,EAC3B,eAAe,CAAC,EAAE,KAAK,GACtB,MAAM,CA4CR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAY5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAY7E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,eAAe,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,IAAI,CAYN;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EACtC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,IAAI,CAYN"}
@@ -54,11 +54,11 @@ function ____exports.findFreePosition(self, startingPosition, avoidActiveEntitie
54
54
  local room = game:GetRoom()
55
55
  local heavenDoors = getEffects(nil, EffectVariant.HEAVEN_LIGHT_DOOR, HeavenLightDoorSubType.HEAVEN_DOOR)
56
56
  do
57
- local i = 0
58
- while i < MAX_FIND_FREE_POSITION_ATTEMPTS do
57
+ local initialStep = 0
58
+ while initialStep < MAX_FIND_FREE_POSITION_ATTEMPTS do
59
59
  do
60
- local position = room:FindFreePickupSpawnPosition(startingPosition, i, avoidActiveEntities)
61
- local closePlayer = getPlayerCloserThan(nil, position, DISTANCE_OF_GRID_TILE * 1.5)
60
+ local position = room:FindFreePickupSpawnPosition(startingPosition, initialStep, avoidActiveEntities)
61
+ local closePlayer = getPlayerCloserThan(nil, position, DISTANCE_OF_GRID_TILE)
62
62
  if closePlayer ~= nil then
63
63
  goto __continue7
64
64
  end
@@ -75,7 +75,7 @@ function ____exports.findFreePosition(self, startingPosition, avoidActiveEntitie
75
75
  return position
76
76
  end
77
77
  ::__continue7::
78
- i = i + 1
78
+ initialStep = initialStep + 1
79
79
  end
80
80
  end
81
81
  return room:FindFreePickupSpawnPosition(startingPosition)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "16.1.7",
3
+ "version": "17.0.0",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -22,6 +22,6 @@
22
22
  "main": "dist/src/index",
23
23
  "types": "dist/src/index.d.ts",
24
24
  "dependencies": {
25
- "isaac-typescript-definitions": "^9.5.2"
25
+ "isaac-typescript-definitions": "^10.0.3"
26
26
  }
27
27
  }
@@ -1,4 +1,5 @@
1
1
  import { ModCallback } from "isaac-typescript-definitions";
2
+ import { CallbackPriority } from "isaac-typescript-definitions/dist/src/enums/CallbackPriority";
2
3
  import { getCallbacks } from "../callbacks";
3
4
  import { EXPORTED_METHOD_NAMES_KEY } from "../decorators";
4
5
  import { ISCFeature } from "../enums/ISCFeature";
@@ -73,16 +74,27 @@ export class ModUpgradedBase implements Mod {
73
74
  * `ModCallback.POST_UPDATE` event corresponds to being executed once at the end of every game
74
75
  * logic frame.
75
76
  */
76
- public AddCallback<T extends ModCallback>(
77
+ public AddCallback<T extends ModCallback | string>(
77
78
  modCallback: T,
78
- ...args: AddCallbackParameters[T]
79
+ ...args: T extends ModCallback ? AddCallbackParameters[T] : unknown[]
80
+ ): void {
81
+ this.AddPriorityCallback(modCallback, CallbackPriority.DEFAULT, ...args);
82
+ }
83
+
84
+ public AddPriorityCallback<T extends ModCallback | string>(
85
+ modCallback: T,
86
+ priority: CallbackPriority | int,
87
+ ...args: T extends ModCallback ? AddCallbackParameters[T] : unknown[]
79
88
  ): void {
80
89
  if (this.debug) {
81
90
  const callback = args[0];
82
91
  const optionalArg = args[1];
83
92
 
84
93
  const parentFunctionDescription = getParentFunctionDescription();
85
- const callbackName = `ModCallback.${ModCallback[modCallback]}`;
94
+ const customCallback = type(modCallback) === "string";
95
+ const callbackName = customCallback
96
+ ? `${modCallback} (custom callback)`
97
+ : `ModCallback.${ModCallback[modCallback as ModCallback]}`;
86
98
  const signature =
87
99
  parentFunctionDescription === undefined
88
100
  ? callbackName
@@ -93,6 +105,8 @@ export class ModUpgradedBase implements Mod {
93
105
  * prefix.
94
106
  */
95
107
  const callbackWithLogger: typeof callback = (
108
+ // @ts-expect-error The compiler is not smart enough to know that the callback args should
109
+ // match the callback.
96
110
  ...callbackArgs: Parameters<typeof callback>
97
111
  ) => {
98
112
  const startTime = getTime();
@@ -100,6 +114,7 @@ export class ModUpgradedBase implements Mod {
100
114
 
101
115
  // @ts-expect-error The compiler is not smart enough to know that the callback args should
102
116
  // match the callback.
117
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
103
118
  const returnValue = callback(...callbackArgs);
104
119
 
105
120
  const endTime = getTime();
@@ -113,16 +128,16 @@ export class ModUpgradedBase implements Mod {
113
128
  Isaac.DebugString(`${signature} - END`);
114
129
  }
115
130
 
131
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
116
132
  return returnValue;
117
133
  };
118
134
 
119
- const newArgs = [
120
- callbackWithLogger,
121
- optionalArg,
122
- ] as unknown as AddCallbackParameters[T];
123
- this.mod.AddCallback(modCallback, ...newArgs);
135
+ const newArgs = [callbackWithLogger, optionalArg];
136
+ // @ts-expect-error The compiler is not smart enough to know that the callback args should
137
+ // match the callback.
138
+ this.mod.AddPriorityCallback(modCallback, priority, ...newArgs);
124
139
  } else {
125
- this.mod.AddCallback(modCallback, ...args);
140
+ this.mod.AddPriorityCallback(modCallback, priority, ...args);
126
141
  }
127
142
  }
128
143
 
@@ -1,14 +1,23 @@
1
1
  import {
2
2
  CacheFlag,
3
+ CardType,
3
4
  CollectibleType,
5
+ ItemConfigCardType,
4
6
  ItemConfigTag,
5
7
  PlayerForm,
6
8
  TrinketType,
7
9
  } from "isaac-typescript-definitions";
8
10
  import { itemConfig } from "../../../core/cachedClasses";
9
- import { FIRST_GLITCHED_COLLECTIBLE_TYPE } from "../../../core/constants";
11
+ import {
12
+ FIRST_GLITCHED_COLLECTIBLE_TYPE,
13
+ ITEM_CONFIG_CARD_TYPES_FOR_CARDS,
14
+ } from "../../../core/constants";
10
15
  import { Exported } from "../../../decorators";
11
16
  import { ISCFeature } from "../../../enums/ISCFeature";
17
+ import {
18
+ getItemConfigCardType,
19
+ getVanillaCardTypes,
20
+ } from "../../../functions/cards";
12
21
  import {
13
22
  collectibleHasCacheFlag,
14
23
  getVanillaCollectibleTypeRange,
@@ -78,6 +87,15 @@ export class ModdedElementSets extends Feature {
78
87
  private moddedTrinketTypesArray: TrinketType[] = [];
79
88
  private moddedTrinketTypesSet = new Set<TrinketType>();
80
89
 
90
+ private allCardTypesArray: CardType[] = [];
91
+ private allCardTypesSet = new Set<CardType>();
92
+
93
+ private vanillaCardTypesArray: CardType[] = [];
94
+ private vanillaCardTypesSet = new Set<CardType>();
95
+
96
+ private moddedCardTypesArray: CardType[] = [];
97
+ private moddedCardTypesSet = new Set<CardType>();
98
+
81
99
  private tagToCollectibleTypesMap = new Map<
82
100
  ItemConfigTag,
83
101
  Set<CollectibleType>
@@ -97,6 +115,19 @@ export class ModdedElementSets extends Feature {
97
115
  private edenActiveCollectibleTypesSet = new Set<CollectibleType>();
98
116
  private edenPassiveCollectibleTypesSet = new Set<CollectibleType>();
99
117
 
118
+ private itemConfigCardTypeToCardTypeMap = new Map<
119
+ ItemConfigCardType,
120
+ Set<CardType>
121
+ >();
122
+
123
+ /**
124
+ * The set of cards that are not:
125
+ *
126
+ * - ItemConfigCardType.RUNE
127
+ * - ItemConfigCardType.SPECIAL_OBJECT
128
+ */
129
+ private cardSet = new Set<CardType>();
130
+
100
131
  private moddedElementDetection: ModdedElementDetection;
101
132
 
102
133
  /** @internal */
@@ -196,6 +227,49 @@ export class ModdedElementSets extends Feature {
196
227
  }
197
228
  }
198
229
 
230
+ private lazyInitVanillaCardTypes() {
231
+ if (this.vanillaCardTypesArray.length > 0) {
232
+ return;
233
+ }
234
+
235
+ const vanillaCardTypes = getVanillaCardTypes();
236
+ for (const cardType of vanillaCardTypes) {
237
+ // Vanilla card types are contiguous, but we check every value just to be safe (and so that
238
+ // the code is similar to the collectible and trinket functions above).
239
+ const itemConfigCard = itemConfig.GetCard(cardType);
240
+ if (itemConfigCard !== undefined) {
241
+ this.vanillaCardTypesArray.push(cardType);
242
+ this.vanillaCardTypesSet.add(cardType);
243
+ }
244
+ }
245
+ }
246
+
247
+ private lazyInitModdedCardTypes() {
248
+ if (this.moddedCardTypesArray.length > 0) {
249
+ return;
250
+ }
251
+
252
+ this.lazyInitVanillaCardTypes();
253
+
254
+ for (const cardType of this.vanillaCardTypesArray) {
255
+ this.allCardTypesArray.push(cardType);
256
+ this.allCardTypesSet.add(cardType);
257
+ }
258
+
259
+ const moddedCardTypes = this.moddedElementDetection.getModdedCardTypes();
260
+ for (const cardType of moddedCardTypes) {
261
+ // Modded card types are contiguous, but we check every value just in case.
262
+ const itemConfigCard = itemConfig.GetCard(cardType);
263
+ if (itemConfigCard !== undefined) {
264
+ this.moddedCardTypesArray.push(cardType);
265
+ this.moddedCardTypesSet.add(cardType);
266
+
267
+ this.allCardTypesArray.push(cardType);
268
+ this.allCardTypesSet.add(cardType);
269
+ }
270
+ }
271
+ }
272
+
199
273
  private lazyInitTagToCollectibleTypesMap() {
200
274
  if (this.tagToCollectibleTypesMap.size > 0) {
201
275
  return;
@@ -337,6 +411,114 @@ export class ModdedElementSets extends Feature {
337
411
  }
338
412
  }
339
413
 
414
+ private lazyInitCardTypes() {
415
+ if (this.itemConfigCardTypeToCardTypeMap.size > 0) {
416
+ return;
417
+ }
418
+
419
+ // The card type to cards map should be valid for every card type, so we initialize it with
420
+ // empty sets.
421
+ for (const itemConfigCardType of getEnumValues(ItemConfigCardType)) {
422
+ this.itemConfigCardTypeToCardTypeMap.set(
423
+ itemConfigCardType,
424
+ new Set<CardType>(),
425
+ );
426
+ }
427
+
428
+ for (const cardType of this.getCardArray()) {
429
+ const itemConfigCardType = getItemConfigCardType(cardType);
430
+ if (itemConfigCardType !== undefined) {
431
+ const cardTypeSet =
432
+ this.itemConfigCardTypeToCardTypeMap.get(itemConfigCardType);
433
+ if (cardTypeSet === undefined) {
434
+ error(
435
+ `Failed to get the card set for item config card type: ${itemConfigCardType}`,
436
+ );
437
+ }
438
+ cardTypeSet.add(cardType);
439
+
440
+ if (ITEM_CONFIG_CARD_TYPES_FOR_CARDS.has(itemConfigCardType)) {
441
+ this.cardSet.add(cardType);
442
+ }
443
+ }
444
+ }
445
+ }
446
+
447
+ // --------------
448
+ // Public Methods
449
+ // --------------
450
+
451
+ /**
452
+ * Returns an array containing every valid card type in the game, including modded cards.
453
+ *
454
+ * Use this if you need to iterate over the cards in order. If you need to do O(1) lookups, then
455
+ * use the `getCardSet` helper function instead.
456
+ *
457
+ * This function can only be called if at least one callback has been executed. This is because
458
+ * not all cards will necessarily be present when a mod first loads (due to mod load order).
459
+ *
460
+ * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
461
+ */
462
+ @Exported
463
+ public getCardArray(): readonly CardType[] {
464
+ this.lazyInitModdedCardTypes();
465
+ return this.allCardTypesArray;
466
+ }
467
+
468
+ /**
469
+ * Returns a set containing every valid card type in the game, including modded cards.
470
+ *
471
+ * Use this if you need to do O(1) lookups. If you need to iterate over the cards in order, then
472
+ * use the `getCardArray` helper function instead.
473
+ *
474
+ * This function can only be called if at least one callback has been executed. This is because
475
+ * not all cards will necessarily be present when a mod first loads (due to mod load order).
476
+ *
477
+ * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
478
+ */
479
+ @Exported
480
+ public getCardSet(): ReadonlySet<CardType> {
481
+ this.lazyInitModdedCardTypes();
482
+ return this.allCardTypesSet;
483
+ }
484
+
485
+ /**
486
+ * Helper function to get a set of card types matching the `ItemConfigCardType`.
487
+ *
488
+ * This function is variadic, meaning that you can you can specify N card types to get a set
489
+ * containing cards that match any of the specified types.
490
+ *
491
+ * This function can only be called if at least one callback has been executed. This is because
492
+ * not all cards will necessarily be present when a mod first loads (due to mod load order).
493
+ *
494
+ * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
495
+ */
496
+ @Exported
497
+ public getCardTypesOfType(
498
+ ...itemConfigCardTypes: ItemConfigCardType[]
499
+ ): Set<CardType> {
500
+ if (this.itemConfigCardTypeToCardTypeMap.size === 0) {
501
+ this.lazyInitCardTypes();
502
+ }
503
+
504
+ const matchingCardTypes = new Set<CardType>();
505
+ for (const itemConfigCardType of itemConfigCardTypes) {
506
+ const cardTypeSet =
507
+ this.itemConfigCardTypeToCardTypeMap.get(itemConfigCardType);
508
+ if (cardTypeSet === undefined) {
509
+ error(
510
+ `Failed to get the card type set for item config type: ${itemConfigCardType}`,
511
+ );
512
+ }
513
+
514
+ for (const cardType of cardTypeSet.values()) {
515
+ matchingCardTypes.add(cardType);
516
+ }
517
+ }
518
+
519
+ return matchingCardTypes;
520
+ }
521
+
340
522
  /**
341
523
  * Returns an array containing every valid collectible type in the game, including modded
342
524
  * collectibles.
@@ -385,6 +567,10 @@ export class ModdedElementSets extends Feature {
385
567
  * const guppyCollectibleTypes = getCollectiblesForTransformation(PlayerForm.GUPPY);
386
568
  * ```
387
569
  *
570
+ * This function can only be called if at least one callback has been executed. This is because
571
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
572
+ * order).
573
+ *
388
574
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
389
575
  */
390
576
  @Exported
@@ -409,6 +595,10 @@ export class ModdedElementSets extends Feature {
409
595
  * not all collectibles will necessarily be present when a mod first loads (due to mod load
410
596
  * order).
411
597
  *
598
+ * This function can only be called if at least one callback has been executed. This is because
599
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
600
+ * order).
601
+ *
412
602
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
413
603
  */
414
604
  @Exported
@@ -435,6 +625,10 @@ export class ModdedElementSets extends Feature {
435
625
  * const offensiveCollectibleTypes = getCollectibleTypesWithTag(ItemConfigTag.OFFENSIVE);
436
626
  * ```
437
627
  *
628
+ * This function can only be called if at least one callback has been executed. This is because
629
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
630
+ * order).
631
+ *
438
632
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
439
633
  */
440
634
  @Exported
@@ -457,6 +651,10 @@ export class ModdedElementSets extends Feature {
457
651
  * Returns a set containing every valid passive item that can be randomly granted to Eden as a
458
652
  * starting item.
459
653
  *
654
+ * This function can only be called if at least one callback has been executed. This is because
655
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
656
+ * order).
657
+ *
460
658
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
461
659
  */
462
660
  @Exported
@@ -469,6 +667,10 @@ export class ModdedElementSets extends Feature {
469
667
  * Returns a set containing every valid passive item that can be randomly granted to Eden as a
470
668
  * starting item.
471
669
  *
670
+ * This function can only be called if at least one callback has been executed. This is because
671
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
672
+ * order).
673
+ *
472
674
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
473
675
  */
474
676
  @Exported
@@ -484,6 +686,10 @@ export class ModdedElementSets extends Feature {
484
686
  * Collectibles that only grant flight conditionally are manually pruned. Collectibles such as
485
687
  * Empty Vessel should be checked for via the `hasFlyingTemporaryEffect` function.
486
688
  *
689
+ * This function can only be called if at least one callback has been executed. This is because
690
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
691
+ * order).
692
+ *
487
693
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
488
694
  *
489
695
  * @param pruneConditionalItems Whether or not collectibles that only grant flight conditionally
@@ -504,6 +710,9 @@ export class ModdedElementSets extends Feature {
504
710
  * Returns a set of all of the trinkets that grant flight. (All trinkets that grant flight do so
505
711
  * conditionally, like Bat Wing and Azazel's Stump.)
506
712
  *
713
+ * This function can only be called if at least one callback has been executed. This is because
714
+ * not all trinkets will necessarily be present when a mod first loads (due to mod load order).
715
+ *
507
716
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
508
717
  */
509
718
  @Exported
@@ -513,6 +722,40 @@ export class ModdedElementSets extends Feature {
513
722
  return this.flyingTrinketTypesSet;
514
723
  }
515
724
 
725
+ /**
726
+ * Returns an array containing every modded card type in the game.
727
+ *
728
+ * Use this if you need to iterate over the cards in order. If you need to do O(1) lookups, then
729
+ * use the `getModdedCardSet` helper function instead.
730
+ *
731
+ * This function can only be called if at least one callback has been executed. This is because
732
+ * not all cards will necessarily be present when a mod first loads (due to mod load order).
733
+ *
734
+ * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
735
+ */
736
+ @Exported
737
+ public getModdedCardArray(): readonly CardType[] {
738
+ this.lazyInitModdedCardTypes();
739
+ return this.moddedCardTypesArray;
740
+ }
741
+
742
+ /**
743
+ * Returns a set containing every modded card type in the game.
744
+ *
745
+ * Use this if you need to do O(1) lookups. If you need to iterate over the cards in order, then
746
+ * use the `getModdedCardArray` helper function instead.
747
+ *
748
+ * This function can only be called if at least one callback has been executed. This is because
749
+ * not all cards will necessarily be present when a mod first loads (due to mod load order).
750
+ *
751
+ * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
752
+ */
753
+ @Exported
754
+ public getModdedCardSet(): ReadonlySet<CardType> {
755
+ this.lazyInitModdedCardTypes();
756
+ return this.moddedCardTypesSet;
757
+ }
758
+
516
759
  /**
517
760
  * Returns an array containing every modded collectible type in the game.
518
761
  *
@@ -550,10 +793,10 @@ export class ModdedElementSets extends Feature {
550
793
  }
551
794
 
552
795
  /**
553
- * Returns an array containing every valid trinket type in the game, including modded trinkets.
796
+ * Returns an array containing every modded trinket type in the game.
554
797
  *
555
798
  * Use this if you need to iterate over the trinkets in order. If you need to do O(1) lookups,
556
- * then use the `getTrinketSet` helper function instead.
799
+ * then use the `getModdedTrinketSet` helper function instead.
557
800
  *
558
801
  * This function can only be called if at least one callback has been executed. This is because
559
802
  * not all trinkets will necessarily be present when a mod first loads (due to mod load order).
@@ -567,10 +810,10 @@ export class ModdedElementSets extends Feature {
567
810
  }
568
811
 
569
812
  /**
570
- * Returns a set containing every valid trinket type in the game, including modded trinkets.
813
+ * Returns a set containing every modded trinket type in the game.
571
814
  *
572
815
  * Use this if you need to do O(1) lookups. If you need to iterate over the trinkets in order,
573
- * then use the `getTrinketArray` helper function instead.
816
+ * then use the `getModdedTrinketArray` helper function instead.
574
817
  *
575
818
  * This function can only be called if at least one callback has been executed. This is because
576
819
  * not all trinkets will necessarily be present when a mod first loads (due to mod load order).
@@ -754,10 +997,72 @@ export class ModdedElementSets extends Feature {
754
997
  return playerTrinkets;
755
998
  }
756
999
 
1000
+ /**
1001
+ * Has an equal chance of returning any card (e.g. Fool, Reverse Fool, Wild Card, etc.).
1002
+ *
1003
+ * This will not return:
1004
+ * - any runes
1005
+ * - any objects like Dice Shard
1006
+ *
1007
+ * @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided,
1008
+ * the `RNG.Next` method will be called. Default is `getRandomSeed()`.
1009
+ * @param exceptions Optional. An array of cards to not select.
1010
+ */
1011
+ @Exported
1012
+ public getRandomCard(
1013
+ seedOrRNG: Seed | RNG = getRandomSeed(),
1014
+ exceptions: CardType[] = [],
1015
+ ): CardType {
1016
+ return getRandomSetElement(this.cardSet, seedOrRNG, exceptions);
1017
+ }
1018
+
1019
+ /**
1020
+ * @param itemConfigCardType The item config card type that represents the pool of cards to select
1021
+ * from.
1022
+ * @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided,
1023
+ * the `RNG.Next` method will be called. Default is `getRandomSeed()`.
1024
+ * @param exceptions Optional. An array of cards to not select.
1025
+ */
1026
+ @Exported
1027
+ public getRandomCardTypeOfType(
1028
+ itemConfigCardType: ItemConfigCardType,
1029
+ seedOrRNG: Seed | RNG = getRandomSeed(),
1030
+ exceptions: CardType[] = [],
1031
+ ): CardType {
1032
+ const cardTypeSet = this.getCardTypesOfType(itemConfigCardType);
1033
+ return getRandomSetElement(cardTypeSet, seedOrRNG, exceptions);
1034
+ }
1035
+
1036
+ /**
1037
+ * Has an equal chance of returning any rune (e.g. Rune of Hagalaz, Blank Rune, Black Rune, Soul
1038
+ * of Isaac, etc.). This will never return a Rune Shard.
1039
+ *
1040
+ * @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided,
1041
+ * the `RNG.Next` method will be called. Default is `getRandomSeed()`.
1042
+ * @param exceptions Optional. An array of runes to not select.
1043
+ */
1044
+ @Exported
1045
+ public getRandomRune(
1046
+ seedOrRNG: Seed | RNG = getRandomSeed(),
1047
+ exceptions: CardType[] = [],
1048
+ ): CardType {
1049
+ const runesSet = this.getCardTypesOfType(ItemConfigCardType.RUNE);
1050
+ runesSet.delete(CardType.RUNE_SHARD);
1051
+ return getRandomSetElement(runesSet, seedOrRNG, exceptions);
1052
+ }
1053
+
757
1054
  /**
758
1055
  * Returns a random active collectible type that that is a valid starting item for Eden.
759
1056
  *
1057
+ * This function can only be called if at least one callback has been executed. This is because
1058
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
1059
+ * order).
1060
+ *
760
1061
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
1062
+ *
1063
+ * @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided,
1064
+ * the `RNG.Next` method will be called. Default is `getRandomSeed()`.
1065
+ * @param exceptions Optional. An array of runes to not select.
761
1066
  */
762
1067
  @Exported
763
1068
  public getRandomEdenActiveCollectible(
@@ -775,7 +1080,15 @@ export class ModdedElementSets extends Feature {
775
1080
  /**
776
1081
  * Returns a random passive collectible type that that is a valid starting item for Eden.
777
1082
  *
1083
+ * This function can only be called if at least one callback has been executed. This is because
1084
+ * not all collectibles will necessarily be present when a mod first loads (due to mod load
1085
+ * order).
1086
+ *
778
1087
  * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
1088
+ *
1089
+ * @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided,
1090
+ * the `RNG.Next` method will be called. Default is `getRandomSeed()`.
1091
+ * @param exceptions Optional. An array of runes to not select.
779
1092
  */
780
1093
  @Exported
781
1094
  public getRandomEdenPassiveCollectible(
@@ -847,6 +1160,34 @@ export class ModdedElementSets extends Feature {
847
1160
  return trinketsSet;
848
1161
  }
849
1162
 
1163
+ /**
1164
+ * Returns an array containing every valid vanilla card type in the game.
1165
+ *
1166
+ * Use this if you need to iterate over the cards in order. If you need to do O(1) lookups, then
1167
+ * use the `getVanillaCardSet` helper function instead.
1168
+ *
1169
+ * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
1170
+ */
1171
+ @Exported
1172
+ public getVanillaCardArray(): readonly CardType[] {
1173
+ this.lazyInitVanillaCardTypes();
1174
+ return this.vanillaCardTypesArray;
1175
+ }
1176
+
1177
+ /**
1178
+ * Returns a set containing every valid vanilla card type in the game.
1179
+ *
1180
+ * Use this if you need to do O(1) lookups. If you need to iterate over the cards in order, then
1181
+ * use the `getVanillaCardArray` helper function instead.
1182
+ *
1183
+ * In order to use this function, you must upgrade your mod with `ISCFeature.MODDED_ELEMENT_SETS`.
1184
+ */
1185
+ @Exported
1186
+ public getVanillaCardSet(): ReadonlySet<CardType> {
1187
+ this.lazyInitVanillaCardTypes();
1188
+ return this.vanillaCardTypesSet;
1189
+ }
1190
+
850
1191
  /**
851
1192
  * Returns an array containing every valid vanilla collectible type in the game.
852
1193
  *
@@ -113,6 +113,11 @@ export class Pause extends Feature {
113
113
  return 1;
114
114
  };
115
115
 
116
+ @Exported
117
+ public isPaused(): boolean {
118
+ return this.v.run.isPseudoPaused;
119
+ }
120
+
116
121
  /**
117
122
  * Helper function to emulate what happens when the player pauses the game. Use the `unpause`
118
123
  * function to return things back to normal.
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  Dimension,
3
3
  DisplayFlag,
4
+ ItemConfigCardType,
4
5
  ItemPoolType,
5
6
  TrinketSlot,
6
7
  } from "isaac-typescript-definitions";
@@ -74,6 +75,14 @@ export const FIRST_GLITCHED_COLLECTIBLE_TYPE = asCollectibleType((1 << 32) - 1);
74
75
  /** Game frames are what is returned by the `Game.GetFrameCount` method. */
75
76
  export const GAME_FRAMES_PER_SECOND = 30;
76
77
 
78
+ /** The set of all `ItemConfigCardType` values that are not a rune or special object. */
79
+ export const ITEM_CONFIG_CARD_TYPES_FOR_CARDS = new Set([
80
+ ItemConfigCardType.TAROT,
81
+ ItemConfigCardType.SUIT,
82
+ ItemConfigCardType.SPECIAL,
83
+ ItemConfigCardType.TAROT_REVERSE,
84
+ ]);
85
+
77
86
  /** Render frames are what is returned by the `Isaac.GetFrameCount` method. */
78
87
  export const RENDER_FRAMES_PER_SECOND = 60;
79
88
 
@@ -53,6 +53,16 @@ export function upgradeMod<T extends readonly ISCFeature[] = never[]>(
53
53
  debug = false,
54
54
  timeThreshold?: float,
55
55
  ): ModUpgraded<T> {
56
+ // First, validate that all of the features exist (for Lua users who don't have type-safety).
57
+ for (const feature of features) {
58
+ const featureType = type(feature);
59
+ if (featureType !== "number") {
60
+ error(
61
+ `Failed to upgrade the mod due to one of the specified features being of type "${featureType}". (All of the features should be numbers represented by the "ISCFeature" enum.)`,
62
+ );
63
+ }
64
+ }
65
+
56
66
  patchErrorFunction();
57
67
 
58
68
  const mod = new ModUpgradedBase(modVanilla, debug, timeThreshold);