isaacscript-common 26.0.0 → 26.1.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 (42) hide show
  1. package/dist/index.rollup.d.ts +21 -11
  2. package/dist/isaacscript-common.lua +201 -185
  3. package/dist/src/classes/callbacks/PostCursedTeleport.d.ts +2 -1
  4. package/dist/src/classes/callbacks/PostCursedTeleport.d.ts.map +1 -1
  5. package/dist/src/classes/callbacks/PostCursedTeleport.lua +26 -29
  6. package/dist/src/classes/callbacks/PostNewRoomEarly.d.ts.map +1 -1
  7. package/dist/src/classes/callbacks/PreNewLevel.d.ts +1 -1
  8. package/dist/src/classes/callbacks/PreNewLevel.d.ts.map +1 -1
  9. package/dist/src/classes/callbacks/PreNewLevel.lua +4 -4
  10. package/dist/src/classes/features/callbackLogic/GameReorderedCallbacks.d.ts.map +1 -1
  11. package/dist/src/classes/features/callbackLogic/PlayerReorderedCallbacks.d.ts +9 -3
  12. package/dist/src/classes/features/callbackLogic/PlayerReorderedCallbacks.d.ts.map +1 -1
  13. package/dist/src/classes/features/callbackLogic/PlayerReorderedCallbacks.lua +13 -9
  14. package/dist/src/classes/features/other/FadeInRemover.d.ts +1 -1
  15. package/dist/src/classes/features/other/FadeInRemover.d.ts.map +1 -1
  16. package/dist/src/classes/features/other/FadeInRemover.lua +6 -6
  17. package/dist/src/classes/features/other/SaveDataManager.d.ts.map +1 -1
  18. package/dist/src/classes/features/other/debugDisplay/DebugDisplayPlayer.d.ts +1 -1
  19. package/dist/src/classes/features/other/debugDisplay/DebugDisplayPlayer.d.ts.map +1 -1
  20. package/dist/src/classes/features/other/debugDisplay/DebugDisplayPlayer.lua +4 -4
  21. package/dist/src/enums/ModCallbackCustom.d.ts +3 -5
  22. package/dist/src/enums/ModCallbackCustom.d.ts.map +1 -1
  23. package/dist/src/functions/utils.d.ts +6 -0
  24. package/dist/src/functions/utils.d.ts.map +1 -1
  25. package/dist/src/functions/utils.lua +18 -0
  26. package/dist/src/interfaces/private/AddCallbackParametersCustom.d.ts +1 -1
  27. package/dist/src/interfaces/private/AddCallbackParametersCustom.d.ts.map +1 -1
  28. package/dist/src/shouldFire.d.ts +1 -1
  29. package/dist/src/shouldFire.d.ts.map +1 -1
  30. package/package.json +2 -2
  31. package/src/classes/callbacks/PostCursedTeleport.ts +59 -65
  32. package/src/classes/callbacks/PostNewRoomEarly.ts +1 -0
  33. package/src/classes/callbacks/PreNewLevel.ts +7 -6
  34. package/src/classes/features/callbackLogic/GameReorderedCallbacks.ts +3 -0
  35. package/src/classes/features/callbackLogic/PlayerReorderedCallbacks.ts +29 -13
  36. package/src/classes/features/other/FadeInRemover.ts +10 -8
  37. package/src/classes/features/other/SaveDataManager.ts +2 -0
  38. package/src/classes/features/other/debugDisplay/DebugDisplayPlayer.ts +8 -6
  39. package/src/enums/ModCallbackCustom.ts +3 -5
  40. package/src/functions/utils.ts +14 -0
  41. package/src/interfaces/private/AddCallbackParametersCustom.ts +1 -1
  42. package/src/shouldFire.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "26.0.0",
3
+ "version": "26.1.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/src/index",
23
23
  "types": "dist/index.rollup.d.ts",
24
24
  "dependencies": {
25
- "isaac-typescript-definitions": "^11.1.6"
25
+ "isaac-typescript-definitions": "^12.0.0"
26
26
  }
27
27
  }
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  CollectibleType,
3
3
  DamageFlag,
4
- ModCallback,
5
4
  PlayerVariant,
6
5
  RoomType,
