isaacscript-common 13.3.3 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/index.d.ts +586 -407
  2. package/dist/isaacscript-common.lua +15849 -15070
  3. package/dist/src/callbacks/postAmbush.d.ts.map +1 -1
  4. package/dist/src/callbacks/postAmbush.lua +7 -12
  5. package/dist/src/callbacks/postBombExploded.lua +3 -3
  6. package/dist/src/callbacks/postRoomClearChanged.d.ts.map +1 -1
  7. package/dist/src/callbacks/postRoomClearChanged.lua +3 -5
  8. package/dist/src/callbacks/subscriptions/{postBoneExploded.d.ts → postBombExploded.d.ts} +1 -1
  9. package/dist/src/callbacks/subscriptions/{postBoneExploded.d.ts.map → postBombExploded.d.ts.map} +1 -1
  10. package/dist/src/callbacks/subscriptions/{postBoneExploded.lua → postBombExploded.lua} +0 -0
  11. package/dist/src/callbacks/subscriptions/postCollectibleEmpty.d.ts +1 -1
  12. package/dist/src/callbacks/subscriptions/postCollectibleEmpty.d.ts.map +1 -1
  13. package/dist/src/callbacks/subscriptions/postCollectibleInitFirst.d.ts +1 -1
  14. package/dist/src/callbacks/subscriptions/postCollectibleInitFirst.d.ts.map +1 -1
  15. package/dist/src/callbacks/subscriptions/postCursedTeleport.d.ts +4 -2
  16. package/dist/src/callbacks/subscriptions/postCursedTeleport.d.ts.map +1 -1
  17. package/dist/src/callbacks/subscriptions/postCursedTeleport.lua +13 -1
  18. package/dist/src/callbacks/subscriptions/postHolyMantleRemoved.d.ts.map +1 -1
  19. package/dist/src/callbacks/subscriptions/postHolyMantleRemoved.lua +2 -2
  20. package/dist/src/callbacks/subscriptions/postPEffectUpdateReordered.d.ts.map +1 -1
  21. package/dist/src/callbacks/subscriptions/postPEffectUpdateReordered.lua +2 -2
  22. package/dist/src/classes/ModUpgraded.d.ts +18 -10
  23. package/dist/src/classes/ModUpgraded.d.ts.map +1 -1
  24. package/dist/src/classes/ModUpgraded.lua +105 -16
  25. package/dist/src/classes/callbacks/PostAmbushFinished.d.ts +12 -0
  26. package/dist/src/classes/callbacks/PostAmbushFinished.d.ts.map +1 -0
  27. package/dist/src/classes/callbacks/PostAmbushFinished.lua +37 -0
  28. package/dist/src/classes/callbacks/PostAmbushStarted.d.ts +12 -0
  29. package/dist/src/classes/callbacks/PostAmbushStarted.d.ts.map +1 -0
  30. package/dist/src/classes/callbacks/PostAmbushStarted.lua +37 -0
  31. package/dist/src/classes/callbacks/PostBombExploded.d.ts +7 -0
  32. package/dist/src/classes/callbacks/PostBombExploded.d.ts.map +1 -0
  33. package/dist/src/classes/callbacks/PostBombExploded.lua +24 -0
  34. package/dist/src/classes/callbacks/PostBombInitLate.d.ts +12 -0
  35. package/dist/src/classes/callbacks/PostBombInitLate.d.ts.map +1 -0
  36. package/dist/src/classes/callbacks/PostBombInitLate.lua +27 -0
  37. package/dist/src/classes/callbacks/PostBoneSwing.d.ts +15 -0
  38. package/dist/src/classes/callbacks/PostBoneSwing.d.ts.map +1 -0
  39. package/dist/src/classes/callbacks/PostBoneSwing.lua +43 -0
  40. package/dist/src/classes/callbacks/PostCollectibleEmpty.d.ts +17 -0
  41. package/dist/src/classes/callbacks/PostCollectibleEmpty.d.ts.map +1 -0
  42. package/dist/src/classes/callbacks/PostCollectibleEmpty.lua +47 -0
  43. package/dist/src/classes/callbacks/PostCollectibleInitFirst.d.ts +13 -0
  44. package/dist/src/classes/callbacks/PostCollectibleInitFirst.d.ts.map +1 -0
  45. package/dist/src/classes/callbacks/PostCollectibleInitFirst.lua +32 -0
  46. package/dist/src/classes/callbacks/PostCursedTeleport.d.ts +21 -0
  47. package/dist/src/classes/callbacks/PostCursedTeleport.d.ts.map +1 -0
  48. package/dist/src/classes/callbacks/PostCursedTeleport.lua +113 -0
  49. package/dist/src/classes/callbacks/PostKnifeInitLate.d.ts +12 -0
  50. package/dist/src/classes/callbacks/PostKnifeInitLate.d.ts.map +1 -0
  51. package/dist/src/classes/callbacks/PostKnifeInitLate.lua +27 -0
  52. package/dist/src/classes/callbacks/PostNewRoomEarly.d.ts +14 -0
  53. package/dist/src/classes/callbacks/PostNewRoomEarly.d.ts.map +1 -0
  54. package/dist/src/classes/callbacks/PostNewRoomEarly.lua +65 -0
  55. package/dist/src/classes/callbacks/PostPitRender.d.ts +7 -0
  56. package/dist/src/classes/callbacks/PostPitRender.d.ts.map +1 -0
  57. package/dist/src/classes/callbacks/PostPitRender.lua +24 -0
  58. package/dist/src/classes/callbacks/PostRoomClearChanged.d.ts +13 -0
  59. package/dist/src/classes/callbacks/PostRoomClearChanged.d.ts.map +1 -0
  60. package/dist/src/classes/callbacks/PostRoomClearChanged.lua +33 -0
  61. package/dist/src/classes/callbacks/PostSpikesRender.d.ts +7 -0
  62. package/dist/src/classes/callbacks/PostSpikesRender.d.ts.map +1 -0
  63. package/dist/src/classes/callbacks/PostSpikesRender.lua +24 -0
  64. package/dist/src/classes/callbacks/validation/CustomCallbackAmbush.d.ts +10 -0
  65. package/dist/src/classes/callbacks/validation/CustomCallbackAmbush.d.ts.map +1 -0
  66. package/dist/src/classes/callbacks/validation/CustomCallbackAmbush.lua +19 -0
  67. package/dist/src/classes/callbacks/validation/CustomCallbackBomb.d.ts +10 -0
  68. package/dist/src/classes/callbacks/validation/CustomCallbackBomb.d.ts.map +1 -0
  69. package/dist/src/classes/callbacks/validation/CustomCallbackBomb.lua +19 -0
  70. package/dist/src/classes/callbacks/validation/CustomCallbackCollectible.d.ts +10 -0
  71. package/dist/src/classes/callbacks/validation/CustomCallbackCollectible.d.ts.map +1 -0
  72. package/dist/src/classes/callbacks/validation/CustomCallbackCollectible.lua +19 -0
  73. package/dist/src/classes/callbacks/validation/CustomCallbackKnife.d.ts +10 -0
  74. package/dist/src/classes/callbacks/validation/CustomCallbackKnife.d.ts.map +1 -0
  75. package/dist/src/classes/callbacks/validation/CustomCallbackKnife.lua +19 -0
  76. package/dist/src/classes/callbacks/validation/CustomCallbackPit.d.ts +10 -0
  77. package/dist/src/classes/callbacks/validation/CustomCallbackPit.d.ts.map +1 -0
  78. package/dist/src/classes/callbacks/validation/CustomCallbackPit.lua +20 -0
  79. package/dist/src/classes/callbacks/validation/CustomCallbackPlayer.d.ts +10 -0
  80. package/dist/src/classes/callbacks/validation/CustomCallbackPlayer.d.ts.map +1 -0
  81. package/dist/src/classes/callbacks/validation/CustomCallbackPlayer.lua +23 -0
  82. package/dist/src/classes/callbacks/validation/CustomCallbackSpikes.d.ts +10 -0
  83. package/dist/src/classes/callbacks/validation/CustomCallbackSpikes.d.ts.map +1 -0
  84. package/dist/src/classes/callbacks/validation/CustomCallbackSpikes.lua +20 -0
  85. package/dist/src/classes/private/CustomCallback.d.ts +32 -0
  86. package/dist/src/classes/private/CustomCallback.d.ts.map +1 -0
  87. package/dist/src/classes/private/CustomCallback.lua +53 -0
  88. package/dist/src/core/upgradeMod.d.ts.map +1 -1
  89. package/dist/src/core/upgradeMod.lua +16 -0
  90. package/dist/src/enums/IsaacScriptCommonFeature.d.ts +35 -0
  91. package/dist/src/enums/IsaacScriptCommonFeature.d.ts.map +1 -0
  92. package/dist/src/enums/IsaacScriptCommonFeature.lua +35 -0
  93. package/dist/src/enums/LadderSubTypeCustom.d.ts +17 -0
  94. package/dist/src/enums/LadderSubTypeCustom.d.ts.map +1 -0
  95. package/dist/src/enums/LadderSubTypeCustom.lua +19 -0
  96. package/dist/src/enums/ModCallbackCustom.d.ts +399 -327
  97. package/dist/src/enums/ModCallbackCustom.d.ts.map +1 -1
  98. package/dist/src/enums/ModCallbackCustom.lua +85 -87
  99. package/dist/src/enums/ModCallbackCustom2.d.ts +17 -0
  100. package/dist/src/enums/ModCallbackCustom2.d.ts.map +1 -0
  101. package/dist/src/enums/ModCallbackCustom2.lua +30 -0
  102. package/dist/src/features/{setHotkey.d.ts → customHotkeys.d.ts} +1 -1
  103. package/dist/src/features/customHotkeys.d.ts.map +1 -0
  104. package/dist/src/features/{setHotkey.lua → customHotkeys.lua} +2 -2
  105. package/dist/src/features/customPickup.d.ts.map +1 -1
  106. package/dist/src/features/customPickup.lua +6 -2
  107. package/dist/src/features/customStage/backdrop.d.ts.map +1 -1
  108. package/dist/src/features/customStage/backdrop.lua +3 -1
  109. package/dist/src/features/customStage/shadows.d.ts.map +1 -1
  110. package/dist/src/features/customStage/shadows.lua +3 -1
  111. package/dist/src/features/customTrapdoor/init.lua +1 -7
  112. package/dist/src/features/firstLast.d.ts.map +1 -1
  113. package/dist/src/features/firstLast.lua +3 -3
  114. package/dist/src/features/saveDataManager/main.d.ts +5 -2
  115. package/dist/src/features/saveDataManager/main.d.ts.map +1 -1
  116. package/dist/src/features/saveDataManager/main.lua +3 -5
  117. package/dist/src/functions/ambush.d.ts +6 -0
  118. package/dist/src/functions/ambush.d.ts.map +1 -1
  119. package/dist/src/functions/ambush.lua +31 -0
  120. package/dist/src/functions/minimap.d.ts +4 -0
  121. package/dist/src/functions/minimap.d.ts.map +1 -1
  122. package/dist/src/functions/minimap.lua +4 -0
  123. package/dist/src/functions/roomTransition.d.ts +3 -4
  124. package/dist/src/functions/roomTransition.d.ts.map +1 -1
  125. package/dist/src/functions/roomTransition.lua +4 -32
  126. package/dist/src/functions/spawnCollectible.d.ts +24 -5
  127. package/dist/src/functions/spawnCollectible.d.ts.map +1 -1
  128. package/dist/src/functions/spawnCollectible.lua +44 -4
  129. package/dist/src/functions/utils.d.ts +7 -2
  130. package/dist/src/functions/utils.d.ts.map +1 -1
  131. package/dist/src/functions/utils.lua +7 -2
  132. package/dist/src/index.d.ts +4 -2
  133. package/dist/src/index.d.ts.map +1 -1
  134. package/dist/src/index.lua +26 -10
  135. package/dist/src/initCustomCallbacks.d.ts.map +1 -1
  136. package/dist/src/initCustomCallbacks.lua +0 -3
  137. package/dist/src/initFeatures.lua +3 -3
  138. package/dist/src/interfaces/private/{AddCallbackParameterCustom.d.ts → AddCallbackParametersCustom.d.ts} +4 -6
  139. package/dist/src/interfaces/private/AddCallbackParametersCustom.d.ts.map +1 -0
  140. package/dist/src/interfaces/private/{AddCallbackParameterCustom.lua → AddCallbackParametersCustom.lua} +0 -0
  141. package/dist/src/interfaces/private/AddCallbackParametersCustom2.d.ts +55 -0
  142. package/dist/src/interfaces/private/AddCallbackParametersCustom2.d.ts.map +1 -0
  143. package/dist/src/interfaces/private/AddCallbackParametersCustom2.lua +4 -0
  144. package/dist/src/objects/callbackRegisterFunctions.d.ts +2 -2
  145. package/dist/src/objects/callbackRegisterFunctions.d.ts.map +1 -1
  146. package/dist/src/objects/callbackRegisterFunctions.lua +2 -5
  147. package/dist/src/types/private/AllButFirst.d.ts +5 -0
  148. package/dist/src/types/private/AllButFirst.d.ts.map +1 -0
  149. package/dist/src/types/private/AllButFirst.lua +2 -0
  150. package/dist/src/types/private/CallbackTuple.d.ts +20 -0
  151. package/dist/src/types/private/CallbackTuple.d.ts.map +1 -0
  152. package/dist/src/types/private/CallbackTuple.lua +2 -0
  153. package/dist/src/types/private/MatchingCallbackCustom.d.ts +14 -0
  154. package/dist/src/types/private/MatchingCallbackCustom.d.ts.map +1 -0
  155. package/dist/src/types/private/MatchingCallbackCustom.lua +2 -0
  156. package/package.json +2 -2
  157. package/src/callbacks/postAmbush.ts +7 -14
  158. package/src/callbacks/postBombExploded.ts +1 -1
  159. package/src/callbacks/postBoneSwing.ts +2 -1
  160. package/src/callbacks/postCollectibleEmpty.ts +2 -0
  161. package/src/callbacks/postCollectibleInitFirst.ts +2 -0
  162. package/src/callbacks/postNewRoomEarly.ts +1 -1
  163. package/src/callbacks/postRoomClearChanged.ts +3 -7
  164. package/src/callbacks/subscriptions/{postBoneExploded.ts → postBombExploded.ts} +0 -0
  165. package/src/callbacks/subscriptions/postCollectibleEmpty.ts +1 -1
  166. package/src/callbacks/subscriptions/postCollectibleInitFirst.ts +1 -1
  167. package/src/callbacks/subscriptions/postCursedTeleport.ts +24 -1
  168. package/src/callbacks/subscriptions/postHolyMantleRemoved.ts +9 -2
  169. package/src/callbacks/subscriptions/postPEffectUpdateReordered.ts +9 -2
  170. package/src/classes/ModUpgraded.ts +132 -31
  171. package/src/classes/callbacks/PostAmbushFinished.ts +39 -0
  172. package/src/classes/callbacks/PostAmbushStarted.ts +39 -0
  173. package/src/classes/callbacks/PostBombExploded.ts +21 -0
  174. package/src/classes/callbacks/PostBombInitLate.ts +28 -0
  175. package/src/classes/callbacks/PostBoneSwing.ts +58 -0
  176. package/src/classes/callbacks/PostCollectibleEmpty.ts +72 -0
  177. package/src/classes/callbacks/PostCollectibleInitFirst.ts +37 -0
  178. package/src/classes/callbacks/PostCursedTeleport.ts +183 -0
  179. package/src/classes/callbacks/PostKnifeInitLate.ts +28 -0
  180. package/src/classes/callbacks/PostNewRoomEarly.ts +93 -0
  181. package/src/classes/callbacks/PostPitRender.ts +21 -0
  182. package/src/classes/callbacks/PostRoomClearChanged.ts +40 -0
  183. package/src/classes/callbacks/PostSpikesRender.ts +21 -0
  184. package/src/classes/callbacks/validation/CustomCallbackAmbush.ts +28 -0
  185. package/src/classes/callbacks/validation/CustomCallbackBomb.ts +27 -0
  186. package/src/classes/callbacks/validation/CustomCallbackCollectible.ts +30 -0
  187. package/src/classes/callbacks/validation/CustomCallbackKnife.ts +27 -0
  188. package/src/classes/callbacks/validation/CustomCallbackPit.ts +28 -0
  189. package/src/classes/callbacks/validation/CustomCallbackPlayer.ts +37 -0
  190. package/src/classes/callbacks/validation/CustomCallbackSpikes.ts +28 -0
  191. package/src/classes/private/CustomCallback.ts +79 -0
  192. package/src/core/upgradeMod.ts +16 -2
  193. package/src/enums/IsaacScriptCommonFeature.ts +34 -0
  194. package/src/enums/LadderSubTypeCustom.ts +17 -0
  195. package/src/enums/ModCallbackCustom.ts +314 -243
  196. package/src/enums/ModCallbackCustom2.ts +17 -0
  197. package/src/features/{setHotkey.ts → customHotkeys.ts} +2 -2
  198. package/src/features/customPickup.ts +4 -2
  199. package/src/features/customStage/backdrop.ts +2 -1
  200. package/src/features/customStage/shadows.ts +2 -1
  201. package/src/features/customTrapdoor/init.ts +0 -1
  202. package/src/features/firstLast.ts +3 -7
  203. package/src/features/saveDataManager/main.ts +32 -21
  204. package/src/functions/ambush.ts +26 -1
  205. package/src/functions/minimap.ts +4 -0
  206. package/src/functions/roomTransition.ts +3 -27
  207. package/src/functions/spawnCollectible.ts +44 -4
  208. package/src/functions/utils.ts +7 -2
  209. package/src/index.ts +4 -2
  210. package/src/initCustomCallbacks.ts +1 -2
  211. package/src/initFeatures.ts +2 -2
  212. package/src/interfaces/private/{AddCallbackParameterCustom.ts → AddCallbackParametersCustom.ts} +3 -25
  213. package/src/interfaces/private/AddCallbackParametersCustom2.ts +79 -0
  214. package/src/objects/callbackRegisterFunctions.ts +3 -5
  215. package/src/types/private/AllButFirst.ts +6 -0
  216. package/src/types/private/CallbackTuple.ts +21 -0
  217. package/src/types/private/MatchingCallbackCustom.ts +26 -0
  218. package/dist/src/callbacks/postCustomDoorEnter.d.ts +0 -6
  219. package/dist/src/callbacks/postCustomDoorEnter.d.ts.map +0 -1
  220. package/dist/src/callbacks/postCustomDoorEnter.lua +0 -199
  221. package/dist/src/callbacks/subscriptions/postCustomDoorEnter.d.ts +0 -9
  222. package/dist/src/callbacks/subscriptions/postCustomDoorEnter.d.ts.map +0 -1
  223. package/dist/src/callbacks/subscriptions/postCustomDoorEnter.lua +0 -29
  224. package/dist/src/features/customDoor.d.ts +0 -51
  225. package/dist/src/features/customDoor.d.ts.map +0 -1
  226. package/dist/src/features/customDoor.lua +0 -53
  227. package/dist/src/features/setHotkey.d.ts.map +0 -1
  228. package/dist/src/indexLua.d.ts +0 -186
  229. package/dist/src/indexLua.d.ts.map +0 -1
  230. package/dist/src/indexLua.lua +0 -1322
  231. package/dist/src/interfaces/private/AddCallbackParameterCustom.d.ts.map +0 -1
  232. package/src/callbacks/postCustomDoorEnter.ts +0 -250
  233. package/src/callbacks/subscriptions/postCustomDoorEnter.ts +0 -42
  234. package/src/features/customDoor.ts +0 -66
