isaacscript-common 7.6.0 → 7.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/features/customGridEntity.d.ts +6 -3
  2. package/dist/features/customGridEntity.d.ts.map +1 -1
  3. package/dist/features/customGridEntity.lua +20 -11
  4. package/dist/features/customStage/customStageConstants.d.ts +1 -0
  5. package/dist/features/customStage/customStageConstants.d.ts.map +1 -1
  6. package/dist/features/customStage/customStageConstants.lua +1 -0
  7. package/dist/features/customStage/init.d.ts.map +1 -1
  8. package/dist/features/customStage/init.lua +3 -1
  9. package/dist/features/customStage/versusScreen.d.ts.map +1 -1
  10. package/dist/features/customStage/versusScreen.lua +6 -0
  11. package/dist/features/customTrapdoor/spawn.d.ts.map +1 -1
  12. package/dist/features/customTrapdoor/spawn.lua +3 -4
  13. package/dist/features/extraConsoleCommands/commandsSubroutines.d.ts +1 -0
  14. package/dist/features/extraConsoleCommands/commandsSubroutines.d.ts.map +1 -1
  15. package/dist/features/extraConsoleCommands/commandsSubroutines.lua +31 -7
  16. package/dist/features/extraConsoleCommands/init.lua +1 -0
  17. package/dist/features/extraConsoleCommands/listCommands.d.ts +2 -0
  18. package/dist/features/extraConsoleCommands/listCommands.d.ts.map +1 -1
  19. package/dist/features/extraConsoleCommands/listCommands.lua +5 -0
  20. package/dist/functions/levelGrid.d.ts +44 -12
  21. package/dist/functions/levelGrid.d.ts.map +1 -1
  22. package/dist/functions/levelGrid.lua +97 -59
  23. package/dist/interfaces/CustomStageTSConfig.d.ts +1 -1
  24. package/dist/interfaces/GridEntityCustomData.d.ts +2 -2
  25. package/dist/interfaces/GridEntityCustomData.d.ts.map +1 -1
  26. package/dist/objects/roomTypeNames.d.ts +0 -1
  27. package/dist/objects/roomTypeNames.d.ts.map +1 -1
  28. package/dist/objects/roomTypeNames.lua +0 -1
  29. package/package.json +1 -1
  30. package/src/features/customGridEntity.ts +30 -20
  31. package/src/features/customStage/customStageConstants.ts +2 -0
  32. package/src/features/customStage/init.ts +2 -1
  33. package/src/features/customStage/versusScreen.ts +7 -1
  34. package/src/features/customTrapdoor/spawn.ts +3 -4
  35. package/src/features/extraConsoleCommands/commandsSubroutines.ts +30 -9
  36. package/src/features/extraConsoleCommands/init.ts +1 -0
  37. package/src/features/extraConsoleCommands/listCommands.ts +6 -0
  38. package/src/functions/levelGrid.ts +126 -61
  39. package/src/interfaces/CustomStageTSConfig.ts +1 -1
  40. package/src/interfaces/GridEntityCustomData.ts +2 -2
  41. package/src/objects/roomTypeNames.ts +0 -2
@@ -1,10 +1,10 @@
1
1
  local ____lualib = require("lualib_bundle")
2
- local __TS__ArrayMap = ____lualib.__TS__ArrayMap
3
2
  local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
3
+ local __TS__ArrayMap = ____lualib.__TS__ArrayMap
4
4
  local Map = ____lualib.Map
5
5
  local __TS__Iterator = ____lualib.__TS__Iterator
6
- local Set = ____lualib.Set
7
6
  local __TS__New = ____lualib.__TS__New
7
+ local Set = ____lualib.Set
8
8
  local ____exports = {}
9
9
  local ADJACENT_ROOM_GRID_INDEX_DELTAS
10
10
  local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
@@ -45,7 +45,20 @@ local ____roomShape = require("functions.roomShape")
45
45
  local getGridIndexDelta = ____roomShape.getGridIndexDelta
46
46
  local ____types = require("functions.types")
47
47
  local asNumber = ____types.asNumber
