isaacscript-common 76.3.0 → 77.1.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 (33) hide show
  1. package/dist/classes/features/other/FlyingDetection.lua +2 -3
  2. package/dist/classes/features/other/ItemPoolDetection.d.ts +1 -1
  3. package/dist/classes/features/other/ItemPoolDetection.d.ts.map +1 -1
  4. package/dist/classes/features/other/ModdedElementSets.d.ts +20 -20
  5. package/dist/classes/features/other/ModdedElementSets.d.ts.map +1 -1
  6. package/dist/classes/features/other/ModdedElementSets.lua +75 -86
  7. package/dist/functions/array.d.ts +3 -3
  8. package/dist/functions/array.d.ts.map +1 -1
  9. package/dist/functions/array.lua +34 -28
  10. package/dist/functions/cards.lua +3 -3
  11. package/dist/functions/collectibles.d.ts +2 -2
  12. package/dist/functions/collectibles.d.ts.map +1 -1
  13. package/dist/functions/collectibles.lua +4 -5
  14. package/dist/functions/pills.d.ts +3 -3
  15. package/dist/functions/pills.d.ts.map +1 -1
  16. package/dist/functions/playerTrinkets.d.ts +1 -1
  17. package/dist/functions/playerTrinkets.d.ts.map +1 -1
  18. package/dist/index.rollup.d.ts +30 -30
  19. package/dist/isaacscript-common.lua +121 -128
  20. package/dist/sets/{itemConfigCardTypesForCardsSet.d.ts → itemConfigCardTypesForCards.d.ts} +2 -2
  21. package/dist/sets/itemConfigCardTypesForCards.d.ts.map +1 -0
  22. package/dist/sets/{itemConfigCardTypesForCardsSet.lua → itemConfigCardTypesForCards.lua} +1 -1
  23. package/dist/tsdoc-metadata.json +1 -1
  24. package/package.json +2 -2
  25. package/src/classes/features/other/ItemPoolDetection.ts +1 -1
  26. package/src/classes/features/other/ModdedElementSets.ts +106 -121
  27. package/src/functions/array.ts +12 -5
  28. package/src/functions/cards.ts +2 -2
  29. package/src/functions/collectibles.ts +7 -7
  30. package/src/functions/pills.ts +3 -3
  31. package/src/functions/playerTrinkets.ts +3 -1
  32. package/src/sets/{itemConfigCardTypesForCardsSet.ts → itemConfigCardTypesForCards.ts} +3 -1
  33. package/dist/sets/itemConfigCardTypesForCardsSet.d.ts.map +0 -1
@@ -26,6 +26,7 @@ import {
26
26
  } from "../../../core/constantsVanilla";
27
27
  import { Exported } from "../../../decorators";
28
28
  import { ISCFeature } from "../../../enums/ISCFeature";
29
+ import { arrayRemove, getRandomArrayElement } from "../../../functions/array";
29
30
  import { getItemConfigCardType } from "../../../functions/cards";
30
31
  import { collectibleHasTag } from "../../../functions/collectibleTag";