@@ -0,0 +1,183 @@
1
+ import {
2
+ CollectibleType,
3
+ DamageFlag,
4
+ EntityType,
5
+ ModCallback,
6
+ PlayerVariant,
7
+ RoomType,
8
+ TrinketType,
9
+ } from "isaac-typescript-definitions";
10
+ import { game } from "../../core/cachedClasses";
11
+ import { ModCallbackCustom2 } from "../../enums/ModCallbackCustom2";
12
+ import { hasFlag } from "../../functions/flag";
13
+ import {
14
+ mapGetPlayer,
15
+ mapSetPlayer,
16
+ } from "../../functions/playerDataStructures";
17
+ import { getPlayerNumHitsRemaining } from "../../functions/players";
18
+ import { PlayerIndex } from "../../types/PlayerIndex";
19
+ import { CustomCallbackPlayer } from "./validation/CustomCallbackPlayer";
20
+
21
+ export class PostCursedTeleport extends CustomCallbackPlayer<ModCallbackCustom2.POST_CURSED_TELEPORT> {
22
+ override v = {
23
+ run: {
24
+ playersDamageFrameMap: new Map<
25
+ PlayerIndex,
26
+ [lastDamageFrame: int, callbackFiredOnThisFrame: boolean]
27
+ >(),
28
+ },
29
+
30
+ level: {
31
+ numSacrifices: 0,
32
+ },
33
+ };
34
+
35
+ constructor() {
36
+ super();
37
+
38
+ this.otherCallbacksUsed = [
39
+ [
40
+ ModCallback.ENTITY_TAKE_DMG,
41
+ [this.entityTakeDmgPlayer, EntityType.PLAYER],
42
+ ], // 11
43
+ [
44
+ ModCallback.POST_PLAYER_RENDER,
45
+ // Co-op babies cannot perform Cursed Eye teleports.
46
+ [this.postPlayerRenderPlayer, PlayerVariant.PLAYER],
47
+ ], // 32
48
+ ];
49
+ }
50
+
51
+ // ModCallback.ENTITY_TAKE_DMG (11)
52
+ // EntityType.PLAYER (1)
53
+ entityTakeDmgPlayer = (
54
+ entity: Entity,
55
+ _amount: float,
56
+ damageFlags: BitFlags<DamageFlag>,
57
+ _source: EntityRef,
58
+ _countdownFrames: int,
59
+ ): boolean | undefined => {
60
+ this.incrementNumSacrifices(damageFlags); // Has to be before setting the damage frame.
61
+ this.setDamageFrame(entity, damageFlags);
62
+
63
+ return undefined;
64
+ };
65
+
66
+ setDamageFrame(entity: Entity, damageFlags: BitFlags<DamageFlag>): void {
67
+ const gameFrameCount = game.GetFrameCount();
68
+
69
+ const player = entity.ToPlayer();
70
+ if (player === undefined) {
71
+ return;
72
+ }
73
+
74
+ // Don't do anything if we already activated the callback on this frame.
75
+ const trackingArray = mapGetPlayer(
76
+ this.v.run.playersDamageFrameMap,
77
+ player,
78
+ );
79
+ if (trackingArray !== undefined) {
80
+ const [lastDamageFrame, callbackFiredOnThisFrame] = trackingArray;
81
+ if (lastDamageFrame === gameFrameCount && callbackFiredOnThisFrame) {
82
+ return;
83
+ }
84
+ }
85
+
86
+ // Don't do anything if this could be a Sacrifice Room teleport.
87
+ if (this.isPotentialNaturalTeleportFromSacrificeRoom(damageFlags)) {
88
+ return;
89
+ }
90
+
91
+ const newTrackingArray = [gameFrameCount, false];
92
+ mapSetPlayer(this.v.run.playersDamageFrameMap, player, newTrackingArray);
93
+ }
94
+
95
+ isPotentialNaturalTeleportFromSacrificeRoom(
96
+ damageFlags: BitFlags<DamageFlag>,
97
+ ): boolean {
98
+ const room = game.GetRoom();
99
+ const roomType = room.GetType();
100
+ const isSpikeDamage = hasFlag(damageFlags, DamageFlag.SPIKES);
101
+
102
+ // Don't record the frame if we are potentially going to the Angel Room or the Dark Room from a
103
+ // Sacrifice Room.
104
+ return (
105
+ roomType === RoomType.SACRIFICE &&
106
+ isSpikeDamage &&
107
+ (this.v.level.numSacrifices === 6 || this.v.level.numSacrifices >= 12)
108
+ );
109
+ }
110
+
111
+ incrementNumSacrifices(damageFlags: BitFlags<DamageFlag>): void {
112
+ const room = game.GetRoom();
113
+ const roomType = room.GetType();
114
+ const isSpikeDamage = hasFlag(damageFlags, DamageFlag.SPIKES);
115
+
116
+ if (roomType === RoomType.SACRIFICE && isSpikeDamage) {
117
+ this.v.level.numSacrifices++;
118
+ }
119
+ }
120
+
121
+ // ModCallback.POST_PLAYER_RENDER (32)
122
+ // PlayerVariant.PLAYER (0)
123
+ postPlayerRenderPlayer = (
124
+ player: EntityPlayer,
125
+ _renderOffset: Vector,
126
+ ): void => {
127
+ // Retrieve information about this player.
128
+ const trackingArray = mapGetPlayer(
129
+ this.v.run.playersDamageFrameMap,
130
+ player,
131
+ );
132
+ if (trackingArray === undefined) {
133
+ return;
134
+ }
135
+ const [lastDamageFrame, callbackActivatedOnThisFrame] = trackingArray;
136
+
137
+ if (!playerIsTeleportingFromCursedTeleport(player, lastDamageFrame)) {
138
+ return;
139
+ }
140
+
141
+ // Do nothing if the callback already fired on this frame.
142
+ if (callbackActivatedOnThisFrame) {
143
+ return;
144
+ }
145
+
146
+ const gameFrameCount = game.GetFrameCount();
147
+ const newTrackingArray = [gameFrameCount, true];
148
+ mapSetPlayer(this.v.run.playersDamageFrameMap, player, newTrackingArray);
149
+
150
+ this.fire(player);
151
+ };
152
+ }
153
+
154
+ function playerIsTeleportingFromCursedTeleport(
155
+ player: EntityPlayer,
156
+ lastDamageFrame: int,
157
+ ) {
158
+ // Check to see if this is the frame that we last took damage.
159
+ const gameFrameCount = game.GetFrameCount();
160
+ if (gameFrameCount !== lastDamageFrame) {
161
+ return false;
162
+ }
163
+
164
+ // Check to see if this is the 1st frame that we are teleporting.
165
+ const sprite = player.GetSprite();
166
+ if (
167
+ !sprite.IsPlaying("TeleportUp") ||
168
+ sprite.GetFrame() !== 1 // The 0th frame never fires
169
+ ) {
170
+ return false;
171
+ }
172
+
173
+ if (player.HasCollectible(CollectibleType.CURSED_EYE)) {
174
+ return true;
175
+ }
176
+
177
+ const numHitsRemaining = getPlayerNumHitsRemaining(player);
178
+ if (player.HasTrinket(TrinketType.CURSED_SKULL) && numHitsRemaining === 1) {
179
+ return true;
180
+ }
181
+
182
+ return false;
183
+ }
@@ -0,0 +1,28 @@
1
+ import { ModCallback } from "isaac-typescript-definitions";
2
+ import { ModCallbackCustom2 } from "../../enums/ModCallbackCustom2";
3
+ import { CustomCallbackKnife } from "./validation/CustomCallbackKnife";
4
+
5
+ export class PostKnifeInitLate extends CustomCallbackKnife<ModCallbackCustom2.POST_KNIFE_INIT_LATE> {
6
+ override v = {
7
+ room: {
8
+ firedSet: new Set<PtrHash>(),
9
+ },
10
+ };
11
+
12
+ constructor() {
13
+ super();
14
+
15
+ this.otherCallbacksUsed = [
16
+ [ModCallback.POST_KNIFE_UPDATE, [this.postKnifeUpdate]], // 51
17
+ ];
18
+ }
19
+
20
+ // ModCallback.POST_KNIFE_UPDATE (51)
21
+ postKnifeUpdate = (knife: EntityKnife): void => {
22
+ const ptrHash = GetPtrHash(knife);
23
+ if (!this.v.room.firedSet.has(ptrHash)) {
24
+ this.v.room.firedSet.add(ptrHash);
25
+ this.fire(knife);
26
+ }
27
+ };
28
+ }
@@ -0,0 +1,93 @@
1
+ import {
2
+ EntityType,
3
+ GridEntityType,
4
+ ModCallback,
5
+ } from "isaac-typescript-definitions";
6
+ import { game } from "../../core/cachedClasses";
7
+ import { ModCallbackCustom2 } from "../../enums/ModCallbackCustom2";
8
+ import {
9
+ getTopLeftWallGridIndex,
10
+ spawnGridEntity,
11
+ } from "../../functions/gridEntities";
12
+ import { logError } from "../../functions/logMisc";
13
+ import { CustomCallback } from "../private/CustomCallback";
14
+
15
+ export class PostNewRoomEarly extends CustomCallback<ModCallbackCustom2.POST_NEW_ROOM_EARLY> {
16
+ currentRoomTopLeftWallPtrHash: PtrHash | null = null;
17
+
18
+ /** The wall entity directly to the right of the top-left wall. */
19
+ currentRoomTopLeftWallPtrHash2: PtrHash | null = null;
20
+
21
+ constructor() {
22
+ super();
23
+
24
+ this.otherCallbacksUsed = [
25
+ [ModCallback.POST_NEW_ROOM, [this.postNewRoom]], // 19
26
+ [ModCallback.PRE_ENTITY_SPAWN, [this.preEntitySpawn]], // 24
27
+ ];
28
+ }
29
+
30
+ // ModCallback.POST_NEW_ROOM (19)
31
+ postNewRoom = (): void => {
32
+ this.checkRoomChanged();
33
+ };
34
+
35
+ // ModCallback.PRE_ENTITY_SPAWN (24)
36
+ preEntitySpawn = (): [EntityType, int, int, int] | undefined => {
37
+ this.checkRoomChanged();
38
+ return undefined;
39
+ };
40
+
41
+ checkRoomChanged(): void {
42
+ if (this.isNewRoom()) {
43
+ this.fire();
44
+ }
45
+ }
46
+
47
+ isNewRoom(): boolean {
48
+ const room = game.GetRoom();
49
+ const topLeftWallGridIndex = getTopLeftWallGridIndex();
50
+ const rightOfTopWallGridIndex = topLeftWallGridIndex + 1;
51
+
52
+ let topLeftWall = room.GetGridEntity(topLeftWallGridIndex);
53
+ let topLeftWall2 = room.GetGridEntity(rightOfTopWallGridIndex);
54
+
55
+ // Sometimes, the PreEntitySpawn callback can fire before any grid entities in the room have
56
+ // spawned, which means that the top-left wall will not exist. If ths is the case, then simply
57
+ // spawn the top-left wall early.
58
+ if (topLeftWall === undefined) {
59
+ topLeftWall = spawnGridEntity(GridEntityType.WALL, topLeftWallGridIndex);
60
+ if (topLeftWall === undefined) {
61
+ logError(
62
+ "Failed to spawn a new wall (1) for the POST_NEW_ROOM_EARLY callback.",
63
+ );
64
+ return false;
65
+ }
66
+ }
67
+
68
+ // For some reason, the above check will rarely fail. We duplicate the check with another wall
69
+ // segment to increase the reliability.
70
+ if (topLeftWall2 === undefined) {
71
+ topLeftWall2 = spawnGridEntity(
72
+ GridEntityType.WALL,
73
+ rightOfTopWallGridIndex,
74
+ );
75
+ if (topLeftWall2 === undefined) {
76
+ logError(
77
+ "Failed to spawn a new wall (2) for the POST_NEW_ROOM_EARLY callback.",
78
+ );
79
+ return false;
80
+ }
81
+ }
82
+
83
+ const oldTopLeftWallPtrHash = this.currentRoomTopLeftWallPtrHash;
84
+ const oldTopLeftWallPtrHash2 = this.currentRoomTopLeftWallPtrHash2;
85
+ this.currentRoomTopLeftWallPtrHash = GetPtrHash(topLeftWall);
86
+ this.currentRoomTopLeftWallPtrHash2 = GetPtrHash(topLeftWall2);
87
+
88
+ return (
89
+ oldTopLeftWallPtrHash !== this.currentRoomTopLeftWallPtrHash ||
90
+ oldTopLeftWallPtrHash2 !== this.currentRoomTopLeftWallPtrHash2
91
+ );
92
+ }
93
+ }
@@ -0,0 +1,21 @@
1
+ import { ModCallback } from "isaac-typescript-definitions";
2
+ import { ModCallbackCustom2 } from "../../enums/ModCallbackCustom2";
3
+ import { getPits } from "../../functions/gridEntitiesSpecific";
4
+ import { CustomCallbackPit } from "./validation/CustomCallbackPit";
5
+
6
+ export class PostPitRender extends CustomCallbackPit<ModCallbackCustom2.POST_PIT_RENDER> {
7
+ constructor() {
8
+ super();
9
+
10
+ this.otherCallbacksUsed = [
11
+ [ModCallback.POST_RENDER, [this.postRender]], // 2
12
+ ];
13
+ }
14
+
15
+ // ModCallback.POST_RENDER (2)
16
+ postRender = (): void => {
17
+ for (const pit of getPits()) {
18
+ this.fire(pit);
19
+ }
20
+ };
21
+ }
@@ -0,0 +1,40 @@
1
+ import { ModCallback } from "isaac-typescript-definitions";
2
+ import { game } from "../../core/cachedClasses";
3
+ import { ModCallbackCustom2 } from "../../enums/ModCallbackCustom2";
4
+ import { CustomCallback } from "../private/CustomCallback";
5
+
6
+ export class PostRoomClearChanged extends CustomCallback<ModCallbackCustom2.POST_ROOM_CLEAR_CHANGED> {
7
+ override v = {
8
+ room: {
9
+ cleared: false,
10
+ },
11
+ };
12
+
13
+ constructor() {
14
+ super();
15
+
16
+ this.otherCallbacksUsed = [
17
+ [ModCallback.POST_UPDATE, [this.postUpdate]], // 1
18
+ [ModCallback.POST_NEW_ROOM, [this.postNewRoom]], // 19
19
+ ];
20
+ }
21
+
22
+ // ModCallback.POST_UPDATE (1)
23
+ postUpdate = (): void => {
24
+ const room = game.GetRoom();
25
+ const roomClear = room.IsClear();
26
+
27
+ if (roomClear !== this.v.room.cleared) {
28
+ this.v.room.cleared = roomClear;
29
+ this.fire(roomClear);
30
+ }
31
+ };
32
+
33
+ // ModCallback.POST_NEW_ROOM (19)
34
+ postNewRoom = (): void => {
35
+ const room = game.GetRoom();
36
+ const roomClear = room.IsClear();
37
+
38
+ this.v.room.cleared = roomClear;
39
+ };
40
+ }
@@ -0,0 +1,21 @@
1
+ import { ModCallback } from "isaac-typescript-definitions";
2
+ import { ModCallbackCustom2 } from "../../enums/ModCallbackCustom2";
3
+ import { getSpikes } from "../../functions/gridEntitiesSpecific";
4
+ import { CustomCallbackSpikes } from "./validation/CustomCallbackSpikes";
5
+
6
+ export class PostSpikesRender extends CustomCallbackSpikes<ModCallbackCustom2.POST_SPIKES_RENDER> {
7
+ constructor() {
8
+ super();
9
+
10
+ this.otherCallbacksUsed = [
11
+ [ModCallback.POST_RENDER, [this.postRender]], // 2
12
+ ];
13
+ }
14
+
15
+ // ModCallback.POST_RENDER (2)
16
+ postRender = (): void => {
17
+ for (const spikes of getSpikes()) {
18
+ this.fire(spikes);
19
+ }
20
+ };
21
+ }
@@ -0,0 +1,28 @@
1
+ import { AmbushType } from "packages/isaacscript-common/src/enums/AmbushType";
2
+ import { MatchingCallbackCustom } from "packages/isaacscript-common/src/types/private/MatchingCallbackCustom";
3
+ import {
4
+ CustomCallback,
5
+ FireArgs,
6
+ OptionalArgs,
7
+ } from "../../private/CustomCallback";
8
+
9
+ type CallbackSignatureAmbush = (ambushType: AmbushType) => void;
10
+ type ModCallbackCustomAmbush = MatchingCallbackCustom<CallbackSignatureAmbush>;
11
+
12
+ export class CustomCallbackAmbush<
13
+ T extends ModCallbackCustomAmbush,
14
+ > extends CustomCallback<T> {
15
+ // eslint-disable-next-line class-methods-use-this
16
+ override shouldFire(
17
+ fireArgs: FireArgs<T>,
18
+ optionalArgs: OptionalArgs<T>,
19
+ ): boolean {
20
+ const [callbackAmbushType] = optionalArgs;
21
+ if (callbackAmbushType === undefined) {
22
+ return true;
23
+ }
24
+
25
+ const [ambushType] = fireArgs;
26
+ return ambushType === callbackAmbushType;
27
+ }
28
+ }
@@ -0,0 +1,27 @@
1
+ import { MatchingCallbackCustom } from "packages/isaacscript-common/src/types/private/MatchingCallbackCustom";
2
+ import {
3
+ CustomCallback,
4
+ FireArgs,
5
+ OptionalArgs,
6
+ } from "../../private/CustomCallback";
7
+
8
+ type CallbackSignatureBomb = (bomb: EntityBomb) => void;
9
+ type ModCallbackCustomBomb = MatchingCallbackCustom<CallbackSignatureBomb>;
10
+
11
+ export class CustomCallbackBomb<
12
+ T extends ModCallbackCustomBomb,
13
+ > extends CustomCallback<T> {
14
+ // eslint-disable-next-line class-methods-use-this
15
+ override shouldFire(
16
+ fireArgs: FireArgs<T>,
17
+ optionalArgs: OptionalArgs<T>,
18
+ ): boolean {
19
+ const [callbackBombVariant] = optionalArgs;
20
+ if (callbackBombVariant === undefined) {
21
+ return true;
22
+ }
23
+
24
+ const [bomb] = fireArgs;
25
+ return bomb.Variant === callbackBombVariant;
26
+ }
27
+ }
@@ -0,0 +1,30 @@
1
+ import { MatchingCallbackCustom } from "packages/isaacscript-common/src/types/private/MatchingCallbackCustom";
2
+ import {
3
+ CustomCallback,
4
+ FireArgs,
5
+ OptionalArgs,
6
+ } from "../../private/CustomCallback";
7
+
8
+ type CallbackSignatureCollectible = (
9
+ collectible: EntityPickupCollectible,
10
+ ) => void;
11
+ type ModCallbackCustomCollectible =
12
+ MatchingCallbackCustom<CallbackSignatureCollectible>;
13
+
14
+ export class CustomCallbackCollectible<
15
+ T extends ModCallbackCustomCollectible,
16
+ > extends CustomCallback<T> {
17
+ // eslint-disable-next-line class-methods-use-this
18
+ override shouldFire(
19
+ fireArgs: FireArgs<T>,
20
+ optionalArgs: OptionalArgs<T>,
21
+ ): boolean {
22
+ const [callbackCollectibleType] = optionalArgs;
23
+ if (callbackCollectibleType === undefined) {
24
+ return true;
25
+ }
26
+
27
+ const [collectible] = fireArgs;
28
+ return collectible.SubType === callbackCollectibleType;
29
+ }
30
+ }
@@ -0,0 +1,27 @@
1
+ import { MatchingCallbackCustom } from "packages/isaacscript-common/src/types/private/MatchingCallbackCustom";
2
+ import {
3
+ CustomCallback,
4
+ FireArgs,
5
+ OptionalArgs,
6
+ } from "../../private/CustomCallback";
7
+
8
+ type CallbackSignatureKnife = (knife: EntityKnife) => void;
9
+ type ModCallbackCustomKnife = MatchingCallbackCustom<CallbackSignatureKnife>;
10
+
11
+ export class CustomCallbackKnife<
12
+ T extends ModCallbackCustomKnife,
13
+ > extends CustomCallback<T> {
14
+ // eslint-disable-next-line class-methods-use-this
15
+ override shouldFire(
16
+ fireArgs: FireArgs<T>,
17
+ optionalArgs: OptionalArgs<T>,
18
+ ): boolean {
19
+ const [callbackKnifeVariant] = optionalArgs;
20
+ if (callbackKnifeVariant === undefined) {
21
+ return true;
22
+ }
23
+
24
+ const [knife] = fireArgs;
25
+ return knife.Variant === callbackKnifeVariant;
26
+ }
27
+ }
@@ -0,0 +1,28 @@
1
+ import { MatchingCallbackCustom } from "packages/isaacscript-common/src/types/private/MatchingCallbackCustom";
2
+ import {
3
+ CustomCallback,
4
+ FireArgs,
5
+ OptionalArgs,
6
+ } from "../../private/CustomCallback";
7
+
8
+ type CallbackSignaturePit = (pit: GridEntityPit) => void;
9
+ type ModCallbackCustomPit = MatchingCallbackCustom<CallbackSignaturePit>;
10
+
11
+ export class CustomCallbackPit<
12
+ T extends ModCallbackCustomPit,
13
+ > extends CustomCallback<T> {
14
+ // eslint-disable-next-line class-methods-use-this
15
+ override shouldFire(
16
+ fireArgs: FireArgs<T>,
17
+ optionalArgs: OptionalArgs<T>,
18
+ ): boolean {
19
+ const [callbackPitVariant] = optionalArgs;
20
+ if (callbackPitVariant === undefined) {
21
+ return true;
22
+ }
23
+
24
+ const [pit] = fireArgs;
25
+ const pitVariant = pit.GetVariant();
26
+ return pitVariant === callbackPitVariant;
27
+ }
28
+ }
@@ -0,0 +1,37 @@
1
+ import { MatchingCallbackCustom } from "packages/isaacscript-common/src/types/private/MatchingCallbackCustom";
2
+ import {
3
+ CustomCallback,
4
+ FireArgs,
5
+ OptionalArgs,
6
+ } from "../../private/CustomCallback";
7
+
8
+ type CallbackSignaturePlayer = (player: EntityPlayer) => void;
9
+ type ModCallbackCustomPlayer = MatchingCallbackCustom<CallbackSignaturePlayer>;
10
+
11
+ export class CustomCallbackPlayer<
12
+ T extends ModCallbackCustomPlayer,
13
+ > extends CustomCallback<T> {
14
+ // eslint-disable-next-line class-methods-use-this
15
+ override shouldFire(
16
+ fireArgs: FireArgs<T>,
17
+ optionalArgs: OptionalArgs<T>,
18
+ ): boolean {
19
+ const [player] = fireArgs;
20
+ const [callbackPlayerVariant, callbackCharacter] = optionalArgs;
21
+
22
+ if (
23
+ callbackPlayerVariant !== undefined &&
24
+ callbackPlayerVariant !== player.Variant
25
+ ) {
26
+ return false;
27
+ }
28
+
29
+ const character = player.GetPlayerType();
30
+
31
+ if (callbackCharacter !== undefined && callbackCharacter !== character) {
32
+ return false;
33
+ }
34
+
35
+ return true;
36
+ }
37
+ }
@@ -0,0 +1,28 @@
1
+ import { MatchingCallbackCustom } from "packages/isaacscript-common/src/types/private/MatchingCallbackCustom";
2
+ import {
3
+ CustomCallback,
4
+ FireArgs,
5
+ OptionalArgs,
6
+ } from "../../private/CustomCallback";
7
+
8
+ type CallbackSignatureSpikes = (spikes: GridEntitySpikes) => void;
9
+ type ModCallbackCustomSpikes = MatchingCallbackCustom<CallbackSignatureSpikes>;
10
+
11
+ export class CustomCallbackSpikes<
12
+ T extends ModCallbackCustomSpikes,
13
+ > extends CustomCallback<T> {
14
+ // eslint-disable-next-line class-methods-use-this
15
+ override shouldFire(
16
+ fireArgs: FireArgs<T>,
17
+ optionalArgs: OptionalArgs<T>,
18
+ ): boolean {
19
+ const [callbackSpikesVariant] = optionalArgs;
20
+ if (callbackSpikesVariant === undefined) {
21
+ return true;
22
+ }
23
+
24
+ const [spikes] = fireArgs;
25
+ const spikesVariant = spikes.GetVariant();
26
+ return spikesVariant === callbackSpikesVariant;
27
+ }
28
+ }
@@ -0,0 +1,79 @@
1
+ import { ModCallbackCustom2 } from "../../enums/ModCallbackCustom2";
2
+ import { AddCallbackParametersCustom2 } from "../../interfaces/private/AddCallbackParametersCustom2";
3
+ import { SaveData } from "../../interfaces/SaveData";
4
+ import { AllButFirst } from "../../types/private/AllButFirst";
5
+ import {
6
+ CallbackTuple,
7
+ CustomCallbackTuple,
8
+ } from "../../types/private/CallbackTuple";
9
+
10
+ export type FireArgs<T extends ModCallbackCustom2> = Parameters<
11
+ AddCallbackParametersCustom2[T][0]
12
+ >;
13
+ export type OptionalArgs<T extends ModCallbackCustom2> = AllButFirst<
14
+ AddCallbackParametersCustom2[T]
15
+ >;
16
+
17
+ /**
18
+ * The base class for a custom callback. Individual custom callbacks (and validation callbacks) will
19
+ * extend from this class.
20
+ */
21
+ export abstract class CustomCallback<T extends ModCallbackCustom2> {
22
+ /** This is manually managed by the `ModUpgraded` class. */
23
+ initialized = false;
24
+
25
+ subscriptions: Array<AddCallbackParametersCustom2[T]> = [];
26
+
27
+ otherCallbacksUsed?: CallbackTuple[];
28
+ otherCustomCallbacksUsed?: CustomCallbackTuple[];
29
+ v?: SaveData;
30
+
31
+ hasSubscriptions(): boolean {
32
+ return this.subscriptions.length > 0;
33
+ }
34
+
35
+ add(...args: AddCallbackParametersCustom2[T]): void {
36
+ this.subscriptions.push(args);
37
+ }
38
+
39
+ /**
40
+ * If the submitted function does not match any of the existing subscriptions, this method will do
41
+ * nothing.
42
+ */
43
+ remove(callback: AddCallbackParametersCustom2[T][0]): void {
44
+ const subscriptionIndexMatchingCallback = this.subscriptions.findIndex(
45
+ (subscription) => {
46
+ const subscriptionCallback = subscription[0];
47
+ return callback === subscriptionCallback;
48
+ },
49
+ );
50
+ if (subscriptionIndexMatchingCallback !== -1) {
51
+ this.subscriptions.splice(subscriptionIndexMatchingCallback, 1);
52
+ }
53
+ }
54
+
55
+ fire(...fireArgs: FireArgs<T>): void {
56
+ for (const [callback, ...optionalArgs] of this.subscriptions) {
57
+ // @ts-expect-error The compiler is not smart enough to know that the arguments should match
58
+ // the method.
59
+ if (this.shouldFire(fireArgs, optionalArgs)) {
60
+ // @ts-expect-error The compiler is not smart enough to know that the arguments should match
61
+ // the callback.
62
+ callback(...fireArgs);
63
+ }
64
+ }
65
+ }
66
+
67
+ /**
68
+ * This method needs to be overwritten for any callback that has optional filtration arguments.
69
+ */
70
+ // eslint-disable-next-line class-methods-use-this
71
+ shouldFire(
72
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
73
+ fireArgs: FireArgs<T>,
74
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
75
+ optionalArgs: OptionalArgs<T>,
76
+ ): boolean {
77
+ return true;
78
+ }
79
+ }