isaacscript-common 8.4.6 → 8.7.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 (77) hide show
  1. package/dist/enums/ModCallbackCustom.d.ts +2 -2
  2. package/dist/features/characterStats.d.ts.map +1 -1
  3. package/dist/features/characterStats.lua +1 -2
  4. package/dist/features/firstLast.d.ts +6 -3
  5. package/dist/features/firstLast.d.ts.map +1 -1
  6. package/dist/features/firstLast.lua +6 -3
  7. package/dist/features/playerInventory.d.ts +11 -3
  8. package/dist/features/playerInventory.d.ts.map +1 -1
  9. package/dist/features/playerInventory.lua +24 -11
  10. package/dist/functions/bosses.d.ts +8 -2
  11. package/dist/functions/bosses.d.ts.map +1 -1
  12. package/dist/functions/bosses.lua +14 -6
  13. package/dist/functions/collectibleCacheFlag.d.ts +1 -1
  14. package/dist/functions/collectibleCacheFlag.d.ts.map +1 -1
  15. package/dist/functions/collectibleCacheFlag.lua +1 -2
  16. package/dist/functions/collectibleSet.lua +32 -32
  17. package/dist/functions/collectibleTag.d.ts +1 -1
  18. package/dist/functions/collectibleTag.d.ts.map +1 -1
  19. package/dist/functions/collectibleTag.lua +1 -3
  20. package/dist/functions/collectibles.d.ts +10 -1
  21. package/dist/functions/collectibles.d.ts.map +1 -1
  22. package/dist/functions/collectibles.lua +17 -1
  23. package/dist/functions/eden.d.ts +1 -1
  24. package/dist/functions/eden.d.ts.map +1 -1
  25. package/dist/functions/eden.lua +1 -2
  26. package/dist/functions/flying.d.ts +1 -1
  27. package/dist/functions/flying.d.ts.map +1 -1
  28. package/dist/functions/flying.lua +5 -2
  29. package/dist/functions/input.d.ts +2 -2
  30. package/dist/functions/input.d.ts.map +1 -1
  31. package/dist/functions/input.lua +2 -4
  32. package/dist/functions/playerHealth.d.ts +93 -0
  33. package/dist/functions/playerHealth.d.ts.map +1 -1
  34. package/dist/functions/playerHealth.lua +216 -33
  35. package/dist/functions/players.d.ts +1 -111
  36. package/dist/functions/players.d.ts.map +1 -1
  37. package/dist/functions/players.lua +20 -279
  38. package/dist/functions/revive.d.ts.map +1 -1
  39. package/dist/functions/revive.lua +2 -1
  40. package/dist/functions/stats.d.ts +16 -0
  41. package/dist/functions/stats.d.ts.map +1 -1
  42. package/dist/functions/stats.lua +78 -0
  43. package/dist/functions/transformations.d.ts +1 -1
  44. package/dist/functions/transformations.d.ts.map +1 -1
  45. package/dist/functions/trinketCacheFlag.d.ts +1 -1
  46. package/dist/functions/trinketCacheFlag.d.ts.map +1 -1
  47. package/dist/functions/trinketCacheFlag.lua +1 -3
  48. package/dist/functions/trinketSet.lua +32 -32
  49. package/dist/functions/trinkets.d.ts +14 -0
  50. package/dist/functions/trinkets.d.ts.map +1 -1
  51. package/dist/functions/trinkets.lua +26 -0
  52. package/dist/index.d.ts +63 -36
  53. package/dist/sets/bossSets.d.ts +1 -0
  54. package/dist/sets/bossSets.d.ts.map +1 -1
  55. package/dist/sets/bossSets.lua +23 -0
  56. package/package.json +1 -1
  57. package/src/enums/ModCallbackCustom.ts +2 -2
  58. package/src/features/characterStats.ts +1 -2
  59. package/src/features/firstLast.ts +6 -3
  60. package/src/features/playerInventory.ts +37 -8
  61. package/src/functions/bosses.ts +18 -6
  62. package/src/functions/collectibleCacheFlag.ts +3 -3
  63. package/src/functions/collectibleSet.ts +32 -32
  64. package/src/functions/collectibleTag.ts +2 -3
  65. package/src/functions/collectibles.ts +25 -1
  66. package/src/functions/eden.ts +3 -3
  67. package/src/functions/flying.ts +4 -4
  68. package/src/functions/input.ts +4 -5
  69. package/src/functions/playerHealth.ts +269 -7
  70. package/src/functions/players.ts +1 -348
  71. package/src/functions/revive.ts +2 -6
  72. package/src/functions/stats.ts +75 -0
  73. package/src/functions/transformations.ts +1 -1
  74. package/src/functions/trinketCacheFlag.ts +2 -3
  75. package/src/functions/trinketSet.ts +32 -32
  76. package/src/functions/trinkets.ts +34 -0
  77. package/src/sets/bossSets.ts +33 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "8.4.6",