31
32
  import {
@@ -36,12 +37,7 @@ import {
36
37
  isPassiveOrFamiliarCollectible,
37
38
  } from "../../../functions/collectibles";
38
39
  import { getFlagName } from "../../../functions/flag";
39
- import {
40
- copySet,
41
- deleteSetsFromSet,
42
- getRandomSetElement,
43
- getSortedSetValues,
44
- } from "../../../functions/set";
40
+ import { getRandomSetElement } from "../../../functions/set";
45
41
  import { trinketHasCacheFlag } from "../../../functions/trinkets";
46
42
  import {
47
43
  asCardType,
@@ -50,9 +46,9 @@ import {
50
46
  asTrinketType,
51
47
  } from "../../../functions/types";
52
48
  import { assertDefined, iRange, repeat } from "../../../functions/utils";
53
- import { ITEM_CONFIG_CARD_TYPES_FOR_CARDS_SET } from "../../../sets/itemConfigCardTypesForCardsSet";
49
+ import { ITEM_CONFIG_CARD_TYPES_FOR_CARDS } from "../../../sets/itemConfigCardTypesForCards";
54
50
  import { ReadonlyMap } from "../../../types/ReadonlyMap";
55
- import { ReadonlySet } from "../../../types/ReadonlySet";
51
+ import type { ReadonlySet } from "../../../types/ReadonlySet";
56
52
  import { Feature } from "../../private/Feature";
57
53
  import type { ModdedElementDetection } from "./ModdedElementDetection";
58
54
 
@@ -125,23 +121,22 @@ export class ModdedElementSets extends Feature {
125
121
 
126
122
  private readonly cacheFlagToCollectibleTypesMap = new Map<
127
123
  CacheFlag,
128
- Set<CollectibleType>
124
+ readonly CollectibleType[]
129
125
  >();
130
126
 
131
127
  private readonly cacheFlagToTrinketTypesMap = new Map<
132
128
  CacheFlag,
133
- Set<TrinketType>
129
+ readonly TrinketType[]
134
130
  >();
135
131
 
136
- private flyingCollectibleTypesSet = new Set<CollectibleType>();
137
- private readonly permanentFlyingCollectibleTypesSet =
138
- new Set<CollectibleType>();
132
+ private flyingCollectibleTypes: CollectibleType[] = [];
133
+ private permanentFlyingCollectibleTypes: CollectibleType[] = [];
139
134
 
140
- private flyingTrinketTypesSet = new Set<TrinketType>();
135
+ private flyingTrinketTypes: TrinketType[] = [];
141
136
 
142
137
  private readonly tagToCollectibleTypesMap = new Map<
143
138
  ItemConfigTag,
144
- Set<CollectibleType>
139
+ CollectibleType[]
145
140
  >();
146
141
 
147
142
  private readonly edenActiveCollectibleTypesSet = new Set<CollectibleType>();
@@ -149,21 +144,21 @@ export class ModdedElementSets extends Feature {
149
144
 
150
145
  private readonly qualityToCollectibleTypesMap = new Map<
151
146
  Quality,
152
- Set<CollectibleType>
147
+ readonly CollectibleType[]
153
148
  >();
154
149
 
155
150
  private readonly itemConfigCardTypeToCardTypeMap = new Map<
156
151
  ItemConfigCardType,
157
- Set<CardType>
152
+ CardType[]
158
153
  >();
159
154
 
160
155
  /**
161
- * The set of card types that are not:
156
+ * The array of card types that are not:
162
157
  *
163
158
  * - ItemConfigCardType.RUNE
164
159
  * - ItemConfigCardType.SPECIAL_OBJECT
165
160
  */
166
- private readonly cardSet = new Set<CardType>();
161
+ private readonly cardTypeCardArray: CardType[] = [];
167
162
 
168
163
  private readonly moddedElementDetection: ModdedElementDetection;
169
164
 
@@ -318,9 +313,9 @@ export class ModdedElementSets extends Feature {
318
313
 
319
314
  private lazyInitTagToCollectibleTypesMap() {
320
315
  // The tag to collectible types map should be valid for every tag, so we initialize it with
321
- // empty sets.
316
+ // empty arrays.
322
317
  for (const itemConfigTag of ITEM_CONFIG_TAG_VALUES) {
323
- this.tagToCollectibleTypesMap.set(itemConfigTag, new Set());
318
+ this.tagToCollectibleTypesMap.set(itemConfigTag, [] as CollectibleType[]);
324
319
  }
325
320
 
326
321
  for (const collectibleType of this.getCollectibleTypes()) {
@@ -329,92 +324,88 @@ export class ModdedElementSets extends Feature {
329
324
  continue;
330
325
  }
331
326
 
332
- const collectibleTypesSet =
327
+ const collectibleTypes =
333
328
  this.tagToCollectibleTypesMap.get(itemConfigTag);
334
- if (collectibleTypesSet === undefined) {
329
+ if (collectibleTypes === undefined) {
335
330
  const flagName = getFlagName(itemConfigTag, ItemConfigTag);
336
331
  error(
337
332
  `Failed to get the collectible types for item tag: ${flagName}`,
338
333
  );
339
334
  }
340
- collectibleTypesSet.add(collectibleType);
335
+ collectibleTypes.push(collectibleType);
341
336
  }
342
337
  }
343
338
  }
344
339
 
345
340
  private lazyInitCacheFlagToCollectibleTypesMap() {
346
341
  for (const cacheFlag of CACHE_FLAG_VALUES) {
347
- const collectibleTypeSet = new Set<CollectibleType>();
342
+ const collectibleTypes: CollectibleType[] = [];
348
343
 
349
344
  for (const collectibleType of this.getCollectibleTypes()) {
350
345
  if (collectibleHasCacheFlag(collectibleType, cacheFlag)) {
351
- collectibleTypeSet.add(collectibleType);
346
+ collectibleTypes.push(collectibleType);
352
347
  }
353
348
  }
354
349
 
355
- this.cacheFlagToCollectibleTypesMap.set(cacheFlag, collectibleTypeSet);
350
+ this.cacheFlagToCollectibleTypesMap.set(cacheFlag, collectibleTypes);
356
351
  }
357
352
  }
358
353
 
359
354
  private lazyInitCacheFlagToTrinketTypesMap() {
360
355
  for (const cacheFlag of CACHE_FLAG_VALUES) {
361
- const trinketTypesSet = new Set<TrinketType>();
356
+ const trinketTypes: TrinketType[] = [];
362
357
 
363
358
  for (const trinketType of this.getTrinketTypes()) {
364
359
  if (trinketHasCacheFlag(trinketType, cacheFlag)) {
365
- trinketTypesSet.add(trinketType);
360
+ trinketTypes.push(trinketType);
366
361
  }
367
362
  }
368
363
 
369
- this.cacheFlagToTrinketTypesMap.set(cacheFlag, trinketTypesSet);
364
+ this.cacheFlagToTrinketTypesMap.set(cacheFlag, trinketTypes);
370
365
  }
371
366
  }
372
367
 
373
368
  private lazyInitFlyingCollectibleTypesSet() {
374
369
  // Instead of manually compiling a list of collectibles that grant flying, we can instead
375
- // dynamically look for collectibles that have `CacheFlag.FLYING`.
376
- this.flyingCollectibleTypesSet = copySet(
377
- this.getCollectibleTypesWithCacheFlag(CacheFlag.FLYING),
378
- );
379
-
380
- // None of the collectibles with a cache of "all" grant flying (including all of the 3 Dollar
381
- // Bill collectibles and all of the Birthright effects), so we can safely remove them from the
382
- // list.
383
- const collectiblesWithAllCacheFlag = this.getCollectibleTypesWithCacheFlag(
384
- CacheFlag.ALL,
385
- );
386
- deleteSetsFromSet(
387
- this.flyingCollectibleTypesSet,
388
- collectiblesWithAllCacheFlag,
370
+ // dynamically look for collectibles that have `CacheFlag.FLYING`. But none of the collectibles
371
+ // with a cache of "all" grant flying (including all of the 3 Dollar Bill collectibles and all
372
+ // of the Birthright effects), so we can safely remove them from the list.
373
+ const collectibleTypesWithFlyingCacheFlag =
374
+ this.getCollectibleTypesWithCacheFlag(CacheFlag.FLYING);
375
+ const collectibleTypesWithAllCacheFlag =
376
+ this.getCollectibleTypesWithCacheFlag(CacheFlag.ALL);
377
+ this.flyingCollectibleTypes = arrayRemove(
378
+ collectibleTypesWithFlyingCacheFlag,
379
+ ...collectibleTypesWithAllCacheFlag,
389
380
  );
390
381
 
391
382
  // Additionally, create a second set that represents the collectible types that grant flying
392
383
  // non-conditionally.
393
- const permanentFlyingCollectibleTypes = copySet(
394
- this.flyingCollectibleTypesSet,
384
+ this.permanentFlyingCollectibleTypes = arrayRemove(
385
+ this.flyingCollectibleTypes,
386
+ ...CONDITIONAL_FLYING_COLLECTIBLE_TYPES,
395
387
  );
396
- for (const collectibleType of CONDITIONAL_FLYING_COLLECTIBLE_TYPES) {
397
- permanentFlyingCollectibleTypes.delete(collectibleType);
398
- }
399
- for (const collectibleType of permanentFlyingCollectibleTypes) {
400
- this.permanentFlyingCollectibleTypesSet.add(collectibleType);
401
- }
402
388
  }
403
389
 
404
390
  private lazyInitFlyingTrinketTypesSet() {
405
391
  // Instead of manually compiling a list of trinkets that grant flying, we can instead
406
- // dynamically look for collectibles that have `CacheFlag.FLYING`.
407
- this.flyingTrinketTypesSet = copySet(
408
- this.getTrinketsTypesWithCacheFlag(CacheFlag.FLYING),
392
+ // dynamically look for collectibles that have `CacheFlag.FLYING`. But none of the trinkets with
393
+ // `CacheFlag.ALL` grant flying except for Azazel's Stump, so we can safely remove them from the
394
+ // list.
395
+ const trinketTypesWithFlyingCacheFlag = this.getTrinketsTypesWithCacheFlag(
396
+ CacheFlag.FLYING,
409
397
  );
410
-
411
- // None of the trinkets with `CacheFlag.ALL` grant flying except for Azazel's Stump, so we can
412
- // safely remove them from the list.
413
- const trinketsWithAllCacheFlag = copySet(
414
- this.getTrinketsTypesWithCacheFlag(CacheFlag.ALL),
398
+ const trinketTypesWithAllCacheFlag = this.getTrinketsTypesWithCacheFlag(
399
+ CacheFlag.ALL,
400
+ );
401
+ const trinketTypesWithAllCacheFlagThatDontGrantFlying = arrayRemove(
402
+ trinketTypesWithAllCacheFlag,
403
+ TrinketType.AZAZELS_STUMP,
404
+ );
405
+ this.flyingTrinketTypes = arrayRemove(
406
+ trinketTypesWithFlyingCacheFlag,
407
+ ...trinketTypesWithAllCacheFlagThatDontGrantFlying,
415
408
  );
416
- trinketsWithAllCacheFlag.delete(TrinketType.AZAZELS_STUMP);
417
- deleteSetsFromSet(this.flyingTrinketTypesSet, trinketsWithAllCacheFlag);
418
409
  }
419
410
 
420
411
  private lazyInitEdenCollectibleTypesSet() {
@@ -438,43 +429,43 @@ export class ModdedElementSets extends Feature {
438
429
 
439
430
  private lazyInitQualityToCollectibleTypesMap() {
440
431
  for (const quality of QUALITIES) {
441
- const collectibleTypesSet = new Set<CollectibleType>();
432
+ const collectibleTypes: CollectibleType[] = [];
442
433
 
443
434
  for (const collectibleType of this.getCollectibleTypes()) {
444
435
  const collectibleTypeQuality = getCollectibleQuality(collectibleType);
445
436
  if (collectibleTypeQuality === quality) {
446
- collectibleTypesSet.add(collectibleType);
437
+ collectibleTypes.push(collectibleType);
447
438
  }
448
439
  }
449
440
 
450
- this.qualityToCollectibleTypesMap.set(quality, collectibleTypesSet);
441
+ this.qualityToCollectibleTypesMap.set(quality, collectibleTypes);
451
442
  }
452
443
  }
453
444
 
454
445
  private lazyInitCardTypes() {
455
446
  // The card type to cards map should be valid for every card type, so we initialize it with
456
- // empty sets.
447
+ // empty arrays.
457
448
  for (const itemConfigCardType of ITEM_CONFIG_CARD_TYPE_VALUES) {
458
449
  this.itemConfigCardTypeToCardTypeMap.set(
459
450
  itemConfigCardType,
460
- new Set<CardType>(),
451
+ [] as CardType[],
461
452
  );
462
453
  }
463
454
 
464
455
  for (const cardType of this.getCardTypes()) {
465
456
  const itemConfigCardType = getItemConfigCardType(cardType);
466
457
  if (itemConfigCardType !== undefined) {
467
- const cardTypeSet =
458
+ const cardTypes =
468
459
  this.itemConfigCardTypeToCardTypeMap.get(itemConfigCardType);
469
460
  assertDefined(
470
- cardTypeSet,
471
- `Failed to get the card set for item config card type: ${itemConfigCardType}`,
461
+ cardTypes,
462
+ `Failed to get the card types for item config card type: ${itemConfigCardType}`,
472
463
  );
473
464
 
474
- cardTypeSet.add(cardType);
465
+ cardTypes.push(cardType);
475
466
 
476
- if (ITEM_CONFIG_CARD_TYPES_FOR_CARDS_SET.has(itemConfigCardType)) {
477
- this.cardSet.add(cardType);
467
+ if (ITEM_CONFIG_CARD_TYPES_FOR_CARDS.has(itemConfigCardType)) {
468
+ this.cardTypeCardArray.push(cardType);
478
469
  }
479
470
  }
480
471
  }
@@ -886,12 +877,12 @@ export class ModdedElementSets extends Feature {
886
877
  @Exported
887
878
  public getCollectibleTypesWithCacheFlag(
888
879
  cacheFlag: CacheFlag,
889
- ): ReadonlySet<CollectibleType> {
880
+ ): readonly CollectibleType[] {
890
881
  this.lazyInit();
891
882
 
892
883
  const collectiblesSet = this.cacheFlagToCollectibleTypesMap.get(cacheFlag);
893
884
  if (collectiblesSet === undefined) {
894
- return new ReadonlySet();
885
+ return [];
895
886
  }
896
887
 
897
888
  return collectiblesSet;
@@ -912,15 +903,15 @@ export class ModdedElementSets extends Feature {
912
903
  @Exported
913
904
  public getTrinketsTypesWithCacheFlag(
914
905
  cacheFlag: CacheFlag,
915
- ): ReadonlySet<TrinketType> {
906
+ ): readonly TrinketType[] {
916
907
  this.lazyInit();
917
908
 
918
- const trinketsSet = this.cacheFlagToTrinketTypesMap.get(cacheFlag);
919
- if (trinketsSet === undefined) {
920
- return new ReadonlySet();
909
+ const trinketTypes = this.cacheFlagToTrinketTypesMap.get(cacheFlag);
910
+ if (trinketTypes === undefined) {
911
+ return [];
921
912
  }
922
913
 
923
- return trinketsSet;
914
+ return trinketTypes;
924
915
  }
925
916
 
926
917
  /**
@@ -953,14 +944,12 @@ export class ModdedElementSets extends Feature {
953
944
  public getPlayerCollectiblesWithCacheFlag(
954
945
  player: EntityPlayer,
955
946
  cacheFlag: CacheFlag,
956
- ): CollectibleType[] {
947
+ ): readonly CollectibleType[] {
957
948
  const collectiblesWithCacheFlag =
958
949
  this.getCollectibleTypesWithCacheFlag(cacheFlag);
959
950
 
960
951
  const playerCollectibles: CollectibleType[] = [];
961
- for (const collectibleType of getSortedSetValues(
962
- collectiblesWithCacheFlag,
963
- )) {
952
+ for (const collectibleType of collectiblesWithCacheFlag) {
964
953
  // We specify "true" as the second argument to filter out things like Lilith's Incubus.
965
954
  const numCollectibles = player.GetCollectibleNum(collectibleType, true);
966
955
  repeat(numCollectibles, () => {
@@ -1027,12 +1016,12 @@ export class ModdedElementSets extends Feature {
1027
1016
  @Exported
1028
1017
  public getFlyingCollectibleTypes(
1029
1018
  includeConditionalItems: boolean,
1030
- ): ReadonlySet<CollectibleType> {
1019
+ ): readonly CollectibleType[] {
1031
1020
  this.lazyInit();
1032
1021
 
1033
1022
  return includeConditionalItems
1034
- ? this.flyingCollectibleTypesSet
1035
- : this.permanentFlyingCollectibleTypesSet;
1023
+ ? this.flyingCollectibleTypes
1024
+ : this.permanentFlyingCollectibleTypes;
1036
1025
  }
1037
1026
 
1038
1027
  /**
@@ -1052,9 +1041,9 @@ export class ModdedElementSets extends Feature {
1052
1041
  * @public
1053
1042
  */
1054
1043
  @Exported
1055
- public getFlyingTrinketTypes(): ReadonlySet<TrinketType> {
1044
+ public getFlyingTrinketTypes(): readonly TrinketType[] {
1056
1045
  this.lazyInit();
1057
- return this.flyingTrinketTypesSet;
1046
+ return this.flyingTrinketTypes;
1058
1047
  }
1059
1048
 
1060
1049
  // ----------------
@@ -1082,7 +1071,7 @@ export class ModdedElementSets extends Feature {
1082
1071
  @Exported
1083
1072
  public getCollectibleTypesWithTag(
1084
1073
  itemConfigTag: ItemConfigTag,
1085
- ): ReadonlySet<CollectibleType> {
1074
+ ): readonly CollectibleType[] {
1086
1075
  this.lazyInit();
1087
1076
 
1088
1077
  const collectibleTypes = this.tagToCollectibleTypesMap.get(itemConfigTag);
@@ -1109,12 +1098,12 @@ export class ModdedElementSets extends Feature {
1109
1098
  public getPlayerCollectiblesWithTag(
1110
1099
  player: EntityPlayer,
1111
1100
  itemConfigTag: ItemConfigTag,
1112
- ): CollectibleType[] {
1101
+ ): readonly CollectibleType[] {
1113
1102
  const collectibleTypesWithTag =
1114
1103
  this.getCollectibleTypesWithTag(itemConfigTag);
1115
1104
 
1116
1105
  const playerCollectibles: CollectibleType[] = [];
1117
- for (const collectibleType of getSortedSetValues(collectibleTypesWithTag)) {
1106
+ for (const collectibleType of collectibleTypesWithTag) {
1118
1107
  // We specify "true" as the second argument to filter out things like Lilith's Incubus.
1119
1108
  const numCollectibles = player.GetCollectibleNum(collectibleType, true);
1120
1109
  repeat(numCollectibles, () => {
@@ -1146,7 +1135,7 @@ export class ModdedElementSets extends Feature {
1146
1135
  @Exported
1147
1136
  public getCollectibleTypesForTransformation(
1148
1137
  playerForm: PlayerForm,
1149
- ): ReadonlySet<CollectibleType> {
1138
+ ): readonly CollectibleType[] {
1150
1139
  const itemConfigTag = TRANSFORMATION_TO_TAG_MAP.get(playerForm);
1151
1140
  assertDefined(
1152
1141
  itemConfigTag,
@@ -1172,14 +1161,12 @@ export class ModdedElementSets extends Feature {
1172
1161
  public getPlayerCollectiblesForTransformation(
1173
1162
  player: EntityPlayer,
1174
1163
  playerForm: PlayerForm,
1175
- ): CollectibleType[] {
1164
+ ): readonly CollectibleType[] {
1176
1165
  const collectibleForTransformation =
1177
1166
  this.getCollectibleTypesForTransformation(playerForm);
1178
1167
 
1179
1168
  const playerCollectibles: CollectibleType[] = [];
1180
- for (const collectibleType of getSortedSetValues(
1181
- collectibleForTransformation,
1182
- )) {
1169
+ for (const collectibleType of collectibleForTransformation) {
1183
1170
  // We specify "true" as the second argument to filter out things like Lilith's Incubus.
1184
1171
  const numCollectibles = player.GetCollectibleNum(collectibleType, true);
1185
1172
  repeat(numCollectibles, () => {
@@ -1300,7 +1287,7 @@ export class ModdedElementSets extends Feature {
1300
1287
  // -------------------
1301
1288
 
1302
1289
  /**
1303
- * Returns a set containing every collectible type with the given quality.
1290
+ * Returns an array containing every collectible type with the given quality.
1304
1291
  *
1305
1292
  * This function can only be called if at least one callback has been executed. This is because
1306
1293
  * not all collectible types will necessarily be present when a mod first loads (due to mod load
@@ -1313,7 +1300,7 @@ export class ModdedElementSets extends Feature {
1313
1300
  @Exported
1314
1301
  public getCollectibleTypesOfQuality(
1315
1302
  quality: Quality,
1316
- ): ReadonlySet<CollectibleType> {
1303
+ ): readonly CollectibleType[] {
1317
1304
  this.lazyInit();
1318
1305
 
1319
1306
  const collectibleTypes = this.qualityToCollectibleTypesMap.get(quality);
@@ -1340,22 +1327,20 @@ export class ModdedElementSets extends Feature {
1340
1327
  public getPlayerCollectiblesOfQuality(
1341
1328
  player: EntityPlayer,
1342
1329
  quality: Quality,
1343
- ): CollectibleType[] {
1330
+ ): readonly CollectibleType[] {
1344
1331
  const collectibleTypesOfQuality =
1345
1332
  this.getCollectibleTypesOfQuality(quality);
1346
1333
 
1347
- const playerCollectibles: CollectibleType[] = [];
1348
- for (const collectibleType of getSortedSetValues(
1349
- collectibleTypesOfQuality,
1350
- )) {
1334
+ const playerCollectibleTypes: CollectibleType[] = [];
1335
+ for (const collectibleType of collectibleTypesOfQuality) {
1351
1336
  // We specify "true" as the second argument to filter out things like Lilith's Incubus.
1352
1337
  const numCollectibles = player.GetCollectibleNum(collectibleType, true);
1353
1338
  repeat(numCollectibles, () => {
1354
- playerCollectibles.push(collectibleType);
1339
+ playerCollectibleTypes.push(collectibleType);
1355
1340
  });
1356
1341
  }
1357
1342
 
1358
- return playerCollectibles;
1343
+ return playerCollectibleTypes;
1359
1344
  }
1360
1345
 
1361
1346
  // ----------------------
@@ -1363,9 +1348,9 @@ export class ModdedElementSets extends Feature {
1363
1348
  // ----------------------
1364
1349
 
1365
1350
  /**
1366
- * Helper function to get a set of card types matching the `ItemConfigCardType`.
1351
+ * Helper function to get an array of card types matching the `ItemConfigCardType`.
1367
1352
  *
1368
- * This function is variadic, meaning that you can you can specify N card types to get a set
1353
+ * This function is variadic, meaning that you can you can specify N card types to get an array
1369
1354
  * containing cards that match any of the specified types.
1370
1355
  *
1371
1356
  * This function can only be called if at least one callback has been executed. This is because
@@ -1378,20 +1363,20 @@ export class ModdedElementSets extends Feature {
1378
1363
  @Exported
1379
1364
  public getCardTypesOfType(
1380
1365
  ...itemConfigCardTypes: ItemConfigCardType[]
1381
- ): Set<CardType> {
1366
+ ): readonly CardType[] {
1382
1367
  this.lazyInit();
1383
1368
 
1384
- const matchingCardTypes = new Set<CardType>();
1369
+ const matchingCardTypes: CardType[] = [];
1385
1370
  for (const itemConfigCardType of itemConfigCardTypes) {
1386
- const cardTypeSet =
1371
+ const cardTypes =
1387
1372
  this.itemConfigCardTypeToCardTypeMap.get(itemConfigCardType);
1388
1373
  assertDefined(
1389
- cardTypeSet,
1390
- `Failed to get the card type set for item config type: ${itemConfigCardType}`,
1374
+ cardTypes,
1375
+ `Failed to get the card types for item config type: ${itemConfigCardType}`,
1391
1376
  );
1392
1377
 
1393
- for (const cardType of cardTypeSet) {
1394
- matchingCardTypes.add(cardType);
1378
+ for (const cardType of cardTypes) {
1379
+ matchingCardTypes.push(cardType);
1395
1380
  }
1396
1381
  }
1397
1382
 
@@ -1423,8 +1408,8 @@ export class ModdedElementSets extends Feature {
1423
1408
  seedOrRNG: Seed | RNG | undefined,
1424
1409
  exceptions: CardType[] = [],
1425
1410
  ): CardType {
1426
- const cardTypeSet = this.getCardTypesOfType(itemConfigCardType);
1427
- return getRandomSetElement(cardTypeSet, seedOrRNG, exceptions);
1411
+ const cardTypes = this.getCardTypesOfType(itemConfigCardType);
1412
+ return getRandomArrayElement(cardTypes, seedOrRNG, exceptions);
1428
1413
  }
1429
1414
 
1430
1415
  /**
@@ -1454,7 +1439,7 @@ export class ModdedElementSets extends Feature {
1454
1439
  exceptions: CardType[] = [],
1455
1440
  ): CardType {
1456
1441
  this.lazyInit();
1457
- return getRandomSetElement(this.cardSet, seedOrRNG, exceptions);
1442
+ return getRandomArrayElement(this.cardTypeCardArray, seedOrRNG, exceptions);
1458
1443
  }
1459
1444
 
1460
1445
  /**
@@ -1480,8 +1465,8 @@ export class ModdedElementSets extends Feature {
1480
1465
  seedOrRNG: Seed | RNG | undefined,
1481
1466
  exceptions: CardType[] = [],
1482
1467
  ): CardType {
1483
- const runesSet = this.getCardTypesOfType(ItemConfigCardType.RUNE);
1484
- runesSet.delete(CardType.RUNE_SHARD);
1485
- return getRandomSetElement(runesSet, seedOrRNG, exceptions);
1468
+ const runeCardTypes = this.getCardTypesOfType(ItemConfigCardType.RUNE);
1469
+ exceptions.push(CardType.RUNE_SHARD);
1470
+ return getRandomArrayElement(runeCardTypes, seedOrRNG, exceptions);
1486
1471
  }
1487
1472
  }
@@ -24,9 +24,9 @@ export function arrayEquals<T>(
24
24
  }
25
25
 
26
26
  /**
27
- * Shallow copies and removes the specified element(s) from the array. Returns the copied array. If
28
- * the specified element(s) are not found in the array, it will simply return a shallow copy of the
29
- * array.
27
+ * Builds a new array based on the original array without the specified element(s). Returns the new
28
+ * array. If the specified element(s) are not found in the array, it will simply return a shallow
29
+ * copy of the array.
30
30
  *
31
31
  * This function is variadic, meaning that you can specify N arguments to remove N elements.
32
32
  *
@@ -38,8 +38,15 @@ export function arrayRemove<T>(
38
38
  originalArray: T[] | readonly T[],
39
39
  ...elementsToRemove: T[]
40
40
  ): T[] {
41
- const array = copyArray(originalArray);
42
- arrayRemoveInPlace(array, ...elementsToRemove);
41
+ const elementsToRemoveSet = new ReadonlySet(elementsToRemove);
42
+
43
+ const array: T[] = [];
44
+ for (const element of originalArray) {
45
+ if (!elementsToRemoveSet.has(element)) {
46
+ array.push(element);
47
+ }
48
+ }
49
+
43
50
  return array;
44
51
  }
45
52
 
@@ -8,7 +8,7 @@ import {
8
8
  DEFAULT_CARD_DESCRIPTION,
9
9
  } from "../objects/cardDescriptions";
10
10
  import { CARD_NAMES, DEFAULT_CARD_NAME } from "../objects/cardNames";
11
- import { ITEM_CONFIG_CARD_TYPES_FOR_CARDS_SET } from "../sets/itemConfigCardTypesForCardsSet";
11
+ import { ITEM_CONFIG_CARD_TYPES_FOR_CARDS } from "../sets/itemConfigCardTypesForCards";
12
12
  import { addFlag } from "./flag";
13
13
 
14
14
  /**
@@ -112,7 +112,7 @@ export function isCard(cardType: CardType): boolean {
112
112
  return false;
113
113
  }
114
114
 
115
- return ITEM_CONFIG_CARD_TYPES_FOR_CARDS_SET.has(itemConfigCardType);
115
+ return ITEM_CONFIG_CARD_TYPES_FOR_CARDS.has(itemConfigCardType);
116
116
  }
117
117
 
118
118
  /** Returns whether the given card type matches the specified item config card type. */
@@ -47,21 +47,21 @@ const GLITCHED_ITEM_THRESHOLD = 4_000_000_000;
47
47
 
48
48
  const QUALITY_TO_VANILLA_COLLECTIBLE_TYPES_MAP: ReadonlyMap<
49
49
  Quality,
50
- ReadonlySet<CollectibleType>
50
+ CollectibleType[]
51
51
  > = (() => {
52
- const qualityToCollectibleTypesMap = new Map<Quality, Set<CollectibleType>>();
52
+ const qualityToCollectibleTypesMap = new Map<Quality, CollectibleType[]>();
53
53
 
54
54
  for (const quality of QUALITIES) {
55
- const collectibleTypesSet = new Set<CollectibleType>();
55
+ const collectibleTypes: CollectibleType[] = [];
56
56
 
57
57
  for (const collectibleType of VANILLA_COLLECTIBLE_TYPES) {
58
58
  const collectibleTypeQuality = getCollectibleQuality(collectibleType);
59
59
  if (collectibleTypeQuality === quality) {
60
- collectibleTypesSet.add(collectibleType);
60
+ collectibleTypes.push(collectibleType);
61
61
  }
62
62
  }
63
63
 
64
- qualityToCollectibleTypesMap.set(quality, collectibleTypesSet);
64
+ qualityToCollectibleTypesMap.set(quality, collectibleTypes);
65
65
  }
66
66
 
67
67
  return qualityToCollectibleTypesMap;
@@ -433,14 +433,14 @@ export function getCollectibleTags(
433
433
  }
434
434
 
435
435
  /**
436
- * Returns a set containing every vanilla collectible type with the given quality.
436
+ * Returns an array containing every vanilla collectible type with the given quality.
437
437
  *
438
438
  * Note that this function will only return vanilla collectible types. To handle modded collectible
439
439
  * types, use the `getCollectibleTypesOfQuality` helper function instead.
440
440
  */
441
441
  export function getVanillaCollectibleTypesOfQuality(
442
442
  quality: Quality,
443
- ): ReadonlySet<CollectibleType> {
443
+ ): readonly CollectibleType[] {
444
444
  const collectibleTypes =
445
445
  QUALITY_TO_VANILLA_COLLECTIBLE_TYPES_MAP.get(quality);
446
446
  assertDefined(
@@ -44,7 +44,7 @@ const HORSE_PILL_ADJUSTMENT = 2048;
44
44
  * Helper function to get an array with every non-null pill color. This includes all gold colors and
45
45
  * all horse colors.
46
46
  */
47
- export function getAllPillColors(): PillColor[] {
47
+ export function getAllPillColors(): readonly PillColor[] {
48
48
  return PILL_COLOR_VALUES.slice(1); // Remove `PillColor.NULL`
49
49
  }
50
50
 
@@ -68,7 +68,7 @@ export function getHorsePillColor(pillColor: PillColor): PillColor {
68
68
  }
69
69
 
70
70
  /** Helper function to get an array with every non-gold horse pill color. */
71
- export function getHorsePillColors(): PillColor[] {
71
+ export function getHorsePillColors(): readonly PillColor[] {
72
72
  return iRange(FIRST_HORSE_PILL_COLOR, LAST_HORSE_PILL_COLOR);
73
73
  }
74
74
 
@@ -88,7 +88,7 @@ export function getNormalPillColorFromHorse(pillColor: PillColor): PillColor {
88
88
  }
89
89
 
90
90
  /** Helper function to get an array with every non-gold and non-horse pill color. */
91
- export function getNormalPillColors(): PillColor[] {
91
+ export function getNormalPillColors(): readonly PillColor[] {
92
92
  return iRange(FIRST_PILL_COLOR, LAST_NORMAL_PILL_COLOR);
93
93
  }
94
94
 
@@ -76,7 +76,9 @@ export function getOpenTrinketSlot(player: EntityPlayer): int | undefined {
76
76
  * Helper function to get all of the trinkets that the player is currently holding. This will not
77
77
  * include any smelted trinkets.
78
78
  */
79
- export function getPlayerTrinkets(player: EntityPlayer): TrinketType[] {
79
+ export function getPlayerTrinkets(
80
+ player: EntityPlayer,
81
+ ): readonly TrinketType[] {
80
82
  const trinketTypes: TrinketType[] = [];
81
83
 
82
84
  for (const trinketSlot of TRINKET_SLOT_VALUES) {