48
- --- Helper function to get the room grid indexes that are adjacent to a given room grid index.
48
+ --- Helper function to get only the adjacent room grid indexes that do not exist (i.e. do not have
49
+ -- room data).
50
+ --
51
+ -- This is just a filtering of the results of the `getAdjacentExistingRoomGridIndexes` function. See
52
+ -- that function for more information.
53
+ function ____exports.getAdjacentNonExistingRoomGridIndexes(self, roomGridIndex)
54
+ local adjacentRoomGridIndexes = ____exports.getAdjacentRoomGridIndexes(nil, roomGridIndex)
55
+ return __TS__ArrayFilter(
56
+ adjacentRoomGridIndexes,
57
+ function(____, adjacentRoomGridIndex) return getRoomData(nil, adjacentRoomGridIndex) == nil end
58
+ )
59
+ end
60
+ --- Helper function to get all of the room grid indexes that are adjacent to a given room grid index
61
+ -- (even if those room grid indexes do not have any rooms in them).
49
62
  --
50
63
  -- Adjacent room grid indexes that are outside of the grid will not be included in the returned
51
64
  -- array.
@@ -85,25 +98,22 @@ function ____exports.getNewRoomCandidatesBesideRoom(self, roomGridIndex)
85
98
  if roomData == nil then
86
99
  return {}
87
100
  end
88
- local doorSlotToRoomGridIndexes = ____exports.getRoomShapeNeighborGridIndexes(nil, roomDescriptor.SafeGridIndex, roomData.Shape)
101
+ local doorSlotToRoomGridIndexes = ____exports.getRoomShapeAdjacentNonExistingGridIndexes(nil, roomDescriptor.SafeGridIndex, roomData.Shape)
89
102
  local roomCandidates = {}
90
103
  for ____, ____value in __TS__Iterator(doorSlotToRoomGridIndexes:entries()) do
91
104
  local doorSlot = ____value[1]
92
- local neighborRoomGridIndex = ____value[2]
105
+ local adjacentRoomGridIndex = ____value[2]
93
106
  do
94
107
  local doorSlotFlag = doorSlotToDoorSlotFlag(nil, doorSlot)
95
108
  if not hasFlag(nil, roomData.Doors, doorSlotFlag) then
96
- goto __continue13
97
- end
98
- if ____exports.roomExists(nil, neighborRoomGridIndex) then
99
- goto __continue13
109
+ goto __continue17
100
110
  end
101
- if not ____exports.isDeadEnd(nil, neighborRoomGridIndex) then
102
- goto __continue13
111
+ if not ____exports.isDeadEnd(nil, adjacentRoomGridIndex) then
112
+ goto __continue17
103
113
  end
