isaacscript-common 6.1.1 → 6.2.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.
@@ -120,7 +120,7 @@ function DefaultMap.prototype.getDefaultValue(self, ...)
120
120
  if self.defaultValueFactory ~= nil then
121
121
  return self:defaultValueFactory(...)
122
122
  end
123
- return error("A DefaultMap was incorrectly instantiated.")
123
+ error("A DefaultMap was incorrectly instantiated.")
124
124
  end
125
125
  function DefaultMap.prototype.getConstructorArg(self)
126
126
  if self.defaultValue ~= nil then
@@ -129,6 +129,6 @@ function DefaultMap.prototype.getConstructorArg(self)
129
129
  if self.defaultValueFactory ~= nil then
130
130
  return self.defaultValueFactory
131
131
  end
132
- return error("A DefaultMap was incorrectly instantiated.")
132
+ error("A DefaultMap was incorrectly instantiated.")
133
133
  end
134
134
  return ____exports
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Helper function to warp to a custom stage/level.
3
3
  *
4
- * Custom stages/levels must first be registered with the `registerCustomStage` function.
4
+ * Custom stages/levels must first be defined in the "tsconfig.json" file. See the documentation for
5
+ * more details: https://isaacscript.github.io/main/custom-stages/
5
6
  */
6
- export declare function setCustomStage(name: string): void;
7
+ export declare function setCustomStage(name: string, verbose?: boolean): void;
@@ -1,15 +1,94 @@
1
1
  local ____lualib = require("lualib_bundle")
2
2
  local Map = ____lualib.Map
3
3
  local ____exports = {}
4
+ local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
5
+ local Direction = ____isaac_2Dtypescript_2Ddefinitions.Direction
6
+ local GridRoom = ____isaac_2Dtypescript_2Ddefinitions.GridRoom
7
+ local RoomShape = ____isaac_2Dtypescript_2Ddefinitions.RoomShape
8
+ local RoomTransitionAnim = ____isaac_2Dtypescript_2Ddefinitions.RoomTransitionAnim
9
+ local RoomType = ____isaac_2Dtypescript_2Ddefinitions.RoomType
10
+ local StageType = ____isaac_2Dtypescript_2Ddefinitions.StageType
11
+ local ____cachedClasses = require("cachedClasses")
12
+ local game = ____cachedClasses.game
13
+ local ____log = require("functions.log")
14
+ local logError = ____log.logError
15
+ local ____rng = require("functions.rng")
16
+ local newRNG = ____rng.newRNG
17
+ local ____roomData = require("functions.roomData")
18
+ local getRoomData = ____roomData.getRoomData
19
+ local ____rooms = require("functions.rooms")
20
+ local getRooms = ____rooms.getRooms
21
+ local ____stage = require("functions.stage")
22
+ local getGotoCommand = ____stage.getGotoCommand
23
+ local setStage = ____stage.setStage
24
+ local ____util = require("features.customStage.util")
25
+ local getRandomCustomStageRoom = ____util.getRandomCustomStageRoom
4
26
  local ____v = require("features.customStage.v")
27
+ local customStageCachedRoomData = ____v.customStageCachedRoomData
5
28
  local customStagesMap = ____v.customStagesMap
6
29
  --- Helper function to warp to a custom stage/level.
7
30
  --
8
- -- Custom stages/levels must first be registered with the `registerCustomStage` function.
9
- function ____exports.setCustomStage(self, name)
31
+ -- Custom stages/levels must first be defined in the "tsconfig.json" file. See the documentation for
32
+ -- more details: https://isaacscript.github.io/main/custom-stages/
33
+ function ____exports.setCustomStage(self, name, verbose)
34
+ if verbose == nil then
35
+ verbose = false
36
+ end
10
37
  local customStage = customStagesMap:get(name)
11
38
  if customStage == nil then
12
- error(("Failed to set the custom stage of \"" .. name) .. "\" because it was not found in the custom stages map. (This means that you probably forgot to define it in your \"tsconfig.json\" file.) See the website for more details on how to set up custom stages..")
39
+ error(("Failed to set the custom stage of \"" .. name) .. "\" because it was not found in the custom stages map. (This means that you probably forgot to define it in your \"tsconfig.json\" file.) See the website for more details on how to set up custom stages.")
40
+ end
41
+ local level = game:GetLevel()
42
+ local startingRoomGridIndex = level:GetStartingRoomIndex()
43
+ local seeds = game:GetSeeds()
44
+ local startSeed = seeds:GetStartSeed()
45
+ local rng = newRNG(nil, startSeed)
46
+ setStage(nil, customStage.baseStage, customStage.baseStageType)
47
+ for ____, room in ipairs(getRooms(nil)) do
48
+ do
49
+ if room.SafeGridIndex == startingRoomGridIndex then
50
+ goto __continue4
51
+ end
52
+ if room.Data == nil then
53
+ goto __continue4
54
+ end
55
+ local roomType = room.Data.Type
56
+ local roomShapeMap = customStage.roomTypeMap:get(roomType)
57
+ if roomShapeMap == nil then
58
+ if roomType == RoomType.DEFAULT then
59
+ logError((((("Failed to find any custom rooms for RoomType." .. tostring(RoomType[roomType])) .. " (") .. tostring(roomType)) .. ") for custom stage: ") .. name)
60
+ end
61
+ goto __continue4
62
+ end
63
+ local roomShape = room.Data.Shape
64
+ local roomDoorSlotFlagMap = roomShapeMap:get(roomShape)
65
+ if roomDoorSlotFlagMap == nil then
66
+ logError((((((((("Failed to find any custom rooms for RoomType." .. tostring(RoomType[roomType])) .. " (") .. tostring(roomType)) .. ") + RoomShape.") .. tostring(RoomShape[roomShape])) .. " (") .. tostring(roomShape)) .. ") for custom stage: ") .. name)
67
+ goto __continue4
68
+ end
69
+ local doorSlotFlags = room.Data.Doors
70
+ local roomsMetadata = roomDoorSlotFlagMap:get(doorSlotFlags)
71
+ if roomsMetadata == nil then
72
+ logError((((((((((("Failed to find any custom rooms for RoomType." .. tostring(RoomType[roomType])) .. " (") .. tostring(roomType)) .. ") + RoomShape.") .. tostring(RoomShape[roomShape])) .. " (") .. tostring(roomShape)) .. ") + DoorSlotFlags ") .. tostring(doorSlotFlags)) .. " for custom stage: ") .. name)
73
+ goto __continue4
74
+ end
75
+ local randomRoom = getRandomCustomStageRoom(nil, roomsMetadata, rng, verbose)
76
+ local newRoomData = customStageCachedRoomData:get(randomRoom.variant)
77
+ if newRoomData == nil then
78
+ local command = getGotoCommand(nil, roomType, randomRoom.variant)
79
+ Isaac.ExecuteCommand(command)
80
+ newRoomData = getRoomData(nil, GridRoom.DEBUG)
81
+ if newRoomData == nil then
82
+ logError((("Failed to get the room data for room variant " .. tostring(randomRoom.variant)) .. " for custom stage: ") .. name)
83
+ goto __continue4
84
+ end
85
+ customStageCachedRoomData:set(randomRoom.variant, newRoomData)
86
+ end
87
+ room.Data = newRoomData
88
+ end
89
+ ::__continue4::
13
90
  end
