isaacscript-common 80.2.1 → 80.2.3

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 (65) hide show
  1. package/dist/classes/ModUpgraded.d.ts.map +1 -1
  2. package/dist/classes/ModUpgraded.lua +18 -8
  3. package/dist/classes/features/other/DeployJSONRoom.lua +11 -10
  4. package/dist/classes/features/other/extraConsoleCommands/commands.d.ts +1 -1
  5. package/dist/classes/features/other/extraConsoleCommands/commands.d.ts.map +1 -1
  6. package/dist/classes/features/other/extraConsoleCommands/commands.lua +104 -102
  7. package/dist/classes/features/other/extraConsoleCommands/subroutines.d.ts.map +1 -1
  8. package/dist/classes/features/other/extraConsoleCommands/subroutines.lua +6 -4
  9. package/dist/core/constantsFirstLast.d.ts +4 -26
  10. package/dist/core/constantsFirstLast.d.ts.map +1 -1
  11. package/dist/core/constantsFirstLast.lua +0 -18
  12. package/dist/functions/cards.d.ts +1 -0
  13. package/dist/functions/cards.d.ts.map +1 -1
  14. package/dist/functions/cards.lua +7 -0
  15. package/dist/functions/collectibles.d.ts +1 -1
  16. package/dist/functions/collectibles.d.ts.map +1 -1
  17. package/dist/functions/collectibles.lua +3 -1
  18. package/dist/functions/doors.d.ts.map +1 -1
  19. package/dist/functions/doors.lua +14 -4
  20. package/dist/functions/entities.d.ts.map +1 -1
  21. package/dist/functions/entities.lua +19 -30
  22. package/dist/functions/gridEntities.d.ts.map +1 -1
  23. package/dist/functions/gridEntities.lua +8 -13
  24. package/dist/functions/jsonRoom.d.ts.map +1 -1
  25. package/dist/functions/jsonRoom.lua +13 -5
  26. package/dist/functions/pills.d.ts +1 -0
  27. package/dist/functions/pills.d.ts.map +1 -1
  28. package/dist/functions/pills.lua +6 -0
  29. package/dist/functions/run.d.ts +1 -2
  30. package/dist/functions/run.d.ts.map +1 -1
  31. package/dist/functions/run.lua +2 -3
  32. package/dist/functions/string.d.ts.map +1 -1
  33. package/dist/functions/string.lua +5 -3
  34. package/dist/functions/table.d.ts +3 -2
  35. package/dist/functions/table.d.ts.map +1 -1
  36. package/dist/functions/table.lua +3 -2
  37. package/dist/functions/trinkets.d.ts +1 -0
  38. package/dist/functions/trinkets.d.ts.map +1 -1
  39. package/dist/functions/trinkets.lua +6 -0
  40. package/dist/functions/types.d.ts +9 -0
  41. package/dist/functions/types.d.ts.map +1 -1
  42. package/dist/functions/types.lua +17 -0
  43. package/dist/index.rollup.d.ts +23 -32
  44. package/dist/isaacscript-common.lua +254 -207
  45. package/dist/lualib_bundle.lua +5 -0
  46. package/dist/objects/itemPoolTypeToCollectibleTypesSet.lua +4 -3
  47. package/package.json +2 -2
  48. package/src/classes/ModUpgraded.ts +18 -4
  49. package/src/classes/features/other/DeployJSONRoom.ts +11 -11
  50. package/src/classes/features/other/extraConsoleCommands/commands.ts +124 -118
  51. package/src/classes/features/other/extraConsoleCommands/subroutines.ts +5 -4
  52. package/src/core/constantsFirstLast.ts +3 -37
  53. package/src/functions/cards.ts +7 -0
  54. package/src/functions/collectibles.ts +5 -4
  55. package/src/functions/doors.ts +8 -3
  56. package/src/functions/entities.ts +40 -19
  57. package/src/functions/gridEntities.ts +15 -5
  58. package/src/functions/jsonRoom.ts +18 -5
  59. package/src/functions/pills.ts +7 -1
  60. package/src/functions/run.ts +6 -4
  61. package/src/functions/string.ts +4 -3
  62. package/src/functions/table.ts +3 -2
  63. package/src/functions/trinkets.ts +9 -1
  64. package/src/functions/types.ts +25 -0
  65. package/src/objects/itemPoolTypeToCollectibleTypesSet.ts +4 -4
