isaacscript-common 6.16.1 → 6.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/enums/ModCallbackCustom.d.ts +1 -1
  2. package/dist/features/customGridEntity.d.ts +3 -3
  3. package/dist/features/customGridEntity.d.ts.map +1 -1
  4. package/dist/features/customGridEntity.lua +18 -11
  5. package/dist/features/extraConsoleCommands/listCommands.lua +2 -2
  6. package/dist/features/persistentEntities.d.ts.map +1 -1
  7. package/dist/features/persistentEntities.lua +15 -5
  8. package/dist/features/pickupIndex.d.ts.map +1 -1
  9. package/dist/features/pickupIndex.lua +5 -6
  10. package/dist/features/roomHistory.d.ts +11 -4
  11. package/dist/features/roomHistory.d.ts.map +1 -1
  12. package/dist/features/roomHistory.lua +18 -5
  13. package/dist/functions/log.d.ts +1 -1
  14. package/dist/functions/log.d.ts.map +1 -1
  15. package/dist/functions/log.lua +33 -28
  16. package/dist/functions/npcs.d.ts +9 -0
  17. package/dist/functions/npcs.d.ts.map +1 -1
  18. package/dist/functions/npcs.lua +16 -3
  19. package/dist/functions/playerHealth.d.ts.map +1 -1
  20. package/dist/functions/playerHealth.lua +29 -12
  21. package/dist/functions/rockAlt.lua +18 -18
  22. package/dist/functions/saveFile.d.ts.map +1 -1
  23. package/dist/functions/saveFile.lua +3 -1
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.lua +1 -1
  27. package/dist/interfaces/{CustomGridEntityData.d.ts → GridEntityCustomData.d.ts} +2 -2
  28. package/dist/interfaces/{CustomGridEntityData.d.ts.map → GridEntityCustomData.d.ts.map} +1 -1
  29. package/dist/interfaces/{CustomGridEntityData.lua → GridEntityCustomData.lua} +0 -0
  30. package/dist/interfaces/PlayerHealth.d.ts +4 -1
  31. package/dist/interfaces/PlayerHealth.d.ts.map +1 -1
  32. package/dist/interfaces/RoomDescription.d.ts +1 -0
  33. package/dist/interfaces/RoomDescription.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/src/enums/ModCallbackCustom.ts +1 -1
  36. package/src/features/customGridEntity.ts +30 -17
  37. package/src/features/extraConsoleCommands/listCommands.ts +2 -2
  38. package/src/features/persistentEntities.ts +19 -5
  39. package/src/features/pickupIndex.ts +9 -15
  40. package/src/features/roomHistory.ts +24 -4
  41. package/src/functions/log.ts +35 -30
  42. package/src/functions/npcs.ts +27 -2
  43. package/src/functions/playerHealth.ts +25 -12
  44. package/src/functions/rockAlt.ts +21 -21
  45. package/src/functions/saveFile.ts +2 -1
  46. package/src/index.ts +1 -1
  47. package/src/interfaces/{CustomGridEntityData.ts → GridEntityCustomData.ts} +1 -1
  48. package/src/interfaces/PlayerHealth.ts +12 -1
  49. package/src/interfaces/RoomDescription.ts +1 -0
@@ -47,11 +47,11 @@ local getRandomVector = ____vector.getRandomVector
47
47
  function spawnRockAltRewardUrn(self, position, rng)
48
48
  local chance = getRandom(nil, rng)
49
49
  local totalChance = 0
50
- totalChance = totalChance + ROCK_ALT_CHANCES.Nothing
50
+ totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
51
51
  if chance < totalChance then
52
52
  return false
53
53
  end
54
- totalChance = totalChance + ROCK_ALT_CHANCES.BasicDrop
54
+ totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
55
55
  if chance < totalChance then
56
56
  local numCoinsChance = getRandom(nil, rng)
57
57
  local numCoins = numCoinsChance < 0.5 and 1 or 2
@@ -73,12 +73,12 @@ function spawnRockAltRewardUrn(self, position, rng)
73
73
  )
74
74
  return true
75
75
  end
76
- totalChance = totalChance + ROCK_ALT_CHANCES.Trinket
76
+ totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
77
77
  if chance < totalChance then
78
78
  spawnTrinketWithSeed(nil, TrinketType.SWALLOWED_PENNY, position, rng)
