isaacscript-common 30.12.10 → 31.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.rollup.d.ts +152 -20
- package/dist/isaacscript-common.lua +181 -110
- package/dist/src/classes/features/other/CustomStages.d.ts +11 -0
- package/dist/src/classes/features/other/CustomStages.d.ts.map +1 -1
- package/dist/src/classes/features/other/CustomStages.lua +42 -9
- package/dist/src/classes/features/other/customStages/backdrop.lua +3 -3
- package/dist/src/functions/levelGrid.d.ts +22 -13
- package/dist/src/functions/levelGrid.d.ts.map +1 -1
- package/dist/src/functions/levelGrid.lua +46 -23
- package/dist/src/functions/logMisc.d.ts.map +1 -1
- package/dist/src/functions/logMisc.lua +3 -7
- package/dist/src/functions/roomData.d.ts +1 -5
- package/dist/src/functions/roomData.d.ts.map +1 -1
- package/dist/src/functions/roomGrid.lua +6 -6
- package/dist/src/functions/roomShape.d.ts +1 -1
- package/dist/src/functions/roomShape.d.ts.map +1 -1
- package/dist/src/functions/roomShape.lua +1 -1
- package/dist/src/functions/roomShapeWalls.lua +2 -2
- package/dist/src/functions/rooms.d.ts +98 -1
- package/dist/src/functions/rooms.d.ts.map +1 -1
- package/dist/src/functions/rooms.lua +145 -68
- package/package.json +1 -1
- package/src/classes/features/other/CustomStages.ts +60 -0
- package/src/classes/features/other/customStages/backdrop.ts +3 -3
- package/src/functions/levelGrid.ts +51 -24
- package/src/functions/logMisc.ts +5 -9
- package/src/functions/roomData.ts +4 -0
- package/src/functions/roomGrid.ts +2 -2
- package/src/functions/roomShape.ts +1 -1
- package/src/functions/roomShapeWalls.ts +2 -2
- package/src/functions/rooms.ts +237 -118
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
import type { DoorSlot, RoomShape } from "isaac-typescript-definitions";
|
|
11
11
|
import {
|
|
12
12
|
DisplayFlag,
|
|
13
|
-
DownpourRoomSubType,
|
|
14
13
|
LevelStateFlag,
|
|
15
|
-
MinesRoomSubType,
|
|
16
14
|
RoomDescriptorFlag,
|
|
17
15
|
RoomType,
|
|
18
16
|
} from "isaac-typescript-definitions";
|
|
@@ -36,8 +34,13 @@ import {
|
|
|
36
34
|
getRoomShape,
|
|
37
35
|
} from "./roomData";
|
|
38
36
|
import { getGridIndexDelta } from "./roomShape";
|
|
39
|
-
import {
|
|
40
|
-
|
|
37
|
+
import {
|
|
38
|
+
getRooms,
|
|
39
|
+
getRoomsInsideGrid,
|
|
40
|
+
isMineShaft,
|
|
41
|
+
isMirrorRoom,
|
|
42
|
+
isSecretRoomType,
|
|
43
|
+
} from "./rooms";
|
|
41
44
|
|
|
42
45
|
const LEFT = -1;
|
|
43
46
|
const UP = -LEVEL_GRID_ROW_WIDTH;
|
|
@@ -123,17 +126,23 @@ export function getAllRoomGridIndexes(): readonly int[] {
|
|
|
123
126
|
*
|
|
124
127
|
* @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
|
|
125
128
|
* `RNG.Next` method will be called. Default is `getRandomSeed()`.
|
|
129
|
+
* @param ensureDeadEnd Optional. Whether to pick a valid dead end attached to a normal room. If
|
|
130
|
+
* false, the function will randomly pick from any valid location that would
|
|
131
|
+
* have a red door.
|
|
126
132
|
* @returns Either a tuple of adjacent room grid index, `DoorSlot`, and new room grid index, or
|
|
127
133
|
* undefined.
|
|
128
134
|
*/
|
|
129
|
-
export function getNewRoomCandidate(
|
|
135
|
+
export function getNewRoomCandidate(
|
|
136
|
+
seedOrRNG: Seed | RNG = getRandomSeed(),
|
|
137
|
+
ensureDeadEnd = true,
|
|
138
|
+
):
|
|
130
139
|
| {
|
|
131
140
|
readonly adjacentRoomGridIndex: int;
|
|
132
141
|
readonly doorSlot: DoorSlot;
|
|
133
142
|
readonly newRoomGridIndex: int;
|
|
134
143
|
}
|
|
135
144
|
| undefined {
|
|
136
|
-
const newRoomCandidatesForLevel = getNewRoomCandidatesForLevel();
|
|
145
|
+
const newRoomCandidatesForLevel = getNewRoomCandidatesForLevel(ensureDeadEnd);
|
|
137
146
|
if (newRoomCandidatesForLevel.length === 0) {
|
|
138
147
|
return undefined;
|
|
139
148
|
}
|
|
@@ -143,14 +152,17 @@ export function getNewRoomCandidate(seedOrRNG: Seed | RNG = getRandomSeed()):
|
|
|
143
152
|
|
|
144
153
|
/**
|
|
145
154
|
* Helper function to iterate through the possible doors for a room and see if any of them would be
|
|
146
|
-
* a valid spot to insert a brand new room on the floor.
|
|
147
|
-
* connected to any other existing rooms on the floor.)
|
|
155
|
+
* a valid spot to insert a brand new room on the floor.
|
|
148
156
|
*
|
|
149
157
|
* @param roomGridIndex Optional. Default is the current room index.
|
|
158
|
+
* @param ensureDeadEnd Optional. Whether to only include doors that lead to a valid dead end
|
|
159
|
+
* attached to a normal room. If false, the function will include all doors
|
|
160
|
+
* that would have a red door.
|
|
150
161
|
* @returns A array of tuples of `DoorSlot` and room grid index.
|
|
151
162
|
*/
|
|
152
163
|
export function getNewRoomCandidatesBesideRoom(
|
|
153
164
|
roomGridIndex?: int,
|
|
165
|
+
ensureDeadEnd = true,
|
|
154
166
|
): ReadonlyArray<{ readonly doorSlot: DoorSlot; readonly roomGridIndex: int }> {
|
|
155
167
|
const roomDescriptor = getRoomDescriptor(roomGridIndex);
|
|
156
168
|
|
|
@@ -189,7 +201,7 @@ export function getNewRoomCandidatesBesideRoom(
|
|
|
189
201
|
// Check to see if hypothetically creating a room at the given room grid index would be a dead
|
|
190
202
|
// end. In other words, if we created the room, we would only want it to connect to one other
|
|
191
203
|
// room (this one).
|
|
192
|
-
if (!isDeadEnd(adjacentRoomGridIndex)) {
|
|
204
|
+
if (ensureDeadEnd && !isDeadEnd(adjacentRoomGridIndex)) {
|
|
193
205
|
continue;
|
|
194
206
|
}
|
|
195
207
|
|
|
@@ -203,13 +215,17 @@ export function getNewRoomCandidatesBesideRoom(
|
|
|
203
215
|
}
|
|
204
216
|
|
|
205
217
|
/**
|
|
206
|
-
* Helper function to
|
|
207
|
-
* room.
|
|
218
|
+
* Helper function to get all of the spots on the floor to insert a brand new room.
|
|
208
219
|
*
|
|
220
|
+
* @param ensureDeadEnd Optional. Whether to only include spots that are a valid dead end attached
|
|
221
|
+
* to a normal room. If false, the function will include all valid spots that
|
|
222
|
+
* have a red door.
|
|
209
223
|
* @returns A array of tuples containing the adjacent room grid index, the `DoorSlot`, and the new
|
|
210
224
|
* room grid index.
|
|
211
225
|
*/
|
|
212
|
-
export function getNewRoomCandidatesForLevel(
|
|
226
|
+
export function getNewRoomCandidatesForLevel(
|
|
227
|
+
ensureDeadEnd = true,
|
|
228
|
+
): ReadonlyArray<{
|
|
213
229
|
readonly adjacentRoomGridIndex: int;
|
|
214
230
|
readonly doorSlot: DoorSlot;
|
|
215
231
|
readonly newRoomGridIndex: int;
|
|
@@ -222,21 +238,22 @@ export function getNewRoomCandidatesForLevel(): ReadonlyArray<{
|
|
|
222
238
|
(room) =>
|
|
223
239
|
room.Data !== undefined &&
|
|
224
240
|
room.Data.Type === RoomType.DEFAULT &&
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
room.Data.Subtype !== asNumber(DownpourRoomSubType.MIRROR) &&
|
|
228
|
-
room.Data.Subtype !== asNumber(MinesRoomSubType.MINESHAFT_ENTRANCE),
|
|
241
|
+
!isMirrorRoom(room.Data) && // Mirror rooms do not count as special rooms.
|
|
242
|
+
!isMineShaft(room.Data), // Mineshaft rooms do not count as special rooms.
|
|
229
243
|
);
|
|
230
244
|
|
|
245
|
+
const roomsToLookThrough = ensureDeadEnd ? normalRooms : rooms;
|
|
246
|
+
|
|
231
247
|
const newRoomCandidates: Array<{
|
|
232
248
|
readonly adjacentRoomGridIndex: int;
|
|
233
249
|
readonly doorSlot: DoorSlot;
|
|
234
250
|
readonly newRoomGridIndex: int;
|
|
235
251
|
}> = [];
|
|
236
252
|
|
|
237
|
-
for (const room of
|
|
253
|
+
for (const room of roomsToLookThrough) {
|
|
238
254
|
const newRoomCandidatesBesideRoom = getNewRoomCandidatesBesideRoom(
|
|
239
255
|
room.SafeGridIndex,
|
|
256
|
+
ensureDeadEnd,
|
|
240
257
|
);
|
|
241
258
|
for (const { doorSlot, roomGridIndex } of newRoomCandidatesBesideRoom) {
|
|
242
259
|
newRoomCandidates.push({
|
|
@@ -489,23 +506,29 @@ export function isRoomInsideGrid(roomGridIndex?: int): boolean {
|
|
|
489
506
|
}
|
|
490
507
|
|
|
491
508
|
/**
|
|
492
|
-
* Helper function to generate a new room on the floor
|
|
493
|
-
* room.
|
|
509
|
+
* Helper function to generate a new room on the floor.
|
|
494
510
|
*
|
|
495
511
|
* Under the hood, this function uses the `Level.MakeRedRoomDoor` method to create the room.
|
|
496
512
|
*
|
|
497
|
-
* The newly created room will have data corresponding to the game's randomly generated red room. If
|
|
498
|
-
* you want to modify this, use the `setRoomData` helper function.
|
|
499
|
-
*
|
|
500
513
|
* @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
|
|
501
514
|
* `RNG.Next` method will be called. Default is `Level.GetDungeonPlacementSeed`.
|
|
502
515
|
* Note that the RNG is only used to select the random location to put the room on
|
|
503
516
|
* the floor; it does not influence the randomly chosen room contents. (That is
|
|
504
517
|
* performed by the game and can not be manipulated prior to its generation.)
|
|
518
|
+
* @param ensureDeadEnd Optional. Whether to place the room at a valid dead end attached to a normal
|
|
519
|
+
* room. If false, it will randomly appear at any valid location that would
|
|
520
|
+
* have a red door.
|
|
521
|
+
* @param customRoomData Optional. By default, the newly created room will have data corresponding
|
|
522
|
+
* to the game's randomly generated red room. If you provide this function
|
|
523
|
+
* with room data, it will be used to override the vanilla data.
|
|
505
524
|
* @returns The room grid index of the new room or undefined if the floor had no valid dead ends to
|
|
506
525
|
* place a room.
|
|
507
526
|
*/
|
|
508
|
-
export function newRoom(
|
|
527
|
+
export function newRoom(
|
|
528
|
+
seedOrRNG?: Seed | RNG,
|
|
529
|
+
ensureDeadEnd = true,
|
|
530
|
+
customRoomData?: RoomConfig,
|
|
531
|
+
): int | undefined {
|
|
509
532
|
const level = game.GetLevel();
|
|
510
533
|
|
|
511
534
|
if (seedOrRNG === undefined) {
|
|
@@ -513,7 +536,7 @@ export function newRoom(seedOrRNG?: Seed | RNG): int | undefined {
|
|
|
513
536
|
}
|
|
514
537
|
const rng = isRNG(seedOrRNG) ? seedOrRNG : newRNG(seedOrRNG);
|
|
515
538
|
|
|
516
|
-
const newRoomCandidate = getNewRoomCandidate(rng);
|
|
539
|
+
const newRoomCandidate = getNewRoomCandidate(rng, ensureDeadEnd);
|
|
517
540
|
if (newRoomCandidate === undefined) {
|
|
518
541
|
return undefined;
|
|
519
542
|
}
|
|
@@ -530,6 +553,10 @@ export function newRoom(seedOrRNG?: Seed | RNG): int | undefined {
|
|
|
530
553
|
RoomDescriptorFlag.RED_ROOM,
|
|
531
554
|
);
|
|
532
555
|
|
|
556
|
+
if (customRoomData !== undefined) {
|
|
557
|
+
roomDescriptor.Data = customRoomData;
|
|
558
|
+
}
|
|
559
|
+
|
|
533
560
|
// By default, the new room will not appear on the map, even if the player has The Mind. Thus, we
|
|
534
561
|
// must manually alter the `DisplayFlags` of the room descriptor.
|
|
535
562
|
const roomData = roomDescriptor.Data;
|
package/src/functions/logMisc.ts
CHANGED
|
@@ -328,15 +328,11 @@ export function logRoom(this: void): void {
|
|
|
328
328
|
const roomData = getRoomData();
|
|
329
329
|
|
|
330
330
|
log("Logging room information:");
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
`- Type/variant/sub-type: ${roomData.Type}.${roomData.Variant}.${roomData.Subtype}`,
|
|
337
|
-
);
|
|
338
|
-
log(`- Name: ${roomData.Name}`);
|
|
339
|
-
}
|
|
331
|
+
log(`- Room stage ID: ${roomData.StageID}`);
|
|
332
|
+
log(
|
|
333
|
+
`- Type/variant/sub-type: ${roomData.Type}.${roomData.Variant}.${roomData.Subtype}`,
|
|
334
|
+
);
|
|
335
|
+
log(`- Name: ${roomData.Name}`);
|
|
340
336
|
|
|
341
337
|
const roomGridIndexName = GridRoom[roomGridIndex];
|
|
342
338
|
if (roomGridIndexName === undefined) {
|
|
@@ -31,6 +31,10 @@ export function getRoomAllowedDoors(roomGridIndex?: int): Set<DoorSlot> {
|
|
|
31
31
|
return allowedDoors;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// We provide an overload because the current room is guaranteed to have data.
|
|
35
|
+
export function getRoomData(): RoomConfig;
|
|
36
|
+
export function getRoomData(roomGridIndex?: int): RoomConfig | undefined;
|
|
37
|
+
|
|
34
38
|
/**
|
|
35
39
|
* Helper function to get the room data for the provided room.
|
|
36
40
|
*
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
getRoomShapeBottomRightPosition,
|
|
15
15
|
getRoomShapeTopLeftPosition,
|
|
16
16
|
getRoomShapeWidth,
|
|
17
|
-
|
|
17
|
+
isLRoomShape,
|
|
18
18
|
} from "./roomShape";
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -70,7 +70,7 @@ export function isValidGridPosition(
|
|
|
70
70
|
gridPosition: Vector,
|
|
71
71
|
roomShape: RoomShape,
|
|
72
72
|
): boolean {
|
|
73
|
-
return
|
|
73
|
+
return isLRoomShape(roomShape)
|
|
74
74
|
? isValidGridPositionLRoom(gridPosition, roomShape)
|
|
75
75
|
: isValidGridPositionNormal(gridPosition, roomShape);
|
|
76
76
|
}
|
|
@@ -109,7 +109,7 @@ export function getRoomShapeWidth(roomShape: RoomShape): int {
|
|
|
109
109
|
return ROOM_SHAPE_TO_GRID_WIDTH[roomShape];
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
export function
|
|
112
|
+
export function isLRoomShape(roomShape: RoomShape): boolean {
|
|
113
113
|
return L_ROOM_SHAPES_SET.has(roomShape);
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -5,7 +5,7 @@ import { CornerType } from "../enums/CornerType";
|
|
|
5
5
|
import type { Corner } from "../interfaces/Corner";
|
|
6
6
|
import { ReadonlySet } from "../types/ReadonlySet";
|
|
7
7
|
import { getGridIndexesBetween } from "./gridIndex";
|
|
8
|
-
import { getRoomShapeCorners,
|
|
8
|
+
import { getRoomShapeCorners, isLRoomShape } from "./roomShape";
|
|
9
9
|
import { inBossRoomOf, inHomeCloset } from "./rooms";
|
|
10
10
|
|
|
11
11
|
const ROOM_SHAPE_TO_WALL_GRID_INDEX_SET: ReadonlyMap<
|
|
@@ -26,7 +26,7 @@ function getVanillaWallGridIndexSetForRoomShape(
|
|
|
26
26
|
roomShape: RoomShape,
|
|
27
27
|
): ReadonlySet<int> {
|
|
28
28
|
const corners = getRoomShapeCorners(roomShape);
|
|
29
|
-
const lRoom =
|
|
29
|
+
const lRoom = isLRoomShape(roomShape);
|
|
30
30
|
|
|
31
31
|
if (lRoom && corners.length !== 6) {
|
|
32
32
|
error(
|