7
6
  TrinketType,
@@ -39,50 +38,16 @@ export class PostCursedTeleport extends CustomCallback<ModCallbackCustom.POST_CU
39
38
  constructor() {
40
39
  super();
41
40
 
42
- this.callbacksUsed = [
43
- // 32
44
- [
45
- ModCallback.POST_PLAYER_RENDER,
46
- // Co-op babies cannot perform Cursed Eye teleports.
47
- this.postPlayerRenderPlayer,
48
- [PlayerVariant.PLAYER],
49
- ],
50
- ];
51
-
52
41
  this.customCallbacksUsed = [
53
42
  [ModCallbackCustom.ENTITY_TAKE_DMG_PLAYER, this.entityTakeDmgPlayer],
43
+ [
44
+ ModCallbackCustom.POST_PLAYER_RENDER_REORDERED,
45
+ this.postPlayerRenderReorderedPlayer,
46
+ [PlayerVariant.PLAYER], // Co-op babies cannot perform Cursed Eye teleports.
47
+ ],
54
48
  ];
55
49
  }
56
50
 
57
- // ModCallback.POST_PLAYER_RENDER (32)
58
- // PlayerVariant.PLAYER (0)
59
- private postPlayerRenderPlayer = (
60
- player: EntityPlayer,
61
- _renderOffset: Vector,
62
- ): void => {
63
- // Retrieve information about this player.
64
- const trackingArray = mapGetPlayer(v.run.playersDamageFrameMap, player);
65
- if (trackingArray === undefined) {
66
- return;
67
- }
68
- const [lastDamageFrame, callbackActivatedOnThisFrame] = trackingArray;
69
-
70
- if (!playerIsTeleportingFromCursedTeleport(player, lastDamageFrame)) {
71
- return;
72
- }
73
-
74
- // Do nothing if the callback already fired on this frame.
75
- if (callbackActivatedOnThisFrame) {
76
- return;
77
- }
78
-
79
- const gameFrameCount = game.GetFrameCount();
80
- const newTrackingArray = [gameFrameCount, true];
81
- mapSetPlayer(v.run.playersDamageFrameMap, player, newTrackingArray);
82
-
83
- this.fire(player);
84
- };
85
-
86
51
  // ModCallbackCustom.ENTITY_TAKE_DMG_PLAYER
87
52
  private entityTakeDmgPlayer = (
88
53
  player: EntityPlayer,
@@ -146,35 +111,64 @@ export class PostCursedTeleport extends CustomCallback<ModCallbackCustom.POST_CU
146
111
  (v.level.numSacrifices === 6 || v.level.numSacrifices >= 12)
147
112
  );
148
113
  }
149
- }
150
114
 
