isaacscript-common 6.18.0 → 6.20.1

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/constants.d.ts +5 -0
  2. package/dist/constants.d.ts.map +1 -1
  3. package/dist/constants.lua +4 -0
  4. package/dist/features/customStage/exports.d.ts.map +1 -1
  5. package/dist/features/customStage/exports.lua +2 -7
  6. package/dist/features/customTrapdoor/init.d.ts.map +1 -1
  7. package/dist/features/customTrapdoor/init.lua +10 -2
  8. package/dist/features/extraConsoleCommands/commandsSubroutines.d.ts.map +1 -1
  9. package/dist/features/extraConsoleCommands/commandsSubroutines.lua +2 -1
  10. package/dist/features/extraConsoleCommands/listCommands.d.ts.map +1 -1
  11. package/dist/features/extraConsoleCommands/listCommands.lua +2 -1
  12. package/dist/features/playerInventory.d.ts.map +1 -1
  13. package/dist/features/playerInventory.lua +2 -4
  14. package/dist/functions/curses.d.ts +3 -0
  15. package/dist/functions/curses.d.ts.map +1 -0
  16. package/dist/functions/curses.lua +11 -0
  17. package/dist/functions/dimensions.d.ts +12 -0
  18. package/dist/functions/dimensions.d.ts.map +1 -0
  19. package/dist/functions/dimensions.lua +35 -0
  20. package/dist/functions/eden.d.ts.map +1 -1
  21. package/dist/functions/eden.lua +2 -4
  22. package/dist/functions/itemPool.d.ts +18 -0
  23. package/dist/functions/itemPool.d.ts.map +1 -0
  24. package/dist/functions/itemPool.lua +133 -0
  25. package/dist/functions/level.d.ts.map +1 -1
  26. package/dist/functions/level.lua +8 -7
  27. package/dist/functions/levelGrid.d.ts +155 -0
  28. package/dist/functions/levelGrid.d.ts.map +1 -0
  29. package/dist/functions/levelGrid.lua +349 -0
  30. package/dist/functions/rockAlt.d.ts +4 -4
  31. package/dist/functions/rockAlt.d.ts.map +1 -1
  32. package/dist/functions/rockAlt.lua +69 -20
  33. package/dist/functions/roomData.d.ts +5 -0
  34. package/dist/functions/roomData.d.ts.map +1 -1
  35. package/dist/functions/roomData.lua +6 -0
  36. package/dist/functions/roomGrid.d.ts +8 -0
  37. package/dist/functions/roomGrid.d.ts.map +1 -1
  38. package/dist/functions/rooms.d.ts +42 -61
  39. package/dist/functions/rooms.d.ts.map +1 -1
  40. package/dist/functions/rooms.lua +129 -200
  41. package/dist/functions/saveFile.d.ts +1 -6
  42. package/dist/functions/saveFile.d.ts.map +1 -1
  43. package/dist/functions/saveFile.lua +4 -113
  44. package/dist/index.d.ts +4 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.lua +32 -0
  47. package/package.json +2 -2
  48. package/src/constants.ts +8 -0
  49. package/src/features/customStage/exports.ts +10 -11
  50. package/src/features/customTrapdoor/init.ts +7 -3
  51. package/src/features/extraConsoleCommands/commandsSubroutines.ts +2 -1
  52. package/src/features/extraConsoleCommands/listCommands.ts +2 -1
  53. package/src/features/playerInventory.ts +2 -3
  54. package/src/functions/curses.ts +9 -0
  55. package/src/functions/dimensions.ts +41 -0
  56. package/src/functions/eden.ts +2 -4
  57. package/src/functions/itemPool.ts +178 -0
  58. package/src/functions/level.ts +7 -10
  59. package/src/functions/levelGrid.ts +468 -0
  60. package/src/functions/rockAlt.ts +111 -29
  61. package/src/functions/roomData.ts +12 -0
  62. package/src/functions/roomGrid.ts +9 -0
  63. package/src/functions/rooms.ts +93 -206
  64. package/src/functions/saveFile.ts +5 -147
  65. package/src/index.ts +4 -0