@@ -39,8 +39,6 @@ eslint "sort-exports/sort-exports": [
39
39
  import type {
40
40
  CardType,
41
41
  PillEffect,
42
- PlayerType,
43
- SoundEffect,
44
42
  TrinketType,
45
43
  } from "isaac-typescript-definitions";
46
44
  import {
@@ -56,13 +54,12 @@ import {
56
54
  GridRoom,
57
55
  LevelStage,
58
56
  PillColor,
57
+ PlayerType,
59
58
  RoomType,
59
+ SoundEffect,
60
60
  StageType,
61
61
  } from "isaac-typescript-definitions";
62
- import {
63
- ACTIVE_SLOT_VALUES,
64
- GRID_ENTITY_TYPE_VALUES,
65
- } from "../../../../arrays/cachedEnumValues";
62
+ import { GRID_ENTITY_TYPE_VALUES } from "../../../../arrays/cachedEnumValues";
66
63
  import { game, sfxManager } from "../../../../core/cachedClasses";
67
64
  import {
68
65
  DOGMA_ROOM_GRID_INDEX,
@@ -71,26 +68,19 @@ import {
71
68
  } from "../../../../core/constants";
72
69
  import {
73
70
  FIRST_CARD_TYPE,
74
- FIRST_CHARACTER,
75
71
  FIRST_HORSE_PILL_COLOR,
76
72
  FIRST_PILL_COLOR,
77
- FIRST_PILL_EFFECT,
78
- FIRST_ROOM_TYPE,
79
- FIRST_STAGE,
80
- LAST_ROOM_TYPE,
81
- LAST_STAGE,
82
73
  LAST_VANILLA_CARD_TYPE,
83
- LAST_VANILLA_CHARACTER,
84
- LAST_VANILLA_PILL_EFFECT,
85
74
  } from "../../../../core/constantsFirstLast";
86
75
  import { HealthType } from "../../../../enums/HealthType";
87
- import { getCardName } from "../../../../functions/cards";
76
+ import { getCardName, isValidCardType } from "../../../../functions/cards";
88
77
  import { getCharacterName } from "../../../../functions/characters";
89
78
  import { addCharge, getTotalCharge } from "../../../../functions/charge";
90
79
  import { isValidCollectibleType } from "../../../../functions/collectibles";
91
80
  import { printEnabled } from "../../../../functions/console";
92
81
  import { runDeepCopyTests } from "../../../../functions/deepCopyTests";
93
82
  import { getNPCs } from "../../../../functions/entitiesSpecific";
83
+ import { isEnumValue } from "../../../../functions/enums";
94
84
  import { addFlag } from "../../../../functions/flag";
95
85
  import { spawnGridEntity } from "../../../../functions/gridEntities";
96
86
  import { getRoomGridIndexesForType } from "../../../../functions/levelGrid";
@@ -107,7 +97,10 @@ import {
107
97
  spawnPill,
108
98
  spawnTrinket as spawnTrinketFunction,
109
99
  } from "../../../../functions/pickupsSpecific";
110
- import { getPillEffectName } from "../../../../functions/pills";
100
+ import {
101
+ getPillEffectName,
102
+ isValidPillEffect,
103
+ } from "../../../../functions/pills";
111
104
  import {
112
105
  addCollectibleCostume,
113
106
  removeCollectibleCostume,
@@ -123,8 +116,11 @@ import { onSetSeed, restart, setUnseeded } from "../../../../functions/run";
123
116
  import { spawnCollectible as spawnCollectibleFunc } from "../../../../functions/spawnCollectible";
124
117
  import { onStage, setStage } from "../../../../functions/stage";
125
118
  import { getMapPartialMatch } from "../../../../functions/string";
126
- import { getGoldenTrinketType } from "../../../../functions/trinkets";
127
- import { asCollectibleType, asTrinketType } from "../../../../functions/types";
119
+ import {
120
+ getGoldenTrinketType,
121
+ isValidTrinketType,
122
+ } from "../../../../functions/trinkets";
123
+ import { parseIntSafe } from "../../../../functions/types";
128
124
  import { iRange } from "../../../../functions/utils";
129
125
  import { CARD_NAME_TO_TYPE_MAP } from "../../../../maps/cardNameToTypeMap";
130
126
  import { CHARACTER_NAME_TO_TYPE_MAP } from "../../../../maps/characterNameToTypeMap";
@@ -161,31 +157,27 @@ export function addCharges(params: string): void {
161
157
  const args = params.split(" ");
162
158
 
163
159
  if (args.length !== 1 && args.length !== 2) {
164
- print("That is an invalid amount of arguments.");
160
+ print(`Invalid amount of arguments: ${args.length}`);
165
161
  return;
166
162
  }
167
163
 
168
164
  const [activeSlotString, numChargeString] = args;
169
165
 
170
- const activeSlot = tonumber(activeSlotString) as ActiveSlot | undefined;
171
- if (activeSlot === undefined) {
172
- print(`The provided slot number is invalid: ${activeSlotString}`);
166
+ if (activeSlotString === undefined) {
173
167
  return;
174
168
  }
175
169
 
176
- if (
177
- activeSlot < ActiveSlot.PRIMARY ||
178
- activeSlot > ActiveSlot.POCKET_SINGLE_USE
179
- ) {
180
- print(`The provided slot number is invalid: ${activeSlot}`);
170
+ const activeSlot = parseIntSafe(activeSlotString);
171
+ if (activeSlot === undefined || !isEnumValue(activeSlot, ActiveSlot)) {
172
+ print(`Invalid slot number: ${activeSlot}`);
181
173
  return;
182
174
  }
183
175
 
184
176
  let numCharges = 1;
185
177
  if (numChargeString !== undefined) {
186
- const numChargesAttempt = tonumber(numChargeString);
178
+ const numChargesAttempt = parseIntSafe(numChargeString);
187
179
  if (numChargesAttempt === undefined) {
188
- print(`The provided charge amount is invalid: ${numChargeString}`);
180
+ print(`Invalid charge amount: ${numChargeString}`);
189
181
  return;
190
182
  }
191
183
  numCharges = numChargesAttempt;
@@ -258,9 +250,9 @@ export function blind(): void {
258
250
  export function bloodCharges(params: string): void {
259
251
  let charges = 1;
260
252
  if (params !== "") {
261
- const num = tonumber(params);
253
+ const num = parseIntSafe(params);
262
254
  if (num === undefined) {
263
- print("That is an invalid amount of charges to add.");
255
+ print(`Invalid charge amount: ${num}`);
264
256
  return;
265
257
  }
266
258
 
@@ -283,9 +275,9 @@ export function bm(): void {
283
275
  export function bomb(params: string): void {
284
276
  let numBombs = 1;
285
277
  if (params !== "") {
286
- const num = tonumber(params);
278
+ const num = parseIntSafe(params);
287
279
  if (num === undefined) {
288
- print("That is an invalid amount of bombs to add.");
280
+ print(`Invalid bomb amount: ${num}`);
289
281
  return;
290
282
  }
291
283
 
@@ -303,9 +295,9 @@ export function bomb(params: string): void {
303
295
  export function bombs(params: string): void {
304
296
  let numBombs = 99;
305
297
  if (params !== "") {
306
- const num = tonumber(params);
298
+ const num = parseIntSafe(params);
307
299
  if (num === undefined) {
308
- print("That is an invalid amount of bombs to add.");
300
+ print(`Invalid bomb amount: ${num}`);
309
301
  return;
310
302
  }
311
303
 
@@ -373,7 +365,7 @@ export function brokenHearts(params: string): void {
373
365
  }
374
366
 
375
367
  /**
376
- * Gives the specified card. Accepts either the card sub-type or the partial name of the card.
368
+ * Gives the specified card. Accepts either the card type or the partial name of the card.
377
369
  *
378
370
  * For example:
379
371
  * - card 5 - Gives The Emperor.
@@ -386,7 +378,7 @@ export function card(params: string): void {
386
378
  }
387
379
 
388
380
  let cardType: CardType;
389
- const num = tonumber(params) as CardType | undefined;
381
+ const num = parseIntSafe(params);
390
382
  if (num === undefined) {
391
383
  const match = getMapPartialMatch(params, CARD_NAME_TO_TYPE_MAP);
392
384
  if (match === undefined) {
@@ -396,8 +388,8 @@ export function card(params: string): void {
396
388
 
397
389
  cardType = match[1];
398
390
  } else {
399
- if (num < FIRST_CARD_TYPE || num > LAST_VANILLA_CARD_TYPE) {
400
- print(`Invalid card sub-type: ${num}`);
391
+ if (!isValidCardType(num)) {
392
+ print(`Invalid card type: ${num}`);
401
393
  return;
402
394
  }
403
395
 
@@ -454,7 +446,7 @@ export function character(params: string): void {
454
446
  }
455
447
 
456
448
  let playerType: PlayerType;
457
- const num = tonumber(params) as PlayerType | undefined;
449
+ const num = parseIntSafe(params);
458
450
  if (num === undefined) {
459
451
  const match = getMapPartialMatch(params, CHARACTER_NAME_TO_TYPE_MAP);
460
452
  if (match === undefined) {
@@ -464,7 +456,7 @@ export function character(params: string): void {
464
456
 
465
457
  playerType = match[1];
466
458
  } else {
467
- if (num < FIRST_CHARACTER || num > LAST_VANILLA_CHARACTER) {
459
+ if (!isEnumValue(num, PlayerType) || num === PlayerType.POSSESSOR) {
468
460
  print(`Invalid character number: ${num}`);
469
461
  return;
470
462
  }
@@ -494,9 +486,9 @@ export function cleanBedroom(): void {
494
486
  export function coin(params: string): void {
495
487
  let numCoins = 1;
496
488
  if (params !== "") {
497
- const num = tonumber(params);
489
+ const num = parseIntSafe(params);
498
490
  if (num === undefined) {
499
- print("That is an invalid amount of coins to add.");
491
+ print(`Invalid coin amount: ${num}`);
500
492
  return;
501
493
  }
502
494
 
@@ -514,9 +506,9 @@ export function coin(params: string): void {
514
506
  export function coins(params: string): void {
515
507
  let numCoins = 999;
516
508
  if (params !== "") {
517
- const num = tonumber(params);
509
+ const num = parseIntSafe(params);
518
510
  if (num === undefined) {
519
- print("That is an invalid amount of coins to add.");
511
+ print(`Invalid coin amount: ${num}`);
520
512
  return;
521
513
  }
522
514
 
@@ -568,9 +560,9 @@ export function dadsNote(): void {
568
560
  */
569
561
  export function damage(params: string): void {
570
562
  if (params !== "") {
571
- const num = tonumber(params);
563
+ const num = tonumber(params); // Can be a float.
572
564
  if (num === undefined) {
573
- print(`The provided damage amount is invalid: ${params}`);
565
+ print(`Invalid damage amount: ${params}`);
574
566
  return;
575
567
  }
576
568
 
@@ -706,9 +698,9 @@ export function getChallenge(): void {
706
698
  export function getCharge(params: string): void {
707
699
  let activeSlot = ActiveSlot.PRIMARY;
708
700
  if (params !== "") {
709
- const num = tonumber(params) as ActiveSlot | undefined;
710
- if (num === undefined) {
711
- print(`The provided slot number is invalid: ${params}`);
701
+ const num = parseIntSafe(params);
702
+ if (num === undefined || !isEnumValue(num, ActiveSlot)) {
703
+ print(`Invalid slot number: ${params}`);
712
704
  return;
713
705
  }
714
706
 
@@ -745,9 +737,9 @@ export function giant(): void {
745
737
  export function gigaBomb(params: string): void {
746
738
  let numBombs = 1;
747
739
  if (params !== "") {
748
- const num = tonumber(params);
740
+ const num = parseIntSafe(params);
749
741
  if (num === undefined) {
750
- print("That is an invalid amount of Giga Bombs to add.");
742
+ print(`Invalid Giga Bomb amount: ${num}`);
751
743
  return;
752
744
  }
753
745
 
@@ -869,9 +861,9 @@ export function iAmErrorRoom(): void {
869
861
  export function key(params: string): void {
870
862
  let numKeys = 1;
871
863
  if (params !== "") {
872
- const num = tonumber(params);
864
+ const num = parseIntSafe(params);
873
865
  if (num === undefined) {
874
- print("That is an invalid amount of keys to add.");
866
+ print(`Invalid key amount: ${num}`);
875
867
  return;
876
868
  }
877
869
 
@@ -889,9 +881,9 @@ export function key(params: string): void {
889
881
  export function keys(params: string): void {
890
882
  let numKeys = 99;
891
883
  if (params !== "") {
892
- const num = tonumber(params);
884
+ const num = parseIntSafe(params);
893
885
  if (num === undefined) {
894
- print("That is an invalid amount of keys to add.");
886
+ print(`Invalid key amount: ${num}`);
895
887
  return;
896
888
  }
897
889
 
@@ -1051,7 +1043,7 @@ export function pill(params: string): void {
1051
1043
  }
1052
1044
 
1053
1045
  let pillEffect: PillEffect;
1054
- const num = tonumber(params) as PillEffect | undefined;
1046
+ const num = parseIntSafe(params);
1055
1047
  if (num === undefined) {
1056
1048
  const match = getMapPartialMatch(params, PILL_NAME_TO_EFFECT_MAP);
1057
1049
  if (match === undefined) {
@@ -1061,7 +1053,7 @@ export function pill(params: string): void {
1061
1053
 
1062
1054
  pillEffect = match[1];
1063
1055
  } else {
1064
- if (num < FIRST_PILL_EFFECT || num > LAST_VANILLA_PILL_EFFECT) {
1056
+ if (!isValidPillEffect(num)) {
1065
1057
  print(`Invalid pill effect ID: ${num}`);
1066
1058
  return;
1067
1059
  }
@@ -1127,14 +1119,12 @@ export function pocket(params: string): void {
1127
1119
  return;
1128
1120
  }
1129
1121
 
1130
- const collectibleType = tonumber(params) as CollectibleType | undefined;
1131
- if (collectibleType === undefined) {
1132
- print("That is an invalid collectible type.");
1133
- return;
1134
- }
1135
-
1136
- if (!isValidCollectibleType(collectibleType)) {
1137
- print("That is an invalid collectible type.");
1122
+ const collectibleType = parseIntSafe(params);
1123
+ if (
1124
+ collectibleType === undefined ||
1125
+ !isValidCollectibleType(collectibleType)
1126
+ ) {
1127
+ print(`Invalid collectible type: ${collectibleType}`);
1138
1128
  return;
1139
1129
  }
1140
1130
 
@@ -1158,9 +1148,9 @@ export function poop(): void {
1158
1148
  export function poopMana(params: string): void {
1159
1149
  let charges = 1;
1160
1150
  if (params !== "") {
1161
- const num = tonumber(params);
1151
+ const num = parseIntSafe(params);
1162
1152
  if (num === undefined) {
1163
- print("That is an invalid amount of mana to add.");
1153
+ print(`Invalid mana amount: ${num}`);
1164
1154
  return;
1165
1155
  }
1166
1156
 
@@ -1248,16 +1238,9 @@ export function s(params: string): void {
1248
1238
  stageTypeLetter = "";
1249
1239
  }
1250
1240
 
1251
- const stage = tonumber(stageString) as LevelStage | undefined;
1252
- if (stage === undefined) {
1253
- print(`That is an invalid stage number: ${stage}`);
1254
- return;
1255
- }
1256
-
1257
- if (stage < FIRST_STAGE || stage > LAST_STAGE) {
1258
- print(
1259
- `Invalid stage number; must be between ${FIRST_STAGE} and ${LAST_STAGE}.`,
1260
- );
1241
+ const stage = parseIntSafe(stageString);
1242
+ if (stage === undefined || !isEnumValue(stage, StageType)) {
1243
+ print(`Invalid stage number: ${stage}`);
1261
1244
  return;
1262
1245
  }
1263
1246
 
@@ -1313,31 +1296,30 @@ export function setCharges(params: string): void {
1313
1296
  }
1314
1297
 
1315
1298
  if (args.length !== 2) {
1316
- print("That is an invalid amount of arguments.");
1299
+ print(`Invalid amount of arguments: ${args.length}`);
1317
1300
  return;
1318
1301
  }
1319
1302
 
1320
1303
  const [activeSlotString, chargeString] = args;
1321
1304
 
1322
- const activeSlot = tonumber(activeSlotString) as ActiveSlot | undefined;
1323
- if (activeSlot === undefined) {
1324
- print(`The provided slot number is invalid: ${activeSlotString}`);
1305
+ if (activeSlotString === undefined || chargeString === undefined) {
1325
1306
  return;
1326
1307
  }
1327
1308
 
1328
- if (!ACTIVE_SLOT_VALUES.includes(activeSlot)) {
1329
- print(`The provided slot number is invalid: ${activeSlot}`);
1309
+ const activeSlot = parseIntSafe(activeSlotString);
1310
+ if (activeSlot === undefined || !isEnumValue(activeSlot, ActiveSlot)) {
1311
+ print(`Invalid slot number: ${activeSlotString}`);
1330
1312
  return;
1331
1313
  }
1332
1314
 
1333
- const chargeNum = tonumber(chargeString);
1315
+ const chargeNum = parseIntSafe(chargeString);
1334
1316
  if (chargeNum === undefined) {
1335
- print(`The provided charge amount is invalid: ${chargeString}`);
1317
+ print(`Invalid charge amount: ${chargeString}`);
1336
1318
  return;
1337
1319
  }
1338
1320
 
1339
1321
  if (chargeNum < 0) {
1340
- print(`The provided charge amount is invalid: ${chargeNum}`);
1322
+ print(`Invalid charge amount: ${chargeNum}`);
1341
1323
  return;
1342
1324
  }
1343
1325
 
@@ -1365,15 +1347,19 @@ export function setPosition(params: string): void {
1365
1347
 
1366
1348
  const [xString, yString] = args;
1367
1349
 
1368
- const x = tonumber(xString);
1350
+ if (xString === undefined || yString === undefined) {
1351
+ return;
1352
+ }
1353
+
1354
+ const x = parseIntSafe(xString);
1369
1355
  if (x === undefined) {
1370
- print(`That is an invalid x value: ${xString}`);
1356
+ print(`Invalid x value: ${xString}`);
1371
1357
  return;
1372
1358
  }
1373
1359
 
1374
- const y = tonumber(yString);
1360
+ const y = parseIntSafe(yString);
1375
1361
  if (y === undefined) {
1376
- print(`That is an invalid y value: ${yString}`);
1362
+ print(`Invalid y value: ${yString}`);
1377
1363
  return;
1378
1364
  }
1379
1365
 
@@ -1400,9 +1386,9 @@ export function smelt(): void {
1400
1386
  export function soulCharges(params: string): void {
1401
1387
  let charges = 1;
1402
1388
  if (params !== "") {
1403
- const num = tonumber(params);
1389
+ const num = parseIntSafe(params);
1404
1390
  if (num === undefined) {
1405
- print("That is an invalid amount of charges to add.");
1391
+ print(`Invalid charges amount: ${num}`);
1406
1392
  return;
1407
1393
  }
1408
1394
 
@@ -1428,9 +1414,9 @@ export function soulHearts(params: string): void {
1428
1414
  * - sound 1 - Plays the 1-Up sound effect.
1429
1415
  */
1430
1416
  export function sound(params: string): void {
1431
- const soundEffect = tonumber(params) as SoundEffect | undefined;
1432
- if (soundEffect === undefined) {
1433
- print("That is an invalid sound effect ID.");
1417
+ const soundEffect = parseIntSafe(params);
1418
+ if (soundEffect === undefined || !isEnumValue(soundEffect, SoundEffect)) {
1419
+ print(`Invalid sound effect ID: ${soundEffect}.`);
1434
1420
  return;
1435
1421
  }
1436
1422
 
@@ -1473,9 +1459,9 @@ export function spawnCollectible(params: string): void {
1473
1459
  return;
1474
1460
  }
1475
1461
 
1476
- const collectibleTypeNumber = tonumber(params);
1462
+ const num = parseIntSafe(params);
1477
1463
  let collectibleType: CollectibleType;
1478
- if (collectibleTypeNumber === undefined) {
1464
+ if (num === undefined) {
1479
1465
  const match = getMapPartialMatch(params, COLLECTIBLE_NAME_TO_TYPE_MAP);
1480
1466
  if (match === undefined) {
1481
1467
  print(`Unknown collectible: ${params}`);
@@ -1484,7 +1470,10 @@ export function spawnCollectible(params: string): void {
1484
1470
 
1485
1471
  collectibleType = match[1];
1486
1472
  } else {
1487
- collectibleType = asCollectibleType(collectibleTypeNumber);
1473
+ if (!isValidCollectibleType(num)) {
1474
+ print(`Invalid collectible type: ${num}`);
1475
+ }
1476
+ collectibleType = num;
1488
1477
  }
1489
1478
 
1490
1479
  const roomClass = game.GetRoom();
@@ -1521,19 +1510,27 @@ export function spawnCollectibleAt(params: string): void {
1521
1510
  return;
1522
1511
  }
1523
1512
 
1524
- const collectibleTypeNumber = tonumber(args[0]);
1525
- if (collectibleTypeNumber === undefined || collectibleTypeNumber < 0) {
1526
- print(`Failed to parse the collectible type of: ${args[0]}`);
1513
+ const [collectibleTypeString, gridIndexString] = args;
1514
+
1515
+ if (collectibleTypeString === undefined || gridIndexString === undefined) {
1527
1516
  return;
1528
1517
  }
1529
1518
 
1530
- const gridIndex = tonumber(args[1]);
1519
+ const collectibleType = parseIntSafe(collectibleTypeString);
1520
+ if (
1521
+ collectibleType === undefined ||
1522
+ !isValidCollectibleType(collectibleType)
1523
+ ) {
1524
+ print(`Invalid collectible type: ${args[0]}`);
1525
+ return;
1526
+ }
1527
+
1528
+ const gridIndex = parseIntSafe(gridIndexString);
1531
1529
  if (gridIndex === undefined || gridIndex < 0) {
1532
1530
  print(`Failed to parse the grid index of: ${args[1]}`);
1533
1531
  return;
1534
1532
  }
1535
1533
 
1536
- const collectibleType = asCollectibleType(collectibleTypeNumber);
1537
1534
  spawnCollectibleFunc(collectibleType, gridIndex, undefined);
1538
1535
  }
1539
1536
 
@@ -1581,9 +1578,9 @@ export function spawnTrinket(params: string, golden = false): void {
1581
1578
  return;
1582
1579
  }
1583
1580
 
1584
- const trinketTypeNumber = tonumber(params);
1581
+ const num = parseIntSafe(params);
1585
1582
  let trinketType: TrinketType;
1586
- if (trinketTypeNumber === undefined) {
1583
+ if (num === undefined) {
1587
1584
  const match = getMapPartialMatch(params, TRINKET_NAME_TO_TYPE_MAP);
1588
1585
  if (match === undefined) {
1589
1586
  print(`Unknown trinket: ${params}`);
@@ -1592,7 +1589,11 @@ export function spawnTrinket(params: string, golden = false): void {
1592
1589
 
1593
1590
  trinketType = match[1];
1594
1591
  } else {
1595
- trinketType = asTrinketType(trinketTypeNumber);
1592
+ if (!isValidTrinketType(num)) {
1593
+ print(`Invalid trinket type: ${num}`);
1594
+ return;
1595
+ }
1596
+ trinketType = num;
1596
1597
  }
1597
1598
 
1598
1599
  const roomClass = game.GetRoom();
@@ -1631,19 +1632,24 @@ export function spawnTrinketAt(params: string, golden = false): void {
1631
1632
  return;
1632
1633
  }
1633
1634
 
1634
- const trinketTypeNumber = tonumber(args[0]);
1635
- if (trinketTypeNumber === undefined || trinketTypeNumber < 0) {
1636
- print(`Failed to parse the trinket type of: ${args[0]}`);
1635
+ const [trinketTypeString, gridIndexString] = args;
1636
+
1637
+ if (trinketTypeString === undefined || gridIndexString === undefined) {
1638
+ return;
1639
+ }
1640
+
1641
+ const trinketType = parseIntSafe(trinketTypeString);
1642
+ if (trinketType === undefined || !isValidTrinketType(trinketType)) {
1643
+ print(`Invalid trinket type: ${trinketTypeString}`);
1637
1644
  return;
1638
1645
  }
1639
1646
 
1640
- const gridIndex = tonumber(args[1]);
1647
+ const gridIndex = parseIntSafe(gridIndexString);
1641
1648
  if (gridIndex === undefined || gridIndex < 0) {
1642
1649
  print(`Failed to parse the grid index of: ${args[1]}`);
1643
1650
  return;
1644
1651
  }
1645
1652
 
1646
- const trinketType = asTrinketType(trinketTypeNumber);
1647
1653
  const goldenTrinketType = getGoldenTrinketType(trinketType);
1648
1654
  const trinketTypeToSpawn = golden ? goldenTrinketType : trinketType;
1649
1655
  spawnTrinketFunction(trinketTypeToSpawn, gridIndex);
@@ -1658,9 +1664,9 @@ export function speed(params: string): void {
1658
1664
  const player = Isaac.GetPlayer();
1659
1665
 
1660
1666
  if (params !== "") {
1661
- const num = tonumber(params);
1667
+ const num = tonumber(params); // Can be a float.
1662
1668
  if (num === undefined) {
1663
- print(`The provided speed amount is invalid: ${params}`);
1669
+ print(`Invalid speed amount: ${params}`);
1664
1670
  return;
1665
1671
  }
1666
1672
 
@@ -1711,9 +1717,9 @@ export function superSecretRoom(): void {
1711
1717
  */
1712
1718
  export function tears(params: string): void {
1713
1719
  if (params !== "") {
1714
- const num = tonumber(params);
1720
+ const num = tonumber(params); // Can be a float.
1715
1721
  if (num === undefined) {
1716
- print(`The provided tear delay amount is invalid: ${params}`);
1722
+ print(`Invalid tear delay amount: ${params}`);
1717
1723
  return;
1718
1724
  }
1719
1725
 
@@ -1791,7 +1797,7 @@ export function warp(params: string): void {
1791
1797
  }
1792
1798
 
1793
1799
  let roomType: RoomType;
1794
- const num = tonumber(params) as RoomType | undefined;
1800
+ const num = parseIntSafe(params);
1795
1801
  if (num === undefined) {
1796
1802
  const match = getMapPartialMatch(params, ROOM_NAME_TO_TYPE_MAP);
1797
1803
  if (match === undefined) {
@@ -1801,7 +1807,7 @@ export function warp(params: string): void {
1801
1807
 
1802
1808
  roomType = match[1];
1803
1809
  } else {
1804
- if (num < FIRST_ROOM_TYPE || num > LAST_ROOM_TYPE) {
1810
+ if (!isEnumValue(num, RoomType)) {
1805
1811
  print(`Invalid room type: ${num}`);
1806
1812
  return;
1807
1813
  }
@@ -19,6 +19,7 @@ import {
19
19
  import { addPlayerHealthType } from "../../../../functions/playerHealth";
20
20
  import { getRoomData, getRoomDescriptor } from "../../../../functions/roomData";
21
21
  import { changeRoom } from "../../../../functions/rooms";
22
+ import { parseIntSafe } from "../../../../functions/types";
22
23
  import { ROOM_TYPE_NAMES } from "../../../../objects/roomTypeNames";
23
24
 
24
25
  const DEFAULT_MOVE_UNITS = 0.5;
@@ -26,7 +27,7 @@ const DEFAULT_MOVE_UNITS = 0.5;
26
27
  export function addHeart(params: string, healthType: HealthType): void {
27
28
  let numHearts = healthType === HealthType.MAX_HEARTS ? 2 : 1;
28
29
  if (params !== "") {
29
- const num = tonumber(params);
30
+ const num = parseIntSafe(params);
30
31
  if (num === undefined) {
31
32
  print("That is an invalid amount of hearts to add.");
32
33
  return;
@@ -68,7 +69,7 @@ export function listEntities(
68
69
  ): void {
69
70
  let entityTypeFilter: EntityType | undefined;
70
71
  if (params !== "") {
71
- entityTypeFilter = tonumber(params);
72
+ entityTypeFilter = parseIntSafe(params);
72
73
  if (entityTypeFilter === undefined) {
73
74
  print("That is an invalid entity type to filter by.");
74
75
  return;
@@ -82,7 +83,7 @@ export function listEntities(
82
83
  export function listGridEntities(params: string, includeWalls: boolean): void {
83
84
  let gridEntityTypeFilter: GridEntityType | undefined;
84
85
  if (params !== "") {
85
- gridEntityTypeFilter = tonumber(params);
86
+ gridEntityTypeFilter = parseIntSafe(params);
86
87
  if (gridEntityTypeFilter === undefined) {
87
88
  print("That is an invalid grid entity type to filter by.");
88
89
  return;
@@ -96,7 +97,7 @@ export function listGridEntities(params: string, includeWalls: boolean): void {
96
97
  export function movePlayer(params: string, direction: Direction): void {
97
98
  let amount = DEFAULT_MOVE_UNITS;
98
99
  if (params !== "") {
99
- const num = tonumber(params);
100
+ const num = parseIntSafe(params);
100
101
  if (num === undefined) {
101
102
  print("That is an invalid amount of units to move.");
102
103
  return;