151
- function playerIsTeleportingFromCursedTeleport(
152
- player: EntityPlayer,
153
- lastDamageFrame: int,
154
- ) {
155
- // Check to see if this is the frame that we last took damage.
156
- const gameFrameCount = game.GetFrameCount();
157
- if (gameFrameCount !== lastDamageFrame) {
158
- return false;
159
- }
115
+ // ModCallbackCustom.POST_PLAYER_RENDER_REORDERED
116
+ // PlayerVariant.PLAYER (0)
117
+ private postPlayerRenderReorderedPlayer = (
118
+ player: EntityPlayer,
119
+ _renderOffset: Vector,
120
+ ): void => {
121
+ // Retrieve information about this player.
122
+ const trackingArray = mapGetPlayer(v.run.playersDamageFrameMap, player);
123
+ if (trackingArray === undefined) {
124
+ return;
125
+ }
126
+ const [lastDamageFrame, callbackActivatedOnThisFrame] = trackingArray;
127
+
128
+ if (!this.playerIsTeleportingFromCursedTeleport(player, lastDamageFrame)) {
129
+ return;
130
+ }
131
+
132
+ // Do nothing if the callback already fired on this frame.
133
+ if (callbackActivatedOnThisFrame) {
134
+ return;
135
+ }
136
+
137
+ const gameFrameCount = game.GetFrameCount();
138
+ const newTrackingArray = [gameFrameCount, true];
139
+ mapSetPlayer(v.run.playersDamageFrameMap, player, newTrackingArray);
140
+
141
+ this.fire(player);
142
+ };
160
143
 
161
- // Check to see if this is the 1st frame that we are teleporting.
162
- const sprite = player.GetSprite();
163
- if (
164
- !sprite.IsPlaying("TeleportUp") ||
165
- sprite.GetFrame() !== 1 // The 0th frame never fires
144
+ private playerIsTeleportingFromCursedTeleport(
145
+ player: EntityPlayer,
146
+ lastDamageFrame: int,
166
147
  ) {
167
- return false;
168
- }
148
+ // Check to see if this is the frame that we last took damage.
149
+ const gameFrameCount = game.GetFrameCount();
150
+ if (gameFrameCount !== lastDamageFrame) {
151
+ return false;
152
+ }
169
153
 
170
- if (player.HasCollectible(CollectibleType.CURSED_EYE)) {
171
- return true;
172
- }
154
+ // Check to see if this is the 1st frame that we are teleporting.
155
+ const sprite = player.GetSprite();
156
+ if (
157
+ !sprite.IsPlaying("TeleportUp") ||
158
+ sprite.GetFrame() !== 1 // The 0th frame never fires
159
+ ) {
160
+ return false;
161
+ }
173
162
 
174
- const numHitsRemaining = getPlayerNumHitsRemaining(player);
175
- if (player.HasTrinket(TrinketType.CURSED_SKULL) && numHitsRemaining === 1) {
176
- return true;
177
- }
163
+ if (player.HasCollectible(CollectibleType.CURSED_EYE)) {
164
+ return true;
165
+ }
178
166
 
179
- return false;
167
+ const numHitsRemaining = getPlayerNumHitsRemaining(player);
168
+ if (player.HasTrinket(TrinketType.CURSED_SKULL) && numHitsRemaining === 1) {
169
+ return true;
170
+ }
171
+
172
+ return false;
173
+ }
180
174
  }
@@ -23,6 +23,7 @@ export class PostNewRoomEarly extends CustomCallback<ModCallbackCustom.POST_NEW_
23
23
 