3
+ "version": "8.7.0",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -959,7 +959,7 @@ export enum ModCallbackCustom {
959
959
 
960
960
  /**
961
961
  * Fires from the `POST_PEFFECT_UPDATE` callback when a player's collectible count is higher than
962
- * what it was on the previous frame.
962
+ * what it was on the previous frame or when a new active collectible is acquired.
963
963
  *
964
964
  * When registering the callback, takes an optional second argument that will make the callback
965
965
  * only fire if the collectible matches the `CollectibleType` provided.
@@ -975,7 +975,7 @@ export enum ModCallbackCustom {
975
975
 
976
976
  /**
977
977
  * Fires from the `POST_PEFFECT_UPDATE` callback when a player's collectible count is lower than
978
- * what it was on the previous frame.
978
+ * what it was on the previous frame or when an active collectible is no longer present.
979
979
  *
980
980
  * When registering the callback, takes an optional second argument that will make the callback
981
981
  * only fire if the collectible matches the `CollectibleType` provided.
@@ -10,8 +10,7 @@ import {
10
10
  PlayerType,
11
11
  } from "isaac-typescript-definitions";
12
12
  import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
13
- import { addStat } from "../functions/players";
14
- import { getDefaultPlayerStat } from "../functions/stats";
13
+ import { addStat, getDefaultPlayerStat } from "../functions/stats";
15
14
 
16
15
  const FEATURE_NAME = "characterStats";
17
16
 
@@ -95,11 +95,11 @@ export function getLastCollectibleType(): CollectibleType {
95
95
  /**
96
96
  * Helper function to get an array that represents the all modded collectible types.
97
97
  *
98
- * This function is only useful when building collectible type objects. For most purposes, you
99
- * should use the `getModdedCollectibleSet` helper function instead.
100
- *
101
98
  * Returns an empty array if there are no modded collectible types.
102
99
  *
100
+ * This function is only useful when building collectible type objects. For most purposes, you
101
+ * should use the `getModdedCollectibleArray` or `getModdedCollectibleSet` helper function instead.
102
+ *
103
103
  * (This function is named differently from the `getVanillaCollectibleTypeRange` function because
104
104
  * all modded collectible types are contiguous. Thus, each value represents a real
105
105
  * `CollectibleType`.)
@@ -189,6 +189,9 @@ export function getLastTrinketType(): TrinketType {
189
189
  *
190
190
  * Returns an empty array if there are no modded trinket types.
191
191
  *
192
+ * This function is only useful when building collectible type objects. For most purposes, you
193
+ * should use the `getModdedCollectibleArray` or `getModdedCollectibleSet` helper function instead.
194
+ *
192
195
  * This function can only be called if at least one callback has been executed. This is because not
193
196
  * all trinkets will necessarily be present when a mod first loads (due to mod load order).
194
197
  */
@@ -3,7 +3,11 @@ import { DefaultMap } from "../classes/DefaultMap";
3
3
  import { ModUpgraded } from "../classes/ModUpgraded";
4
4
  import { ModCallbackCustom } from "../enums/ModCallbackCustom";
5
5
  import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
6
- import { arrayRemoveInPlace, copyArray } from "../functions/array";
6
+ import {
7
+ arrayRemoveInPlace,
8
+ copyArray,
9
+ getLastElement,
10
+ } from "../functions/array";
7
11
  import { isActiveCollectible } from "../functions/collectibles";
8
12
  import { getCollectibleArray } from "../functions/collectibleSet";
9
13
  import {
@@ -31,10 +35,16 @@ function newPlayerInventory(player: EntityPlayer) {
31
35
  const inventory: CollectibleType[] = [];
32
36
 
33
37
  for (const collectibleType of getCollectibleArray()) {
34
- const numCollectibles = player.GetCollectibleNum(collectibleType, true);
35
- repeat(numCollectibles, () => {
36
- inventory.push(collectibleType);
37
- });
38
+ // We have to use the `EntityPlayer.HasCollectible` method in addition to the
39
+ // `EntityPlayer.GetCollectibleNum` method in order to mitigate situations like Lilith's Incubus
40
+ // counting as a collectible. (The former method will return false for her innate Incubus, but
41
+ // the latter method will return 1.)
42
+ if (player.HasCollectible(collectibleType)) {
43
+ const numCollectibles = player.GetCollectibleNum(collectibleType, true);
44
+ repeat(numCollectibles, () => {
45
+ inventory.push(collectibleType);
46
+ });
47
+ }
38
48
  }
39
49
 
40
50
  return inventory;
@@ -68,6 +78,9 @@ function useItemD4(
68
78
  _rng: RNG,
69
79
  player: EntityPlayer,
70
80
  ): boolean | undefined {
81
+ // This function is also triggered when the player uses D100, D Infinity, a 1-pip dice room, or a
82
+ // 6-pip dice room. (Genesis should be automatically handled by the
83
+ // `POST_PLAYER_COLLECTIBLE_REMOVED` callback.)
71
84
  resetInventory(player);
72
85
 
73
86
  return undefined;
@@ -107,9 +120,6 @@ function postCollectibleRemoved(
107
120
  * Helper function to get all of the collectibles that the player has gotten so far on this run, in
108
121
  * order.
109
122
  *
110
- * Note that this does not include active collectibles that have since been dropped for other
111
- * collectibles.
112
- *
113
123
  * In the case of inventory initialization or the case where the player rerolls their build in the
114
124
  * middle of the run (e.g. with D4), the order of the inventory will not correspond to the order
115
125
  * that the items were actually given to the player. In this case, the inventory will be in the
@@ -121,6 +131,10 @@ function postCollectibleRemoved(
121
131
  * would not be updated. In vanilla, this situation would never happen, but another mod might do
122
132
  * this for some reason. (With that said, the next time that a collectible is normally added or
123
133
  * removed, it would trigger a re-scan, and the previous changes would be picked up.)
134
+ *
135
+ * @param player The player to get the inventory for.
136
+ * @param includeActiveCollectibles Optional. If true, will include all active collectibles. Default
137
+ * is true.
124
138
  */
125
139
  export function getPlayerInventory(
126
140
  player: EntityPlayer,
@@ -139,3 +153,18 @@ export function getPlayerInventory(
139
153
  (collectibleType) => !isActiveCollectible(collectibleType),
140
154
  );
141
155
  }
156
+
157
+ /**
158
+ * Helper function to get the last passive collectible that the player picked up. In most cases,
159
+ * this will be the passive that is removed when the player would use Clicker.
160
+ *
161
+ * Returns undefined if the player does not have any passive collectibles.
162
+ */
163
+ export function getPlayerLastPassiveCollectible(
164
+ player: EntityPlayer,
165
+ ): CollectibleType | undefined {
166
+ errorIfFeaturesNotInitialized(FEATURE_NAME);
167
+
168
+ const inventory = getPlayerInventory(player, false);
169
+ return getLastElement(inventory);
170
+ }
@@ -5,6 +5,7 @@ import {
5
5
  } from "isaac-typescript-definitions";
6
6
  import { VectorZero } from "../core/constants";
7
7
  import {
8
+ ALL_BOSSES_EXCLUDING_STORY_BOSSES_SET,
8
9
  ALL_BOSSES_SET,
9
10
  STAGE_TO_COMBINED_BOSS_SET_MAP,
10
11
  STAGE_TO_STAGE_TYPE_TO_BOSS_SET_MAP,
@@ -13,7 +14,6 @@ import { SIN_ENTITY_TYPES_SET } from "../sets/sinEntityTypesSet";
13
14
  import { getNPCs, spawnNPC } from "./entitiesSpecific";
14
15
  import { getAliveNPCs } from "./npcs";
15
16
  import { isRNG } from "./rng";
16
- import { copySet } from "./set";
17
17
  import { asNumber } from "./types";
18
18
  import { repeat } from "./utils";
19
19
 
@@ -56,10 +56,20 @@ export function getAliveBosses(
56
56
  *
57
57
  * The set contains strings with the entity type and variant, separated by a period.
58
58
  *
59
+ * Note that this set does not include bosses that do not appear in Boss Rooms (e.g. Krampus, Uriel,
60
+ * and Gabriel.).
61
+ *
59
62
  * Also see the `getBossSet` and `getCombinedBossSet` functions.
63
+ *
64
+ * @param includeStoryBosses Optional. Whether to include "story" bosses like Mom and It Lives!
65
+ * Default is true.
60
66
  */
61
- export function getAllBossesSet(): Set<string> {
62
- return copySet(ALL_BOSSES_SET);
67
+ export function getAllBossesSet(
68
+ includeStoryBosses = true,
69
+ ): ReadonlySet<string> {
70
+ return includeStoryBosses
71
+ ? ALL_BOSSES_SET
72
+ : ALL_BOSSES_EXCLUDING_STORY_BOSSES_SET;
63
73
  }
64
74
 
65
75
  /**
@@ -84,7 +94,7 @@ export function getBossSet(
84
94
  return undefined;
85
95
  }
86
96
 
87
- return copySet(bossSet);
97
+ return bossSet;
88
98
  }
89
99
 
90
100
  /**
@@ -117,13 +127,15 @@ export function getBosses(
117
127
  *
118
128
  * Also see the `getAllBossesSet` and `getBossSet` functions.
119
129
  */
120
- export function getCombinedBossSet(stage: int): Set<string> | undefined {
130
+ export function getCombinedBossSet(
131
+ stage: int,
132
+ ): ReadonlySet<string> | undefined {
121
133
  const bossSet = STAGE_TO_COMBINED_BOSS_SET_MAP.get(stage);
122
134
  if (bossSet === undefined) {
123
135
  return undefined;
124
136
  }
125
137
 
126
- return copySet(bossSet);
138
+ return bossSet;
127
139
  }
128
140
 
129
141
  /** Helper function to check if the provided NPC is a Sin miniboss, such as Sloth or Lust. */
@@ -3,7 +3,7 @@ import { itemConfig } from "../core/cachedClasses";
3
3
  import { getCollectibleArray } from "./collectibleSet";
4
4
  import { getEnumValues } from "./enums";
5
5
  import { hasFlag } from "./flag";
6
- import { copySet, getSortedSetValues } from "./set";
6
+ import { getSortedSetValues } from "./set";
7
7
  import { repeat } from "./utils";
8
8
 
9
9
  const CACHE_FLAG_TO_COLLECTIBLES_MAP = new Map<
@@ -51,7 +51,7 @@ export function collectibleHasCacheFlag(
51
51
  */
52
52
  export function getCollectiblesForCacheFlag(
53
53
  cacheFlag: CacheFlag,
54
- ): Set<CollectibleType> {
54
+ ): ReadonlySet<CollectibleType> {
55
55
  lazyInitCacheFlagMap();
56
56
 
57
57
  const collectiblesSet = CACHE_FLAG_TO_COLLECTIBLES_MAP.get(cacheFlag);
@@ -59,7 +59,7 @@ export function getCollectiblesForCacheFlag(
59
59
  return new Set();
60
60
  }
61
61
 
62
- return copySet(collectiblesSet);
62
+ return collectiblesSet;
63
63
  }
64
64
 
65
65
  /**
@@ -3,17 +3,17 @@ import { itemConfig } from "../core/cachedClasses";
3
3
  import { getModdedCollectibleTypes } from "../features/firstLast";
4
4
  import { getVanillaCollectibleTypeRange } from "./collectibles";
5
5
 
6
- const ALL_COLLECTIBLES_ARRAY: CollectibleType[] = [];
7
- const ALL_COLLECTIBLES_SET = new Set<CollectibleType>();
6
+ const ALL_COLLECTIBLE_TYPES_ARRAY: CollectibleType[] = [];
7
+ const ALL_COLLECTIBLE_TYPES_SET = new Set<CollectibleType>();
8
8
 
9
- const VANILLA_COLLECTIBLES_ARRAY: CollectibleType[] = [];
10
- const VANILLA_COLLECTIBLES_SET = new Set<CollectibleType>();
9
+ const VANILLA_COLLECTIBLE_TYPES_ARRAY: CollectibleType[] = [];
10
+ const VANILLA_COLLECTIBLE_TYPES_SET = new Set<CollectibleType>();
11
11
 
12
- const MODDED_COLLECTIBLES_ARRAY: CollectibleType[] = [];
13
- const MODDED_COLLECTIBLES_SET = new Set<CollectibleType>();
12
+ const MODDED_COLLECTIBLE_TYPES_ARRAY: CollectibleType[] = [];
13
+ const MODDED_COLLECTIBLE_TYPES_SET = new Set<CollectibleType>();
14
14
 
15
- function lazyInitVanillaCollectibles() {
16
- if (VANILLA_COLLECTIBLES_ARRAY.length > 0) {
15
+ function lazyInitVanillaCollectibleTypes() {
16
+ if (VANILLA_COLLECTIBLE_TYPES_ARRAY.length > 0) {
17
17
  return;
18
18
  }
19
19
 
@@ -22,22 +22,22 @@ function lazyInitVanillaCollectibles() {
22
22
  // Vanilla collectible types are not contiguous, so we must check every value.
23
23
  const itemConfigItem = itemConfig.GetCollectible(collectibleType);
24
24
  if (itemConfigItem !== undefined) {
25
- VANILLA_COLLECTIBLES_ARRAY.push(collectibleType);
26
- VANILLA_COLLECTIBLES_SET.add(collectibleType);
25
+ VANILLA_COLLECTIBLE_TYPES_ARRAY.push(collectibleType);
26
+ VANILLA_COLLECTIBLE_TYPES_SET.add(collectibleType);
27
27
  }
28
28
  }
29
29
  }
30
30
 
31
- function lazyInitModdedCollectibles() {
32
- if (MODDED_COLLECTIBLES_ARRAY.length > 0) {
31
+ function lazyInitModdedCollectibleTypes() {
32
+ if (MODDED_COLLECTIBLE_TYPES_ARRAY.length > 0) {
33
33
  return;
34
34
  }
35
35
 
36
- lazyInitVanillaCollectibles();
36
+ lazyInitVanillaCollectibleTypes();
37
37
 
38
- for (const collectibleType of VANILLA_COLLECTIBLES_ARRAY) {
39
- ALL_COLLECTIBLES_ARRAY.push(collectibleType);
40
- ALL_COLLECTIBLES_SET.add(collectibleType);
38
+ for (const collectibleType of VANILLA_COLLECTIBLE_TYPES_ARRAY) {
39
+ ALL_COLLECTIBLE_TYPES_ARRAY.push(collectibleType);
40
+ ALL_COLLECTIBLE_TYPES_SET.add(collectibleType);
41
41
  }
42
42
 
43
43
  const moddedCollectibleTypes = getModdedCollectibleTypes();
@@ -45,11 +45,11 @@ function lazyInitModdedCollectibles() {
45
45
  // Modded collectible types are contiguous, but we check every value just in case.
46
46
  const itemConfigItem = itemConfig.GetCollectible(collectibleType);
47
47
  if (itemConfigItem !== undefined) {
48
- MODDED_COLLECTIBLES_ARRAY.push(collectibleType);
49
- MODDED_COLLECTIBLES_SET.add(collectibleType);
48
+ MODDED_COLLECTIBLE_TYPES_ARRAY.push(collectibleType);
49
+ MODDED_COLLECTIBLE_TYPES_SET.add(collectibleType);
50
50
 
51
- ALL_COLLECTIBLES_ARRAY.push(collectibleType);
52
- ALL_COLLECTIBLES_SET.add(collectibleType);
51
+ ALL_COLLECTIBLE_TYPES_ARRAY.push(collectibleType);
52
+ ALL_COLLECTIBLE_TYPES_SET.add(collectibleType);
53
53
  }
54
54
  }
55
55
  }
@@ -65,8 +65,8 @@ function lazyInitModdedCollectibles() {
65
65
  * all collectibles will necessarily be present when a mod first loads (due to mod load order).
66
66
  */
67
67
  export function getCollectibleArray(): readonly CollectibleType[] {
68
- lazyInitModdedCollectibles();
69
- return ALL_COLLECTIBLES_ARRAY;
68
+ lazyInitModdedCollectibleTypes();
69
+ return ALL_COLLECTIBLE_TYPES_ARRAY;
70
70
  }
71
71
 
72
72
  /**
@@ -79,8 +79,8 @@ export function getCollectibleArray(): readonly CollectibleType[] {
79
79
  * all collectibles will necessarily be present when a mod first loads (due to mod load order).
80
80
  */
81
81
  export function getCollectibleSet(): ReadonlySet<CollectibleType> {
82
- lazyInitModdedCollectibles();
83
- return ALL_COLLECTIBLES_SET;
82
+ lazyInitModdedCollectibleTypes();
83
+ return ALL_COLLECTIBLE_TYPES_SET;
84
84
  }
85
85
 
86
86
  /**
@@ -93,8 +93,8 @@ export function getCollectibleSet(): ReadonlySet<CollectibleType> {
93
93
  * all collectibles will necessarily be present when a mod first loads (due to mod load order).
94
94
  */
95
95
  export function getModdedCollectibleArray(): readonly CollectibleType[] {
96
- lazyInitModdedCollectibles();
97
- return MODDED_COLLECTIBLES_ARRAY;
96
+ lazyInitModdedCollectibleTypes();
97
+ return MODDED_COLLECTIBLE_TYPES_ARRAY;
98
98
  }
99
99
 
100
100
  /**
@@ -107,8 +107,8 @@ export function getModdedCollectibleArray(): readonly CollectibleType[] {
107
107
  * all collectibles will necessarily be present when a mod first loads (due to mod load order).
108
108
  */
109
109
  export function getModdedCollectibleSet(): ReadonlySet<CollectibleType> {
110
- lazyInitModdedCollectibles();
111
- return MODDED_COLLECTIBLES_SET;
110
+ lazyInitModdedCollectibleTypes();
111
+ return MODDED_COLLECTIBLE_TYPES_SET;
112
112
  }
113
113
 
114
114
  /**
@@ -118,8 +118,8 @@ export function getModdedCollectibleSet(): ReadonlySet<CollectibleType> {
118
118
  * then use the `getVanillaCollectibleSet` helper function instead.
119
119
  */
120
120
  export function getVanillaCollectibleArray(): readonly CollectibleType[] {
121
- lazyInitVanillaCollectibles();
122
- return VANILLA_COLLECTIBLES_ARRAY;
121
+ lazyInitVanillaCollectibleTypes();
122
+ return VANILLA_COLLECTIBLE_TYPES_ARRAY;
123
123
  }
124
124
 
125
125
  /**
@@ -129,6 +129,6 @@ export function getVanillaCollectibleArray(): readonly CollectibleType[] {
129
129
  * then use the `getVanillaCollectibleArray` helper function instead.
130
130
  */
131
131
  export function getVanillaCollectibleSet(): ReadonlySet<CollectibleType> {
132
- lazyInitVanillaCollectibles();
133
- return VANILLA_COLLECTIBLES_SET;
132
+ lazyInitVanillaCollectibleTypes();
133
+ return VANILLA_COLLECTIBLE_TYPES_SET;
134
134
  }
@@ -4,7 +4,6 @@ import { getCollectibleArray } from "./collectibleSet";
4
4
  import { getEnumValues } from "./enums";
5
5
  import { getFlagName } from "./flag";
6
6
  import { getPlayerCollectibleCount } from "./players";
7
- import { copySet } from "./set";
8
7
 
9
8
  const TAG_TO_COLLECTIBLE_TYPES_MAP = new Map<
10
9
  ItemConfigTag,
@@ -59,7 +58,7 @@ export function collectibleHasTag(
59
58
  */
60
59
  export function getCollectibleTypesWithTag(
61
60
  itemConfigTag: ItemConfigTag,
62
- ): Set<CollectibleType> {
61
+ ): ReadonlySet<CollectibleType> {
63
62
  // Lazy initialize the map.
64
63
  if (TAG_TO_COLLECTIBLE_TYPES_MAP.size === 0) {
65
64
  initTagMap();
@@ -72,7 +71,7 @@ export function getCollectibleTypesWithTag(
72
71
  );
73
72
  }
74
73
 
75
- return copySet(collectibleTypes);
74
+ return collectibleTypes;
76
75
  }
77
76
 
78
77
  /** Returns the number of items that a player has towards a particular transformation. */
@@ -31,6 +31,7 @@ import { getRoomListIndex } from "./roomData";
31
31
  import { clearSprite, spriteEquals } from "./sprites";
32
32
  import { irange } from "./utils";
33
33
 
34
+ const COLLECTIBLE_ANM2_PATH = "gfx/005.100_collectible.anm2";
34
35
  const COLLECTIBLE_SPRITE_LAYER = 1;
35
36
  const COLLECTIBLE_SHADOW_LAYER = 4;
36
37
 
@@ -159,8 +160,12 @@ export function getCollectibleDevilHeartPrice(
159
160
  }
160
161
 
161
162
  /**
162
- * Helper function to get the path to a collectible's sprite. Returns the path to the question mark
163
+ * Helper function to get the path to a collectible PNG file. Returns the path to the question mark
163
164
  * sprite (i.e. from Curse of the Blind) if the provided collectible type was not valid.
165
+ *
166
+ * Note that this does not return the file name, but the full path to the collectible's PNG file.
167
+ * The function is named "GfxFilename" to correspond to the associated `ItemConfigItem.GfxFileName`
168
+ * field.
164
169
  */
165
170
  export function getCollectibleGfxFilename(
166
171
  collectibleType: CollectibleType,
@@ -469,6 +474,25 @@ export function isVanillaCollectibleType(
469
474
  return collectibleType <= LAST_VANILLA_COLLECTIBLE_TYPE;
470
475
  }
471
476
 
477
+ /**
478
+ * Helper function to generate a new sprite based on a collectible. If the provided collectible type
479
+ * is invalid, a sprite with a Curse of the Blind question mark will be returned.
480
+ */
481
+ export function newCollectibleSprite(collectibleType: CollectibleType): Sprite {
482
+ const sprite = Sprite();
483
+ sprite.Load(COLLECTIBLE_ANM2_PATH, false);
484
+
485
+ // We want to clear the pedestal layers so that the returned sprite only has the collectible
486
+ // image.
487
+ clearSprite(sprite);
488
+
489
+ const gfxFileName = getCollectibleGfxFilename(collectibleType);
490
+ sprite.ReplaceSpritesheet(COLLECTIBLE_SPRITE_LAYER, gfxFileName);
491
+ sprite.LoadGraphics();
492
+
493
+ return sprite;
494
+ }
495
+
472
496
  /**
473
497
  * Helper function to put a message in the log.txt file to let the Rebirth Item Tracker know that it
474
498
  * should remove an item.
@@ -3,7 +3,7 @@ import { isHiddenCollectible, isPassiveCollectible } from "./collectibles";
3
3
  import { getCollectibleArray } from "./collectibleSet";
4
4
  import { collectibleHasTag } from "./collectibleTag";
5
5
  import { getRandomSeed } from "./rng";
6
- import { copySet, getRandomSetElement } from "./set";
6
+ import { getRandomSetElement } from "./set";
7
7
 
8
8
  const EDEN_PASSIVE_COLLECTIBLES_SET = new Set<CollectibleType>();
9
9
 
@@ -19,13 +19,13 @@ function initCollectibleSet() {
19
19
  }
20
20
  }
21
21
 
22
- export function getEdenPassives(): Set<CollectibleType> {
22
+ export function getEdenPassives(): ReadonlySet<CollectibleType> {
23
23
  // Lazy initialize the set.
24
24
  if (EDEN_PASSIVE_COLLECTIBLES_SET.size === 0) {
25
25
  initCollectibleSet();
26
26
  }
27
27
 
28
- return copySet(EDEN_PASSIVE_COLLECTIBLES_SET);
28
+ return EDEN_PASSIVE_COLLECTIBLES_SET;
29
29
  }
30
30
 
31
31
  export function getRandomEdenPassive(
@@ -47,11 +47,11 @@ const CONDITIONAL_FLYING_COLLECTIBLE_TYPES: readonly CollectibleType[] = [
47
47
  */
48
48
  export function getFlyingCollectibles(
49
49
  pruneConditionalItems: boolean,
50
- ): Set<CollectibleType> {
50
+ ): ReadonlySet<CollectibleType> {
51
51
  // Instead of manually compiling a list of collectibles that grant flying, we can instead
52
52
  // dynamically look for collectibles that have `CacheFlag.FLYING`.
53
- const collectiblesWithFlyingCacheFlag = getCollectiblesForCacheFlag(
54
- CacheFlag.FLYING,
53
+ const collectiblesWithFlyingCacheFlag = copySet(
54
+ getCollectiblesForCacheFlag(CacheFlag.FLYING),
55
55
  );
56
56
 
57
57
  // None of the collectibles with a cache of "all" grant flying, so we can safely remove them from
@@ -80,7 +80,7 @@ export function getFlyingCollectibles(
80
80
  export function getFlyingTrinkets(): ReadonlySet<TrinketType> {
81
81
  // We use a different algorithm than the "getFlyingCollectibles" function because Azazel's Stump
82
82
  // has a cache of "all".
83
- return copySet(FLYING_TRINKETS);
83
+ return FLYING_TRINKETS;
84
84
  }
85
85
 
86
86
  export function hasFlyingTemporaryEffect(player: EntityPlayer): boolean {
@@ -6,7 +6,6 @@ import {
6
6
  } from "isaac-typescript-definitions";
7
7
  import { KEYBOARD_TO_STRING } from "../maps/keyboardToString";
8
8
  import { getEnumValues } from "./enums";
9
- import { copySet } from "./set";
10
9
  import { trimPrefix } from "./string";
11
10
 
12
11
  const MODIFIER_KEYS: readonly Keyboard[] = [
@@ -52,12 +51,12 @@ export function controllerToString(controller: Controller): string | undefined {
52
51
  return trimPrefix(key, "BUTTON_");
53
52
  }
54
53
 
55
- export function getMoveActions(): Set<ButtonAction> {
56
- return copySet(MOVEMENT_ACTIONS_SET);
54
+ export function getMoveActions(): ReadonlySet<ButtonAction> {
55
+ return MOVEMENT_ACTIONS_SET;
57
56
  }
58
57
 
59
- export function getShootActions(): Set<ButtonAction> {
60
- return copySet(SHOOTING_ACTIONS_SET);
58
+ export function getShootActions(): ReadonlySet<ButtonAction> {
59
+ return SHOOTING_ACTIONS_SET;
61
60
  }
62
61
 
63
62
  /** Iterates over all inputs to determine if a particular button is pressed (i.e. held down). */