isaacscript-common 6.14.0 → 6.16.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 (131) hide show
  1. package/dist/callbacks/postGridEntityCustomCollision.d.ts +2 -0
  2. package/dist/callbacks/postGridEntityCustomCollision.d.ts.map +1 -0
  3. package/dist/callbacks/postGridEntityCustomCollision.lua +71 -0
  4. package/dist/callbacks/postGridEntityCustomRender.lua +0 -7
  5. package/dist/callbacks/postGridEntityCustomUpdate.lua +0 -7
  6. package/dist/callbacks/subscriptions/postGridEntityCustomBroken.d.ts +6 -0
  7. package/dist/callbacks/subscriptions/postGridEntityCustomBroken.d.ts.map +1 -0
  8. package/dist/callbacks/subscriptions/postGridEntityCustomBroken.lua +24 -0
  9. package/dist/callbacks/subscriptions/postGridEntityCustomCollision.d.ts +6 -0
  10. package/dist/callbacks/subscriptions/postGridEntityCustomCollision.d.ts.map +1 -0
  11. package/dist/callbacks/subscriptions/postGridEntityCustomCollision.lua +29 -0
  12. package/dist/enums/ModCallbackCustom.d.ts +96 -62
  13. package/dist/enums/ModCallbackCustom.d.ts.map +1 -1
  14. package/dist/enums/ModCallbackCustom.lua +64 -60
  15. package/dist/features/customGridEntity.d.ts +5 -1
  16. package/dist/features/customGridEntity.d.ts.map +1 -1
  17. package/dist/features/customGridEntity.lua +65 -5
  18. package/dist/functions/collectibles.d.ts +6 -2
  19. package/dist/functions/collectibles.d.ts.map +1 -1
  20. package/dist/functions/collectibles.lua +4 -2
  21. package/dist/functions/color.d.ts +11 -15
  22. package/dist/functions/color.d.ts.map +1 -1
  23. package/dist/functions/color.lua +55 -74
  24. package/dist/functions/deepCopy.d.ts.map +1 -1
  25. package/dist/functions/deepCopy.lua +22 -1
  26. package/dist/functions/gridEntities.d.ts +0 -16
  27. package/dist/functions/gridEntities.d.ts.map +1 -1
  28. package/dist/functions/gridEntities.lua +0 -19
  29. package/dist/functions/isaacAPIClass.d.ts +1 -1
  30. package/dist/functions/isaacAPIClass.d.ts.map +1 -1
  31. package/dist/functions/itemPool.d.ts +10 -0
  32. package/dist/functions/itemPool.d.ts.map +1 -0
  33. package/dist/functions/itemPool.lua +116 -0
  34. package/dist/functions/kColor.d.ts +11 -15
  35. package/dist/functions/kColor.d.ts.map +1 -1
  36. package/dist/functions/kColor.lua +42 -61
  37. package/dist/functions/mergeTests.lua +2 -2
  38. package/dist/functions/npcs.d.ts +1 -29
  39. package/dist/functions/npcs.d.ts.map +1 -1
  40. package/dist/functions/npcs.lua +0 -45
  41. package/dist/functions/projectiles.d.ts +32 -0
  42. package/dist/functions/projectiles.d.ts.map +1 -0
  43. package/dist/functions/projectiles.lua +73 -0
  44. package/dist/functions/rng.d.ts +11 -15
  45. package/dist/functions/rng.d.ts.map +1 -1
  46. package/dist/functions/rng.lua +32 -52
  47. package/dist/functions/rockAlt.d.ts +26 -6
  48. package/dist/functions/rockAlt.d.ts.map +1 -1
  49. package/dist/functions/rockAlt.lua +303 -78
  50. package/dist/functions/saveFile.d.ts +8 -7
  51. package/dist/functions/saveFile.d.ts.map +1 -1
  52. package/dist/functions/saveFile.lua +10 -96
  53. package/dist/functions/serialization.d.ts +26 -7
  54. package/dist/functions/serialization.d.ts.map +1 -1
  55. package/dist/functions/serialization.lua +51 -19
  56. package/dist/functions/table.d.ts +2 -2
  57. package/dist/functions/table.lua +2 -2
  58. package/dist/functions/trinketGive.d.ts +13 -0
  59. package/dist/functions/trinketGive.d.ts.map +1 -1
  60. package/dist/functions/trinketGive.lua +16 -0
  61. package/dist/functions/tstlClass.d.ts +1 -1
  62. package/dist/functions/tstlClass.d.ts.map +1 -1
  63. package/dist/functions/vector.d.ts +11 -15
  64. package/dist/functions/vector.d.ts.map +1 -1
  65. package/dist/functions/vector.lua +36 -55
  66. package/dist/index.d.ts +2 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.lua +16 -0
  69. package/dist/initCustomCallbacks.d.ts.map +1 -1
  70. package/dist/initCustomCallbacks.lua +3 -0
  71. package/dist/interfaces/AddCallbackParameterCustom.d.ts +4 -0
  72. package/dist/interfaces/AddCallbackParameterCustom.d.ts.map +1 -1
  73. package/dist/objects/callbackRegisterFunctions.d.ts.map +1 -1
  74. package/dist/objects/callbackRegisterFunctions.lua +6 -0
  75. package/dist/objects/isaacAPIClassTypeToFunctions.d.ts +12 -0
  76. package/dist/objects/isaacAPIClassTypeToFunctions.d.ts.map +1 -0
  77. package/dist/objects/isaacAPIClassTypeToFunctions.lua +25 -0
  78. package/dist/types/{private/IsaacAPIClass.d.ts → IsaacAPIClass.d.ts} +0 -0
  79. package/dist/types/IsaacAPIClass.d.ts.map +1 -0
  80. package/dist/types/{private/IsaacAPIClass.lua → IsaacAPIClass.lua} +0 -0
  81. package/dist/types/{private/SerializedIsaacAPIClass.d.ts → SerializedIsaacAPIClass.d.ts} +0 -0
  82. package/dist/types/SerializedIsaacAPIClass.d.ts.map +1 -0
  83. package/dist/types/{private/SerializedIsaacAPIClass.lua → SerializedIsaacAPIClass.lua} +0 -0
  84. package/dist/types/{private/TSTLClass.d.ts → TSTLClass.d.ts} +0 -0
  85. package/dist/types/TSTLClass.d.ts.map +1 -0
  86. package/dist/types/{private/TSTLClass.lua → TSTLClass.lua} +0 -0
  87. package/package.json +2 -2
  88. package/src/callbacks/postGridEntityCustomCollision.ts +74 -0
  89. package/src/callbacks/postGridEntityCustomRender.ts +1 -17
  90. package/src/callbacks/postGridEntityCustomUpdate.ts +1 -17
  91. package/src/callbacks/subscriptions/postGridEntityCustomBroken.ts +36 -0
  92. package/src/callbacks/subscriptions/postGridEntityCustomCollision.ts +43 -0
  93. package/src/enums/ModCallbackCustom.ts +38 -2
  94. package/src/features/customGridEntity.ts +76 -0
  95. package/src/functions/collectibles.ts +6 -2
  96. package/src/functions/color.ts +67 -87
  97. package/src/functions/deepCopy.ts +15 -2
  98. package/src/functions/gridEntities.ts +0 -23
  99. package/src/functions/isaacAPIClass.ts +1 -1
  100. package/src/functions/itemPool.ts +153 -0
  101. package/src/functions/kColor.ts +65 -84
  102. package/src/functions/mergeTests.ts +2 -2
  103. package/src/functions/npcs.ts +1 -58
  104. package/src/functions/projectiles.ts +78 -0
  105. package/src/functions/rng.ts +45 -65
  106. package/src/functions/rockAlt.ts +339 -60
  107. package/src/functions/saveFile.ts +13 -119
  108. package/src/functions/serialization.ts +81 -25
  109. package/src/functions/table.ts +2 -2
  110. package/src/functions/trinketGive.ts +21 -0
  111. package/src/functions/tstlClass.ts +1 -1
  112. package/src/functions/vector.ts +55 -74
  113. package/src/index.ts +2 -0
  114. package/src/initCustomCallbacks.ts +2 -0
  115. package/src/interfaces/AddCallbackParameterCustom.ts +4 -0
  116. package/src/objects/callbackRegisterFunctions.ts +6 -0
  117. package/src/objects/isaacAPIClassTypeToFunctions.ts +63 -0
  118. package/src/types/{private/IsaacAPIClass.ts → IsaacAPIClass.ts} +0 -0
  119. package/src/types/{private/SerializedIsaacAPIClass.ts → SerializedIsaacAPIClass.ts} +0 -0
  120. package/src/types/{private/TSTLClass.ts → TSTLClass.ts} +0 -0
  121. package/dist/objects/isaacAPIClassTypeToCopyFunction.d.ts +0 -6
  122. package/dist/objects/isaacAPIClassTypeToCopyFunction.d.ts.map +0 -1
  123. package/dist/objects/isaacAPIClassTypeToCopyFunction.lua +0 -13
  124. package/dist/objects/serializedIsaacAPIClassTypeToIdentityFunction.d.ts +0 -5
  125. package/dist/objects/serializedIsaacAPIClassTypeToIdentityFunction.d.ts.map +0 -1
  126. package/dist/objects/serializedIsaacAPIClassTypeToIdentityFunction.lua +0 -13
  127. package/dist/types/private/IsaacAPIClass.d.ts.map +0 -1
  128. package/dist/types/private/SerializedIsaacAPIClass.d.ts.map +0 -1
  129. package/dist/types/private/TSTLClass.d.ts.map +0 -1
  130. package/src/objects/isaacAPIClassTypeToCopyFunction.ts +0 -18
  131. package/src/objects/serializedIsaacAPIClassTypeToIdentityFunction.ts +0 -14
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TSTLClass.d.ts","sourceRoot":"","sources":["../../src/types/TSTLClass.ts"],"names":[],"mappings":";AAAA,oBAAY,SAAS,GAAG,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG;IACnD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "6.14.0",
3
+ "version": "6.16.1",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -22,6 +22,6 @@
22
22
  "main": "dist/index",