24
24
  this.callbacksUsed = [
25
25
  // 19
26
+ // eslint-disable-next-line deprecation/deprecation
26
27
  [ModCallback.POST_NEW_ROOM, this.postNewRoom],
27
28
 
28
29
  // 24
@@ -1,4 +1,3 @@
1
- import { ModCallback } from "isaac-typescript-definitions";
2
1
  import { ModCallbackCustom } from "../../enums/ModCallbackCustom";
3
2
  import { getLastFrameOfAnimation } from "../../functions/sprites";
4
3
  import { getEffectiveStage } from "../../functions/stage";
@@ -22,14 +21,16 @@ export class PreNewLevel extends CustomCallback<ModCallbackCustom.PRE_NEW_LEVEL>
22
21
  constructor() {
23
22
  super();
24
23
 
25
- this.callbacksUsed = [
26
- // 32
27
- [ModCallback.POST_PLAYER_RENDER, this.postPlayerRender],
24
+ this.customCallbacksUsed = [
25
+ [
26
+ ModCallbackCustom.POST_PLAYER_RENDER_REORDERED,
27
+ this.postPlayerRenderReordered,
28
+ ],
28
29
  ];
29
30
  }
30
31
 
31
- // ModCallback.POST_PLAYER_RENDER (32)
32
- private postPlayerRender = (player: EntityPlayer) => {
32
+ // ModCallbackCustom.POST_PLAYER_RENDER_REORDERED
33
+ private postPlayerRenderReordered = (player: EntityPlayer) => {
33
34
  const effectiveStage = getEffectiveStage();
34
35
  if (effectiveStage === v.run.firedOnStage) {
35
36
  return;
@@ -57,12 +57,15 @@ export class GameReorderedCallbacks extends Feature {
57
57
  ],
58
58
 
59
59
  // 15
60
+ // eslint-disable-next-line deprecation/deprecation
60
61
  [ModCallback.POST_GAME_STARTED, this.postGameStarted],
61
62
 
62
63
  // 18
64
+ // eslint-disable-next-line deprecation/deprecation
63
65
  [ModCallback.POST_NEW_LEVEL, this.postNewLevel],
64
66
 
65
67
  // 19
68
+ // eslint-disable-next-line deprecation/deprecation
66
69
  [ModCallback.POST_NEW_ROOM, this.postNewRoom],
67
70
  ];
68
71
 
@@ -4,6 +4,7 @@
4
4
  // - POST_PLAYER_UPDATE_REORDERED
5
5
 
6
6
  import { ModCallback } from "isaac-typescript-definitions";
7
+ import { VectorZero } from "../../../core/constants";
7
8
  import { ModCallbackCustom } from "../../../enums/ModCallbackCustom";
8
9
  import { emptyArray } from "../../../functions/array";
9
10
  import {
@@ -16,13 +17,18 @@ import { PostPlayerRenderReordered } from "../../callbacks/PostPlayerRenderReord
16
17
  import { PostPlayerUpdateReordered } from "../../callbacks/PostPlayerUpdateReordered";
17
18
  import { Feature } from "../../private/Feature";
18
19
 
20
+ interface QueueElement {
21
+ playerIndex: PlayerIndex;
22
+ renderOffset: Vector;
23
+ }
24
+
19
25
  const v = {
20
26
  run: {
21
27
  postGameStartedFiredOnThisRun: false,
22
28
 
23
- postPEffectUpdateQueue: [] as PlayerIndex[],
24
- postPlayerUpdateQueue: [] as PlayerIndex[],
25
- postPlayerRenderQueue: [] as PlayerIndex[],
29
+ postPEffectUpdateQueue: [] as QueueElement[],
30
+ postPlayerUpdateQueue: [] as QueueElement[],
31
+ postPlayerRenderQueue: [] as QueueElement[],
26
32
  },
27
33
  };
28
34
 
@@ -42,12 +48,15 @@ export class PlayerReorderedCallbacks extends Feature {
42
48
 
43
49
  this.callbacksUsed = [
44
50
  // 4
51
+ // eslint-disable-next-line deprecation/deprecation
45
52
  [ModCallback.POST_PEFFECT_UPDATE, this.postPEffectUpdate],
46
53
 
47
54
  // 31
55
+ // eslint-disable-next-line deprecation/deprecation
48
56
  [ModCallback.POST_PLAYER_UPDATE, this.postPlayerUpdate],
49
57
 
50
58
  // 32
59
+ // eslint-disable-next-line deprecation/deprecation
51
60
  [ModCallback.POST_PLAYER_RENDER, this.postPlayerRender],
52
61
  ];
53
62
 
@@ -70,7 +79,10 @@ export class PlayerReorderedCallbacks extends Feature {
70
79
  } else {
71
80
  // Defer callback execution until the `POST_GAME_STARTED` callback fires.
72
81
  const playerIndex = getPlayerIndex(player);
73
- v.run.postPEffectUpdateQueue.push(playerIndex);
82
+ v.run.postPEffectUpdateQueue.push({
83
+ playerIndex,
84
+ renderOffset: VectorZero,
85
+ });
74
86
  }
75
87
  };
76
88
 
@@ -81,21 +93,24 @@ export class PlayerReorderedCallbacks extends Feature {
81
93
  } else {
82
94
  // Defer callback execution until the `POST_GAME_STARTED` callback fires.
83
95
  const playerIndex = getPlayerIndex(player);
84
- v.run.postPlayerUpdateQueue.push(playerIndex);
96
+ v.run.postPlayerUpdateQueue.push({
97
+ playerIndex,
98
+ renderOffset: VectorZero,
99
+ });
85
100
  }
86
101
  };
87
102
 
88
103
  // ModCallback.POST_PLAYER_RENDER (32)
89
104
  private postPlayerRender = (
90
105
  player: EntityPlayer,
91
- _renderOffset: Vector,
106
+ renderOffset: Vector,
92
107
  ): void => {
93
108
  if (v.run.postGameStartedFiredOnThisRun) {
94
- this.postPlayerRenderReordered.fire(player);
109
+ this.postPlayerRenderReordered.fire(player, renderOffset);
95
110
  } else {
96
111
  // Defer callback execution until the `POST_GAME_STARTED` callback fires.
97
112
  const playerIndex = getPlayerIndex(player);
98
- v.run.postPlayerRenderQueue.push(playerIndex);
113
+ v.run.postPlayerRenderQueue.push({ playerIndex, renderOffset });
99
114
  }
100
115
  };
101
116
 
@@ -110,15 +125,16 @@ export class PlayerReorderedCallbacks extends Feature {
110
125
  }
111
126
 
112
127
  function dequeue(
113
- playerIndexes: PlayerIndex[],
114
- fireFunc: (player: EntityPlayer) => void,
128
+ queue: QueueElement[],
129
+ fireFunc: (player: EntityPlayer, renderOffset: Vector) => void,
115
130
  ) {
116
- for (const playerIndex of playerIndexes) {
131
+ for (const element of queue) {
132
+ const { playerIndex, renderOffset } = element;
117
133
  const player = getPlayerFromIndex(playerIndex);
118
134
  if (player !== undefined) {
119
- fireFunc(player);
135
+ fireFunc(player, renderOffset);
120
136
  }
121
137
  }
122
138
 
123
- emptyArray(playerIndexes);
139
+ emptyArray(queue);
124
140
  }
@@ -1,9 +1,9 @@
1
- import { ModCallback } from "isaac-typescript-definitions";
2
1
  import { game } from "../../../core/cachedClasses";
3
2
  import { Exported } from "../../../decorators";
3
+ import { ModCallbackCustom } from "../../../enums/ModCallbackCustom";
4
4
  import { Feature } from "../../private/Feature";
5
5
 
6
- const FADE_IN_SPEED = 1;
6
+ const INSTANT_FADE_IN_SPEED = 1;
7
7
 
8
8
  export class FadeInRemover extends Feature {
9
9
  private enabled = false;
@@ -12,16 +12,18 @@ export class FadeInRemover extends Feature {
12
12
  constructor() {
13
13
  super();
14
14
 
15
- this.callbacksUsed = [
16
- // 15
17
- [ModCallback.POST_GAME_STARTED, this.postGameStarted],
15
+ this.customCallbacksUsed = [
16
+ [
17
+ ModCallbackCustom.POST_GAME_STARTED_REORDERED,
18
+ this.postGameStartedReordered,
19
+ ],
18
20
  ];
19
21
  }
20
22
 
21
- // ModCallback.POST_GAME_STARTED (15)
22
- private postGameStarted = (_isContinued: boolean) => {
23
+ // ModCallbackCustom.POST_GAME_STARTED_REORDERED
24
+ private postGameStartedReordered = () => {
23
25
  if (this.enabled) {
24
- game.Fadein(FADE_IN_SPEED);
26
+ game.Fadein(INSTANT_FADE_IN_SPEED);
25
27
  }
26
28
  };
27
29
 
@@ -103,6 +103,8 @@ export class SaveDataManager extends Feature {
103
103
  [ModCallback.PRE_GAME_EXIT, this.preGameExit],
104
104
 
105
105
  // 18
106
+ // We want to avoid a needless dependency on the `GameReorderedCallbacks` feature.
107
+ // eslint-disable-next-line deprecation/deprecation
106
108
  [ModCallback.POST_NEW_LEVEL, this.postNewLevel],
107
109
  ];
108
110
 
@@ -1,4 +1,4 @@
1
- import { ModCallback } from "isaac-typescript-definitions";
1
+ import { ModCallbackCustom } from "../../../../enums/ModCallbackCustom";
2
2
  import { Feature } from "../../../private/Feature";
3
3
  import { defaultEntityDisplayCallback, renderTextOnEntity } from "./utils";
4
4
 
@@ -9,14 +9,16 @@ export class DebugDisplayPlayer extends Feature {
9
9
  constructor() {
10
10
  super();
11
11
 
12
- this.callbacksUsed = [
13
- // 32
14
- [ModCallback.POST_PLAYER_RENDER, this.postPlayerRender],
12
+ this.customCallbacksUsed = [
13
+ [
14
+ ModCallbackCustom.POST_PLAYER_RENDER_REORDERED,
15
+ this.postPlayerRenderReordered,
16
+ ],
15
17
  ];
16
18
  }
17
19
 
18
- // ModCallback.POST_PLAYER_RENDER (32)
19
- private postPlayerRender = (player: EntityPlayer) => {
20
+ // ModCallbackCustom.POST_PLAYER_RENDER_REORDERED
21
+ private postPlayerRenderReordered = (player: EntityPlayer) => {
20
22
  const text = this.textCallback(player);
21
23
  renderTextOnEntity(player, text);
22
24
  };
@@ -428,8 +428,7 @@ export enum ModCallbackCustom {
428
428
  *
429
429
  * `POST_GAME_STARTED_REORDERED` --> `POST_NEW_LEVEL_REORDERED` --> `POST_NEW_ROOM_REORDERED`
430
430
  *
431
- * - You must provide a third argument to specify if you want the callback to fire if the game is
432
- * continued:
431
+ * - You must provide a third argument:
433
432
  * - Pass true if you want the callback to only fire if the run is continued.
434
433
  * - Pass false if you want the callback to only fire when the run is not continued.
435
434
  * - Pass undefined if you want the callback to fire in both situations.
@@ -449,8 +448,7 @@ export enum ModCallbackCustom {
449
448
  * new run has started (or continued), but you can be sure that all new-run-related initialization
450
449
  * has been completed.
451
450
  *
452
- * - You must provide a third argument to specify if you want the callback to fire if the game is
453
- * continued:
451
+ * - You must provide a third argument:
454
452
  * - Pass true if you want the callback to only fire if the run is continued.
455
453
  * - Pass false if you want the callback to only fire when the run is not continued.
456
454
  * - Pass undefined if you want the callback to fire in both situations.
@@ -1466,7 +1464,7 @@ export enum ModCallbackCustom {
1466
1464
  * matches the `PlayerType` provided.
1467
1465
  *
1468
1466
  * ```ts
1469
- * function postPlayerRenderReordered(player: EntityPlayer): void {}
1467
+ * function postPlayerRenderReordered(player: EntityPlayer, renderOffset: Vector): void {}
1470
1468
  * ```
1471
1469
  */
1472
1470
  POST_PLAYER_RENDER_REORDERED,
@@ -1,5 +1,6 @@
1
1
  import { RenderMode } from "isaac-typescript-definitions";
2
2
  import { game } from "../core/cachedClasses";
3
+ import { getAllPlayers } from "./playerIndex";
3
4
  import { isFunction } from "./types";
4
5
 
5
6
  /**
@@ -79,6 +80,19 @@ export function inRange(num: int, start: int, end: int): boolean {
79
80
  return num >= start && num <= end;
80
81
  }
81
82
 
83
+ /**
84
+ * Helper function to detect if there is two or more players currently playing.
85
+ *
86
+ * Specifically, this function looks for unique `ControllerIndex` values across all players.
87
+ */
88
+ export function isMultiplayer(): boolean {
89
+ const players = getAllPlayers();
90
+ const controllerIndexes = players.map((player) => player.ControllerIndex);
91
+ const controllerIndexesSet = new Set(controllerIndexes);
92
+
93
+ return controllerIndexesSet.size > 1;
94
+ }
95
+
82
96
  /**
83
97
  * Helper function to see if the current render callback is rendering a water reflection.
84
98
  *
@@ -589,7 +589,7 @@ export interface AddCallbackParametersCustom {
589
589
  ];
590
590
 
591
591
  [ModCallbackCustom.POST_PLAYER_RENDER_REORDERED]: [
592
- callback: (player: EntityPlayer) => void,
592
+ callback: (player: EntityPlayer, renderOffset: Vector) => void,
593
593
  playerVariant?: PlayerVariant,
594
594
  character?: PlayerType,
595
595
  ];
package/src/shouldFire.ts CHANGED
@@ -313,6 +313,7 @@ export function shouldFirePit(
313
313
  export function shouldFirePlayer(
314
314
  fireArgs:
315
315
  | [player: EntityPlayer]
316
+ | [player: EntityPlayer, renderOffset: Vector]
316
317
  | [player: EntityPlayer, numSacrifices: int]
317
318
  | [player: EntityPlayer, collectible: EntityPickupCollectible]
318
319
  | [player: EntityPlayer, oldCharacter: PlayerType, newCharacter: PlayerType]