79
79
  return true
80
80
  end
81
- totalChance = totalChance + ROCK_ALT_CHANCES.Collectible
81
+ totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
82
82
  if chance < totalChance then
83
83
  local stillInPools = isCollectibleInItemPool(nil, CollectibleType.QUARTER, ItemPoolType.DEVIL)
84
84
  if stillInPools then
@@ -113,21 +113,21 @@ function spawnRockAltRewardMushroom(self, position, rng)
113
113
  local roomType = room:GetType()
114
114
  local chance = getRandom(nil, rng)
115
115
  local totalChance = 0
116
- totalChance = totalChance + ROCK_ALT_CHANCES.Nothing
116
+ totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
117
117
  if chance < totalChance then
118
118
  return false
119
119
  end
120
- totalChance = totalChance + ROCK_ALT_CHANCES.BasicDrop
120
+ totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
121
121
  if chance < totalChance then
122
122
  spawnPillWithSeed(nil, PillColor.NULL, position, rng)
123
123
  return true
124
124
  end
125
- totalChance = totalChance + ROCK_ALT_CHANCES.Trinket
125
+ totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
126
126
  if chance < totalChance then
127
127
  spawnTrinketWithSeed(nil, TrinketType.LIBERTY_CAP, position, rng)
128
128
  return true
129
129
  end
130
- totalChance = totalChance + ROCK_ALT_CHANCES.Collectible
130
+ totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
131
131
  if chance < totalChance then
132
132
  if roomType == RoomType.SECRET then
133
133
  local wavyCapChance = getRandom(nil, rng)
@@ -169,21 +169,21 @@ end
169
169
  function spawnRockAltRewardSkull(self, position, rng)
170
170
  local chance = getRandom(nil, rng)
171
171
  local totalChance = 0
172
- totalChance = totalChance + ROCK_ALT_CHANCES.Nothing
172
+ totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
173
173
  if chance < totalChance then
174
174
  return false
175
175
  end
176
- totalChance = totalChance + ROCK_ALT_CHANCES.BasicDrop
176
+ totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
177
177
  if chance < totalChance then
178
178
  spawnCardWithSeed(nil, Card.NULL, position, rng)
179
179
  return true
180
180
  end
181
- totalChance = totalChance + ROCK_ALT_CHANCES.Trinket
181
+ totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
182
182
  if chance < totalChance then
183
183
  spawnHeartWithSeed(nil, HeartSubType.BLACK, position, rng)
184
184
  return true
185
185
  end
186
- totalChance = totalChance + ROCK_ALT_CHANCES.Collectible
186
+ totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
187
187
  if chance < totalChance then
188
188
  local ghostBabyStillInPools = isCollectibleInItemPool(nil, CollectibleType.GHOST_BABY, ItemPoolType.TREASURE)
189
189
  local dryBabyStillInPools = isCollectibleInItemPool(nil, CollectibleType.DRY_BABY, ItemPoolType.TREASURE)
@@ -216,21 +216,21 @@ end
216
216
  function spawnRockAltRewardPolyp(self, position, rng)
217
217
  local chance = getRandom(nil, rng)
218
218
  local totalChance = 0
219
- totalChance = totalChance + ROCK_ALT_CHANCES.Nothing
219
+ totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
220
220
  if chance < totalChance then
221
221
  return false
222
222
  end
223
- totalChance = totalChance + ROCK_ALT_CHANCES.BasicDrop
223
+ totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
224
224
  if chance < totalChance then
225
225
  spawnHeartWithSeed(nil, HeartSubType.NULL, position, rng)
226
226
  return true
227
227
  end
228
- totalChance = totalChance + ROCK_ALT_CHANCES.Trinket
228
+ totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
229
229
  if chance < totalChance then
230
230
  spawnTrinketWithSeed(nil, TrinketType.UMBILICAL_CORD, position, rng)
231
231
  return true
232
232
  end
233
- totalChance = totalChance + ROCK_ALT_CHANCES.Collectible
233
+ totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
234
234
  if chance < totalChance then
235
235
  local placentaStillInPools = isCollectibleInItemPool(nil, CollectibleType.PLACENTA, ItemPoolType.BOSS)