23
23
  "types": "dist/index.d.ts",
24
24
  "dependencies": {
25
- "isaac-typescript-definitions": "^3.0.35"
25
+ "isaac-typescript-definitions": "^3.1.0"
26
26
  }
27
27
  }
@@ -0,0 +1,74 @@
1
+ import { GridCollisionClass, ModCallback } from "isaac-typescript-definitions";
2
+ import { DefaultMap } from "../classes/DefaultMap";
3
+ import { ModUpgraded } from "../classes/ModUpgraded";
4
+ import { getCustomGridEntities } from "../features/customGridEntity";
5
+ import { saveDataManager } from "../features/saveDataManager/exports";
6
+ import { getCollidingEntitiesWithGridEntity } from "../functions/gridEntities";
7
+ import {
8
+ postGridEntityCustomCollisionFire,
9
+ postGridEntityCustomCollisionHasSubscriptions,
10
+ } from "./subscriptions/postGridEntityCustomCollision";
11
+
12
+ const v = {
13
+ room: {
14
+ /** Indexed by grid entity pointer hash. */
15
+ collidingEntitiesMap: new DefaultMap<PtrHash, Set<PtrHash>>(
16
+ () => new Set(),
17
+ ),
18
+ },
19
+ };
20
+
21
+ /** @internal */
22
+ export function postGridEntityCustomCollisionInit(mod: ModUpgraded): void {
23
+ saveDataManager("postGridEntityCustomCollisionInit", v, hasSubscriptions);
24
+
25
+ mod.AddCallback(ModCallback.POST_UPDATE, postUpdate); // 1
26
+ }
27
+
28
+ function hasSubscriptions() {
29
+ return postGridEntityCustomCollisionHasSubscriptions();
30
+ }
31
+
32
+ // ModCallback.POST_UPDATE (1)
33
+ function postUpdate() {
34
+ if (!hasSubscriptions()) {
35
+ return;
36
+ }
37
+
38
+ const customGridEntities = getCustomGridEntities();
39
+ for (const [gridEntity, data] of customGridEntities) {
40
+ if (gridEntity.CollisionClass === GridCollisionClass.NONE) {
41
+ continue;
42
+ }
43
+
44
+ // The following code is copied from the `POST_GRID_ENTITY_COLLISION` callback.
45
+ const gridEntityPtrHash = GetPtrHash(gridEntity);
46
+ const oldCollidingEntities =
47
+ v.room.collidingEntitiesMap.getAndSetDefault(gridEntityPtrHash);
48
+
49
+ // Check for new colliding entities.
50
+ const collidingEntities = getCollidingEntitiesWithGridEntity(gridEntity);
51
+ for (const entity of collidingEntities) {
52
+ const entityPtrHash = GetPtrHash(entity);
53
+ if (!oldCollidingEntities.has(entityPtrHash)) {
54
+ oldCollidingEntities.add(entityPtrHash);
55
+ postGridEntityCustomCollisionFire(
56
+ gridEntity,
57
+ data.gridEntityTypeCustom,
58
+ entity,
59
+ );
60
+ }
61
+ }
62
+
63
+ // Remove old colliding entities.
64
+ const collidingEntitiesPtrHashes = collidingEntities.map((entity) =>
65
+ GetPtrHash(entity),
66
+ );
67
+ const collidingEntitiesPtrHashSet = new Set(collidingEntitiesPtrHashes);
68
+ for (const oldCollidingEntityPtrHash of oldCollidingEntities.values()) {
69
+ if (!collidingEntitiesPtrHashSet.has(oldCollidingEntityPtrHash)) {
70
+ oldCollidingEntities.delete(oldCollidingEntityPtrHash);
71
+ }
72
+ }
73
+ }
74
+ }
@@ -1,29 +1,13 @@
1
- import { GridEntityType, ModCallback } from "isaac-typescript-definitions";
1
+ import { ModCallback } from "isaac-typescript-definitions";
2
2
  import { ModUpgraded } from "../classes/ModUpgraded";