@@ -0,0 +1,155 @@
1
+ /**
2
+ * These functions have to do with the room grid index for the level (i.e. the position that the
3
+ * room is on the grid that represents the map for the level).
4
+ *
5
+ * For functions having to do with the grid index inside of the room, see the "Room Grid" functions.
6
+ *
7
+ * @module
8
+ */
9
+ import { DoorSlot, RoomShape, RoomType } from "isaac-typescript-definitions";
10
+ /**
11
+ * Helper function to get the room grid indexes that are adjacent to a given room grid index.
12
+ *
13
+ * Adjacent room grid indexes that are outside of the grid will not be included in the returned
14
+ * array.
15
+ *
16
+ * If a room grid index is provided that is outside of the grid, then an empty array will be
17
+ * returned.
18
+ *
19
+ * Note that this function does not take the shape of the room into account; it only looks at a
20
+ * single room grid index.
21
+ *
22
+ * @param roomGridIndex Optional. Default is the current room index.
23
+ */
24
+ export declare function getAdjacentRoomGridIndexes(roomGridIndex?: int): int[];
25
+ /** Helper function to get the room safe grid index for every room on the entire floor. */
26
+ export declare function getAllRoomGridIndexes(): int[];
27
+ /**
28
+ * Helper function to pick a random valid spot on the floor to insert a brand new room. Note that
29
+ * some floors will not have any valid spots. If this is the case, this function will return
30
+ * undefined.
31
+ *
32
+ * @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
33
+ * `RNG.Next` method will be called. Default is `getRandomSeed()`.
34
+ * @returns Either a tuple of adjacent room grid index, `DoorSlot`, and new room grid index, or
35
+ * undefined.
36
+ */
37
+ export declare function getNewRoomCandidate(seedOrRNG?: Seed | RNG): [adjacentRoomGridIndex: int, doorSlot: DoorSlot, newRoomGridIndex: int] | undefined;
38
+ /**
39
+ * Helper function to iterate through the possible doors for a room and see if any of them would be
40
+ * a valid spot to insert a brand new room on the floor.
41
+ *
42
+ * @param roomGridIndex Optional. Default is the current room index.
43
+ * @returns A array of tuples of `DoorSlot` and room grid index.
44
+ */
45
+ export declare function getNewRoomCandidatesBesideRoom(roomGridIndex?: int): Array<[doorSlot: DoorSlot, roomGridIndex: int]>;
46
+ /**
47
+ * Helper function to search through all of the rooms on the floor for a spot to insert a brand new
48
+ * room.
49
+ *
50
+ * @returns A array of tuples of adjacent room grid index, `DoorSlot`, and new room grid index.
51
+ */
52
+ export declare function getNewRoomCandidatesForLevel(): Array<[
53
+ adjacentRoomGridIndex: int,
54
+ doorSlot: DoorSlot,
55
+ newRoomGridIndex: int
56
+ ]>;
57
+ /**
58
+ * Helper function to get an array of all of the safe grid indexes for rooms that match the
59
+ * specified room type.
60
+ *
61
+ * This function only searches through rooms in the current dimension.
62
+ *
63
+ * This function is variadic, meaning that you can specify N arguments to get the combined grid
64
+ * indexes for N room types.
65
+ */
66
+ export declare function getRoomGridIndexesForType(...roomTypes: RoomType[]): int[];
67
+ /**
68
+ * Helper function to get the grid indexes of all the rooms connected to the given room index,
69
+ * taking the shape of the room into account. (This will only include rooms with valid data.)
70
+ *
71
+ * Returns an empty map if the provided room grid index is out of bounds or has no associated room
72
+ * data.
73
+ *
74
+ * @param roomGridIndex Optional. Default is the current room index.
75
+ * @returns A map of `DoorSlot` to the corresponding room grid index.
76
+ */
77
+ export declare function getRoomNeighbors(roomGridIndex?: int): Map<DoorSlot, int>;
78
+ /**
79
+ * Helper function to get the room grid index delta that each hypothetical door in a given room
80
+ * shape would go to.
81
+ *
82
+ * This is used by the `getRoomShapeNeighborGridIndexes` function.
83
+ *
84
+ * @returns A map of `DoorSlot` to the corresponding room grid index delta.
85
+ */
86
+ export declare function getRoomShapeNeighborGridIndexDeltas(roomShape: RoomShape): Map<DoorSlot, int>;
87
+ /**
88
+ * Helper function to get the room grid index that each hypothetical door in a given room shape
89
+ * would go to. (This will not include room grid indexes that are outside of the grid.)
90
+ *
91
+ * @param safeRoomGridIndex This must be the room safe grid index (i.e. the top-left room grid index
92
+ * for the respective room).
93
+ * @param roomShape The shape of the room.
94
+ * @returns A map of `DoorSlot` to the corresponding room grid index.
95
+ */
96
+ export declare function getRoomShapeNeighborGridIndexes(safeRoomGridIndex: int, roomShape: RoomShape): Map<DoorSlot, int>;
97
+ /**
98
+ * Helper function to check if the given room grid index is a dead end. Specifically, this is
99
+ * defined as having only one adjacent room that exists.
100
+ *
101
+ * Note that this function does not take the shape of the room into account; it only looks at a
102
+ * single room grid index.
103
+ *
104
+ * This function does not care if the given room grid index actually exists, so you can use it to
105
+ * check if a hypothetical room would be a dead end.
106
+ *
107
+ * @param roomGridIndex Optional. Default is the current room index.
108
+ */
109
+ export declare function isDeadEnd(roomGridIndex?: int): boolean;
110
+ export declare function isDoorSlotValidAtGridIndex(doorSlot: DoorSlot, roomGridIndex: int): boolean;
111
+ export declare function isDoorSlotValidAtGridIndexForRedRoom(doorSlot: DoorSlot, roomGridIndex: int): boolean;
112
+ /**
113
+ * Helper function to detect if the provided room was created by the Red Key item. Under the hood,
114
+ * this checks for the `RoomDescriptorFlag.FLAG_RED_ROOM` flag.
115
+ *
116
+ * @param roomGridIndex Optional. Default is the current room index.
117
+ */
118
+ export declare function isRedKeyRoom(roomGridIndex?: int): boolean;
119
+ /**
120
+ * Helper function to determine if a given room grid index is inside of the normal 13x13 level grid.
121
+ *
122
+ * For example, Devil Rooms and the Mega Satan room are not considered to be inside the grid.
123
+ */
124
+ export declare function isRoomGridIndexInBounds(roomGridIndex: int): boolean;
125
+ /**
126
+ * Helper function to generate a new room on the floor at a valid dead end attached to a normal
127
+ * room.
128
+ *
129
+ * Under the hood, this function uses the `Level.MakeRedRoomDoor` method to create the room.
130
+ *
131
+ * The newly created room will have data corresponding to the game's randomly generated red room. If
132
+ * you want to modify this, use the `setRoomData` helper function.
133
+ *
134
+ * @returns The room grid index of the new room or undefined if the floor had no valid dead ends to
135
+ * place a room.
136
+ */
137
+ export declare function newRoom(): int | undefined;
138
+ /**
139
+ * Helper function to check if a room exists at the given room grid index. (A room will exist if it
140
+ * has non-undefined data in the room descriptor.)
141
+ */
142
+ export declare function roomExists(roomGridIndex: int): boolean;
143
+ /**
144
+ * Helper function to get the coordinates of a given grid index. The floor is represented by a 13x13
145
+ * grid.
146
+ *
147
+ * - Since the starting room is in the center, the starting room grid index of 84 is equal to
148
+ * coordinates of (6, 6).
149
+ * - The top-left grid index of 0 is equal to coordinates of: (12, 0)
150
+ * - The top-right grid index of 12 is equal to coordinates of: (0, 0)
151
+ * - The bottom-left grid index of 156 is equal to coordinates of: (0, 12)
152
+ * - The bottom-right grid index of 168 is equal to coordinates of: (12, 12)
153
+ */
154
+ export declare function roomGridIndexToXY(roomGridIndex: int): [x: int, y: int];
155
+ //# sourceMappingURL=levelGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"levelGrid.d.ts","sourceRoot":"","sources":["../../src/functions/levelGrid.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,QAAQ,EAKR,SAAS,EACT,QAAQ,EACT,MAAM,8BAA8B,CAAC;AA6BtC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,aAAa,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,CAerE;AAED,0FAA0F;AAC1F,wBAAgB,qBAAqB,IAAI,GAAG,EAAE,CAG7C;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,IAAI,GAAG,GAAqB,GAErC,CAAC,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,CAAC,GACvE,SAAS,CAOZ;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,aAAa,CAAC,EAAE,GAAG,GAClB,KAAK,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC,CA+CjD;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,IAAI,KAAK,CACnD;IAAC,qBAAqB,EAAE,GAAG;IAAE,QAAQ,EAAE,QAAQ;IAAE,gBAAgB,EAAE,GAAG;CAAC,CACxE,CAsBA;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,GAAG,EAAE,CAWzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CA+BxE;AAED;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,SAAS,GACnB,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAEpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAC7C,iBAAiB,EAAE,GAAG,EACtB,SAAS,EAAE,SAAS,GACnB,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAapB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,aAAa,CAAC,EAAE,GAAG,GAAG,OAAO,CAUtD;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,GAAG,GACjB,OAAO,CAGT;AAED,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,GAAG,GACjB,OAAO,CAuBT;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,aAAa,CAAC,EAAE,GAAG,GAAG,OAAO,CAGzD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,GAAG,GAAG,OAAO,CAEnE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,IAAI,GAAG,GAAG,SAAS,CA6CzC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,GAAG,GAAG,OAAO,CAGtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAKtE"}
@@ -0,0 +1,349 @@
1
+ local ____lualib = require("lualib_bundle")
2
+ local __TS__ArrayMap = ____lualib.__TS__ArrayMap
3
+ local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
4
+ local Map = ____lualib.Map
5
+ local __TS__Iterator = ____lualib.__TS__Iterator
6
+ local Set = ____lualib.Set
7
+ local __TS__New = ____lualib.__TS__New
8
+ local ____exports = {}
9
+ local ADJACENT_ROOM_GRID_INDEX_DELTAS
10
+ local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
11
+ local DisplayFlag = ____isaac_2Dtypescript_2Ddefinitions.DisplayFlag
12
+ local DownpourRoomSubType = ____isaac_2Dtypescript_2Ddefinitions.DownpourRoomSubType
13
+ local LevelStateFlag = ____isaac_2Dtypescript_2Ddefinitions.LevelStateFlag
14
+ local MinesRoomSubType = ____isaac_2Dtypescript_2Ddefinitions.MinesRoomSubType
15
+ local RoomDescriptorFlag = ____isaac_2Dtypescript_2Ddefinitions.RoomDescriptorFlag
16
+ local RoomType = ____isaac_2Dtypescript_2Ddefinitions.RoomType
17
+ local ____cachedClasses = require("cachedClasses")
18
+ local game = ____cachedClasses.game
19
+ local ____constants = require("constants")
20
+ local ALL_DISPLAY_FLAGS = ____constants.ALL_DISPLAY_FLAGS
21
+ local LEVEL_GRID_ROW_WIDTH = ____constants.LEVEL_GRID_ROW_WIDTH
22
+ local MAX_LEVEL_GRID_INDEX = ____constants.MAX_LEVEL_GRID_INDEX
23
+ local ____roomShapeToDoorSlotsToGridIndexDelta = require("objects.roomShapeToDoorSlotsToGridIndexDelta")
24
+ local ROOM_SHAPE_TO_DOOR_SLOTS_TO_GRID_INDEX_DELTA = ____roomShapeToDoorSlotsToGridIndexDelta.ROOM_SHAPE_TO_DOOR_SLOTS_TO_GRID_INDEX_DELTA
25
+ local ____array = require("functions.array")
26
+ local getRandomArrayElement = ____array.getRandomArrayElement
27
+ local ____doors = require("functions.doors")
28
+ local doorSlotToDoorSlotFlag = ____doors.doorSlotToDoorSlotFlag
29
+ local ____flag = require("functions.flag")
30
+ local addFlag = ____flag.addFlag
31
+ local hasFlag = ____flag.hasFlag
32
+ local removeFlag = ____flag.removeFlag
33
+ local ____rng = require("functions.rng")
34
+ local getRandomSeed = ____rng.getRandomSeed
35
+ local ____roomData = require("functions.roomData")
36
+ local getRoomAllowedDoors = ____roomData.getRoomAllowedDoors
37
+ local getRoomData = ____roomData.getRoomData
38
+ local getRoomDescriptor = ____roomData.getRoomDescriptor
39
+ local getRoomGridIndex = ____roomData.getRoomGridIndex
40
+ local getRoomShape = ____roomData.getRoomShape
41
+ local ____rooms = require("functions.rooms")
42
+ local getRooms = ____rooms.getRooms
43
+ local getRoomsInGrid = ____rooms.getRoomsInGrid
44
+ local ____roomShape = require("functions.roomShape")
45
+ local getGridIndexDelta = ____roomShape.getGridIndexDelta
46
+ --- Helper function to get the room grid indexes that are adjacent to a given room grid index.
47
+ --
48
+ -- Adjacent room grid indexes that are outside of the grid will not be included in the returned
49
+ -- array.
50
+ --
51
+ -- If a room grid index is provided that is outside of the grid, then an empty array will be
52
+ -- returned.
53
+ --
54
+ -- Note that this function does not take the shape of the room into account; it only looks at a
55
+ -- single room grid index.
56
+ --
57
+ -- @param roomGridIndex Optional. Default is the current room index.
58
+ function ____exports.getAdjacentRoomGridIndexes(self, roomGridIndex)
59
+ local roomGridIndexToUse = roomGridIndex == nil and getRoomGridIndex(nil) or roomGridIndex
60
+ if not ____exports.isRoomGridIndexInBounds(nil, roomGridIndexToUse) then
61
+ return {}
62
+ end
63
+ local adjacentRoomGridIndexes = __TS__ArrayMap(
64
+ ADJACENT_ROOM_GRID_INDEX_DELTAS,
65
+ function(____, delta) return roomGridIndexToUse + delta end
66
+ )
67
+ return __TS__ArrayFilter(
68
+ adjacentRoomGridIndexes,
69
+ function(____, adjacentRoomGridIndex) return ____exports.isRoomGridIndexInBounds(nil, adjacentRoomGridIndex) end
70
+ )
71
+ end
72
+ --- Helper function to iterate through the possible doors for a room and see if any of them would be
73
+ -- a valid spot to insert a brand new room on the floor.
74
+ --
75
+ -- @param roomGridIndex Optional. Default is the current room index.
76
+ -- @returns A array of tuples of `DoorSlot` and room grid index.
77
+ function ____exports.getNewRoomCandidatesBesideRoom(self, roomGridIndex)
78
+ local roomDescriptor = getRoomDescriptor(nil, roomGridIndex)
79
+ if not ____exports.isRoomGridIndexInBounds(nil, roomDescriptor.SafeGridIndex) then
80
+ return {}
81
+ end
82
+ local roomData = roomDescriptor.Data
83
+ if roomData == nil then
84
+ return {}
85
+ end
86
+ local doorSlotToRoomGridIndexes = ____exports.getRoomShapeNeighborGridIndexes(nil, roomDescriptor.SafeGridIndex, roomData.Shape)
87
+ local roomCandidates = {}
88
+ for ____, ____value in __TS__Iterator(doorSlotToRoomGridIndexes:entries()) do
89
+ local doorSlot = ____value[1]
90
+ local neighborRoomGridIndex = ____value[2]
91
+ do
92
+ local doorSlotFlag = doorSlotToDoorSlotFlag(nil, doorSlot)
93
+ if not hasFlag(nil, roomData.Doors, doorSlotFlag) then
94
+ goto __continue13
95
+ end
96
+ if ____exports.roomExists(nil, neighborRoomGridIndex) then
97
+ goto __continue13
98
+ end
99
+ if not ____exports.isDeadEnd(nil, neighborRoomGridIndex) then
100
+ goto __continue13
101
+ end
102
+ roomCandidates[#roomCandidates + 1] = {doorSlot, neighborRoomGridIndex}
103
+ end
104
+ ::__continue13::
105
+ end
106
+ return roomCandidates
107
+ end
108
+ --- Helper function to search through all of the rooms on the floor for a spot to insert a brand new
109
+ -- room.
110
+ --
111
+ -- @returns A array of tuples of adjacent room grid index, `DoorSlot`, and new room grid index.
112
+ function ____exports.getNewRoomCandidatesForLevel(self)
113
+ local rooms = getRoomsInGrid(nil)
114
+ local normalRooms = __TS__ArrayFilter(
115
+ rooms,
116
+ function(____, room) return room.Data ~= nil and room.Data.Type == RoomType.DEFAULT and room.Data.Subtype ~= DownpourRoomSubType.MIRROR and room.Data.Subtype ~= MinesRoomSubType.MINESHAFT_ENTRANCE end
117
+ )
118
+ local newRoomCandidates = {}
119
+ for ____, room in ipairs(normalRooms) do
120
+ local newRoomCandidatesBesideRoom = ____exports.getNewRoomCandidatesBesideRoom(nil, room.SafeGridIndex)
121
+ for ____, ____value in ipairs(newRoomCandidatesBesideRoom) do
122
+ local doorSlot = ____value[1]
123
+ local newRoomGridIndex = ____value[2]
124
+ newRoomCandidates[#newRoomCandidates + 1] = {room.SafeGridIndex, doorSlot, newRoomGridIndex}
125
+ end
126
+ end
127
+ return newRoomCandidates
128
+ end
129
+ --- Helper function to get the room grid index delta that each hypothetical door in a given room
130
+ -- shape would go to.
131
+ --
132
+ -- This is used by the `getRoomShapeNeighborGridIndexes` function.
133
+ --
134
+ -- @returns A map of `DoorSlot` to the corresponding room grid index delta.
135
+ function ____exports.getRoomShapeNeighborGridIndexDeltas(self, roomShape)
136
+ return ROOM_SHAPE_TO_DOOR_SLOTS_TO_GRID_INDEX_DELTA[roomShape]
137
+ end
138
+ --- Helper function to get the room grid index that each hypothetical door in a given room shape
139
+ -- would go to. (This will not include room grid indexes that are outside of the grid.)
140
+ --
141
+ -- @param safeRoomGridIndex This must be the room safe grid index (i.e. the top-left room grid index
142
+ -- for the respective room).
143
+ -- @param roomShape The shape of the room.
144
+ -- @returns A map of `DoorSlot` to the corresponding room grid index.
145
+ function ____exports.getRoomShapeNeighborGridIndexes(self, safeRoomGridIndex, roomShape)
146
+ local roomShapeNeighborGridIndexDeltas = ____exports.getRoomShapeNeighborGridIndexDeltas(nil, roomShape)
147
+ local neighborGridIndexes = __TS__New(Map)
148
+ for ____, ____value in __TS__Iterator(roomShapeNeighborGridIndexDeltas:entries()) do
149
+ local doorSlot = ____value[1]
150
+ local delta = ____value[2]
151
+ local roomGridIndex = safeRoomGridIndex + delta
152
+ if ____exports.isRoomGridIndexInBounds(nil, roomGridIndex) then
153
+ neighborGridIndexes:set(doorSlot, roomGridIndex)
154
+ end
155
+ end
156
+ return neighborGridIndexes
157
+ end
158
+ --- Helper function to check if the given room grid index is a dead end. Specifically, this is
159
+ -- defined as having only one adjacent room that exists.
160
+ --
161
+ -- Note that this function does not take the shape of the room into account; it only looks at a
162
+ -- single room grid index.
163
+ --
164
+ -- This function does not care if the given room grid index actually exists, so you can use it to
165
+ -- check if a hypothetical room would be a dead end.
166
+ --
167
+ -- @param roomGridIndex Optional. Default is the current room index.
168
+ function ____exports.isDeadEnd(self, roomGridIndex)
169
+ local adjacentRoomGridIndexes = ____exports.getAdjacentRoomGridIndexes(nil, roomGridIndex)
170
+ local adjacentRoomData = __TS__ArrayMap(
171
+ adjacentRoomGridIndexes,
172
+ function(____, adjacentRoomGridIndex) return getRoomData(nil, adjacentRoomGridIndex) end
173
+ )
174
+ local existingRoomData = __TS__ArrayFilter(
175
+ adjacentRoomData,
176
+ function(____, data) return data ~= nil end
177
+ )
178
+ return #existingRoomData == 1
179
+ end
180
+ --- Helper function to determine if a given room grid index is inside of the normal 13x13 level grid.
181
+ --
182
+ -- For example, Devil Rooms and the Mega Satan room are not considered to be inside the grid.
183
+ function ____exports.isRoomGridIndexInBounds(self, roomGridIndex)
184
+ return roomGridIndex >= 0 and roomGridIndex <= MAX_LEVEL_GRID_INDEX
185
+ end
186
+ --- Helper function to check if a room exists at the given room grid index. (A room will exist if it
187
+ -- has non-undefined data in the room descriptor.)
188
+ function ____exports.roomExists(self, roomGridIndex)
189
+ local roomData = getRoomData(nil, roomGridIndex)
190
+ return roomData ~= nil
191
+ end
192
+ local LEFT = -1
193
+ local UP = -LEVEL_GRID_ROW_WIDTH
194
+ local RIGHT = 1
195
+ local DOWN = LEVEL_GRID_ROW_WIDTH
196
+ ADJACENT_ROOM_GRID_INDEX_DELTAS = {LEFT, UP, RIGHT, DOWN}
197
+ --- Helper function to get the room safe grid index for every room on the entire floor.
198
+ function ____exports.getAllRoomGridIndexes(self)
199
+ local rooms = getRooms(nil)
200
+ return __TS__ArrayMap(
201
+ rooms,
202
+ function(____, roomDescriptor) return roomDescriptor.SafeGridIndex end
203
+ )
204
+ end
205
+ --- Helper function to pick a random valid spot on the floor to insert a brand new room. Note that
206
+ -- some floors will not have any valid spots. If this is the case, this function will return
207
+ -- undefined.
208
+ --
209
+ -- @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
210
+ -- `RNG.Next` method will be called. Default is `getRandomSeed()`.
211
+ -- @returns Either a tuple of adjacent room grid index, `DoorSlot`, and new room grid index, or
212
+ -- undefined.
213
+ function ____exports.getNewRoomCandidate(self, seedOrRNG)
214
+ if seedOrRNG == nil then
215
+ seedOrRNG = getRandomSeed(nil)
216
+ end
217
+ local newRoomCandidatesForLevel = ____exports.getNewRoomCandidatesForLevel(nil)
218
+ if #newRoomCandidatesForLevel == 0 then
219
+ return nil
220
+ end
221
+ return getRandomArrayElement(nil, newRoomCandidatesForLevel, seedOrRNG)
222
+ end
223
+ --- Helper function to get an array of all of the safe grid indexes for rooms that match the
224
+ -- specified room type.
225
+ --
226
+ -- This function only searches through rooms in the current dimension.
227
+ --
228
+ -- This function is variadic, meaning that you can specify N arguments to get the combined grid
229
+ -- indexes for N room types.
230
+ function ____exports.getRoomGridIndexesForType(self, ...)
231
+ local roomTypesSet = __TS__New(Set, {...})
232
+ local rooms = getRooms(nil)
233
+ local matchingRooms = __TS__ArrayFilter(
234
+ rooms,
235
+ function(____, roomDescriptor) return roomDescriptor.Data ~= nil and roomTypesSet:has(roomDescriptor.Data.Type) end
236
+ )
237
+ return __TS__ArrayMap(
238
+ matchingRooms,
239
+ function(____, roomDescriptor) return roomDescriptor.SafeGridIndex end
240
+ )
241
+ end
242
+ --- Helper function to get the grid indexes of all the rooms connected to the given room index,
243
+ -- taking the shape of the room into account. (This will only include rooms with valid data.)
244
+ --
245
+ -- Returns an empty map if the provided room grid index is out of bounds or has no associated room
246
+ -- data.
247
+ --
248
+ -- @param roomGridIndex Optional. Default is the current room index.
249
+ -- @returns A map of `DoorSlot` to the corresponding room grid index.
250
+ function ____exports.getRoomNeighbors(self, roomGridIndex)
251
+ local roomDescriptor = getRoomDescriptor(nil, roomGridIndex)
252
+ if not ____exports.isRoomGridIndexInBounds(nil, roomDescriptor.SafeGridIndex) then
253
+ return __TS__New(Map)
254
+ end
255
+ local roomData = roomDescriptor.Data
256
+ if roomData == nil then
257
+ return __TS__New(Map)
258
+ end
259
+ local doorSlotToRoomGridIndexes = ____exports.getRoomShapeNeighborGridIndexes(nil, roomDescriptor.SafeGridIndex, roomData.Shape)
260
+ local roomNeighbors = __TS__New(Map)
261
+ for ____, ____value in __TS__Iterator(doorSlotToRoomGridIndexes:entries()) do
262
+ local doorSlot = ____value[1]
263
+ local neighborRoomGridIndex = ____value[2]
264
+ if ____exports.roomExists(nil, neighborRoomGridIndex) then
265
+ roomNeighbors:set(doorSlot, neighborRoomGridIndex)
266
+ end
267
+ end
268
+ return roomNeighbors
269
+ end
270
+ function ____exports.isDoorSlotValidAtGridIndex(self, doorSlot, roomGridIndex)
271
+ local allowedDoors = getRoomAllowedDoors(nil, roomGridIndex)
272
+ return allowedDoors:has(doorSlot)
273
+ end
274
+ function ____exports.isDoorSlotValidAtGridIndexForRedRoom(self, doorSlot, roomGridIndex)
275
+ local doorSlotValidAtGridIndex = ____exports.isDoorSlotValidAtGridIndex(nil, doorSlot, roomGridIndex)
276
+ if not doorSlotValidAtGridIndex then
277
+ return false
278
+ end
279
+ local roomShape = getRoomShape(nil, roomGridIndex)
280
+ if roomShape == nil then
281
+ return false
282
+ end
283
+ local delta = getGridIndexDelta(nil, roomShape, doorSlot)
284
+ if delta == nil then
285
+ return false
286
+ end
287
+ local redRoomGridIndex = roomGridIndex + delta
288
+ return not ____exports.roomExists(nil, redRoomGridIndex) and ____exports.isRoomGridIndexInBounds(nil, redRoomGridIndex)
289
+ end
290
+ --- Helper function to detect if the provided room was created by the Red Key item. Under the hood,
291
+ -- this checks for the `RoomDescriptorFlag.FLAG_RED_ROOM` flag.
292
+ --
293
+ -- @param roomGridIndex Optional. Default is the current room index.
294
+ function ____exports.isRedKeyRoom(self, roomGridIndex)
295
+ local roomDescriptor = getRoomDescriptor(nil, roomGridIndex)
296
+ return hasFlag(nil, roomDescriptor.Flags, RoomDescriptorFlag.RED_ROOM)
297
+ end
298
+ --- Helper function to generate a new room on the floor at a valid dead end attached to a normal
299
+ -- room.
300
+ --
301
+ -- Under the hood, this function uses the `Level.MakeRedRoomDoor` method to create the room.
302
+ --
303
+ -- The newly created room will have data corresponding to the game's randomly generated red room. If
304
+ -- you want to modify this, use the `setRoomData` helper function.
305
+ --
306
+ -- @returns The room grid index of the new room or undefined if the floor had no valid dead ends to
307
+ -- place a room.
308
+ function ____exports.newRoom(self)
309
+ local newRoomCandidate = ____exports.getNewRoomCandidate(nil)
310
+ if newRoomCandidate == nil then
311
+ return nil
312
+ end
313
+ local adjacentRoomGridIndex, doorSlot, newRoomGridIndex = table.unpack(newRoomCandidate)
314
+ local level = game:GetLevel()
315
+ level:MakeRedRoomDoor(adjacentRoomGridIndex, doorSlot)
316
+ local roomDescriptor = getRoomDescriptor(nil, newRoomGridIndex)
317
+ roomDescriptor.Flags = removeFlag(nil, roomDescriptor.Flags, RoomDescriptorFlag.RED_ROOM)
318
+ local roomData = roomDescriptor.Data
319
+ if roomData ~= nil then
320
+ local hasFullMap = level:GetStateFlag(LevelStateFlag.FULL_MAP_EFFECT)
321
+ local hasCompass = level:GetStateFlag(LevelStateFlag.COMPASS_EFFECT)
322
+ local hasBlueMap = level:GetStateFlag(LevelStateFlag.BLUE_MAP_EFFECT)
323
+ local roomType = roomData.Type
324
+ local isSecretRoom = roomType == RoomType.SECRET or roomType == RoomType.SUPER_SECRET
325
+ if hasFullMap then
326
+ roomDescriptor.DisplayFlags = ALL_DISPLAY_FLAGS
327
+ elseif not isSecretRoom and hasCompass then
328
+ roomDescriptor.DisplayFlags = addFlag(nil, DisplayFlag.VISIBLE, DisplayFlag.SHOW_ICON)
329
+ elseif isSecretRoom and hasBlueMap then
330
+ roomDescriptor.DisplayFlags = addFlag(nil, DisplayFlag.VISIBLE, DisplayFlag.SHOW_ICON)
331
+ end
332
+ end
333
+ return newRoomGridIndex
334
+ end
335
+ --- Helper function to get the coordinates of a given grid index. The floor is represented by a 13x13
336
+ -- grid.
337
+ --
338
+ -- - Since the starting room is in the center, the starting room grid index of 84 is equal to
339
+ -- coordinates of (6, 6).
340
+ -- - The top-left grid index of 0 is equal to coordinates of: (12, 0)
341
+ -- - The top-right grid index of 12 is equal to coordinates of: (0, 0)
342
+ -- - The bottom-left grid index of 156 is equal to coordinates of: (0, 12)
343
+ -- - The bottom-right grid index of 168 is equal to coordinates of: (12, 12)
344
+ function ____exports.roomGridIndexToXY(self, roomGridIndex)
345
+ local x = roomGridIndex % LEVEL_GRID_ROW_WIDTH
346
+ local y = math.floor(roomGridIndex / LEVEL_GRID_ROW_WIDTH)
347
+ return {x, y}
348
+ end
349
+ return ____exports
@@ -24,10 +24,10 @@ export declare function getRockAltType(): RockAltType;
24
24
  * Most of the time, this function will do nothing, similar to how most of the time, when an
25
25
  * individual urn is destroyed, nothing will spawn.
26
26
  *
27
- * Note that in vanilla, collectibles and trinkets will not spawn if they have already been removed
28
- * from the respective pool. This function cannot replicate that behavior because there is no way to
29
- * check to see if a collectible or trinket is still in the pool. Thus, it will always have a chance
30
- * to spawn the respective collectible/trinket (e.g. Swallowed Penny from urns).
27
+ * Note that in vanilla, trinkets will not spawn if they have already been removed from the trinket
28
+ * pool. This function cannot replicate that behavior because there is no way to check to see if a
29
+ * trinket is still in the pool. Thus, it will always have a chance to spawn the respective trinket
30
+ * (e.g. Swallowed Penny from urns).
31
31
  *
32
32
  * The logic in this function is based on the rewards listed on the wiki:
33
33
  * https://bindingofisaacrebirth.fandom.com/wiki/Rocks
@@ -1 +1 @@
1
- {"version":3,"file":"rockAlt.d.ts","sourceRoot":"","sources":["../../src/functions/rockAlt.ts"],"names":[],"mappings":";;;AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA8BnD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAK5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,WAAW,EACxB,OAAO,SAAI,EACX,SAAS,GAAE,IAAI,GAAG,GAAqB,GACtC,OAAO,CAwBT"}
1
+ {"version":3,"file":"rockAlt.d.ts","sourceRoot":"","sources":["../../src/functions/rockAlt.ts"],"names":[],"mappings":";;;AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA+BnD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAK5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,WAAW,EACxB,OAAO,SAAI,EACX,SAAS,GAAE,IAAI,GAAG,GAAqB,GACtC,OAAO,CAwBT"}
@@ -7,6 +7,7 @@ local CollectibleType = ____isaac_2Dtypescript_2Ddefinitions.CollectibleType
7
7
  local EffectVariant = ____isaac_2Dtypescript_2Ddefinitions.EffectVariant
8
8
  local EntityType = ____isaac_2Dtypescript_2Ddefinitions.EntityType
9
9
  local HeartSubType = ____isaac_2Dtypescript_2Ddefinitions.HeartSubType
10
+ local ItemPoolType = ____isaac_2Dtypescript_2Ddefinitions.ItemPoolType
10
11
  local PillColor = ____isaac_2Dtypescript_2Ddefinitions.PillColor
11
12
  local RoomType = ____isaac_2Dtypescript_2Ddefinitions.RoomType
12
13
  local TrinketType = ____isaac_2Dtypescript_2Ddefinitions.TrinketType
@@ -21,6 +22,8 @@ local BACKDROP_TYPE_TO_ROCK_ALT_TYPE = ____backdropTypeToRockAltType.BACKDROP_TY
21
22
  local ____entitiesSpecific = require("functions.entitiesSpecific")
22
23
  local spawnEffectWithSeed = ____entitiesSpecific.spawnEffectWithSeed
23
24
  local spawnNPCWithSeed = ____entitiesSpecific.spawnNPCWithSeed
25
+ local ____itemPool = require("functions.itemPool")
26
+ local isCollectibleInItemPool = ____itemPool.isCollectibleInItemPool
24
27
  local ____pickupsSpecific = require("functions.pickupsSpecific")
25
28
  local spawnCardWithSeed = ____pickupsSpecific.spawnCardWithSeed
26
29
  local spawnCoinWithSeed = ____pickupsSpecific.spawnCoinWithSeed
@@ -77,8 +80,12 @@ function spawnRockAltRewardUrn(self, position, rng)
77
80
  end
78
81
  totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
79
82
  if chance < totalChance then
80
- spawnCollectible(nil, CollectibleType.QUARTER, position, rng)
81
- return true
83
+ local stillInPools = isCollectibleInItemPool(nil, CollectibleType.QUARTER, ItemPoolType.DEVIL)
84
+ if stillInPools then
85
+ spawnCollectible(nil, CollectibleType.QUARTER, position, rng)
86
+ return true
87
+ end
88
+ return false
82
89
  end
83
90
  local numSpidersChance = getRandom(nil, rng)
84
91
  local numSpiders = numSpidersChance < 0.5 and 1 or 2
@@ -125,14 +132,30 @@ function spawnRockAltRewardMushroom(self, position, rng)
125
132
  if roomType == RoomType.SECRET then
126
133
  local wavyCapChance = getRandom(nil, rng)
127
134
  if wavyCapChance < 0.0272 then
128
- spawnCollectible(nil, CollectibleType.WAVY_CAP, position, rng)
129
- return true
135
+ local stillInPools = isCollectibleInItemPool(nil, CollectibleType.WAVY_CAP, ItemPoolType.SECRET)
136
+ if stillInPools then
137
+ spawnCollectible(nil, CollectibleType.WAVY_CAP, position, rng)
138
+ return true
139
+ end
130
140
  end
131
141
  end
132
- local collectibleChance = getRandom(nil, rng)
133
- local collectibleType = collectibleChance < 0.5 and CollectibleType.MAGIC_MUSHROOM or CollectibleType.MINI_MUSH
134
- spawnCollectible(nil, collectibleType, position, rng)
135
- return true
142
+ local magicMushroomStillInPools = isCollectibleInItemPool(nil, CollectibleType.MAGIC_MUSHROOM, ItemPoolType.TREASURE)
143
+ local miniMushStillInPools = isCollectibleInItemPool(nil, CollectibleType.MINI_MUSH, ItemPoolType.TREASURE)
144
+ if magicMushroomStillInPools and miniMushStillInPools then
145
+ local collectibleChance = getRandom(nil, rng)
146
+ local collectibleType = collectibleChance < 0.5 and CollectibleType.MAGIC_MUSHROOM or CollectibleType.MINI_MUSH
147
+ spawnCollectible(nil, collectibleType, position, rng)
148
+ return true
149
+ end
150
+ if magicMushroomStillInPools then
151
+ spawnCollectible(nil, CollectibleType.MINI_MUSH, position, rng)
152
+ return true
153
+ end
154
+ if miniMushStillInPools then
155
+ spawnCollectible(nil, CollectibleType.MAGIC_MUSHROOM, position, rng)
156
+ return true
157
+ end
158
+ return false
136
159
  end
137
160
  spawnEffectWithSeed(
138
161
  nil,
@@ -162,10 +185,23 @@ function spawnRockAltRewardSkull(self, position, rng)
162
185
  end
163
186
  totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
164
187
  if chance < totalChance then
165
- local collectibleChance = getRandom(nil, rng)
166
- local collectibleType = collectibleChance < 0.5 and CollectibleType.GHOST_BABY or CollectibleType.DRY_BABY
167
- spawnCollectible(nil, collectibleType, position, rng)
168
- return true
188
+ local ghostBabyStillInPools = isCollectibleInItemPool(nil, CollectibleType.GHOST_BABY, ItemPoolType.TREASURE)
189
+ local dryBabyStillInPools = isCollectibleInItemPool(nil, CollectibleType.DRY_BABY, ItemPoolType.TREASURE)
190
+ if ghostBabyStillInPools and dryBabyStillInPools then
191
+ local collectibleChance = getRandom(nil, rng)
192
+ local collectibleType = collectibleChance < 0.5 and CollectibleType.GHOST_BABY or CollectibleType.DRY_BABY
193
+ spawnCollectible(nil, collectibleType, position, rng)
194
+ return true
195
+ end
196
+ if ghostBabyStillInPools then
197
+ spawnCollectible(nil, CollectibleType.DRY_BABY, position, rng)
198
+ return true
199
+ end
200
+ if dryBabyStillInPools then
201
+ spawnCollectible(nil, CollectibleType.GHOST_BABY, position, rng)
202
+ return true
203
+ end
204
+ return false
169
205
  end
170
206
  spawnNPCWithSeed(
171
207
  nil,
@@ -196,10 +232,23 @@ function spawnRockAltRewardPolyp(self, position, rng)
196
232
  end
197
233
  totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
198
234
  if chance < totalChance then
199
- local collectibleChance = getRandom(nil, rng)
200
- local collectibleType = collectibleChance < 0.5 and CollectibleType.PLACENTA or CollectibleType.BLOOD_CLOT
201
- spawnCollectible(nil, collectibleType, position, rng)
202
- return true
235
+ local placentaStillInPools = isCollectibleInItemPool(nil, CollectibleType.PLACENTA, ItemPoolType.BOSS)
236
+ local bloodClotStillInPools = isCollectibleInItemPool(nil, CollectibleType.BLOOD_CLOT, ItemPoolType.BOSS)
237
+ if bloodClotStillInPools and placentaStillInPools then
238
+ local collectibleChance = getRandom(nil, rng)
239
+ local collectibleType = collectibleChance < 0.5 and CollectibleType.PLACENTA or CollectibleType.BLOOD_CLOT
240
+ spawnCollectible(nil, collectibleType, position, rng)
241
+ return true
242
+ end
243
+ if bloodClotStillInPools then
244
+ spawnCollectible(nil, CollectibleType.MINI_MUSH, position, rng)
245
+ return true
246
+ end
247
+ if placentaStillInPools then
248
+ spawnCollectible(nil, CollectibleType.MAGIC_MUSHROOM, position, rng)
249
+ return true
250
+ end
251
+ return false
203
252
  end
204
253
  spawnEffectWithSeed(
205
254
  nil,
@@ -252,10 +301,10 @@ end
252
301
  -- Most of the time, this function will do nothing, similar to how most of the time, when an
253
302
  -- individual urn is destroyed, nothing will spawn.
254
303
  --
255
- -- Note that in vanilla, collectibles and trinkets will not spawn if they have already been removed
256
- -- from the respective pool. This function cannot replicate that behavior because there is no way to
257
- -- check to see if a collectible or trinket is still in the pool. Thus, it will always have a chance
258
- -- to spawn the respective collectible/trinket (e.g. Swallowed Penny from urns).
304
+ -- Note that in vanilla, trinkets will not spawn if they have already been removed from the trinket
305
+ -- pool. This function cannot replicate that behavior because there is no way to check to see if a
306
+ -- trinket is still in the pool. Thus, it will always have a chance to spawn the respective trinket
307
+ -- (e.g. Swallowed Penny from urns).
259
308
  --
260
309
  -- The logic in this function is based on the rewards listed on the wiki:
261
310
  -- https://bindingofisaacrebirth.fandom.com/wiki/Rocks