104
- roomCandidates[#roomCandidates + 1] = {doorSlot, neighborRoomGridIndex}
114
+ roomCandidates[#roomCandidates + 1] = {doorSlot, adjacentRoomGridIndex}
105
115
  end
106
- ::__continue13::
116
+ ::__continue17::
107
117
  end
108
118
  return roomCandidates
109
119
  end
@@ -128,13 +138,30 @@ function ____exports.getNewRoomCandidatesForLevel(self)
128
138
  end
129
139
  return newRoomCandidates
130
140
  end
141
+ --- Helper function to get only the adjacent room grid indexes for a room shape that exist (i.e. have
142
+ -- room data).
143
+ --
144
+ -- This is just a filtering of the results of the `getRoomShapeAdjacentGridIndexes` function. See
145
+ -- that function for more information.
146
+ function ____exports.getRoomShapeAdjacentExistingGridIndexes(self, safeRoomGridIndex, roomShape)
147
+ local roomShapeAdjacentGridIndexes = ____exports.getRoomShapeAdjacentGridIndexes(nil, safeRoomGridIndex, roomShape)
148
+ for ____, ____value in __TS__Iterator(roomShapeAdjacentGridIndexes:entries()) do
149
+ local doorSlot = ____value[1]
150
+ local roomGridIndex = ____value[2]
151
+ local roomData = getRoomData(nil, roomGridIndex)
152
+ if roomData == nil then
153
+ roomShapeAdjacentGridIndexes:delete(doorSlot)
154
+ end
155
+ end
156
+ return roomShapeAdjacentGridIndexes
157
+ end
131
158
  --- Helper function to get the room grid index delta that each hypothetical door in a given room
132
159
  -- shape would go to.
133
160
  --
134
- -- This is used by the `getRoomShapeNeighborGridIndexes` function.
161
+ -- This is used by the `getRoomShapeAdjacentGridIndexes` function.
135
162
  --
136
163
  -- @returns A map of `DoorSlot` to the corresponding room grid index delta.
137
- function ____exports.getRoomShapeNeighborGridIndexDeltas(self, roomShape)
164
+ function ____exports.getRoomShapeAdjacentGridIndexDeltas(self, roomShape)
138
165
  return ROOM_SHAPE_TO_DOOR_SLOTS_TO_GRID_INDEX_DELTA[roomShape]
139
166
  end
140
167
  --- Helper function to get the room grid index that each hypothetical door in a given room shape
@@ -144,18 +171,35 @@ end
144
171
  -- for the respective room).
145
172
  -- @param roomShape The shape of the room.
146
173
  -- @returns A map of `DoorSlot` to the corresponding room grid index.
147
- function ____exports.getRoomShapeNeighborGridIndexes(self, safeRoomGridIndex, roomShape)
148
- local roomShapeNeighborGridIndexDeltas = ____exports.getRoomShapeNeighborGridIndexDeltas(nil, roomShape)
149
- local neighborGridIndexes = __TS__New(Map)
150
- for ____, ____value in __TS__Iterator(roomShapeNeighborGridIndexDeltas:entries()) do
174
+ function ____exports.getRoomShapeAdjacentGridIndexes(self, safeRoomGridIndex, roomShape)
175
+ local roomShapeAdjacentGridIndexDeltas = ____exports.getRoomShapeAdjacentGridIndexDeltas(nil, roomShape)
176
+ local adjacentGridIndexes = __TS__New(Map)
177
+ for ____, ____value in __TS__Iterator(roomShapeAdjacentGridIndexDeltas:entries()) do
151
178
  local doorSlot = ____value[1]
152
179
  local delta = ____value[2]
153
180
  local roomGridIndex = safeRoomGridIndex + delta
154
181
  if ____exports.isRoomInsideGrid(nil, roomGridIndex) then
155
- neighborGridIndexes:set(doorSlot, roomGridIndex)
182
+ adjacentGridIndexes:set(doorSlot, roomGridIndex)
156
183
  end
157
184
  end
158
- return neighborGridIndexes
185
+ return adjacentGridIndexes
186
+ end
187
+ --- Helper function to get only the adjacent room grid indexes for a room shape that do not exist
188
+ -- (i.e. do not have room data).
189
+ --
190
+ -- This is just a filtering of the results of the `getRoomShapeAdjacentGridIndexes` function. See
191
+ -- that function for more information.
192
+ function ____exports.getRoomShapeAdjacentNonExistingGridIndexes(self, safeRoomGridIndex, roomShape)
193
+ local roomShapeAdjacentGridIndexes = ____exports.getRoomShapeAdjacentGridIndexes(nil, safeRoomGridIndex, roomShape)
194
+ for ____, ____value in __TS__Iterator(roomShapeAdjacentGridIndexes:entries()) do
195
+ local doorSlot = ____value[1]
196
+ local roomGridIndex = ____value[2]
197
+ local roomData = getRoomData(nil, roomGridIndex)
198
+ if roomData ~= nil then
199
+ roomShapeAdjacentGridIndexes:delete(doorSlot)
200
+ end
201
+ end
202
+ return roomShapeAdjacentGridIndexes
159
203
  end
160
204
  --- Helper function to check if the given room grid index is a dead end. Specifically, this is
161
205
  -- defined as having only one adjacent room that exists.
@@ -168,16 +212,8 @@ end
168
212
  --
169
213
  -- @param roomGridIndex Optional. Default is the current room index.
170
214
  function ____exports.isDeadEnd(self, roomGridIndex)
171
- local adjacentRoomGridIndexes = ____exports.getAdjacentRoomGridIndexes(nil, roomGridIndex)
172
- local adjacentRoomData = __TS__ArrayMap(
173
- adjacentRoomGridIndexes,
174
- function(____, adjacentRoomGridIndex) return getRoomData(nil, adjacentRoomGridIndex) end
175
- )
176
- local existingRoomData = __TS__ArrayFilter(
177
- adjacentRoomData,
178
- function(____, data) return data ~= nil end
179
- )
180
- return #existingRoomData == 1
215
+ local adjacentNonExistingRoomGridIndexes = ____exports.getAdjacentNonExistingRoomGridIndexes(nil, roomGridIndex)
216
+ return #adjacentNonExistingRoomGridIndexes == 1
181
217
  end
182
218
  --- Helper function to determine if a given room grid index is inside of the normal 13x13 level grid.
183
219
  --
@@ -201,6 +237,17 @@ local UP = -LEVEL_GRID_ROW_WIDTH
201
237
  local RIGHT = 1
202
238
  local DOWN = LEVEL_GRID_ROW_WIDTH
203
239
  ADJACENT_ROOM_GRID_INDEX_DELTAS = {LEFT, UP, RIGHT, DOWN}
240
+ --- Helper function to get only the adjacent room grid indexes that exist (i.e. have room data).
241
+ --
242
+ -- This is just a filtering of the results of the `getAdjacentExistingRoomGridIndexes` function. See
243
+ -- that function for more information.
244
+ function ____exports.getAdjacentExistingRoomGridIndexes(self, roomGridIndex)
245
+ local adjacentRoomGridIndexes = ____exports.getAdjacentRoomGridIndexes(nil, roomGridIndex)
246
+ return __TS__ArrayFilter(
247
+ adjacentRoomGridIndexes,
248
+ function(____, adjacentRoomGridIndex) return getRoomData(nil, adjacentRoomGridIndex) ~= nil end
249
+ )
250
+ end
204
251
  --- Helper function to get the room safe grid index for every room on the entire floor.
205
252
  function ____exports.getAllRoomGridIndexes(self)
206
253
  local rooms = getRooms(nil)
@@ -227,6 +274,25 @@ function ____exports.getNewRoomCandidate(self, seedOrRNG)
227
274
  end
228
275
  return getRandomArrayElement(nil, newRoomCandidatesForLevel, seedOrRNG)
229
276
  end
277
+ --- Helper function to get the grid indexes of all the rooms connected to the given room index,
278
+ -- taking the shape of the room into account. (This will only include rooms with valid data.)
279
+ --
280
+ -- Returns an empty map if the provided room grid index is out of bounds or has no associated room
281
+ -- data.
282
+ --
283
+ -- @param roomGridIndex Optional. Default is the current room index.
284
+ -- @returns A map of `DoorSlot` to the corresponding room grid index.
285
+ function ____exports.getRoomAdjacentGridIndexes(self, roomGridIndex)
286
+ local roomDescriptor = getRoomDescriptor(nil, roomGridIndex)
287
+ if not ____exports.isRoomInsideGrid(nil, roomDescriptor.SafeGridIndex) then
288
+ return __TS__New(Map)
289
+ end
290
+ local roomData = roomDescriptor.Data
291
+ if roomData == nil then
292
+ return __TS__New(Map)
293
+ end
294
+ return ____exports.getRoomShapeAdjacentExistingGridIndexes(nil, roomDescriptor.SafeGridIndex, roomData.Shape)
295
+ end
230
296
  --- Helper function to get an array of all of the safe grid indexes for rooms that match the
231
297
  -- specified room type.
232
298
  --
@@ -246,34 +312,6 @@ function ____exports.getRoomGridIndexesForType(self, ...)
246
312
  function(____, roomDescriptor) return roomDescriptor.SafeGridIndex end
247
313
  )