236
236
  local bloodClotStillInPools = isCollectibleInItemPool(nil, CollectibleType.BLOOD_CLOT, ItemPoolType.BOSS)
@@ -269,13 +269,13 @@ end
269
269
  function spawnRockAltRewardBucket(self, _position, rng, _variant)
270
270
  local chance = getRandom(nil, rng)
271
271
  local totalChance = 0
272
- totalChance = totalChance + ROCK_ALT_CHANCES.Nothing
272
+ totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
273
273
  if chance < totalChance then
274
274
  return false
275
275
  end
276
276
  return false
277
277
  end
278
- ROCK_ALT_CHANCES = {Nothing = 0.68, BasicDrop = 0.0967, Trinket = 0.025, Collectible = 0.005}
278
+ ROCK_ALT_CHANCES = {NOTHING = 0.68, BASIC_DROP = 0.0967, TRINKET = 0.025, COLLECTIBLE = 0.005}
279
279
  POLYP_PROJECTILE_SPEED = 10
280
280
  POLYP_NUM_PROJECTILES = 6
281
281
  --- Helper function to get the alternate rock type (i.e. urn, mushroom, etc.) that the current room
@@ -1 +1 @@
1
- {"version":3,"file":"saveFile.d.ts","sourceRoot":"","sources":["../../src/functions/saveFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAG7E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,eAAe,EAChC,YAAY,EAAE,YAAY,GACzB,OAAO,CAMT"}
1
+ {"version":3,"file":"saveFile.d.ts","sourceRoot":"","sources":["../../src/functions/saveFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI7E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,eAAe,EAChC,YAAY,EAAE,YAAY,GACzB,OAAO,CAMT"}
@@ -1,4 +1,6 @@
1
1
  local ____exports = {}
2
+ local ____itemPool = require("functions.itemPool")
3
+ local isCollectibleInItemPool = ____itemPool.isCollectibleInItemPool
2
4
  local ____players = require("functions.players")
3
5
  local anyPlayerHasCollectible = ____players.anyPlayerHasCollectible
4
6
  --- Helper function to see if the given collectible is unlocked on the current save file. This
@@ -17,6 +19,6 @@ function ____exports.isCollectibleUnlocked(self, collectibleType, itemPoolType)
17
19
  if anyPlayerHasCollectible(nil, collectibleType) then
18
20
  return true
19
21
  end
20
- return ____exports.isCollectibleUnlocked(nil, collectibleType, itemPoolType)
22
+ return isCollectibleInItemPool(nil, collectibleType, itemPoolType)
21
23
  end
22
24
  return ____exports
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@ export * from "./enums/SerializationType";
12
12
  export { ConversionHeartSubType, registerCharacterHealthConversion, } from "./features/characterHealthConversion";
13
13
  export { registerCharacterStats } from "./features/characterStats";
14
14
  export { getCollectibleItemPoolType } from "./features/collectibleItemPoolType";
15
- export { removeCustomGrid, spawnCustomGridEntity as spawnCustomGrid, } from "./features/customGridEntity";
15
+ export { removeCustomGridEntity as removeCustomGrid, spawnCustomGridEntity as spawnCustomGrid, } from "./features/customGridEntity";
16
16
  export * from "./features/customStage/exports";
17
17
  export * from "./features/customTrapdoor/exports";
18
18
  export * from "./features/debugDisplay/exports";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.lua CHANGED
@@ -104,7 +104,7 @@ do
104
104
  end
105
105
  do
106
106
  local ____customGridEntity = require("features.customGridEntity")
107
- local removeCustomGrid = ____customGridEntity.removeCustomGrid
107
+ local removeCustomGrid = ____customGridEntity.removeCustomGridEntity
108
108
  local spawnCustomGrid = ____customGridEntity.spawnCustomGridEntity
109
109
  ____exports.removeCustomGrid = removeCustomGrid
110
110
  ____exports.spawnCustomGrid = spawnCustomGrid
@@ -1,5 +1,5 @@
1
1
  import { GridCollisionClass, GridEntityType } from "isaac-typescript-definitions";
2
- export interface CustomGridEntityData {
2
+ export interface GridEntityCustomData {
3
3
  /**
4
4
  * This is not a real `GridEntityType`; rather it is an arbitrary integer selected by end-user
5
5
  * mods.
@@ -11,4 +11,4 @@ export interface CustomGridEntityData {
11
11
  defaultAnimation?: string;
12
12
  gridCollisionClass: GridCollisionClass;
13
13
  }
14
- //# sourceMappingURL=CustomGridEntityData.d.ts.map
14
+ //# sourceMappingURL=GridEntityCustomData.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CustomGridEntityData.d.ts","sourceRoot":"","sources":["../../src/interfaces/CustomGridEntityData.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,cAAc,EACf,MAAM,8BAA8B,CAAC;AAEtC,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,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"}
@@ -4,13 +4,16 @@ export interface PlayerHealth {
4
4
  maxHearts: int;
5
5
  hearts: int;
6
6
  eternalHearts: int;
7
+ /** For soul hearts to apply, they also have to be specified in the `soulHeartTypes` array. */
7
8
  soulHearts: int;
9
+ /** For bone hearts to apply, they also have to be specified in the `soulHeartTypes` array. */
8
10
  boneHearts: int;
9
11
  goldenHearts: int;
10
12
  rottenHearts: int;
11
13
  brokenHearts: int;
12
14
  soulCharges: int;
13
15
  bloodCharges: int;
14
- soulHeartTypes: HeartSubType[];
16
+ soulHeartTypes: SoulHeartType[];
15
17
  }
18
+ export declare type SoulHeartType = HeartSubType.SOUL | HeartSubType.BLACK | HeartSubType.BONE;
16
19
  //# sourceMappingURL=PlayerHealth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlayerHealth.d.ts","sourceRoot":"","sources":["../../src/interfaces/PlayerHealth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,GAAG,CAAC;IACnB,UAAU,EAAE,GAAG,CAAC;IAChB,UAAU,EAAE,GAAG,CAAC;IAChB,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC;IACjB,YAAY,EAAE,GAAG,CAAC;IAClB,cAAc,EAAE,YAAY,EAAE,CAAC;CAChC"}
1
+ {"version":3,"file":"PlayerHealth.d.ts","sourceRoot":"","sources":["../../src/interfaces/PlayerHealth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,GAAG,CAAC;IAEnB,8FAA8F;IAC9F,UAAU,EAAE,GAAG,CAAC;IAEhB,8FAA8F;IAC9F,UAAU,EAAE,GAAG,CAAC;IAEhB,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC;IACjB,YAAY,EAAE,GAAG,CAAC;IAElB,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAED,oBAAY,aAAa,GACrB,YAAY,CAAC,IAAI,GACjB,YAAY,CAAC,KAAK,GAClB,YAAY,CAAC,IAAI,CAAC"}
@@ -10,5 +10,6 @@ export interface RoomDescription {
10
10
  roomName: string;
11
11
  roomGridIndex: int;
12
12
  roomListIndex: int;
13
+ roomVisitedCount: int;
13
14
  }
14
15
  //# sourceMappingURL=RoomDescription.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RoomDescription.d.ts","sourceRoot":"","sources":["../../src/interfaces/RoomDescription.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACV,MAAM,8BAA8B,CAAC;AAEtC,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,GAAG,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC;CACpB"}
1
+ {"version":3,"file":"RoomDescription.d.ts","sourceRoot":"","sources":["../../src/interfaces/RoomDescription.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACV,MAAM,8BAA8B,CAAC;AAEtC,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,GAAG,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC;IACnB,gBAAgB,EAAE,GAAG,CAAC;CACvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "6.16.1",
3
+ "version": "6.17.1",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -564,7 +564,7 @@ export enum ModCallbackCustom {
564
564
  * - When registering the callback, takes an optional second argument that will make the callback
565
565
  * only fire if it matches the `ItemType` provided.
566
566
  * - When registering the callback, takes an optional third argument that will make the callback
567
- * only fire if the `CollectibleType` or the `TrinketType` matches the ID provided.
567
+ * only fire if the `CollectibleType` or the `TrinketType` matches the sub-type provided.
568
568
  *
569
569
  * ```ts
570
570
  * function postItemPickup(
@@ -2,6 +2,7 @@ import {
2
2
  ActiveSlot,
3
3
  CollectibleType,
4
4
  DamageFlag,
5
+ EntityFlag,
5
6
  EntityType,
6
7
  GridCollisionClass,
7
8
  GridEntityType,
@@ -15,7 +16,7 @@ import { ModUpgraded } from "../classes/ModUpgraded";
15
16
  import { DecorationVariant } from "../enums/DecorationVariant";
16
17
  import { ModCallbackCustom } from "../enums/ModCallbackCustom";
17
18
  import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
18
- import { spawnNPC } from "../functions/entitiesSpecific";
19
+ import { spawn } from "../functions/entities";
19
20
  import { hasFlag } from "../functions/flag";
20
21
  import {
21
22
  removeGridEntity,
@@ -23,22 +24,23 @@ import {
23
24
  } from "../functions/gridEntities";
24
25
  import { getRoomListIndex } from "../functions/roomData";
25
26
  import { isVector } from "../functions/vector";
26
- import { CustomGridEntityData } from "../interfaces/CustomGridEntityData";
27
+ import { GridEntityCustomData } from "../interfaces/GridEntityCustomData";
27
28
  import { runNextGameFrame } from "./runInNFrames";
28
29
  import { saveDataManager } from "./saveDataManager/exports";
29
30
 
30
31
  const FEATURE_NAME = "customGridEntity";
32
+ const GENERIC_PROP_SIZE_MULTIPLIER = 0.66;
31
33
 
32
34
  const v = {
33
35
  level: {
34
36
  /** Indexed by room list index and grid index. */
35
- customGridEntities: new DefaultMap<int, Map<int, CustomGridEntityData>>(
37
+ customGridEntities: new DefaultMap<int, Map<int, GridEntityCustomData>>(
36
38
  () => new Map(),
37
39
  ),
38
40
  },
39
41
 
40
42
  room: {
41
- dummyPtrHashes: new Set<PtrHash>(),
43
+ genericPropPtrHashes: new Set<PtrHash>(),
42
44
  manuallyUsingShovel: false,
43
45
  },
44
46
  };
@@ -49,8 +51,8 @@ export function customGridEntityInit(mod: ModUpgraded): void {
49
51
 
50
52
  mod.AddCallback(
51
53
  ModCallback.ENTITY_TAKE_DMG,
52
- entityTakeDmgDummy,
53
- EntityType.DUMMY,
54
+ entityTakeDmgGenericProp,
55
+ EntityType.GENERIC_PROP,
54
56
  ); // 11
55
57
 
56
58
  mod.AddCallback(
@@ -66,8 +68,8 @@ export function customGridEntityInit(mod: ModUpgraded): void {
66
68
  }
67
69
 
68
70
  // ModCallback.ENTITY_TAKE_DMG (11)
69
- // EntityType.DUMMY (964)
70
- function entityTakeDmgDummy(
71
+ // EntityType.GENERIC_PROP (960)
72
+ function entityTakeDmgGenericProp(
71
73
  tookDamage: Entity,
72
74
  _damageAmount: float,
73
75
  damageFlags: BitFlags<DamageFlag>,
@@ -75,7 +77,7 @@ function entityTakeDmgDummy(
75
77
  _damageCountdownFrames: int,
76
78
  ): boolean | undefined {
77
79
  const ptrHash = GetPtrHash(tookDamage);
78
- if (!v.room.dummyPtrHashes.has(ptrHash)) {
80
+ if (!v.room.genericPropPtrHashes.has(ptrHash)) {
79
81
  return undefined;
80
82
  }
81
83
 
@@ -105,8 +107,8 @@ function entityTakeDmgDummy(
105
107
 
106
108
  postGridEntityCustomBrokenFire(gridEntity, data.gridEntityTypeCustom);
107
109
 
108
- // Even though the custom grid entity is now broke, we do not want to remove it, as the end-user
109
- // could intend for it to persist with different graphics.
110
+ // Even though the custom grid entity is now broken, we do not want to remove it, as the end-user
111
+ // could intend for it to persist with different graphics (or take multiple hits to be destroyed).
110
112
  return false;
111
113
  }
112
114
 
@@ -261,6 +263,7 @@ export function spawnCustomGridEntity(
261
263
  if (decoration === undefined) {
262
264
  error("Failed to spawn a decoration for a custom grid entity.");
263
265
  }
266
+ decoration.CollisionClass = gridCollisionClass;
264
267
 
265
268
  const sprite = decoration.GetSprite();
266
269
  sprite.Load(anm2Path, true);
@@ -270,7 +273,7 @@ export function spawnCustomGridEntity(
270
273
  : defaultAnimation;
271
274
  sprite.Play(animationToPlay, true);
272
275
 
273
- const customGridEntityData: CustomGridEntityData = {
276
+ const customGridEntityData: GridEntityCustomData = {
274
277
  gridEntityTypeCustom,
275
278
  roomListIndex,
276
279
  gridIndex,
@@ -287,8 +290,18 @@ export function spawnCustomGridEntity(
287
290
  // the monitoring for explosions in the `ENTITY_TAKE_DMG` callback.
288
291
  if (breakable) {
289
292
  const position = room.GetGridPosition(gridIndex);
290
- const dummy = spawnNPC(EntityType.DUMMY, 0, 0, position);
291
- dummy.Visible = false;
293
+ const entity = spawn(EntityType.GENERIC_PROP, 0, 0, position);
294
+ entity.ClearEntityFlags(EntityFlag.APPEAR);
295
+ entity.Visible = false;
296
+
297
+ // By default, it is larger than a grid tile, so make it a bit smaller.
298
+ entity.SizeMulti = Vector(
299
+ GENERIC_PROP_SIZE_MULTIPLIER,
300
+ GENERIC_PROP_SIZE_MULTIPLIER,
301
+ );
302
+
303
+ const ptrHash = GetPtrHash(entity);
304
+ v.room.genericPropPtrHashes.add(ptrHash);
292
305
  }
293
306
 
294
307
  return decoration;
@@ -309,7 +322,7 @@ export function spawnCustomGridEntity(
309
322
  * @returns The grid entity that was removed. Returns undefined if no grid entity was found at the
310
323
  * given location or if the given grid entity was not a custom grid entity.
311
324
  */
312
- export function removeCustomGrid(
325
+ export function removeCustomGridEntity(
313
326
  gridIndexOrPositionOrGridEntity: int | Vector | GridEntity,
314
327
  updateRoom = true,
315
328
  ): GridEntity | undefined {
@@ -356,7 +369,7 @@ export function removeCustomGrid(
356
369
  * containing the raw decoration grid entity and the associated entity data.
357
370
  */
358
371
  export function getCustomGridEntities(): Array<
359
- [gridEntity: GridEntity, data: CustomGridEntityData]
372
+ [gridEntity: GridEntity, data: GridEntityCustomData]
360
373
  > {
361
374
  const roomListIndex = getRoomListIndex();
362
375
  const roomCustomGridEntities = v.level.customGridEntities.get(roomListIndex);
@@ -365,7 +378,7 @@ export function getCustomGridEntities(): Array<
365
378
  }
366
379
 
367
380
  const room = game.GetRoom();
368
- const customGridEntities: Array<[GridEntity, CustomGridEntityData]> = [];
381
+ const customGridEntities: Array<[GridEntity, GridEntityCustomData]> = [];
369
382
  for (const [gridIndex, data] of roomCustomGridEntities.entries()) {
370
383
  const gridEntity = room.GetGridEntity(gridIndex);
371
384
  if (gridEntity !== undefined) {
@@ -64,7 +64,7 @@ import { getEnumValues } from "../../functions/enums";
64
64
  import { addFlag } from "../../functions/flag";
65
65
  import { spawnGridEntity } from "../../functions/gridEntities";
66
66
  import {
67
- logEffects,
67
+ logPlayerEffects,
68
68
  logRoom,
69
69
  logSeedEffects,
70
70
  logSounds,
@@ -515,7 +515,7 @@ export function dungeon(): void {
515
515
  /** Logs the player's current temporary effects to the "log.txt" file. */
516
516
  export function effects(): void {
517
517
  const player = Isaac.GetPlayer();
518
- logEffects(player);
518
+ logPlayerEffects(player);
519
519
  printConsole('Logged the player\'s effects to the "log.txt" file.');
520
520
  }
521
521
 
@@ -8,7 +8,7 @@ import { ModCallbackCustom } from "../enums/ModCallbackCustom";
8
8
  import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
9
9
  import { spawn } from "../functions/entities";
10
10
  import { getRoomListIndex } from "../functions/roomData";
11
- import { getLatestRoomDescription } from "./roomHistory";
11
+ import { getLatestRoomDescription, isLeavingRoom } from "./roomHistory";
12
12
  import { saveDataManager } from "./saveDataManager/exports";
13
13
 
14
14
  interface PersistentEntityDescription {
@@ -56,6 +56,10 @@ export function persistentEntitiesInit(mod: ModUpgraded): void {
56
56
 
57
57
  // ModCallback.POST_ENTITY_REMOVE (67)
58
58
  function postEntityRemove(entity: Entity) {
59
+ checkDespawningFromPlayerLeavingRoom(entity);
60
+ }
61
+
62
+ function checkDespawningFromPlayerLeavingRoom(entity: Entity) {
59
63
  const ptrHash = GetPtrHash(entity);
60
64
  const tuple = v.room.spawnedPersistentEntities.get(ptrHash);
61
65
  if (tuple === undefined) {
@@ -63,10 +67,20 @@ function postEntityRemove(entity: Entity) {
63
67
  }
64
68
  const index = tuple[0];
65
69
 
66
- // The persistent entity is despawning, presumably because the player is in the process of leaving
67
- // the room. Keep track of the position for later. We use the previous room list index because
68
- // even though the `POST_NEW_ROOM` callback was not fired yet, we have already traveled to the
69
- // next room.
70
+ if (!isLeavingRoom()) {
71
+ return;
72
+ }
73
+
74
+ trackDespawningPickupPosition(entity, index);
75
+ }
76
+
77
+ /**
78
+ * The persistent entity is despawning because the player is in the process of leaving the room.
79
+ * Keep track of the position for later.
80
+ */
81
+ function trackDespawningPickupPosition(entity: Entity, index: int) {
82
+ // (The "latest" room description is really the previous room, because the `POST_NEW_ROOM`
83
+ // callback was not fired yet.)
70
84
  const previousRoomDescription = getLatestRoomDescription();
71
85
  const previousRoomListIndex = previousRoomDescription.roomListIndex;
72
86
  const persistentEntityDescription: PersistentEntityDescription = {
@@ -14,7 +14,7 @@ import { getRoomListIndex } from "../functions/roomData";
14
14
  import { onAscent } from "../functions/stage";
15
15
  import { vectorEquals } from "../functions/vector";
16
16
  import { PickupIndex } from "../types/PickupIndex";
17
- import { getLatestRoomDescription } from "./roomHistory";
17
+ import { getLatestRoomDescription, isLeavingRoom } from "./roomHistory";
18
18
  import { saveDataManager } from "./saveDataManager/exports";
19
19
 
20
20
  interface PickupDescription {
@@ -27,7 +27,6 @@ const FEATURE_NAME = "pickupIndex";
27
27
  const v = {
28
28
  run: {
29
29
  pickupCounter: 0 as PickupIndex,
30
- currentRoomListIndex: 0,
31
30
 
32
31
  pickupDataTreasureRooms: new Map<PickupIndex, PickupDescription>(),
33
32
  pickupDataBossRooms: new Map<PickupIndex, PickupDescription>(),
@@ -81,9 +80,6 @@ function postPickupInit(pickup: EntityPickup) {
81
80
 
82
81
  v.run.pickupCounter++;
83
82
  v.room.pickupIndexes.set(ptrHash, v.run.pickupCounter);
84
-
85
- // Additionally, keep track of which room we are storing the pointer hashes for.
86
- v.run.currentRoomListIndex = getRoomListIndex();
87
83
  }
88
84
 
89
85
  // ModCallback.POST_ENTITY_REMOVE (67)
@@ -99,10 +95,7 @@ function checkDespawningFromPlayerLeavingRoom(entity: Entity) {
99
95
  return;
100
96
  }
101
97
 
102
- const roomListIndex = getRoomListIndex();
103
- if (roomListIndex === v.run.currentRoomListIndex) {
104
- // This is a pickup that is despawning in the current room. For example, it could be a heart
105
- // pickup that the player picked up. Thus, we do not need to keep track of it's metadata.
98
+ if (!isLeavingRoom()) {
106
99
  return;
107
100
  }
108
101
 
@@ -111,13 +104,14 @@ function checkDespawningFromPlayerLeavingRoom(entity: Entity) {
111
104
 
112
105
  /**
113
106
  * This is a pickup that is despawning because the player is in the process of leaving the room.
114
- * Keep track of the metadata for later. We need to use the previous room list index because even
115
- * though the `POST_NEW_ROOM` callback was not fired yet, we have already traveled to the next room.
107
+ * Keep track of the metadata for later.
116
108
  */
117
109
  function trackDespawningPickupMetadata(
118
110
  entity: Entity,
119
111
  pickupIndex: PickupIndex,
120
112
  ) {
113
+ // The "latest" room description is really the previous room, because the `POST_NEW_ROOM` callback
114
+ // was not fired yet.
121
115
  const previousRoomDescription = getLatestRoomDescription();
122
116
  const previousRoomListIndex = previousRoomDescription.roomListIndex;
123
117
  const pickupDescriptions = v.level.pickupData.getAndSetDefault(
@@ -176,10 +170,10 @@ function postNewRoomReordered() {
176
170
  }
177
171
 
178
172
  if (pickupIndex === undefined) {
179
- const entityID = getEntityID(pickup);
180
- error(
181
- `Failed to find a pickup index corresponding to existing pickup: ${entityID}`,
182
- );
173
+ // At this point, if we do not already have an existing pickup index, we need to create a new
174
+ // one in order to cover the cases where mods spawn items in the `POST_NEW_ROOM` callback.
175
+ v.run.pickupCounter++;
176
+ pickupIndex = v.run.pickupCounter;
183
177
  }
184
178
 
185
179
  const ptrHash = GetPtrHash(pickup);
@@ -10,6 +10,7 @@ import {
10
10
  getRoomStageID,
11
11
  getRoomSubType,
12
12
  getRoomVariant,
13
+ getRoomVisitedCount,
13
14
  } from "../functions/roomData";
14
15
  import { RoomDescription } from "../interfaces/RoomDescription";
15
16
  import { saveDataManager } from "./saveDataManager/exports";
@@ -45,6 +46,7 @@ function postNewRoomEarly() {
45
46
  const roomName = getRoomName();
46
47
  const roomGridIndex = getRoomGridIndex();
47
48
  const roomListIndex = getRoomListIndex();
49
+ const roomVisitedCount = getRoomVisitedCount();
48
50
 
49
51
  const roomDescription: RoomDescription = {
50
52
  stage,
@@ -56,6 +58,7 @@ function postNewRoomEarly() {
56
58
  roomName,
57
59
  roomGridIndex,
58
60
  roomListIndex,
61
+ roomVisitedCount,
59
62
  };
60
63
  v.run.roomHistory.push(roomDescription);
61
64
  }
@@ -96,10 +99,7 @@ export function getPreviousRoomDescription(): RoomDescription {
96
99
  * Helper function to get information about the most recent room that is stored in the room history
97
100
  * array.
98
101
  *
99
- * This is useful in the `POST_ENTITY_REMOVE` callback, since if an entity is despawning due to a
100
- * player having left the room, the current room will have changed already, but the `POST_NEW_ROOM`
101
- * callback will not have fired yet, and there will not be an entry in the room history array for
102
- * the current room.
102
+ * This is useful in the `POST_ENTITY_REMOVE` callback; see the `isLeavingRoom` function.
103
103
  */
104
104
  export function getLatestRoomDescription(): RoomDescription {
105
105
  const latestRoomDescription = getLastElement(v.run.roomHistory);
@@ -111,3 +111,23 @@ export function getLatestRoomDescription(): RoomDescription {
111
111
 
112
112
  return latestRoomDescription;
113
113
  }
114
+
115
+ /**
116
+ * Helper function to detect if the game is in the state where the room index has changed to a new
117
+ * room, but the entities from the previous room are currently in the process of despawning. (At
118
+ * this point, the `POST_NEW_ROOM` callback will not have fired yet, and there will not be an entry
119
+ * in the room history array for the current room.)
120
+ *
121
+ * This function is intended to be used in the `POST_ENTITY_REMOVE` callback to detect when an
122
+ * entity is pseudo-persistent entity such as a pickup is despawning.
123
+ */
124
+ export function isLeavingRoom(): boolean {
125
+ const roomListIndex = getRoomListIndex();
126
+ const roomVisitedCount = getRoomVisitedCount();
127
+ const latestRoomDescription = getLatestRoomDescription();
128
+
129
+ return (
130
+ roomListIndex !== latestRoomDescription.roomListIndex ||
131
+ roomVisitedCount !== latestRoomDescription.roomVisitedCount
132
+ );
133
+ }