3
3
  import { getCustomGridEntities } from "../features/customGridEntity";
4
- import { saveDataManager } from "../features/saveDataManager/exports";
5
4
  import {
6
5
  postGridEntityCustomRenderFire,
7
6
  postGridEntityCustomRenderHasSubscriptions,
8
7
  } from "./subscriptions/postGridEntityCustomRender";
9
8
 
10
- type GridEntityTuple = [
11
- gridEntityType: GridEntityType,
12
- gridEntityVariant: int,
13
- state: int,
14
- ];
15
-
16
- const v = {
17
- room: {
18
- /** Indexed by grid index. */
19
- initializedGridEntities: new Map<int, GridEntityTuple>(),
20
- },
21
- };
22
-
23
9
  /** @internal */
24
10
  export function postGridEntityCustomRenderInit(mod: ModUpgraded): void {
25
- saveDataManager("postGridEntityCustomRender", v, hasSubscriptions);
26
-
27
11
  mod.AddCallback(ModCallback.POST_RENDER, postRender); // 2
28
12
  }
29
13
 
@@ -1,29 +1,13 @@
1
- import { GridEntityType, ModCallback } from "isaac-typescript-definitions";
1
+ import { ModCallback } from "isaac-typescript-definitions";
2
2
  import { ModUpgraded } from "../classes/ModUpgraded";