248
314
  end
249
- --- Helper function to get the grid indexes of all the rooms connected to the given room index,
250
- -- taking the shape of the room into account. (This will only include rooms with valid data.)
251
- --
252
- -- Returns an empty map if the provided room grid index is out of bounds or has no associated room
253
- -- data.
254
- --
255
- -- @param roomGridIndex Optional. Default is the current room index.
256
- -- @returns A map of `DoorSlot` to the corresponding room grid index.
257
- function ____exports.getRoomNeighbors(self, roomGridIndex)
258
- local roomDescriptor = getRoomDescriptor(nil, roomGridIndex)
259
- if not ____exports.isRoomInsideGrid(nil, roomDescriptor.SafeGridIndex) then
260
- return __TS__New(Map)
261
- end
262
- local roomData = roomDescriptor.Data
263
- if roomData == nil then
264
- return __TS__New(Map)
265
- end
266
- local doorSlotToRoomGridIndexes = ____exports.getRoomShapeNeighborGridIndexes(nil, roomDescriptor.SafeGridIndex, roomData.Shape)
267
- local roomNeighbors = __TS__New(Map)
268
- for ____, ____value in __TS__Iterator(doorSlotToRoomGridIndexes:entries()) do
269
- local doorSlot = ____value[1]
270
- local neighborRoomGridIndex = ____value[2]
271
- if ____exports.roomExists(nil, neighborRoomGridIndex) then
272
- roomNeighbors:set(doorSlot, neighborRoomGridIndex)
273
- end
274
- end
275
- return roomNeighbors
276
- end
277
315
  function ____exports.isDoorSlotValidAtGridIndex(self, doorSlot, roomGridIndex)