91
+ level:SetStage(-1, StageType.ORIGINAL)
92
+ game:StartRoomTransition(startingRoomGridIndex, Direction.NO_DIRECTION, RoomTransitionAnim.FADE)
14
93
  end
15
94
  return ____exports
@@ -1,17 +1,47 @@
1
1
  local ____lualib = require("lualib_bundle")
2
2
  local Map = ____lualib.Map
3
+ local __TS__ObjectAssign = ____lualib.__TS__ObjectAssign
4
+ local __TS__New = ____lualib.__TS__New
3
5
  local ____exports = {}
6
+ local getRoomTypeMap
4
7
  local ____array = require("functions.array")
5
8
  local isArray = ____array.isArray
6
9
  local metadataJSON = require("features.customStage.metadata")
7
10
  local ____v = require("features.customStage.v")
8
11
  local customStagesMap = ____v.customStagesMap
12
+ function getRoomTypeMap(self, customStageLua)
13
+ local roomTypeMap = __TS__New(Map)
14
+ for ____, roomMetadata in ipairs(customStageLua.roomsMetadata) do
15
+ local roomType = roomMetadata.type
16
+ local roomShapeMap = roomTypeMap:get(roomType)
17
+ if roomShapeMap == nil then
18
+ roomShapeMap = __TS__New(Map)
19
+ roomTypeMap:set(roomType, roomShapeMap)
20
+ end
21
+ local roomShape = roomMetadata.shape
22
+ local roomDoorSlotFlagMap = roomShapeMap:get(roomShape)
23
+ if roomDoorSlotFlagMap == nil then
24
+ roomDoorSlotFlagMap = __TS__New(Map)
25
+ roomShapeMap:set(roomShape, roomDoorSlotFlagMap)
26
+ end
27
+ local doorSlotFlags = roomMetadata.doorSlotFlags
28
+ local rooms = roomDoorSlotFlagMap:get(doorSlotFlags)
29
+ if rooms == nil then
30
+ rooms = {}
31
+ roomDoorSlotFlagMap:set(doorSlotFlags, rooms)
32
+ end
33
+ rooms[#rooms + 1] = roomMetadata
34
+ end
35
+ return roomTypeMap
36
+ end
9
37
  function ____exports.customStageInit(self)
10
- local customStages = metadataJSON
11
- if not isArray(nil, customStages) then
38
+ local customStagesLua = metadataJSON
39
+ if not isArray(nil, customStagesLua) then
12
40
  error("The IsaacScript standard library attempted to read the custom stage metadata from the \"metadata.lua\" file, but it was not an array.")
13
41
  end
14
- for ____, customStage in ipairs(customStages) do
42
+ for ____, customStageLua in ipairs(customStagesLua) do
43
+ local roomTypeMap = getRoomTypeMap(nil, customStageLua)
44
+ local customStage = __TS__ObjectAssign({}, customStageLua, {roomTypeMap = roomTypeMap})
15
45
  customStagesMap:set(customStage.name, customStage)
16
46
  end
17
47
  end
@@ -0,0 +1,11 @@
1
+ /// <reference types="isaac-typescript-definitions" />
2
+ /// <reference types="isaac-typescript-definitions" />
3
+ import { CustomStageRoomMetadata } from "../../interfaces/CustomStageLua";
4
+ /**
5
+ * Helper function to get a random custom stage room from an array of custom stage rooms.
6
+ *
7
+ * Note that this function does not simply choose a random element in the provided array; it will
8
+ * properly account for each room weight using the algorithm from:
9
+ * https://stackoverflow.com/questions/1761626/weighted-random-numbers
10
+ */
11
+ export declare function getRandomCustomStageRoom(roomsMetadata: readonly CustomStageRoomMetadata[], seedOrRNG?: Seed | RNG, verbose?: boolean): CustomStageRoomMetadata;
@@ -0,0 +1,51 @@
1
+ local ____lualib = require("lualib_bundle")
2
+ local __TS__ArrayMap = ____lualib.__TS__ArrayMap
3
+ local ____exports = {}
4
+ local getTotalWeightOfCustomStageRooms, getCustomStageRoomWithChosenWeight
5
+ local ____array = require("functions.array")
6
+ local sumArray = ____array.sumArray
7
+ local ____log = require("functions.log")
8
+ local log = ____log.log
9
+ local ____random = require("functions.random")
10
+ local getRandomFloat = ____random.getRandomFloat
11
+ local ____rng = require("functions.rng")
12
+ local getRandomSeed = ____rng.getRandomSeed
13
+ function getTotalWeightOfCustomStageRooms(self, roomsMetadata)
14
+ local weights = __TS__ArrayMap(
15
+ roomsMetadata,
16
+ function(____, roomMetadata) return roomMetadata.weight end
17
+ )
18
+ return sumArray(nil, weights)
19
+ end
20
+ function getCustomStageRoomWithChosenWeight(self, roomsMetadata, chosenWeight)
21
+ for ____, roomMetadata in ipairs(roomsMetadata) do
22
+ if chosenWeight < roomMetadata.weight then
23
+ return roomMetadata
24
+ end
25
+ chosenWeight = chosenWeight - roomMetadata.weight
26
+ end
27
+ error("Failed to get a custom stage room with chosen weight: " .. tostring(chosenWeight))
28
+ end
29
+ --- Helper function to get a random custom stage room from an array of custom stage rooms.
30
+ --
31
+ -- Note that this function does not simply choose a random element in the provided array; it will
32
+ -- properly account for each room weight using the algorithm from:
33
+ -- https://stackoverflow.com/questions/1761626/weighted-random-numbers
34
+ function ____exports.getRandomCustomStageRoom(self, roomsMetadata, seedOrRNG, verbose)
35
+ if seedOrRNG == nil then
36
+ seedOrRNG = getRandomSeed(nil)
37
+ end
38
+ if verbose == nil then
39
+ verbose = false
40
+ end
41
+ local totalWeight = getTotalWeightOfCustomStageRooms(nil, roomsMetadata)
42
+ if verbose then
43
+ log("Total weight of the custom stage rooms provided: " .. tostring(totalWeight))
44
+ end
45
+ local chosenWeight = getRandomFloat(nil, 0, totalWeight, seedOrRNG)
46
+ if verbose then
47
+ log("Randomly chose weight for custom stage room: " .. tostring(chosenWeight))
48
+ end
49
+ return getCustomStageRoomWithChosenWeight(nil, roomsMetadata, chosenWeight)
50
+ end
51
+ return ____exports
@@ -1,2 +1,6 @@
1
+ /// <reference types="isaac-typescript-definitions" />
1
2
  import { CustomStage } from "../../interfaces/CustomStage";
3
+ /** Indexed by custom stage name. */
2
4
  export declare const customStagesMap: Map<string, CustomStage>;
5
+ /** Indexed by room variant. */
6
+ export declare const customStageCachedRoomData: Map<number, Readonly<RoomConfig>>;
@@ -2,5 +2,8 @@ local ____lualib = require("lualib_bundle")
2
2
  local Map = ____lualib.Map
3
3
  local __TS__New = ____lualib.__TS__New
4
4
  local ____exports = {}
5
+ --- Indexed by custom stage name.
5
6
  ____exports.customStagesMap = __TS__New(Map)
7
+ --- Indexed by room variant.
8
+ ____exports.customStageCachedRoomData = __TS__New(Map)
6
9
  return ____exports
@@ -53,6 +53,10 @@ export declare function getDoors(...roomTypes: RoomType[]): GridEntityDoor[];
53
53
  export declare function getDoorsToRoomIndex(...roomGridIndex: int[]): GridEntityDoor[];
54
54
  export declare function getOppositeDoorSlot(doorSlot: DoorSlot): DoorSlot | undefined;
55
55
  export declare function getRepentanceDoor(): GridEntityDoor | undefined;
56
+ /**
57
+ * Helper function to get the corresponding door slot for a given room shape and grid coordinates.
58
+ */
59
+ export declare function getRoomShapeDoorSlot(roomShape: RoomShape, x: int, y: int): DoorSlot | undefined;
56
60
  /**
57
61
  * Helper function to get the room grid coordinates for a specific room shape and door slot
58
62
  * combination.
@@ -5,6 +5,7 @@ local __TS__ArrayMap = ____lualib.__TS__ArrayMap
5
5
  local __TS__New = ____lualib.__TS__New
6
6
  local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
7
7
  local __TS__ArrayFind = ____lualib.__TS__ArrayFind
8
+ local __TS__Iterator = ____lualib.__TS__Iterator
8
9
  local ____exports = {}
9
10
  local ROOM_ENTRY_OFFSET_FROM_DOOR
10
11
  local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
@@ -193,6 +194,19 @@ function ____exports.getRepentanceDoor(self)
193
194
  function(____, door) return ____exports.isRepentanceDoor(nil, door) end
194
195
  )
195
196
  end
197
+ --- Helper function to get the corresponding door slot for a given room shape and grid coordinates.
198
+ function ____exports.getRoomShapeDoorSlot(self, roomShape, x, y)
199
+ local coordinatesMap = ROOM_SHAPE_TO_DOOR_SLOT_COORDINATES[roomShape]
200
+ for ____, ____value in __TS__Iterator(coordinatesMap:entries()) do
201
+ local doorSlot = ____value[1]
202
+ local doorX = ____value[2][1]
203
+ local doorY = ____value[2][2]
204
+ if x == doorX and y == doorY then
205
+ return doorSlot
206
+ end
207
+ end
208
+ return nil
209
+ end
196
210
  --- Helper function to get the room grid coordinates for a specific room shape and door slot
197
211
  -- combination.
198
212
  function ____exports.getRoomShapeDoorSlotCoordinates(self, roomShape, doorSlot)
@@ -57,4 +57,6 @@ export declare function checkFamiliar(player: EntityPlayer, collectibleType: Col
57
57
  * spawn new familiars with a sub-type of 0.
58
58
  */
59
59
  export declare function checkFamiliarFromCollectibles(player: EntityPlayer, collectibleType: CollectibleType, familiarVariant: FamiliarVariant, familiarSubType?: int): void;
60
+ /** Helper function to get only the familiars that belong to a specific player. */
61
+ export declare function getPlayerFamiliars(player: EntityPlayer): EntityFamiliar[];
60
62
  export declare function isFamiliarThatShootsPlayerTears(familiar: EntityFamiliar): boolean;
@@ -1,8 +1,12 @@
1
+ local ____lualib = require("lualib_bundle")
2
+ local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
1
3
  local ____exports = {}
2
4
  local ____cachedClasses = require("cachedClasses")
3
5
  local itemConfig = ____cachedClasses.itemConfig
4
6
  local ____familiarsThatShootPlayerTearsSet = require("sets.familiarsThatShootPlayerTearsSet")
5
7
  local FAMILIARS_THAT_SHOOT_PLAYER_TEARS_SET = ____familiarsThatShootPlayerTearsSet.FAMILIARS_THAT_SHOOT_PLAYER_TEARS_SET
8
+ local ____entitySpecific = require("functions.entitySpecific")
9
+ local getFamiliars = ____entitySpecific.getFamiliars
6
10
  --- Helper function to add and remove familiars based on a target amount that you specify.
7
11
  --
8
12
  -- This is a convenience wrapper around the `EntityPlayer.CheckFamiliar` method. Use this helper
@@ -79,6 +83,18 @@ function ____exports.checkFamiliarFromCollectibles(self, player, collectibleType
79
83
  familiarSubType
80
84
  )
81
85
  end
86
+ --- Helper function to get only the familiars that belong to a specific player.
87
+ function ____exports.getPlayerFamiliars(self, player)
88
+ local playerPtrHash = GetPtrHash(player)
89
+ local familiars = getFamiliars(nil)
90
+ return __TS__ArrayFilter(
91
+ familiars,
92
+ function(____, familiar)
93
+ local familiarPlayerPtrHash = GetPtrHash(familiar.Player)
94
+ return familiarPlayerPtrHash == playerPtrHash
95
+ end
96
+ )
97
+ end
82
98
  function ____exports.isFamiliarThatShootsPlayerTears(self, familiar)
83
99
  return FAMILIARS_THAT_SHOOT_PLAYER_TEARS_SET:has(familiar.Variant)
84
100
  end
@@ -1,8 +1,24 @@
1
- /// <reference types="isaac-typescript-definitions" />
2
- /// <reference types="isaac-typescript-definitions" />
3
- /// <reference types="isaac-typescript-definitions" />
1
+ import { DoorSlotFlag } from "isaac-typescript-definitions";
4
2
  import { JSONRoom } from "../interfaces/JSONRoomsFile";
3
+ /**
4
+ * Helper function to calculate what the resulting `BitFlags<DoorSlotFlag>` value would be for a
5
+ * given JSON room.
6
+ */
7
+ export declare function getJSONRoomDoorSlotFlags(jsonRoom: JSONRoom): BitFlags<DoorSlotFlag>;
8
+ /**
9
+ * Helper function to find a specific room from an array of JSON rooms.
10
+ *
11
+ * @param jsonRooms The array of rooms to search through.
12
+ * @param variant The room variant to select. (The room variant can be thought of as the ID of the
13
+ * room.)
14
+ */
5
15
  export declare function getJSONRoomOfVariant(jsonRooms: JSONRoom[] | readonly JSONRoom[], variant: int): JSONRoom | undefined;
16
+ /**
17
+ * Helper function to find all of the JSON rooms that match the sub-type provided.
18
+ *
19
+ * @param jsonRooms The array of rooms to search through.
20
+ * @param subType The sub-type to match.
21
+ */
6
22
  export declare function getJSONRoomsOfSubType(jsonRooms: JSONRoom[] | readonly JSONRoom[], subType: int): JSONRoom[];
7
23
  /**
8
24
  * Helper function to get a random JSON room from an array of JSON rooms.
@@ -10,5 +26,11 @@ export declare function getJSONRoomsOfSubType(jsonRooms: JSONRoom[] | readonly J
10
26
  * Note that this function does not simply choose a random element in the provided array; it will
11
27
  * properly account for each room weight using the algorithm from:
12
28
  * https://stackoverflow.com/questions/1761626/weighted-random-numbers
29
+ *
30
+ * @param jsonRooms The array of rooms to random choose between.
31
+ * @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
32
+ * `RNG.Next` method will be called. Default is `getRandomSeed()`.
33
+ * @param verbose Optional. If specified, will write entries to the "log.txt" file that describe
34
+ * what the function is doing. Default is false.
13
35
  */
14
36
  export declare function getRandomJSONRoom(jsonRooms: JSONRoom[] | readonly JSONRoom[], seedOrRNG?: Seed | RNG, verbose?: boolean): JSONRoom;
@@ -3,8 +3,15 @@ local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
3
3
  local __TS__ArrayMap = ____lualib.__TS__ArrayMap
4
4
  local ____exports = {}
5
5
  local getTotalWeightOfJSONRooms, getJSONRoomWithChosenWeight
6
+ local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
7
+ local DoorSlotFlagZero = ____isaac_2Dtypescript_2Ddefinitions.DoorSlotFlagZero
6
8
  local ____array = require("functions.array")
7
9
  local sumArray = ____array.sumArray
10
+ local ____doors = require("functions.doors")
11
+ local doorSlotToDoorSlotFlag = ____doors.doorSlotToDoorSlotFlag
12
+ local getRoomShapeDoorSlot = ____doors.getRoomShapeDoorSlot
13
+ local ____flag = require("functions.flag")
14
+ local addFlag = ____flag.addFlag
8
15
  local ____log = require("functions.log")
9
16
  local log = ____log.log
10
17
  local ____random = require("functions.random")
@@ -37,8 +44,53 @@ function getJSONRoomWithChosenWeight(self, jsonRooms, chosenWeight)
37
44
  end
38
45
  chosenWeight = chosenWeight - roomWeight
39
46
  end
40
- return error("Failed to get a JSON room with chosen weight: " .. tostring(chosenWeight))
47
+ error("Failed to get a JSON room with chosen weight: " .. tostring(chosenWeight))
41
48
  end
49
+ --- Helper function to calculate what the resulting `BitFlags<DoorSlotFlag>` value would be for a
50
+ -- given JSON room.
51
+ function ____exports.getJSONRoomDoorSlotFlags(self, jsonRoom)
52
+ local roomShapeString = jsonRoom["$"].shape
53
+ local roomShapeNumber = tonumber(roomShapeString)
54
+ if roomShapeNumber == nil then
55
+ error("Failed to parse the \"shape\" property of a JSON room: " .. roomShapeString)
56
+ end
57
+ local roomShape = roomShapeNumber
58
+ local doorSlotFlags = DoorSlotFlagZero
59
+ for ____, door in ipairs(jsonRoom.door) do
60
+ do
61
+ local existsString = door["$"].exists
62
+ if existsString ~= "True" and existsString ~= "False" then
63
+ error("Failed to parse the \"exists\" property of a JSON room door: " .. existsString)
64
+ end
65
+ if existsString == "False" then
66
+ goto __continue4
67
+ end
68
+ local xString = door["$"].x
69
+ local x = tonumber(xString)
70
+ if x == nil then
71
+ error("Failed to parse the \"x\" property of a JSON room door: " .. xString)
72
+ end
73
+ local yString = door["$"].y
74
+ local y = tonumber(yString)
75
+ if y == nil then
76
+ error("Failed to parse the \"y\" property of a JSON room door: " .. yString)
77
+ end
78
+ local doorSlot = getRoomShapeDoorSlot(nil, roomShape, x, y)
79
+ if doorSlot == nil then
80
+ error(((("Failed to retrieve the door slot for a JSON room door at coordinates: [" .. tostring(x)) .. ", ") .. tostring(y)) .. "]")
81
+ end
82
+ local doorSlotFlag = doorSlotToDoorSlotFlag(nil, doorSlot)
83
+ doorSlotFlags = addFlag(nil, doorSlotFlags, doorSlotFlag)
84
+ end
85
+ ::__continue4::
86
+ end
87
+ return doorSlotFlags
88
+ end
89
+ --- Helper function to find a specific room from an array of JSON rooms.
90
+ --
91
+ -- @param jsonRooms The array of rooms to search through.
92
+ -- @param variant The room variant to select. (The room variant can be thought of as the ID of the
93
+ -- room.)
42
94
  function ____exports.getJSONRoomOfVariant(self, jsonRooms, variant)
43
95
  local jsonRoomsOfVariant = __TS__ArrayFilter(
44
96
  jsonRooms,
@@ -54,8 +106,12 @@ function ____exports.getJSONRoomOfVariant(self, jsonRooms, variant)
54
106
  if #jsonRoomsOfVariant == 1 then
55
107
  return jsonRoomsOfVariant[1]
56
108
  end
57
- return error(((("Found " .. tostring(#jsonRoomsOfVariant)) .. " JSON rooms with a variant of ") .. tostring(variant)) .. ", when there should only be 1.")
109
+ error(((("Found " .. tostring(#jsonRoomsOfVariant)) .. " JSON rooms with a variant of ") .. tostring(variant)) .. ", when there should only be 1.")
58
110
  end
111
+ --- Helper function to find all of the JSON rooms that match the sub-type provided.
112
+ --
113
+ -- @param jsonRooms The array of rooms to search through.
114
+ -- @param subType The sub-type to match.
59
115
  function ____exports.getJSONRoomsOfSubType(self, jsonRooms, subType)
60
116
  return __TS__ArrayFilter(
61
117
  jsonRooms,
@@ -71,6 +127,12 @@ end
71
127
  -- Note that this function does not simply choose a random element in the provided array; it will
72
128
  -- properly account for each room weight using the algorithm from:
73
129
  -- https://stackoverflow.com/questions/1761626/weighted-random-numbers
130
+ --
131
+ -- @param jsonRooms The array of rooms to random choose between.
132
+ -- @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
133
+ -- `RNG.Next` method will be called. Default is `getRandomSeed()`.
134
+ -- @param verbose Optional. If specified, will write entries to the "log.txt" file that describe
135
+ -- what the function is doing. Default is false.
74
136
  function ____exports.getRandomJSONRoom(self, jsonRooms, seedOrRNG, verbose)
75
137
  if seedOrRNG == nil then
76
138
  seedOrRNG = getRandomSeed(nil)
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Helper function to move all of the players to the center of the room.
3
+ *
4
+ * This function emulates what happens in the vanilla game when you travel to a new floor.
5
+ */
6
+ export declare function movePlayersToCenter(): void;
@@ -0,0 +1,57 @@
1
+ local ____exports = {}
2
+ local movePlayerAndTheirFamiliars
3
+ local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
4
+ local Direction = ____isaac_2Dtypescript_2Ddefinitions.Direction
5
+ local ____cachedClasses = require("cachedClasses")
6
+ local game = ____cachedClasses.game
7
+ local ____familiars = require("functions.familiars")
8
+ local getPlayerFamiliars = ____familiars.getPlayerFamiliars
9
+ local ____math = require("functions.math")
10
+ local getCircleDiscretizedPoints = ____math.getCircleDiscretizedPoints
11
+ local ____playerIndex = require("functions.playerIndex")
12
+ local getPlayers = ____playerIndex.getPlayers
13
+ function movePlayerAndTheirFamiliars(self, player, position)
14
+ player.Position = position
15
+ local familiars = getPlayerFamiliars(nil, player)
16
+ for ____, familiar in ipairs(familiars) do
17
+ familiar.Position = position
18
+ end
19
+ end
20
+ local CIRCLE_RADIUS_BETWEEN_PLAYERS = 50
21
+ --- Helper function to move all of the players to the center of the room.
22
+ --
23
+ -- This function emulates what happens in the vanilla game when you travel to a new floor.
24
+ function ____exports.movePlayersToCenter(self)
25
+ local room = game:GetRoom()
26
+ local centerPos = room:GetCenterPos()
27
+ local players = getPlayers(nil)
28
+ local firstPlayer = players[1]
29
+ if firstPlayer == nil then
30
+ return
31
+ end
32
+ if #players == 1 then
33
+ movePlayerAndTheirFamiliars(nil, firstPlayer, centerPos)
34
+ return
35
+ end
36
+ local circlePoints = getCircleDiscretizedPoints(
37
+ nil,
38
+ centerPos,
39
+ CIRCLE_RADIUS_BETWEEN_PLAYERS,
40
+ #players,
41
+ 1,
42
+ 1,
43
+ Direction.LEFT
44
+ )
45
+ do
46
+ local i = 0
47
+ while i < #players do
48
+ local player = players[i + 1]
49
+ local position = circlePoints[i + 1]
50
+ if player ~= nil and position ~= nil then
51
+ player.Position = position
52
+ end
53
+ i = i + 1
54
+ end
55
+ end
56
+ end
57
+ return ____exports
@@ -55,7 +55,7 @@ export declare function getRoomTypeName(roomType: RoomType): string;
55
55
  * non-existent and are not added to the list.
56
56
  *
57
57
  * @param includeExtraDimensionalRooms Optional. On some floors (e.g. Downpour 2, Mines 2),
58
- * extra-dimensional rooms are automatically be generated and can be
58
+ * extra-dimensional rooms are automatically generated and can be
59
59
  * seen when you iterate over the `RoomList`. Default is false.
60
60
  */
61
61
  export declare function getRooms(includeExtraDimensionalRooms?: boolean): RoomDescriptor[];
@@ -72,7 +72,7 @@ end
72
72
  -- non-existent and are not added to the list.
73
73
  --
74
74
  -- @param includeExtraDimensionalRooms Optional. On some floors (e.g. Downpour 2, Mines 2),
75
- -- extra-dimensional rooms are automatically be generated and can be
75
+ -- extra-dimensional rooms are automatically generated and can be
76
76
  -- seen when you iterate over the `RoomList`. Default is false.
77
77
  function ____exports.getRooms(self, includeExtraDimensionalRooms)
78
78
  if includeExtraDimensionalRooms == nil then
@@ -145,7 +145,7 @@ function ____exports.getDimension(self)
145
145
  return dimension
146
146
  end
147
147
  end
148
- return error("Failed to get the current dimension.")
148
+ error("Failed to get the current dimension.")
149
149
  end
150
150
  --- Helper function to get the number of rooms that are currently on the floor layout. This does not
151
151
  -- include off-grid rooms, like the Devil Room.
@@ -16,10 +16,10 @@ export declare function calculateStageTypeRepentance(stage: LevelStage): StageTy
16
16
  */
17
17
  export declare function getEffectiveStage(): int;
18
18
  /**
19
- * Helper function to get the prefix to use with the "goto" console command that would correspond to
20
- * the provided room type.
19
+ * Helper function to get the corresponding "goto" console command that would correspond to the
20
+ * provided room type and room variant.
21
21
  */
22
- export declare function getGotoCommandPrefix(roomType: RoomType): string;
22
+ export declare function getGotoCommand(roomType: RoomType, roomVariant: int): string;
23
23
  /** Alias for the `Level.GetStage` method. */
24
24
  export declare function getStage(): LevelStage;
25
25
  /** Alias for the `Level.GetStageType` method. */
@@ -64,10 +64,11 @@ function ____exports.getEffectiveStage(self)
64
64
  end
65
65
  return stage
66
66
  end
67
- --- Helper function to get the prefix to use with the "goto" console command that would correspond to
68
- -- the provided room type.
69
- function ____exports.getGotoCommandPrefix(self, roomType)
70
- return ROOM_TYPE_GOTO_PREFIXES[roomType]
67
+ --- Helper function to get the corresponding "goto" console command that would correspond to the
68
+ -- provided room type and room variant.
69
+ function ____exports.getGotoCommand(self, roomType, roomVariant)
70
+ local prefix = ROOM_TYPE_GOTO_PREFIXES[roomType]
71
+ return (("goto " .. prefix) .. ".") .. tostring(roomVariant)
71
72
  end
72
73
  --- Alias for the `Level.GetStage` method.
73
74
  function ____exports.getStage(self)
@@ -76,7 +76,7 @@ function ____exports.getOpenTrinketSlot(self, player)
76
76
  end
77
77
  return trinketType2 == TrinketType.NULL and 1 or nil
78
78
  end
79
- return error("The player has an unknown number of trinket slots: " .. tostring(maxTrinkets))
79
+ error("The player has an unknown number of trinket slots: " .. tostring(maxTrinkets))
80
80
  end
81
81
  --- Helper function to get the in-game description for a trinket. Returns "Unknown" if the provided
82
82
  -- trinket type was not valid.
@@ -1,51 +1,10 @@
1
- /**
2
- * This is the format of a custom stage in the "isaacscript" section of the "tsconfig.json" file.
3
- *
4
- * The contents of this interface are used to create a "tsconfig-isaacscript-section-schema.json"
5
- * schema with the "ts-json-schema-generator" library.
6
- *
7
- * The contents of this interface are validated at run-time against the schema using the Ajv
8
- * library.
9
- *
10
- * The `CustomStage` interface extends this, adding room metadata.
11
- */
12
- export interface CustomStageTSConfig {
13
- /** The name of the custom stage. */
14
- name: string;
15
- /**
16
- * Path to the XML file that contains the rooms for the custom stage (created with Basement
17
- * Renovator).
18
- */
19
- xmlPath: string;
20
- /** An arbitrarily chosen prefix in the range of 101-999. */
21
- roomVariantPrefix: number;
22
- /**
23
- * An integer between 1 and 13, corresponding to the `LevelStage` enum. This is the number of the
24
- * stage that will be warped to and used as a basis for the stage by the level generation
25
- * algorithm.
26
- */
27
- baseStage: number;
28
- /**
29
- * An integer between 0 and 5, corresponding to the `StageType` enum. This is the number of the
30
- * stage type that will be warped to and used as a basis for the stage by the level generation
31
- * algorithm.
32
- */
33
- baseStageType: number;
34
- }
35
- /**
36
- * An object that represents a custom stage. The "metadata.lua" file contains an array of these
37
- * objects. Besides the room metadata, the data is the same as what is specified inside the
38
- * "tsconfig.json" file.
39
- */
40
- export interface CustomStage extends CustomStageTSConfig {
41
- roomsMetadata: CustomStageRoomMetadata[];
42
- }
43
- /**
44
- * Metadata about a custom stage room. Each custom stage object contains an array with metadata for
45
- * each room.
46
- */
47
- export interface CustomStageRoomMetadata {
48
- variant: number;
49
- shape: number;
50
- weight: number;
1
+ import { DoorSlotFlag, RoomShape, RoomType } from "isaac-typescript-definitions";
2
+ import { CustomStageLua, CustomStageRoomMetadata } from "./CustomStageLua";
3
+ export interface CustomStage extends CustomStageLua {
4
+ /** A map that makes it easier to select certain room type/shape/door combinations. */
5
+ readonly roomTypeMap: RoomTypeMap;
51
6
  }
7
+ export declare type RoomTypeMap = ReadonlyMap<RoomType, RoomShapeMap>;
8
+ declare type RoomShapeMap = ReadonlyMap<RoomShape, RoomDoorSlotMap>;
9
+ declare type RoomDoorSlotMap = ReadonlyMap<DoorSlotFlag, CustomStageRoomMetadata[]>;
10
+ export {};
@@ -0,0 +1,118 @@
1
+ /**
2
+ * This is the format of a custom stage in the "isaacscript" section of the "tsconfig.json" file.
3
+ *
4
+ * The contents of this interface are used to create a "tsconfig-isaacscript-section-schema.json"
5
+ * schema with the "ts-json-schema-generator" library.
6
+ *
7
+ * The contents of this interface are validated at run-time against the schema using the Ajv
8
+ * library.
9
+ *
10
+ * The `CustomStageLua` interface extends this, adding room metadata.
11
+ */
12
+ export interface CustomStageTSConfig {
13
+ /** The name of the custom stage. Mandatory. */
14
+ readonly name: string;
15
+ /**
16
+ * Path to the XML file that contains the rooms for the custom stage (created with Basement
17
+ * Renovator). Mandatory.
18
+ */
19
+ readonly xmlPath: string;
20
+ /** An arbitrarily chosen prefix in the range of 101-999. Mandatory. */
21
+ readonly roomVariantPrefix: number;
22
+ /**
23
+ * An integer between 2 and 13, corresponding to the `LevelStage` enum. This is the number of the
24
+ * stage that will be warped to and used as a basis for the stage by the level generation
25
+ * algorithm. Mandatory.
26
+ *
27
+ * (It is not possible to use Basement 1 as a base due to conflicts with the `Game.SetStage`
28
+ * method.)
29
+ */
30
+ readonly baseStage: number;
31
+ /**
32
+ * An integer between 0 and 5, corresponding to the `StageType` enum. This is the number of the
33
+ * stage type that will be warped to and used as a basis for the stage by the level generation
34
+ * algorithm. Mandatory.
35
+ */
36
+ readonly baseStageType: number;
37
+ /**
38
+ * An object containing the paths to the backdrop for the stage. (A backdrop is the graphics for
39
+ * the walls and floor.) Mandatory.
40
+ */
41
+ readonly backdrop: CustomStageBackdrop;
42
+ }
43
+ interface CustomStageBackdrop {
44
+ /**
45
+ * The beginning of the path that leads to the backdrop graphics. For example:
46
+ *
47
+ * ```sh
48
+ * gfx/backdrop/revelations/revelations_
49
+ * ```
50
+ */
51
+ prefix: string;
52
+ /**
53
+ * The end of the path that leads to the backdrop graphics. In most cases, this will be ".png".
54
+ */
55
+ suffix: string;
56
+ /**
57
+ * An array of strings that represent the graphic files for the stage's "nFloor". You must have at
58
+ * least one string in this array, but you can specify more than one to randomly add extra variety
59
+ * (like the vanilla stages do).
60
+ *
61
+ * For an example of this, see the vanilla file "resources/gfx/backdrop/01_basement_nfloor.png".
62
+ */
63
+ nFloors: string[];
64
+ /**
65
+ * An array of strings that represent the graphic files for the stage's "lFloor". You must have at
66
+ * least one in the array, but you can specify more than one to randomly add extra variety (like
67
+ * the vanilla stages do).
68
+ *
69
+ * For an example of this, see the vanilla file "resources/gfx/backdrop/01_lbasementfloor.png".
70
+ */
71
+ lFloors: string[];
72
+ /**
73
+ * An array of strings that represent the graphic files for the stage's walls. You must have at
74
+ * least one string in this array, but you can specify more than one to randomly add extra variety
75
+ * (like the vanilla stages do).
76
+ *
77
+ * For an example of this, see the vanilla file "resources/gfx/backdrop/01_basement.png". (In the
78
+ * vanilla file, they concatenate all four variations together into one PNG file. However, for the
79
+ * custom stages feature, you must separate each wall variation into a separate file.)
80
+ */
81
+ walls: string[];
82
+ /**
83
+ * An array of strings that represent the graphic files for the stage's corners. You must have at
84
+ * least one string in this array, but you can specify more than one to randomly add extra variety
85
+ * (like the vanilla stages do).
86
+ *
87
+ * For an example of this, see the vanilla file "resources/gfx/backdrop/01_basement.png". (In the
88
+ * vanilla file, they concatenate both variations together into one PNG file and put it in the top
89
+ * right hand corner. The corners are shown in the top right hand corner of the file, with two
90
+ * different variations concatenated together. However, for the custom stages feature, you must
91
+ * separate each corner variation into a separate file (and put it in a different file from the
92
+ * walls).
93
+ */
94
+ corners: string[];
95
+ }
96
+ /**
97
+ * An object that represents a custom stage. The "metadata.lua" file contains an array of these
98
+ * objects. Besides the room metadata, the data is the same as what is specified inside the
99
+ * "tsconfig.json" file.
100
+ *
101
+ * The `CustomStage` interface extends this, adding more data.
102
+ */
103
+ export interface CustomStageLua extends CustomStageTSConfig {
104
+ readonly roomsMetadata: readonly CustomStageRoomMetadata[];
105
+ }
106
+ /**
107
+ * Metadata about a custom stage room. Each custom stage object contains an array with metadata for
108
+ * each room.
109
+ */
110
+ export interface CustomStageRoomMetadata {
111
+ readonly type: number;
112
+ readonly variant: number;
113
+ readonly subType: number;
114
+ readonly shape: number;
115
+ readonly doorSlotFlags: number;
116
+ readonly weight: number;
117
+ }
118
+ export {};
@@ -0,0 +1,2 @@
1
+ local ____exports = {}
2
+ return ____exports
@@ -2,34 +2,34 @@ local ____exports = {}
2
2
  local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
3
3
  local RoomType = ____isaac_2Dtypescript_2Ddefinitions.RoomType
4
4
  ____exports.ROOM_TYPE_GOTO_PREFIXES = {
5
- [RoomType.DEFAULT] = "d.",
6
- [RoomType.SHOP] = "s.shop.",
7
- [RoomType.ERROR] = "s.error.",
8
- [RoomType.TREASURE] = "s.treasure.",
9
- [RoomType.BOSS] = "s.boss.",
10
- [RoomType.MINI_BOSS] = "s.miniboss.",
11
- [RoomType.SECRET] = "s.secret.",
12
- [RoomType.SUPER_SECRET] = "s.supersecret.",
13
- [RoomType.ARCADE] = "s.arcade.",
14
- [RoomType.CURSE] = "s.curse.",
15
- [RoomType.CHALLENGE] = "s.challenge.",
16
- [RoomType.LIBRARY] = "s.library.",
17
- [RoomType.SACRIFICE] = "s.sacrifice.",
18
- [RoomType.DEVIL] = "s.devil.",
19
- [RoomType.ANGEL] = "s.angel.",
20
- [RoomType.DUNGEON] = "s.itemdungeon.",
21
- [RoomType.BOSS_RUSH] = "s.bossrush.",
22
- [RoomType.CLEAN_BEDROOM] = "s.isaacs.",
23
- [RoomType.DIRTY_BEDROOM] = "s.barren.",
24
- [RoomType.CHEST] = "s.chest.",
25
- [RoomType.DICE] = "s.dice.",
26
- [RoomType.BLACK_MARKET] = "s.blackmarket.",
27
- [RoomType.GREED_EXIT] = "s.greedexit.",
28
- [RoomType.PLANETARIUM] = "s.planetarium.",
29
- [RoomType.TELEPORTER] = "s.teleporter.",
30
- [RoomType.TELEPORTER_EXIT] = "s.teleporterexit.",
31
- [RoomType.SECRET_EXIT] = "s.secretexit.",
32
- [RoomType.BLUE] = "s.blue.",
33
- [RoomType.ULTRA_SECRET] = "s.ultrasecret."
5
+ [RoomType.DEFAULT] = "s.default",
6
+ [RoomType.SHOP] = "s.shop",
7
+ [RoomType.ERROR] = "s.error",
8
+ [RoomType.TREASURE] = "s.treasure",
9
+ [RoomType.BOSS] = "s.boss",
10
+ [RoomType.MINI_BOSS] = "s.miniboss",
11
+ [RoomType.SECRET] = "s.secret",
12
+ [RoomType.SUPER_SECRET] = "s.supersecret",
13
+ [RoomType.ARCADE] = "s.arcade",
14
+ [RoomType.CURSE] = "s.curse",
15
+ [RoomType.CHALLENGE] = "s.challenge",
16
+ [RoomType.LIBRARY] = "s.library",
17
+ [RoomType.SACRIFICE] = "s.sacrifice",
18
+ [RoomType.DEVIL] = "s.devil",
19
+ [RoomType.ANGEL] = "s.angel",
20
+ [RoomType.DUNGEON] = "s.itemdungeon",
21
+ [RoomType.BOSS_RUSH] = "s.bossrush",
22
+ [RoomType.CLEAN_BEDROOM] = "s.isaacs",
23
+ [RoomType.DIRTY_BEDROOM] = "s.barren",
24
+ [RoomType.CHEST] = "s.chest",
25
+ [RoomType.DICE] = "s.dice",
26
+ [RoomType.BLACK_MARKET] = "s.blackmarket",
27
+ [RoomType.GREED_EXIT] = "s.greedexit",
28
+ [RoomType.PLANETARIUM] = "s.planetarium",
29
+ [RoomType.TELEPORTER] = "s.teleporter",
30
+ [RoomType.TELEPORTER_EXIT] = "s.teleporterexit",
31
+ [RoomType.SECRET_EXIT] = "s.secretexit",
32
+ [RoomType.BLUE] = "s.blue",
33
+ [RoomType.ULTRA_SECRET] = "s.ultrasecret"
34
34
  }
35
35
  return ____exports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "6.1.1",
3
+ "version": "6.2.0",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",