3
3
  import { getCustomGridEntities } from "../features/customGridEntity";
4
- import { saveDataManager } from "../features/saveDataManager/exports";
5
4
  import {
6
5
  postGridEntityCustomUpdateFire,
7
6
  postGridEntityCustomUpdateHasSubscriptions,
8
7
  } from "./subscriptions/postGridEntityCustomUpdate";
9
8
 
10
- type GridEntityTuple = [
11
- gridEntityType: GridEntityType,
12
- gridEntityVariant: int,
13
- state: int,
14
- ];
15
-
16
- const v = {
17
- room: {
18
- /** Indexed by grid index. */
19
- initializedGridEntities: new Map<int, GridEntityTuple>(),
20
- },
21
- };
22
-
23
9
  /** @internal */
24
10
  export function postGridEntityCustomUpdateInit(mod: ModUpgraded): void {
25
- saveDataManager("postGridEntityCustomUpdate", v, hasSubscriptions);
26
-
27
11
  mod.AddCallback(ModCallback.POST_UPDATE, postUpdate); // 1
28
12
  }
29
13
 
@@ -0,0 +1,36 @@
1
+ import { GridEntityType } from "isaac-typescript-definitions";
2
+
3
+ export type PostGridEntityCustomBrokenRegisterParameters = [
4
+ callback: (
5
+ gridEntity: GridEntity,
6
+ gridEntityTypeCustom: GridEntityType,
7
+ ) => void,
8
+ gridEntityTypeCustom?: GridEntityType,
9
+ ];
10
+
11
+ const subscriptions: PostGridEntityCustomBrokenRegisterParameters[] = [];
12
+
13
+ /** @internal */
14
+ export function postGridEntityCustomBrokenRegister(
15
+ ...args: PostGridEntityCustomBrokenRegisterParameters
16
+ ): void {
17
+ subscriptions.push(args);
18
+ }
19
+
20
+ /** @internal */
21
+ export function postGridEntityCustomBrokenFire(
22
+ gridEntity: GridEntity,
23
+ gridEntityTypeCustom: GridEntityType,
24
+ ): void {
25
+ for (const [callback, callbackGridEntityTypeCustom] of subscriptions) {
26
+ // Handle the optional 2nd callback argument.
27
+ if (
28
+ callbackGridEntityTypeCustom !== undefined &&
29
+ callbackGridEntityTypeCustom !== gridEntityTypeCustom
30
+ ) {
31
+ continue;
32
+ }
33
+
34
+ callback(gridEntity, gridEntityTypeCustom);
35
+ }
36
+ }
@@ -0,0 +1,43 @@
1
+ import { GridEntityType } from "isaac-typescript-definitions";
2
+
3
+ export type PostGridEntityCustomCollisionRegisterParameters = [
4
+ callback: (
5
+ gridEntity: GridEntity,
6
+ gridEntityTypeCustom: GridEntityType,
7
+ entity: Entity,
8
+ ) => void,
9
+ gridEntityTypeCustom?: GridEntityType,
10
+ ];
11
+
12
+ const subscriptions: PostGridEntityCustomCollisionRegisterParameters[] = [];
13
+
14
+ /** @internal */
15
+ export function postGridEntityCustomCollisionHasSubscriptions(): boolean {
16
+ return subscriptions.length > 0;
17
+ }
18
+
19
+ /** @internal */
20
+ export function postGridEntityCustomCollisionRegister(
21
+ ...args: PostGridEntityCustomCollisionRegisterParameters
22
+ ): void {
23
+ subscriptions.push(args);
24
+ }
25
+
26
+ /** @internal */
27
+ export function postGridEntityCustomCollisionFire(
28
+ gridEntity: GridEntity,
29
+ gridEntityTypeCustom: GridEntityType,
30
+ entity: Entity,
31
+ ): void {
32
+ for (const [callback, callbackGridEntityTypeCustom] of subscriptions) {
33
+ // Handle the optional 2nd callback argument.
34
+ if (
35
+ callbackGridEntityTypeCustom !== undefined &&
36
+ callbackGridEntityTypeCustom !== gridEntityTypeCustom
37
+ ) {
38
+ continue;
39
+ }
40
+
41
+ callback(gridEntity, gridEntityTypeCustom, entity);
42
+ }
43
+ }
@@ -363,6 +363,42 @@ export enum ModCallbackCustom {
363
363
  */
364
364
  POST_GRID_ENTITY_COLLISION,
365
365
 
366
+ /**
367
+ * Fires from the `POST_UPDATE` callback when a grid entity created with the
368
+ * `spawnCustomGridEntity` helper function is hit by an explosion.
369
+ *
370
+ * In most cases, you will want to remove the grid entity inside of this callback in order to
371
+ * prevent further "broken" callbacks from firing. (This would not be the case if you were trying
372
+ * to emulate a super tinted rock that takes multiple explosions to destroy, for example.)
373
+ *
374
+ * When registering the callback, takes an optional second argument that will make the callback
375
+ * only fire if it matches the `GridEntityType` provided.
376
+ *
377
+ * ```ts
378
+ * function postGridEntityCustomBroken(
379
+ * gridEntity: GridEntity,
380
+ * gridEntityTypeCustom: GridEntityType,
381
+ * ): void {}
382
+ * ```
383
+ */
384
+ POST_GRID_ENTITY_CUSTOM_BROKEN,
385
+
386
+ /**
387
+ * Fires from the `POST_UPDATE` callback a new entity collides with a grid entity created with the
388
+ * `spawnCustomGridEntity` helper function.
389
+ *
390
+ * When registering the callback, takes an optional second argument that will make the callback
391
+ * only fire if it matches the `GridEntityType` provided.
392
+ *
393
+ * ```ts
394
+ * function postGridEntityCustomRender(
395
+ * gridEntity: GridEntity,
396
+ * gridEntityTypeCustom: GridEntityType,
397
+ * ): void {}
398
+ * ```
399
+ */
400
+ POST_GRID_ENTITY_CUSTOM_COLLISION,
401
+
366
402
  /**
367
403
  * Fires from the `POST_RENDER` callback on every frame that a grid entity created with the
368
404
  * `spawnCustomGridEntity` helper function exists.
@@ -371,7 +407,7 @@ export enum ModCallbackCustom {
371
407
  * only fire if it matches the `GridEntityType` provided.
372
408
  *
373
409
  * ```ts
374
- * function postGridEntityRenderCustom(
410
+ * function postGridEntityCustomRender(
375
411
  * gridEntity: GridEntity,
376
412
  * gridEntityTypeCustom: GridEntityType,
377
413
  * ): void {}
@@ -387,7 +423,7 @@ export enum ModCallbackCustom {
387
423
  * only fire if it matches the `GridEntityType` provided.
388
424
  *
389
425
  * ```ts
390
- * function postGridEntityUpdateCustom(
426
+ * function postGridEntityCustomUpdate(
391
427
  * gridEntity: GridEntity,
392
428
  * gridEntityTypeCustom: GridEntityType,
393
429
  * ): void {}
@@ -1,17 +1,22 @@
1
1
  import {
2
2
  ActiveSlot,
3
3
  CollectibleType,
4
+ DamageFlag,
5
+ EntityType,
4
6
  GridCollisionClass,
5
7
  GridEntityType,
6
8
  ModCallback,
7
9
  UseFlag,
8
10
  } from "isaac-typescript-definitions";
9
11
  import { game } from "../cachedClasses";
12
+ import { postGridEntityCustomBrokenFire } from "../callbacks/subscriptions/postGridEntityCustomBroken";
10
13
  import { DefaultMap } from "../classes/DefaultMap";
11
14
  import { ModUpgraded } from "../classes/ModUpgraded";
12
15
  import { DecorationVariant } from "../enums/DecorationVariant";
13
16
  import { ModCallbackCustom } from "../enums/ModCallbackCustom";
14
17
  import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
18
+ import { spawnNPC } from "../functions/entitiesSpecific";
19
+ import { hasFlag } from "../functions/flag";
15
20
  import {
16
21
  removeGridEntity,
17
22
  spawnGridEntityWithVariant,
@@ -33,6 +38,7 @@ const v = {
33
38
  },
34
39
 
35
40
  room: {
41
+ dummyPtrHashes: new Set<PtrHash>(),
36
42
  manuallyUsingShovel: false,
37
43
  },
38
44
  };
@@ -41,6 +47,12 @@ const v = {
41
47
  export function customGridEntityInit(mod: ModUpgraded): void {
42
48
  saveDataManager(FEATURE_NAME, v);
43
49
 
50
+ mod.AddCallback(
51
+ ModCallback.ENTITY_TAKE_DMG,
52
+ entityTakeDmgDummy,
53
+ EntityType.DUMMY,
54
+ ); // 11
55
+
44
56
  mod.AddCallback(
45
57
  ModCallback.PRE_USE_ITEM,
46
58
  preUseItemWeNeedToGoDeeper,
@@ -53,6 +65,51 @@ export function customGridEntityInit(mod: ModUpgraded): void {
53
65
  );
54
66
  }
55
67
 
68
+ // ModCallback.ENTITY_TAKE_DMG (11)
69
+ // EntityType.DUMMY (964)
70
+ function entityTakeDmgDummy(
71
+ tookDamage: Entity,
72
+ _damageAmount: float,
73
+ damageFlags: BitFlags<DamageFlag>,
74
+ _damageSource: EntityRef,
75
+ _damageCountdownFrames: int,
76
+ ): boolean | undefined {
77
+ const ptrHash = GetPtrHash(tookDamage);
78
+ if (!v.room.dummyPtrHashes.has(ptrHash)) {
79
+ return undefined;
80
+ }
81
+
82
+ if (!hasFlag(damageFlags, DamageFlag.EXPLOSION)) {
83
+ return false;
84
+ }
85
+
86
+ const room = game.GetRoom();
87
+ const roomListIndex = getRoomListIndex();
88
+ const roomCustomGridEntities = v.level.customGridEntities.get(roomListIndex);
89
+ if (roomCustomGridEntities === undefined) {
90
+ return false;
91
+ }
92
+
93
+ const gridIndex = room.GetGridIndex(tookDamage.Position);
94
+ const data = roomCustomGridEntities.get(gridIndex);
95
+ if (data === undefined) {
96
+ return false;
97
+ }
98
+
99
+ const gridEntity = room.GetGridEntity(gridIndex);
100
+ if (gridEntity === undefined) {
101
+ error(
102
+ `Failed to get the grid entity for a custom grid entity that broke at grid index: ${gridIndex}`,
103
+ );
104
+ }
105
+
106
+ postGridEntityCustomBrokenFire(gridEntity, data.gridEntityTypeCustom);
107
+
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
+ return false;
111
+ }
112
+
56
113
  // ModCallback.PRE_USE_ITEM (23)
57
114
  // CollectibleType.WE_NEED_TO_GO_DEEPER (84)
58
115
  function preUseItemWeNeedToGoDeeper(
@@ -161,6 +218,10 @@ function postNewRoomReordered() {
161
218
  * @param defaultAnimation Optional. The name of the animation to play after the sprite is
162
219
  * initialized and after the player re-enters a room with this grid entity
163
220
  * in it. If not specified, the default animation in the anm2 will be used.
221
+ * @param breakable Optional. Whether or not an explosion will be able to break this grid entity.
222
+ * False by default. Use the `POST_GRID_ENTITY_CUSTOM_BROKEN` callback to detect
223
+ * when it breaks. Due to technical limitations, you can only set the grid entity
224
+ * to be breakable if it has a collision class.
164
225
  */
165
226
  export function spawnCustomGridEntity(
166
227
  gridEntityTypeCustom: GridEntityType,
@@ -168,9 +229,16 @@ export function spawnCustomGridEntity(
168
229
  gridCollisionClass: GridCollisionClass,
169
230
  anm2Path: string,
170
231
  defaultAnimation?: string,
232
+ breakable = false,
171
233
  ): GridEntity {
172
234
  errorIfFeaturesNotInitialized(FEATURE_NAME);
173
235
 
236
+ if (breakable && gridCollisionClass === GridCollisionClass.NONE) {
237
+ error(
238
+ "Failed to spawn a custom grid entity because it is not possible to have breakable custom grid entities with a collision class of: GridCollisionClass.NONE (0)",
239
+ );
240
+ }
241
+
174
242
  const room = game.GetRoom();
175
243
  const roomListIndex = getRoomListIndex();
176
244
  const gridIndex = isVector(gridIndexOrPosition)
@@ -215,6 +283,14 @@ export function spawnCustomGridEntity(
215
283
  v.level.customGridEntities.getAndSetDefault(roomListIndex);
216
284
  roomCustomGridEntities.set(gridIndex, customGridEntityData);
217
285
 
286
+ // We check to see if an explosion touches a custom grid entity by spawning a Dummy on top, and
287
+ // the monitoring for explosions in the `ENTITY_TAKE_DMG` callback.
288
+ if (breakable) {
289
+ const position = room.GetGridPosition(gridIndex);
290
+ const dummy = spawnNPC(EntityType.DUMMY, 0, 0, position);
291
+ dummy.Visible = false;
292
+ }
293
+
218
294
  return decoration;
219
295
  }
220
296
 
@@ -323,6 +323,10 @@ export function getCollectibleName(collectibleType: CollectibleType): string {
323
323
  return DEFAULT_COLLECTIBLE_NAME;
324
324
  }
325
325
 
326
+ /**
327
+ * Helper function to get the "pedestal type" of a collectible. For example, it might be sitting on
328
+ * top of a broken Blood Donation Machine, or it might be sitting on top of an opened Spiked Chest.
329
+ */
326
330
  export function getCollectiblePedestalType(
327
331
  collectible: EntityPickup,
328
332
  ): CollectiblePedestalType {
@@ -338,8 +342,8 @@ export function getCollectiblePedestalType(
338
342
  }
339
343
 
340
344
  /**
341
- * Helper function to get the path to a collectible's quality. Returns 0 if the provided collectible
342
- * type was not valid.
345
+ * Helper function to get a collectible's quality. For example, Mom's Knife has a quality of 4.
346
+ * Returns 0 if the provided collectible type was not valid.
343
347
  */
344
348
  export function getCollectibleQuality(collectibleType: CollectibleType): int {
345
349
  const itemConfigItem = itemConfig.GetCollectible(collectibleType);
@@ -1,21 +1,14 @@
1
1
  import { SerializationBrand } from "../enums/private/SerializationBrand";
2
- import { SerializationType } from "../enums/SerializationType";
3
2
  import { isaacAPIClassEquals, isIsaacAPIClassOfType } from "./isaacAPIClass";
4
3
  import { getRandom } from "./random";
5
4
  import { getRandomSeed, isRNG, newRNG } from "./rng";
6
5
  import { copyValuesToTable, getNumbersFromTable, tableHasKeys } from "./table";
7
6
  import { isTable } from "./types";
8
7
 
9
- type SerializedColor = LuaMap<string, unknown> & {
8
+ export type SerializedColor = LuaMap<string, unknown> & {
10
9
  readonly __serializedColorBrand: symbol;
11
10
  };
12
11
 
13
- interface CopyColorReturn {
14
- [SerializationType.NONE]: Color;
15
- [SerializationType.SERIALIZE]: SerializedColor;
16
- [SerializationType.DESERIALIZE]: Color;
17
- }
18
-
19
12
  const KEYS = ["R", "G", "B", "A", "RO", "GO", "BO"];
20
13
  const OBJECT_NAME = "Color";
21
14
 
@@ -23,88 +16,59 @@ export function colorEquals(color1: Color, color2: Color): boolean {
23
16
  return isaacAPIClassEquals(color1, color2, KEYS);
24
17
  }
25
18
 
19
+ /** Helper function to copy a `Color` Isaac API class. */
20
+ export function copyColor(color: Color): Color {
21
+ if (!isColor(color)) {
22
+ error(
23
+ `Failed to copy a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
24
+ );
25
+ }
26
+
27
+ return Color(
28
+ color.R,
29
+ color.G,
30
+ color.B,
31
+ color.A,
32
+ color.RO,
33
+ color.GO,
34
+ color.BO,
35
+ );
36
+ }
37
+
26
38
  /**
27
- * Helper function to copy a `Color` object.
28
- *
29
- * @param color The Color object to copy. In the case of deserialization, this will actually be a
30
- * Lua table instead of an instantiated Color class.
31
- * @param serializationType Default is `SerializationType.NONE`.
39
+ * Helper function to convert a `SerializedColor` object to a normal `Color` object. (This is used
40
+ * by the save data manager when reading data from the "save#.dat" file.)
32
41
  */
33
- export function copyColor<
34
- C extends Color | SerializedColor,
35
- S extends SerializationType,
36
- >(color: C, serializationType: S): CopyColorReturn[S];
37
- export function copyColor<C extends Color | SerializedColor>(
38
- color: C,
39
- ): CopyColorReturn[SerializationType.NONE];
40
- export function copyColor(
41
- color: Color | SerializedColor,
42
- serializationType = SerializationType.NONE,
43
- ): CopyColorReturn[keyof CopyColorReturn] {
44
- switch (serializationType) {
45
- case SerializationType.NONE: {
46
- if (!isColor(color)) {
47
- error(
48
- `Failed to copy a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
49
- );
50
- }
51
-
52
- return Color(
53
- color.R,
54
- color.G,
55
- color.B,
56
- color.A,
57
- color.RO,
58
- color.GO,
59
- color.BO,
60
- );
61
- }
62
-
63
- case SerializationType.SERIALIZE: {
64
- if (!isColor(color)) {
65
- error(
66
- `Failed to serialize a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
67
- );
68
- }
69
-
70
- const colorTable = new LuaMap<string, unknown>();
71
- copyValuesToTable(color, KEYS, colorTable);
72
- colorTable.set(SerializationBrand.COLOR, "");
73
- return colorTable as SerializedColor;
74
- }
75
-
76
- case SerializationType.DESERIALIZE: {
77
- if (!isTable(color)) {
78
- error(
79
- `Failed to deserialize a ${OBJECT_NAME} object since the provided object was not a Lua table.`,
80
- );
81
- }
82
-
83
- const [r, g, b, a, ro, go, bo] = getNumbersFromTable(
84
- color as LuaMap<string, unknown>,
85
- OBJECT_NAME,
86
- ...KEYS,
87
- );
88
-
89
- if (r === undefined) {
90
- error(
91
- `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: r`,
92
- );
93
- }
94
- if (g === undefined) {
95
- error(
96
- `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: g`,
97
- );
98
- }
99
- if (b === undefined) {
100
- error(
101
- `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: b`,
102
- );
103
- }
104
-
105
- return Color(r, g, b, a, ro, go, bo);
106
- }
42
+ export function deserializeColor(color: SerializedColor): Color {
43
+ if (!isTable(color)) {
44
+ error(
45
+ `Failed to deserialize a ${OBJECT_NAME} object since the provided object was not a Lua table.`,
46
+ );
47
+ }
48
+
49
+ const [r, g, b, a, ro, go, bo] = getNumbersFromTable(
50
+ color as LuaMap<string, unknown>,
51
+ OBJECT_NAME,
52
+ ...KEYS,
53
+ );
54
+
55
+ if (r === undefined) {
56
+ error(
57
+ `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: R`,
58
+ );
59
+ }
60
+ if (g === undefined) {
61
+ error(
62
+ `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: G`,
63
+ );
64
+ }
65
+ if (b === undefined) {
66
+ error(
67
+ `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: B`,
68
+ );
107
69
  }
70
+
71
+ return Color(r, g, b, a, ro, go, bo);
108
72
  }
109
73
 
110
74
  /**
@@ -143,3 +107,19 @@ export function isSerializedColor(object: unknown): object is SerializedColor {
143
107
 
144
108
  return tableHasKeys(object, ...KEYS) && object.has(SerializationBrand.COLOR);
145
109
  }
110
+ /**
111
+ * Helper function to convert a `Color` object to a `SerializedColor` object. (This is used by the
112
+ * save data manager when writing data from the "save#.dat" file.)
113
+ */
114
+ export function serializeColor(color: Color): SerializedColor {
115
+ if (!isColor(color)) {
116
+ error(
117
+ `Failed to serialize a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
118
+ );
119
+ }
120
+
121
+ const colorTable = new LuaMap<string, unknown>();
122
+ copyValuesToTable(color, KEYS, colorTable);
123
+ colorTable.set(SerializationBrand.COLOR, "");
124
+ return colorTable as SerializedColor;
125
+ }
@@ -4,7 +4,7 @@ import { SerializationBrand } from "../enums/private/SerializationBrand";
4
4
  import { SerializationType } from "../enums/SerializationType";
5
5
  import { SAVE_DATA_MANAGER_DEBUG } from "../features/saveDataManager/saveDataManagerConstants";
6
6
  import { isSerializationBrand } from "../features/saveDataManager/serializationBrands";
7
- import { TSTLClass } from "../types/private/TSTLClass";
7
+ import { TSTLClass } from "../types/TSTLClass";
8
8
  import { isArray } from "./array";
9
9
  import { getEnumValues } from "./enums";
10
10
  import { getIsaacAPIClassName } from "./isaacAPIClass";
@@ -13,6 +13,7 @@ import {
13
13
  copyIsaacAPIClass,
14
14
  deserializeIsaacAPIClass,
15
15
  isSerializedIsaacAPIClass,
16
+ serializeIsaacAPIClass,
16
17
  } from "./serialization";
17
18
  import {
18
19
  getTSTLClassName,
@@ -664,5 +665,17 @@ function deepCopyUserdata(
664
665
  );
665
666
  }
666
667
 
667
- return copyIsaacAPIClass(value, serializationType);
668
+ switch (serializationType) {
669
+ case SerializationType.NONE: {
670
+ return copyIsaacAPIClass(value);
671
+ }
672
+
673
+ case SerializationType.SERIALIZE: {
674
+ return serializeIsaacAPIClass(value);
675
+ }
676
+
677
+ case SerializationType.DESERIALIZE: {
678
+ return deserializeIsaacAPIClass(value);
679
+ }
680
+ }
668
681
  }