isaacscript-common 1.0.482 → 1.0.486

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.
@@ -201,6 +201,8 @@ function spawnAllEntities(self, jsonRoom, seed, verbose)
201
201
  log("Setting the room to be uncleared since there were one or more battle NPCs spawned.")
202
202
  end
203
203
  setRoomUncleared(nil)
204
+ elseif verbose then
205
+ log("Leaving the room cleared since there were no battle NPCs spawned.")
204
206
  end
205
207
  return seed
206
208
  end
@@ -60,6 +60,25 @@ export declare function getEffects(matchingVariant?: number, matchingSubType?: n
60
60
  * returned. False by default. Will only be taken into account if `matchingEntityType` is specified.
61
61
  */
62
62
  export declare function getEntities(matchingEntityType?: EntityType | int, matchingVariant?: number, matchingSubType?: number, ignoreFriendly?: boolean): Entity[];
63
+ /**
64
+ * Helper function to get a map containing the positions of every entity in the current room.
65
+ *
66
+ * This is useful for rewinding entity positions at a later time. Also see `setEntityPositions()`.
67
+ *
68
+ * @param entities Optional. If provided, will only get the positions of the provided entities. This
69
+ * can be used to cache the entities to avoid invoking `Isaac.GetRoomEntities()` multiple times.
70
+ */
71
+ export declare function getEntityPositions(entities?: Entity[]): Map<PtrHash, Vector>;
72
+ /**
73
+ * Helper function to get a map containing the velocities of every entity in the current room.
74
+ *
75
+ * This is useful for rewinding entity velocities at a later time. Also see `setEntityVelocities()`.
76
+ *
77
+ * @param entities Optional. If provided, will only get the velocities of the provided entities.
78
+ * This can be used to cache the entities to avoid invoking `Isaac.GetRoomEntities()` multiple
79
+ * times.
80
+ */
81
+ export declare function getEntityVelocities(entities?: Entity[]): Map<PtrHash, Vector>;
63
82
  /**
64
83
  * Helper function to get all of the familiars in the room.
65
84
  *
@@ -144,4 +163,31 @@ export declare function removeAllMatchingEntities(entityType: int, entityVariant
144
163
  export declare function removeAllPickups(): void;
145
164
  export declare function removeAllProjectiles(): void;
146
165
  export declare function removeAllTears(): void;
166
+ /**
167
+ * Helper function to set the position of every entity in the room based on a map of positions. If
168
+ * an entity is found that does not have matching element in the provided map, then that entity will
169
+ * be skipped.
170
+ *
171
+ * This function is useful for rewinding entity positions at a later time. Also see
172
+ * `getEntityPositions()`.
173
+ *
174
+ * @param entityPositions The map providing the positions for every entity.
175
+ * @param entities Optional. If provided, will only set the positions of the provided entities. This
176
+ * can be used to cache the entities to avoid invoking `Isaac.GetRoomEntities()` multiple times.
177
+ */
178
+ export declare function setEntityPositions(entityPositions: Map<PtrHash, Vector>, entities?: Entity[]): void;
147
179
  export declare function setEntityRandomColor(entity: Entity): void;
180
+ /**
181
+ * Helper function to set the velocity of every entity in the room based on a map of velocities. If
182
+ * an entity is found that does not have matching element in the provided map, then that entity will
183
+ * be skipped.
184
+ *
185
+ * This function is useful for rewinding entity velocities at a later time. Also see
186
+ * `getEntityVelocities()`.
187
+ *
188
+ * @param entityVelocities The map providing the velocities for every entity.
189
+ * @param entities Optional. If provided, will only set the velocities of the provided entities.
190
+ * This can be used to cache the entities to avoid invoking `Isaac.GetRoomEntities()` multiple
191
+ * times.
192
+ */
193
+ export declare function setEntityVelocities(entityVelocities: Map<PtrHash, Vector>, entities?: Entity[]): void;
@@ -76,6 +76,28 @@ function ____exports.getEntities(self, matchingEntityType, matchingVariant, matc
76
76
  end
77
77
  return Isaac.FindByType(matchingEntityType, matchingVariant, matchingSubType, ignoreFriendly)
78
78
  end
79
+ function ____exports.getEntityPositions(self, entities)
80
+ if entities == nil then
81
+ entities = ____exports.getEntities(nil)
82
+ end
83
+ local entityPositions = __TS__New(Map)
84
+ for ____, entity in ipairs(entities) do
85
+ local ptrHash = GetPtrHash(entity)
86
+ entityPositions:set(ptrHash, entity.Position)
87
+ end
88
+ return entityPositions
89
+ end
90
+ function ____exports.getEntityVelocities(self, entities)
91
+ if entities == nil then
92
+ entities = ____exports.getEntities(nil)
93
+ end
94
+ local entityVelocities = __TS__New(Map)
95
+ for ____, entity in ipairs(entities) do
96
+ local ptrHash = GetPtrHash(entity)
97
+ entityVelocities:set(ptrHash, entity.Velocity)
98
+ end
99
+ return entityVelocities
100
+ end
79
101
  function ____exports.getFamiliars(self, matchingVariant, matchingSubType)
80
102
  if matchingVariant == nil then
81
103
  matchingVariant = -1
@@ -251,6 +273,18 @@ function ____exports.removeAllTears(self)
251
273
  tear:Remove()
252
274
  end
253
275
  end
276
+ function ____exports.setEntityPositions(self, entityPositions, entities)
277
+ if entities == nil then
278
+ entities = ____exports.getEntities(nil)
279
+ end
280
+ for ____, entity in ipairs(entities) do
281
+ local ptrHash = GetPtrHash(entity)
282
+ local entityPosition = entityPositions:get(ptrHash)
283
+ if entityPosition ~= nil then
284
+ entity.Position = entityPosition
285
+ end
286
+ end
287
+ end
254
288
  function ____exports.setEntityRandomColor(self, entity)
255
289
  local colorValues = {}
256
290
  local seed = entity.InitSeed
@@ -266,4 +300,16 @@ function ____exports.setEntityRandomColor(self, entity)
266
300
  local color = Color(colorValues[1], colorValues[2], colorValues[3])
267
301
  entity:SetColor(color, 100000, 100000, false, false)
268
302
  end
303
+ function ____exports.setEntityVelocities(self, entityVelocities, entities)
304
+ if entities == nil then
305
+ entities = ____exports.getEntities(nil)
306
+ end
307
+ for ____, entity in ipairs(entities) do
308
+ local ptrHash = GetPtrHash(entity)
309
+ local entityVelocity = entityVelocities:get(ptrHash)
310
+ if entityVelocity ~= nil then
311
+ entity.Velocity = entityVelocity
312
+ end
313
+ end
314
+ end
269
315
  return ____exports
@@ -38,9 +38,30 @@ export declare function isAllPressurePlatesPushed(): boolean;
38
38
  * at the VarData of the entity.)
39
39
  */
40
40
  export declare function isPostBossVoidPortal(gridEntity: GridEntity): boolean;
41
+ /**
42
+ * Helper function to remove most grid entities in the room.
43
+ *
44
+ * Example:
45
+ * ```
46
+ * removeAllGridEntitiesExceptFor(
47
+ * GridEntityType.GRID_WALL,
48
+ * GridEntityType.GRID_DOOR,
49
+ * );
50
+ * ```
51
+ */
41
52
  export declare function removeAllGridEntitiesExceptFor(...gridEntityTypes: GridEntityType[]): void;
42
53
  export declare function removeAllMatchingGridEntities(gridEntityType: GridEntityType): void;
43
- export declare function removeGridEntity(gridEntity: GridEntity): void;
54
+ /**
55
+ * Helper function to remove a grid entity simply by providing the grid entity object.
56
+ *
57
+ * @param gridEntity The grid entity to remove.
58
+ * @param updateRoom Optional. Whether or not to update the room after the grid entity is removed.
59
+ * True by default. This is generally a good idea because if the room is not updated, you will be
60
+ * unable to spawn another grid entity on the same tile until a frame has passed. However, doing
61
+ * this is expensive, since it involves a call to `Isaac.GetRoomEntities()`, so set it to false if
62
+ * you need to invoke this function multiple times.
63
+ */
64
+ export declare function removeGridEntity(gridEntity: GridEntity, updateRoom?: boolean): void;
44
65
  /**
45
66
  * Helper function to make a grid entity invisible. This is accomplished by setting its sprite to
46
67
  * "gfx/none.png" (a non-existent PNG file).
@@ -3,12 +3,19 @@ require("lualib_bundle");
3
3
  local ____exports = {}
4
4
  local ____constants = require("constants")
5
5
  local GRID_ENTITY_XML_MAP = ____constants.GRID_ENTITY_XML_MAP
6
- function ____exports.removeGridEntity(self, gridEntity)
6
+ local ____rooms = require("functions.rooms")
7
+ local roomUpdateSafe = ____rooms.roomUpdateSafe
8
+ function ____exports.removeGridEntity(self, gridEntity, updateRoom)
9
+ if updateRoom == nil then
10
+ updateRoom = true
11
+ end
7
12
  local game = Game()
8
13
  local room = game:GetRoom()
9
14
  local gridIndex = gridEntity:GetGridIndex()
10
15
  room:RemoveGridEntity(gridIndex, 0, false)
11
- room:Update()
16
+ if updateRoom then
17
+ roomUpdateSafe(nil)
18
+ end
12
19
  end
13
20
  function ____exports.spawnGridEntityWithVariant(self, gridEntityType, variant, gridIndex)
14
21
  local game = Game()
@@ -113,15 +120,17 @@ function ____exports.removeAllGridEntitiesExceptFor(self, ...)
113
120
  for ____, gridEntity in ipairs(gridEntities) do
114
121
  local gridEntityType = gridEntity:GetType()
115
122
  if not gridEntityTypeExceptions:has(gridEntityType) then
116
- ____exports.removeGridEntity(nil, gridEntity)
123
+ ____exports.removeGridEntity(nil, gridEntity, false)
117
124
  end
118
125
  end
126
+ roomUpdateSafe(nil)
119
127
  end
120
128
  function ____exports.removeAllMatchingGridEntities(self, gridEntityType)
121
129
  local gridEntities = ____exports.getGridEntities(nil, gridEntityType)
122
130
  for ____, gridEntity in ipairs(gridEntities) do
123
- ____exports.removeGridEntity(nil, gridEntity)
131
+ ____exports.removeGridEntity(nil, gridEntity, false)
124
132
  end
133
+ roomUpdateSafe(nil)
125
134
  end
126
135
  function ____exports.setGridEntityInvisible(self, gridEntity)
127
136
  local sprite = gridEntity:GetSprite()
@@ -5,31 +5,28 @@
5
5
  */
6
6
  export declare function getDebugPrependString(msg: string, numParentFunctions?: number): string;
7
7
  /**
8
- * Helper function to avoid typing out `Isaac.DebugString()`.
9
- * If you have the --luadebug launch flag turned on or the Racing+ sandbox enabled,
10
- * then this function will also prepend the function name and the line number before the string.
8
+ * Helper function to avoid typing out `Isaac.DebugString()`. If you have the --luadebug launch flag
9
+ * turned on or the Racing+ sandbox enabled, then this function will also prepend the function name
10
+ * and the line number before the string.
11
11
  */
12
12
  export declare function log(this: void, msg: string): void;
13
- /**
14
- * Helper function for printing out every damage flag that is turned on. Helpful when debugging.
15
- */
13
+ /** Helper function for printing out every damage flag that is turned on. Helpful when debugging. */
16
14
  export declare function logAllDamageFlags(this: void, flags: int): void;
17
- /**
18
- * Helper function for printing out every entity flag that is turned on. Helpful when debugging.
19
- */
15
+ /** Helper function for printing out every entity flag that is turned on. Helpful when debugging. */
20
16
  export declare function logAllEntityFlags(this: void, flags: int): void;
17
+ /** Helper function for printing out every flag that is turned on. Helpful when debugging. */
18
+ export declare function logAllFlags(this: void, flags: int, flagEnum: LuaTable, description?: string): void;
21
19
  /**
22
- * Helper function for printing out every flag that is turned on. Helpful when debugging.
20
+ * Helper function for printing out every game state flag that is turned on. Helpful when debugging.
23
21
  */
24
- export declare function logAllFlags(this: void, flags: int, flagEnum: LuaTable, description?: string): void;
25
22
  export declare function logAllGameStateFlags(this: void): void;
26
23
  /**
27
24
  * Helper function for printing out every projectile flag that is turned on. Helpful when debugging.
28
25
  */
29
26
  export declare function logAllProjectileFlags(this: void, flags: int): void;
30
- /**
31
- * Helper function for printing out every use flag that is turned on. Helpful when debugging.
32
- */
27
+ /** Helper function for printing out every use flag that is turned on. Helpful when debugging. */
28
+ export declare function logAllTearFlags(this: void, flags: int): void;
29
+ /** Helper function for printing out every use flag that is turned on. Helpful when debugging. */
33
30
  export declare function logAllUseFlags(this: void, flags: int): void;
34
31
  export declare function logArray<T>(this: void, array: T[]): void;
35
32
  export declare function logColor(this: void, color: Color): void;
@@ -68,6 +68,9 @@ end
68
68
  function ____exports.logAllProjectileFlags(flags)
69
69
  ____exports.logAllFlags(flags, ProjectileFlags, "projectile")
70
70
  end
71
+ function ____exports.logAllTearFlags(flags)
72
+ ____exports.logAllFlags(flags, TearFlags, "tear")
73
+ end
71
74
  function ____exports.logAllUseFlags(flags)
72
75
  ____exports.logAllFlags(flags, UseFlag, "use")
73
76
  end
@@ -1,6 +1,5 @@
1
1
  /// <reference types="isaac-typescript-definitions" />
2
2
  import { HealthType } from "../types/HealthType";
3
- import { PocketItemDescription } from "../types/PocketItemDescription";
4
3
  /**
5
4
  * PlayerIndex is a specific type of string; see the documentation for the [[`getPlayerIndex`]]
6
5
  * function. Mods can signify that data structures handle EntityPlayers by using this type:
@@ -47,20 +46,6 @@ export declare function getLastHeart(player: EntityPlayer): HealthType;
47
46
  */
48
47
  export declare function getNewestPlayer(): EntityPlayer;
49
48
  export declare function getFinalPlayer(): EntityPlayer;
50
- /**
51
- * Returns the slot number corresponding to where a trinket can be safely inserted.
52
- *
53
- * Example:
54
- * ```
55
- * const player = Isaac.GetPlayer();
56
- * const trinketSlot = getOpenTrinketSlotNum(player);
57
- * if (trinketSlot !== undefined) {
58
- * // They have one or more open trinket slots
59
- * player.AddTrinket(TrinketType.TRINKET_SWALLOWED_PENNY);
60
- * }
61
- * ```
62
- */
63
- export declare function getOpenTrinketSlot(player: EntityPlayer): int | undefined;
64
49
  /**
65
50
  * Iterates over all players and checks if any are close enough to the specified position.
66
51
  *
@@ -115,17 +100,6 @@ export declare function getPlayerIndexVanilla(playerToFind: EntityPlayer): int |
115
100
  * This is equivalent to the number of hits that the player can currently take.
116
101
  */
117
102
  export declare function getPlayerNumAllHearts(player: EntityPlayer): int;
118
- /**
119
- * Use this helper function as a workaround for `EntityPlayer.GetPocketItem()` not working
120
- * correctly.
121
- *
122
- * Note that due to API limitations, there is no way to determine the location of a Dice Bag trinket
123
- * dice. Furthermore, when the player has a Dice Bag trinket dice and a pocket active at the same
124
- * time, there is no way to determine the location of the pocket active item. If this function
125
- * cannot determine the identity of a particular slot, it will mark the type of the slot as
126
- * `PocketItemType.UNDETERMINABLE`.
127
- */
128
- export declare function getPocketItems(player: EntityPlayer): PocketItemDescription[];
129
103
  /**
130
104
  * Helper function to return the active charge and the battery charge combined. This is useful
131
105
  * because you are not able to set the battery charge directly.
@@ -146,23 +120,6 @@ export declare function hasLostCurse(player: EntityPlayer): boolean;
146
120
  * items. (Only Tainted Forgotten can pick up items.)
147
121
  */
148
122
  export declare function hasOpenActiveItemSlot(player: EntityPlayer): boolean;
149
- /**
150
- * Returns whether or not the player can hold an additional pocket item, beyond what they are
151
- * currently carrying. This takes into account items that modify the max number of pocket items,
152
- * like Starter Deck.
153
- *
154
- * If the player is the Tainted Soul, this always returns false, since that character cannot pick up
155
- * items. (Only Tainted Forgotten can pick up items.)
156
- */
157
- export declare function hasOpenPocketItemSlot(player: EntityPlayer): boolean;
158
- /**
159
- * Returns whether or not the player can hold an additional trinket, beyond what they are currently
160
- * carrying. This takes into account items that modify the max number of trinkets, like Mom's Purse.
161
- *
162
- * If the player is the Tainted Soul, this always returns false, since that character cannot pick up
163
- * items. (Only Tainted Forgotten can pick up items.)
164
- */
165
- export declare function hasOpenTrinketSlot(player: EntityPlayer): boolean;
166
123
  /**
167
124
  * Helper function for detecting when a player is Bethany or Tainted Bethany. This is useful if you
168
125
  * need to adjust UI elements to account for Bethany's soul charges or Tainted Bethany's blood
@@ -198,6 +155,22 @@ export declare function removeCollectibleCostume(player: EntityPlayer, collectib
198
155
  */
199
156
  export declare function removeDeadEyeMultiplier(player: EntityPlayer): void;
200
157
  export declare function removeTrinketCostume(player: EntityPlayer, trinketType: TrinketType | int): void;
158
+ /**
159
+ * Helper function to set an active collectible to a particular slot. This has different behavior
160
+ * than calling `player.AddCollectible()` with the `activeSlot` argument, because this function will
161
+ * not shift existing items into the Schoolbag and it handles `ActiveSlot.SLOT_POCKET2`.
162
+ *
163
+ * Note that if an item is set to `ActiveSlot.SLOT_POCKET2`, it will disappear after being used and
164
+ * will be automatically removed upon entering a new room.
165
+ *
166
+ * @param player The player to give the item to.
167
+ * @param collectibleType The collectible type of the item to give.
168
+ * @param activeSlot The slot to set.
169
+ * @param charge Optional. The argument of charges to set. If not specified, the item will be set
170
+ * with maximum charges.
171
+ * @param keepInPools Optional. Whether or not to remove the item from pools. False by default.
172
+ */
173
+ export declare function setActiveItem(player: EntityPlayer, collectibleType: CollectibleType, activeSlot: ActiveSlot, charge?: int, keepInPools?: boolean): void;
201
174
  /**
202
175
  * If you want to stop the player from shooting without the blindfold costume, then simply call
203
176
  * `player.TryRemoveNullCostume(NullItemID.ID_BLINDFOLD)` after invoking this function.
@@ -6,13 +6,15 @@ local ____constants = require("constants")
6
6
  local LOST_STYLE_PLAYER_TYPES = ____constants.LOST_STYLE_PLAYER_TYPES
7
7
  local ____HealthType = require("types.HealthType")
8
8
  local HealthType = ____HealthType.HealthType
9
- local ____PocketItemType = require("types.PocketItemType")
10
- local PocketItemType = ____PocketItemType.PocketItemType
11
9
  local ____bitwise = require("functions.bitwise")
12
10
  local getKBitOfN = ____bitwise.getKBitOfN
13
11
  local getNumBitsOfN = ____bitwise.getNumBitsOfN
12
+ local ____collectibles = require("functions.collectibles")
13
+ local getCollectibleMaxCharges = ____collectibles.getCollectibleMaxCharges
14
14
  local ____collectibleSet = require("functions.collectibleSet")
15
15
  local getCollectibleSet = ____collectibleSet.getCollectibleSet
16
+ local ____util = require("functions.util")
17
+ local ensureAllCases = ____util.ensureAllCases
16
18
  function ____exports.getPlayers(self, performExclusions)
17
19
  if performExclusions == nil then
18
20
  performExclusions = false
@@ -25,18 +27,18 @@ function ____exports.getPlayers(self, performExclusions)
25
27
  do
26
28
  local player = Isaac.GetPlayer(i)
27
29
  if player == nil then
28
- goto __continue55
30
+ goto __continue51
29
31
  end
30
32
  if ____exports.isChildPlayer(nil, player) then
31
- goto __continue55
33
+ goto __continue51
32
34
  end
33
35
  local character = player:GetPlayerType()
34
36
  if performExclusions and EXCLUDED_CHARACTERS:has(character) then
35
- goto __continue55
37
+ goto __continue51
36
38
  end
37
39
  __TS__ArrayPush(players, player)
38
40
  end
39
- ::__continue55::
41
+ ::__continue51::
40
42
  i = i + 1
41
43
  end
42
44
  end
@@ -206,24 +208,6 @@ function ____exports.getFinalPlayer(self)
206
208
  local players = ____exports.getPlayers(nil)
207
209
  return players[#players]
208
210
  end
209
- function ____exports.getOpenTrinketSlot(self, player)
210
- local maxTrinkets = player:GetMaxTrinkets()
211
- local trinket0 = player:GetTrinket(0)
212
- local trinket1 = player:GetTrinket(1)
213
- if maxTrinkets == 1 then
214
- return ((trinket0 == TrinketType.TRINKET_NULL) and 0) or nil
215
- end
216
- if maxTrinkets == 2 then
217
- if trinket0 == TrinketType.TRINKET_NULL then
218
- return 0
219
- end
220
- return ((trinket1 == TrinketType.TRINKET_NULL) and 1) or nil
221
- end
222
- error(
223
- "The player has an unknown number of trinket slots: " .. tostring(maxTrinkets)
224
- )
225
- return nil
226
- end
227
211
  function ____exports.getPlayerCloserThan(self, position, distance)
228
212
  for ____, player in ipairs(
229
213
  ____exports.getPlayers(nil)
@@ -279,14 +263,14 @@ function ____exports.getPlayerIndexVanilla(self, playerToFind)
279
263
  do
280
264
  local player = Isaac.GetPlayer(i)
281
265
  if player == nil then
282
- goto __continue64
266
+ goto __continue60
283
267
  end
284
268
  local playerHash = GetPtrHash(player)
285
269
  if playerHash == playerToFindHash then
286
270
  return i
287
271
  end
288
272
  end
289
- ::__continue64::
273
+ ::__continue60::
290
274
  i = i + 1
291
275
  end
292
276
  end
@@ -299,43 +283,6 @@ function ____exports.getPlayerNumAllHearts(self, player)
299
283
  local eternalHearts = player:GetEternalHearts()
300
284
  return ((hearts + soulHearts) + boneHearts) + eternalHearts
301
285
  end
302
- function ____exports.getPocketItems(self, player)
303
- local pocketItem = player:GetActiveItem(ActiveSlot.SLOT_POCKET)
304
- local hasPocketItem = pocketItem ~= CollectibleType.COLLECTIBLE_NULL
305
- local pocketItem2 = player:GetActiveItem(ActiveSlot.SLOT_POCKET2)
306
- local hasPocketItem2 = pocketItem2 ~= CollectibleType.COLLECTIBLE_NULL
307
- local maxPocketItems = player:GetMaxPocketItems()
308
- local pocketItems = {}
309
- local pocketItemIdentified = false
310
- local pocketItem2Identified = false
311
- do
312
- local slot = 0
313
- while slot < 4 do
314
- local card = player:GetCard(slot)
315
- local pill = player:GetPill(slot)
316
- if card ~= Card.CARD_NULL then
317
- __TS__ArrayPush(pocketItems, {type = PocketItemType.CARD, id = card})
318
- elseif pill ~= PillColor.PILL_NULL then
319
- __TS__ArrayPush(pocketItems, {type = PocketItemType.PILL, id = pill})
320
- elseif (hasPocketItem and (not hasPocketItem2)) and (not pocketItemIdentified) then
321
- pocketItemIdentified = true
322
- __TS__ArrayPush(pocketItems, {type = PocketItemType.ACTIVE_ITEM, id = pocketItem})
323
- elseif ((not hasPocketItem) and hasPocketItem2) and (not pocketItem2Identified) then
324
- pocketItem2Identified = true
325
- __TS__ArrayPush(pocketItems, {type = PocketItemType.DICE_BAG_DICE, id = pocketItem2})
326
- elseif hasPocketItem and hasPocketItem2 then
327
- __TS__ArrayPush(pocketItems, {type = PocketItemType.UNDETERMINABLE, id = 0})
328
- else
329
- __TS__ArrayPush(pocketItems, {type = PocketItemType.EMPTY, id = 0})
330
- end
331
- if (slot + 1) == maxPocketItems then
332
- break
333
- end
334
- slot = slot + 1
335
- end
336
- end
337
- return pocketItems
338
- end
339
286
  function ____exports.getTotalCharge(self, player, activeSlot)
340
287
  local activeCharge = player:GetActiveCharge(activeSlot)
341
288
  local batteryCharge = player:GetBatteryCharge(activeSlot)
@@ -367,27 +314,6 @@ function ____exports.hasOpenActiveItemSlot(self, player)
367
314
  end
368
315
  return activeItemPrimary == CollectibleType.COLLECTIBLE_NULL
369
316
  end
370
- function ____exports.hasOpenPocketItemSlot(self, player)
371
- local character = player:GetPlayerType()
372
- if character == PlayerType.PLAYER_THESOUL_B then
373
- return false
374
- end
375
- local pocketItems = ____exports.getPocketItems(nil, player)
376
- for ____, pocketItem in ipairs(pocketItems) do
377
- if pocketItem.type == PocketItemType.EMPTY then
378
- return true
379
- end
380
- end
381
- return false
382
- end
383
- function ____exports.hasOpenTrinketSlot(self, player)
384
- local character = player:GetPlayerType()
385
- if character == PlayerType.PLAYER_THESOUL_B then
386
- return false
387
- end
388
- local openTrinketSlot = ____exports.getOpenTrinketSlot(nil, player)
389
- return openTrinketSlot ~= nil
390
- end
391
317
  function ____exports.isBethany(self, player)
392
318
  local character = player:GetPlayerType()
393
319
  return (character == PlayerType.PLAYER_BETHANY) or (character == PlayerType.PLAYER_BETHANY_B)
@@ -436,6 +362,71 @@ function ____exports.removeTrinketCostume(self, player, trinketType)
436
362
  end
437
363
  player:RemoveCostume(itemConfigTrinket)
438
364
  end
365
+ function ____exports.setActiveItem(self, player, collectibleType, activeSlot, charge, keepInPools)
366
+ if keepInPools == nil then
367
+ keepInPools = false
368
+ end
369
+ local game = Game()
370
+ local itemPool = game:GetItemPool()
371
+ local primaryCollectibleType = player:GetActiveItem(ActiveSlot.SLOT_PRIMARY)
372
+ local primaryCharge = player:GetActiveCharge(ActiveSlot.SLOT_PRIMARY)
373
+ local secondaryCollectibleType = player:GetActiveItem(ActiveSlot.SLOT_SECONDARY)
374
+ if charge == nil then
375
+ charge = getCollectibleMaxCharges(nil, collectibleType)
376
+ end
377
+ if not keepInPools then
378
+ itemPool:RemoveCollectible(collectibleType)
379
+ end
380
+ repeat
381
+ local ____switch87 = activeSlot
382
+ local ____cond87 = ____switch87 == ActiveSlot.SLOT_PRIMARY
383
+ if ____cond87 then
384
+ do
385
+ if primaryCollectibleType ~= CollectibleType.COLLECTIBLE_NULL then
386
+ player:RemoveCollectible(primaryCollectibleType)
387
+ end
388
+ player:AddCollectible(collectibleType, charge, false)
389
+ break
390
+ end
391
+ end
392
+ ____cond87 = ____cond87 or (____switch87 == ActiveSlot.SLOT_SECONDARY)
393
+ if ____cond87 then
394
+ do
395
+ if primaryCollectibleType ~= CollectibleType.COLLECTIBLE_NULL then
396
+ player:RemoveCollectible(primaryCollectibleType)
397
+ end
398
+ if secondaryCollectibleType ~= CollectibleType.COLLECTIBLE_NULL then
399
+ player:RemoveCollectible(secondaryCollectibleType)
400
+ end
401
+ player:AddCollectible(secondaryCollectibleType, charge, false)
402
+ if primaryCollectibleType ~= CollectibleType.COLLECTIBLE_NULL then
403
+ player:AddCollectible(primaryCollectibleType, primaryCharge, false)
404
+ end
405
+ break
406
+ end
407
+ end
408
+ ____cond87 = ____cond87 or (____switch87 == ActiveSlot.SLOT_POCKET)
409
+ if ____cond87 then
410
+ do
411
+ player:SetPocketActiveItem(collectibleType, activeSlot, keepInPools)
412
+ player:SetActiveCharge(charge, activeSlot)
413
+ break
414
+ end
415
+ end
416
+ ____cond87 = ____cond87 or (____switch87 == ActiveSlot.SLOT_POCKET2)
417
+ if ____cond87 then
418
+ do
419
+ player:SetPocketActiveItem(collectibleType, activeSlot, keepInPools)
420
+ break
421
+ end
422
+ end
423
+ do
424
+ do
425
+ ensureAllCases(nil, activeSlot)
426
+ end
427
+ end
428
+ until true
429
+ end
439
430
  function ____exports.setBlindfold(self, player, enabled)
440
431
  local game = Game()
441
432
  local character = player:GetPlayerType()
@@ -1,21 +1,23 @@
1
1
  /// <reference types="isaac-typescript-definitions" />
2
+ import { PocketItemDescription } from "../types/PocketItemDescription";
3
+ export declare function getFirstCardOrPill(player: EntityPlayer): PocketItemDescription | undefined;
2
4
  /**
3
- * This is a helper function to get a card name from a Card.
5
+ * Use this helper function as a workaround for `EntityPlayer.GetPocketItem()` not working
6
+ * correctly.
4
7
  *
5
- * Example:
6
- * ```
7
- * const card = Card.CARD_FOOL;
8
- * const cardName = getCardName(card); // cardName is "0 - The Fool"
9
- * ```
8
+ * Note that due to API limitations, there is no way to determine the location of a Dice Bag trinket
9
+ * dice. Furthermore, when the player has a Dice Bag trinket dice and a pocket active at the same
10
+ * time, there is no way to determine the location of the pocket active item. If this function
11
+ * cannot determine the identity of a particular slot, it will mark the type of the slot as
12
+ * `PocketItemType.UNDETERMINABLE`.
10
13
  */
11
- export declare function getCardName(card: Card | int): string;
14
+ export declare function getPocketItems(player: EntityPlayer): PocketItemDescription[];
12
15
  /**
13
- * This is a helper function to get a pill effect name from a PillEffect.
16
+ * Returns whether or not the player can hold an additional pocket item, beyond what they are
17
+ * currently carrying. This takes into account items that modify the max number of pocket items,
18
+ * like Starter Deck.
14
19
  *
15
- * Example:
16
- * ```
17
- * const pillEffect = PillEffect.PILLEFFECT_BAD_GAS;
18
- * const pillEffectName = getPillEffectName(pillEffect); // trinketName is "Bad Gas"
19
- * ```
20
+ * If the player is the Tainted Soul, this always returns false, since that character cannot pick up
21
+ * items. (Only Tainted Forgotten can pick up items.)
20
22
  */
21
- export declare function getPillEffectName(pillEffect: PillEffect | int): string;
23
+ export declare function hasOpenPocketItemSlot(player: EntityPlayer): boolean;
@@ -1,39 +1,65 @@
1
1
  --[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
2
+ require("lualib_bundle");
2
3
  local ____exports = {}
3
- local ____cardNameMap = require("maps.cardNameMap")
4
- local CARD_NAME_MAP = ____cardNameMap.CARD_NAME_MAP
5
- local ____pillEffectNameMap = require("maps.pillEffectNameMap")
6
- local PILL_EFFECT_NAME_MAP = ____pillEffectNameMap.PILL_EFFECT_NAME_MAP
7
- function ____exports.getCardName(self, card)
8
- local itemConfig = Isaac.GetItemConfig()
9
- local defaultName = "Unknown"
10
- if type(card) ~= "number" then
11
- return defaultName
4
+ local ____PocketItemType = require("types.PocketItemType")
5
+ local PocketItemType = ____PocketItemType.PocketItemType
6
+ function ____exports.getPocketItems(self, player)
7
+ local pocketItem = player:GetActiveItem(ActiveSlot.SLOT_POCKET)
8
+ local hasPocketItem = pocketItem ~= CollectibleType.COLLECTIBLE_NULL
9
+ local pocketItem2 = player:GetActiveItem(ActiveSlot.SLOT_POCKET2)
10
+ local hasPocketItem2 = pocketItem2 ~= CollectibleType.COLLECTIBLE_NULL
11
+ local maxPocketItems = player:GetMaxPocketItems()
12
+ local pocketItems = {}
13
+ local pocketItemIdentified = false
14
+ local pocketItem2Identified = false
15
+ do
16
+ local slot = 0
17
+ while slot < 4 do
18
+ local card = player:GetCard(slot)
19
+ local pill = player:GetPill(slot)
20
+ if card ~= Card.CARD_NULL then
21
+ __TS__ArrayPush(pocketItems, {type = PocketItemType.CARD, id = card})
22
+ elseif pill ~= PillColor.PILL_NULL then
23
+ __TS__ArrayPush(pocketItems, {type = PocketItemType.PILL, id = pill})
24
+ elseif (hasPocketItem and (not hasPocketItem2)) and (not pocketItemIdentified) then
25
+ pocketItemIdentified = true
26
+ __TS__ArrayPush(pocketItems, {type = PocketItemType.ACTIVE_ITEM, id = pocketItem})
27
+ elseif ((not hasPocketItem) and hasPocketItem2) and (not pocketItem2Identified) then
28
+ pocketItem2Identified = true
29
+ __TS__ArrayPush(pocketItems, {type = PocketItemType.DICE_BAG_DICE, id = pocketItem2})
30
+ elseif hasPocketItem and hasPocketItem2 then
31
+ __TS__ArrayPush(pocketItems, {type = PocketItemType.UNDETERMINABLE, id = 0})
32
+ else
33
+ __TS__ArrayPush(pocketItems, {type = PocketItemType.EMPTY, id = 0})
34
+ end
35
+ if (slot + 1) == maxPocketItems then
36
+ break
37
+ end
38
+ slot = slot + 1
39
+ end
12
40
  end
13
- local cardName = CARD_NAME_MAP:get(card)
14
- if cardName ~= nil then
15
- return cardName
16
- end
17
- local itemConfigCard = itemConfig:GetCard(card)
18
- if itemConfigCard == nil then
19
- return defaultName
20
- end
21
- return itemConfigCard.Name
41
+ return pocketItems
22
42
  end
23
- function ____exports.getPillEffectName(self, pillEffect)
24
- local itemConfig = Isaac.GetItemConfig()
25
- local defaultName = "Unknown"
26
- if type(pillEffect) ~= "number" then
27
- return defaultName
43
+ function ____exports.getFirstCardOrPill(self, player)
44
+ local pocketItems = ____exports.getPocketItems(nil, player)
45
+ for ____, pocketItem in ipairs(pocketItems) do
46
+ if (pocketItem.type == PocketItemType.CARD) or (pocketItem.type == PocketItemType.PILL) then
47
+ return pocketItem
48
+ end
28
49
  end
29
- local pillEffectName = PILL_EFFECT_NAME_MAP:get(pillEffect)
30
- if pillEffectName ~= nil then
31
- return pillEffectName
50
+ return nil
51
+ end
52
+ function ____exports.hasOpenPocketItemSlot(self, player)
53
+ local character = player:GetPlayerType()
54
+ if character == PlayerType.PLAYER_THESOUL_B then
55
+ return false
32
56
  end
33
- local itemConfigPillEffect = itemConfig:GetPillEffect(pillEffect)
34
- if itemConfigPillEffect == nil then
35
- return defaultName
57
+ local pocketItems = ____exports.getPocketItems(nil, player)
58
+ for ____, pocketItem in ipairs(pocketItems) do
59
+ if pocketItem.type == PocketItemType.EMPTY then
60
+ return true
61
+ end
36
62
  end
37
- return itemConfigPillEffect.Name
63
+ return false
38
64
  end
39
65
  return ____exports
@@ -108,6 +108,13 @@ export declare function inDimension(dimension: Dimension): boolean;
108
108
  export declare function inLRoom(): boolean;
109
109
  export declare function inGenesisRoom(): boolean;
110
110
  export declare function inStartingRoom(): boolean;
111
+ /**
112
+ * If `Room.Update()` is called in a PostNewRoom callback, then some entities will slide around
113
+ * (such as the player). Since those entity velocities are already at zero, setting them to zero
114
+ * will have no effect. Thus, a generic solution is to record all of the entity positions/velocities
115
+ * before updating the room, and then restore those positions/velocities.
116
+ */
117
+ export declare function roomUpdateSafe(): void;
111
118
  /**
112
119
  * Helper function to convert an uncleared room to a cleared room in the PostNewRoom callback. This
113
120
  * is useful because if enemies are removed in this callback, a room drop will be awarded and the
@@ -11,6 +11,12 @@ local ____doors = require("functions.doors")
11
11
  local closeAllDoors = ____doors.closeAllDoors
12
12
  local getDoors = ____doors.getDoors
13
13
  local isHiddenSecretRoomDoor = ____doors.isHiddenSecretRoomDoor
14
+ local ____entity = require("functions.entity")
15
+ local getEntities = ____entity.getEntities
16
+ local getEntityPositions = ____entity.getEntityPositions
17
+ local getEntityVelocities = ____entity.getEntityVelocities
18
+ local setEntityPositions = ____entity.setEntityPositions
19
+ local setEntityVelocities = ____entity.setEntityVelocities
14
20
  local ____flag = require("functions.flag")
15
21
  local hasFlag = ____flag.hasFlag
16
22
  function ____exports.getRoomIndex(self)
@@ -196,6 +202,16 @@ function ____exports.inStartingRoom(self)
196
202
  local roomIndex = ____exports.getRoomIndex(nil)
197
203
  return roomIndex == startingRoomIndex
198
204
  end
205
+ function ____exports.roomUpdateSafe(self)
206
+ local game = Game()
207
+ local room = game:GetRoom()
208
+ local entities = getEntities(nil)
209
+ local entityPositions = getEntityPositions(nil, entities)
210
+ local entityVelocities = getEntityVelocities(nil, entities)
211
+ room:Update()
212
+ setEntityPositions(nil, entityPositions, entities)
213
+ setEntityVelocities(nil, entityVelocities, entities)
214
+ end
199
215
  function ____exports.setRoomCleared(self)
200
216
  local game = Game()
201
217
  local room = game:GetRoom()
@@ -210,14 +226,14 @@ function ____exports.setRoomCleared(self)
210
226
  ) do
211
227
  do
212
228
  if isHiddenSecretRoomDoor(nil, door) then
213
- goto __continue38
229
+ goto __continue39
214
230
  end
215
231
  door.State = DoorState.STATE_OPEN
216
232
  local sprite = door:GetSprite()
217
233
  sprite:Play("Opened", true)
218
234
  door.ExtraVisible = false
219
235
  end
220
- ::__continue38::
236
+ ::__continue39::
221
237
  end
222
238
  sfx:Stop(SoundEffect.SOUND_DOOR_HEAVY_OPEN)
223
239
  game:ShakeScreen(0)
@@ -1,6 +1,20 @@
1
1
  /// <reference types="isaac-typescript-definitions" />
2
2
  export declare function getMaxTrinketID(): int;
3
- /** Helper function to get all of the collectible entities in the room. */
3
+ /**
4
+ * Returns the slot number corresponding to where a trinket can be safely inserted.
5
+ *
6
+ * Example:
7
+ * ```
8
+ * const player = Isaac.GetPlayer();
9
+ * const trinketSlot = getOpenTrinketSlotNum(player);
10
+ * if (trinketSlot !== undefined) {
11
+ * // They have one or more open trinket slots
12
+ * player.AddTrinket(TrinketType.TRINKET_SWALLOWED_PENNY);
13
+ * }
14
+ * ```
15
+ */
16
+ export declare function getOpenTrinketSlot(player: EntityPlayer): int | undefined;
17
+ /** Helper function to get all of the trinket entities in the room. */
4
18
  export declare function getTrinkets(matchingSubType?: number): EntityPickup[];
5
19
  /** This is a helper function to get a trinket description from a TrinketType. */
6
20
  export declare function getTrinketDescription(trinketType: TrinketType | int): string;
@@ -14,4 +28,12 @@ export declare function getTrinketDescription(trinketType: TrinketType | int): s
14
28
  * ```
15
29
  */
16
30
  export declare function getTrinketName(trinketType: TrinketType | int): string;
31
+ /**
32
+ * Returns whether or not the player can hold an additional trinket, beyond what they are currently
33
+ * carrying. This takes into account items that modify the max number of trinkets, like Mom's Purse.
34
+ *
35
+ * If the player is the Tainted Soul, this always returns false, since that character cannot pick up
36
+ * items. (Only Tainted Forgotten can pick up items.)
37
+ */
38
+ export declare function hasOpenTrinketSlot(player: EntityPlayer): boolean;
17
39
  export declare function isGoldenTrinket(trinketType: TrinketType | int): boolean;
@@ -11,6 +11,24 @@ function ____exports.getMaxTrinketID(self)
11
11
  local itemConfig = Isaac.GetItemConfig()
12
12
  return itemConfig:GetTrinkets().Size - 1
13
13
  end
14
+ function ____exports.getOpenTrinketSlot(self, player)
15
+ local maxTrinkets = player:GetMaxTrinkets()
16
+ local trinket0 = player:GetTrinket(0)
17
+ local trinket1 = player:GetTrinket(1)
18
+ if maxTrinkets == 1 then
19
+ return ((trinket0 == TrinketType.TRINKET_NULL) and 0) or nil
20
+ end
21
+ if maxTrinkets == 2 then
22
+ if trinket0 == TrinketType.TRINKET_NULL then
23
+ return 0
24
+ end
25
+ return ((trinket1 == TrinketType.TRINKET_NULL) and 1) or nil
26
+ end
27
+ error(
28
+ "The player has an unknown number of trinket slots: " .. tostring(maxTrinkets)
29
+ )
30
+ return nil
31
+ end
14
32
  function ____exports.getTrinkets(self, matchingSubType)
15
33
  if matchingSubType == nil then
16
34
  matchingSubType = -1
@@ -57,6 +75,14 @@ function ____exports.getTrinketName(self, trinketType)
57
75
  end
58
76
  return itemConfigItem.Name
59
77
  end
78
+ function ____exports.hasOpenTrinketSlot(self, player)
79
+ local character = player:GetPlayerType()
80
+ if character == PlayerType.PLAYER_THESOUL_B then
81
+ return false
82
+ end
83
+ local openTrinketSlot = ____exports.getOpenTrinketSlot(nil, player)
84
+ return openTrinketSlot ~= nil
85
+ end
60
86
  function ____exports.isGoldenTrinket(self, trinketType)
61
87
  return trinketType > GOLDEN_TRINKET_SHIFT
62
88
  end
package/dist/index.d.ts CHANGED
@@ -32,6 +32,7 @@ export * from "./functions/pickups";
32
32
  export * from "./functions/pills";
33
33
  export * from "./functions/player";
34
34
  export * from "./functions/playerHealth";
35
+ export * from "./functions/pocketItems";
35
36
  export * from "./functions/position";
36
37
  export * from "./functions/random";
37
38
  export * from "./functions/revive";
package/dist/index.lua CHANGED
@@ -262,6 +262,14 @@ do
262
262
  end
263
263
  end
264
264
  end
265
+ do
266
+ local ____export = require("functions.pocketItems")
267
+ for ____exportKey, ____exportValue in pairs(____export) do
268
+ if ____exportKey ~= "default" then
269
+ ____exports[____exportKey] = ____exportValue
270
+ end
271
+ end
272
+ end
265
273
  do
266
274
  local ____export = require("functions.position")
267
275
  for ____exportKey, ____exportValue in pairs(____export) do
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "1.0.482",
3
+ "version": "1.0.486",
4
4
  "description": "Helper functions for IsaacScript mods",
5
5
  "keywords": [
6
6
  "isaac",
@@ -25,7 +25,7 @@
25
25
  "dist/**/*.d.ts"
26
26
  ],
27
27
  "devDependencies": {
28
- "isaac-typescript-definitions": "^1.0.282",
28
+ "isaac-typescript-definitions": "^1.0.284",
29
29
  "isaacscript-lint": "^1.0.67",
30
30
  "typedoc": "^0.22.10",
31
31
  "typescript": "4.4.4",