278
316
  local allowedDoors = getRoomAllowedDoors(nil, roomGridIndex)
279
317
  return allowedDoors:has(doorSlot)
@@ -26,7 +26,7 @@ export interface CustomStageTSConfig {
26
26
  * https://isaacscript.github.io/main/custom-stages
27
27
  *
28
28
  * @minimum 101
29
- * @maximum 109
29
+ * @maximum 999
30
30
  */
31
31
  roomVariantPrefix: number;
32
32
  /**
@@ -13,8 +13,8 @@ export interface GridEntityCustomData {
13
13
  gridEntityTypeCustom: GridEntityType;
14
14
  roomListIndex: int;
15
15
  gridIndex: int;
16
- anm2Path: string;
16
+ gridCollisionClass?: GridCollisionClass;
17
+ anm2Path?: string;
17
18
  defaultAnimation?: string;
18
- gridCollisionClass: GridCollisionClass;
19
19
  }
20
20
  //# sourceMappingURL=GridEntityCustomData.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GridEntityCustomData.d.ts","sourceRoot":"","sources":["../../src/interfaces/GridEntityCustomData.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,cAAc,EACf,MAAM,8BAA8B,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,oBAAoB,EAAE,cAAc,CAAC;IAErC,aAAa,EAAE,GAAG,CAAC;IACnB,SAAS,EAAE,GAAG,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,kBAAkB,CAAC;CACxC"}
1
+ {"version":3,"file":"GridEntityCustomData.d.ts","sourceRoot":"","sources":["../../src/interfaces/GridEntityCustomData.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,cAAc,EACf,MAAM,8BAA8B,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,oBAAoB,EAAE,cAAc,CAAC;IAErC,aAAa,EAAE,GAAG,CAAC;IACnB,SAAS,EAAE,GAAG,CAAC;IACf,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B"}
@@ -1,5 +1,4 @@
1
1
  import { RoomType } from "isaac-typescript-definitions";
2
- export declare const DEFAULT_ROOM_TYPE_NAME = "Unknown";
3
2
  export declare const ROOM_TYPE_NAMES: {
4
3
  readonly [key in RoomType]: string;
5
4
  };
@@ -1 +1 @@
1
- {"version":3,"file":"roomTypeNames.d.ts","sourceRoot":"","sources":["../../src/objects/roomTypeNames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAExD,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,eAAO,MAAM,eAAe,EAAE;IAAE,QAAQ,EAAE,GAAG,IAAI,QAAQ,GAAG,MAAM;CA8BxD,CAAC"}
1
+ {"version":3,"file":"roomTypeNames.d.ts","sourceRoot":"","sources":["../../src/objects/roomTypeNames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAExD,eAAO,MAAM,eAAe,EAAE;IAAE,QAAQ,EAAE,GAAG,IAAI,QAAQ,GAAG,MAAM;CA8BxD,CAAC"}
@@ -1,7 +1,6 @@
1
1
  local ____exports = {}
2
2
  local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
3
3
  local RoomType = ____isaac_2Dtypescript_2Ddefinitions.RoomType
4
- ____exports.DEFAULT_ROOM_TYPE_NAME = "Unknown"
5
4
  ____exports.ROOM_TYPE_NAMES = {
6
5
  [RoomType.DEFAULT] = "default room",
7
6
  [RoomType.SHOP] = "shop",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "7.6.0",
3
+ "version": "7.7.0",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -184,13 +184,15 @@ function postNewRoomReordered() {
184
184
  continue;
185
185
  }
186
186
 
187
- const sprite = decoration.GetSprite();
188
- sprite.Load(data.anm2Path, true);
189
- const animationToPlay =
190
- data.defaultAnimation === undefined
191
- ? sprite.GetDefaultAnimation()
192
- : data.defaultAnimation;
193
- sprite.Play(animationToPlay, true);
187
+ if (data.anm2Path !== undefined) {
188
+ const sprite = decoration.GetSprite();
189
+ sprite.Load(data.anm2Path, true);
190
+ const animationToPlay =
191
+ data.defaultAnimation === undefined
192
+ ? sprite.GetDefaultAnimation()
193
+ : data.defaultAnimation;
194
+ sprite.Play(animationToPlay, true);
195
+ }
194
196
  }
195
197
  }
196
198
 
@@ -220,8 +222,11 @@ function postNewRoomReordered() {
220
222
  * @param gridIndexOrPosition The grid index or position in the room that you want to spawn the grid
221
223
  * entity at. If a position is specified, the closest grid index will be
222
224
  * used.
223
- * @param gridCollisionClass The collision class that you want the custom grid entity to have.
224
- * @param anm2Path The path to the ANM2 file to use for the sprite.
225
+ * @param gridCollisionClass Optional. The collision class that you want the custom grid entity to
226
+ * have. If not specified, the grid collision class from the base grid
227
+ * entity will be used.
228
+ * @param anm2Path Optional. The path to the ANM2 file to use for the sprite. If not specified, the
229
+ * normal sprite from the base grid entity will be used.
225
230
  * @param defaultAnimation Optional. The name of the animation to play after the sprite is
226
231
  * initialized and after the player re-enters a room with this grid entity
227
232
  * in it. If not specified, the default animation in the anm2 will be used.
@@ -233,8 +238,8 @@ function postNewRoomReordered() {
233
238
  export function spawnCustomGridEntity(
234
239
  gridEntityTypeCustom: GridEntityType,
235
240
  gridIndexOrPosition: int | Vector,
236
- gridCollisionClass: GridCollisionClass,
237
- anm2Path: string,
241
+ gridCollisionClass?: GridCollisionClass,
242
+ anm2Path?: string,
238
243
  defaultAnimation?: string,
239
244
  baseGridEntityType = GridEntityType.DECORATION,
240
245
  baseGridEntityVariant = 0,
@@ -255,15 +260,20 @@ export function spawnCustomGridEntity(
255
260
  if (customGridEntity === undefined) {
256
261
  error("Failed to spawn a custom grid entity.");
257
262
  }
258
- customGridEntity.CollisionClass = gridCollisionClass;
259
-
260
- const sprite = customGridEntity.GetSprite();
261
- sprite.Load(anm2Path, true);
262
- const animationToPlay =
263
- defaultAnimation === undefined
264
- ? sprite.GetDefaultAnimation()
265
- : defaultAnimation;
266
- sprite.Play(animationToPlay, true);
263
+
264
+ if (gridCollisionClass !== undefined) {
265
+ customGridEntity.CollisionClass = gridCollisionClass;
266
+ }
267
+
268
+ if (anm2Path !== undefined) {
269
+ const sprite = customGridEntity.GetSprite();
270
+ sprite.Load(anm2Path, true);
271
+ const animationToPlay =
272
+ defaultAnimation === undefined
273
+ ? sprite.GetDefaultAnimation()
274
+ : defaultAnimation;
275
+ sprite.Play(animationToPlay, true);
276
+ }
267
277
 
268
278
  const customGridEntityData: GridEntityCustomData = {
269
279
  gridEntityTypeCustom,
@@ -1,3 +1,5 @@
1
+ export const CUSTOM_STAGE_FEATURE_NAME = "customStage";
2
+
1
3
  export const ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH = "gfx/isaacscript-custom-stage";
2
4
 
3
5
  /** Corresponds to "ui_streak.anm2". */
@@ -17,6 +17,7 @@ import {
17
17
  import { CustomStage, RoomTypeMap } from "../../interfaces/private/CustomStage";
18
18
  import { saveDataManager } from "../saveDataManager/exports";
19
19
  import { setCustomStageBackdrop } from "./backdrop";
20
+ import { CUSTOM_STAGE_FEATURE_NAME } from "./customStageConstants";
20
21
  import {
21
22
  convertVanillaTrapdoors,
22
23
  removeUrnRewards,
@@ -42,7 +43,7 @@ export function customStageInit(mod: ModUpgraded): void {
42
43
  return;
43
44
  }
44
45
 
45
- saveDataManager("customStage", v);
46
+ saveDataManager(CUSTOM_STAGE_FEATURE_NAME, v);
46
47
  versusScreenInit();
47
48
 
48
49
  mod.AddCallback(ModCallback.POST_RENDER, postRender); // 2
@@ -18,9 +18,13 @@ import { PLAYER_NAME_PNG_FILE_NAMES } from "../../objects/playerNamePNGFileNames
18
18
  import { PLAYER_PORTRAIT_PNG_FILE_NAMES } from "../../objects/playerPortraitPNGFileNames";
19
19
  import { VERSUS_SCREEN_BACKGROUND_COLORS } from "../../objects/versusScreenBackgroundColors";
20
20
  import { VERSUS_SCREEN_DIRT_SPOT_COLORS } from "../../objects/versusScreenDirtSpotColors";
21
+ import { disableAllSound, enableAllSound } from "../disableAllSound";
21
22
  import { pause, unpause } from "../pause";
22
23
  import { runNextGameFrame } from "../runInNFrames";
23
- import { ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH } from "./customStageConstants";
24
+ import {
25
+ CUSTOM_STAGE_FEATURE_NAME,
26
+ ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH,
27
+ } from "./customStageConstants";
24
28
  import {
25
29
  DEFAULT_BASE_STAGE,
26
30
  DEFAULT_BASE_STAGE_TYPE,
@@ -136,6 +140,7 @@ export function playVersusScreenAnimation(customStage: CustomStage): void {
136
140
 
137
141
  pause();
138
142
  hud.SetVisible(false);
143
+ disableAllSound(CUSTOM_STAGE_FEATURE_NAME);
139
144
 
140
145
  // Player
141
146
  {
@@ -273,6 +278,7 @@ function finishVersusScreenAnimation() {
273
278
 
274
279
  unpause();
275
280
  hud.SetVisible(true);
281
+ enableAllSound(CUSTOM_STAGE_FEATURE_NAME);
276
282
 
277
283
  // The sound effect only plays once the versus cutscene is over.
278
284
  sfxManager.Play(SoundEffect.CASTLE_PORTCULLIS);
@@ -45,10 +45,9 @@ export function spawnCustomTrapdoorToDestination(
45
45
  };
46
46
  roomTrapdoorMap.set(gridIndex, customTrapdoorDescription);
47
47
 
48
- if (!open) {
49
- const sprite = gridEntity.GetSprite();
50
- sprite.Play(TrapdoorAnimation.CLOSED, true);
51
- }
48
+ const sprite = gridEntity.GetSprite();
49
+ const animation = open ? TrapdoorAnimation.OPENED : TrapdoorAnimation.CLOSED;
50
+ sprite.Play(animation, true);
52
51
 
53
52
  return gridEntity;
54
53
  }
@@ -9,7 +9,10 @@ import { game } from "../../core/cachedClasses";
9
9
  import { HealthType } from "../../enums/HealthType";
10
10
  import { directionToVector } from "../../functions/direction";
11
11
  import { spawnGridEntityWithVariant } from "../../functions/gridEntities";
12
- import { getRoomGridIndexesForType } from "../../functions/levelGrid";
12
+ import {
13
+ getRoomAdjacentGridIndexes,
14
+ getRoomGridIndexesForType,
15
+ } from "../../functions/levelGrid";
13
16
  import {
14
17
  logAllEntities,
15
18
  logAllGridEntities,
@@ -18,10 +21,7 @@ import { addPlayerHealthType } from "../../functions/playerHealth";
18
21
  import { getRoomData, getRoomDescriptor } from "../../functions/roomData";
19
22
  import { changeRoom } from "../../functions/rooms";
20
23
  import { printConsole } from "../../functions/utils";
21
- import {
22
- DEFAULT_ROOM_TYPE_NAME,
23
- ROOM_TYPE_NAMES,
24
- } from "../../objects/roomTypeNames";
24
+ import { ROOM_TYPE_NAMES } from "../../objects/roomTypeNames";
25
25
 
26
26
  const DEFAULT_MOVE_UNITS = 0.5;
27
27
 
@@ -127,10 +127,6 @@ export function spawnTrapdoorOrCrawlSpace(trapdoor: boolean): void {
127
127
 
128
128
  export function warpToRoomType(roomType: RoomType): void {
129
129
  const roomTypeName = ROOM_TYPE_NAMES[roomType];
130
- if (roomTypeName === DEFAULT_ROOM_TYPE_NAME) {
131
- printConsole(`Invalid room type: ${roomType}`);
132
- }
133
-
134
130
  const gridIndexes = getRoomGridIndexesForType(roomType);
135
131
  const firstGridIndex = gridIndexes[0];
136
132
  if (firstGridIndex === undefined) {
@@ -141,3 +137,28 @@ export function warpToRoomType(roomType: RoomType): void {
141
137
  changeRoom(firstGridIndex);
142
138
  printConsole(`Warped to room type: ${roomTypeName} (${roomType})`);
143
139
  }
140
+
141
+ export function warpNextToRoomType(roomType: RoomType): void {
142
+ const roomTypeName = ROOM_TYPE_NAMES[roomType];
143
+ const gridIndexes = getRoomGridIndexesForType(roomType);
144
+ const firstGridIndex = gridIndexes[0];
145
+ if (firstGridIndex === undefined) {
146
+ printConsole(`There are no ${roomTypeName}s on this floor.`);
147
+ return;
148
+ }
149
+
150
+ const adjacentRoomGridIndexes = getRoomAdjacentGridIndexes(firstGridIndex);
151
+
152
+ for (const [_doorSlot, roomGridIndex] of adjacentRoomGridIndexes.entries()) {
153
+ const roomData = getRoomData(roomGridIndex);
154
+ if (roomData !== undefined && roomData.Type === RoomType.DEFAULT) {
155
+ changeRoom(firstGridIndex);
156
+ printConsole(`Warped next to room type: ${roomTypeName} (${roomType})`);
157
+ return;
158
+ }
159
+ }
160
+
161
+ printConsole(
162
+ `Failed to find the room next to room type: ${roomTypeName} (${roomType})`,
163
+ );
164
+ }
@@ -46,6 +46,7 @@ function initMap() {
46
46
  );
47
47
  extraConsoleCommandsFunctionMap.set("bombs", commands.bombs);
48
48
  extraConsoleCommandsFunctionMap.set("boneHearts", commands.boneHearts);
49
+ extraConsoleCommandsFunctionMap.set("bossNextRoom", commands.bossNextRoom);
49
50
  extraConsoleCommandsFunctionMap.set("bossRoom", commands.bossRoom);
50
51
  extraConsoleCommandsFunctionMap.set("bossRush", commands.bossRush);
51
52
  extraConsoleCommandsFunctionMap.set("brokenHearts", commands.brokenHearts);
@@ -102,6 +102,7 @@ import {
102
102
  listGridEntities,
103
103
  movePlayer,
104
104
  spawnTrapdoorOrCrawlSpace,
105
+ warpNextToRoomType,
105
106
  warpToRoomType,
106
107
  } from "./commandsSubroutines";
107
108
  import v from "./v";
@@ -284,6 +285,11 @@ export function boneHearts(params: string): void {
284
285
  addHeart(params, HealthType.BONE);
285
286
  }
286
287
 
288
+ /** Warps to the room next to the first Boss Room on the floor. */
289
+ export function bossNextRoom(): void {
290
+ warpNextToRoomType(RoomType.BOSS);
291
+ }
292
+
287
293
  /** Warps to the first Boss Room on the floor. */
288
294
  export function bossRoom(): void {
289
295
  warpToRoomType(RoomType.BOSS);