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.
- package/dist/classes/ModUpgraded.d.ts.map +1 -1
- package/dist/classes/ModUpgraded.lua +18 -8
- package/dist/classes/features/other/DeployJSONRoom.lua +11 -10
- package/dist/classes/features/other/extraConsoleCommands/commands.d.ts +1 -1
- package/dist/classes/features/other/extraConsoleCommands/commands.d.ts.map +1 -1
- package/dist/classes/features/other/extraConsoleCommands/commands.lua +104 -102
- package/dist/classes/features/other/extraConsoleCommands/subroutines.d.ts.map +1 -1
- package/dist/classes/features/other/extraConsoleCommands/subroutines.lua +6 -4
- package/dist/core/constantsFirstLast.d.ts +4 -26
- package/dist/core/constantsFirstLast.d.ts.map +1 -1
- package/dist/core/constantsFirstLast.lua +0 -18
- package/dist/functions/cards.d.ts +1 -0
- package/dist/functions/cards.d.ts.map +1 -1
- package/dist/functions/cards.lua +7 -0
- package/dist/functions/collectibles.d.ts +1 -1
- package/dist/functions/collectibles.d.ts.map +1 -1
- package/dist/functions/collectibles.lua +3 -1
- package/dist/functions/doors.d.ts.map +1 -1
- package/dist/functions/doors.lua +14 -4
- package/dist/functions/entities.d.ts.map +1 -1
- package/dist/functions/entities.lua +19 -30
- package/dist/functions/gridEntities.d.ts.map +1 -1
- package/dist/functions/gridEntities.lua +8 -13
- package/dist/functions/jsonRoom.d.ts.map +1 -1
- package/dist/functions/jsonRoom.lua +13 -5
- package/dist/functions/pills.d.ts +1 -0
- package/dist/functions/pills.d.ts.map +1 -1
- package/dist/functions/pills.lua +6 -0
- package/dist/functions/run.d.ts +1 -2
- package/dist/functions/run.d.ts.map +1 -1
- package/dist/functions/run.lua +2 -3
- package/dist/functions/string.d.ts.map +1 -1
- package/dist/functions/string.lua +5 -3
- package/dist/functions/table.d.ts +3 -2
- package/dist/functions/table.d.ts.map +1 -1
- package/dist/functions/table.lua +3 -2
- package/dist/functions/trinkets.d.ts +1 -0
- package/dist/functions/trinkets.d.ts.map +1 -1
- package/dist/functions/trinkets.lua +6 -0
- package/dist/functions/types.d.ts +9 -0
- package/dist/functions/types.d.ts.map +1 -1
- package/dist/functions/types.lua +17 -0
- package/dist/index.rollup.d.ts +23 -32
- package/dist/isaacscript-common.lua +254 -207
- package/dist/lualib_bundle.lua +5 -0
- package/dist/objects/itemPoolTypeToCollectibleTypesSet.lua +4 -3
- package/package.json +2 -2
- package/src/classes/ModUpgraded.ts +18 -4
- package/src/classes/features/other/DeployJSONRoom.ts +11 -11
- package/src/classes/features/other/extraConsoleCommands/commands.ts +124 -118
- package/src/classes/features/other/extraConsoleCommands/subroutines.ts +5 -4
- package/src/core/constantsFirstLast.ts +3 -37
- package/src/functions/cards.ts +7 -0
- package/src/functions/collectibles.ts +5 -4
- package/src/functions/doors.ts +8 -3
- package/src/functions/entities.ts +40 -19
- package/src/functions/gridEntities.ts +15 -5
- package/src/functions/jsonRoom.ts +18 -5
- package/src/functions/pills.ts +7 -1
- package/src/functions/run.ts +6 -4
- package/src/functions/string.ts +4 -3
- package/src/functions/table.ts +3 -2
- package/src/functions/trinkets.ts +9 -1
- package/src/functions/types.ts +25 -0
- package/src/objects/itemPoolTypeToCollectibleTypesSet.ts +4 -4
|
@@ -8,11 +8,9 @@ import {
|
|
|
8
8
|
CardType,
|
|
9
9
|
Challenge,
|
|
10
10
|
CollectibleType,
|
|
11
|
-
LevelStage,
|
|
12
11
|
PillColor,
|
|
13
12
|
PillEffect,
|
|
14
13
|
PlayerType,
|
|
15
|
-
RoomType,
|
|
16
14
|
TrinketType,
|
|
17
15
|
} from "isaac-typescript-definitions";
|
|
18
16
|
import { getEnumLength, getHighestEnumValue } from "../functions/enums";
|
|
@@ -62,13 +60,7 @@ export const NUM_VANILLA_TRINKET_TYPES = getEnumLength(TrinketType) - 1;
|
|
|
62
60
|
/** Equal to `Card.FOOL`. */
|
|
63
61
|
export const FIRST_CARD_TYPE = CardType.FOOL;
|
|
64
62
|
|
|
65
|
-
/**
|
|
66
|
-
* Calculated from the `CardType` enum.
|
|
67
|
-
*
|
|
68
|
-
* Note that this could be calculated from the length of the enum, because card types are
|
|
69
|
-
* contiguous. However, we instead get the highest enum value to be safer and to make the code more
|
|
70
|
-
* consistent with collectibles and trinkets.
|
|
71
|
-
*/
|
|
63
|
+
/** Calculated from the `CardType` enum. */
|
|
72
64
|
export const LAST_VANILLA_CARD_TYPE = getHighestEnumValue(CardType);
|
|
73
65
|
|
|
74
66
|
/** Calculated from the `Card` enum. `Card.NULL` is not included. */
|
|
@@ -81,13 +73,7 @@ export const NUM_VANILLA_CARD_TYPES = getEnumLength(CardType) - 1;
|
|
|
81
73
|
/** Equal to `PillEffect.BAD_GAS`. */
|
|
82
74
|
export const FIRST_PILL_EFFECT = PillEffect.BAD_GAS;
|
|
83
75
|
|
|
84
|
-
/**
|
|
85
|
-
* Calculated from the `PillEffect` enum.
|
|
86
|
-
*
|
|
87
|
-
* Note that this could be calculated from the length of the enum, because pill effects are
|
|
88
|
-
* contiguous. However, we instead get the highest enum value to be safer and to make the code more
|
|
89
|
-
* consistent with collectibles and trinkets.
|
|
90
|
-
*/
|
|
76
|
+
/** Calculated from the `PillEffect` enum. */
|
|
91
77
|
export const LAST_VANILLA_PILL_EFFECT = getHighestEnumValue(PillEffect);
|
|
92
78
|
|
|
93
79
|
/**
|
|
@@ -136,29 +122,9 @@ export const FIRST_CHARACTER = PlayerType.ISAAC;
|
|
|
136
122
|
|
|
137
123
|
// It is not possible to determine "LAST_PLAYER_TYPE", since there is no associated config.
|
|
138
124
|
|
|
139
|
-
/**
|
|
140
|
-
* Calculated from the `PlayerType` enum.
|
|
141
|
-
*
|
|
142
|
-
* Note that this could be calculated from the length of the enum, because characters are
|
|
143
|
-
* contiguous. However, we instead get the highest enum value to be safer and to make the code more
|
|
144
|
-
* consistent with collectibles and trinkets.
|
|
145
|
-
*/
|
|
125
|
+
/** Calculated from the `PlayerType` enum. */
|
|
146
126
|
export const LAST_VANILLA_CHARACTER = getHighestEnumValue(PlayerType);
|
|
147
127
|
|
|
148
|
-
// ----------
|
|
149
|
-
// Room Types
|
|
150
|
-
// ----------
|
|
151
|
-
|
|
152
|
-
export const FIRST_ROOM_TYPE = RoomType.DEFAULT;
|
|
153
|
-
export const LAST_ROOM_TYPE = getHighestEnumValue(RoomType);
|
|
154
|
-
|
|
155
|
-
// ------
|
|
156
|
-
// Stages
|
|
157
|
-
// ------
|
|
158
|
-
|
|
159
|
-
export const FIRST_STAGE = LevelStage.BASEMENT_1;
|
|
160
|
-
export const LAST_STAGE = getHighestEnumValue(LevelStage);
|
|
161
|
-
|
|
162
128
|
// ----------
|
|
163
129
|
// Challenges
|
|
164
130
|
// ----------
|
package/src/functions/cards.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { CARD_NAMES, DEFAULT_CARD_NAME } from "../objects/cardNames";
|
|
11
11
|
import { ITEM_CONFIG_CARD_TYPES_FOR_CARDS } from "../sets/itemConfigCardTypesForCards";
|
|
12
12
|
import { addFlag } from "./flag";
|
|
13
|
+
import { asCardType } from "./types";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Helper function to get a card description from a `CardType` value. Returns "Unknown" if the
|
|
@@ -158,6 +159,12 @@ export function isTarotCard(cardType: CardType): boolean {
|
|
|
158
159
|
return isCardType(cardType, ItemConfigCardType.TAROT);
|
|
159
160
|
}
|
|
160
161
|
|
|
162
|
+
export function isValidCardType(cardType: int): cardType is CardType {
|
|
163
|
+
const potentialCardType = asCardType(cardType);
|
|
164
|
+
const itemConfigCard = itemConfig.GetCard(potentialCardType);
|
|
165
|
+
return itemConfigCard !== undefined;
|
|
166
|
+
}
|
|
167
|
+
|
|
161
168
|
export function isVanillaCardType(cardType: CardType): boolean {
|
|
162
169
|
return cardType <= LAST_VANILLA_CARD_TYPE;
|
|
163
170
|
}
|
|
@@ -35,7 +35,7 @@ import { getEntityID } from "./entities";
|
|
|
35
35
|
import { hasFlag } from "./flag";
|
|
36
36
|
import { isCollectible } from "./pickupVariants";
|
|
37
37
|
import { clearSprite, spriteEquals } from "./sprites";
|
|
38
|
-
import { isInteger } from "./types";
|
|
38
|
+
import { asCollectibleType, isInteger } from "./types";
|
|
39
39
|
import { assertDefined } from "./utils";
|
|
40
40
|
|
|
41
41
|
const COLLECTIBLE_ANM2_PATH = "gfx/005.100_collectible.anm2";
|
|
@@ -569,9 +569,10 @@ export function isSingleUseCollectible(
|
|
|
569
569
|
}
|
|
570
570
|
|
|
571
571
|
export function isValidCollectibleType(
|
|
572
|
-
collectibleType:
|
|
573
|
-
):
|
|
574
|
-
const
|
|
572
|
+
collectibleType: int,
|
|
573
|
+
): collectibleType is CollectibleType {
|
|
574
|
+
const potentialCollectibleType = asCollectibleType(collectibleType);
|
|
575
|
+
const itemConfigItem = itemConfig.GetCollectible(potentialCollectibleType);
|
|
575
576
|
return itemConfigItem !== undefined;
|
|
576
577
|
}
|
|
577
578
|
|
package/src/functions/doors.ts
CHANGED
|
@@ -29,8 +29,10 @@ import { ROOM_SHAPE_TO_DOOR_SLOTS } from "../objects/roomShapeToDoorSlots";
|
|
|
29
29
|
import { ReadonlySet } from "../types/ReadonlySet";
|
|
30
30
|
import { arrayToBitFlags } from "./bitwise";
|
|
31
31
|
import { directionToVector } from "./direction";
|
|
32
|
+
import { isEnumValue } from "./enums";
|
|
32
33
|
import { hasFlag } from "./flag";
|
|
33
34
|
import { isTSTLSet } from "./tstlClass";
|
|
35
|
+
import { parseIntSafe } from "./types";
|
|
34
36
|
|
|
35
37
|
export function closeAllDoors(): void {
|
|
36
38
|
for (const door of getDoors()) {
|
|
@@ -278,7 +280,6 @@ export function getRoomShapeDoorSlot(
|
|
|
278
280
|
x: int,
|
|
279
281
|
y: int,
|
|
280
282
|
): DoorSlot | undefined {
|
|
281
|
-
// The type assertion is necessary for some reason.
|
|
282
283
|
const doorSlotCoordinates = ROOM_SHAPE_TO_DOOR_SLOT_COORDINATES[
|
|
283
284
|
roomShape
|
|
284
285
|
] as Record<DoorSlot, readonly [x: int, y: int]>;
|
|
@@ -286,7 +287,11 @@ export function getRoomShapeDoorSlot(
|
|
|
286
287
|
for (const [doorSlotString, coordinates] of Object.entries(
|
|
287
288
|
doorSlotCoordinates,
|
|
288
289
|
)) {
|
|
289
|
-
const doorSlot =
|
|
290
|
+
const doorSlot = parseIntSafe(doorSlotString);
|
|
291
|
+
if (doorSlot === undefined || !isEnumValue(doorSlot, DoorSlot)) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
|
|
290
295
|
const [doorX, doorY] = coordinates;
|
|
291
296
|
if (x === doorX && y === doorY) {
|
|
292
297
|
return doorSlot;
|
|
@@ -304,10 +309,10 @@ export function getRoomShapeDoorSlotCoordinates(
|
|
|
304
309
|
roomShape: RoomShape,
|
|
305
310
|
doorSlot: DoorSlot,
|
|
306
311
|
): readonly [x: int, y: int] | undefined {
|
|
307
|
-
// The type assertion is necessary for some reason.
|
|
308
312
|
const doorSlotCoordinates = ROOM_SHAPE_TO_DOOR_SLOT_COORDINATES[
|
|
309
313
|
roomShape
|
|
310
314
|
] as Record<DoorSlot, readonly [x: int, y: int]>;
|
|
315
|
+
|
|
311
316
|
return doorSlotCoordinates[doorSlot];
|
|
312
317
|
}
|
|
313
318
|
|
|
@@ -18,7 +18,7 @@ import { newReadonlyColor } from "./readOnly";
|
|
|
18
18
|
import { getRandomSeed, isRNG, newRNG } from "./rng";
|
|
19
19
|
import { setSpriteOpacity } from "./sprites";
|
|
20
20
|
import { isTSTLSet } from "./tstlClass";
|
|
21
|
-
import { asNPCState, isPrimitive } from "./types";
|
|
21
|
+
import { asNPCState, isPrimitive, parseIntSafe } from "./types";
|
|
22
22
|
import { assertDefined } from "./utils";
|
|
23
23
|
import { doesVectorHaveLength, isVector, vectorToString } from "./vector";
|
|
24
24
|
|
|
@@ -173,22 +173,37 @@ export function getConstituentsFromEntityID(
|
|
|
173
173
|
|
|
174
174
|
const [entityTypeString, variantString, subTypeString] = parts;
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
assertDefined(
|
|
177
|
+
entityTypeString,
|
|
178
|
+
`Failed to get the first constituent from an entity ID: ${entityID}`,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
assertDefined(
|
|
182
|
+
variantString,
|
|
183
|
+
`Failed to get the second constituent from an entity ID: ${entityID}`,
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
assertDefined(
|
|
187
|
+
subTypeString,
|
|
188
|
+
`Failed to get the third constituent from an entity ID: ${entityID}`,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const entityType = parseIntSafe(entityTypeString);
|
|
177
192
|
assertDefined(
|
|
178
193
|
entityType,
|
|
179
|
-
`Failed to convert the entity type to
|
|
194
|
+
`Failed to convert the entity type to an integer: ${entityTypeString}`,
|
|
180
195
|
);
|
|
181
196
|
|
|
182
|
-
const variant =
|
|
197
|
+
const variant = parseIntSafe(variantString);
|
|
183
198
|
assertDefined(
|
|
184
199
|
variant,
|
|
185
|
-
`Failed to convert the entity variant to
|
|
200
|
+
`Failed to convert the entity variant to an integer: ${variantString}`,
|
|
186
201
|
);
|
|
187
202
|
|
|
188
|
-
const subType =
|
|
203
|
+
const subType = parseIntSafe(subTypeString);
|
|
189
204
|
assertDefined(
|
|
190
205
|
subType,
|
|
191
|
-
`Failed to convert the entity sub-type to
|
|
206
|
+
`Failed to convert the entity sub-type to an integer: ${subTypeString}`,
|
|
192
207
|
);
|
|
193
208
|
|
|
194
209
|
return [entityType, variant, subType];
|
|
@@ -464,18 +479,23 @@ export function parseEntityID(
|
|
|
464
479
|
|
|
465
480
|
const [entityTypeString, variantString, subTypeString] = entityIDArray;
|
|
466
481
|
|
|
467
|
-
|
|
468
|
-
|
|
482
|
+
if (
|
|
483
|
+
entityTypeString === undefined ||
|
|
484
|
+
variantString === undefined ||
|
|
485
|
+
subTypeString === undefined
|
|
486
|
+
) {
|
|
469
487
|
return undefined;
|
|
470
488
|
}
|
|
471
489
|
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
490
|
+
const entityType = parseIntSafe(entityTypeString);
|
|
491
|
+
const variant = parseIntSafe(variantString);
|
|
492
|
+
const subType = parseIntSafe(subTypeString);
|
|
476
493
|
|
|
477
|
-
|
|
478
|
-
|
|
494
|
+
if (
|
|
495
|
+
entityType === undefined ||
|
|
496
|
+
variant === undefined ||
|
|
497
|
+
subType === undefined
|
|
498
|
+
) {
|
|
479
499
|
return undefined;
|
|
480
500
|
}
|
|
481
501
|
|
|
@@ -500,13 +520,14 @@ export function parseEntityTypeVariantString(
|
|
|
500
520
|
|
|
501
521
|
const [entityTypeString, variantString] = entityTypeVariantArray;
|
|
502
522
|
|
|
503
|
-
|
|
504
|
-
if (entityType === undefined) {
|
|
523
|
+
if (entityTypeString === undefined || variantString === undefined) {
|
|
505
524
|
return undefined;
|
|
506
525
|
}
|
|
507
526
|
|
|
508
|
-
const
|
|
509
|
-
|
|
527
|
+
const entityType = parseIntSafe(entityTypeString);
|
|
528
|
+
const variant = parseIntSafe(variantString);
|
|
529
|
+
|
|
530
|
+
if (entityType === undefined || variant === undefined) {
|
|
510
531
|
return undefined;
|
|
511
532
|
}
|
|
512
533
|
|
|
@@ -26,7 +26,7 @@ import { removeEntities } from "./entities";
|
|
|
26
26
|
import { getEffects } from "./entitiesSpecific";
|
|
27
27
|
import { isCircleIntersectingRectangle } from "./math";
|
|
28
28
|
import { roomUpdateSafe } from "./rooms";
|
|
29
|
-
import { isInteger } from "./types";
|
|
29
|
+
import { isInteger, parseIntSafe } from "./types";
|
|
30
30
|
import { assertDefined, eRange, iRange } from "./utils";
|
|
31
31
|
import { isVector, vectorEquals } from "./vector";
|
|
32
32
|
|
|
@@ -169,22 +169,32 @@ export function getConstituentsFromGridEntityID(
|
|
|
169
169
|
const parts = gridEntityID.split(".");
|
|
170
170
|
if (parts.length !== 2) {
|
|
171
171
|
error(
|
|
172
|
-
`Failed to get the constituents from grid entity ID: ${gridEntityID}`,
|
|
172
|
+
`Failed to get the constituents from a grid entity ID: ${gridEntityID}`,
|
|
173
173
|
);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
const [gridEntityTypeString, variantString] = parts;
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
assertDefined(
|
|
179
|
+
gridEntityTypeString,
|
|
180
|
+
`Failed to get the first constituent from a grid entity ID: ${gridEntityID}`,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
assertDefined(
|
|
184
|
+
variantString,
|
|
185
|
+
`Failed to get the second constituent from a grid entity ID: ${gridEntityID}`,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const gridEntityType = parseIntSafe(gridEntityTypeString);
|
|
179
189
|
assertDefined(
|
|
180
190
|
gridEntityType,
|
|
181
191
|
`Failed to convert the grid entity type to a number: ${gridEntityTypeString}`,
|
|
182
192
|
);
|
|
183
193
|
|
|
184
|
-
const variant =
|
|
194
|
+
const variant = parseIntSafe(variantString);
|
|
185
195
|
assertDefined(
|
|
186
196
|
variant,
|
|
187
|
-
`Failed to convert the grid entity variant to
|
|
197
|
+
`Failed to convert the grid entity variant to an integer: ${variantString}`,
|
|
188
198
|
);
|
|
189
199
|
|
|
190
200
|
return [gridEntityType, variant];
|
|
@@ -7,6 +7,7 @@ import { isEnumValue } from "./enums";
|
|
|
7
7
|
import { addFlag } from "./flag";
|
|
8
8
|
import { log } from "./log";
|
|
9
9
|
import { getRandomFloat } from "./random";
|
|
10
|
+
import { parseIntSafe } from "./types";
|
|
10
11
|
import { assertDefined } from "./utils";
|
|
11
12
|
|
|
12
13
|
/** This represents either a `JSONRoom` or a `JSONEntity`. */
|
|
@@ -24,7 +25,7 @@ export function getJSONRoomDoorSlotFlags(
|
|
|
24
25
|
jsonRoom: JSONRoom,
|
|
25
26
|
): BitFlags<DoorSlotFlag> {
|
|
26
27
|
const roomShapeString = jsonRoom.$.shape;
|
|
27
|
-
const roomShape =
|
|
28
|
+
const roomShape = parseIntSafe(roomShapeString);
|
|
28
29
|
assertDefined(
|
|
29
30
|
roomShape,
|
|
30
31
|
`Failed to parse the "shape" field of a JSON room: ${roomShapeString}`,
|
|
@@ -51,14 +52,14 @@ export function getJSONRoomDoorSlotFlags(
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
const xString = door.$.x;
|
|
54
|
-
const x =
|
|
55
|
+
const x = parseIntSafe(xString);
|
|
55
56
|
assertDefined(
|
|
56
57
|
x,
|
|
57
58
|
`Failed to parse the "x" field of a JSON room door: ${xString}`,
|
|
58
59
|
);
|
|
59
60
|
|
|
60
61
|
const yString = door.$.y;
|
|
61
|
-
const y =
|
|
62
|
+
const y = parseIntSafe(yString);
|
|
62
63
|
assertDefined(
|
|
63
64
|
y,
|
|
64
65
|
`Failed to parse the "y" field of a JSON room door: ${yString}`,
|
|
@@ -92,7 +93,13 @@ export function getJSONRoomOfVariant(
|
|
|
92
93
|
): JSONRoom | undefined {
|
|
93
94
|
const jsonRoomsOfVariant = jsonRooms.filter((jsonRoom) => {
|
|
94
95
|
const roomVariantString = jsonRoom.$.variant;
|
|
95
|
-
const roomVariant =
|
|
96
|
+
const roomVariant = parseIntSafe(roomVariantString);
|
|
97
|
+
if (roomVariant === undefined) {
|
|
98
|
+
error(
|
|
99
|
+
`Failed to convert a JSON room variant to an integer: ${roomVariantString}`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
96
103
|
return roomVariant === variant;
|
|
97
104
|
});
|
|
98
105
|
|
|
@@ -125,7 +132,13 @@ export function getJSONRoomsOfSubType(
|
|
|
125
132
|
): JSONRoom[] {
|
|
126
133
|
return jsonRooms.filter((jsonRoom) => {
|
|
127
134
|
const roomSubTypeString = jsonRoom.$.subtype;
|
|
128
|
-
const roomSubType =
|
|
135
|
+
const roomSubType = parseIntSafe(roomSubTypeString);
|
|
136
|
+
if (roomSubType === undefined) {
|
|
137
|
+
error(
|
|
138
|
+
`Failed to convert a JSON room sub-type to an integer: ${roomSubTypeString}`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
129
142
|
return roomSubType === subType;
|
|
130
143
|
});
|
|
131
144
|
}
|
package/src/functions/pills.ts
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
DEFAULT_PILL_EFFECT_TYPE,
|
|
29
29
|
PILL_EFFECT_TYPES,
|
|
30
30
|
} from "../objects/pillEffectTypes";
|
|
31
|
-
import { asNumber, asPillColor } from "./types";
|
|
31
|
+
import { asNumber, asPillColor, asPillEffect } from "./types";
|
|
32
32
|
import { iRange } from "./utils";
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -214,6 +214,12 @@ export function isModdedPillEffect(pillEffect: PillEffect): boolean {
|
|
|
214
214
|
return !isVanillaPillEffect(pillEffect);
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
export function isValidPillEffect(pillEffect: int): pillEffect is PillEffect {
|
|
218
|
+
const potentialPillEffect = asPillEffect(pillEffect);
|
|
219
|
+
const itemConfigPillEffect = itemConfig.GetPillEffect(potentialPillEffect);
|
|
220
|
+
return itemConfigPillEffect !== undefined;
|
|
221
|
+
}
|
|
222
|
+
|
|
217
223
|
export function isVanillaPillEffect(pillEffect: PillEffect): boolean {
|
|
218
224
|
return pillEffect <= LAST_VANILLA_PILL_EFFECT;
|
|
219
225
|
}
|
package/src/functions/run.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Challenge,
|
|
3
|
+
PlayerType,
|
|
4
|
+
SeedEffect,
|
|
5
|
+
} from "isaac-typescript-definitions";
|
|
3
6
|
import { SEED_EFFECTS } from "../arrays/cachedEnumValues";
|
|
4
7
|
import { game } from "../core/cachedClasses";
|
|
5
|
-
import { FIRST_CHARACTER } from "../core/constantsFirstLast";
|
|
6
8
|
import { getCharacterName } from "./characters";
|
|
7
9
|
import { log } from "./log";
|
|
8
10
|
import { isString } from "./types";
|
|
@@ -84,7 +86,7 @@ export function restart(character?: PlayerType): void {
|
|
|
84
86
|
return;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
if (character <
|
|
89
|
+
if (character < PlayerType.ISAAC) {
|
|
88
90
|
error(`Restarting as a character of ${character} would crash the game.`);
|
|
89
91
|
}
|
|
90
92
|
|
package/src/functions/string.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseIntSafe } from "./types";
|
|
1
2
|
import { assertDefined } from "./utils";
|
|
2
3
|
|
|
3
4
|
export function capitalizeFirstLetter(string: string): string {
|
|
@@ -158,9 +159,9 @@ export function parseSemanticVersion(versionString: string):
|
|
|
158
159
|
return undefined;
|
|
159
160
|
}
|
|
160
161
|
|
|
161
|
-
const majorVersion =
|
|
162
|
-
const minorVersion =
|
|
163
|
-
const patchVersion =
|
|
162
|
+
const majorVersion = parseIntSafe(majorVersionString);
|
|
163
|
+
const minorVersion = parseIntSafe(minorVersionString);
|
|
164
|
+
const patchVersion = parseIntSafe(patchVersionString);
|
|
164
165
|
|
|
165
166
|
if (
|
|
166
167
|
majorVersion === undefined ||
|
package/src/functions/table.ts
CHANGED
|
@@ -66,8 +66,9 @@ export function getBooleansFromTable(
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
|
-
* Helper function to safely get number values from specific keys on a Lua table.
|
|
70
|
-
*
|
|
69
|
+
* Helper function to safely get number values from specific keys on a Lua table. If the values are
|
|
70
|
+
* strings, they will be converted to numbers. Will throw an error if the specific value does not
|
|
71
|
+
* exist on the table or if it cannot be converted to a number.
|
|
71
72
|
*
|
|
72
73
|
* This function is variadic, meaning that you can specify N arguments to get N values.
|
|
73
74
|
*/
|
|
@@ -14,7 +14,7 @@ import { getEnumLength } from "./enums";
|
|
|
14
14
|
import { hasFlag } from "./flag";
|
|
15
15
|
import { isTrinket } from "./pickupVariants";
|
|
16
16
|
import { clearSprite } from "./sprites";
|
|
17
|
-
import { asNumber } from "./types";
|
|
17
|
+
import { asNumber, asTrinketType } from "./types";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Add this to a `TrinketType` to get the corresponding golden trinket type.
|
|
@@ -165,6 +165,14 @@ export function isModdedTrinketType(trinketType: TrinketType): boolean {
|
|
|
165
165
|
return !isVanillaTrinketType(trinketType);
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
export function isValidTrinketType(
|
|
169
|
+
trinketType: int,
|
|
170
|
+
): trinketType is TrinketType {
|
|
171
|
+
const potentialTrinketType = asTrinketType(trinketType);
|
|
172
|
+
const itemConfigItem = itemConfig.GetTrinket(potentialTrinketType);
|
|
173
|
+
return itemConfigItem !== undefined;
|
|
174
|
+
}
|
|
175
|
+
|
|
168
176
|
export function isVanillaTrinketType(trinketType: TrinketType): boolean {
|
|
169
177
|
return trinketType <= LAST_VANILLA_TRINKET_TYPE;
|
|
170
178
|
}
|
package/src/functions/types.ts
CHANGED
|
@@ -216,3 +216,28 @@ export function isTable(
|
|
|
216
216
|
export function isUserdata(variable: unknown): variable is LuaUserdata {
|
|
217
217
|
return type(variable) === "userdata";
|
|
218
218
|
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Helper function to convert a string to an integer. Returns undefined if the string is not an
|
|
222
|
+
* integer.
|
|
223
|
+
*
|
|
224
|
+
* Under the hood, this uses the built-in `tonumber` and `math.floor` functions.
|
|
225
|
+
*
|
|
226
|
+
* This is named `parseIntSafe` in order to match the helper function in `isaacscript-common-ts`.
|
|
227
|
+
*/
|
|
228
|
+
export function parseIntSafe(string: string): int | undefined {
|
|
229
|
+
if (!isString(string)) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// - The `tonumber` function correctly deals with leading and trailing whitespace.
|
|
234
|
+
// - The `tonumber` function correctly deals with a mix of numbers and letters. (e.g. `1a` returns
|
|
235
|
+
// undefined.)
|
|
236
|
+
const number = tonumber(string);
|
|
237
|
+
if (number === undefined) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const flooredNumber = math.floor(number);
|
|
242
|
+
return number === flooredNumber ? flooredNumber : undefined;
|
|
243
|
+
}
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
} from "isaac-typescript-definitions";
|
|
5
5
|
import { ITEM_POOL_TYPE_VALUES } from "../arrays/cachedEnumValues";
|
|
6
6
|
import * as itemPoolsJSON from "../data/itempools.json";
|
|
7
|
-
import { asCollectibleType } from "../functions/types";
|
|
7
|
+
import { asCollectibleType, parseIntSafe } from "../functions/types";
|
|
8
8
|
import { ITEM_POOL_TYPE_TO_ITEM_POOL_NAME } from "../maps/itemPoolTypeToItemPoolName";
|
|
9
9
|
|
|
10
10
|
export const ITEM_POOL_TYPE_TO_COLLECTIBLE_TYPES_SET: Readonly<
|
|
@@ -22,14 +22,14 @@ export const ITEM_POOL_TYPE_TO_COLLECTIBLE_TYPES_SET: Readonly<
|
|
|
22
22
|
const collectibleTypesSet = new Set<CollectibleType>();
|
|
23
23
|
|
|
24
24
|
for (const itemPoolJSONElement of itemPoolJSON.Item) {
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
25
|
+
const collectibleTypeInt = parseIntSafe(itemPoolJSONElement.$.Id);
|
|
26
|
+
if (collectibleTypeInt === undefined) {
|
|
27
27
|
error(
|
|
28
28
|
`Failed to parse a collectible type in the "itempools.json" file: ${itemPoolJSONElement.$.Id}`,
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const collectibleType = asCollectibleType(
|
|
32
|
+
const collectibleType = asCollectibleType(collectibleTypeInt);
|
|
33
33
|
collectibleTypesSet.add(collectibleType);
|
|
34
34
|
}
|
|
35
35
|
|